mkfont update, now supports variable width fonts.

This commit is contained in:
Marisa the Magician 2022-09-22 17:24:02 +02:00
commit 7e47305aa4

View file

@ -27,10 +27,12 @@
/* /*
Known bugs/limitations: Known bugs/limitations:
- There is currently no handling of proportional fonts whatsoever, this - There is no handling of proportional fonts where glyphs are wider
expects monospaced fonts where all glyphs have the same size. Dunno than their advance length. As this isn't supported by GZDoom itself,
if I'd ever bother with that in the future. it's not a priority either. There's no way to encode the "real width"
- Non-bitmap fonts might sometimes spew lots of (out of bounds) drawing 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. warnings. This is mainly due to the peculiarities of antialiasing.
- Doesn't handle unicode blocks beyond the basic multilingual plane, - Doesn't handle unicode blocks beyond the basic multilingual plane,
might actually be an issue with freetype itself, or the fonts I use, might actually be an issue with freetype itself, or the fonts I use,
@ -116,9 +118,10 @@ FT_Library ftlib;
FT_Face fnt; FT_Face fnt;
int iw, ih; int iw, ih;
int w, h, pxsiz; int w, h, pxsiz, datsiz;
uint8_t *idata; uint8_t *idata;
int autosize = 0;
int gradient = 0; int gradient = 0;
int upshift = 0; int upshift = 0;
@ -353,11 +356,7 @@ int main( int argc, char **argv )
} }
uint32_t range[2] = {0x0000,0x00FF}; uint32_t range[2] = {0x0000,0x00FF};
sscanf(argv[2],"%d",&pxsiz); sscanf(argv[2],"%d",&pxsiz);
if ( !strcmp(argv[3],"auto") ) if ( !strcmp(argv[3],"auto") ) autosize = 1;
{
w = -1;
h = -1;
}
else sscanf(argv[3],"%dx%d",&w,&h); else sscanf(argv[3],"%dx%d",&w,&h);
sscanf(argv[4],"%x-%x",&range[0],&range[1]); sscanf(argv[4],"%x-%x",&range[0],&range[1]);
if ( argc > 5 ) sscanf(argv[5],"%d",&gradient); if ( argc > 5 ) sscanf(argv[5],"%d",&gradient);
@ -372,7 +371,7 @@ int main( int argc, char **argv )
{ {
if ( fnt->num_fixed_sizes <= 0 ) 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; return 8;
} }
fprintf(stderr,"warning: failed to set pixel size '%d', trying fixed sizes.\n",pxsiz); 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 ) if ( rightshift )
fprintf(stderr,"info: right shift detected, grAb X offset %d will be used.\n",rightshift); fprintf(stderr,"info: right shift detected, grAb X offset %d will be used.\n",rightshift);
// third pass to compute the "real" cell size // third pass to compute the maximum cell size (for memory allocation)
if ( w == -1 ) if ( autosize )
{ {
h = pxsiz+1; // should be fine
for ( uint32_t i=range[0]; i<=range[1]; i++ ) for ( uint32_t i=range[0]; i<=range[1]; i++ )
{ {
FT_UInt glyph = FT_Get_Char_Index(fnt,i); FT_UInt glyph = FT_Get_Char_Index(fnt,i);
if ( !glyph || FT_Load_Glyph(fnt,glyph,LOADFLAGS) ) continue; if ( !glyph || FT_Load_Glyph(fnt,glyph,LOADFLAGS) ) continue;
FT_Render_Glyph(fnt->glyph,RENDERMODE); FT_Render_Glyph(fnt->glyph,RENDERMODE);
int valid = 0; int adv = fnt->glyph->linearHoriAdvance>>16;
for ( unsigned j=0; j<fnt->glyph->bitmap.rows; j++ ) if ( adv > w ) w = adv;
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; j<fnt->glyph->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;
} }
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; iw = w+1;
ih = h+1; ih = h+1;
@ -480,17 +463,29 @@ int main( int argc, char **argv )
iw++; iw++;
ih++; ih++;
} }
datsiz = palsize?(iw*ih*4):(iw*ih*2);
fprintf(stderr,"info: gradient selected is '%s'.\n",grads[gradient&7]); 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; uint32_t drawn = 0;
for ( uint32_t i=range[0]; i<=range[1]; i++ ) for ( uint32_t i=range[0]; i<=range[1]; i++ )
{ {
FT_UInt glyph = FT_Get_Char_Index(fnt,i); FT_UInt glyph = FT_Get_Char_Index(fnt,i);
if ( !glyph || FT_Load_Glyph(fnt,glyph,LOADFLAGS) ) continue; if ( !glyph || FT_Load_Glyph(fnt,glyph,LOADFLAGS) ) continue;
FT_Render_Glyph(fnt->glyph,RENDERMODE); FT_Render_Glyph(fnt->glyph,RENDERMODE);
int valid = 0;
for ( unsigned j=0; j<fnt->glyph->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 xx = rightshift;
int yy = upshift+xupshift+1; int yy = upshift+xupshift+1;
int valid; valid = 0;
oob = 0; oob = 0;
if ( gradient&4 ) if ( gradient&4 )
{ {
@ -519,7 +514,7 @@ int main( int argc, char **argv )
writepng(fname,idata,iw,ih,palsize?(iw*4):(iw*2)); writepng(fname,idata,iw,ih,palsize?(iw*4):(iw*2));
drawn++; drawn++;
} }
memset(idata,0,palsize?(iw*ih*4):(iw*ih*2)); memset(idata,0,datsiz);
} }
fprintf(stderr,"info: %u glyphs drawn.\n",drawn); fprintf(stderr,"info: %u glyphs drawn.\n",drawn);
free(idata); free(idata);