aboutsummaryrefslogtreecommitdiff
path: root/src/libdraw/md-arc.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/libdraw/md-arc.c')
-rw-r--r--src/libdraw/md-arc.c116
1 files changed, 116 insertions, 0 deletions
diff --git a/src/libdraw/md-arc.c b/src/libdraw/md-arc.c
new file mode 100644
index 00000000..df836a00
--- /dev/null
+++ b/src/libdraw/md-arc.c
@@ -0,0 +1,116 @@
+#include <u.h>
+#include <libc.h>
+#include <draw.h>
+#include <memdraw.h>
+
+/*
+ * elarc(dst,c,a,b,t,src,sp,alpha,phi)
+ * draws the part of an ellipse between rays at angles alpha and alpha+phi
+ * measured counterclockwise from the positive x axis. other
+ * arguments are as for ellipse(dst,c,a,b,t,src,sp)
+ */
+
+enum
+{
+ R, T, L, B /* right, top, left, bottom */
+};
+
+static
+Point corners[] = {
+ {1,1},
+ {-1,1},
+ {-1,-1},
+ {1,-1}
+};
+
+static
+Point p00;
+
+/*
+ * make a "wedge" mask covering the desired angle and contained in
+ * a surrounding square; draw a full ellipse; intersect that with the
+ * wedge to make a mask through which to copy src to dst.
+ */
+void
+memarc(Memimage *dst, Point c, int a, int b, int t, Memimage *src, Point sp, int alpha, int phi, int op)
+{
+ int i, w, beta, tmp, c1, c2, m, m1;
+ Rectangle rect;
+ Point p, bnd[8];
+ Memimage *wedge, *figure, *mask;
+
+ if(a < 0)
+ a = -a;
+ if(b < 0)
+ b = -b;
+ w = t;
+ if(w < 0)
+ w = 0;
+ alpha = -alpha; /* compensate for upside-down coords */
+ phi = -phi;
+ beta = alpha + phi;
+ if(phi < 0){
+ tmp = alpha;
+ alpha = beta;
+ beta = tmp;
+ phi = -phi;
+ }
+ if(phi >= 360){
+ memellipse(dst, c, a, b, t, src, sp, op);
+ return;
+ }
+ while(alpha < 0)
+ alpha += 360;
+ while(beta < 0)
+ beta += 360;
+ c1 = alpha/90 & 3; /* number of nearest corner */
+ c2 = beta/90 & 3;
+ /*
+ * icossin returns point at radius ICOSSCALE.
+ * multiplying by m1 moves it outside the ellipse
+ */
+ rect = Rect(-a-w, -b-w, a+w+1, b+w+1);
+ m = rect.max.x; /* inradius of bounding square */
+ if(m < rect.max.y)
+ m = rect.max.y;
+ m1 = (m+ICOSSCALE-1) >> 10;
+ m = m1 << 10; /* assure m1*cossin is inside */
+ i = 0;
+ bnd[i++] = Pt(0,0);
+ icossin(alpha, &p.x, &p.y);
+ bnd[i++] = mulpt(p, m1);
+ for(;;) {
+ bnd[i++] = mulpt(corners[c1], m);
+ if(c1==c2 && phi<180)
+ break;
+ c1 = (c1+1) & 3;
+ phi -= 90;
+ }
+ icossin(beta, &p.x, &p.y);
+ bnd[i++] = mulpt(p, m1);
+
+ figure = nil;
+ mask = nil;
+ wedge = allocmemimage(rect, GREY1);
+ if(wedge == nil)
+ goto Return;
+ memfillcolor(wedge, DTransparent);
+ memfillpoly(wedge, bnd, i, ~0, memopaque, p00, S);
+ figure = allocmemimage(rect, GREY1);
+ if(figure == nil)
+ goto Return;
+ memfillcolor(figure, DTransparent);
+ memellipse(figure, p00, a, b, t, memopaque, p00, S);
+ mask = allocmemimage(rect, GREY1);
+ if(mask == nil)
+ goto Return;
+ memfillcolor(mask, DTransparent);
+ memimagedraw(mask, rect, figure, rect.min, wedge, rect.min, S);
+ c = subpt(c, dst->r.min);
+ memdraw(dst, dst->r, src, subpt(sp, c), mask, subpt(p00, c), op);
+
+ Return:
+ freememimage(wedge);
+ freememimage(figure);
+ freememimage(mask);
+}