From 324891a5579d6f504201a6107369c64dab245a98 Mon Sep 17 00:00:00 2001 From: rsc Date: Sun, 25 Jun 2006 18:58:06 +0000 Subject: separate out --- src/libmemdraw/arc.c | 116 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 116 insertions(+) create mode 100644 src/libmemdraw/arc.c (limited to 'src/libmemdraw/arc.c') diff --git a/src/libmemdraw/arc.c b/src/libmemdraw/arc.c new file mode 100644 index 00000000..df836a00 --- /dev/null +++ b/src/libmemdraw/arc.c @@ -0,0 +1,116 @@ +#include +#include +#include +#include + +/* + * 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); +} -- cgit v1.2.3