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