@@ 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);
}