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