shithub: fnt

ref: f9bb63633ce47c39a98d929a98b8392c98b07e87
dir: /test_unix.c/

View raw version
#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;
}