summaryrefslogtreecommitdiff
path: root/libmemlayer/layerop.c
diff options
context:
space:
mode:
authorCharles.Forsyth <devnull@localhost>2006-12-22 17:07:39 +0000
committerCharles.Forsyth <devnull@localhost>2006-12-22 17:07:39 +0000
commit37da2899f40661e3e9631e497da8dc59b971cbd0 (patch)
treecbc6d4680e347d906f5fa7fca73214418741df72 /libmemlayer/layerop.c
parent54bc8ff236ac10b3eaa928fd6bcfc0cdb2ba46ae (diff)
20060303a
Diffstat (limited to 'libmemlayer/layerop.c')
-rw-r--r--libmemlayer/layerop.c111
1 files changed, 111 insertions, 0 deletions
diff --git a/libmemlayer/layerop.c b/libmemlayer/layerop.c
new file mode 100644
index 00000000..042adce5
--- /dev/null
+++ b/libmemlayer/layerop.c
@@ -0,0 +1,111 @@
+#include "lib9.h"
+#include "draw.h"
+#include "memdraw.h"
+#include "memlayer.h"
+
+#define RECUR(a,b,c,d) _layerop(fn, i, Rect(a.x, b.y, c.x, d.y), clipr, etc, front->layer->rear);
+
+static void
+_layerop(
+ void (*fn)(Memimage*, Rectangle, Rectangle, void*, int),
+ Memimage *i,
+ Rectangle r,
+ Rectangle clipr,
+ void *etc,
+ Memimage *front)
+{
+ Rectangle fr;
+
+ Top:
+ if(front == i){
+ /* no one is in front of this part of window; use the screen */
+ fn(i->layer->screen->image, r, clipr, etc, 0);
+ return;
+ }
+ fr = front->layer->screenr;
+ if(rectXrect(r, fr) == 0){
+ /* r doesn't touch this window; continue on next rearmost */
+ /* assert(front && front->layer && front->layer->screen && front->layer->rear); */
+ front = front->layer->rear;
+ goto Top;
+ }
+ if(fr.max.y < r.max.y){
+ RECUR(r.min, fr.max, r.max, r.max);
+ r.max.y = fr.max.y;
+ }
+ if(r.min.y < fr.min.y){
+ RECUR(r.min, r.min, r.max, fr.min);
+ r.min.y = fr.min.y;
+ }
+ if(fr.max.x < r.max.x){
+ RECUR(fr.max, r.min, r.max, r.max);
+ r.max.x = fr.max.x;
+ }
+ if(r.min.x < fr.min.x){
+ RECUR(r.min, r.min, fr.min, r.max);
+ r.min.x = fr.min.x;
+ }
+ /* r is covered by front, so put in save area */
+ (*fn)(i->layer->save, r, clipr, etc, 1);
+}
+
+/*
+ * Assumes incoming rectangle has already been clipped to i's logical r and clipr
+ */
+void
+_memlayerop(
+ void (*fn)(Memimage*, Rectangle, Rectangle, void*, int),
+ Memimage *i,
+ Rectangle screenr, /* clipped to window boundaries */
+ Rectangle clipr, /* clipped also to clipping rectangles of hierarchy */
+ void *etc)
+{
+ Memlayer *l;
+ Rectangle r, scr;
+
+ l = i->layer;
+ if(!rectclip(&screenr, l->screenr))
+ return;
+ if(l->clear){
+ fn(l->screen->image, screenr, clipr, etc, 0);
+ return;
+ }
+ r = screenr;
+ scr = l->screen->image->clipr;
+
+ /*
+ * Do the piece on the screen
+ */
+ if(rectclip(&screenr, scr))
+ _layerop(fn, i, screenr, clipr, etc, l->screen->frontmost);
+ if(rectinrect(r, scr))
+ return;
+
+ /*
+ * Do the piece off the screen
+ */
+ if(!rectXrect(r, scr)){
+ /* completely offscreen; easy */
+ fn(l->save, r, clipr, etc, 1);
+ return;
+ }
+ if(r.min.y < scr.min.y){
+ /* above screen */
+ fn(l->save, Rect(r.min.x, r.min.y, r.max.x, scr.min.y), clipr, etc, 1);
+ r.min.y = scr.min.y;
+ }
+ if(r.max.y > scr.max.y){
+ /* below screen */
+ fn(l->save, Rect(r.min.x, scr.max.y, r.max.x, r.max.y), clipr, etc, 1);
+ r.max.y = scr.max.y;
+ }
+ if(r.min.x < scr.min.x){
+ /* left of screen */
+ fn(l->save, Rect(r.min.x, r.min.y, scr.min.x, r.max.y), clipr, etc, 1);
+ r.min.x = scr.min.x;
+ }
+ if(r.max.x > scr.max.x){
+ /* right of screen */
+ fn(l->save, Rect(scr.max.x, r.min.y, r.max.x, r.max.y), clipr, etc, 1);
+ }
+}