From 324891a5579d6f504201a6107369c64dab245a98 Mon Sep 17 00:00:00 2001 From: rsc Date: Sun, 25 Jun 2006 18:58:06 +0000 Subject: separate out --- src/libmemlayer/draw.c | 192 ++++++++++++++++++++++++++++++++++++++++++ src/libmemlayer/lalloc.c | 79 +++++++++++++++++ src/libmemlayer/layerop.c | 112 ++++++++++++++++++++++++ src/libmemlayer/ldelete.c | 67 +++++++++++++++ src/libmemlayer/lhide.c | 67 +++++++++++++++ src/libmemlayer/line.c | 122 +++++++++++++++++++++++++++ src/libmemlayer/load.c | 55 ++++++++++++ src/libmemlayer/lorigin.c | 107 +++++++++++++++++++++++ src/libmemlayer/lsetrefresh.c | 35 ++++++++ src/libmemlayer/ltofront.c | 80 ++++++++++++++++++ src/libmemlayer/ltorear.c | 69 +++++++++++++++ src/libmemlayer/mkfile | 25 ++++++ src/libmemlayer/unload.c | 52 ++++++++++++ 13 files changed, 1062 insertions(+) create mode 100644 src/libmemlayer/draw.c create mode 100644 src/libmemlayer/lalloc.c create mode 100644 src/libmemlayer/layerop.c create mode 100644 src/libmemlayer/ldelete.c create mode 100644 src/libmemlayer/lhide.c create mode 100644 src/libmemlayer/line.c create mode 100644 src/libmemlayer/load.c create mode 100644 src/libmemlayer/lorigin.c create mode 100644 src/libmemlayer/lsetrefresh.c create mode 100644 src/libmemlayer/ltofront.c create mode 100644 src/libmemlayer/ltorear.c create mode 100644 src/libmemlayer/mkfile create mode 100644 src/libmemlayer/unload.c (limited to 'src/libmemlayer') diff --git a/src/libmemlayer/draw.c b/src/libmemlayer/draw.c new file mode 100644 index 00000000..c352a0b2 --- /dev/null +++ b/src/libmemlayer/draw.c @@ -0,0 +1,192 @@ +#include +#include +#include +#include +#include + +struct Draw +{ + Point deltas; + Point deltam; + Memlayer *dstlayer; + Memimage *src; + Memimage *mask; + int op; +}; + +static +void +ldrawop(Memimage *dst, Rectangle screenr, Rectangle clipr, void *etc, int insave) +{ + struct Draw *d; + Point p0, p1; + Rectangle oclipr, srcr, r, mr; + int ok; + + d = etc; + if(insave && d->dstlayer->save==nil) + return; + + p0 = addpt(screenr.min, d->deltas); + p1 = addpt(screenr.min, d->deltam); + + if(insave){ + r = rectsubpt(screenr, d->dstlayer->delta); + clipr = rectsubpt(clipr, d->dstlayer->delta); + }else + r = screenr; + + /* now in logical coordinates */ + + /* clipr may have narrowed what we should draw on, so clip if necessary */ + if(!rectinrect(r, clipr)){ + oclipr = dst->clipr; + dst->clipr = clipr; + ok = drawclip(dst, &r, d->src, &p0, d->mask, &p1, &srcr, &mr); + dst->clipr = oclipr; + if(!ok) + return; + } + memdraw(dst, r, d->src, p0, d->mask, p1, d->op); +} + +void +memdraw(Memimage *dst, Rectangle r, Memimage *src, Point p0, Memimage *mask, Point p1, int op) +{ + struct Draw d; + Rectangle srcr, tr, mr; + Memlayer *dl, *sl; + + if(drawdebug) + iprint("memdraw %p %R %p %P %p %P\n", dst, r, src, p0, mask, p1); + + if(mask == nil) + mask = memopaque; + + if(mask->layer){ +if(drawdebug) iprint("mask->layer != nil\n"); + return; /* too hard, at least for now */ + } + + Top: + if(dst->layer==nil && src->layer==nil){ + memimagedraw(dst, r, src, p0, mask, p1, op); + return; + } + + if(drawclip(dst, &r, src, &p0, mask, &p1, &srcr, &mr) == 0){ +if(drawdebug) iprint("drawclip dstcr %R srccr %R maskcr %R\n", dst->clipr, src->clipr, mask->clipr); + return; + } + + /* + * Convert to screen coordinates. + */ + dl = dst->layer; + if(dl != nil){ + r.min.x += dl->delta.x; + r.min.y += dl->delta.y; + r.max.x += dl->delta.x; + r.max.y += dl->delta.y; + } + Clearlayer: + if(dl!=nil && dl->clear){ + if(src == dst){ + p0.x += dl->delta.x; + p0.y += dl->delta.y; + src = dl->screen->image; + } + dst = dl->screen->image; + goto Top; + } + + sl = src->layer; + if(sl != nil){ + p0.x += sl->delta.x; + p0.y += sl->delta.y; + srcr.min.x += sl->delta.x; + srcr.min.y += sl->delta.y; + srcr.max.x += sl->delta.x; + srcr.max.y += sl->delta.y; + } + + /* + * Now everything is in screen coordinates. + * mask is an image. dst and src are images or obscured layers. + */ + + /* + * if dst and src are the same layer, just draw in save area and expose. + */ + if(dl!=nil && dst==src){ + if(dl->save == nil) + return; /* refresh function makes this case unworkable */ + if(rectXrect(r, srcr)){ + tr = r; + if(srcr.min.x < tr.min.x){ + p1.x += tr.min.x - srcr.min.x; + tr.min.x = srcr.min.x; + } + if(srcr.min.y < tr.min.y){ + p1.y += tr.min.x - srcr.min.x; + tr.min.y = srcr.min.y; + } + if(srcr.max.x > tr.max.x) + tr.max.x = srcr.max.x; + if(srcr.max.y > tr.max.y) + tr.max.y = srcr.max.y; + memlhide(dst, tr); + }else{ + memlhide(dst, r); + memlhide(dst, srcr); + } + memdraw(dl->save, rectsubpt(r, dl->delta), dl->save, + subpt(srcr.min, src->layer->delta), mask, p1, op); + memlexpose(dst, r); + return; + } + + if(sl){ + if(sl->clear){ + src = sl->screen->image; + if(dl != nil){ + r.min.x -= dl->delta.x; + r.min.y -= dl->delta.y; + r.max.x -= dl->delta.x; + r.max.y -= dl->delta.y; + } + goto Top; + } + /* relatively rare case; use save area */ + if(sl->save == nil) + return; /* refresh function makes this case unworkable */ + memlhide(src, srcr); + /* convert back to logical coordinates */ + p0.x -= sl->delta.x; + p0.y -= sl->delta.y; + srcr.min.x -= sl->delta.x; + srcr.min.y -= sl->delta.y; + srcr.max.x -= sl->delta.x; + srcr.max.y -= sl->delta.y; + src = src->layer->save; + } + + /* + * src is now an image. dst may be an image or a clear layer + */ + if(dst->layer==nil) + goto Top; + if(dst->layer->clear) + goto Clearlayer; + + /* + * dst is an obscured layer + */ + d.deltas = subpt(p0, r.min); + d.deltam = subpt(p1, r.min); + d.dstlayer = dl; + d.src = src; + d.op = op; + d.mask = mask; + _memlayerop(ldrawop, dst, r, r, &d); +} diff --git a/src/libmemlayer/lalloc.c b/src/libmemlayer/lalloc.c new file mode 100644 index 00000000..17d934d3 --- /dev/null +++ b/src/libmemlayer/lalloc.c @@ -0,0 +1,79 @@ +#include +#include +#include +#include +#include + +Memimage* +memlalloc(Memscreen *s, Rectangle screenr, Refreshfn refreshfn, void *refreshptr, u32int val) +{ + Memlayer *l; + Memimage *n; + static Memimage *paint; + + if(paint == nil){ + paint = allocmemimage(Rect(0,0,1,1), RGBA32); + if(paint == nil) + return nil; + paint->flags |= Frepl; + paint->clipr = Rect(-0x3FFFFFF, -0x3FFFFFF, 0x3FFFFFF, 0x3FFFFFF); + } + + n = allocmemimaged(screenr, s->image->chan, s->image->data, nil); + if(n == nil) + return nil; + l = malloc(sizeof(Memlayer)); + if(l == nil){ + free(n); + return nil; + } + + l->screen = s; + if(refreshfn) + l->save = nil; + else{ + l->save = allocmemimage(screenr, s->image->chan); + if(l->save == nil){ + free(l); + free(n); + return nil; + } + /* allocmemimage doesn't initialize memory; this paints save area */ + if(val != DNofill) + memfillcolor(l->save, val); + } + l->refreshfn = refreshfn; + l->refreshptr = nil; /* don't set it until we're done */ + l->screenr = screenr; + l->delta = Pt(0,0); + + n->data->ref++; + n->zero = s->image->zero; + n->width = s->image->width; + n->layer = l; + + /* start with new window behind all existing ones */ + l->front = s->rearmost; + l->rear = nil; + if(s->rearmost) + s->rearmost->layer->rear = n; + s->rearmost = n; + if(s->frontmost == nil) + s->frontmost = n; + l->clear = 0; + + /* now pull new window to front */ + _memltofrontfill(n, val != DNofill); + l->refreshptr = refreshptr; + + /* + * paint with requested color; previously exposed areas are already right + * if this window has backing store, but just painting the whole thing is simplest. + */ + if(val != DNofill){ + memsetchan(paint, n->chan); + memfillcolor(paint, val); + memdraw(n, n->r, paint, n->r.min, nil, n->r.min, S); + } + return n; +} diff --git a/src/libmemlayer/layerop.c b/src/libmemlayer/layerop.c new file mode 100644 index 00000000..800ffc85 --- /dev/null +++ b/src/libmemlayer/layerop.c @@ -0,0 +1,112 @@ +#include +#include +#include +#include +#include + +#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); + } +} diff --git a/src/libmemlayer/ldelete.c b/src/libmemlayer/ldelete.c new file mode 100644 index 00000000..34cd6ead --- /dev/null +++ b/src/libmemlayer/ldelete.c @@ -0,0 +1,67 @@ +#include +#include +#include +#include +#include + +void +memldelete(Memimage *i) +{ + Memscreen *s; + Memlayer *l; + + l = i->layer; + /* free backing store and disconnect refresh, to make pushback fast */ + freememimage(l->save); + l->save = nil; + l->refreshptr = nil; + memltorear(i); + + /* window is now the rearmost; clean up screen structures and deallocate */ + s = i->layer->screen; + if(s->fill){ + i->clipr = i->r; + memdraw(i, i->r, s->fill, i->r.min, nil, i->r.min, S); + } + if(l->front){ + l->front->layer->rear = nil; + s->rearmost = l->front; + }else{ + s->frontmost = nil; + s->rearmost = nil; + } + free(l); + freememimage(i); +} + +/* + * Just free the data structures, don't do graphics + */ +void +memlfree(Memimage *i) +{ + Memlayer *l; + + l = i->layer; + freememimage(l->save); + free(l); + freememimage(i); +} + +void +_memlsetclear(Memscreen *s) +{ + Memimage *i, *j; + Memlayer *l; + + for(i=s->rearmost; i; i=i->layer->front){ + l = i->layer; + l->clear = rectinrect(l->screenr, l->screen->image->clipr); + if(l->clear) + for(j=l->front; j; j=j->layer->front) + if(rectXrect(l->screenr, j->layer->screenr)){ + l->clear = 0; + break; + } + } +} diff --git a/src/libmemlayer/lhide.c b/src/libmemlayer/lhide.c new file mode 100644 index 00000000..d6aaa55f --- /dev/null +++ b/src/libmemlayer/lhide.c @@ -0,0 +1,67 @@ +#include +#include +#include +#include +#include + +/* + * Hide puts that portion of screenr now on the screen into the window's save area. + * Expose puts that portion of screenr now in the save area onto the screen. + * + * Hide and Expose both require that the layer structures in the screen + * match the geometry they are being asked to update, that is, they update the + * save area (hide) or screen (expose) based on what those structures tell them. + * This means they must be called at the correct time during window shuffles. + */ + +static +void +lhideop(Memimage *src, Rectangle screenr, Rectangle clipr, void *etc, int insave) +{ + Rectangle r; + Memlayer *l; + + USED(clipr.min.x); + USED(insave); + l = etc; + if(src != l->save){ /* do nothing if src is already in save area */ + r = rectsubpt(screenr, l->delta); + memdraw(l->save, r, src, screenr.min, nil, screenr.min, S); + } +} + +void +memlhide(Memimage *i, Rectangle screenr) +{ + if(i->layer->save == nil) + return; + if(rectclip(&screenr, i->layer->screen->image->r) == 0) + return; + _memlayerop(lhideop, i, screenr, screenr, i->layer); +} + +static +void +lexposeop(Memimage *dst, Rectangle screenr, Rectangle clipr, void *etc, int insave) +{ + Memlayer *l; + Rectangle r; + + USED(clipr.min.x); + if(insave) /* if dst is save area, don't bother */ + return; + l = etc; + r = rectsubpt(screenr, l->delta); + if(l->save) + memdraw(dst, screenr, l->save, r.min, nil, r.min, S); + else + l->refreshfn(dst, r, l->refreshptr); +} + +void +memlexpose(Memimage *i, Rectangle screenr) +{ + if(rectclip(&screenr, i->layer->screen->image->r) == 0) + return; + _memlayerop(lexposeop, i, screenr, screenr, i->layer); +} diff --git a/src/libmemlayer/line.c b/src/libmemlayer/line.c new file mode 100644 index 00000000..f74930ef --- /dev/null +++ b/src/libmemlayer/line.c @@ -0,0 +1,122 @@ +#include +#include +#include +#include +#include + +struct Lline +{ + Point p0; + Point p1; + Point delta; + int end0; + int end1; + int radius; + Point sp; + Memlayer *dstlayer; + Memimage *src; + int op; +}; + +static void llineop(Memimage*, Rectangle, Rectangle, void*, int); + +static +void +_memline(Memimage *dst, Point p0, Point p1, int end0, int end1, int radius, Memimage *src, Point sp, Rectangle clipr, int op) +{ + Rectangle r; + struct Lline ll; + Point d; + int srcclipped; + Memlayer *dl; + + if(radius < 0) + return; + if(src->layer) /* can't draw line with layered source */ + return; + srcclipped = 0; + + Top: + dl = dst->layer; + if(dl == nil){ + _memimageline(dst, p0, p1, end0, end1, radius, src, sp, clipr, op); + return; + } + if(!srcclipped){ + d = subpt(sp, p0); + if(rectclip(&clipr, rectsubpt(src->clipr, d)) == 0) + return; + if((src->flags&Frepl)==0 && rectclip(&clipr, rectsubpt(src->r, d))==0) + return; + srcclipped = 1; + } + + /* dst is known to be a layer */ + p0.x += dl->delta.x; + p0.y += dl->delta.y; + p1.x += dl->delta.x; + p1.y += dl->delta.y; + clipr.min.x += dl->delta.x; + clipr.min.y += dl->delta.y; + clipr.max.x += dl->delta.x; + clipr.max.y += dl->delta.y; + if(dl->clear){ + dst = dst->layer->screen->image; + goto Top; + } + + /* XXX */ + /* this is not the correct set of tests */ +/* if(log2[dst->depth] != log2[src->depth] || log2[dst->depth]!=3) */ +/* return; */ + + /* can't use sutherland-cohen clipping because lines are wide */ + r = memlinebbox(p0, p1, end0, end1, radius); + /* + * r is now a bounding box for the line; + * use it as a clipping rectangle for subdivision + */ + if(rectclip(&r, clipr) == 0) + return; + ll.p0 = p0; + ll.p1 = p1; + ll.end0 = end0; + ll.end1 = end1; + ll.sp = sp; + ll.dstlayer = dst->layer; + ll.src = src; + ll.radius = radius; + ll.delta = dl->delta; + ll.op = op; + _memlayerop(llineop, dst, r, r, &ll); +} + +static +void +llineop(Memimage *dst, Rectangle screenr, Rectangle clipr, void *etc, int insave) +{ + struct Lline *ll; + Point p0, p1; + + USED(screenr.min.x); + ll = etc; + if(insave && ll->dstlayer->save==nil) + return; + if(!rectclip(&clipr, screenr)) + return; + if(insave){ + p0 = subpt(ll->p0, ll->delta); + p1 = subpt(ll->p1, ll->delta); + clipr = rectsubpt(clipr, ll->delta); + }else{ + p0 = ll->p0; + p1 = ll->p1; + } + _memline(dst, p0, p1, ll->end0, ll->end1, ll->radius, ll->src, ll->sp, clipr, ll->op); +} + +void +memline(Memimage *dst, Point p0, Point p1, int end0, int end1, int radius, Memimage *src, Point sp, int op) +{ + _memline(dst, p0, p1, end0, end1, radius, src, sp, dst->clipr, op); +} diff --git a/src/libmemlayer/load.c b/src/libmemlayer/load.c new file mode 100644 index 00000000..d211564b --- /dev/null +++ b/src/libmemlayer/load.c @@ -0,0 +1,55 @@ +#include +#include +#include +#include +#include + +int +memload(Memimage *dst, Rectangle r, uchar *data, int n, int iscompressed) +{ + int (*loadfn)(Memimage*, Rectangle, uchar*, int); + Memimage *tmp; + Memlayer *dl; + Rectangle lr; + int dx; + + loadfn = loadmemimage; + if(iscompressed) + loadfn = cloadmemimage; + + Top: + dl = dst->layer; + if(dl == nil) + return loadfn(dst, r, data, n); + + /* + * Convert to screen coordinates. + */ + lr = r; + r.min.x += dl->delta.x; + r.min.y += dl->delta.y; + r.max.x += dl->delta.x; + r.max.y += dl->delta.y; + dx = dl->delta.x&(7/dst->depth); + if(dl->clear && dx==0){ + dst = dl->screen->image; + goto Top; + } + + /* + * dst is an obscured layer or data is unaligned + */ + if(dl->save && dx==0){ + n = loadfn(dl->save, lr, data, n); + if(n > 0) + memlexpose(dst, r); + return n; + } + tmp = allocmemimage(lr, dst->chan); + if(tmp == nil) + return -1; + n = loadfn(tmp, lr, data, n); + memdraw(dst, lr, tmp, lr.min, nil, lr.min, S); + freememimage(tmp); + return n; +} diff --git a/src/libmemlayer/lorigin.c b/src/libmemlayer/lorigin.c new file mode 100644 index 00000000..0926ee8d --- /dev/null +++ b/src/libmemlayer/lorigin.c @@ -0,0 +1,107 @@ +#include +#include +#include +#include +#include + +/* + * Place i so i->r.min = log, i->layer->screenr.min == scr. +*/ +int +memlorigin(Memimage *i, Point log, Point scr) +{ + Memlayer *l; + Memscreen *s; + Memimage *t, *shad, *nsave; + Rectangle x, newr, oldr; + Point delta; + int overlap, eqlog, eqscr, wasclear; + + l = i->layer; + s = l->screen; + oldr = l->screenr; + newr = Rect(scr.x, scr.y, scr.x+Dx(oldr), scr.y+Dy(oldr)); + eqscr = eqpt(scr, oldr.min); + eqlog = eqpt(log, i->r.min); + if(eqscr && eqlog) + return 0; + nsave = nil; + if(eqlog==0 && l->save!=nil){ + nsave = allocmemimage(Rect(log.x, log.y, log.x+Dx(oldr), log.y+Dy(oldr)), i->chan); + if(nsave == nil) + return -1; + } + + /* + * Bring it to front and move logical coordinate system. + */ + memltofront(i); + wasclear = l->clear; + if(nsave){ + if(!wasclear) + memimagedraw(nsave, nsave->r, l->save, l->save->r.min, nil, Pt(0,0), S); + freememimage(l->save); + l->save = nsave; + } + delta = subpt(log, i->r.min); + i->r = rectaddpt(i->r, delta); + i->clipr = rectaddpt(i->clipr, delta); + l->delta = subpt(l->screenr.min, i->r.min); + if(eqscr) + return 0; + + /* + * To clean up old position, make a shadow window there, don't paint it, + * push it behind this one, and (later) delete it. Because the refresh function + * for this fake window is a no-op, this will cause no graphics action except + * to restore the background and expose the windows previously hidden. + */ + shad = memlalloc(s, oldr, memlnorefresh, nil, DNofill); + if(shad == nil) + return -1; + s->frontmost = i; + if(s->rearmost == i) + s->rearmost = shad; + else + l->rear->layer->front = shad; + shad->layer->front = i; + shad->layer->rear = l->rear; + l->rear = shad; + l->front = nil; + shad->layer->clear = 0; + + /* + * Shadow is now holding down the fort at the old position. + * Move the window and hide things obscured by new position. + */ + for(t=l->rear->layer->rear; t!=nil; t=t->layer->rear){ + x = newr; + overlap = rectclip(&x, t->layer->screenr); + if(overlap){ + memlhide(t, x); + t->layer->clear = 0; + } + } + l->screenr = newr; + l->delta = subpt(scr, i->r.min); + l->clear = rectinrect(newr, l->screen->image->clipr); + + /* + * Everything's covered. Copy to new position and delete shadow window. + */ + if(wasclear) + memdraw(s->image, newr, s->image, oldr.min, nil, Pt(0,0), S); + else + memlexpose(i, newr); + memldelete(shad); + + return 1; +} + +void +memlnorefresh(Memimage *l, Rectangle r, void *v) +{ + USED(l); + USED(r.min.x); + USED(v); +} diff --git a/src/libmemlayer/lsetrefresh.c b/src/libmemlayer/lsetrefresh.c new file mode 100644 index 00000000..526bd668 --- /dev/null +++ b/src/libmemlayer/lsetrefresh.c @@ -0,0 +1,35 @@ +#include +#include +#include +#include +#include + +int +memlsetrefresh(Memimage *i, Refreshfn fn, void *ptr) +{ + Memlayer *l; + + l = i->layer; + if(l->refreshfn!=0 && fn!=0){ /* just change functions */ + l->refreshfn = fn; + l->refreshptr = ptr; + return 1; + } + + if(l->refreshfn == 0){ /* is using backup image; just free it */ + freememimage(l->save); + l->save = nil; + l->refreshfn = fn; + l->refreshptr = ptr; + return 1; + } + + l->save = allocmemimage(i->r, i->chan); + if(l->save == nil) + return 0; + /* easiest way is just to update the entire save area */ + l->refreshfn(i, i->r, l->refreshptr); + l->refreshfn = 0; + l->refreshptr = nil; + return 1; +} diff --git a/src/libmemlayer/ltofront.c b/src/libmemlayer/ltofront.c new file mode 100644 index 00000000..447b40bd --- /dev/null +++ b/src/libmemlayer/ltofront.c @@ -0,0 +1,80 @@ +#include +#include +#include +#include +#include + +/* + * Pull i towards top of screen, just behind front +*/ +static +void +_memltofront(Memimage *i, Memimage *front, int fill) +{ + Memlayer *l; + Memscreen *s; + Memimage *f, *ff, *rr; + Rectangle x; + int overlap; + + l = i->layer; + s = l->screen; + while(l->front != front){ + f = l->front; + x = l->screenr; + overlap = rectclip(&x, f->layer->screenr); + if(overlap){ + memlhide(f, x); + f->layer->clear = 0; + } + /* swap l and f in screen's list */ + ff = f->layer->front; + rr = l->rear; + if(ff == nil) + s->frontmost = i; + else + ff->layer->rear = i; + if(rr == nil) + s->rearmost = f; + else + rr->layer->front = f; + l->front = ff; + l->rear = f; + f->layer->front = i; + f->layer->rear = rr; + if(overlap && fill) + memlexpose(i, x); + } +} + +void +_memltofrontfill(Memimage *i, int fill) +{ + _memltofront(i, nil, fill); + _memlsetclear(i->layer->screen); +} + +void +memltofront(Memimage *i) +{ + _memltofront(i, nil, 1); + _memlsetclear(i->layer->screen); +} + +void +memltofrontn(Memimage **ip, int n) +{ + Memimage *i, *front; + Memscreen *s; + + if(n == 0) + return; + front = nil; + while(--n >= 0){ + i = *ip++; + _memltofront(i, front, 1); + front = i; + } + s = front->layer->screen; + _memlsetclear(s); +} diff --git a/src/libmemlayer/ltorear.c b/src/libmemlayer/ltorear.c new file mode 100644 index 00000000..d53e8cc9 --- /dev/null +++ b/src/libmemlayer/ltorear.c @@ -0,0 +1,69 @@ +#include +#include +#include +#include +#include + +void +_memltorear(Memimage *i, Memimage *rear) +{ + Memlayer *l; + Memscreen *s; + Memimage *f, *r, *rr; + Rectangle x; + int overlap; + + l = i->layer; + s = l->screen; + while(l->rear != rear){ + r = l->rear; + x = l->screenr; + overlap = rectclip(&x, r->layer->screenr); + if(overlap){ + memlhide(i, x); + l->clear = 0; + } + /* swap l and r in screen's list */ + rr = r->layer->rear; + f = l->front; + if(rr == nil) + s->rearmost = i; + else + rr->layer->front = i; + if(f == nil) + s->frontmost = r; + else + f->layer->rear = r; + l->rear = rr; + l->front = r; + r->layer->rear = i; + r->layer->front = f; + if(overlap) + memlexpose(r, x); + } +} + +void +memltorear(Memimage *i) +{ + _memltorear(i, nil); + _memlsetclear(i->layer->screen); +} + +void +memltorearn(Memimage **ip, int n) +{ + Memimage *i, *rear; + Memscreen *s; + + if(n == 0) + return; + rear = nil; + while(--n >= 0){ + i = *ip++; + _memltorear(i, rear); + rear = i; + } + s = rear->layer->screen; + _memlsetclear(s); +} diff --git a/src/libmemlayer/mkfile b/src/libmemlayer/mkfile new file mode 100644 index 00000000..c1d05419 --- /dev/null +++ b/src/libmemlayer/mkfile @@ -0,0 +1,25 @@ +<$PLAN9/src/mkhdr + +LIB=libmemlayer.a + +OFILES=\ + draw.$O\ + lalloc.$O\ + layerop.$O\ + ldelete.$O\ + lhide.$O\ + line.$O\ + load.$O\ + lorigin.$O\ + lsetrefresh.$O\ + ltofront.$O\ + ltorear.$O\ + unload.$O\ + +HFILES=\ + $PLAN9/include/draw.h\ + $PLAN9/include/memdraw.h\ + $PLAN9/include/memlayer.h\ + +<$PLAN9/src/mksyslib + diff --git a/src/libmemlayer/unload.c b/src/libmemlayer/unload.c new file mode 100644 index 00000000..b9534117 --- /dev/null +++ b/src/libmemlayer/unload.c @@ -0,0 +1,52 @@ +#include +#include +#include +#include +#include + +int +memunload(Memimage *src, Rectangle r, uchar *data, int n) +{ + Memimage *tmp; + Memlayer *dl; + Rectangle lr; + int dx; + + Top: + dl = src->layer; + if(dl == nil) + return unloadmemimage(src, r, data, n); + + /* + * Convert to screen coordinates. + */ + lr = r; + r.min.x += dl->delta.x; + r.min.y += dl->delta.y; + r.max.x += dl->delta.x; + r.max.y += dl->delta.y; + dx = dl->delta.x&(7/src->depth); + if(dl->clear && dx==0){ + src = dl->screen->image; + goto Top; + } + + /* + * src is an obscured layer or data is unaligned + */ + if(dl->save && dx==0){ + if(dl->refreshfn != 0) + return -1; /* can't unload window if it's not Refbackup */ + if(n > 0) + memlhide(src, r); + n = unloadmemimage(dl->save, lr, data, n); + return n; + } + tmp = allocmemimage(lr, src->chan); + if(tmp == nil) + return -1; + memdraw(tmp, lr, src, lr.min, nil, lr.min, S); + n = unloadmemimage(tmp, lr, data, n); + freememimage(tmp); + return n; +} -- cgit v1.2.3