|  | #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); | 
|  | } |