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
_layerop(void (* fn)(Memimage *,Rectangle,Rectangle,void *,int),Memimage * i,Rectangle r,Rectangle clipr,void * etc,Memimage * front)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
_memlayerop(void (* fn)(Memimage *,Rectangle,Rectangle,void *,int),Memimage * i,Rectangle screenr,Rectangle clipr,void * etc)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