123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201 |
- /*
- * This file is part of the UCB release of Plan 9. It is subject to the license
- * terms in the LICENSE file found in the top-level directory of this
- * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
- * part of the UCB release of Plan 9, including this file, may be copied,
- * modified, propagated, or distributed except according to the terms contained
- * in the LICENSE file.
- */
- #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);
- }
|