1*7dd7cddfSDavid du Colombier #include "../lib9.h" 2*7dd7cddfSDavid du Colombier 3*7dd7cddfSDavid du Colombier #include "../libdraw/draw.h" 4*7dd7cddfSDavid du Colombier #include "../libmemdraw/memdraw.h" 5*7dd7cddfSDavid du Colombier #include "../libmemlayer/memlayer.h" 6*7dd7cddfSDavid du Colombier 7*7dd7cddfSDavid du Colombier /* 8*7dd7cddfSDavid du Colombier * elarc(dst,c,a,b,t,src,sp,alpha,phi) 9*7dd7cddfSDavid du Colombier * draws the part of an ellipse between rays at angles alpha and alpha+phi 10*7dd7cddfSDavid du Colombier * measured counterclockwise from the positive x axis. other 11*7dd7cddfSDavid du Colombier * arguments are as for ellipse(dst,c,a,b,t,src,sp) 12*7dd7cddfSDavid du Colombier */ 13*7dd7cddfSDavid du Colombier 14*7dd7cddfSDavid du Colombier enum 15*7dd7cddfSDavid du Colombier { 16*7dd7cddfSDavid du Colombier R, T, L, B /* right, top, left, bottom */ 17*7dd7cddfSDavid du Colombier }; 18*7dd7cddfSDavid du Colombier 19*7dd7cddfSDavid du Colombier static 20*7dd7cddfSDavid du Colombier Point corners[] = { 21*7dd7cddfSDavid du Colombier {1,1}, 22*7dd7cddfSDavid du Colombier {-1,1}, 23*7dd7cddfSDavid du Colombier {-1,-1}, 24*7dd7cddfSDavid du Colombier {1,-1} 25*7dd7cddfSDavid du Colombier }; 26*7dd7cddfSDavid du Colombier 27*7dd7cddfSDavid du Colombier static 28*7dd7cddfSDavid du Colombier Point p00; 29*7dd7cddfSDavid du Colombier 30*7dd7cddfSDavid du Colombier /* 31*7dd7cddfSDavid du Colombier * make a "wedge" mask covering the desired angle and contained in 32*7dd7cddfSDavid du Colombier * a surrounding square; draw a full ellipse; intersect that with the 33*7dd7cddfSDavid du Colombier * wedge to make a mask through which to copy src to dst. 34*7dd7cddfSDavid du Colombier */ 35*7dd7cddfSDavid du Colombier void 36*7dd7cddfSDavid du Colombier memarc(Memimage *dst, Point c, int a, int b, int t, Memimage *src, Point sp, int alpha, int phi) 37*7dd7cddfSDavid du Colombier { 38*7dd7cddfSDavid du Colombier int i, w, beta, tmp, c1, c2, m, m1; 39*7dd7cddfSDavid du Colombier Rectangle rect; 40*7dd7cddfSDavid du Colombier Point p, bnd[8]; 41*7dd7cddfSDavid du Colombier Memimage *wedge, *figure, *mask; 42*7dd7cddfSDavid du Colombier 43*7dd7cddfSDavid du Colombier if(a < 0) 44*7dd7cddfSDavid du Colombier a = -a; 45*7dd7cddfSDavid du Colombier if(b < 0) 46*7dd7cddfSDavid du Colombier b = -b; 47*7dd7cddfSDavid du Colombier w = t; 48*7dd7cddfSDavid du Colombier if(w < 0) 49*7dd7cddfSDavid du Colombier w = 0; 50*7dd7cddfSDavid du Colombier alpha = -alpha; /* compensate for upside-down coords */ 51*7dd7cddfSDavid du Colombier phi = -phi; 52*7dd7cddfSDavid du Colombier beta = alpha + phi; 53*7dd7cddfSDavid du Colombier if(phi < 0){ 54*7dd7cddfSDavid du Colombier tmp = alpha; 55*7dd7cddfSDavid du Colombier alpha = beta; 56*7dd7cddfSDavid du Colombier beta = tmp; 57*7dd7cddfSDavid du Colombier phi = -phi; 58*7dd7cddfSDavid du Colombier } 59*7dd7cddfSDavid du Colombier if(phi >= 360){ 60*7dd7cddfSDavid du Colombier memellipse(dst, c, a, b, t, src, sp); 61*7dd7cddfSDavid du Colombier return; 62*7dd7cddfSDavid du Colombier } 63*7dd7cddfSDavid du Colombier while(alpha < 0) 64*7dd7cddfSDavid du Colombier alpha += 360; 65*7dd7cddfSDavid du Colombier while(beta < 0) 66*7dd7cddfSDavid du Colombier beta += 360; 67*7dd7cddfSDavid du Colombier c1 = alpha/90 & 3; /* number of nearest corner */ 68*7dd7cddfSDavid du Colombier c2 = beta/90 & 3; 69*7dd7cddfSDavid du Colombier /* 70*7dd7cddfSDavid du Colombier * icossin returns point at radius ICOSSCALE. 71*7dd7cddfSDavid du Colombier * multiplying by m1 moves it outside the ellipse 72*7dd7cddfSDavid du Colombier */ 73*7dd7cddfSDavid du Colombier rect = Rect(-a-w, -b-w, a+w+1, b+w+1); 74*7dd7cddfSDavid du Colombier m = rect.max.x; /* inradius of bounding square */ 75*7dd7cddfSDavid du Colombier if(m < rect.max.y) 76*7dd7cddfSDavid du Colombier m = rect.max.y; 77*7dd7cddfSDavid du Colombier m1 = (m+ICOSSCALE-1) >> 10; 78*7dd7cddfSDavid du Colombier m = m1 << 10; /* assure m1*cossin is inside */ 79*7dd7cddfSDavid du Colombier i = 0; 80*7dd7cddfSDavid du Colombier bnd[i++] = Pt(0,0); 81*7dd7cddfSDavid du Colombier icossin(alpha, &p.x, &p.y); 82*7dd7cddfSDavid du Colombier bnd[i++] = mulpt(p, m1); 83*7dd7cddfSDavid du Colombier for(;;) { 84*7dd7cddfSDavid du Colombier bnd[i++] = mulpt(corners[c1], m); 85*7dd7cddfSDavid du Colombier if(c1==c2 && phi<180) 86*7dd7cddfSDavid du Colombier break; 87*7dd7cddfSDavid du Colombier c1 = (c1+1) & 3; 88*7dd7cddfSDavid du Colombier phi -= 90; 89*7dd7cddfSDavid du Colombier } 90*7dd7cddfSDavid du Colombier icossin(beta, &p.x, &p.y); 91*7dd7cddfSDavid du Colombier bnd[i++] = mulpt(p, m1); 92*7dd7cddfSDavid du Colombier 93*7dd7cddfSDavid du Colombier figure = nil; 94*7dd7cddfSDavid du Colombier mask = nil; 95*7dd7cddfSDavid du Colombier wedge = allocmemimage(rect, GREY1); 96*7dd7cddfSDavid du Colombier if(wedge == nil) 97*7dd7cddfSDavid du Colombier goto Return; 98*7dd7cddfSDavid du Colombier memfillcolor(wedge, DTransparent); 99*7dd7cddfSDavid du Colombier memfillpoly(wedge, bnd, i, ~0, memopaque, p00); 100*7dd7cddfSDavid du Colombier figure = allocmemimage(rect, GREY1); 101*7dd7cddfSDavid du Colombier if(figure == nil) 102*7dd7cddfSDavid du Colombier goto Return; 103*7dd7cddfSDavid du Colombier memfillcolor(figure, DTransparent); 104*7dd7cddfSDavid du Colombier memellipse(figure, p00, a, b, t, memopaque, p00); 105*7dd7cddfSDavid du Colombier mask = allocmemimage(rect, GREY1); 106*7dd7cddfSDavid du Colombier if(mask == nil) 107*7dd7cddfSDavid du Colombier goto Return; 108*7dd7cddfSDavid du Colombier memfillcolor(mask, DTransparent); 109*7dd7cddfSDavid du Colombier memimagedraw(mask, rect, figure, rect.min, wedge, rect.min); 110*7dd7cddfSDavid du Colombier c = subpt(c, dst->r.min); 111*7dd7cddfSDavid du Colombier memdraw(dst, dst->r, src, subpt(sp, c), mask, subpt(p00, c)); 112*7dd7cddfSDavid du Colombier 113*7dd7cddfSDavid du Colombier Return: 114*7dd7cddfSDavid du Colombier freememimage(wedge); 115*7dd7cddfSDavid du Colombier freememimage(figure); 116*7dd7cddfSDavid du Colombier freememimage(mask); 117*7dd7cddfSDavid du Colombier } 118