Oh boy, this is a mess.
This commit is contained in:
parent
c5b1bb0430
commit
5ff8bd2367
1 changed files with 49 additions and 74 deletions
123
mkfont.c
123
mkfont.c
|
|
@ -49,10 +49,13 @@
|
|||
|
||||
uint8_t pal[768];
|
||||
int palsize = 0;
|
||||
int xupshift = 0;
|
||||
int rightshift = 0;
|
||||
int bordshift = 0;
|
||||
|
||||
int tewi_hotfix = 0; // U+0309 and U+030A glyphs are offset incorrectly
|
||||
// and the entire font height needs to be cropped
|
||||
int miniwi_hotfix = 0; // U+01C2 glyph is offset incorrect
|
||||
// this font's height also needs a crop
|
||||
|
||||
uint32_t endianswap( uint32_t n )
|
||||
{
|
||||
// if we're in a big endian system, we don't need this
|
||||
|
|
@ -94,9 +97,9 @@ int writepng( const char *filename, uint8_t *fdata, int w, int h, int p )
|
|||
png_set_IHDR(pngp,infp,w,h,8,palsize?PNG_COLOR_TYPE_RGBA:PNG_COLOR_TYPE_GA,
|
||||
PNG_INTERLACE_NONE,PNG_COMPRESSION_TYPE_DEFAULT,
|
||||
PNG_FILTER_TYPE_DEFAULT);
|
||||
if ( xupshift || rightshift || bordshift )
|
||||
if ( bordshift )
|
||||
{
|
||||
uint32_t grabs[2] = {endianswap(rightshift+bordshift),endianswap(xupshift+bordshift)};
|
||||
uint32_t grabs[2] = {endianswap(bordshift),endianswap(bordshift)};
|
||||
png_unknown_chunk grab =
|
||||
{
|
||||
.name = "grAb",
|
||||
|
|
@ -118,10 +121,10 @@ FT_Library ftlib;
|
|||
FT_Face fnt;
|
||||
|
||||
int iw, ih;
|
||||
int w, h, pxsiz, datsiz;
|
||||
int w, h, datsiz;
|
||||
uint8_t *idata;
|
||||
|
||||
int autosize = 0;
|
||||
int calcsize = 1;
|
||||
int gradient = 0;
|
||||
int upshift = 0;
|
||||
|
||||
|
|
@ -191,9 +194,9 @@ int draw_glyph( FT_Bitmap *bmp, uint8_t v, int px, int py, int ox, int oy )
|
|||
if ( v == 255 )
|
||||
{
|
||||
float a;
|
||||
int ofs = j+oy+(upshift+1);
|
||||
int ofs = j+oy+(upshift+tewi_hotfix+miniwi_hotfix);
|
||||
if ( ofs < 0 ) a = 0.;
|
||||
else a = ofs/(float)(h+upshift+1);
|
||||
else a = ofs/(float)(h-1);
|
||||
if ( (gradient&3) == 1 ) rv = lerpg(1.-a);
|
||||
else if ( (gradient&3) == 2 ) rv = lerpg(a);
|
||||
else if ( (gradient&3) == 3 ) rv = lerpg((a>.5)?((1.-a)*2.):(a*2.));
|
||||
|
|
@ -343,10 +346,10 @@ const char grads[8][20] =
|
|||
|
||||
int main( int argc, char **argv )
|
||||
{
|
||||
if ( argc < 4 )
|
||||
if ( argc < 3 )
|
||||
{
|
||||
fprintf(stderr,"usage: mkfontsingle <font name> <pxsize> <wxh|auto>"
|
||||
" <unicode range (hex)> [gradient type] [color palette] [-palinv]\n");
|
||||
fprintf(stderr,"usage: mkfont <font name> <pxsize> <unicode range (hex)>"
|
||||
" [gradient type] [color palette] [-palinv]\n");
|
||||
return 1;
|
||||
}
|
||||
if ( FT_Init_FreeType(&ftlib) )
|
||||
|
|
@ -355,18 +358,20 @@ int main( int argc, char **argv )
|
|||
return 2;
|
||||
}
|
||||
uint32_t range[2] = {0x0000,0x00FF};
|
||||
int pxsiz;
|
||||
sscanf(argv[2],"%d",&pxsiz);
|
||||
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);
|
||||
if ( argc > 7 ) palinv = !strcmp(argv[7],"-palinv");
|
||||
if ( argc > 6 ) loadpalette(argv[6]);
|
||||
sscanf(argv[3],"%x-%x",&range[0],&range[1]);
|
||||
if ( argc > 4 ) sscanf(argv[4],"%d",&gradient);
|
||||
if ( argc > 6 ) palinv = !strcmp(argv[6],"-palinv");
|
||||
if ( argc > 5 ) loadpalette(argv[5]);
|
||||
if ( FT_New_Face(ftlib,argv[1],0,&fnt) )
|
||||
{
|
||||
fprintf(stderr,"error: failed to open font '%s'\n",argv[1]);
|
||||
return 4;
|
||||
}
|
||||
fprintf(stderr,"info: loaded font \'%s %s\'.\n",fnt->family_name,fnt->style_name);
|
||||
if ( !strcmp(fnt->family_name,"tewi") ) tewi_hotfix = 1;
|
||||
else if ( !strcmp(fnt->family_name,"miniwi") ) miniwi_hotfix = 1;
|
||||
if ( FT_Set_Pixel_Sizes(fnt,0,pxsiz) )
|
||||
{
|
||||
if ( fnt->num_fixed_sizes <= 0 )
|
||||
|
|
@ -391,10 +396,11 @@ int main( int argc, char **argv )
|
|||
return 8;
|
||||
}
|
||||
}
|
||||
h = (fnt->size->metrics.height>>6)-tewi_hotfix-miniwi_hotfix;
|
||||
FT_Select_Charmap(fnt,FT_ENCODING_UNICODE);
|
||||
// first pass to compute baseline upshift
|
||||
upshift = 65535;
|
||||
for ( uint32_t i=range[0]; i<=range[1]; i++ )
|
||||
for ( uint32_t i=0; i<=0xFFFF; i++ )
|
||||
{
|
||||
FT_UInt glyph = FT_Get_Char_Index(fnt,i);
|
||||
if ( !glyph || FT_Load_Glyph(fnt,glyph,LOADFLAGS) ) continue;
|
||||
|
|
@ -407,48 +413,13 @@ int main( int argc, char **argv )
|
|||
if ( gshift < upshift ) upshift = gshift;
|
||||
}
|
||||
fprintf(stderr,"info: estimated baseline upshift is %d.\n",upshift);
|
||||
// second pass to compute "real" upshift, which is used for the grAb Y offset
|
||||
// as well as the "rightshift" for the X offset
|
||||
xupshift = 65535;
|
||||
for ( uint32_t i=range[0]; i<=range[1]; i++ )
|
||||
// second pass to compute the maximum cell size (for memory allocation)
|
||||
if ( calcsize )
|
||||
{
|
||||
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; j<fnt->glyph->bitmap.rows; j++ )
|
||||
valid |= valid_row(&fnt->glyph->bitmap,j);
|
||||
if ( !valid ) continue;
|
||||
int xx = fnt->glyph->bitmap_left;
|
||||
if ( -xx > rightshift ) rightshift = -xx;
|
||||
int yy = upshift+1+(pxsiz-fnt->glyph->bitmap_top);
|
||||
for ( unsigned j=0; j<fnt->glyph->bitmap.rows; j++ )
|
||||
{
|
||||
if ( !valid_row(&fnt->glyph->bitmap,j) ) yy++;
|
||||
else break;
|
||||
}
|
||||
if ( yy < 0 )
|
||||
{
|
||||
int xup = -yy;
|
||||
if ( xup < xupshift ) xupshift = xup;
|
||||
}
|
||||
}
|
||||
if ( xupshift == 65535 ) xupshift = 0;
|
||||
if ( xupshift )
|
||||
{
|
||||
fprintf(stderr,"info: real upshift is %d.\n",upshift+xupshift);
|
||||
fprintf(stderr,"info: grAb Y offset %d will be used.\n",xupshift);
|
||||
}
|
||||
if ( rightshift )
|
||||
fprintf(stderr,"info: right shift detected, grAb X offset %d will be used.\n",rightshift);
|
||||
// third pass to compute the maximum cell size (for memory allocation)
|
||||
if ( autosize )
|
||||
{
|
||||
h = (fnt->size->metrics.height>>6)+1;
|
||||
if ( FT_IS_FIXED_WIDTH(fnt) )
|
||||
{
|
||||
w = fnt->size->metrics.max_advance>>6;
|
||||
autosize = 0; // don't readjust per-glyph
|
||||
calcsize = 0; // don't readjust per-glyph
|
||||
}
|
||||
else for ( uint32_t i=range[0]; i<=range[1]; i++ )
|
||||
{
|
||||
|
|
@ -457,8 +428,8 @@ int main( int argc, char **argv )
|
|||
FT_Render_Glyph(fnt->glyph,RENDERMODE);
|
||||
int adv = fnt->glyph->linearHoriAdvance>>16;
|
||||
int adv2 = fnt->glyph->advance.x>>6;
|
||||
if ( !adv ) adv = adv2;
|
||||
if ( (adv+rightshift) > w ) w = adv+rightshift;
|
||||
if ( adv2 ) adv = adv2;
|
||||
if ( adv > w ) w = adv;
|
||||
}
|
||||
fprintf(stderr,"info: max cell size is %dx%d.\n",w,h);
|
||||
}
|
||||
|
|
@ -483,37 +454,41 @@ int main( int argc, char **argv )
|
|||
for ( unsigned j=0; j<fnt->glyph->bitmap.rows; j++ )
|
||||
valid |= valid_row(&fnt->glyph->bitmap,j);
|
||||
if ( !valid ) continue;
|
||||
if ( autosize )
|
||||
if ( calcsize )
|
||||
{
|
||||
// readjust cell width (but not height) for this character
|
||||
int adv = fnt->glyph->linearHoriAdvance>>16;
|
||||
int adv2 = fnt->glyph->advance.x>>6;
|
||||
if ( !adv ) adv = adv2;
|
||||
w = adv+rightshift;
|
||||
if ( adv2 ) adv = adv2;
|
||||
w = adv;
|
||||
iw = w+((gradient&4)?2:1);
|
||||
}
|
||||
int xx = rightshift;
|
||||
int yy = upshift+xupshift+1;
|
||||
int xx = 0;
|
||||
int yy = upshift+tewi_hotfix+miniwi_hotfix;
|
||||
if ( tewi_hotfix && ((i != 0x0309) && (i != 0x030A)) )
|
||||
fnt->glyph->bitmap_top++;
|
||||
if ( miniwi_hotfix && (i == 0x01C2) )
|
||||
fnt->glyph->bitmap_top++;
|
||||
valid = 0;
|
||||
oob = 0;
|
||||
if ( gradient&4 )
|
||||
{
|
||||
// draw outline first
|
||||
draw_glyph(&fnt->glyph->bitmap,0,xx,yy,fnt->glyph->bitmap_left,pxsiz-fnt->glyph->bitmap_top);
|
||||
draw_glyph(&fnt->glyph->bitmap,0,xx+1,yy,fnt->glyph->bitmap_left,pxsiz-fnt->glyph->bitmap_top);
|
||||
draw_glyph(&fnt->glyph->bitmap,0,xx+2,yy,fnt->glyph->bitmap_left,pxsiz-fnt->glyph->bitmap_top);
|
||||
draw_glyph(&fnt->glyph->bitmap,0,xx,yy+1,fnt->glyph->bitmap_left,pxsiz-fnt->glyph->bitmap_top);
|
||||
draw_glyph(&fnt->glyph->bitmap,0,xx+2,yy+1,fnt->glyph->bitmap_left,pxsiz-fnt->glyph->bitmap_top);
|
||||
draw_glyph(&fnt->glyph->bitmap,0,xx,yy+2,fnt->glyph->bitmap_left,pxsiz-fnt->glyph->bitmap_top);
|
||||
draw_glyph(&fnt->glyph->bitmap,0,xx+1,yy+2,fnt->glyph->bitmap_left,pxsiz-fnt->glyph->bitmap_top);
|
||||
draw_glyph(&fnt->glyph->bitmap,0,xx+2,yy+2,fnt->glyph->bitmap_left,pxsiz-fnt->glyph->bitmap_top);
|
||||
valid = draw_glyph(&fnt->glyph->bitmap,255,xx+1,yy+1,fnt->glyph->bitmap_left,pxsiz-fnt->glyph->bitmap_top);
|
||||
draw_glyph(&fnt->glyph->bitmap,0,xx,yy,fnt->glyph->bitmap_left,h-fnt->glyph->bitmap_top);
|
||||
draw_glyph(&fnt->glyph->bitmap,0,xx+1,yy,fnt->glyph->bitmap_left,h-fnt->glyph->bitmap_top);
|
||||
draw_glyph(&fnt->glyph->bitmap,0,xx+2,yy,fnt->glyph->bitmap_left,h-fnt->glyph->bitmap_top);
|
||||
draw_glyph(&fnt->glyph->bitmap,0,xx,yy+1,fnt->glyph->bitmap_left,h-fnt->glyph->bitmap_top);
|
||||
draw_glyph(&fnt->glyph->bitmap,0,xx+2,yy+1,fnt->glyph->bitmap_left,h-fnt->glyph->bitmap_top);
|
||||
draw_glyph(&fnt->glyph->bitmap,0,xx,yy+2,fnt->glyph->bitmap_left,h-fnt->glyph->bitmap_top);
|
||||
draw_glyph(&fnt->glyph->bitmap,0,xx+1,yy+2,fnt->glyph->bitmap_left,h-fnt->glyph->bitmap_top);
|
||||
draw_glyph(&fnt->glyph->bitmap,0,xx+2,yy+2,fnt->glyph->bitmap_left,h-fnt->glyph->bitmap_top);
|
||||
valid = draw_glyph(&fnt->glyph->bitmap,255,xx+1,yy+1,fnt->glyph->bitmap_left,h-fnt->glyph->bitmap_top);
|
||||
}
|
||||
else
|
||||
{
|
||||
// draw drop shadow first
|
||||
draw_glyph(&fnt->glyph->bitmap,0,xx+1,yy+1,fnt->glyph->bitmap_left,pxsiz-fnt->glyph->bitmap_top);
|
||||
valid = draw_glyph(&fnt->glyph->bitmap,255,xx,yy,fnt->glyph->bitmap_left,pxsiz-fnt->glyph->bitmap_top);
|
||||
draw_glyph(&fnt->glyph->bitmap,0,xx+1,yy+1,fnt->glyph->bitmap_left,h-fnt->glyph->bitmap_top);
|
||||
valid = draw_glyph(&fnt->glyph->bitmap,255,xx,yy,fnt->glyph->bitmap_left,h-fnt->glyph->bitmap_top);
|
||||
}
|
||||
if ( valid )
|
||||
{
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue