shithub: cursexp

Download patch

ref: 044014910f2ffded4bebadbd729d76aa4dea2111
author: sirjofri <sirjofri@sirjofri.de>
date: Tue Jun 17 15:42:42 EDT 2025

adds cursexp

--- /dev/null
+++ b/cursexp.c
@@ -1,0 +1,249 @@
+#include <u.h>
+#include <libc.h>
+#include <draw.h>
+#include <memdraw.h>
+
+void
+usage(void)
+{
+	fprint(2, "usage: %s [-g] [-c]\n", argv0);
+	exits("usage");
+}
+
+#define UNPACK(a, n) (((*a)>>n)&0x3)
+
+uchar byte = 0;
+uchar num = 0;
+uchar numforrow = 0;
+
+void
+condwrite(int one)
+{
+	uchar new = byte<<1 | one;
+	byte = new;
+	num++;
+	if (num == 8) {
+		if (numforrow == 0)
+			print("\t");
+		print("0x%02x,", byte);
+		num = 0;
+		byte = 0;
+		numforrow++;
+		if (numforrow != 8)
+			print(" ");
+	}
+	if (numforrow == 8) {
+		numforrow = 0;
+		print("\n");
+	}
+}
+
+void
+i2c(Memimage *img)
+{
+	Point pt;
+	uchar *b;
+	uchar v;
+	int x, y;
+	
+	for (y = 0; y < 16; y++) {
+		for (x = 0; x < 4; x++) {
+			pt.x = x*4;
+			pt.y = y;
+			b = byteaddr(img, pt);
+			v = UNPACK(b, 6);
+			condwrite(v == 3);
+			v = UNPACK(b, 4);
+			condwrite(v == 3);
+			v = UNPACK(b, 2);
+			condwrite(v == 3);
+			v = UNPACK(b, 0);
+			condwrite(v == 3);
+		}
+	}
+	print("\n");
+	for (y = 0; y < 16; y++) {
+		for (x = 0; x < 4; x++) {
+			pt.x = x*4;
+			pt.y = y;
+			b = byteaddr(img, pt);
+			v = UNPACK(b, 6);
+			condwrite(v == 0);
+			v = UNPACK(b, 4);
+			condwrite(v == 0);
+			v = UNPACK(b, 2);
+			condwrite(v == 0);
+			v = UNPACK(b, 0);
+			condwrite(v == 0);
+		}
+	}
+}
+
+char hex[] = "0123456789abcdef";
+char HEX[] = "0123456789ABCDEF";
+char ign[] = " \t\n,";
+char Eformat[] = "invalid format";
+
+uchar
+readbyte(void)
+{
+	char buf;
+	uchar v = 0;
+	int stage = 0;
+	char *p;
+	ulong nbytes = 0;
+	int n;
+	
+	for (;;) {
+		n = read(0, &buf, 1);
+		if (n < 0)
+			sysfatal("read: %r");
+		if (n == 0) {
+			fprint(2, "read: eof at %uld\n", nbytes);
+			exits("eof");
+		}
+		nbytes++;
+		switch (stage) {
+		case 0: /* ign */
+			if (buf == '0') {
+				stage++;
+				break;
+			}
+			if (strchr(ign, buf))
+				break;
+			fprint(2, "invalid character: '%c' at %uld\n", buf, nbytes);
+			exits(Eformat);
+		case 1: /* '0' */
+			if (buf == 'x') {
+				stage++;
+				break;
+			}
+			goto Errnohex;
+		case 2: /* 'x' */
+			p = strchr(hex, buf);
+			if (!p)
+				p = strchr(HEX, buf);
+			if (!p)
+				goto Errnohex;
+			v = ((p-hex)<<4)&0xf0;
+			stage++;
+			break;
+		case 3: /* 'N' */
+			p = strchr(hex, buf);
+			if (!p)
+				p = strchr(HEX, buf);
+			if (!p)
+				goto Errnohex;
+			v |= (p-hex)&0x0f;
+			stage++;
+			break;
+		case 4: /* 'N' */
+			return v;
+		}
+	}
+	
+Errnohex:
+	fprint(2, "invalid format: no valid hex (got '%c' at %uld)\n", buf, nbytes);
+	exits(Eformat);
+}
+
+void
+c2i(void)
+{
+	Memimage *white, *black, *img;
+	int x, y;
+	uchar *b;
+	uchar r;
+	Point pt;
+	
+	white = allocmemimage(Rect(0, 0, 16, 16), GREY1);
+	black = allocmemimage(Rect(0, 0, 16, 16), GREY1);
+	img = allocmemimage(Rect(0, 0, 16, 16), GREY2);
+	
+	for (y = 0; y < 16; y++) {
+		for (x = 0; x < 4; x++) {
+			pt.x = x*4;
+			pt.y = y;
+			b = byteaddr(img, pt);
+			/* 10 or 01 would both work, but 10 is visually easier to read */
+			*b = 0b10101010;
+		}
+	}
+	
+	for (y = 0; y < 16; y++) {
+		for (x = 0; x < 2; x++) {
+			pt.x = x*8;
+			pt.y = y;
+			r = readbyte();
+			b = byteaddr(white, pt);
+			*b = r;
+		}
+	}
+	for (y = 0; y < 16; y++) {
+		for (x = 0; x < 2; x++) {
+			pt.x = x*8;
+			pt.y = y;
+			r = readbyte();
+			b = byteaddr(black, pt);
+			*b = r;
+		}
+	}
+	memimagedraw(img, img->r, memwhite, ZP, white, ZP, SatopD);
+	memimagedraw(img, img->r, memblack, ZP, black, ZP, SatopD);
+	writememimage(1, img);
+	freememimage(img);
+}
+
+void
+gentemplate(void)
+{
+	Memimage *img;
+	
+	if (memimageinit())
+		sysfatal("%r");
+	
+	img = allocmemimage(Rect(0, 0, 16, 16), GREY2);
+	memfillcolor(img, 0xaaaaaaff);
+	writememimage(1, img);
+	freememimage(img);
+}
+
+void
+main(int argc, char **argv)
+{
+	int gentempl = 0;
+	int reverse = 0;
+	Memimage *img;
+	
+	ARGBEGIN {
+	case 'h':
+		usage();
+		break;
+	case 'g':
+		gentempl++;
+		break;
+	case 'c':
+		reverse++;
+		break;
+	} ARGEND;
+	
+	if (memimageinit())
+		sysfatal("%r");
+	
+	if (gentempl) {
+		gentemplate();
+		exits(nil);
+	}
+	
+	if (reverse) {
+		c2i();
+		exits(nil);
+	}
+	
+	img = readmemimage(0);
+	if (!img)
+		sysfatal("invalid image format: %r");
+	
+	i2c(img);
+	exits(nil);
+}
--- /dev/null
+++ b/mkfile
@@ -1,0 +1,6 @@
+</$objtype/mkfile
+
+TARG=cursexp
+OFILES=cursexp.$O
+
+</sys/src/cmd/mkone
binary files /dev/null b/test/in.img differ
--- /dev/null
+++ b/test/inc.rc
@@ -1,0 +1,14 @@
+#!/bin/rc
+
+# test cursor include generation
+../$O.out <in.img >out.inc
+../$O.out -c <out.inc >out.img
+cmp in.img out.img
+
+
+# test template generation
+expected='gen.img: Compressed plan 9 image or subfont, depth 2, size 16x16'
+
+../$O.out -g >gen.img
+cap=`{file gen.img}
+~ $"cap $"expected || echo 'invalid file format'
--- /dev/null
+++ b/test/main.c
@@ -1,0 +1,67 @@
+#include <u.h>
+#include <libc.h>
+#include <draw.h>
+#include <event.h>
+#include <keyboard.h>
+#include <cursor.h>
+
+Cursor cursor = {
+	0, 0,
+#include "out.inc"
+};
+
+Image *grey;
+Image *original = nil;
+
+void
+eresized(int new)
+{
+	if (new && getwindow(display, Refnone) < 0)
+		sysfatal("%r");
+	
+	draw(screen, screen->r, grey, nil, ZP);
+	draw(screen, rectaddpt(screen->r, Pt(50, 50)), original, nil, ZP);
+}
+
+void
+main(int argc, char **argv)
+{
+	Event ev;
+	int fd;
+	int run = 0;
+	
+	ARGBEGIN{
+	case 'r':
+		run++;
+		break;
+	}ARGEND;
+	
+	if (!run) {
+		print("cursexp/test/main needs -r to be run (needs graphics).\n");
+		exits(nil);
+	}
+	
+	initdraw(nil, nil, "test");
+	
+	fd = open("in.img", OREAD);
+	if (fd < 0)
+		sysfatal("open: %r");
+	
+	original = readimage(display, fd, 0);
+	close(fd);
+	
+	einit(Emouse|Ekeyboard);
+	esetcursor(&cursor);
+	
+	grey = allocimage(display, Rect(0, 0, 1, 1), screen->chan, 1, 0xaaaaaaff);
+	eresized(0);
+	
+	for (;;) {
+		event(&ev);
+		switch (ev.kbdc) {
+		case 'q':
+		case Kdel:
+			exits(nil);
+		}
+	}
+}
--- /dev/null
+++ b/test/mkfile
@@ -1,0 +1,13 @@
+</$objtype/mkfile
+
+TEST=inc main
+CLEANFILES=out.img out.inc gen.img
+
+</sys/src/cmd/mktest
+
+out.img: out.inc ../$O.out
+	../$O.out -c <out.inc >$target
+	cmp $target in.img
+
+out.inc: in.img ../$O.out
+	../$O.out <in.img >$target
--