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