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