shithub: pain

Download patch

ref: 2135d47a94469871de61d2efe2e9dbf8993c583d
parent: 4bcb73eb20638b1564d6757405508ea63ccf5f14
author: jmq <jmq@jmq.sh>
date: Mon Dec 9 22:17:56 EST 2024

start float resize

--- a/dat.h
+++ b/dat.h
@@ -35,14 +35,13 @@
 	void (*func)(void);
 } Task;
 
-// extern Rectangle CanvasSize = {0};
-// extern Point CanvasAt = {0};
+extern Rectangle CanvasSize = {0};
 extern Layer * LayerRoot;
 extern Layer * CurrentLayer;
 extern Binding * BindingRoot;
 extern Image * ViewImage;
 extern int RunLoop;
-extern int ZoomSensitivity;
+extern float ZoomSensitivity;
 extern Point MousePosition;
 extern Point PastMousePosition;
 extern Point CanvasAt;
@@ -49,7 +48,5 @@
 extern int CanvasMoved;
 extern int DrawAllLayers;
 extern ulong LastUpdate;
-extern int TargetZoom;
-// extern Layer * CurrentLayer = nil;
-// extern Image * Background = nil;
-// extern Image * Canvas = nil;
+extern float TargetZoom;
+extern Layer * CurrentLayer = nil;
--- a/fns.h
+++ b/fns.h
@@ -9,7 +9,7 @@
 void setbackground(ulong col);
 void drawcanvas(void);
 void applyzoom(void);
-void zoom(int);
+void zoom(float);
 void zoomin(void);
 void zoomout(void);
 void stroke(void);
@@ -16,7 +16,7 @@
 void clearlayer(Layer *);
 void clearview(void);
 void setbrushcolor(ulong col);
-int resizeimage(Image *, Rectangle, int, Image *, Point);
+int resizeimage(Image *, Rectangle, float, Image *, Point);
 int newtask(ulong, void (*)(void));
 int removetask(int);
 void runtasks(void);
@@ -25,6 +25,7 @@
 Layer * newlayer(void);
 void ntfprint(char *, ...);
 void setcurrentlayer(Layer *);
+Point mulptf(Point, float);
 
 Point globaltoscreenpt(Point p);
 Point globaltoscreenatcanvaspt(Point p);
--- a/main.c
+++ b/main.c
@@ -41,9 +41,9 @@
 Image * CanvasBackgroundImage = nil;
 ulong LastUpdate = 0;
 int DrawAllLayers = 0;
-int Zoom = 1;
-int TargetZoom = 1;
-int ZoomSensitivity = 1;
+float Zoom = 1;
+float TargetZoom = 1;
+float ZoomSensitivity = 0.1;
 Mouse CurrentMouse = {0};
 Mouse PastMouse = {0};
 Point MousePosition = {0};
@@ -157,8 +157,9 @@
 
 	if (ZoomedImage == nil) {
 		ZoomedImage = allocimage(display, ZoomedSize, RGBA32, 1, DNofill);
+		print("ZoomedSize: %R\n", ZoomedSize);
 		if (ZoomedImage == nil)
-			sysfatal("z allocimage: %r");
+			sysfatal("failed to allocate ZoomedImage: %r");
 		sr = 1;
 	}
 
@@ -243,7 +244,7 @@
 }
 
 static void
-zoomrect(Rectangle * zs, Point * ca, int z)
+zoomrect(Rectangle * zs, Point * ca, float z)
 {
 	int osx, osy;
 	Point c;
@@ -252,8 +253,8 @@
 	osx = Dx(ZoomedSize);
 	osy = Dy(ZoomedSize);
 
-	zs->min = mulpt(CanvasSize.min, z);
-	zs->max = mulpt(CanvasSize.max, z);
+	zs->min = mulptf(CanvasSize.min, z);
+	zs->max = mulptf(CanvasSize.max, z);
 
 	*ca = addpt(
 		Pt(Dx(ZoomedSize)*c.x/osx, Dy(ZoomedSize)*c.y/osy), 
@@ -273,16 +274,16 @@
 
  	DrawAllLayers = 1;
 	ZoomTaskId = -1;
-	ntfprint("zoom set to %d", Zoom);
+	ntfprint("zoom set to %f", Zoom);
 }
 
 void
-zoom(int z)
+zoom(float z)
 {
 	Rectangle zs;
 	Point ca;
 
-	if ((TargetZoom + z) <= 1 || z == 0)
+	if ((TargetZoom + z) < 0)
 		TargetZoom = 1;
 	else
 		TargetZoom += z;
--- a/resize.c
+++ b/resize.c
@@ -9,87 +9,131 @@
 // and /sys/src/cmd/page.c:/^zoomdraw
 // Thanks sigrid!
 int
-resizeimage(Image * di, Rectangle dr, int scale, Image * si, Point sp)
+resizeimage(Image * di, Rectangle dr, float scale, Image * si, Point sp)
 {
-	int i, c, sh;
+	float d, f;
+	Point p;
+	Rectangle r;
+	int sh, i;
 	Image * t, * ci;
 
-	if (scale < 1) {
-		werrstr("scale < 1");
+	if (scale < 0) {
+		werrstr("scale < 0");
 		return -1;
 	} else if (scale == 1) {
 		draw(di, dr, si, nil, addpt(sp, dr.min));
 		return 1;
 	}
-
+	
 	sh = Dy(si->r);
+	// Allocate temporary image with the size of the dimensions
+	// we are supposed to write on
 	if ((t = allocimage(display, dr, si->chan, 1, DNofill)) == nil) {
 		werrstr("allocimage: %r");
 		return -1;
 	}
-
+	
+	// Allocate the cursor image. Think of it as a line that scans an
+	// image and copies the pixels underneath it to another image
+	//
+	// For this first scan, we will be using a vertical line of width 1, and height
+	// sh (so the source image's height)
 	if ((ci = allocimage(display, Rect(0, 0, 1, sh), si->chan, 1, DNofill)) == nil) {
 		werrstr("allocimage: %r");
 		freeimage(t);
 		return -1;
 	}
+	
+	// Location of the cursor relative to the source image's sp
+	p.x = (int)(((float)dr.min.x)/scale);
+	p.y = (int)(((float)dr.min.y)/scale);
+	p = addpt(p, sp);
 
-	for (i = dr.min.x; i < dr.max.x; i+=scale) {
-		draw(ci, ci->r, si, nil, addpt(sp, Pt(i/scale, dr.min.y/scale)));
-		draw(t, Rect(i, dr.min.y, i + scale, dr.max.y), ci, nil, ZP);
+	// Tall rectangle where the ci image will be drawn in
+	// the temporary image
+	r.min = dr.min;
+	r.max.y = dr.max.y;
+	r.max.x = r.min.x + MAX(1.0, 1/scale);	// It wouldn't make much sense to have
+											// a horizontal width of less than 1
+	print("t->r = %R\n", t->r);
+	print("ci->r = %R\n", ci->r);
+	i = r.max.x - r.min.x;
+	d = p.x;
+	f = r.min.x;
+	// Scan the source image with a vertical cursor image and apply it to the
+	// temporary image. We want to do this until we try to scan outside the
+	// source image, or we try to write outside of the target image.
+	while (r.min.x < dr.max.x || p.x < (si->r.max.x/scale)) {
+		// If we are expanding an image, one scan on the source image will result on
+		// multiple draws on the target image. Conversively, if we are shrinking an
+		// image, for every line on the target image will we will skip over multiple
+		// lines on the source image.
+		
+		print("f = %f, p = %P, r = %R\n", scale, p, r);
+		// Move the ci one 1/scale space to the right
+		draw(ci, ci->r, si, nil, p);
+		d += 1/scale;
+		p.x = d;
+		
+		// Move the draw rectangle for the temporary image scale
+		// rectangles to the right
+		draw(t, r, ci, nil, ZP);
+		f += scale;
+		r.min.x = f;
+		r.max.x = r.min.x + i;
 	}
+
 	freeimage(ci);
 	
+	// Now let's do the same, but this time we will use a horizontal
+	// cursor image and instead of reading from the source image into the temporary
+	// image, we will read from the temporary image to the destination image.
+	//
+	// This is because we already expanded the image horizontally, how we just have
+	// to do it vertically
+	
+	// Make our horizontal scan image
 	if ((ci = allocimage(display, Rect(0, 0, Dx(dr), 1), si->chan, 1, DNofill)) == nil) {
 		werrstr("allocimage: %r");
 		freeimage(t);
 		return -1;
 	}
-	c = dr.min.y;
- 	for (i = dr.min.y; i < dr.max.y; i+=scale) {
-		draw(ci, ci->r, t, nil, Pt(dr.min.x, c++));
- 		draw(di, Rect(dr.min.x, i, dr.max.x, i + scale), ci, nil, ZP);
+
+	// Location of the cursor relative to the source image's sp
+	p.y = dr.min.y;
+	p.x = (int)(((float)dr.min.x)/scale);
+	p = addpt(p, sp);
+
+	// Wide rectangle where the ci image will be drawn in
+	// the temporary image
+	r.min = dr.min;
+	r.max.x = dr.max.x;
+	r.max.y = r.min.y + MAX(1.0, scale);
+	
+	i = r.max.y - r.min.y;
+	d = p.y;
+	draw(di, t->r, t, nil, ZP);
+	while (0) {
+		// If we are expanding an image, one scan on the source image will result on
+		// multiple draws on the target image. Conversively, if we are shrinking an
+		// image, for every line on the target image will we will skip over multiple
+		// lines on the source image.
+		
+		// Move the ci one 1/scale space to the right
+		draw(ci, ci->r, t, nil, p);
+		d += 1/scale;
+		p.y = d;
+		
+		// Move the draw rectangle for the temporary image scale
+		// rectangles to the right
+		draw(di, r, ci, nil, ZP);
+		r.max.y += i;
+		r.min.y += i;
+		print("f = %f, p = %P, r = %R\n", scale, p, r);
 	}
 
 	freeimage(t);
 	freeimage(ci);
-
-// 	x = dr.min.y;
-// 	for (i = sp.y; i < sh; i++) 
-// 		draw(di, Rect(dr.min.x, x, dr.max.x, (x += scale)), t, nil, dr.min);
-// 	freeimage(t);
-
-// 	
-// 	// Draw the cursor for vertical line
-//  	if (t == nil || ) {
-//  		if (t != nil)
-//  			freeimage(t);
-//  	 	t = allocimage(display, Rect(0, 0, sw*scale, sh), si->chan, 1, DNofill);
-//  	 	if (t == nil) {
-//  	 		return -1;
-//  	 	}
-//  	}
-
-// 	// print("min.x = %d, min.y = %d, max.x = %d, max.y = %d\n",
-// 	//	clipr.min.x, clipr.min.y, clipr.max.x, clipr.max.y);
-// 	r = Rect(0, 0, 1, sh);
-// 	for (i = 0; i < sw; i++) {
-// 		cr = Rect(i*scale, 0, (i+1)*scale, r.max.y);
-// 		if (!rectclip(&cr, clipr))
-// 			continue;
-// 		draw(t, cr, si, nil, Pt(i, 0));
-// 	}
-
-//  	// Draw the cursor for vertical lines
-// 	cr = di->clipr;
-//     r = Rect(0, 0, sw*scale, 1);
-//    	for (i = 0; i < sh; i++) {
-// 		cr = Rect(0, i*scale, r.max.x, (i+1)*scale);
-// 		if (!rectclip(&cr, clipr))
-// 			continue;
-//    		draw(di, cr, t, nil, Pt(0, i));
-// 	}
-
 
 	return 1;
 }
--- a/utils.c
+++ b/utils.c
@@ -10,3 +10,11 @@
 {
 	RunLoop = 0;
 }
+
+Point
+mulptf(Point p, float f)
+{
+	p.x = (int)(((float)p.x) * f);
+	p.y = (int)(((float)p.y) * f);
+	return p;
+}
--