]> git.lizzy.rs Git - plan9front.git/blob - sys/src/libmemlayer/draw.c
nusb/kb: correct Mod4 scancode (125 → 91, to match what kbdfs has)
[plan9front.git] / sys / src / libmemlayer / draw.c
1 #include <u.h>
2 #include <libc.h>
3 #include <draw.h>
4 #include <memdraw.h>
5 #include <memlayer.h>
6
7 struct Draw
8 {
9         Point   deltas;
10         Point   deltam;
11         Memlayer                *dstlayer;
12         Memimage        *src;
13         Memimage        *mask;
14         int     op;
15 };
16
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;
25
26         d = etc;
27         if(insave && d->dstlayer->save==nil)
28                 return;
29
30         p0 = addpt(screenr.min, d->deltas);
31         p1 = addpt(screenr.min, d->deltam);
32
33         if(insave){
34                 r = rectsubpt(screenr, d->dstlayer->delta);
35                 clipr = rectsubpt(clipr, d->dstlayer->delta);
36         }else
37                 r = screenr;
38
39         /* now in logical coordinates */
40
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 = drawclipnorepl(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 }
52
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;
59
60         if(mask == nil)
61                 mask = memopaque;
62
63         if(mask->layer)
64                 return; /* too hard, at least for now */
65
66     Top:
67         if(dst->layer==nil && src->layer==nil){
68                 memimagedraw(dst, r, src, p0, mask, p1, op);
69                 return;
70         }
71
72         if(drawclipnorepl(dst, &r, src, &p0, mask, &p1, &srcr, &mr) == 0)
73                 return;
74
75         /*
76          * Convert to screen coordinates.
77          */
78         dl = dst->layer;
79         if(dl != nil){
80                 r.min.x += dl->delta.x;
81                 r.min.y += dl->delta.y;
82                 r.max.x += dl->delta.x;
83                 r.max.y += dl->delta.y;
84         }
85     Clearlayer:
86         if(dl!=nil && dl->clear){
87                 if(src == dst){
88                         p0.x += dl->delta.x;
89                         p0.y += dl->delta.y;
90                         src = dl->screen->image;
91                 }
92                 dst = dl->screen->image;
93                 goto Top;
94         }
95
96         sl = src->layer;
97         if(sl != nil){
98                 p0.x += sl->delta.x;
99                 p0.y += sl->delta.y;
100                 srcr.min.x += sl->delta.x;
101                 srcr.min.y += sl->delta.y;
102                 srcr.max.x += sl->delta.x;
103                 srcr.max.y += sl->delta.y;
104         }
105
106         /*
107          * Now everything is in screen coordinates.
108          * mask is an image.  dst and src are images or obscured layers.
109          */
110
111         /*
112          * if dst and src are the same layer, just draw in save area and expose.
113          */
114         if(dl!=nil && dst==src){
115                 if(dl->save == nil)
116                         return; /* refresh function makes this case unworkable */
117                 if(rectXrect(r, srcr)){
118                         tr = r;
119                         if(srcr.min.x < tr.min.x){
120                                 p1.x += tr.min.x - srcr.min.x;
121                                 tr.min.x = srcr.min.x;
122                         }
123                         if(srcr.min.y < tr.min.y){
124                                 p1.y += tr.min.x - srcr.min.x;
125                                 tr.min.y = srcr.min.y;
126                         }
127                         if(srcr.max.x > tr.max.x)
128                                 tr.max.x = srcr.max.x;
129                         if(srcr.max.y > tr.max.y)
130                                 tr.max.y = srcr.max.y;
131                         memlhide(dst, tr);
132                 }else{
133                         memlhide(dst, r);
134                         memlhide(dst, srcr);
135                 }
136                 memdraw(dl->save, rectsubpt(r, dl->delta), dl->save,
137                         subpt(srcr.min, src->layer->delta), mask, p1, op);
138                 memlexpose(dst, r);
139                 return;
140         }
141
142         if(sl){
143                 if(sl->clear){
144                         src = sl->screen->image;
145                         if(dl != nil){
146                                 r.min.x -= dl->delta.x;
147                                 r.min.y -= dl->delta.y;
148                                 r.max.x -= dl->delta.x;
149                                 r.max.y -= dl->delta.y;
150                         }
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.op = op;
183         d.mask = mask;
184         _memlayerop(ldrawop, dst, r, r, &d);
185 }