Migrate mkfont from Demolitionist project to here.
This commit is contained in:
parent
cc65edd617
commit
fda850359b
3 changed files with 533 additions and 37 deletions
521
mkfont.c
521
mkfont.c
|
|
@ -1,44 +1,495 @@
|
|||
/*
|
||||
mkfont.c : Make font pngs for gzdoom, in an ugly cheap way.
|
||||
This code is a mess but I keep it here so people know how much I had
|
||||
to suffer to get this done.
|
||||
|
||||
Copyright (c) 2020-2022 Marisa Kirisame, UnSX Team
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
/*
|
||||
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.
|
||||
- While non-bitmap fonts are technically supported, they will
|
||||
oftentimes act extremely weirdly (e.g.: some glyphs will have REALLY
|
||||
broken offsets).
|
||||
- Doesn't handle unicode blocks beyond the basic multilingual plane,
|
||||
might actually be an issue with freetype itself, or the fonts I use,
|
||||
though I CAN see that the glyphs are there if I use a character map
|
||||
program. Not that this doesn't even matter considering GZDoom only
|
||||
supports the 0000-FFFF range anyway.
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/wait.h>
|
||||
#include <sys/stat.h>
|
||||
#include <png.h>
|
||||
#include <ft2build.h>
|
||||
#include FT_FREETYPE_H
|
||||
|
||||
uint8_t pal[768];
|
||||
int palsize = 0;
|
||||
int xupshift = 0;
|
||||
|
||||
uint32_t endianswap( uint32_t n )
|
||||
{
|
||||
// if we're in a big endian system, we don't need this
|
||||
uint16_t testme = 0x1234;
|
||||
if ( *(uint8_t*)(&testme) == 0x12 ) return n;
|
||||
uint32_t on;
|
||||
for ( int i=0; i<4; i++ )
|
||||
*(((uint8_t*)(&on))+i) = *(((uint8_t*)(&n))+(3-i));
|
||||
return on;
|
||||
}
|
||||
|
||||
int writepng( const char *filename, uint8_t *fdata, int w, int h, int p )
|
||||
{
|
||||
if ( !filename ) return 0;
|
||||
png_structp pngp;
|
||||
png_infop infp;
|
||||
FILE *pf;
|
||||
if ( !(pf = fopen(filename,"wb")) ) return 0;
|
||||
pngp = png_create_write_struct(PNG_LIBPNG_VER_STRING,0,0,0);
|
||||
if ( !pngp )
|
||||
{
|
||||
fclose(pf);
|
||||
return 0;
|
||||
}
|
||||
infp = png_create_info_struct(pngp);
|
||||
if ( !infp )
|
||||
{
|
||||
fclose(pf);
|
||||
png_destroy_write_struct(&pngp,0);
|
||||
return 0;
|
||||
}
|
||||
if ( setjmp(png_jmpbuf(pngp)) )
|
||||
{
|
||||
png_destroy_write_struct(&pngp,&infp);
|
||||
fclose(pf);
|
||||
return 0;
|
||||
}
|
||||
png_init_io(pngp,pf);
|
||||
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 )
|
||||
{
|
||||
uint32_t grabs[2] = {0,endianswap(-xupshift)};
|
||||
png_unknown_chunk grab =
|
||||
{
|
||||
.name = "grAb",
|
||||
.data = (uint8_t*)grabs,
|
||||
.size = 8,
|
||||
.location = PNG_HAVE_IHDR
|
||||
};
|
||||
png_set_unknown_chunks(pngp,infp,&grab,1);
|
||||
}
|
||||
png_write_info(pngp,infp);
|
||||
for ( int i=0; i<h; i++ ) png_write_row(pngp,fdata+(p*i));
|
||||
png_write_end(pngp,infp);
|
||||
png_destroy_write_struct(&pngp,&infp);
|
||||
fclose(pf);
|
||||
return 1;
|
||||
}
|
||||
|
||||
FT_Library ftlib;
|
||||
FT_Face fnt;
|
||||
|
||||
int iw, ih;
|
||||
int w, h, pxsiz;
|
||||
uint8_t *idata;
|
||||
|
||||
int gradient = 0;
|
||||
int upshift = 0;
|
||||
|
||||
void putpixel_grayscale( uint8_t v, uint8_t a, int x, int y )
|
||||
{
|
||||
uint32_t tpos = (x+y*iw)*2;
|
||||
// add alpha
|
||||
int alph = idata[tpos+1];
|
||||
alph += a;
|
||||
if ( alph > 255 ) alph = 255;
|
||||
idata[tpos+1] = alph;
|
||||
// blend color
|
||||
int col = idata[tpos]*(a-255);
|
||||
col += v*a;
|
||||
col /= 255;
|
||||
idata[tpos] = col;
|
||||
}
|
||||
|
||||
void putpixel_color( uint8_t v, uint8_t a, int x, int y )
|
||||
{
|
||||
uint32_t tpos = (x+y*iw)*4;
|
||||
// add alpha
|
||||
int alph = idata[tpos+3];
|
||||
alph += a;
|
||||
if ( alph > 255 ) alph = 255;
|
||||
idata[tpos+3] = alph;
|
||||
// blend color (RGB)
|
||||
for ( int i=0; i<3; i++ )
|
||||
{
|
||||
int col = idata[tpos+i]*(a-255);
|
||||
int palent = (v*palsize)/256;
|
||||
col += pal[palent*3+i]*a;
|
||||
col /= 255;
|
||||
idata[tpos+i] = col;
|
||||
}
|
||||
}
|
||||
|
||||
int oob = 0;
|
||||
|
||||
void putpixel( uint8_t v, uint8_t a, int x, int y )
|
||||
{
|
||||
if ( (x < 0) || (x >= iw) || (y < 0) || (y >= ih) )
|
||||
{
|
||||
oob = 1;
|
||||
return;
|
||||
}
|
||||
if ( palsize == 0 ) putpixel_grayscale(v,a,x,y);
|
||||
else putpixel_color(v,a,x,y);
|
||||
}
|
||||
|
||||
uint8_t lerpg( float a )
|
||||
{
|
||||
if ( a >= 1. ) return 255;
|
||||
if ( a <= 0. ) return 64;
|
||||
return (uint8_t)(a*191+64);
|
||||
}
|
||||
|
||||
int draw_glyph( FT_Bitmap *bmp, uint8_t v, uint32_t px, uint32_t py, uint8_t ox, uint8_t oy )
|
||||
{
|
||||
int drawn = 0;
|
||||
unsigned i, j;
|
||||
for ( j=0; j<bmp->rows; j++ )
|
||||
{
|
||||
uint8_t rv = v;
|
||||
// apply gradient, if any
|
||||
if ( v == 255 )
|
||||
{
|
||||
float a;
|
||||
int ofs = j+oy+(upshift+1);
|
||||
if ( ofs < 0 ) a = 0.;
|
||||
else a = ofs/(float)(h+upshift+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.));
|
||||
}
|
||||
for ( i=0; i<bmp->width; i++ )
|
||||
{
|
||||
if ( bmp->pixel_mode == FT_PIXEL_MODE_GRAY )
|
||||
{
|
||||
uint8_t a = bmp->buffer[i+j*bmp->pitch];
|
||||
drawn |= (a > 0);
|
||||
putpixel(rv,a,px+ox+i,py+oy+j);
|
||||
}
|
||||
else if ( bmp->pixel_mode == FT_PIXEL_MODE_MONO )
|
||||
{
|
||||
// thanks to https://stackoverflow.com/a/14905971
|
||||
unsigned p = bmp->pitch;
|
||||
uint8_t *row = &bmp->buffer[p*j];
|
||||
uint8_t a = ((row[i>>3])&(128>>(i&7)))?255:0;
|
||||
drawn |= (a > 0);
|
||||
putpixel(rv,a,px+ox+i,py+oy+j);
|
||||
}
|
||||
}
|
||||
}
|
||||
return drawn;
|
||||
}
|
||||
|
||||
int valid_row( FT_Bitmap *bmp, unsigned j )
|
||||
{
|
||||
int drawn = 0;
|
||||
for ( unsigned i=0; i<bmp->width; i++ )
|
||||
{
|
||||
if ( bmp->pixel_mode == FT_PIXEL_MODE_GRAY )
|
||||
{
|
||||
uint8_t a = bmp->buffer[i+j*bmp->pitch];
|
||||
drawn |= (a > 0);
|
||||
}
|
||||
else if ( bmp->pixel_mode == FT_PIXEL_MODE_MONO )
|
||||
{
|
||||
// thanks to https://stackoverflow.com/a/14905971
|
||||
unsigned p = bmp->pitch;
|
||||
uint8_t *row = &bmp->buffer[p*j];
|
||||
uint8_t a = ((row[i>>3])&(128>>(i&7)))?255:0;
|
||||
drawn |= (a > 0);
|
||||
}
|
||||
}
|
||||
return drawn;
|
||||
}
|
||||
|
||||
unsigned row_width( FT_Bitmap *bmp, unsigned j )
|
||||
{
|
||||
unsigned dw = 0;
|
||||
for ( unsigned i=0; i<bmp->width; i++ )
|
||||
{
|
||||
if ( bmp->pixel_mode == FT_PIXEL_MODE_GRAY )
|
||||
{
|
||||
uint8_t a = bmp->buffer[i+j*bmp->pitch];
|
||||
if ( (a > 0) && (i > dw) ) dw = i;
|
||||
}
|
||||
else if ( bmp->pixel_mode == FT_PIXEL_MODE_MONO )
|
||||
{
|
||||
// thanks to https://stackoverflow.com/a/14905971
|
||||
unsigned p = bmp->pitch;
|
||||
uint8_t *row = &bmp->buffer[p*j];
|
||||
uint8_t a = ((row[i>>3])&(128>>(i&7)))?255:0;
|
||||
if ( (a > 0) && (i > dw) ) dw = i;
|
||||
}
|
||||
}
|
||||
return dw;
|
||||
}
|
||||
|
||||
int palinv = 0;
|
||||
|
||||
void loadpalette( const char *path )
|
||||
{
|
||||
FILE *f = fopen(path,"rb");
|
||||
if ( !f )
|
||||
{
|
||||
fprintf(stderr,"warning: could not open palette file '%s', falling back to grayscale\n",path);
|
||||
return;
|
||||
}
|
||||
fseek(f,0,SEEK_END);
|
||||
long sz = ftell(f);
|
||||
fseek(f,0,SEEK_SET);
|
||||
if ( sz <= 0 )
|
||||
{
|
||||
fprintf(stderr,"warning: palette is empty, falling back to grayscale\n");
|
||||
goto palend;
|
||||
}
|
||||
if ( !(sz%3) )
|
||||
{
|
||||
// RGB8 palette
|
||||
if ( sz > 768 )
|
||||
{
|
||||
fprintf(stderr,"warning: palette has more than 256 entries, extra colors will be ignored\n");
|
||||
palsize = 256;
|
||||
}
|
||||
else palsize = sz/3;
|
||||
for ( int i=0; i<palsize; i++ )
|
||||
{
|
||||
int j = palinv?(palsize-(i+1)):i;
|
||||
pal[j*3] = fgetc(f);
|
||||
pal[j*3+1] = fgetc(f);
|
||||
pal[j*3+2] = fgetc(f);
|
||||
}
|
||||
fprintf(stderr,"info: RGB8 palette loaded with %d colors.\n",palsize);
|
||||
}
|
||||
else if ( !(sz%4) )
|
||||
{
|
||||
// RGBA8 palette
|
||||
if ( sz > 1024 )
|
||||
{
|
||||
fprintf(stderr,"warning: palette has more than 256 entries, extra colors will be ignored\n");
|
||||
palsize = 256;
|
||||
}
|
||||
else palsize = sz/4;
|
||||
for ( int i=0; i<palsize; i++ )
|
||||
{
|
||||
int j = palinv?(palsize-(i+1)):i;
|
||||
pal[j*3] = fgetc(f);
|
||||
pal[j*3+1] = fgetc(f);
|
||||
pal[j*3+2] = fgetc(f);
|
||||
fgetc(f); // skip alpha
|
||||
}
|
||||
fprintf(stderr,"info: RGBA8 palette loaded with %d colors (alpha will be ignored).\n",palsize);
|
||||
}
|
||||
else fprintf(stderr,"warning: palette is in an unsupported format, falling back to grayscale\n");
|
||||
palend:
|
||||
fclose(f);
|
||||
}
|
||||
|
||||
const char grads[8][20] =
|
||||
{
|
||||
"Flat (Shadow)",
|
||||
"Top-Bottom (Shadow)",
|
||||
"Bottom-Top (Shadow)",
|
||||
"Centered (Shadow)",
|
||||
"Flat (Border)",
|
||||
"Top-Bottom (Border)",
|
||||
"Bottom-Top (Border)",
|
||||
"Centered (Border)"
|
||||
};
|
||||
|
||||
#define LOADFLAGS FT_LOAD_DEFAULT
|
||||
#define RENDERMODE FT_RENDER_MODE_NORMAL
|
||||
|
||||
int main( int argc, char **argv )
|
||||
{
|
||||
if ( argc < 2 ) return 1;
|
||||
char tname[256] = {0};
|
||||
unsigned cell = 0;
|
||||
int x = 0, y = 0, w = 0, h = 0;
|
||||
char cropargs[256] = {0};
|
||||
char cname[256] = {0};
|
||||
char* hargs[7] =
|
||||
if ( argc < 4 )
|
||||
{
|
||||
"convert",
|
||||
tname,
|
||||
"-crop",
|
||||
cropargs,
|
||||
"+repage",
|
||||
cname,
|
||||
0
|
||||
};
|
||||
mkdir(argv[1],S_IRWXU|S_IRWXG|S_IROTH|S_IXOTH);
|
||||
while ( !feof(stdin) )
|
||||
{
|
||||
int ret = scanf("0x%x: %s (%d,%d)-(%d,%d)\n",&cell,tname,&x,&y,&w,&h);
|
||||
if ( ret != 6 )
|
||||
{
|
||||
printf("%d != 6\n",ret);
|
||||
return 2;
|
||||
}
|
||||
strcat(tname,".png");
|
||||
if ( (w <= 0) || (h <= 0) ) continue;
|
||||
printf("%u, %s %+d%+d,%d,%d\n",cell,tname,x,y,w,h);
|
||||
sprintf(cname,"%s/%04x.png",argv[1],cell);
|
||||
sprintf(cropargs,"%dx%d%+d%+d",w,h,x,y);
|
||||
int pid = fork();
|
||||
if ( !pid ) execvp(hargs[0],hargs);
|
||||
else waitpid(pid,0,0);
|
||||
fprintf(stderr,"usage: mkfontsingle <font name> <pxsize> <wxh|auto>"
|
||||
" <unicode range (hex)> [gradient type] [color palette] [-palinv]\n");
|
||||
return 1;
|
||||
}
|
||||
if ( FT_Init_FreeType(&ftlib) )
|
||||
{
|
||||
fprintf(stderr,"error: failed to init freetype library\n");
|
||||
return 2;
|
||||
}
|
||||
uint32_t range[2] = {0x0000,0x00FF};
|
||||
sscanf(argv[2],"%d",&pxsiz);
|
||||
if ( !strcmp(argv[3],"auto") )
|
||||
{
|
||||
w = -1;
|
||||
h = -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]);
|
||||
if ( FT_New_Face(ftlib,argv[1],0,&fnt) )
|
||||
{
|
||||
fprintf(stderr,"error: failed to open font '%s'\n",argv[1]);
|
||||
return 4;
|
||||
}
|
||||
if ( FT_Set_Pixel_Sizes(fnt,0,pxsiz) )
|
||||
{
|
||||
fprintf(stderr,"error: font pixel size of '%d' not available\n",pxsiz);
|
||||
return 8;
|
||||
}
|
||||
FT_Select_Charmap(fnt,FT_ENCODING_UNICODE);
|
||||
// first pass to compute baseline upshift
|
||||
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); // also render it while we're at it
|
||||
int valid = 0;
|
||||
for ( unsigned j=0; j<fnt->glyph->bitmap.rows; j++ )
|
||||
valid |= valid_row(&fnt->glyph->bitmap,j);
|
||||
if ( !valid ) continue;
|
||||
int gshift = (fnt->glyph->metrics.horiBearingY-fnt->glyph->metrics.height)>>6;
|
||||
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
|
||||
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;
|
||||
int valid = 0;
|
||||
for ( unsigned j=0; j<fnt->glyph->bitmap.rows; j++ )
|
||||
valid |= valid_row(&fnt->glyph->bitmap,j);
|
||||
if ( !valid ) continue;
|
||||
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;
|
||||
printf("%04X - top: %d upshift: %d yy: %d xup: %d\n",i,fnt->glyph->bitmap_top,upshift,yy,xup);
|
||||
if ( xup > xupshift ) xupshift = xup;
|
||||
}
|
||||
}
|
||||
if ( xupshift )
|
||||
{
|
||||
fprintf(stderr,"info: real upshift is %d.\n",upshift+xupshift);
|
||||
fprintf(stderr,"info: grAb Y offset %d will be used.\n",xupshift);
|
||||
}
|
||||
// third pass to compute the "real" cell size
|
||||
if ( w == -1 )
|
||||
{
|
||||
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;
|
||||
int valid = 0;
|
||||
for ( unsigned j=0; j<fnt->glyph->bitmap.rows; j++ )
|
||||
valid |= valid_row(&fnt->glyph->bitmap,j);
|
||||
if ( !valid ) continue;
|
||||
int gw = fnt->glyph->bitmap_left;
|
||||
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);
|
||||
}
|
||||
iw = w+1;
|
||||
ih = h+1;
|
||||
if ( gradient&4 )
|
||||
{
|
||||
iw++;
|
||||
ih++;
|
||||
}
|
||||
fprintf(stderr,"info: gradient selected is '%s'.\n",grads[gradient&7]);
|
||||
idata = calloc(iw*ih,palsize?4:2);
|
||||
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;
|
||||
int xx = 0;
|
||||
int yy = upshift+xupshift+1;
|
||||
int valid;
|
||||
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);
|
||||
}
|
||||
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);
|
||||
}
|
||||
if ( valid )
|
||||
{
|
||||
if ( oob ) fprintf(stderr,"warning: glyph %04X drawn out of bounds, cell size may be incorrect.\n",i);
|
||||
char fname[256];
|
||||
snprintf(fname,256,"%04X.png",i);
|
||||
writepng(fname,idata,iw,ih,palsize?(iw*4):(iw*2));
|
||||
drawn++;
|
||||
}
|
||||
memset(idata,0,palsize?(iw*ih*4):(iw*ih*2));
|
||||
}
|
||||
fprintf(stderr,"info: %u glyphs drawn.\n",drawn);
|
||||
free(idata);
|
||||
FT_Done_Face(fnt);
|
||||
FT_Done_FreeType(ftlib);
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue