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