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>
74 # include <netinet/in.h>
75 # define BITBUCKET "/dev/null"
76 # include <sys/wait.h>
78 # define WINDOWS_FUNCTIONS /* ask to define functions - in one file only */
79 # include "win_missing.h"
80 # define BITBUCKET "NUL"
89 /* table of front-ends */
91 extern struct frontsw ttf_sw;
92 extern struct frontsw bdf_sw;
93 #if defined(USE_FREETYPE)
94 extern struct frontsw freetype_sw;
97 struct frontsw *frontswtab[] = {
99 #if defined(USE_FREETYPE) && defined(PREFER_FREETYPE)
103 #if defined(USE_FREETYPE) && !defined(PREFER_FREETYPE)
106 NULL /* end of table */
109 struct frontsw *cursw=0; /* the active front end */
110 char *front_arg=""; /* optional argument */
113 int encode = 0; /* encode the resulting file */
114 int pfbflag = 0; /* produce compressed file */
115 int wantafm=0; /* want to see .afm instead of .t1a on stdout */
116 int correctvsize=0; /* try to correct the vertical size of characters */
117 int wantuid = 0; /* user wants UniqueID entry in the font */
118 int allglyphs = 0; /* convert all glyphs, not only 256 of them */
119 int warnlevel = 3; /* the level of permitted warnings */
120 int forcemap = 0; /* do mapping even on non-Unicode fonts */
121 /* options - maximal limits */
122 int max_stemdepth = 128; /* maximal depth of stem stack in interpreter (128 - limit from X11) */
123 /* options - debugging */
124 int absolute = 0; /* print out in absolute values */
125 int reverse = 1; /* reverse font to Type1 path directions */
126 /* options - suboptions of Outline Processing, defaults are set in table */
127 int optimize; /* enables space optimization */
128 int smooth; /* enable smoothing of outlines */
129 int transform; /* enables transformation to 1000x1000 matrix */
130 int hints; /* enables autogeneration of hints */
131 int subhints; /* enables autogeneration of substituted hints */
132 int trybold; /* try to guess whether the font is bold */
133 int correctwidth; /* try to correct the character width */
134 int vectorize; /* vectorize the bitmaps */
135 int use_autotrace; /* use the autotrace library on bitmap */
136 /* options - suboptions of File Generation, defaults are set in table */
137 int gen_pfa; /* generate the font file */
138 int gen_afm; /* generate the metrics file */
139 int gen_dvienc; /* generate the dvips encoding file */
141 /* not quite options to select a particular source encoding */
142 int force_pid = -1; /* specific platform id */
143 int force_eid = -1; /* specific encoding id */
145 /* structure to define the sub-option lists controlled by the
146 * case: uppercase enables them, lowercase disables
149 char disbl; /* character to disable - enforced lowercase */
150 char enbl; /* character to enable - auto-set as toupper(disbl) */
151 int *valp; /* pointer to the actual variable containing value */
152 int dflt; /* default value */
153 char *descr; /* description */
156 int debug = DEBUG; /* debugging flag */
158 FILE *null_file, *pfa_file, *afm_file, *dvienc_file;
160 struct font_metrics fontm;
163 static char *strUID = 0; /* user-supplied UniqueID */
164 static unsigned long numUID; /* auto-generated UniqueID */
166 static int ps_fmt_3 = 0;
167 static double scale_factor, original_scale_factor;
169 static char *glyph_rename[ENCTABSZ];
171 /* the names assigned if the original font
172 * does not specify any
175 static char *Fmt3Encoding[256] = {
176 "c0", "c1", "c2", "c3",
177 "c4", "c5", "c6", "c7",
178 "c8", "c9", "c10", "c11",
179 "c12", "CR", "c14", "c15",
180 "c16", "c17", "c18", "c19",
181 "c20", "c21", "c22", "c23",
182 "c24", "c25", "c26", "c27",
183 "c28", "c29", "c30", "c31",
184 "space", "exclam", "quotedbl", "numbersign",
185 "dollar", "percent", "ampersand", "quotesingle",
186 "parenleft", "parenright", "asterisk", "plus",
187 "comma", "hyphen", "period", "slash",
188 "zero", "one", "two", "three",
189 "four", "five", "six", "seven",
190 "eight", "nine", "colon", "semicolon",
191 "less", "equal", "greater", "question",
198 "X", "Y", "Z", "bracketleft",
199 "backslash", "bracketright", "asciicircum", "underscore",
200 "grave", "a", "b", "c",
206 "x", "y", "z", "braceleft",
207 "bar", "braceright", "asciitilde", "c127",
208 "c128", "c129", "quotesinglbase", "florin",
209 "quotedblbase", "ellipsis", "dagger", "daggerdbl",
210 "circumflex", "perthousand", "Scaron", "guilsinglleft",
211 "OE", "c141", "c142", "c143",
212 "c144", "quoteleft", "quoteright", "quotedblleft",
213 "quotedblright", "bullet", "endash", "emdash",
214 "tilde", "trademark", "scaron", "guilsinglright",
215 "oe", "c157", "c158", "Ydieresis",
216 "nbspace", "exclamdown", "cent", "sterling",
217 "currency", "yen", "brokenbar", "section",
218 "dieresis", "copyright", "ordfeminine", "guillemotleft",
219 "logicalnot", "sfthyphen", "registered", "macron",
220 "degree", "plusminus", "twosuperior", "threesuperior",
221 "acute", "mu", "paragraph", "periodcentered",
222 "cedilla", "onesuperior", "ordmasculine", "guillemotright",
223 "onequarter", "onehalf", "threequarters", "questiondown",
224 "Agrave", "Aacute", "Acircumflex", "Atilde",
225 "Adieresis", "Aring", "AE", "Ccedilla",
226 "Egrave", "Eacute", "Ecircumflex", "Edieresis",
227 "Igrave", "Iacute", "Icircumflex", "Idieresis",
228 "Eth", "Ntilde", "Ograve", "Oacute",
229 "Ocircumflex", "Otilde", "Odieresis", "multiply",
230 "Oslash", "Ugrave", "Uacute", "Ucircumflex",
231 "Udieresis", "Yacute", "Thorn", "germandbls",
232 "agrave", "aacute", "acircumflex", "atilde",
233 "adieresis", "aring", "ae", "ccedilla",
234 "egrave", "eacute", "ecircumflex", "edieresis",
235 "igrave", "iacute", "icircumflex", "idieresis",
236 "eth", "ntilde", "ograve", "oacute",
237 "ocircumflex", "otilde", "odieresis", "divide",
238 "oslash", "ugrave", "uacute", "ucircumflex",
239 "udieresis", "yacute", "thorn", "ydieresis"
242 #ifdef notdef /* { */
243 /* This table is not used anywhere in the code
244 * so it's ifdef-ed out by default but left in
245 * the source code for reference purposes (and
246 * possibly for future use)
249 static char *ISOLatin1Encoding[256] = {
250 ".null", ".notdef", ".notdef", ".notdef",
251 ".notdef", ".notdef", ".notdef", ".notdef",
252 ".notdef", ".notdef", ".notdef", ".notdef",
253 ".notdef", "CR", ".notdef", ".notdef",
254 ".notdef", ".notdef", ".notdef", ".notdef",
255 ".notdef", ".notdef", ".notdef", ".notdef",
256 ".notdef", ".notdef", ".notdef", ".notdef",
257 ".notdef", ".notdef", ".notdef", ".notdef",
258 "space", "exclam", "quotedbl", "numbersign",
259 "dollar", "percent", "ampersand", "quoteright",
260 "parenleft", "parenright", "asterisk", "plus",
261 "comma", "hyphen", "period", "slash",
262 "zero", "one", "two", "three",
263 "four", "five", "six", "seven",
264 "eight", "nine", "colon", "semicolon",
265 "less", "equal", "greater", "question",
272 "X", "Y", "Z", "bracketleft",
273 "backslash", "bracketright", "asciicircum", "underscore",
274 "grave", "a", "b", "c",
280 "x", "y", "z", "braceleft",
281 "bar", "braceright", "asciitilde", "c127",
282 "c128", "c129", "quotesinglbase", "florin",
283 "quotedblbase", "ellipsis", "dagger", "daggerdbl",
284 "circumflex", "perthousand", "Scaron", "guilsinglleft",
285 "OE", "c141", "c142", "c143",
286 "c144", "quoteleft", "quoteright", "quotedblleft",
287 "quotedblright", "bullet", "endash", "emdash",
288 "tilde", "trademark", "scaron", "guilsinglright",
289 "oe", "c157", "c158", "Ydieresis",
290 "nbspace", "exclamdown", "cent", "sterling",
291 "currency", "yen", "brokenbar", "section",
292 "dieresis", "copyright", "ordfeminine", "guillemotleft",
293 "logicalnot", "sfthyphen", "registered", "macron",
294 "degree", "plusminus", "twosuperior", "threesuperior",
295 "acute", "mu", "paragraph", "periodcentered",
296 "cedilla", "onesuperior", "ordmasculine", "guillemotright",
297 "onequarter", "onehalf", "threequarters", "questiondown",
298 "Agrave", "Aacute", "Acircumflex", "Atilde",
299 "Adieresis", "Aring", "AE", "Ccedilla",
300 "Egrave", "Eacute", "Ecircumflex", "Edieresis",
301 "Igrave", "Iacute", "Icircumflex", "Idieresis",
302 "Eth", "Ntilde", "Ograve", "Oacute",
303 "Ocircumflex", "Otilde", "Odieresis", "multiply",
304 "Oslash", "Ugrave", "Uacute", "Ucircumflex",
305 "Udieresis", "Yacute", "Thorn", "germandbls",
306 "agrave", "aacute", "acircumflex", "atilde",
307 "adieresis", "aring", "ae", "ccedilla",
308 "egrave", "eacute", "ecircumflex", "edieresis",
309 "igrave", "iacute", "icircumflex", "idieresis",
310 "eth", "ntilde", "ograve", "oacute",
311 "ocircumflex", "otilde", "odieresis", "divide",
312 "oslash", "ugrave", "uacute", "ucircumflex",
313 "udieresis", "yacute", "thorn", "ydieresis"
316 #endif /* } notdef */
318 static char *adobe_StandardEncoding[256] = {
319 ".notdef", ".notdef", ".notdef", ".notdef",
320 ".notdef", ".notdef", ".notdef", ".notdef",
321 ".notdef", ".notdef", ".notdef", ".notdef",
322 ".notdef", ".notdef", ".notdef", ".notdef",
323 ".notdef", ".notdef", ".notdef", ".notdef",
324 ".notdef", ".notdef", ".notdef", ".notdef",
325 ".notdef", ".notdef", ".notdef", ".notdef",
326 ".notdef", ".notdef", ".notdef", ".notdef",
327 "space", "exclam", "quotedbl", "numbersign",
328 "dollar", "percent", "ampersand", "quoteright",
329 "parenleft", "parenright", "asterisk", "plus",
330 "comma", "hyphen", "period", "slash",
331 "zero", "one", "two", "three",
332 "four", "five", "six", "seven",
333 "eight", "nine", "colon", "semicolon",
334 "less", "equal", "greater", "question",
335 "at", "A", "B", "C", "D", "E", "F", "G",
336 "H", "I", "J", "K", "L", "M", "N", "O",
337 "P", "Q", "R", "S", "T", "U", "V", "W",
338 "X", "Y", "Z", "bracketleft",
339 "backslash", "bracketright", "asciicircum", "underscore",
340 "quoteleft", "a", "b", "c", "d", "e", "f", "g",
341 "h", "i", "j", "k", "l", "m", "n", "o",
342 "p", "q", "r", "s", "t", "u", "v", "w",
343 "x", "y", "z", "braceleft",
344 "bar", "braceright", "asciitilde", ".notdef",
345 ".notdef", ".notdef", ".notdef", ".notdef",
346 ".notdef", ".notdef", ".notdef", ".notdef",
347 ".notdef", ".notdef", ".notdef", ".notdef",
348 ".notdef", ".notdef", ".notdef", ".notdef",
349 ".notdef", ".notdef", ".notdef", ".notdef",
350 ".notdef", ".notdef", ".notdef", ".notdef",
351 ".notdef", ".notdef", ".notdef", ".notdef",
352 ".notdef", ".notdef", ".notdef", ".notdef",
353 ".notdef", "exclamdown", "cent", "sterling",
354 "fraction", "yen", "florin", "section",
355 "currency", "quotesingle", "quotedblleft", "guillemotleft",
356 "guilsinglleft", "guilsinglright", "fi", "fl",
357 ".notdef", "endash", "dagger", "daggerdbl",
358 "periodcentered", ".notdef", "paragraph", "bullet",
359 "quotesinglbase", "quotedblbase", "quotedblright", "guillemotright",
360 "ellipsis", "perthousand", ".notdef", "questiondown",
361 ".notdef", "grave", "acute", "circumflex",
362 "tilde", "macron", "breve", "dotaccent",
363 "dieresis", ".notdef", "ring", "cedilla",
364 ".notdef", "hungarumlaut", "ogonek", "caron",
365 "emdash", ".notdef", ".notdef", ".notdef",
366 ".notdef", ".notdef", ".notdef", ".notdef",
367 ".notdef", ".notdef", ".notdef", ".notdef",
368 ".notdef", ".notdef", ".notdef", ".notdef",
369 ".notdef", "AE", ".notdef", "ordfeminine",
370 ".notdef", ".notdef", ".notdef", ".notdef",
371 "Lslash", "Oslash", "OE", "ordmasculine",
372 ".notdef", ".notdef", ".notdef", ".notdef",
373 ".notdef", "ae", ".notdef", ".notdef",
374 ".notdef", "dotlessi", ".notdef", ".notdef",
375 "lslash", "oslash", "oe", "germandbls",
376 ".notdef", ".notdef", ".notdef", ".notdef"
380 * Decription of the supported conversions from Unicode
383 * Yes, I know that the compiled-in conversion is stupid but
384 * it is simple to implement and allows not to worry about the
385 * filesystem context. After all, the source is always available
386 * and adding another language to it is easy.
388 * The language name is expected to be the same as the subdirectory name
389 * in the `encodings' directory (for possible future extensions).
390 * The primary use of the aliases is for guessing based on the current
394 #define MAXUNIALIAS 10
395 #define MAXUNITABLES 3
397 /* the character used as the language argument separator */
398 #define LANG_ARG_SEP '+'
402 * Types of language-related routines. Arguments are:
403 * name is the glyph name
404 * arg is the user-specified language-dependent argument
405 * which can for example select the subfont plane for Eastern fonts.
406 * If none is supplied by user then an empty string ("") is passed.
407 * If no language is specified by user and auto-guessing happens
408 * then NULL is passed.
409 * when shows if the conversion by name was called before conversion by
410 * map or after (it's called twice)
413 /* type of the Unicode map initialization routine */
414 typedef void uni_init_t(char *arg);
416 /* type of Unicode converter-by-name function
417 * it's called for each glyph twice: one time for each glyph
418 * before doing conversion by map and one time after
420 typedef int uni_conv_t(char *name, char *arg, int when);
421 #define UNICONV_BYNAME_BEFORE 0
422 #define UNICONV_BYNAME_AFTER 1
424 struct uni_language {
425 uni_init_t *init[MAXUNITABLES]; /* map initialization routines */
426 uni_conv_t *convbyname; /* the name-based conversion function */
427 char *name; /* the language name */
428 char *descr; /* description */
429 char *alias[MAXUNIALIAS]; /* aliases of the language name */
430 int sample_upper; /* code of some uppercase character for correctvsize() */
433 /* the converter routines have an option of adding this suffix to the font name */
434 static char *uni_font_name_suffix = ""; /* empty by default */
435 /* this buffer may be used to store the suffix */
436 #define UNI_MAX_SUFFIX_LEN 100
437 static char uni_suffix_buf[UNI_MAX_SUFFIX_LEN+1];
440 * Prototypes of the conversion routines
443 static uni_init_t unicode_latin1;
444 static uni_init_t unicode_latin2;
445 static uni_init_t unicode_latin4;
446 static uni_init_t unicode_latin5;
447 static uni_init_t unicode_cyrillic;
448 static uni_init_t unicode_adobestd;
449 static uni_init_t unicode_plane;
450 static uni_conv_t unicode_adobestd_byname;
452 static uni_init_t unicode_init_user;
455 * The order of descriptions is important: if we can't guess the
456 * language we just call all the conversion routines in order until
457 * we find one that understands this glyph.
459 static struct uni_language uni_lang[]= {
460 /* pseudo-language for all the languages using Latin1 */
463 0, /* no name-based mapping */
465 "works for most of the Western languages",
466 { "en_", "de_", "fr_", "nl_", "no_", "da_", "it_" },
469 { /* by Szalay Tamas <tomek@elender.hu> */
471 0, /* no name-based mapping */
473 "works for Central European languages",
474 { "hu_","pl_","cz_","si_","sk_" },
477 { /* by Rièardas Èepas <rch@WriteMe.Com> */
479 0, /* no name-based mapping */
481 "works for Baltic languages",
482 { "lt_", "lv_" }, /* doubt about ee_ */
485 { /* by Turgut Uyar <uyar@cs.itu.edu.tr> */
487 0, /* no name-based mapping */
493 { /* by Zvezdan Petkovic <z.petkovic@computer.org> */
494 { unicode_cyrillic, unicode_latin1 },
495 0, /* no name-based mapping */
497 "in Windows encoding",
498 { "bg_", "be_", "mk_", "ru_", "sr_", "su_", "uk_" },
502 { unicode_cyrillic, unicode_latin1 },
503 0, /* no name-based mapping */
505 "obsolete, use cyrillic instead",
510 { unicode_cyrillic, unicode_latin1 },
511 0, /* no name-based mapping */
513 "obsolete, use cyrillic instead",
518 { unicode_adobestd },
519 unicode_adobestd_byname,
521 "Adobe Standard, expected by TeX",
527 0, /* no name-based mapping */
529 "one plane of Unicode or other multi-byte encoding as is",
531 0 /* no easy way to predict the capital letters */
535 static struct uni_language uni_lang_user = {
536 { unicode_init_user },
537 0, /* no name-based mapping */
539 0, /* no description */
544 static struct uni_language *uni_lang_selected=0; /* 0 means "unknown, try all" */
545 static int uni_sample='A'; /* sample of an uppercase character */
546 static char *uni_lang_arg=""; /* user-supplied language-dependent argument */
548 extern int runt1asm(int);
551 * user-defined loadable maps
555 /* The idea begind buckets is to avoid comparing every code with all ENCTABSZ codes in table.
556 * All the 16-bit unicode space is divided between a number of equal-sized buckets.
557 * Initially all the buckets are marked with 0. Then if any code in the bucket is
558 * used it's marked with 1. Later during translation we check the code's bucket first
559 * and it it's 0 then return failure right away. This may be useful for
560 * Chinese fonts with many thousands of glyphs.
563 #define BUCKET_ID_BITS 11
564 #define MARK_UNI_BUCKET(unicode) SET_BITMAP(uni_user_buckets, (unicode)>>(16-BUCKET_ID_BITS))
565 #define IS_UNI_BUCKET(unicode) IS_BITMAP(uni_user_buckets, (unicode)>>(16-BUCKET_ID_BITS))
567 static DEF_BITMAP(uni_user_buckets, 1<<BUCKET_ID_BITS);
569 static unsigned int unicode_map[ENCTABSZ]; /* font-encoding to unicode map */
570 static int enctabsz = 256; /* actual number of codes used */
577 FILE *unicode_map_file;
579 char buffer[UNIBFSZ];
580 unsigned code, unicode, curpos, unicode2;
582 int enabled, found, sawplane;
583 int lineno, cnt, n, nchars;
585 int pid, eid, overid=0;
587 /* check if we have an argument (plane name) */
588 arg = strrchr(path, LANG_ARG_SEP);
591 if( sscanf(arg, "pid=%d,eid=%d%n", &pid, &eid, &nchars) == 2 ) {
592 force_pid = pid; force_eid = eid; overid = 1;
593 WARNING_1 fprintf(stderr, "User override of the source encoding: pid=%d eid=%d\n", pid, eid);
599 if( *arg == 0 || strlen(arg) > UNI_MAX_SUFFIX_LEN-1)
602 sprintf(uni_suffix_buf, "-%s", arg);
603 uni_font_name_suffix = uni_suffix_buf;
607 /* now read in the encoding description file, if requested */
608 if ((unicode_map_file = fopen(path, "r")) == NULL) {
609 fprintf(stderr, "**** Cannot access map file '%s' ****\n", path);
620 while (fgets (buffer, UNIBFSZ, unicode_map_file) != NULL) {
625 if(sscanf(buffer, "plane %s", name)==1) {
628 fprintf(stderr, "**** map file '%s' requires plane name\n", path);
629 fprintf(stderr, "for example:\n");
630 fprintf(stderr, " ttf2pt1 -L %s%c[pid=N,eid=N,]%s ...\n",
631 path, LANG_ARG_SEP, name);
632 fprintf(stderr, "to select plane '%s'\n", name);
635 if( !strcmp(arg, name) ) {
640 if(found) /* no need to read further */
646 if(sscanf(buffer, "id %d %d", pid, eid)==2) {
647 if( !overid /* only if the user has not overriden */
648 && (enabled || !sawplane) ) {
649 force_pid = pid; force_eid = eid;
656 continue; /* skip to the next plane */
658 if( sscanf(buffer, "at %i", &curpos) == 1 ) {
660 fprintf(stderr, "**** map file '%s' line %d: code over 255\n", path, lineno);
663 if(ISDBG(EXTMAP)) fprintf(stderr, "=== at 0x%x\n", curpos);
667 /* try the format of Roman Czyborra's files */
668 if ( sscanf (buffer, " =%x U+%4x", &code, &unicode) == 2
669 /* try the format of Linux locale charmap file */
670 || sscanf (buffer, " <%*s /x%x <U%4x>", &code, &unicode) == 2 ) {
671 if (code < ENCTABSZ) {
672 if(code >= enctabsz) enctabsz=code+1;
673 unicode_map[code] = unicode;
674 glyph_rename[code] = NULL;
677 /* try the format with glyph renaming */
678 else if (sscanf (buffer, " !%x U+%4x %128s", &code,
679 &unicode, name) == 3) {
680 if (code < ENCTABSZ) {
681 if(code >= enctabsz) enctabsz=code+1;
682 unicode_map[code] = unicode;
683 glyph_rename[code] = strdup(name);
686 /* try the compact sequence format */
687 else if( (n=sscanf(buffer, " %i%n", &unicode, &cnt)) == 1 ) {
691 fprintf(stderr, "**** map file '%s' line %d: code over 255 for unicode 0x%x\n",
692 path, lineno, unicode);
695 if(ISDBG(EXTMAP)) fprintf(stderr, "=== 0x%d -> 0x%x\n", curpos, unicode);
696 unicode_map[curpos++] = unicode;
698 if( sscanf(p, " %[,-]%n", &next,&cnt) == 1 ) {
699 if(ISDBG(EXTMAP)) fprintf(stderr, "=== next: '%c'\n", next);
701 if( next == '-' ) { /* range */
702 if ( sscanf(p, " %i%n", &unicode2, &cnt) != 1 ) {
703 fprintf(stderr, "**** map file '%s' line %d: missing end of range\n", path, lineno);
707 if(ISDBG(EXTMAP)) fprintf(stderr, "=== range 0x%x to 0x%x\n", unicode, unicode2);
708 for(unicode++; unicode <= unicode2; unicode++) {
710 fprintf(stderr, "**** map file '%s' line %d: code over 255 in unicode range ...-0x%x\n",
711 path, lineno, unicode2);
714 if(ISDBG(EXTMAP)) fprintf(stderr, "=== 0x%x -> 0x%x\n", curpos, unicode);
715 unicode_map[curpos++] = unicode;
719 } while ( sscanf(p, " %i%n", &unicode, &cnt) == 1 );
724 fclose (unicode_map_file);
727 fprintf(stderr, "**** map file '%s' has no plane '%s'\n", path, arg);
731 if(unicode_map['A'] == 'A')
732 uni_sample = 'A'; /* seems to be compatible with Latin */
734 uni_sample = 0; /* don't make any assumptions */
738 * by Zvezdan Petkovic <z.petkovic@computer.org>
746 static unsigned int cyrillic_unicode_map[] = {
747 0x0402, 0x0403, 0x201a, 0x0453, 0x201e, 0x2026, 0x2020, 0x2021, /* 80 */
748 0x20ac, 0x2030, 0x0409, 0x2039, 0x040a, 0x040c, 0x040b, 0x040f, /* 88 */
749 0x0452, 0x2018, 0x2019, 0x201c, 0x201d, 0x2022, 0x2013, 0x2014, /* 90 */
750 0x02dc, 0x2122, 0x0459, 0x203a, 0x045a, 0x045c, 0x045b, 0x045f, /* 98 */
751 0x00a0, 0x040e, 0x045e, 0x0408, 0x00a4, 0x0490, 0x00a6, 0x00a7, /* A0 */
752 0x0401, 0x00a9, 0x0404, 0x00ab, 0x00ac, 0x00ad, 0x00ae, 0x0407, /* A8 */
753 0x00b0, 0x00b1, 0x0406, 0x0456, 0x0491, 0x00b5, 0x00b6, 0x00b7, /* B0 */
754 0x0451, 0x2116, 0x0454, 0x00bb, 0x0458, 0x0405, 0x0455, 0x0457, /* B8 */
757 for(i=0; i<=0x7F; i++)
760 for(i=0x80; i<=0xBF; i++)
761 unicode_map[i] = cyrillic_unicode_map[i-0x80];
763 for(i=0xC0; i<=0xFF; i++)
764 unicode_map[i] = i+0x350;
774 static unsigned int latin1_unicode_map[] = {
775 0x20ac, -1, 0x201a, 0x0192, 0x201e, 0x2026, 0x2020, 0x2021, /* 80 */
776 0x02c6, 0x2030, 0x0160, 0x2039, 0x0152, 0x008d, 0x017d, 0x008f, /* 88 */
777 0x0090, 0x2018, 0x2019, 0x201c, 0x201d, 0x2022, 0x2013, 0x2014, /* 90 */
778 0x02dc, 0x2122, 0x0161, 0x203a, 0x0153, 0x009d, 0x017e, 0x0178, /* 98 */
781 for(i=0; i<=0x7F; i++)
784 for(i=0x80; i<=0x9F; i++)
785 unicode_map[i] = latin1_unicode_map[i-0x80];
787 for(i=0xA0; i<=0xFF; i++)
797 static unsigned int adobestd_unicode_map[] = {
798 -1, 0x00a1, 0x00a2, 0x00a3, 0x2215, 0x00a5, 0x0192, 0x00a7, /* A0 */
799 0x00a4, 0x0027, 0x201c, 0x00ab, 0x2039, 0x203a, 0xfb01, 0xfb02, /* A8 */
800 -1, 0x2013, 0x2020, 0x2021, 0x2219, -1, 0x00b6, 0x2022, /* B0 */
801 0x201a, 0x201e, 0x201d, 0x00bb, 0x2026, 0x2030, -1, 0x00bf, /* B8 */
802 -1, 0x0060, 0x00b4, 0x02c6, 0x02dc, 0x02c9, 0x02d8, 0x02d9, /* C0 */
803 0x00a8, -1, 0x02da, 0x00b8, -1, 0x02dd, 0x02db, 0x02c7, /* C8 */
804 0x2014, -1, -1, -1, -1, -1, -1, -1, /* D0 */
805 -1, -1, -1, -1, -1, -1, -1, -1, /* D8 */
806 -1, 0x00c6, -1, 0x00aa, -1, -1, -1, -1, /* E0 */
807 0x0141, 0x00d8, 0x0152, 0x00ba, -1, -1, -1, -1, /* E8 */
808 -1, 0x00e6, -1, -1, -1, 0x0131, -1, -1, /* F0 */
809 0x0142, 0x00f8, 0x0153, 0x00df, -1, -1, -1, -1, /* F8 */
812 for(i=0; i<=0x7F; i++)
815 unicode_map[0x27] = 0x2019;
816 unicode_map[0x60] = -1;
818 /* 0x80 to 0x9F is a hole */
820 for(i=0xA0; i<=0xFF; i++)
821 unicode_map[i] = adobestd_unicode_map[i-0xA0];
825 * Not all of the Adobe glyphs are in the Unicode
826 * standard maps, so the font creators have
827 * different ideas about their codes. Because
828 * of this we try to map based on the glyph
829 * names instead of Unicode codes. If there are
830 * no glyph names (ps_fmt_3!=0) we fall back
831 * to the code-based scheme.
835 unicode_adobestd_byname(
843 /* names always take precedence over codes */
844 if(where == UNICONV_BYNAME_AFTER)
847 for(i=32; i<256; i++) {
848 if(!strcmp(name, adobe_StandardEncoding[i]))
861 static unsigned int latin2_unicode_map[] = {
862 0x00a0, 0x0104, 0x02d8, 0x0141, 0x00a4, 0x013d, 0x015a, 0x00a7, /* A0 */
863 0x00a8, 0x0160, 0x015e, 0x0164, 0x0179, 0x00ad, 0x017d, 0x017b, /* A8 */
864 0x00b0, 0x0105, 0x02db, 0x0142, 0x00b4, 0x013e, 0x015b, 0x02c7, /* B0 */
865 0x00b8, 0x0161, 0x015f, 0x0165, 0x017a, 0x02dd, 0x017e, 0x017c, /* B8 */
866 0x0154, 0x00c1, 0x00c2, 0x0102, 0x00c4, 0x0139, 0x0106, 0x00c7, /* C0 */
867 0x010c, 0x00c9, 0x0118, 0x00cb, 0x011a, 0x00cd, 0x00ce, 0x010e, /* C8 */
868 0x0110, 0x0143, 0x0147, 0x00d3, 0x00d4, 0x0150, 0x00d6, 0x00d7, /* D0 */
869 0x0158, 0x016e, 0x00da, 0x0170, 0x00dc, 0x00dd, 0x0162, 0x00df, /* D8 */
870 0x0155, 0x00e1, 0x00e2, 0x0103, 0x00e4, 0x013a, 0x0107, 0x00e7, /* E0 */
871 0x010d, 0x00e9, 0x0119, 0x00eb, 0x011b, 0x00ed, 0x00ee, 0x010f, /* E8 */
872 0x0111, 0x0144, 0x0148, 0x00f3, 0x00f4, 0x0151, 0x00f6, 0x00f7, /* F0 */
873 0x0159, 0x016f, 0x00fa, 0x0171, 0x00fc, 0x00fd, 0x0163, 0x02d9, /* F8 */
876 for(i=0; i<=0x7E; i++)
879 /* 7F-9F are unused */
881 for(i=0xA0; i<=0xFF; i++)
882 unicode_map[i] = latin2_unicode_map[i-0xA0];
891 static unsigned int latin4_unicode_map[] = {
892 0x0080, 0x0081, 0x201a, 0x0192, -1, 0x2026, 0x2020, 0x2021, /* 80 */
893 0x02c6, 0x2030, -1, 0x2039, 0x0152, 0x008d, 0x008e, 0x008f, /* 88 */
894 0x201e, 0x201c, 0x2019, -1, 0x201d, 0x2022, 0x2013, 0x2014, /* 90 */
895 0x02dc, 0x2122, -1, 0x203a, 0x0153, 0x009d, 0x009e, 0x0178, /* 98 */
896 0x00a0, 0x0104, 0x0138, 0x0156, 0x00a4, 0x0128, 0x013b, 0x00a7, /* A0 */
897 0x00a8, 0x0160, 0x0112, 0x0122, 0x0166, 0x00ad, 0x017d, 0x00af, /* A8 */
898 0x00b0, 0x0105, 0x02db, 0x0157, 0x00b4, 0x0129, 0x013c, 0x02c7, /* B0 */
899 0x00b8, 0x0161, 0x0113, 0x0123, 0x0167, 0x014a, 0x017e, 0x014b, /* B8 */
900 0x0100, 0x00c1, 0x00c2, 0x00c3, 0x00c4, 0x00c5, 0x00c6, 0x012e, /* C0 */
901 0x010c, 0x00c9, 0x0118, 0x00cb, 0x0116, 0x00cd, 0x00ce, 0x012a, /* C8 */
902 0x0110, 0x0145, 0x014c, 0x0136, 0x00d4, 0x00d5, 0x00d6, 0x00d7, /* D0 */
903 0x00d8, 0x0172, 0x00da, 0x00db, 0x00dc, 0x0168, 0x016a, 0x00df, /* D8 */
904 0x0101, 0x00e1, 0x00e2, 0x00e3, 0x00e4, 0x00e5, 0x00e6, 0x012f, /* E0 */
905 0x010d, 0x00e9, 0x0119, 0x00eb, 0x0117, 0x00ed, 0x00ee, 0x012b, /* E8 */
906 0x0111, 0x0146, 0x014d, 0x0137, 0x00f4, 0x00f5, 0x00f6, 0x00f7, /* F0 */
907 0x00f8, 0x0173, 0x00fa, 0x00fb, 0x00fc, 0x0169, 0x016b, 0x02d9, /* F8 */
910 for(i=0; i<=0x7F; i++)
913 for(i=0x80; i<=0xFF; i++)
914 unicode_map[i] = latin4_unicode_map[i-0x80];
916 #if 0 /* for documentation purposes only */
917 case 0x201e: return 0x90; /* these two quotes are a hack only */
918 case 0x201c: return 0x91; /* these two quotes are a hack only */
919 case 0x00A0: return 0xA0; /* NO-BREAK SPACE */
920 case 0x0104: return 0xA1; /* LATIN CAPITAL LETTER A WITH OGONEK */
921 case 0x0138: return 0xA2; /* LATIN SMALL LETTER KRA */
922 case 0x0156: return 0xA3; /* LATIN CAPITAL LETTER R WITH CEDILLA */
923 case 0x00A4: return 0xA4; /* CURRENCY SIGN */
924 case 0x0128: return 0xA5; /* LATIN CAPITAL LETTER I WITH TILDE */
925 case 0x013B: return 0xA6; /* LATIN CAPITAL LETTER L WITH CEDILLA */
926 case 0x00A7: return 0xA7; /* SECTION SIGN */
927 case 0x00A8: return 0xA8; /* DIAERESIS */
928 case 0x0160: return 0xA9; /* LATIN CAPITAL LETTER S WITH CARON */
929 case 0x0112: return 0xAA; /* LATIN CAPITAL LETTER E WITH MACRON */
930 case 0x0122: return 0xAB; /* LATIN CAPITAL LETTER G WITH CEDILLA */
931 case 0x0166: return 0xAC; /* LATIN CAPITAL LETTER T WITH STROKE */
932 case 0x00AD: return 0xAD; /* SOFT HYPHEN */
933 case 0x017D: return 0xAE; /* LATIN CAPITAL LETTER Z WITH CARON */
934 case 0x00AF: return 0xAF; /* MACRON */
935 case 0x00B0: return 0xB0; /* DEGREE SIGN */
936 case 0x0105: return 0xB1; /* LATIN SMALL LETTER A WITH OGONEK */
937 case 0x02DB: return 0xB2; /* OGONEK */
938 case 0x0157: return 0xB3; /* LATIN SMALL LETTER R WITH CEDILLA */
939 case 0x00B4: return 0xB4; /* ACUTE ACCENT */
940 case 0x0129: return 0xB5; /* LATIN SMALL LETTER I WITH TILDE */
941 case 0x013C: return 0xB6; /* LATIN SMALL LETTER L WITH CEDILLA */
942 case 0x02C7: return 0xB7; /* CARON */
943 case 0x00B8: return 0xB8; /* CEDILLA */
944 case 0x0161: return 0xB9; /* LATIN SMALL LETTER S WITH CARON */
945 case 0x0113: return 0xBA; /* LATIN SMALL LETTER E WITH MACRON */
946 case 0x0123: return 0xBB; /* LATIN SMALL LETTER G WITH CEDILLA */
947 case 0x0167: return 0xBC; /* LATIN SMALL LETTER T WITH STROKE */
948 case 0x014A: return 0xBD; /* LATIN CAPITAL LETTER ENG */
949 case 0x017E: return 0xBE; /* LATIN SMALL LETTER Z WITH CARON */
950 case 0x014B: return 0xBF; /* LATIN SMALL LETTER ENG */
951 case 0x0100: return 0xC0; /* LATIN CAPITAL LETTER A WITH MACRON */
952 case 0x00C1: return 0xC1; /* LATIN CAPITAL LETTER A WITH ACUTE */
953 case 0x00C2: return 0xC2; /* LATIN CAPITAL LETTER A WITH CIRCUMFLEX */
954 case 0x00C3: return 0xC3; /* LATIN CAPITAL LETTER A WITH TILDE */
955 case 0x00C4: return 0xC4; /* LATIN CAPITAL LETTER A WITH DIAERESIS */
956 case 0x00C5: return 0xC5; /* LATIN CAPITAL LETTER A WITH RING ABOVE */
957 case 0x00C6: return 0xC6; /* LATIN CAPITAL LIGATURE AE */
958 case 0x012E: return 0xC7; /* LATIN CAPITAL LETTER I WITH OGONEK */
959 case 0x010C: return 0xC8; /* LATIN CAPITAL LETTER C WITH CARON */
960 case 0x00C9: return 0xC9; /* LATIN CAPITAL LETTER E WITH ACUTE */
961 case 0x0118: return 0xCA; /* LATIN CAPITAL LETTER E WITH OGONEK */
962 case 0x00CB: return 0xCB; /* LATIN CAPITAL LETTER E WITH DIAERESIS */
963 case 0x0116: return 0xCC; /* LATIN CAPITAL LETTER E WITH DOT ABOVE */
964 case 0x00CD: return 0xCD; /* LATIN CAPITAL LETTER I WITH ACUTE */
965 case 0x00CE: return 0xCE; /* LATIN CAPITAL LETTER I WITH CIRCUMFLEX */
966 case 0x012A: return 0xCF; /* LATIN CAPITAL LETTER I WITH MACRON */
967 case 0x0110: return 0xD0; /* LATIN CAPITAL LETTER D WITH STROKE */
968 case 0x0145: return 0xD1; /* LATIN CAPITAL LETTER N WITH CEDILLA */
969 case 0x014C: return 0xD2; /* LATIN CAPITAL LETTER O WITH MACRON */
970 case 0x0136: return 0xD3; /* LATIN CAPITAL LETTER K WITH CEDILLA */
971 case 0x00D4: return 0xD4; /* LATIN CAPITAL LETTER O WITH CIRCUMFLEX */
972 case 0x00D5: return 0xD5; /* LATIN CAPITAL LETTER O WITH TILDE */
973 case 0x00D6: return 0xD6; /* LATIN CAPITAL LETTER O WITH DIAERESIS */
974 case 0x00D7: return 0xD7; /* MULTIPLICATION SIGN */
975 case 0x00D8: return 0xD8; /* LATIN CAPITAL LETTER O WITH STROKE */
976 case 0x0172: return 0xD9; /* LATIN CAPITAL LETTER U WITH OGONEK */
977 case 0x00DA: return 0xDA; /* LATIN CAPITAL LETTER U WITH ACUTE */
978 case 0x00DB: return 0xDB; /* LATIN CAPITAL LETTER U WITH CIRCUMFLEX */
979 case 0x00DC: return 0xDC; /* LATIN CAPITAL LETTER U WITH DIAERESIS */
980 case 0x0168: return 0xDD; /* LATIN CAPITAL LETTER U WITH TILDE */
981 case 0x016A: return 0xDE; /* LATIN CAPITAL LETTER U WITH MACRON */
982 case 0x00DF: return 0xDF; /* LATIN SMALL LETTER SHARP S */
983 case 0x0101: return 0xE0; /* LATIN SMALL LETTER A WITH MACRON */
984 case 0x00E1: return 0xE1; /* LATIN SMALL LETTER A WITH ACUTE */
985 case 0x00E2: return 0xE2; /* LATIN SMALL LETTER A WITH CIRCUMFLEX */
986 case 0x00E3: return 0xE3; /* LATIN SMALL LETTER A WITH TILDE */
987 case 0x00E4: return 0xE4; /* LATIN SMALL LETTER A WITH DIAERESIS */
988 case 0x00E5: return 0xE5; /* LATIN SMALL LETTER A WITH RING ABOVE */
989 case 0x00E6: return 0xE6; /* LATIN SMALL LIGATURE AE */
990 case 0x012F: return 0xE7; /* LATIN SMALL LETTER I WITH OGONEK */
991 case 0x010D: return 0xE8; /* LATIN SMALL LETTER C WITH CARON */
992 case 0x00E9: return 0xE9; /* LATIN SMALL LETTER E WITH ACUTE */
993 case 0x0119: return 0xEA; /* LATIN SMALL LETTER E WITH OGONEK */
994 case 0x00EB: return 0xEB; /* LATIN SMALL LETTER E WITH DIAERESIS */
995 case 0x0117: return 0xEC; /* LATIN SMALL LETTER E WITH DOT ABOVE */
996 case 0x00ED: return 0xED; /* LATIN SMALL LETTER I WITH ACUTE */
997 case 0x00EE: return 0xEE; /* LATIN SMALL LETTER I WITH CIRCUMFLEX */
998 case 0x012B: return 0xEF; /* LATIN SMALL LETTER I WITH MACRON */
999 case 0x0111: return 0xF0; /* LATIN SMALL LETTER D WITH STROKE */
1000 case 0x0146: return 0xF1; /* LATIN SMALL LETTER N WITH CEDILLA */
1001 case 0x014D: return 0xF2; /* LATIN SMALL LETTER O WITH MACRON */
1002 case 0x0137: return 0xF3; /* LATIN SMALL LETTER K WITH CEDILLA */
1003 case 0x00F4: return 0xF4; /* LATIN SMALL LETTER O WITH CIRCUMFLEX */
1004 case 0x00F5: return 0xF5; /* LATIN SMALL LETTER O WITH TILDE */
1005 case 0x00F6: return 0xF6; /* LATIN SMALL LETTER O WITH DIAERESIS */
1006 case 0x00F7: return 0xF7; /* DIVISION SIGN */
1007 case 0x00F8: return 0xF8; /* LATIN SMALL LETTER O WITH STROKE */
1008 case 0x0173: return 0xF9; /* LATIN SMALL LETTER U WITH OGONEK */
1009 case 0x00FA: return 0xFA; /* LATIN SMALL LETTER U WITH ACUTE */
1010 case 0x00FB: return 0xFB; /* LATIN SMALL LETTER U WITH CIRCUMFLEX */
1011 case 0x00FC: return 0xFC; /* LATIN SMALL LETTER U WITH DIAERESIS */
1012 case 0x0169: return 0xFD; /* LATIN SMALL LETTER U WITH TILDE */
1013 case 0x016B: return 0xFE; /* LATIN SMALL LETTER U WITH MACRON */
1014 case 0x02D9: return 0xFF; /* DOT ABOVE */
1024 static unsigned int latin5_unicode_map1[] = {
1025 0x0080, 0x0081, 0x201a, 0x0192, 0x201e, 0x2026, 0x2020, 0x2021, /* 80 */
1026 0x02c6, 0x2030, 0x0160, 0x2039, 0x0152, 0x008d, 0x008e, 0x008f, /* 88 */
1027 0x0090, 0x2018, 0x2019, 0x201c, 0x201d, 0x2022, 0x2013, 0x2014, /* 90 */
1028 0x02dc, 0x2122, 0x0161, 0x203a, 0x0153, 0x009d, 0x009e, 0x0178, /* 98 */
1030 static unsigned int latin5_unicode_map2[] = {
1031 0x011e, 0x00d1, 0x00d2, 0x00d3, 0x00d4, 0x00d5, 0x00d6, 0x00d7, /* D0 */
1032 0x00d8, 0x00d9, 0x00da, 0x00db, 0x00dc, 0x0130, 0x015e, 0x00df, /* D8 */
1033 0x00e0, 0x00e1, 0x00e2, 0x00e3, 0x00e4, 0x00e5, 0x00e6, 0x00e7, /* E0 direct */
1034 0x00e8, 0x00e9, 0x00ea, 0x00eb, 0x00ec, 0x00ed, 0x00ee, 0x00ef, /* E8 direct */
1035 0x011f, 0x00f1, 0x00f2, 0x00f3, 0x00f4, 0x00f5, 0x00f6, 0x00f7, /* F0 */
1036 0x00f8, 0x00f9, 0x00fa, 0x00fb, 0x00fc, 0x0131, 0x015f, 0x00ff, /* F8 */
1039 for(i=0; i<=0x7F; i++)
1042 for(i=0x80; i<=0x9F; i++)
1043 unicode_map[i] = latin5_unicode_map1[i-0x80];
1045 for(i=0xA0; i<=0xCF; i++)
1048 for(i=0xD0; i<=0xFF; i++)
1049 unicode_map[i] = latin5_unicode_map2[i-0xD0];
1052 /* a way to select one 256-character plane from Unicode
1053 * or other multi-byte encoding
1061 static unsigned plane;
1065 if(uni_lang_selected == 0)
1066 return; /* don't participate in auto-guessing */
1068 plane = 0; force_pid = force_eid = -1;
1070 c1 = sscanf(arg, "pid=%d,eid=%d%n", &force_pid, &force_eid, &nchars);
1076 if(arg[0] == '0' && (arg[1]=='x' || arg[1]=='X') ) {
1078 c2 = sscanf(arg, "%x", &plane);
1080 c2 = sscanf(arg, "%d", &plane);
1083 if( (c1!=2 && c1!=0) || (c1==0 && c2==0) ) {
1084 fprintf(stderr, "**** option -l plane expects one of the following formats:\n");
1085 fprintf(stderr, " -l plane+0xNN - select hexadecimal number of plane of Unicode\n");
1086 fprintf(stderr, " -l plane+NN - select decimal number of plane of Unicode\n");
1087 fprintf(stderr, " -l plane+pid=N,eid=N - select plane 0 of specified encoding\n");
1088 fprintf(stderr, " -l plane+pid=N,eid=N,0xNN - select hex plane of TTF encoding with this PID/EID\n");
1089 fprintf(stderr, " -l plane+pid=N,eid=N,NN - select decimal plane of TTF encoding with this PID/EID\n");
1094 if(strlen(arg) > sizeof(uni_suffix_buf)-2) {
1095 fprintf(stderr, "**** plane number is too large\n");
1098 sprintf(uni_suffix_buf, "-%s", arg);
1099 uni_font_name_suffix = uni_suffix_buf;
1101 uni_font_name_suffix = "";
1105 for(i=0; i<=0xFF; i++)
1106 unicode_map[i] = plane | i;
1109 /* look up the 8-bit code by unicode */
1118 if( ! IS_UNI_BUCKET(unival) )
1121 for (res = 0; res < enctabsz; res++)
1122 if (unicode_map[res] == unival)
1127 /* mark the buckets for quick lookup */
1130 unicode_prepare_buckets(
1136 memset(uni_user_buckets, 0, sizeof uni_user_buckets);
1137 for(i=0; i<enctabsz; i++) {
1138 if(unicode_map[i] != (unsigned) -1)
1139 MARK_UNI_BUCKET(unicode_map[i]);
1144 * When we print errors about bad names we want to print these names in
1145 * some decent-looking form
1153 static char res[50];
1156 for(i=0; ( c =* s )!=0 && i<sizeof(res)-8; s++) {
1157 if(c < ' ' || c > 126) {
1158 sprintf(res+i, "\\x%02X", c);
1174 * Scale the values according to the scale_factor
1182 return scale_factor * val;
1190 return (int) (val > 0 ? scale_factor * val + 0.5
1191 : scale_factor * val - 0.5);
1195 * Try to force fixed width of characters
1202 int n = 0, avg, max = 0, min = 3000, sum = 0, x;
1204 for (i = 0; i < numglyphs; i++) {
1205 if (glyph_list[i].flags & GF_USED) {
1206 x = glyph_list[i].width;
1225 WARNING_3 fprintf(stderr, "widths: max=%d avg=%d min=%d\n", max, avg, min);
1227 /* if less than 5% variation from average */
1228 /* force fixed width */
1229 if (20 * (avg - min) < avg && 20 * (max - avg) < avg) {
1230 for (i = 0; i < numglyphs; i++) {
1231 if (glyph_list[i].flags & GF_USED)
1232 glyph_list[i].width = avg;
1234 fontm.is_fixed_pitch = 1;
1246 g = &glyph_list[glyphno];
1249 g->scaledwidth = iscale(g->width);
1254 if (g->ttf_pathlen != 0) {
1255 cursw->glpath(glyphno, glyph_list);
1259 dumppaths(g, NULL, NULL);
1261 assertpath(g->entries, __FILE__, __LINE__, g->name);
1264 assertpath(g->entries, __FILE__, __LINE__, g->name);
1266 /* float processing */
1269 assertpath(g->entries, __FILE__, __LINE__, g->name);
1272 assertpath(g->entries, __FILE__, __LINE__, g->name);
1275 assertpath(g->entries, __FILE__, __LINE__, g->name);
1278 assertpath(g->entries, __FILE__, __LINE__, g->name);
1282 /* all processing past this point expects integer path */
1283 assertpath(g->entries, __FILE__, __LINE__, g->name);
1290 /* int processing */
1293 assertpath(g->entries, __FILE__, __LINE__, g->name);
1299 for(ge = g->entries; ge; ge = ge->next)
1302 if (ncurves > 200) {
1303 WARNING_3 fprintf(stderr,
1304 "** Glyph %s is too long, may display incorrectly\n",
1308 /* for buildstems */
1309 g->flags &= ~GF_FLOAT;
1316 int i, n, found, c, type;
1318 /* get the names from the font file */
1319 ps_fmt_3 = cursw->glnames(glyph_list);
1321 /* check for names with wrong characters */
1322 for (n = 0; n < numglyphs; n++) {
1324 for (i = 0; (c = glyph_list[n].name[i]) != 0; i++) {
1325 if (!(isalnum(c) || c == '.' || c == '_' || c == '-')
1326 || i==0 && isdigit(c)) { /* must not start with a digit */
1327 WARNING_3 fprintf(stderr, "Glyph %d %s (%s), ",
1328 n, isdigit(c) ? "name starts with a digit" :
1329 "has bad characters in name",
1330 nametoprint(glyph_list[n].name));
1331 glyph_list[n].name = malloc(16);
1332 sprintf(glyph_list[n].name, "_b_%d", n);
1333 WARNING_3 fprintf(stderr, "changing to %s\n", glyph_list[n].name);
1340 /* check for duplicate names */
1341 for (n = 0; n < numglyphs; n++) {
1343 for (i = 0; i < n && !found; i++) {
1344 if (strcmp(glyph_list[i].name, glyph_list[n].name) == 0) {
1345 if (( glyph_list[n].name = malloc(16) )==0) {
1346 fprintf (stderr, "****malloc failed %s line %d\n", __FILE__, __LINE__);
1349 sprintf(glyph_list[n].name, "_d_%d", n);
1351 /* if the font has no names in it (what the native parser
1352 * recognises as ps_fmt_3), FreeType returns all the
1353 * names as .notdef, so don't complain in this case
1355 if(strcmp(glyph_list[i].name, ".notdef")) {
1356 WARNING_3 fprintf(stderr,
1357 "Glyph %d has the same name as %d: (%s), changing to %s\n",
1360 glyph_list[n].name);
1369 /* start the encoding stuff */
1370 for (i = 0; i < ENCTABSZ; i++) {
1374 /* do the 1st round of encoding by name */
1375 if(!ps_fmt_3 && uni_lang_selected && uni_lang_selected->convbyname) {
1376 for (n = 0; n < numglyphs; n++) {
1377 c = uni_lang_selected->convbyname(glyph_list[n].name,
1378 uni_lang_arg, UNICONV_BYNAME_BEFORE);
1379 if(c>=0 && c<ENCTABSZ && encoding[c] == -1)
1384 /* now do the encoding by table */
1385 if(uni_lang_selected) {
1386 for(i=0; i < MAXUNITABLES && uni_lang_selected->init[i]; i++) {
1387 for (n = 0; n < ENCTABSZ; n++)
1388 unicode_map[n] = -1;
1389 uni_lang_selected->init[i](uni_lang_arg);
1390 unicode_prepare_buckets();
1391 type = cursw->glenc(glyph_list, encoding, unicode_map);
1393 /* if we have an 8-bit encoding we don't need more tries */
1397 /* language is unknown, try the first table of each */
1398 for(i=0; i < sizeof uni_lang/(sizeof uni_lang[0]); i++) {
1399 if(uni_lang[i].init[0] == NULL)
1401 for (n = 0; n < ENCTABSZ; n++)
1402 unicode_map[n] = -1;
1403 uni_lang[i].init[0](uni_lang_arg);
1404 unicode_prepare_buckets();
1405 type = cursw->glenc(glyph_list, encoding, unicode_map);
1407 /* if we have an 8-bit encoding we don't need more tries */
1413 /* get rid of the old names, they are all "UNKNOWN" anyawy */
1414 for (i = 0; i < numglyphs; i++) {
1415 glyph_list[i].name = 0;
1418 /* 8-bit - give 8859/1 names to the first 256 glyphs */
1419 for (i = 0; i < 256; i++) { /* here 256, not ENCTABSZ */
1420 if (encoding[i] > 0) {
1421 glyph_list[encoding[i]].name = Fmt3Encoding[i];
1424 } else if(type == 1) {
1425 /* Unicode - give 8859/1 names to the first 256 glyphs of Unicode */
1426 for (n = 0; n < 256; n++) { /* here 256, not ENCTABSZ */
1427 i = unicode_rev_lookup(n);
1428 if (i>=0 && encoding[i] > 0) {
1429 glyph_list[encoding[i]].name = Fmt3Encoding[i];
1432 } /* for other types of encodings just give generated names */
1433 /* assign unique names to the rest of the glyphs */
1434 for (i = 0; i < numglyphs; i++) {
1435 if (glyph_list[i].name == 0) {
1436 if (( glyph_list[i].name = malloc(16) )==0) {
1437 fprintf (stderr, "****malloc failed %s line %d\n", __FILE__, __LINE__);
1440 sprintf(glyph_list[i].name, "_d_%d", i);
1445 /* do the 2nd round of encoding by name */
1446 if(uni_lang_selected && uni_lang_selected->convbyname) {
1447 for (n = 0; n < numglyphs; n++) {
1448 c = uni_lang_selected->convbyname(glyph_list[n].name,
1449 uni_lang_arg, UNICONV_BYNAME_AFTER);
1450 if(c>=0 && c<ENCTABSZ && encoding[c] == -1)
1454 /* all the encoding things are done */
1456 for (i = 0; i < ENCTABSZ; i++)
1457 if(encoding[i] == -1) {
1458 /* check whether this character might be a duplicate
1459 * (in which case it would be missed by unicode_rev_lookup())
1462 if((type != 0 || forcemap) && c != -1) {
1463 for(n = 0; n < i; n++) {
1464 if(unicode_map[n] == c) {
1465 encoding[i] = encoding[n];
1469 if(encoding[i] == -1) /* still not found, defaults to .notdef */
1473 for (i = 0; i < 256; i++) /* here 256, not ENCTABSZ */
1474 glyph_list[encoding[i]].char_no = i;
1476 /* enforce two special cases defined in TTF manual */
1478 glyph_list[0].name = ".notdef";
1480 glyph_list[1].name = ".null";
1482 for (i = 0; i < ENCTABSZ; i++) {
1483 if ((encoding[i] != 0) && glyph_rename[i]) {
1484 glyph_list[encoding[i]].name = glyph_rename[i];
1495 # define fplop(txt) fputs(txt, stderr);
1500 fputs("Use:\n", stderr);
1501 fputs("ttf2pt1 [-<opts>] [-l language | -L file] <ttf-file> [<fontname>]\n", stderr);
1502 fputs(" or\n", stderr);
1503 fputs("ttf2pt1 [-<opts>] [-l language | -L file] <ttf-file> -\n", stderr);
1504 fputs(" or\n", stderr);
1505 fputs("ttf2pt1 [-<opts>] [-l language | -L file] <ttf-file> - | t1asm > <pfa-file>\n", stderr);
1508 fplop("This build supports both short and long option names,\n");
1509 fplop("the long options are listed before corresponding short ones\n");
1511 fplop(" --all-glyphs\n");
1512 fputs(" -a - include all glyphs, even those not in the encoding table\n", stderr);
1514 fputs(" -b - produce a compressed .pfb file\n", stderr);
1515 fplop(" --debug dbg_suboptions\n");
1516 fputs(" -d dbg_suboptions - debugging options, run ttf2pt1 -d? for help\n", stderr);
1517 fplop(" --encode\n");
1518 fputs(" -e - produce a fully encoded .pfa file\n", stderr);
1519 fplop(" --force-unicode\n");
1520 fputs(" -F - force use of Unicode encoding even if other MS encoding detected\n", stderr);
1521 fplop(" --generate suboptions\n");
1522 fputs(" -G suboptions - control the file generation, run ttf2pt1 -G? for help\n", stderr);
1523 fplop(" --language language\n");
1524 fputs(" -l language - convert Unicode to specified language, run ttf2pt1 -l? for list\n", stderr);
1525 fplop(" --language-map file\n");
1526 fputs(" -L file - convert Unicode according to encoding description file\n", stderr);
1527 fplop(" --limit <type>=<value>\n");
1528 fputs(" -m <type>=<value> - set maximal limit of given type to value, types:\n", stderr);
1529 fputs(" h - maximal hint stack depth in the PostScript interpreter\n", stderr);
1530 fplop(" --processing suboptions\n");
1531 fputs(" -O suboptions - control outline processing, run ttf2pt1 -O? for help\n", stderr);
1532 fplop(" --parser name\n");
1533 fputs(" -p name - use specific front-end parser, run ttf2pt1 -p? for list\n", stderr);
1534 fplop(" --uid id\n");
1535 fputs(" -u id - use this UniqueID, -u A means autogeneration\n", stderr);
1536 fplop(" --vertical-autoscale size\n");
1537 fputs(" -v size - scale the font to make uppercase letters >size/1000 high\n", stderr);
1538 fplop(" --version\n");
1539 fputs(" -V - print ttf2pt1 version number\n", stderr);
1540 fplop(" --warning number\n");
1541 fputs(" -W number - set the level of permitted warnings (0 - disable)\n", stderr);
1542 fputs("Obsolete options (will be removed in future releases):\n", stderr);
1544 fputs(" -A - write the .afm file to STDOUT instead of the font, now -GA\n", stderr);
1545 fputs(" -f - don't try to guess the value of the ForceBold hint, now -Ob\n", stderr);
1546 fputs(" -h - disable autogeneration of hints, now -Oh\n", stderr);
1547 fputs(" -H - disable hint substitution, now -Ou\n", stderr);
1548 fputs(" -o - disable outline optimization, now -Oo\n", stderr);
1549 fputs(" -s - disable outline smoothing, now -Os\n", stderr);
1550 fputs(" -t - disable auto-scaling to 1000x1000 standard matrix, now -Ot\n", stderr);
1551 fputs(" -w - correct the glyph widths (use only for buggy fonts), now -OW\n", stderr);
1552 fputs("With no <fontname>, write to <ttf-file> with suffix replaced.\n", stderr);
1553 fputs("The last '-' means 'use STDOUT'.\n", stderr);
1562 fprintf(stderr, "ttf2pt1 %s\n", TTF2PT1_VERSION);
1565 /* initialize a table of suboptions */
1568 struct subo_case *tbl
1573 for(i=0; tbl[i].disbl != 0; i++) {
1574 tbl[i].disbl = tolower(tbl[i].disbl);
1575 tbl[i].enbl = toupper(tbl[i].disbl);
1576 *(tbl[i].valp) = tbl[i].dflt;
1580 /* print the default value of the suboptions */
1584 struct subo_case *tbl
1589 for(i=0; tbl[i].disbl != 0; i++) {
1591 putc(tbl[i].enbl, f);
1593 putc(tbl[i].disbl, f);
1597 /* print the usage message for the suboptions */
1601 struct subo_case *tbl
1606 fprintf(f,"The lowercase suboptions disable features, corresponding\n");
1607 fprintf(f,"uppercase suboptions enable them. The supported suboptions,\n");
1608 fprintf(f,"their default states and the features they control are:\n");
1609 for(i=0; tbl[i].disbl != 0; i++) {
1610 fprintf(f," %c/%c - [%s] %s\n", tbl[i].disbl, tbl[i].enbl,
1611 tbl[i].dflt ? "enabled" : "disabled", tbl[i].descr);
1615 /* find and set the entry according to suboption,
1616 * return the found entry (or if not found return NULL)
1620 struct subo_case *tbl,
1626 for(i=0; tbl[i].disbl != 0; i++) {
1627 if(subopt == tbl[i].disbl) {
1630 } else if(subopt == tbl[i].enbl) {
1647 char filename[4096];
1648 int c,nchars,nmetrics;
1650 int forcebold= -1; /* -1 means "don't know" */
1656 # define ttf2pt1_getopt(a, b, c, d, e) getopt_long(a, b, c, d, e)
1657 static struct option longopts[] = {
1658 { "afm", 0, NULL, 'A' },
1659 { "all-glyphs", 0, NULL, 'a' },
1660 { "pfb", 0, NULL, 'b' },
1661 { "debug", 1, NULL, 'd' },
1662 { "encode", 0, NULL, 'e' },
1663 { "force-unicode", 0, NULL, 'F' },
1664 { "generate", 1, NULL, 'G' },
1665 { "language", 1, NULL, 'l' },
1666 { "language-map", 1, NULL, 'L' },
1667 { "limit", 1, NULL, 'm' },
1668 { "processing", 1, NULL, 'O' },
1669 { "parser", 1, NULL, 'p' },
1670 { "uid", 1, NULL, 'u' },
1671 { "vertical-autoscale", 1, NULL, 'v' },
1672 { "version", 0, NULL, 'V' },
1673 { "warning", 1, NULL, 'W' },
1674 { NULL, 0, NULL, 0 }
1677 # define ttf2pt1_getopt(a, b, c, d, e) getopt(a, b, c)
1679 /* table of Outline Processing (may think also as Optimization) options */
1680 static struct subo_case opotbl[] = {
1681 { 'b', 0/*auto-set*/, &trybold, 1, "guessing of the ForceBold hint" },
1682 { 'h', 0/*auto-set*/, &hints, 1, "autogeneration of hints" },
1683 { 'u', 0/*auto-set*/, &subhints, 1, "hint substitution technique" },
1684 { 'o', 0/*auto-set*/, &optimize, 1, "space optimization of font files" },
1685 { 's', 0/*auto-set*/, &smooth, 1, "smoothing and repair of outlines" },
1686 { 't', 0/*auto-set*/, &transform, 1, "auto-scaling to the standard matrix 1000x1000" },
1687 { 'w', 0/*auto-set*/, &correctwidth, 0, "correct the glyph widths (use only for buggy fonts)" },
1688 { 'v', 0/*auto-set*/, &vectorize, 0, "vectorize (trace) the bitmaps" },
1689 #ifdef USE_AUTOTRACE
1690 { 'z', 0/*auto-set*/, &use_autotrace, 0, "use the autotrace library on bitmaps (works badly)" },
1691 #endif /*USE_AUTOTRACE*/
1692 { 0, 0, 0, 0, 0} /* terminator */
1694 /* table of the File Generation options */
1695 static struct subo_case fgotbl[] = {
1696 { 'f', 0/*auto-set*/, &gen_pfa, 1, "generate the font file (.t1a, .pfa or .pfb)" },
1697 { 'a', 0/*auto-set*/, &gen_afm, 1, "generate the Adobe metrics file (.afm)" },
1698 { 'e', 0/*auto-set*/, &gen_dvienc, 0, "generate the dvips encoding file (.enc)" },
1699 { 0, 0, 0, 0, 0} /* terminator */
1701 int *genlast = NULL;
1704 init_subo_tbl(opotbl); /* initialize sub-options of -O */
1705 init_subo_tbl(fgotbl); /* initialize sub-options of -G */
1707 /* save the command line for the record
1708 * (we don't bother about escaping the shell special characters)
1712 for(i=1; i<argc; i++) {
1713 j += strlen(argv[i])+1;
1715 if ((cmdline = malloc(j+1)) == NULL) {
1716 fprintf (stderr, "****malloc failed %s line %d\n", __FILE__, __LINE__);
1720 for(i=1; i<argc; i++) {
1721 strcat(cmdline, argv[i]);
1722 strcat(cmdline, " ");
1724 for(i=0; (j=cmdline[i])!=0; i++)
1729 while(( oc=ttf2pt1_getopt(argc, argv, "FaoebAsthHfwVv:p:l:d:u:L:m:W:O:G:",
1730 longopts, NULL) )!= -1) {
1733 if(sscanf(optarg, "%d", &warnlevel) < 1 || warnlevel < 0) {
1734 fprintf(stderr, "**** warning level must be a positive number\n");
1742 fputs("Warning: option -o is obsolete, use -Oo instead\n", stderr);
1749 encode = pfbflag = 1;
1752 fputs("Warning: option -A is obsolete, use -GA instead\n", stderr);
1759 fputs("Warning: option -s is obsolete, use -Os instead\n", stderr);
1763 fputs("Warning: option -t is obsolete, use -Ot instead\n", stderr);
1767 for(i=0; optarg[i]!=0; i++)
1776 if (optarg[i] != '?')
1777 fprintf(stderr, "**** Unknown debugging option '%c' ****\n", optarg[i]);
1778 fputs("The recognized debugging options are:\n", stderr);
1779 fputs(" a - enable absolute coordinates\n", stderr);
1780 fputs(" r - do not reverse font outlines directions\n", stderr);
1790 if(sscanf(optarg, "%c=%d", &subopt, &val) !=2) {
1791 fprintf(stderr, "**** Misformatted maximal limit ****\n");
1792 fprintf(stderr, "spaces around the equal sign are not allowed\n");
1793 fprintf(stderr, "good examples: -mh=100 -m h=100\n");
1794 fprintf(stderr, "bad examples: -mh = 100 -mh= 100\n");
1800 max_stemdepth = val;
1804 fprintf(stderr, "**** Unknown limit type '%c' ****\n", subopt);
1805 fputs("The recognized limit types are:\n", stderr);
1806 fputs(" h - maximal hint stack depth in the PostScript interpreter\n", stderr);
1815 for(p=optarg; *p != 0; p++) {
1816 if(set_subo(opotbl, *p) == NULL) { /* found no match */
1818 fprintf(stderr, "**** Unknown outline processing suboption '%c' ****\n", *p);
1819 fprintf(stderr,"The general form of the outline processing option is:\n");
1820 fprintf(stderr," -O suboptions\n");
1821 fprintf(stderr,"(To remember easily -O may be also thought of as \"optimization\").\n");
1822 print_subo_usage(stderr, opotbl);
1823 fprintf(stderr, "The default state corresponds to the option -O ");
1824 print_subo_dflt(stderr, opotbl);
1825 fprintf(stderr, "\n");
1834 struct subo_case *s;
1836 for(p=optarg; *p != 0; p++) {
1837 if(( s = set_subo(fgotbl, *p) )==NULL) { /* found no match */
1839 fprintf(stderr, "**** Unknown outline processing suboption '%c' ****\n", *p);
1840 fprintf(stderr,"The general form of the file generation option is:\n");
1841 fprintf(stderr," -G suboptions\n");
1842 print_subo_usage(stderr, fgotbl);
1843 fprintf(stderr, "The default state corresponds to the option -G ");
1844 print_subo_dflt(stderr, fgotbl);
1845 fprintf(stderr, "\n");
1846 fprintf(stderr, "If the result is written to STDOUT, the last specified enabling suboption of -G\n");
1847 fprintf(stderr, "selects the file to be written to STDOUT (the font file by default).\n");
1856 fputs("Warning: option -h is obsolete, use -Oh instead\n", stderr);
1860 fputs("Warning: meaning of option -H has been changed to its opposite\n", stderr);
1861 fputs("Warning: option -H is obsolete, use -Ou instead\n", stderr);
1865 fputs("Warning: option -f is obsolete, use -Ob instead\n", stderr);
1869 fputs("Warning: option -w is obsolete, use -OW instead\n", stderr);
1874 fprintf(stderr, "**** UniqueID may be specified only once ****\n");
1878 if(optarg[0]=='A' && optarg[1]==0)
1879 strUID=0; /* will be generated automatically */
1882 for(i=0; optarg[i]!=0; i++)
1883 if( !isdigit(optarg[i]) ) {
1884 fprintf(stderr, "**** UniqueID must be numeric or A for automatic ****\n");
1890 correctvsize = atoi(optarg);
1891 if(correctvsize <= 0 && correctvsize > 1000) {
1892 fprintf(stderr, "**** wrong vsize '%d', ignored ****\n", correctvsize);
1898 fprintf(stderr, "**** only one front-end parser be used ****\n");
1902 { /* separate parser from parser-specific argument */
1903 char *p = strchr(optarg, LANG_ARG_SEP);
1910 for(i=0; frontswtab[i] != NULL; i++)
1911 if( !strcmp(frontswtab[i]->name, optarg) ) {
1912 cursw = frontswtab[i];
1917 if (strcmp(optarg, "?"))
1918 fprintf(stderr, "**** unknown front-end parser '%s' ****\n", optarg);
1919 fputs("the following front-ends are supported now:\n", stderr);
1920 for(i=0; frontswtab[i] != NULL; i++) {
1921 fprintf(stderr," %s (%s)\n file suffixes: ",
1922 frontswtab[i]->name,
1923 frontswtab[i]->descr ? frontswtab[i]->descr : "no description"
1925 for(j=0; j<MAXSUFFIX; j++)
1926 if(frontswtab[i]->suffix[j])
1927 fprintf(stderr, "%s ", frontswtab[i]->suffix[j]);
1928 fprintf(stderr, "\n");
1934 if(uni_lang_selected!=0) {
1935 fprintf(stderr, "**** only one language option may be used ****\n");
1939 { /* separate language from language-specific argument */
1940 char *p = strchr(optarg, LANG_ARG_SEP);
1947 for(i=0; i < sizeof uni_lang/(sizeof uni_lang[0]); i++)
1948 if( !strcmp(uni_lang[i].name, optarg) ) {
1949 uni_lang_selected = &uni_lang[i];
1950 uni_sample = uni_lang[i].sample_upper;
1954 if(uni_lang_selected==0) {
1955 if (strcmp(optarg, "?"))
1956 fprintf(stderr, "**** unknown language '%s' ****\n", optarg);
1957 fputs(" the following languages are supported now:\n", stderr);
1958 for(i=0; i < sizeof uni_lang/(sizeof uni_lang[0]); i++)
1959 fprintf(stderr," %s (%s)\n",
1961 uni_lang[i].descr ? uni_lang[i].descr : "no description"
1967 if(uni_lang_selected!=0) {
1968 fprintf(stderr, "**** only one language option may be used ****\n");
1971 uni_lang_selected = &uni_lang_user;
1972 uni_lang_arg = optarg;
1984 argc-=optind-1; /* the rest of code counts from argv[0] */
1987 if (absolute && encode) {
1988 fprintf(stderr, "**** options -a and -e are incompatible ****\n");
1991 if ((argc != 2) && (argc != 3)) {
1996 /* try to guess the language by the locale used */
1997 if(uni_lang_selected==0 && (lang=getenv("LANG"))!=0 ) {
1998 for(i=0; i < sizeof uni_lang/sizeof(struct uni_language); i++) {
1999 if( !strncmp(uni_lang[i].name, lang, strlen(uni_lang[i].name)) ) {
2000 uni_lang_selected = &uni_lang[i];
2001 goto got_a_language;
2004 /* no full name ? try aliases */
2005 for(i=0; i < sizeof uni_lang/sizeof(struct uni_language); i++) {
2006 for(c=0; c<MAXUNIALIAS; c++)
2007 if( uni_lang[i].alias[c]!=0
2008 && !strncmp(uni_lang[i].alias[c], lang, strlen(uni_lang[i].alias[c])) ) {
2009 uni_lang_selected = &uni_lang[i];
2010 goto got_a_language;
2014 if(uni_lang_selected!=0) {
2015 WARNING_1 fprintf(stderr, "Using language '%s' for Unicode fonts\n", uni_lang[i].name);
2016 uni_sample = uni_lang[i].sample_upper;
2020 /* try to guess the front-end parser by the file name suffix */
2022 char *p = strrchr(argv[1], '.');
2025 if(p!=0 && (s = strdup(p+1))!=0) {
2030 for(i=0; frontswtab[i] != 0 && cursw == 0; i++) {
2031 for(j=0; j<MAXSUFFIX; j++)
2032 if(frontswtab[i]->suffix[j]
2033 && !strcmp(p, frontswtab[i]->suffix[j]) ) {
2034 cursw = frontswtab[i];
2035 WARNING_1 fprintf(stderr, "Auto-detected front-end parser '%s'\n",
2037 WARNING_1 fprintf(stderr, " (use ttf2pt1 -p? to get the full list of available front-ends)\n");
2045 cursw = frontswtab[0];
2046 WARNING_1 fprintf(stderr, "Can't detect front-end parser, using '%s' by default\n",
2048 WARNING_1 fprintf(stderr, " (use ttf2pt1 -p? to get the full list of available front-ends)\n");
2052 /* open the input file */
2053 cursw->open(argv[1], front_arg);
2055 /* Get base name of output file (if not specified)
2056 * by removing (known) suffixes
2060 argv[2] = strdup (argv[1]);
2061 p = strrchr(argv[2], '.');
2063 for (j = 0; (j < MAXSUFFIX) && (cursw->suffix[j]); j++)
2064 if (!strcmp(p+1, cursw->suffix[j])) {
2070 if ((null_file = fopen(BITBUCKET, "w")) == NULL) {
2071 fprintf(stderr, "**** Cannot open %s ****\n",
2076 if (argv[2][0] == '-' && argv[2][1] == 0) {
2079 fprintf(stderr, "**** can't write encoded file to stdout ***\n");
2083 pfa_file = afm_file = dvienc_file = null_file;
2085 if(wantafm || genlast == &gen_afm) { /* print .afm instead of .pfa */
2087 } else if(genlast == &gen_dvienc) { /* print .enc instead of .pfa */
2094 snprintf(filename, sizeof filename, "%s.%s", argv[2], encode ? (pfbflag ? "pfb" : "pfa") : "t1a" );
2096 snprintf(filename, sizeof filename, "%s.t1a", argv[2]);
2099 if ((pfa_file = fopen(filename, "w+b")) == NULL) {
2100 fprintf(stderr, "**** Cannot create %s ****\n", filename);
2103 WARNING_2 fprintf(stderr, "Creating file %s\n", filename);
2106 pfa_file = null_file;
2109 snprintf(filename, sizeof filename, "%s.afm", argv[2]) ;
2110 if ((afm_file = fopen(filename, "w+")) == NULL) {
2111 fprintf(stderr, "**** Cannot create %s ****\n", filename);
2115 afm_file = null_file;
2118 snprintf(filename, sizeof filename, "%s.enc", argv[2]) ;
2119 if ((dvienc_file = fopen(filename, "w+")) == NULL) {
2120 fprintf(stderr, "**** Cannot create %s ****\n", filename);
2124 dvienc_file = null_file;
2128 * Now check whether we want a fully encoded .pfa file
2131 if (encode && pfa_file != null_file) {
2133 extern FILE *ifp, *ofp; /* from t1asm.c */
2139 perror("**** Cannot create pipe ****\n");
2143 ifp = fdopen(p[0], "r");
2145 perror("**** Cannot use pipe for reading ****\n");
2148 pfa_file = fdopen(p[1], "w");
2149 if (pfa_file == NULL) {
2150 perror("**** Cannot use pipe for writing ****\n");
2155 perror("**** Cannot fork the assembler process ****\n");
2159 exit(runt1asm(pfbflag));
2160 default: /* parent */
2161 fclose(ifp); fclose(ofp);
2166 numglyphs = cursw->nglyphs();
2168 WARNING_3 fprintf(stderr, "numglyphs = %d\n", numglyphs);
2170 glyph_list = (GLYPH *) calloc(numglyphs, sizeof(GLYPH));
2172 /* initialize non-0 fields */
2173 for (i = 0; i < numglyphs; i++) {
2179 g->name = "UNKNOWN";
2180 g->flags = GF_FLOAT; /* we start with float representation */
2185 cursw->glmetrics(glyph_list);
2186 cursw->fnmetrics(&fontm);
2188 original_scale_factor = 1000.0 / (double) fontm.units_per_em;
2191 scale_factor = 1.0; /* don't transform */
2193 scale_factor = original_scale_factor;
2195 if(correctvsize && uni_sample!=0) { /* only for known languages */
2196 /* try to adjust the scale factor to make a typical
2197 * uppercase character of hight at least (correctvsize), this
2198 * may improve the appearance of the font but also
2199 * make it weird, use with caution
2203 ysz = iscale(glyph_list[encoding[uni_sample]].yMax);
2204 if( ysz<correctvsize ) {
2205 scale_factor *= (double)correctvsize / ysz;
2210 for (i = 0; i < numglyphs; i++) {
2211 glyph_list[i].flags |= GF_USED;
2214 for (i = 0; i < ENCTABSZ; i++) {
2215 glyph_list[encoding[i]].flags |= GF_USED;
2218 /* also always include .notdef */
2219 for (i = 0; i < numglyphs; i++)
2220 if(!strcmp(glyph_list[i].name, ".notdef")) {
2221 glyph_list[i].flags |= GF_USED;
2226 for (i = 0; i < numglyphs; i++) {
2227 if (glyph_list[i].flags & GF_USED) {
2228 DBG_TO_GLYPH(&glyph_list[i]);
2230 DBG_FROM_GLYPH(&glyph_list[i]);
2234 italic_angle = fontm.italic_angle;
2236 if (italic_angle > 45.0 || italic_angle < -45.0)
2237 italic_angle = 0.0; /* consider buggy */
2241 for (i = 0; i < numglyphs; i++) {
2242 if (glyph_list[i].flags & GF_USED) {
2243 DBG_TO_GLYPH(&glyph_list[i]);
2244 buildstems(&glyph_list[i]);
2245 assertpath(glyph_list[i].entries, __FILE__, __LINE__, glyph_list[i].name);
2246 DBG_FROM_GLYPH(&glyph_list[i]);
2252 bbox[i] = iscale(fontm.bbox[i]);
2254 /* don't touch the width of fixed width fonts */
2255 if( fontm.is_fixed_pitch )
2257 docorrectwidth(); /* checks correctwidth inside */
2259 for (i = 0; i < numglyphs; i++) {
2260 if (glyph_list[i].flags & GF_USED) {
2261 DBG_TO_GLYPH(&glyph_list[i]);
2262 reversepaths(&glyph_list[i]);
2263 assertpath(glyph_list[i].entries, __FILE__, __LINE__, glyph_list[i].name);
2264 DBG_FROM_GLYPH(&glyph_list[i]);
2271 ** It seems to bring troubles. The problem is that some
2272 ** styles of the font may be recognized as fixed-width
2273 ** while other styles of the same font as proportional.
2274 ** So it's better to be commented out yet.
2281 forcebold = fontm.force_bold;
2284 fprintf(pfa_file, "%%!PS-AdobeFont-1.0: %s %s\n", fontm.name_ps, fontm.name_copyright);
2286 fprintf(pfa_file, "%%%%CreationDate: %s", ctime(&now));
2287 fprintf(pfa_file, "%% Converted by ttf2pt1 %s/%s\n", TTF2PT1_VERSION, cursw->name);
2288 fprintf(pfa_file, "%% Args: %s\n", cmdline);
2289 fprintf(pfa_file, "%%%%EndComments\n");
2290 fprintf(pfa_file, "12 dict begin\n/FontInfo 9 dict dup begin\n");
2292 WARNING_3 fprintf(stderr, "FontName %s%s\n", fontm.name_ps, uni_font_name_suffix);
2295 fprintf(pfa_file, "/version (%s) readonly def\n", fontm.name_version);
2297 fprintf(pfa_file, "/Notice (%s) readonly def\n", fontm.name_copyright);
2299 fprintf(pfa_file, "/FullName (%s) readonly def\n", fontm.name_full);
2300 fprintf(pfa_file, "/FamilyName (%s) readonly def\n", fontm.name_family);
2304 fprintf(pfa_file, "/UniqueID %s def\n", strUID);
2307 for(i=0; fontm.name_full[i]!=0; i++) {
2308 numUID *= 37; /* magic number, good for hash */
2309 numUID += fontm.name_full[i]-' ';
2310 /* if the name is long the first chars
2311 * may be lost forever, so re-insert
2312 * them thus making kind of CRC
2314 numUID += (numUID>>24) & 0xFF;
2316 /* the range for private UIDs is 4 000 000 - 4 999 999 */
2317 fprintf(pfa_file, "/UniqueID %lu def\n", numUID%1000000+4000000);
2321 fprintf(pfa_file, "/Weight (%s) readonly def\n", fontm.name_style);
2323 fprintf(pfa_file, "/ItalicAngle %f def\n", italic_angle);
2324 fprintf(pfa_file, "/isFixedPitch %s def\n",
2325 fontm.is_fixed_pitch ? "true" : "false");
2327 /* we don't print out the unused glyphs */
2329 for (i = 0; i < numglyphs; i++) {
2330 if (glyph_list[i].flags & GF_USED) {
2335 fprintf(afm_file, "StartFontMetrics 4.1\n");
2336 fprintf(afm_file, "FontName %s%s\n", fontm.name_ps, uni_font_name_suffix);
2337 fprintf(afm_file, "FullName %s\n", fontm.name_full);
2338 fprintf(afm_file, "Notice %s\n", fontm.name_copyright);
2339 fprintf(afm_file, "EncodingScheme FontSpecific\n");
2340 fprintf(afm_file, "FamilyName %s\n", fontm.name_family);
2341 fprintf(afm_file, "Weight %s\n", fontm.name_style);
2342 fprintf(afm_file, "Version %s\n", fontm.name_version);
2343 fprintf(afm_file, "Characters %d\n", nchars);
2344 fprintf(afm_file, "ItalicAngle %.1f\n", italic_angle);
2346 fprintf(afm_file, "Ascender %d\n", iscale(fontm.ascender));
2347 fprintf(afm_file, "Descender %d\n", iscale(fontm.descender));
2349 fprintf(pfa_file, "/UnderlinePosition %d def\n",
2350 iscale(fontm.underline_position));
2352 fprintf(pfa_file, "/UnderlineThickness %hd def\nend readonly def\n",
2353 iscale(fontm.underline_thickness));
2355 fprintf(afm_file, "UnderlineThickness %d\n",
2356 iscale(fontm.underline_thickness));
2358 fprintf(afm_file, "UnderlinePosition %d\n",
2359 iscale(fontm.underline_position));
2361 fprintf(afm_file, "IsFixedPitch %s\n",
2362 fontm.is_fixed_pitch ? "true" : "false");
2363 fprintf(afm_file, "FontBBox %d %d %d %d\n",
2364 bbox[0], bbox[1], bbox[2], bbox[3]);
2366 fprintf(pfa_file, "/FontName /%s%s def\n", fontm.name_ps, uni_font_name_suffix);
2367 fprintf(pfa_file, "/PaintType 0 def\n/StrokeWidth 0 def\n");
2368 /* I'm not sure if these are fixed */
2369 fprintf(pfa_file, "/FontType 1 def\n");
2372 fprintf(pfa_file, "/FontMatrix [0.001 0 0 0.001 0 0] def\n");
2374 fprintf(pfa_file, "/FontMatrix [%9.7f 0 0 %9.7f 0 0] def\n",
2375 original_scale_factor / 1000.0, original_scale_factor / 1000.0);
2378 fprintf(pfa_file, "/FontBBox {%d %d %d %d} readonly def\n",
2379 bbox[0], bbox[1], bbox[2], bbox[3]);
2381 fprintf(pfa_file, "/Encoding 256 array\n");
2382 /* determine number of elements for metrics table */
2384 for (i = 0; i < numglyphs; i++) {
2385 if( glyph_list[i].flags & GF_USED
2386 && glyph_list[i].char_no == -1 ) {
2390 fprintf(afm_file, "StartCharMetrics %d\n", nmetrics);
2392 fprintf(dvienc_file, "/%s%sEncoding [\n",
2393 fontm.name_ps, uni_font_name_suffix);
2395 for (i = 0; i < 256; i++) { /* here 256, not ENCTABSZ */
2397 "dup %d /%s put\n", i, glyph_list[encoding[i]].name);
2398 if( glyph_list[encoding[i]].flags & GF_USED ) {
2399 print_glyph_metrics(i, encoding[i]);
2402 fprintf (dvienc_file, "/index0x%04X\n", encoding[i]);
2404 fprintf (dvienc_file, "/.notdef\n");
2407 /* print the metrics for glyphs not in encoding table */
2408 for(i=0; i<numglyphs; i++) {
2409 if( (glyph_list[i].flags & GF_USED)
2410 && glyph_list[i].char_no == -1 ) {
2411 print_glyph_metrics(-1, i);
2415 fprintf(pfa_file, "readonly def\ncurrentdict end\ncurrentfile eexec\n");
2416 fprintf(pfa_file, "dup /Private 16 dict dup begin\n");
2418 fprintf(pfa_file, "/RD{string currentfile exch readstring pop}executeonly def\n");
2419 fprintf(pfa_file, "/ND{noaccess def}executeonly def\n");
2420 fprintf(pfa_file, "/NP{noaccess put}executeonly def\n");
2422 /* UniqueID must be shown twice, in both font and Private dictionary */
2425 fprintf(pfa_file, "/UniqueID %s def\n", strUID);
2427 /* the range for private UIDs is 4 000 000 - 4 999 999 */
2428 fprintf(pfa_file, "/UniqueID %lu def\n", numUID%1000000+4000000);
2432 fprintf(pfa_file, "/ForceBold false def\n");
2433 else if(forcebold==1)
2434 fprintf(pfa_file, "/ForceBold true def\n");
2436 fprintf(pfa_file, "/BlueValues [ ");
2437 for (i = 0; i < nblues; i++)
2438 fprintf(pfa_file, "%d ", bluevalues[i]);
2439 fprintf(pfa_file, "] def\n");
2441 fprintf(pfa_file, "/OtherBlues [ ");
2442 for (i = 0; i < notherb; i++)
2443 fprintf(pfa_file, "%d ", otherblues[i]);
2444 fprintf(pfa_file, "] def\n");
2447 fprintf(pfa_file, "/StdHW [ %d ] def\n", stdhw);
2449 fprintf(pfa_file, "/StdVW [ %d ] def\n", stdvw);
2450 fprintf(pfa_file, "/StemSnapH [ ");
2451 for (i = 0; i < 12 && stemsnaph[i] != 0; i++)
2452 fprintf(pfa_file, "%d ", stemsnaph[i]);
2453 fprintf(pfa_file, "] def\n");
2454 fprintf(pfa_file, "/StemSnapV [ ");
2455 for (i = 0; i < 12 && stemsnapv[i] != 0; i++)
2456 fprintf(pfa_file, "%d ", stemsnapv[i]);
2457 fprintf(pfa_file, "] def\n");
2459 fprintf(pfa_file, "/MinFeature {16 16} def\n");
2460 /* Are these fixed also ? */
2461 fprintf(pfa_file, "/password 5839 def\n");
2463 /* calculate the number of subroutines */
2466 for (i = 0; i < numglyphs; i++) {
2467 if (glyph_list[i].flags & GF_USED) {
2468 subid+=glyph_list[i].nsg;
2472 fprintf(pfa_file, "/Subrs %d array\n", subid);
2473 /* standard subroutines */
2474 fprintf(pfa_file, "dup 0 {\n\t3 0 callothersubr pop pop setcurrentpoint return\n\t} NP\n");
2475 fprintf(pfa_file, "dup 1 {\n\t0 1 callothersubr return\n\t} NP\n");
2476 fprintf(pfa_file, "dup 2 {\n\t0 2 callothersubr return\n\t} NP\n");
2477 fprintf(pfa_file, "dup 3 {\n\treturn\n\t} NP\n");
2478 /* our sub to make the hint substitution code shorter */
2479 fprintf(pfa_file, "dup 4 {\n\t1 3 callothersubr pop callsubr return\n\t} NP\n");
2481 if(pfa_file != null_file) { /* save time if the output would be wasted */
2482 /* print the hinting subroutines */
2484 for (i = 0; i < numglyphs; i++) {
2485 if (glyph_list[i].flags & GF_USED) {
2486 subid+=print_glyph_subs(i, subid);
2490 fprintf(pfa_file, "ND\n");
2492 fprintf(pfa_file, "2 index /CharStrings %d dict dup begin\n", nchars);
2494 for (i = 0; i < numglyphs; i++) {
2495 if (glyph_list[i].flags & GF_USED) {
2502 fprintf(pfa_file, "end\nend\nreadonly put\n");
2503 fprintf(pfa_file, "noaccess put\n");
2504 fprintf(pfa_file, "dup/FontName get exch definefont pop\n");
2505 fprintf(pfa_file, "mark currentfile closefile\n");
2506 fprintf(pfa_file, "cleartomark\n");
2507 if(pfa_file != null_file)
2510 fprintf(afm_file, "EndCharMetrics\n");
2512 if(afm_file != null_file) { /* save time if the output would be wasted */
2513 /* print the kerning data if present */
2514 cursw->kerning(glyph_list);
2515 print_kerning(afm_file);
2518 fprintf(afm_file, "EndFontMetrics\n");
2519 if(afm_file != null_file)
2522 fprintf(dvienc_file, "] def\n");
2523 if(dvienc_file != null_file)
2524 fclose(dvienc_file);
2526 WARNING_1 fprintf(stderr, "Finished - font files created\n");
2531 while (wait(&ws) > 0) {
2534 if (encode && pfa_file != null_file) {
2535 extern FILE *ifp, *ofp; /* from t1asm.c */
2537 snprintf(filename, sizeof filename, "%s.%s", argv[2], pfbflag ? "pfb" : "pfa" );
2539 if ((ofp = fopen(filename, "w+b")) == NULL) {
2540 fprintf(stderr, "**** Cannot create %s ****\n", filename);
2543 WARNING_2 fprintf(stderr, "Creating file %s\n", filename);
2546 snprintf(filename, sizeof filename, "%s.t1a", argv[2]);
2548 if ((ifp = fopen(filename, "rb")) == NULL) {
2549 fprintf(stderr, "**** Cannot read %s ****\n", filename);
2552 WARNING_2 fprintf(stderr, "Converting file %s\n", filename);
2557 WARNING_2 fprintf(stderr, "Removing file %s\n", filename);
2558 if(unlink(filename) < 0)
2559 WARNING_1 fprintf(stderr, "Unable to remove file %s\n", filename);