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