arc.c - vx32 - Local 9vx git repository for patches.
 (HTM) git clone git://r-36.net/vx32
 (DIR) Log
 (DIR) Files
 (DIR) 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 }