123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117 |
- #include <u.h>
- #include <libc.h>
- #include <draw.h>
- #include <memdraw.h>
- #include <memlayer.h>
- /*
- * elarc(dst,c,a,b,t,src,sp,alpha,phi)
- * draws the part of an ellipse between rays at angles alpha and alpha+phi
- * measured counterclockwise from the positive x axis. other
- * arguments are as for ellipse(dst,c,a,b,t,src,sp)
- */
- enum
- {
- R, T, L, B /* right, top, left, bottom */
- };
- static
- Point corners[] = {
- {1,1},
- {-1,1},
- {-1,-1},
- {1,-1}
- };
- static
- Point p00;
- /*
- * make a "wedge" mask covering the desired angle and contained in
- * a surrounding square; draw a full ellipse; intersect that with the
- * wedge to make a mask through which to copy src to dst.
- */
- void
- memarc(Memimage *dst, Point c, int a, int b, int t, Memimage *src, Point sp, int alpha, int phi, int op)
- {
- int i, w, beta, tmp, c1, c2, m, m1;
- Rectangle rect;
- Point p, bnd[8];
- Memimage *wedge, *figure, *mask;
- if(a < 0)
- a = -a;
- if(b < 0)
- b = -b;
- w = t;
- if(w < 0)
- w = 0;
- alpha = -alpha; /* compensate for upside-down coords */
- phi = -phi;
- beta = alpha + phi;
- if(phi < 0){
- tmp = alpha;
- alpha = beta;
- beta = tmp;
- phi = -phi;
- }
- if(phi >= 360){
- memellipse(dst, c, a, b, t, src, sp, op);
- return;
- }
- while(alpha < 0)
- alpha += 360;
- while(beta < 0)
- beta += 360;
- c1 = alpha/90 & 3; /* number of nearest corner */
- c2 = beta/90 & 3;
- /*
- * icossin returns point at radius ICOSSCALE.
- * multiplying by m1 moves it outside the ellipse
- */
- rect = Rect(-a-w, -b-w, a+w+1, b+w+1);
- m = rect.max.x; /* inradius of bounding square */
- if(m < rect.max.y)
- m = rect.max.y;
- m1 = (m+ICOSSCALE-1) >> 10;
- m = m1 << 10; /* assure m1*cossin is inside */
- i = 0;
- bnd[i++] = Pt(0,0);
- icossin(alpha, &p.x, &p.y);
- bnd[i++] = mulpt(p, m1);
- for(;;) {
- bnd[i++] = mulpt(corners[c1], m);
- if(c1==c2 && phi<180)
- break;
- c1 = (c1+1) & 3;
- phi -= 90;
- }
- icossin(beta, &p.x, &p.y);
- bnd[i++] = mulpt(p, m1);
- figure = nil;
- mask = nil;
- wedge = allocmemimage(rect, GREY1);
- if(wedge == nil)
- goto Return;
- memfillcolor(wedge, DTransparent);
- memfillpoly(wedge, bnd, i, ~0, memopaque, p00, S);
- figure = allocmemimage(rect, GREY1);
- if(figure == nil)
- goto Return;
- memfillcolor(figure, DTransparent);
- memellipse(figure, p00, a, b, t, memopaque, p00, S);
- mask = allocmemimage(rect, GREY1);
- if(mask == nil)
- goto Return;
- memfillcolor(mask, DTransparent);
- memimagedraw(mask, rect, figure, rect.min, wedge, rect.min, S);
- c = subpt(c, dst->r.min);
- memdraw(dst, dst->r, src, subpt(sp, c), mask, subpt(p00, c), op);
- Return:
- freememimage(wedge);
- freememimage(figure);
- freememimage(mask);
- }
|