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