1 #include <u.h>
2 #include <libc.h>
3 #include <draw.h>
4 #include <memdraw.h>
5 #include <memlayer.h>
6 
7 struct Lline
8 {
9 	Point			p0;
10 	Point			p1;
11 	Point			delta;
12 	int			end0;
13 	int			end1;
14 	int			radius;
15 	Point			sp;
16 	Memlayer		*dstlayer;
17 	Memimage	*src;
18 	int			op;
19 };
20 
21 static void llineop(Memimage*, Rectangle, Rectangle, void*, int);
22 
23 static
24 void
_memline(Memimage * dst,Point p0,Point p1,int end0,int end1,int radius,Memimage * src,Point sp,Rectangle clipr,int op)25 _memline(Memimage *dst, Point p0, Point p1, int end0, int end1, int radius, Memimage *src, Point sp, Rectangle clipr, int op)
26 {
27 	Rectangle r;
28 	struct Lline ll;
29 	Point d;
30 	int srcclipped;
31 	Memlayer *dl;
32 
33 	if(radius < 0)
34 		return;
35 	if(src->layer)	/* can't draw line with layered source */
36 		return;
37 	srcclipped = 0;
38 
39    Top:
40 	dl = dst->layer;
41 	if(dl == nil){
42 		_memimageline(dst, p0, p1, end0, end1, radius, src, sp, clipr, op);
43 		return;
44 	}
45 	if(!srcclipped){
46 		d = subpt(sp, p0);
47 		if(rectclip(&clipr, rectsubpt(src->clipr, d)) == 0)
48 			return;
49 		if((src->flags&Frepl)==0 && rectclip(&clipr, rectsubpt(src->r, d))==0)
50 			return;
51 		srcclipped = 1;
52 	}
53 
54 	/* dst is known to be a layer */
55 	p0.x += dl->delta.x;
56 	p0.y += dl->delta.y;
57 	p1.x += dl->delta.x;
58 	p1.y += dl->delta.y;
59 	clipr.min.x += dl->delta.x;
60 	clipr.min.y += dl->delta.y;
61 	clipr.max.x += dl->delta.x;
62 	clipr.max.y += dl->delta.y;
63 	if(dl->clear){
64 		dst = dst->layer->screen->image;
65 		goto Top;
66 	}
67 
68 	/* XXX */
69 	/* this is not the correct set of tests */
70 //	if(log2[dst->depth] != log2[src->depth] || log2[dst->depth]!=3)
71 //		return;
72 
73 	/* can't use sutherland-cohen clipping because lines are wide */
74 	r = memlinebbox(p0, p1, end0, end1, radius);
75 	/*
76 	 * r is now a bounding box for the line;
77 	 * use it as a clipping rectangle for subdivision
78 	 */
79 	if(rectclip(&r, clipr) == 0)
80 		return;
81 	ll.p0 = p0;
82 	ll.p1 = p1;
83 	ll.end0 = end0;
84 	ll.end1 = end1;
85 	ll.sp = sp;
86 	ll.dstlayer = dst->layer;
87 	ll.src = src;
88 	ll.radius = radius;
89 	ll.delta = dl->delta;
90 	ll.op = op;
91 	_memlayerop(llineop, dst, r, r, &ll);
92 }
93 
94 static
95 void
llineop(Memimage * dst,Rectangle screenr,Rectangle clipr,void * etc,int insave)96 llineop(Memimage *dst, Rectangle screenr, Rectangle clipr, void *etc, int insave)
97 {
98 	struct Lline *ll;
99 	Point p0, p1;
100 
101 	USED(screenr.min.x);
102 	ll = etc;
103 	if(insave && ll->dstlayer->save==nil)
104 		return;
105 	if(!rectclip(&clipr, screenr))
106 		return;
107 	if(insave){
108 		p0 = subpt(ll->p0, ll->delta);
109 		p1 = subpt(ll->p1, ll->delta);
110 		clipr = rectsubpt(clipr, ll->delta);
111 	}else{
112 		p0 = ll->p0;
113 		p1 = ll->p1;
114 	}
115 	_memline(dst, p0, p1, ll->end0, ll->end1, ll->radius, ll->src, ll->sp, clipr, ll->op);
116 }
117 
118 void
memline(Memimage * dst,Point p0,Point p1,int end0,int end1,int radius,Memimage * src,Point sp,int op)119 memline(Memimage *dst, Point p0, Point p1, int end0, int end1, int radius, Memimage *src, Point sp, int op)
120 {
121 	_memline(dst, p0, p1, end0, end1, radius, src, sp, dst->clipr, op);
122 }
123