void memlexpose(Memimage *i, Rectangle screenr) { if(rectclip(&screenr, i->layer->screen->image->r) == 0) return; _memlayerop(lexposeop, i, screenr, screenr, i->layer); }
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 _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); }
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); }