mingw fixes
[swftools.git] / pdf2swf / ttf2pt1 / ttf2pt1.c
1 /*
2  * True Type Font to Adobe Type 1 font converter 
3  * By Mark Heath <mheath@netspace.net.au> 
4  * Based on ttf2pfa by Andrew Weeks <ccsaw@bath.ac.uk> 
5  * With help from Frank M. Siegert <fms@this.net> 
6  *
7  * see COPYRIGHT
8  *
9 ***********************************************************************
10  *
11  * Sergey Babkin <babkin@users.sourceforge.net>, <sab123@hotmail.com>
12  *
13  * Added post-processing of resulting outline to correct the errors
14  * both introduced during conversion and present in the original font,
15  * autogeneration of hints (has yet to be improved though) and BlueValues,
16  * scaling to 1000x1000 matrix, option to print the result on STDOUT,
17  * support of Unicode to CP1251 conversion, optimization  of the
18  * resulting font code by space (that improves the speed too). Excluded
19  * the glyphs that are unaccessible through the encoding table from
20  * the output file. Added the built-in Type1 assembler (taken from
21  * the `t1utils' package).
22  *
23 ***********************************************************************
24  *
25  * Thomas Henlich <thenlich@rcs.urz.tu-dresden.de>
26  *
27  * Added generation of .afm file (font metrics)
28  * Read encoding information from encoding description file
29  * Fixed bug in error message about unknown language ('-l' option)
30  * Added `:' after %%!PS-AdobeFont-1.0
31  * changed unused entries in ISOLatin1Encoding[] from .notdef to c127,c128...
32  *
33 ***********************************************************************
34  *
35  * Thomas Henlich <thenlich@rcs.urz.tu-dresden.de>
36  *
37  * Added generation of .afm file (font metrics)
38  *
39 ***********************************************************************
40  *
41  * Bug Fixes: 
42 ************************************************************************
43  *
44  * Sun, 21 Jun 1998 Thomas Henlich <thenlich@Rcs1.urz.tu-dresden.de> 
45  * 1. "width" should be "short int" because otherwise: 
46  *     characters with negative widths (e.g. -4) become *very* wide (65532) 
47  * 2. the number of /CharStrings is numglyphs and not numglyphs+1 
48  *
49 ***********************************************************************
50  *
51  *
52  *
53  * The resultant font file produced by this program still needs to be ran
54  * through t1asm (from the t1utils archive) to produce a completely valid
55  * font. 
56  *
57  */
58 #include <stdio.h>
59 #include <stdlib.h>
60 #include <string.h>
61 #include <sys/types.h>
62 #include <sys/stat.h>
63 #include <fcntl.h>
64 #include <time.h>
65 #include <ctype.h>
66 #include <math.h>
67
68 #ifdef _GNU_SOURCE
69 #include <getopt.h>
70 #endif
71
72 #ifndef WIN32
73 #       include <unistd.h>
74 #       include <netinet/in.h>
75 #       define BITBUCKET "/dev/null"
76 #       include <sys/wait.h>
77 #else
78 #       define WINDOWS_FUNCTIONS /* ask to define functions - in one file only */
79 #       include "win_missing.h"
80 #       define BITBUCKET "NUL"
81 #endif
82
83 #include "pt1.h"
84 #include "global.h"
85 #include "version.h"
86
87 /* globals */
88
89 /* table of front-ends */
90
91 extern struct frontsw ttf_sw;
92 #if defined(USE_FREETYPE)
93         extern struct frontsw freetype_sw;
94 #endif
95
96 struct frontsw *frontswtab[] = {
97 #if defined(USE_FREETYPE) && defined(PREFER_FREETYPE)
98         &freetype_sw,
99 #endif
100         &ttf_sw,
101 #if defined(USE_FREETYPE) && !defined(PREFER_FREETYPE)
102         &freetype_sw,
103 #endif
104         NULL /* end of table */
105 };
106
107 struct frontsw *cursw=0; /* the active front end */
108 char *front_arg=""; /* optional argument */
109
110 /* options */
111 int      encode = 0;    /* encode the resulting file */
112 int      pfbflag = 0;   /* produce compressed file */
113 int      wantafm=0;     /* want to see .afm instead of .t1a on stdout */
114 int      correctvsize=0;        /* try to correct the vertical size of characters */
115 int      wantuid = 0;   /* user wants UniqueID entry in the font */
116 int      allglyphs = 0; /* convert all glyphs, not only 256 of them */
117 int      warnlevel = -1;        /* the level of permitted warnings */
118 int      forcemap = 0; /* do mapping even on non-Unicode fonts */
119 /* options - maximal limits */
120 int      max_stemdepth = 128;   /* maximal depth of stem stack in interpreter (128 - limit from X11) */
121 /* options - debugging */
122 int      absolute = 0;  /* print out in absolute values */
123 int      reverse = 1;   /* reverse font to Type1 path directions */
124 /* options - suboptions of Outline Processing, defaults are set in table */
125 int      optimize;      /* enables space optimization */
126 int      smooth;        /* enable smoothing of outlines */
127 int      transform;     /* enables transformation to 1000x1000 matrix */
128 int      hints; /* enables autogeneration of hints */
129 int      subhints;      /* enables autogeneration of substituted hints */
130 int      trybold;       /* try to guess whether the font is bold */
131 int      correctwidth;  /* try to correct the character width */
132
133 /* not quite options to select a particular source encoding */
134 int      force_pid = -1; /* specific platform id */
135 int      force_eid = -1; /* specific encoding id */
136
137 /* table of Outline Processing (may think also as Optimization) options */
138 static struct {
139         char disbl; /* character to disable - enforced lowercase */
140         char enbl;  /* character to enable - auto-set as toupper(disbl) */
141         int *valp; /* pointer to the actual variable containing value */
142         int  dflt; /* default value */
143         char *descr; /* description */
144 } opotbl[] = {
145         { 'b', 0/*auto-set*/, &trybold, 1, "guessing of the ForceBold hint" },
146         { 'h', 0/*auto-set*/, &hints, 1, "autogeneration of hints" },
147         { 'u', 0/*auto-set*/, &subhints, 1, "hint substitution technique" },
148         { 'o', 0/*auto-set*/, &optimize, 1, "space optimization of font files" },
149         { 's', 0/*auto-set*/, &smooth, 1, "smoothing and repair of outlines" },
150         { 't', 0/*auto-set*/, &transform, 1, "auto-scaling to the standard matrix 1000x1000" },
151         { 'w', 0/*auto-set*/, &correctwidth, 0, "correct the glyph widths (use only for buggy fonts)" },
152 };
153
154 int      debug = DEBUG; /* debugging flag */
155
156 FILE    *pfa_file, *afm_file;
157 int      numglyphs;
158 struct font_metrics fontm;
159
160 /* non-globals */
161 static char    *strUID = 0;     /* user-supplied UniqueID */
162 static unsigned long numUID;    /* auto-generated UniqueID */
163
164 static int      ps_fmt_3 = 0;
165 static double   scale_factor, original_scale_factor;
166
167 static char     *glyph_rename[ENCTABSZ];
168
169 /* the names assigned if the original font
170  * does not specify any
171  */
172
173 static char    *Fmt3Encoding[256] = {
174         "c0", "c1", "c2", "c3",
175         "c4", "c5", "c6", "c7",
176         "c8", "c9", "c10", "c11",
177         "c12", "CR", "c14", "c15",
178         "c16", "c17", "c18", "c19",
179         "c20", "c21", "c22", "c23",
180         "c24", "c25", "c26", "c27",
181         "c28", "c29", "c30", "c31",
182         "space", "exclam", "quotedbl", "numbersign",
183         "dollar", "percent", "ampersand", "quotesingle",
184         "parenleft", "parenright", "asterisk", "plus",
185         "comma", "hyphen", "period", "slash",
186         "zero", "one", "two", "three",
187         "four", "five", "six", "seven",
188         "eight", "nine", "colon", "semicolon",
189         "less", "equal", "greater", "question",
190         "at", "A", "B", "C",
191         "D", "E", "F", "G",
192         "H", "I", "J", "K",
193         "L", "M", "N", "O",
194         "P", "Q", "R", "S",
195         "T", "U", "V", "W",
196         "X", "Y", "Z", "bracketleft",
197         "backslash", "bracketright", "asciicircum", "underscore",
198         "grave", "a", "b", "c",
199         "d", "e", "f", "g",
200         "h", "i", "j", "k",
201         "l", "m", "n", "o",
202         "p", "q", "r", "s",
203         "t", "u", "v", "w",
204         "x", "y", "z", "braceleft",
205         "bar", "braceright", "asciitilde", "c127",
206         "c128", "c129", "quotesinglbase", "florin",
207         "quotedblbase", "ellipsis", "dagger", "daggerdbl",
208         "circumflex", "perthousand", "Scaron", "guilsinglleft",
209         "OE", "c141", "c142", "c143",
210         "c144", "quoteleft", "quoteright", "quotedblleft",
211         "quotedblright", "bullet", "endash", "emdash",
212         "tilde", "trademark", "scaron", "guilsinglright",
213         "oe", "c157", "c158", "Ydieresis",
214         "nbspace", "exclamdown", "cent", "sterling",
215         "currency", "yen", "brokenbar", "section",
216         "dieresis", "copyright", "ordfeminine", "guillemotleft",
217         "logicalnot", "sfthyphen", "registered", "macron",
218         "degree", "plusminus", "twosuperior", "threesuperior",
219         "acute", "mu", "paragraph", "periodcentered",
220         "cedilla", "onesuperior", "ordmasculine", "guillemotright",
221         "onequarter", "onehalf", "threequarters", "questiondown",
222         "Agrave", "Aacute", "Acircumflex", "Atilde",
223         "Adieresis", "Aring", "AE", "Ccedilla",
224         "Egrave", "Eacute", "Ecircumflex", "Edieresis",
225         "Igrave", "Iacute", "Icircumflex", "Idieresis",
226         "Eth", "Ntilde", "Ograve", "Oacute",
227         "Ocircumflex", "Otilde", "Odieresis", "multiply",
228         "Oslash", "Ugrave", "Uacute", "Ucircumflex",
229         "Udieresis", "Yacute", "Thorn", "germandbls",
230         "agrave", "aacute", "acircumflex", "atilde",
231         "adieresis", "aring", "ae", "ccedilla",
232         "egrave", "eacute", "ecircumflex", "edieresis",
233         "igrave", "iacute", "icircumflex", "idieresis",
234         "eth", "ntilde", "ograve", "oacute",
235         "ocircumflex", "otilde", "odieresis", "divide",
236         "oslash", "ugrave", "uacute", "ucircumflex",
237         "udieresis", "yacute", "thorn", "ydieresis"
238 };
239
240 #ifdef notdef /* { */
241 /* This table is not used anywhere in the code
242  * so it's ifdef-ed out by default but left in
243  * the source code for reference purposes (and
244  * possibly for future use)
245  */
246
247 static char    *ISOLatin1Encoding[256] = {
248         ".null", ".notdef", ".notdef", ".notdef",
249         ".notdef", ".notdef", ".notdef", ".notdef",
250         ".notdef", ".notdef", ".notdef", ".notdef",
251         ".notdef", "CR", ".notdef", ".notdef",
252         ".notdef", ".notdef", ".notdef", ".notdef",
253         ".notdef", ".notdef", ".notdef", ".notdef",
254         ".notdef", ".notdef", ".notdef", ".notdef",
255         ".notdef", ".notdef", ".notdef", ".notdef",
256         "space", "exclam", "quotedbl", "numbersign",
257         "dollar", "percent", "ampersand", "quoteright",
258         "parenleft", "parenright", "asterisk", "plus",
259         "comma", "hyphen", "period", "slash",
260         "zero", "one", "two", "three",
261         "four", "five", "six", "seven",
262         "eight", "nine", "colon", "semicolon",
263         "less", "equal", "greater", "question",
264         "at", "A", "B", "C",
265         "D", "E", "F", "G",
266         "H", "I", "J", "K",
267         "L", "M", "N", "O",
268         "P", "Q", "R", "S",
269         "T", "U", "V", "W",
270         "X", "Y", "Z", "bracketleft",
271         "backslash", "bracketright", "asciicircum", "underscore",
272         "grave", "a", "b", "c",
273         "d", "e", "f", "g",
274         "h", "i", "j", "k",
275         "l", "m", "n", "o",
276         "p", "q", "r", "s",
277         "t", "u", "v", "w",
278         "x", "y", "z", "braceleft",
279         "bar", "braceright", "asciitilde", "c127",
280         "c128", "c129", "quotesinglbase", "florin",
281         "quotedblbase", "ellipsis", "dagger", "daggerdbl",
282         "circumflex", "perthousand", "Scaron", "guilsinglleft",
283         "OE", "c141", "c142", "c143",
284         "c144", "quoteleft", "quoteright", "quotedblleft",
285         "quotedblright", "bullet", "endash", "emdash",
286         "tilde", "trademark", "scaron", "guilsinglright",
287         "oe", "c157", "c158", "Ydieresis",
288         "nbspace", "exclamdown", "cent", "sterling",
289         "currency", "yen", "brokenbar", "section",
290         "dieresis", "copyright", "ordfeminine", "guillemotleft",
291         "logicalnot", "sfthyphen", "registered", "macron",
292         "degree", "plusminus", "twosuperior", "threesuperior",
293         "acute", "mu", "paragraph", "periodcentered",
294         "cedilla", "onesuperior", "ordmasculine", "guillemotright",
295         "onequarter", "onehalf", "threequarters", "questiondown",
296         "Agrave", "Aacute", "Acircumflex", "Atilde",
297         "Adieresis", "Aring", "AE", "Ccedilla",
298         "Egrave", "Eacute", "Ecircumflex", "Edieresis",
299         "Igrave", "Iacute", "Icircumflex", "Idieresis",
300         "Eth", "Ntilde", "Ograve", "Oacute",
301         "Ocircumflex", "Otilde", "Odieresis", "multiply",
302         "Oslash", "Ugrave", "Uacute", "Ucircumflex",
303         "Udieresis", "Yacute", "Thorn", "germandbls",
304         "agrave", "aacute", "acircumflex", "atilde",
305         "adieresis", "aring", "ae", "ccedilla",
306         "egrave", "eacute", "ecircumflex", "edieresis",
307         "igrave", "iacute", "icircumflex", "idieresis",
308         "eth", "ntilde", "ograve", "oacute",
309         "ocircumflex", "otilde", "odieresis", "divide",
310         "oslash", "ugrave", "uacute", "ucircumflex",
311         "udieresis", "yacute", "thorn", "ydieresis"
312 };
313
314 #endif /* } notdef */
315
316 static char    *adobe_StandardEncoding[256] = {
317         ".notdef", ".notdef", ".notdef", ".notdef",
318         ".notdef", ".notdef", ".notdef", ".notdef",
319         ".notdef", ".notdef", ".notdef", ".notdef",
320         ".notdef", ".notdef", ".notdef", ".notdef",
321         ".notdef", ".notdef", ".notdef", ".notdef",
322         ".notdef", ".notdef", ".notdef", ".notdef",
323         ".notdef", ".notdef", ".notdef", ".notdef",
324         ".notdef", ".notdef", ".notdef", ".notdef",
325         "space", "exclam", "quotedbl", "numbersign",
326         "dollar", "percent", "ampersand", "quoteright",
327         "parenleft", "parenright", "asterisk", "plus",
328         "comma", "hyphen", "period", "slash",
329         "zero", "one", "two", "three",
330         "four", "five", "six", "seven",
331         "eight", "nine", "colon", "semicolon",
332         "less", "equal", "greater", "question",
333         "at", "A", "B", "C", "D", "E", "F", "G",
334         "H", "I", "J", "K", "L", "M", "N", "O",
335         "P", "Q", "R", "S", "T", "U", "V", "W",
336         "X", "Y", "Z", "bracketleft",
337         "backslash", "bracketright", "asciicircum", "underscore",
338         "quoteleft", "a", "b", "c", "d", "e", "f", "g",
339         "h", "i", "j", "k", "l", "m", "n", "o",
340         "p", "q", "r", "s", "t", "u", "v", "w",
341         "x", "y", "z", "braceleft",
342         "bar", "braceright", "asciitilde", ".notdef",
343         ".notdef", ".notdef", ".notdef", ".notdef",
344         ".notdef", ".notdef", ".notdef", ".notdef",
345         ".notdef", ".notdef", ".notdef", ".notdef",
346         ".notdef", ".notdef", ".notdef", ".notdef",
347         ".notdef", ".notdef", ".notdef", ".notdef",
348         ".notdef", ".notdef", ".notdef", ".notdef",
349         ".notdef", ".notdef", ".notdef", ".notdef",
350         ".notdef", ".notdef", ".notdef", ".notdef",
351         ".notdef", "exclamdown", "cent", "sterling",
352         "fraction", "yen", "florin", "section",
353         "currency", "quotesingle", "quotedblleft", "guillemotleft",
354         "guilsinglleft", "guilsinglright", "fi", "fl",
355         ".notdef", "endash", "dagger", "daggerdbl",
356         "periodcentered", ".notdef", "paragraph", "bullet",
357         "quotesinglbase", "quotedblbase", "quotedblright", "guillemotright",
358         "ellipsis", "perthousand", ".notdef", "questiondown",
359         ".notdef", "grave", "acute", "circumflex",
360         "tilde", "macron", "breve", "dotaccent",
361         "dieresis", ".notdef", "ring", "cedilla",
362         ".notdef", "hungarumlaut", "ogonek", "caron",
363         "emdash", ".notdef", ".notdef", ".notdef",
364         ".notdef", ".notdef", ".notdef", ".notdef",
365         ".notdef", ".notdef", ".notdef", ".notdef",
366         ".notdef", ".notdef", ".notdef", ".notdef",
367         ".notdef", "AE", ".notdef", "ordfeminine",
368         ".notdef", ".notdef", ".notdef", ".notdef",
369         "Lslash", "Oslash", "OE", "ordmasculine",
370         ".notdef", ".notdef", ".notdef", ".notdef",
371         ".notdef", "ae", ".notdef", ".notdef",
372         ".notdef", "dotlessi", ".notdef", ".notdef",
373         "lslash", "oslash", "oe", "germandbls",
374         ".notdef", ".notdef", ".notdef", ".notdef"
375 };
376
377 /*
378  * Decription of the supported conversions from Unicode
379  *
380  * SB
381  * Yes, I know that the compiled-in conversion is stupid but
382  * it is simple to implement and allows not to worry about the
383  * filesystem context. After all, the source is always available
384  * and adding another language to it is easy.
385  *
386  * The language name is expected to be the same as the subdirectory name 
387  * in the `encodings' directory (for possible future extensions). 
388  * The primary use of the aliases is for guessing based on the current 
389  * locale.
390  */
391
392 #define MAXUNIALIAS 10
393 #define MAXUNITABLES 3
394
395 /* the character used as the language argument separator */
396 #define LANG_ARG_SEP '+'
397
398
399 /*
400  * Types of language-related routines. Arguments are:
401  * name is the glyph name
402  * arg is the user-specified language-dependent argument
403  *   which can for example select the subfont plane for Eastern fonts.
404  *   If none is supplied by user then an empty string ("") is passed.
405  *   If no language is specified by user and auto-guessing happens
406  *   then NULL is passed.
407  * when shows if the conversion by name was called before conversion by
408  *   map or after (it's called twice)
409  */
410
411 /* type of the Unicode map initialization routine */
412 typedef void uni_init_t(char *arg);
413
414 /* type of Unicode converter-by-name function
415  * it's called for each glyph twice: one time for each glyph
416  * before doing conversion by map and one time after
417  */
418 typedef int uni_conv_t(char *name, char *arg, int when);
419 #define UNICONV_BYNAME_BEFORE 0
420 #define UNICONV_BYNAME_AFTER 1
421
422 struct uni_language {
423         uni_init_t      *init[MAXUNITABLES]; /* map initialization routines */
424         uni_conv_t      *convbyname; /* the name-based conversion function */
425         char *name; /* the language name */
426         char *descr; /* description */
427         char *alias[MAXUNIALIAS]; /* aliases of the language name */
428         int sample_upper; /* code of some uppercase character for correctvsize() */
429 };
430
431 /* the converter routines have an option of adding this suffix to the font name */
432 static char *uni_font_name_suffix = ""; /* empty by default */
433 /* this buffer may be used to store the suffix */
434 #define UNI_MAX_SUFFIX_LEN      100
435 static char uni_suffix_buf[UNI_MAX_SUFFIX_LEN+1];
436
437 /*
438  * Prototypes of the conversion routines
439  */
440
441 static uni_init_t unicode_latin1;
442 static uni_init_t unicode_latin2;
443 static uni_init_t unicode_latin4;
444 static uni_init_t unicode_latin5;
445 static uni_init_t unicode_cyrillic;
446 static uni_init_t unicode_adobestd;
447 static uni_init_t unicode_plane;
448 static uni_conv_t unicode_adobestd_byname;
449
450 static uni_init_t unicode_init_user;
451
452 /*
453  * The order of descriptions is important: if we can't guess the
454  * language we just call all the conversion routines in order until
455  * we find one that understands this glyph.
456  */
457 static struct uni_language uni_lang[]= {
458         /* pseudo-language for all the languages using Latin1 */
459         {
460                 { unicode_latin1 },
461                 0, /* no name-based mapping */
462                 "latin1",
463                 "works for most of the Western languages",
464                 { "en_", "de_", "fr_", "nl_", "no_", "da_", "it_" },
465                 'A'
466         },
467         { /* by Szalay Tamas <tomek@elender.hu> */
468                 { unicode_latin2 },
469                 0, /* no name-based mapping */
470                 "latin2",
471                 "works for Central European languages",
472                 { "hu_","pl_","cz_","si_","sk_" },
473                 'A'
474         },
475         { /* by Rièardas Ãˆepas <rch@WriteMe.Com> */
476                 { unicode_latin4 }, 
477                 0, /* no name-based mapping */
478                 "latin4",
479                 "works for Baltic languages",
480                 { "lt_", "lv_" }, /* doubt about ee_ */
481                 'A'
482         },
483         { /* by Turgut Uyar <uyar@cs.itu.edu.tr> */
484                 { unicode_latin5 }, 
485                 0, /* no name-based mapping */
486                 "latin5",
487                 "for Turkish",
488                 { "tr_" },
489                 'A'
490         },
491         { /* by Zvezdan Petkovic <z.petkovic@computer.org> */
492                 { unicode_cyrillic, unicode_latin1 },
493                 0, /* no name-based mapping */
494                 "cyrillic",
495                 "in Windows encoding",
496                 { "bg_", "be_", "mk_", "ru_", "sr_", "su_", "uk_" },
497                 'A'
498         },
499         {
500                 { unicode_cyrillic, unicode_latin1 },
501                 0, /* no name-based mapping */
502                 "russian",
503                 "obsolete, use cyrillic instead",
504                 { 0 },
505                 'A'
506         },
507         {
508                 { unicode_cyrillic, unicode_latin1 },
509                 0, /* no name-based mapping */
510                 "bulgarian",
511                 "obsolete, use cyrillic instead",
512                 { 0 },
513                 'A'
514         },
515         {
516                 { unicode_adobestd },
517                 unicode_adobestd_byname,
518                 "adobestd",
519                 "Adobe Standard, expected by TeX",
520                 { NULL },
521                 'A'
522         },
523         {
524                 { unicode_plane },
525                 0, /* no name-based mapping */
526                 "plane",
527                 "one plane of Unicode or other multi-byte encoding as is",
528                 { NULL },
529                 0 /* no easy way to predict the capital letters */
530         },
531 };
532
533 static struct uni_language uni_lang_user = {
534         { unicode_init_user }, 
535         0, /* no name-based mapping */
536         0, /* no name */
537         0, /* no description */
538         { 0 },
539         0 /* no sample */
540 };
541
542 static struct uni_language *uni_lang_selected=0; /* 0 means "unknown, try all" */
543 static int uni_sample='A'; /* sample of an uppercase character */
544 static char *uni_lang_arg=""; /* user-supplied language-dependent argument */
545
546 extern int      runt1asm(int);
547
548 /*
549  * user-defined loadable maps
550  */
551
552
553 /* The idea begind buckets is to avoid comparing every code with all ENCTABSZ codes in table.
554  * All the 16-bit unicode space is divided between a number of equal-sized buckets.
555  * Initially all the buckets are marked with 0. Then if any code in the bucket is
556  * used it's marked with 1. Later during translation we check the code's bucket first
557  * and it it's 0 then return failure right away. This may be useful for
558  * Chinese fonts with many thousands of glyphs.
559  */
560
561 #define BUCKET_ID_BITS  11
562 #define MARK_UNI_BUCKET(unicode) SET_BITMAP(uni_user_buckets, (unicode)>>(16-BUCKET_ID_BITS))
563 #define IS_UNI_BUCKET(unicode) IS_BITMAP(uni_user_buckets, (unicode)>>(16-BUCKET_ID_BITS))
564
565 static DEF_BITMAP(uni_user_buckets, 1<<BUCKET_ID_BITS);
566
567 static unsigned int unicode_map[ENCTABSZ]; /* font-encoding to unicode map */
568 static int enctabsz = 256; /* actual number of codes used */
569
570 static void
571 unicode_init_user(
572                  char *path
573 )
574 {
575         FILE           *unicode_map_file;
576 #define UNIBFSZ 256
577         char            buffer[UNIBFSZ];
578         unsigned        code, unicode, curpos, unicode2;
579         char           *arg, *p;
580         int             enabled, found, sawplane;
581         int             lineno, cnt, n, nchars;
582         char            next;
583         int             pid, eid, overid=0;
584
585         /* check if we have an argument (plane name) */
586         arg = strrchr(path, LANG_ARG_SEP);
587         if(arg != 0) {
588                 *arg++ = 0;
589                 if( sscanf(arg, "pid=%d,eid=%d%n", &pid, &eid, &nchars) == 2 ) {
590                         force_pid = pid; force_eid = eid; overid = 1;
591                         WARNING_1 fprintf(stderr, "User override of the source encoding: pid=%d eid=%d\n", pid, eid);
592                         forcemap = 1;
593                         arg += nchars;
594                         if(*arg == ',')
595                                 arg++;
596                 }
597                 if( *arg == 0 || strlen(arg) > UNI_MAX_SUFFIX_LEN-1) 
598                         arg = NULL;
599                 else {
600                         sprintf(uni_suffix_buf, "-%s", arg);
601                         uni_font_name_suffix = uni_suffix_buf;
602                 }
603         } 
604
605         /* now read in the encoding description file, if requested */
606         if ((unicode_map_file = fopen(path, "r")) == NULL) {
607                 fprintf(stderr, "**** Cannot access map file '%s' ****\n", path);
608                 exit(1);
609         }
610
611         sawplane = 0;
612         if(arg==NULL)
613                 enabled = found = 1;
614         else
615                 enabled = found = 0;
616
617         lineno=0; curpos=0;
618         while (fgets (buffer, UNIBFSZ, unicode_map_file) != NULL) {
619                 char name[UNIBFSZ];
620
621                 lineno++;
622
623                 if(sscanf(buffer, "plane %s", name)==1) {
624                         sawplane = 1;
625                         if(arg == 0) {
626                                 fprintf(stderr, "**** map file '%s' requires plane name\n", path);
627                                 fprintf(stderr, "for example:\n");
628                                 fprintf(stderr, "  ttf2pt1 -L %s%c[pid=N,eid=N,]%s ...\n", 
629                                         path, LANG_ARG_SEP, name);
630                                 fprintf(stderr, "to select plane '%s'\n", name);
631                                 exit(1);
632                         }
633                         if( !strcmp(arg, name) ) {
634                                 enabled = found = 1; 
635                                 curpos = 0;
636                         } else {
637                                 enabled = 0;
638                                 if(found) /* no need to read further */
639                                         break;
640                         }
641                         continue;
642                 }
643
644                 if(sscanf(buffer, "id %d %d", pid, eid)==2) {
645                         if( !overid /* only if the user has not overriden */
646                         && (enabled || !sawplane) ) { 
647                                 force_pid = pid; force_eid = eid;
648                                 forcemap = 1;
649                         }
650                         continue;
651                 }
652
653                 if( !enabled )
654                         continue; /* skip to the next plane */
655
656                 if( sscanf(buffer, "at %i", &curpos) == 1 ) {
657                         if(curpos > 255) {
658                                 fprintf(stderr, "**** map file '%s' line %d: code over 255\n", path, lineno);
659                                 exit(1);
660                         }
661                         if(ISDBG(EXTMAP)) fprintf(stderr, "=== at 0x%x\n", curpos);
662                         continue;
663                 }
664
665                 /* try the format of Roman Czyborra's files */
666                 if ( sscanf (buffer, " =%x U+%4x", &code, &unicode) == 2
667                 /* try the format of Linux locale charmap file */
668                 || sscanf (buffer, " <%*s /x%x <U%4x>", &code, &unicode) == 2 ) {
669                         if (code < ENCTABSZ) {
670                                 if(code >= enctabsz) enctabsz=code+1;
671                                 unicode_map[code] = unicode;
672                                 glyph_rename[code] = NULL;
673                         }
674                 }
675                 /* try the format with glyph renaming */
676                 else if (sscanf (buffer, " !%x U+%4x %128s", &code,
677                         &unicode, name) == 3) {
678                         if (code < ENCTABSZ) {
679                                 if(code >= enctabsz) enctabsz=code+1;
680                                 unicode_map[code] = unicode;
681                                 glyph_rename[code] = strdup(name);
682                         }
683                 }
684                 /* try the compact sequence format */
685                 else if( (n=sscanf(buffer, " %i%n", &unicode, &cnt)) == 1 ) {
686                         p = buffer;
687                         do {
688                                 if(curpos > 255) {
689                                         fprintf(stderr, "**** map file '%s' line %d: code over 255 for unicode 0x%x\n", 
690                                                 path, lineno, unicode);
691                                         exit(1);
692                                 }
693                                 if(ISDBG(EXTMAP)) fprintf(stderr, "=== 0x%d -> 0x%x\n", curpos, unicode);
694                                 unicode_map[curpos++] = unicode;
695                                 p += cnt;
696                                 if( sscanf(p, " %[,-]%n", &next,&cnt) == 1 ) {
697                                         if(ISDBG(EXTMAP)) fprintf(stderr, "=== next: '%c'\n", next);
698                                         p += cnt;
699                                         if( next == '-' ) { /* range */
700                                                 if ( sscanf(p, " %i%n", &unicode2, &cnt) != 1 ) {
701                                                         fprintf(stderr, "**** map file '%s' line %d: missing end of range\n", path, lineno);
702                                                         exit(1);
703                                                 }
704                                                 p += cnt;
705                                                 if(ISDBG(EXTMAP)) fprintf(stderr, "=== range 0x%x to 0x%x\n", unicode, unicode2);
706                                                 for(unicode++; unicode <= unicode2; unicode++) {
707                                                         if(curpos > 255) {
708                                                                 fprintf(stderr, "**** map file '%s' line %d: code over 255 in unicode range ...-0x%x\n", 
709                                                                         path, lineno, unicode2);
710                                                                 exit(1);
711                                                         }
712                                                         if(ISDBG(EXTMAP)) fprintf(stderr, "=== 0x%x -> 0x%x\n", curpos, unicode);
713                                                         unicode_map[curpos++] = unicode;
714                                                 }
715                                         }
716                                 }
717                         } while ( sscanf(p, " %i%n", &unicode, &cnt) == 1 );
718                 }
719
720         }
721
722         fclose (unicode_map_file);
723
724         if( !found ) {
725                 fprintf(stderr, "**** map file '%s' has no plane '%s'\n", path, arg);
726                 exit(1);
727         }
728
729         if(unicode_map['A'] == 'A')
730                 uni_sample = 'A'; /* seems to be compatible with Latin */
731         else
732                 uni_sample = 0; /* don't make any assumptions */
733 }
734
735 /*
736  * by Zvezdan Petkovic <z.petkovic@computer.org> 
737  */
738 static void
739 unicode_cyrillic(
740                  char *arg
741 )
742 {
743         int i;
744         static unsigned int cyrillic_unicode_map[] = {
745                 0x0402, 0x0403, 0x201a, 0x0453, 0x201e, 0x2026, 0x2020, 0x2021,  /* 80 */
746                 0x20ac, 0x2030, 0x0409, 0x2039, 0x040a, 0x040c, 0x040b, 0x040f,  /* 88 */
747                 0x0452, 0x2018, 0x2019, 0x201c, 0x201d, 0x2022, 0x2013, 0x2014,  /* 90 */
748                 0x02dc, 0x2122, 0x0459, 0x203a, 0x045a, 0x045c, 0x045b, 0x045f,  /* 98 */
749                 0x00a0, 0x040e, 0x045e, 0x0408, 0x00a4, 0x0490, 0x00a6, 0x00a7,  /* A0 */
750                 0x0401, 0x00a9, 0x0404, 0x00ab, 0x00ac, 0x00ad, 0x00ae, 0x0407,  /* A8 */
751                 0x00b0, 0x00b1, 0x0406, 0x0456, 0x0491, 0x00b5, 0x00b6, 0x00b7,  /* B0 */
752                 0x0451, 0x2116, 0x0454, 0x00bb, 0x0458, 0x0405, 0x0455, 0x0457,  /* B8 */
753         };
754
755         for(i=0; i<=0x7F; i++)
756                 unicode_map[i] = i;
757
758         for(i=0x80; i<=0xBF; i++)
759                 unicode_map[i] = cyrillic_unicode_map[i-0x80];
760
761         for(i=0xC0; i<=0xFF; i++)
762                 unicode_map[i] = i+0x350;
763
764 }
765
766 static void
767 unicode_latin1(
768                  char *arg
769 )
770 {
771         int i;
772         static unsigned int latin1_unicode_map[] = {
773                 0x20ac,     -1, 0x201a, 0x0192, 0x201e, 0x2026, 0x2020, 0x2021,  /* 80 */
774                 0x02c6, 0x2030, 0x0160, 0x2039, 0x0152, 0x008d, 0x017d, 0x008f,  /* 88 */
775                 0x0090, 0x2018, 0x2019, 0x201c, 0x201d, 0x2022, 0x2013, 0x2014,  /* 90 */
776                 0x02dc, 0x2122, 0x0161, 0x203a, 0x0153, 0x009d, 0x017e, 0x0178,  /* 98 */
777         };
778
779         for(i=0; i<=0x7F; i++)
780                 unicode_map[i] = i;
781
782         for(i=0x80; i<=0x9F; i++)
783                 unicode_map[i] = latin1_unicode_map[i-0x80];
784
785         for(i=0xA0; i<=0xFF; i++)
786                 unicode_map[i] = i;
787 }
788
789 static void
790 unicode_adobestd(
791                  char *arg
792 )
793 {
794         int i;
795         static unsigned int adobestd_unicode_map[] = {
796                         -1, 0x00a1, 0x00a2, 0x00a3, 0x2215, 0x00a5, 0x0192, 0x00a7,  /* A0 */
797                 0x00a4, 0x0027, 0x201c, 0x00ab, 0x2039, 0x203a, 0xfb01, 0xfb02,  /* A8 */
798                         -1, 0x2013, 0x2020, 0x2021, 0x2219,     -1, 0x00b6, 0x2022,  /* B0 */
799                 0x201a, 0x201e, 0x201d, 0x00bb, 0x2026, 0x2030,     -1, 0x00bf,  /* B8 */
800                         -1, 0x0060, 0x00b4, 0x02c6, 0x02dc, 0x02c9, 0x02d8, 0x02d9,  /* C0 */
801                 0x00a8,     -1, 0x02da, 0x00b8,     -1, 0x02dd, 0x02db, 0x02c7,  /* C8 */
802                 0x2014,     -1,     -1,     -1,     -1,     -1,     -1,     -1,  /* D0 */
803                         -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,  /* D8 */
804                         -1, 0x00c6,     -1, 0x00aa,     -1,     -1,     -1,     -1,  /* E0 */
805                 0x0141, 0x00d8, 0x0152, 0x00ba,     -1,     -1,     -1,     -1,  /* E8 */
806                         -1, 0x00e6,     -1,     -1,     -1, 0x0131,     -1,     -1,  /* F0 */
807                 0x0142, 0x00f8, 0x0153, 0x00df,     -1,     -1,     -1,     -1,  /* F8 */
808         };
809
810         for(i=0; i<=0x7F; i++)
811                 unicode_map[i] = i;
812
813         unicode_map[0x27] = 0x2019;
814         unicode_map[0x60] = -1;
815
816         /* 0x80 to 0x9F is a hole */
817
818         for(i=0xA0; i<=0xFF; i++)
819                 unicode_map[i] = adobestd_unicode_map[i-0xA0];
820 }
821
822 /*
823  * Not all of the Adobe glyphs are in the Unicode
824  * standard maps, so the font creators have
825  * different ideas about their codes. Because
826  * of this we try to map based on the glyph
827  * names instead of Unicode codes. If there are
828  * no glyph names (ps_fmt_3!=0) we fall back
829  * to the code-based scheme.
830  */
831
832 static int
833 unicode_adobestd_byname(
834                  char *name,
835                  char *arg,
836                  int where
837 )
838 {
839         int i;
840
841         /* names always take precedence over codes */
842         if(where == UNICONV_BYNAME_AFTER)
843                 return -1;
844
845         for(i=32; i<256; i++) {
846                 if(!strcmp(name, adobe_StandardEncoding[i]))
847                         return i;
848         }
849         return -1;
850
851 }
852
853 static void
854 unicode_latin2(
855                  char *arg
856 )
857 {
858         int i;
859         static unsigned int latin2_unicode_map[] = {
860                 0x00a0, 0x0104, 0x02d8, 0x0141, 0x00a4, 0x013d, 0x015a, 0x00a7,  /* A0 */
861                 0x00a8, 0x0160, 0x015e, 0x0164, 0x0179, 0x00ad, 0x017d, 0x017b,  /* A8 */
862                 0x00b0, 0x0105, 0x02db, 0x0142, 0x00b4, 0x013e, 0x015b, 0x02c7,  /* B0 */
863                 0x00b8, 0x0161, 0x015f, 0x0165, 0x017a, 0x02dd, 0x017e, 0x017c,  /* B8 */
864                 0x0154, 0x00c1, 0x00c2, 0x0102, 0x00c4, 0x0139, 0x0106, 0x00c7,  /* C0 */
865                 0x010c, 0x00c9, 0x0118, 0x00cb, 0x011a, 0x00cd, 0x00ce, 0x010e,  /* C8 */
866                 0x0110, 0x0143, 0x0147, 0x00d3, 0x00d4, 0x0150, 0x00d6, 0x00d7,  /* D0 */
867                 0x0158, 0x016e, 0x00da, 0x0170, 0x00dc, 0x00dd, 0x0162, 0x00df,  /* D8 */
868                 0x0155, 0x00e1, 0x00e2, 0x0103, 0x00e4, 0x013a, 0x0107, 0x00e7,  /* E0 */
869                 0x010d, 0x00e9, 0x0119, 0x00eb, 0x011b, 0x00ed, 0x00ee, 0x010f,  /* E8 */
870                 0x0111, 0x0144, 0x0148, 0x00f3, 0x00f4, 0x0151, 0x00f6, 0x00f7,  /* F0 */
871                 0x0159, 0x016f, 0x00fa, 0x0171, 0x00fc, 0x00fd, 0x0163, 0x02d9,  /* F8 */
872         };
873
874         for(i=0; i<=0x7E; i++)
875                 unicode_map[i] = i;
876
877         /* 7F-9F are unused */
878
879         for(i=0xA0; i<=0xFF; i++)
880                 unicode_map[i] = latin2_unicode_map[i-0xA0];
881 }
882
883 static void
884 unicode_latin4(
885                  char *arg
886 )
887 {
888         int i;
889         static unsigned int latin4_unicode_map[] = {
890                 0x0080, 0x0081, 0x201a, 0x0192,     -1, 0x2026, 0x2020, 0x2021,  /* 80 */
891                 0x02c6, 0x2030,     -1, 0x2039, 0x0152, 0x008d, 0x008e, 0x008f,  /* 88 */
892                 0x201e, 0x201c, 0x2019,     -1, 0x201d, 0x2022, 0x2013, 0x2014,  /* 90 */
893                 0x02dc, 0x2122,     -1, 0x203a, 0x0153, 0x009d, 0x009e, 0x0178,  /* 98 */
894                 0x00a0, 0x0104, 0x0138, 0x0156, 0x00a4, 0x0128, 0x013b, 0x00a7,  /* A0 */
895                 0x00a8, 0x0160, 0x0112, 0x0122, 0x0166, 0x00ad, 0x017d, 0x00af,  /* A8 */
896                 0x00b0, 0x0105, 0x02db, 0x0157, 0x00b4, 0x0129, 0x013c, 0x02c7,  /* B0 */
897                 0x00b8, 0x0161, 0x0113, 0x0123, 0x0167, 0x014a, 0x017e, 0x014b,  /* B8 */
898                 0x0100, 0x00c1, 0x00c2, 0x00c3, 0x00c4, 0x00c5, 0x00c6, 0x012e,  /* C0 */
899                 0x010c, 0x00c9, 0x0118, 0x00cb, 0x0116, 0x00cd, 0x00ce, 0x012a,  /* C8 */
900                 0x0110, 0x0145, 0x014c, 0x0136, 0x00d4, 0x00d5, 0x00d6, 0x00d7,  /* D0 */
901                 0x00d8, 0x0172, 0x00da, 0x00db, 0x00dc, 0x0168, 0x016a, 0x00df,  /* D8 */
902                 0x0101, 0x00e1, 0x00e2, 0x00e3, 0x00e4, 0x00e5, 0x00e6, 0x012f,  /* E0 */
903                 0x010d, 0x00e9, 0x0119, 0x00eb, 0x0117, 0x00ed, 0x00ee, 0x012b,  /* E8 */
904                 0x0111, 0x0146, 0x014d, 0x0137, 0x00f4, 0x00f5, 0x00f6, 0x00f7,  /* F0 */
905                 0x00f8, 0x0173, 0x00fa, 0x00fb, 0x00fc, 0x0169, 0x016b, 0x02d9,  /* F8 */
906         };
907
908         for(i=0; i<=0x7F; i++)
909                 unicode_map[i] = i;
910
911         for(i=0x80; i<=0xFF; i++)
912                 unicode_map[i] = latin4_unicode_map[i-0x80];
913
914 #if 0 /* for documentation purposes only */
915         case 0x201e: return 0x90; /* these two quotes are a hack only */
916         case 0x201c: return 0x91; /* these two quotes are a hack only */
917         case 0x00A0: return 0xA0; /*  NO-BREAK SPACE */
918         case 0x0104: return 0xA1; /*  LATIN CAPITAL LETTER A WITH OGONEK */
919         case 0x0138: return 0xA2; /*  LATIN SMALL LETTER KRA */
920         case 0x0156: return 0xA3; /*  LATIN CAPITAL LETTER R WITH CEDILLA */
921         case 0x00A4: return 0xA4; /*  CURRENCY SIGN */
922         case 0x0128: return 0xA5; /*  LATIN CAPITAL LETTER I WITH TILDE */
923         case 0x013B: return 0xA6; /*  LATIN CAPITAL LETTER L WITH CEDILLA */
924         case 0x00A7: return 0xA7; /*  SECTION SIGN */
925         case 0x00A8: return 0xA8; /*  DIAERESIS */
926         case 0x0160: return 0xA9; /*  LATIN CAPITAL LETTER S WITH CARON */
927         case 0x0112: return 0xAA; /*  LATIN CAPITAL LETTER E WITH MACRON */
928         case 0x0122: return 0xAB; /*  LATIN CAPITAL LETTER G WITH CEDILLA */
929         case 0x0166: return 0xAC; /*  LATIN CAPITAL LETTER T WITH STROKE */
930         case 0x00AD: return 0xAD; /*  SOFT HYPHEN */
931         case 0x017D: return 0xAE; /*  LATIN CAPITAL LETTER Z WITH CARON */
932         case 0x00AF: return 0xAF; /*  MACRON */
933         case 0x00B0: return 0xB0; /*  DEGREE SIGN */
934         case 0x0105: return 0xB1; /*  LATIN SMALL LETTER A WITH OGONEK */
935         case 0x02DB: return 0xB2; /*  OGONEK */
936         case 0x0157: return 0xB3; /*  LATIN SMALL LETTER R WITH CEDILLA */
937         case 0x00B4: return 0xB4; /*  ACUTE ACCENT */
938         case 0x0129: return 0xB5; /*  LATIN SMALL LETTER I WITH TILDE */
939         case 0x013C: return 0xB6; /*  LATIN SMALL LETTER L WITH CEDILLA */
940         case 0x02C7: return 0xB7; /*  CARON */
941         case 0x00B8: return 0xB8; /*  CEDILLA */
942         case 0x0161: return 0xB9; /*  LATIN SMALL LETTER S WITH CARON */
943         case 0x0113: return 0xBA; /*  LATIN SMALL LETTER E WITH MACRON */
944         case 0x0123: return 0xBB; /*  LATIN SMALL LETTER G WITH CEDILLA */
945         case 0x0167: return 0xBC; /*  LATIN SMALL LETTER T WITH STROKE */
946         case 0x014A: return 0xBD; /*  LATIN CAPITAL LETTER ENG */
947         case 0x017E: return 0xBE; /*  LATIN SMALL LETTER Z WITH CARON */
948         case 0x014B: return 0xBF; /*  LATIN SMALL LETTER ENG */
949         case 0x0100: return 0xC0; /*  LATIN CAPITAL LETTER A WITH MACRON */
950         case 0x00C1: return 0xC1; /*  LATIN CAPITAL LETTER A WITH ACUTE */
951         case 0x00C2: return 0xC2; /*  LATIN CAPITAL LETTER A WITH CIRCUMFLEX */
952         case 0x00C3: return 0xC3; /*  LATIN CAPITAL LETTER A WITH TILDE */
953         case 0x00C4: return 0xC4; /*  LATIN CAPITAL LETTER A WITH DIAERESIS */
954         case 0x00C5: return 0xC5; /*  LATIN CAPITAL LETTER A WITH RING ABOVE */
955         case 0x00C6: return 0xC6; /*  LATIN CAPITAL LIGATURE AE */
956         case 0x012E: return 0xC7; /*  LATIN CAPITAL LETTER I WITH OGONEK */
957         case 0x010C: return 0xC8; /*  LATIN CAPITAL LETTER C WITH CARON */
958         case 0x00C9: return 0xC9; /*  LATIN CAPITAL LETTER E WITH ACUTE */
959         case 0x0118: return 0xCA; /*  LATIN CAPITAL LETTER E WITH OGONEK */
960         case 0x00CB: return 0xCB; /*  LATIN CAPITAL LETTER E WITH DIAERESIS */
961         case 0x0116: return 0xCC; /*  LATIN CAPITAL LETTER E WITH DOT ABOVE */
962         case 0x00CD: return 0xCD; /*  LATIN CAPITAL LETTER I WITH ACUTE */
963         case 0x00CE: return 0xCE; /*  LATIN CAPITAL LETTER I WITH CIRCUMFLEX */
964         case 0x012A: return 0xCF; /*  LATIN CAPITAL LETTER I WITH MACRON */
965         case 0x0110: return 0xD0; /*  LATIN CAPITAL LETTER D WITH STROKE */
966         case 0x0145: return 0xD1; /*  LATIN CAPITAL LETTER N WITH CEDILLA */
967         case 0x014C: return 0xD2; /*  LATIN CAPITAL LETTER O WITH MACRON */
968         case 0x0136: return 0xD3; /*  LATIN CAPITAL LETTER K WITH CEDILLA */
969         case 0x00D4: return 0xD4; /*  LATIN CAPITAL LETTER O WITH CIRCUMFLEX */
970         case 0x00D5: return 0xD5; /*  LATIN CAPITAL LETTER O WITH TILDE */
971         case 0x00D6: return 0xD6; /*  LATIN CAPITAL LETTER O WITH DIAERESIS */
972         case 0x00D7: return 0xD7; /*  MULTIPLICATION SIGN */
973         case 0x00D8: return 0xD8; /*  LATIN CAPITAL LETTER O WITH STROKE */
974         case 0x0172: return 0xD9; /*  LATIN CAPITAL LETTER U WITH OGONEK */
975         case 0x00DA: return 0xDA; /*  LATIN CAPITAL LETTER U WITH ACUTE */
976         case 0x00DB: return 0xDB; /*  LATIN CAPITAL LETTER U WITH CIRCUMFLEX */
977         case 0x00DC: return 0xDC; /*  LATIN CAPITAL LETTER U WITH DIAERESIS */
978         case 0x0168: return 0xDD; /*  LATIN CAPITAL LETTER U WITH TILDE */
979         case 0x016A: return 0xDE; /*  LATIN CAPITAL LETTER U WITH MACRON */
980         case 0x00DF: return 0xDF; /*  LATIN SMALL LETTER SHARP S */
981         case 0x0101: return 0xE0; /*  LATIN SMALL LETTER A WITH MACRON */
982         case 0x00E1: return 0xE1; /*  LATIN SMALL LETTER A WITH ACUTE */
983         case 0x00E2: return 0xE2; /*  LATIN SMALL LETTER A WITH CIRCUMFLEX */
984         case 0x00E3: return 0xE3; /*  LATIN SMALL LETTER A WITH TILDE */
985         case 0x00E4: return 0xE4; /*  LATIN SMALL LETTER A WITH DIAERESIS */
986         case 0x00E5: return 0xE5; /*  LATIN SMALL LETTER A WITH RING ABOVE */
987         case 0x00E6: return 0xE6; /*  LATIN SMALL LIGATURE AE */
988         case 0x012F: return 0xE7; /*  LATIN SMALL LETTER I WITH OGONEK */
989         case 0x010D: return 0xE8; /*  LATIN SMALL LETTER C WITH CARON */
990         case 0x00E9: return 0xE9; /*  LATIN SMALL LETTER E WITH ACUTE */
991         case 0x0119: return 0xEA; /*  LATIN SMALL LETTER E WITH OGONEK */
992         case 0x00EB: return 0xEB; /*  LATIN SMALL LETTER E WITH DIAERESIS */
993         case 0x0117: return 0xEC; /*  LATIN SMALL LETTER E WITH DOT ABOVE */
994         case 0x00ED: return 0xED; /*  LATIN SMALL LETTER I WITH ACUTE */
995         case 0x00EE: return 0xEE; /*  LATIN SMALL LETTER I WITH CIRCUMFLEX */
996         case 0x012B: return 0xEF; /*  LATIN SMALL LETTER I WITH MACRON */
997         case 0x0111: return 0xF0; /*  LATIN SMALL LETTER D WITH STROKE */
998         case 0x0146: return 0xF1; /*  LATIN SMALL LETTER N WITH CEDILLA */
999         case 0x014D: return 0xF2; /*  LATIN SMALL LETTER O WITH MACRON */
1000         case 0x0137: return 0xF3; /*  LATIN SMALL LETTER K WITH CEDILLA */
1001         case 0x00F4: return 0xF4; /*  LATIN SMALL LETTER O WITH CIRCUMFLEX */
1002         case 0x00F5: return 0xF5; /*  LATIN SMALL LETTER O WITH TILDE */
1003         case 0x00F6: return 0xF6; /*  LATIN SMALL LETTER O WITH DIAERESIS */
1004         case 0x00F7: return 0xF7; /*  DIVISION SIGN */
1005         case 0x00F8: return 0xF8; /*  LATIN SMALL LETTER O WITH STROKE */
1006         case 0x0173: return 0xF9; /*  LATIN SMALL LETTER U WITH OGONEK */
1007         case 0x00FA: return 0xFA; /*  LATIN SMALL LETTER U WITH ACUTE */
1008         case 0x00FB: return 0xFB; /*  LATIN SMALL LETTER U WITH CIRCUMFLEX */
1009         case 0x00FC: return 0xFC; /*  LATIN SMALL LETTER U WITH DIAERESIS */
1010         case 0x0169: return 0xFD; /*  LATIN SMALL LETTER U WITH TILDE */
1011         case 0x016B: return 0xFE; /*  LATIN SMALL LETTER U WITH MACRON */
1012         case 0x02D9: return 0xFF; /*  DOT ABOVE */
1013 #endif
1014 }
1015
1016 static void
1017 unicode_latin5(
1018                  char *arg
1019 )
1020 {
1021         int i;
1022         static unsigned int latin5_unicode_map1[] = {
1023                 0x0080, 0x0081, 0x201a, 0x0192, 0x201e, 0x2026, 0x2020, 0x2021,  /* 80 */
1024                 0x02c6, 0x2030, 0x0160, 0x2039, 0x0152, 0x008d, 0x008e, 0x008f,  /* 88 */
1025                 0x0090, 0x2018, 0x2019, 0x201c, 0x201d, 0x2022, 0x2013, 0x2014,  /* 90 */
1026                 0x02dc, 0x2122, 0x0161, 0x203a, 0x0153, 0x009d, 0x009e, 0x0178,  /* 98 */
1027         };
1028         static unsigned int latin5_unicode_map2[] = {
1029                 0x011e, 0x00d1, 0x00d2, 0x00d3, 0x00d4, 0x00d5, 0x00d6, 0x00d7,  /* D0 */
1030                 0x00d8, 0x00d9, 0x00da, 0x00db, 0x00dc, 0x0130, 0x015e, 0x00df,  /* D8 */
1031                 0x00e0, 0x00e1, 0x00e2, 0x00e3, 0x00e4, 0x00e5, 0x00e6, 0x00e7,  /* E0 direct */
1032                 0x00e8, 0x00e9, 0x00ea, 0x00eb, 0x00ec, 0x00ed, 0x00ee, 0x00ef,  /* E8 direct */
1033                 0x011f, 0x00f1, 0x00f2, 0x00f3, 0x00f4, 0x00f5, 0x00f6, 0x00f7,  /* F0 */
1034                 0x00f8, 0x00f9, 0x00fa, 0x00fb, 0x00fc, 0x0131, 0x015f, 0x00ff,  /* F8 */
1035         };
1036
1037         for(i=0; i<=0x7F; i++)
1038                 unicode_map[i] = i;
1039
1040         for(i=0x80; i<=0x9F; i++)
1041                 unicode_map[i] = latin5_unicode_map1[i-0x80];
1042
1043         for(i=0xA0; i<=0xCF; i++)
1044                 unicode_map[i] = i;
1045
1046         for(i=0xD0; i<=0xFF; i++)
1047                 unicode_map[i] = latin5_unicode_map2[i-0xD0];
1048 }
1049
1050 /* a way to select one 256-character plane from Unicode 
1051  * or other multi-byte encoding
1052  */
1053
1054 static void
1055 unicode_plane(
1056                  char *arg
1057 )
1058 {
1059         static unsigned plane;
1060         int nchars;
1061         int c1, c2, i;
1062
1063         if(uni_lang_selected == 0)
1064                 return; /* don't participate in auto-guessing */
1065
1066         plane = 0; force_pid = force_eid = -1;
1067
1068         c1 = sscanf(arg, "pid=%d,eid=%d%n", &force_pid, &force_eid, &nchars);
1069         if(c1 == 2) {
1070                 arg += nchars;
1071                 if(*arg == ',')
1072                         arg++;
1073         }
1074         if(arg[0] == '0' && (arg[1]=='x' || arg[1]=='X') ) {
1075                 arg += 2;
1076                 c2 = sscanf(arg, "%x", &plane);
1077         } else {
1078                 c2 = sscanf(arg, "%d", &plane);
1079         }
1080
1081         if( (c1!=2 && c1!=0) || (c1==0 && c2==0) ) {
1082                 fprintf(stderr, "**** option -l plane expects one of the following formats:\n");
1083                 fprintf(stderr, "  -l plane+0xNN - select hexadecimal number of plane of Unicode\n");
1084                 fprintf(stderr, "  -l plane+NN - select decimal number of plane of Unicode\n");
1085                 fprintf(stderr, "  -l plane+pid=N,eid=N - select plane 0 of specified encoding\n");
1086                 fprintf(stderr, "  -l plane+pid=N,eid=N,0xNN - select hex plane of TTF encoding with this PID/EID\n");
1087                 fprintf(stderr, "  -l plane+pid=N,eid=N,NN - select decimal plane of TTF encoding with this PID/EID\n");
1088                 exit(1);
1089         }
1090
1091         if(c2!=0) {
1092                 if(strlen(arg) > sizeof(uni_suffix_buf)-2) {
1093                         fprintf(stderr, "**** plane number is too large\n");
1094                 }
1095
1096                 sprintf(uni_suffix_buf, "-%s", arg);
1097                 uni_font_name_suffix = uni_suffix_buf;
1098         } else {
1099                 uni_font_name_suffix = "";
1100         }
1101
1102         plane <<= 8;
1103         for(i=0; i<=0xFF; i++)
1104                 unicode_map[i] = plane | i;
1105 }
1106
1107 /* look up the 8-bit code by unicode */
1108
1109 int
1110 unicode_rev_lookup(
1111                  int unival
1112 )
1113 {
1114         int res;
1115
1116         if( ! IS_UNI_BUCKET(unival) )
1117                 return -1;
1118
1119         for (res = 0; res < enctabsz; res++)
1120                 if (unicode_map[res] == unival)
1121                         return res;
1122         return -1;
1123 }
1124
1125 /* mark the buckets for quick lookup */
1126
1127 static void
1128 unicode_prepare_buckets(
1129         void
1130 )
1131 {
1132         int i;
1133
1134         memset(uni_user_buckets, 0, sizeof uni_user_buckets);
1135         for(i=0; i<enctabsz; i++) {
1136                 if(unicode_map[i] != (unsigned) -1)
1137                         MARK_UNI_BUCKET(unicode_map[i]);
1138         }
1139 }
1140
1141 /*
1142  * Scale the values according to the scale_factor
1143  */
1144
1145 double
1146 fscale(
1147       double val
1148 )
1149 {
1150         return scale_factor * val;
1151 }
1152
1153 int
1154 iscale(
1155       int val
1156 )
1157 {
1158         return (int) (val > 0 ? scale_factor * val + 0.5
1159                       : scale_factor * val - 0.5);
1160 }
1161
1162 /*
1163  * Try to force fixed width of characters
1164  */
1165
1166 static void
1167 alignwidths(void)
1168 {
1169         int             i;
1170         int             n = 0, avg, max = 0, min = 3000, sum = 0, x;
1171
1172         for (i = 0; i < numglyphs; i++) {
1173                 if (glyph_list[i].flags & GF_USED) {
1174                         x = glyph_list[i].width;
1175
1176                         if (x != 0) {
1177                                 if (x < min)
1178                                         min = x;
1179                                 if (x > max)
1180                                         max = x;
1181
1182                                 sum += x;
1183                                 n++;
1184                         }
1185                 }
1186         }
1187
1188         if (n == 0)
1189                 return;
1190
1191         avg = sum / n;
1192
1193         WARNING_3 fprintf(stderr, "widths: max=%d avg=%d min=%d\n", max, avg, min);
1194
1195         /* if less than 5% variation from average */
1196         /* force fixed width */
1197         if (20 * (avg - min) < avg && 20 * (max - avg) < avg) {
1198                 for (i = 0; i < numglyphs; i++) {
1199                         if (glyph_list[i].flags & GF_USED)
1200                                 glyph_list[i].width = avg;
1201                 }
1202                 fontm.is_fixed_pitch = 1;
1203         }
1204 }
1205
1206 static void
1207 convert_glyf(
1208         int     glyphno
1209 )
1210 {
1211         GLYPH          *g;
1212         int ncurves;
1213
1214         g = &glyph_list[glyphno];
1215
1216
1217         g->scaledwidth = iscale(g->width);
1218
1219         g->entries = 0;
1220         g->lastentry = 0;
1221         g->path = 0;
1222         if (g->ttf_pathlen != 0) {
1223                 cursw->glpath(glyphno, glyph_list);
1224                 g->lastentry = 0;
1225
1226                 if(ISDBG(BUILDG))
1227                         dumppaths(g, NULL, NULL);
1228
1229                 assertpath(g->entries, __FILE__, __LINE__, g->name);
1230
1231                 fclosepaths(g);
1232                 assertpath(g->entries, __FILE__, __LINE__, g->name);
1233
1234                 /* float processing */
1235                 if(smooth) {
1236                         ffixquadrants(g);
1237                         assertpath(g->entries, __FILE__, __LINE__, g->name);
1238
1239                         fsplitzigzags(g);
1240                         assertpath(g->entries, __FILE__, __LINE__, g->name);
1241
1242                         fforceconcise(g);
1243                         assertpath(g->entries, __FILE__, __LINE__, g->name);
1244
1245                         fstraighten(g);
1246                         assertpath(g->entries, __FILE__, __LINE__, g->name);
1247                 }
1248
1249                 pathtoint(g); 
1250                 /* all processing past this point expects integer path */
1251                 assertpath(g->entries, __FILE__, __LINE__, g->name);
1252
1253 #if 0
1254                 fixcontours(g);
1255                 testfixcvdir(g);
1256 #endif
1257
1258                 /* int processing */
1259                 if (smooth) {
1260                         smoothjoints(g);
1261                         assertpath(g->entries, __FILE__, __LINE__, g->name);
1262
1263                         flattencurves(g);
1264                 }
1265
1266                 ncurves = 0;
1267                 {
1268                         GENTRY *ge;
1269                         for(ge = g->entries; ge; ge = ge->next)
1270                                 ncurves++;
1271                 }
1272                 if (ncurves > 100) {
1273                         WARNING_2 fprintf(stderr,
1274                         "** Glyph %s is too long, may display incorrectly\n",
1275                                 g->name);
1276                 }
1277         } else {
1278                 /* for buildstems */
1279                 g->flags &= ~GF_FLOAT;
1280         }
1281 }
1282
1283 static void
1284 handle_gnames(void)
1285 {
1286         int             i, n, found, c, type;
1287
1288         /* get the names from the font file */
1289         ps_fmt_3 = cursw->glnames(glyph_list);
1290
1291         /* check for names with wrong characters */
1292         for (n = 0; n < numglyphs; n++) {
1293                 int             c;
1294                 for (i = 0; (c = glyph_list[n].name[i]) != 0; i++) {
1295                         if (!(isalnum(c) || c == '.' || c == '_' ) 
1296                         || i==0 && isdigit(c)) { /* must not start with a digit */
1297                                 WARNING_3 fprintf(stderr, "Glyph %d %s (%s), ",
1298                                         n, isdigit(c) ? "name starts with a digit" : 
1299                                                 "has bad characters in name",
1300                                         glyph_list[n].name);
1301                                 glyph_list[n].name = malloc(10);
1302                                 sprintf(glyph_list[n].name, "_%d", n);
1303                                 WARNING_3 fprintf(stderr, "changing to %s\n", glyph_list[n].name);
1304                                 break;
1305                         }
1306                 }
1307         }
1308
1309         if( !ps_fmt_3 ) {
1310                 /* check for duplicate names */
1311                 for (n = 0; n < numglyphs; n++) {
1312                         found = 0;
1313                         for (i = 0; i < n && !found; i++) {
1314                                 if (strcmp(glyph_list[i].name, glyph_list[n].name) == 0) {
1315                                         glyph_list[n].name = malloc(10);
1316                                         sprintf(glyph_list[n].name, "_%d", n);
1317                                         WARNING_3 fprintf(stderr,
1318                                                 "Glyph %d has the same name as %d: (%s), changing to %s\n",
1319                                                 n, i,
1320                                                 glyph_list[i].name,
1321                                                 glyph_list[n].name);
1322                                         found = 1;
1323                                 }
1324                         }
1325                 }
1326
1327         }
1328
1329         /* start the encoding stuff */
1330         for (i = 0; i < ENCTABSZ; i++) {
1331                 encoding[i] = -1;
1332         }
1333
1334         /* do the 1st round of encoding by name */
1335         if(!ps_fmt_3 && uni_lang_selected && uni_lang_selected->convbyname) {
1336                 for (n = 0; n < numglyphs; n++) {
1337                         c = uni_lang_selected->convbyname(glyph_list[n].name, 
1338                                 uni_lang_arg, UNICONV_BYNAME_BEFORE);
1339                         if(c>=0 && c<ENCTABSZ && encoding[c] == -1)
1340                                 encoding[c] = n;
1341                 }
1342         }
1343
1344         /* now do the encoding by table */
1345         if(uni_lang_selected) {
1346                 for(i=0; i < MAXUNITABLES && uni_lang_selected->init[i]; i++) {
1347                         for (n = 0; n < ENCTABSZ; n++)
1348                                 unicode_map[n] = -1;
1349                         uni_lang_selected->init[i](uni_lang_arg);
1350                         unicode_prepare_buckets();
1351                         if( cursw->glenc(glyph_list, encoding, unicode_map) == 0 )
1352                                 /* if we have an 8-bit encoding we don't need more tries */
1353                                 break;
1354                 }
1355         } else {
1356                 /* language is unknown, try the first table of each */
1357                 for(i=0; i < sizeof uni_lang/(sizeof uni_lang[0]); i++) {
1358                         if(uni_lang[i].init[0] == NULL)
1359                                 continue;
1360                         for (n = 0; n < ENCTABSZ; n++)
1361                                 unicode_map[n] = -1;
1362                         uni_lang[i].init[0](uni_lang_arg);
1363                         unicode_prepare_buckets();
1364                         if( cursw->glenc(glyph_list, encoding, unicode_map) == 0 )
1365                                 /* if we have an 8-bit encoding we don't need more tries */
1366                                 break;
1367                 }
1368         }
1369
1370         if (ps_fmt_3) {
1371                 for (i = 0; i < 256; i++) { /* here 256, not ENCTABSZ */
1372                         if (encoding[i] > 0) {
1373                                 glyph_list[encoding[i]].name = Fmt3Encoding[i];
1374                         }
1375                 }
1376         }
1377
1378         /* do the 2nd round of encoding by name */
1379         if(uni_lang_selected && uni_lang_selected->convbyname) {
1380                 for (n = 0; n < numglyphs; n++) {
1381                         c = uni_lang_selected->convbyname(glyph_list[n].name, 
1382                                 uni_lang_arg, UNICONV_BYNAME_AFTER);
1383                         if(c>=0 && c<ENCTABSZ && encoding[c] == -1)
1384                                 encoding[c] = n;
1385                 }
1386         }
1387         /* all the encoding things are done */
1388
1389         for (i = 0; i < ENCTABSZ; i++)
1390                 if(encoding[i] == -1) /* defaults to .notdef */
1391                         encoding[i] = 0;
1392
1393         for (i = 0; i < 256; i++) /* here 256, not ENCTABSZ */
1394                 glyph_list[encoding[i]].char_no = i;
1395
1396         /* enforce two special cases defined in TTF manual */
1397         if(numglyphs > 0)
1398                 glyph_list[0].name = ".notdef";
1399         if(numglyphs > 1)
1400                 glyph_list[1].name = ".null";
1401
1402         for (i = 0; i < ENCTABSZ; i++) {
1403                 if ((encoding[i] != 0) && glyph_rename[i]) {
1404                     glyph_list[encoding[i]].name = glyph_rename[i];
1405                 }
1406         }
1407         
1408 }
1409
1410 static void
1411 usage(void)
1412 {
1413
1414 #ifdef _GNU_SOURCE
1415 #       define fplop(txt)       fputs(txt, stderr);
1416 #else
1417 #       define fplop(txt)
1418 #endif
1419
1420         fputs("Use:\n", stderr);
1421         fputs("ttf2pt1 [-<opts>] [-l language | -L file] <ttf-file> [<fontname>]\n", stderr);
1422         fputs("  or\n", stderr);
1423         fputs("ttf2pt1 [-<opts>] [-l language | -L file] <ttf-file> -\n", stderr);
1424         fputs("  or\n", stderr);
1425         fputs("ttf2pt1 [-<opts>] [-l language | -L file] <ttf-file> - | t1asm > <pfa-file>\n", stderr);
1426
1427         fplop("\n");
1428         fplop("This build supports both short and long option names,\n");
1429         fplop("the long options are listed before corresponding short ones\n");
1430
1431         fplop(" --afm\n");
1432         fputs("  -A - write the .afm file to STDOUT instead of the font itself\n", stderr);
1433         fplop(" --all-glyphs\n");
1434         fputs("  -a - include all glyphs, even those not in the encoding table\n", stderr);
1435         fplop(" --pfb\n");
1436         fputs("  -b - produce a compressed .pfb file\n", stderr);
1437         fplop(" --debug dbg_suboptions\n");
1438         fputs("  -d dbg_suboptions - debugging options, run ttf2pt1 -d? for help\n", stderr);
1439         fplop(" --encode\n");
1440         fputs("  -e - produce a fully encoded .pfa file\n", stderr);
1441         fplop(" --force-unicode\n");
1442         fputs("  -F - force use of Unicode encoding even if other MS encoding detected\n", stderr); 
1443         fplop(" --language language\n");
1444         fputs("  -l language - convert Unicode to specified language, run ttf2pt1 -l? for list\n", stderr);
1445         fplop(" --language-map file\n");
1446         fputs("  -L file - convert Unicode according to encoding description file\n", stderr);
1447         fplop(" --limit <type>=<value>\n");
1448         fputs("  -m <type>=<value> - set maximal limit of given type to value, types:\n", stderr);
1449         fputs("      h - maximal hint stack depth in the PostScript interpreter\n", stderr);
1450         fplop(" --processing suboptions\n");
1451         fputs("  -O suboptions - control outline processing, run ttf2pt1 -O? for help\n", stderr);
1452         fplop(" --parser name\n");
1453         fputs("  -p name - use specific front-end parser, run ttf2pt1 -p? for list\n", stderr);
1454         fplop(" --uid id\n");
1455         fputs("  -u id - use this UniqueID, -u A means autogeneration\n", stderr);
1456         fplop(" --vertical-autoscale size\n");
1457         fputs("  -v size - scale the font to make uppercase letters >size/1000 high\n", stderr);
1458         fplop(" --version\n");
1459         fputs("  -V - print ttf2pt1 version number\n", stderr);
1460         fplop(" --warning number\n");
1461         fputs("  -W number - set the level of permitted warnings (0 - disable)\n", stderr);
1462         fputs("Obsolete options (will be removed in future releases, use -O? instead):\n", stderr);
1463         fputs("  -f - don't try to guess the value of the ForceBold hint\n", stderr);
1464         fputs("  -h - disable autogeneration of hints\n", stderr);
1465         fputs("  -H - disable hint substitution\n", stderr);
1466         fputs("  -o - disable outline optimization\n", stderr);
1467         fputs("  -s - disable outline smoothing\n", stderr);
1468         fputs("  -t - disable auto-scaling to 1000x1000 standard matrix\n", stderr);
1469         fputs("  -w - correct the glyph widths (use only for buggy fonts)\n", stderr);
1470         fputs("With no <fontname>, write to <ttf-file> with suffix replaced.\n", stderr);
1471         fputs("The last '-' means 'use STDOUT'.\n", stderr);
1472
1473 #undef fplop
1474
1475 }
1476
1477 static void
1478 printversion(void)
1479 {
1480   fprintf(stderr, "ttf2pt1 %s\n", TTF2PT1_VERSION);
1481 }
1482   
1483 int
1484 ttf2pt1_main(
1485      int argc,
1486      char **argv
1487 )
1488 {
1489         int             i, j;
1490         time_t          now;
1491         char            filename[256];
1492         int             c,nchars,nmetrics;
1493         int             ws;
1494         int             forcebold= -1; /* -1 means "don't know" */
1495         char           *lang;
1496         int             oc;
1497         int             subid;
1498 #ifdef _GNU_SOURCE
1499 #       define ttf2pt1_getopt(a, b, c, d, e)    getopt_long(a, b, c, d, e)
1500         static struct option longopts[] = {
1501                 { "afm", 0, NULL, 'A' },
1502                 { "all-glyphs", 0, NULL, 'a' },
1503                 { "pfb", 0, NULL, 'b' },
1504                 { "debug", 1, NULL, 'd' },
1505                 { "encode", 0, NULL, 'e' },
1506                 { "force-unicode", 0, NULL, 'F' },
1507                 { "language", 1, NULL, 'l' },
1508                 { "language-map", 1, NULL, 'L' },
1509                 { "limit", 1, NULL, 'm' },
1510                 { "processing", 1, NULL, 'O' },
1511                 { "parser", 1, NULL, 'p' },
1512                 { "uid", 1, NULL, 'u' },
1513                 { "vertical-autoscale", 1, NULL, 'v' },
1514                 { "version", 0, NULL, 'V' },
1515                 { "warning", 1, NULL, 'W' },
1516                 { NULL, 0, NULL, 0 }
1517         };
1518 #else
1519 #       define ttf2pt1_getopt(a, b, c, d, e)    getopt(a, b, c)
1520 #endif
1521
1522         /* initialize sub-options of -O */
1523         for(i=0; i< (sizeof opotbl)/(sizeof opotbl[0]); i++) {
1524                 opotbl[i].disbl = tolower(opotbl[i].disbl);
1525                 opotbl[i].enbl = toupper(opotbl[i].disbl);
1526                 *(opotbl[i].valp) = opotbl[i].dflt;
1527         }
1528
1529         while(( oc=ttf2pt1_getopt(argc, argv, "FaoebAsthHfwVv:p:l:d:u:L:m:W:O:",
1530                         longopts, NULL) )!= -1) {
1531                 switch(oc) {
1532                 case 'F':
1533                         forcemap = 1;
1534                         break;
1535                 case 'o':
1536                         fputs("Warning: option -o is obsolete, use -Oo instead\n", stderr);
1537                         optimize = 0;
1538                         break;
1539                 case 'e':
1540                         encode = 1;
1541                         break;
1542                 case 'b':
1543                         encode = pfbflag = 1;
1544                         break;
1545                 case 'A':
1546                         wantafm = 1;
1547                         break;
1548                 case 'a':
1549                         allglyphs = 1;
1550                         break;
1551                 case 's':
1552                         fputs("Warning: option -s is obsolete, use -Os instead\n", stderr);
1553                         smooth = 0;
1554                         break;
1555                 case 't':
1556                         fputs("Warning: option -t is obsolete, use -Ot instead\n", stderr);
1557                         transform = 0;
1558                         break;
1559                 case 'd':
1560                         for(i=0; optarg[i]!=0; i++)
1561                                 switch(optarg[i]) {
1562                                 case 'a':
1563                                         absolute = 1;
1564                                         break;
1565                                 case 'r':
1566                                         reverse = 0;
1567                                         break;
1568                                 default:
1569                                         if (optarg[i] != '?')
1570                                           fprintf(stderr, "**** Unknown debugging option '%c' ****\n", optarg[i]);
1571                                         fputs("The recognized debugging options are:\n", stderr);
1572                                         fputs("  a - enable absolute coordinates\n", stderr);
1573                                         fputs("  r - do not reverse font outlines directions\n", stderr);
1574                                         exit(1);
1575                                         break;
1576                                 };
1577                         break;
1578                 case 'm':
1579                 {
1580                         char subopt;
1581                         int val;
1582
1583                         if(sscanf(optarg, "%c=%d", &subopt, &val) !=2) {
1584                                 fprintf(stderr, "**** Misformatted maximal limit ****\n");
1585                                 fprintf(stderr, "spaces around the equal sign are not allowed\n");
1586                                 fprintf(stderr, "good examples: -mh=100 -m h=100\n");
1587                                 fprintf(stderr, "bad examples: -mh = 100 -mh= 100\n");
1588                                 exit(1);
1589                                 break;
1590                         }
1591                         switch(subopt) {
1592                         case 'h':
1593                                 max_stemdepth = val;
1594                                 break;
1595                         default:
1596                                 if (subopt != '?')
1597                                   fprintf(stderr, "**** Unknown limit type '%c' ****\n", subopt);
1598                                 fputs("The recognized limit types are:\n", stderr);
1599                                 fputs("  h - maximal hint stack depth in the PostScript interpreter\n", stderr);
1600                                 exit(1);
1601                                 break;
1602                         }
1603                         break;
1604                 }
1605                 case 'O':
1606                 {
1607                         char subopt;
1608                         char *p;
1609                         char dflt[20]; /* should be big enough */
1610                         for(p=optarg; (subopt = *p) != 0; p++) {
1611                                 for(i=0; i< (sizeof opotbl)/(sizeof opotbl[0]); i++) {
1612                                         if(subopt == opotbl[i].disbl) {
1613                                                 *(opotbl[i].valp) = 0;
1614                                                 break;
1615                                         } else if(subopt == opotbl[i].enbl) {
1616                                                 *(opotbl[i].valp) = 1;
1617                                                 break;
1618                                         } 
1619                                 }
1620                                 if( i == (sizeof opotbl)/(sizeof opotbl[0]) ) { /* found no match */
1621                                         if (subopt != '?')
1622                                                 fprintf(stderr, "**** Unknown outline processing suboption '%c' ****\n", subopt);
1623                                         fprintf(stderr,"The general form of the outline processing option is:\n");
1624                                         fprintf(stderr,"   -O suboptions\n");
1625                                         fprintf(stderr,"(To remember easily -O may be also thought of as \"optimization\").\n");
1626                                         fprintf(stderr,"The lowercase suboptions disable features, corresponding\n");
1627                                         fprintf(stderr,"uppercase suboptions enable them. The supported suboptions,\n");
1628                                         fprintf(stderr,"their default states and the features they control are:\n");
1629                                         p = dflt;
1630                                         for(i=0; i< (sizeof opotbl)/(sizeof opotbl[0]); i++) {
1631                                                 fprintf(stderr,"   %c/%c - [%s] %s\n", opotbl[i].disbl, opotbl[i].enbl,
1632                                                         opotbl[i].dflt ? "enabled" : "disabled", opotbl[i].descr);
1633                                                 if(opotbl[i].dflt)
1634                                                         *p++ = opotbl[i].enbl;
1635                                                 else
1636                                                         *p++ = opotbl[i].disbl;
1637                                         }
1638                                         *p = 0;
1639                                         fprintf(stderr, "The default state corresponds to the option -O %s\n", dflt);
1640                                         exit(1);
1641                                 }
1642                         }
1643                         break;
1644                 }
1645                 case 'h':
1646                         fputs("Warning: option -h is obsolete, use -Oh instead\n", stderr);
1647                         hints = 0;
1648                         break;
1649                 case 'H':
1650                         fputs("Warning: meaning of option -H has been changed to its opposite\n", stderr);
1651                         fputs("Warning: option -H is obsolete, use -Ou instead\n", stderr);
1652                         subhints = 0;
1653                         break;
1654                 case 'f':
1655                         fputs("Warning: option -f is obsolete, use -Ob instead\n", stderr);
1656                         trybold = 0;
1657                         break;
1658                 case 'w':
1659                         fputs("Warning: option -w is obsolete, use -OW instead\n", stderr);
1660                         correctwidth = 1;
1661                         break;
1662                 case 'u':
1663                         if(wantuid) {
1664                                 fprintf(stderr, "**** UniqueID may be specified only once ****\n");
1665                                 exit(1);
1666                         }
1667                         wantuid = 1; 
1668                         if(optarg[0]=='A' && optarg[1]==0)
1669                                 strUID=0; /* will be generated automatically */
1670                         else {
1671                                 strUID=optarg;
1672                                 for(i=0; optarg[i]!=0; i++)
1673                                         if( !isdigit(optarg[i]) ) {
1674                                                 fprintf(stderr, "**** UniqueID must be numeric or A for automatic ****\n");
1675                                                 exit(1);
1676                                         }
1677                         }
1678                         break;
1679                 case 'v':
1680                         correctvsize = atoi(optarg);
1681                         if(correctvsize <= 0 && correctvsize > 1000) {
1682                                 fprintf(stderr, "**** wrong vsize '%d', ignored ****\n", correctvsize);
1683                                 correctvsize=0;
1684                         }
1685                         break;
1686                 case 'p':
1687                         if(cursw!=0) {
1688                                 fprintf(stderr, "**** only one front-end parser be used ****\n");
1689                                 exit(1);
1690                         }
1691
1692                         { /* separate parser from parser-specific argument */
1693                                 char *p = strchr(optarg, LANG_ARG_SEP);
1694                                 if(p != 0) {
1695                                         *p = 0;
1696                                         front_arg = p+1;
1697                                 } else
1698                                         front_arg = "";
1699                         }
1700                         for(i=0; frontswtab[i] != NULL; i++)
1701                                 if( !strcmp(frontswtab[i]->name, optarg) ) {
1702                                         cursw = frontswtab[i];
1703                                         break;
1704                                 }
1705
1706                         if(cursw==0) {
1707                                 if (strcmp(optarg, "?"))
1708                                   fprintf(stderr, "**** unknown front-end parser '%s' ****\n", optarg);
1709                                 fputs("the following front-ends are supported now:\n", stderr);
1710                                 for(i=0; frontswtab[i] != NULL; i++) {
1711                                         fprintf(stderr,"  %s (%s)\n   file suffixes: ", 
1712                                                 frontswtab[i]->name,
1713                                                 frontswtab[i]->descr ? frontswtab[i]->descr : "no description"
1714                                         );
1715                                         for(j=0; j<MAXSUFFIX; j++)
1716                                                 if(frontswtab[i]->suffix[j])
1717                                                         fprintf(stderr, "%s ", frontswtab[i]->suffix[j]);
1718                                         fprintf(stderr, "\n");
1719                                 }
1720                                 exit(1);
1721                         }
1722                         break;
1723                 case 'l':
1724                         if(uni_lang_selected!=0) {
1725                                 fprintf(stderr, "**** only one language option may be used ****\n");
1726                                 exit(1);
1727                         }
1728
1729                         { /* separate language from language-specific argument */
1730                                 char *p = strchr(optarg, LANG_ARG_SEP);
1731                                 if(p != 0) {
1732                                         *p = 0;
1733                                         uni_lang_arg = p+1;
1734                                 } else
1735                                         uni_lang_arg = "";
1736                         }
1737                         for(i=0; i < sizeof uni_lang/(sizeof uni_lang[0]); i++)
1738                                 if( !strcmp(uni_lang[i].name, optarg) ) {
1739                                         uni_lang_selected = &uni_lang[i];
1740                                         uni_sample = uni_lang[i].sample_upper;
1741                                         break;
1742                                 }
1743
1744                         if(uni_lang_selected==0) {
1745                                 if (strcmp(optarg, "?"))
1746                                         fprintf(stderr, "**** unknown language '%s' ****\n", optarg);
1747                                 fputs("       the following languages are supported now:\n", stderr);
1748                                 for(i=0; i < sizeof uni_lang/(sizeof uni_lang[0]); i++)
1749                                         fprintf(stderr,"         %s (%s)\n", 
1750                                                 uni_lang[i].name,
1751                                                 uni_lang[i].descr ? uni_lang[i].descr : "no description"
1752                                         );
1753                                 exit(1);
1754                         }
1755                         break;
1756                 case 'L':
1757                         if(uni_lang_selected!=0) {
1758                                 fprintf(stderr, "**** only one language option may be used ****\n");
1759                                 exit(1);
1760                         }
1761                         uni_lang_selected = &uni_lang_user;
1762                         uni_lang_arg = optarg;
1763                         break;
1764                 case 'V':
1765                         printversion();
1766                         exit(0);
1767                         break;
1768                 default:
1769                         usage();
1770                         exit(1);
1771                         break;
1772                 }
1773         }
1774         argc-=optind-1; /* the rest of code counts from argv[0] */
1775         argv+=optind-1;
1776
1777         if (absolute && encode) {
1778                 fprintf(stderr, "**** options -a and -e are incompatible ****\n");
1779                 exit(1);
1780         }
1781         if ((argc != 2) && (argc != 3)) {
1782                 usage();
1783                 exit(1);
1784         }
1785
1786         /* try to guess the language by the locale used */
1787         if(uni_lang_selected==0 && (lang=getenv("LANG"))!=0 ) {
1788                 for(i=0; i < sizeof uni_lang/sizeof(struct uni_language); i++) {
1789                         if( !strncmp(uni_lang[i].name, lang, strlen(uni_lang[i].name)) ) {
1790                                 uni_lang_selected = &uni_lang[i];
1791                                 goto got_a_language;
1792                         }
1793                 }
1794                 /* no full name ? try aliases */
1795                 for(i=0; i < sizeof uni_lang/sizeof(struct uni_language); i++) {
1796                         for(c=0; c<MAXUNIALIAS; c++)
1797                                 if( uni_lang[i].alias[c]!=0
1798                                 && !strncmp(uni_lang[i].alias[c], lang, strlen(uni_lang[i].alias[c])) ) {
1799                                         uni_lang_selected = &uni_lang[i];
1800                                         goto got_a_language;
1801                                 }
1802                 }
1803         got_a_language:
1804                 if(uni_lang_selected!=0) {
1805                         WARNING_1 fprintf(stderr, "Using language '%s' for Unicode fonts\n", uni_lang[i].name);
1806                         uni_sample = uni_lang[i].sample_upper;
1807                 }
1808         }
1809
1810         /* try to guess the front-end parser by the file name suffix */
1811         if(cursw==0) {
1812                 char *p = strrchr(argv[1], '.');
1813                 char *s;
1814
1815                 if(p!=0 && (s = strdup(p+1))!=0) {
1816                         for(p=s; *p; p++)
1817                                 *p = tolower(*p);
1818                         p = s;
1819
1820                         for(i=0; frontswtab[i] != 0 && cursw == 0; i++) {
1821                                 for(j=0; j<MAXSUFFIX; j++)
1822                                         if(frontswtab[i]->suffix[j]
1823                                         && !strcmp(p, frontswtab[i]->suffix[j]) ) {
1824                                                 cursw = frontswtab[i];
1825                                                 WARNING_1 fprintf(stderr, "Auto-detected front-end parser '%s'\n",
1826                                                         cursw->name);
1827                                                 WARNING_1 fprintf(stderr, " (use ttf2pt1 -p? to get the full list of available front-ends)\n");
1828                                                 break;
1829                                         }
1830                         }
1831                         free(s);
1832                 }
1833
1834                 if(cursw==0) {
1835                         cursw = frontswtab[0];
1836                         WARNING_1 fprintf(stderr, "Can't detect front-end parser, using '%s' by default\n", 
1837                                 cursw->name);
1838                         WARNING_1 fprintf(stderr, " (use ttf2pt1 -p? to get the full list of available front-ends)\n");
1839                 }
1840         }
1841
1842         /* open the input file */
1843         cursw->open(argv[1], front_arg);
1844
1845         /* Get base name of output file (if not specified)
1846          * by removing (known) suffixes
1847          */
1848         if (argc == 2) {
1849                 char *p;
1850                 argv[2] = strdup (argv[1]);
1851                 p = strrchr(argv[2], '.');
1852                 if (p != NULL)
1853                   for (j = 0; (j < MAXSUFFIX) && (cursw->suffix[j]); j++)
1854                     if (!strcmp(p+1, cursw->suffix[j])) {
1855                       *p = '\0';
1856                       break;
1857                     }
1858         }
1859
1860         if (argv[2][0] == '-' && argv[2][1] == 0) {
1861                 pfa_file = stdout;
1862 #ifdef WIN32
1863                 if(encode) {
1864                         fprintf(stderr, "**** can't write encoded file to stdout ***\n");
1865                         exit(1);
1866                 }
1867 #endif /* WINDOWS */
1868                 if ((afm_file = fopen(BITBUCKET, "w+")) == NULL) {
1869                         fprintf(stderr, "**** Cannot open %s ****\n",
1870                                 BITBUCKET);
1871                         exit(1);
1872                 }
1873                 if(wantafm) { /* print .afm instead of .pfa */
1874                         FILE *n;
1875                         n=pfa_file;
1876                         pfa_file=afm_file;
1877                         afm_file=n;
1878                 }
1879         } else {
1880 #ifndef WIN32
1881                 sprintf(filename, "%s.%s", argv[2], encode ? (pfbflag ? "pfb" : "pfa") : "t1a" );
1882 #else /* WINDOWS */
1883                 sprintf(filename, "%s.t1a", argv[2]);
1884 #endif /* WINDOWS */
1885                 if ((pfa_file = fopen(filename, "w+b")) == NULL) {
1886                         fprintf(stderr, "**** Cannot create %s ****\n", filename);
1887                         exit(1);
1888                 } else {
1889                         WARNING_2 fprintf(stderr, "Creating file %s\n", filename);
1890                 }
1891
1892                 sprintf(filename, "%s.afm", argv[2]) ;
1893                 if ((afm_file = fopen(filename, "w+")) == NULL) {
1894                         fprintf(stderr, "**** Cannot create %s ****\n", filename);
1895                         exit(1);
1896                 }
1897         }
1898
1899         /*
1900          * Now check whether we want a fully encoded .pfa file
1901          */
1902 #ifndef WIN32
1903         if (encode) {
1904                 int             p[2];
1905                 extern FILE    *ifp, *ofp;      /* from t1asm.c */
1906
1907                 ifp=stdin;
1908                 ofp=stdout;
1909
1910                 if (pipe(p) < 0) {
1911                         perror("**** Cannot create pipe ****\n");
1912                         exit(1);
1913                 }
1914                 ofp = pfa_file;
1915                 ifp = fdopen(p[0], "r");
1916                 if (ifp == NULL) {
1917                         perror("**** Cannot use pipe for reading ****\n");
1918                         exit(1);
1919                 }
1920                 pfa_file = fdopen(p[1], "w");
1921                 if (pfa_file == NULL) {
1922                         perror("**** Cannot use pipe for writing ****\n");
1923                         exit(1);
1924                 }
1925                 switch (fork()) {
1926                 case -1:
1927                         perror("**** Cannot fork the assembler process ****\n");
1928                         exit(1);
1929                 case 0: /* child */
1930                         fclose(pfa_file);
1931                         exit(runt1asm(pfbflag));
1932                 default: /* parent */
1933                         fclose(ifp); fclose(ofp);
1934                 }
1935         }
1936 #endif /* WINDOWS */
1937
1938         numglyphs = cursw->nglyphs();
1939
1940         WARNING_3 fprintf(stderr, "numglyphs = %d\n", numglyphs);
1941
1942         glyph_list = (GLYPH *) calloc(numglyphs,  sizeof(GLYPH));
1943
1944         /* initialize non-0 fields */
1945         for (i = 0; i < numglyphs; i++) {
1946                 GLYPH *g;
1947
1948                 g = &glyph_list[i];
1949                 g->char_no = -1;
1950                 g->orig_code = -1;
1951                 g->name = "UNKNOWN";
1952                 g->flags = GF_FLOAT; /* we start with float representation */
1953         }
1954
1955         handle_gnames();
1956
1957         cursw->glmetrics(glyph_list);
1958         cursw->fnmetrics(&fontm);
1959  
1960         original_scale_factor = 1000.0 / (double) fontm.units_per_em;
1961
1962         if(transform == 0)
1963                 scale_factor = 1.0; /* don't transform */
1964         else
1965                 scale_factor = original_scale_factor;
1966
1967         if(correctvsize && uni_sample!=0) { /* only for known languages */
1968                 /* try to adjust the scale factor to make a typical
1969                  * uppercase character of hight at least (correctvsize), this
1970                  * may improve the appearance of the font but also
1971                  * make it weird, use with caution
1972                  */
1973                 int ysz;
1974
1975                 ysz = iscale(glyph_list[encoding[uni_sample]].yMax);
1976                 if( ysz<correctvsize ) {
1977                         scale_factor *= (double)correctvsize / ysz;
1978                 }
1979         }
1980
1981         if(allglyphs) {
1982                 for (i = 0; i < numglyphs; i++) {
1983                         glyph_list[i].flags |= GF_USED;
1984                 }
1985         } else {
1986                 for (i = 0; i < ENCTABSZ; i++) {
1987                         glyph_list[encoding[i]].flags |= GF_USED;
1988                 }
1989
1990                 /* also always include .notdef */
1991                 for (i = 0; i < numglyphs; i++) 
1992                         if(!strcmp(glyph_list[i].name, ".notdef")) {
1993                                 glyph_list[i].flags |= GF_USED;
1994                                 break;
1995                         }
1996         }
1997
1998         for (i = 0; i < numglyphs; i++) {
1999                 if (glyph_list[i].flags & GF_USED) {
2000                         DBG_TO_GLYPH(&glyph_list[i]);
2001                         convert_glyf(i);
2002                         DBG_FROM_GLYPH(&glyph_list[i]);
2003                 }
2004         }
2005
2006         italic_angle = fontm.italic_angle;
2007
2008         if (italic_angle > 45.0 || italic_angle < -45.0)
2009                 italic_angle = 0.0;     /* consider buggy */
2010
2011         if (hints) {
2012                 findblues();
2013                 for (i = 0; i < numglyphs; i++) {
2014                         if (glyph_list[i].flags & GF_USED) {
2015                                 DBG_TO_GLYPH(&glyph_list[i]);
2016                                 buildstems(&glyph_list[i]);
2017                                 assertpath(glyph_list[i].entries, __FILE__, __LINE__, glyph_list[i].name);
2018                                 DBG_FROM_GLYPH(&glyph_list[i]);
2019                         }
2020                 }
2021                 stemstatistics();
2022         } else {
2023                 for(i=0; i<4; i++)
2024                         bbox[i] = iscale(fontm.bbox[i]);
2025         }
2026         /* don't touch the width of fixed width fonts */
2027         if( fontm.is_fixed_pitch )
2028                 correctwidth=0;
2029         docorrectwidth(); /* checks correctwidth inside */
2030         if (reverse)
2031                 for (i = 0; i < numglyphs; i++) {
2032                         if (glyph_list[i].flags & GF_USED) {
2033                                 DBG_TO_GLYPH(&glyph_list[i]);
2034                                 reversepaths(&glyph_list[i]);
2035                                 assertpath(glyph_list[i].entries, __FILE__, __LINE__, glyph_list[i].name);
2036                                 DBG_FROM_GLYPH(&glyph_list[i]);
2037                         }
2038                 }
2039
2040
2041 #if 0
2042         /*
2043         ** It seems to bring troubles. The problem is that some
2044         ** styles of the font may be recognized as fixed-width
2045         ** while other styles of the same font as proportional.
2046         ** So it's better to be commented out yet.
2047         */
2048         if (tryfixed) 
2049                 alignwidths();
2050 #endif
2051
2052         if(trybold) {
2053                 forcebold = fontm.force_bold;
2054         }
2055
2056         fprintf(pfa_file, "%%!PS-AdobeFont-1.0: %s %s\n", fontm.name_ps, fontm.name_copyright);
2057         time(&now);
2058         fprintf(pfa_file, "%%%%CreationDate: %s", ctime(&now));
2059         fprintf(pfa_file, "%% Converted from TrueType font %s by ttf2pt1 %s/%s\n%%\n", argv[1], TTF2PT1_VERSION, cursw->name);
2060         fprintf(pfa_file, "%%%%EndComments\n");
2061         fprintf(pfa_file, "12 dict begin\n/FontInfo 9 dict dup begin\n");
2062
2063         WARNING_3 fprintf(stderr, "FontName %s%s\n", fontm.name_ps, uni_font_name_suffix);
2064
2065
2066         fprintf(pfa_file, "/version (%s) readonly def\n", fontm.name_version);
2067
2068         fprintf(pfa_file, "/Notice (%s) readonly def\n", fontm.name_copyright);
2069
2070         fprintf(pfa_file, "/FullName (%s) readonly def\n", fontm.name_full);
2071         fprintf(pfa_file, "/FamilyName (%s) readonly def\n", fontm.name_family);
2072
2073         if(wantuid) {
2074                 if(strUID)
2075                         fprintf(pfa_file, "/UniqueID %s def\n", strUID);
2076                 else {
2077                         numUID=0;
2078                         for(i=0; fontm.name_full[i]!=0; i++) {
2079                                 numUID *= 37; /* magic number, good for hash */
2080                                 numUID += fontm.name_full[i]-' ';
2081                                 /* if the name is long the first chars
2082                                  * may be lost forever, so re-insert
2083                                  * them thus making kind of CRC
2084                                  */
2085                                 numUID += (numUID>>24) & 0xFF;
2086                         }
2087                         /* the range for private UIDs is 4 000 000 - 4 999 999 */
2088                         fprintf(pfa_file, "/UniqueID %lu def\n", numUID%1000000+4000000);
2089                 }
2090         }
2091
2092         fprintf(pfa_file, "/Weight (%s) readonly def\n", fontm.name_style);
2093
2094         fprintf(pfa_file, "/ItalicAngle %f def\n", italic_angle);
2095         fprintf(pfa_file, "/isFixedPitch %s def\n",
2096                 fontm.is_fixed_pitch ? "true" : "false");
2097
2098         /* we don't print out the unused glyphs */
2099         nchars = 0;
2100         for (i = 0; i < numglyphs; i++) {
2101                 if (glyph_list[i].flags & GF_USED) {
2102                         nchars++;
2103                 }
2104         }
2105
2106     fprintf(afm_file, "StartFontMetrics 4.1\n");
2107     fprintf(afm_file, "FontName %s%s\n", fontm.name_ps, uni_font_name_suffix);
2108     fprintf(afm_file, "FullName %s\n", fontm.name_full);
2109     fprintf(afm_file, "Notice %s\n", fontm.name_copyright);
2110     fprintf(afm_file, "EncodingScheme FontSpecific\n");
2111     fprintf(afm_file, "FamilyName %s\n", fontm.name_family);
2112     fprintf(afm_file, "Weight %s\n", fontm.name_style);
2113     fprintf(afm_file, "Version %s\n", fontm.name_version);
2114     fprintf(afm_file, "Characters %d\n", nchars);
2115     fprintf(afm_file, "ItalicAngle %.1f\n", italic_angle);
2116
2117     fprintf(afm_file, "Ascender %d\n", iscale(fontm.ascender));
2118     fprintf(afm_file, "Descender %d\n", iscale(fontm.descender));
2119
2120         fprintf(pfa_file, "/UnderlinePosition %d def\n",
2121                 iscale(fontm.underline_position));
2122
2123         fprintf(pfa_file, "/UnderlineThickness %hd def\nend readonly def\n",
2124                 iscale(fontm.underline_thickness));
2125
2126         fprintf(afm_file, "UnderlineThickness %d\n",
2127                 iscale(fontm.underline_thickness));
2128
2129         fprintf(afm_file, "UnderlinePosition %d\n",
2130                 iscale(fontm.underline_position));
2131
2132     fprintf(afm_file, "IsFixedPitch %s\n",
2133                 fontm.is_fixed_pitch ? "true" : "false");
2134     fprintf(afm_file, "FontBBox %d %d %d %d\n",
2135                 bbox[0], bbox[1], bbox[2], bbox[3]);
2136
2137         fprintf(pfa_file, "/FontName /%s%s def\n", fontm.name_ps, uni_font_name_suffix);
2138         fprintf(pfa_file, "/PaintType 0 def\n/StrokeWidth 0 def\n");
2139         /* I'm not sure if these are fixed */
2140         fprintf(pfa_file, "/FontType 1 def\n");
2141
2142         if (transform) {
2143                 fprintf(pfa_file, "/FontMatrix [0.001 0 0 0.001 0 0] def\n");
2144         } else {
2145                 fprintf(pfa_file, "/FontMatrix [%9.7f 0 0 %9.7f 0 0] def\n",
2146                         original_scale_factor / 1000.0, original_scale_factor / 1000.0);
2147         }
2148
2149         fprintf(pfa_file, "/FontBBox {%d %d %d %d} readonly def\n",
2150                 bbox[0], bbox[1], bbox[2], bbox[3]);
2151
2152         fprintf(pfa_file, "/Encoding 256 array\n");
2153         /* determine number of elements for metrics table */
2154         nmetrics = 256;
2155         for (i = 0; i < numglyphs; i++) {
2156                 if( glyph_list[i].flags & GF_USED 
2157                 && glyph_list[i].char_no == -1 ) {
2158                         nmetrics++;
2159                 }
2160         }
2161         fprintf(afm_file, "StartCharMetrics %d\n", nmetrics);
2162
2163         for (i = 0; i < 256; i++) { /* here 256, not ENCTABSZ */
2164                 fprintf(pfa_file,
2165                         "dup %d /%s put\n", i, glyph_list[encoding[i]].name);
2166                 if( glyph_list[encoding[i]].flags & GF_USED )  {
2167                         print_glyph_metrics(i, encoding[i]);
2168                 }
2169         }
2170
2171         /* print the metrics for glyphs not in encoding table */
2172         for(i=0; i<numglyphs; i++) {
2173                 if( (glyph_list[i].flags & GF_USED)
2174                 && glyph_list[i].char_no == -1 ) {
2175                         print_glyph_metrics(-1, i);
2176                 }
2177         }
2178
2179         fprintf(pfa_file, "readonly def\ncurrentdict end\ncurrentfile eexec\n");
2180         fprintf(pfa_file, "dup /Private 16 dict dup begin\n");
2181
2182         fprintf(pfa_file, "/RD{string currentfile exch readstring pop}executeonly def\n");
2183         fprintf(pfa_file, "/ND{noaccess def}executeonly def\n");
2184         fprintf(pfa_file, "/NP{noaccess put}executeonly def\n");
2185
2186         /* UniqueID must be shown twice, in both font and Private dictionary */
2187         if(wantuid) {
2188                 if(strUID)
2189                         fprintf(pfa_file, "/UniqueID %s def\n", strUID);
2190                 else
2191                         fprintf(pfa_file, "/UniqueID %lu def\n", numUID);
2192         }
2193
2194         if(forcebold==0)
2195                 fprintf(pfa_file, "/ForceBold false def\n");
2196         else if(forcebold==1)
2197                 fprintf(pfa_file, "/ForceBold true def\n");
2198
2199         fprintf(pfa_file, "/BlueValues [ ");
2200         for (i = 0; i < nblues; i++)
2201                 fprintf(pfa_file, "%d ", bluevalues[i]);
2202         fprintf(pfa_file, "] def\n");
2203
2204         fprintf(pfa_file, "/OtherBlues [ ");
2205         for (i = 0; i < notherb; i++)
2206                 fprintf(pfa_file, "%d ", otherblues[i]);
2207         fprintf(pfa_file, "] def\n");
2208
2209         if (stdhw != 0)
2210                 fprintf(pfa_file, "/StdHW [ %d ] def\n", stdhw);
2211         if (stdvw != 0)
2212                 fprintf(pfa_file, "/StdVW [ %d ] def\n", stdvw);
2213         fprintf(pfa_file, "/StemSnapH [ ");
2214         for (i = 0; i < 12 && stemsnaph[i] != 0; i++)
2215                 fprintf(pfa_file, "%d ", stemsnaph[i]);
2216         fprintf(pfa_file, "] def\n");
2217         fprintf(pfa_file, "/StemSnapV [ ");
2218         for (i = 0; i < 12 && stemsnapv[i] != 0; i++)
2219                 fprintf(pfa_file, "%d ", stemsnapv[i]);
2220         fprintf(pfa_file, "] def\n");
2221
2222         fprintf(pfa_file, "/MinFeature {16 16} def\n");
2223         /* Are these fixed also ? */
2224         fprintf(pfa_file, "/password 5839 def\n");
2225
2226         /* calculate the number of subroutines */
2227
2228         subid=5;
2229         for (i = 0; i < numglyphs; i++) {
2230                 if (glyph_list[i].flags & GF_USED) {
2231                         subid+=glyph_list[i].nsg;
2232                 }
2233         }
2234
2235         fprintf(pfa_file, "/Subrs %d array\n", subid);
2236         /* standard subroutines */
2237         fprintf(pfa_file, "dup 0 {\n\t3 0 callothersubr pop pop setcurrentpoint return\n\t} NP\n");
2238         fprintf(pfa_file, "dup 1 {\n\t0 1 callothersubr return\n\t} NP\n");
2239         fprintf(pfa_file, "dup 2 {\n\t0 2 callothersubr return\n\t} NP\n");
2240         fprintf(pfa_file, "dup 3 {\n\treturn\n\t} NP\n");
2241         /* our sub to make the hint substitution code shorter */
2242         fprintf(pfa_file, "dup 4 {\n\t1 3 callothersubr pop callsubr return\n\t} NP\n");
2243
2244         /* print the hinting subroutines */
2245         subid=5;
2246         for (i = 0; i < numglyphs; i++) {
2247                 if (glyph_list[i].flags & GF_USED) {
2248                         subid+=print_glyph_subs(i, subid);
2249                 }
2250         }
2251
2252         fprintf(pfa_file, "ND\n");
2253
2254         fprintf(pfa_file, "2 index /CharStrings %d dict dup begin\n", nchars);
2255
2256         for (i = 0; i < numglyphs; i++) {
2257                 if (glyph_list[i].flags & GF_USED) {
2258                         print_glyph(i);
2259                 }
2260         }
2261
2262
2263         fprintf(pfa_file, "end\nend\nreadonly put\n");
2264         fprintf(pfa_file, "noaccess put\n");
2265         fprintf(pfa_file, "dup/FontName get exch definefont pop\n");
2266         fprintf(pfa_file, "mark currentfile closefile\n");
2267         fprintf(pfa_file, "cleartomark\n");
2268         fclose(pfa_file);
2269
2270     fprintf(afm_file, "EndCharMetrics\n");
2271
2272         /* print the kerning data if present */
2273         cursw->kerning(glyph_list);
2274         print_kerning(afm_file);
2275
2276     fprintf(afm_file, "EndFontMetrics\n");
2277     fclose(afm_file);
2278
2279         WARNING_1 fprintf(stderr, "Finished - font files created\n");
2280
2281         cursw->close();
2282
2283 #ifndef WIN32
2284         while (wait(&ws) > 0) {
2285         }
2286 #else 
2287         if (encode) {
2288                 extern FILE    *ifp, *ofp;      /* from t1asm.c */
2289
2290                 sprintf(filename, "%s.%s", argv[2], pfbflag ? "pfb" : "pfa" );
2291
2292                 if ((ofp = fopen(filename, "w+b")) == NULL) {
2293                         fprintf(stderr, "**** Cannot create %s ****\n", filename);
2294                         exit(1);
2295                 } else {
2296                         WARNING_2 fprintf(stderr, "Creating file %s\n", filename);
2297                 }
2298
2299                 sprintf(filename, "%s.t1a", argv[2]);
2300
2301                 if ((ifp = fopen(filename, "rb")) == NULL) {
2302                         fprintf(stderr, "**** Cannot read %s ****\n", filename);
2303                         exit(1);
2304                 } else {
2305                         WARNING_2 fprintf(stderr, "Converting file %s\n", filename);
2306                 }
2307
2308                 runt1asm(pfbflag);
2309
2310                 WARNING_2 fprintf(stderr, "Removing file %s\n", filename);
2311                 if(unlink(filename) < 0) 
2312                         WARNING_1 fprintf(stderr, "Unable to remove file %s\n", filename);
2313         }
2314 #endif /* WINDOWS */
2315
2316         return 0;
2317 }