|  | #include <u.h> | 
|  | #include <libc.h> | 
|  | #include <draw.h> | 
|  | #include <memdraw.h> | 
|  | #include <memlayer.h> | 
|  |  | 
|  | 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); | 
|  | } |