Blob


1 #include <u.h>
2 #include <libc.h>
3 #include <draw.h>
4 #include <memdraw.h>
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 */
13 enum
14 {
15 R, T, L, B /* right, top, left, bottom */
16 };
18 static
19 Point corners[] = {
20 {1,1},
21 {-1,1},
22 {-1,-1},
23 {1,-1}
24 };
26 static
27 Point p00;
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;
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);
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);
112 Return:
113 freememimage(wedge);
114 freememimage(figure);
115 freememimage(mask);