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