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>
7 * see COPYRIGHT for full copyright notice
9 ***********************************************************************
11 * Sergey Babkin <babkin@users.sourceforge.net>, <sab123@hotmail.com>
13 * Added post-processing of resulting outline to correct the errors
14 * both introduced during conversion and present in the original font,
15 * autogeneration of hints (has yet to be improved though) and BlueValues,
16 * scaling to 1000x1000 matrix, option to print the result on STDOUT,
17 * support of Unicode to CP1251 conversion, optimization of the
18 * resulting font code by space (that improves the speed too). Excluded
19 * the glyphs that are unaccessible through the encoding table from
20 * the output file. Added the built-in Type1 assembler (taken from
21 * the `t1utils' package).
23 ***********************************************************************
25 * Thomas Henlich <thenlich@rcs.urz.tu-dresden.de>
27 * Added generation of .afm file (font metrics)
28 * Read encoding information from encoding description file
29 * Fixed bug in error message about unknown language ('-l' option)
30 * Added `:' after %%!PS-AdobeFont-1.0
31 * changed unused entries in ISOLatin1Encoding[] from .notdef to c127,c128...
33 ***********************************************************************
35 * Thomas Henlich <thenlich@rcs.urz.tu-dresden.de>
37 * Added generation of .afm file (font metrics)
39 ***********************************************************************
42 ************************************************************************
44 * Sun, 21 Jun 1998 Thomas Henlich <thenlich@Rcs1.urz.tu-dresden.de>
45 * 1. "width" should be "short int" because otherwise:
46 * characters with negative widths (e.g. -4) become *very* wide (65532)
47 * 2. the number of /CharStrings is numglyphs and not numglyphs+1
49 ***********************************************************************
53 * The resultant font file produced by this program still needs to be ran
54 * through t1asm (from the t1utils archive) to produce a completely valid
61 #include <sys/types.h>
68 #include "../../config.h"
76 # include <netinet/in.h>
77 # define BITBUCKET "/dev/null"
78 # include <sys/wait.h>
80 # define WINDOWS_FUNCTIONS /* ask to define functions - in one file only */
81 # include "win_missing.h"
82 # define BITBUCKET "NUL"
91 /* table of front-ends */
93 extern struct frontsw ttf_sw;
94 extern struct frontsw bdf_sw;
95 #if defined(USE_FREETYPE)
96 extern struct frontsw freetype_sw;
99 struct frontsw *frontswtab[] = {
101 #if defined(USE_FREETYPE) && defined(PREFER_FREETYPE)
105 #if defined(USE_FREETYPE) && !defined(PREFER_FREETYPE)
108 NULL /* end of table */
111 struct frontsw *cursw=0; /* the active front end */
112 char *front_arg=""; /* optional argument */
115 int encode = 0; /* encode the resulting file */
116 int pfbflag = 0; /* produce compressed file */
117 int wantafm=0; /* want to see .afm instead of .t1a on stdout */
118 int correctvsize=0; /* try to correct the vertical size of characters */
119 int wantuid = 0; /* user wants UniqueID entry in the font */
120 int allglyphs = 0; /* convert all glyphs, not only 256 of them */
121 int warnlevel = 3; /* the level of permitted warnings */
122 int forcemap = 0; /* do mapping even on non-Unicode fonts */
123 /* options - maximal limits */
124 int max_stemdepth = 128; /* maximal depth of stem stack in interpreter (128 - limit from X11) */
125 /* options - debugging */
126 int absolute = 0; /* print out in absolute values */
127 int reverse = 1; /* reverse font to Type1 path directions */
128 /* options - suboptions of Outline Processing, defaults are set in table */
129 int optimize; /* enables space optimization */
130 int smooth; /* enable smoothing of outlines */
131 int transform; /* enables transformation to 1000x1000 matrix */
132 int hints; /* enables autogeneration of hints */
133 int subhints; /* enables autogeneration of substituted hints */
134 int trybold; /* try to guess whether the font is bold */
135 int correctwidth; /* try to correct the character width */
136 int vectorize; /* vectorize the bitmaps */
137 int use_autotrace; /* use the autotrace library on bitmap */
138 /* options - suboptions of File Generation, defaults are set in table */
139 int gen_pfa; /* generate the font file */
140 int gen_afm; /* generate the metrics file */
141 int gen_dvienc; /* generate the dvips encoding file */
143 /* not quite options to select a particular source encoding */
144 int force_pid = -1; /* specific platform id */
145 int force_eid = -1; /* specific encoding id */
147 /* structure to define the sub-option lists controlled by the
148 * case: uppercase enables them, lowercase disables
151 char disbl; /* character to disable - enforced lowercase */
152 char enbl; /* character to enable - auto-set as toupper(disbl) */
153 int *valp; /* pointer to the actual variable containing value */
154 int dflt; /* default value */
155 char *descr; /* description */
158 int debug = DEBUG; /* debugging flag */
160 FILE *null_file, *pfa_file, *afm_file, *dvienc_file;
162 struct font_metrics fontm;
165 static char *strUID = 0; /* user-supplied UniqueID */
166 static unsigned long numUID; /* auto-generated UniqueID */
168 static int ps_fmt_3 = 0;
169 static double scale_factor, original_scale_factor;
171 static char *glyph_rename[ENCTABSZ];
173 /* the names assigned if the original font
174 * does not specify any
177 static char *Fmt3Encoding[256] = {
178 "c0", "c1", "c2", "c3",
179 "c4", "c5", "c6", "c7",
180 "c8", "c9", "c10", "c11",
181 "c12", "CR", "c14", "c15",
182 "c16", "c17", "c18", "c19",
183 "c20", "c21", "c22", "c23",
184 "c24", "c25", "c26", "c27",
185 "c28", "c29", "c30", "c31",
186 "space", "exclam", "quotedbl", "numbersign",
187 "dollar", "percent", "ampersand", "quotesingle",
188 "parenleft", "parenright", "asterisk", "plus",
189 "comma", "hyphen", "period", "slash",
190 "zero", "one", "two", "three",
191 "four", "five", "six", "seven",
192 "eight", "nine", "colon", "semicolon",
193 "less", "equal", "greater", "question",
200 "X", "Y", "Z", "bracketleft",
201 "backslash", "bracketright", "asciicircum", "underscore",
202 "grave", "a", "b", "c",
208 "x", "y", "z", "braceleft",
209 "bar", "braceright", "asciitilde", "c127",
210 "c128", "c129", "quotesinglbase", "florin",
211 "quotedblbase", "ellipsis", "dagger", "daggerdbl",
212 "circumflex", "perthousand", "Scaron", "guilsinglleft",
213 "OE", "c141", "c142", "c143",
214 "c144", "quoteleft", "quoteright", "quotedblleft",
215 "quotedblright", "bullet", "endash", "emdash",
216 "tilde", "trademark", "scaron", "guilsinglright",
217 "oe", "c157", "c158", "Ydieresis",
218 "nbspace", "exclamdown", "cent", "sterling",
219 "currency", "yen", "brokenbar", "section",
220 "dieresis", "copyright", "ordfeminine", "guillemotleft",
221 "logicalnot", "sfthyphen", "registered", "macron",
222 "degree", "plusminus", "twosuperior", "threesuperior",
223 "acute", "mu", "paragraph", "periodcentered",
224 "cedilla", "onesuperior", "ordmasculine", "guillemotright",
225 "onequarter", "onehalf", "threequarters", "questiondown",
226 "Agrave", "Aacute", "Acircumflex", "Atilde",
227 "Adieresis", "Aring", "AE", "Ccedilla",
228 "Egrave", "Eacute", "Ecircumflex", "Edieresis",
229 "Igrave", "Iacute", "Icircumflex", "Idieresis",
230 "Eth", "Ntilde", "Ograve", "Oacute",
231 "Ocircumflex", "Otilde", "Odieresis", "multiply",
232 "Oslash", "Ugrave", "Uacute", "Ucircumflex",
233 "Udieresis", "Yacute", "Thorn", "germandbls",
234 "agrave", "aacute", "acircumflex", "atilde",
235 "adieresis", "aring", "ae", "ccedilla",
236 "egrave", "eacute", "ecircumflex", "edieresis",
237 "igrave", "iacute", "icircumflex", "idieresis",
238 "eth", "ntilde", "ograve", "oacute",
239 "ocircumflex", "otilde", "odieresis", "divide",
240 "oslash", "ugrave", "uacute", "ucircumflex",
241 "udieresis", "yacute", "thorn", "ydieresis"
244 #ifdef notdef /* { */
245 /* This table is not used anywhere in the code
246 * so it's ifdef-ed out by default but left in
247 * the source code for reference purposes (and
248 * possibly for future use)
251 static char *ISOLatin1Encoding[256] = {
252 ".null", ".notdef", ".notdef", ".notdef",
253 ".notdef", ".notdef", ".notdef", ".notdef",
254 ".notdef", ".notdef", ".notdef", ".notdef",
255 ".notdef", "CR", ".notdef", ".notdef",
256 ".notdef", ".notdef", ".notdef", ".notdef",
257 ".notdef", ".notdef", ".notdef", ".notdef",
258 ".notdef", ".notdef", ".notdef", ".notdef",
259 ".notdef", ".notdef", ".notdef", ".notdef",
260 "space", "exclam", "quotedbl", "numbersign",
261 "dollar", "percent", "ampersand", "quoteright",
262 "parenleft", "parenright", "asterisk", "plus",
263 "comma", "hyphen", "period", "slash",
264 "zero", "one", "two", "three",
265 "four", "five", "six", "seven",
266 "eight", "nine", "colon", "semicolon",
267 "less", "equal", "greater", "question",
274 "X", "Y", "Z", "bracketleft",
275 "backslash", "bracketright", "asciicircum", "underscore",
276 "grave", "a", "b", "c",
282 "x", "y", "z", "braceleft",
283 "bar", "braceright", "asciitilde", "c127",
284 "c128", "c129", "quotesinglbase", "florin",
285 "quotedblbase", "ellipsis", "dagger", "daggerdbl",
286 "circumflex", "perthousand", "Scaron", "guilsinglleft",
287 "OE", "c141", "c142", "c143",
288 "c144", "quoteleft", "quoteright", "quotedblleft",
289 "quotedblright", "bullet", "endash", "emdash",
290 "tilde", "trademark", "scaron", "guilsinglright",
291 "oe", "c157", "c158", "Ydieresis",
292 "nbspace", "exclamdown", "cent", "sterling",
293 "currency", "yen", "brokenbar", "section",
294 "dieresis", "copyright", "ordfeminine", "guillemotleft",
295 "logicalnot", "sfthyphen", "registered", "macron",
296 "degree", "plusminus", "twosuperior", "threesuperior",
297 "acute", "mu", "paragraph", "periodcentered",
298 "cedilla", "onesuperior", "ordmasculine", "guillemotright",
299 "onequarter", "onehalf", "threequarters", "questiondown",
300 "Agrave", "Aacute", "Acircumflex", "Atilde",
301 "Adieresis", "Aring", "AE", "Ccedilla",
302 "Egrave", "Eacute", "Ecircumflex", "Edieresis",
303 "Igrave", "Iacute", "Icircumflex", "Idieresis",
304 "Eth", "Ntilde", "Ograve", "Oacute",
305 "Ocircumflex", "Otilde", "Odieresis", "multiply",
306 "Oslash", "Ugrave", "Uacute", "Ucircumflex",
307 "Udieresis", "Yacute", "Thorn", "germandbls",
308 "agrave", "aacute", "acircumflex", "atilde",
309 "adieresis", "aring", "ae", "ccedilla",
310 "egrave", "eacute", "ecircumflex", "edieresis",
311 "igrave", "iacute", "icircumflex", "idieresis",
312 "eth", "ntilde", "ograve", "oacute",
313 "ocircumflex", "otilde", "odieresis", "divide",
314 "oslash", "ugrave", "uacute", "ucircumflex",
315 "udieresis", "yacute", "thorn", "ydieresis"
318 #endif /* } notdef */
320 static char *adobe_StandardEncoding[256] = {
321 ".notdef", ".notdef", ".notdef", ".notdef",
322 ".notdef", ".notdef", ".notdef", ".notdef",
323 ".notdef", ".notdef", ".notdef", ".notdef",
324 ".notdef", ".notdef", ".notdef", ".notdef",
325 ".notdef", ".notdef", ".notdef", ".notdef",
326 ".notdef", ".notdef", ".notdef", ".notdef",
327 ".notdef", ".notdef", ".notdef", ".notdef",
328 ".notdef", ".notdef", ".notdef", ".notdef",
329 "space", "exclam", "quotedbl", "numbersign",
330 "dollar", "percent", "ampersand", "quoteright",
331 "parenleft", "parenright", "asterisk", "plus",
332 "comma", "hyphen", "period", "slash",
333 "zero", "one", "two", "three",
334 "four", "five", "six", "seven",
335 "eight", "nine", "colon", "semicolon",
336 "less", "equal", "greater", "question",
337 "at", "A", "B", "C", "D", "E", "F", "G",
338 "H", "I", "J", "K", "L", "M", "N", "O",
339 "P", "Q", "R", "S", "T", "U", "V", "W",
340 "X", "Y", "Z", "bracketleft",
341 "backslash", "bracketright", "asciicircum", "underscore",
342 "quoteleft", "a", "b", "c", "d", "e", "f", "g",
343 "h", "i", "j", "k", "l", "m", "n", "o",
344 "p", "q", "r", "s", "t", "u", "v", "w",
345 "x", "y", "z", "braceleft",
346 "bar", "braceright", "asciitilde", ".notdef",
347 ".notdef", ".notdef", ".notdef", ".notdef",
348 ".notdef", ".notdef", ".notdef", ".notdef",
349 ".notdef", ".notdef", ".notdef", ".notdef",
350 ".notdef", ".notdef", ".notdef", ".notdef",
351 ".notdef", ".notdef", ".notdef", ".notdef",
352 ".notdef", ".notdef", ".notdef", ".notdef",
353 ".notdef", ".notdef", ".notdef", ".notdef",
354 ".notdef", ".notdef", ".notdef", ".notdef",
355 ".notdef", "exclamdown", "cent", "sterling",
356 "fraction", "yen", "florin", "section",
357 "currency", "quotesingle", "quotedblleft", "guillemotleft",
358 "guilsinglleft", "guilsinglright", "fi", "fl",
359 ".notdef", "endash", "dagger", "daggerdbl",
360 "periodcentered", ".notdef", "paragraph", "bullet",
361 "quotesinglbase", "quotedblbase", "quotedblright", "guillemotright",
362 "ellipsis", "perthousand", ".notdef", "questiondown",
363 ".notdef", "grave", "acute", "circumflex",
364 "tilde", "macron", "breve", "dotaccent",
365 "dieresis", ".notdef", "ring", "cedilla",
366 ".notdef", "hungarumlaut", "ogonek", "caron",
367 "emdash", ".notdef", ".notdef", ".notdef",
368 ".notdef", ".notdef", ".notdef", ".notdef",
369 ".notdef", ".notdef", ".notdef", ".notdef",
370 ".notdef", ".notdef", ".notdef", ".notdef",
371 ".notdef", "AE", ".notdef", "ordfeminine",
372 ".notdef", ".notdef", ".notdef", ".notdef",
373 "Lslash", "Oslash", "OE", "ordmasculine",
374 ".notdef", ".notdef", ".notdef", ".notdef",
375 ".notdef", "ae", ".notdef", ".notdef",
376 ".notdef", "dotlessi", ".notdef", ".notdef",
377 "lslash", "oslash", "oe", "germandbls",
378 ".notdef", ".notdef", ".notdef", ".notdef"
382 * Decription of the supported conversions from Unicode
385 * Yes, I know that the compiled-in conversion is stupid but
386 * it is simple to implement and allows not to worry about the
387 * filesystem context. After all, the source is always available
388 * and adding another language to it is easy.
390 * The language name is expected to be the same as the subdirectory name
391 * in the `encodings' directory (for possible future extensions).
392 * The primary use of the aliases is for guessing based on the current
396 #define MAXUNIALIAS 10
397 #define MAXUNITABLES 3
399 /* the character used as the language argument separator */
400 #define LANG_ARG_SEP '+'
404 * Types of language-related routines. Arguments are:
405 * name is the glyph name
406 * arg is the user-specified language-dependent argument
407 * which can for example select the subfont plane for Eastern fonts.
408 * If none is supplied by user then an empty string ("") is passed.
409 * If no language is specified by user and auto-guessing happens
410 * then NULL is passed.
411 * when shows if the conversion by name was called before conversion by
412 * map or after (it's called twice)
415 /* type of the Unicode map initialization routine */
416 typedef void uni_init_t(char *arg);
418 /* type of Unicode converter-by-name function
419 * it's called for each glyph twice: one time for each glyph
420 * before doing conversion by map and one time after
422 typedef int uni_conv_t(char *name, char *arg, int when);
423 #define UNICONV_BYNAME_BEFORE 0
424 #define UNICONV_BYNAME_AFTER 1
426 struct uni_language {
427 uni_init_t *init[MAXUNITABLES]; /* map initialization routines */
428 uni_conv_t *convbyname; /* the name-based conversion function */
429 char *name; /* the language name */
430 char *descr; /* description */
431 char *alias[MAXUNIALIAS]; /* aliases of the language name */
432 int sample_upper; /* code of some uppercase character for correctvsize() */
435 /* the converter routines have an option of adding this suffix to the font name */
436 static char *uni_font_name_suffix = ""; /* empty by default */
437 /* this buffer may be used to store the suffix */
438 #define UNI_MAX_SUFFIX_LEN 100
439 static char uni_suffix_buf[UNI_MAX_SUFFIX_LEN+1];
442 * Prototypes of the conversion routines
445 static uni_init_t unicode_latin1;
446 static uni_init_t unicode_latin2;
447 static uni_init_t unicode_latin4;
448 static uni_init_t unicode_latin5;
449 static uni_init_t unicode_cyrillic;
450 static uni_init_t unicode_adobestd;
451 static uni_init_t unicode_plane;
452 static uni_conv_t unicode_adobestd_byname;
454 static uni_init_t unicode_init_user;
457 * The order of descriptions is important: if we can't guess the
458 * language we just call all the conversion routines in order until
459 * we find one that understands this glyph.
461 static struct uni_language uni_lang[]= {
462 /* pseudo-language for all the languages using Latin1 */
465 0, /* no name-based mapping */
467 "works for most of the Western languages",
468 { "en_", "de_", "fr_", "nl_", "no_", "da_", "it_" },
471 { /* by Szalay Tamas <tomek@elender.hu> */
473 0, /* no name-based mapping */
475 "works for Central European languages",
476 { "hu_","pl_","cz_","si_","sk_" },
479 { /* by Rièardas Èepas <rch@WriteMe.Com> */
481 0, /* no name-based mapping */
483 "works for Baltic languages",
484 { "lt_", "lv_" }, /* doubt about ee_ */
487 { /* by Turgut Uyar <uyar@cs.itu.edu.tr> */
489 0, /* no name-based mapping */
495 { /* by Zvezdan Petkovic <z.petkovic@computer.org> */
496 { unicode_cyrillic, unicode_latin1 },
497 0, /* no name-based mapping */
499 "in Windows encoding",
500 { "bg_", "be_", "mk_", "ru_", "sr_", "su_", "uk_" },
504 { unicode_cyrillic, unicode_latin1 },
505 0, /* no name-based mapping */
507 "obsolete, use cyrillic instead",
512 { unicode_cyrillic, unicode_latin1 },
513 0, /* no name-based mapping */
515 "obsolete, use cyrillic instead",
520 { unicode_adobestd },
521 unicode_adobestd_byname,
523 "Adobe Standard, expected by TeX",
529 0, /* no name-based mapping */
531 "one plane of Unicode or other multi-byte encoding as is",
533 0 /* no easy way to predict the capital letters */
537 static struct uni_language uni_lang_user = {
538 { unicode_init_user },
539 0, /* no name-based mapping */
541 0, /* no description */
546 static struct uni_language *uni_lang_selected=0; /* 0 means "unknown, try all" */
547 static int uni_sample='A'; /* sample of an uppercase character */
548 static char *uni_lang_arg=""; /* user-supplied language-dependent argument */
550 extern int runt1asm(int);
553 * user-defined loadable maps
557 /* The idea begind buckets is to avoid comparing every code with all ENCTABSZ codes in table.
558 * All the 16-bit unicode space is divided between a number of equal-sized buckets.
559 * Initially all the buckets are marked with 0. Then if any code in the bucket is
560 * used it's marked with 1. Later during translation we check the code's bucket first
561 * and it it's 0 then return failure right away. This may be useful for
562 * Chinese fonts with many thousands of glyphs.
565 #define BUCKET_ID_BITS 11
566 #define MARK_UNI_BUCKET(unicode) SET_BITMAP(uni_user_buckets, (unicode)>>(16-BUCKET_ID_BITS))
567 #define IS_UNI_BUCKET(unicode) IS_BITMAP(uni_user_buckets, (unicode)>>(16-BUCKET_ID_BITS))
569 static DEF_BITMAP(uni_user_buckets, 1<<BUCKET_ID_BITS);
571 static unsigned int unicode_map[ENCTABSZ]; /* font-encoding to unicode map */
572 static int enctabsz = 256; /* actual number of codes used */
579 FILE *unicode_map_file;
581 char buffer[UNIBFSZ];
582 unsigned code, unicode, curpos, unicode2;
584 int enabled, found, sawplane;
585 int lineno, cnt, n, nchars;
587 int pid, eid, overid=0;
589 /* check if we have an argument (plane name) */
590 arg = strrchr(path, LANG_ARG_SEP);
593 if( sscanf(arg, "pid=%d,eid=%d%n", &pid, &eid, &nchars) == 2 ) {
594 force_pid = pid; force_eid = eid; overid = 1;
595 WARNING_1 fprintf(stderr, "User override of the source encoding: pid=%d eid=%d\n", pid, eid);
601 if( *arg == 0 || strlen(arg) > UNI_MAX_SUFFIX_LEN-1)
604 sprintf(uni_suffix_buf, "-%s", arg);
605 uni_font_name_suffix = uni_suffix_buf;
609 /* now read in the encoding description file, if requested */
610 if ((unicode_map_file = fopen(path, "r")) == NULL) {
611 fprintf(stderr, "**** Cannot access map file '%s' ****\n", path);
622 while (fgets (buffer, UNIBFSZ, unicode_map_file) != NULL) {
627 if(sscanf(buffer, "plane %s", name)==1) {
630 fprintf(stderr, "**** map file '%s' requires plane name\n", path);
631 fprintf(stderr, "for example:\n");
632 fprintf(stderr, " ttf2pt1 -L %s%c[pid=N,eid=N,]%s ...\n",
633 path, LANG_ARG_SEP, name);
634 fprintf(stderr, "to select plane '%s'\n", name);
637 if( !strcmp(arg, name) ) {
642 if(found) /* no need to read further */
648 if(sscanf(buffer, "id %d %d", pid, eid)==2) {
649 if( !overid /* only if the user has not overriden */
650 && (enabled || !sawplane) ) {
651 force_pid = pid; force_eid = eid;
658 continue; /* skip to the next plane */
660 if( sscanf(buffer, "at %i", &curpos) == 1 ) {
662 fprintf(stderr, "**** map file '%s' line %d: code over 255\n", path, lineno);
665 if(ISDBG(EXTMAP)) fprintf(stderr, "=== at 0x%x\n", curpos);
669 /* try the format of Roman Czyborra's files */
670 if ( sscanf (buffer, " =%x U+%4x", &code, &unicode) == 2
671 /* try the format of Linux locale charmap file */
672 || sscanf (buffer, " <%*s /x%x <U%4x>", &code, &unicode) == 2 ) {
673 if (code < ENCTABSZ) {
674 if(code >= enctabsz) enctabsz=code+1;
675 unicode_map[code] = unicode;
676 glyph_rename[code] = NULL;
679 /* try the format with glyph renaming */
680 else if (sscanf (buffer, " !%x U+%4x %128s", &code,
681 &unicode, name) == 3) {
682 if (code < ENCTABSZ) {
683 if(code >= enctabsz) enctabsz=code+1;
684 unicode_map[code] = unicode;
685 glyph_rename[code] = strdup(name);
688 /* try the compact sequence format */
689 else if( (n=sscanf(buffer, " %i%n", &unicode, &cnt)) == 1 ) {
693 fprintf(stderr, "**** map file '%s' line %d: code over 255 for unicode 0x%x\n",
694 path, lineno, unicode);
697 if(ISDBG(EXTMAP)) fprintf(stderr, "=== 0x%d -> 0x%x\n", curpos, unicode);
698 unicode_map[curpos++] = unicode;
700 if( sscanf(p, " %[,-]%n", &next,&cnt) == 1 ) {
701 if(ISDBG(EXTMAP)) fprintf(stderr, "=== next: '%c'\n", next);
703 if( next == '-' ) { /* range */
704 if ( sscanf(p, " %i%n", &unicode2, &cnt) != 1 ) {
705 fprintf(stderr, "**** map file '%s' line %d: missing end of range\n", path, lineno);
709 if(ISDBG(EXTMAP)) fprintf(stderr, "=== range 0x%x to 0x%x\n", unicode, unicode2);
710 for(unicode++; unicode <= unicode2; unicode++) {
712 fprintf(stderr, "**** map file '%s' line %d: code over 255 in unicode range ...-0x%x\n",
713 path, lineno, unicode2);
716 if(ISDBG(EXTMAP)) fprintf(stderr, "=== 0x%x -> 0x%x\n", curpos, unicode);
717 unicode_map[curpos++] = unicode;
721 } while ( sscanf(p, " %i%n", &unicode, &cnt) == 1 );
726 fclose (unicode_map_file);
729 fprintf(stderr, "**** map file '%s' has no plane '%s'\n", path, arg);
733 if(unicode_map['A'] == 'A')
734 uni_sample = 'A'; /* seems to be compatible with Latin */
736 uni_sample = 0; /* don't make any assumptions */
740 * by Zvezdan Petkovic <z.petkovic@computer.org>
748 static unsigned int cyrillic_unicode_map[] = {
749 0x0402, 0x0403, 0x201a, 0x0453, 0x201e, 0x2026, 0x2020, 0x2021, /* 80 */
750 0x20ac, 0x2030, 0x0409, 0x2039, 0x040a, 0x040c, 0x040b, 0x040f, /* 88 */
751 0x0452, 0x2018, 0x2019, 0x201c, 0x201d, 0x2022, 0x2013, 0x2014, /* 90 */
752 0x02dc, 0x2122, 0x0459, 0x203a, 0x045a, 0x045c, 0x045b, 0x045f, /* 98 */
753 0x00a0, 0x040e, 0x045e, 0x0408, 0x00a4, 0x0490, 0x00a6, 0x00a7, /* A0 */
754 0x0401, 0x00a9, 0x0404, 0x00ab, 0x00ac, 0x00ad, 0x00ae, 0x0407, /* A8 */
755 0x00b0, 0x00b1, 0x0406, 0x0456, 0x0491, 0x00b5, 0x00b6, 0x00b7, /* B0 */
756 0x0451, 0x2116, 0x0454, 0x00bb, 0x0458, 0x0405, 0x0455, 0x0457, /* B8 */
759 for(i=0; i<=0x7F; i++)
762 for(i=0x80; i<=0xBF; i++)
763 unicode_map[i] = cyrillic_unicode_map[i-0x80];
765 for(i=0xC0; i<=0xFF; i++)
766 unicode_map[i] = i+0x350;
776 static unsigned int latin1_unicode_map[] = {
777 0x20ac, -1, 0x201a, 0x0192, 0x201e, 0x2026, 0x2020, 0x2021, /* 80 */
778 0x02c6, 0x2030, 0x0160, 0x2039, 0x0152, 0x008d, 0x017d, 0x008f, /* 88 */
779 0x0090, 0x2018, 0x2019, 0x201c, 0x201d, 0x2022, 0x2013, 0x2014, /* 90 */
780 0x02dc, 0x2122, 0x0161, 0x203a, 0x0153, 0x009d, 0x017e, 0x0178, /* 98 */
783 for(i=0; i<=0x7F; i++)
786 for(i=0x80; i<=0x9F; i++)
787 unicode_map[i] = latin1_unicode_map[i-0x80];
789 for(i=0xA0; i<=0xFF; i++)
799 static unsigned int adobestd_unicode_map[] = {
800 -1, 0x00a1, 0x00a2, 0x00a3, 0x2215, 0x00a5, 0x0192, 0x00a7, /* A0 */
801 0x00a4, 0x0027, 0x201c, 0x00ab, 0x2039, 0x203a, 0xfb01, 0xfb02, /* A8 */
802 -1, 0x2013, 0x2020, 0x2021, 0x2219, -1, 0x00b6, 0x2022, /* B0 */
803 0x201a, 0x201e, 0x201d, 0x00bb, 0x2026, 0x2030, -1, 0x00bf, /* B8 */
804 -1, 0x0060, 0x00b4, 0x02c6, 0x02dc, 0x02c9, 0x02d8, 0x02d9, /* C0 */
805 0x00a8, -1, 0x02da, 0x00b8, -1, 0x02dd, 0x02db, 0x02c7, /* C8 */
806 0x2014, -1, -1, -1, -1, -1, -1, -1, /* D0 */
807 -1, -1, -1, -1, -1, -1, -1, -1, /* D8 */
808 -1, 0x00c6, -1, 0x00aa, -1, -1, -1, -1, /* E0 */
809 0x0141, 0x00d8, 0x0152, 0x00ba, -1, -1, -1, -1, /* E8 */
810 -1, 0x00e6, -1, -1, -1, 0x0131, -1, -1, /* F0 */
811 0x0142, 0x00f8, 0x0153, 0x00df, -1, -1, -1, -1, /* F8 */
814 for(i=0; i<=0x7F; i++)
817 unicode_map[0x27] = 0x2019;
818 unicode_map[0x60] = -1;
820 /* 0x80 to 0x9F is a hole */
822 for(i=0xA0; i<=0xFF; i++)
823 unicode_map[i] = adobestd_unicode_map[i-0xA0];
827 * Not all of the Adobe glyphs are in the Unicode
828 * standard maps, so the font creators have
829 * different ideas about their codes. Because
830 * of this we try to map based on the glyph
831 * names instead of Unicode codes. If there are
832 * no glyph names (ps_fmt_3!=0) we fall back
833 * to the code-based scheme.
837 unicode_adobestd_byname(
845 /* names always take precedence over codes */
846 if(where == UNICONV_BYNAME_AFTER)
849 for(i=32; i<256; i++) {
850 if(!strcmp(name, adobe_StandardEncoding[i]))
863 static unsigned int latin2_unicode_map[] = {
864 0x00a0, 0x0104, 0x02d8, 0x0141, 0x00a4, 0x013d, 0x015a, 0x00a7, /* A0 */
865 0x00a8, 0x0160, 0x015e, 0x0164, 0x0179, 0x00ad, 0x017d, 0x017b, /* A8 */
866 0x00b0, 0x0105, 0x02db, 0x0142, 0x00b4, 0x013e, 0x015b, 0x02c7, /* B0 */
867 0x00b8, 0x0161, 0x015f, 0x0165, 0x017a, 0x02dd, 0x017e, 0x017c, /* B8 */
868 0x0154, 0x00c1, 0x00c2, 0x0102, 0x00c4, 0x0139, 0x0106, 0x00c7, /* C0 */
869 0x010c, 0x00c9, 0x0118, 0x00cb, 0x011a, 0x00cd, 0x00ce, 0x010e, /* C8 */
870 0x0110, 0x0143, 0x0147, 0x00d3, 0x00d4, 0x0150, 0x00d6, 0x00d7, /* D0 */
871 0x0158, 0x016e, 0x00da, 0x0170, 0x00dc, 0x00dd, 0x0162, 0x00df, /* D8 */
872 0x0155, 0x00e1, 0x00e2, 0x0103, 0x00e4, 0x013a, 0x0107, 0x00e7, /* E0 */
873 0x010d, 0x00e9, 0x0119, 0x00eb, 0x011b, 0x00ed, 0x00ee, 0x010f, /* E8 */
874 0x0111, 0x0144, 0x0148, 0x00f3, 0x00f4, 0x0151, 0x00f6, 0x00f7, /* F0 */
875 0x0159, 0x016f, 0x00fa, 0x0171, 0x00fc, 0x00fd, 0x0163, 0x02d9, /* F8 */
878 for(i=0; i<=0x7E; i++)
881 /* 7F-9F are unused */
883 for(i=0xA0; i<=0xFF; i++)
884 unicode_map[i] = latin2_unicode_map[i-0xA0];
893 static unsigned int latin4_unicode_map[] = {
894 0x0080, 0x0081, 0x201a, 0x0192, -1, 0x2026, 0x2020, 0x2021, /* 80 */
895 0x02c6, 0x2030, -1, 0x2039, 0x0152, 0x008d, 0x008e, 0x008f, /* 88 */
896 0x201e, 0x201c, 0x2019, -1, 0x201d, 0x2022, 0x2013, 0x2014, /* 90 */
897 0x02dc, 0x2122, -1, 0x203a, 0x0153, 0x009d, 0x009e, 0x0178, /* 98 */
898 0x00a0, 0x0104, 0x0138, 0x0156, 0x00a4, 0x0128, 0x013b, 0x00a7, /* A0 */
899 0x00a8, 0x0160, 0x0112, 0x0122, 0x0166, 0x00ad, 0x017d, 0x00af, /* A8 */
900 0x00b0, 0x0105, 0x02db, 0x0157, 0x00b4, 0x0129, 0x013c, 0x02c7, /* B0 */
901 0x00b8, 0x0161, 0x0113, 0x0123, 0x0167, 0x014a, 0x017e, 0x014b, /* B8 */
902 0x0100, 0x00c1, 0x00c2, 0x00c3, 0x00c4, 0x00c5, 0x00c6, 0x012e, /* C0 */
903 0x010c, 0x00c9, 0x0118, 0x00cb, 0x0116, 0x00cd, 0x00ce, 0x012a, /* C8 */
904 0x0110, 0x0145, 0x014c, 0x0136, 0x00d4, 0x00d5, 0x00d6, 0x00d7, /* D0 */
905 0x00d8, 0x0172, 0x00da, 0x00db, 0x00dc, 0x0168, 0x016a, 0x00df, /* D8 */
906 0x0101, 0x00e1, 0x00e2, 0x00e3, 0x00e4, 0x00e5, 0x00e6, 0x012f, /* E0 */
907 0x010d, 0x00e9, 0x0119, 0x00eb, 0x0117, 0x00ed, 0x00ee, 0x012b, /* E8 */
908 0x0111, 0x0146, 0x014d, 0x0137, 0x00f4, 0x00f5, 0x00f6, 0x00f7, /* F0 */
909 0x00f8, 0x0173, 0x00fa, 0x00fb, 0x00fc, 0x0169, 0x016b, 0x02d9, /* F8 */
912 for(i=0; i<=0x7F; i++)
915 for(i=0x80; i<=0xFF; i++)
916 unicode_map[i] = latin4_unicode_map[i-0x80];
918 #if 0 /* for documentation purposes only */
919 case 0x201e: return 0x90; /* these two quotes are a hack only */
920 case 0x201c: return 0x91; /* these two quotes are a hack only */
921 case 0x00A0: return 0xA0; /* NO-BREAK SPACE */
922 case 0x0104: return 0xA1; /* LATIN CAPITAL LETTER A WITH OGONEK */
923 case 0x0138: return 0xA2; /* LATIN SMALL LETTER KRA */
924 case 0x0156: return 0xA3; /* LATIN CAPITAL LETTER R WITH CEDILLA */
925 case 0x00A4: return 0xA4; /* CURRENCY SIGN */
926 case 0x0128: return 0xA5; /* LATIN CAPITAL LETTER I WITH TILDE */
927 case 0x013B: return 0xA6; /* LATIN CAPITAL LETTER L WITH CEDILLA */
928 case 0x00A7: return 0xA7; /* SECTION SIGN */
929 case 0x00A8: return 0xA8; /* DIAERESIS */
930 case 0x0160: return 0xA9; /* LATIN CAPITAL LETTER S WITH CARON */
931 case 0x0112: return 0xAA; /* LATIN CAPITAL LETTER E WITH MACRON */
932 case 0x0122: return 0xAB; /* LATIN CAPITAL LETTER G WITH CEDILLA */
933 case 0x0166: return 0xAC; /* LATIN CAPITAL LETTER T WITH STROKE */
934 case 0x00AD: return 0xAD; /* SOFT HYPHEN */
935 case 0x017D: return 0xAE; /* LATIN CAPITAL LETTER Z WITH CARON */
936 case 0x00AF: return 0xAF; /* MACRON */
937 case 0x00B0: return 0xB0; /* DEGREE SIGN */
938 case 0x0105: return 0xB1; /* LATIN SMALL LETTER A WITH OGONEK */
939 case 0x02DB: return 0xB2; /* OGONEK */
940 case 0x0157: return 0xB3; /* LATIN SMALL LETTER R WITH CEDILLA */
941 case 0x00B4: return 0xB4; /* ACUTE ACCENT */
942 case 0x0129: return 0xB5; /* LATIN SMALL LETTER I WITH TILDE */
943 case 0x013C: return 0xB6; /* LATIN SMALL LETTER L WITH CEDILLA */
944 case 0x02C7: return 0xB7; /* CARON */
945 case 0x00B8: return 0xB8; /* CEDILLA */
946 case 0x0161: return 0xB9; /* LATIN SMALL LETTER S WITH CARON */
947 case 0x0113: return 0xBA; /* LATIN SMALL LETTER E WITH MACRON */
948 case 0x0123: return 0xBB; /* LATIN SMALL LETTER G WITH CEDILLA */
949 case 0x0167: return 0xBC; /* LATIN SMALL LETTER T WITH STROKE */
950 case 0x014A: return 0xBD; /* LATIN CAPITAL LETTER ENG */
951 case 0x017E: return 0xBE; /* LATIN SMALL LETTER Z WITH CARON */
952 case 0x014B: return 0xBF; /* LATIN SMALL LETTER ENG */
953 case 0x0100: return 0xC0; /* LATIN CAPITAL LETTER A WITH MACRON */
954 case 0x00C1: return 0xC1; /* LATIN CAPITAL LETTER A WITH ACUTE */
955 case 0x00C2: return 0xC2; /* LATIN CAPITAL LETTER A WITH CIRCUMFLEX */
956 case 0x00C3: return 0xC3; /* LATIN CAPITAL LETTER A WITH TILDE */
957 case 0x00C4: return 0xC4; /* LATIN CAPITAL LETTER A WITH DIAERESIS */
958 case 0x00C5: return 0xC5; /* LATIN CAPITAL LETTER A WITH RING ABOVE */
959 case 0x00C6: return 0xC6; /* LATIN CAPITAL LIGATURE AE */
960 case 0x012E: return 0xC7; /* LATIN CAPITAL LETTER I WITH OGONEK */
961 case 0x010C: return 0xC8; /* LATIN CAPITAL LETTER C WITH CARON */
962 case 0x00C9: return 0xC9; /* LATIN CAPITAL LETTER E WITH ACUTE */
963 case 0x0118: return 0xCA; /* LATIN CAPITAL LETTER E WITH OGONEK */
964 case 0x00CB: return 0xCB; /* LATIN CAPITAL LETTER E WITH DIAERESIS */
965 case 0x0116: return 0xCC; /* LATIN CAPITAL LETTER E WITH DOT ABOVE */
966 case 0x00CD: return 0xCD; /* LATIN CAPITAL LETTER I WITH ACUTE */
967 case 0x00CE: return 0xCE; /* LATIN CAPITAL LETTER I WITH CIRCUMFLEX */
968 case 0x012A: return 0xCF; /* LATIN CAPITAL LETTER I WITH MACRON */
969 case 0x0110: return 0xD0; /* LATIN CAPITAL LETTER D WITH STROKE */
970 case 0x0145: return 0xD1; /* LATIN CAPITAL LETTER N WITH CEDILLA */
971 case 0x014C: return 0xD2; /* LATIN CAPITAL LETTER O WITH MACRON */
972 case 0x0136: return 0xD3; /* LATIN CAPITAL LETTER K WITH CEDILLA */
973 case 0x00D4: return 0xD4; /* LATIN CAPITAL LETTER O WITH CIRCUMFLEX */
974 case 0x00D5: return 0xD5; /* LATIN CAPITAL LETTER O WITH TILDE */
975 case 0x00D6: return 0xD6; /* LATIN CAPITAL LETTER O WITH DIAERESIS */
976 case 0x00D7: return 0xD7; /* MULTIPLICATION SIGN */
977 case 0x00D8: return 0xD8; /* LATIN CAPITAL LETTER O WITH STROKE */
978 case 0x0172: return 0xD9; /* LATIN CAPITAL LETTER U WITH OGONEK */
979 case 0x00DA: return 0xDA; /* LATIN CAPITAL LETTER U WITH ACUTE */
980 case 0x00DB: return 0xDB; /* LATIN CAPITAL LETTER U WITH CIRCUMFLEX */
981 case 0x00DC: return 0xDC; /* LATIN CAPITAL LETTER U WITH DIAERESIS */
982 case 0x0168: return 0xDD; /* LATIN CAPITAL LETTER U WITH TILDE */
983 case 0x016A: return 0xDE; /* LATIN CAPITAL LETTER U WITH MACRON */
984 case 0x00DF: return 0xDF; /* LATIN SMALL LETTER SHARP S */
985 case 0x0101: return 0xE0; /* LATIN SMALL LETTER A WITH MACRON */
986 case 0x00E1: return 0xE1; /* LATIN SMALL LETTER A WITH ACUTE */
987 case 0x00E2: return 0xE2; /* LATIN SMALL LETTER A WITH CIRCUMFLEX */
988 case 0x00E3: return 0xE3; /* LATIN SMALL LETTER A WITH TILDE */
989 case 0x00E4: return 0xE4; /* LATIN SMALL LETTER A WITH DIAERESIS */
990 case 0x00E5: return 0xE5; /* LATIN SMALL LETTER A WITH RING ABOVE */
991 case 0x00E6: return 0xE6; /* LATIN SMALL LIGATURE AE */
992 case 0x012F: return 0xE7; /* LATIN SMALL LETTER I WITH OGONEK */
993 case 0x010D: return 0xE8; /* LATIN SMALL LETTER C WITH CARON */
994 case 0x00E9: return 0xE9; /* LATIN SMALL LETTER E WITH ACUTE */
995 case 0x0119: return 0xEA; /* LATIN SMALL LETTER E WITH OGONEK */
996 case 0x00EB: return 0xEB; /* LATIN SMALL LETTER E WITH DIAERESIS */
997 case 0x0117: return 0xEC; /* LATIN SMALL LETTER E WITH DOT ABOVE */
998 case 0x00ED: return 0xED; /* LATIN SMALL LETTER I WITH ACUTE */
999 case 0x00EE: return 0xEE; /* LATIN SMALL LETTER I WITH CIRCUMFLEX */
1000 case 0x012B: return 0xEF; /* LATIN SMALL LETTER I WITH MACRON */
1001 case 0x0111: return 0xF0; /* LATIN SMALL LETTER D WITH STROKE */
1002 case 0x0146: return 0xF1; /* LATIN SMALL LETTER N WITH CEDILLA */
1003 case 0x014D: return 0xF2; /* LATIN SMALL LETTER O WITH MACRON */
1004 case 0x0137: return 0xF3; /* LATIN SMALL LETTER K WITH CEDILLA */
1005 case 0x00F4: return 0xF4; /* LATIN SMALL LETTER O WITH CIRCUMFLEX */
1006 case 0x00F5: return 0xF5; /* LATIN SMALL LETTER O WITH TILDE */
1007 case 0x00F6: return 0xF6; /* LATIN SMALL LETTER O WITH DIAERESIS */
1008 case 0x00F7: return 0xF7; /* DIVISION SIGN */
1009 case 0x00F8: return 0xF8; /* LATIN SMALL LETTER O WITH STROKE */
1010 case 0x0173: return 0xF9; /* LATIN SMALL LETTER U WITH OGONEK */
1011 case 0x00FA: return 0xFA; /* LATIN SMALL LETTER U WITH ACUTE */
1012 case 0x00FB: return 0xFB; /* LATIN SMALL LETTER U WITH CIRCUMFLEX */
1013 case 0x00FC: return 0xFC; /* LATIN SMALL LETTER U WITH DIAERESIS */
1014 case 0x0169: return 0xFD; /* LATIN SMALL LETTER U WITH TILDE */
1015 case 0x016B: return 0xFE; /* LATIN SMALL LETTER U WITH MACRON */
1016 case 0x02D9: return 0xFF; /* DOT ABOVE */
1026 static unsigned int latin5_unicode_map1[] = {
1027 0x0080, 0x0081, 0x201a, 0x0192, 0x201e, 0x2026, 0x2020, 0x2021, /* 80 */
1028 0x02c6, 0x2030, 0x0160, 0x2039, 0x0152, 0x008d, 0x008e, 0x008f, /* 88 */
1029 0x0090, 0x2018, 0x2019, 0x201c, 0x201d, 0x2022, 0x2013, 0x2014, /* 90 */
1030 0x02dc, 0x2122, 0x0161, 0x203a, 0x0153, 0x009d, 0x009e, 0x0178, /* 98 */
1032 static unsigned int latin5_unicode_map2[] = {
1033 0x011e, 0x00d1, 0x00d2, 0x00d3, 0x00d4, 0x00d5, 0x00d6, 0x00d7, /* D0 */
1034 0x00d8, 0x00d9, 0x00da, 0x00db, 0x00dc, 0x0130, 0x015e, 0x00df, /* D8 */
1035 0x00e0, 0x00e1, 0x00e2, 0x00e3, 0x00e4, 0x00e5, 0x00e6, 0x00e7, /* E0 direct */
1036 0x00e8, 0x00e9, 0x00ea, 0x00eb, 0x00ec, 0x00ed, 0x00ee, 0x00ef, /* E8 direct */
1037 0x011f, 0x00f1, 0x00f2, 0x00f3, 0x00f4, 0x00f5, 0x00f6, 0x00f7, /* F0 */
1038 0x00f8, 0x00f9, 0x00fa, 0x00fb, 0x00fc, 0x0131, 0x015f, 0x00ff, /* F8 */
1041 for(i=0; i<=0x7F; i++)
1044 for(i=0x80; i<=0x9F; i++)
1045 unicode_map[i] = latin5_unicode_map1[i-0x80];
1047 for(i=0xA0; i<=0xCF; i++)
1050 for(i=0xD0; i<=0xFF; i++)
1051 unicode_map[i] = latin5_unicode_map2[i-0xD0];
1054 /* a way to select one 256-character plane from Unicode
1055 * or other multi-byte encoding
1063 static unsigned plane;
1067 if(uni_lang_selected == 0)
1068 return; /* don't participate in auto-guessing */
1070 plane = 0; force_pid = force_eid = -1;
1072 c1 = sscanf(arg, "pid=%d,eid=%d%n", &force_pid, &force_eid, &nchars);
1078 if(arg[0] == '0' && (arg[1]=='x' || arg[1]=='X') ) {
1080 c2 = sscanf(arg, "%x", &plane);
1082 c2 = sscanf(arg, "%d", &plane);
1085 if( (c1!=2 && c1!=0) || (c1==0 && c2==0) ) {
1086 fprintf(stderr, "**** option -l plane expects one of the following formats:\n");
1087 fprintf(stderr, " -l plane+0xNN - select hexadecimal number of plane of Unicode\n");
1088 fprintf(stderr, " -l plane+NN - select decimal number of plane of Unicode\n");
1089 fprintf(stderr, " -l plane+pid=N,eid=N - select plane 0 of specified encoding\n");
1090 fprintf(stderr, " -l plane+pid=N,eid=N,0xNN - select hex plane of TTF encoding with this PID/EID\n");
1091 fprintf(stderr, " -l plane+pid=N,eid=N,NN - select decimal plane of TTF encoding with this PID/EID\n");
1096 if(strlen(arg) > sizeof(uni_suffix_buf)-2) {
1097 fprintf(stderr, "**** plane number is too large\n");
1100 sprintf(uni_suffix_buf, "-%s", arg);
1101 uni_font_name_suffix = uni_suffix_buf;
1103 uni_font_name_suffix = "";
1107 for(i=0; i<=0xFF; i++)
1108 unicode_map[i] = plane | i;
1111 /* look up the 8-bit code by unicode */
1120 if( ! IS_UNI_BUCKET(unival) )
1123 for (res = 0; res < enctabsz; res++)
1124 if (unicode_map[res] == unival)
1129 /* mark the buckets for quick lookup */
1132 unicode_prepare_buckets(
1138 memset(uni_user_buckets, 0, sizeof uni_user_buckets);
1139 for(i=0; i<enctabsz; i++) {
1140 if(unicode_map[i] != (unsigned) -1)
1141 MARK_UNI_BUCKET(unicode_map[i]);
1146 * When we print errors about bad names we want to print these names in
1147 * some decent-looking form
1155 static char res[50];
1158 for(i=0; ( c =* s )!=0 && i<sizeof(res)-8; s++) {
1159 if(c < ' ' || c > 126) {
1160 sprintf(res+i, "\\x%02X", c);
1176 * Scale the values according to the scale_factor
1184 return scale_factor * val;
1192 return (int) (val > 0 ? scale_factor * val + 0.5
1193 : scale_factor * val - 0.5);
1197 * Try to force fixed width of characters
1204 int n = 0, avg, max = 0, min = 3000, sum = 0, x;
1206 for (i = 0; i < numglyphs; i++) {
1207 if (glyph_list[i].flags & GF_USED) {
1208 x = glyph_list[i].width;
1227 WARNING_3 fprintf(stderr, "widths: max=%d avg=%d min=%d\n", max, avg, min);
1229 /* if less than 5% variation from average */
1230 /* force fixed width */
1231 if (20 * (avg - min) < avg && 20 * (max - avg) < avg) {
1232 for (i = 0; i < numglyphs; i++) {
1233 if (glyph_list[i].flags & GF_USED)
1234 glyph_list[i].width = avg;
1236 fontm.is_fixed_pitch = 1;
1248 g = &glyph_list[glyphno];
1251 g->scaledwidth = iscale(g->width);
1256 if (g->ttf_pathlen != 0) {
1257 cursw->glpath(glyphno, glyph_list);
1261 dumppaths(g, NULL, NULL);
1263 assertpath(g->entries, __FILE__, __LINE__, g->name);
1266 assertpath(g->entries, __FILE__, __LINE__, g->name);
1268 /* float processing */
1271 assertpath(g->entries, __FILE__, __LINE__, g->name);
1274 assertpath(g->entries, __FILE__, __LINE__, g->name);
1277 assertpath(g->entries, __FILE__, __LINE__, g->name);
1280 assertpath(g->entries, __FILE__, __LINE__, g->name);
1284 /* all processing past this point expects integer path */
1285 assertpath(g->entries, __FILE__, __LINE__, g->name);
1292 /* int processing */
1295 assertpath(g->entries, __FILE__, __LINE__, g->name);
1301 for(ge = g->entries; ge; ge = ge->next)
1304 if (ncurves > 200) {
1305 WARNING_3 fprintf(stderr,
1306 "** Glyph %s is too long, may display incorrectly\n",
1310 /* for buildstems */
1311 g->flags &= ~GF_FLOAT;
1318 int i, n, found, c, type;
1320 /* get the names from the font file */
1321 ps_fmt_3 = cursw->glnames(glyph_list);
1323 /* check for names with wrong characters */
1324 for (n = 0; n < numglyphs; n++) {
1326 for (i = 0; (c = glyph_list[n].name[i]) != 0; i++) {
1327 if (!(isalnum(c) || c == '.' || c == '_' || c == '-')
1328 || i==0 && isdigit(c)) { /* must not start with a digit */
1329 WARNING_3 fprintf(stderr, "Glyph %d %s (%s), ",
1330 n, isdigit(c) ? "name starts with a digit" :
1331 "has bad characters in name",
1332 nametoprint(glyph_list[n].name));
1333 glyph_list[n].name = malloc(16);
1334 sprintf(glyph_list[n].name, "_b_%d", n);
1335 WARNING_3 fprintf(stderr, "changing to %s\n", glyph_list[n].name);
1342 /* check for duplicate names */
1343 for (n = 0; n < numglyphs; n++) {
1345 for (i = 0; i < n && !found; i++) {
1346 if (strcmp(glyph_list[i].name, glyph_list[n].name) == 0) {
1347 if (( glyph_list[n].name = malloc(16) )==0) {
1348 fprintf (stderr, "****malloc failed %s line %d\n", __FILE__, __LINE__);
1351 sprintf(glyph_list[n].name, "_d_%d", n);
1353 /* if the font has no names in it (what the native parser
1354 * recognises as ps_fmt_3), FreeType returns all the
1355 * names as .notdef, so don't complain in this case
1357 if(strcmp(glyph_list[i].name, ".notdef")) {
1358 WARNING_3 fprintf(stderr,
1359 "Glyph %d has the same name as %d: (%s), changing to %s\n",
1362 glyph_list[n].name);
1371 /* start the encoding stuff */
1372 for (i = 0; i < ENCTABSZ; i++) {
1376 /* do the 1st round of encoding by name */
1377 if(!ps_fmt_3 && uni_lang_selected && uni_lang_selected->convbyname) {
1378 for (n = 0; n < numglyphs; n++) {
1379 c = uni_lang_selected->convbyname(glyph_list[n].name,
1380 uni_lang_arg, UNICONV_BYNAME_BEFORE);
1381 if(c>=0 && c<ENCTABSZ && encoding[c] == -1)
1386 /* now do the encoding by table */
1387 if(uni_lang_selected) {
1388 for(i=0; i < MAXUNITABLES && uni_lang_selected->init[i]; i++) {
1389 for (n = 0; n < ENCTABSZ; n++)
1390 unicode_map[n] = -1;
1391 uni_lang_selected->init[i](uni_lang_arg);
1392 unicode_prepare_buckets();
1393 type = cursw->glenc(glyph_list, encoding, unicode_map);
1395 /* if we have an 8-bit encoding we don't need more tries */
1399 /* language is unknown, try the first table of each */
1400 for(i=0; i < sizeof uni_lang/(sizeof uni_lang[0]); i++) {
1401 if(uni_lang[i].init[0] == NULL)
1403 for (n = 0; n < ENCTABSZ; n++)
1404 unicode_map[n] = -1;
1405 uni_lang[i].init[0](uni_lang_arg);
1406 unicode_prepare_buckets();
1407 type = cursw->glenc(glyph_list, encoding, unicode_map);
1409 /* if we have an 8-bit encoding we don't need more tries */
1415 /* get rid of the old names, they are all "UNKNOWN" anyawy */
1416 for (i = 0; i < numglyphs; i++) {
1417 glyph_list[i].name = 0;
1420 /* 8-bit - give 8859/1 names to the first 256 glyphs */
1421 for (i = 0; i < 256; i++) { /* here 256, not ENCTABSZ */
1422 if (encoding[i] > 0) {
1423 glyph_list[encoding[i]].name = Fmt3Encoding[i];
1426 } else if(type == 1) {
1427 /* Unicode - give 8859/1 names to the first 256 glyphs of Unicode */
1428 for (n = 0; n < 256; n++) { /* here 256, not ENCTABSZ */
1429 i = unicode_rev_lookup(n);
1430 if (i>=0 && encoding[i] > 0) {
1431 glyph_list[encoding[i]].name = Fmt3Encoding[i];
1434 } /* for other types of encodings just give generated names */
1435 /* assign unique names to the rest of the glyphs */
1436 for (i = 0; i < numglyphs; i++) {
1437 if (glyph_list[i].name == 0) {
1438 if (( glyph_list[i].name = malloc(16) )==0) {
1439 fprintf (stderr, "****malloc failed %s line %d\n", __FILE__, __LINE__);
1442 sprintf(glyph_list[i].name, "_d_%d", i);
1447 /* do the 2nd round of encoding by name */
1448 if(uni_lang_selected && uni_lang_selected->convbyname) {
1449 for (n = 0; n < numglyphs; n++) {
1450 c = uni_lang_selected->convbyname(glyph_list[n].name,
1451 uni_lang_arg, UNICONV_BYNAME_AFTER);
1452 if(c>=0 && c<ENCTABSZ && encoding[c] == -1)
1456 /* all the encoding things are done */
1458 for (i = 0; i < ENCTABSZ; i++)
1459 if(encoding[i] == -1) {
1460 /* check whether this character might be a duplicate
1461 * (in which case it would be missed by unicode_rev_lookup())
1464 if((type != 0 || forcemap) && c != -1) {
1465 for(n = 0; n < i; n++) {
1466 if(unicode_map[n] == c) {
1467 encoding[i] = encoding[n];
1471 if(encoding[i] == -1) /* still not found, defaults to .notdef */
1475 for (i = 0; i < 256; i++) /* here 256, not ENCTABSZ */
1476 glyph_list[encoding[i]].char_no = i;
1478 /* enforce two special cases defined in TTF manual */
1480 glyph_list[0].name = ".notdef";
1482 glyph_list[1].name = ".null";
1484 for (i = 0; i < ENCTABSZ; i++) {
1485 if ((encoding[i] != 0) && glyph_rename[i]) {
1486 glyph_list[encoding[i]].name = glyph_rename[i];
1497 # define fplop(txt) fputs(txt, stderr);
1502 fputs("Use:\n", stderr);
1503 fputs("ttf2pt1 [-<opts>] [-l language | -L file] <ttf-file> [<fontname>]\n", stderr);
1504 fputs(" or\n", stderr);
1505 fputs("ttf2pt1 [-<opts>] [-l language | -L file] <ttf-file> -\n", stderr);
1506 fputs(" or\n", stderr);
1507 fputs("ttf2pt1 [-<opts>] [-l language | -L file] <ttf-file> - | t1asm > <pfa-file>\n", stderr);
1510 fplop("This build supports both short and long option names,\n");
1511 fplop("the long options are listed before corresponding short ones\n");
1513 fplop(" --all-glyphs\n");
1514 fputs(" -a - include all glyphs, even those not in the encoding table\n", stderr);
1516 fputs(" -b - produce a compressed .pfb file\n", stderr);
1517 fplop(" --debug dbg_suboptions\n");
1518 fputs(" -d dbg_suboptions - debugging options, run ttf2pt1 -d? for help\n", stderr);
1519 fplop(" --encode\n");
1520 fputs(" -e - produce a fully encoded .pfa file\n", stderr);
1521 fplop(" --force-unicode\n");
1522 fputs(" -F - force use of Unicode encoding even if other MS encoding detected\n", stderr);
1523 fplop(" --generate suboptions\n");
1524 fputs(" -G suboptions - control the file generation, run ttf2pt1 -G? for help\n", stderr);
1525 fplop(" --language language\n");
1526 fputs(" -l language - convert Unicode to specified language, run ttf2pt1 -l? for list\n", stderr);
1527 fplop(" --language-map file\n");
1528 fputs(" -L file - convert Unicode according to encoding description file\n", stderr);
1529 fplop(" --limit <type>=<value>\n");
1530 fputs(" -m <type>=<value> - set maximal limit of given type to value, types:\n", stderr);
1531 fputs(" h - maximal hint stack depth in the PostScript interpreter\n", stderr);
1532 fplop(" --processing suboptions\n");
1533 fputs(" -O suboptions - control outline processing, run ttf2pt1 -O? for help\n", stderr);
1534 fplop(" --parser name\n");
1535 fputs(" -p name - use specific front-end parser, run ttf2pt1 -p? for list\n", stderr);
1536 fplop(" --uid id\n");
1537 fputs(" -u id - use this UniqueID, -u A means autogeneration\n", stderr);
1538 fplop(" --vertical-autoscale size\n");
1539 fputs(" -v size - scale the font to make uppercase letters >size/1000 high\n", stderr);
1540 fplop(" --version\n");
1541 fputs(" -V - print ttf2pt1 version number\n", stderr);
1542 fplop(" --warning number\n");
1543 fputs(" -W number - set the level of permitted warnings (0 - disable)\n", stderr);
1544 fputs("Obsolete options (will be removed in future releases):\n", stderr);
1546 fputs(" -A - write the .afm file to STDOUT instead of the font, now -GA\n", stderr);
1547 fputs(" -f - don't try to guess the value of the ForceBold hint, now -Ob\n", stderr);
1548 fputs(" -h - disable autogeneration of hints, now -Oh\n", stderr);
1549 fputs(" -H - disable hint substitution, now -Ou\n", stderr);
1550 fputs(" -o - disable outline optimization, now -Oo\n", stderr);
1551 fputs(" -s - disable outline smoothing, now -Os\n", stderr);
1552 fputs(" -t - disable auto-scaling to 1000x1000 standard matrix, now -Ot\n", stderr);
1553 fputs(" -w - correct the glyph widths (use only for buggy fonts), now -OW\n", stderr);
1554 fputs("With no <fontname>, write to <ttf-file> with suffix replaced.\n", stderr);
1555 fputs("The last '-' means 'use STDOUT'.\n", stderr);
1564 fprintf(stderr, "ttf2pt1 %s\n", TTF2PT1_VERSION);
1567 /* initialize a table of suboptions */
1570 struct subo_case *tbl
1575 for(i=0; tbl[i].disbl != 0; i++) {
1576 tbl[i].disbl = tolower(tbl[i].disbl);
1577 tbl[i].enbl = toupper(tbl[i].disbl);
1578 *(tbl[i].valp) = tbl[i].dflt;
1582 /* print the default value of the suboptions */
1586 struct subo_case *tbl
1591 for(i=0; tbl[i].disbl != 0; i++) {
1593 putc(tbl[i].enbl, f);
1595 putc(tbl[i].disbl, f);
1599 /* print the usage message for the suboptions */
1603 struct subo_case *tbl
1608 fprintf(f,"The lowercase suboptions disable features, corresponding\n");
1609 fprintf(f,"uppercase suboptions enable them. The supported suboptions,\n");
1610 fprintf(f,"their default states and the features they control are:\n");
1611 for(i=0; tbl[i].disbl != 0; i++) {
1612 fprintf(f," %c/%c - [%s] %s\n", tbl[i].disbl, tbl[i].enbl,
1613 tbl[i].dflt ? "enabled" : "disabled", tbl[i].descr);
1617 /* find and set the entry according to suboption,
1618 * return the found entry (or if not found return NULL)
1622 struct subo_case *tbl,
1628 for(i=0; tbl[i].disbl != 0; i++) {
1629 if(subopt == tbl[i].disbl) {
1632 } else if(subopt == tbl[i].enbl) {
1649 char filename[4096];
1650 int c,nchars,nmetrics;
1652 int forcebold= -1; /* -1 means "don't know" */
1658 # define ttf2pt1_getopt(a, b, c, d, e) getopt_long(a, b, c, d, e)
1659 static struct option longopts[] = {
1660 { "afm", 0, NULL, 'A' },
1661 { "all-glyphs", 0, NULL, 'a' },
1662 { "pfb", 0, NULL, 'b' },
1663 { "debug", 1, NULL, 'd' },
1664 { "encode", 0, NULL, 'e' },
1665 { "force-unicode", 0, NULL, 'F' },
1666 { "generate", 1, NULL, 'G' },
1667 { "language", 1, NULL, 'l' },
1668 { "language-map", 1, NULL, 'L' },
1669 { "limit", 1, NULL, 'm' },
1670 { "processing", 1, NULL, 'O' },
1671 { "parser", 1, NULL, 'p' },
1672 { "uid", 1, NULL, 'u' },
1673 { "vertical-autoscale", 1, NULL, 'v' },
1674 { "version", 0, NULL, 'V' },
1675 { "warning", 1, NULL, 'W' },
1676 { NULL, 0, NULL, 0 }
1679 # define ttf2pt1_getopt(a, b, c, d, e) getopt(a, b, c)
1681 /* table of Outline Processing (may think also as Optimization) options */
1682 static struct subo_case opotbl[] = {
1683 { 'b', 0/*auto-set*/, &trybold, 1, "guessing of the ForceBold hint" },
1684 { 'h', 0/*auto-set*/, &hints, 1, "autogeneration of hints" },
1685 { 'u', 0/*auto-set*/, &subhints, 1, "hint substitution technique" },
1686 { 'o', 0/*auto-set*/, &optimize, 1, "space optimization of font files" },
1687 { 's', 0/*auto-set*/, &smooth, 1, "smoothing and repair of outlines" },
1688 { 't', 0/*auto-set*/, &transform, 1, "auto-scaling to the standard matrix 1000x1000" },
1689 { 'w', 0/*auto-set*/, &correctwidth, 0, "correct the glyph widths (use only for buggy fonts)" },
1690 { 'v', 0/*auto-set*/, &vectorize, 0, "vectorize (trace) the bitmaps" },
1691 #ifdef USE_AUTOTRACE
1692 { 'z', 0/*auto-set*/, &use_autotrace, 0, "use the autotrace library on bitmaps (works badly)" },
1693 #endif /*USE_AUTOTRACE*/
1694 { 0, 0, 0, 0, 0} /* terminator */
1696 /* table of the File Generation options */
1697 static struct subo_case fgotbl[] = {
1698 { 'f', 0/*auto-set*/, &gen_pfa, 1, "generate the font file (.t1a, .pfa or .pfb)" },
1699 { 'a', 0/*auto-set*/, &gen_afm, 1, "generate the Adobe metrics file (.afm)" },
1700 { 'e', 0/*auto-set*/, &gen_dvienc, 0, "generate the dvips encoding file (.enc)" },
1701 { 0, 0, 0, 0, 0} /* terminator */
1703 int *genlast = NULL;
1706 init_subo_tbl(opotbl); /* initialize sub-options of -O */
1707 init_subo_tbl(fgotbl); /* initialize sub-options of -G */
1709 /* save the command line for the record
1710 * (we don't bother about escaping the shell special characters)
1714 for(i=1; i<argc; i++) {
1715 j += strlen(argv[i])+1;
1717 if ((cmdline = malloc(j+1)) == NULL) {
1718 fprintf (stderr, "****malloc failed %s line %d\n", __FILE__, __LINE__);
1722 for(i=1; i<argc; i++) {
1723 strcat(cmdline, argv[i]);
1724 strcat(cmdline, " ");
1726 for(i=0; (j=cmdline[i])!=0; i++)
1731 while(( oc=ttf2pt1_getopt(argc, argv, "FaoebAsthHfwVv:p:l:d:u:L:m:W:O:G:",
1732 longopts, NULL) )!= -1) {
1735 if(sscanf(optarg, "%d", &warnlevel) < 1 || warnlevel < 0) {
1736 fprintf(stderr, "**** warning level must be a positive number\n");
1744 fputs("Warning: option -o is obsolete, use -Oo instead\n", stderr);
1751 encode = pfbflag = 1;
1754 fputs("Warning: option -A is obsolete, use -GA instead\n", stderr);
1761 fputs("Warning: option -s is obsolete, use -Os instead\n", stderr);
1765 fputs("Warning: option -t is obsolete, use -Ot instead\n", stderr);
1769 for(i=0; optarg[i]!=0; i++)
1778 if (optarg[i] != '?')
1779 fprintf(stderr, "**** Unknown debugging option '%c' ****\n", optarg[i]);
1780 fputs("The recognized debugging options are:\n", stderr);
1781 fputs(" a - enable absolute coordinates\n", stderr);
1782 fputs(" r - do not reverse font outlines directions\n", stderr);
1792 if(sscanf(optarg, "%c=%d", &subopt, &val) !=2) {
1793 fprintf(stderr, "**** Misformatted maximal limit ****\n");
1794 fprintf(stderr, "spaces around the equal sign are not allowed\n");
1795 fprintf(stderr, "good examples: -mh=100 -m h=100\n");
1796 fprintf(stderr, "bad examples: -mh = 100 -mh= 100\n");
1802 max_stemdepth = val;
1806 fprintf(stderr, "**** Unknown limit type '%c' ****\n", subopt);
1807 fputs("The recognized limit types are:\n", stderr);
1808 fputs(" h - maximal hint stack depth in the PostScript interpreter\n", stderr);
1817 for(p=optarg; *p != 0; p++) {
1818 if(set_subo(opotbl, *p) == NULL) { /* found no match */
1820 fprintf(stderr, "**** Unknown outline processing suboption '%c' ****\n", *p);
1821 fprintf(stderr,"The general form of the outline processing option is:\n");
1822 fprintf(stderr," -O suboptions\n");
1823 fprintf(stderr,"(To remember easily -O may be also thought of as \"optimization\").\n");
1824 print_subo_usage(stderr, opotbl);
1825 fprintf(stderr, "The default state corresponds to the option -O ");
1826 print_subo_dflt(stderr, opotbl);
1827 fprintf(stderr, "\n");
1836 struct subo_case *s;
1838 for(p=optarg; *p != 0; p++) {
1839 if(( s = set_subo(fgotbl, *p) )==NULL) { /* found no match */
1841 fprintf(stderr, "**** Unknown outline processing suboption '%c' ****\n", *p);
1842 fprintf(stderr,"The general form of the file generation option is:\n");
1843 fprintf(stderr," -G suboptions\n");
1844 print_subo_usage(stderr, fgotbl);
1845 fprintf(stderr, "The default state corresponds to the option -G ");
1846 print_subo_dflt(stderr, fgotbl);
1847 fprintf(stderr, "\n");
1848 fprintf(stderr, "If the result is written to STDOUT, the last specified enabling suboption of -G\n");
1849 fprintf(stderr, "selects the file to be written to STDOUT (the font file by default).\n");
1858 fputs("Warning: option -h is obsolete, use -Oh instead\n", stderr);
1862 fputs("Warning: meaning of option -H has been changed to its opposite\n", stderr);
1863 fputs("Warning: option -H is obsolete, use -Ou instead\n", stderr);
1867 fputs("Warning: option -f is obsolete, use -Ob instead\n", stderr);
1871 fputs("Warning: option -w is obsolete, use -OW instead\n", stderr);
1876 fprintf(stderr, "**** UniqueID may be specified only once ****\n");
1880 if(optarg[0]=='A' && optarg[1]==0)
1881 strUID=0; /* will be generated automatically */
1884 for(i=0; optarg[i]!=0; i++)
1885 if( !isdigit(optarg[i]) ) {
1886 fprintf(stderr, "**** UniqueID must be numeric or A for automatic ****\n");
1892 correctvsize = atoi(optarg);
1893 if(correctvsize <= 0 && correctvsize > 1000) {
1894 fprintf(stderr, "**** wrong vsize '%d', ignored ****\n", correctvsize);
1900 fprintf(stderr, "**** only one front-end parser be used ****\n");
1904 { /* separate parser from parser-specific argument */
1905 char *p = strchr(optarg, LANG_ARG_SEP);
1912 for(i=0; frontswtab[i] != NULL; i++)
1913 if( !strcmp(frontswtab[i]->name, optarg) ) {
1914 cursw = frontswtab[i];
1919 if (strcmp(optarg, "?"))
1920 fprintf(stderr, "**** unknown front-end parser '%s' ****\n", optarg);
1921 fputs("the following front-ends are supported now:\n", stderr);
1922 for(i=0; frontswtab[i] != NULL; i++) {
1923 fprintf(stderr," %s (%s)\n file suffixes: ",
1924 frontswtab[i]->name,
1925 frontswtab[i]->descr ? frontswtab[i]->descr : "no description"
1927 for(j=0; j<MAXSUFFIX; j++)
1928 if(frontswtab[i]->suffix[j])
1929 fprintf(stderr, "%s ", frontswtab[i]->suffix[j]);
1930 fprintf(stderr, "\n");
1936 if(uni_lang_selected!=0) {
1937 fprintf(stderr, "**** only one language option may be used ****\n");
1941 { /* separate language from language-specific argument */
1942 char *p = strchr(optarg, LANG_ARG_SEP);
1949 for(i=0; i < sizeof uni_lang/(sizeof uni_lang[0]); i++)
1950 if( !strcmp(uni_lang[i].name, optarg) ) {
1951 uni_lang_selected = &uni_lang[i];
1952 uni_sample = uni_lang[i].sample_upper;
1956 if(uni_lang_selected==0) {
1957 if (strcmp(optarg, "?"))
1958 fprintf(stderr, "**** unknown language '%s' ****\n", optarg);
1959 fputs(" the following languages are supported now:\n", stderr);
1960 for(i=0; i < sizeof uni_lang/(sizeof uni_lang[0]); i++)
1961 fprintf(stderr," %s (%s)\n",
1963 uni_lang[i].descr ? uni_lang[i].descr : "no description"
1969 if(uni_lang_selected!=0) {
1970 fprintf(stderr, "**** only one language option may be used ****\n");
1973 uni_lang_selected = &uni_lang_user;
1974 uni_lang_arg = optarg;
1986 argc-=optind-1; /* the rest of code counts from argv[0] */
1989 if (absolute && encode) {
1990 fprintf(stderr, "**** options -a and -e are incompatible ****\n");
1993 if ((argc != 2) && (argc != 3)) {
1998 /* try to guess the language by the locale used */
1999 if(uni_lang_selected==0 && (lang=getenv("LANG"))!=0 ) {
2000 for(i=0; i < sizeof uni_lang/sizeof(struct uni_language); i++) {
2001 if( !strncmp(uni_lang[i].name, lang, strlen(uni_lang[i].name)) ) {
2002 uni_lang_selected = &uni_lang[i];
2003 goto got_a_language;
2006 /* no full name ? try aliases */
2007 for(i=0; i < sizeof uni_lang/sizeof(struct uni_language); i++) {
2008 for(c=0; c<MAXUNIALIAS; c++)
2009 if( uni_lang[i].alias[c]!=0
2010 && !strncmp(uni_lang[i].alias[c], lang, strlen(uni_lang[i].alias[c])) ) {
2011 uni_lang_selected = &uni_lang[i];
2012 goto got_a_language;
2016 if(uni_lang_selected!=0) {
2017 WARNING_1 fprintf(stderr, "Using language '%s' for Unicode fonts\n", uni_lang[i].name);
2018 uni_sample = uni_lang[i].sample_upper;
2022 /* try to guess the front-end parser by the file name suffix */
2024 char *p = strrchr(argv[1], '.');
2027 if(p!=0 && (s = strdup(p+1))!=0) {
2032 for(i=0; frontswtab[i] != 0 && cursw == 0; i++) {
2033 for(j=0; j<MAXSUFFIX; j++)
2034 if(frontswtab[i]->suffix[j]
2035 && !strcmp(p, frontswtab[i]->suffix[j]) ) {
2036 cursw = frontswtab[i];
2037 WARNING_1 fprintf(stderr, "Auto-detected front-end parser '%s'\n",
2039 WARNING_1 fprintf(stderr, " (use ttf2pt1 -p? to get the full list of available front-ends)\n");
2047 cursw = frontswtab[0];
2048 WARNING_1 fprintf(stderr, "Can't detect front-end parser, using '%s' by default\n",
2050 WARNING_1 fprintf(stderr, " (use ttf2pt1 -p? to get the full list of available front-ends)\n");
2054 /* open the input file */
2055 cursw->open(argv[1], front_arg);
2057 /* Get base name of output file (if not specified)
2058 * by removing (known) suffixes
2062 argv[2] = strdup (argv[1]);
2063 p = strrchr(argv[2], '.');
2065 for (j = 0; (j < MAXSUFFIX) && (cursw->suffix[j]); j++)
2066 if (!strcmp(p+1, cursw->suffix[j])) {
2072 if ((null_file = fopen(BITBUCKET, "w")) == NULL) {
2073 fprintf(stderr, "**** Cannot open %s ****\n",
2078 if (argv[2][0] == '-' && argv[2][1] == 0) {
2081 fprintf(stderr, "**** can't write encoded file to stdout ***\n");
2085 pfa_file = afm_file = dvienc_file = null_file;
2087 if(wantafm || genlast == &gen_afm) { /* print .afm instead of .pfa */
2089 } else if(genlast == &gen_dvienc) { /* print .enc instead of .pfa */
2096 snprintf(filename, sizeof filename, "%s.%s", argv[2], encode ? (pfbflag ? "pfb" : "pfa") : "t1a" );
2098 snprintf(filename, sizeof filename, "%s.t1a", argv[2]);
2101 if ((pfa_file = fopen(filename, "w+b")) == NULL) {
2102 fprintf(stderr, "**** Cannot create %s ****\n", filename);
2105 WARNING_2 fprintf(stderr, "Creating file %s\n", filename);
2108 pfa_file = null_file;
2111 snprintf(filename, sizeof filename, "%s.afm", argv[2]) ;
2112 if ((afm_file = fopen(filename, "w+")) == NULL) {
2113 fprintf(stderr, "**** Cannot create %s ****\n", filename);
2117 afm_file = null_file;
2120 snprintf(filename, sizeof filename, "%s.enc", argv[2]) ;
2121 if ((dvienc_file = fopen(filename, "w+")) == NULL) {
2122 fprintf(stderr, "**** Cannot create %s ****\n", filename);
2126 dvienc_file = null_file;
2130 * Now check whether we want a fully encoded .pfa file
2133 if (encode && pfa_file != null_file) {
2135 extern FILE *ifp, *ofp; /* from t1asm.c */
2141 perror("**** Cannot create pipe ****\n");
2145 ifp = fdopen(p[0], "r");
2147 perror("**** Cannot use pipe for reading ****\n");
2150 pfa_file = fdopen(p[1], "w");
2151 if (pfa_file == NULL) {
2152 perror("**** Cannot use pipe for writing ****\n");
2157 perror("**** Cannot fork the assembler process ****\n");
2161 exit(runt1asm(pfbflag));
2162 default: /* parent */
2163 fclose(ifp); fclose(ofp);
2168 numglyphs = cursw->nglyphs();
2170 WARNING_3 fprintf(stderr, "numglyphs = %d\n", numglyphs);
2172 glyph_list = (GLYPH *) calloc(numglyphs, sizeof(GLYPH));
2174 /* initialize non-0 fields */
2175 for (i = 0; i < numglyphs; i++) {
2181 g->name = "UNKNOWN";
2182 g->flags = GF_FLOAT; /* we start with float representation */
2187 cursw->glmetrics(glyph_list);
2188 cursw->fnmetrics(&fontm);
2190 original_scale_factor = 1000.0 / (double) fontm.units_per_em;
2193 scale_factor = 1.0; /* don't transform */
2195 scale_factor = original_scale_factor;
2197 if(correctvsize && uni_sample!=0) { /* only for known languages */
2198 /* try to adjust the scale factor to make a typical
2199 * uppercase character of hight at least (correctvsize), this
2200 * may improve the appearance of the font but also
2201 * make it weird, use with caution
2205 ysz = iscale(glyph_list[encoding[uni_sample]].yMax);
2206 if( ysz<correctvsize ) {
2207 scale_factor *= (double)correctvsize / ysz;
2212 for (i = 0; i < numglyphs; i++) {
2213 glyph_list[i].flags |= GF_USED;
2216 for (i = 0; i < ENCTABSZ; i++) {
2217 glyph_list[encoding[i]].flags |= GF_USED;
2220 /* also always include .notdef */
2221 for (i = 0; i < numglyphs; i++)
2222 if(!strcmp(glyph_list[i].name, ".notdef")) {
2223 glyph_list[i].flags |= GF_USED;
2228 for (i = 0; i < numglyphs; i++) {
2229 if (glyph_list[i].flags & GF_USED) {
2230 DBG_TO_GLYPH(&glyph_list[i]);
2232 DBG_FROM_GLYPH(&glyph_list[i]);
2236 italic_angle = fontm.italic_angle;
2238 if (italic_angle > 45.0 || italic_angle < -45.0)
2239 italic_angle = 0.0; /* consider buggy */
2243 for (i = 0; i < numglyphs; i++) {
2244 if (glyph_list[i].flags & GF_USED) {
2245 DBG_TO_GLYPH(&glyph_list[i]);
2246 buildstems(&glyph_list[i]);
2247 assertpath(glyph_list[i].entries, __FILE__, __LINE__, glyph_list[i].name);
2248 DBG_FROM_GLYPH(&glyph_list[i]);
2254 bbox[i] = iscale(fontm.bbox[i]);
2256 /* don't touch the width of fixed width fonts */
2257 if( fontm.is_fixed_pitch )
2259 docorrectwidth(); /* checks correctwidth inside */
2261 for (i = 0; i < numglyphs; i++) {
2262 if (glyph_list[i].flags & GF_USED) {
2263 DBG_TO_GLYPH(&glyph_list[i]);
2264 reversepaths(&glyph_list[i]);
2265 assertpath(glyph_list[i].entries, __FILE__, __LINE__, glyph_list[i].name);
2266 DBG_FROM_GLYPH(&glyph_list[i]);
2273 ** It seems to bring troubles. The problem is that some
2274 ** styles of the font may be recognized as fixed-width
2275 ** while other styles of the same font as proportional.
2276 ** So it's better to be commented out yet.
2283 forcebold = fontm.force_bold;
2286 fprintf(pfa_file, "%%!PS-AdobeFont-1.0: %s %s\n", fontm.name_ps, fontm.name_copyright);
2288 fprintf(pfa_file, "%%%%CreationDate: %s", ctime(&now));
2289 fprintf(pfa_file, "%% Converted by ttf2pt1 %s/%s\n", TTF2PT1_VERSION, cursw->name);
2290 fprintf(pfa_file, "%% Args: %s\n", cmdline);
2291 fprintf(pfa_file, "%%%%EndComments\n");
2292 fprintf(pfa_file, "12 dict begin\n/FontInfo 9 dict dup begin\n");
2294 WARNING_3 fprintf(stderr, "FontName %s%s\n", fontm.name_ps, uni_font_name_suffix);
2297 fprintf(pfa_file, "/version (%s) readonly def\n", fontm.name_version);
2299 fprintf(pfa_file, "/Notice (%s) readonly def\n", fontm.name_copyright);
2301 fprintf(pfa_file, "/FullName (%s) readonly def\n", fontm.name_full);
2302 fprintf(pfa_file, "/FamilyName (%s) readonly def\n", fontm.name_family);
2306 fprintf(pfa_file, "/UniqueID %s def\n", strUID);
2309 for(i=0; fontm.name_full[i]!=0; i++) {
2310 numUID *= 37; /* magic number, good for hash */
2311 numUID += fontm.name_full[i]-' ';
2312 /* if the name is long the first chars
2313 * may be lost forever, so re-insert
2314 * them thus making kind of CRC
2316 numUID += (numUID>>24) & 0xFF;
2318 /* the range for private UIDs is 4 000 000 - 4 999 999 */
2319 fprintf(pfa_file, "/UniqueID %lu def\n", numUID%1000000+4000000);
2323 fprintf(pfa_file, "/Weight (%s) readonly def\n", fontm.name_style);
2325 fprintf(pfa_file, "/ItalicAngle %f def\n", italic_angle);
2326 fprintf(pfa_file, "/isFixedPitch %s def\n",
2327 fontm.is_fixed_pitch ? "true" : "false");
2329 /* we don't print out the unused glyphs */
2331 for (i = 0; i < numglyphs; i++) {
2332 if (glyph_list[i].flags & GF_USED) {
2337 fprintf(afm_file, "StartFontMetrics 4.1\n");
2338 fprintf(afm_file, "FontName %s%s\n", fontm.name_ps, uni_font_name_suffix);
2339 fprintf(afm_file, "FullName %s\n", fontm.name_full);
2340 fprintf(afm_file, "Notice %s\n", fontm.name_copyright);
2341 fprintf(afm_file, "EncodingScheme FontSpecific\n");
2342 fprintf(afm_file, "FamilyName %s\n", fontm.name_family);
2343 fprintf(afm_file, "Weight %s\n", fontm.name_style);
2344 fprintf(afm_file, "Version %s\n", fontm.name_version);
2345 fprintf(afm_file, "Characters %d\n", nchars);
2346 fprintf(afm_file, "ItalicAngle %.1f\n", italic_angle);
2348 fprintf(afm_file, "Ascender %d\n", iscale(fontm.ascender));
2349 fprintf(afm_file, "Descender %d\n", iscale(fontm.descender));
2351 fprintf(pfa_file, "/UnderlinePosition %d def\n",
2352 iscale(fontm.underline_position));
2354 fprintf(pfa_file, "/UnderlineThickness %hd def\nend readonly def\n",
2355 iscale(fontm.underline_thickness));
2357 fprintf(afm_file, "UnderlineThickness %d\n",
2358 iscale(fontm.underline_thickness));
2360 fprintf(afm_file, "UnderlinePosition %d\n",
2361 iscale(fontm.underline_position));
2363 fprintf(afm_file, "IsFixedPitch %s\n",
2364 fontm.is_fixed_pitch ? "true" : "false");
2365 fprintf(afm_file, "FontBBox %d %d %d %d\n",
2366 bbox[0], bbox[1], bbox[2], bbox[3]);
2368 fprintf(pfa_file, "/FontName /%s%s def\n", fontm.name_ps, uni_font_name_suffix);
2369 fprintf(pfa_file, "/PaintType 0 def\n/StrokeWidth 0 def\n");
2370 /* I'm not sure if these are fixed */
2371 fprintf(pfa_file, "/FontType 1 def\n");
2374 fprintf(pfa_file, "/FontMatrix [0.001 0 0 0.001 0 0] def\n");
2376 fprintf(pfa_file, "/FontMatrix [%9.7f 0 0 %9.7f 0 0] def\n",
2377 original_scale_factor / 1000.0, original_scale_factor / 1000.0);
2380 fprintf(pfa_file, "/FontBBox {%d %d %d %d} readonly def\n",
2381 bbox[0], bbox[1], bbox[2], bbox[3]);
2383 fprintf(pfa_file, "/Encoding 256 array\n");
2384 /* determine number of elements for metrics table */
2386 for (i = 0; i < numglyphs; i++) {
2387 if( glyph_list[i].flags & GF_USED
2388 && glyph_list[i].char_no == -1 ) {
2392 fprintf(afm_file, "StartCharMetrics %d\n", nmetrics);
2394 fprintf(dvienc_file, "/%s%sEncoding [\n",
2395 fontm.name_ps, uni_font_name_suffix);
2397 for (i = 0; i < 256; i++) { /* here 256, not ENCTABSZ */
2399 "dup %d /%s put\n", i, glyph_list[encoding[i]].name);
2400 if( glyph_list[encoding[i]].flags & GF_USED ) {
2401 print_glyph_metrics(i, encoding[i]);
2404 fprintf (dvienc_file, "/index0x%04X\n", encoding[i]);
2406 fprintf (dvienc_file, "/.notdef\n");
2409 /* print the metrics for glyphs not in encoding table */
2410 for(i=0; i<numglyphs; i++) {
2411 if( (glyph_list[i].flags & GF_USED)
2412 && glyph_list[i].char_no == -1 ) {
2413 print_glyph_metrics(-1, i);
2417 fprintf(pfa_file, "readonly def\ncurrentdict end\ncurrentfile eexec\n");
2418 fprintf(pfa_file, "dup /Private 16 dict dup begin\n");
2420 fprintf(pfa_file, "/RD{string currentfile exch readstring pop}executeonly def\n");
2421 fprintf(pfa_file, "/ND{noaccess def}executeonly def\n");
2422 fprintf(pfa_file, "/NP{noaccess put}executeonly def\n");
2424 /* UniqueID must be shown twice, in both font and Private dictionary */
2427 fprintf(pfa_file, "/UniqueID %s def\n", strUID);
2429 /* the range for private UIDs is 4 000 000 - 4 999 999 */
2430 fprintf(pfa_file, "/UniqueID %lu def\n", numUID%1000000+4000000);
2434 fprintf(pfa_file, "/ForceBold false def\n");
2435 else if(forcebold==1)
2436 fprintf(pfa_file, "/ForceBold true def\n");
2438 fprintf(pfa_file, "/BlueValues [ ");
2439 for (i = 0; i < nblues; i++)
2440 fprintf(pfa_file, "%d ", bluevalues[i]);
2441 fprintf(pfa_file, "] def\n");
2443 fprintf(pfa_file, "/OtherBlues [ ");
2444 for (i = 0; i < notherb; i++)
2445 fprintf(pfa_file, "%d ", otherblues[i]);
2446 fprintf(pfa_file, "] def\n");
2449 fprintf(pfa_file, "/StdHW [ %d ] def\n", stdhw);
2451 fprintf(pfa_file, "/StdVW [ %d ] def\n", stdvw);
2452 fprintf(pfa_file, "/StemSnapH [ ");
2453 for (i = 0; i < 12 && stemsnaph[i] != 0; i++)
2454 fprintf(pfa_file, "%d ", stemsnaph[i]);
2455 fprintf(pfa_file, "] def\n");
2456 fprintf(pfa_file, "/StemSnapV [ ");
2457 for (i = 0; i < 12 && stemsnapv[i] != 0; i++)
2458 fprintf(pfa_file, "%d ", stemsnapv[i]);
2459 fprintf(pfa_file, "] def\n");
2461 fprintf(pfa_file, "/MinFeature {16 16} def\n");
2462 /* Are these fixed also ? */
2463 fprintf(pfa_file, "/password 5839 def\n");
2465 /* calculate the number of subroutines */
2468 for (i = 0; i < numglyphs; i++) {
2469 if (glyph_list[i].flags & GF_USED) {
2470 subid+=glyph_list[i].nsg;
2474 fprintf(pfa_file, "/Subrs %d array\n", subid);
2475 /* standard subroutines */
2476 fprintf(pfa_file, "dup 0 {\n\t3 0 callothersubr pop pop setcurrentpoint return\n\t} NP\n");
2477 fprintf(pfa_file, "dup 1 {\n\t0 1 callothersubr return\n\t} NP\n");
2478 fprintf(pfa_file, "dup 2 {\n\t0 2 callothersubr return\n\t} NP\n");
2479 fprintf(pfa_file, "dup 3 {\n\treturn\n\t} NP\n");
2480 /* our sub to make the hint substitution code shorter */
2481 fprintf(pfa_file, "dup 4 {\n\t1 3 callothersubr pop callsubr return\n\t} NP\n");
2483 if(pfa_file != null_file) { /* save time if the output would be wasted */
2484 /* print the hinting subroutines */
2486 for (i = 0; i < numglyphs; i++) {
2487 if (glyph_list[i].flags & GF_USED) {
2488 subid+=print_glyph_subs(i, subid);
2492 fprintf(pfa_file, "ND\n");
2494 fprintf(pfa_file, "2 index /CharStrings %d dict dup begin\n", nchars);
2496 for (i = 0; i < numglyphs; i++) {
2497 if (glyph_list[i].flags & GF_USED) {
2504 fprintf(pfa_file, "end\nend\nreadonly put\n");
2505 fprintf(pfa_file, "noaccess put\n");
2506 fprintf(pfa_file, "dup/FontName get exch definefont pop\n");
2507 fprintf(pfa_file, "mark currentfile closefile\n");
2508 fprintf(pfa_file, "cleartomark\n");
2509 if(pfa_file != null_file)
2512 fprintf(afm_file, "EndCharMetrics\n");
2514 if(afm_file != null_file) { /* save time if the output would be wasted */
2515 /* print the kerning data if present */
2516 cursw->kerning(glyph_list);
2517 print_kerning(afm_file);
2520 fprintf(afm_file, "EndFontMetrics\n");
2521 if(afm_file != null_file)
2524 fprintf(dvienc_file, "] def\n");
2525 if(dvienc_file != null_file)
2526 fclose(dvienc_file);
2528 WARNING_1 fprintf(stderr, "Finished - font files created\n");
2533 while (wait(&ws) > 0) {
2536 if (encode && pfa_file != null_file) {
2537 extern FILE *ifp, *ofp; /* from t1asm.c */
2539 snprintf(filename, sizeof filename, "%s.%s", argv[2], pfbflag ? "pfb" : "pfa" );
2541 if ((ofp = fopen(filename, "w+b")) == NULL) {
2542 fprintf(stderr, "**** Cannot create %s ****\n", filename);
2545 WARNING_2 fprintf(stderr, "Creating file %s\n", filename);
2548 snprintf(filename, sizeof filename, "%s.t1a", argv[2]);
2550 if ((ifp = fopen(filename, "rb")) == NULL) {
2551 fprintf(stderr, "**** Cannot read %s ****\n", filename);
2554 WARNING_2 fprintf(stderr, "Converting file %s\n", filename);
2559 WARNING_2 fprintf(stderr, "Removing file %s\n", filename);
2560 if(unlink(filename) < 0)
2561 WARNING_1 fprintf(stderr, "Unable to remove file %s\n", filename);