~aleteoryx/9c

ed66e1448f0b4a291d411339c50d7688b6485b3d — glenda 12 days ago fc5841a
lotta refactoring
1 files changed, 123 insertions(+), 79 deletions(-)

M ufx2font.c
M ufx2font.c => ufx2font.c +123 -79
@@ 7,6 7,7 @@
#define ufxlen(n) ((n)*(n)*8)
#define max(a, b) ((a) > (b) ? (a) : (b))
#define min(a, b) ((a) < (b) ? (a) : (b))
#define warn(fmt, ...) fprint(2, "%s: " fmt "\n", argv0, __VA_ARGS__)


enum{


@@ 50,8 51,7 @@ struct MapFile *mapfiles, *lastmf;

uchar wasmferr, wasreaderr;

uchar *gbitmaps;
struct GlyphInfo *ginfo;
struct GlyphInfo *glyphs;


void


@@ 120,7 120,7 @@ _parsemapfile(Biobuf *b, struct MapFile *mf)
	line = Brdline(b, '\n');
	if(line == nil){
		if(!wasreaderr)
			fprint(2, "%s: warn: %s: empty file\n", argv0, mf->file);
			warn("warn: %s: empty file\n", mf->file);
		return;
	}



@@ 285,64 285,92 @@ printmapfile(struct MapFile *mf)
		}
	}
}
void
addmapfile(char *file)
{
	if(lastmf == nil)
		mapfiles = lastmf = malloc(sizeof(struct MapFile));
	else
		lastmf = lastmf->next = malloc(sizeof(struct MapFile));
	lastmf->file = file;
	lastmf->next = nil;
	lastmf->mappings = nil;

	parsemapfile(lastmf);
}
void
checkmapfiles(void)
{
	if(wasmferr)
		exits("mapfile");
}


void
sniffdims(char *file)
guesswidth(char *file)
{
	uint len;
	Dir *d;
	char c;

	len = strlen(file);
	c = file[len-1];

	if(fwidth < 1){
		c = file[len-1];
		if('1' <= c && c <= '8' && strncmp(file+len-4, ".uf", 3) == 0){
			fwidth = c - '0';
		}
	if('1' <= c && c <= '8' && strncmp(file+len-4, ".uf", 3) == 0){
		fwidth = c - '0';
	}
}
void
guesslength(char *file, Dir *d)
{
	if(nglyphs == 0){
		if(d->length % (1+glyphlen) != 0)
			sysfatal("%s: can't determine file dimensions", file);
		nglyphs = d->length / (1+glyphlen);
	}else if(nglyphs * (1+glyphlen) > d->length)
		sysfatal("%s: file too short", file);
}
void
guessdims(char *file)
{
	Dir *d;

	if(fwidth < 1)
		guesswidth(file);
	if(fwidth < 1)
		sysfatal("%s: can't determine glyph width", file);
	
	glyphlen = ufxlen(fwidth);
	glyphedge = fwidth * 8;	


	d = dirstat(file);
	if(d == nil)
		sysfatal("%r");

	if(nglyphs == 0){
		if(d->length % (1+glyphlen) != 0)
			sysfatal("%s: can't determine file dimensions", file);
		nglyphs = d->length / (1+glyphlen);
	}else if(nglyphs * (1+glyphlen) > d->length)
		sysfatal("%s: file too short", file);
	guesslength(file, d);
	free(d);
}


void
loadufx(char *infile)
loadwidths(Biobuf *b, char *file)
{
	Biobuf *b;
	uint i, len;
	uint i;
	int n;

	len = nglyphs * glyphlen;
	gbitmaps = malloc(len);
	ginfo = malloc(nglyphs * sizeof(struct GlyphInfo));
	b = Bopen(infile, OREAD);
	
	for(i = 0; i < nglyphs; i++){
		n = Bgetc(b);
		if(n < 0)
			sysfatal("%r");
		ginfo[i].width = n;
	}

	if(Bread(b, gbitmaps, len) != len)
		sysfatal("%r");
		
		if(n > glyphedge){
			warn("%s: 0x%02x: bad width %d, truncating\n", file, i, n);
			n = glyphedge;
		}

	Bterm(b);
		glyphs[i].width = n;
	}
}

uchar
testscanline(uchar *bitmap, int rowlen)
{


@@ 357,40 385,52 @@ testscanline(uchar *bitmap, int rowlen)
	return 0;	
}
void
parseglyphs(char *file)
parseglyph(uchar *bitmap, struct GlyphInfo *ginfo, uint *botfreqs)
{
	uint i, y, top, bot, *botfreqs = nil, bestfreq;
	int rowlen;
	uint top, bot;
	int rowlen = ginfo->width;

	for(top = 0; top < glyphedge; top++)
		if(testscanline(bitmap+top, rowlen))
			break;
	for(bot = glyphedge-1; bot >= top; bot--)
		if(testscanline(bitmap+bot, rowlen))
			break;

	if(botfreqs != nil && top <= bot)	/* don't count empty glyphs */
		botfreqs[bot]++;
	ginfo->top = top; ginfo->bottom = bot;
}
void
readglyphs(Biobuf *b, uint *botfreqs)
{
	uint i;
	uchar *bitmap;
	long n;

	if(baseline < 1)
		botfreqs = calloc(glyphedge, sizeof(uint));
	bitmap = malloc(glyphlen);

	for(i = 0; i < nglyphs; i++){
		rowlen = ginfo[i].width;
		if(rowlen == 0)
			continue;
		if(rowlen > glyphedge){
			fprint(2, "%s: %s: 0x%2x: bad width %dpx, truncating\n", argv0, file, i, rowlen);
			rowlen = glyphedge;
		}
		bitmap = gbitmaps+i*glyphlen;

		for(y = 0; y < glyphedge; y++)
			if(testscanline(bitmap+y, rowlen))
				break;
		top = y;
		for(y = glyphedge-1; y >= top; y--)
			if(testscanline(bitmap+y, rowlen))
				break;
		bot = y;

		ginfo[i].top = top; ginfo[i].bottom = bot;
		if(baseline < 1 && top <= bot)	/* don't count empty glyphs */
			botfreqs[bot]++;
		n = Bread(b, bitmap, glyphlen);
		if(n < 0)
			sysfatal("%r");
		if(n != glyphlen)
			sysfatal("unexpected eof");
		parseglyph(bitmap, glyphs+i, botfreqs);
	}

	free(bitmap);
}
void
loadglyphs(Biobuf *b)
{
	uint i, *botfreqs, bestfreq;

	if(baseline < 1){
		botfreqs = calloc(glyphedge, sizeof(uint));

		readglyphs(b, botfreqs);

		bestfreq = 0;
		for(i = 0; i < glyphedge; i++){
			if(botfreqs[i] > bestfreq){


@@ 398,14 438,32 @@ parseglyphs(char *file)
				bestfreq = botfreqs[i];
			}
		}
	}
	}else
		readglyphs(b, nil);
}

void
loadufx(char *infile)
{
	Biobuf *b;

	glyphs = malloc(nglyphs * sizeof(struct GlyphInfo));
	b = Bopen(infile, OREAD);
	
	loadwidths(b, infile);
	loadglyphs(b);

	Bterm(b);
}


void
usage(void)
{
	fprint(2, "usage: %s [-nh] [-b baseline] [-m mapfile] [-l length] [-x width] in.ufx out/\n", argv0);
	fprint(2,
		"usage: %s [-nh] [-b baseline] [-m mapfile]"
			"[-l length] [-x width] in.ufx out/\n",
		argv0);
	exits("usage");
}



@@ 413,7 471,6 @@ void
main(int argc, char **argv)
{
	char *infile, *outdir;
	struct MapFile *mf;

	ARGBEGIN{
	case 'l':


@@ 434,13 491,7 @@ main(int argc, char **argv)
		break;
	case 'm':
		setconv = 1;
		if(lastmf == nil)
			mapfiles = lastmf = malloc(sizeof(struct MapFile));
		else
			lastmf = lastmf->next = malloc(sizeof(struct MapFile));
		lastmf->file = EARGF(usage());
		lastmf->next = nil;
		lastmf->mappings = nil;
		addmapfile(EARGF(usage()));
		break;
	case 'b':
		baseline = atoi(EARGF(usage()));


@@ 451,28 502,21 @@ main(int argc, char **argv)
		usage();
	}ARGEND;
	
	checkmapfiles();


	if(argv0 == nil)
		argv0 = "ufx2font";

	if(argc != 2)
		usage();

	infile = argv[0];
	outdir = argv[1];


	sniffdims(infile);
	guessdims(infile);
	if(baseline >= glyphedge)
		sysfatal("-b: baseline must be in range 1-width*8");

	for(mf = mapfiles; mf != nil; mf = mf->next)
		parsemapfile(mf);
	if(wasmferr)
		exits("mapfile");
	for(mf = mapfiles; mf != nil; mf = mf->next)
		printmapfile(mf);

	loadufx(infile);
	parseglyphs(infile);

	print("baseline=%ud\n", baseline);
}