From 78feedfca690b08a94736b9ca1a2bd36964a6f01 Mon Sep 17 00:00:00 2001 From: Mikko Rasa Date: Tue, 19 Sep 2006 14:44:49 +0300 Subject: [PATCH] Version 0.2 --- Makefile | 2 +- Readme | 16 ++++ ttf2png.c | 259 +++++++++++++++++++++++++++++++++++------------------- 3 files changed, 184 insertions(+), 93 deletions(-) diff --git a/Makefile b/Makefile index b1dbdd2..c201847 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ ttf2png: ttf2png.c gcc -Wall $^ -o $@ $(shell freetype-config --cflags --libs) $(shell pkg-config --cflags --libs libpng12) -VER=0.1.1 +VER=0.2 .PHONY: tarball tarball: ttf2png-$(VER).tar.gz diff --git a/Readme b/Readme index bbd8b59..c387b10 100644 --- a/Readme +++ b/Readme @@ -9,6 +9,22 @@ libpng 1.2 C compiler (preferably GCC) +Changes + +0.2 +- Added output to stdout +- Clean up code a bit +- Added sequential mode +- Added definition file writing + +0.1.1 +- Added more verbosity +- Added transparency mode + +0.1 +- Initial release + + License This program is free software; you can redistribute it and/or diff --git a/ttf2png.c b/ttf2png.c index dfdde4b..4fbe990 100644 --- a/ttf2png.c +++ b/ttf2png.c @@ -24,33 +24,36 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA #include #include FT_FREETYPE_H +unsigned round_to_pot(unsigned); void usage(); int save_png(char *, char *, int, int); -char verbose=0; -char alpha=0; +char verbose=0; +char alpha=0; int main(int argc, char **argv) { - FT_Library freetype; - FT_Face face; - int err; - int o; - int begin=0; - int end=255; - char *fn; - int size=10; - int cpl=16; - int w,h; - int i; - char *data; - int ch,cw; - int cell=16; - int ascent; - char *out="font.png"; - const char *name; - char autohinter=0; - int count; + FT_Library freetype; + FT_Face face; + int err; + int o; + int begin=0; + int end=255; + char *fn; + int size=10; + int cpl=16; + int w,h; + int i; + char *data; + int ch,cw; + int cell=16; + int ascent; + char *out="font.png"; + char autohinter=0; + int count; + char *def_fn=NULL; + char seq=0; + FILE *def=NULL; if(argc<2) { @@ -58,35 +61,45 @@ int main(int argc, char **argv) return 1; } - while((o=getopt(argc,argv,"r:s:l:c:o:atvh?"))!=-1) + while((o=getopt(argc, argv, "r:s:l:c:o:atvh?ed:"))!=-1) { - char *ptr; - int temp; + char *ptr; + int temp; switch(o) { case 'r': - if(!isdigit(optarg[0])) temp=-1; - else + if(!strcmp(optarg, "all")) { - temp=strtol(optarg,&ptr,0); - if(ptr[0]!=',' || !isdigit(ptr[1])) temp=-1; + begin=0; + end=0x110000; } - if(temp<0) - printf("Not a valid range: %s\n",optarg); else { - begin=temp; - end=strtol(ptr+1,NULL,0); + if(!isdigit(optarg[0])) + temp=-1; + else + { + temp=strtol(optarg, &ptr, 0); + if(ptr[0]!=',' || !isdigit(ptr[1])) + temp=-1; + } + if(temp<0) + printf("Not a valid range: %s\n", optarg); + else + { + begin=temp; + end=strtol(ptr+1, NULL, 0); + } } break; case 's': - size=strtol(optarg,NULL,0); + size=strtol(optarg, NULL, 0); break; case 'l': - cpl=strtol(optarg,NULL,0); + cpl=strtol(optarg, NULL, 0); break; case 'c': - cell=strtol(optarg,NULL,0); + cell=strtol(optarg, NULL, 0); break; case 'o': out=optarg; @@ -104,43 +117,52 @@ int main(int argc, char **argv) case '?': usage(); return 0; + case 'e': + seq=1; + break; + case 'd': + def_fn=optarg; + break; } } + if(!strcmp(out,"-")) + verbose=0; - if(optind>=argc) + if(optind!=argc-1) { usage(); return 1; } + fn=argv[optind]; err=FT_Init_FreeType(&freetype); if(err) { - fprintf(stderr,"Couldn't initialize FreeType library\n"); + fprintf(stderr, "Couldn't initialize FreeType library\n"); return 1; } - err=FT_New_Face(freetype,fn,0,&face); + err=FT_New_Face(freetype, fn, 0, &face); if(err) { - fprintf(stderr,"Couldn't load font file\n"); + fprintf(stderr, "Couldn't load font file\n"); if(err==FT_Err_Unknown_File_Format) - fprintf(stderr,"Unknown file format\n"); + fprintf(stderr, "Unknown file format\n"); return 1; } - name=FT_Get_Postscript_Name(face); if(verbose) { - printf("Font name: %s\n",name); - printf("Glyphs: %ld\n",face->num_glyphs); + const char *name=FT_Get_Postscript_Name(face); + printf("Font name: %s\n", name); + printf("Glyphs: %ld\n", face->num_glyphs); } - err=FT_Set_Pixel_Sizes(face,0,size); + err=FT_Set_Pixel_Sizes(face, 0, size); if(err) { - fprintf(stderr,"Couldn't set size\n"); + fprintf(stderr, "Couldn't set size\n"); return 1; } ascent=(face->bbox.yMax*face->size->metrics.x_scale)>>16; @@ -158,54 +180,100 @@ int main(int argc, char **argv) } 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; + w=round_to_pot(cpl*cell); + if(seq) + h=(face->num_glyphs+cpl-1)/cpl*cell; + else + h=(end-begin+cpl-1)/cpl*cell; + h=round_to_pot(h); + data=(char *)malloc(w*h); - memset(data,255,w*h); + memset(data, 255, w*h); + + if(def_fn) + def=fopen(def_fn, "w"); + + if(def) + fprintf(def, "%d %d %d\n", w, h, size); count=0; - for(i=begin;i<=end;++i) + for(i=begin; i<=end; ++i) { - int glyph=FT_Get_Char_Index(face,i); - FT_Bitmap *bmp=&face->glyph->bitmap; - int x,y; - int cx=(i%cpl)*cell; - int cy=(i/cpl)*cell; - int flags=0; - int dy; + int glyph=FT_Get_Char_Index(face,i); + FT_Bitmap *bmp=&face->glyph->bitmap; + int x,y; + int cx,cy; + 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); - if(cell>bmp->width) cx+=(cell-bmp->width)/2; + + if(seq) + { + cx=(count%cpl)*cell; + cy=(count/cpl)*cell; + } + else + { + cx=(i%cpl)*cell; + cy=(i/cpl)*cell; + } + + if(autohinter) + flags|=FT_LOAD_FORCE_AUTOHINT; + FT_Load_Glyph(face, glyph, flags); + FT_Render_Glyph(face->glyph, FT_RENDER_MODE_NORMAL); + 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); + 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); + fprintf(stderr, "Warning: Character %d not rendered (can't handle reversed bitmaps)\n", i); continue; } - for(y=0;yrows;++y) for(x=0;xwidth;++x) + + for(y=0; yrows; ++y) for(x=0; xwidth; ++x) { if(cx+x<0 || cx+x>=w || cy+y<0 || cy+y>=h) continue; data[cx+x+(cy+y)*w]=255-bmp->buffer[x+y*bmp->pitch]; } + + if(def) + fprintf(def, "%d %d %d %d %d %d %d\n",i, cx, cy, bmp->width, bmp->rows, face->glyph->bitmap_top-bmp->rows, (int)(face->glyph->advance.x+32)/64); + ++count; } - save_png(out,data,w,h); + if(def) + fclose(def); + + save_png(out, data, w, h); if(verbose) printf("Converted %d glyphs\n",count); return 0; } +unsigned round_to_pot(unsigned n) +{ + n-=1; + n|=n>>1; + n|=n>>2; + n|=n>>4; + n|=n>>8; + n|=n>>16; + + return n+1; +} + void usage() { printf("ttf2png - True Type Font to PNG converter\n" @@ -217,70 +285,77 @@ void usage() " -s Font size to use, in pixels [10]\n" " -l Number of characters to put in one line [16]\n" " -c Character cell size, in pixels [16]\n" - " -o Output file name [font.png]\n" + " -o Output file name (or - for stdout) [font.png]\n" " -a Force autohinter\n" " -t Render font to alpha channel\n" " -v Increase the level of verbosity\n" + " -e Use cells in sequence, rather than by code\n" + " -d Write a definition to the given file\n" " -h Print this message\n"); } int save_png(char *fn, char *data, int w, int h) { - FILE *out; - png_struct *pngs; - png_info *pngi; - png_byte *rows[h]; - int i; - png_byte *data2; - int color; - - out=fopen(fn,"wb"); - if(!out) + FILE *out; + png_struct *pngs; + png_info *pngi; + png_byte *rows[h]; + int i; + png_byte *data2; + int color; + + if(!strcmp(fn, "-")) + out=stdout; + else { - fprintf(stderr,"Couldn't open output file\n"); - return -1; + out=fopen(fn, "wb"); + if(!out) + { + fprintf(stderr, "Couldn't open output file\n"); + return -1; + } } - pngs=png_create_write_struct(PNG_LIBPNG_VER_STRING,NULL,NULL,NULL); + pngs=png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if(!pngs) { - fprintf(stderr,"Error writing PNG file\n"); + fprintf(stderr, "Error writing PNG file\n"); return -1; } pngi=png_create_info_struct(pngs); if(!pngi) { - png_destroy_write_struct(&pngs,NULL); - fprintf(stderr,"Error writing PNG file\n"); + png_destroy_write_struct(&pngs, NULL); + fprintf(stderr, "Error writing PNG file\n"); return -1; } - png_init_io(pngs,out); + png_init_io(pngs, out); if(alpha) { data2=(png_byte *)malloc(w*h*2); - for(i=0;i