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