]> git.tdb.fi Git - ttf2png.git/blob - ttf2png.c
Version 0.1.1
[ttf2png.git] / ttf2png.c
1 /*
2 ttf2png - True Type Font to PNG converter
3 Copyright (c) 2004 Mikkosoft Productions
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18 */
19
20 #include <stdio.h>
21 #include <unistd.h>
22 #include <getopt.h>
23 #include <png.h>
24 #include <ft2build.h>
25 #include FT_FREETYPE_H
26
27 void usage();
28 int save_png(char *, char *, int, int);
29
30 char    verbose=0;
31 char    alpha=0;
32
33 int main(int argc, char **argv)
34 {
35         FT_Library      freetype;
36         FT_Face         face;
37         int     err;
38         int     o;
39         int     begin=0;
40         int     end=255;
41         char    *fn;
42         int     size=10;
43         int     cpl=16;
44         int     w,h;
45         int     i;
46         char    *data;
47         int     ch,cw;
48         int     cell=16;
49         int     ascent;
50         char    *out="font.png";
51         const char      *name;
52         char    autohinter=0;
53         int     count;
54
55         if(argc<2)
56         {
57                 usage();
58                 return 1;
59         }
60
61         while((o=getopt(argc,argv,"r:s:l:c:o:atvh?"))!=-1)
62         {
63                 char    *ptr;
64                 int     temp;
65                 switch(o)
66                 {
67                 case 'r':
68                         if(!isdigit(optarg[0])) temp=-1;
69                         else
70                         {
71                                 temp=strtol(optarg,&ptr,0);
72                                 if(ptr[0]!=',' || !isdigit(ptr[1])) temp=-1;
73                         }
74                         if(temp<0)
75                                 printf("Not a valid range: %s\n",optarg);
76                         else
77                         {
78                                 begin=temp;
79                                 end=strtol(ptr+1,NULL,0);
80                         }
81                         break;
82                 case 's':
83                         size=strtol(optarg,NULL,0);
84                         break;
85                 case 'l':
86                         cpl=strtol(optarg,NULL,0);
87                         break;
88                 case 'c':
89                         cell=strtol(optarg,NULL,0);
90                         break;
91                 case 'o':
92                         out=optarg;
93                         break;
94                 case 'a':
95                         autohinter=1;
96                         break;
97                 case 't':
98                         alpha=1;
99                         break;
100                 case 'v':
101                         ++verbose;
102                         break;
103                 case 'h':
104                 case '?':
105                         usage();
106                         return 0;
107                 }
108         }
109
110         if(optind>=argc)
111         {
112                 usage();
113                 return 1;
114         }
115         fn=argv[optind];
116
117         err=FT_Init_FreeType(&freetype);
118         if(err)
119         {
120                 fprintf(stderr,"Couldn't initialize FreeType library\n");
121                 return 1;
122         }
123
124         err=FT_New_Face(freetype,fn,0,&face);
125         if(err)
126         {
127                 fprintf(stderr,"Couldn't load font file\n");
128                 if(err==FT_Err_Unknown_File_Format)
129                         fprintf(stderr,"Unknown file format\n");
130                 return 1;
131         }
132
133         name=FT_Get_Postscript_Name(face);
134         if(verbose)
135         {
136                 printf("Font name: %s\n",name);
137                 printf("Glyphs: %ld\n",face->num_glyphs);
138         }
139
140         err=FT_Set_Pixel_Sizes(face,0,size);
141         if(err)
142         {
143                 fprintf(stderr,"Couldn't set size\n");
144                 return 1;
145         }
146         ascent=(face->bbox.yMax*face->size->metrics.x_scale)>>16;
147         ascent=(ascent+63)/64;
148         ch=((face->bbox.yMax-face->bbox.yMin)*face->size->metrics.y_scale)>>16;
149         ch=(ch+63)/64;
150         cw=((face->bbox.xMax-face->bbox.xMin)*face->size->metrics.x_scale)>>16;
151         cw=(cw+63)/64;
152         if(verbose)
153         {
154                 printf("Ascent %d\n",ascent);
155                 printf("Descent %ld\n",(((face->bbox.yMin*face->size->metrics.y_scale)>>16)+63)/64);
156                 printf("Max height %d\n",ch);
157                 printf("Max width %d\n",cw);
158         }
159         if(verbose>=1 && (ch>cell || cw>cell)) fprintf(stderr,"Warning: character size exceeds cell size\n");
160
161         w=cpl*cell;
162         h=(end-begin+cpl-1)/cpl*cell;
163         data=(char *)malloc(w*h);
164         memset(data,255,w*h);
165
166         count=0;
167         for(i=begin;i<=end;++i)
168         {
169                 int                     glyph=FT_Get_Char_Index(face,i);
170                 FT_Bitmap       *bmp=&face->glyph->bitmap;
171                 int                     x,y;
172                 int                     cx=(i%cpl)*cell;
173                 int                     cy=(i/cpl)*cell;
174                 int                     flags=0;
175                 int                     dy;
176                 if(!glyph) continue;
177                 fflush(stdout);
178                 if(autohinter) flags|=FT_LOAD_FORCE_AUTOHINT;
179                 FT_Load_Glyph(face,glyph,flags);
180                 FT_Render_Glyph(face->glyph,FT_RENDER_MODE_NORMAL);
181                 if(cell>bmp->width) cx+=(cell-bmp->width)/2;
182                 dy=ascent-face->glyph->bitmap_top;
183                 cy+=dy;
184                 if(verbose>=2)
185                 {
186                         printf("  Char %d: glyph %d, size %dx%d\n",i,glyph,bmp->width,bmp->rows);
187                         if(bmp->width>cell || dy+bmp->rows>cell || dy<0) printf("  Warning: Character %d does not fit in cell\n",i);
188                 }
189                 if(bmp->pitch<0)
190                 {
191                         fprintf(stderr,"Warning: Character %d not rendered (can't handle reversed bitmaps)\n",i);
192                         continue;
193                 }
194                 for(y=0;y<bmp->rows;++y) for(x=0;x<bmp->width;++x)
195                 {
196                         if(cx+x<0 || cx+x>=w || cy+y<0 || cy+y>=h) continue;
197                         data[cx+x+(cy+y)*w]=255-bmp->buffer[x+y*bmp->pitch];
198                 }
199                 ++count;
200         }
201
202         save_png(out,data,w,h);
203
204         if(verbose) printf("Converted %d glyphs\n",count);
205
206         return 0;
207 }
208
209 void usage()
210 {
211         printf("ttf2png - True Type Font to PNG converter\n"
212                 "Copyright (c) 2004 Mikkosoft Productions\n"
213                 "Distributed under the GNU General Public License\n\n"
214                 "Usage: ttf2png [options] <TTF file>\n\n"
215                 "Accepted options (default values in [brackets])\n"
216                 "  -r  Range of characters to convert in the format low,high [0,255]\n"
217                 "  -s  Font size to use, in pixels [10]\n"
218                 "  -l  Number of characters to put in one line [16]\n"
219                 "  -c  Character cell size, in pixels [16]\n"
220                 "  -o  Output file name [font.png]\n"
221                 "  -a  Force autohinter\n"
222                 "  -t  Render font to alpha channel\n"
223                 "  -v  Increase the level of verbosity\n"
224                 "  -h  Print this message\n");
225 }
226
227 int save_png(char *fn, char *data, int w, int h)
228 {
229         FILE                    *out;
230         png_struct      *pngs;
231         png_info                *pngi;
232         png_byte                *rows[h];
233         int                     i;
234         png_byte                *data2;
235         int                     color;
236
237         out=fopen(fn,"wb");
238         if(!out)
239         {
240                 fprintf(stderr,"Couldn't open output file\n");
241                 return -1;
242         }
243
244         pngs=png_create_write_struct(PNG_LIBPNG_VER_STRING,NULL,NULL,NULL);
245         if(!pngs)
246         {
247                 fprintf(stderr,"Error writing PNG file\n");
248                 return -1;
249         }
250         pngi=png_create_info_struct(pngs);
251         if(!pngi)
252         {
253                 png_destroy_write_struct(&pngs,NULL);
254                 fprintf(stderr,"Error writing PNG file\n");
255                 return -1;
256         }
257
258         png_init_io(pngs,out);
259         if(alpha)
260         {
261                 data2=(png_byte *)malloc(w*h*2);
262                 for(i=0;i<w*h;++i)
263                 {
264                         data2[i*2]=255;
265                         data2[i*2+1]=255-data[i];
266                 }
267                 for(i=0;i<h;++i)
268                         rows[i]=(png_byte *)(data2+i*w*2);
269                 color=PNG_COLOR_TYPE_GRAY_ALPHA;
270         }
271         else
272         {
273                 for(i=0;i<h;++i)
274                         rows[i]=(png_byte *)(data+i*w);
275                 color=PNG_COLOR_TYPE_GRAY;
276         }
277         png_set_IHDR(pngs,pngi,w,h,8,color,PNG_INTERLACE_NONE,PNG_COMPRESSION_TYPE_DEFAULT,PNG_FILTER_TYPE_DEFAULT);
278         png_set_rows(pngs,pngi,rows);
279         png_write_png(pngs,pngi,PNG_TRANSFORM_IDENTITY,NULL);
280         png_destroy_write_struct(&pngs,&pngi);
281         if(alpha) free(data2);
282
283         if(verbose) printf("Saved %dx%d PNG image to %s\n",w,h,fn);
284
285         return 0;
286 }