xref: /plan9/sys/src/cmd/unix/drawterm/libmemlayer/draw.c (revision 8ccd4a6360d974db7bd7bbd4f37e7018419ea908)
1*8ccd4a63SDavid du Colombier #include <u.h>
2*8ccd4a63SDavid du Colombier #include <libc.h>
3*8ccd4a63SDavid du Colombier #include <draw.h>
4*8ccd4a63SDavid du Colombier #include <memdraw.h>
5*8ccd4a63SDavid du Colombier #include <memlayer.h>
67dd7cddfSDavid du Colombier 
77dd7cddfSDavid du Colombier struct Draw
87dd7cddfSDavid du Colombier {
97dd7cddfSDavid du Colombier 	Point	deltas;
107dd7cddfSDavid du Colombier 	Point	deltam;
117dd7cddfSDavid du Colombier 	Memlayer		*dstlayer;
127dd7cddfSDavid du Colombier 	Memimage	*src;
137dd7cddfSDavid du Colombier 	Memimage	*mask;
14*8ccd4a63SDavid du Colombier 	int	op;
157dd7cddfSDavid du Colombier };
167dd7cddfSDavid du Colombier 
177dd7cddfSDavid du Colombier static
187dd7cddfSDavid du Colombier void
ldrawop(Memimage * dst,Rectangle screenr,Rectangle clipr,void * etc,int insave)197dd7cddfSDavid du Colombier ldrawop(Memimage *dst, Rectangle screenr, Rectangle clipr, void *etc, int insave)
207dd7cddfSDavid du Colombier {
217dd7cddfSDavid du Colombier 	struct Draw *d;
227dd7cddfSDavid du Colombier 	Point p0, p1;
237dd7cddfSDavid du Colombier 	Rectangle oclipr, srcr, r, mr;
247dd7cddfSDavid du Colombier 	int ok;
257dd7cddfSDavid du Colombier 
267dd7cddfSDavid du Colombier 	d = etc;
277dd7cddfSDavid du Colombier 	if(insave && d->dstlayer->save==nil)
287dd7cddfSDavid du Colombier 		return;
297dd7cddfSDavid du Colombier 
307dd7cddfSDavid du Colombier 	p0 = addpt(screenr.min, d->deltas);
317dd7cddfSDavid du Colombier 	p1 = addpt(screenr.min, d->deltam);
327dd7cddfSDavid du Colombier 
337dd7cddfSDavid du Colombier 	if(insave){
347dd7cddfSDavid du Colombier 		r = rectsubpt(screenr, d->dstlayer->delta);
357dd7cddfSDavid du Colombier 		clipr = rectsubpt(clipr, d->dstlayer->delta);
367dd7cddfSDavid du Colombier 	}else
377dd7cddfSDavid du Colombier 		r = screenr;
387dd7cddfSDavid du Colombier 
397dd7cddfSDavid du Colombier 	/* now in logical coordinates */
407dd7cddfSDavid du Colombier 
417dd7cddfSDavid du Colombier 	/* clipr may have narrowed what we should draw on, so clip if necessary */
427dd7cddfSDavid du Colombier 	if(!rectinrect(r, clipr)){
437dd7cddfSDavid du Colombier 		oclipr = dst->clipr;
447dd7cddfSDavid du Colombier 		dst->clipr = clipr;
457dd7cddfSDavid du Colombier 		ok = drawclip(dst, &r, d->src, &p0, d->mask, &p1, &srcr, &mr);
467dd7cddfSDavid du Colombier 		dst->clipr = oclipr;
477dd7cddfSDavid du Colombier 		if(!ok)
487dd7cddfSDavid du Colombier 			return;
497dd7cddfSDavid du Colombier 	}
50*8ccd4a63SDavid du Colombier 	memdraw(dst, r, d->src, p0, d->mask, p1, d->op);
517dd7cddfSDavid du Colombier }
527dd7cddfSDavid du Colombier 
537dd7cddfSDavid du Colombier void
memdraw(Memimage * dst,Rectangle r,Memimage * src,Point p0,Memimage * mask,Point p1,int op)54*8ccd4a63SDavid du Colombier memdraw(Memimage *dst, Rectangle r, Memimage *src, Point p0, Memimage *mask, Point p1, int op)
557dd7cddfSDavid du Colombier {
567dd7cddfSDavid du Colombier 	struct Draw d;
577dd7cddfSDavid du Colombier 	Rectangle srcr, tr, mr;
587dd7cddfSDavid du Colombier 	Memlayer *dl, *sl;
597dd7cddfSDavid du Colombier 
607dd7cddfSDavid du Colombier 	if(drawdebug)
617dd7cddfSDavid du Colombier 		iprint("memdraw %p %R %p %P %p %P\n", dst, r, src, p0, mask, p1);
627dd7cddfSDavid du Colombier 
637dd7cddfSDavid du Colombier 	if(mask == nil)
647dd7cddfSDavid du Colombier 		mask = memopaque;
657dd7cddfSDavid du Colombier 
667dd7cddfSDavid du Colombier 	if(mask->layer){
677dd7cddfSDavid du Colombier if(drawdebug)	iprint("mask->layer != nil\n");
687dd7cddfSDavid du Colombier 		return;	/* too hard, at least for now */
697dd7cddfSDavid du Colombier 	}
707dd7cddfSDavid du Colombier 
717dd7cddfSDavid du Colombier     Top:
727dd7cddfSDavid du Colombier 	if(dst->layer==nil && src->layer==nil){
73*8ccd4a63SDavid du Colombier 		memimagedraw(dst, r, src, p0, mask, p1, op);
747dd7cddfSDavid du Colombier 		return;
757dd7cddfSDavid du Colombier 	}
767dd7cddfSDavid du Colombier 
777dd7cddfSDavid du Colombier 	if(drawclip(dst, &r, src, &p0, mask, &p1, &srcr, &mr) == 0){
787dd7cddfSDavid du Colombier if(drawdebug)	iprint("drawclip dstcr %R srccr %R maskcr %R\n", dst->clipr, src->clipr, mask->clipr);
797dd7cddfSDavid du Colombier 		return;
807dd7cddfSDavid du Colombier 	}
817dd7cddfSDavid du Colombier 
827dd7cddfSDavid du Colombier 	/*
837dd7cddfSDavid du Colombier  	 * Convert to screen coordinates.
847dd7cddfSDavid du Colombier 	 */
857dd7cddfSDavid du Colombier 	dl = dst->layer;
867dd7cddfSDavid du Colombier 	if(dl != nil){
877dd7cddfSDavid du Colombier 		r.min.x += dl->delta.x;
887dd7cddfSDavid du Colombier 		r.min.y += dl->delta.y;
897dd7cddfSDavid du Colombier 		r.max.x += dl->delta.x;
907dd7cddfSDavid du Colombier 		r.max.y += dl->delta.y;
917dd7cddfSDavid du Colombier 	}
927dd7cddfSDavid du Colombier     Clearlayer:
937dd7cddfSDavid du Colombier 	if(dl!=nil && dl->clear){
947dd7cddfSDavid du Colombier 		if(src == dst){
957dd7cddfSDavid du Colombier 			p0.x += dl->delta.x;
967dd7cddfSDavid du Colombier 			p0.y += dl->delta.y;
977dd7cddfSDavid du Colombier 			src = dl->screen->image;
987dd7cddfSDavid du Colombier 		}
997dd7cddfSDavid du Colombier 		dst = dl->screen->image;
1007dd7cddfSDavid du Colombier 		goto Top;
1017dd7cddfSDavid du Colombier 	}
1027dd7cddfSDavid du Colombier 
1037dd7cddfSDavid du Colombier 	sl = src->layer;
1047dd7cddfSDavid du Colombier 	if(sl != nil){
1057dd7cddfSDavid du Colombier 		p0.x += sl->delta.x;
1067dd7cddfSDavid du Colombier 		p0.y += sl->delta.y;
1077dd7cddfSDavid du Colombier 		srcr.min.x += sl->delta.x;
1087dd7cddfSDavid du Colombier 		srcr.min.y += sl->delta.y;
1097dd7cddfSDavid du Colombier 		srcr.max.x += sl->delta.x;
1107dd7cddfSDavid du Colombier 		srcr.max.y += sl->delta.y;
1117dd7cddfSDavid du Colombier 	}
1127dd7cddfSDavid du Colombier 
1137dd7cddfSDavid du Colombier 	/*
1147dd7cddfSDavid du Colombier 	 * Now everything is in screen coordinates.
1157dd7cddfSDavid du Colombier 	 * mask is an image.  dst and src are images or obscured layers.
1167dd7cddfSDavid du Colombier 	 */
1177dd7cddfSDavid du Colombier 
1187dd7cddfSDavid du Colombier 	/*
1197dd7cddfSDavid du Colombier 	 * if dst and src are the same layer, just draw in save area and expose.
1207dd7cddfSDavid du Colombier 	 */
1217dd7cddfSDavid du Colombier 	if(dl!=nil && dst==src){
1227dd7cddfSDavid du Colombier 		if(dl->save == nil)
1237dd7cddfSDavid du Colombier 			return;	/* refresh function makes this case unworkable */
1247dd7cddfSDavid du Colombier 		if(rectXrect(r, srcr)){
1257dd7cddfSDavid du Colombier 			tr = r;
1267dd7cddfSDavid du Colombier 			if(srcr.min.x < tr.min.x){
1277dd7cddfSDavid du Colombier 				p1.x += tr.min.x - srcr.min.x;
1287dd7cddfSDavid du Colombier 				tr.min.x = srcr.min.x;
1297dd7cddfSDavid du Colombier 			}
1307dd7cddfSDavid du Colombier 			if(srcr.min.y < tr.min.y){
1317dd7cddfSDavid du Colombier 				p1.y += tr.min.x - srcr.min.x;
1327dd7cddfSDavid du Colombier 				tr.min.y = srcr.min.y;
1337dd7cddfSDavid du Colombier 			}
1347dd7cddfSDavid du Colombier 			if(srcr.max.x > tr.max.x)
1357dd7cddfSDavid du Colombier 				tr.max.x = srcr.max.x;
1367dd7cddfSDavid du Colombier 			if(srcr.max.y > tr.max.y)
1377dd7cddfSDavid du Colombier 				tr.max.y = srcr.max.y;
1387dd7cddfSDavid du Colombier 			memlhide(dst, tr);
1397dd7cddfSDavid du Colombier 		}else{
1407dd7cddfSDavid du Colombier 			memlhide(dst, r);
1417dd7cddfSDavid du Colombier 			memlhide(dst, srcr);
1427dd7cddfSDavid du Colombier 		}
1437dd7cddfSDavid du Colombier 		memdraw(dl->save, rectsubpt(r, dl->delta), dl->save,
144*8ccd4a63SDavid du Colombier 			subpt(srcr.min, src->layer->delta), mask, p1, op);
1457dd7cddfSDavid du Colombier 		memlexpose(dst, r);
1467dd7cddfSDavid du Colombier 		return;
1477dd7cddfSDavid du Colombier 	}
1487dd7cddfSDavid du Colombier 
1497dd7cddfSDavid du Colombier 	if(sl){
1507dd7cddfSDavid du Colombier 		if(sl->clear){
1517dd7cddfSDavid du Colombier 			src = sl->screen->image;
152*8ccd4a63SDavid du Colombier 			if(dl != nil){
153*8ccd4a63SDavid du Colombier 				r.min.x -= dl->delta.x;
154*8ccd4a63SDavid du Colombier 				r.min.y -= dl->delta.y;
155*8ccd4a63SDavid du Colombier 				r.max.x -= dl->delta.x;
156*8ccd4a63SDavid du Colombier 				r.max.y -= dl->delta.y;
157*8ccd4a63SDavid du Colombier 			}
1587dd7cddfSDavid du Colombier 			goto Top;
1597dd7cddfSDavid du Colombier 		}
1607dd7cddfSDavid du Colombier 		/* relatively rare case; use save area */
1617dd7cddfSDavid du Colombier 		if(sl->save == nil)
1627dd7cddfSDavid du Colombier 			return;	/* refresh function makes this case unworkable */
1637dd7cddfSDavid du Colombier 		memlhide(src, srcr);
1647dd7cddfSDavid du Colombier 		/* convert back to logical coordinates */
1657dd7cddfSDavid du Colombier 		p0.x -= sl->delta.x;
1667dd7cddfSDavid du Colombier 		p0.y -= sl->delta.y;
1677dd7cddfSDavid du Colombier 		srcr.min.x -= sl->delta.x;
1687dd7cddfSDavid du Colombier 		srcr.min.y -= sl->delta.y;
1697dd7cddfSDavid du Colombier 		srcr.max.x -= sl->delta.x;
1707dd7cddfSDavid du Colombier 		srcr.max.y -= sl->delta.y;
1717dd7cddfSDavid du Colombier 		src = src->layer->save;
1727dd7cddfSDavid du Colombier 	}
1737dd7cddfSDavid du Colombier 
1747dd7cddfSDavid du Colombier 	/*
1757dd7cddfSDavid du Colombier 	 * src is now an image.  dst may be an image or a clear layer
1767dd7cddfSDavid du Colombier 	 */
1777dd7cddfSDavid du Colombier 	if(dst->layer==nil)
1787dd7cddfSDavid du Colombier 		goto Top;
1797dd7cddfSDavid du Colombier 	if(dst->layer->clear)
1807dd7cddfSDavid du Colombier 		goto Clearlayer;
1817dd7cddfSDavid du Colombier 
1827dd7cddfSDavid du Colombier 	/*
1837dd7cddfSDavid du Colombier 	 * dst is an obscured layer
1847dd7cddfSDavid du Colombier 	 */
1857dd7cddfSDavid du Colombier 	d.deltas = subpt(p0, r.min);
1867dd7cddfSDavid du Colombier 	d.deltam = subpt(p1, r.min);
1877dd7cddfSDavid du Colombier 	d.dstlayer = dl;
1887dd7cddfSDavid du Colombier 	d.src = src;
189*8ccd4a63SDavid du Colombier 	d.op = op;
1907dd7cddfSDavid du Colombier 	d.mask = mask;
191*8ccd4a63SDavid du Colombier 	_memlayerop(ldrawop, dst, r, r, &d);
1927dd7cddfSDavid du Colombier }
193