shithub: pain

Download patch

ref: 1527811f3015c04a1d84528d6eb7fb50575a57e2
parent: c8dfc9e70b9e9df578e0c1213b04ae31d5c28c08
author: jmq <jmq@jmq.sh>
date: Sat Jan 18 22:21:26 EST 2025

I donnu man I haven't work on this in months

--- a/fns.h
+++ b/fns.h
@@ -17,9 +17,6 @@
 void clearview(void);
 void setbrushcolor(ulong col);
 int resizeimage(Image *, Rectangle, float, Image *, Point);
-int newtask(ulong, void (*)(void));
-int removetask(int);
-void runtasks(void);
 int newlayerimage(Layer *);
 void centercanvas(void);
 Layer * newlayer(void);
@@ -49,3 +46,6 @@
 
 // utils
 void quitloop(void);
+int newtask(ulong, void (*)(void));
+int removetask(int);
+void runtasks(void);
--- a/fs.c
+++ b/fs.c
@@ -1,246 +1,159 @@
 #include <u.h>
 #include <libc.h>
-#include <auth.h>
 #include <fcall.h>
 #include <thread.h>
-#include <9p.h>
 #include <draw.h>
-#include <mouse.h>
+#include <9p.h>
 
 #include "dat.h"
 #include "fns.h"
 
-#define WALK1NAMEQID(q_, n_)	\
-if (strcmp(n_, name) == 0) {	\
-	*qid = (Qid){q_, 0, QTDIR};	\
-	return nil;					\
-}
+static void fsstart(Srv *);
+static void fsend(Srv *);
+static void fswrite(Req *);
+static void fsread(Req *);
 
-int fillstat(ulong qid, Dir *d);
+static char * canvasread(Req *);
+static char * canvaswrite(Req *);
+static int FsPID = -1;
 
-static void fsopen(Req * req);
-static void fsread(Req * req);
-static void fswrite(Req * req);
-static void fswstat(Req * req);
-static void fscreate(Req * req);
-static void fsattach(Req * req);
-static void fsdestroyfid(Fid * req);
-static void fswalk1(Fid *fid, char *name, Qid *qid);
-static void fsstart(Srv * srv);
-static void fsdetroyfile(File * f);
+typedef struct FileEntry {
+	char * name;
+	char * (*read) (Req *);
+	char * (*write) (Req *);
+	int mode;
+} FileEntry;
 
-static char mntpath[128] = {0};
-static void fssrvforker(void (*fn)(void*), void *arg, int flags);
-
-static Srv fs = {
-	.open =			fsopen,
-	.read =			fsread,
-	.write = 		fswrite,
-	.wstat = 		fswstat,
-	.walk1 =		fswalk1,
-	.create = 		fscreate,
-	.destroyfid = 	fsdestroyfid,
-	.attach =		fsattach,
-	.start = 		fsstart,
-	.forker =		fssrvforker,
+FileEntry entries[] = {
+	{"canvas", canvasread, canvaswrite, 0666 }
 };
+static Image * CanvasReadImage = nil;
+static long CanvasReadReady = 0;
+static char * FsName = nil;
 
-enum {
-	Qdir,
-	Qctl,
-	Qcanvas,
-	Qerrors,
-	Qevent,
-	Qcursor,
-	Qwindow,
-	Qlog,
-	Qlabel,
-	Qbrush,
+Srv s = {
+	.start = fsstart,
+	.end = fsend,
+	.read = fsread,
+	.write = fswrite,
 };
 
-int
-fillstat(ulong qid, Dir *d)
+static void
+fsstart(Srv *)
 {
-	static char buf[32];
+	File * r, * t;
+	char * u;
+	int i;
 
-	nulldir(d);
-	d->type = L'M';
-	d->dev = 1;
-	d->length = 0;
-	d->uid = d->gid = buf;
-	d->muid = "";
-	d->qid = (Qid){qid, drive->nchange, 0};
-	d->atime = time(0);
-	d->mtime = drive->changetime;
+	u = getuser();
+	if ((s.tree = alloctree(u, u, 0555, nil)) == nil)
+		sysfatal("alloctree: %r");
 
-	switch(qid){
-	case Qdir:
-		d->name = "/";
-		d->qid.type = QTDIR;
-		d->mode = DMDIR|0777;
-		break;
-
-	case Qctl:
-		d->name = "ctl";
-		d->mode = 0666;
-		break;
-
-	case Qwa:
-		if(drive->writeok == No ||
-		    drive->mmctype != Mmcnone &&
-		    drive->mmctype != Mmccd)
-			return 0;
-		d->name = "wa";
-		d->qid.type = QTDIR;
-		d->mode = DMDIR|0777;
-		break;
-
-	case Qwd:
-		if(drive->writeok == No)
-			return 0;
-		d->name = "wd";
-		d->qid.type = QTDIR;
-		d->mode = DMDIR|0777;
-		break;
-
-	default:
-		if(qid-Qtrack >= drive->ntrack)
-			return 0;
-		t = &drive->track[qid-Qtrack];
-		if(strcmp(t->name, "") == 0)
-			return 0;
-		d->name = t->name;
-		d->mode = t->mode;
-		d->length = t->size;
-		break;
-	}
-	return 1;
+	r = s.tree->root;
+	if ((t = createfile(r, FsName, u, DMDIR | 0555, nil)) == nil)
+		sysfatal("createfile: %r");
+	
+	for (i = 0; i < ARRLEN(entries); i++)
+		if (createfile(t, entries[i].name, u, entries[i].mode, &entries[i]) == nil)
+			sysfatal("createfile: %r");
+	FsPID = getpid();
 }
 
 static void
-fsopen(Req * req) {
-	respond(req, nil);
+fsend(Srv *)
+{
+	exits(nil);
 }
 
 static void
-fsread(Req * req) {
-	respond(req,nil);
+fsread(Req * r)
+{
+	FileEntry * e;
+	r->ofcall.count = 0;
+	e = r->fid->file->aux;
+	respond(r, e->read(r));
 }
 
 static void
-fswrite(Req * req) {
-	respond(req,nil);
+fswrite(Req * r)
+{
+	FileEntry * e;
+	e = r->fid->file->aux;
+	respond(r, e->write(r));
 }
 
 static void
-fswstat(Req * req) {
-	respond(req,nil);
+canvasreadtask(void)
+{
+	if (CanvasReadImage != nil)
+		freeimage(CanvasReadImage);
+	
+	if ((CanvasReadImage = allocimage(display, ViewImage->r, ViewImage->chan, ViewImage->repl, DTransparent)) == nil) {
+		semrelease(&CanvasReadReady, 1);
+		return;
+	}
+	
+	draw(CanvasReadImage, CanvasReadImage->r, ViewImage, nil, ZP);
+	semrelease(&CanvasReadReady, 1);
 }
 
-static void
-fscreate(Req * req) {
-	respond(req,nil);
-}
+static char *
+canvasread(Req * r)
+{
+	uchar * b;
+	int n;
+	char hdr[11+5*12+1], cbuf[20];;
 
-static void 
-fswalk1(Fid *fid, char *name, Qid *qid) {
-	switch(fid->qid.path) {
-	case Qdir:
-		if (strcmp("..", name) == 0) {
-			*qid = (Qid){Qdir, 0, QTDIR};
-			return nil;
-		}
-		if (strcmp("ctl", name) == 0) {
-			*qid = (Qid){Qdir, 0, QTDIR};
-			return nil;
-		}
-		if (strcmp("canvas", name) == 0) {
-			*qid = (Qid){Qcanvas, 0, QTDIR};
-			return nil;
-		}
-		if (strcmp("errors", name) == 0) {
-			*qid = (Qid){Qerrors, 0, QTDIR};
-			return nil;
-		}
-		if (strcmp("event", name) == 0) {
-			*qid = (Qid){Qevent, 0, QTDIR};
-			return nil;
-		}
-		if (strcmp("cursor", name) == 0) {
-			*qid = (Qid){Qcursor, 0, QTDIR};
-			return nil;
-		}
-		if (strcmp("window", name) == 0) {
-			*qid = (Qid){Qwindow, 0, QTDIR};
-			return nil;
-		}
-		if (strcmp("log", name) == 0) {
-			*qid = (Qid){Qlog, 0, QTDIR};
-			return nil;
-		}
-		if (strcmp("brush", name) == 0) {
-			*qid = (Qid){Qbrush, 0, QTDIR};
-			return nil;
-		}
-		return "file not found";
-	default:
-		return "walk in non-directory";
+	if (newtask(0, canvasreadtask) < 0)
+		return "failed to allocated canvas read task";
+	if (tsemacquire(&CanvasReadReady, 1000) < 0)
+		return "canvas read timed out";
+	
+	if (CanvasReadImage == nil) {
+		return "no view image";
 	}
-}
 
-static void
-fsdestroyfid(Fid * req) {
-	USED(req);
-}
-
-static void
-fsattach(Req * req) {
-	char *spec;
-
-	spec = r->ifcall.aname;
-	if(spec && spec[0]){
-		respond(r, "invalid attach specifier");
-		return;
+	sprint(hdr, "%11s %11d %11d %11d %11d ",
+			chantostr(cbuf, CanvasReadImage->chan), 
+			CanvasReadImage->r.min.x, 
+			CanvasReadImage->r.min.y, 
+			CanvasReadImage->r.max.x, 
+			CanvasReadImage->r.max.y
+	);
+	
+	n = bytesperline(CanvasReadImage->r, CanvasReadImage->depth) * Dy(CanvasReadImage->r);
+	b = emalloc9p(n + sizeof(hdr));
+	memcpy(b, hdr, sizeof(hdr));
+	b += sizeof(hdr);
+	if (b != nil) {
+		unloadimage(CanvasReadImage, CanvasReadImage->r, b, n);
+		b -= sizeof(hdr);
+		readbuf(r, b, n + sizeof(hdr));
+		free(b);
 	}
 
-	r->ofcall.qid = (Qid){Qdir, 0, QTDIR};
-	r->fid->qid = r->ofcall.qid;
-	respond(r, nil);
+	return nil;
 }
 
-static void
-fsstart(Srv * srv) {
-	USED(srv);
+static char *
+canvaswrite(Req *)
+{
+	return nil;
 }
 
-static void 
-fsdestroyfile(File * f) {
-	USED(f);
+int
+fsinit(char * name)
+{
+	FsName = name;
+	postmountsrv(&s, name, "/n", MBEFORE);
+	return 1;
 }
 
 void
 fsclose(void)
 {
-	Waitmsg * m;
-	while ((m = wait()) != nil)
-		free(m);
-}
+	if (FsPID < 0)
+		return;
 
-static void
-fssrvforker(void (*fn)(void*), void *arg, int flags)
-{
-	srvforker(fn, arg, RFPROC|RFNAMEG|RFNOTEG|RFMEM|flags);
+	postnote(PNGROUP, FsPID, "shutdown");
 }
-
-int
-fsinit(char * srvname)
-{
-	if (fs.tree == nil) {
-		return -1;
-	}
-	snprint(mntpath, sizeof(mntpath), "/mnt/%s", srvname);
-	postmountsrv(&fs, srvname, mntpath, MCREATE|MREPL);
-
-	return 1;
-}
-
--- a/main.c
+++ b/main.c
@@ -17,7 +17,6 @@
 #define RECTOPPT(r, op)	((Rectangle){op(r.min),op(r.max)})
 #define DEFAULTCANVASSIZE RECTANGLE(1920, 1080)
 #define STROKEEND Endsquare
-#define TASKLISTSIZE 2
 #define NOTIFICATIONFONTCOLOR DBlack
 #define NOTIFICATIONBACKGROUNDCOLOR 0x72DEC2FF
 #define ZOOMAPPLYDELAY (1000/6)
@@ -49,7 +48,6 @@
 Point MousePosition = {0};
 Point PastMousePosition = {0};
 int RunLoop = 1;
-Task TaskList[TASKLISTSIZE] = {0};
 int ZoomTaskId = -1;
 uint LayerIDCounter = 0;
 
@@ -177,10 +175,14 @@
 	i = rectclip(&vr,Rect(0, 0, Dx(screen->r), Dy(screen->r)));
 	if (i && ((CanvasMoved && Ar(vr) != Ar(ZoomedSize)) || sr)) {
 		p = CanvasAt;
-		if (p.x < 0)
+		if (p.x < 0) {
+			vr.max.x += -p.x;
 			p.x = 0;
-		if (p.y < 0)
+		}
+		if (p.y < 0) {
+			vr.max.y += -p.y;
 			p.y = 0;
+		}
 		vr = rectsubpt(vr, p);
 		if (resizeimage(ZoomedImage, vr, Zoom, ViewImage, ZP) < 0)
 			sysfatal("resizeimage: %r");
@@ -201,43 +203,6 @@
 	return (ulong)(nsec()/1000000);
 }
 
-int newtask(ulong s, void (*f)(void))
-{
-	uint i;
-	for (i = 0; i < ARRLEN(TaskList); i++) {
-		if (TaskList[i].func != nil)
-			continue;
-
-		TaskList[i] = (Task) { s, f };
-		return i;
-	}
-	
-	return -1;
-}
-
-int removetask(int id)
-{
-	if (id < 0 || id >= ARRLEN(TaskList))
-		return -1;
-	TaskList[id] = (Task) {0, nil};
-	return 0;
-}
-
-void runtasks(void)
-{
-	Task * t;
-	ulong i;
-
-	for (i = 0; i < ARRLEN(TaskList); i++) {
-		t = &TaskList[i];
-		if (t->func == nil || t->start > msec())
-			continue;
-
-		t->func();
-		removetask(i);
-	}
-}
-
 void
 setbackground(ulong col)
 {	
@@ -280,7 +245,6 @@
 
  	DrawAllLayers = 1;
 	ZoomTaskId = -1;
-	ntfprint("zoom set to %f", Zoom);
 }
 
 void
@@ -304,6 +268,7 @@
 		werrstr("newtask: no tasks available");
 		return;
 	}
+	ntfprint("zoom set to %f", TargetZoom);
 }
 
 void
@@ -334,10 +299,10 @@
 	line(l->image, addpt(f, l->offset), addpt(t, l->offset), STROKEEND, STROKEEND, 1, BrushImage, ZP);
 
 	// Draw on the zoomed image
-	f = mulpt(f, Zoom);
-	t = mulpt(t, Zoom);
+	f = mulptf(f, Zoom);
+	t = mulptf(t, Zoom);
 	if (ZoomedImage != nil)
-		line(ZoomedImage, addpt(f, l->offset), addpt(t, l->offset), STROKEEND, STROKEEND, 1*Zoom, BrushImage, ZP);
+		line(ZoomedImage, addpt(f, l->offset), addpt(t, l->offset), STROKEEND, STROKEEND, Zoom, BrushImage, ZP);
 
 	// Draw on the screen
 	f = screentoglobalatcanvaspt(f);
@@ -473,6 +438,12 @@
 	CanvasAt = subpt(CanvasAt, Pt((Dx(ZoomedSize)/2), (Dy(ZoomedSize)/2)));
 }
 
+static void
+cleannup(void)
+{
+	fsclose();
+}
+
 void
 main(int argc, char * argv[])
 {
@@ -485,11 +456,11 @@
 	if (initdraw(nil, nil, "pain") < 0)
 		sysfatal("initdraw: %r\n");
 
-// 	if (fsinit(nil) < 1)
-// 		sysfatal("fsinit: %r");
+ 	if (fsinit("pain") < 1)
+ 		sysfatal("fsinit: %r");
 
-// 	if (!atexit(fsclose))
-// 		sysfatal("atexit: %r");
+ 	if (!atexit(cleannup))
+ 		sysfatal("atexit: %r");
 
 	if ((BorderImage = allocimage(display, RECTANGLE(1, 1), RGBA32, 1, DBlack)) == nil)
 		sysfatal("allocimage: %r");
--- a/mkfile
+++ b/mkfile
@@ -5,7 +5,8 @@
 	main.$O 	\
 	resize.$O	\
 	bindings.$O	\
-	utils.$O
+	utils.$O	\
+	fs.$O
 
 HFILES=fns.h dat.h
 BIN=$home/bin/$objtype
--- a/resize.c
+++ b/resize.c
@@ -57,12 +57,8 @@
 	// the temporary image
 	r.min = tr.min;
 	r.max.y = tr.max.y;
-	r.max.x = r.min.x + MAX(1.0, scale);	// It wouldn't make much sense to have
-											// a horizontal width of less than 1
 
-	i = r.max.x - r.min.x;
-	d = p.x;
-	f = r.min.x;
+	i = 0;
 	// 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.
@@ -72,17 +68,16 @@
 		// 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
+		// Move the ci one 1/scale space to the righ
 		draw(ci, ci->r, si, nil, p);
-		d += MAX(1/scale, 1);
-		p.x = d;
+		p.x += 1;
 		
 		// Move the draw rectangle for the temporary image scale
 		// rectangles to the right
+		r.min.x = (int)(((float)(i))*scale) + tr.min.x;
+		r.max.x = (int)(((float)(i+1))*scale) + tr.min.x;
 		draw(t, r, ci, nil, ZP);
-		f += MAX(scale, 1);
-		r.min.x = f;
-		r.max.x = r.min.x + i;
+		i+=1;
 	}
 
 	freeimage(ci);
@@ -101,7 +96,7 @@
 		return -1;
 	}
 
-	// Location of the cursor relative to the source image's sp
+	// Location of the cursor relative to the source image's s
 	p.x = (int)(((float)dr.min.x)/scale);
 	p.y = (int)(((float)dr.min.y)/scale);
 	p = addpt(p, sp);
@@ -112,7 +107,7 @@
 	r.max.x = tr.max.x;
 	r.max.y = r.min.y + MAX(1.0, scale);
 
-	i = r.max.y - r.min.y;
+	i = 0;
 	d = p.y;
 	f = r.min.y;
 	while (r.min.y < dr.max.y) {
@@ -123,15 +118,14 @@
 		
 		// Move the ci one 1/scale space to the right
 		draw(ci, ci->r, t, nil, p);
-		d += MAX(1/scale, 1);
-		p.y = d;
+		p.y += 1;
 		
 		// Move the draw rectangle for the temporary image scale
 		// rectangles to the right
+		r.min.y = (int)(((float)(i))*scale) + dr.min.x;
+		r.max.y = (int)(((float)(i+1))*scale) + dr.min.x;
 		draw(di, r, ci, nil, ZP);
-		f += MAX(scale, 1);
-		r.min.y = f;
-		r.max.y = r.min.y + i;
+		i+=1;
 	}
 
 	freeimage(t);
--- a/utils.c
+++ b/utils.c
@@ -5,6 +5,58 @@
 #include "dat.h"
 #include "fns.h"
 
+#define TASKLISTSIZE 10
+
+QLock TaskLock;
+Task TaskList[TASKLISTSIZE] = {0};
+
+int newtask(ulong s, void (*f)(void))
+{
+	uint i;
+	
+	qlock(&TaskLock);
+	for (i = 0; i < ARRLEN(TaskList); i++) {
+		if (TaskList[i].func != nil)
+			continue;
+
+		TaskList[i] = (Task) { s, f };
+		break;
+	}
+	qunlock(&TaskLock);
+	
+	return i >= ARRLEN(TaskList) ? -1 : i;
+}
+
+int removetask(int id)
+{
+	if (id < 0 || id >= ARRLEN(TaskList))
+		return -1;
+	qlock(&TaskLock);
+	TaskList[id] = (Task) {0, nil};
+	qunlock(&TaskLock);
+	return 0;
+}
+
+void runtasks(void)
+{
+	Task * t;
+	Task tl[ARRLEN(TaskList)];
+	ulong i;
+	
+	qlock(&TaskLock);
+	memcpy(tl, TaskList, sizeof(TaskList));
+	qunlock(&TaskLock);
+
+	for (i = 0; i < ARRLEN(tl); i++) {
+		t = &tl[i];
+		if (t->func == nil || t->start > msec())
+			continue;
+
+		t->func();
+		removetask(i);
+	}
+}
+
 void
 quitloop(void)
 {
@@ -18,3 +70,4 @@
 	p.y = (int)(((float)p.y) * f);
 	return p;
 }
+
--