shithub: front

Download patch

ref: 69cd42bb94c4454c8478eae8a61c5fec9e16ebb7
parent: a222ad25f1656a5d098028c11283cc7f8c67f0e4
author: rodri <rgl@antares-labs.eu>
date: Fri Aug 15 11:07:22 EDT 2025

libmemdraw: follow draw(2)'s behavior for clipr and repl

--- a/sys/src/libmemdraw/warp.c
+++ b/sys/src/libmemdraw/warp.c
@@ -24,6 +24,7 @@
 {
 	Memimage *i;
 	uchar *a;
+	Rectangle r;
 	int bpp;
 	int bpl;
 	int cmask;
@@ -40,23 +41,22 @@
 }
 
 static ulong
-edgehandler(Sampler*, Point*)
-{
-	return 0;	/* constant */
-}
-
-static ulong
 sample(Sampler *s, Point p)
 {
 	ulong c;
 
-	if(p.x >= s->i->r.min.x && p.x < s->i->r.max.x
-	&& p.y >= s->i->r.min.y && p.y < s->i->r.max.y){
+	if(p.x >= s->r.min.x && p.x < s->r.max.x
+	&& p.y >= s->r.min.y && p.y < s->r.max.y){
+inside:
 		c = *(ulong*)(s->a + p.y*s->bpl + p.x*s->bpp);
 		c &= s->cmask;
-	}else
-		c = edgehandler(s, &p);
-	return c;
+		return c;
+	}else if(s->i->flags & Frepl){
+		p = drawrepl(s->r, p);
+		goto inside;
+	}
+	/* edge handler: constant */
+	return 0;
 }
 
 int
@@ -65,15 +65,17 @@
 	Sampler samp;
 	Point sp, dp;
 	Foint p2;
+	Rectangle dr;
 	long Δx, Δy;
 	ulong c00, c01, c10, c11;
-	uchar c0, c1, c, *a;
-	int bpp, bploff;
+	uchar c0, c1, c, *a0, *a;
+	int bpp, bpl;
 
-	if(s->depth < 8 || (s->depth & 3) != 0){
-		werrstr("unsupported image format");
-		return -1;
-	}
+	for(c00 = s->chan; c00; c00 >>= 8)
+		if(NBITS(c00) != 8){
+			werrstr("unsupported image format");
+			return -1;
+		}
 
 	if(d->chan != s->chan){
 		werrstr("image formats differ");
@@ -80,24 +82,29 @@
 		return -1;
 	}
 
-	if(rectclip(&r, d->r) == 0)
+	dr = d->clipr;
+	rectclip(&dr, d->r);
+	if(rectclip(&r, dr) == 0)
 		return 0;
 
+	samp.r = s->clipr;
+	if(rectclip(&samp.r, s->r) == 0)
+		return 0;
+
 	samp.i = s;
 	samp.a = s->data->bdata + s->zero;
 	samp.bpp = s->depth >> 3;
 	samp.bpl = sizeof(ulong)*s->width;
 	samp.cmask = (1ULL << s->depth) - 1;
-	a = d->data->bdata + d->zero;
+	a0 = d->data->bdata + d->zero;
 	bpp = d->depth >> 3;
-	bploff = sizeof(ulong)*d->width - Dx(d->r)*bpp;
+	bpl = sizeof(ulong)*d->width;
 
-	r = rectsubpt(r, r.min);
+	for(dp.y = r.min.y; dp.y < r.max.y; dp.y++)
+	for(dp.x = r.min.x; dp.x < r.max.x; dp.x++){
+		a = a0 + dp.y*bpl + dp.x*bpp;
+		p2 = fix_xform((Foint){int2fix(dp.x - dr.min.x), int2fix(dp.y - dr.min.y), 1<<7}, m);
 
-	for(dp.y = 0; dp.y < r.max.y; dp.y++, a += bploff)
-	for(dp.x = 0; dp.x < r.max.x; dp.x++, a += bpp){
-		p2 = fix_xform((Foint){int2fix(dp.x), int2fix(dp.y), 1<<7}, m);
-
 		Δx = fixfrac(p2.x);
 		Δy = fixfrac(p2.y);
 
@@ -118,22 +125,22 @@
 			c0 = c00 >> 8*3 & 0xFF; c0 = lerp(c0, c01 >> 8*3 & 0xFF, Δx);
 			c1 = c10 >> 8*3 & 0xFF; c1 = lerp(c1, c11 >> 8*3 & 0xFF, Δx);
 			c  = lerp(c0, c1, Δy);
-			*(a + 3) = c;
+			a[3] = c;
 		case 3:
 			c0 = c00 >> 8*2 & 0xFF; c0 = lerp(c0, c01 >> 8*2 & 0xFF, Δx);
 			c1 = c10 >> 8*2 & 0xFF; c1 = lerp(c1, c11 >> 8*2 & 0xFF, Δx);
 			c  = lerp(c0, c1, Δy);
-			*(a + 2) = c;
+			a[2] = c;
 		case 2:
 			c0 = c00 >> 8*1 & 0xFF; c0 = lerp(c0, c01 >> 8*1 & 0xFF, Δx);
 			c1 = c10 >> 8*1 & 0xFF; c1 = lerp(c1, c11 >> 8*1 & 0xFF, Δx);
 			c  = lerp(c0, c1, Δy);
-			*(a + 1) = c;
+			a[1] = c;
 		case 1:
 			c0 = c00 >> 8*0 & 0xFF; c0 = lerp(c0, c01 >> 8*0 & 0xFF, Δx);
 			c1 = c10 >> 8*0 & 0xFF; c1 = lerp(c1, c11 >> 8*0 & 0xFF, Δx);
 			c  = lerp(c0, c1, Δy);
-			*(a + 0) = c;
+			a[0] = c;
 		}
 	}
 
--- a/sys/src/libmemdraw/warptest.c
+++ b/sys/src/libmemdraw/warptest.c
@@ -130,11 +130,25 @@
 //	dr = getbbox(&src->r, T);
 	dr = src->r;
 	dst = allocmemimage(dr, src->chan);
+	memfillcolor(dst, DTransparent);
 
 	mkwarp(w, T);
 
 	profbegin();
-	if(memaffinewarp(dst, dst->r, src, src->r.min, w) < 0)
+	dr = rectaddpt(Rect(0,0,Dx(dst->r)/2,Dy(dst->r)/2), dst->r.min);
+	dst->clipr = dr;
+	if(memaffinewarp(dst, dr, src, src->r.min, w) < 0)
+		sysfatal("memaffinewarp: %r");
+	dr = rectaddpt(Rect(Dx(dst->r)/2+1,0,Dx(dst->r),Dy(dst->r)/2), dst->r.min);
+	dst->clipr = dst->r;
+	if(memaffinewarp(dst, dr, src, src->r.min, w) < 0)
+		sysfatal("memaffinewarp: %r");
+	dr = rectaddpt(Rect(0,Dy(dst->r)/2+1,Dx(dst->r)/2,Dy(dst->r)), dst->r.min);
+	if(memaffinewarp(dst, dr, src, src->r.min, w) < 0)
+		sysfatal("memaffinewarp: %r");
+	dr = rectaddpt(Rect(Dx(dst->r)/2+1,Dy(dst->r)/2+1,Dx(dst->r),Dy(dst->r)), dst->r.min);
+	dst->clipr = dr;
+	if(memaffinewarp(dst, dr, src, src->r.min, w) < 0)
 		sysfatal("memaffinewarp: %r");
 	profend();
 	writememimage(1, dst);
--