From fc5841aa95872eddc403b9618747d07ca9a92c91 Mon Sep 17 00:00:00 2001 From: glenda Date: Sun, 23 Nov 2025 00:31:40 +0000 Subject: [PATCH] glyph metrics --- ufx2font.c | 107 ++++++++++++++++++++++++----------------------------- 1 file changed, 48 insertions(+), 59 deletions(-) diff --git a/ufx2font.c b/ufx2font.c index 7f1ee919996e922a7bb2a6fa37c394a0379525c2..0ff846b9906c663c8b8c3792090a05717578e181 100644 --- a/ufx2font.c +++ b/ufx2font.c @@ -5,6 +5,8 @@ /* entry has 1 byte in widtab + 8 bytes per tile */ #define ufxlen(n) ((n)*(n)*8) +#define max(a, b) ((a) > (b) ? (a) : (b)) +#define min(a, b) ((a) < (b) ? (a) : (b)) enum{ @@ -41,7 +43,7 @@ struct GlyphInfo{ }; -uint fwidth, nglyphs, glyphlen, glyphedge; +uint fwidth, nglyphs, glyphlen, glyphedge, baseline; uchar setconv, donaive, doholes; struct MapFile *mapfiles, *lastmf; @@ -341,49 +343,28 @@ loadufx(char *infile) Bterm(b); } -void -testcol(uchar len, uint offset, uchar *top, uchar *bot) -{ - uchar mask; - - if(len > 8) - len = 8; - mask = 0xff<<(8-len); - - for(*top = 0; *top < glyphedge; (*top)++){ - print("gbitmaps[off+top]=%2ux; mask=%2ux\n", gbitmaps[offset + *top], mask); - if(gbitmaps[offset + *top] & mask != 0) - break; - } - - for(*bot = (glyphedge - 1); *bot >= *top; (*bot)--) - if(gbitmaps[offset + *bot] & mask != 0) - break; -} -/* uchar -highbit(uchar b) +testscanline(uchar *bitmap, int rowlen) { - uchar i = 0; - while(b != 0){ - i++; - b >>= 1; + uchar mask, x; + for(x = 0; x <= (rowlen-1)/8; x++){ + /* ignore the right edge of the last byte */ + mask = 0xff << (8-min(8, rowlen-x*8)); + if((bitmap[x*glyphedge] & mask) != 0) + return 1; } - return 8 - i; // returns 8 if b == 0 + return 0; } -uchar -findleft(uint offset) -{ - uchar left = 0; -} -*/ void parseglyphs(char *file) { - uint i, offset; + uint i, y, top, bot, *botfreqs = nil, bestfreq; int rowlen; - uchar top, bot; + uchar *bitmap; + + if(baseline < 1) + botfreqs = calloc(glyphedge, sizeof(uint)); for(i = 0; i < nglyphs; i++){ rowlen = ginfo[i].width; @@ -393,31 +374,30 @@ parseglyphs(char *file) 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]++; + } - offset = glyphlen * i; - ginfo[i].top = glyphedge; - ginfo[i].bottom = 0; - - while(rowlen > 0){ - testcol(rowlen, offset, &top, &bot); - if(top < ginfo[i].top) - ginfo[i].top = top; - if(bot > ginfo[i].bottom) - ginfo[i].bottom = bot; - - // TODO: calculate .left, maybe? - - offset += glyphedge; - rowlen -= 8; - } - - if(ginfo[i].top == glyphedge){ - // blank glyph - ginfo[i].top = 0; - ginfo[i].bottom = glyphedge - 1; + if(baseline < 1){ + bestfreq = 0; + for(i = 0; i < glyphedge; i++){ + if(botfreqs[i] > bestfreq){ + baseline = i; + bestfreq = botfreqs[i]; + } } - - print("glyphs[%2x]: rowlen=%02d top=%02d bottom=%02d\n", i, ginfo[i].width, ginfo[i].top, ginfo[i].bottom); } } @@ -425,7 +405,7 @@ parseglyphs(char *file) void usage(void) { - fprint(2, "usage: %s [-nh] [-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"); } @@ -462,6 +442,11 @@ main(int argc, char **argv) lastmf->next = nil; lastmf->mappings = nil; break; + case 'b': + baseline = atoi(EARGF(usage())); + if(baseline < 1) + sysfatal("-b: baseline must be in range 1-width*8"); + break; default: usage(); }ARGEND; @@ -476,6 +461,8 @@ main(int argc, char **argv) sniffdims(infile); + if(baseline >= glyphedge) + sysfatal("-b: baseline must be in range 1-width*8"); for(mf = mapfiles; mf != nil; mf = mf->next) parsemapfile(mf); @@ -486,4 +473,6 @@ main(int argc, char **argv) loadufx(infile); parseglyphs(infile); + + print("baseline=%ud\n", baseline); }