1 #include <u.h>
2 #include <libc.h>
3 #include <draw.h>
4 #include <memdraw.h>
5 #include <memlayer.h>
6 
7 struct Draw
8 {
9 	Point	deltas;
10 	Point	deltam;
11 	Memlayer		*dstlayer;
12 	Memimage	*src;
13 	Memimage	*mask;
14 	int	op;
15 };
16 
17 static
18 void
ldrawop(Memimage * dst,Rectangle screenr,Rectangle clipr,void * etc,int insave)19 ldrawop(Memimage *dst, Rectangle screenr, Rectangle clipr, void *etc, int insave)
20 {
21 	struct Draw *d;
22 	Point p0, p1;
23 	Rectangle oclipr, srcr, r, mr;
24 	int ok;
25 
26 	d = etc;
27 	if(insave && d->dstlayer->save==nil)
28 		return;
29 
30 	p0 = addpt(screenr.min, d->deltas);
31 	p1 = addpt(screenr.min, d->deltam);
32 
33 	if(insave){
34 		r = rectsubpt(screenr, d->dstlayer->delta);
35 		clipr = rectsubpt(clipr, d->dstlayer->delta);
36 	}else
37 		r = screenr;
38 
39 	/* now in logical coordinates */
40 
41 	/* clipr may have narrowed what we should draw on, so clip if necessary */
42 	if(!rectinrect(r, clipr)){
43 		oclipr = dst->clipr;
44 		dst->clipr = clipr;
45 		ok = drawclip(dst, &r, d->src, &p0, d->mask, &p1, &srcr, &mr);
46 		dst->clipr = oclipr;
47 		if(!ok)
48 			return;
49 	}
50 	memdraw(dst, r, d->src, p0, d->mask, p1, d->op);
51 }
52 
53 void
memdraw(Memimage * dst,Rectangle r,Memimage * src,Point p0,Memimage * mask,Point p1,int op)54 memdraw(Memimage *dst, Rectangle r, Memimage *src, Point p0, Memimage *mask, Point p1, int op)
55 {
56 	struct Draw d;
57 	Rectangle srcr, tr, mr;
58 	Memlayer *dl, *sl;
59 
60 	if(drawdebug)
61 		iprint("memdraw %p %R %p %P %p %P\n", dst, r, src, p0, mask, p1);
62 
63 	if(mask == nil)
64 		mask = memopaque;
65 
66 	if(mask->layer){
67 if(drawdebug)	iprint("mask->layer != nil\n");
68 		return;	/* too hard, at least for now */
69 	}
70 
71     Top:
72 	if(dst->layer==nil && src->layer==nil){
73 		memimagedraw(dst, r, src, p0, mask, p1, op);
74 		return;
75 	}
76 
77 	if(drawclip(dst, &r, src, &p0, mask, &p1, &srcr, &mr) == 0){
78 if(drawdebug)	iprint("drawclip dstcr %R srccr %R maskcr %R\n", dst->clipr, src->clipr, mask->clipr);
79 		return;
80 	}
81 
82 	/*
83  	 * Convert to screen coordinates.
84 	 */
85 	dl = dst->layer;
86 	if(dl != nil){
87 		r.min.x += dl->delta.x;
88 		r.min.y += dl->delta.y;
89 		r.max.x += dl->delta.x;
90 		r.max.y += dl->delta.y;
91 	}
92     Clearlayer:
93 	if(dl!=nil && dl->clear){
94 		if(src == dst){
95 			p0.x += dl->delta.x;
96 			p0.y += dl->delta.y;
97 			src = dl->screen->image;
98 		}
99 		dst = dl->screen->image;
100 		goto Top;
101 	}
102 
103 	sl = src->layer;
104 	if(sl != nil){
105 		p0.x += sl->delta.x;
106 		p0.y += sl->delta.y;
107 		srcr.min.x += sl->delta.x;
108 		srcr.min.y += sl->delta.y;
109 		srcr.max.x += sl->delta.x;
110 		srcr.max.y += sl->delta.y;
111 	}
112 
113 	/*
114 	 * Now everything is in screen coordinates.
115 	 * mask is an image.  dst and src are images or obscured layers.
116 	 */
117 
118 	/*
119 	 * if dst and src are the same layer, just draw in save area and expose.
120 	 */
121 	if(dl!=nil && dst==src){
122 		if(dl->save == nil)
123 			return;	/* refresh function makes this case unworkable */
124 		if(rectXrect(r, srcr)){
125 			tr = r;
126 			if(srcr.min.x < tr.min.x){
127 				p1.x += tr.min.x - srcr.min.x;
128 				tr.min.x = srcr.min.x;
129 			}
130 			if(srcr.min.y < tr.min.y){
131 				p1.y += tr.min.x - srcr.min.x;
132 				tr.min.y = srcr.min.y;
133 			}
134 			if(srcr.max.x > tr.max.x)
135 				tr.max.x = srcr.max.x;
136 			if(srcr.max.y > tr.max.y)
137 				tr.max.y = srcr.max.y;
138 			memlhide(dst, tr);
139 		}else{
140 			memlhide(dst, r);
141 			memlhide(dst, srcr);
142 		}
143 		memdraw(dl->save, rectsubpt(r, dl->delta), dl->save,
144 			subpt(srcr.min, src->layer->delta), mask, p1, op);
145 		memlexpose(dst, r);
146 		return;
147 	}
148 
149 	if(sl){
150 		if(sl->clear){
151 			src = sl->screen->image;
152 			if(dl != nil){
153 				r.min.x -= dl->delta.x;
154 				r.min.y -= dl->delta.y;
155 				r.max.x -= dl->delta.x;
156 				r.max.y -= dl->delta.y;
157 			}
158 			goto Top;
159 		}
160 		/* relatively rare case; use save area */
161 		if(sl->save == nil)
162 			return;	/* refresh function makes this case unworkable */
163 		memlhide(src, srcr);
164 		/* convert back to logical coordinates */
165 		p0.x -= sl->delta.x;
166 		p0.y -= sl->delta.y;
167 		srcr.min.x -= sl->delta.x;
168 		srcr.min.y -= sl->delta.y;
169 		srcr.max.x -= sl->delta.x;
170 		srcr.max.y -= sl->delta.y;
171 		src = src->layer->save;
172 	}
173 
174 	/*
175 	 * src is now an image.  dst may be an image or a clear layer
176 	 */
177 	if(dst->layer==nil)
178 		goto Top;
179 	if(dst->layer->clear)
180 		goto Clearlayer;
181 
182 	/*
183 	 * dst is an obscured layer
184 	 */
185 	d.deltas = subpt(p0, r.min);
186 	d.deltam = subpt(p1, r.min);
187 	d.dstlayer = dl;
188 	d.src = src;
189 	d.op = op;
190 	d.mask = mask;
191 	_memlayerop(ldrawop, dst, r, r, &d);
192 }
193