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>
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 */
80 # define BITBUCKET "NUL"
89 /* table of front-ends */
91 extern struct frontsw ttf_sw;
92 #if defined(USE_FREETYPE)
93 extern struct frontsw freetype_sw;
96 struct frontsw *frontswtab[] = {
97 #if defined(USE_FREETYPE) && defined(PREFER_FREETYPE)
101 #if defined(USE_FREETYPE) && !defined(PREFER_FREETYPE)
104 NULL /* end of table */
107 struct frontsw *cursw=0; /* the active front end */
108 char *front_arg=""; /* optional argument */
111 int encode = 0; /* encode the resulting file */
112 int pfbflag = 0; /* produce compressed file */
113 int wantafm=0; /* want to see .afm instead of .t1a on stdout */
114 int correctvsize=0; /* try to correct the vertical size of characters */
115 int wantuid = 0; /* user wants UniqueID entry in the font */
116 int allglyphs = 0; /* convert all glyphs, not only 256 of them */
117 int warnlevel = -1; /* the level of permitted warnings */
118 int forcemap = 0; /* do mapping even on non-Unicode fonts */
119 /* options - maximal limits */
120 int max_stemdepth = 128; /* maximal depth of stem stack in interpreter (128 - limit from X11) */
121 /* options - debugging */
122 int absolute = 0; /* print out in absolute values */
123 int reverse = 1; /* reverse font to Type1 path directions */
124 /* options - suboptions of Outline Processing, defaults are set in table */
125 int optimize; /* enables space optimization */
126 int smooth; /* enable smoothing of outlines */
127 int transform; /* enables transformation to 1000x1000 matrix */
128 int hints; /* enables autogeneration of hints */
129 int subhints; /* enables autogeneration of substituted hints */
130 int trybold; /* try to guess whether the font is bold */
131 int correctwidth; /* try to correct the character width */
133 /* not quite options to select a particular source encoding */
134 int force_pid = -1; /* specific platform id */
135 int force_eid = -1; /* specific encoding id */
137 /* table of Outline Processing (may think also as Optimization) options */
139 char disbl; /* character to disable - enforced lowercase */
140 char enbl; /* character to enable - auto-set as toupper(disbl) */
141 int *valp; /* pointer to the actual variable containing value */
142 int dflt; /* default value */
143 char *descr; /* description */
145 { 'b', 0/*auto-set*/, &trybold, 1, "guessing of the ForceBold hint" },
146 { 'h', 0/*auto-set*/, &hints, 1, "autogeneration of hints" },
147 { 'u', 0/*auto-set*/, &subhints, 1, "hint substitution technique" },
148 { 'o', 0/*auto-set*/, &optimize, 1, "space optimization of font files" },
149 { 's', 0/*auto-set*/, &smooth, 1, "smoothing and repair of outlines" },
150 { 't', 0/*auto-set*/, &transform, 1, "auto-scaling to the standard matrix 1000x1000" },
151 { 'w', 0/*auto-set*/, &correctwidth, 0, "correct the glyph widths (use only for buggy fonts)" },
154 int debug = DEBUG; /* debugging flag */
156 FILE *pfa_file, *afm_file;
158 struct font_metrics fontm;
161 static char *strUID = 0; /* user-supplied UniqueID */
162 static unsigned long numUID; /* auto-generated UniqueID */
164 static int ps_fmt_3 = 0;
165 static double scale_factor, original_scale_factor;
167 static char *glyph_rename[ENCTABSZ];
169 /* the names assigned if the original font
170 * does not specify any
173 static char *Fmt3Encoding[256] = {
174 "c0", "c1", "c2", "c3",
175 "c4", "c5", "c6", "c7",
176 "c8", "c9", "c10", "c11",
177 "c12", "CR", "c14", "c15",
178 "c16", "c17", "c18", "c19",
179 "c20", "c21", "c22", "c23",
180 "c24", "c25", "c26", "c27",
181 "c28", "c29", "c30", "c31",
182 "space", "exclam", "quotedbl", "numbersign",
183 "dollar", "percent", "ampersand", "quotesingle",
184 "parenleft", "parenright", "asterisk", "plus",
185 "comma", "hyphen", "period", "slash",
186 "zero", "one", "two", "three",
187 "four", "five", "six", "seven",
188 "eight", "nine", "colon", "semicolon",
189 "less", "equal", "greater", "question",
196 "X", "Y", "Z", "bracketleft",
197 "backslash", "bracketright", "asciicircum", "underscore",
198 "grave", "a", "b", "c",
204 "x", "y", "z", "braceleft",
205 "bar", "braceright", "asciitilde", "c127",
206 "c128", "c129", "quotesinglbase", "florin",
207 "quotedblbase", "ellipsis", "dagger", "daggerdbl",
208 "circumflex", "perthousand", "Scaron", "guilsinglleft",
209 "OE", "c141", "c142", "c143",
210 "c144", "quoteleft", "quoteright", "quotedblleft",
211 "quotedblright", "bullet", "endash", "emdash",
212 "tilde", "trademark", "scaron", "guilsinglright",
213 "oe", "c157", "c158", "Ydieresis",
214 "nbspace", "exclamdown", "cent", "sterling",
215 "currency", "yen", "brokenbar", "section",
216 "dieresis", "copyright", "ordfeminine", "guillemotleft",
217 "logicalnot", "sfthyphen", "registered", "macron",
218 "degree", "plusminus", "twosuperior", "threesuperior",
219 "acute", "mu", "paragraph", "periodcentered",
220 "cedilla", "onesuperior", "ordmasculine", "guillemotright",
221 "onequarter", "onehalf", "threequarters", "questiondown",
222 "Agrave", "Aacute", "Acircumflex", "Atilde",
223 "Adieresis", "Aring", "AE", "Ccedilla",
224 "Egrave", "Eacute", "Ecircumflex", "Edieresis",
225 "Igrave", "Iacute", "Icircumflex", "Idieresis",
226 "Eth", "Ntilde", "Ograve", "Oacute",
227 "Ocircumflex", "Otilde", "Odieresis", "multiply",
228 "Oslash", "Ugrave", "Uacute", "Ucircumflex",
229 "Udieresis", "Yacute", "Thorn", "germandbls",
230 "agrave", "aacute", "acircumflex", "atilde",
231 "adieresis", "aring", "ae", "ccedilla",
232 "egrave", "eacute", "ecircumflex", "edieresis",
233 "igrave", "iacute", "icircumflex", "idieresis",
234 "eth", "ntilde", "ograve", "oacute",
235 "ocircumflex", "otilde", "odieresis", "divide",
236 "oslash", "ugrave", "uacute", "ucircumflex",
237 "udieresis", "yacute", "thorn", "ydieresis"
240 #ifdef notdef /* { */
241 /* This table is not used anywhere in the code
242 * so it's ifdef-ed out by default but left in
243 * the source code for reference purposes (and
244 * possibly for future use)
247 static char *ISOLatin1Encoding[256] = {
248 ".null", ".notdef", ".notdef", ".notdef",
249 ".notdef", ".notdef", ".notdef", ".notdef",
250 ".notdef", ".notdef", ".notdef", ".notdef",
251 ".notdef", "CR", ".notdef", ".notdef",
252 ".notdef", ".notdef", ".notdef", ".notdef",
253 ".notdef", ".notdef", ".notdef", ".notdef",
254 ".notdef", ".notdef", ".notdef", ".notdef",
255 ".notdef", ".notdef", ".notdef", ".notdef",
256 "space", "exclam", "quotedbl", "numbersign",
257 "dollar", "percent", "ampersand", "quoteright",
258 "parenleft", "parenright", "asterisk", "plus",
259 "comma", "hyphen", "period", "slash",
260 "zero", "one", "two", "three",
261 "four", "five", "six", "seven",
262 "eight", "nine", "colon", "semicolon",
263 "less", "equal", "greater", "question",
270 "X", "Y", "Z", "bracketleft",
271 "backslash", "bracketright", "asciicircum", "underscore",
272 "grave", "a", "b", "c",
278 "x", "y", "z", "braceleft",
279 "bar", "braceright", "asciitilde", "c127",
280 "c128", "c129", "quotesinglbase", "florin",
281 "quotedblbase", "ellipsis", "dagger", "daggerdbl",
282 "circumflex", "perthousand", "Scaron", "guilsinglleft",
283 "OE", "c141", "c142", "c143",
284 "c144", "quoteleft", "quoteright", "quotedblleft",
285 "quotedblright", "bullet", "endash", "emdash",
286 "tilde", "trademark", "scaron", "guilsinglright",
287 "oe", "c157", "c158", "Ydieresis",
288 "nbspace", "exclamdown", "cent", "sterling",
289 "currency", "yen", "brokenbar", "section",
290 "dieresis", "copyright", "ordfeminine", "guillemotleft",
291 "logicalnot", "sfthyphen", "registered", "macron",
292 "degree", "plusminus", "twosuperior", "threesuperior",
293 "acute", "mu", "paragraph", "periodcentered",
294 "cedilla", "onesuperior", "ordmasculine", "guillemotright",
295 "onequarter", "onehalf", "threequarters", "questiondown",
296 "Agrave", "Aacute", "Acircumflex", "Atilde",
297 "Adieresis", "Aring", "AE", "Ccedilla",
298 "Egrave", "Eacute", "Ecircumflex", "Edieresis",
299 "Igrave", "Iacute", "Icircumflex", "Idieresis",
300 "Eth", "Ntilde", "Ograve", "Oacute",
301 "Ocircumflex", "Otilde", "Odieresis", "multiply",
302 "Oslash", "Ugrave", "Uacute", "Ucircumflex",
303 "Udieresis", "Yacute", "Thorn", "germandbls",
304 "agrave", "aacute", "acircumflex", "atilde",
305 "adieresis", "aring", "ae", "ccedilla",
306 "egrave", "eacute", "ecircumflex", "edieresis",
307 "igrave", "iacute", "icircumflex", "idieresis",
308 "eth", "ntilde", "ograve", "oacute",
309 "ocircumflex", "otilde", "odieresis", "divide",
310 "oslash", "ugrave", "uacute", "ucircumflex",
311 "udieresis", "yacute", "thorn", "ydieresis"
314 #endif /* } notdef */
316 static char *adobe_StandardEncoding[256] = {
317 ".notdef", ".notdef", ".notdef", ".notdef",
318 ".notdef", ".notdef", ".notdef", ".notdef",
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 "space", "exclam", "quotedbl", "numbersign",
326 "dollar", "percent", "ampersand", "quoteright",
327 "parenleft", "parenright", "asterisk", "plus",
328 "comma", "hyphen", "period", "slash",
329 "zero", "one", "two", "three",
330 "four", "five", "six", "seven",
331 "eight", "nine", "colon", "semicolon",
332 "less", "equal", "greater", "question",
333 "at", "A", "B", "C", "D", "E", "F", "G",
334 "H", "I", "J", "K", "L", "M", "N", "O",
335 "P", "Q", "R", "S", "T", "U", "V", "W",
336 "X", "Y", "Z", "bracketleft",
337 "backslash", "bracketright", "asciicircum", "underscore",
338 "quoteleft", "a", "b", "c", "d", "e", "f", "g",
339 "h", "i", "j", "k", "l", "m", "n", "o",
340 "p", "q", "r", "s", "t", "u", "v", "w",
341 "x", "y", "z", "braceleft",
342 "bar", "braceright", "asciitilde", ".notdef",
343 ".notdef", ".notdef", ".notdef", ".notdef",
344 ".notdef", ".notdef", ".notdef", ".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", "exclamdown", "cent", "sterling",
352 "fraction", "yen", "florin", "section",
353 "currency", "quotesingle", "quotedblleft", "guillemotleft",
354 "guilsinglleft", "guilsinglright", "fi", "fl",
355 ".notdef", "endash", "dagger", "daggerdbl",
356 "periodcentered", ".notdef", "paragraph", "bullet",
357 "quotesinglbase", "quotedblbase", "quotedblright", "guillemotright",
358 "ellipsis", "perthousand", ".notdef", "questiondown",
359 ".notdef", "grave", "acute", "circumflex",
360 "tilde", "macron", "breve", "dotaccent",
361 "dieresis", ".notdef", "ring", "cedilla",
362 ".notdef", "hungarumlaut", "ogonek", "caron",
363 "emdash", ".notdef", ".notdef", ".notdef",
364 ".notdef", ".notdef", ".notdef", ".notdef",
365 ".notdef", ".notdef", ".notdef", ".notdef",
366 ".notdef", ".notdef", ".notdef", ".notdef",
367 ".notdef", "AE", ".notdef", "ordfeminine",
368 ".notdef", ".notdef", ".notdef", ".notdef",
369 "Lslash", "Oslash", "OE", "ordmasculine",
370 ".notdef", ".notdef", ".notdef", ".notdef",
371 ".notdef", "ae", ".notdef", ".notdef",
372 ".notdef", "dotlessi", ".notdef", ".notdef",
373 "lslash", "oslash", "oe", "germandbls",
374 ".notdef", ".notdef", ".notdef", ".notdef"
378 * Decription of the supported conversions from Unicode
381 * Yes, I know that the compiled-in conversion is stupid but
382 * it is simple to implement and allows not to worry about the
383 * filesystem context. After all, the source is always available
384 * and adding another language to it is easy.
386 * The language name is expected to be the same as the subdirectory name
387 * in the `encodings' directory (for possible future extensions).
388 * The primary use of the aliases is for guessing based on the current
392 #define MAXUNIALIAS 10
393 #define MAXUNITABLES 3
395 /* the character used as the language argument separator */
396 #define LANG_ARG_SEP '+'
400 * Types of language-related routines. Arguments are:
401 * name is the glyph name
402 * arg is the user-specified language-dependent argument
403 * which can for example select the subfont plane for Eastern fonts.
404 * If none is supplied by user then an empty string ("") is passed.
405 * If no language is specified by user and auto-guessing happens
406 * then NULL is passed.
407 * when shows if the conversion by name was called before conversion by
408 * map or after (it's called twice)
411 /* type of the Unicode map initialization routine */
412 typedef void uni_init_t(char *arg);
414 /* type of Unicode converter-by-name function
415 * it's called for each glyph twice: one time for each glyph
416 * before doing conversion by map and one time after
418 typedef int uni_conv_t(char *name, char *arg, int when);
419 #define UNICONV_BYNAME_BEFORE 0
420 #define UNICONV_BYNAME_AFTER 1
422 struct uni_language {
423 uni_init_t *init[MAXUNITABLES]; /* map initialization routines */
424 uni_conv_t *convbyname; /* the name-based conversion function */
425 char *name; /* the language name */
426 char *descr; /* description */
427 char *alias[MAXUNIALIAS]; /* aliases of the language name */
428 int sample_upper; /* code of some uppercase character for correctvsize() */
431 /* the converter routines have an option of adding this suffix to the font name */
432 static char *uni_font_name_suffix = ""; /* empty by default */
433 /* this buffer may be used to store the suffix */
434 #define UNI_MAX_SUFFIX_LEN 100
435 static char uni_suffix_buf[UNI_MAX_SUFFIX_LEN+1];
438 * Prototypes of the conversion routines
441 static uni_init_t unicode_latin1;
442 static uni_init_t unicode_latin2;
443 static uni_init_t unicode_latin4;
444 static uni_init_t unicode_latin5;
445 static uni_init_t unicode_cyrillic;
446 static uni_init_t unicode_adobestd;
447 static uni_init_t unicode_plane;
448 static uni_conv_t unicode_adobestd_byname;
450 static uni_init_t unicode_init_user;
453 * The order of descriptions is important: if we can't guess the
454 * language we just call all the conversion routines in order until
455 * we find one that understands this glyph.
457 static struct uni_language uni_lang[]= {
458 /* pseudo-language for all the languages using Latin1 */
461 0, /* no name-based mapping */
463 "works for most of the Western languages",
464 { "en_", "de_", "fr_", "nl_", "no_", "da_", "it_" },
467 { /* by Szalay Tamas <tomek@elender.hu> */
469 0, /* no name-based mapping */
471 "works for Central European languages",
472 { "hu_","pl_","cz_","si_","sk_" },
475 { /* by Rièardas Èepas <rch@WriteMe.Com> */
477 0, /* no name-based mapping */
479 "works for Baltic languages",
480 { "lt_", "lv_" }, /* doubt about ee_ */
483 { /* by Turgut Uyar <uyar@cs.itu.edu.tr> */
485 0, /* no name-based mapping */
491 { /* by Zvezdan Petkovic <z.petkovic@computer.org> */
492 { unicode_cyrillic, unicode_latin1 },
493 0, /* no name-based mapping */
495 "in Windows encoding",
496 { "bg_", "be_", "mk_", "ru_", "sr_", "su_", "uk_" },
500 { unicode_cyrillic, unicode_latin1 },
501 0, /* no name-based mapping */
503 "obsolete, use cyrillic instead",
508 { unicode_cyrillic, unicode_latin1 },
509 0, /* no name-based mapping */
511 "obsolete, use cyrillic instead",
516 { unicode_adobestd },
517 unicode_adobestd_byname,
519 "Adobe Standard, expected by TeX",
525 0, /* no name-based mapping */
527 "one plane of Unicode or other multi-byte encoding as is",
529 0 /* no easy way to predict the capital letters */
533 static struct uni_language uni_lang_user = {
534 { unicode_init_user },
535 0, /* no name-based mapping */
537 0, /* no description */
542 static struct uni_language *uni_lang_selected=0; /* 0 means "unknown, try all" */
543 static int uni_sample='A'; /* sample of an uppercase character */
544 static char *uni_lang_arg=""; /* user-supplied language-dependent argument */
546 extern int runt1asm(int);
549 * user-defined loadable maps
553 /* The idea begind buckets is to avoid comparing every code with all ENCTABSZ codes in table.
554 * All the 16-bit unicode space is divided between a number of equal-sized buckets.
555 * Initially all the buckets are marked with 0. Then if any code in the bucket is
556 * used it's marked with 1. Later during translation we check the code's bucket first
557 * and it it's 0 then return failure right away. This may be useful for
558 * Chinese fonts with many thousands of glyphs.
561 #define BUCKET_ID_BITS 11
562 #define MARK_UNI_BUCKET(unicode) SET_BITMAP(uni_user_buckets, (unicode)>>(16-BUCKET_ID_BITS))
563 #define IS_UNI_BUCKET(unicode) IS_BITMAP(uni_user_buckets, (unicode)>>(16-BUCKET_ID_BITS))
565 static DEF_BITMAP(uni_user_buckets, 1<<BUCKET_ID_BITS);
567 static unsigned int unicode_map[ENCTABSZ]; /* font-encoding to unicode map */
568 static int enctabsz = 256; /* actual number of codes used */
575 FILE *unicode_map_file;
577 char buffer[UNIBFSZ];
578 unsigned code, unicode, curpos, unicode2;
580 int enabled, found, sawplane;
581 int lineno, cnt, n, nchars;
583 int pid, eid, overid=0;
585 /* check if we have an argument (plane name) */
586 arg = strrchr(path, LANG_ARG_SEP);
589 if( sscanf(arg, "pid=%d,eid=%d%n", &pid, &eid, &nchars) == 2 ) {
590 force_pid = pid; force_eid = eid; overid = 1;
591 WARNING_1 fprintf(stderr, "User override of the source encoding: pid=%d eid=%d\n", pid, eid);
597 if( *arg == 0 || strlen(arg) > UNI_MAX_SUFFIX_LEN-1)
600 sprintf(uni_suffix_buf, "-%s", arg);
601 uni_font_name_suffix = uni_suffix_buf;
605 /* now read in the encoding description file, if requested */
606 if ((unicode_map_file = fopen(path, "r")) == NULL) {
607 fprintf(stderr, "**** Cannot access map file '%s' ****\n", path);
618 while (fgets (buffer, UNIBFSZ, unicode_map_file) != NULL) {
623 if(sscanf(buffer, "plane %s", name)==1) {
626 fprintf(stderr, "**** map file '%s' requires plane name\n", path);
627 fprintf(stderr, "for example:\n");
628 fprintf(stderr, " ttf2pt1 -L %s%c[pid=N,eid=N,]%s ...\n",
629 path, LANG_ARG_SEP, name);
630 fprintf(stderr, "to select plane '%s'\n", name);
633 if( !strcmp(arg, name) ) {
638 if(found) /* no need to read further */
644 if(sscanf(buffer, "id %d %d", pid, eid)==2) {
645 if( !overid /* only if the user has not overriden */
646 && (enabled || !sawplane) ) {
647 force_pid = pid; force_eid = eid;
654 continue; /* skip to the next plane */
656 if( sscanf(buffer, "at %i", &curpos) == 1 ) {
658 fprintf(stderr, "**** map file '%s' line %d: code over 255\n", path, lineno);
661 if(ISDBG(EXTMAP)) fprintf(stderr, "=== at 0x%x\n", curpos);
665 /* try the format of Roman Czyborra's files */
666 if ( sscanf (buffer, " =%x U+%4x", &code, &unicode) == 2
667 /* try the format of Linux locale charmap file */
668 || sscanf (buffer, " <%*s /x%x <U%4x>", &code, &unicode) == 2 ) {
669 if (code < ENCTABSZ) {
670 if(code >= enctabsz) enctabsz=code+1;
671 unicode_map[code] = unicode;
672 glyph_rename[code] = NULL;
675 /* try the format with glyph renaming */
676 else if (sscanf (buffer, " !%x U+%4x %128s", &code,
677 &unicode, name) == 3) {
678 if (code < ENCTABSZ) {
679 if(code >= enctabsz) enctabsz=code+1;
680 unicode_map[code] = unicode;
681 glyph_rename[code] = strdup(name);
684 /* try the compact sequence format */
685 else if( (n=sscanf(buffer, " %i%n", &unicode, &cnt)) == 1 ) {
689 fprintf(stderr, "**** map file '%s' line %d: code over 255 for unicode 0x%x\n",
690 path, lineno, unicode);
693 if(ISDBG(EXTMAP)) fprintf(stderr, "=== 0x%d -> 0x%x\n", curpos, unicode);
694 unicode_map[curpos++] = unicode;
696 if( sscanf(p, " %[,-]%n", &next,&cnt) == 1 ) {
697 if(ISDBG(EXTMAP)) fprintf(stderr, "=== next: '%c'\n", next);
699 if( next == '-' ) { /* range */
700 if ( sscanf(p, " %i%n", &unicode2, &cnt) != 1 ) {
701 fprintf(stderr, "**** map file '%s' line %d: missing end of range\n", path, lineno);
705 if(ISDBG(EXTMAP)) fprintf(stderr, "=== range 0x%x to 0x%x\n", unicode, unicode2);
706 for(unicode++; unicode <= unicode2; unicode++) {
708 fprintf(stderr, "**** map file '%s' line %d: code over 255 in unicode range ...-0x%x\n",
709 path, lineno, unicode2);
712 if(ISDBG(EXTMAP)) fprintf(stderr, "=== 0x%x -> 0x%x\n", curpos, unicode);
713 unicode_map[curpos++] = unicode;
717 } while ( sscanf(p, " %i%n", &unicode, &cnt) == 1 );
722 fclose (unicode_map_file);
725 fprintf(stderr, "**** map file '%s' has no plane '%s'\n", path, arg);
729 if(unicode_map['A'] == 'A')
730 uni_sample = 'A'; /* seems to be compatible with Latin */
732 uni_sample = 0; /* don't make any assumptions */
736 * by Zvezdan Petkovic <z.petkovic@computer.org>
744 static unsigned int cyrillic_unicode_map[] = {
745 0x0402, 0x0403, 0x201a, 0x0453, 0x201e, 0x2026, 0x2020, 0x2021, /* 80 */
746 0x20ac, 0x2030, 0x0409, 0x2039, 0x040a, 0x040c, 0x040b, 0x040f, /* 88 */
747 0x0452, 0x2018, 0x2019, 0x201c, 0x201d, 0x2022, 0x2013, 0x2014, /* 90 */
748 0x02dc, 0x2122, 0x0459, 0x203a, 0x045a, 0x045c, 0x045b, 0x045f, /* 98 */
749 0x00a0, 0x040e, 0x045e, 0x0408, 0x00a4, 0x0490, 0x00a6, 0x00a7, /* A0 */
750 0x0401, 0x00a9, 0x0404, 0x00ab, 0x00ac, 0x00ad, 0x00ae, 0x0407, /* A8 */
751 0x00b0, 0x00b1, 0x0406, 0x0456, 0x0491, 0x00b5, 0x00b6, 0x00b7, /* B0 */
752 0x0451, 0x2116, 0x0454, 0x00bb, 0x0458, 0x0405, 0x0455, 0x0457, /* B8 */
755 for(i=0; i<=0x7F; i++)
758 for(i=0x80; i<=0xBF; i++)
759 unicode_map[i] = cyrillic_unicode_map[i-0x80];
761 for(i=0xC0; i<=0xFF; i++)
762 unicode_map[i] = i+0x350;
772 static unsigned int latin1_unicode_map[] = {
773 0x20ac, -1, 0x201a, 0x0192, 0x201e, 0x2026, 0x2020, 0x2021, /* 80 */
774 0x02c6, 0x2030, 0x0160, 0x2039, 0x0152, 0x008d, 0x017d, 0x008f, /* 88 */
775 0x0090, 0x2018, 0x2019, 0x201c, 0x201d, 0x2022, 0x2013, 0x2014, /* 90 */
776 0x02dc, 0x2122, 0x0161, 0x203a, 0x0153, 0x009d, 0x017e, 0x0178, /* 98 */
779 for(i=0; i<=0x7F; i++)
782 for(i=0x80; i<=0x9F; i++)
783 unicode_map[i] = latin1_unicode_map[i-0x80];
785 for(i=0xA0; i<=0xFF; i++)
795 static unsigned int adobestd_unicode_map[] = {
796 -1, 0x00a1, 0x00a2, 0x00a3, 0x2215, 0x00a5, 0x0192, 0x00a7, /* A0 */
797 0x00a4, 0x0027, 0x201c, 0x00ab, 0x2039, 0x203a, 0xfb01, 0xfb02, /* A8 */
798 -1, 0x2013, 0x2020, 0x2021, 0x2219, -1, 0x00b6, 0x2022, /* B0 */
799 0x201a, 0x201e, 0x201d, 0x00bb, 0x2026, 0x2030, -1, 0x00bf, /* B8 */
800 -1, 0x0060, 0x00b4, 0x02c6, 0x02dc, 0x02c9, 0x02d8, 0x02d9, /* C0 */
801 0x00a8, -1, 0x02da, 0x00b8, -1, 0x02dd, 0x02db, 0x02c7, /* C8 */
802 0x2014, -1, -1, -1, -1, -1, -1, -1, /* D0 */
803 -1, -1, -1, -1, -1, -1, -1, -1, /* D8 */
804 -1, 0x00c6, -1, 0x00aa, -1, -1, -1, -1, /* E0 */
805 0x0141, 0x00d8, 0x0152, 0x00ba, -1, -1, -1, -1, /* E8 */
806 -1, 0x00e6, -1, -1, -1, 0x0131, -1, -1, /* F0 */
807 0x0142, 0x00f8, 0x0153, 0x00df, -1, -1, -1, -1, /* F8 */
810 for(i=0; i<=0x7F; i++)
813 unicode_map[0x27] = 0x2019;
814 unicode_map[0x60] = -1;
816 /* 0x80 to 0x9F is a hole */
818 for(i=0xA0; i<=0xFF; i++)
819 unicode_map[i] = adobestd_unicode_map[i-0xA0];
823 * Not all of the Adobe glyphs are in the Unicode
824 * standard maps, so the font creators have
825 * different ideas about their codes. Because
826 * of this we try to map based on the glyph
827 * names instead of Unicode codes. If there are
828 * no glyph names (ps_fmt_3!=0) we fall back
829 * to the code-based scheme.
833 unicode_adobestd_byname(
841 /* names always take precedence over codes */
842 if(where == UNICONV_BYNAME_AFTER)
845 for(i=32; i<256; i++) {
846 if(!strcmp(name, adobe_StandardEncoding[i]))
859 static unsigned int latin2_unicode_map[] = {
860 0x00a0, 0x0104, 0x02d8, 0x0141, 0x00a4, 0x013d, 0x015a, 0x00a7, /* A0 */
861 0x00a8, 0x0160, 0x015e, 0x0164, 0x0179, 0x00ad, 0x017d, 0x017b, /* A8 */
862 0x00b0, 0x0105, 0x02db, 0x0142, 0x00b4, 0x013e, 0x015b, 0x02c7, /* B0 */
863 0x00b8, 0x0161, 0x015f, 0x0165, 0x017a, 0x02dd, 0x017e, 0x017c, /* B8 */
864 0x0154, 0x00c1, 0x00c2, 0x0102, 0x00c4, 0x0139, 0x0106, 0x00c7, /* C0 */
865 0x010c, 0x00c9, 0x0118, 0x00cb, 0x011a, 0x00cd, 0x00ce, 0x010e, /* C8 */
866 0x0110, 0x0143, 0x0147, 0x00d3, 0x00d4, 0x0150, 0x00d6, 0x00d7, /* D0 */
867 0x0158, 0x016e, 0x00da, 0x0170, 0x00dc, 0x00dd, 0x0162, 0x00df, /* D8 */
868 0x0155, 0x00e1, 0x00e2, 0x0103, 0x00e4, 0x013a, 0x0107, 0x00e7, /* E0 */
869 0x010d, 0x00e9, 0x0119, 0x00eb, 0x011b, 0x00ed, 0x00ee, 0x010f, /* E8 */
870 0x0111, 0x0144, 0x0148, 0x00f3, 0x00f4, 0x0151, 0x00f6, 0x00f7, /* F0 */
871 0x0159, 0x016f, 0x00fa, 0x0171, 0x00fc, 0x00fd, 0x0163, 0x02d9, /* F8 */
874 for(i=0; i<=0x7E; i++)
877 /* 7F-9F are unused */
879 for(i=0xA0; i<=0xFF; i++)
880 unicode_map[i] = latin2_unicode_map[i-0xA0];
889 static unsigned int latin4_unicode_map[] = {
890 0x0080, 0x0081, 0x201a, 0x0192, -1, 0x2026, 0x2020, 0x2021, /* 80 */
891 0x02c6, 0x2030, -1, 0x2039, 0x0152, 0x008d, 0x008e, 0x008f, /* 88 */
892 0x201e, 0x201c, 0x2019, -1, 0x201d, 0x2022, 0x2013, 0x2014, /* 90 */
893 0x02dc, 0x2122, -1, 0x203a, 0x0153, 0x009d, 0x009e, 0x0178, /* 98 */
894 0x00a0, 0x0104, 0x0138, 0x0156, 0x00a4, 0x0128, 0x013b, 0x00a7, /* A0 */
895 0x00a8, 0x0160, 0x0112, 0x0122, 0x0166, 0x00ad, 0x017d, 0x00af, /* A8 */
896 0x00b0, 0x0105, 0x02db, 0x0157, 0x00b4, 0x0129, 0x013c, 0x02c7, /* B0 */
897 0x00b8, 0x0161, 0x0113, 0x0123, 0x0167, 0x014a, 0x017e, 0x014b, /* B8 */
898 0x0100, 0x00c1, 0x00c2, 0x00c3, 0x00c4, 0x00c5, 0x00c6, 0x012e, /* C0 */
899 0x010c, 0x00c9, 0x0118, 0x00cb, 0x0116, 0x00cd, 0x00ce, 0x012a, /* C8 */
900 0x0110, 0x0145, 0x014c, 0x0136, 0x00d4, 0x00d5, 0x00d6, 0x00d7, /* D0 */
901 0x00d8, 0x0172, 0x00da, 0x00db, 0x00dc, 0x0168, 0x016a, 0x00df, /* D8 */
902 0x0101, 0x00e1, 0x00e2, 0x00e3, 0x00e4, 0x00e5, 0x00e6, 0x012f, /* E0 */
903 0x010d, 0x00e9, 0x0119, 0x00eb, 0x0117, 0x00ed, 0x00ee, 0x012b, /* E8 */
904 0x0111, 0x0146, 0x014d, 0x0137, 0x00f4, 0x00f5, 0x00f6, 0x00f7, /* F0 */
905 0x00f8, 0x0173, 0x00fa, 0x00fb, 0x00fc, 0x0169, 0x016b, 0x02d9, /* F8 */
908 for(i=0; i<=0x7F; i++)
911 for(i=0x80; i<=0xFF; i++)
912 unicode_map[i] = latin4_unicode_map[i-0x80];
914 #if 0 /* for documentation purposes only */
915 case 0x201e: return 0x90; /* these two quotes are a hack only */
916 case 0x201c: return 0x91; /* these two quotes are a hack only */
917 case 0x00A0: return 0xA0; /* NO-BREAK SPACE */
918 case 0x0104: return 0xA1; /* LATIN CAPITAL LETTER A WITH OGONEK */
919 case 0x0138: return 0xA2; /* LATIN SMALL LETTER KRA */
920 case 0x0156: return 0xA3; /* LATIN CAPITAL LETTER R WITH CEDILLA */
921 case 0x00A4: return 0xA4; /* CURRENCY SIGN */
922 case 0x0128: return 0xA5; /* LATIN CAPITAL LETTER I WITH TILDE */
923 case 0x013B: return 0xA6; /* LATIN CAPITAL LETTER L WITH CEDILLA */
924 case 0x00A7: return 0xA7; /* SECTION SIGN */
925 case 0x00A8: return 0xA8; /* DIAERESIS */
926 case 0x0160: return 0xA9; /* LATIN CAPITAL LETTER S WITH CARON */
927 case 0x0112: return 0xAA; /* LATIN CAPITAL LETTER E WITH MACRON */
928 case 0x0122: return 0xAB; /* LATIN CAPITAL LETTER G WITH CEDILLA */
929 case 0x0166: return 0xAC; /* LATIN CAPITAL LETTER T WITH STROKE */
930 case 0x00AD: return 0xAD; /* SOFT HYPHEN */
931 case 0x017D: return 0xAE; /* LATIN CAPITAL LETTER Z WITH CARON */
932 case 0x00AF: return 0xAF; /* MACRON */
933 case 0x00B0: return 0xB0; /* DEGREE SIGN */
934 case 0x0105: return 0xB1; /* LATIN SMALL LETTER A WITH OGONEK */
935 case 0x02DB: return 0xB2; /* OGONEK */
936 case 0x0157: return 0xB3; /* LATIN SMALL LETTER R WITH CEDILLA */
937 case 0x00B4: return 0xB4; /* ACUTE ACCENT */
938 case 0x0129: return 0xB5; /* LATIN SMALL LETTER I WITH TILDE */
939 case 0x013C: return 0xB6; /* LATIN SMALL LETTER L WITH CEDILLA */
940 case 0x02C7: return 0xB7; /* CARON */
941 case 0x00B8: return 0xB8; /* CEDILLA */
942 case 0x0161: return 0xB9; /* LATIN SMALL LETTER S WITH CARON */
943 case 0x0113: return 0xBA; /* LATIN SMALL LETTER E WITH MACRON */
944 case 0x0123: return 0xBB; /* LATIN SMALL LETTER G WITH CEDILLA */
945 case 0x0167: return 0xBC; /* LATIN SMALL LETTER T WITH STROKE */
946 case 0x014A: return 0xBD; /* LATIN CAPITAL LETTER ENG */
947 case 0x017E: return 0xBE; /* LATIN SMALL LETTER Z WITH CARON */
948 case 0x014B: return 0xBF; /* LATIN SMALL LETTER ENG */
949 case 0x0100: return 0xC0; /* LATIN CAPITAL LETTER A WITH MACRON */
950 case 0x00C1: return 0xC1; /* LATIN CAPITAL LETTER A WITH ACUTE */
951 case 0x00C2: return 0xC2; /* LATIN CAPITAL LETTER A WITH CIRCUMFLEX */
952 case 0x00C3: return 0xC3; /* LATIN CAPITAL LETTER A WITH TILDE */
953 case 0x00C4: return 0xC4; /* LATIN CAPITAL LETTER A WITH DIAERESIS */
954 case 0x00C5: return 0xC5; /* LATIN CAPITAL LETTER A WITH RING ABOVE */
955 case 0x00C6: return 0xC6; /* LATIN CAPITAL LIGATURE AE */
956 case 0x012E: return 0xC7; /* LATIN CAPITAL LETTER I WITH OGONEK */
957 case 0x010C: return 0xC8; /* LATIN CAPITAL LETTER C WITH CARON */
958 case 0x00C9: return 0xC9; /* LATIN CAPITAL LETTER E WITH ACUTE */
959 case 0x0118: return 0xCA; /* LATIN CAPITAL LETTER E WITH OGONEK */
960 case 0x00CB: return 0xCB; /* LATIN CAPITAL LETTER E WITH DIAERESIS */
961 case 0x0116: return 0xCC; /* LATIN CAPITAL LETTER E WITH DOT ABOVE */
962 case 0x00CD: return 0xCD; /* LATIN CAPITAL LETTER I WITH ACUTE */
963 case 0x00CE: return 0xCE; /* LATIN CAPITAL LETTER I WITH CIRCUMFLEX */
964 case 0x012A: return 0xCF; /* LATIN CAPITAL LETTER I WITH MACRON */
965 case 0x0110: return 0xD0; /* LATIN CAPITAL LETTER D WITH STROKE */
966 case 0x0145: return 0xD1; /* LATIN CAPITAL LETTER N WITH CEDILLA */
967 case 0x014C: return 0xD2; /* LATIN CAPITAL LETTER O WITH MACRON */
968 case 0x0136: return 0xD3; /* LATIN CAPITAL LETTER K WITH CEDILLA */
969 case 0x00D4: return 0xD4; /* LATIN CAPITAL LETTER O WITH CIRCUMFLEX */
970 case 0x00D5: return 0xD5; /* LATIN CAPITAL LETTER O WITH TILDE */
971 case 0x00D6: return 0xD6; /* LATIN CAPITAL LETTER O WITH DIAERESIS */
972 case 0x00D7: return 0xD7; /* MULTIPLICATION SIGN */
973 case 0x00D8: return 0xD8; /* LATIN CAPITAL LETTER O WITH STROKE */
974 case 0x0172: return 0xD9; /* LATIN CAPITAL LETTER U WITH OGONEK */
975 case 0x00DA: return 0xDA; /* LATIN CAPITAL LETTER U WITH ACUTE */
976 case 0x00DB: return 0xDB; /* LATIN CAPITAL LETTER U WITH CIRCUMFLEX */
977 case 0x00DC: return 0xDC; /* LATIN CAPITAL LETTER U WITH DIAERESIS */
978 case 0x0168: return 0xDD; /* LATIN CAPITAL LETTER U WITH TILDE */
979 case 0x016A: return 0xDE; /* LATIN CAPITAL LETTER U WITH MACRON */
980 case 0x00DF: return 0xDF; /* LATIN SMALL LETTER SHARP S */
981 case 0x0101: return 0xE0; /* LATIN SMALL LETTER A WITH MACRON */
982 case 0x00E1: return 0xE1; /* LATIN SMALL LETTER A WITH ACUTE */
983 case 0x00E2: return 0xE2; /* LATIN SMALL LETTER A WITH CIRCUMFLEX */
984 case 0x00E3: return 0xE3; /* LATIN SMALL LETTER A WITH TILDE */
985 case 0x00E4: return 0xE4; /* LATIN SMALL LETTER A WITH DIAERESIS */
986 case 0x00E5: return 0xE5; /* LATIN SMALL LETTER A WITH RING ABOVE */
987 case 0x00E6: return 0xE6; /* LATIN SMALL LIGATURE AE */
988 case 0x012F: return 0xE7; /* LATIN SMALL LETTER I WITH OGONEK */
989 case 0x010D: return 0xE8; /* LATIN SMALL LETTER C WITH CARON */
990 case 0x00E9: return 0xE9; /* LATIN SMALL LETTER E WITH ACUTE */
991 case 0x0119: return 0xEA; /* LATIN SMALL LETTER E WITH OGONEK */
992 case 0x00EB: return 0xEB; /* LATIN SMALL LETTER E WITH DIAERESIS */
993 case 0x0117: return 0xEC; /* LATIN SMALL LETTER E WITH DOT ABOVE */
994 case 0x00ED: return 0xED; /* LATIN SMALL LETTER I WITH ACUTE */
995 case 0x00EE: return 0xEE; /* LATIN SMALL LETTER I WITH CIRCUMFLEX */
996 case 0x012B: return 0xEF; /* LATIN SMALL LETTER I WITH MACRON */
997 case 0x0111: return 0xF0; /* LATIN SMALL LETTER D WITH STROKE */
998 case 0x0146: return 0xF1; /* LATIN SMALL LETTER N WITH CEDILLA */
999 case 0x014D: return 0xF2; /* LATIN SMALL LETTER O WITH MACRON */
1000 case 0x0137: return 0xF3; /* LATIN SMALL LETTER K WITH CEDILLA */
1001 case 0x00F4: return 0xF4; /* LATIN SMALL LETTER O WITH CIRCUMFLEX */
1002 case 0x00F5: return 0xF5; /* LATIN SMALL LETTER O WITH TILDE */
1003 case 0x00F6: return 0xF6; /* LATIN SMALL LETTER O WITH DIAERESIS */
1004 case 0x00F7: return 0xF7; /* DIVISION SIGN */
1005 case 0x00F8: return 0xF8; /* LATIN SMALL LETTER O WITH STROKE */
1006 case 0x0173: return 0xF9; /* LATIN SMALL LETTER U WITH OGONEK */
1007 case 0x00FA: return 0xFA; /* LATIN SMALL LETTER U WITH ACUTE */
1008 case 0x00FB: return 0xFB; /* LATIN SMALL LETTER U WITH CIRCUMFLEX */
1009 case 0x00FC: return 0xFC; /* LATIN SMALL LETTER U WITH DIAERESIS */
1010 case 0x0169: return 0xFD; /* LATIN SMALL LETTER U WITH TILDE */
1011 case 0x016B: return 0xFE; /* LATIN SMALL LETTER U WITH MACRON */
1012 case 0x02D9: return 0xFF; /* DOT ABOVE */
1022 static unsigned int latin5_unicode_map1[] = {
1023 0x0080, 0x0081, 0x201a, 0x0192, 0x201e, 0x2026, 0x2020, 0x2021, /* 80 */
1024 0x02c6, 0x2030, 0x0160, 0x2039, 0x0152, 0x008d, 0x008e, 0x008f, /* 88 */
1025 0x0090, 0x2018, 0x2019, 0x201c, 0x201d, 0x2022, 0x2013, 0x2014, /* 90 */
1026 0x02dc, 0x2122, 0x0161, 0x203a, 0x0153, 0x009d, 0x009e, 0x0178, /* 98 */
1028 static unsigned int latin5_unicode_map2[] = {
1029 0x011e, 0x00d1, 0x00d2, 0x00d3, 0x00d4, 0x00d5, 0x00d6, 0x00d7, /* D0 */
1030 0x00d8, 0x00d9, 0x00da, 0x00db, 0x00dc, 0x0130, 0x015e, 0x00df, /* D8 */
1031 0x00e0, 0x00e1, 0x00e2, 0x00e3, 0x00e4, 0x00e5, 0x00e6, 0x00e7, /* E0 direct */
1032 0x00e8, 0x00e9, 0x00ea, 0x00eb, 0x00ec, 0x00ed, 0x00ee, 0x00ef, /* E8 direct */
1033 0x011f, 0x00f1, 0x00f2, 0x00f3, 0x00f4, 0x00f5, 0x00f6, 0x00f7, /* F0 */
1034 0x00f8, 0x00f9, 0x00fa, 0x00fb, 0x00fc, 0x0131, 0x015f, 0x00ff, /* F8 */
1037 for(i=0; i<=0x7F; i++)
1040 for(i=0x80; i<=0x9F; i++)
1041 unicode_map[i] = latin5_unicode_map1[i-0x80];
1043 for(i=0xA0; i<=0xCF; i++)
1046 for(i=0xD0; i<=0xFF; i++)
1047 unicode_map[i] = latin5_unicode_map2[i-0xD0];
1050 /* a way to select one 256-character plane from Unicode
1051 * or other multi-byte encoding
1059 static unsigned plane;
1063 if(uni_lang_selected == 0)
1064 return; /* don't participate in auto-guessing */
1066 plane = 0; force_pid = force_eid = -1;
1068 c1 = sscanf(arg, "pid=%d,eid=%d%n", &force_pid, &force_eid, &nchars);
1074 if(arg[0] == '0' && (arg[1]=='x' || arg[1]=='X') ) {
1076 c2 = sscanf(arg, "%x", &plane);
1078 c2 = sscanf(arg, "%d", &plane);
1081 if( (c1!=2 && c1!=0) || (c1==0 && c2==0) ) {
1082 fprintf(stderr, "**** option -l plane expects one of the following formats:\n");
1083 fprintf(stderr, " -l plane+0xNN - select hexadecimal number of plane of Unicode\n");
1084 fprintf(stderr, " -l plane+NN - select decimal number of plane of Unicode\n");
1085 fprintf(stderr, " -l plane+pid=N,eid=N - select plane 0 of specified encoding\n");
1086 fprintf(stderr, " -l plane+pid=N,eid=N,0xNN - select hex plane of TTF encoding with this PID/EID\n");
1087 fprintf(stderr, " -l plane+pid=N,eid=N,NN - select decimal plane of TTF encoding with this PID/EID\n");
1092 if(strlen(arg) > sizeof(uni_suffix_buf)-2) {
1093 fprintf(stderr, "**** plane number is too large\n");
1096 sprintf(uni_suffix_buf, "-%s", arg);
1097 uni_font_name_suffix = uni_suffix_buf;
1099 uni_font_name_suffix = "";
1103 for(i=0; i<=0xFF; i++)
1104 unicode_map[i] = plane | i;
1107 /* look up the 8-bit code by unicode */
1116 if( ! IS_UNI_BUCKET(unival) )
1119 for (res = 0; res < enctabsz; res++)
1120 if (unicode_map[res] == unival)
1125 /* mark the buckets for quick lookup */
1128 unicode_prepare_buckets(
1134 memset(uni_user_buckets, 0, sizeof uni_user_buckets);
1135 for(i=0; i<enctabsz; i++) {
1136 if(unicode_map[i] != (unsigned) -1)
1137 MARK_UNI_BUCKET(unicode_map[i]);
1142 * Scale the values according to the scale_factor
1150 return scale_factor * val;
1158 return (int) (val > 0 ? scale_factor * val + 0.5
1159 : scale_factor * val - 0.5);
1163 * Try to force fixed width of characters
1170 int n = 0, avg, max = 0, min = 3000, sum = 0, x;
1172 for (i = 0; i < numglyphs; i++) {
1173 if (glyph_list[i].flags & GF_USED) {
1174 x = glyph_list[i].width;
1193 WARNING_3 fprintf(stderr, "widths: max=%d avg=%d min=%d\n", max, avg, min);
1195 /* if less than 5% variation from average */
1196 /* force fixed width */
1197 if (20 * (avg - min) < avg && 20 * (max - avg) < avg) {
1198 for (i = 0; i < numglyphs; i++) {
1199 if (glyph_list[i].flags & GF_USED)
1200 glyph_list[i].width = avg;
1202 fontm.is_fixed_pitch = 1;
1214 g = &glyph_list[glyphno];
1217 g->scaledwidth = iscale(g->width);
1222 if (g->ttf_pathlen != 0) {
1223 cursw->glpath(glyphno, glyph_list);
1227 dumppaths(g, NULL, NULL);
1229 assertpath(g->entries, __FILE__, __LINE__, g->name);
1232 assertpath(g->entries, __FILE__, __LINE__, g->name);
1234 /* float processing */
1237 assertpath(g->entries, __FILE__, __LINE__, g->name);
1240 assertpath(g->entries, __FILE__, __LINE__, g->name);
1243 assertpath(g->entries, __FILE__, __LINE__, g->name);
1246 assertpath(g->entries, __FILE__, __LINE__, g->name);
1250 /* all processing past this point expects integer path */
1251 assertpath(g->entries, __FILE__, __LINE__, g->name);
1258 /* int processing */
1261 assertpath(g->entries, __FILE__, __LINE__, g->name);
1269 for(ge = g->entries; ge; ge = ge->next)
1272 if (ncurves > 100) {
1273 WARNING_2 fprintf(stderr,
1274 "** Glyph %s is too long, may display incorrectly\n",
1278 /* for buildstems */
1279 g->flags &= ~GF_FLOAT;
1286 int i, n, found, c, type;
1288 /* get the names from the font file */
1289 ps_fmt_3 = cursw->glnames(glyph_list);
1291 /* check for names with wrong characters */
1292 for (n = 0; n < numglyphs; n++) {
1294 for (i = 0; (c = glyph_list[n].name[i]) != 0; i++) {
1295 if (!(isalnum(c) || c == '.' || c == '_' )
1296 || i==0 && isdigit(c)) { /* must not start with a digit */
1297 WARNING_3 fprintf(stderr, "Glyph %d %s (%s), ",
1298 n, isdigit(c) ? "name starts with a digit" :
1299 "has bad characters in name",
1300 glyph_list[n].name);
1301 glyph_list[n].name = malloc(10);
1302 sprintf(glyph_list[n].name, "_%d", n);
1303 WARNING_3 fprintf(stderr, "changing to %s\n", glyph_list[n].name);
1310 /* check for duplicate names */
1311 for (n = 0; n < numglyphs; n++) {
1313 for (i = 0; i < n && !found; i++) {
1314 if (strcmp(glyph_list[i].name, glyph_list[n].name) == 0) {
1315 glyph_list[n].name = malloc(10);
1316 sprintf(glyph_list[n].name, "_%d", n);
1317 WARNING_3 fprintf(stderr,
1318 "Glyph %d has the same name as %d: (%s), changing to %s\n",
1321 glyph_list[n].name);
1329 /* start the encoding stuff */
1330 for (i = 0; i < ENCTABSZ; i++) {
1334 /* do the 1st round of encoding by name */
1335 if(!ps_fmt_3 && uni_lang_selected && uni_lang_selected->convbyname) {
1336 for (n = 0; n < numglyphs; n++) {
1337 c = uni_lang_selected->convbyname(glyph_list[n].name,
1338 uni_lang_arg, UNICONV_BYNAME_BEFORE);
1339 if(c>=0 && c<ENCTABSZ && encoding[c] == -1)
1344 /* now do the encoding by table */
1345 if(uni_lang_selected) {
1346 for(i=0; i < MAXUNITABLES && uni_lang_selected->init[i]; i++) {
1347 for (n = 0; n < ENCTABSZ; n++)
1348 unicode_map[n] = -1;
1349 uni_lang_selected->init[i](uni_lang_arg);
1350 unicode_prepare_buckets();
1351 if( cursw->glenc(glyph_list, encoding, unicode_map) == 0 )
1352 /* if we have an 8-bit encoding we don't need more tries */
1356 /* language is unknown, try the first table of each */
1357 for(i=0; i < sizeof uni_lang/(sizeof uni_lang[0]); i++) {
1358 if(uni_lang[i].init[0] == NULL)
1360 for (n = 0; n < ENCTABSZ; n++)
1361 unicode_map[n] = -1;
1362 uni_lang[i].init[0](uni_lang_arg);
1363 unicode_prepare_buckets();
1364 if( cursw->glenc(glyph_list, encoding, unicode_map) == 0 )
1365 /* if we have an 8-bit encoding we don't need more tries */
1371 for (i = 0; i < 256; i++) { /* here 256, not ENCTABSZ */
1372 if (encoding[i] > 0) {
1373 glyph_list[encoding[i]].name = Fmt3Encoding[i];
1378 /* do the 2nd round of encoding by name */
1379 if(uni_lang_selected && uni_lang_selected->convbyname) {
1380 for (n = 0; n < numglyphs; n++) {
1381 c = uni_lang_selected->convbyname(glyph_list[n].name,
1382 uni_lang_arg, UNICONV_BYNAME_AFTER);
1383 if(c>=0 && c<ENCTABSZ && encoding[c] == -1)
1387 /* all the encoding things are done */
1389 for (i = 0; i < ENCTABSZ; i++)
1390 if(encoding[i] == -1) /* defaults to .notdef */
1393 for (i = 0; i < 256; i++) /* here 256, not ENCTABSZ */
1394 glyph_list[encoding[i]].char_no = i;
1396 /* enforce two special cases defined in TTF manual */
1398 glyph_list[0].name = ".notdef";
1400 glyph_list[1].name = ".null";
1402 for (i = 0; i < ENCTABSZ; i++) {
1403 if ((encoding[i] != 0) && glyph_rename[i]) {
1404 glyph_list[encoding[i]].name = glyph_rename[i];
1415 # define fplop(txt) fputs(txt, stderr);
1420 fputs("Use:\n", stderr);
1421 fputs("ttf2pt1 [-<opts>] [-l language | -L file] <ttf-file> [<fontname>]\n", stderr);
1422 fputs(" or\n", stderr);
1423 fputs("ttf2pt1 [-<opts>] [-l language | -L file] <ttf-file> -\n", stderr);
1424 fputs(" or\n", stderr);
1425 fputs("ttf2pt1 [-<opts>] [-l language | -L file] <ttf-file> - | t1asm > <pfa-file>\n", stderr);
1428 fplop("This build supports both short and long option names,\n");
1429 fplop("the long options are listed before corresponding short ones\n");
1432 fputs(" -A - write the .afm file to STDOUT instead of the font itself\n", stderr);
1433 fplop(" --all-glyphs\n");
1434 fputs(" -a - include all glyphs, even those not in the encoding table\n", stderr);
1436 fputs(" -b - produce a compressed .pfb file\n", stderr);
1437 fplop(" --debug dbg_suboptions\n");
1438 fputs(" -d dbg_suboptions - debugging options, run ttf2pt1 -d? for help\n", stderr);
1439 fplop(" --encode\n");
1440 fputs(" -e - produce a fully encoded .pfa file\n", stderr);
1441 fplop(" --force-unicode\n");
1442 fputs(" -F - force use of Unicode encoding even if other MS encoding detected\n", stderr);
1443 fplop(" --language language\n");
1444 fputs(" -l language - convert Unicode to specified language, run ttf2pt1 -l? for list\n", stderr);
1445 fplop(" --language-map file\n");
1446 fputs(" -L file - convert Unicode according to encoding description file\n", stderr);
1447 fplop(" --limit <type>=<value>\n");
1448 fputs(" -m <type>=<value> - set maximal limit of given type to value, types:\n", stderr);
1449 fputs(" h - maximal hint stack depth in the PostScript interpreter\n", stderr);
1450 fplop(" --processing suboptions\n");
1451 fputs(" -O suboptions - control outline processing, run ttf2pt1 -O? for help\n", stderr);
1452 fplop(" --parser name\n");
1453 fputs(" -p name - use specific front-end parser, run ttf2pt1 -p? for list\n", stderr);
1454 fplop(" --uid id\n");
1455 fputs(" -u id - use this UniqueID, -u A means autogeneration\n", stderr);
1456 fplop(" --vertical-autoscale size\n");
1457 fputs(" -v size - scale the font to make uppercase letters >size/1000 high\n", stderr);
1458 fplop(" --version\n");
1459 fputs(" -V - print ttf2pt1 version number\n", stderr);
1460 fplop(" --warning number\n");
1461 fputs(" -W number - set the level of permitted warnings (0 - disable)\n", stderr);
1462 fputs("Obsolete options (will be removed in future releases, use -O? instead):\n", stderr);
1463 fputs(" -f - don't try to guess the value of the ForceBold hint\n", stderr);
1464 fputs(" -h - disable autogeneration of hints\n", stderr);
1465 fputs(" -H - disable hint substitution\n", stderr);
1466 fputs(" -o - disable outline optimization\n", stderr);
1467 fputs(" -s - disable outline smoothing\n", stderr);
1468 fputs(" -t - disable auto-scaling to 1000x1000 standard matrix\n", stderr);
1469 fputs(" -w - correct the glyph widths (use only for buggy fonts)\n", stderr);
1470 fputs("With no <fontname>, write to <ttf-file> with suffix replaced.\n", stderr);
1471 fputs("The last '-' means 'use STDOUT'.\n", stderr);
1480 fprintf(stderr, "ttf2pt1 %s\n", TTF2PT1_VERSION);
1492 int c,nchars,nmetrics;
1494 int forcebold= -1; /* -1 means "don't know" */
1499 # define ttf2pt1_getopt(a, b, c, d, e) getopt_long(a, b, c, d, e)
1500 static struct option longopts[] = {
1501 { "afm", 0, NULL, 'A' },
1502 { "all-glyphs", 0, NULL, 'a' },
1503 { "pfb", 0, NULL, 'b' },
1504 { "debug", 1, NULL, 'd' },
1505 { "encode", 0, NULL, 'e' },
1506 { "force-unicode", 0, NULL, 'F' },
1507 { "language", 1, NULL, 'l' },
1508 { "language-map", 1, NULL, 'L' },
1509 { "limit", 1, NULL, 'm' },
1510 { "processing", 1, NULL, 'O' },
1511 { "parser", 1, NULL, 'p' },
1512 { "uid", 1, NULL, 'u' },
1513 { "vertical-autoscale", 1, NULL, 'v' },
1514 { "version", 0, NULL, 'V' },
1515 { "warning", 1, NULL, 'W' },
1516 { NULL, 0, NULL, 0 }
1519 # define ttf2pt1_getopt(a, b, c, d, e) getopt(a, b, c)
1522 /* initialize sub-options of -O */
1523 for(i=0; i< (sizeof opotbl)/(sizeof opotbl[0]); i++) {
1524 opotbl[i].disbl = tolower(opotbl[i].disbl);
1525 opotbl[i].enbl = toupper(opotbl[i].disbl);
1526 *(opotbl[i].valp) = opotbl[i].dflt;
1529 while(( oc=ttf2pt1_getopt(argc, argv, "FaoebAsthHfwVv:p:l:d:u:L:m:W:O:",
1530 longopts, NULL) )!= -1) {
1536 fputs("Warning: option -o is obsolete, use -Oo instead\n", stderr);
1543 encode = pfbflag = 1;
1552 fputs("Warning: option -s is obsolete, use -Os instead\n", stderr);
1556 fputs("Warning: option -t is obsolete, use -Ot instead\n", stderr);
1560 for(i=0; optarg[i]!=0; i++)
1569 if (optarg[i] != '?')
1570 fprintf(stderr, "**** Unknown debugging option '%c' ****\n", optarg[i]);
1571 fputs("The recognized debugging options are:\n", stderr);
1572 fputs(" a - enable absolute coordinates\n", stderr);
1573 fputs(" r - do not reverse font outlines directions\n", stderr);
1583 if(sscanf(optarg, "%c=%d", &subopt, &val) !=2) {
1584 fprintf(stderr, "**** Misformatted maximal limit ****\n");
1585 fprintf(stderr, "spaces around the equal sign are not allowed\n");
1586 fprintf(stderr, "good examples: -mh=100 -m h=100\n");
1587 fprintf(stderr, "bad examples: -mh = 100 -mh= 100\n");
1593 max_stemdepth = val;
1597 fprintf(stderr, "**** Unknown limit type '%c' ****\n", subopt);
1598 fputs("The recognized limit types are:\n", stderr);
1599 fputs(" h - maximal hint stack depth in the PostScript interpreter\n", stderr);
1609 char dflt[20]; /* should be big enough */
1610 for(p=optarg; (subopt = *p) != 0; p++) {
1611 for(i=0; i< (sizeof opotbl)/(sizeof opotbl[0]); i++) {
1612 if(subopt == opotbl[i].disbl) {
1613 *(opotbl[i].valp) = 0;
1615 } else if(subopt == opotbl[i].enbl) {
1616 *(opotbl[i].valp) = 1;
1620 if( i == (sizeof opotbl)/(sizeof opotbl[0]) ) { /* found no match */
1622 fprintf(stderr, "**** Unknown outline processing suboption '%c' ****\n", subopt);
1623 fprintf(stderr,"The general form of the outline processing option is:\n");
1624 fprintf(stderr," -O suboptions\n");
1625 fprintf(stderr,"(To remember easily -O may be also thought of as \"optimization\").\n");
1626 fprintf(stderr,"The lowercase suboptions disable features, corresponding\n");
1627 fprintf(stderr,"uppercase suboptions enable them. The supported suboptions,\n");
1628 fprintf(stderr,"their default states and the features they control are:\n");
1630 for(i=0; i< (sizeof opotbl)/(sizeof opotbl[0]); i++) {
1631 fprintf(stderr," %c/%c - [%s] %s\n", opotbl[i].disbl, opotbl[i].enbl,
1632 opotbl[i].dflt ? "enabled" : "disabled", opotbl[i].descr);
1634 *p++ = opotbl[i].enbl;
1636 *p++ = opotbl[i].disbl;
1639 fprintf(stderr, "The default state corresponds to the option -O %s\n", dflt);
1646 fputs("Warning: option -h is obsolete, use -Oh instead\n", stderr);
1650 fputs("Warning: meaning of option -H has been changed to its opposite\n", stderr);
1651 fputs("Warning: option -H is obsolete, use -Ou instead\n", stderr);
1655 fputs("Warning: option -f is obsolete, use -Ob instead\n", stderr);
1659 fputs("Warning: option -w is obsolete, use -OW instead\n", stderr);
1664 fprintf(stderr, "**** UniqueID may be specified only once ****\n");
1668 if(optarg[0]=='A' && optarg[1]==0)
1669 strUID=0; /* will be generated automatically */
1672 for(i=0; optarg[i]!=0; i++)
1673 if( !isdigit(optarg[i]) ) {
1674 fprintf(stderr, "**** UniqueID must be numeric or A for automatic ****\n");
1680 correctvsize = atoi(optarg);
1681 if(correctvsize <= 0 && correctvsize > 1000) {
1682 fprintf(stderr, "**** wrong vsize '%d', ignored ****\n", correctvsize);
1688 fprintf(stderr, "**** only one front-end parser be used ****\n");
1692 { /* separate parser from parser-specific argument */
1693 char *p = strchr(optarg, LANG_ARG_SEP);
1700 for(i=0; frontswtab[i] != NULL; i++)
1701 if( !strcmp(frontswtab[i]->name, optarg) ) {
1702 cursw = frontswtab[i];
1707 if (strcmp(optarg, "?"))
1708 fprintf(stderr, "**** unknown front-end parser '%s' ****\n", optarg);
1709 fputs("the following front-ends are supported now:\n", stderr);
1710 for(i=0; frontswtab[i] != NULL; i++) {
1711 fprintf(stderr," %s (%s)\n file suffixes: ",
1712 frontswtab[i]->name,
1713 frontswtab[i]->descr ? frontswtab[i]->descr : "no description"
1715 for(j=0; j<MAXSUFFIX; j++)
1716 if(frontswtab[i]->suffix[j])
1717 fprintf(stderr, "%s ", frontswtab[i]->suffix[j]);
1718 fprintf(stderr, "\n");
1724 if(uni_lang_selected!=0) {
1725 fprintf(stderr, "**** only one language option may be used ****\n");
1729 { /* separate language from language-specific argument */
1730 char *p = strchr(optarg, LANG_ARG_SEP);
1737 for(i=0; i < sizeof uni_lang/(sizeof uni_lang[0]); i++)
1738 if( !strcmp(uni_lang[i].name, optarg) ) {
1739 uni_lang_selected = &uni_lang[i];
1740 uni_sample = uni_lang[i].sample_upper;
1744 if(uni_lang_selected==0) {
1745 if (strcmp(optarg, "?"))
1746 fprintf(stderr, "**** unknown language '%s' ****\n", optarg);
1747 fputs(" the following languages are supported now:\n", stderr);
1748 for(i=0; i < sizeof uni_lang/(sizeof uni_lang[0]); i++)
1749 fprintf(stderr," %s (%s)\n",
1751 uni_lang[i].descr ? uni_lang[i].descr : "no description"
1757 if(uni_lang_selected!=0) {
1758 fprintf(stderr, "**** only one language option may be used ****\n");
1761 uni_lang_selected = &uni_lang_user;
1762 uni_lang_arg = optarg;
1774 argc-=optind-1; /* the rest of code counts from argv[0] */
1777 if (absolute && encode) {
1778 fprintf(stderr, "**** options -a and -e are incompatible ****\n");
1781 if ((argc != 2) && (argc != 3)) {
1786 /* try to guess the language by the locale used */
1787 if(uni_lang_selected==0 && (lang=getenv("LANG"))!=0 ) {
1788 for(i=0; i < sizeof uni_lang/sizeof(struct uni_language); i++) {
1789 if( !strncmp(uni_lang[i].name, lang, strlen(uni_lang[i].name)) ) {
1790 uni_lang_selected = &uni_lang[i];
1791 goto got_a_language;
1794 /* no full name ? try aliases */
1795 for(i=0; i < sizeof uni_lang/sizeof(struct uni_language); i++) {
1796 for(c=0; c<MAXUNIALIAS; c++)
1797 if( uni_lang[i].alias[c]!=0
1798 && !strncmp(uni_lang[i].alias[c], lang, strlen(uni_lang[i].alias[c])) ) {
1799 uni_lang_selected = &uni_lang[i];
1800 goto got_a_language;
1804 if(uni_lang_selected!=0) {
1805 WARNING_1 fprintf(stderr, "Using language '%s' for Unicode fonts\n", uni_lang[i].name);
1806 uni_sample = uni_lang[i].sample_upper;
1810 /* try to guess the front-end parser by the file name suffix */
1812 char *p = strrchr(argv[1], '.');
1815 if(p!=0 && (s = strdup(p+1))!=0) {
1820 for(i=0; frontswtab[i] != 0 && cursw == 0; i++) {
1821 for(j=0; j<MAXSUFFIX; j++)
1822 if(frontswtab[i]->suffix[j]
1823 && !strcmp(p, frontswtab[i]->suffix[j]) ) {
1824 cursw = frontswtab[i];
1825 WARNING_1 fprintf(stderr, "Auto-detected front-end parser '%s'\n",
1827 WARNING_1 fprintf(stderr, " (use ttf2pt1 -p? to get the full list of available front-ends)\n");
1835 cursw = frontswtab[0];
1836 WARNING_1 fprintf(stderr, "Can't detect front-end parser, using '%s' by default\n",
1838 WARNING_1 fprintf(stderr, " (use ttf2pt1 -p? to get the full list of available front-ends)\n");
1842 /* open the input file */
1843 cursw->open(argv[1], front_arg);
1845 /* Get base name of output file (if not specified)
1846 * by removing (known) suffixes
1850 argv[2] = strdup (argv[1]);
1851 p = strrchr(argv[2], '.');
1853 for (j = 0; (j < MAXSUFFIX) && (cursw->suffix[j]); j++)
1854 if (!strcmp(p+1, cursw->suffix[j])) {
1860 if (argv[2][0] == '-' && argv[2][1] == 0) {
1864 fprintf(stderr, "**** can't write encoded file to stdout ***\n");
1867 #endif /* WINDOWS */
1868 if ((afm_file = fopen(BITBUCKET, "w+")) == NULL) {
1869 fprintf(stderr, "**** Cannot open %s ****\n",
1873 if(wantafm) { /* print .afm instead of .pfa */
1881 sprintf(filename, "%s.%s", argv[2], encode ? (pfbflag ? "pfb" : "pfa") : "t1a" );
1883 sprintf(filename, "%s.t1a", argv[2]);
1884 #endif /* WINDOWS */
1885 if ((pfa_file = fopen(filename, "w+b")) == NULL) {
1886 fprintf(stderr, "**** Cannot create %s ****\n", filename);
1889 WARNING_2 fprintf(stderr, "Creating file %s\n", filename);
1892 sprintf(filename, "%s.afm", argv[2]) ;
1893 if ((afm_file = fopen(filename, "w+")) == NULL) {
1894 fprintf(stderr, "**** Cannot create %s ****\n", filename);
1900 * Now check whether we want a fully encoded .pfa file
1905 extern FILE *ifp, *ofp; /* from t1asm.c */
1911 perror("**** Cannot create pipe ****\n");
1915 ifp = fdopen(p[0], "r");
1917 perror("**** Cannot use pipe for reading ****\n");
1920 pfa_file = fdopen(p[1], "w");
1921 if (pfa_file == NULL) {
1922 perror("**** Cannot use pipe for writing ****\n");
1927 perror("**** Cannot fork the assembler process ****\n");
1931 exit(runt1asm(pfbflag));
1932 default: /* parent */
1933 fclose(ifp); fclose(ofp);
1936 #endif /* WINDOWS */
1938 numglyphs = cursw->nglyphs();
1940 WARNING_3 fprintf(stderr, "numglyphs = %d\n", numglyphs);
1942 glyph_list = (GLYPH *) calloc(numglyphs, sizeof(GLYPH));
1944 /* initialize non-0 fields */
1945 for (i = 0; i < numglyphs; i++) {
1951 g->name = "UNKNOWN";
1952 g->flags = GF_FLOAT; /* we start with float representation */
1957 cursw->glmetrics(glyph_list);
1958 cursw->fnmetrics(&fontm);
1960 original_scale_factor = 1000.0 / (double) fontm.units_per_em;
1963 scale_factor = 1.0; /* don't transform */
1965 scale_factor = original_scale_factor;
1967 if(correctvsize && uni_sample!=0) { /* only for known languages */
1968 /* try to adjust the scale factor to make a typical
1969 * uppercase character of hight at least (correctvsize), this
1970 * may improve the appearance of the font but also
1971 * make it weird, use with caution
1975 ysz = iscale(glyph_list[encoding[uni_sample]].yMax);
1976 if( ysz<correctvsize ) {
1977 scale_factor *= (double)correctvsize / ysz;
1982 for (i = 0; i < numglyphs; i++) {
1983 glyph_list[i].flags |= GF_USED;
1986 for (i = 0; i < ENCTABSZ; i++) {
1987 glyph_list[encoding[i]].flags |= GF_USED;
1990 /* also always include .notdef */
1991 for (i = 0; i < numglyphs; i++)
1992 if(!strcmp(glyph_list[i].name, ".notdef")) {
1993 glyph_list[i].flags |= GF_USED;
1998 for (i = 0; i < numglyphs; i++) {
1999 if (glyph_list[i].flags & GF_USED) {
2000 DBG_TO_GLYPH(&glyph_list[i]);
2002 DBG_FROM_GLYPH(&glyph_list[i]);
2006 italic_angle = fontm.italic_angle;
2008 if (italic_angle > 45.0 || italic_angle < -45.0)
2009 italic_angle = 0.0; /* consider buggy */
2013 for (i = 0; i < numglyphs; i++) {
2014 if (glyph_list[i].flags & GF_USED) {
2015 DBG_TO_GLYPH(&glyph_list[i]);
2016 buildstems(&glyph_list[i]);
2017 assertpath(glyph_list[i].entries, __FILE__, __LINE__, glyph_list[i].name);
2018 DBG_FROM_GLYPH(&glyph_list[i]);
2024 bbox[i] = iscale(fontm.bbox[i]);
2026 /* don't touch the width of fixed width fonts */
2027 if( fontm.is_fixed_pitch )
2029 docorrectwidth(); /* checks correctwidth inside */
2031 for (i = 0; i < numglyphs; i++) {
2032 if (glyph_list[i].flags & GF_USED) {
2033 DBG_TO_GLYPH(&glyph_list[i]);
2034 reversepaths(&glyph_list[i]);
2035 assertpath(glyph_list[i].entries, __FILE__, __LINE__, glyph_list[i].name);
2036 DBG_FROM_GLYPH(&glyph_list[i]);
2043 ** It seems to bring troubles. The problem is that some
2044 ** styles of the font may be recognized as fixed-width
2045 ** while other styles of the same font as proportional.
2046 ** So it's better to be commented out yet.
2053 forcebold = fontm.force_bold;
2056 fprintf(pfa_file, "%%!PS-AdobeFont-1.0: %s %s\n", fontm.name_ps, fontm.name_copyright);
2058 fprintf(pfa_file, "%%%%CreationDate: %s", ctime(&now));
2059 fprintf(pfa_file, "%% Converted from TrueType font %s by ttf2pt1 %s/%s\n%%\n", argv[1], TTF2PT1_VERSION, cursw->name);
2060 fprintf(pfa_file, "%%%%EndComments\n");
2061 fprintf(pfa_file, "12 dict begin\n/FontInfo 9 dict dup begin\n");
2063 WARNING_3 fprintf(stderr, "FontName %s%s\n", fontm.name_ps, uni_font_name_suffix);
2066 fprintf(pfa_file, "/version (%s) readonly def\n", fontm.name_version);
2068 fprintf(pfa_file, "/Notice (%s) readonly def\n", fontm.name_copyright);
2070 fprintf(pfa_file, "/FullName (%s) readonly def\n", fontm.name_full);
2071 fprintf(pfa_file, "/FamilyName (%s) readonly def\n", fontm.name_family);
2075 fprintf(pfa_file, "/UniqueID %s def\n", strUID);
2078 for(i=0; fontm.name_full[i]!=0; i++) {
2079 numUID *= 37; /* magic number, good for hash */
2080 numUID += fontm.name_full[i]-' ';
2081 /* if the name is long the first chars
2082 * may be lost forever, so re-insert
2083 * them thus making kind of CRC
2085 numUID += (numUID>>24) & 0xFF;
2087 /* the range for private UIDs is 4 000 000 - 4 999 999 */
2088 fprintf(pfa_file, "/UniqueID %lu def\n", numUID%1000000+4000000);
2092 fprintf(pfa_file, "/Weight (%s) readonly def\n", fontm.name_style);
2094 fprintf(pfa_file, "/ItalicAngle %f def\n", italic_angle);
2095 fprintf(pfa_file, "/isFixedPitch %s def\n",
2096 fontm.is_fixed_pitch ? "true" : "false");
2098 /* we don't print out the unused glyphs */
2100 for (i = 0; i < numglyphs; i++) {
2101 if (glyph_list[i].flags & GF_USED) {
2106 fprintf(afm_file, "StartFontMetrics 4.1\n");
2107 fprintf(afm_file, "FontName %s%s\n", fontm.name_ps, uni_font_name_suffix);
2108 fprintf(afm_file, "FullName %s\n", fontm.name_full);
2109 fprintf(afm_file, "Notice %s\n", fontm.name_copyright);
2110 fprintf(afm_file, "EncodingScheme FontSpecific\n");
2111 fprintf(afm_file, "FamilyName %s\n", fontm.name_family);
2112 fprintf(afm_file, "Weight %s\n", fontm.name_style);
2113 fprintf(afm_file, "Version %s\n", fontm.name_version);
2114 fprintf(afm_file, "Characters %d\n", nchars);
2115 fprintf(afm_file, "ItalicAngle %.1f\n", italic_angle);
2117 fprintf(afm_file, "Ascender %d\n", iscale(fontm.ascender));
2118 fprintf(afm_file, "Descender %d\n", iscale(fontm.descender));
2120 fprintf(pfa_file, "/UnderlinePosition %d def\n",
2121 iscale(fontm.underline_position));
2123 fprintf(pfa_file, "/UnderlineThickness %hd def\nend readonly def\n",
2124 iscale(fontm.underline_thickness));
2126 fprintf(afm_file, "UnderlineThickness %d\n",
2127 iscale(fontm.underline_thickness));
2129 fprintf(afm_file, "UnderlinePosition %d\n",
2130 iscale(fontm.underline_position));
2132 fprintf(afm_file, "IsFixedPitch %s\n",
2133 fontm.is_fixed_pitch ? "true" : "false");
2134 fprintf(afm_file, "FontBBox %d %d %d %d\n",
2135 bbox[0], bbox[1], bbox[2], bbox[3]);
2137 fprintf(pfa_file, "/FontName /%s%s def\n", fontm.name_ps, uni_font_name_suffix);
2138 fprintf(pfa_file, "/PaintType 0 def\n/StrokeWidth 0 def\n");
2139 /* I'm not sure if these are fixed */
2140 fprintf(pfa_file, "/FontType 1 def\n");
2143 fprintf(pfa_file, "/FontMatrix [0.001 0 0 0.001 0 0] def\n");
2145 fprintf(pfa_file, "/FontMatrix [%9.7f 0 0 %9.7f 0 0] def\n",
2146 original_scale_factor / 1000.0, original_scale_factor / 1000.0);
2149 fprintf(pfa_file, "/FontBBox {%d %d %d %d} readonly def\n",
2150 bbox[0], bbox[1], bbox[2], bbox[3]);
2152 fprintf(pfa_file, "/Encoding 256 array\n");
2153 /* determine number of elements for metrics table */
2155 for (i = 0; i < numglyphs; i++) {
2156 if( glyph_list[i].flags & GF_USED
2157 && glyph_list[i].char_no == -1 ) {
2161 fprintf(afm_file, "StartCharMetrics %d\n", nmetrics);
2163 for (i = 0; i < 256; i++) { /* here 256, not ENCTABSZ */
2165 "dup %d /%s put\n", i, glyph_list[encoding[i]].name);
2166 if( glyph_list[encoding[i]].flags & GF_USED ) {
2167 print_glyph_metrics(i, encoding[i]);
2171 /* print the metrics for glyphs not in encoding table */
2172 for(i=0; i<numglyphs; i++) {
2173 if( (glyph_list[i].flags & GF_USED)
2174 && glyph_list[i].char_no == -1 ) {
2175 print_glyph_metrics(-1, i);
2179 fprintf(pfa_file, "readonly def\ncurrentdict end\ncurrentfile eexec\n");
2180 fprintf(pfa_file, "dup /Private 16 dict dup begin\n");
2182 fprintf(pfa_file, "/RD{string currentfile exch readstring pop}executeonly def\n");
2183 fprintf(pfa_file, "/ND{noaccess def}executeonly def\n");
2184 fprintf(pfa_file, "/NP{noaccess put}executeonly def\n");
2186 /* UniqueID must be shown twice, in both font and Private dictionary */
2189 fprintf(pfa_file, "/UniqueID %s def\n", strUID);
2191 fprintf(pfa_file, "/UniqueID %lu def\n", numUID);
2195 fprintf(pfa_file, "/ForceBold false def\n");
2196 else if(forcebold==1)
2197 fprintf(pfa_file, "/ForceBold true def\n");
2199 fprintf(pfa_file, "/BlueValues [ ");
2200 for (i = 0; i < nblues; i++)
2201 fprintf(pfa_file, "%d ", bluevalues[i]);
2202 fprintf(pfa_file, "] def\n");
2204 fprintf(pfa_file, "/OtherBlues [ ");
2205 for (i = 0; i < notherb; i++)
2206 fprintf(pfa_file, "%d ", otherblues[i]);
2207 fprintf(pfa_file, "] def\n");
2210 fprintf(pfa_file, "/StdHW [ %d ] def\n", stdhw);
2212 fprintf(pfa_file, "/StdVW [ %d ] def\n", stdvw);
2213 fprintf(pfa_file, "/StemSnapH [ ");
2214 for (i = 0; i < 12 && stemsnaph[i] != 0; i++)
2215 fprintf(pfa_file, "%d ", stemsnaph[i]);
2216 fprintf(pfa_file, "] def\n");
2217 fprintf(pfa_file, "/StemSnapV [ ");
2218 for (i = 0; i < 12 && stemsnapv[i] != 0; i++)
2219 fprintf(pfa_file, "%d ", stemsnapv[i]);
2220 fprintf(pfa_file, "] def\n");
2222 fprintf(pfa_file, "/MinFeature {16 16} def\n");
2223 /* Are these fixed also ? */
2224 fprintf(pfa_file, "/password 5839 def\n");
2226 /* calculate the number of subroutines */
2229 for (i = 0; i < numglyphs; i++) {
2230 if (glyph_list[i].flags & GF_USED) {
2231 subid+=glyph_list[i].nsg;
2235 fprintf(pfa_file, "/Subrs %d array\n", subid);
2236 /* standard subroutines */
2237 fprintf(pfa_file, "dup 0 {\n\t3 0 callothersubr pop pop setcurrentpoint return\n\t} NP\n");
2238 fprintf(pfa_file, "dup 1 {\n\t0 1 callothersubr return\n\t} NP\n");
2239 fprintf(pfa_file, "dup 2 {\n\t0 2 callothersubr return\n\t} NP\n");
2240 fprintf(pfa_file, "dup 3 {\n\treturn\n\t} NP\n");
2241 /* our sub to make the hint substitution code shorter */
2242 fprintf(pfa_file, "dup 4 {\n\t1 3 callothersubr pop callsubr return\n\t} NP\n");
2244 /* print the hinting subroutines */
2246 for (i = 0; i < numglyphs; i++) {
2247 if (glyph_list[i].flags & GF_USED) {
2248 subid+=print_glyph_subs(i, subid);
2252 fprintf(pfa_file, "ND\n");
2254 fprintf(pfa_file, "2 index /CharStrings %d dict dup begin\n", nchars);
2256 for (i = 0; i < numglyphs; i++) {
2257 if (glyph_list[i].flags & GF_USED) {
2263 fprintf(pfa_file, "end\nend\nreadonly put\n");
2264 fprintf(pfa_file, "noaccess put\n");
2265 fprintf(pfa_file, "dup/FontName get exch definefont pop\n");
2266 fprintf(pfa_file, "mark currentfile closefile\n");
2267 fprintf(pfa_file, "cleartomark\n");
2270 fprintf(afm_file, "EndCharMetrics\n");
2272 /* print the kerning data if present */
2273 cursw->kerning(glyph_list);
2274 print_kerning(afm_file);
2276 fprintf(afm_file, "EndFontMetrics\n");
2279 WARNING_1 fprintf(stderr, "Finished - font files created\n");
2284 while (wait(&ws) > 0) {
2288 extern FILE *ifp, *ofp; /* from t1asm.c */
2290 sprintf(filename, "%s.%s", argv[2], pfbflag ? "pfb" : "pfa" );
2292 if ((ofp = fopen(filename, "w+b")) == NULL) {
2293 fprintf(stderr, "**** Cannot create %s ****\n", filename);
2296 WARNING_2 fprintf(stderr, "Creating file %s\n", filename);
2299 sprintf(filename, "%s.t1a", argv[2]);
2301 if ((ifp = fopen(filename, "rb")) == NULL) {
2302 fprintf(stderr, "**** Cannot read %s ****\n", filename);
2305 WARNING_2 fprintf(stderr, "Converting file %s\n", filename);
2310 WARNING_2 fprintf(stderr, "Removing file %s\n", filename);
2311 if(unlink(filename) < 0)
2312 WARNING_1 fprintf(stderr, "Unable to remove file %s\n", filename);
2314 #endif /* WINDOWS */