Blob


1 #include <u.h>
2 #include <libc.h>
3 #include <draw.h>
4 #include <memdraw.h>
5 #include <memlayer.h>
7 struct Draw
8 {
9 Point deltas;
10 Point deltam;
11 Memlayer *dstlayer;
12 Memimage *src;
13 Memimage *mask;
14 int op;
15 };
17 static
18 void
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;
26 d = etc;
27 if(insave && d->dstlayer->save==nil)
28 return;
30 p0 = addpt(screenr.min, d->deltas);
31 p1 = addpt(screenr.min, d->deltam);
33 if(insave){
34 r = rectsubpt(screenr, d->dstlayer->delta);
35 clipr = rectsubpt(clipr, d->dstlayer->delta);
36 }else
37 r = screenr;
39 /* now in logical coordinates */
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 }
53 void
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;
60 if(drawdebug)
61 iprint("memdraw %p %R %p %P %p %P\n", dst, r, src, p0, mask, p1);
63 if(mask == nil)
64 mask = memopaque;
66 if(mask->layer){
67 if(drawdebug) iprint("mask->layer != nil\n");
68 return; /* too hard, at least for now */
69 }
71 Top:
72 if(dst->layer==nil && src->layer==nil){
73 memimagedraw(dst, r, src, p0, mask, p1, op);
74 return;
75 }
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 }
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;
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;
113 /*
114 * Now everything is in screen coordinates.
115 * mask is an image. dst and src are images or obscured layers.
116 */
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;
130 if(srcr.min.y < tr.min.y){
131 p1.y += tr.min.x - srcr.min.x;
132 tr.min.y = srcr.min.y;
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);
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;
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;
158 goto Top;
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;
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;
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);