diff options
Diffstat (limited to 'sys/src/cmd/unix/drawterm/libmemdraw/ellipse.c')
-rw-r--r-- | sys/src/cmd/unix/drawterm/libmemdraw/ellipse.c | 248 |
1 files changed, 0 insertions, 248 deletions
diff --git a/sys/src/cmd/unix/drawterm/libmemdraw/ellipse.c b/sys/src/cmd/unix/drawterm/libmemdraw/ellipse.c deleted file mode 100644 index 164ab0a1b..000000000 --- a/sys/src/cmd/unix/drawterm/libmemdraw/ellipse.c +++ /dev/null @@ -1,248 +0,0 @@ -#include <u.h> -#include <libc.h> -#include <draw.h> -#include <memdraw.h> -#include <memlayer.h> - -/* - * ellipse(dst, c, a, b, t, src, sp) - * draws an ellipse centered at c with semiaxes a,b>=0 - * and semithickness t>=0, or filled if t<0. point sp - * in src maps to c in dst - * - * very thick skinny ellipses are brushed with circles (slow) - * others are approximated by filling between 2 ellipses - * criterion for very thick when b<a: t/b > 0.5*x/(1-x) - * where x = b/a - */ - -typedef struct Param Param; -typedef struct State State; - -static void bellipse(int, State*, Param*); -static void erect(int, int, int, int, Param*); -static void eline(int, int, int, int, Param*); - -struct Param { - Memimage *dst; - Memimage *src; - Point c; - int t; - Point sp; - Memimage *disc; - int op; -}; - -/* - * denote residual error by e(x,y) = b^2*x^2 + a^2*y^2 - a^2*b^2 - * e(x,y) = 0 on ellipse, e(x,y) < 0 inside, e(x,y) > 0 outside - */ - -struct State { - int a; - int x; - vlong a2; /* a^2 */ - vlong b2; /* b^2 */ - vlong b2x; /* b^2 * x */ - vlong a2y; /* a^2 * y */ - vlong c1; - vlong c2; /* test criteria */ - vlong ee; /* ee = e(x+1/2,y-1/2) - (a^2+b^2)/4 */ - vlong dxe; - vlong dye; - vlong d2xe; - vlong d2ye; -}; - -static -State* -newstate(State *s, int a, int b) -{ - s->x = 0; - s->a = a; - s->a2 = (vlong)(a*a); - s->b2 = (vlong)(b*b); - s->b2x = (vlong)0; - s->a2y = s->a2*(vlong)b; - s->c1 = -((s->a2>>2) + (vlong)(a&1) + s->b2); - s->c2 = -((s->b2>>2) + (vlong)(b&1)); - s->ee = -s->a2y; - s->dxe = (vlong)0; - s->dye = s->ee<<1; - s->d2xe = s->b2<<1; - s->d2ye = s->a2<<1; - return s; -} - -/* - * return x coord of rightmost pixel on next scan line - */ -static -int -step(State *s) -{ - while(s->x < s->a) { - if(s->ee+s->b2x <= s->c1 || /* e(x+1,y-1/2) <= 0 */ - s->ee+s->a2y <= s->c2) { /* e(x+1/2,y) <= 0 (rare) */ - s->dxe += s->d2xe; - s->ee += s->dxe; - s->b2x += s->b2; - s->x++; - continue; - } - s->dye += s->d2ye; - s->ee += s->dye; - s->a2y -= s->a2; - if(s->ee-s->a2y <= s->c2) { /* e(x+1/2,y-1) <= 0 */ - s->dxe += s->d2xe; - s->ee += s->dxe; - s->b2x += s->b2; - return s->x++; - } - break; - } - return s->x; -} - -void -memellipse(Memimage *dst, Point c, int a, int b, int t, Memimage *src, Point sp, int op) -{ - State in, out; - int y, inb, inx, outx, u; - Param p; - - if(a < 0) - a = -a; - if(b < 0) - b = -b; - p.dst = dst; - p.src = src; - p.c = c; - p.t = t; - p.sp = subpt(sp, c); - p.disc = nil; - p.op = op; - - u = (t<<1)*(a-b); - if((b<a && u>b*b) || (a<b && -u>a*a)) { -/* if(b<a&&(t<<1)>b*b/a || a<b&&(t<<1)>a*a/b) # very thick */ - bellipse(b, newstate(&in, a, b), &p); - return; - } - - if(t < 0) { - inb = -1; - newstate(&out, a, y = b); - } else { - inb = b - t; - newstate(&out, a+t, y = b+t); - } - if(t > 0) - newstate(&in, a-t, inb); - inx = 0; - for( ; y>=0; y--) { - outx = step(&out); - if(y > inb) { - erect(-outx, y, outx, y, &p); - if(y != 0) - erect(-outx, -y, outx, -y, &p); - continue; - } - if(t > 0) { - inx = step(&in); - if(y == inb) - inx = 0; - } else if(inx > outx) - inx = outx; - erect(inx, y, outx, y, &p); - if(y != 0) - erect(inx, -y, outx, -y, &p); - erect(-outx, y, -inx, y, &p); - if(y != 0) - erect(-outx, -y, -inx, -y, &p); - inx = outx + 1; - } -} - -static Point p00 = {0, 0}; - -/* - * a brushed ellipse - */ -static -void -bellipse(int y, State *s, Param *p) -{ - int t, ox, oy, x, nx; - - t = p->t; - p->disc = allocmemimage(Rect(-t,-t,t+1,t+1), GREY1); - if(p->disc == nil) - return; - memfillcolor(p->disc, DTransparent); - memellipse(p->disc, p00, t, t, -1, memopaque, p00, p->op); - oy = y; - ox = 0; - nx = x = step(s); - do { - while(nx==x && y-->0) - nx = step(s); - y++; - eline(-x,-oy,-ox, -y, p); - eline(ox,-oy, x, -y, p); - eline(-x, y,-ox, oy, p); - eline(ox, y, x, oy, p); - ox = x+1; - x = nx; - y--; - oy = y; - } while(oy > 0); -} - -/* - * a rectangle with closed (not half-open) coordinates expressed - * relative to the center of the ellipse - */ -static -void -erect(int x0, int y0, int x1, int y1, Param *p) -{ - Rectangle r; - -/* print("R %d,%d %d,%d\n", x0, y0, x1, y1); */ - r = Rect(p->c.x+x0, p->c.y+y0, p->c.x+x1+1, p->c.y+y1+1); - memdraw(p->dst, r, p->src, addpt(p->sp, r.min), memopaque, p00, p->op); -} - -/* - * a brushed point similarly specified - */ -static -void -epoint(int x, int y, Param *p) -{ - Point p0; - Rectangle r; - -/* print("P%d %d,%d\n", p->t, x, y); */ - p0 = Pt(p->c.x+x, p->c.y+y); - r = Rpt(addpt(p0, p->disc->r.min), addpt(p0, p->disc->r.max)); - memdraw(p->dst, r, p->src, addpt(p->sp, r.min), p->disc, p->disc->r.min, p->op); -} - -/* - * a brushed horizontal or vertical line similarly specified - */ -static -void -eline(int x0, int y0, int x1, int y1, Param *p) -{ -/* print("L%d %d,%d %d,%d\n", p->t, x0, y0, x1, y1); */ - if(x1 > x0+1) - erect(x0+1, y0-p->t, x1-1, y1+p->t, p); - else if(y1 > y0+1) - erect(x0-p->t, y0+1, x1+p->t, y1-1, p); - epoint(x0, y0, p); - if(x1-x0 || y1-y0) - epoint(x1, y1, p); -} |