1 #include "lib9.h" 2 #include "draw.h" 3 #include "memdraw.h" 4 #include "memlayer.h" 5 6 /* 7 * elarc(dst,c,a,b,t,src,sp,alpha,phi) 8 * draws the part of an ellipse between rays at angles alpha and alpha+phi 9 * measured counterclockwise from the positive x axis. other 10 * arguments are as for ellipse(dst,c,a,b,t,src,sp) 11 */ 12 13 enum 14 { 15 R, T, L, B /* right, top, left, bottom */ 16 }; 17 18 static 19 Point corners[] = { 20 {1,1}, 21 {-1,1}, 22 {-1,-1}, 23 {1,-1} 24 }; 25 26 static 27 Point p00; 28 29 /* 30 * make a "wedge" mask covering the desired angle and contained in 31 * a surrounding square; draw a full ellipse; intersect that with the 32 * wedge to make a mask through which to copy src to dst. 33 */ 34 void 35 memarc(Memimage *dst, Point c, int a, int b, int t, Memimage *src, Point sp, int alpha, int phi, int op) 36 { 37 int i, w, beta, tmp, c1, c2, m, m1; 38 Rectangle rect; 39 Point p, bnd[8]; 40 Memimage *wedge, *figure, *mask; 41 42 if(a < 0) 43 a = -a; 44 if(b < 0) 45 b = -b; 46 w = t; 47 if(w < 0) 48 w = 0; 49 alpha = -alpha; /* compensate for upside-down coords */ 50 phi = -phi; 51 beta = alpha + phi; 52 if(phi < 0){ 53 tmp = alpha; 54 alpha = beta; 55 beta = tmp; 56 phi = -phi; 57 } 58 if(phi >= 360){ 59 memellipse(dst, c, a, b, t, src, sp, op); 60 return; 61 } 62 while(alpha < 0) 63 alpha += 360; 64 while(beta < 0) 65 beta += 360; 66 c1 = alpha/90 & 3; /* number of nearest corner */ 67 c2 = beta/90 & 3; 68 /* 69 * icossin returns point at radius ICOSSCALE. 70 * multiplying by m1 moves it outside the ellipse 71 */ 72 rect = Rect(-a-w, -b-w, a+w+1, b+w+1); 73 m = rect.max.x; /* inradius of bounding square */ 74 if(m < rect.max.y) 75 m = rect.max.y; 76 m1 = (m+ICOSSCALE-1) >> 10; 77 m = m1 << 10; /* assure m1*cossin is inside */ 78 i = 0; 79 bnd[i++] = Pt(0,0); 80 icossin(alpha, &p.x, &p.y); 81 bnd[i++] = mulpt(p, m1); 82 for(;;) { 83 bnd[i++] = mulpt(corners[c1], m); 84 if(c1==c2 && phi<180) 85 break; 86 c1 = (c1+1) & 3; 87 phi -= 90; 88 } 89 icossin(beta, &p.x, &p.y); 90 bnd[i++] = mulpt(p, m1); 91 92 figure = nil; 93 mask = nil; 94 wedge = allocmemimage(rect, GREY1); 95 if(wedge == nil) 96 goto Return; 97 memfillcolor(wedge, DTransparent); 98 memfillpoly(wedge, bnd, i, ~0, memopaque, p00, S); 99 figure = allocmemimage(rect, GREY1); 100 if(figure == nil) 101 goto Return; 102 memfillcolor(figure, DTransparent); 103 memellipse(figure, p00, a, b, t, memopaque, p00, S); 104 mask = allocmemimage(rect, GREY1); 105 if(mask == nil) 106 goto Return; 107 memfillcolor(mask, DTransparent); 108 memimagedraw(mask, rect, figure, rect.min, wedge, rect.min, S); 109 c = subpt(c, dst->r.min); 110 memdraw(dst, dst->r, src, subpt(sp, c), mask, subpt(p00, c), op); 111 112 Return: 113 freememimage(wedge); 114 freememimage(figure); 115 freememimage(mask); 116 } 117