shithub: fnt

ref: 5877598b3b65ae59ec9d1447e222af4b1e848911
dir: /plan9/test.c/

View raw version
#include <u.h>
#include <libc.h>
#include <bio.h>
#include "otf.h"

static void
dumpmap(Biobuf *out, GlyfImage *im, int n)
{
#define gap 1
	int total, mid, npix, bw, bh, x, y, i, maxh, d;
	u8int *b;

	total = 0;
	maxh = 0;
	for(i = 0; i < n; i++){
		if(maxh < im[i].h)
			maxh = im[i].h;
		total += im[i].w;
	}
	mid = total / n;
	npix = (mid+gap)*(maxh+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++){
		if((bw-x) < im[i].w+gap){
			y += maxh + gap;
			x = gap;
		}
		if((bh-y) < maxh+gap)
			continue;
		for(d = 0; d < im[i].h; d++)
			memcpy(b + (maxh - im[i].h + y + im[i].baseline + d)*bw + x, im[i].b + d*im[i].w, im[i].w);
		x += im[i].w + gap;
	}
	Bprint(out, "%11s %11d %11d %11d %11d ", "k8", 0, 0, bw, y+maxh*2+gap);
	Bwrite(out, b, bw*(y+maxh*2+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] [-p PPM] 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, " -p: draw (of size in pixels per em) and write the image to stdout\n");
	exits("usage");
}

void
main(int argc, char **argv)
{
	int i, gi, G, ppem;
	Otfile in, out;
	Otf *o;

	gi = -1;
	G = 0;
	ppem = 0;
	ARGBEGIN{
	case 'g':
		gi = strtol(EARGF(usage()), nil, 0);
		break;
	case 'G':
		G++;
		break;
	case 'p':
		ppem = 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((in.aux = Bopen(argv[i], OREAD)) == nil || (o = otfopen(&in)) == nil){
			fprint(2, "%r\n");
			continue;
		}
		if(ppem <= 0)
			Bprint(out.aux, "%s\n", argv[i]);
		if(G && gi < 0){
			int i, n = otfglyfnum(o);
			GlyfImage *im = ppem > 0 ? calloc(n, sizeof(*im)) : nil;
			for(i = 0; i < n; i++){
				Glyf *g = otfglyf(o, i);
				if(g == nil)
					sysfatal("glyf %d: %r", i);
				if(ppem > 0 && g->numberOfContours != 0){
					if(otfdrawglyf(o, g, ppem, &im[i]) != 0)
						sysfatal("glyf %d: %r", i);
				}else if(ppem <= 0){
					Bprint(out.aux, "%d (%s):\n", i,
						g->simple ? "simple" : (g->component ? "component" : "empty"));
					print_Glyf(&out, indentΔ, o, g);
				}
				free(g);
			}
			if(ppem > 0){
				dumpmap(out.aux, im, n);
				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", gi, n-1);
			Glyf *g = otfglyf(o, gi);
			if(g == nil){
				fprint(2, "%d: %r\n", gi);
			}else if(ppem > 0){
				GlyfImage im;
				if(otfdrawglyf(o, g, ppem, &im) != 0)
					sysfatal("%r");
				fprint(1, "%11s %11d %11d %11d %11d ", "k8", 0, 0, im.w, im.h);
				write(1, im.b, im.w*im.h);
				free(im.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);
}