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