source: branches/2.2/filemanager/tp/dompdf/lib/ttf2ufm/ttf2ufm-src/ttf2pt1.c @ 3019

Revision 3019, 88.4 KB checked in by amuller, 14 years ago (diff)

Ticket #1135 - Corrigindo CSS e adicionando filemanager

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