]> git.lizzy.rs Git - plan9front.git/blob - sys/src/libmemdraw/arc.c
add HISTORY to various man pages
[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 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 }