shithub: fnt

Download patch

ref: 195e8566f95f1b519335cc875cc88c8eea2fa5a6
parent: 74a12cfebee05bc12502b499e3d818ba2aac6f7d
author: Sigrid Solveig Haflínudóttir <sigrid@ftrv.se>
date: Fri Jul 12 20:13:15 EDT 2024

move platform-dependent files around

--- a/meson.build
+++ b/meson.build
@@ -40,8 +40,8 @@
 
 src = [
 	'rast.c',
-	'unix.c',
-	'test_unix.c',
+	'unix/otfsys.c',
+	'unix/test.c',
 ]
 
 cc = meson.get_compiler('c')
--- a/mkfile
+++ b/mkfile
@@ -7,8 +7,8 @@
 OFILES=\
 	otf.$O\
 	rast.$O\
-	plan9.$O\
-	test_plan9.$O\
+	otfsys.$O\
+	test.$O\
 
 HFILES=\
 	plan9/otf.h\
@@ -18,6 +18,12 @@
 
 otf.$O: plan9/otf.c
 	$CC $CFLAGS plan9/otf.c
+
+otfsys.$O: plan9/otf.c
+	$CC $CFLAGS plan9/otfsys.c
+
+test.$O: plan9/test.c
+	$CC $CFLAGS plan9/test.c
 
 plan9/otf.h plan9/otf.c: gen.rkt otf.rkt
 	ssh $s76 'cd w/_/fnt && ./gen.rkt --plan9 --outdir plan9'
--- a/plan9.c
+++ /dev/null
@@ -1,8 +1,0 @@
-#include "otfsys.h"
-
-Tmfmt
-fmttime(vlong v)
-{
-	Tm t;
-	return tmfmt(tmtime(&t, v, nil), nil);
-}
--- /dev/null
+++ b/plan9/otfsys.c
@@ -1,0 +1,8 @@
+#include "otfsys.h"
+
+Tmfmt
+fmttime(vlong v)
+{
+	Tm t;
+	return tmfmt(tmtime(&t, v, nil), nil);
+}
--- /dev/null
+++ b/plan9/test.c
@@ -1,0 +1,175 @@
+#include <u.h>
+#include <libc.h>
+#include <bio.h>
+#include "otf.h"
+
+typedef struct Image Image;
+
+struct Image {
+	int w;
+	u8int *b;
+};
+
+static void
+fit(u8int *b, int bw, int bh, Image *im, int h, int *x, int *y, int gap)
+{
+	int d;
+
+	if((bw-*x) < im->w+gap){
+		*y += h + gap;
+		*x = gap;
+	}
+	if((bh-*y) < h+gap)
+		return;
+	for(d = 0; d < h; d++)
+		memcpy(b + (*y + d)*bw + *x, im->b + d*im->w, im->w);
+	*x += im->w + gap;
+}
+
+static void
+dumpmap(Biobuf *out, Image *im, int n, int h)
+{
+#define gap 2
+	int total, mid, npix, bw, bh, x, y, i;
+	u8int *b;
+
+	total = 0;
+	for(i = 0; i < n; i++)
+		total += im[i].w;
+	mid = total / n;
+	npix = (mid+gap)*(h+gap)*n;
+	bh = sqrt(npix);
+	bw = npix/bh;
+	bh *= 1.5;
+	npix *= 1.5;
+	npix += bw*gap;
+	if((b = malloc(npix)) == nil)
+		sysfatal("no memory");
+	memset(b, 0xff, npix);
+	x = y = gap;
+	for(i = 0; i < n; i++)
+		fit(b, bw, bh, im+i, h, &x, &y, gap);
+	Bprint(out, "%11s %11d %11d %11d %11d ", "k8", 0, 0, bw, y+h+gap);
+	Bwrite(out, b, bw*(y+h+gap));
+	free(b);
+}
+
+static int
+otfseek(void *aux, int off, int whence)
+{
+	return Bseek(aux, off, whence);
+}
+
+static int
+otfread(void *aux, void *dst, int sz)
+{
+	return Bread(aux, dst, sz);
+}
+
+static void
+usage(void)
+{
+	fprint(2, "usage: %s [-g GLYPH_ID] [-G] [-i N] [-s PX] font.otf ...\n", argv0);
+	fprint(2, " -g: specifies a single glyph id\n");
+	fprint(2, " -G: print out glyph ids, only ones that can be drawn atm (no compound yet)\n");
+	fprint(2, " -s: draw (of size PX) and write the image to stdout\n");
+	exits("usage");
+}
+
+void
+main(int argc, char **argv)
+{
+	int i, gi, G, h;
+	Otfile in, out;
+	Otf *o;
+
+	gi = -1;
+	G = 0;
+	h = 0;
+	ARGBEGIN{
+	case 'g':
+		gi = strtol(EARGF(usage()), nil, 0);
+		break;
+	case 'G':
+		G++;
+		break;
+	case 's':
+		h = strtol(EARGF(usage()), nil, 0);
+		break;
+	default:
+		usage();
+	}ARGEND
+
+	in.seek = otfseek;
+	in.read = otfread;
+	out.print = (void*)Bprint;
+
+	out.aux = Bfdopen(1, OWRITE);
+	for(i = 0; i < argc; i++){
+		if(h <= 0)
+			Bprint(out.aux, "%s\n", argv[i]);
+		if((in.aux = Bopen(argv[i], OREAD)) == nil || (o = otfopen(&in)) == nil){
+			fprint(2, "%r\n");
+			continue;
+		}
+		if(G && gi < 0){
+			int i, n = otfglyfnum(o);
+			Image *im = h > 0 ? calloc(n, sizeof(*im)) : nil;
+			for(i = 0; i < n; i++){
+				Glyf *g = otfglyf(o, i);
+				if(g == nil)
+					continue;
+				if(h > 0 && g->simple != nil && g->numberOfContours > 0){
+					int w;
+					u8int *b = otfdrawglyf(g, h, &w);
+					if(b == nil)
+						sysfatal("%r");
+					im[i].w = w;
+					im[i].b = b;
+				}else if(h <= 0){
+					Bprint(out.aux, "%d (%s):\n", i, g->simple ? "simple" : "component");
+					print_Glyf(&out, indentΔ, o, g);
+				}
+				free(g);
+			}
+			if(h > 0){
+				dumpmap(out.aux, im, n, h);
+				for(i = 0; i < n; i++)
+					free(im[i].b);
+				free(im);
+			}else{
+				fprint(2, "\n");
+			}
+		}else if(gi < 0){
+			otfprint(o, &out, indentΔ);
+		}else{
+			int n = otfglyfnum(o);
+			if(gi >= n)
+				sysfatal("glyph %d out of range, max %d\n", gi, n-1);
+			Glyf *g = otfglyf(o, gi);
+			if(g == nil){
+				fprint(2, "%d: %r\n", gi);
+			}else if(h > 0){
+				if(g->component != nil)
+					fprint(2, "%d: component\n", gi);
+				else{
+					int w;
+					u8int *b = otfdrawglyf(g, h, &w);
+					if(b == nil)
+						sysfatal("%r");
+					fprint(1, "%11s %11d %11d %11d %11d ", "k8", 0, 0, w, h);
+					write(1, b, w*h);
+					free(b);
+				}
+			}else{
+				Bprint(out.aux, "\n%d:\n", gi);
+				print_Glyf(&out, indentΔ, o, g);
+			}
+		}
+		otfclose(o);
+		Bterm(in.aux);
+	}
+	Bterm(out.aux);
+
+	exits(nil);
+}
--- a/test_plan9.c
+++ /dev/null
@@ -1,175 +1,0 @@
-#include <u.h>
-#include <libc.h>
-#include <bio.h>
-#include "otf.h"
-
-typedef struct Image Image;
-
-struct Image {
-	int w;
-	u8int *b;
-};
-
-static void
-fit(u8int *b, int bw, int bh, Image *im, int h, int *x, int *y, int gap)
-{
-	int d;
-
-	if((bw-*x) < im->w+gap){
-		*y += h + gap;
-		*x = gap;
-	}
-	if((bh-*y) < h+gap)
-		return;
-	for(d = 0; d < h; d++)
-		memcpy(b + (*y + d)*bw + *x, im->b + d*im->w, im->w);
-	*x += im->w + gap;
-}
-
-static void
-dumpmap(Biobuf *out, Image *im, int n, int h)
-{
-#define gap 2
-	int total, mid, npix, bw, bh, x, y, i;
-	u8int *b;
-
-	total = 0;
-	for(i = 0; i < n; i++)
-		total += im[i].w;
-	mid = total / n;
-	npix = (mid+gap)*(h+gap)*n;
-	bh = sqrt(npix);
-	bw = npix/bh;
-	bh *= 1.5;
-	npix *= 1.5;
-	npix += bw*gap;
-	if((b = malloc(npix)) == nil)
-		sysfatal("no memory");
-	memset(b, 0xff, npix);
-	x = y = gap;
-	for(i = 0; i < n; i++)
-		fit(b, bw, bh, im+i, h, &x, &y, gap);
-	Bprint(out, "%11s %11d %11d %11d %11d ", "k8", 0, 0, bw, y+h+gap);
-	Bwrite(out, b, bw*(y+h+gap));
-	free(b);
-}
-
-static int
-otfseek(void *aux, int off, int whence)
-{
-	return Bseek(aux, off, whence);
-}
-
-static int
-otfread(void *aux, void *dst, int sz)
-{
-	return Bread(aux, dst, sz);
-}
-
-static void
-usage(void)
-{
-	fprint(2, "usage: %s [-g GLYPH_ID] [-G] [-i N] [-s PX] font.otf ...\n", argv0);
-	fprint(2, " -g: specifies a single glyph id\n");
-	fprint(2, " -G: print out glyph ids, only ones that can be drawn atm (no compound yet)\n");
-	fprint(2, " -s: draw (of size PX) and write the image to stdout\n");
-	exits("usage");
-}
-
-void
-main(int argc, char **argv)
-{
-	int i, gi, G, h;
-	Otfile in, out;
-	Otf *o;
-
-	gi = -1;
-	G = 0;
-	h = 0;
-	ARGBEGIN{
-	case 'g':
-		gi = strtol(EARGF(usage()), nil, 0);
-		break;
-	case 'G':
-		G++;
-		break;
-	case 's':
-		h = strtol(EARGF(usage()), nil, 0);
-		break;
-	default:
-		usage();
-	}ARGEND
-
-	in.seek = otfseek;
-	in.read = otfread;
-	out.print = (void*)Bprint;
-
-	out.aux = Bfdopen(1, OWRITE);
-	for(i = 0; i < argc; i++){
-		if(h <= 0)
-			Bprint(out.aux, "%s\n", argv[i]);
-		if((in.aux = Bopen(argv[i], OREAD)) == nil || (o = otfopen(&in)) == nil){
-			fprint(2, "%r\n");
-			continue;
-		}
-		if(G && gi < 0){
-			int i, n = otfglyfnum(o);
-			Image *im = h > 0 ? calloc(n, sizeof(*im)) : nil;
-			for(i = 0; i < n; i++){
-				Glyf *g = otfglyf(o, i);
-				if(g == nil)
-					continue;
-				if(h > 0 && g->simple != nil && g->numberOfContours > 0){
-					int w;
-					u8int *b = otfdrawglyf(g, h, &w);
-					if(b == nil)
-						sysfatal("%r");
-					im[i].w = w;
-					im[i].b = b;
-				}else if(h <= 0){
-					Bprint(out.aux, "%d (%s):\n", i, g->simple ? "simple" : "component");
-					print_Glyf(&out, indentΔ, o, g);
-				}
-				free(g);
-			}
-			if(h > 0){
-				dumpmap(out.aux, im, n, h);
-				for(i = 0; i < n; i++)
-					free(im[i].b);
-				free(im);
-			}else{
-				fprint(2, "\n");
-			}
-		}else if(gi < 0){
-			otfprint(o, &out, indentΔ);
-		}else{
-			int n = otfglyfnum(o);
-			if(gi >= n)
-				sysfatal("glyph %d out of range, max %d\n", gi, n-1);
-			Glyf *g = otfglyf(o, gi);
-			if(g == nil){
-				fprint(2, "%d: %r\n", gi);
-			}else if(h > 0){
-				if(g->component != nil)
-					fprint(2, "%d: component\n", gi);
-				else{
-					int w;
-					u8int *b = otfdrawglyf(g, h, &w);
-					if(b == nil)
-						sysfatal("%r");
-					fprint(1, "%11s %11d %11d %11d %11d ", "k8", 0, 0, w, h);
-					write(1, b, w*h);
-					free(b);
-				}
-			}else{
-				Bprint(out.aux, "\n%d:\n", gi);
-				print_Glyf(&out, indentΔ, o, g);
-			}
-		}
-		otfclose(o);
-		Bterm(in.aux);
-	}
-	Bterm(out.aux);
-
-	exits(nil);
-}
--- a/test_unix.c
+++ /dev/null
@@ -1,206 +1,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <math.h>
-#include "otf.h"
-
-typedef struct Image Image;
-
-struct Image {
-	int w;
-	u8int *b;
-};
-
-static void
-fit(u8int *b, int bw, int bh, Image *im, int h, int *x, int *y, int gap)
-{
-	int d;
-
-	if((bw-*x) < im->w+gap){
-		*y += h + gap;
-		*x = gap;
-	}
-	if((bh-*y) < h+gap)
-		return;
-	for(d = 0; d < h; d++)
-		memcpy(b + (*y + d)*bw + *x, im->b + d*im->w, im->w);
-	*x += im->w + gap;
-}
-
-static void
-dumpmap(FILE *out, Image *im, int n, int h)
-{
-#define gap 2
-	int total, mid, npix, bw, bh, x, y, i;
-	u8int *b;
-
-	total = 0;
-	for(i = 0; i < n; i++)
-		total += im[i].w;
-	mid = total / n;
-	npix = (mid+gap)*(h+gap)*n;
-	bh = sqrt(npix);
-	bw = npix/bh;
-	bh *= 1.5;
-	npix *= 1.5;
-	npix += bw*gap;
-	if((b = malloc(npix)) == NULL){
-		fprintf(stderr, "no memory\n");
-		exit(1);
-	}
-	memset(b, 0xff, npix);
-	x = y = gap;
-	for(i = 0; i < n; i++)
-		fit(b, bw, bh, im+i, h, &x, &y, gap);
-	fprintf(out, "%11s %11d %11d %11d %11d ", "k8", 0, 0, bw, y+h+gap);
-	fwrite(b, 1, bw*(y+h+gap), out);
-	free(b);
-}
-
-static char *argv0;
-
-#define	ARGBEGIN	for((argv0? 0: (argv0=*argv)),argv++,argc--;\
-			    argv[0] && argv[0][0]=='-' && argv[0][1];\
-			    argc--, argv++) {\
-				char *_args, *_argt;\
-				int _argc;\
-				_args = &argv[0][1];\
-				if(_args[0]=='-' && _args[1]==0){\
-					argc--; argv++; break;\
-				}\
-				_argc = 0;\
-				while((_argc = *_args++) != 0)\
-				switch(_argc)
-#define	ARGEND		(void)_argt; (void)_argc; (void)_args;}(void)argv; (void)argc;
-#define	ARGF()		(_argt=_args, _args="",\
-				(*_argt? _argt: argv[1]? (argc--, *++argv): 0))
-#define	ARGC()		_argc
-
-#define	EARGF(x)		(_argt=_args, _args="",\
-				(*_argt? _argt: argv[1]? (argc--, *++argv): (x, (char*)0)))
-
-static int
-otfseek(void *aux, int off, int whence)
-{
-	if(fseek(aux, off, whence) < 0)
-		return -1;
-	return ftell(aux);
-}
-
-static int
-otfread(void *aux, void *dst, int sz)
-{
-	return fread(dst, 1, sz, aux);
-}
-
-static void
-usage(void)
-{
-	fprintf(stderr, "usage: %s [-g GLYPH_ID] [-G] [-i N] [-s PX] font.otf ...\n", argv0);
-	fprintf(stderr, " -g: specifies a single glyph id\n");
-	fprintf(stderr, " -G: print out glyph ids, only ones that can be drawn atm (no compound yet)\n");
-	fprintf(stderr, " -s: draw (of size PX) and write the image to stdout\n");
-	exit(1);
-}
-
-int
-main(int argc, char **argv)
-{
-	int i, gi, G, h;
-	Otfile in, out;
-	Otf *o;
-
-	gi = -1;
-	G = 0;
-	h = 0;
-	ARGBEGIN{
-	case 'g':
-		gi = strtol(EARGF(usage()), NULL, 0);
-		break;
-	case 'G':
-		G++;
-		break;
-	case 's':
-		h = strtol(EARGF(usage()), NULL, 0);
-		break;
-	default:
-		usage();
-	}ARGEND
-
-	in.seek = otfseek;
-	in.read = otfread;
-	out.print = (void*)fprintf;
-
-	out.aux = fdopen(1, "wb");
-	for(i = 0; i < argc; i++){
-		if(h <= 0)
-			fprintf(out.aux, "%s\n", argv[i]);
-		if((in.aux = fopen(argv[i], "rb")) == NULL || (o = otfopen(&in)) == NULL){
-			fprintf(stderr, "%s: failed\n", argv[i]);
-			continue;
-		}
-		if(G && gi < 0){
-			int i, n = otfglyfnum(o);
-			Image *im = h > 0 ? calloc(n, sizeof(*im)) : NULL;
-			for(i = 0; i < n; i++){
-				Glyf *g = otfglyf(o, i);
-				if(g == NULL)
-					continue;
-				if(h > 0 && g->simple != NULL && g->numberOfContours > 0){
-					int w;
-					u8int *b = otfdrawglyf(g, h, &w);
-					if(b == NULL){
-						fprintf(stderr, "failed\n");
-						exit(1);
-					}
-					im[i].w = w;
-					im[i].b = b;
-				}else if(h <= 0){
-					fprintf(out.aux, "%d (%s):\n", i, g->simple ? "simple" : "component");
-					print_Glyf(&out, indentΔ, o, g);
-				}
-				free(g);
-			}
-			if(h > 0){
-				dumpmap(out.aux, im, n, h);
-				for(i = 0; i < n; i++)
-					free(im[i].b);
-				free(im);
-			}
-		}else if(gi < 0){
-			otfprint(o, &out, indentΔ);
-		}else{
-			int n = otfglyfnum(o);
-			if(gi >= n){
-				fprintf(stderr, "glyph %d out of range, max %d\n", gi, n-1);
-				exit(1);
-			}
-			Glyf *g = otfglyf(o, gi);
-			if(g == NULL){
-				fprintf(stderr, "%d: failed\n", gi);
-			}else if(h > 0){
-				if(g->component != NULL)
-					fprintf(stderr, "%d: component\n", gi);
-				else{
-					int w;
-					u8int *b = otfdrawglyf(g, h, &w);
-					if(b == NULL){
-						fprintf(stderr, "failed\n");
-						exit(1);
-					}
-					fprintf(out.aux, "%11s %11d %11d %11d %11d ", "k8", 0, 0, w, h);
-					fwrite(b, 1, w*h, out.aux);
-					free(b);
-				}
-			}else{
-				fprintf(out.aux, "\n%d:\n", gi);
-				print_Glyf(&out, indentΔ, o, g);
-			}
-		}
-		otfclose(o);
-		fclose(in.aux);
-	}
-	fclose(out.aux);
-
-	return 0;
-}
--- a/unix.c
+++ /dev/null
@@ -1,33 +1,0 @@
-#include "otfsys.h"
-#include <stdarg.h>
-#include <time.h>
-
-char *
-fmttime(long long v)
-{
-	static char buf[32];
-	time_t t = v;
-	struct tm *tm;
-	tm = gmtime(&t);
-	strftime(buf, sizeof(buf), "%c", tm);
-	return buf;
-}
-
-#define ERRMAX 512
-
-static char errstr[ERRMAX];
-
-void
-werrstr(char *fmt, ...)
-{
-	va_list a;
-	char buf[ERRMAX];
-	int n;
-
-	va_start(a, fmt);
-	n = vsnprintf(buf, sizeof(buf), fmt, a);
-	va_end(a);
-	if(n >= 2 && buf[n-2] == '%' && buf[n-1] == 'r')
-		snprintf(buf+n-2, sizeof(buf)-n+2, "%s", errstr);
-	strcpy(errstr, buf);
-}
--- /dev/null
+++ b/unix/otfsys.c
@@ -1,0 +1,33 @@
+#include "otfsys.h"
+#include <stdarg.h>
+#include <time.h>
+
+char *
+fmttime(long long v)
+{
+	static char buf[32];
+	time_t t = v;
+	struct tm *tm;
+	tm = gmtime(&t);
+	strftime(buf, sizeof(buf), "%c", tm);
+	return buf;
+}
+
+#define ERRMAX 512
+
+static char errstr[ERRMAX];
+
+void
+werrstr(char *fmt, ...)
+{
+	va_list a;
+	char buf[ERRMAX];
+	int n;
+
+	va_start(a, fmt);
+	n = vsnprintf(buf, sizeof(buf), fmt, a);
+	va_end(a);
+	if(n >= 2 && buf[n-2] == '%' && buf[n-1] == 'r')
+		snprintf(buf+n-2, sizeof(buf)-n+2, "%s", errstr);
+	strcpy(errstr, buf);
+}
--- /dev/null
+++ b/unix/test.c
@@ -1,0 +1,206 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+#include "otf.h"
+
+typedef struct Image Image;
+
+struct Image {
+	int w;
+	u8int *b;
+};
+
+static void
+fit(u8int *b, int bw, int bh, Image *im, int h, int *x, int *y, int gap)
+{
+	int d;
+
+	if((bw-*x) < im->w+gap){
+		*y += h + gap;
+		*x = gap;
+	}
+	if((bh-*y) < h+gap)
+		return;
+	for(d = 0; d < h; d++)
+		memcpy(b + (*y + d)*bw + *x, im->b + d*im->w, im->w);
+	*x += im->w + gap;
+}
+
+static void
+dumpmap(FILE *out, Image *im, int n, int h)
+{
+#define gap 2
+	int total, mid, npix, bw, bh, x, y, i;
+	u8int *b;
+
+	total = 0;
+	for(i = 0; i < n; i++)
+		total += im[i].w;
+	mid = total / n;
+	npix = (mid+gap)*(h+gap)*n;
+	bh = sqrt(npix);
+	bw = npix/bh;
+	bh *= 1.5;
+	npix *= 1.5;
+	npix += bw*gap;
+	if((b = malloc(npix)) == NULL){
+		fprintf(stderr, "no memory\n");
+		exit(1);
+	}
+	memset(b, 0xff, npix);
+	x = y = gap;
+	for(i = 0; i < n; i++)
+		fit(b, bw, bh, im+i, h, &x, &y, gap);
+	fprintf(out, "%11s %11d %11d %11d %11d ", "k8", 0, 0, bw, y+h+gap);
+	fwrite(b, 1, bw*(y+h+gap), out);
+	free(b);
+}
+
+static char *argv0;
+
+#define	ARGBEGIN	for((argv0? 0: (argv0=*argv)),argv++,argc--;\
+			    argv[0] && argv[0][0]=='-' && argv[0][1];\
+			    argc--, argv++) {\
+				char *_args, *_argt;\
+				int _argc;\
+				_args = &argv[0][1];\
+				if(_args[0]=='-' && _args[1]==0){\
+					argc--; argv++; break;\
+				}\
+				_argc = 0;\
+				while((_argc = *_args++) != 0)\
+				switch(_argc)
+#define	ARGEND		(void)_argt; (void)_argc; (void)_args;}(void)argv; (void)argc;
+#define	ARGF()		(_argt=_args, _args="",\
+				(*_argt? _argt: argv[1]? (argc--, *++argv): 0))
+#define	ARGC()		_argc
+
+#define	EARGF(x)		(_argt=_args, _args="",\
+				(*_argt? _argt: argv[1]? (argc--, *++argv): (x, (char*)0)))
+
+static int
+otfseek(void *aux, int off, int whence)
+{
+	if(fseek(aux, off, whence) < 0)
+		return -1;
+	return ftell(aux);
+}
+
+static int
+otfread(void *aux, void *dst, int sz)
+{
+	return fread(dst, 1, sz, aux);
+}
+
+static void
+usage(void)
+{
+	fprintf(stderr, "usage: %s [-g GLYPH_ID] [-G] [-i N] [-s PX] font.otf ...\n", argv0);
+	fprintf(stderr, " -g: specifies a single glyph id\n");
+	fprintf(stderr, " -G: print out glyph ids, only ones that can be drawn atm (no compound yet)\n");
+	fprintf(stderr, " -s: draw (of size PX) and write the image to stdout\n");
+	exit(1);
+}
+
+int
+main(int argc, char **argv)
+{
+	int i, gi, G, h;
+	Otfile in, out;
+	Otf *o;
+
+	gi = -1;
+	G = 0;
+	h = 0;
+	ARGBEGIN{
+	case 'g':
+		gi = strtol(EARGF(usage()), NULL, 0);
+		break;
+	case 'G':
+		G++;
+		break;
+	case 's':
+		h = strtol(EARGF(usage()), NULL, 0);
+		break;
+	default:
+		usage();
+	}ARGEND
+
+	in.seek = otfseek;
+	in.read = otfread;
+	out.print = (void*)fprintf;
+
+	out.aux = fdopen(1, "wb");
+	for(i = 0; i < argc; i++){
+		if(h <= 0)
+			fprintf(out.aux, "%s\n", argv[i]);
+		if((in.aux = fopen(argv[i], "rb")) == NULL || (o = otfopen(&in)) == NULL){
+			fprintf(stderr, "%s: failed\n", argv[i]);
+			continue;
+		}
+		if(G && gi < 0){
+			int i, n = otfglyfnum(o);
+			Image *im = h > 0 ? calloc(n, sizeof(*im)) : NULL;
+			for(i = 0; i < n; i++){
+				Glyf *g = otfglyf(o, i);
+				if(g == NULL)
+					continue;
+				if(h > 0 && g->simple != NULL && g->numberOfContours > 0){
+					int w;
+					u8int *b = otfdrawglyf(g, h, &w);
+					if(b == NULL){
+						fprintf(stderr, "failed\n");
+						exit(1);
+					}
+					im[i].w = w;
+					im[i].b = b;
+				}else if(h <= 0){
+					fprintf(out.aux, "%d (%s):\n", i, g->simple ? "simple" : "component");
+					print_Glyf(&out, indentΔ, o, g);
+				}
+				free(g);
+			}
+			if(h > 0){
+				dumpmap(out.aux, im, n, h);
+				for(i = 0; i < n; i++)
+					free(im[i].b);
+				free(im);
+			}
+		}else if(gi < 0){
+			otfprint(o, &out, indentΔ);
+		}else{
+			int n = otfglyfnum(o);
+			if(gi >= n){
+				fprintf(stderr, "glyph %d out of range, max %d\n", gi, n-1);
+				exit(1);
+			}
+			Glyf *g = otfglyf(o, gi);
+			if(g == NULL){
+				fprintf(stderr, "%d: failed\n", gi);
+			}else if(h > 0){
+				if(g->component != NULL)
+					fprintf(stderr, "%d: component\n", gi);
+				else{
+					int w;
+					u8int *b = otfdrawglyf(g, h, &w);
+					if(b == NULL){
+						fprintf(stderr, "failed\n");
+						exit(1);
+					}
+					fprintf(out.aux, "%11s %11d %11d %11d %11d ", "k8", 0, 0, w, h);
+					fwrite(b, 1, w*h, out.aux);
+					free(b);
+				}
+			}else{
+				fprintf(out.aux, "\n%d:\n", gi);
+				print_Glyf(&out, indentΔ, o, g);
+			}
+		}
+		otfclose(o);
+		fclose(in.aux);
+	}
+	fclose(out.aux);
+
+	return 0;
+}