Mercurial > yawc
view cursors/92h.sh @ 0:f0372d3356b4 default tip
initial import
| author | Yasuri <linuxoverwindows@charliesmp.net> |
|---|---|
| date | Sun, 30 Aug 2026 12:47:10 -0500 |
| parents | |
| children |
line wrap: on
line source
#!/bin/sh # convert plan 9 cursor definitions in a C file to packed argb cursor_data[] + cursor_metadata[] for swc # asage: # ./92h.sh 9cursors.c > out.c # ./92h.sh 9cursors.c tl t tr l r bl b br > out.c # explicit order/subset infile=${1:-/dev/stdin} shift 2>/dev/null || true # remaining args are optional, desired cursor names in output order. order="$*" awk -v ORDER="$order" ' function hexval(c) { c = toupper(c) if (c >= "0" && c <= "9") return c + 0 return 10 + index("ABCDEF", c) - 1 } function hex2dec(s, i,n) { sub(/^0[xX]/, "", s) n = 0 for (i = 1; i <= length(s); i++) n = n * 16 + hexval(substr(s, i, 1)) return n } function pow2(n, i,p) { p=1; for(i=0;i<n;i++) p*=2; return p } function bit16msb(v, col, shift) { shift = 15 - col return int(v / P2[shift]) % 2 } function pix(setb, clrb) { # clr=0,set=0 => transparent # clr=1,set=0 => black # clr=0,set=1 => white # clr=1,set=1 => invert (approximate as white for ARGB cursors) if (!clrb && !setb) return "0x00000000" if (clrb && !setb) return "0xff000000" if (!clrb && setb) return "0xffffffff" return "0xffffffff" } function min(a,b){ return (a<b)?a:b } function max(a,b){ return (a>b)?a:b } BEGIN { # precompute powers of two up to 15 for (i=0;i<16;i++) P2[i]=pow2(i) want_cnt = 0 if (ORDER != "") { n = split(ORDER, want, /[[:space:]]+/) for (i=1;i<=n;i++) if (want[i] != "") { want_cnt++; wantlist[want[i]]=i } } in_cursor = 0 arr = 0 c1 = c2 = 0 name_cnt = 0 } # start of a cursor block: cursor foo = { match($0, /^[[:space:]]*Cursor[[:space:]]+[A-Za-z_][A-Za-z0-9_]*[[:space:]]*=/) { # extract the name line = $0 sub(/^[[:space:]]*Cursor[[:space:]]+/, "", line) cur = line sub(/[[:space:]]*=.*/, "", cur) in_cursor = 1 got_hot = 0 arr = 0 c1 = 0 c2 = 0 next } # inside cursor: hotspot like {-7, -7}, compute it properly so it offsets, in_cursor && !got_hot && match($0, /\{[[:space:]]*-?[0-9]+[[:space:]]*,[[:space:]]*-?[0-9]+[[:space:]]*\}/) { s = substr($0, RSTART+1, RLENGTH-2) gsub(/[[:space:]]*/, "", s) split(s, a, ",") hx[cur] = a[1] + 0 hy[cur] = a[2] + 0 got_hot = 1 } in_cursor { while (match($0, /0[xX][0-9A-Fa-f]+/)) { tok = substr($0, RSTART, RLENGTH) val = hex2dec(tok) if (arr == 0) arr = 1 if (arr == 1) { clr[cur, c1++] = val if (c1 >= 32) arr = 2 } else { set[cur, c2++] = val } $0 = substr($0, RSTART + RLENGTH) } } # end of cursor block in_cursor && /};/ { in_cursor = 0 if (!(seen[cur]++)) { name_cnt++ names[name_cnt] = cur } if (c1 < 32 || c2 < 32) { warn[cur] = 1 } } END { # decide output order outn = 0 if (want_cnt > 0) { for (i=1; i<=want_cnt; i++) out[++outn] = want[i] } else { for (i=1; i<=name_cnt; i++) out[++outn] = names[i] } print "/* generated from plan 9 cursor data */" print "#include <stdint.h>" print "#include <stddef.h>" print "" print "enum {" for (oi=1; oi<=outn; oi++) { n = out[oi] if (n == "") continue name = toupper(n) gsub(/[^A-Z0-9]+/, "_", name) printf "\tNEIN_CURSOR_%s = %d,\n", name, oi-1 } print "};" print "" print "static const uint32_t nein_cursor_data[] = {" off = 0 perline = 0 for (oi=1; oi<=outn; oi++) { n = out[oi] if (n == "") continue if (!(seen[n])) { printf "/* WARNING: cursor %s not found */\n", n continue } if (warn[n]) { printf "/* WARNING: cursor %s looked incomplete (expected 32 clr + 32 set bytes) */\n", n } # build full 16x16 pixels and compute tight bbox minx=16; miny=16; maxx=-1; maxy=-1 for (y=0; y<16; y++) { rowc = clr[n,2*y]*256 + clr[n,2*y+1] rows = set[n,2*y]*256 + set[n,2*y+1] for (x=0; x<16; x++) { pb = pix(bit16msb(rows,x), bit16msb(rowc,x)) full[n,y,x] = pb if (pb != "0x00000000") { minx = min(minx, x); maxx = max(maxx, x) miny = min(miny, y); maxy = max(maxy, y) } } } # if entirely transparent, fall back to 1x1 if (maxx < 0) { minx=0; maxx=0; miny=0; maxy=0 } w = maxx - minx + 1 h = maxy - miny + 1 #offset hostspot xhot = -hx[n] yhot = -hy[n] hx2 = xhot - minx hy2 = yhot - miny meta_name[oi] = n meta_w[oi] = w meta_h[oi] = h meta_hx[oi] = hx2 meta_hy[oi] = hy2 meta_off[oi] = off for (y=miny; y<=maxy; y++) { for (x=minx; x<=maxx; x++) { v = full[n,y,x] if (perline == 0) printf "\t" printf "%s,", v perline++ off++ if (perline >= 6) { printf "\n"; perline = 0 } else printf " " } } if (perline != 0) { printf "\n"; perline = 0 } } print "};" print "" print "struct nein_cursor_meta {" print "\tuint32_t width, height;" print "\tint32_t hotspot_x, hotspot_y;" print "\tsize_t offset;" print "};" print "" print "static const struct nein_cursor_meta nein_cursor_metadata[] = {" for (oi=1; oi<=outn; oi++) { n = meta_name[oi] if (n == "") continue printf "\t{ %d, %d, %d, %d, %d }, /* %s */\n", meta_w[oi], meta_h[oi], meta_hx[oi], meta_hy[oi], meta_off[oi], n } print "};" } ' "$infile"
