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