[ Index ] |
PHP Cross Reference of vtigercrm-6.1.0 |
[Summary view] [Print] [Text view]
1 /* 2 * True Type Font to Adobe Type 1 font converter 3 * By Mark Heath <[email protected]> 4 * Based on ttf2pfa by Andrew Weeks <[email protected]> 5 * With help from Frank M. Siegert <[email protected]> 6 * 7 * see COPYRIGHT for full copyright notice 8 * 9 *********************************************************************** 10 * 11 * Steven Wittens <[email protected]> 12 * 13 * Added generation of .ufm file 14 * 15 *********************************************************************** 16 * 17 * Sergey Babkin <[email protected]>, <[email protected]> 18 * 19 * Added post-processing of resulting outline to correct the errors 20 * both introduced during conversion and present in the original font, 21 * autogeneration of hints (has yet to be improved though) and BlueValues, 22 * scaling to 1000x1000 matrix, option to print the result on STDOUT, 23 * support of Unicode to CP1251 conversion, optimization of the 24 * resulting font code by space (that improves the speed too). Excluded 25 * the glyphs that are unaccessible through the encoding table from 26 * the output file. Added the built-in Type1 assembler (taken from 27 * the `t1utils' package). 28 * 29 *********************************************************************** 30 * 31 * Thomas Henlich <[email protected]> 32 * 33 * Added generation of .afm file (font metrics) 34 * Read encoding information from encoding description file 35 * Fixed bug in error message about unknown language ('-l' option) 36 * Added `:' after %%!PS-AdobeFont-1.0 37 * changed unused entries in ISOLatin1Encoding[] from .notdef to c127,c128... 38 * 39 *********************************************************************** 40 * 41 * Thomas Henlich <[email protected]> 42 * 43 * Added generation of .afm file (font metrics) 44 * 45 *********************************************************************** 46 * 47 * Bug Fixes: 48 ************************************************************************ 49 * 50 * Sun, 21 Jun 1998 Thomas Henlich <[email protected]> 51 * 1. "width" should be "short int" because otherwise: 52 * characters with negative widths (e.g. -4) become *very* wide (65532) 53 * 2. the number of /CharStrings is numglyphs and not numglyphs+1 54 * 55 *********************************************************************** 56 * 57 * 58 * 59 * The resultant font file produced by this program still needs to be ran 60 * through t1asm (from the t1utils archive) to produce a completely valid 61 * font. 62 * 63 */ 64 #include <stdio.h> 65 #include <stdlib.h> 66 #include <string.h> 67 #include <sys/types.h> 68 #include <sys/stat.h> 69 #include <fcntl.h> 70 #include <time.h> 71 #include <ctype.h> 72 #include <math.h> 73 74 #ifdef _GNU_SOURCE 75 #include <getopt.h> 76 #endif 77 78 #ifndef WINDOWS 79 # include <unistd.h> 80 # include <netinet/in.h> 81 # define BITBUCKET "/dev/null" 82 # include <sys/wait.h> 83 #else 84 # define WINDOWS_FUNCTIONS /* ask to define functions - in one file only */ 85 # include "windows.h" 86 # define BITBUCKET "NUL" 87 # define snprintf _snprintf 88 #endif 89 90 #include "pt1.h" 91 #include "global.h" 92 #include "version.h" 93 94 /* globals */ 95 96 /* table of front-ends */ 97 98 extern struct frontsw ttf_sw; 99 extern struct frontsw bdf_sw; 100 #if defined(USE_FREETYPE) 101 extern struct frontsw freetype_sw; 102 #endif 103 104 struct frontsw *frontswtab[] = { 105 &bdf_sw, 106 #if defined(USE_FREETYPE) && defined(PREFER_FREETYPE) 107 &freetype_sw, 108 #endif 109 &ttf_sw, 110 #if defined(USE_FREETYPE) && !defined(PREFER_FREETYPE) 111 &freetype_sw, 112 #endif 113 NULL /* end of table */ 114 }; 115 116 struct frontsw *cursw=0; /* the active front end */ 117 char *front_arg=""; /* optional argument */ 118 119 /* options */ 120 int encode = 0; /* encode the resulting file */ 121 int pfbflag = 0; /* produce compressed file */ 122 int wantafm=0; /* want to see .afm instead of .t1a on stdout */ 123 int correctvsize=0; /* try to correct the vertical size of characters */ 124 int wantuid = 0; /* user wants UniqueID entry in the font */ 125 int allglyphs = 0; /* convert all glyphs, not only 256 of them */ 126 int warnlevel = 3; /* the level of permitted warnings */ 127 int forcemap = 0; /* do mapping even on non-Unicode fonts */ 128 /* options - maximal limits */ 129 int max_stemdepth = 128; /* maximal depth of stem stack in interpreter (128 - limit from X11) */ 130 /* options - debugging */ 131 int absolute = 0; /* print out in absolute values */ 132 int reverse = 1; /* reverse font to Type1 path directions */ 133 /* options - suboptions of Outline Processing, defaults are set in table */ 134 int optimize; /* enables space optimization */ 135 int smooth; /* enable smoothing of outlines */ 136 int transform; /* enables transformation to 1000x1000 matrix */ 137 int hints; /* enables autogeneration of hints */ 138 int subhints; /* enables autogeneration of substituted hints */ 139 int trybold; /* try to guess whether the font is bold */ 140 int correctwidth; /* try to correct the character width */ 141 int vectorize; /* vectorize the bitmaps */ 142 int use_autotrace; /* use the autotrace library on bitmap */ 143 /* options - suboptions of File Generation, defaults are set in table */ 144 int gen_pfa; /* generate the font file */ 145 int gen_afm; /* generate the metrics file */ 146 int gen_ufm; /* generate the unicode metrics file */ 147 int gen_dvienc; /* generate the dvips encoding file */ 148 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 */ 152 153 /* structure to define the sub-option lists controlled by the 154 * case: uppercase enables them, lowercase disables 155 */ 156 struct subo_case { 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 */ 162 }; 163 164 int debug = DEBUG; /* debugging flag */ 165 166 FILE *null_file, *pfa_file, *afm_file, *ufm_file, *dvienc_file; 167 int numglyphs; 168 struct font_metrics fontm; 169 170 /* non-globals */ 171 static char *strUID = 0; /* user-supplied UniqueID */ 172 static unsigned long numUID; /* auto-generated UniqueID */ 173 174 static int ps_fmt_3 = 0; 175 static double scale_factor, original_scale_factor; 176 177 static char *glyph_rename[ENCTABSZ]; 178 179 /* the names assigned if the original font 180 * does not specify any 181 */ 182 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", 200 "at", "A", "B", "C", 201 "D", "E", "F", "G", 202 "H", "I", "J", "K", 203 "L", "M", "N", "O", 204 "P", "Q", "R", "S", 205 "T", "U", "V", "W", 206 "X", "Y", "Z", "bracketleft", 207 "backslash", "bracketright", "asciicircum", "underscore", 208 "grave", "a", "b", "c", 209 "d", "e", "f", "g", 210 "h", "i", "j", "k", 211 "l", "m", "n", "o", 212 "p", "q", "r", "s", 213 "t", "u", "v", "w", 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" 248 }; 249 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) 255 */ 256 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", 274 "at", "A", "B", "C", 275 "D", "E", "F", "G", 276 "H", "I", "J", "K", 277 "L", "M", "N", "O", 278 "P", "Q", "R", "S", 279 "T", "U", "V", "W", 280 "X", "Y", "Z", "bracketleft", 281 "backslash", "bracketright", "asciicircum", "underscore", 282 "grave", "a", "b", "c", 283 "d", "e", "f", "g", 284 "h", "i", "j", "k", 285 "l", "m", "n", "o", 286 "p", "q", "r", "s", 287 "t", "u", "v", "w", 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" 322 }; 323 324 #endif /* } notdef */ 325 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" 385 }; 386 387 /* 388 * Decription of the supported conversions from Unicode 389 * 390 * SB 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. 395 * 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 399 * locale. 400 */ 401 402 #define MAXUNIALIAS 10 403 #define MAXUNITABLES 3 404 405 /* the character used as the language argument separator */ 406 #define LANG_ARG_SEP '+' 407 408 409 /* 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) 419 */ 420 421 /* type of the Unicode map initialization routine */ 422 typedef void uni_init_t(char *arg); 423 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 427 */ 428 typedef int uni_conv_t(char *name, char *arg, int when); 429 #define UNICONV_BYNAME_BEFORE 0 430 #define UNICONV_BYNAME_AFTER 1 431 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() */ 439 }; 440 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]; 446 447 /* 448 * Prototypes of the conversion routines 449 */ 450 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; 459 460 static uni_init_t unicode_init_user; 461 462 /* 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. 466 */ 467 static struct uni_language uni_lang[]= { 468 /* pseudo-language for all the languages using Latin1 */ 469 { 470 { unicode_latin1 }, 471 0, /* no name-based mapping */ 472 "latin1", 473 "works for most of the Western languages", 474 { "en_", "de_", "fr_", "nl_", "no_", "da_", "it_" }, 475 'A' 476 }, 477 { /* by Szalay Tamas <[email protected]> */ 478 { unicode_latin2 }, 479 0, /* no name-based mapping */ 480 "latin2", 481 "works for Central European languages", 482 { "hu_","pl_","cz_","si_","sk_" }, 483 'A' 484 }, 485 { /* by Ri�ardas �epas <[email protected]> */ 486 { unicode_latin4 }, 487 0, /* no name-based mapping */ 488 "latin4", 489 "works for Baltic languages", 490 { "lt_", "lv_" }, /* doubt about ee_ */ 491 'A' 492 }, 493 { /* by Turgut Uyar <[email protected]> */ 494 { unicode_latin5 }, 495 0, /* no name-based mapping */ 496 "latin5", 497 "for Turkish", 498 { "tr_" }, 499 'A' 500 }, 501 { /* by Zvezdan Petkovic <[email protected]> */ 502 { unicode_cyrillic, unicode_latin1 }, 503 0, /* no name-based mapping */ 504 "cyrillic", 505 "in Windows encoding", 506 { "bg_", "be_", "mk_", "ru_", "sr_", "su_", "uk_" }, 507 'A' 508 }, 509 { 510 { unicode_cyrillic, unicode_latin1 }, 511 0, /* no name-based mapping */ 512 "russian", 513 "obsolete, use cyrillic instead", 514 { 0 }, 515 'A' 516 }, 517 { 518 { unicode_cyrillic, unicode_latin1 }, 519 0, /* no name-based mapping */ 520 "bulgarian", 521 "obsolete, use cyrillic instead", 522 { 0 }, 523 'A' 524 }, 525 { 526 { unicode_adobestd }, 527 unicode_adobestd_byname, 528 "adobestd", 529 "Adobe Standard, expected by TeX", 530 { NULL }, 531 'A' 532 }, 533 { 534 { unicode_plane }, 535 0, /* no name-based mapping */ 536 "plane", 537 "one plane of Unicode or other multi-byte encoding as is", 538 { NULL }, 539 0 /* no easy way to predict the capital letters */ 540 }, 541 }; 542 543 static struct uni_language uni_lang_user = { 544 { unicode_init_user }, 545 0, /* no name-based mapping */ 546 0, /* no name */ 547 0, /* no description */ 548 { 0 }, 549 0 /* no sample */ 550 }; 551 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 */ 555 556 extern int runt1asm(int); 557 558 /* 559 * user-defined loadable maps 560 */ 561 562 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. 569 */ 570 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)) 574 575 static DEF_BITMAP(uni_user_buckets, 1<<BUCKET_ID_BITS); 576 577 static unsigned int unicode_map[ENCTABSZ]; /* font-encoding to unicode map */ 578 static int enctabsz = 256; /* actual number of codes used */ 579 580 static void 581 unicode_init_user( 582 char *path 583 ) 584 { 585 FILE *unicode_map_file; 586 #define UNIBFSZ 256 587 char buffer[UNIBFSZ]; 588 unsigned code, unicode, curpos, unicode2; 589 char *arg, *p; 590 int enabled, found, sawplane; 591 int lineno, cnt, n, nchars; 592 char next; 593 int pid, eid, overid=0; 594 595 /* check if we have an argument (plane name) */ 596 arg = strrchr(path, LANG_ARG_SEP); 597 if(arg != 0) { 598 *arg++ = 0; 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); 602 forcemap = 1; 603 arg += nchars; 604 if(*arg == ',') 605 arg++; 606 } 607 if( *arg == 0 || strlen(arg) > UNI_MAX_SUFFIX_LEN-1) 608 arg = NULL; 609 else { 610 sprintf(uni_suffix_buf, "-%s", arg); 611 uni_font_name_suffix = uni_suffix_buf; 612 } 613 } 614 615 /* now read in the encoding description file, if requested */ 616 if ((unicode_map_file = fopen(path, "r")) == NULL) { 617 fprintf(stderr, "**** Cannot access map file '%s' ****\n", path); 618 exit(1); 619 } 620 621 sawplane = 0; 622 if(arg==NULL) 623 enabled = found = 1; 624 else 625 enabled = found = 0; 626 627 lineno=0; curpos=0; 628 while (fgets (buffer, UNIBFSZ, unicode_map_file) != NULL) { 629 char name[UNIBFSZ]; 630 631 lineno++; 632 633 if(sscanf(buffer, "plane %s", name)==1) { 634 sawplane = 1; 635 if(arg == 0) { 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); 641 exit(1); 642 } 643 if( !strcmp(arg, name) ) { 644 enabled = found = 1; 645 curpos = 0; 646 } else { 647 enabled = 0; 648 if(found) /* no need to read further */ 649 break; 650 } 651 continue; 652 } 653 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; 658 forcemap = 1; 659 } 660 continue; 661 } 662 663 if( !enabled ) 664 continue; /* skip to the next plane */ 665 666 if( sscanf(buffer, "at %i", &curpos) == 1 ) { 667 if(curpos > 255) { 668 fprintf(stderr, "**** map file '%s' line %d: code over 255\n", path, lineno); 669 exit(1); 670 } 671 if(ISDBG(EXTMAP)) fprintf(stderr, "=== at 0x%x\n", curpos); 672 continue; 673 } 674 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; 683 } 684 } 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); 692 } 693 } 694 /* try the compact sequence format */ 695 else if( (n=sscanf(buffer, " %i%n", &unicode, &cnt)) == 1 ) { 696 p = buffer; 697 do { 698 if(curpos > 255) { 699 fprintf(stderr, "**** map file '%s' line %d: code over 255 for unicode 0x%x\n", 700 path, lineno, unicode); 701 exit(1); 702 } 703 if(ISDBG(EXTMAP)) fprintf(stderr, "=== 0x%d -> 0x%x\n", curpos, unicode); 704 unicode_map[curpos++] = unicode; 705 p += cnt; 706 if( sscanf(p, " %[,-]%n", &next,&cnt) == 1 ) { 707 if(ISDBG(EXTMAP)) fprintf(stderr, "=== next: '%c'\n", next); 708 p += cnt; 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); 712 exit(1); 713 } 714 p += cnt; 715 if(ISDBG(EXTMAP)) fprintf(stderr, "=== range 0x%x to 0x%x\n", unicode, unicode2); 716 for(unicode++; unicode <= unicode2; unicode++) { 717 if(curpos > 255) { 718 fprintf(stderr, "**** map file '%s' line %d: code over 255 in unicode range ...-0x%x\n", 719 path, lineno, unicode2); 720 exit(1); 721 } 722 if(ISDBG(EXTMAP)) fprintf(stderr, "=== 0x%x -> 0x%x\n", curpos, unicode); 723 unicode_map[curpos++] = unicode; 724 } 725 } 726 } 727 } while ( sscanf(p, " %i%n", &unicode, &cnt) == 1 ); 728 } 729 730 } 731 732 fclose (unicode_map_file); 733 734 if( !found ) { 735 fprintf(stderr, "**** map file '%s' has no plane '%s'\n", path, arg); 736 exit(1); 737 } 738 739 if(unicode_map['A'] == 'A') 740 uni_sample = 'A'; /* seems to be compatible with Latin */ 741 else 742 uni_sample = 0; /* don't make any assumptions */ 743 } 744 745 /* 746 * by Zvezdan Petkovic <[email protected]> 747 */ 748 static void 749 unicode_cyrillic( 750 char *arg 751 ) 752 { 753 int i; 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 */ 763 }; 764 765 for(i=0; i<=0x7F; i++) 766 unicode_map[i] = i; 767 768 for(i=0x80; i<=0xBF; i++) 769 unicode_map[i] = cyrillic_unicode_map[i-0x80]; 770 771 for(i=0xC0; i<=0xFF; i++) 772 unicode_map[i] = i+0x350; 773 774 } 775 776 static void 777 unicode_latin1( 778 char *arg 779 ) 780 { 781 int i; 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 */ 787 }; 788 789 for(i=0; i<=0x7F; i++) 790 unicode_map[i] = i; 791 792 for(i=0x80; i<=0x9F; i++) 793 unicode_map[i] = latin1_unicode_map[i-0x80]; 794 795 for(i=0xA0; i<=0xFF; i++) 796 unicode_map[i] = i; 797 } 798 799 static void 800 unicode_adobestd( 801 char *arg 802 ) 803 { 804 int 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 */ 818 }; 819 820 for(i=0; i<=0x7F; i++) 821 unicode_map[i] = i; 822 823 unicode_map[0x27] = 0x2019; 824 unicode_map[0x60] = -1; 825 826 /* 0x80 to 0x9F is a hole */ 827 828 for(i=0xA0; i<=0xFF; i++) 829 unicode_map[i] = adobestd_unicode_map[i-0xA0]; 830 } 831 832 /* 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. 840 */ 841 842 static int 843 unicode_adobestd_byname( 844 char *name, 845 char *arg, 846 int where 847 ) 848 { 849 int i; 850 851 /* names always take precedence over codes */ 852 if(where == UNICONV_BYNAME_AFTER) 853 return -1; 854 855 for(i=32; i<256; i++) { 856 if(!strcmp(name, adobe_StandardEncoding[i])) 857 return i; 858 } 859 return -1; 860 861 } 862 863 static void 864 unicode_latin2( 865 char *arg 866 ) 867 { 868 int 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 */ 882 }; 883 884 for(i=0; i<=0x7E; i++) 885 unicode_map[i] = i; 886 887 /* 7F-9F are unused */ 888 889 for(i=0xA0; i<=0xFF; i++) 890 unicode_map[i] = latin2_unicode_map[i-0xA0]; 891 } 892 893 static void 894 unicode_latin4( 895 char *arg 896 ) 897 { 898 int i; 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 */ 916 }; 917 918 for(i=0; i<=0x7F; i++) 919 unicode_map[i] = i; 920 921 for(i=0x80; i<=0xFF; i++) 922 unicode_map[i] = latin4_unicode_map[i-0x80]; 923 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 */ 1023 #endif 1024 } 1025 1026 static void 1027 unicode_latin5( 1028 char *arg 1029 ) 1030 { 1031 int i; 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 */ 1037 }; 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 */ 1045 }; 1046 1047 for(i=0; i<=0x7F; i++) 1048 unicode_map[i] = i; 1049 1050 for(i=0x80; i<=0x9F; i++) 1051 unicode_map[i] = latin5_unicode_map1[i-0x80]; 1052 1053 for(i=0xA0; i<=0xCF; i++) 1054 unicode_map[i] = i; 1055 1056 for(i=0xD0; i<=0xFF; i++) 1057 unicode_map[i] = latin5_unicode_map2[i-0xD0]; 1058 } 1059 1060 /* a way to select one 256-character plane from Unicode 1061 * or other multi-byte encoding 1062 */ 1063 1064 static void 1065 unicode_plane( 1066 char *arg 1067 ) 1068 { 1069 static unsigned plane; 1070 int nchars; 1071 int c1, c2, i; 1072 1073 if(uni_lang_selected == 0) 1074 return; /* don't participate in auto-guessing */ 1075 1076 plane = 0; force_pid = force_eid = -1; 1077 1078 c1 = sscanf(arg, "pid=%d,eid=%d%n", &force_pid, &force_eid, &nchars); 1079 if(c1 == 2) { 1080 arg += nchars; 1081 if(*arg == ',') 1082 arg++; 1083 } 1084 if(arg[0] == '0' && (arg[1]=='x' || arg[1]=='X') ) { 1085 arg += 2; 1086 c2 = sscanf(arg, "%x", &plane); 1087 } else { 1088 c2 = sscanf(arg, "%d", &plane); 1089 } 1090 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"); 1098 exit(1); 1099 } 1100 1101 if(c2!=0) { 1102 if(strlen(arg) > sizeof(uni_suffix_buf)-2) { 1103 fprintf(stderr, "**** plane number is too large\n"); 1104 } 1105 1106 sprintf(uni_suffix_buf, "-%s", arg); 1107 uni_font_name_suffix = uni_suffix_buf; 1108 } else { 1109 uni_font_name_suffix = ""; 1110 } 1111 1112 plane <<= 8; 1113 for(i=0; i<=0xFF; i++) 1114 unicode_map[i] = plane | i; 1115 } 1116 1117 /* look up the 8-bit code by unicode */ 1118 1119 int 1120 unicode_rev_lookup( 1121 int unival 1122 ) 1123 { 1124 int res; 1125 1126 if( ! IS_UNI_BUCKET(unival) ) 1127 return -1; 1128 1129 for (res = 0; res < enctabsz; res++) 1130 if (unicode_map[res] == unival) 1131 return res; 1132 return -1; 1133 } 1134 1135 /* mark the buckets for quick lookup */ 1136 1137 static void 1138 unicode_prepare_buckets( 1139 void 1140 ) 1141 { 1142 int i; 1143 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]); 1148 } 1149 } 1150 1151 /* 1152 * When we print errors about bad names we want to print these names in 1153 * some decent-looking form 1154 */ 1155 1156 static char * 1157 nametoprint( 1158 unsigned char *s 1159 ) 1160 { 1161 static char res[50]; 1162 int c, i; 1163 1164 for(i=0; ( c =* s )!=0 && i<sizeof(res)-8; s++) { 1165 if(c < ' ' || c > 126) { 1166 sprintf(res+i, "\\x%02X", c); 1167 i+=4; 1168 } else { 1169 res[i++] = c; 1170 } 1171 } 1172 if(*s != 0) { 1173 res[i++] = '.'; 1174 res[i++] = '.'; 1175 res[i++] = '.'; 1176 } 1177 res[i++] = 0; 1178 return res; 1179 } 1180 1181 /* 1182 * Scale the values according to the scale_factor 1183 */ 1184 1185 double 1186 fscale( 1187 double val 1188 ) 1189 { 1190 return scale_factor * val; 1191 } 1192 1193 int 1194 iscale( 1195 int val 1196 ) 1197 { 1198 return (int) (val > 0 ? scale_factor * val + 0.5 1199 : scale_factor * val - 0.5); 1200 } 1201 1202 /* 1203 * Try to force fixed width of characters 1204 */ 1205 1206 static void 1207 alignwidths(void) 1208 { 1209 int i; 1210 int n = 0, avg, max = 0, min = 3000, sum = 0, x; 1211 1212 for (i = 0; i < numglyphs; i++) { 1213 if (glyph_list[i].flags & GF_USED) { 1214 x = glyph_list[i].width; 1215 1216 if (x != 0) { 1217 if (x < min) 1218 min = x; 1219 if (x > max) 1220 max = x; 1221 1222 sum += x; 1223 n++; 1224 } 1225 } 1226 } 1227 1228 if (n == 0) 1229 return; 1230 1231 avg = sum / n; 1232 1233 WARNING_3 fprintf(stderr, "widths: max=%d avg=%d min=%d\n", max, avg, min); 1234 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; 1241 } 1242 fontm.is_fixed_pitch = 1; 1243 } 1244 } 1245 1246 static void 1247 convert_glyf( 1248 int glyphno 1249 ) 1250 { 1251 GLYPH *g; 1252 int ncurves; 1253 1254 g = &glyph_list[glyphno]; 1255 1256 1257 g->scaledwidth = iscale(g->width); 1258 1259 g->entries = 0; 1260 g->lastentry = 0; 1261 g->path = 0; 1262 if (g->ttf_pathlen != 0) { 1263 cursw->glpath(glyphno, glyph_list); 1264 g->lastentry = 0; 1265 1266 if(ISDBG(BUILDG)) 1267 dumppaths(g, NULL, NULL); 1268 1269 assertpath(g->entries, __FILE__, __LINE__, g->name); 1270 1271 fclosepaths(g); 1272 assertpath(g->entries, __FILE__, __LINE__, g->name); 1273 1274 /* float processing */ 1275 if(smooth) { 1276 ffixquadrants(g); 1277 assertpath(g->entries, __FILE__, __LINE__, g->name); 1278 1279 fsplitzigzags(g); 1280 assertpath(g->entries, __FILE__, __LINE__, g->name); 1281 1282 fforceconcise(g); 1283 assertpath(g->entries, __FILE__, __LINE__, g->name); 1284 1285 fstraighten(g); 1286 assertpath(g->entries, __FILE__, __LINE__, g->name); 1287 } 1288 1289 pathtoint(g); 1290 /* all processing past this point expects integer path */ 1291 assertpath(g->entries, __FILE__, __LINE__, g->name); 1292 1293 #if 0 1294 fixcontours(g); 1295 testfixcvdir(g); 1296 #endif 1297 1298 /* int processing */ 1299 if (smooth) { 1300 smoothjoints(g); 1301 assertpath(g->entries, __FILE__, __LINE__, g->name); 1302 } 1303 1304 ncurves = 0; 1305 { 1306 GENTRY *ge; 1307 for(ge = g->entries; ge; ge = ge->next) 1308 ncurves++; 1309 } 1310 if (ncurves > 200) { 1311 WARNING_3 fprintf(stderr, 1312 "** Glyph %s is too long, may display incorrectly\n", 1313 g->name); 1314 } 1315 } else { 1316 /* for buildstems */ 1317 g->flags &= ~GF_FLOAT; 1318 } 1319 } 1320 1321 static void 1322 handle_gnames(void) 1323 { 1324 int i, n, found, c, type; 1325 1326 /* get the names from the font file */ 1327 ps_fmt_3 = cursw->glnames(glyph_list); 1328 1329 /* check for names with wrong characters */ 1330 for (n = 0; n < numglyphs; n++) { 1331 int c; 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); 1342 break; 1343 } 1344 } 1345 } 1346 1347 if( !ps_fmt_3 ) { 1348 /* check for duplicate names */ 1349 for (n = 0; n < numglyphs; n++) { 1350 found = 0; 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__); 1355 exit(255); 1356 } 1357 sprintf(glyph_list[n].name, "_d_%d", n); 1358 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 1362 */ 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", 1366 n, i, 1367 glyph_list[i].name, 1368 glyph_list[n].name); 1369 } 1370 found = 1; 1371 } 1372 } 1373 } 1374 1375 } 1376 1377 /* start the encoding stuff */ 1378 for (i = 0; i < ENCTABSZ; i++) { 1379 encoding[i] = -1; 1380 } 1381 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) 1388 encoding[c] = n; 1389 } 1390 } 1391 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); 1400 if( type == 0 ) 1401 /* if we have an 8-bit encoding we don't need more tries */ 1402 break; 1403 } 1404 } else { 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) 1408 continue; 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); 1414 if( type == 0 ) 1415 /* if we have an 8-bit encoding we don't need more tries */ 1416 break; 1417 } 1418 } 1419 1420 if (ps_fmt_3) { 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; 1424 } 1425 if(type == 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]; 1430 } 1431 } 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]; 1438 } 1439 } 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__); 1446 exit(255); 1447 } 1448 sprintf(glyph_list[i].name, "_d_%d", i); 1449 } 1450 } 1451 } 1452 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) 1459 encoding[c] = n; 1460 } 1461 } 1462 /* all the encoding things are done */ 1463 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()) 1468 */ 1469 c = unicode_map[i]; 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]; 1474 } 1475 } 1476 } 1477 if(encoding[i] == -1) /* still not found, defaults to .notdef */ 1478 encoding[i] = 0; 1479 } 1480 1481 for (i = 0; i < 256; i++) /* here 256, not ENCTABSZ */ 1482 glyph_list[encoding[i]].char_no = i; 1483 1484 /* enforce two special cases defined in TTF manual */ 1485 if(numglyphs > 0) 1486 glyph_list[0].name = ".notdef"; 1487 if(numglyphs > 1) 1488 glyph_list[1].name = ".null"; 1489 1490 for (i = 0; i < ENCTABSZ; i++) { 1491 if ((encoding[i] != 0) && glyph_rename[i]) { 1492 glyph_list[encoding[i]].name = glyph_rename[i]; 1493 } 1494 } 1495 1496 } 1497 1498 /* duplicate a string with counter to a 0-terminated string, 1499 * and by the way filter out the characters that won't look good 1500 * in the Postscript strings or comments; limit the length 1501 * to a reasonable amount. 1502 */ 1503 1504 char * 1505 dupcnstring( 1506 unsigned char *s, 1507 int len 1508 ) 1509 { 1510 char *res, *out; 1511 int i, c; 1512 static int warned=0; 1513 1514 if(len > 255) { 1515 WARNING_1 fprintf(stderr, "Some font name strings are longer than 255 characters, cut down\n"); 1516 len = 255; 1517 } 1518 1519 if(( res = malloc(len+1) )==NULL) { 1520 fprintf (stderr, "****malloc failed %s line %d\n", __FILE__, __LINE__); 1521 exit(255); 1522 } 1523 1524 out = res; 1525 for(i=0; i<len; i++) { 1526 c = s[i]; 1527 if( c>=' ' && c!=127) { 1528 /* translate the inconvenient chacracters */ 1529 if( c== '(' ) 1530 c = '['; 1531 else if( c== ')' ) 1532 c = ']'; 1533 *out++ = c; 1534 } else if( c=='\n' || c=='\r' ) { 1535 WARNING_1 fprintf(stderr, "Some font name strings contain end of line or Unicode, cut down\n"); 1536 *out = 0; 1537 return res; 1538 } else if(!warned) { 1539 warned=1; 1540 WARNING_1 fprintf(stderr, "Some font name strings are in Unicode, may not show properly\n"); 1541 } 1542 } 1543 *out = 0; 1544 return res; 1545 } 1546 1547 static void 1548 usage(void) 1549 { 1550 1551 #ifdef _GNU_SOURCE 1552 # define fplop(txt) fputs(txt, stderr); 1553 #else 1554 # define fplop(txt) 1555 #endif 1556 1557 fputs("Use:\n", stderr); 1558 fputs("ttf2pt1 [-<opts>] [-l language | -L file] <ttf-file> [<fontname>]\n", stderr); 1559 fputs(" or\n", stderr); 1560 fputs("ttf2pt1 [-<opts>] [-l language | -L file] <ttf-file> -\n", stderr); 1561 fputs(" or\n", stderr); 1562 fputs("ttf2pt1 [-<opts>] [-l language | -L file] <ttf-file> - | t1asm > <pfa-file>\n", stderr); 1563 1564 fplop("\n"); 1565 fplop("This build supports both short and long option names,\n"); 1566 fplop("the long options are listed before corresponding short ones\n"); 1567 1568 fplop(" --all-glyphs\n"); 1569 fputs(" -a - include all glyphs, even those not in the encoding table\n", stderr); 1570 fplop(" --pfb\n"); 1571 fputs(" -b - produce a compressed .pfb file\n", stderr); 1572 fplop(" --debug dbg_suboptions\n"); 1573 fputs(" -d dbg_suboptions - debugging options, run ttf2pt1 -d? for help\n", stderr); 1574 fplop(" --encode\n"); 1575 fputs(" -e - produce a fully encoded .pfa file\n", stderr); 1576 fplop(" --force-unicode\n"); 1577 fputs(" -F - force use of Unicode encoding even if other MS encoding detected\n", stderr); 1578 fplop(" --generate suboptions\n"); 1579 fputs(" -G suboptions - control the file generation, run ttf2pt1 -G? for help\n", stderr); 1580 fplop(" --language language\n"); 1581 fputs(" -l language - convert Unicode to specified language, run ttf2pt1 -l? for list\n", stderr); 1582 fplop(" --language-map file\n"); 1583 fputs(" -L file - convert Unicode according to encoding description file\n", stderr); 1584 fplop(" --limit <type>=<value>\n"); 1585 fputs(" -m <type>=<value> - set maximal limit of given type to value, types:\n", stderr); 1586 fputs(" h - maximal hint stack depth in the PostScript interpreter\n", stderr); 1587 fplop(" --processing suboptions\n"); 1588 fputs(" -O suboptions - control outline processing, run ttf2pt1 -O? for help\n", stderr); 1589 fplop(" --parser name\n"); 1590 fputs(" -p name - use specific front-end parser, run ttf2pt1 -p? for list\n", stderr); 1591 fplop(" --uid id\n"); 1592 fputs(" -u id - use this UniqueID, -u A means autogeneration\n", stderr); 1593 fplop(" --vertical-autoscale size\n"); 1594 fputs(" -v size - scale the font to make uppercase letters >size/1000 high\n", stderr); 1595 fplop(" --version\n"); 1596 fputs(" -V - print ttf2pt1 version number\n", stderr); 1597 fplop(" --warning number\n"); 1598 fputs(" -W number - set the level of permitted warnings (0 - disable)\n", stderr); 1599 fputs("Obsolete options (will be removed in future releases):\n", stderr); 1600 fplop(" --afm\n"); 1601 fputs(" -A - write the .afm file to STDOUT instead of the font, now -GA\n", stderr); 1602 fputs(" -f - don't try to guess the value of the ForceBold hint, now -Ob\n", stderr); 1603 fputs(" -h - disable autogeneration of hints, now -Oh\n", stderr); 1604 fputs(" -H - disable hint substitution, now -Ou\n", stderr); 1605 fputs(" -o - disable outline optimization, now -Oo\n", stderr); 1606 fputs(" -s - disable outline smoothing, now -Os\n", stderr); 1607 fputs(" -t - disable auto-scaling to 1000x1000 standard matrix, now -Ot\n", stderr); 1608 fputs(" -w - correct the glyph widths (use only for buggy fonts), now -OW\n", stderr); 1609 fputs("With no <fontname>, write to <ttf-file> with suffix replaced.\n", stderr); 1610 fputs("The last '-' means 'use STDOUT'.\n", stderr); 1611 1612 #undef fplop 1613 1614 } 1615 1616 static void 1617 printversion(void) 1618 { 1619 fprintf(stderr, "ttf2pt1 %s\n", TTF2PT1_VERSION); 1620 } 1621 1622 /* initialize a table of suboptions */ 1623 static void 1624 init_subo_tbl( 1625 struct subo_case *tbl 1626 ) 1627 { 1628 int i; 1629 1630 for(i=0; tbl[i].disbl != 0; i++) { 1631 tbl[i].disbl = tolower(tbl[i].disbl); 1632 tbl[i].enbl = toupper(tbl[i].disbl); 1633 *(tbl[i].valp) = tbl[i].dflt; 1634 } 1635 } 1636 1637 /* print the default value of the suboptions */ 1638 static void 1639 print_subo_dflt( 1640 FILE *f, 1641 struct subo_case *tbl 1642 ) 1643 { 1644 int i; 1645 1646 for(i=0; tbl[i].disbl != 0; i++) { 1647 if(tbl[i].dflt) 1648 putc(tbl[i].enbl, f); 1649 else 1650 putc(tbl[i].disbl, f); 1651 } 1652 } 1653 1654 /* print the usage message for the suboptions */ 1655 static void 1656 print_subo_usage( 1657 FILE *f, 1658 struct subo_case *tbl 1659 ) 1660 { 1661 int i; 1662 1663 fprintf(f,"The lowercase suboptions disable features, corresponding\n"); 1664 fprintf(f,"uppercase suboptions enable them. The supported suboptions,\n"); 1665 fprintf(f,"their default states and the features they control are:\n"); 1666 for(i=0; tbl[i].disbl != 0; i++) { 1667 fprintf(f," %c/%c - [%s] %s\n", tbl[i].disbl, tbl[i].enbl, 1668 tbl[i].dflt ? "enabled" : "disabled", tbl[i].descr); 1669 } 1670 } 1671 1672 /* find and set the entry according to suboption, 1673 * return the found entry (or if not found return NULL) 1674 */ 1675 struct subo_case * 1676 set_subo( 1677 struct subo_case *tbl, 1678 int subopt 1679 ) 1680 { 1681 int i; 1682 1683 for(i=0; tbl[i].disbl != 0; i++) { 1684 if(subopt == tbl[i].disbl) { 1685 *(tbl[i].valp) = 0; 1686 return &tbl[i]; 1687 } else if(subopt == tbl[i].enbl) { 1688 *(tbl[i].valp) = 1; 1689 return &tbl[i]; 1690 } 1691 } 1692 return NULL; 1693 } 1694 1695 1696 int 1697 main( 1698 int argc, 1699 char **argv 1700 ) 1701 { 1702 int i, j; 1703 time_t now; 1704 char filename[4096]; 1705 int c,nchars,nmetrics; 1706 int ws; 1707 int forcebold= -1; /* -1 means "don't know" */ 1708 char *lang; 1709 int oc; 1710 int subid; 1711 char *cmdline; 1712 #ifdef _GNU_SOURCE 1713 # define ttf2pt1_getopt(a, b, c, d, e) getopt_long(a, b, c, d, e) 1714 static struct option longopts[] = { 1715 { "afm", 0, NULL, 'A' }, 1716 { "all-glyphs", 0, NULL, 'a' }, 1717 { "pfb", 0, NULL, 'b' }, 1718 { "debug", 1, NULL, 'd' }, 1719 { "encode", 0, NULL, 'e' }, 1720 { "force-unicode", 0, NULL, 'F' }, 1721 { "generate", 1, NULL, 'G' }, 1722 { "language", 1, NULL, 'l' }, 1723 { "language-map", 1, NULL, 'L' }, 1724 { "limit", 1, NULL, 'm' }, 1725 { "processing", 1, NULL, 'O' }, 1726 { "parser", 1, NULL, 'p' }, 1727 { "uid", 1, NULL, 'u' }, 1728 { "vertical-autoscale", 1, NULL, 'v' }, 1729 { "version", 0, NULL, 'V' }, 1730 { "warning", 1, NULL, 'W' }, 1731 { NULL, 0, NULL, 0 } 1732 }; 1733 #else 1734 # define ttf2pt1_getopt(a, b, c, d, e) getopt(a, b, c) 1735 #endif 1736 /* table of Outline Processing (may think also as Optimization) options */ 1737 static struct subo_case opotbl[] = { 1738 { 'b', 0/*auto-set*/, &trybold, 1, "guessing of the ForceBold hint" }, 1739 { 'h', 0/*auto-set*/, &hints, 1, "autogeneration of hints" }, 1740 { 'u', 0/*auto-set*/, &subhints, 1, "hint substitution technique" }, 1741 { 'o', 0/*auto-set*/, &optimize, 1, "space optimization of font files" }, 1742 { 's', 0/*auto-set*/, &smooth, 1, "smoothing and repair of outlines" }, 1743 { 't', 0/*auto-set*/, &transform, 1, "auto-scaling to the standard matrix 1000x1000" }, 1744 { 'w', 0/*auto-set*/, &correctwidth, 0, "correct the glyph widths (use only for buggy fonts)" }, 1745 { 'v', 0/*auto-set*/, &vectorize, 0, "vectorize (trace) the bitmaps" }, 1746 #ifdef USE_AUTOTRACE 1747 { 'z', 0/*auto-set*/, &use_autotrace, 0, "use the autotrace library on bitmaps (works badly)" }, 1748 #endif /*USE_AUTOTRACE*/ 1749 { 0, 0, 0, 0, 0} /* terminator */ 1750 }; 1751 /* table of the File Generation options */ 1752 static struct subo_case fgotbl[] = { 1753 { 'f', 0/*auto-set*/, &gen_pfa, 1, "generate the font file (.t1a, .pfa or .pfb)" }, 1754 { 'a', 0/*auto-set*/, &gen_afm, 1, "generate the Adobe metrics file (.afm)" }, 1755 { 'u', 0/*auto-set*/, &gen_ufm, 1, "generate the Unicode metrics file (.ufm)" }, 1756 { 'e', 0/*auto-set*/, &gen_dvienc, 0, "generate the dvips encoding file (.enc)" }, 1757 { 0, 0, 0, 0, 0} /* terminator */ 1758 }; 1759 int *genlast = NULL; 1760 1761 1762 init_subo_tbl(opotbl); /* initialize sub-options of -O */ 1763 init_subo_tbl(fgotbl); /* initialize sub-options of -G */ 1764 1765 /* save the command line for the record 1766 * (we don't bother about escaping the shell special characters) 1767 */ 1768 1769 j = 0; 1770 for(i=1; i<argc; i++) { 1771 j += strlen(argv[i])+1; 1772 } 1773 if ((cmdline = malloc(j+1)) == NULL) { 1774 fprintf (stderr, "****malloc failed %s line %d\n", __FILE__, __LINE__); 1775 exit(255); 1776 } 1777 cmdline[0] = 0; 1778 for(i=1; i<argc; i++) { 1779 strcat(cmdline, argv[i]); 1780 strcat(cmdline, " "); 1781 } 1782 for(i=0; (j=cmdline[i])!=0; i++) 1783 if(j == '\n') 1784 cmdline[i] = ' '; 1785 1786 1787 while(( oc=ttf2pt1_getopt(argc, argv, "FaoebAsthHfwVv:p:l:d:u:L:m:W:O:G:", 1788 longopts, NULL) )!= -1) { 1789 switch(oc) { 1790 case 'W': 1791 if(sscanf(optarg, "%d", &warnlevel) < 1 || warnlevel < 0) { 1792 fprintf(stderr, "**** warning level must be a positive number\n"); 1793 exit(1); 1794 } 1795 break; 1796 case 'F': 1797 forcemap = 1; 1798 break; 1799 case 'o': 1800 fputs("Warning: option -o is obsolete, use -Oo instead\n", stderr); 1801 optimize = 0; 1802 break; 1803 case 'e': 1804 encode = 1; 1805 break; 1806 case 'b': 1807 encode = pfbflag = 1; 1808 break; 1809 case 'A': 1810 fputs("Warning: option -A is obsolete, use -GA instead\n", stderr); 1811 wantafm = 1; 1812 break; 1813 case 'a': 1814 allglyphs = 1; 1815 break; 1816 case 's': 1817 fputs("Warning: option -s is obsolete, use -Os instead\n", stderr); 1818 smooth = 0; 1819 break; 1820 case 't': 1821 fputs("Warning: option -t is obsolete, use -Ot instead\n", stderr); 1822 transform = 0; 1823 break; 1824 case 'd': 1825 for(i=0; optarg[i]!=0; i++) 1826 switch(optarg[i]) { 1827 case 'a': 1828 absolute = 1; 1829 break; 1830 case 'r': 1831 reverse = 0; 1832 break; 1833 default: 1834 if (optarg[i] != '?') 1835 fprintf(stderr, "**** Unknown debugging option '%c' ****\n", optarg[i]); 1836 fputs("The recognized debugging options are:\n", stderr); 1837 fputs(" a - enable absolute coordinates\n", stderr); 1838 fputs(" r - do not reverse font outlines directions\n", stderr); 1839 exit(1); 1840 break; 1841 }; 1842 break; 1843 case 'm': 1844 { 1845 char subopt; 1846 int val; 1847 1848 if(sscanf(optarg, "%c=%d", &subopt, &val) !=2) { 1849 fprintf(stderr, "**** Misformatted maximal limit ****\n"); 1850 fprintf(stderr, "spaces around the equal sign are not allowed\n"); 1851 fprintf(stderr, "good examples: -mh=100 -m h=100\n"); 1852 fprintf(stderr, "bad examples: -mh = 100 -mh= 100\n"); 1853 exit(1); 1854 break; 1855 } 1856 switch(subopt) { 1857 case 'h': 1858 max_stemdepth = val; 1859 break; 1860 default: 1861 if (subopt != '?') 1862 fprintf(stderr, "**** Unknown limit type '%c' ****\n", subopt); 1863 fputs("The recognized limit types are:\n", stderr); 1864 fputs(" h - maximal hint stack depth in the PostScript interpreter\n", stderr); 1865 exit(1); 1866 break; 1867 } 1868 break; 1869 } 1870 case 'O': 1871 { 1872 char *p; 1873 for(p=optarg; *p != 0; p++) { 1874 if(set_subo(opotbl, *p) == NULL) { /* found no match */ 1875 if (*p != '?') 1876 fprintf(stderr, "**** Unknown outline processing suboption '%c' ****\n", *p); 1877 fprintf(stderr,"The general form of the outline processing option is:\n"); 1878 fprintf(stderr," -O suboptions\n"); 1879 fprintf(stderr,"(To remember easily -O may be also thought of as \"optimization\").\n"); 1880 print_subo_usage(stderr, opotbl); 1881 fprintf(stderr, "The default state corresponds to the option -O "); 1882 print_subo_dflt(stderr, opotbl); 1883 fprintf(stderr, "\n"); 1884 exit(1); 1885 } 1886 } 1887 break; 1888 } 1889 case 'G': 1890 { 1891 char *p; 1892 struct subo_case *s; 1893 1894 for(p=optarg; *p != 0; p++) { 1895 if(( s = set_subo(fgotbl, *p) )==NULL) { /* found no match */ 1896 if (*p != '?') 1897 fprintf(stderr, "**** Unknown outline processing suboption '%c' ****\n", *p); 1898 fprintf(stderr,"The general form of the file generation option is:\n"); 1899 fprintf(stderr," -G suboptions\n"); 1900 print_subo_usage(stderr, fgotbl); 1901 fprintf(stderr, "The default state corresponds to the option -G "); 1902 print_subo_dflt(stderr, fgotbl); 1903 fprintf(stderr, "\n"); 1904 fprintf(stderr, "If the result is written to STDOUT, the last specified enabling suboption of -G\n"); 1905 fprintf(stderr, "selects the file to be written to STDOUT (the font file by default).\n"); 1906 exit(1); 1907 } 1908 if( *(s->valp) ) 1909 genlast = s->valp; 1910 } 1911 break; 1912 } 1913 case 'h': 1914 fputs("Warning: option -h is obsolete, use -Oh instead\n", stderr); 1915 hints = 0; 1916 break; 1917 case 'H': 1918 fputs("Warning: meaning of option -H has been changed to its opposite\n", stderr); 1919 fputs("Warning: option -H is obsolete, use -Ou instead\n", stderr); 1920 subhints = 0; 1921 break; 1922 case 'f': 1923 fputs("Warning: option -f is obsolete, use -Ob instead\n", stderr); 1924 trybold = 0; 1925 break; 1926 case 'w': 1927 fputs("Warning: option -w is obsolete, use -OW instead\n", stderr); 1928 correctwidth = 1; 1929 break; 1930 case 'u': 1931 if(wantuid) { 1932 fprintf(stderr, "**** UniqueID may be specified only once ****\n"); 1933 exit(1); 1934 } 1935 wantuid = 1; 1936 if(optarg[0]=='A' && optarg[1]==0) 1937 strUID=0; /* will be generated automatically */ 1938 else { 1939 strUID=optarg; 1940 for(i=0; optarg[i]!=0; i++) 1941 if( !isdigit(optarg[i]) ) { 1942 fprintf(stderr, "**** UniqueID must be numeric or A for automatic ****\n"); 1943 exit(1); 1944 } 1945 } 1946 break; 1947 case 'v': 1948 correctvsize = atoi(optarg); 1949 if(correctvsize <= 0 && correctvsize > 1000) { 1950 fprintf(stderr, "**** wrong vsize '%d', ignored ****\n", correctvsize); 1951 correctvsize=0; 1952 } 1953 break; 1954 case 'p': 1955 if(cursw!=0) { 1956 fprintf(stderr, "**** only one front-end parser be used ****\n"); 1957 exit(1); 1958 } 1959 1960 { /* separate parser from parser-specific argument */ 1961 char *p = strchr(optarg, LANG_ARG_SEP); 1962 if(p != 0) { 1963 *p = 0; 1964 front_arg = p+1; 1965 } else 1966 front_arg = ""; 1967 } 1968 for(i=0; frontswtab[i] != NULL; i++) 1969 if( !strcmp(frontswtab[i]->name, optarg) ) { 1970 cursw = frontswtab[i]; 1971 break; 1972 } 1973 1974 if(cursw==0) { 1975 if (strcmp(optarg, "?")) 1976 fprintf(stderr, "**** unknown front-end parser '%s' ****\n", optarg); 1977 fputs("the following front-ends are supported now:\n", stderr); 1978 for(i=0; frontswtab[i] != NULL; i++) { 1979 fprintf(stderr," %s (%s)\n file suffixes: ", 1980 frontswtab[i]->name, 1981 frontswtab[i]->descr ? frontswtab[i]->descr : "no description" 1982 ); 1983 for(j=0; j<MAXSUFFIX; j++) 1984 if(frontswtab[i]->suffix[j]) 1985 fprintf(stderr, "%s ", frontswtab[i]->suffix[j]); 1986 fprintf(stderr, "\n"); 1987 } 1988 exit(1); 1989 } 1990 break; 1991 case 'l': 1992 if(uni_lang_selected!=0) { 1993 fprintf(stderr, "**** only one language option may be used ****\n"); 1994 exit(1); 1995 } 1996 1997 { /* separate language from language-specific argument */ 1998 char *p = strchr(optarg, LANG_ARG_SEP); 1999 if(p != 0) { 2000 *p = 0; 2001 uni_lang_arg = p+1; 2002 } else 2003 uni_lang_arg = ""; 2004 } 2005 for(i=0; i < sizeof uni_lang/(sizeof uni_lang[0]); i++) 2006 if( !strcmp(uni_lang[i].name, optarg) ) { 2007 uni_lang_selected = &uni_lang[i]; 2008 uni_sample = uni_lang[i].sample_upper; 2009 break; 2010 } 2011 2012 if(uni_lang_selected==0) { 2013 if (strcmp(optarg, "?")) 2014 fprintf(stderr, "**** unknown language '%s' ****\n", optarg); 2015 fputs(" the following languages are supported now:\n", stderr); 2016 for(i=0; i < sizeof uni_lang/(sizeof uni_lang[0]); i++) 2017 fprintf(stderr," %s (%s)\n", 2018 uni_lang[i].name, 2019 uni_lang[i].descr ? uni_lang[i].descr : "no description" 2020 ); 2021 exit(1); 2022 } 2023 break; 2024 case 'L': 2025 if(uni_lang_selected!=0) { 2026 fprintf(stderr, "**** only one language option may be used ****\n"); 2027 exit(1); 2028 } 2029 uni_lang_selected = &uni_lang_user; 2030 uni_lang_arg = optarg; 2031 break; 2032 case 'V': 2033 printversion(); 2034 exit(0); 2035 break; 2036 default: 2037 usage(); 2038 exit(1); 2039 break; 2040 } 2041 } 2042 argc-=optind-1; /* the rest of code counts from argv[0] */ 2043 argv+=optind-1; 2044 2045 if (absolute && encode) { 2046 fprintf(stderr, "**** options -a and -e are incompatible ****\n"); 2047 exit(1); 2048 } 2049 if ((argc != 2) && (argc != 3)) { 2050 usage(); 2051 exit(1); 2052 } 2053 2054 /* try to guess the language by the locale used */ 2055 if(uni_lang_selected==0 && (lang=getenv("LANG"))!=0 ) { 2056 for(i=0; i < sizeof uni_lang/sizeof(struct uni_language); i++) { 2057 if( !strncmp(uni_lang[i].name, lang, strlen(uni_lang[i].name)) ) { 2058 uni_lang_selected = &uni_lang[i]; 2059 goto got_a_language; 2060 } 2061 } 2062 /* no full name ? try aliases */ 2063 for(i=0; i < sizeof uni_lang/sizeof(struct uni_language); i++) { 2064 for(c=0; c<MAXUNIALIAS; c++) 2065 if( uni_lang[i].alias[c]!=0 2066 && !strncmp(uni_lang[i].alias[c], lang, strlen(uni_lang[i].alias[c])) ) { 2067 uni_lang_selected = &uni_lang[i]; 2068 goto got_a_language; 2069 } 2070 } 2071 got_a_language: 2072 if(uni_lang_selected!=0) { 2073 WARNING_1 fprintf(stderr, "Using language '%s' for Unicode fonts\n", uni_lang[i].name); 2074 uni_sample = uni_lang[i].sample_upper; 2075 } 2076 } 2077 2078 /* try to guess the front-end parser by the file name suffix */ 2079 if(cursw==0) { 2080 char *p = strrchr(argv[1], '.'); 2081 char *s; 2082 2083 if(p!=0 && (s = strdup(p+1))!=0) { 2084 for(p=s; *p; p++) 2085 *p = tolower(*p); 2086 p = s; 2087 2088 for(i=0; frontswtab[i] != 0 && cursw == 0; i++) { 2089 for(j=0; j<MAXSUFFIX; j++) 2090 if(frontswtab[i]->suffix[j] 2091 && !strcmp(p, frontswtab[i]->suffix[j]) ) { 2092 cursw = frontswtab[i]; 2093 WARNING_1 fprintf(stderr, "Auto-detected front-end parser '%s'\n", 2094 cursw->name); 2095 WARNING_1 fprintf(stderr, " (use ttf2pt1 -p? to get the full list of available front-ends)\n"); 2096 break; 2097 } 2098 } 2099 free(s); 2100 } 2101 2102 if(cursw==0) { 2103 cursw = frontswtab[0]; 2104 WARNING_1 fprintf(stderr, "Can't detect front-end parser, using '%s' by default\n", 2105 cursw->name); 2106 WARNING_1 fprintf(stderr, " (use ttf2pt1 -p? to get the full list of available front-ends)\n"); 2107 } 2108 } 2109 2110 /* open the input file */ 2111 cursw->open(argv[1], front_arg); 2112 2113 /* Get base name of output file (if not specified) 2114 * by removing (known) suffixes 2115 */ 2116 if (argc == 2) { 2117 char *p; 2118 argv[2] = strdup (argv[1]); 2119 p = strrchr(argv[2], '.'); 2120 if (p != NULL) 2121 for (j = 0; (j < MAXSUFFIX) && (cursw->suffix[j]); j++) 2122 if (!strcmp(p+1, cursw->suffix[j])) { 2123 *p = '\0'; 2124 break; 2125 } 2126 } 2127 2128 if ((null_file = fopen(BITBUCKET, "w")) == NULL) { 2129 fprintf(stderr, "**** Cannot open %s ****\n", 2130 BITBUCKET); 2131 exit(1); 2132 } 2133 2134 if (argv[2][0] == '-' && argv[2][1] == 0) { 2135 #ifdef WINDOWS 2136 if(encode) { 2137 fprintf(stderr, "**** can't write encoded file to stdout ***\n"); 2138 exit(1); 2139 } 2140 #endif /* WINDOWS */ 2141 pfa_file = ufm_file = afm_file = dvienc_file = null_file; 2142 2143 if(wantafm || genlast == &gen_afm) { /* print .afm instead of .pfa */ 2144 afm_file=stdout; 2145 } else if(genlast == &gen_dvienc) { /* print .enc instead of .pfa */ 2146 dvienc_file=stdout; 2147 } else { 2148 pfa_file=stdout; 2149 } 2150 } else { 2151 #ifndef WINDOWS 2152 snprintf(filename, sizeof filename, "%s.%s", argv[2], encode ? (pfbflag ? "pfb" : "pfa") : "t1a" ); 2153 #else /* WINDOWS */ 2154 snprintf(filename, sizeof filename, "%s.t1a", argv[2]); 2155 #endif /* WINDOWS */ 2156 if(gen_pfa) { 2157 if ((pfa_file = fopen(filename, "w+b")) == NULL) { 2158 fprintf(stderr, "**** Cannot create %s ****\n", filename); 2159 exit(1); 2160 } else { 2161 WARNING_2 fprintf(stderr, "Creating file %s\n", filename); 2162 } 2163 } else 2164 pfa_file = null_file; 2165 2166 if(gen_ufm) { 2167 snprintf(filename, sizeof filename, "%s.ufm", argv[2]) ; 2168 if ((ufm_file = fopen(filename, "w+")) == NULL) { 2169 fprintf(stderr, "**** Cannot create %s ****\n", filename); 2170 exit(1); 2171 } 2172 } else 2173 ufm_file = null_file; 2174 2175 if(gen_afm) { 2176 snprintf(filename, sizeof filename, "%s.afm", argv[2]) ; 2177 if ((afm_file = fopen(filename, "w+")) == NULL) { 2178 fprintf(stderr, "**** Cannot create %s ****\n", filename); 2179 exit(1); 2180 } 2181 } else 2182 afm_file = null_file; 2183 2184 if(gen_dvienc) { 2185 snprintf(filename, sizeof filename, "%s.enc", argv[2]) ; 2186 if ((dvienc_file = fopen(filename, "w+")) == NULL) { 2187 fprintf(stderr, "**** Cannot create %s ****\n", filename); 2188 exit(1); 2189 } 2190 } else 2191 dvienc_file = null_file; 2192 } 2193 2194 /* 2195 * Now check whether we want a fully encoded .pfa file 2196 */ 2197 #ifndef WINDOWS 2198 if (encode && pfa_file != null_file) { 2199 int p[2]; 2200 extern FILE *ifp, *ofp; /* from t1asm.c */ 2201 2202 ifp=stdin; 2203 ofp=stdout; 2204 2205 if (pipe(p) < 0) { 2206 perror("**** Cannot create pipe ****\n"); 2207 exit(1); 2208 } 2209 ofp = pfa_file; 2210 ifp = fdopen(p[0], "r"); 2211 if (ifp == NULL) { 2212 perror("**** Cannot use pipe for reading ****\n"); 2213 exit(1); 2214 } 2215 pfa_file = fdopen(p[1], "w"); 2216 if (pfa_file == NULL) { 2217 perror("**** Cannot use pipe for writing ****\n"); 2218 exit(1); 2219 } 2220 switch (fork()) { 2221 case -1: 2222 perror("**** Cannot fork the assembler process ****\n"); 2223 exit(1); 2224 case 0: /* child */ 2225 fclose(pfa_file); 2226 exit(runt1asm(pfbflag)); 2227 default: /* parent */ 2228 fclose(ifp); fclose(ofp); 2229 } 2230 } 2231 #endif /* WINDOWS */ 2232 2233 numglyphs = cursw->nglyphs(); 2234 2235 WARNING_3 fprintf(stderr, "numglyphs = %d\n", numglyphs); 2236 2237 glyph_list = (GLYPH *) calloc(numglyphs, sizeof(GLYPH)); 2238 2239 /* initialize non-0 fields */ 2240 for (i = 0; i < numglyphs; i++) { 2241 GLYPH *g; 2242 2243 g = &glyph_list[i]; 2244 g->char_no = -1; 2245 g->orig_code = -1; 2246 g->name = "UNKNOWN"; 2247 g->flags = GF_FLOAT; /* we start with float representation */ 2248 } 2249 2250 handle_gnames(); 2251 2252 cursw->glmetrics(glyph_list); 2253 cursw->fnmetrics(&fontm); 2254 2255 original_scale_factor = 1000.0 / (double) fontm.units_per_em; 2256 2257 if(transform == 0) 2258 scale_factor = 1.0; /* don't transform */ 2259 else 2260 scale_factor = original_scale_factor; 2261 2262 if(correctvsize && uni_sample!=0) { /* only for known languages */ 2263 /* try to adjust the scale factor to make a typical 2264 * uppercase character of hight at least (correctvsize), this 2265 * may improve the appearance of the font but also 2266 * make it weird, use with caution 2267 */ 2268 int ysz; 2269 2270 ysz = iscale(glyph_list[encoding[uni_sample]].yMax); 2271 if( ysz<correctvsize ) { 2272 scale_factor *= (double)correctvsize / ysz; 2273 } 2274 } 2275 2276 if(allglyphs) { 2277 for (i = 0; i < numglyphs; i++) { 2278 glyph_list[i].flags |= GF_USED; 2279 } 2280 } else { 2281 for (i = 0; i < ENCTABSZ; i++) { 2282 glyph_list[encoding[i]].flags |= GF_USED; 2283 } 2284 2285 /* also always include .notdef */ 2286 for (i = 0; i < numglyphs; i++) 2287 if(!strcmp(glyph_list[i].name, ".notdef")) { 2288 glyph_list[i].flags |= GF_USED; 2289 break; 2290 } 2291 } 2292 2293 for (i = 0; i < numglyphs; i++) { 2294 if (glyph_list[i].flags & GF_USED) { 2295 DBG_TO_GLYPH(&glyph_list[i]); 2296 convert_glyf(i); 2297 DBG_FROM_GLYPH(&glyph_list[i]); 2298 } 2299 } 2300 2301 italic_angle = fontm.italic_angle; 2302 2303 if (italic_angle > 45.0 || italic_angle < -45.0) 2304 italic_angle = 0.0; /* consider buggy */ 2305 2306 if (hints) { 2307 findblues(); 2308 for (i = 0; i < numglyphs; i++) { 2309 if (glyph_list[i].flags & GF_USED) { 2310 DBG_TO_GLYPH(&glyph_list[i]); 2311 buildstems(&glyph_list[i]); 2312 assertpath(glyph_list[i].entries, __FILE__, __LINE__, glyph_list[i].name); 2313 DBG_FROM_GLYPH(&glyph_list[i]); 2314 } 2315 } 2316 stemstatistics(); 2317 } else { 2318 for(i=0; i<4; i++) 2319 bbox[i] = iscale(fontm.bbox[i]); 2320 } 2321 /* don't touch the width of fixed width fonts */ 2322 if( fontm.is_fixed_pitch ) 2323 correctwidth=0; 2324 docorrectwidth(); /* checks correctwidth inside */ 2325 if (reverse) 2326 for (i = 0; i < numglyphs; i++) { 2327 if (glyph_list[i].flags & GF_USED) { 2328 DBG_TO_GLYPH(&glyph_list[i]); 2329 reversepaths(&glyph_list[i]); 2330 assertpath(glyph_list[i].entries, __FILE__, __LINE__, glyph_list[i].name); 2331 DBG_FROM_GLYPH(&glyph_list[i]); 2332 } 2333 } 2334 2335 2336 #if 0 2337 /* 2338 ** It seems to bring troubles. The problem is that some 2339 ** styles of the font may be recognized as fixed-width 2340 ** while other styles of the same font as proportional. 2341 ** So it's better to be commented out yet. 2342 */ 2343 if (tryfixed) 2344 alignwidths(); 2345 #endif 2346 2347 if(trybold) { 2348 forcebold = fontm.force_bold; 2349 } 2350 2351 fprintf(pfa_file, "%%!PS-AdobeFont-1.0: %s %s\n", fontm.name_ps, fontm.name_copyright); 2352 time(&now); 2353 fprintf(pfa_file, "%%%%CreationDate: %s", ctime(&now)); 2354 fprintf(pfa_file, "%% Converted by ttf2pt1 %s/%s\n", TTF2PT1_VERSION, cursw->name); 2355 fprintf(pfa_file, "%% Args: %s\n", cmdline); 2356 fprintf(pfa_file, "%%%%EndComments\n"); 2357 fprintf(pfa_file, "12 dict begin\n/FontInfo 9 dict dup begin\n"); 2358 2359 WARNING_3 fprintf(stderr, "FontName %s%s\n", fontm.name_ps, uni_font_name_suffix); 2360 2361 2362 fprintf(pfa_file, "/version (%s) readonly def\n", fontm.name_version); 2363 2364 fprintf(pfa_file, "/Notice (%s) readonly def\n", fontm.name_copyright); 2365 2366 fprintf(pfa_file, "/FullName (%s) readonly def\n", fontm.name_full); 2367 fprintf(pfa_file, "/FamilyName (%s) readonly def\n", fontm.name_family); 2368 2369 if(wantuid) { 2370 if(strUID) 2371 fprintf(pfa_file, "/UniqueID %s def\n", strUID); 2372 else { 2373 numUID=0; 2374 for(i=0; fontm.name_full[i]!=0; i++) { 2375 numUID *= 37; /* magic number, good for hash */ 2376 numUID += fontm.name_full[i]-' '; 2377 /* if the name is long the first chars 2378 * may be lost forever, so re-insert 2379 * them thus making kind of CRC 2380 */ 2381 numUID += (numUID>>24) & 0xFF; 2382 } 2383 /* the range for private UIDs is 4 000 000 - 4 999 999 */ 2384 fprintf(pfa_file, "/UniqueID %lu def\n", numUID%1000000+4000000); 2385 } 2386 } 2387 2388 fprintf(pfa_file, "/Weight (%s) readonly def\n", fontm.name_style); 2389 2390 fprintf(pfa_file, "/ItalicAngle %f def\n", italic_angle); 2391 fprintf(pfa_file, "/isFixedPitch %s def\n", 2392 fontm.is_fixed_pitch ? "true" : "false"); 2393 2394 /* we don't print out the unused glyphs */ 2395 nchars = 0; 2396 for (i = 0; i < numglyphs; i++) { 2397 if (glyph_list[i].flags & GF_USED) { 2398 nchars++; 2399 } 2400 } 2401 2402 fprintf(afm_file, "StartFontMetrics 4.1\n"); 2403 fprintf(afm_file, "FontName %s%s\n", fontm.name_ps, uni_font_name_suffix); 2404 fprintf(afm_file, "FullName %s\n", fontm.name_full); 2405 fprintf(afm_file, "Notice %s\n", fontm.name_copyright); 2406 fprintf(afm_file, "EncodingScheme FontSpecific\n"); 2407 fprintf(afm_file, "FamilyName %s\n", fontm.name_family); 2408 fprintf(afm_file, "Weight %s\n", fontm.name_style); 2409 fprintf(afm_file, "Version %s\n", fontm.name_version); 2410 fprintf(afm_file, "Characters %d\n", nchars); 2411 fprintf(afm_file, "ItalicAngle %.1f\n", italic_angle); 2412 2413 fprintf(afm_file, "Ascender %d\n", iscale(fontm.ascender)); 2414 fprintf(afm_file, "Descender %d\n", iscale(fontm.descender)); 2415 2416 fprintf(ufm_file, "StartFontMetrics 4.1\n"); 2417 fprintf(ufm_file, "FontName %s%s\n", fontm.name_ps, uni_font_name_suffix); 2418 fprintf(ufm_file, "FullName %s\n", fontm.name_full); 2419 fprintf(ufm_file, "Notice %s\n", fontm.name_copyright); 2420 fprintf(ufm_file, "EncodingScheme FontSpecific\n"); 2421 fprintf(ufm_file, "FamilyName %s\n", fontm.name_family); 2422 fprintf(ufm_file, "Weight %s\n", fontm.name_style); 2423 fprintf(ufm_file, "Version %s\n", fontm.name_version); 2424 fprintf(ufm_file, "Characters %d\n", nchars); 2425 fprintf(ufm_file, "ItalicAngle %.1f\n", italic_angle); 2426 2427 fprintf(ufm_file, "Ascender %d\n", iscale(fontm.ascender)); 2428 fprintf(ufm_file, "Descender %d\n", iscale(fontm.descender)); 2429 2430 fprintf(pfa_file, "/UnderlinePosition %d def\n", 2431 iscale(fontm.underline_position)); 2432 2433 fprintf(pfa_file, "/UnderlineThickness %hd def\nend readonly def\n", 2434 iscale(fontm.underline_thickness)); 2435 2436 fprintf(afm_file, "UnderlineThickness %d\n", 2437 iscale(fontm.underline_thickness)); 2438 2439 fprintf(afm_file, "UnderlinePosition %d\n", 2440 iscale(fontm.underline_position)); 2441 2442 fprintf(afm_file, "IsFixedPitch %s\n", 2443 fontm.is_fixed_pitch ? "true" : "false"); 2444 fprintf(afm_file, "FontBBox %d %d %d %d\n", 2445 bbox[0], bbox[1], bbox[2], bbox[3]); 2446 2447 fprintf(ufm_file, "UnderlineThickness %d\n", 2448 iscale(fontm.underline_thickness)); 2449 2450 fprintf(ufm_file, "UnderlinePosition %d\n", 2451 iscale(fontm.underline_position)); 2452 2453 fprintf(ufm_file, "IsFixedPitch %s\n", 2454 fontm.is_fixed_pitch ? "true" : "false"); 2455 fprintf(ufm_file, "FontBBox %d %d %d %d\n", 2456 bbox[0], bbox[1], bbox[2], bbox[3]); 2457 2458 fprintf(pfa_file, "/FontName /%s%s def\n", fontm.name_ps, uni_font_name_suffix); 2459 fprintf(pfa_file, "/PaintType 0 def\n/StrokeWidth 0 def\n"); 2460 /* I'm not sure if these are fixed */ 2461 fprintf(pfa_file, "/FontType 1 def\n"); 2462 2463 if (transform) { 2464 fprintf(pfa_file, "/FontMatrix [0.001 0 0 0.001 0 0] def\n"); 2465 } else { 2466 fprintf(pfa_file, "/FontMatrix [%9.7f 0 0 %9.7f 0 0] def\n", 2467 original_scale_factor / 1000.0, original_scale_factor / 1000.0); 2468 } 2469 2470 fprintf(pfa_file, "/FontBBox {%d %d %d %d} readonly def\n", 2471 bbox[0], bbox[1], bbox[2], bbox[3]); 2472 2473 fprintf(pfa_file, "/Encoding 256 array\n"); 2474 /* determine number of elements for metrics table */ 2475 nmetrics = 256; 2476 for (i = 0; i < numglyphs; i++) { 2477 if( glyph_list[i].flags & GF_USED 2478 && glyph_list[i].char_no == -1 ) { 2479 nmetrics++; 2480 } 2481 } 2482 fprintf(afm_file, "StartCharMetrics %d\n", nmetrics); 2483 fprintf(ufm_file, "StartCharMetrics %d\n", nmetrics); 2484 2485 fprintf(dvienc_file, "/%s%sEncoding [\n", 2486 fontm.name_ps, uni_font_name_suffix); 2487 2488 for (i = 0; i < 256; i++) { /* here 256, not ENCTABSZ */ 2489 fprintf(pfa_file, 2490 "dup %d /%s put\n", i, glyph_list[encoding[i]].name); 2491 if( glyph_list[encoding[i]].flags & GF_USED ) { 2492 print_glyph_metrics(afm_file, i, encoding[i]); 2493 print_glyph_metrics_ufm(ufm_file, glyph_list[encoding[i]].orig_code, encoding[i]); 2494 } 2495 if (encoding[i]) 2496 fprintf (dvienc_file, "/index0x%04X\n", encoding[i]); 2497 else 2498 fprintf (dvienc_file, "/.notdef\n"); 2499 } 2500 2501 /* print the metrics for glyphs not in encoding table */ 2502 for(i=0; i<numglyphs; i++) { 2503 if( (glyph_list[i].flags & GF_USED) 2504 && glyph_list[i].char_no == -1 ) { 2505 print_glyph_metrics(afm_file, -1, i); 2506 print_glyph_metrics_ufm(ufm_file, glyph_list[i].orig_code, i); 2507 } 2508 } 2509 2510 fprintf(pfa_file, "readonly def\ncurrentdict end\ncurrentfile eexec\n"); 2511 fprintf(pfa_file, "dup /Private 16 dict dup begin\n"); 2512 2513 fprintf(pfa_file, "/RD{string currentfile exch readstring pop}executeonly def\n"); 2514 fprintf(pfa_file, "/ND{noaccess def}executeonly def\n"); 2515 fprintf(pfa_file, "/NP{noaccess put}executeonly def\n"); 2516 2517 /* UniqueID must be shown twice, in both font and Private dictionary */ 2518 if(wantuid) { 2519 if(strUID) 2520 fprintf(pfa_file, "/UniqueID %s def\n", strUID); 2521 else 2522 /* the range for private UIDs is 4 000 000 - 4 999 999 */ 2523 fprintf(pfa_file, "/UniqueID %lu def\n", numUID%1000000+4000000); 2524 } 2525 2526 if(forcebold==0) 2527 fprintf(pfa_file, "/ForceBold false def\n"); 2528 else if(forcebold==1) 2529 fprintf(pfa_file, "/ForceBold true def\n"); 2530 2531 fprintf(pfa_file, "/BlueValues [ "); 2532 for (i = 0; i < nblues; i++) 2533 fprintf(pfa_file, "%d ", bluevalues[i]); 2534 fprintf(pfa_file, "] def\n"); 2535 2536 fprintf(pfa_file, "/OtherBlues [ "); 2537 for (i = 0; i < notherb; i++) 2538 fprintf(pfa_file, "%d ", otherblues[i]); 2539 fprintf(pfa_file, "] def\n"); 2540 2541 if (stdhw != 0) 2542 fprintf(pfa_file, "/StdHW [ %d ] def\n", stdhw); 2543 if (stdvw != 0) 2544 fprintf(pfa_file, "/StdVW [ %d ] def\n", stdvw); 2545 fprintf(pfa_file, "/StemSnapH [ "); 2546 for (i = 0; i < 12 && stemsnaph[i] != 0; i++) 2547 fprintf(pfa_file, "%d ", stemsnaph[i]); 2548 fprintf(pfa_file, "] def\n"); 2549 fprintf(pfa_file, "/StemSnapV [ "); 2550 for (i = 0; i < 12 && stemsnapv[i] != 0; i++) 2551 fprintf(pfa_file, "%d ", stemsnapv[i]); 2552 fprintf(pfa_file, "] def\n"); 2553 2554 fprintf(pfa_file, "/MinFeature {16 16} def\n"); 2555 /* Are these fixed also ? */ 2556 fprintf(pfa_file, "/password 5839 def\n"); 2557 2558 /* calculate the number of subroutines */ 2559 2560 subid=5; 2561 for (i = 0; i < numglyphs; i++) { 2562 if (glyph_list[i].flags & GF_USED) { 2563 subid+=glyph_list[i].nsg; 2564 } 2565 } 2566 2567 fprintf(pfa_file, "/Subrs %d array\n", subid); 2568 /* standard subroutines */ 2569 fprintf(pfa_file, "dup 0 {\n\t3 0 callothersubr pop pop setcurrentpoint return\n\t} NP\n"); 2570 fprintf(pfa_file, "dup 1 {\n\t0 1 callothersubr return\n\t} NP\n"); 2571 fprintf(pfa_file, "dup 2 {\n\t0 2 callothersubr return\n\t} NP\n"); 2572 fprintf(pfa_file, "dup 3 {\n\treturn\n\t} NP\n"); 2573 /* our sub to make the hint substitution code shorter */ 2574 fprintf(pfa_file, "dup 4 {\n\t1 3 callothersubr pop callsubr return\n\t} NP\n"); 2575 2576 if(pfa_file != null_file) { /* save time if the output would be wasted */ 2577 /* print the hinting subroutines */ 2578 subid=5; 2579 for (i = 0; i < numglyphs; i++) { 2580 if (glyph_list[i].flags & GF_USED) { 2581 subid+=print_glyph_subs(i, subid); 2582 } 2583 } 2584 2585 fprintf(pfa_file, "ND\n"); 2586 2587 fprintf(pfa_file, "2 index /CharStrings %d dict dup begin\n", nchars); 2588 2589 for (i = 0; i < numglyphs; i++) { 2590 if (glyph_list[i].flags & GF_USED) { 2591 print_glyph(i); 2592 } 2593 } 2594 } 2595 2596 2597 fprintf(pfa_file, "end\nend\nreadonly put\n"); 2598 fprintf(pfa_file, "noaccess put\n"); 2599 fprintf(pfa_file, "dup/FontName get exch definefont pop\n"); 2600 fprintf(pfa_file, "mark currentfile closefile\n"); 2601 fprintf(pfa_file, "cleartomark\n"); 2602 if(pfa_file != null_file) 2603 fclose(pfa_file); 2604 2605 fprintf(afm_file, "EndCharMetrics\n"); 2606 fprintf(ufm_file, "EndCharMetrics\n"); 2607 2608 if(afm_file != null_file) { /* save time if the output would be wasted */ 2609 /* print the kerning data if present */ 2610 cursw->kerning(glyph_list); 2611 print_kerning(afm_file); 2612 } 2613 if(ufm_file != null_file) { /* save time if the output would be wasted */ 2614 /* print the kerning data if present */ 2615 cursw->kerning(glyph_list); 2616 print_kerning(ufm_file); 2617 } 2618 2619 fprintf(afm_file, "EndFontMetrics\n"); 2620 if(afm_file != null_file) 2621 fclose(afm_file); 2622 2623 fprintf(ufm_file, "EndFontMetrics\n"); 2624 if(ufm_file != null_file) 2625 fclose(ufm_file); 2626 2627 fprintf(dvienc_file, "] def\n"); 2628 if(dvienc_file != null_file) 2629 fclose(dvienc_file); 2630 2631 WARNING_1 fprintf(stderr, "Finished - font files created\n"); 2632 2633 cursw->close(); 2634 2635 #ifndef WINDOWS 2636 while (wait(&ws) > 0) { 2637 } 2638 #else 2639 if (encode && pfa_file != null_file) { 2640 extern FILE *ifp, *ofp; /* from t1asm.c */ 2641 2642 snprintf(filename, sizeof filename, "%s.%s", argv[2], pfbflag ? "pfb" : "pfa" ); 2643 2644 if ((ofp = fopen(filename, "w+b")) == NULL) { 2645 fprintf(stderr, "**** Cannot create %s ****\n", filename); 2646 exit(1); 2647 } else { 2648 WARNING_2 fprintf(stderr, "Creating file %s\n", filename); 2649 } 2650 2651 snprintf(filename, sizeof filename, "%s.t1a", argv[2]); 2652 2653 if ((ifp = fopen(filename, "rb")) == NULL) { 2654 fprintf(stderr, "**** Cannot read %s ****\n", filename); 2655 exit(1); 2656 } else { 2657 WARNING_2 fprintf(stderr, "Converting file %s\n", filename); 2658 } 2659 2660 runt1asm(pfbflag); 2661 2662 WARNING_2 fprintf(stderr, "Removing file %s\n", filename); 2663 if(unlink(filename) < 0) 2664 WARNING_1 fprintf(stderr, "Unable to remove file %s\n", filename); 2665 } 2666 #endif /* WINDOWS */ 2667 2668 fclose(null_file); 2669 return 0; 2670 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Fri Nov 28 20:08:37 2014 | Cross-referenced by PHPXref 0.7.1 |