]> git.tdb.fi Git - ttf2png.git/blob - ttf2png.c
97be0f1fc6ef4934f991bfc323c5b80a02eecd93
[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 int main(int argc, char **argv)
31 {
32         FT_Library      freetype;
33         FT_Face         face;
34         int     err;
35         int     o;
36         int     begin=0;
37         int     end=255;
38         char    *fn;
39         int     size=10;
40         int     cpl=16;
41         int     w,h;
42         int     i;
43         char    *data;
44         int     ch,cw;
45         int     cell=16;
46         int     ascent;
47         char    *out="font.png";
48         char    verbose=0;
49         const char      *name;
50         char    autohinter=0;
51         int     count;
52
53         if(argc<2)
54         {
55                 usage();
56                 return 1;
57         }
58
59         while((o=getopt(argc,argv,"r:s:l:c:o:avh?"))!=-1)
60         {
61                 char    *ptr;
62                 int     temp;
63                 switch(o)
64                 {
65                 case 'r':
66                         if(!isdigit(optarg[0])) temp=-1;
67                         else
68                         {
69                                 temp=strtol(optarg,&ptr,0);
70                                 if(ptr[0]!=',' || !isdigit(ptr[1])) temp=-1;
71                         }
72                         if(temp<0)
73                                 printf("Not a valid range: %s\n",optarg);
74                         else
75                         {
76                                 begin=temp;
77                                 end=strtol(ptr+1,NULL,0);
78                         }
79                         break;
80                 case 's':
81                         size=strtol(optarg,NULL,0);
82                         break;
83                 case 'l':
84                         cpl=strtol(optarg,NULL,0);
85                         break;
86                 case 'c':
87                         cell=strtol(optarg,NULL,0);
88                         break;
89                 case 'o':
90                         out=optarg;
91                         break;
92                 case 'a':
93                         autohinter=1;
94                         break;
95                 case 'v':
96                         verbose=1;
97                         break;
98                 case 'h':
99                 case '?':
100                         usage();
101                         return 0;
102                 }
103         }
104
105         if(optind>=argc)
106         {
107                 usage();
108                 return 1;
109         }
110         fn=argv[optind];
111
112         err=FT_Init_FreeType(&freetype);
113         if(err)
114         {
115                 fprintf(stderr,"Couldn't initialize FreeType library\n");
116                 return 1;
117         }
118
119         err=FT_New_Face(freetype,fn,0,&face);
120         if(err)
121         {
122                 fprintf(stderr,"Couldn't load font file\n");
123                 if(err==FT_Err_Unknown_File_Format)
124                         fprintf(stderr,"Unknown file format\n");
125                 return 1;
126         }
127
128         name=FT_Get_Postscript_Name(face);
129         if(verbose) printf("Font name: %s\n",name);
130
131         err=FT_Set_Pixel_Sizes(face,0,size);
132         if(err)
133         {
134                 fprintf(stderr,"Couldn't set size\n");
135                 return 1;
136         }
137         ascent=face->size->metrics.ascender/64;
138         ch=(face->size->metrics.ascender-face->size->metrics.descender)/64;
139         cw=face->size->metrics.max_advance/64;
140         if(verbose)
141         {
142                 printf("Ascent %d\n",ascent);
143                 printf("Descent %ld\n",face->size->metrics.descender/64);
144                 printf("Height %d\n",ch);
145                 printf("Width %d\n",cw);
146         }
147         if(ch>cell || cw>cell) fprintf(stderr,"ttf2png: Warning: character size exceeds cell size\n");
148
149         w=cpl*cell;
150         h=(end-begin+cpl-1)/cpl*cell;
151         data=(char *)malloc(w*h);
152         memset(data,255,w*h);
153
154         count=0;
155         for(i=begin;i<=end;++i)
156         {
157                 int                     glyph=FT_Get_Char_Index(face,i);
158                 FT_Bitmap       *bmp=&face->glyph->bitmap;
159                 int                     x,y;
160                 int                     cx=(i%cpl)*cell+(cell-cw)/2;
161                 int                     cy=(i/cpl)*cell;
162                 int                     flags=0;
163                 if(!glyph) continue;
164                 fflush(stdout);
165                 if(autohinter) flags|=FT_LOAD_FORCE_AUTOHINT;
166                 FT_Load_Glyph(face,glyph,flags);
167                 FT_Render_Glyph(face->glyph,FT_RENDER_MODE_NORMAL);
168                 cx+=face->glyph->bitmap_left;
169                 cy+=ascent-face->glyph->bitmap_top;
170                 for(y=0;y<bmp->rows;++y) for(x=0;x<bmp->width;++x)
171                 {
172                         if(cx+x<0 || cx+x>=w || cy+y<0 || cy+y>=h) continue;
173                         if(bmp->pitch>0)
174                                 data[cx+x+(cy+y)*w]=255-bmp->buffer[x+y*bmp->pitch];
175                 }
176                 ++count;
177         }
178
179         save_png(out,data,w,h);
180
181         if(verbose) printf("Converted %d glyphs\n",count);
182
183         return 0;
184 }
185
186 void usage()
187 {
188         printf("ttf2png - True Type Font to PNG converter\n"
189                 "Copyright (c) 2004 Mikkosoft Productions\n"
190                 "Distributed under the GNU General Public License\n\n"
191                 "Usage: ttf2png [options] <TTF file>\n\n"
192                 "Accepted options (default values in [brackets])\n"
193                 "  -r  Range of characters to convert in the format low,high [0,255]\n"
194                 "  -s  Font size to use, in pixels [10]\n"
195                 "  -l  Number of characters to put in one line [16]\n"
196                 "  -c  Character cell size, in pixels [16]\n"
197                 "  -o  Output file name [font.png]\n"
198                 "  -a  Force autohinter\n"
199                 "  -v  Enable verbose mode\n"
200                 "  -h  Print this message\n");
201 }
202
203 int save_png(char *fn, char *data, int w, int h)
204 {
205         FILE                    *out;
206         png_struct      *pngs;
207         png_info                *pngi;
208         png_byte                *rows[h];
209         int                     i;
210
211         out=fopen(fn,"wb");
212         if(!out)
213         {
214                 fprintf(stderr,"Couldn't open output file\n");
215                 return -1;
216         }
217
218         pngs=png_create_write_struct(PNG_LIBPNG_VER_STRING,NULL,NULL,NULL);
219         if(!pngs)
220         {
221                 fprintf(stderr,"Error writing PNG file\n");
222                 return -1;
223         }
224         pngi=png_create_info_struct(pngs);
225         if(!pngi)
226         {
227                 png_destroy_write_struct(&pngs,NULL);
228                 fprintf(stderr,"Error writing PNG file\n");
229                 return -1;
230         }
231
232         png_init_io(pngs,out);
233         png_set_IHDR(pngs,pngi,w,h,8,PNG_COLOR_TYPE_GRAY,PNG_INTERLACE_NONE,PNG_COMPRESSION_TYPE_DEFAULT,PNG_FILTER_TYPE_DEFAULT);
234         for(i=0;i<h;++i)
235                 rows[i]=(png_byte *)(data+i*w);
236         png_set_rows(pngs,pngi,rows);
237         png_write_png(pngs,pngi,PNG_TRANSFORM_IDENTITY,NULL);
238         png_destroy_write_struct(&pngs,&pngi);
239
240         return 0;
241 }