Blob


1 #include <u.h>
2 #include <libc.h>
3 #include <draw.h>
4 #include <memdraw.h>
5 #include <memlayer.h>
7 #define RECUR(a,b,c,d) _layerop(fn, i, Rect(a.x, b.y, c.x, d.y), clipr, etc, front->layer->rear);
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;
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 }
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;
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;
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;
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;
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;
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);