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