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 */
117 struct frontsw *cursw=0; /* the active front end */
118 char *front_arg=""; /* optional argument */
121 int encode = 0; /* encode the resulting file */
122 int pfbflag = 0; /* produce compressed file */
123 int wantafm=0; /* want to see .afm instead of .t1a on stdout */
124 int correctvsize=0; /* try to correct the vertical size of characters */
125 int wantuid = 0; /* user wants UniqueID entry in the font */
126 int allglyphs = 0; /* convert all glyphs, not only 256 of them */
127 int warnlevel = 3; /* the level of permitted warnings */
128 int forcemap = 0; /* do mapping even on non-Unicode fonts */
129 /* options - maximal limits */
130 int max_stemdepth = 128; /* maximal depth of stem stack in interpreter (128 - limit from X11) */
131 /* options - debugging */
132 int absolute = 0; /* print out in absolute values */
133 int reverse = 1; /* reverse font to Type1 path directions */
134 /* options - suboptions of Outline Processing, defaults are set in table */
135 int optimize; /* enables space optimization */
136 int smooth; /* enable smoothing of outlines */
137 int transform; /* enables transformation to 1000x1000 matrix */
138 int hints; /* enables autogeneration of hints */
139 int subhints; /* enables autogeneration of substituted hints */
140 int trybold; /* try to guess whether the font is bold */
141 int correctwidth; /* try to correct the character width */
142 int vectorize; /* vectorize the bitmaps */
143 int use_autotrace; /* use the autotrace library on bitmap */
144 /* options - suboptions of File Generation, defaults are set in table */
145 int gen_pfa; /* generate the font file */
146 int gen_afm; /* generate the metrics file */
147 int gen_dvienc; /* generate the dvips encoding file */
149 /* not quite options to select a particular source encoding */
150 int force_pid = -1; /* specific platform id */
151 int force_eid = -1; /* specific encoding id */
153 /* structure to define the sub-option lists controlled by the
154 * case: uppercase enables them, lowercase disables
157 char disbl; /* character to disable - enforced lowercase */
158 char enbl; /* character to enable - auto-set as toupper(disbl) */
159 int *valp; /* pointer to the actual variable containing value */
160 int dflt; /* default value */
161 char *descr; /* description */
164 int debug = DEBUG; /* debugging flag */
166 FILE *null_file, *pfa_file, *afm_file, *dvienc_file;
168 struct font_metrics fontm;
171 static char *strUID = 0; /* user-supplied UniqueID */
172 static unsigned long numUID; /* auto-generated UniqueID */
174 static int ps_fmt_3 = 0;
175 static double scale_factor, original_scale_factor;
177 static char *glyph_rename[ENCTABSZ];
179 /* the names assigned if the original font
180 * does not specify any
183 static char *Fmt3Encoding[256] = {
184 "c0", "c1", "c2", "c3",
185 "c4", "c5", "c6", "c7",
186 "c8", "c9", "c10", "c11",
187 "c12", "CR", "c14", "c15",
188 "c16", "c17", "c18", "c19",
189 "c20", "c21", "c22", "c23",
190 "c24", "c25", "c26", "c27",
191 "c28", "c29", "c30", "c31",
192 "space", "exclam", "quotedbl", "numbersign",
193 "dollar", "percent", "ampersand", "quotesingle",
194 "parenleft", "parenright", "asterisk", "plus",
195 "comma", "hyphen", "period", "slash",
196 "zero", "one", "two", "three",
197 "four", "five", "six", "seven",
198 "eight", "nine", "colon", "semicolon",
199 "less", "equal", "greater", "question",
206 "X", "Y", "Z", "bracketleft",
207 "backslash", "bracketright", "asciicircum", "underscore",
208 "grave", "a", "b", "c",
214 "x", "y", "z", "braceleft",
215 "bar", "braceright", "asciitilde", "c127",
216 "c128", "c129", "quotesinglbase", "florin",
217 "quotedblbase", "ellipsis", "dagger", "daggerdbl",
218 "circumflex", "perthousand", "Scaron", "guilsinglleft",
219 "OE", "c141", "c142", "c143",
220 "c144", "quoteleft", "quoteright", "quotedblleft",
221 "quotedblright", "bullet", "endash", "emdash",
222 "tilde", "trademark", "scaron", "guilsinglright",
223 "oe", "c157", "c158", "Ydieresis",
224 "nbspace", "exclamdown", "cent", "sterling",
225 "currency", "yen", "brokenbar", "section",
226 "dieresis", "copyright", "ordfeminine", "guillemotleft",
227 "logicalnot", "sfthyphen", "registered", "macron",
228 "degree", "plusminus", "twosuperior", "threesuperior",
229 "acute", "mu", "paragraph", "periodcentered",
230 "cedilla", "onesuperior", "ordmasculine", "guillemotright",
231 "onequarter", "onehalf", "threequarters", "questiondown",
232 "Agrave", "Aacute", "Acircumflex", "Atilde",
233 "Adieresis", "Aring", "AE", "Ccedilla",
234 "Egrave", "Eacute", "Ecircumflex", "Edieresis",
235 "Igrave", "Iacute", "Icircumflex", "Idieresis",
236 "Eth", "Ntilde", "Ograve", "Oacute",
237 "Ocircumflex", "Otilde", "Odieresis", "multiply",
238 "Oslash", "Ugrave", "Uacute", "Ucircumflex",
239 "Udieresis", "Yacute", "Thorn", "germandbls",
240 "agrave", "aacute", "acircumflex", "atilde",
241 "adieresis", "aring", "ae", "ccedilla",
242 "egrave", "eacute", "ecircumflex", "edieresis",
243 "igrave", "iacute", "icircumflex", "idieresis",
244 "eth", "ntilde", "ograve", "oacute",
245 "ocircumflex", "otilde", "odieresis", "divide",
246 "oslash", "ugrave", "uacute", "ucircumflex",
247 "udieresis", "yacute", "thorn", "ydieresis"
250 #ifdef notdef /* { */
251 /* This table is not used anywhere in the code
252 * so it's ifdef-ed out by default but left in
253 * the source code for reference purposes (and
254 * possibly for future use)
257 static char *ISOLatin1Encoding[256] = {
258 ".null", ".notdef", ".notdef", ".notdef",
259 ".notdef", ".notdef", ".notdef", ".notdef",
260 ".notdef", ".notdef", ".notdef", ".notdef",
261 ".notdef", "CR", ".notdef", ".notdef",
262 ".notdef", ".notdef", ".notdef", ".notdef",
263 ".notdef", ".notdef", ".notdef", ".notdef",
264 ".notdef", ".notdef", ".notdef", ".notdef",
265 ".notdef", ".notdef", ".notdef", ".notdef",
266 "space", "exclam", "quotedbl", "numbersign",
267 "dollar", "percent", "ampersand", "quoteright",
268 "parenleft", "parenright", "asterisk", "plus",
269 "comma", "hyphen", "period", "slash",
270 "zero", "one", "two", "three",
271 "four", "five", "six", "seven",
272 "eight", "nine", "colon", "semicolon",
273 "less", "equal", "greater", "question",
280 "X", "Y", "Z", "bracketleft",
281 "backslash", "bracketright", "asciicircum", "underscore",
282 "grave", "a", "b", "c",
288 "x", "y", "z", "braceleft",
289 "bar", "braceright", "asciitilde", "c127",
290 "c128", "c129", "quotesinglbase", "florin",
291 "quotedblbase", "ellipsis", "dagger", "daggerdbl",
292 "circumflex", "perthousand", "Scaron", "guilsinglleft",
293 "OE", "c141", "c142", "c143",
294 "c144", "quoteleft", "quoteright", "quotedblleft",
295 "quotedblright", "bullet", "endash", "emdash",
296 "tilde", "trademark", "scaron", "guilsinglright",
297 "oe", "c157", "c158", "Ydieresis",
298 "nbspace", "exclamdown", "cent", "sterling",
299 "currency", "yen", "brokenbar", "section",
300 "dieresis", "copyright", "ordfeminine", "guillemotleft",
301 "logicalnot", "sfthyphen", "registered", "macron",
302 "degree", "plusminus", "twosuperior", "threesuperior",
303 "acute", "mu", "paragraph", "periodcentered",
304 "cedilla", "onesuperior", "ordmasculine", "guillemotright",
305 "onequarter", "onehalf", "threequarters", "questiondown",
306 "Agrave", "Aacute", "Acircumflex", "Atilde",
307 "Adieresis", "Aring", "AE", "Ccedilla",
308 "Egrave", "Eacute", "Ecircumflex", "Edieresis",
309 "Igrave", "Iacute", "Icircumflex", "Idieresis",
310 "Eth", "Ntilde", "Ograve", "Oacute",
311 "Ocircumflex", "Otilde", "Odieresis", "multiply",
312 "Oslash", "Ugrave", "Uacute", "Ucircumflex",
313 "Udieresis", "Yacute", "Thorn", "germandbls",
314 "agrave", "aacute", "acircumflex", "atilde",
315 "adieresis", "aring", "ae", "ccedilla",
316 "egrave", "eacute", "ecircumflex", "edieresis",
317 "igrave", "iacute", "icircumflex", "idieresis",
318 "eth", "ntilde", "ograve", "oacute",
319 "ocircumflex", "otilde", "odieresis", "divide",
320 "oslash", "ugrave", "uacute", "ucircumflex",
321 "udieresis", "yacute", "thorn", "ydieresis"
324 #endif /* } notdef */
326 static char *adobe_StandardEncoding[256] = {
327 ".notdef", ".notdef", ".notdef", ".notdef",
328 ".notdef", ".notdef", ".notdef", ".notdef",
329 ".notdef", ".notdef", ".notdef", ".notdef",
330 ".notdef", ".notdef", ".notdef", ".notdef",
331 ".notdef", ".notdef", ".notdef", ".notdef",
332 ".notdef", ".notdef", ".notdef", ".notdef",
333 ".notdef", ".notdef", ".notdef", ".notdef",
334 ".notdef", ".notdef", ".notdef", ".notdef",
335 "space", "exclam", "quotedbl", "numbersign",
336 "dollar", "percent", "ampersand", "quoteright",
337 "parenleft", "parenright", "asterisk", "plus",
338 "comma", "hyphen", "period", "slash",
339 "zero", "one", "two", "three",
340 "four", "five", "six", "seven",
341 "eight", "nine", "colon", "semicolon",
342 "less", "equal", "greater", "question",
343 "at", "A", "B", "C", "D", "E", "F", "G",
344 "H", "I", "J", "K", "L", "M", "N", "O",
345 "P", "Q", "R", "S", "T", "U", "V", "W",
346 "X", "Y", "Z", "bracketleft",
347 "backslash", "bracketright", "asciicircum", "underscore",
348 "quoteleft", "a", "b", "c", "d", "e", "f", "g",
349 "h", "i", "j", "k", "l", "m", "n", "o",
350 "p", "q", "r", "s", "t", "u", "v", "w",
351 "x", "y", "z", "braceleft",
352 "bar", "braceright", "asciitilde", ".notdef",
353 ".notdef", ".notdef", ".notdef", ".notdef",
354 ".notdef", ".notdef", ".notdef", ".notdef",
355 ".notdef", ".notdef", ".notdef", ".notdef",
356 ".notdef", ".notdef", ".notdef", ".notdef",
357 ".notdef", ".notdef", ".notdef", ".notdef",
358 ".notdef", ".notdef", ".notdef", ".notdef",
359 ".notdef", ".notdef", ".notdef", ".notdef",
360 ".notdef", ".notdef", ".notdef", ".notdef",
361 ".notdef", "exclamdown", "cent", "sterling",
362 "fraction", "yen", "florin", "section",
363 "currency", "quotesingle", "quotedblleft", "guillemotleft",
364 "guilsinglleft", "guilsinglright", "fi", "fl",
365 ".notdef", "endash", "dagger", "daggerdbl",
366 "periodcentered", ".notdef", "paragraph", "bullet",
367 "quotesinglbase", "quotedblbase", "quotedblright", "guillemotright",
368 "ellipsis", "perthousand", ".notdef", "questiondown",
369 ".notdef", "grave", "acute", "circumflex",
370 "tilde", "macron", "breve", "dotaccent",
371 "dieresis", ".notdef", "ring", "cedilla",
372 ".notdef", "hungarumlaut", "ogonek", "caron",
373 "emdash", ".notdef", ".notdef", ".notdef",
374 ".notdef", ".notdef", ".notdef", ".notdef",
375 ".notdef", ".notdef", ".notdef", ".notdef",
376 ".notdef", ".notdef", ".notdef", ".notdef",
377 ".notdef", "AE", ".notdef", "ordfeminine",
378 ".notdef", ".notdef", ".notdef", ".notdef",
379 "Lslash", "Oslash", "OE", "ordmasculine",
380 ".notdef", ".notdef", ".notdef", ".notdef",
381 ".notdef", "ae", ".notdef", ".notdef",
382 ".notdef", "dotlessi", ".notdef", ".notdef",
383 "lslash", "oslash", "oe", "germandbls",
384 ".notdef", ".notdef", ".notdef", ".notdef"
388 * Decription of the supported conversions from Unicode
391 * Yes, I know that the compiled-in conversion is stupid but
392 * it is simple to implement and allows not to worry about the
393 * filesystem context. After all, the source is always available
394 * and adding another language to it is easy.
396 * The language name is expected to be the same as the subdirectory name
397 * in the `encodings' directory (for possible future extensions).
398 * The primary use of the aliases is for guessing based on the current
402 #define MAXUNIALIAS 10
403 #define MAXUNITABLES 3
405 /* the character used as the language argument separator */
406 #define LANG_ARG_SEP '+'
410 * Types of language-related routines. Arguments are:
411 * name is the glyph name
412 * arg is the user-specified language-dependent argument
413 * which can for example select the subfont plane for Eastern fonts.
414 * If none is supplied by user then an empty string ("") is passed.
415 * If no language is specified by user and auto-guessing happens
416 * then NULL is passed.
417 * when shows if the conversion by name was called before conversion by
418 * map or after (it's called twice)
421 /* type of the Unicode map initialization routine */
422 typedef void uni_init_t(char *arg);
424 /* type of Unicode converter-by-name function
425 * it's called for each glyph twice: one time for each glyph
426 * before doing conversion by map and one time after
428 typedef int uni_conv_t(char *name, char *arg, int when);
429 #define UNICONV_BYNAME_BEFORE 0
430 #define UNICONV_BYNAME_AFTER 1
432 struct uni_language {
433 uni_init_t *init[MAXUNITABLES]; /* map initialization routines */
434 uni_conv_t *convbyname; /* the name-based conversion function */
435 char *name; /* the language name */
436 char *descr; /* description */
437 char *alias[MAXUNIALIAS]; /* aliases of the language name */
438 int sample_upper; /* code of some uppercase character for correctvsize() */
441 /* the converter routines have an option of adding this suffix to the font name */
442 static char *uni_font_name_suffix = ""; /* empty by default */
443 /* this buffer may be used to store the suffix */
444 #define UNI_MAX_SUFFIX_LEN 100
445 static char uni_suffix_buf[UNI_MAX_SUFFIX_LEN+1];
448 * Prototypes of the conversion routines
451 static uni_init_t unicode_latin1;
452 static uni_init_t unicode_latin2;
453 static uni_init_t unicode_latin4;
454 static uni_init_t unicode_latin5;
455 static uni_init_t unicode_cyrillic;
456 static uni_init_t unicode_adobestd;
457 static uni_init_t unicode_plane;
458 static uni_conv_t unicode_adobestd_byname;
460 static uni_init_t unicode_init_user;
463 * The order of descriptions is important: if we can't guess the
464 * language we just call all the conversion routines in order until
465 * we find one that understands this glyph.
467 static struct uni_language uni_lang[]= {
468 /* pseudo-language for all the languages using Latin1 */
471 0, /* no name-based mapping */
473 "works for most of the Western languages",
474 { "en_", "de_", "fr_", "nl_", "no_", "da_", "it_" },
477 { /* by Szalay Tamas <tomek@elender.hu> */
479 0, /* no name-based mapping */
481 "works for Central European languages",
482 { "hu_","pl_","cz_","si_","sk_" },
485 { /* by Rièardas Èepas <rch@WriteMe.Com> */
487 0, /* no name-based mapping */
489 "works for Baltic languages",
490 { "lt_", "lv_" }, /* doubt about ee_ */
493 { /* by Turgut Uyar <uyar@cs.itu.edu.tr> */
495 0, /* no name-based mapping */
501 { /* by Zvezdan Petkovic <z.petkovic@computer.org> */
502 { unicode_cyrillic, unicode_latin1 },
503 0, /* no name-based mapping */
505 "in Windows encoding",
506 { "bg_", "be_", "mk_", "ru_", "sr_", "su_", "uk_" },
510 { unicode_cyrillic, unicode_latin1 },
511 0, /* no name-based mapping */
513 "obsolete, use cyrillic instead",
518 { unicode_cyrillic, unicode_latin1 },
519 0, /* no name-based mapping */
521 "obsolete, use cyrillic instead",
526 { unicode_adobestd },
527 unicode_adobestd_byname,
529 "Adobe Standard, expected by TeX",
535 0, /* no name-based mapping */
537 "one plane of Unicode or other multi-byte encoding as is",
539 0 /* no easy way to predict the capital letters */
543 static struct uni_language uni_lang_user = {
544 { unicode_init_user },
545 0, /* no name-based mapping */
547 0, /* no description */
552 static struct uni_language *uni_lang_selected=0; /* 0 means "unknown, try all" */
553 static int uni_sample='A'; /* sample of an uppercase character */
554 static char *uni_lang_arg=""; /* user-supplied language-dependent argument */
556 extern int runt1asm(int);
559 * user-defined loadable maps
563 /* The idea begind buckets is to avoid comparing every code with all ENCTABSZ codes in table.
564 * All the 16-bit unicode space is divided between a number of equal-sized buckets.
565 * Initially all the buckets are marked with 0. Then if any code in the bucket is
566 * used it's marked with 1. Later during translation we check the code's bucket first
567 * and it it's 0 then return failure right away. This may be useful for
568 * Chinese fonts with many thousands of glyphs.
571 #define BUCKET_ID_BITS 11
572 #define MARK_UNI_BUCKET(unicode) SET_BITMAP(uni_user_buckets, (unicode)>>(16-BUCKET_ID_BITS))
573 #define IS_UNI_BUCKET(unicode) IS_BITMAP(uni_user_buckets, (unicode)>>(16-BUCKET_ID_BITS))
575 static DEF_BITMAP(uni_user_buckets, 1<<BUCKET_ID_BITS);
577 static unsigned int unicode_map[ENCTABSZ]; /* font-encoding to unicode map */
578 static int enctabsz = 256; /* actual number of codes used */
585 FILE *unicode_map_file;
587 char buffer[UNIBFSZ];
588 unsigned code, unicode, curpos, unicode2;
590 int enabled, found, sawplane;
591 int lineno, cnt, n, nchars;
593 int pid, eid, overid=0;
595 /* check if we have an argument (plane name) */
596 arg = strrchr(path, LANG_ARG_SEP);
599 if( sscanf(arg, "pid=%d,eid=%d%n", &pid, &eid, &nchars) == 2 ) {
600 force_pid = pid; force_eid = eid; overid = 1;
601 WARNING_1 fprintf(stderr, "User override of the source encoding: pid=%d eid=%d\n", pid, eid);
607 if( *arg == 0 || strlen(arg) > UNI_MAX_SUFFIX_LEN-1)
610 sprintf(uni_suffix_buf, "-%s", arg);
611 uni_font_name_suffix = uni_suffix_buf;
615 /* now read in the encoding description file, if requested */
616 if ((unicode_map_file = fopen(path, "rb")) == NULL) {
617 fprintf(stderr, "**** Cannot access map file '%s' ****\n", path);
628 while (fgets (buffer, UNIBFSZ, unicode_map_file) != NULL) {
633 if(sscanf(buffer, "plane %s", name)==1) {
636 fprintf(stderr, "**** map file '%s' requires plane name\n", path);
637 fprintf(stderr, "for example:\n");
638 fprintf(stderr, " ttf2pt1 -L %s%c[pid=N,eid=N,]%s ...\n",
639 path, LANG_ARG_SEP, name);
640 fprintf(stderr, "to select plane '%s'\n", name);
643 if( !strcmp(arg, name) ) {
648 if(found) /* no need to read further */
654 if(sscanf(buffer, "id %d %d", pid, eid)==2) {
655 if( !overid /* only if the user has not overriden */
656 && (enabled || !sawplane) ) {
657 force_pid = pid; force_eid = eid;
664 continue; /* skip to the next plane */
666 if( sscanf(buffer, "at %i", &curpos) == 1 ) {
668 fprintf(stderr, "**** map file '%s' line %d: code over 255\n", path, lineno);
671 if(ISDBG(EXTMAP)) fprintf(stderr, "=== at 0x%x\n", curpos);
675 /* try the format of Roman Czyborra's files */
676 if ( sscanf (buffer, " =%x U+%4x", &code, &unicode) == 2
677 /* try the format of Linux locale charmap file */
678 || sscanf (buffer, " <%*s /x%x <U%4x>", &code, &unicode) == 2 ) {
679 if (code < ENCTABSZ) {
680 if(code >= enctabsz) enctabsz=code+1;
681 unicode_map[code] = unicode;
682 glyph_rename[code] = NULL;
685 /* try the format with glyph renaming */
686 else if (sscanf (buffer, " !%x U+%4x %128s", &code,
687 &unicode, name) == 3) {
688 if (code < ENCTABSZ) {
689 if(code >= enctabsz) enctabsz=code+1;
690 unicode_map[code] = unicode;
691 glyph_rename[code] = strdup(name);
694 /* try the compact sequence format */
695 else if( (n=sscanf(buffer, " %i%n", &unicode, &cnt)) == 1 ) {
699 fprintf(stderr, "**** map file '%s' line %d: code over 255 for unicode 0x%x\n",
700 path, lineno, unicode);
703 if(ISDBG(EXTMAP)) fprintf(stderr, "=== 0x%d -> 0x%x\n", curpos, unicode);
704 unicode_map[curpos++] = unicode;
706 if( sscanf(p, " %[,-]%n", &next,&cnt) == 1 ) {
707 if(ISDBG(EXTMAP)) fprintf(stderr, "=== next: '%c'\n", next);
709 if( next == '-' ) { /* range */
710 if ( sscanf(p, " %i%n", &unicode2, &cnt) != 1 ) {
711 fprintf(stderr, "**** map file '%s' line %d: missing end of range\n", path, lineno);
715 if(ISDBG(EXTMAP)) fprintf(stderr, "=== range 0x%x to 0x%x\n", unicode, unicode2);
716 for(unicode++; unicode <= unicode2; unicode++) {
718 fprintf(stderr, "**** map file '%s' line %d: code over 255 in unicode range ...-0x%x\n",
719 path, lineno, unicode2);
722 if(ISDBG(EXTMAP)) fprintf(stderr, "=== 0x%x -> 0x%x\n", curpos, unicode);
723 unicode_map[curpos++] = unicode;
727 } while ( sscanf(p, " %i%n", &unicode, &cnt) == 1 );
732 fclose (unicode_map_file);
735 fprintf(stderr, "**** map file '%s' has no plane '%s'\n", path, arg);
739 if(unicode_map['A'] == 'A')
740 uni_sample = 'A'; /* seems to be compatible with Latin */
742 uni_sample = 0; /* don't make any assumptions */
746 * by Zvezdan Petkovic <z.petkovic@computer.org>
754 static unsigned int cyrillic_unicode_map[] = {
755 0x0402, 0x0403, 0x201a, 0x0453, 0x201e, 0x2026, 0x2020, 0x2021, /* 80 */
756 0x20ac, 0x2030, 0x0409, 0x2039, 0x040a, 0x040c, 0x040b, 0x040f, /* 88 */
757 0x0452, 0x2018, 0x2019, 0x201c, 0x201d, 0x2022, 0x2013, 0x2014, /* 90 */
758 0x02dc, 0x2122, 0x0459, 0x203a, 0x045a, 0x045c, 0x045b, 0x045f, /* 98 */
759 0x00a0, 0x040e, 0x045e, 0x0408, 0x00a4, 0x0490, 0x00a6, 0x00a7, /* A0 */
760 0x0401, 0x00a9, 0x0404, 0x00ab, 0x00ac, 0x00ad, 0x00ae, 0x0407, /* A8 */
761 0x00b0, 0x00b1, 0x0406, 0x0456, 0x0491, 0x00b5, 0x00b6, 0x00b7, /* B0 */
762 0x0451, 0x2116, 0x0454, 0x00bb, 0x0458, 0x0405, 0x0455, 0x0457, /* B8 */
765 for(i=0; i<=0x7F; i++)
768 for(i=0x80; i<=0xBF; i++)
769 unicode_map[i] = cyrillic_unicode_map[i-0x80];
771 for(i=0xC0; i<=0xFF; i++)
772 unicode_map[i] = i+0x350;
782 static unsigned int latin1_unicode_map[] = {
783 0x20ac, -1, 0x201a, 0x0192, 0x201e, 0x2026, 0x2020, 0x2021, /* 80 */
784 0x02c6, 0x2030, 0x0160, 0x2039, 0x0152, 0x008d, 0x017d, 0x008f, /* 88 */
785 0x0090, 0x2018, 0x2019, 0x201c, 0x201d, 0x2022, 0x2013, 0x2014, /* 90 */
786 0x02dc, 0x2122, 0x0161, 0x203a, 0x0153, 0x009d, 0x017e, 0x0178, /* 98 */
789 for(i=0; i<=0x7F; i++)
792 for(i=0x80; i<=0x9F; i++)
793 unicode_map[i] = latin1_unicode_map[i-0x80];
795 for(i=0xA0; i<=0xFF; i++)
805 static unsigned int adobestd_unicode_map[] = {
806 -1, 0x00a1, 0x00a2, 0x00a3, 0x2215, 0x00a5, 0x0192, 0x00a7, /* A0 */
807 0x00a4, 0x0027, 0x201c, 0x00ab, 0x2039, 0x203a, 0xfb01, 0xfb02, /* A8 */
808 -1, 0x2013, 0x2020, 0x2021, 0x2219, -1, 0x00b6, 0x2022, /* B0 */
809 0x201a, 0x201e, 0x201d, 0x00bb, 0x2026, 0x2030, -1, 0x00bf, /* B8 */
810 -1, 0x0060, 0x00b4, 0x02c6, 0x02dc, 0x02c9, 0x02d8, 0x02d9, /* C0 */
811 0x00a8, -1, 0x02da, 0x00b8, -1, 0x02dd, 0x02db, 0x02c7, /* C8 */
812 0x2014, -1, -1, -1, -1, -1, -1, -1, /* D0 */
813 -1, -1, -1, -1, -1, -1, -1, -1, /* D8 */
814 -1, 0x00c6, -1, 0x00aa, -1, -1, -1, -1, /* E0 */
815 0x0141, 0x00d8, 0x0152, 0x00ba, -1, -1, -1, -1, /* E8 */
816 -1, 0x00e6, -1, -1, -1, 0x0131, -1, -1, /* F0 */
817 0x0142, 0x00f8, 0x0153, 0x00df, -1, -1, -1, -1, /* F8 */
820 for(i=0; i<=0x7F; i++)
823 unicode_map[0x27] = 0x2019;
824 unicode_map[0x60] = -1;
826 /* 0x80 to 0x9F is a hole */
828 for(i=0xA0; i<=0xFF; i++)
829 unicode_map[i] = adobestd_unicode_map[i-0xA0];
833 * Not all of the Adobe glyphs are in the Unicode
834 * standard maps, so the font creators have
835 * different ideas about their codes. Because
836 * of this we try to map based on the glyph
837 * names instead of Unicode codes. If there are
838 * no glyph names (ps_fmt_3!=0) we fall back
839 * to the code-based scheme.
843 unicode_adobestd_byname(
851 /* names always take precedence over codes */
852 if(where == UNICONV_BYNAME_AFTER)
855 for(i=32; i<256; i++) {
856 if(!strcmp(name, adobe_StandardEncoding[i]))
869 static unsigned int latin2_unicode_map[] = {
870 0x00a0, 0x0104, 0x02d8, 0x0141, 0x00a4, 0x013d, 0x015a, 0x00a7, /* A0 */
871 0x00a8, 0x0160, 0x015e, 0x0164, 0x0179, 0x00ad, 0x017d, 0x017b, /* A8 */
872 0x00b0, 0x0105, 0x02db, 0x0142, 0x00b4, 0x013e, 0x015b, 0x02c7, /* B0 */
873 0x00b8, 0x0161, 0x015f, 0x0165, 0x017a, 0x02dd, 0x017e, 0x017c, /* B8 */
874 0x0154, 0x00c1, 0x00c2, 0x0102, 0x00c4, 0x0139, 0x0106, 0x00c7, /* C0 */
875 0x010c, 0x00c9, 0x0118, 0x00cb, 0x011a, 0x00cd, 0x00ce, 0x010e, /* C8 */
876 0x0110, 0x0143, 0x0147, 0x00d3, 0x00d4, 0x0150, 0x00d6, 0x00d7, /* D0 */
877 0x0158, 0x016e, 0x00da, 0x0170, 0x00dc, 0x00dd, 0x0162, 0x00df, /* D8 */
878 0x0155, 0x00e1, 0x00e2, 0x0103, 0x00e4, 0x013a, 0x0107, 0x00e7, /* E0 */
879 0x010d, 0x00e9, 0x0119, 0x00eb, 0x011b, 0x00ed, 0x00ee, 0x010f, /* E8 */
880 0x0111, 0x0144, 0x0148, 0x00f3, 0x00f4, 0x0151, 0x00f6, 0x00f7, /* F0 */
881 0x0159, 0x016f, 0x00fa, 0x0171, 0x00fc, 0x00fd, 0x0163, 0x02d9, /* F8 */
884 for(i=0; i<=0x7E; i++)
887 /* 7F-9F are unused */
889 for(i=0xA0; i<=0xFF; i++)
890 unicode_map[i] = latin2_unicode_map[i-0xA0];
899 static unsigned int latin4_unicode_map[] = {
900 0x0080, 0x0081, 0x201a, 0x0192, -1, 0x2026, 0x2020, 0x2021, /* 80 */
901 0x02c6, 0x2030, -1, 0x2039, 0x0152, 0x008d, 0x008e, 0x008f, /* 88 */
902 0x201e, 0x201c, 0x2019, -1, 0x201d, 0x2022, 0x2013, 0x2014, /* 90 */
903 0x02dc, 0x2122, -1, 0x203a, 0x0153, 0x009d, 0x009e, 0x0178, /* 98 */
904 0x00a0, 0x0104, 0x0138, 0x0156, 0x00a4, 0x0128, 0x013b, 0x00a7, /* A0 */
905 0x00a8, 0x0160, 0x0112, 0x0122, 0x0166, 0x00ad, 0x017d, 0x00af, /* A8 */
906 0x00b0, 0x0105, 0x02db, 0x0157, 0x00b4, 0x0129, 0x013c, 0x02c7, /* B0 */
907 0x00b8, 0x0161, 0x0113, 0x0123, 0x0167, 0x014a, 0x017e, 0x014b, /* B8 */
908 0x0100, 0x00c1, 0x00c2, 0x00c3, 0x00c4, 0x00c5, 0x00c6, 0x012e, /* C0 */
909 0x010c, 0x00c9, 0x0118, 0x00cb, 0x0116, 0x00cd, 0x00ce, 0x012a, /* C8 */
910 0x0110, 0x0145, 0x014c, 0x0136, 0x00d4, 0x00d5, 0x00d6, 0x00d7, /* D0 */
911 0x00d8, 0x0172, 0x00da, 0x00db, 0x00dc, 0x0168, 0x016a, 0x00df, /* D8 */
912 0x0101, 0x00e1, 0x00e2, 0x00e3, 0x00e4, 0x00e5, 0x00e6, 0x012f, /* E0 */
913 0x010d, 0x00e9, 0x0119, 0x00eb, 0x0117, 0x00ed, 0x00ee, 0x012b, /* E8 */
914 0x0111, 0x0146, 0x014d, 0x0137, 0x00f4, 0x00f5, 0x00f6, 0x00f7, /* F0 */
915 0x00f8, 0x0173, 0x00fa, 0x00fb, 0x00fc, 0x0169, 0x016b, 0x02d9, /* F8 */
918 for(i=0; i<=0x7F; i++)
921 for(i=0x80; i<=0xFF; i++)
922 unicode_map[i] = latin4_unicode_map[i-0x80];
924 #if 0 /* for documentation purposes only */
925 case 0x201e: return 0x90; /* these two quotes are a hack only */
926 case 0x201c: return 0x91; /* these two quotes are a hack only */
927 case 0x00A0: return 0xA0; /* NO-BREAK SPACE */
928 case 0x0104: return 0xA1; /* LATIN CAPITAL LETTER A WITH OGONEK */
929 case 0x0138: return 0xA2; /* LATIN SMALL LETTER KRA */
930 case 0x0156: return 0xA3; /* LATIN CAPITAL LETTER R WITH CEDILLA */
931 case 0x00A4: return 0xA4; /* CURRENCY SIGN */
932 case 0x0128: return 0xA5; /* LATIN CAPITAL LETTER I WITH TILDE */
933 case 0x013B: return 0xA6; /* LATIN CAPITAL LETTER L WITH CEDILLA */
934 case 0x00A7: return 0xA7; /* SECTION SIGN */
935 case 0x00A8: return 0xA8; /* DIAERESIS */
936 case 0x0160: return 0xA9; /* LATIN CAPITAL LETTER S WITH CARON */
937 case 0x0112: return 0xAA; /* LATIN CAPITAL LETTER E WITH MACRON */
938 case 0x0122: return 0xAB; /* LATIN CAPITAL LETTER G WITH CEDILLA */
939 case 0x0166: return 0xAC; /* LATIN CAPITAL LETTER T WITH STROKE */
940 case 0x00AD: return 0xAD; /* SOFT HYPHEN */
941 case 0x017D: return 0xAE; /* LATIN CAPITAL LETTER Z WITH CARON */
942 case 0x00AF: return 0xAF; /* MACRON */
943 case 0x00B0: return 0xB0; /* DEGREE SIGN */
944 case 0x0105: return 0xB1; /* LATIN SMALL LETTER A WITH OGONEK */
945 case 0x02DB: return 0xB2; /* OGONEK */
946 case 0x0157: return 0xB3; /* LATIN SMALL LETTER R WITH CEDILLA */
947 case 0x00B4: return 0xB4; /* ACUTE ACCENT */
948 case 0x0129: return 0xB5; /* LATIN SMALL LETTER I WITH TILDE */
949 case 0x013C: return 0xB6; /* LATIN SMALL LETTER L WITH CEDILLA */
950 case 0x02C7: return 0xB7; /* CARON */
951 case 0x00B8: return 0xB8; /* CEDILLA */
952 case 0x0161: return 0xB9; /* LATIN SMALL LETTER S WITH CARON */
953 case 0x0113: return 0xBA; /* LATIN SMALL LETTER E WITH MACRON */
954 case 0x0123: return 0xBB; /* LATIN SMALL LETTER G WITH CEDILLA */
955 case 0x0167: return 0xBC; /* LATIN SMALL LETTER T WITH STROKE */
956 case 0x014A: return 0xBD; /* LATIN CAPITAL LETTER ENG */
957 case 0x017E: return 0xBE; /* LATIN SMALL LETTER Z WITH CARON */
958 case 0x014B: return 0xBF; /* LATIN SMALL LETTER ENG */
959 case 0x0100: return 0xC0; /* LATIN CAPITAL LETTER A WITH MACRON */
960 case 0x00C1: return 0xC1; /* LATIN CAPITAL LETTER A WITH ACUTE */
961 case 0x00C2: return 0xC2; /* LATIN CAPITAL LETTER A WITH CIRCUMFLEX */
962 case 0x00C3: return 0xC3; /* LATIN CAPITAL LETTER A WITH TILDE */
963 case 0x00C4: return 0xC4; /* LATIN CAPITAL LETTER A WITH DIAERESIS */
964 case 0x00C5: return 0xC5; /* LATIN CAPITAL LETTER A WITH RING ABOVE */
965 case 0x00C6: return 0xC6; /* LATIN CAPITAL LIGATURE AE */
966 case 0x012E: return 0xC7; /* LATIN CAPITAL LETTER I WITH OGONEK */
967 case 0x010C: return 0xC8; /* LATIN CAPITAL LETTER C WITH CARON */
968 case 0x00C9: return 0xC9; /* LATIN CAPITAL LETTER E WITH ACUTE */
969 case 0x0118: return 0xCA; /* LATIN CAPITAL LETTER E WITH OGONEK */
970 case 0x00CB: return 0xCB; /* LATIN CAPITAL LETTER E WITH DIAERESIS */
971 case 0x0116: return 0xCC; /* LATIN CAPITAL LETTER E WITH DOT ABOVE */
972 case 0x00CD: return 0xCD; /* LATIN CAPITAL LETTER I WITH ACUTE */
973 case 0x00CE: return 0xCE; /* LATIN CAPITAL LETTER I WITH CIRCUMFLEX */
974 case 0x012A: return 0xCF; /* LATIN CAPITAL LETTER I WITH MACRON */
975 case 0x0110: return 0xD0; /* LATIN CAPITAL LETTER D WITH STROKE */
976 case 0x0145: return 0xD1; /* LATIN CAPITAL LETTER N WITH CEDILLA */
977 case 0x014C: return 0xD2; /* LATIN CAPITAL LETTER O WITH MACRON */
978 case 0x0136: return 0xD3; /* LATIN CAPITAL LETTER K WITH CEDILLA */
979 case 0x00D4: return 0xD4; /* LATIN CAPITAL LETTER O WITH CIRCUMFLEX */
980 case 0x00D5: return 0xD5; /* LATIN CAPITAL LETTER O WITH TILDE */
981 case 0x00D6: return 0xD6; /* LATIN CAPITAL LETTER O WITH DIAERESIS */
982 case 0x00D7: return 0xD7; /* MULTIPLICATION SIGN */
983 case 0x00D8: return 0xD8; /* LATIN CAPITAL LETTER O WITH STROKE */
984 case 0x0172: return 0xD9; /* LATIN CAPITAL LETTER U WITH OGONEK */
985 case 0x00DA: return 0xDA; /* LATIN CAPITAL LETTER U WITH ACUTE */
986 case 0x00DB: return 0xDB; /* LATIN CAPITAL LETTER U WITH CIRCUMFLEX */
987 case 0x00DC: return 0xDC; /* LATIN CAPITAL LETTER U WITH DIAERESIS */
988 case 0x0168: return 0xDD; /* LATIN CAPITAL LETTER U WITH TILDE */
989 case 0x016A: return 0xDE; /* LATIN CAPITAL LETTER U WITH MACRON */
990 case 0x00DF: return 0xDF; /* LATIN SMALL LETTER SHARP S */
991 case 0x0101: return 0xE0; /* LATIN SMALL LETTER A WITH MACRON */
992 case 0x00E1: return 0xE1; /* LATIN SMALL LETTER A WITH ACUTE */
993 case 0x00E2: return 0xE2; /* LATIN SMALL LETTER A WITH CIRCUMFLEX */
994 case 0x00E3: return 0xE3; /* LATIN SMALL LETTER A WITH TILDE */
995 case 0x00E4: return 0xE4; /* LATIN SMALL LETTER A WITH DIAERESIS */
996 case 0x00E5: return 0xE5; /* LATIN SMALL LETTER A WITH RING ABOVE */
997 case 0x00E6: return 0xE6; /* LATIN SMALL LIGATURE AE */
998 case 0x012F: return 0xE7; /* LATIN SMALL LETTER I WITH OGONEK */
999 case 0x010D: return 0xE8; /* LATIN SMALL LETTER C WITH CARON */
1000 case 0x00E9: return 0xE9; /* LATIN SMALL LETTER E WITH ACUTE */
1001 case 0x0119: return 0xEA; /* LATIN SMALL LETTER E WITH OGONEK */
1002 case 0x00EB: return 0xEB; /* LATIN SMALL LETTER E WITH DIAERESIS */
1003 case 0x0117: return 0xEC; /* LATIN SMALL LETTER E WITH DOT ABOVE */
1004 case 0x00ED: return 0xED; /* LATIN SMALL LETTER I WITH ACUTE */
1005 case 0x00EE: return 0xEE; /* LATIN SMALL LETTER I WITH CIRCUMFLEX */
1006 case 0x012B: return 0xEF; /* LATIN SMALL LETTER I WITH MACRON */
1007 case 0x0111: return 0xF0; /* LATIN SMALL LETTER D WITH STROKE */
1008 case 0x0146: return 0xF1; /* LATIN SMALL LETTER N WITH CEDILLA */
1009 case 0x014D: return 0xF2; /* LATIN SMALL LETTER O WITH MACRON */
1010 case 0x0137: return 0xF3; /* LATIN SMALL LETTER K WITH CEDILLA */
1011 case 0x00F4: return 0xF4; /* LATIN SMALL LETTER O WITH CIRCUMFLEX */
1012 case 0x00F5: return 0xF5; /* LATIN SMALL LETTER O WITH TILDE */
1013 case 0x00F6: return 0xF6; /* LATIN SMALL LETTER O WITH DIAERESIS */
1014 case 0x00F7: return 0xF7; /* DIVISION SIGN */
1015 case 0x00F8: return 0xF8; /* LATIN SMALL LETTER O WITH STROKE */
1016 case 0x0173: return 0xF9; /* LATIN SMALL LETTER U WITH OGONEK */
1017 case 0x00FA: return 0xFA; /* LATIN SMALL LETTER U WITH ACUTE */
1018 case 0x00FB: return 0xFB; /* LATIN SMALL LETTER U WITH CIRCUMFLEX */
1019 case 0x00FC: return 0xFC; /* LATIN SMALL LETTER U WITH DIAERESIS */
1020 case 0x0169: return 0xFD; /* LATIN SMALL LETTER U WITH TILDE */
1021 case 0x016B: return 0xFE; /* LATIN SMALL LETTER U WITH MACRON */
1022 case 0x02D9: return 0xFF; /* DOT ABOVE */
1032 static unsigned int latin5_unicode_map1[] = {
1033 0x0080, 0x0081, 0x201a, 0x0192, 0x201e, 0x2026, 0x2020, 0x2021, /* 80 */
1034 0x02c6, 0x2030, 0x0160, 0x2039, 0x0152, 0x008d, 0x008e, 0x008f, /* 88 */
1035 0x0090, 0x2018, 0x2019, 0x201c, 0x201d, 0x2022, 0x2013, 0x2014, /* 90 */
1036 0x02dc, 0x2122, 0x0161, 0x203a, 0x0153, 0x009d, 0x009e, 0x0178, /* 98 */
1038 static unsigned int latin5_unicode_map2[] = {
1039 0x011e, 0x00d1, 0x00d2, 0x00d3, 0x00d4, 0x00d5, 0x00d6, 0x00d7, /* D0 */
1040 0x00d8, 0x00d9, 0x00da, 0x00db, 0x00dc, 0x0130, 0x015e, 0x00df, /* D8 */
1041 0x00e0, 0x00e1, 0x00e2, 0x00e3, 0x00e4, 0x00e5, 0x00e6, 0x00e7, /* E0 direct */
1042 0x00e8, 0x00e9, 0x00ea, 0x00eb, 0x00ec, 0x00ed, 0x00ee, 0x00ef, /* E8 direct */
1043 0x011f, 0x00f1, 0x00f2, 0x00f3, 0x00f4, 0x00f5, 0x00f6, 0x00f7, /* F0 */
1044 0x00f8, 0x00f9, 0x00fa, 0x00fb, 0x00fc, 0x0131, 0x015f, 0x00ff, /* F8 */
1047 for(i=0; i<=0x7F; i++)
1050 for(i=0x80; i<=0x9F; i++)
1051 unicode_map[i] = latin5_unicode_map1[i-0x80];
1053 for(i=0xA0; i<=0xCF; i++)
1056 for(i=0xD0; i<=0xFF; i++)
1057 unicode_map[i] = latin5_unicode_map2[i-0xD0];
1060 /* a way to select one 256-character plane from Unicode
1061 * or other multi-byte encoding
1069 static unsigned plane;
1073 if(uni_lang_selected == 0)
1074 return; /* don't participate in auto-guessing */
1076 plane = 0; force_pid = force_eid = -1;
1078 c1 = sscanf(arg, "pid=%d,eid=%d%n", &force_pid, &force_eid, &nchars);
1084 if(arg[0] == '0' && (arg[1]=='x' || arg[1]=='X') ) {
1086 c2 = sscanf(arg, "%x", &plane);
1088 c2 = sscanf(arg, "%d", &plane);
1091 if( (c1!=2 && c1!=0) || (c1==0 && c2==0) ) {
1092 fprintf(stderr, "**** option -l plane expects one of the following formats:\n");
1093 fprintf(stderr, " -l plane+0xNN - select hexadecimal number of plane of Unicode\n");
1094 fprintf(stderr, " -l plane+NN - select decimal number of plane of Unicode\n");
1095 fprintf(stderr, " -l plane+pid=N,eid=N - select plane 0 of specified encoding\n");
1096 fprintf(stderr, " -l plane+pid=N,eid=N,0xNN - select hex plane of TTF encoding with this PID/EID\n");
1097 fprintf(stderr, " -l plane+pid=N,eid=N,NN - select decimal plane of TTF encoding with this PID/EID\n");
1102 if(strlen(arg) > sizeof(uni_suffix_buf)-2) {
1103 fprintf(stderr, "**** plane number is too large\n");
1106 sprintf(uni_suffix_buf, "-%s", arg);
1107 uni_font_name_suffix = uni_suffix_buf;
1109 uni_font_name_suffix = "";
1113 for(i=0; i<=0xFF; i++)
1114 unicode_map[i] = plane | i;
1117 /* look up the 8-bit code by unicode */
1126 if( ! IS_UNI_BUCKET(unival) )
1129 for (res = 0; res < enctabsz; res++)
1130 if (unicode_map[res] == unival)
1135 /* mark the buckets for quick lookup */
1138 unicode_prepare_buckets(
1144 memset(uni_user_buckets, 0, sizeof uni_user_buckets);
1145 for(i=0; i<enctabsz; i++) {
1146 if(unicode_map[i] != (unsigned) -1)
1147 MARK_UNI_BUCKET(unicode_map[i]);
1152 * When we print errors about bad names we want to print these names in
1153 * some decent-looking form
1161 static char res[50];
1164 for(i=0; ( c =* s )!=0 && i<sizeof(res)-8; s++) {
1165 if(c < ' ' || c > 126) {
1166 sprintf(res+i, "\\x%02X", c);
1182 * Scale the values according to the scale_factor
1190 return scale_factor * val;
1198 return (int) (val > 0 ? scale_factor * val + 0.5
1199 : scale_factor * val - 0.5);
1203 * Try to force fixed width of characters
1210 int n = 0, avg, max = 0, min = 3000, sum = 0, x;
1212 for (i = 0; i < numglyphs; i++) {
1213 if (glyph_list[i].flags & GF_USED) {
1214 x = glyph_list[i].width;
1233 WARNING_3 fprintf(stderr, "widths: max=%d avg=%d min=%d\n", max, avg, min);
1235 /* if less than 5% variation from average */
1236 /* force fixed width */
1237 if (20 * (avg - min) < avg && 20 * (max - avg) < avg) {
1238 for (i = 0; i < numglyphs; i++) {
1239 if (glyph_list[i].flags & GF_USED)
1240 glyph_list[i].width = avg;
1242 fontm.is_fixed_pitch = 1;
1254 g = &glyph_list[glyphno];
1257 g->scaledwidth = iscale(g->width);
1262 if (g->ttf_pathlen != 0) {
1263 cursw->glpath(glyphno, glyph_list);
1267 dumppaths(g, NULL, NULL);
1269 assertpath(g->entries, __FILE__, __LINE__, g->name);
1272 assertpath(g->entries, __FILE__, __LINE__, g->name);
1274 /* float processing */
1277 assertpath(g->entries, __FILE__, __LINE__, g->name);
1280 assertpath(g->entries, __FILE__, __LINE__, g->name);
1283 assertpath(g->entries, __FILE__, __LINE__, g->name);
1286 assertpath(g->entries, __FILE__, __LINE__, g->name);
1290 /* all processing past this point expects integer path */
1291 assertpath(g->entries, __FILE__, __LINE__, g->name);
1298 /* int processing */
1301 assertpath(g->entries, __FILE__, __LINE__, g->name);
1307 for(ge = g->entries; ge; ge = ge->next)
1310 if (ncurves > 200) {
1311 WARNING_3 fprintf(stderr,
1312 "** Glyph %s is too long, may display incorrectly\n",
1316 /* for buildstems */
1317 g->flags &= ~GF_FLOAT;
1324 int i, n, found, c, type;
1326 /* get the names from the font file */
1327 ps_fmt_3 = cursw->glnames(glyph_list);
1329 /* check for names with wrong characters */
1330 for (n = 0; n < numglyphs; n++) {
1332 for (i = 0; (c = glyph_list[n].name[i]) != 0; i++) {
1333 if (!(isalnum(c) || c == '.' || c == '_' || c == '-')
1334 || i==0 && isdigit(c)) { /* must not start with a digit */
1335 WARNING_3 fprintf(stderr, "Glyph %d %s (%s), ",
1336 n, isdigit(c) ? "name starts with a digit" :
1337 "has bad characters in name",
1338 nametoprint(glyph_list[n].name));
1339 glyph_list[n].name = malloc(16);
1340 sprintf(glyph_list[n].name, "_b_%d", n);
1341 WARNING_3 fprintf(stderr, "changing to %s\n", glyph_list[n].name);
1348 /* check for duplicate names */
1349 for (n = 0; n < numglyphs; n++) {
1351 for (i = 0; i < n && !found; i++) {
1352 if (strcmp(glyph_list[i].name, glyph_list[n].name) == 0) {
1353 if (( glyph_list[n].name = malloc(16) )==0) {
1354 fprintf (stderr, "****malloc failed %s line %d\n", __FILE__, __LINE__);
1357 sprintf(glyph_list[n].name, "_d_%d", n);
1359 /* if the font has no names in it (what the native parser
1360 * recognises as ps_fmt_3), FreeType returns all the
1361 * names as .notdef, so don't complain in this case
1363 if(strcmp(glyph_list[i].name, ".notdef")) {
1364 WARNING_3 fprintf(stderr,
1365 "Glyph %d has the same name as %d: (%s), changing to %s\n",
1368 glyph_list[n].name);
1377 /* start the encoding stuff */
1378 for (i = 0; i < ENCTABSZ; i++) {
1382 /* do the 1st round of encoding by name */
1383 if(!ps_fmt_3 && uni_lang_selected && uni_lang_selected->convbyname) {
1384 for (n = 0; n < numglyphs; n++) {
1385 c = uni_lang_selected->convbyname(glyph_list[n].name,
1386 uni_lang_arg, UNICONV_BYNAME_BEFORE);
1387 if(c>=0 && c<ENCTABSZ && encoding[c] == -1)
1392 /* now do the encoding by table */
1393 if(uni_lang_selected) {
1394 for(i=0; i < MAXUNITABLES && uni_lang_selected->init[i]; i++) {
1395 for (n = 0; n < ENCTABSZ; n++)
1396 unicode_map[n] = -1;
1397 uni_lang_selected->init[i](uni_lang_arg);
1398 unicode_prepare_buckets();
1399 type = cursw->glenc(glyph_list, encoding, unicode_map);
1401 /* if we have an 8-bit encoding we don't need more tries */
1405 /* language is unknown, try the first table of each */
1406 for(i=0; i < sizeof uni_lang/(sizeof uni_lang[0]); i++) {
1407 if(uni_lang[i].init[0] == NULL)
1409 for (n = 0; n < ENCTABSZ; n++)
1410 unicode_map[n] = -1;
1411 uni_lang[i].init[0](uni_lang_arg);
1412 unicode_prepare_buckets();
1413 type = cursw->glenc(glyph_list, encoding, unicode_map);
1415 /* if we have an 8-bit encoding we don't need more tries */
1421 /* get rid of the old names, they are all "UNKNOWN" anyawy */
1422 for (i = 0; i < numglyphs; i++) {
1423 glyph_list[i].name = 0;
1426 /* 8-bit - give 8859/1 names to the first 256 glyphs */
1427 for (i = 0; i < 256; i++) { /* here 256, not ENCTABSZ */
1428 if (encoding[i] > 0) {
1429 glyph_list[encoding[i]].name = Fmt3Encoding[i];
1432 } else if(type == 1) {
1433 /* Unicode - give 8859/1 names to the first 256 glyphs of Unicode */
1434 for (n = 0; n < 256; n++) { /* here 256, not ENCTABSZ */
1435 i = unicode_rev_lookup(n);
1436 if (i>=0 && encoding[i] > 0) {
1437 glyph_list[encoding[i]].name = Fmt3Encoding[i];
1440 } /* for other types of encodings just give generated names */
1441 /* assign unique names to the rest of the glyphs */
1442 for (i = 0; i < numglyphs; i++) {
1443 if (glyph_list[i].name == 0) {
1444 if (( glyph_list[i].name = malloc(16) )==0) {
1445 fprintf (stderr, "****malloc failed %s line %d\n", __FILE__, __LINE__);
1448 sprintf(glyph_list[i].name, "_d_%d", i);
1453 /* do the 2nd round of encoding by name */
1454 if(uni_lang_selected && uni_lang_selected->convbyname) {
1455 for (n = 0; n < numglyphs; n++) {
1456 c = uni_lang_selected->convbyname(glyph_list[n].name,
1457 uni_lang_arg, UNICONV_BYNAME_AFTER);
1458 if(c>=0 && c<ENCTABSZ && encoding[c] == -1)
1462 /* all the encoding things are done */
1464 for (i = 0; i < ENCTABSZ; i++)
1465 if(encoding[i] == -1) {
1466 /* check whether this character might be a duplicate
1467 * (in which case it would be missed by unicode_rev_lookup())
1470 if((type != 0 || forcemap) && c != -1) {
1471 for(n = 0; n < i; n++) {
1472 if(unicode_map[n] == c) {
1473 encoding[i] = encoding[n];
1477 if(encoding[i] == -1) /* still not found, defaults to .notdef */
1481 for (i = 0; i < 256; i++) /* here 256, not ENCTABSZ */
1482 glyph_list[encoding[i]].char_no = i;
1484 /* enforce two special cases defined in TTF manual */
1486 glyph_list[0].name = ".notdef";
1488 glyph_list[1].name = ".null";
1490 for (i = 0; i < ENCTABSZ; i++) {
1491 if ((encoding[i] != 0) && glyph_rename[i]) {
1492 glyph_list[encoding[i]].name = glyph_rename[i];
1503 # define fplop(txt) fputs(txt, stderr);
1508 fputs("Use:\n", stderr);
1509 fputs("ttf2pt1 [-<opts>] [-l language | -L file] <ttf-file> [<fontname>]\n", stderr);
1510 fputs(" or\n", stderr);
1511 fputs("ttf2pt1 [-<opts>] [-l language | -L file] <ttf-file> -\n", stderr);
1512 fputs(" or\n", stderr);
1513 fputs("ttf2pt1 [-<opts>] [-l language | -L file] <ttf-file> - | t1asm > <pfa-file>\n", stderr);
1516 fplop("This build supports both short and long option names,\n");
1517 fplop("the long options are listed before corresponding short ones\n");
1519 fplop(" --all-glyphs\n");
1520 fputs(" -a - include all glyphs, even those not in the encoding table\n", stderr);
1522 fputs(" -b - produce a compressed .pfb file\n", stderr);
1523 fplop(" --debug dbg_suboptions\n");
1524 fputs(" -d dbg_suboptions - debugging options, run ttf2pt1 -d? for help\n", stderr);
1525 fplop(" --encode\n");
1526 fputs(" -e - produce a fully encoded .pfa file\n", stderr);
1527 fplop(" --force-unicode\n");
1528 fputs(" -F - force use of Unicode encoding even if other MS encoding detected\n", stderr);
1529 fplop(" --generate suboptions\n");
1530 fputs(" -G suboptions - control the file generation, run ttf2pt1 -G? for help\n", stderr);
1531 fplop(" --language language\n");
1532 fputs(" -l language - convert Unicode to specified language, run ttf2pt1 -l? for list\n", stderr);
1533 fplop(" --language-map file\n");
1534 fputs(" -L file - convert Unicode according to encoding description file\n", stderr);
1535 fplop(" --limit <type>=<value>\n");
1536 fputs(" -m <type>=<value> - set maximal limit of given type to value, types:\n", stderr);
1537 fputs(" h - maximal hint stack depth in the PostScript interpreter\n", stderr);
1538 fplop(" --processing suboptions\n");
1539 fputs(" -O suboptions - control outline processing, run ttf2pt1 -O? for help\n", stderr);
1540 fplop(" --parser name\n");
1541 fputs(" -p name - use specific front-end parser, run ttf2pt1 -p? for list\n", stderr);
1542 fplop(" --uid id\n");
1543 fputs(" -u id - use this UniqueID, -u A means autogeneration\n", stderr);
1544 fplop(" --vertical-autoscale size\n");
1545 fputs(" -v size - scale the font to make uppercase letters >size/1000 high\n", stderr);
1546 fplop(" --version\n");
1547 fputs(" -V - print ttf2pt1 version number\n", stderr);
1548 fplop(" --warning number\n");
1549 fputs(" -W number - set the level of permitted warnings (0 - disable)\n", stderr);
1550 fputs("Obsolete options (will be removed in future releases):\n", stderr);
1552 fputs(" -A - write the .afm file to STDOUT instead of the font, now -GA\n", stderr);
1553 fputs(" -f - don't try to guess the value of the ForceBold hint, now -Ob\n", stderr);
1554 fputs(" -h - disable autogeneration of hints, now -Oh\n", stderr);
1555 fputs(" -H - disable hint substitution, now -Ou\n", stderr);
1556 fputs(" -o - disable outline optimization, now -Oo\n", stderr);
1557 fputs(" -s - disable outline smoothing, now -Os\n", stderr);
1558 fputs(" -t - disable auto-scaling to 1000x1000 standard matrix, now -Ot\n", stderr);
1559 fputs(" -w - correct the glyph widths (use only for buggy fonts), now -OW\n", stderr);
1560 fputs("With no <fontname>, write to <ttf-file> with suffix replaced.\n", stderr);
1561 fputs("The last '-' means 'use STDOUT'.\n", stderr);
1570 fprintf(stderr, "ttf2pt1 %s\n", TTF2PT1_VERSION);
1573 /* initialize a table of suboptions */
1576 struct subo_case *tbl
1581 for(i=0; tbl[i].disbl != 0; i++) {
1582 tbl[i].disbl = tolower(tbl[i].disbl);
1583 tbl[i].enbl = toupper(tbl[i].disbl);
1584 *(tbl[i].valp) = tbl[i].dflt;
1588 /* print the default value of the suboptions */
1592 struct subo_case *tbl
1597 for(i=0; tbl[i].disbl != 0; i++) {
1599 putc(tbl[i].enbl, f);
1601 putc(tbl[i].disbl, f);
1605 /* print the usage message for the suboptions */
1609 struct subo_case *tbl
1614 fprintf(f,"The lowercase suboptions disable features, corresponding\n");
1615 fprintf(f,"uppercase suboptions enable them. The supported suboptions,\n");
1616 fprintf(f,"their default states and the features they control are:\n");
1617 for(i=0; tbl[i].disbl != 0; i++) {
1618 fprintf(f," %c/%c - [%s] %s\n", tbl[i].disbl, tbl[i].enbl,
1619 tbl[i].dflt ? "enabled" : "disabled", tbl[i].descr);
1623 /* find and set the entry according to suboption,
1624 * return the found entry (or if not found return NULL)
1628 struct subo_case *tbl,
1634 for(i=0; tbl[i].disbl != 0; i++) {
1635 if(subopt == tbl[i].disbl) {
1638 } else if(subopt == tbl[i].enbl) {
1655 char filename[4096];
1656 int c,nchars,nmetrics;
1658 int forcebold= -1; /* -1 means "don't know" */
1664 # define ttf2pt1_getopt(a, b, c, d, e) getopt_long(a, b, c, d, e)
1665 static struct option longopts[] = {
1666 { "afm", 0, NULL, 'A' },
1667 { "all-glyphs", 0, NULL, 'a' },
1668 { "pfb", 0, NULL, 'b' },
1669 { "debug", 1, NULL, 'd' },
1670 { "encode", 0, NULL, 'e' },
1671 { "force-unicode", 0, NULL, 'F' },
1672 { "generate", 1, NULL, 'G' },
1673 { "language", 1, NULL, 'l' },
1674 { "language-map", 1, NULL, 'L' },
1675 { "limit", 1, NULL, 'm' },
1676 { "processing", 1, NULL, 'O' },
1677 { "parser", 1, NULL, 'p' },
1678 { "uid", 1, NULL, 'u' },
1679 { "vertical-autoscale", 1, NULL, 'v' },
1680 { "version", 0, NULL, 'V' },
1681 { "warning", 1, NULL, 'W' },
1682 { NULL, 0, NULL, 0 }
1685 # define ttf2pt1_getopt(a, b, c, d, e) getopt(a, b, c)
1687 /* table of Outline Processing (may think also as Optimization) options */
1688 static struct subo_case opotbl[] = {
1689 { 'b', 0/*auto-set*/, &trybold, 1, "guessing of the ForceBold hint" },
1690 { 'h', 0/*auto-set*/, &hints, 1, "autogeneration of hints" },
1691 { 'u', 0/*auto-set*/, &subhints, 1, "hint substitution technique" },
1692 { 'o', 0/*auto-set*/, &optimize, 1, "space optimization of font files" },
1693 { 's', 0/*auto-set*/, &smooth, 1, "smoothing and repair of outlines" },
1694 { 't', 0/*auto-set*/, &transform, 1, "auto-scaling to the standard matrix 1000x1000" },
1695 { 'w', 0/*auto-set*/, &correctwidth, 0, "correct the glyph widths (use only for buggy fonts)" },
1696 { 'v', 0/*auto-set*/, &vectorize, 0, "vectorize (trace) the bitmaps" },
1697 #ifdef USE_AUTOTRACE
1698 { 'z', 0/*auto-set*/, &use_autotrace, 0, "use the autotrace library on bitmaps (works badly)" },
1699 #endif /*USE_AUTOTRACE*/
1700 { 0, 0, 0, 0, 0} /* terminator */
1702 /* table of the File Generation options */
1703 static struct subo_case fgotbl[] = {
1704 { 'f', 0/*auto-set*/, &gen_pfa, 1, "generate the font file (.t1a, .pfa or .pfb)" },
1705 { 'a', 0/*auto-set*/, &gen_afm, 1, "generate the Adobe metrics file (.afm)" },
1706 { 'e', 0/*auto-set*/, &gen_dvienc, 0, "generate the dvips encoding file (.enc)" },
1707 { 0, 0, 0, 0, 0} /* terminator */
1709 int *genlast = NULL;
1712 init_subo_tbl(opotbl); /* initialize sub-options of -O */
1713 init_subo_tbl(fgotbl); /* initialize sub-options of -G */
1715 /* save the command line for the record
1716 * (we don't bother about escaping the shell special characters)
1720 for(i=1; i<argc; i++) {
1721 j += strlen(argv[i])+1;
1723 if ((cmdline = malloc(j+1)) == NULL) {
1724 fprintf (stderr, "****malloc failed %s line %d\n", __FILE__, __LINE__);
1728 for(i=1; i<argc; i++) {
1729 strcat(cmdline, argv[i]);
1730 strcat(cmdline, " ");
1732 for(i=0; (j=cmdline[i])!=0; i++)
1737 while(( oc=ttf2pt1_getopt(argc, argv, "FaoebAsthHfwVv:p:l:d:u:L:m:W:O:G:",
1738 longopts, NULL) )!= -1) {
1741 if(sscanf(optarg, "%d", &warnlevel) < 1 || warnlevel < 0) {
1742 fprintf(stderr, "**** warning level must be a positive number: %s (%d)\n", optarg, warnlevel);
1750 fputs("Warning: option -o is obsolete, use -Oo instead\n", stderr);
1757 encode = pfbflag = 1;
1760 fputs("Warning: option -A is obsolete, use -GA instead\n", stderr);
1767 fputs("Warning: option -s is obsolete, use -Os instead\n", stderr);
1771 fputs("Warning: option -t is obsolete, use -Ot instead\n", stderr);
1775 for(i=0; optarg[i]!=0; i++)
1784 if (optarg[i] != '?')
1785 fprintf(stderr, "**** Unknown debugging option '%c' ****\n", optarg[i]);
1786 fputs("The recognized debugging options are:\n", stderr);
1787 fputs(" a - enable absolute coordinates\n", stderr);
1788 fputs(" r - do not reverse font outlines directions\n", stderr);
1798 if(sscanf(optarg, "%c=%d", &subopt, &val) !=2) {
1799 fprintf(stderr, "**** Misformatted maximal limit ****\n");
1800 fprintf(stderr, "spaces around the equal sign are not allowed\n");
1801 fprintf(stderr, "good examples: -mh=100 -m h=100\n");
1802 fprintf(stderr, "bad examples: -mh = 100 -mh= 100\n");
1808 max_stemdepth = val;
1812 fprintf(stderr, "**** Unknown limit type '%c' ****\n", subopt);
1813 fputs("The recognized limit types are:\n", stderr);
1814 fputs(" h - maximal hint stack depth in the PostScript interpreter\n", stderr);
1823 for(p=optarg; *p != 0; p++) {
1824 if(set_subo(opotbl, *p) == NULL) { /* found no match */
1826 fprintf(stderr, "**** Unknown outline processing suboption '%c' ****\n", *p);
1827 fprintf(stderr,"The general form of the outline processing option is:\n");
1828 fprintf(stderr," -O suboptions\n");
1829 fprintf(stderr,"(To remember easily -O may be also thought of as \"optimization\").\n");
1830 print_subo_usage(stderr, opotbl);
1831 fprintf(stderr, "The default state corresponds to the option -O ");
1832 print_subo_dflt(stderr, opotbl);
1833 fprintf(stderr, "\n");
1842 struct subo_case *s;
1844 for(p=optarg; *p != 0; p++) {
1845 if(( s = set_subo(fgotbl, *p) )==NULL) { /* found no match */
1847 fprintf(stderr, "**** Unknown outline processing suboption '%c' ****\n", *p);
1848 fprintf(stderr,"The general form of the file generation option is:\n");
1849 fprintf(stderr," -G suboptions\n");
1850 print_subo_usage(stderr, fgotbl);
1851 fprintf(stderr, "The default state corresponds to the option -G ");
1852 print_subo_dflt(stderr, fgotbl);
1853 fprintf(stderr, "\n");
1854 fprintf(stderr, "If the result is written to STDOUT, the last specified enabling suboption of -G\n");
1855 fprintf(stderr, "selects the file to be written to STDOUT (the font file by default).\n");
1864 fputs("Warning: option -h is obsolete, use -Oh instead\n", stderr);
1868 fputs("Warning: meaning of option -H has been changed to its opposite\n", stderr);
1869 fputs("Warning: option -H is obsolete, use -Ou instead\n", stderr);
1873 fputs("Warning: option -f is obsolete, use -Ob instead\n", stderr);
1877 fputs("Warning: option -w is obsolete, use -OW instead\n", stderr);
1882 fprintf(stderr, "**** UniqueID may be specified only once ****\n");
1886 if(optarg[0]=='A' && optarg[1]==0)
1887 strUID=0; /* will be generated automatically */
1890 for(i=0; optarg[i]!=0; i++)
1891 if( !isdigit(optarg[i]) ) {
1892 fprintf(stderr, "**** UniqueID must be numeric or A for automatic ****\n");
1898 correctvsize = atoi(optarg);
1899 if(correctvsize <= 0 && correctvsize > 1000) {
1900 fprintf(stderr, "**** wrong vsize '%d', ignored ****\n", correctvsize);
1906 fprintf(stderr, "**** only one front-end parser be used ****\n");
1910 { /* separate parser from parser-specific argument */
1911 char *p = strchr(optarg, LANG_ARG_SEP);
1918 for(i=0; frontswtab[i] != NULL; i++)
1919 if( !strcmp(frontswtab[i]->name, optarg) ) {
1920 cursw = frontswtab[i];
1925 if (strcmp(optarg, "?"))
1926 fprintf(stderr, "**** unknown front-end parser '%s' ****\n", optarg);
1927 fputs("the following front-ends are supported now:\n", stderr);
1928 for(i=0; frontswtab[i] != NULL; i++) {
1929 fprintf(stderr," %s (%s)\n file suffixes: ",
1930 frontswtab[i]->name,
1931 frontswtab[i]->descr ? frontswtab[i]->descr : "no description"
1933 for(j=0; j<MAXSUFFIX; j++)
1934 if(frontswtab[i]->suffix[j])
1935 fprintf(stderr, "%s ", frontswtab[i]->suffix[j]);
1936 fprintf(stderr, "\n");
1942 if(uni_lang_selected!=0) {
1943 fprintf(stderr, "**** only one language option may be used ****\n");
1947 { /* separate language from language-specific argument */
1948 char *p = strchr(optarg, LANG_ARG_SEP);
1955 for(i=0; i < sizeof uni_lang/(sizeof uni_lang[0]); i++)
1956 if( !strcmp(uni_lang[i].name, optarg) ) {
1957 uni_lang_selected = &uni_lang[i];
1958 uni_sample = uni_lang[i].sample_upper;
1962 if(uni_lang_selected==0) {
1963 if (strcmp(optarg, "?"))
1964 fprintf(stderr, "**** unknown language '%s' ****\n", optarg);
1965 fputs(" the following languages are supported now:\n", stderr);
1966 for(i=0; i < sizeof uni_lang/(sizeof uni_lang[0]); i++)
1967 fprintf(stderr," %s (%s)\n",
1969 uni_lang[i].descr ? uni_lang[i].descr : "no description"
1975 if(uni_lang_selected!=0) {
1976 fprintf(stderr, "**** only one language option may be used ****\n");
1979 uni_lang_selected = &uni_lang_user;
1980 uni_lang_arg = optarg;
1993 argc-=optind-1; /* the rest of code counts from argv[0] */
1996 if (absolute && encode) {
1997 fprintf(stderr, "**** options -a and -e are incompatible ****\n");
2000 if ((argc != 2) && (argc != 3)) {
2004 /* try to guess the language by the locale used */
2005 if(uni_lang_selected==0 && (lang=getenv("LANG"))!=0 ) {
2006 for(i=0; i < sizeof uni_lang/sizeof(struct uni_language); i++) {
2007 if( !strncmp(uni_lang[i].name, lang, strlen(uni_lang[i].name)) ) {
2008 uni_lang_selected = &uni_lang[i];
2009 goto got_a_language;
2012 /* no full name ? try aliases */
2013 for(i=0; i < sizeof uni_lang/sizeof(struct uni_language); i++) {
2014 for(c=0; c<MAXUNIALIAS; c++)
2015 if( uni_lang[i].alias[c]!=0
2016 && !strncmp(uni_lang[i].alias[c], lang, strlen(uni_lang[i].alias[c])) ) {
2017 uni_lang_selected = &uni_lang[i];
2018 goto got_a_language;
2022 if(uni_lang_selected!=0) {
2023 WARNING_1 fprintf(stderr, "Using language '%s' for Unicode fonts\n", uni_lang[i].name);
2024 uni_sample = uni_lang[i].sample_upper;
2028 /* try to guess the front-end parser by the file name suffix */
2030 char *p = strrchr(argv[1], '.');
2033 if(p!=0 && (s = strdup(p+1))!=0) {
2038 for(i=0; frontswtab[i] != 0 && cursw == 0; i++) {
2039 for(j=0; j<MAXSUFFIX; j++)
2040 if(frontswtab[i]->suffix[j]
2041 && !strcmp(p, frontswtab[i]->suffix[j]) ) {
2042 cursw = frontswtab[i];
2043 WARNING_1 fprintf(stderr, "Auto-detected front-end parser '%s'\n",
2045 WARNING_1 fprintf(stderr, " (use ttf2pt1 -p? to get the full list of available front-ends)\n");
2053 cursw = frontswtab[0];
2054 WARNING_1 fprintf(stderr, "Can't detect front-end parser, using '%s' by default\n",
2056 WARNING_1 fprintf(stderr, " (use ttf2pt1 -p? to get the full list of available front-ends)\n");
2060 /* open the input file */
2061 cursw->open(argv[1], front_arg);
2063 /* Get base name of output file (if not specified)
2064 * by removing (known) suffixes
2068 argv[2] = strdup (argv[1]);
2069 p = strrchr(argv[2], '.');
2071 for (j = 0; (j < MAXSUFFIX) && (cursw->suffix[j]); j++)
2072 if (!strcmp(p+1, cursw->suffix[j])) {
2078 if ((null_file = fopen(BITBUCKET, "wb")) == NULL) {
2079 fprintf(stderr, "**** Cannot open %s ****\n",
2083 if (argv[2][0] == '-' && argv[2][1] == 0) {
2086 fprintf(stderr, "**** can't write encoded file to stdout ***\n");
2089 #endif /* NOPIPES */
2090 pfa_file = afm_file = dvienc_file = null_file;
2092 if(wantafm || genlast == &gen_afm) { /* print .afm instead of .pfa */
2094 } else if(genlast == &gen_dvienc) { /* print .enc instead of .pfa */
2101 snprintf(filename, sizeof filename, "%s.%s", argv[2], encode ? (pfbflag ? "pfb" : "pfa") : "t1a" );
2103 snprintf(filename, sizeof filename, "%s.t1a", argv[2]);
2104 #endif /* NOPIPES */
2106 if ((pfa_file = fopen(filename, "wb+")) == NULL) {
2107 fprintf(stderr, "**** Cannot create %s ****\n", filename);
2110 WARNING_2 fprintf(stderr, "Creating file %s\n", filename);
2113 pfa_file = null_file;
2116 snprintf(filename, sizeof filename, "%s.afm", argv[2]) ;
2117 if ((afm_file = fopen(filename, "w+")) == NULL) {
2118 fprintf(stderr, "**** Cannot create %s ****\n", filename);
2122 afm_file = null_file;
2125 snprintf(filename, sizeof filename, "%s.enc", argv[2]) ;
2126 if ((dvienc_file = fopen(filename, "w+")) == NULL) {
2127 fprintf(stderr, "**** Cannot create %s ****\n", filename);
2131 dvienc_file = null_file;
2135 * Now check whether we want a fully encoded .pfa file
2138 if (encode && pfa_file != null_file) {
2140 extern FILE *ifp, *ofp; /* from t1asm.c */
2146 perror("**** Cannot create pipe ****\n");
2150 ifp = fdopen(p[0], "rb");
2152 perror("**** Cannot use pipe for reading ****\n");
2155 pfa_file = fdopen(p[1], "wb");
2156 if (pfa_file == NULL) {
2157 perror("**** Cannot use pipe for writing ****\n");
2162 perror("**** Cannot fork the assembler process ****\n");
2166 exit(runt1asm(pfbflag));
2167 default: /* parent */
2168 fclose(ifp); fclose(ofp);
2171 #endif /* NOPIPES */
2173 numglyphs = cursw->nglyphs();
2175 WARNING_3 fprintf(stderr, "numglyphs = %d\n", numglyphs);
2177 glyph_list = (GLYPH *) calloc(numglyphs, sizeof(GLYPH));
2179 /* initialize non-0 fields */
2180 for (i = 0; i < numglyphs; i++) {
2186 g->name = "UNKNOWN";
2187 g->flags = GF_FLOAT; /* we start with float representation */
2192 cursw->glmetrics(glyph_list);
2193 cursw->fnmetrics(&fontm);
2195 original_scale_factor = 1000.0 / (double) fontm.units_per_em;
2198 scale_factor = 1.0; /* don't transform */
2200 scale_factor = original_scale_factor;
2202 if(correctvsize && uni_sample!=0) { /* only for known languages */
2203 /* try to adjust the scale factor to make a typical
2204 * uppercase character of hight at least (correctvsize), this
2205 * may improve the appearance of the font but also
2206 * make it weird, use with caution
2210 ysz = iscale(glyph_list[encoding[uni_sample]].yMax);
2211 if( ysz<correctvsize ) {
2212 scale_factor *= (double)correctvsize / ysz;
2217 for (i = 0; i < numglyphs; i++) {
2218 glyph_list[i].flags |= GF_USED;
2221 for (i = 0; i < ENCTABSZ; i++) {
2222 glyph_list[encoding[i]].flags |= GF_USED;
2225 /* also always include .notdef */
2226 for (i = 0; i < numglyphs; i++)
2227 if(!strcmp(glyph_list[i].name, ".notdef")) {
2228 glyph_list[i].flags |= GF_USED;
2233 for (i = 0; i < numglyphs; i++) {
2234 if (glyph_list[i].flags & GF_USED) {
2235 DBG_TO_GLYPH(&glyph_list[i]);
2237 DBG_FROM_GLYPH(&glyph_list[i]);
2241 italic_angle = fontm.italic_angle;
2243 if (italic_angle > 45.0 || italic_angle < -45.0)
2244 italic_angle = 0.0; /* consider buggy */
2248 for (i = 0; i < numglyphs; i++) {
2249 if (glyph_list[i].flags & GF_USED) {
2250 DBG_TO_GLYPH(&glyph_list[i]);
2251 buildstems(&glyph_list[i]);
2252 assertpath(glyph_list[i].entries, __FILE__, __LINE__, glyph_list[i].name);
2253 DBG_FROM_GLYPH(&glyph_list[i]);
2259 bbox[i] = iscale(fontm.bbox[i]);
2261 /* don't touch the width of fixed width fonts */
2262 if( fontm.is_fixed_pitch )
2264 docorrectwidth(); /* checks correctwidth inside */
2266 for (i = 0; i < numglyphs; i++) {
2267 if (glyph_list[i].flags & GF_USED) {
2268 DBG_TO_GLYPH(&glyph_list[i]);
2269 reversepaths(&glyph_list[i]);
2270 assertpath(glyph_list[i].entries, __FILE__, __LINE__, glyph_list[i].name);
2271 DBG_FROM_GLYPH(&glyph_list[i]);
2278 ** It seems to bring troubles. The problem is that some
2279 ** styles of the font may be recognized as fixed-width
2280 ** while other styles of the same font as proportional.
2281 ** So it's better to be commented out yet.
2288 forcebold = fontm.force_bold;
2291 fprintf(pfa_file, "%%!PS-AdobeFont-1.0: %s %s\n", fontm.name_ps, fontm.name_copyright);
2293 fprintf(pfa_file, "%%%%CreationDate: %s", ctime(&now));
2294 fprintf(pfa_file, "%% Converted by ttf2pt1 %s/%s\n", TTF2PT1_VERSION, cursw->name);
2295 fprintf(pfa_file, "%% Args: %s\n", cmdline);
2296 fprintf(pfa_file, "%%%%EndComments\n");
2297 fprintf(pfa_file, "12 dict begin\n/FontInfo 9 dict dup begin\n");
2299 WARNING_3 fprintf(stderr, "FontName %s%s\n", fontm.name_ps, uni_font_name_suffix);
2302 fprintf(pfa_file, "/version (%s) readonly def\n", fontm.name_version);
2304 fprintf(pfa_file, "/Notice (%s) readonly def\n", fontm.name_copyright);
2306 fprintf(pfa_file, "/FullName (%s) readonly def\n", fontm.name_full);
2307 fprintf(pfa_file, "/FamilyName (%s) readonly def\n", fontm.name_family);
2311 fprintf(pfa_file, "/UniqueID %s def\n", strUID);
2314 for(i=0; fontm.name_full[i]!=0; i++) {
2315 numUID *= 37; /* magic number, good for hash */
2316 numUID += fontm.name_full[i]-' ';
2317 /* if the name is long the first chars
2318 * may be lost forever, so re-insert
2319 * them thus making kind of CRC
2321 numUID += (numUID>>24) & 0xFF;
2323 /* the range for private UIDs is 4 000 000 - 4 999 999 */
2324 fprintf(pfa_file, "/UniqueID %lu def\n", numUID%1000000+4000000);
2328 fprintf(pfa_file, "/Weight (%s) readonly def\n", fontm.name_style);
2330 fprintf(pfa_file, "/ItalicAngle %f def\n", italic_angle);
2331 fprintf(pfa_file, "/isFixedPitch %s def\n",
2332 fontm.is_fixed_pitch ? "true" : "false");
2334 /* we don't print out the unused glyphs */
2336 for (i = 0; i < numglyphs; i++) {
2337 if (glyph_list[i].flags & GF_USED) {
2342 fprintf(afm_file, "StartFontMetrics 4.1\n");
2343 fprintf(afm_file, "FontName %s%s\n", fontm.name_ps, uni_font_name_suffix);
2344 fprintf(afm_file, "FullName %s\n", fontm.name_full);
2345 fprintf(afm_file, "Notice %s\n", fontm.name_copyright);
2346 fprintf(afm_file, "EncodingScheme FontSpecific\n");
2347 fprintf(afm_file, "FamilyName %s\n", fontm.name_family);
2348 fprintf(afm_file, "Weight %s\n", fontm.name_style);
2349 fprintf(afm_file, "Version %s\n", fontm.name_version);
2350 fprintf(afm_file, "Characters %d\n", nchars);
2351 fprintf(afm_file, "ItalicAngle %.1f\n", italic_angle);
2353 fprintf(afm_file, "Ascender %d\n", iscale(fontm.ascender));
2354 fprintf(afm_file, "Descender %d\n", iscale(fontm.descender));
2356 fprintf(pfa_file, "/UnderlinePosition %d def\n",
2357 iscale(fontm.underline_position));
2359 fprintf(pfa_file, "/UnderlineThickness %hd def\nend readonly def\n",
2360 iscale(fontm.underline_thickness));
2362 fprintf(afm_file, "UnderlineThickness %d\n",
2363 iscale(fontm.underline_thickness));
2365 fprintf(afm_file, "UnderlinePosition %d\n",
2366 iscale(fontm.underline_position));
2368 fprintf(afm_file, "IsFixedPitch %s\n",
2369 fontm.is_fixed_pitch ? "true" : "false");
2370 fprintf(afm_file, "FontBBox %d %d %d %d\n",
2371 bbox[0], bbox[1], bbox[2], bbox[3]);
2373 fprintf(pfa_file, "/FontName /%s%s def\n", fontm.name_ps, uni_font_name_suffix);
2374 fprintf(pfa_file, "/PaintType 0 def\n/StrokeWidth 0 def\n");
2375 /* I'm not sure if these are fixed */
2376 fprintf(pfa_file, "/FontType 1 def\n");
2379 fprintf(pfa_file, "/FontMatrix [0.001 0 0 0.001 0 0] def\n");
2381 fprintf(pfa_file, "/FontMatrix [%9.7f 0 0 %9.7f 0 0] def\n",
2382 original_scale_factor / 1000.0, original_scale_factor / 1000.0);
2385 fprintf(pfa_file, "/FontBBox {%d %d %d %d} readonly def\n",
2386 bbox[0], bbox[1], bbox[2], bbox[3]);
2388 fprintf(pfa_file, "/Encoding 256 array\n");
2389 /* determine number of elements for metrics table */
2391 for (i = 0; i < numglyphs; i++) {
2392 if( glyph_list[i].flags & GF_USED
2393 && glyph_list[i].char_no == -1 ) {
2397 fprintf(afm_file, "StartCharMetrics %d\n", nmetrics);
2399 fprintf(dvienc_file, "/%s%sEncoding [\n",
2400 fontm.name_ps, uni_font_name_suffix);
2402 for (i = 0; i < 256; i++) { /* here 256, not ENCTABSZ */
2404 "dup %d /%s put\n", i, glyph_list[encoding[i]].name);
2405 if( glyph_list[encoding[i]].flags & GF_USED ) {
2406 print_glyph_metrics(i, encoding[i]);
2409 fprintf (dvienc_file, "/index0x%04X\n", encoding[i]);
2411 fprintf (dvienc_file, "/.notdef\n");
2414 /* print the metrics for glyphs not in encoding table */
2415 for(i=0; i<numglyphs; i++) {
2416 if( (glyph_list[i].flags & GF_USED)
2417 && glyph_list[i].char_no == -1 ) {
2418 print_glyph_metrics(-1, i);
2422 fprintf(pfa_file, "readonly def\ncurrentdict end\ncurrentfile eexec\n");
2423 fprintf(pfa_file, "dup /Private 16 dict dup begin\n");
2425 fprintf(pfa_file, "/RD{string currentfile exch readstring pop}executeonly def\n");
2426 fprintf(pfa_file, "/ND{noaccess def}executeonly def\n");
2427 fprintf(pfa_file, "/NP{noaccess put}executeonly def\n");
2429 /* UniqueID must be shown twice, in both font and Private dictionary */
2432 fprintf(pfa_file, "/UniqueID %s def\n", strUID);
2434 /* the range for private UIDs is 4 000 000 - 4 999 999 */
2435 fprintf(pfa_file, "/UniqueID %lu def\n", numUID%1000000+4000000);
2439 fprintf(pfa_file, "/ForceBold false def\n");
2440 else if(forcebold==1)
2441 fprintf(pfa_file, "/ForceBold true def\n");
2443 fprintf(pfa_file, "/BlueValues [ ");
2444 for (i = 0; i < nblues; i++)
2445 fprintf(pfa_file, "%d ", bluevalues[i]);
2446 fprintf(pfa_file, "] def\n");
2448 fprintf(pfa_file, "/OtherBlues [ ");
2449 for (i = 0; i < notherb; i++)
2450 fprintf(pfa_file, "%d ", otherblues[i]);
2451 fprintf(pfa_file, "] def\n");
2454 fprintf(pfa_file, "/StdHW [ %d ] def\n", stdhw);
2456 fprintf(pfa_file, "/StdVW [ %d ] def\n", stdvw);
2457 fprintf(pfa_file, "/StemSnapH [ ");
2458 for (i = 0; i < 12 && stemsnaph[i] != 0; i++)
2459 fprintf(pfa_file, "%d ", stemsnaph[i]);
2460 fprintf(pfa_file, "] def\n");
2461 fprintf(pfa_file, "/StemSnapV [ ");
2462 for (i = 0; i < 12 && stemsnapv[i] != 0; i++)
2463 fprintf(pfa_file, "%d ", stemsnapv[i]);
2464 fprintf(pfa_file, "] def\n");
2466 fprintf(pfa_file, "/MinFeature {16 16} def\n");
2467 /* Are these fixed also ? */
2468 fprintf(pfa_file, "/password 5839 def\n");
2470 /* calculate the number of subroutines */
2473 for (i = 0; i < numglyphs; i++) {
2474 if (glyph_list[i].flags & GF_USED) {
2475 subid+=glyph_list[i].nsg;
2479 fprintf(pfa_file, "/Subrs %d array\n", subid);
2480 /* standard subroutines */
2481 fprintf(pfa_file, "dup 0 {\n\t3 0 callothersubr pop pop setcurrentpoint return\n\t} NP\n");
2482 fprintf(pfa_file, "dup 1 {\n\t0 1 callothersubr return\n\t} NP\n");
2483 fprintf(pfa_file, "dup 2 {\n\t0 2 callothersubr return\n\t} NP\n");
2484 fprintf(pfa_file, "dup 3 {\n\treturn\n\t} NP\n");
2485 /* our sub to make the hint substitution code shorter */
2486 fprintf(pfa_file, "dup 4 {\n\t1 3 callothersubr pop callsubr return\n\t} NP\n");
2488 if(pfa_file != null_file) { /* save time if the output would be wasted */
2489 /* print the hinting subroutines */
2491 for (i = 0; i < numglyphs; i++) {
2492 if (glyph_list[i].flags & GF_USED) {
2493 subid+=print_glyph_subs(i, subid);
2497 fprintf(pfa_file, "ND\n");
2499 fprintf(pfa_file, "2 index /CharStrings %d dict dup begin\n", nchars);
2501 for (i = 0; i < numglyphs; i++) {
2502 if (glyph_list[i].flags & GF_USED) {
2509 fprintf(pfa_file, "end\nend\nreadonly put\n");
2510 fprintf(pfa_file, "noaccess put\n");
2511 fprintf(pfa_file, "dup/FontName get exch definefont pop\n");
2512 fprintf(pfa_file, "mark currentfile closefile\n");
2513 fprintf(pfa_file, "cleartomark\n");
2514 if(pfa_file != null_file)
2517 fprintf(afm_file, "EndCharMetrics\n");
2519 if(afm_file != null_file) { /* save time if the output would be wasted */
2520 /* print the kerning data if present */
2521 cursw->kerning(glyph_list);
2522 print_kerning(afm_file);
2525 fprintf(afm_file, "EndFontMetrics\n");
2526 if(afm_file != null_file)
2529 fprintf(dvienc_file, "] def\n");
2530 if(dvienc_file != null_file)
2531 fclose(dvienc_file);
2533 WARNING_1 fprintf(stderr, "Finished - font files created\n");
2538 while (wait(&ws) > 0) {
2541 if (encode && pfa_file != null_file) {
2542 extern FILE *ifp, *ofp; /* from t1asm.c */
2544 snprintf(filename, sizeof filename, "%s.%s", argv[2], pfbflag ? "pfb" : "pfa" );
2546 if ((ofp = fopen(filename, "wb+")) == NULL) {
2549 WARNING_2 fprintf(stderr, "Creating file %s\n", filename);
2552 snprintf(filename, sizeof filename, "%s.t1a", argv[2]);
2554 if ((ifp = fopen(filename, "rb")) == NULL) {
2557 WARNING_2 fprintf(stderr, "Converting file %s\n", filename);
2562 WARNING_2 fprintf(stderr, "Removing file %s\n", filename);
2563 if(unlink(filename) < 0)
2564 WARNING_1 fprintf(stderr, "Unable to remove file %s\n", filename);
2566 #endif /* NOPIPES */