diff options
Diffstat (limited to 'src/libdraw/md-line.c')
-rw-r--r-- | src/libdraw/md-line.c | 486 |
1 files changed, 0 insertions, 486 deletions
diff --git a/src/libdraw/md-line.c b/src/libdraw/md-line.c deleted file mode 100644 index c7042b9f..00000000 --- a/src/libdraw/md-line.c +++ /dev/null @@ -1,486 +0,0 @@ -#include <u.h> -#include <libc.h> -#include <draw.h> -#include <memdraw.h> - -enum -{ - Arrow1 = 8, - Arrow2 = 10, - Arrow3 = 3 -}; - -/* -static -int -lmin(int a, int b) -{ - if(a < b) - return a; - return b; -} -*/ - -static -int -lmax(int a, int b) -{ - if(a > b) - return a; - return b; -} - -#ifdef NOTUSED -/* - * Rather than line clip, we run the Bresenham loop over the full line, - * and clip on each pixel. This is more expensive but means that - * lines look the same regardless of how the windowing has tiled them. - * For speed, we check for clipping outside the loop and make the - * test easy when possible. - */ - -static -void -horline1(Memimage *dst, Point p0, Point p1, int srcval, Rectangle clipr) -{ - int x, y, dy, deltay, deltax, maxx; - int dd, easy, e, bpp, m, m0; - uchar *d; - - deltax = p1.x - p0.x; - deltay = p1.y - p0.y; - dd = dst->width*sizeof(u32int); - dy = 1; - if(deltay < 0){ - dd = -dd; - deltay = -deltay; - dy = -1; - } - maxx = lmin(p1.x, clipr.max.x-1); - bpp = dst->depth; - m0 = 0xFF^(0xFF>>bpp); - m = m0 >> (p0.x&(7/dst->depth))*bpp; - easy = ptinrect(p0, clipr) && ptinrect(p1, clipr); - e = 2*deltay - deltax; - y = p0.y; - d = byteaddr(dst, p0); - deltay *= 2; - deltax = deltay - 2*deltax; - for(x=p0.x; x<=maxx; x++){ - if(easy || (clipr.min.x<=x && clipr.min.y<=y && y<clipr.max.y)) - *d ^= (*d^srcval) & m; - if(e > 0){ - y += dy; - d += dd; - e += deltax; - }else - e += deltay; - d++; - m >>= bpp; - if(m == 0) - m = m0; - } -} - -static -void -verline1(Memimage *dst, Point p0, Point p1, int srcval, Rectangle clipr) -{ - int x, y, deltay, deltax, maxy; - int easy, e, bpp, m, m0, dd; - uchar *d; - - deltax = p1.x - p0.x; - deltay = p1.y - p0.y; - dd = 1; - if(deltax < 0){ - dd = -1; - deltax = -deltax; - } - maxy = lmin(p1.y, clipr.max.y-1); - bpp = dst->depth; - m0 = 0xFF^(0xFF>>bpp); - m = m0 >> (p0.x&(7/dst->depth))*bpp; - easy = ptinrect(p0, clipr) && ptinrect(p1, clipr); - e = 2*deltax - deltay; - x = p0.x; - d = byteaddr(dst, p0); - deltax *= 2; - deltay = deltax - 2*deltay; - for(y=p0.y; y<=maxy; y++){ - if(easy || (clipr.min.y<=y && clipr.min.x<=x && x<clipr.max.x)) - *d ^= (*d^srcval) & m; - if(e > 0){ - x += dd; - d += dd; - e += deltay; - }else - e += deltax; - d += dst->width*sizeof(u32int); - m >>= bpp; - if(m == 0) - m = m0; - } -} - -static -void -horliner(Memimage *dst, Point p0, Point p1, Memimage *src, Point dsrc, Rectangle clipr) -{ - int x, y, sx, sy, deltay, deltax, minx, maxx; - int bpp, m, m0; - uchar *d, *s; - - deltax = p1.x - p0.x; - deltay = p1.y - p0.y; - sx = drawreplxy(src->r.min.x, src->r.max.x, p0.x+dsrc.x); - minx = lmax(p0.x, clipr.min.x); - maxx = lmin(p1.x, clipr.max.x-1); - bpp = dst->depth; - m0 = 0xFF^(0xFF>>bpp); - m = m0 >> (minx&(7/dst->depth))*bpp; - for(x=minx; x<=maxx; x++){ - y = p0.y + (deltay*(x-p0.x)+deltax/2)/deltax; - if(clipr.min.y<=y && y<clipr.max.y){ - d = byteaddr(dst, Pt(x, y)); - sy = drawreplxy(src->r.min.y, src->r.max.y, y+dsrc.y); - s = byteaddr(src, Pt(sx, sy)); - *d ^= (*d^*s) & m; - } - if(++sx >= src->r.max.x) - sx = src->r.min.x; - m >>= bpp; - if(m == 0) - m = m0; - } -} - -static -void -verliner(Memimage *dst, Point p0, Point p1, Memimage *src, Point dsrc, Rectangle clipr) -{ - int x, y, sx, sy, deltay, deltax, miny, maxy; - int bpp, m, m0; - uchar *d, *s; - - deltax = p1.x - p0.x; - deltay = p1.y - p0.y; - sy = drawreplxy(src->r.min.y, src->r.max.y, p0.y+dsrc.y); - miny = lmax(p0.y, clipr.min.y); - maxy = lmin(p1.y, clipr.max.y-1); - bpp = dst->depth; - m0 = 0xFF^(0xFF>>bpp); - for(y=miny; y<=maxy; y++){ - if(deltay == 0) /* degenerate line */ - x = p0.x; - else - x = p0.x + (deltax*(y-p0.y)+deltay/2)/deltay; - if(clipr.min.x<=x && x<clipr.max.x){ - m = m0 >> (x&(7/dst->depth))*bpp; - d = byteaddr(dst, Pt(x, y)); - sx = drawreplxy(src->r.min.x, src->r.max.x, x+dsrc.x); - s = byteaddr(src, Pt(sx, sy)); - *d ^= (*d^*s) & m; - } - if(++sy >= src->r.max.y) - sy = src->r.min.y; - } -} - -static -void -horline(Memimage *dst, Point p0, Point p1, Memimage *src, Point dsrc, Rectangle clipr) -{ - int x, y, deltay, deltax, minx, maxx; - int bpp, m, m0; - uchar *d, *s; - - deltax = p1.x - p0.x; - deltay = p1.y - p0.y; - minx = lmax(p0.x, clipr.min.x); - maxx = lmin(p1.x, clipr.max.x-1); - bpp = dst->depth; - m0 = 0xFF^(0xFF>>bpp); - m = m0 >> (minx&(7/dst->depth))*bpp; - for(x=minx; x<=maxx; x++){ - y = p0.y + (deltay*(x-p0.x)+deltay/2)/deltax; - if(clipr.min.y<=y && y<clipr.max.y){ - d = byteaddr(dst, Pt(x, y)); - s = byteaddr(src, addpt(dsrc, Pt(x, y))); - *d ^= (*d^*s) & m; - } - m >>= bpp; - if(m == 0) - m = m0; - } -} - -static -void -verline(Memimage *dst, Point p0, Point p1, Memimage *src, Point dsrc, Rectangle clipr) -{ - int x, y, deltay, deltax, miny, maxy; - int bpp, m, m0; - uchar *d, *s; - - deltax = p1.x - p0.x; - deltay = p1.y - p0.y; - miny = lmax(p0.y, clipr.min.y); - maxy = lmin(p1.y, clipr.max.y-1); - bpp = dst->depth; - m0 = 0xFF^(0xFF>>bpp); - for(y=miny; y<=maxy; y++){ - if(deltay == 0) /* degenerate line */ - x = p0.x; - else - x = p0.x + deltax*(y-p0.y)/deltay; - if(clipr.min.x<=x && x<clipr.max.x){ - m = m0 >> (x&(7/dst->depth))*bpp; - d = byteaddr(dst, Pt(x, y)); - s = byteaddr(src, addpt(dsrc, Pt(x, y))); - *d ^= (*d^*s) & m; - } - } -} -#endif /* NOTUSED */ - -static Memimage* -membrush(int radius) -{ - static Memimage *brush; - static int brushradius; - - if(brush==nil || brushradius!=radius){ - freememimage(brush); - brush = allocmemimage(Rect(0, 0, 2*radius+1, 2*radius+1), memopaque->chan); - if(brush != nil){ - memfillcolor(brush, DTransparent); /* zeros */ - memellipse(brush, Pt(radius, radius), radius, radius, -1, memopaque, Pt(radius, radius), S); - } - brushradius = radius; - } - return brush; -} - -static -void -discend(Point p, int radius, Memimage *dst, Memimage *src, Point dsrc, int op) -{ - Memimage *disc; - Rectangle r; - - disc = membrush(radius); - if(disc != nil){ - r.min.x = p.x - radius; - r.min.y = p.y - radius; - r.max.x = p.x + radius+1; - r.max.y = p.y + radius+1; - memdraw(dst, r, src, addpt(r.min, dsrc), disc, Pt(0,0), op); - } -} - -static -void -arrowend(Point tip, Point *pp, int end, int sin, int cos, int radius) -{ - int x1, x2, x3; - - /* before rotation */ - if(end == Endarrow){ - x1 = Arrow1; - x2 = Arrow2; - x3 = Arrow3; - }else{ - x1 = (end>>5) & 0x1FF; /* distance along line from end of line to tip */ - x2 = (end>>14) & 0x1FF; /* distance along line from barb to tip */ - x3 = (end>>23) & 0x1FF; /* distance perpendicular from edge of line to barb */ - } - - /* comments follow track of right-facing arrowhead */ - pp->x = tip.x+((2*radius+1)*sin/2-x1*cos); /* upper side of shaft */ - pp->y = tip.y-((2*radius+1)*cos/2+x1*sin); - pp++; - pp->x = tip.x+((2*radius+2*x3+1)*sin/2-x2*cos); /* upper barb */ - pp->y = tip.y-((2*radius+2*x3+1)*cos/2+x2*sin); - pp++; - pp->x = tip.x; - pp->y = tip.y; - pp++; - pp->x = tip.x+(-(2*radius+2*x3+1)*sin/2-x2*cos); /* lower barb */ - pp->y = tip.y-(-(2*radius+2*x3+1)*cos/2+x2*sin); - pp++; - pp->x = tip.x+(-(2*radius+1)*sin/2-x1*cos); /* lower side of shaft */ - pp->y = tip.y+((2*radius+1)*cos/2-x1*sin); -} - -void -_memimageline(Memimage *dst, Point p0, Point p1, int end0, int end1, int radius, Memimage *src, Point sp, Rectangle clipr, int op) -{ - /* - * BUG: We should really really pick off purely horizontal and purely - * vertical lines and handle them separately with calls to memimagedraw - * on rectangles. - */ - - int hor; - int sin, cos, dx, dy, t; - Rectangle oclipr, r; - Point q, pts[10], *pp, d; - - if(radius < 0) - return; - if(rectclip(&clipr, dst->r) == 0) - return; - if(rectclip(&clipr, dst->clipr) == 0) - return; - d = subpt(sp, p0); - if(rectclip(&clipr, rectsubpt(src->clipr, d)) == 0) - return; - if((src->flags&Frepl)==0 && rectclip(&clipr, rectsubpt(src->r, d))==0) - return; - /* this means that only verline() handles degenerate lines (p0==p1) */ - hor = (abs(p1.x-p0.x) > abs(p1.y-p0.y)); - /* - * Clipping is a little peculiar. We can't use Sutherland-Cohen - * clipping because lines are wide. But this is probably just fine: - * we do all math with the original p0 and p1, but clip when deciding - * what pixels to draw. This means the layer code can call this routine, - * using clipr to define the region being written, and get the same set - * of pixels regardless of the dicing. - */ - if((hor && p0.x>p1.x) || (!hor && p0.y>p1.y)){ - q = p0; - p0 = p1; - p1 = q; - t = end0; - end0 = end1; - end1 = t; - } - - if((p0.x == p1.x || p0.y == p1.y) && (end0&0x1F) == Endsquare && (end1&0x1F) == Endsquare){ - r.min = p0; - r.max = p1; - if(p0.x == p1.x){ - r.min.x -= radius; - r.max.x += radius+1; - } - else{ - r.min.y -= radius; - r.max.y += radius+1; - } - oclipr = dst->clipr; - dst->clipr = clipr; - memimagedraw(dst, r, src, sp, memopaque, sp, op); - dst->clipr = oclipr; - return; - } - -/* Hard: */ - /* draw thick line using polygon fill */ - icossin2(p1.x-p0.x, p1.y-p0.y, &cos, &sin); - dx = (sin*(2*radius+1))/2; - dy = (cos*(2*radius+1))/2; - pp = pts; - oclipr = dst->clipr; - dst->clipr = clipr; - q.x = ICOSSCALE*p0.x+ICOSSCALE/2-cos/2; - q.y = ICOSSCALE*p0.y+ICOSSCALE/2-sin/2; - switch(end0 & 0x1F){ - case Enddisc: - discend(p0, radius, dst, src, d, op); - /* fall through */ - case Endsquare: - default: - pp->x = q.x-dx; - pp->y = q.y+dy; - pp++; - pp->x = q.x+dx; - pp->y = q.y-dy; - pp++; - break; - case Endarrow: - arrowend(q, pp, end0, -sin, -cos, radius); - _memfillpolysc(dst, pts, 5, ~0, src, addpt(pts[0], mulpt(d, ICOSSCALE)), 1, 10, 1, op); - pp[1] = pp[4]; - pp += 2; - } - q.x = ICOSSCALE*p1.x+ICOSSCALE/2+cos/2; - q.y = ICOSSCALE*p1.y+ICOSSCALE/2+sin/2; - switch(end1 & 0x1F){ - case Enddisc: - discend(p1, radius, dst, src, d, op); - /* fall through */ - case Endsquare: - default: - pp->x = q.x+dx; - pp->y = q.y-dy; - pp++; - pp->x = q.x-dx; - pp->y = q.y+dy; - pp++; - break; - case Endarrow: - arrowend(q, pp, end1, sin, cos, radius); - _memfillpolysc(dst, pp, 5, ~0, src, addpt(pts[0], mulpt(d, ICOSSCALE)), 1, 10, 1, op); - pp[1] = pp[4]; - pp += 2; - } - _memfillpolysc(dst, pts, pp-pts, ~0, src, addpt(pts[0], mulpt(d, ICOSSCALE)), 0, 10, 1, op); - dst->clipr = oclipr; - return; -} - -void -memimageline(Memimage *dst, Point p0, Point p1, int end0, int end1, int radius, Memimage *src, Point sp, int op) -{ - _memimageline(dst, p0, p1, end0, end1, radius, src, sp, dst->clipr, op); -} - -/* - * Simple-minded conservative code to compute bounding box of line. - * Result is probably a little larger than it needs to be. - */ -static -void -addbbox(Rectangle *r, Point p) -{ - if(r->min.x > p.x) - r->min.x = p.x; - if(r->min.y > p.y) - r->min.y = p.y; - if(r->max.x < p.x+1) - r->max.x = p.x+1; - if(r->max.y < p.y+1) - r->max.y = p.y+1; -} - -int -memlineendsize(int end) -{ - int x3; - - if((end&0x3F) != Endarrow) - return 0; - if(end == Endarrow) - x3 = Arrow3; - else - x3 = (end>>23) & 0x1FF; - return x3; -} - -Rectangle -memlinebbox(Point p0, Point p1, int end0, int end1, int radius) -{ - Rectangle r, r1; - int extra; - - r.min.x = 10000000; - r.min.y = 10000000; - r.max.x = -10000000; - r.max.y = -10000000; - extra = lmax(memlineendsize(end0), memlineendsize(end1)); - r1 = insetrect(canonrect(Rpt(p0, p1)), -(radius+extra)); - addbbox(&r, r1.min); - addbbox(&r, r1.max); - return r; -} |