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