vx32

Local 9vx git repository for patches.
git clone git://r-36.net/vx32
Log | Files | Refs

arc.c (2607B)


      1 #include "u.h"
      2 #include "lib.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 }