void usage();
int save_png(char *, char *, int, int);
+char verbose=0;
+char alpha=0;
+
int main(int argc, char **argv)
{
FT_Library freetype;
int cell=16;
int ascent;
char *out="font.png";
- char verbose=0;
const char *name;
char autohinter=0;
int count;
return 1;
}
- while((o=getopt(argc,argv,"r:s:l:c:o:avh?"))!=-1)
+ while((o=getopt(argc,argv,"r:s:l:c:o:atvh?"))!=-1)
{
char *ptr;
int temp;
case 'a':
autohinter=1;
break;
+ case 't':
+ alpha=1;
+ break;
case 'v':
- verbose=1;
+ ++verbose;
break;
case 'h':
case '?':
}
name=FT_Get_Postscript_Name(face);
- if(verbose) printf("Font name: %s\n",name);
+ if(verbose)
+ {
+ printf("Font name: %s\n",name);
+ printf("Glyphs: %ld\n",face->num_glyphs);
+ }
err=FT_Set_Pixel_Sizes(face,0,size);
if(err)
fprintf(stderr,"Couldn't set size\n");
return 1;
}
- ascent=face->size->metrics.ascender/64;
- ch=(face->size->metrics.ascender-face->size->metrics.descender)/64;
- cw=face->size->metrics.max_advance/64;
+ ascent=(face->bbox.yMax*face->size->metrics.x_scale)>>16;
+ ascent=(ascent+63)/64;
+ ch=((face->bbox.yMax-face->bbox.yMin)*face->size->metrics.y_scale)>>16;
+ ch=(ch+63)/64;
+ cw=((face->bbox.xMax-face->bbox.xMin)*face->size->metrics.x_scale)>>16;
+ cw=(cw+63)/64;
if(verbose)
{
printf("Ascent %d\n",ascent);
- printf("Descent %ld\n",face->size->metrics.descender/64);
- printf("Height %d\n",ch);
- printf("Width %d\n",cw);
+ printf("Descent %ld\n",(((face->bbox.yMin*face->size->metrics.y_scale)>>16)+63)/64);
+ printf("Max height %d\n",ch);
+ printf("Max width %d\n",cw);
}
- if(ch>cell || cw>cell) fprintf(stderr,"ttf2png: Warning: character size exceeds cell size\n");
+ if(verbose>=1 && (ch>cell || cw>cell)) fprintf(stderr,"Warning: character size exceeds cell size\n");
w=cpl*cell;
h=(end-begin+cpl-1)/cpl*cell;
int glyph=FT_Get_Char_Index(face,i);
FT_Bitmap *bmp=&face->glyph->bitmap;
int x,y;
- int cx=(i%cpl)*cell+(cell-cw)/2;
+ int cx=(i%cpl)*cell;
int cy=(i/cpl)*cell;
int flags=0;
+ int dy;
if(!glyph) continue;
fflush(stdout);
if(autohinter) flags|=FT_LOAD_FORCE_AUTOHINT;
FT_Load_Glyph(face,glyph,flags);
FT_Render_Glyph(face->glyph,FT_RENDER_MODE_NORMAL);
- cx+=face->glyph->bitmap_left;
- cy+=ascent-face->glyph->bitmap_top;
+ if(cell>bmp->width) cx+=(cell-bmp->width)/2;
+ dy=ascent-face->glyph->bitmap_top;
+ cy+=dy;
+ if(verbose>=2)
+ {
+ printf(" Char %d: glyph %d, size %dx%d\n",i,glyph,bmp->width,bmp->rows);
+ if(bmp->width>cell || dy+bmp->rows>cell || dy<0) printf(" Warning: Character %d does not fit in cell\n",i);
+ }
+ if(bmp->pitch<0)
+ {
+ fprintf(stderr,"Warning: Character %d not rendered (can't handle reversed bitmaps)\n",i);
+ continue;
+ }
for(y=0;y<bmp->rows;++y) for(x=0;x<bmp->width;++x)
{
if(cx+x<0 || cx+x>=w || cy+y<0 || cy+y>=h) continue;
- if(bmp->pitch>0)
- data[cx+x+(cy+y)*w]=255-bmp->buffer[x+y*bmp->pitch];
+ data[cx+x+(cy+y)*w]=255-bmp->buffer[x+y*bmp->pitch];
}
++count;
}
" -c Character cell size, in pixels [16]\n"
" -o Output file name [font.png]\n"
" -a Force autohinter\n"
- " -v Enable verbose mode\n"
+ " -t Render font to alpha channel\n"
+ " -v Increase the level of verbosity\n"
" -h Print this message\n");
}
png_info *pngi;
png_byte *rows[h];
int i;
+ png_byte *data2;
+ int color;
out=fopen(fn,"wb");
if(!out)
}
png_init_io(pngs,out);
- png_set_IHDR(pngs,pngi,w,h,8,PNG_COLOR_TYPE_GRAY,PNG_INTERLACE_NONE,PNG_COMPRESSION_TYPE_DEFAULT,PNG_FILTER_TYPE_DEFAULT);
- for(i=0;i<h;++i)
- rows[i]=(png_byte *)(data+i*w);
+ if(alpha)
+ {
+ data2=(png_byte *)malloc(w*h*2);
+ for(i=0;i<w*h;++i)
+ {
+ data2[i*2]=255;
+ data2[i*2+1]=255-data[i];
+ }
+ for(i=0;i<h;++i)
+ rows[i]=(png_byte *)(data2+i*w*2);
+ color=PNG_COLOR_TYPE_GRAY_ALPHA;
+ }
+ else
+ {
+ for(i=0;i<h;++i)
+ rows[i]=(png_byte *)(data+i*w);
+ color=PNG_COLOR_TYPE_GRAY;
+ }
+ png_set_IHDR(pngs,pngi,w,h,8,color,PNG_INTERLACE_NONE,PNG_COMPRESSION_TYPE_DEFAULT,PNG_FILTER_TYPE_DEFAULT);
png_set_rows(pngs,pngi,rows);
png_write_png(pngs,pngi,PNG_TRANSFORM_IDENTITY,NULL);
png_destroy_write_struct(&pngs,&pngi);
+ if(alpha) free(data2);
+
+ if(verbose) printf("Saved %dx%d PNG image to %s\n",w,h,fn);
return 0;
}