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