plan9port

fork of plan9port with libvec, libstr and libsdb
Log | Files | Refs | README | LICENSE

arc.c (2586B)


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