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