* added freetype support in ttf2pt1
[swftools.git] / pdf2swf / font2swf.cc
1 /* makefonts.cc
2
3    Utility for converting Type 1 fonts to SWF.
4    
5    Part of the swftools package.
6
7    Copyright (c) 2001 Matthias Kramm <kramm@quiss.org>
8  
9    This file is distributed under the GPL, see file COPYING for details 
10
11 */
12
13
14 #include <stdio.h>
15 #include <unistd.h>
16 #include <fcntl.h>
17 #include <math.h>
18 #include "../lib/rfxswf.h"
19 #include "../lib/args.h"
20 #include "swfoutput.h"
21 #include "spline.h"
22
23 static char * filenames[256];
24 static int filenum;
25 static char * destfilename = "output.swf";
26 int all=0;
27 int verbose=0;
28
29 struct options_t options[] =
30 {
31  {"o","output"},
32  {"v","verbose"},
33  {"V","version"},
34  {0,0}
35 };
36 int args_callback_option(char*name,char*val)
37 {
38     if(!strcmp(name, "V")) {
39         printf("font2swf - part of %s %s\n", PACKAGE, VERSION);
40         exit(0);
41     }
42     else if(!strcmp(name, "o")) {
43         destfilename = val;
44         return 1;
45     }
46     else if(!strcmp(name, "v")) {
47         verbose ++;
48         return 0;
49     }
50     else {
51         printf("Unknown option: -%s\n", name);
52         exit(1);
53     }
54     return 0;
55 }
56 int args_callback_longoption(char*name,char*val)
57 {
58     return args_long2shortoption(options, name, val);
59 }
60 void args_callback_usage(char*name)
61 {    
62     printf("Usage: %s file.afm [...]\n", name);
63     printf("   OR: %s all\n", name);
64     printf("\n");
65     printf("\tIf \"all\" is given instead of font names, all standard fonts\n");
66     printf("\t(Courier, Arial etc.) will be created\n");
67     printf("\n");
68     printf("Options:\n");
69     printf("\n");
70     printf("\t-h , --help\t\t Print help and exit\n");
71     printf("\t-o , --output filename\t set output filename\n");
72     printf("\t-v , --verbose\t\t Be more verbose\n");
73     printf("\t-V , --version\t\t Print program version and exit\n");
74 }
75 int args_callback_command(char*name,char*val)
76 {
77     if(!strcmp(name, "all"))
78         all = 1;
79     else {
80         filenames[filenum++] = strdup(name);
81     }
82     return 0;
83 }
84
85
86 #define standardEncodingSize 256
87 #define symbolEncodingSize 256
88 #define zapfDingbatsEncodingSize 256
89 #define macRomanEncodingSize 256
90
91 extern char *standardEncoding[standardEncodingSize];
92 extern char *symbolEncoding[symbolEncodingSize];
93 extern char *zapfDingbatsEncoding[zapfDingbatsEncodingSize];
94 extern char *macRomanEncoding[macRomanEncodingSize];
95
96 extern void drawpath(TAG*tag, T1_OUTLINE*outline, struct swfmatrix*m, int log);
97 extern void resetdrawer();
98 extern void moveto(TAG*tag, plotxy p0);
99 extern void lineto(TAG*tag, plotxy p0);
100
101 SWFFONT * t1font2swffont(int i)
102 {
103     T1_LoadFont(i);
104
105     float angle = T1_GetItalicAngle(i);
106     char*fontname = T1_GetFontName(i);
107     char*fullname = T1_GetFullName(i);
108     char*familyname = T1_GetFamilyName(i);
109     float underline = T1_GetUnderlinePosition(i);
110     BBox bbox = T1_GetFontBBox(i);
111
112     /* if "all" is given, translate the font names in something more
113        readable */
114     if(!strcmp(fullname, "Nimbus Roman No9 L Regular")) fontname = "Helvetica";
115     if(!strcmp(fullname, "Nimbus Roman No9 L Regular Italic")) fontname = "HelveticaItalic";
116     if(!strcmp(fullname, "Nimbus Roman No9 L Medium")) fontname = "HelveticaBold";
117     if(!strcmp(fullname, "Nimbus Roman No9 L Medium Italic")) fontname = "HelveticaBoldItalic";
118     if(!strcmp(fullname, "Nimbus Sans L Regular")) fontname = "Times";
119     if(!strcmp(fullname, "Nimbus Sans L Regular Italic")) fontname = "TimesItalic";
120     if(!strcmp(fullname, "Nimbus Sans L Bold")) fontname = "TimesBold";
121     if(!strcmp(fullname, "Nimbus Sans L Bold Italic")) fontname = "TimesBoldItalic";
122     if(!strcmp(fullname, "Nimbus Mono L Regular")) fontname = "Courier";
123     if(!strcmp(fullname, "Nimbus Mono L Regular Oblique")) fontname = "CourierItalic";
124     if(!strcmp(fullname, "Nimbus Mono L Bold")) fontname = "CourierBold";
125     if(!strcmp(fullname, "Nimbus Mono L Bold Oblique")) fontname = "CourierBoldItalic";
126     if(!strcmp(fullname, "Standard Symbols L")) fontname = "Symbol";
127
128     char ** encoding = standardEncoding;
129     int encodingsize = standardEncodingSize;
130
131     printf("processing \"%s\" (\"%s\")...\n", fullname, fontname);
132
133     if(strstr(fullname, "Dingbats")) {// Zapf Dingbats
134         encoding = zapfDingbatsEncoding;
135         encodingsize = zapfDingbatsEncodingSize;
136     }
137     else if(strstr(fullname, "Symbol")) {// Symbol
138         encoding = symbolEncoding;
139         encodingsize = symbolEncodingSize;
140     }
141
142     SWFFONT * wfont = (SWFFONT*)malloc(sizeof(SWFFONT));
143     SWFFont * font = new SWFFont("", i, "");
144
145     memset(wfont, 0, sizeof(SWFFONT));
146
147     wfont->version = 2;
148     wfont->name = (U8*)strdup(fontname);
149     wfont->layout = (SWFLAYOUT*)malloc(sizeof(SWFLAYOUT));
150     memset(wfont->layout, 0, sizeof(SWFLAYOUT));
151
152     int s,num;
153     num = 0;
154     for(s=0;s<encodingsize;s++)
155     {
156         if(encoding[s]) {
157             T1_OUTLINE*outline = font->getOutline(encoding[s], 0);
158             if(outline) num++;
159         }
160     }
161
162     wfont->maxascii = encodingsize;
163     wfont->numchars = num;
164     
165     wfont->style = (/*bold*/0?FONT_STYLE_BOLD:0) + (angle>0.05?FONT_STYLE_ITALIC:0);
166
167     wfont->glyph = (SWFGLYPH*)malloc(num*sizeof(SWFGLYPH));
168     memset(wfont->glyph, 0, num*sizeof(SWFGLYPH));
169     wfont->glyph2ascii = (U16*)malloc(num*sizeof(U16));
170     memset(wfont->glyph2ascii, 0, num*sizeof(U16));
171     wfont->ascii2glyph = (int*)malloc(encodingsize*sizeof(int));
172     memset(wfont->ascii2glyph, -1, encodingsize*sizeof(int));
173     wfont->layout->ascent = (U16)(underline - bbox.lly);
174     wfont->layout->descent = (U16)(bbox.ury - underline);
175     wfont->layout->leading = (U16)(wfont->layout->ascent - 
176                              wfont->layout->descent -
177                              (bbox.lly - bbox.ury));
178     wfont->layout->bounds = (SRECT*)malloc(sizeof(SRECT)*num);
179     memset(wfont->layout->bounds, 0, sizeof(SRECT)*num);
180     wfont->layout->kerningcount = 0;
181     wfont->layout->kerning = 0;
182   
183     num = 0;
184     for(s=0;s<encodingsize;s++)
185     {
186         if(encoding[s]) {
187             T1_OUTLINE*outline = font->getOutline(encoding[s],0);
188             int width = font->getWidth(encoding[s]);
189
190             if(outline) {
191                 int log = 0;
192                 wfont->ascii2glyph[s] = num;
193                 wfont->glyph2ascii[num] = s;
194                 swf_ShapeNew(&wfont->glyph[num].shape);
195                 SHAPE*shape = wfont->glyph[num].shape;
196                 int firstx = outline->dest.x/0xffff;
197                 
198                 TAG*tag = swf_InsertTag(0,ST_DEFINESHAPE);
199
200                 swfmatrix m;
201                 m.m11 = 1.0;
202                 m.m22 = 1.0;
203                 m.m21 = 0;
204                 m.m12 = 0;
205                 m.m13 = 0;
206                 m.m23 = 0;
207
208                 swf_SetU8(tag,0);
209
210                 shape->bits.fill = 1;
211                 shape->bits.line = 0;
212                 swf_ShapeSetStyle(tag,shape,0,1,0);
213                 resetdrawer();
214
215                 drawpath(tag, outline, &m, log);
216
217                 /*uncomment this to mark the glyph sizes:
218                 plotxy p1,p2; p1.x=0; p1.y=0; p2.x=width/8; p2.y=-width/8;
219                 moveto(tag, p1); lineto(tag, p2); p1.x += 2; p2.x += 2;
220                 lineto(tag, p2); lineto(tag, p1); p1.x -= 2; lineto(tag, p1);// */
221
222                 swf_ShapeSetEnd(tag);
223
224                 wfont->glyph[num].shape->bitlen = (tag->len-1)*8;
225                 wfont->glyph[num].shape->data = (U8*)malloc(tag->len-1);
226                 memcpy(wfont->glyph[num].shape->data, &tag->data[1], tag->len-1);
227                 swf_DeleteTag(tag);
228
229                 /* fix bounding box */
230                 SHAPE2*shape2;
231                 SRECT bbox;
232                 shape2 = swf_ShapeToShape2(shape);
233                 if(!shape2) { fprintf(stderr, "Shape parse error\n");exit(1);}
234                 bbox = swf_GetShapeBoundingBox(shape2);
235                 swf_Shape2Free(shape2);
236                 wfont->layout->bounds[num] = bbox;
237                 //wfont->glyph[num].advance = (int)(width/6.4); // 128/20
238                 wfont->glyph[num].advance = bbox.xmax/20;
239                 if(!wfont->glyph[num].advance) {
240                     wfont->glyph[num].advance = firstx;
241                 }
242                 
243                 num++;
244             }
245         }
246     }
247     return wfont;
248 }
249
250 int main(int argc, char ** argv)
251 {
252   char cwd[128];
253   getcwd(cwd, 128);
254   processargs(argc, argv);
255   if(!all && !filenum) {
256       fprintf(stderr, "You must supply a filename.\n");
257       exit(1);
258   }
259   //TODO: use tempnam here. Check if environment already contains a
260   //T1LIB_CONFIG.
261   putenv( "T1LIB_CONFIG=/tmp/t1lib.config.tmp");
262   FILE*fi = fopen("/tmp/t1lib.config.tmp", "wb");
263   if(all) {
264       fprintf(fi, "FONTDATABASE=/tmp/FontDataBase\n");
265       fprintf(fi, "ENCODING=%s/fonts:.\n", SWFTOOLS_DATADIR);
266       fprintf(fi, "AFM=%s/fonts:.\n", SWFTOOLS_DATADIR);
267       fprintf(fi, "TYPE1=%s/fonts:.\n", SWFTOOLS_DATADIR);
268   } else {
269       fprintf(fi, "FONTDATABASE=/tmp/FontDataBase\n");
270       fprintf(fi, "ENCODING=%s:.\n", cwd);
271       fprintf(fi, "AFM=%s:.\n", cwd);
272       fprintf(fi, "TYPE1=%s:.\n", cwd);
273   }
274   fclose(fi);
275   fi = fopen("/tmp/FontDataBase", "wb");
276   if(all) {
277       fprintf(fi, "14\n");             
278       fprintf(fi, "%s/fonts/n021003l.afm\n", SWFTOOLS_DATADIR);
279       fprintf(fi, "%s/fonts/n021023l.afm\n", SWFTOOLS_DATADIR);
280       fprintf(fi, "%s/fonts/n021004l.afm\n", SWFTOOLS_DATADIR);
281       fprintf(fi, "%s/fonts/n021024l.afm\n", SWFTOOLS_DATADIR);
282       fprintf(fi, "%s/fonts/n019003l.afm\n", SWFTOOLS_DATADIR);
283       fprintf(fi, "%s/fonts/n019023l.afm\n", SWFTOOLS_DATADIR);
284       fprintf(fi, "%s/fonts/n019004l.afm\n", SWFTOOLS_DATADIR);
285       fprintf(fi, "%s/fonts/n019024l.afm\n", SWFTOOLS_DATADIR);
286       fprintf(fi, "%s/fonts/n022003l.afm\n", SWFTOOLS_DATADIR);
287       fprintf(fi, "%s/fonts/n022023l.afm\n", SWFTOOLS_DATADIR);
288       fprintf(fi, "%s/fonts/n022004l.afm\n", SWFTOOLS_DATADIR);
289       fprintf(fi, "%s/fonts/n022024l.afm\n", SWFTOOLS_DATADIR);
290       fprintf(fi, "%s/fonts/s050000l.afm\n", SWFTOOLS_DATADIR);
291       fprintf(fi, "%s/fonts/d050000l.afm\n", SWFTOOLS_DATADIR);
292   } else {
293     fprintf(fi, "%d\n", filenum);
294     int t;
295     for(t=0;t<filenum;t++) {
296         fprintf(fi, "%s/%s\n", cwd, filenames[t]);
297     }
298   }
299   fclose(fi);
300   /* initialize t1lib */
301   T1_SetBitmapPad( 16);
302   if ((T1_InitLib(NO_LOGFILE)==NULL)){
303       fprintf(stderr, "Initialization of t1lib failed\n");
304       exit(1);
305   }
306   unlink("/tmp/t1lib.config.tmp");
307
308   int i,num;
309   for( i=0; i<T1_Get_no_fonts(); i++)
310   {
311     SWFFONT * font = t1font2swffont(i);
312     
313     char filename[128];
314     sprintf(filename, "%s.swf", font->name);
315     swf_WriteFont(font, filename);
316     swf_FontFree(font);
317   }
318   unlink("/tmp/FontDataBase");
319 }
320
321