ref: ec862e9c8acd30ec73eb9e11b8e849ed5b711e76
parent: bdaf1a663cf88374589d1aad556614aa3af838fa
author: rodri <rgl@antares-labs.eu>
date: Sat Dec 27 12:38:50 EST 2025
libmem(draw|layer), devdraw: bring affinewarp changes from 9front
--- a/include/memdraw.h
+++ b/include/memdraw.h
@@ -144,7 +144,8 @@
extern void memarc(Memimage*, Point, int, int, int, Memimage*, Point, int, int, int);
extern Rectangle memlinebbox(Point, Point, int, int, int);
extern int memlineendsize(int);
-extern int memaffinewarp(Memimage*, Rectangle, Memimage*, Point, Warp, int);
+extern void memaffinewarp(Memimage*, Rectangle, Memimage*, Point, Warp, int);
+extern void memlaffinewarp(Memimage*, Rectangle, Memimage*, Point, Warp, int);
extern Memimage* allocmemimagekernel(double*, int, int, double);
extern int memimagecorrelate(Memimage*, Rectangle, Memimage*, Point, Memimage*);
extern void _memmkcmap(void);
--- a/kern/devdraw.c
+++ b/kern/devdraw.c
@@ -1388,6 +1388,13 @@
q += sprint(q, " [%d %d]", BGLONG(a), BGLONG(a+4));
a += 8;
break;
+ case 'M':
+ q += sprint(q, " [[%d %d %d][%d %d %d][%d %d %d]]",
+ BGLONG(a), BGLONG(a+ 4), BGLONG(a+ 8),
+ BGLONG(a+12), BGLONG(a+16), BGLONG(a+20),
+ BGLONG(a+24), BGLONG(a+28), BGLONG(a+32));
+ a += 36;
+ break;
case 'b':
q += sprint(q, " %d", *a++);
break;
@@ -1532,8 +1539,7 @@
src = drawimage(client, a+21);
drawpoint(&p, a+25);
drawwarp(w, a+33);
- if(memaffinewarp(dst, r, src, p, w, a[33+3*3*4]) < 0)
- error("memaffinewarp failed");+ memlaffinewarp(dst, r, src, p, w, a[33+3*3*4]);
dstflush(dstid, dst, r);
continue;
--- a/libmemdraw/warp.c
+++ b/libmemdraw/warp.c
@@ -713,7 +713,7 @@
return r<<24|g<<16|b<<8|a;
}
-int
+void
memaffinewarp(Memimage *d, Rectangle r, Memimage *s, Point sp0, Warp m, int smooth)
{ulong (*sample)(Sampler*, Point) = sample1;
@@ -726,11 +726,11 @@
dr = d->clipr;
rectclip(&dr, d->r);
if(rectclip(&r, dr) == 0)
- return 0;
+ return;
samp.r = s->clipr;
if(rectclip(&samp.r, s->r) == 0)
- return 0;
+ return;
if(smooth)
sample = bilinear;
@@ -744,7 +744,10 @@
* Lee, S., Lee, GG., Jang, E.S., Kim, WY,
* Intelligent Computing. ICIC 2006. LNCS, vol 4113.
*/
- p2 = p2₀ = xform((Point){int2fix(r.min.x - dr.min.x) + (1<<6), int2fix(r.min.y - dr.min.y) + (1<<6)}, m);+ p2 = p2₀ = xform((Point){+ int2fix(r.min.x - d->r.min.x) + (1<<6),
+ int2fix(r.min.y - d->r.min.y) + (1<<6)
+ }, m);
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++){samp.Δx = fixfrac(p2.x);
@@ -762,7 +765,6 @@
p2.x = p2₀.x += m[0][1];
p2.y = p2₀.y += m[1][1];
}
- return 0;
}
static double
--- a/libmemlayer/Makefile
+++ b/libmemlayer/Makefile
@@ -4,6 +4,7 @@
OFILES=\
draw.$O\
+ warp.$O\
lalloc.$O\
layerop.$O\
ldelete.$O\
--- /dev/null
+++ b/libmemlayer/warp.c
@@ -1,0 +1,159 @@
+#include <u.h>
+#include <libc.h>
+#include <draw.h>
+#include <memdraw.h>
+#include <memlayer.h>
+
+struct Draw
+{+ Memlayer *dstlayer;
+ Memimage *src;
+ Point sp;
+ Warp warp;
+ int smooth;
+};
+
+static
+void
+ldrawop(Memimage *dst, Rectangle screenr, Rectangle clipr, void *etc, int insave)
+{+ struct Draw *d;
+ Rectangle r;
+
+ d = etc;
+ if(insave && d->dstlayer->save == nil)
+ return;
+
+ 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) && rectclip(&r, clipr) == 0)
+ return;
+ memlaffinewarp(dst, r, d->src, d->sp, d->warp, d->smooth);
+}
+
+void
+memlaffinewarp(Memimage *dst, Rectangle r, Memimage *src, Point p0, Warp w, int smooth)
+{+ struct Draw d;
+ Rectangle srcr, tr;
+ Memlayer *dl, *sl;
+
+ Top:
+ if(dst->layer == nil && src->layer == nil){+ memaffinewarp(dst, r, src, p0, w, smooth);
+ 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->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)
+ tr.min.x = srcr.min.x;
+ if(srcr.min.y < tr.min.y)
+ 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);
+ }
+ memlaffinewarp(dl->save, rectsubpt(r, dl->delta), dl->save,
+ subpt(srcr.min, src->layer->delta), w, smooth);
+ memlexpose(dst, r);
+ return;
+ }
+
+ if(sl != nil){+ 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.dstlayer = dl;
+ d.src = src;
+ d.sp = p0;
+ memmove(d.warp, w, sizeof(Warp));
+ d.smooth = smooth;
+ _memlayerop(ldrawop, dst, r, r, &d);
+}
--
⑨