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;
+}
--
⑨