]> git.lizzy.rs Git - plan9front.git/blob - sys/src/libmemdraw/arc.c
snoopy(8): avoid extra spaces in dhcp filter output
[plan9front.git] / sys / src / libmemdraw / arc.c
1 #include <u.h>
2 #include <libc.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 /*
28  * make a "wedge" mask covering the desired angle and contained in
29  * a surrounding square; draw a full ellipse; intersect that with the
30  * wedge to make a mask through which to copy src to dst.
31  */
32 void
33 memarc(Memimage *dst, Point c, int a, int b, int t, Memimage *src, Point sp, int alpha, int phi, int op)
34 {
35         int i, w, beta, tmp, c1, c2, m, m1;
36         Rectangle rect;
37         Point p,        bnd[8];
38         Memimage *wedge, *figure, *mask;
39
40         if(phi == 0)
41                 return;
42         if(phi <= -360 || phi >= 360){
43                 memellipse(dst, c, a, b, t, src, sp, op);
44                 return;
45         }
46         alpha %= 360;
47         alpha = -alpha;         /* compensate for upside-down coords */
48         phi = -phi;
49         beta = alpha + phi;
50         if(phi < 0){
51                 tmp = alpha;
52                 alpha = beta;
53                 beta = tmp;
54                 phi = -phi;
55         }
56         while(alpha < 0)
57                 alpha += 360;
58         while(beta < 0)
59                 beta += 360;
60         c1 = alpha/90 & 3;      /* number of nearest corner */
61         c2 = beta/90 & 3;
62                 /*
63                  * icossin returns point at radius ICOSSCALE.
64                  * multiplying by m1 moves it outside the ellipse
65                 */
66
67         if(a < 0)
68                 a = -a;
69         if(b < 0)
70                 b = -b;
71         w = t;
72         if(w < 0)
73                 w = 0;
74
75         rect = Rect(-a-w, -b-w, a+w+1, b+w+1);
76         m = rect.max.x; /* inradius of bounding square */
77         if(m < rect.max.y)
78                 m = rect.max.y;
79         m1 = (m+ICOSSCALE-1) >> 10;
80         m = m1 << 10;           /* assure m1*cossin is inside */
81         i = 0;
82         bnd[i++] = Pt(0,0);
83         icossin(alpha, &p.x, &p.y);
84         bnd[i++] = mulpt(p, m1);
85         for(;;) {
86                 bnd[i++] = mulpt(corners[c1], m);
87                 if(c1==c2 && phi<180)
88                         break;
89                 c1 = (c1+1) & 3;
90                 phi -= 90;
91         }
92         icossin(beta, &p.x, &p.y);
93         bnd[i++] = mulpt(p, m1);
94
95         figure = nil;
96         mask = nil;
97         wedge = allocmemimage(rect, GREY1);
98         if(wedge == nil)
99                 goto Return;
100         memfillcolor(wedge, DTransparent);
101         memfillpoly(wedge, bnd, i, ~0, memopaque, ZP, S);
102         figure = allocmemimage(rect, GREY1);
103         if(figure == nil)
104                 goto Return;
105         memfillcolor(figure, DTransparent);
106         memellipse(figure, ZP, a, b, t, memopaque, ZP, S);
107         mask = allocmemimage(rect, GREY1);
108         if(mask == nil)
109                 goto Return;
110         memfillcolor(mask, DTransparent);
111         memimagedraw(mask, rect, figure, rect.min, wedge, rect.min, S);
112         c = subpt(c, dst->r.min);
113         memdraw(dst, dst->r, src, subpt(sp, c), mask, subpt(ZP, c), op);
114
115     Return:
116         freememimage(wedge);
117         freememimage(figure);
118         freememimage(mask);
119 }