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