xref: /plan9/sys/src/cmd/unix/drawterm/libmemdraw/arc.c (revision 8ccd4a6360d974db7bd7bbd4f37e7018419ea908)
1*8ccd4a63SDavid du Colombier #include <u.h>
2*8ccd4a63SDavid du Colombier #include <libc.h>
3*8ccd4a63SDavid du Colombier #include <draw.h>
4*8ccd4a63SDavid du Colombier #include <memdraw.h>
5*8ccd4a63SDavid du Colombier #include <memlayer.h>
67dd7cddfSDavid du Colombier 
77dd7cddfSDavid du Colombier /*
87dd7cddfSDavid du Colombier  * elarc(dst,c,a,b,t,src,sp,alpha,phi)
97dd7cddfSDavid du Colombier  *   draws the part of an ellipse between rays at angles alpha and alpha+phi
107dd7cddfSDavid du Colombier  *   measured counterclockwise from the positive x axis. other
117dd7cddfSDavid du Colombier  *   arguments are as for ellipse(dst,c,a,b,t,src,sp)
127dd7cddfSDavid du Colombier  */
137dd7cddfSDavid du Colombier 
147dd7cddfSDavid du Colombier enum
157dd7cddfSDavid du Colombier {
167dd7cddfSDavid du Colombier 	R, T, L, B	/* right, top, left, bottom */
177dd7cddfSDavid du Colombier };
187dd7cddfSDavid du Colombier 
197dd7cddfSDavid du Colombier static
207dd7cddfSDavid du Colombier Point corners[] = {
217dd7cddfSDavid du Colombier 	{1,1},
227dd7cddfSDavid du Colombier 	{-1,1},
237dd7cddfSDavid du Colombier 	{-1,-1},
247dd7cddfSDavid du Colombier 	{1,-1}
257dd7cddfSDavid du Colombier };
267dd7cddfSDavid du Colombier 
277dd7cddfSDavid du Colombier static
287dd7cddfSDavid du Colombier Point p00;
297dd7cddfSDavid du Colombier 
307dd7cddfSDavid du Colombier /*
317dd7cddfSDavid du Colombier  * make a "wedge" mask covering the desired angle and contained in
327dd7cddfSDavid du Colombier  * a surrounding square; draw a full ellipse; intersect that with the
337dd7cddfSDavid du Colombier  * wedge to make a mask through which to copy src to dst.
347dd7cddfSDavid du Colombier  */
357dd7cddfSDavid du Colombier void
memarc(Memimage * dst,Point c,int a,int b,int t,Memimage * src,Point sp,int alpha,int phi,int op)36*8ccd4a63SDavid du Colombier memarc(Memimage *dst, Point c, int a, int b, int t, Memimage *src, Point sp, int alpha, int phi, int op)
377dd7cddfSDavid du Colombier {
387dd7cddfSDavid du Colombier 	int i, w, beta, tmp, c1, c2, m, m1;
397dd7cddfSDavid du Colombier 	Rectangle rect;
407dd7cddfSDavid du Colombier 	Point p,	bnd[8];
417dd7cddfSDavid du Colombier 	Memimage *wedge, *figure, *mask;
427dd7cddfSDavid du Colombier 
437dd7cddfSDavid du Colombier 	if(a < 0)
447dd7cddfSDavid du Colombier 		a = -a;
457dd7cddfSDavid du Colombier 	if(b < 0)
467dd7cddfSDavid du Colombier 		b = -b;
477dd7cddfSDavid du Colombier 	w = t;
487dd7cddfSDavid du Colombier 	if(w < 0)
497dd7cddfSDavid du Colombier 		w = 0;
507dd7cddfSDavid du Colombier 	alpha = -alpha;		/* compensate for upside-down coords */
517dd7cddfSDavid du Colombier 	phi = -phi;
527dd7cddfSDavid du Colombier 	beta = alpha + phi;
537dd7cddfSDavid du Colombier 	if(phi < 0){
547dd7cddfSDavid du Colombier 		tmp = alpha;
557dd7cddfSDavid du Colombier 		alpha = beta;
567dd7cddfSDavid du Colombier 		beta = tmp;
577dd7cddfSDavid du Colombier 		phi = -phi;
587dd7cddfSDavid du Colombier 	}
597dd7cddfSDavid du Colombier 	if(phi >= 360){
60*8ccd4a63SDavid du Colombier 		memellipse(dst, c, a, b, t, src, sp, op);
617dd7cddfSDavid du Colombier 		return;
627dd7cddfSDavid du Colombier 	}
637dd7cddfSDavid du Colombier 	while(alpha < 0)
647dd7cddfSDavid du Colombier 		alpha += 360;
657dd7cddfSDavid du Colombier 	while(beta < 0)
667dd7cddfSDavid du Colombier 		beta += 360;
677dd7cddfSDavid du Colombier 	c1 = alpha/90 & 3;	/* number of nearest corner */
687dd7cddfSDavid du Colombier 	c2 = beta/90 & 3;
697dd7cddfSDavid du Colombier 		/*
707dd7cddfSDavid du Colombier 		 * icossin returns point at radius ICOSSCALE.
717dd7cddfSDavid du Colombier 		 * multiplying by m1 moves it outside the ellipse
727dd7cddfSDavid du Colombier 		*/
737dd7cddfSDavid du Colombier 	rect = Rect(-a-w, -b-w, a+w+1, b+w+1);
747dd7cddfSDavid du Colombier 	m = rect.max.x;	/* inradius of bounding square */
757dd7cddfSDavid du Colombier 	if(m < rect.max.y)
767dd7cddfSDavid du Colombier 		m = rect.max.y;
777dd7cddfSDavid du Colombier 	m1 = (m+ICOSSCALE-1) >> 10;
787dd7cddfSDavid du Colombier 	m = m1 << 10;		/* assure m1*cossin is inside */
797dd7cddfSDavid du Colombier 	i = 0;
807dd7cddfSDavid du Colombier 	bnd[i++] = Pt(0,0);
817dd7cddfSDavid du Colombier 	icossin(alpha, &p.x, &p.y);
827dd7cddfSDavid du Colombier 	bnd[i++] = mulpt(p, m1);
837dd7cddfSDavid du Colombier 	for(;;) {
847dd7cddfSDavid du Colombier 		bnd[i++] = mulpt(corners[c1], m);
857dd7cddfSDavid du Colombier 		if(c1==c2 && phi<180)
867dd7cddfSDavid du Colombier 			break;
877dd7cddfSDavid du Colombier 		c1 = (c1+1) & 3;
887dd7cddfSDavid du Colombier 		phi -= 90;
897dd7cddfSDavid du Colombier 	}
907dd7cddfSDavid du Colombier 	icossin(beta, &p.x, &p.y);
917dd7cddfSDavid du Colombier 	bnd[i++] = mulpt(p, m1);
927dd7cddfSDavid du Colombier 
937dd7cddfSDavid du Colombier 	figure = nil;
947dd7cddfSDavid du Colombier 	mask = nil;
957dd7cddfSDavid du Colombier 	wedge = allocmemimage(rect, GREY1);
967dd7cddfSDavid du Colombier 	if(wedge == nil)
977dd7cddfSDavid du Colombier 		goto Return;
987dd7cddfSDavid du Colombier 	memfillcolor(wedge, DTransparent);
99*8ccd4a63SDavid du Colombier 	memfillpoly(wedge, bnd, i, ~0, memopaque, p00, S);
1007dd7cddfSDavid du Colombier 	figure = allocmemimage(rect, GREY1);
1017dd7cddfSDavid du Colombier 	if(figure == nil)
1027dd7cddfSDavid du Colombier 		goto Return;
1037dd7cddfSDavid du Colombier 	memfillcolor(figure, DTransparent);
104*8ccd4a63SDavid du Colombier 	memellipse(figure, p00, a, b, t, memopaque, p00, S);
1057dd7cddfSDavid du Colombier 	mask = allocmemimage(rect, GREY1);
1067dd7cddfSDavid du Colombier 	if(mask == nil)
1077dd7cddfSDavid du Colombier 		goto Return;
1087dd7cddfSDavid du Colombier 	memfillcolor(mask, DTransparent);
109*8ccd4a63SDavid du Colombier 	memimagedraw(mask, rect, figure, rect.min, wedge, rect.min, S);
1107dd7cddfSDavid du Colombier 	c = subpt(c, dst->r.min);
111*8ccd4a63SDavid du Colombier 	memdraw(dst, dst->r, src, subpt(sp, c), mask, subpt(p00, c), op);
1127dd7cddfSDavid du Colombier 
1137dd7cddfSDavid du Colombier     Return:
1147dd7cddfSDavid du Colombier 	freememimage(wedge);
1157dd7cddfSDavid du Colombier 	freememimage(figure);
1167dd7cddfSDavid du Colombier 	freememimage(mask);
1177dd7cddfSDavid du Colombier }
118