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
--
⑨