[ Index ]

PHP Cross Reference of vtigercrm-6.1.0

title

Body

[close]

/libraries/tcpdf/fonts/ttf2ufm/ttf2ufm-src/ -> ttf2pt1.c (source)

   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  }


Generated: Fri Nov 28 20:08:37 2014 Cross-referenced by PHPXref 0.7.1