1 #include "lib9.h" 2 #include "draw.h" 3 #include "memdraw.h" 4 #include "memlayer.h" 5 6 #define RECUR(a,b,c,d) _layerop(fn, i, Rect(a.x, b.y, c.x, d.y), clipr, etc, front->layer->rear); 7 8 static void 9 _layerop( 10 void (*fn)(Memimage*, Rectangle, Rectangle, void*, int), 11 Memimage *i, 12 Rectangle r, 13 Rectangle clipr, 14 void *etc, 15 Memimage *front) 16 { 17 Rectangle fr; 18 19 Top: 20 if(front == i){ 21 /* no one is in front of this part of window; use the screen */ 22 fn(i->layer->screen->image, r, clipr, etc, 0); 23 return; 24 } 25 fr = front->layer->screenr; 26 if(rectXrect(r, fr) == 0){ 27 /* r doesn't touch this window; continue on next rearmost */ 28 /* assert(front && front->layer && front->layer->screen && front->layer->rear); */ 29 front = front->layer->rear; 30 goto Top; 31 } 32 if(fr.max.y < r.max.y){ 33 RECUR(r.min, fr.max, r.max, r.max); 34 r.max.y = fr.max.y; 35 } 36 if(r.min.y < fr.min.y){ 37 RECUR(r.min, r.min, r.max, fr.min); 38 r.min.y = fr.min.y; 39 } 40 if(fr.max.x < r.max.x){ 41 RECUR(fr.max, r.min, r.max, r.max); 42 r.max.x = fr.max.x; 43 } 44 if(r.min.x < fr.min.x){ 45 RECUR(r.min, r.min, fr.min, r.max); 46 r.min.x = fr.min.x; 47 } 48 /* r is covered by front, so put in save area */ 49 (*fn)(i->layer->save, r, clipr, etc, 1); 50 } 51 52 /* 53 * Assumes incoming rectangle has already been clipped to i's logical r and clipr 54 */ 55 void 56 _memlayerop( 57 void (*fn)(Memimage*, Rectangle, Rectangle, void*, int), 58 Memimage *i, 59 Rectangle screenr, /* clipped to window boundaries */ 60 Rectangle clipr, /* clipped also to clipping rectangles of hierarchy */ 61 void *etc) 62 { 63 Memlayer *l; 64 Rectangle r, scr; 65 66 l = i->layer; 67 if(!rectclip(&screenr, l->screenr)) 68 return; 69 if(l->clear){ 70 fn(l->screen->image, screenr, clipr, etc, 0); 71 return; 72 } 73 r = screenr; 74 scr = l->screen->image->clipr; 75 76 /* 77 * Do the piece on the screen 78 */ 79 if(rectclip(&screenr, scr)) 80 _layerop(fn, i, screenr, clipr, etc, l->screen->frontmost); 81 if(rectinrect(r, scr)) 82 return; 83 84 /* 85 * Do the piece off the screen 86 */ 87 if(!rectXrect(r, scr)){ 88 /* completely offscreen; easy */ 89 fn(l->save, r, clipr, etc, 1); 90 return; 91 } 92 if(r.min.y < scr.min.y){ 93 /* above screen */ 94 fn(l->save, Rect(r.min.x, r.min.y, r.max.x, scr.min.y), clipr, etc, 1); 95 r.min.y = scr.min.y; 96 } 97 if(r.max.y > scr.max.y){ 98 /* below screen */ 99 fn(l->save, Rect(r.min.x, scr.max.y, r.max.x, r.max.y), clipr, etc, 1); 100 r.max.y = scr.max.y; 101 } 102 if(r.min.x < scr.min.x){ 103 /* left of screen */ 104 fn(l->save, Rect(r.min.x, r.min.y, scr.min.x, r.max.y), clipr, etc, 1); 105 r.min.x = scr.min.x; 106 } 107 if(r.max.x > scr.max.x){ 108 /* right of screen */ 109 fn(l->save, Rect(scr.max.x, r.min.y, r.max.x, r.max.y), clipr, etc, 1); 110 } 111 } 112