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