From 7e47305aa4799bdb54c6f921c241e0dcaec0555f Mon Sep 17 00:00:00 2001 From: Marisa the Magician Date: Thu, 22 Sep 2022 17:24:02 +0200 Subject: [PATCH] mkfont update, now supports variable width fonts. --- mkfont.c | 67 ++++++++++++++++++++++++++------------------------------ 1 file changed, 31 insertions(+), 36 deletions(-) diff --git a/mkfont.c b/mkfont.c index c3a826d..67a4405 100644 --- a/mkfont.c +++ b/mkfont.c @@ -27,10 +27,12 @@ /* Known bugs/limitations: - - There is currently no handling of proportional fonts whatsoever, this - expects monospaced fonts where all glyphs have the same size. Dunno - if I'd ever bother with that in the future. - - Non-bitmap fonts might sometimes spew lots of (out of bounds) drawing + - There is no handling of proportional fonts where glyphs are wider + than their advance length. As this isn't supported by GZDoom itself, + it's not a priority either. There's no way to encode the "real width" + of a glyph into the PNG. Also, glyphs might end up rendered with + cropped sides. + - Non-bitmap fonts might sometimes spew lots of "out of bounds" drawing warnings. This is mainly due to the peculiarities of antialiasing. - Doesn't handle unicode blocks beyond the basic multilingual plane, might actually be an issue with freetype itself, or the fonts I use, @@ -116,9 +118,10 @@ FT_Library ftlib; FT_Face fnt; int iw, ih; -int w, h, pxsiz; +int w, h, pxsiz, datsiz; uint8_t *idata; +int autosize = 0; int gradient = 0; int upshift = 0; @@ -353,11 +356,7 @@ int main( int argc, char **argv ) } uint32_t range[2] = {0x0000,0x00FF}; sscanf(argv[2],"%d",&pxsiz); - if ( !strcmp(argv[3],"auto") ) - { - w = -1; - h = -1; - } + if ( !strcmp(argv[3],"auto") ) autosize = 1; else sscanf(argv[3],"%dx%d",&w,&h); sscanf(argv[4],"%x-%x",&range[0],&range[1]); if ( argc > 5 ) sscanf(argv[5],"%d",&gradient); @@ -372,7 +371,7 @@ int main( int argc, char **argv ) { if ( fnt->num_fixed_sizes <= 0 ) { - fprintf(stderr,"error: font pixel size of '%d' not available\n",pxsiz); + fprintf(stderr,"error: font pixel size of '%d' not available.\n",pxsiz); return 8; } fprintf(stderr,"warning: failed to set pixel size '%d', trying fixed sizes.\n",pxsiz); @@ -442,35 +441,19 @@ int main( int argc, char **argv ) } if ( rightshift ) fprintf(stderr,"info: right shift detected, grAb X offset %d will be used.\n",rightshift); - // third pass to compute the "real" cell size - if ( w == -1 ) + // third pass to compute the maximum cell size (for memory allocation) + if ( autosize ) { + h = pxsiz+1; // should be fine for ( uint32_t i=range[0]; i<=range[1]; i++ ) { FT_UInt glyph = FT_Get_Char_Index(fnt,i); if ( !glyph || FT_Load_Glyph(fnt,glyph,LOADFLAGS) ) continue; FT_Render_Glyph(fnt->glyph,RENDERMODE); - int valid = 0; - for ( unsigned j=0; jglyph->bitmap.rows; j++ ) - valid |= valid_row(&fnt->glyph->bitmap,j); - if ( !valid ) continue; - int gw = fnt->glyph->bitmap_left+rightshift; - int gh = (upshift+xupshift+1)+(pxsiz-fnt->glyph->bitmap_top); - int mw = 0; - int mh = 0; - for ( unsigned j=0; jglyph->bitmap.rows; j++ ) - { - if ( !valid_row(&fnt->glyph->bitmap,j) ) continue; - int rw = row_width(&fnt->glyph->bitmap,j); - if ( rw > mw ) mw = rw; - mh = j; - } - gw += mw+1; - gh += mh+1; - if ( gw > w ) w = gw; - if ( gh > h ) h = gh; + int adv = fnt->glyph->linearHoriAdvance>>16; + if ( adv > w ) w = adv; } - fprintf(stderr,"info: guessed cell size is %dx%d.\n",w,h); + fprintf(stderr,"info: max cell size is %dx%d.\n",w,h); } iw = w+1; ih = h+1; @@ -480,17 +463,29 @@ int main( int argc, char **argv ) iw++; ih++; } + datsiz = palsize?(iw*ih*4):(iw*ih*2); fprintf(stderr,"info: gradient selected is '%s'.\n",grads[gradient&7]); - idata = calloc(iw*ih,palsize?4:2); + idata = calloc(datsiz,1); uint32_t drawn = 0; for ( uint32_t i=range[0]; i<=range[1]; i++ ) { FT_UInt glyph = FT_Get_Char_Index(fnt,i); if ( !glyph || FT_Load_Glyph(fnt,glyph,LOADFLAGS) ) continue; FT_Render_Glyph(fnt->glyph,RENDERMODE); + int valid = 0; + for ( unsigned j=0; jglyph->bitmap.rows; j++ ) + valid |= valid_row(&fnt->glyph->bitmap,j); + if ( !valid ) continue; + if ( autosize ) + { + // readjust cell width (but not height) for this character + int adv = fnt->glyph->linearHoriAdvance>>16; + w = adv; + iw = w+((gradient&4)?2:1); + } int xx = rightshift; int yy = upshift+xupshift+1; - int valid; + valid = 0; oob = 0; if ( gradient&4 ) { @@ -519,7 +514,7 @@ int main( int argc, char **argv ) writepng(fname,idata,iw,ih,palsize?(iw*4):(iw*2)); drawn++; } - memset(idata,0,palsize?(iw*ih*4):(iw*ih*2)); + memset(idata,0,datsiz); } fprintf(stderr,"info: %u glyphs drawn.\n",drawn); free(idata);