w32tex
About: TeX Live provides a comprehensive TeX system including all the major TeX-related programs, macro packages, and fonts that are free software. Windows sources.
  Fossies Dox: w32tex-src.tar.xz  ("unofficial" and yet experimental doxygen-generated source code documentation)  

otftotfm.cc
Go to the documentation of this file.
1 /* otftotfm.cc -- driver for translating OpenType fonts to TeX metrics
2  *
3  * Copyright (c) 2003-2019 Eddie Kohler
4  *
5  * This program is free software; you can redistribute it and/or modify it
6  * under the terms of the GNU General Public License as published by the Free
7  * Software Foundation; either version 2 of the License, or (at your option)
8  * any later version. This program is distributed in the hope that it will be
9  * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
11  * Public License for more details.
12  */
13 
14 #ifdef HAVE_CONFIG_H
15 # include <config.h>
16 #endif
17 #ifdef WIN32
18 # define _USE_MATH_DEFINES
19 #endif
20 #include <efont/psres.hh>
21 #include <efont/t1rw.hh>
22 #include <efont/t1font.hh>
23 #include <efont/t1item.hh>
24 #include <efont/t1bounds.hh>
25 #include <efont/otfcmap.hh>
26 #include <efont/otfname.hh>
27 #include <efont/otfgsub.hh>
28 #include <efont/ttfkern.hh>
29 #include "glyphfilter.hh"
30 #include "metrics.hh"
31 #include "dvipsencoding.hh"
32 #include "automatic.hh"
33 #include "secondary.hh"
34 #include "kpseinterface.h"
35 #include "util.hh"
36 #include "otftotfm.hh"
37 #include <lcdf/md5.h>
38 #include <lcdf/clp.h>
39 #include <lcdf/error.hh>
40 #include <lcdf/hashmap.hh>
41 #include <lcdf/straccum.hh>
42 #include <efont/cff.hh>
43 #include <efont/otf.hh>
44 #include <stdlib.h>
45 #include <string.h>
46 #include <stdio.h>
47 #include <stdarg.h>
48 #include <ctype.h>
49 #include <errno.h>
50 #include <signal.h>
51 #include <algorithm>
52 #include <math.h>
53 /* M_PI isn't defined in C99 */
54 #ifndef M_PI
55 # define M_PI 3.14159265358979323846264338327
56 #endif
57 #ifdef HAVE_CTIME
58 # include <time.h>
59 #endif
60 #ifdef HAVE_UNISTD_H
61 # include <unistd.h>
62 #endif
63 #ifdef HAVE_FCNTL_H
64 # include <fcntl.h>
65 #endif
66 #ifdef _MSC_VER
67 # include <io.h>
68 #endif
69 
70 using namespace Efont;
71 
72 #define VERSION_OPT 301
73 #define HELP_OPT 302
74 #define QUERY_SCRIPTS_OPT 303
75 #define QUERY_FEATURES_OPT 304
76 #define KPATHSEA_DEBUG_OPT 305
77 
78 #define SCRIPT_OPT 311
79 #define FEATURE_OPT 312
80 #define ENCODING_OPT 313
81 #define LITERAL_ENCODING_OPT 314
82 #define EXTEND_OPT 315
83 #define SLANT_OPT 316
84 #define LETTERSPACE_OPT 317
85 #define LIGKERN_OPT 318
86 #define CODINGSCHEME_OPT 319
87 #define UNICODING_OPT 320
88 #define BOUNDARY_CHAR_OPT 321
89 #define DESIGN_SIZE_OPT 322
90 #define MINIMUM_KERN_OPT 323
91 #define ALTSELECTOR_CHAR_OPT 324
92 #define INCLUDE_ALTERNATES_OPT 325
93 #define EXCLUDE_ALTERNATES_OPT 326
94 #define CLEAR_ALTERNATES_OPT 327
95 #define ALTSELECTOR_FEATURE_OPT 328
96 #define DEFAULT_LIGKERN_OPT 329
97 #define NO_ECOMMAND_OPT 330
98 #define LETTER_FEATURE_OPT 331
99 #define INCLUDE_SUBS_OPT 332
100 #define EXCLUDE_SUBS_OPT 333
101 #define CLEAR_SUBS_OPT 334
102 #define SUBS_FILTER_OPT 335
103 #define ALTERNATES_FILTER_OPT 336
104 #define SPACE_FACTOR_OPT 337
105 #define MATH_SPACING_OPT 338
106 #define POSITION_OPT 339
107 #define WARN_MISSING_OPT 340
108 #define BASE_ENCODINGS_OPT 341
109 #define FIXED_PITCH_OPT 342
110 #define ITALIC_ANGLE_OPT 343
111 #define PROPORTIONAL_WIDTH_OPT 344
112 #define X_HEIGHT_OPT 345
113 
114 #define AUTOMATIC_OPT 350
115 #define FONT_NAME_OPT 351
116 #define QUIET_OPT 352
117 #define GLYPHLIST_OPT 353
118 #define VENDOR_OPT 354
119 #define TYPEFACE_OPT 355
120 #define NOCREATE_OPT 356
121 #define VERBOSE_OPT 357
122 #define FORCE_OPT 358
123 
124 #define VIRTUAL_OPT 360
125 #define PL_OPT 361
126 #define TFM_OPT 362
127 #define MAP_FILE_OPT 363
128 #define OUTPUT_ENCODING_OPT 364
129 
130 #define DIR_OPTS 380
131 #define ENCODING_DIR_OPT (DIR_OPTS + O_ENCODING)
132 #define TFM_DIR_OPT (DIR_OPTS + O_TFM)
133 #define PL_DIR_OPT (DIR_OPTS + O_PL)
134 #define VF_DIR_OPT (DIR_OPTS + O_VF)
135 #define VPL_DIR_OPT (DIR_OPTS + O_VPL)
136 #define TYPE1_DIR_OPT (DIR_OPTS + O_TYPE1)
137 #define TYPE42_DIR_OPT (DIR_OPTS + O_TYPE42)
138 #define TRUETYPE_DIR_OPT (DIR_OPTS + O_TRUETYPE)
139 #define DIR_OPT (DIR_OPTS + NUMODIR)
140 
141 #define NO_OUTPUT_OPTS 400
142 #define NO_ENCODING_OPT (NO_OUTPUT_OPTS + G_ENCODING)
143 #define NO_TYPE1_OPT (NO_OUTPUT_OPTS + G_TYPE1)
144 #define NO_DOTLESSJ_OPT (NO_OUTPUT_OPTS + G_DOTLESSJ)
145 #define NO_UPDMAP_OPT (NO_OUTPUT_OPTS + G_UPDMAP)
146 #define UPDMAP_SYS_OPT (NO_OUTPUT_OPTS + G_UPDMAP_USER)
147 
148 #define YES_OUTPUT_OPTS 2000
149 #define TRUETYPE_OPT (YES_OUTPUT_OPTS + G_TRUETYPE)
150 #define TYPE42_OPT (YES_OUTPUT_OPTS + G_TYPE42)
151 #define UPDMAP_USER_OPT (YES_OUTPUT_OPTS + G_UPDMAP_USER)
152 
153 #define CHAR_OPTTYPE (Clp_ValFirstUser)
154 
155 static Clp_Option options[] = {
156 
157  { "script", 's', SCRIPT_OPT, Clp_ValString, 0 },
158  { "feature", 'f', FEATURE_OPT, Clp_ValString, 0 },
159  { "letter-feature", 0, LETTER_FEATURE_OPT, Clp_ValString, 0 },
160  { "lf", 0, LETTER_FEATURE_OPT, Clp_ValString, 0 },
161  { "include-substitutions", 0, INCLUDE_SUBS_OPT, Clp_ValString, 0 },
162  { "exclude-substitutions", 0, EXCLUDE_SUBS_OPT, Clp_ValString, 0 },
163  { "clear-substitutions", 0, CLEAR_SUBS_OPT, 0, 0 },
164  { "substitution-filter", 0, SUBS_FILTER_OPT, Clp_ValString, 0 },
165  { "subs-filter", 0, SUBS_FILTER_OPT, Clp_ValString, 0 },
166  { "encoding", 'e', ENCODING_OPT, Clp_ValString, 0 },
167  { "literal-encoding", 0, LITERAL_ENCODING_OPT, Clp_ValString, 0 },
168  { "base-encodings", 0, BASE_ENCODINGS_OPT, Clp_ValString, 0 },
169  { "extend", 'E', EXTEND_OPT, Clp_ValDouble, 0 },
170  { "slant", 'S', SLANT_OPT, Clp_ValDouble, 0 },
171  { "letterspacing", 'L', LETTERSPACE_OPT, Clp_ValInt, 0 },
172  { "letterspace", 'L', LETTERSPACE_OPT, Clp_ValInt, 0 },
173  { "min-kern", 'k', MINIMUM_KERN_OPT, Clp_ValDouble, 0 },
174  { "minimum-kern", 'k', MINIMUM_KERN_OPT, Clp_ValDouble, 0 },
175  { "kern-precision", 'k', MINIMUM_KERN_OPT, Clp_ValDouble, 0 },
176  { "ligkern", 0, LIGKERN_OPT, Clp_ValString, 0 },
177  { "position", 0, POSITION_OPT, Clp_ValString, 0 },
178  { "warn-missing", 0, WARN_MISSING_OPT, 0, Clp_Negate },
179  { "no-encoding-commands", 0, NO_ECOMMAND_OPT, 0, 0 },
180  { "default-ligkern", 0, DEFAULT_LIGKERN_OPT, 0, Clp_Negate },
181  { "unicoding", 0, UNICODING_OPT, Clp_ValString, 0 },
182  { "coding-scheme", 0, CODINGSCHEME_OPT, Clp_ValString, 0 },
183  { "boundary-char", 0, BOUNDARY_CHAR_OPT, CHAR_OPTTYPE, 0 },
184  { "altselector", 0, ALTSELECTOR_CHAR_OPT, CHAR_OPTTYPE, Clp_PreferredMatch },
185  { "altselector-char", 0, ALTSELECTOR_CHAR_OPT, CHAR_OPTTYPE, 0 },
186  { "altselector-feature", 0, ALTSELECTOR_FEATURE_OPT, Clp_ValString, 0 },
187  { "design-size", 0, DESIGN_SIZE_OPT, Clp_ValDouble, 0 },
188  { "include-alternates", 0, INCLUDE_ALTERNATES_OPT, Clp_ValString, 0 },
189  { "exclude-alternates", 0, EXCLUDE_ALTERNATES_OPT, Clp_ValString, 0 },
190  { "clear-alternates", 0, CLEAR_ALTERNATES_OPT, 0, 0 },
191  { "alternates-filter", 0, ALTERNATES_FILTER_OPT, Clp_ValString, 0 },
192  { "space-factor", 0, SPACE_FACTOR_OPT, Clp_ValDouble, 0 },
193  { "math-spacing", 0, MATH_SPACING_OPT, CHAR_OPTTYPE, Clp_Negate | Clp_Optional },
194  { "fixed-pitch", 0, FIXED_PITCH_OPT, 0, Clp_Negate },
195  { "fixed-width", 0, FIXED_PITCH_OPT, 0, Clp_Negate },
196  { "proportional-width", 0, PROPORTIONAL_WIDTH_OPT, 0, Clp_Negate },
197  { "italic-angle", 0, ITALIC_ANGLE_OPT, Clp_ValDouble, 0 },
198  { "x-height", 0, X_HEIGHT_OPT, Clp_ValString, 0 },
199 
200  { "pl", 'p', PL_OPT, 0, Clp_Negate },
201  { "tfm", 't', TFM_OPT, 0, Clp_Negate }, // not in documentation
202  { "virtual", 0, VIRTUAL_OPT, 0, Clp_Negate },
203  { "no-encoding", 0, NO_ENCODING_OPT, 0, 0 },
204  { "no-type1", 0, NO_TYPE1_OPT, 0, 0 },
205  { "no-dotlessj", 0, NO_DOTLESSJ_OPT, 0, 0 },
206  { "no-updmap", 0, NO_UPDMAP_OPT, 0, 0 },
207  { "updmap-sys", 0, UPDMAP_SYS_OPT, 0, 0 },
208  { "updmap-user", 0, UPDMAP_USER_OPT, 0, 0 },
209  { "truetype", 0, TRUETYPE_OPT, 0, Clp_Negate },
210  { "type42", 0, TYPE42_OPT, 0, Clp_Negate },
211  { "map-file", 0, MAP_FILE_OPT, Clp_ValString, Clp_Negate },
212  { "output-encoding", 0, OUTPUT_ENCODING_OPT, Clp_ValString, Clp_Optional },
213 
214  { "automatic", 'a', AUTOMATIC_OPT, 0, Clp_Negate },
215  { "name", 'n', FONT_NAME_OPT, Clp_ValString, 0 },
216  { "vendor", 'v', VENDOR_OPT, Clp_ValString, 0 },
217  { "typeface", 0, TYPEFACE_OPT, Clp_ValString, 0 },
218 
219  { "directory", 0, DIR_OPT, Clp_ValString, 0 },
220  { "encoding-directory", 0, ENCODING_DIR_OPT, Clp_ValString, 0 },
221  { "pl-directory", 0, PL_DIR_OPT, Clp_ValString, 0 },
222  { "tfm-directory", 0, TFM_DIR_OPT, Clp_ValString, 0 },
223  { "vpl-directory", 0, VPL_DIR_OPT, Clp_ValString, 0 },
224  { "vf-directory", 0, VF_DIR_OPT, Clp_ValString, 0 },
225  { "type1-directory", 0, TYPE1_DIR_OPT, Clp_ValString, 0 },
226  { "type42-directory", 0, TYPE42_DIR_OPT, Clp_ValString, 0 },
227  { "truetype-directory", 0, TRUETYPE_DIR_OPT, Clp_ValString, 0 },
228 
229  { "quiet", 'q', QUIET_OPT, 0, Clp_Negate },
230  { "glyphlist", 0, GLYPHLIST_OPT, Clp_ValString, 0 },
231  { "no-create", 0, NOCREATE_OPT, 0, 0 },
232  { "force", 0, FORCE_OPT, 0, Clp_Negate },
233  { "verbose", 'V', VERBOSE_OPT, 0, Clp_Negate },
234  { "kpathsea-debug", 0, KPATHSEA_DEBUG_OPT, Clp_ValInt, 0 },
235 
236  { "help", 'h', HELP_OPT, 0, 0 },
237  { "version", 0, VERSION_OPT, 0, 0 },
238 
239  { "query-features", 0, QUERY_FEATURES_OPT, 0, 0 },
240  { "qf", 0, QUERY_FEATURES_OPT, 0, 0 },
241  { "query-scripts", 0, QUERY_SCRIPTS_OPT, 0, 0 },
242  { "qs", 0, QUERY_SCRIPTS_OPT, 0, 0 },
243 
244 };
245 
246 static const char * const default_ligkerns = "\
247 space l =: lslash ; space L =: Lslash ; \
248 question quoteleft =: questiondown ; \
249 exclam quoteleft =: exclamdown ; \
250 hyphen hyphen =: endash ; endash hyphen =: emdash ; \
251 quoteleft quoteleft =: quotedblleft ; \
252 quoteright quoteright =: quotedblright ;";
253 
254 struct BaseEncoding {
258 };
259 
260 static const char *program_name;
263 
265 static PermString dot_notdef(".notdef");
266 
273 
277 static double extend;
278 static double slant;
280 static double design_size;
281 static double minimum_kern = 2.0;
282 static double space_factor = 1.0;
283 static bool math_spacing = false;
284 static int skew_char = -1;
285 static bool override_is_fixed_pitch = false;
286 static bool is_fixed_pitch;
287 static bool override_italic_angle = false;
288 static double italic_angle;
290 static double x_height;
291 
294 
296 
297 bool automatic = false;
298 bool verbose = false;
299 bool no_create = false;
300 bool quiet = false;
301 bool force = false;
302 
304 
305 
306 void
308 {
309  va_list val;
311  if (!error_message)
312  errh->message("Usage: %s [OPTION]... FONT", program_name);
313  else
315  errh->message("Type %s --help for more information.", program_name);
316  exit(1);
317 }
318 
319 void
321 {
322  FileErrorHandler uerrh(stdout);
323  uerrh.message("\
324 %<Otftotfm%> generates TeX font metrics files from an OpenType font (PostScript\n\
325 flavor only), including ligatures, kerns, and some positionings. Supply\n\
326 %<-s SCRIPT[.LANG]%> options to specify a language system, %<-f FEAT%> options to\n\
327 turn on optional OpenType features, and a %<-e ENC%> option to specify a base\n\
328 encoding. Output files are written to the current directory (but see\n\
329 %<--automatic%> and the %<directory%> options).\n\
330 \n\
331 Usage: %s [-a] [OPTIONS] OTFFILE FONTNAME\n\n",
332  program_name);
333  uerrh.message("\
334 Font feature and transformation options:\n\
335  -s, --script=SCRIPT[.LANG] Use features for script SCRIPT[.LANG] [latn].\n\
336  -f, --feature=FEAT Activate feature FEAT.\n\
337  --lf, --letter-feature=FEAT Activate feature FEAT for letters.\n\
338  --subs-filter=PAT Substitute only characters matching PAT.\n\
339  --include-subs=PAT Same, but cumulative.\n\
340  --exclude-subs=PAT Don%,t substitute characters matching PAT.\n\
341  --clear-subs Clear included/excluded substitutions.\n\
342  -E, --extend=F Widen characters by a factor of F.\n\
343  -S, --slant=AMT Oblique characters by AMT, generally <<1.\n\
344  -L, --letterspacing=AMT Letterspace each character by AMT units.\n\
345  --math-spacing[=SKEWCH] Use letterspacing appropriate for math.\n\
346  -k, --min-kern=N Omit kerns with absolute value < N [2.0].\n\
347  --space-factor=F Scale wordspace by a factor of F.\n\
348  --design-size=SIZE Set font design size to SIZE.\n\
349  --fixed-width Set fixed width (no space stretch).\n\
350  --italic-angle=ANGLE Set font italic angle (for positioning accents).\n\
351  --x-height=AMT Set x-height to AMT units.\n\
352 \n");
353  uerrh.message("\
354 Encoding options:\n\
355  -e, --encoding=FILE Use DVIPS encoding FILE as a base encoding.\n\
356  --boundary-char=CHAR Set the boundary character to CHAR.\n\
357  --altselector-char=CHAR Set the alternate selector character to CHAR.\n\
358  --altselector-feature=F Activate feature F for --altselector-char.\n\
359  --alternates-filter=PAT Include only alternate characters matching PAT.\n\
360  --include-alternates=PAT Same as --alternates-filter, but cumulative.\n\
361  --exclude-alternates=PAT Ignore alternate characters matching PAT.\n\
362  --clear-alternates Clear included/excluded alternates.\n\
363  --ligkern=COMMAND Add a ligature or kern.\n\
364  --position=COMMAND Add a POSITION command.\n\
365  --unicoding=COMMAND Add a UNICODING command.\n\
366  --no-encoding-commands Ignore encoding file%,s LIGKERN/UNICODINGs.\n\
367  --no-default-ligkern Don%,t include default LIGKERNs.\n\
368  --coding-scheme=SCHEME Set the output coding scheme to SCHEME.\n\
369  --warn-missing Warn about characters not supported by font.\n\
370  --literal-encoding=FILE Use DVIPS encoding FILE verbatim.\n\
371  --base-encodings=FILE Output can refer to base fonts named in FILE.\n\
372 \n");
373  uerrh.message("\
374 Automatic mode options:\n\
375  -a, --automatic Install in a TeX Directory Structure.\n\
376  -v, --vendor=NAME Set font vendor for TDS [lcdftools].\n\
377  --typeface=NAME Set typeface name for TDS [<font family>].\n\
378  --no-type1 Do not generate Type 1 fonts.\n\
379  --no-dotlessj Do not generate dotless-j fonts.\n\
380  --no-truetype Do not install TrueType-flavored input fonts.\n\
381  --no-updmap Do not run updmap.\n\
382  --updmap-user Run `updmap-user` instead of `updmap-sys`.\n\
383 \n\
384 Output options:\n\
385  -n, --name=NAME Generated font name is NAME.\n\
386  -p, --pl Output human-readable PL/VPLs, not TFM/VFs.\n\
387  --no-virtual Do not generate VFs or VPLs.\n\
388  --no-encoding Do not generate an encoding file.\n\
389  --no-map Do not generate a psfonts.map line.\n\
390  --output-encoding[=FILE] Only generate an encoding file.\n\
391 \n");
392  uerrh.message("\
393 File location options:\n\
394  --tfm-directory=DIR Put TFM files in DIR [.|automatic].\n\
395  --pl-directory=DIR Put PL files in DIR [.|automatic].\n\
396  --vf-directory=DIR Put VF files in DIR [.|automatic].\n\
397  --vpl-directory=DIR Put VPL files in DIR [.|automatic].\n\
398  --encoding-directory=DIR Put encoding files in DIR [.|automatic].\n\
399  --type1-directory=DIR Put Type 1 fonts in DIR [automatic].\n\
400  --truetype-directory=DIR Put TrueType fonts in DIR [automatic].\n\
401  --directory=DIR Put output in DIR [.|automatic].\n\
402  --map-file=FILE Update FILE with psfonts.map information [-].\n\
403 \n\
404 Other options:\n\
405  --glyphlist=FILE Use FILE to map Adobe glyph names to Unicode.\n\
406  -V, --verbose Print progress information to standard error.\n\
407  --no-create Print messages, don't modify any files.\n\
408  --force Generate files even if versions already exist.\n"
409 #if HAVE_KPATHSEA
410 " --kpathsea-debug=MASK Set path searching debug flags to MASK.\n"
411 #endif
412 " -h, --help Print this message and exit.\n\
413  -q, --quiet Do not generate any error messages.\n\
414  --version Print version number and exit.\n\
415 \n\
416 Report bugs to <ekohler@gmail.com>.\n");
417 }
418 
419 #ifndef WIN32
420 extern "C" {
421 static void
423 {
424 #if !HAVE_SIGACTION
426 #else
427  (void) s;
428 #endif
429 }
430 }
431 
432 static void
434 {
435 #ifdef SIGCHLD
436  int sigchld = SIGCHLD;
437 #else
438  int sigchld = SIGCLD;
439 #endif
440 #if HAVE_SIGACTION
441  struct sigaction sa;
442  sigaction(sigchld, 0, &sa);
443  sa.sa_handler = sigchld_handler;
444  sa.sa_flags = 0;
445  sigaction(sigchld, &sa, 0);
446 #else
447  signal(sigchld, sigchld_handler);
448 #endif
449 }
450 #endif
451 
452 
453 // MAIN
454 
455 String
457 {
458  const char *begin = font_name.begin(), *end = font_name.end();
459  while (end > begin && isdigit((unsigned char) end[-1]))
460  --end;
461  if (end < font_name.end() && end > begin && end[-1] != '-' && end[-1] != '+')
462  end = font_name.end();
463  else
464  while (end > begin && (end[-1] == '-' || end[-1] == '+'))
465  --end;
466  if (end == begin)
467  end = font_name.end();
469 }
470 
471 static inline String
473 {
474  return suffix_font_name(font_name, "--base");
475 }
476 
477 static double
479 {
480  try {
481  String gpos_table = finfo.otf->table("GPOS");
482  if (!gpos_table)
483  throw OpenType::Error();
484 
486  OpenType::Gpos gpos(gpos_table, errh);
487 
488  // extract 'size' feature(s)
489  int required_fid;
490  Vector<int> fids;
491  for (const OpenType::Tag *t = interesting_scripts.begin(); t < interesting_scripts.end(); t += 2)
492  gpos.script_list().features(t[0], t[1], required_fid, fids, 0, false);
493 
494  int size_fid = gpos.feature_list().find(OpenType::Tag("size"), fids);
495  if (size_fid < 0)
496  throw OpenType::Error();
497 
498  // old Adobe fonts implement an old, incorrect idea
499  // of what the FeatureParams offset means.
500  OpenType::Name name(finfo.otf->table("name"), errh);
501  OpenType::Data size_data = gpos.feature_list().size_params(size_fid, name, errh);
502  if (!size_data.length())
503  throw OpenType::Error();
504 
505  double result = size_data.u16(0) / 10.;
506  // check for insane design sizes
507  if (result < 1 || result > 1000)
508  throw OpenType::Error();
509 
510  // return a number in 'pt', not 'bp'
511  return result * 72.27 / 72.;
512 
513  } catch (OpenType::Error) {
514  return 10.0;
515  }
516 }
517 
518 static const char * const digit_names[] = {
519  "zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine"
520 };
521 
522 static inline const char *
524 {
525  return (ctx == 0 ? "LIG" : (ctx < 0 ? "/LIG" : "LIG/"));
526 }
527 
528 static double max_printed_real;
529 
530 namespace {
531 struct Printer {
532  Printer(FILE* f, unsigned design_units, unsigned units_per_em)
533  : f_(f), du_((double) design_units / units_per_em),
534  round_(design_units == 1000) {
535  }
536  inline double transform(double value) const;
537  void print_transformed(const char* prefix, double value) const;
538  void print(const char* prefix, double value) const;
539  String render(double value) const;
540  FILE* f_;
541  double du_;
542  bool round_;
543 };
544 
545 inline double Printer::transform(double value) const {
546  value *= du_;
547  if (round_)
548  value = ceil(value);
549  return value;
550 }
551 
552 void Printer::print_transformed(const char* prefix, double value) const {
553  if (round_ || value == 0 || (value > 0.01 && value - floor(value) < 0.01))
554  fprintf(f_, "%s R %g)\n", prefix, value);
555  else
556  fprintf(f_, "%s R %.4f)\n", prefix, value);
558 }
559 
560 void Printer::print(const char* prefix, double value) const {
561  print_transformed(prefix, transform(value));
562 }
563 
564 String Printer::render(double value) const {
565  value = transform(value);
566  if (round_ || value == 0 || (value > 0.01 && value - floor(value) < 0.01))
567  return String(value);
568  else {
569  char buf[128];
570  sprintf(buf, "%.4f", value);
571  return String(buf);
572  }
573 }
574 } // namespace
575 
576 double
577 font_slant(const FontInfo &finfo)
578 {
579  double val = finfo.italic_angle();
580  return -tan(val * M_PI / 180.0) + slant;
581 }
582 
583 static void
585  const FontInfo &finfo, bool vpl,
586  const String &filename, ErrorHandler *errh)
587 {
588  // create file
589  if (no_create) {
590  errh->message("would create %s", filename.c_str());
591  return;
592  }
593 
594  if (verbose)
595  errh->message("creating %s", filename.c_str());
596  FILE *f = fopen(filename.c_str(), "wb");
597  if (!f) {
598  errh->error("%s: %s", filename.c_str(), strerror(errno));
599  return;
600  }
601 
602  // XXX check DESIGNSIZE and DESIGNUNITS for correctness
603 
604  fprintf(f, "(COMMENT Created by '%s'%s)\n", invocation.c_str(), current_time.c_str());
605 
606  // calculate a TeX FAMILY name using afm2tfm's algorithm
607  String family_name = String("TeX-") + ps_name;
608  if (family_name.length() > 19)
609  family_name = family_name.substring(0, 9) + family_name.substring(-10);
610  fprintf(f, "(FAMILY %s)\n", family_name.c_str());
611 
612  if (metrics.coding_scheme())
613  fprintf(f, "(CODINGSCHEME %.39s)\n", String(metrics.coding_scheme()).c_str());
614  int design_units = metrics.design_units();
615 
616  if (design_size <= 0)
617  design_size = get_design_size(finfo);
618  max_printed_real = 0;
619 
620  fprintf(f, "(DESIGNSIZE R %.1f)\n"
621  "(DESIGNUNITS R %d.0)\n"
622  "(COMMENT DESIGNSIZE (1 em) IS IN POINTS)\n"
623  "(COMMENT OTHER DIMENSIONS ARE MULTIPLES OF DESIGNSIZE/%d)\n"
624  "(FONTDIMEN\n", design_size, design_units, design_units);
625 
626  // figure out font dimensions
627  Transform font_xform;
628  if (extend)
629  font_xform.scale(extend, 1);
630  if (slant)
631  font_xform.shear(slant);
632  double bounds[4], width;
633  Printer pr(f, design_units, metrics.units_per_em());
634 
635  double actual_slant = font_slant(finfo);
636  if (actual_slant)
637  fprintf(f, " (SLANT R %g)\n", actual_slant);
638 
639  if (char_bounds(bounds, width, finfo, font_xform, ' ')) {
640  // advance space width by letterspacing, scale by space_factor
641  double space_width = (width + (vpl ? letterspace : 0)) * space_factor;
642  pr.print(" (SPACE", space_width);
643  if (finfo.is_fixed_pitch()) {
644  // fixed-pitch: no space stretch or shrink
645  pr.print(" (STRETCH", 0);
646  pr.print(" (SHRINK", 0);
647  pr.print(" (EXTRASPACE", space_width);
648  } else {
649  pr.print(" (STRETCH", space_width / 2.);
650  pr.print(" (SHRINK", space_width / 3.);
651  pr.print(" (EXTRASPACE", space_width / 6.);
652  }
653  }
654 
655  double x_height = finfo.x_height(font_xform);
656  if (x_height < finfo.units_per_em())
657  pr.print(" (XHEIGHT", x_height);
658 
659  pr.print(" (QUAD", finfo.units_per_em());
660  fprintf(f, " )\n");
661 
662  if (boundary_char >= 0)
663  fprintf(f, "(BOUNDARYCHAR D %d)\n", boundary_char);
664 
665  // figure out font mapping
666  int mapped_font0 = 0;
667  Vector<int> font_mapping;
668  if (vpl) {
669  int vpl_first_font = (metrics.need_base() ? 0 : 1);
670  font_mapping.assign(metrics.n_mapped_fonts(), 0);
671  if (vpl_first_font == 1 && font_mapping.size() == 1)
672  font_mapping.push_back(0);
673  // how many times is each font used?
674  Vector<Setting> settings;
675  for (int i = 0; i < 256; i++)
676  if (metrics.setting(i, settings)) {
677  int font_number = 0;
678  for (const Setting *s = settings.begin(); s < settings.end(); s++)
679  if (s->op == Setting::SHOW)
680  font_mapping[font_number]++;
681  else if (s->op == Setting::FONT)
682  font_number = (int) s->x;
683  }
684  // make sure the most-used font is number 0
685  mapped_font0 = std::max_element(font_mapping.begin(), font_mapping.end()) - font_mapping.begin();
686  // prepare the mapping
687  for (int i = vpl_first_font; i < font_mapping.size(); i++)
688  font_mapping[i] = i - vpl_first_font;
689  font_mapping[mapped_font0] = 0;
690  font_mapping[vpl_first_font] = mapped_font0 - vpl_first_font;
691  if (vpl_first_font != 0)
692  font_mapping[0] = font_mapping.size() - 1;
693  // write MAPFONT
694  for (int i = 0; i < metrics.n_mapped_fonts() - vpl_first_font; i++) {
695  int j = std::find(font_mapping.begin(), font_mapping.end(), i) - font_mapping.begin();
696  String name = metrics.mapped_font_name(j);
697  if (!name)
699  fprintf(f, "(MAPFONT D %d\n (FONTNAME %s)\n (FONTDSIZE R %.1f)\n )\n", i, name.c_str(), design_size);
700  }
701  } else
702  for (int i = 0; i < metrics.n_mapped_fonts(); i++)
703  font_mapping.push_back(i);
704 
705  // figure out the proper names and numbers for glyphs
706  Vector<String> glyph_ids;
707  Vector<String> glyph_comments(257, String());
708  Vector<String> glyph_base_comments(257, String());
709  for (int i = 0; i < metrics.encoding_size(); i++) {
710  if (metrics.glyph(i)) {
711  PermString name = metrics.code_name(i), expected_name;
712  if (i >= '0' && i <= '9')
713  expected_name = digit_names[i - '0'];
714  else if ((i >= 'A' && i <= 'Z') || (i >= 'a' && i <= 'z'))
715  expected_name = PermString((char)i);
716  String glyph_comment;
717  if (name != expected_name)
718  glyph_comment = " (COMMENT " + String(name) + ")";
719 
720  int base = metrics.base_code(i);
721  if (base >= 0 && base < 256)
722  glyph_base_comments[base] = glyph_comment;
723 
724  if (i >= 256)
725  continue;
726 
727  char* expected_name_end;
728  if (expected_name
729  && (name == expected_name
730  || (name.length() == 7
731  && memcmp(name.data(), "uni00", 5) == 0
732  && strtol(name.c_str() + 3, &expected_name_end, 16) == i
733  && *expected_name_end == 0)))
734  glyph_ids.push_back("C " + String((char)i));
735  else
736  glyph_ids.push_back("D " + String(i));
737 
738  glyph_comments[i] = glyph_base_comments[i] = glyph_comment;
739 
740  } else if (i < 256)
741  glyph_ids.push_back("D " + String(i));
742  }
743  // finally, BOUNDARYCHAR
744  glyph_ids.push_back("BOUNDARYCHAR");
745 
746  // LIGTABLE
747  fprintf(f, "(LIGTABLE\n");
748  Vector<int> lig_code2, lig_outcode, lig_context, kern_code2, kern_amt;
749  // don't print KRN x after printing LIG x
750  uint32_t used[8];
751  bool any_ligs = false;
752  StringAccum omitted_clig_sa;
753  for (int i = 0; i <= 256; i++)
754  if (metrics.glyph(i) && minimum_kern < 10000) {
755  int any_lig = metrics.ligatures(i, lig_code2, lig_outcode, lig_context);
756  int any_kern = metrics.kerns(i, kern_code2, kern_amt);
757  if (any_lig || any_kern) {
758  StringAccum kern_sa;
759  memset(used, 0, sizeof(used));
760  for (int j = 0; j < lig_code2.size(); j++) {
761  if (lig_outcode[j] < 257) {
762  kern_sa << " (" << lig_context_str(lig_context[j])
763  << ' ' << glyph_ids[lig_code2[j]]
764  << ' ' << glyph_ids[lig_outcode[j]]
765  << ')' << glyph_comments[lig_code2[j]]
766  << glyph_comments[lig_outcode[j]] << '\n';
767  used[lig_code2[j] >> 5] |= (1 << (lig_code2[j] & 0x1F));
768  } else {
769  omitted_clig_sa << "(COMMENT omitted "
770  << lig_context_str(lig_context[j])
771  << ' ' << metrics.code_name(i)
772  << ' ' << metrics.code_name(lig_code2[j])
773  << ' ' << metrics.code_name(lig_outcode[j])
774  << ")\n";
775  }
776  }
777  for (Vector<int>::const_iterator k2 = kern_code2.begin(); k2 < kern_code2.end(); k2++)
778  if (!(used[*k2 >> 5] & (1 << (*k2 & 0x1F)))) {
779  double this_kern = kern_amt[k2 - kern_code2.begin()];
780  if (fabs(this_kern) >= minimum_kern)
781  kern_sa << " (KRN " << glyph_ids[*k2]
782  << " R " << pr.render(this_kern)
783  << ')' << glyph_comments[*k2] << '\n';
784  }
785  if (kern_sa) {
786  if (any_ligs)
787  fprintf(f, "\n");
788  fprintf(f, " (LABEL %s)%s\n%s (STOP)\n", glyph_ids[i].c_str(), glyph_comments[i].c_str(), kern_sa.c_str());
789  any_ligs = true;
790  }
791  }
792  }
793  fprintf(f, " )\n");
794  if (omitted_clig_sa)
795  fprintf(f, "%s\n", omitted_clig_sa.c_str());
796 
797  // CHARACTERs
798  Vector<Setting> settings;
799  StringAccum sa;
801 
802  for (int i = 0; i < 256; i++)
803  if (metrics.setting(i, settings)) {
804  fprintf(f, "(CHARACTER %s%s\n", glyph_ids[i].c_str(), glyph_comments[i].c_str());
805 
806  // unparse settings into DVI commands
807  sa.clear();
808  push_stack.clear();
809  CharstringBounds boundser(font_xform);
810  int program_number = mapped_font0;
811  const CharstringProgram *program = finfo.program();
812  for (const Setting *s = settings.begin(); s < settings.end(); s++)
813  switch (s->op) {
814 
815  case Setting::SHOW:
816  if (vpl || program == finfo.program())
817  boundser.char_bounds(program->glyph_context(s->y));
818  // 3.Aug.2004 -- reported by Marco Kuhlmann: Don't use
819  // glyph_ids[] array when looking at a different font.
820  if (program_number == 0)
821  sa << " (SETCHAR " << glyph_ids[s->x] << ')' << glyph_base_comments[s->x] << "\n";
822  else
823  sa << " (SETCHAR D " << s->x << ")\n";
824  break;
825 
826  case Setting::MOVE: {
827  int x = 0, y = 0;
828  while (s+1 < settings.end() && s[1].op == Setting::MOVE)
829  x += s->x, y += s->y, s++;
830  if (vpl)
831  boundser.translate(s->x + x, s->y + y);
832  if (s->x + x)
833  sa << " (MOVERIGHT R " << pr.render(s->x + x) << ")\n";
834  if (s->y + y)
835  sa << " (MOVEUP R " << pr.render(s->y + y) << ")\n";
836  break;
837  }
838 
839  case Setting::RULE:
840  if (vpl) {
841  boundser.mark(Point(0, 0));
842  boundser.mark(Point(s->x, s->y));
843  boundser.translate(s->x, 0);
844  }
845  sa << " (SETRULE R " << pr.render(s->y) << " R " << pr.render(s->x) << ")\n";
846  break;
847 
848  case Setting::FONT:
849  if ((int) s->x != program_number) {
850  program = metrics.mapped_font((int) s->x);
851  program_number = (int) s->x;
852  sa << " (SELECTFONT D " << font_mapping[program_number] << ")\n";
853  }
854  break;
855 
856  case Setting::PUSH:
857  push_stack.push_back(boundser.transform(Point(0, 0)));
858  sa << " (PUSH)\n";
859  break;
860 
861  case Setting::POP: {
862  assert(push_stack.size());
863  Point p = push_stack.back() - boundser.transform(Point(0, 0));
864  if (vpl)
865  boundser.translate(p.x, p.y);
866  push_stack.pop_back();
867  sa << " (POP)\n";
868  break;
869  }
870 
871  case Setting::SPECIAL: {
872  bool needhex = false;
873  for (const char *str = s->s.begin(); str < s->s.end() && !needhex; str++)
874  if (*str < ' ' || *str > '~' || *str == '(' || *str == ')')
875  needhex = true;
876  if (needhex) {
877  sa << " (SPECIALHEX ";
878  for (const char *str = s->s.begin(); str < s->s.end(); str++) {
879  static const char hexdig[] = "0123456789ABCDEF";
880  int val = (unsigned char) *str;
881  sa << hexdig[val >> 4] << hexdig[val & 0xF];
882  }
883  sa << ")\n";
884  } else
885  sa << " (SPECIAL " << s->s << ")\n";
886  break;
887  }
888 
889  }
890 
891  assert(push_stack.size() == 0);
892 
893  // output information
894  boundser.output(bounds, width);
895  pr.print(" (CHARWD", width);
896  if (bounds[3] > 0)
897  pr.print(" (CHARHT", bounds[3]);
898  if (bounds[1] < 0)
899  pr.print(" (CHARDP", -bounds[1]);
900  if (bounds[2] > width)
901  pr.print_transformed(" (CHARIC", pr.transform(bounds[2]) - pr.transform(width));
902  if (vpl && (settings.size() > 1 || settings[0].op != Setting::SHOW))
903  fprintf(f, " (MAP\n%s )\n", sa.c_str());
904  fprintf(f, " )\n");
905  }
906 
907  // at last, close the file
908  fclose(f);
909 
910  // Did we print a number too big for TeX to handle? If so, try again.
911  if (max_printed_real >= 2047) {
912  if (metrics.design_units() <= 1)
913  errh->fatal("This font appears to be broken. It has characters so big that the PL format\ncannot represent them.");
914  metrics.set_design_units(metrics.design_units() > 200 ? metrics.design_units() - 250 : 1);
915  if (verbose)
916  errh->message("the font%,s metrics overflow the limits of PL files\n(reducing DESIGNUNITS to %d and trying again)", metrics.design_units());
917  output_pl(metrics, ps_name, boundary_char, finfo, vpl, filename, errh);
918  }
919 }
920 
921 struct Lookup {
922  bool used;
923  bool required;
927 };
928 
929 static void
931 {
932  Vector<int> fids, lookupids;
933  int required;
934 
935  // go over all scripts
936  for (int i = 0; i < interesting_scripts.size(); i += 2) {
939 
940  // collect features applying to this script
941  scripts.features(script, langsys, required, fids, errh);
942 
943  // only use the selected features
944  features.filter(fids, interesting_features);
945 
946  // mark features as having been used
947  for (int j = (required < 0 ? 0 : -1); j < fids.size(); j++) {
948  int fid = (j < 0 ? required : fids[j]);
949  OpenType::Tag ftag = features.tag(fid);
950  if (features.lookups(fid, lookupids, errh) < 0)
951  lookupids.clear();
952  for (int k = 0; k < lookupids.size(); k++) {
953  int l = lookupids[k];
954  if (l < 0 || l >= lookups.size())
955  errh->error("lookup for %<%s%> feature out of range", OpenType::Tag::langsys_text(script, langsys).c_str());
956  else {
957  lookups[l].used = true;
958  lookups[l].features.push_back(ftag);
959  if (j < 0)
960  lookups[l].required = true;
961  }
962  }
963  }
964  }
965 
966  // now check for compatible glyph filters
967  for (Lookup* l = lookups.begin(); l < lookups.end(); l++)
968  if (l->used && !l->required) {
969  l->filter = feature_filters[l->features[0]];
970  for (OpenType::Tag* ft = l->features.begin() + 1; ft < l->features.end(); ft++)
971  if (!l->filter->check_eq(*feature_filters[*ft])) {
972  errh->error("%<%s%> and %<%s%> features share a lookup, but have different filters", l->features[0].text().c_str(), ft->text().c_str());
973  break;
974  }
975  }
976 }
977 
978 static int
980  StringAccum &contents, ErrorHandler *errh)
981 {
982  FILE *f;
983  int ok_retval = (access(filename.c_str(), R_OK) >= 0 ? 0 : 1);
984 
985  if (no_create) {
986  errh->message((ok_retval ? "would create encoding file %s" : "would update encoding file %s"), filename.c_str());
987  return ok_retval;
988  } else if (verbose)
989  errh->message((ok_retval ? "creating encoding file %s" : "updating encoding file %s"), filename.c_str());
990 
991  int fd = open(filename.c_str(), O_RDWR | O_CREAT, 0666);
992  if (fd < 0)
993  return errh->error("%s: %s", filename.c_str(), strerror(errno));
994  f = fdopen(fd, "r+");
995  // NB: also change update_autofont_map if you change this code
996 
997 #if defined(F_SETLKW) && defined(HAVE_FTRUNCATE)
998  {
999  struct flock lock;
1000  lock.l_type = F_WRLCK;
1001  lock.l_whence = SEEK_SET;
1002  lock.l_start = 0;
1003  lock.l_len = 0;
1004  int result;
1005  while ((result = fcntl(fd, F_SETLKW, &lock)) < 0 && errno == EINTR)
1006  /* try again */;
1007  if (result < 0) {
1008  result = errno;
1009  fclose(f);
1010  return errh->error("locking %s: %s", filename.c_str(), strerror(result));
1011  }
1012  }
1013 #endif
1014 
1015  // read old data from encoding file
1016  StringAccum sa;
1017  int amt;
1018  do {
1019  if (char *x = sa.reserve(8192)) {
1020  amt = fread(x, 1, 8192, f);
1021  sa.adjust_length(amt);
1022  } else
1023  amt = 0;
1024  } while (amt != 0);
1025  if (!feof(f) || ferror(f))
1026  return errh->error("%s: %s", filename.c_str(), strerror(errno));
1027  String old_encodings = sa.take_string();
1028  bool created = (!old_encodings);
1029 
1030  // append old encodings
1031  int pos1 = old_encodings.find_left("\n%%");
1032  while (pos1 >= 0 && pos1 < old_encodings.length()) {
1033  int pos2 = old_encodings.find_left("\n%%", pos1 + 1);
1034  if (pos2 < 0)
1035  pos2 = old_encodings.length();
1036  if (old_encodings.substring(pos1 + 3, encoding_name.length()) == encoding_name) {
1037  // encoding already exists, don't change it
1038  fclose(f);
1039  if (verbose)
1040  errh->message("%s unchanged", filename.c_str());
1041  return 0;
1042  } else
1043  contents << old_encodings.substring(pos1, pos2 - pos1);
1044  pos1 = pos2;
1045  }
1046 
1047  // rewind file
1048 #ifdef HAVE_FTRUNCATE
1049  rewind(f);
1050  if (ftruncate(fd, 0) < 0)
1051 #endif
1052  {
1053  fclose(f);
1054  f = fopen(filename.c_str(), "wb");
1055  fd = fileno(f);
1056  }
1057 
1058  ignore_result(fwrite(contents.data(), 1, contents.length(), f));
1059 
1060  fclose(f);
1061 
1062  // inform about the new file if necessary
1063  if (created)
1065  return 0;
1066 }
1067 
1068 static bool
1070  const Vector<PermString> &glyph_names,
1071  ErrorHandler *errh)
1072 {
1073  static const char * const hex_digits = "0123456789ABCDEF";
1074 
1075  // collect encoding data
1077  if (!metrics.base_glyphs(glyphs, 256))
1078  return false;
1079 
1080  StringAccum sa;
1081  for (int i = 0; i < 256; i++) {
1082  if ((i & 0xF) == 0)
1083  sa << (i ? "\n%" : "%") << hex_digits[(i >> 4) & 0xF] << '0' << '\n' << ' ';
1084  else if ((i & 0x7) == 0)
1085  sa << '\n' << ' ';
1086  int g = glyphs[i];
1087  if (g > 0 && g < glyph_names.size())
1088  sa << ' ' << '/' << glyph_names[g];
1089  else
1090  sa << " /.notdef";
1091  }
1092  sa << '\n';
1093 
1094  // digest encoding data
1095  MD5_CONTEXT md5;
1096  md5_init(&md5);
1097  md5_update(&md5, (const unsigned char *)sa.data(), sa.length());
1098  char text_digest[MD5_TEXT_DIGEST_SIZE + 1];
1099  md5_final_text(text_digest, &md5);
1100 
1101  // name encoding using digest
1102  out_encoding_name = "AutoEnc_" + String(text_digest);
1103 
1104  // create encoding filename
1105  bool output_encoding_only = (bool) out_encoding_file;
1106  if (!out_encoding_file)
1107  out_encoding_file = getodir(O_ENCODING, errh) + String("/a_") + String(text_digest).substring(0, 6) + ".enc";
1108 
1109  // exit if we're not responsible for generating an encoding
1110  if (!(output_flags & G_ENCODING))
1111  return true;
1112 
1113  // put encoding block in a StringAccum
1114  // 3.Jun.2003: stick command line definition at the end of the encoding,
1115  // where it won't confuse idiotic ps2pk
1116  StringAccum contents;
1117  if (!output_encoding_only)
1118  contents << "% THIS FILE WAS AUTOMATICALLY GENERATED -- DO NOT EDIT\n\n\
1119 %%" << out_encoding_name << "\n";
1120  contents << "% Encoding created by otftotfm" << current_time << "\n\
1121 % Command line follows encoding\n";
1122 
1123  // the encoding itself
1124  contents << '/' << out_encoding_name << " [\n" << sa << "] def\n";
1125 
1126  // write banner -- unfortunately this takes some doing
1127  String banner = String("Command line: '") + String(invocation.data(), invocation.length()) + String("'");
1128  char *buf = banner.mutable_data();
1129  // get rid of crap characters
1130  for (int i = 0; i < banner.length(); i++)
1131  if (buf[i] < ' ' || buf[i] > 0176) {
1132  if (buf[i] == '\n' || buf[i] == '\r')
1133  buf[i] = ' ';
1134  else
1135  buf[i] = '.';
1136  }
1137  // break lines at 80 characters -- it would be nice if this were in a
1138  // library
1139  while (banner.length() > 0) {
1140  int pos = banner.find_left(' '), last_pos = pos;
1141  while (pos < 75 && pos >= 0) {
1142  last_pos = pos;
1143  pos = banner.find_left(' ', pos + 1);
1144  }
1145  if (last_pos < 0 || (pos < 0 && banner.length() < 75))
1146  last_pos = banner.length();
1147  contents << "% " << banner.substring(0, last_pos) << '\n';
1148  banner = banner.substring(last_pos + 1);
1149  }
1150 
1151  // open encoding file
1152  if (out_encoding_file == "-")
1153  ignore_result(fwrite(contents.data(), 1, contents.length(), stdout));
1154  else if (write_encoding_file(out_encoding_file, out_encoding_name, contents, errh) == 1)
1156  return true;
1157 }
1158 
1159 static void
1161  const FontInfo &finfo, String tfm_filename, String vf_filename,
1162  String pl_filename, ErrorHandler *errh)
1163 {
1164  bool had_pl_filename = !pl_filename.empty();
1165  bool vpl = vf_filename;
1166 
1167  if (!pl_filename) {
1168  if (no_create) {
1169  errh->message("would write %s to temporary file", (vpl ? "VPL" : "PL"));
1170  pl_filename = "<temporary>";
1171  } else {
1172  int pl_fd = temporary_file(pl_filename, errh);
1173  if (pl_fd < 0)
1174  return;
1175  output_pl(metrics, ps_name, boundary_char, finfo, vpl, pl_filename, errh);
1176  close(pl_fd);
1177  }
1178  }
1179 
1181  if (vpl)
1182  command << "vptovf " << shell_quote(pl_filename) << ' ' << shell_quote(vf_filename) << ' ' << shell_quote(tfm_filename) << " 2>&1";
1183  else
1184  command << "pltotf " << shell_quote(pl_filename) << ' ' << shell_quote(tfm_filename) << " 2>&1";
1185 
1186  FILE* cmdfile = mypopen(command.c_str(), "r", errh);
1187  int status;
1188  if (cmdfile) {
1190  while (!feof(cmdfile)) {
1191  char* buf = results.reserve(BUFSIZ);
1192  results.adjust_length(fread(buf, 1, BUFSIZ, cmdfile));
1193  }
1194  // compensate for shitty vptovf/pltotf messages
1195  char* by_units, *last_line;
1196  while (!results.empty()
1197  && (by_units = strstr((char*) results.c_str(), " units"))
1198  && (last_line = strrchr((char*) results.c_str(), '\n'))
1199  && results.end() - last_line > 1
1200  && isdigit((unsigned char) last_line[1])) {
1201  char* start_number = last_line + 1;
1202  char* end_number = last_line + 2;
1203  while (end_number < results.end()
1204  && isdigit((unsigned char) *end_number))
1205  ++end_number;
1206  if (end_number < results.end() && *end_number == '.') {
1207  char* dot = end_number;
1208  ++end_number;
1209  while (end_number < results.end()
1210  && end_number < dot + 8
1211  && isdigit((unsigned char) *end_number))
1212  ++end_number;
1213  }
1214  String number(start_number, end_number);
1215  char* by_units_dest = by_units + 1 + (end_number - start_number);
1216  memmove(by_units_dest, by_units + 1, start_number - (by_units + 1));
1217  memmove(by_units + 1, number.begin(), number.length());
1218  }
1219  if (!results.empty())
1220  fwrite(results.begin(), 1, results.length(), stderr);
1221  status = pclose(cmdfile);
1222  } else
1223  status = -1;
1224 
1225  if (!no_create && !had_pl_filename)
1226  unlink(pl_filename.c_str());
1227 
1228  if (status != 0)
1229  errh->fatal("%s execution failed", (vpl ? "vptovf" : "pltotf"));
1230  else {
1231  update_odir(O_TFM, tfm_filename, errh);
1232  if (vpl)
1233  update_odir(O_VF, vf_filename, errh);
1234  }
1235 }
1236 
1237 void
1239  const FontInfo &finfo,
1240  const String &encoding_name, const String &encoding_file,
1241  const String &font_name,
1242  String (*dvips_include)(const String &ps_name, const FontInfo &, ErrorHandler *),
1243  ErrorHandler *errh)
1244 {
1245  String base_font_name = font_name;
1246  bool need_virtual = metrics.need_virtual(257);
1247  if (need_virtual) {
1248  if (output_flags & G_VMETRICS)
1249  base_font_name = make_base_font_name(font_name);
1250  else if (output_flags & G_METRICS)
1251  errh->warning("features require virtual fonts");
1252  }
1253 
1254  // output virtual metrics
1255  if (!(output_flags & G_VMETRICS))
1256  /* do nothing */;
1257  else if (!need_virtual) {
1258  if (automatic) {
1259  // erase old virtual font
1260  String vf = getodir(O_VF, errh) + "/" + font_name + ".vf";
1261  if (no_create)
1262  errh->message("would remove potential VF file %<%s%>", vf.c_str());
1263  else {
1264  if (verbose)
1265  errh->message("removing potential VF file %<%s%>", vf.c_str());
1266  if (unlink(vf.c_str()) < 0 && errno != ENOENT)
1267  errh->error("removing %s: %s", vf.c_str(), strerror(errno));
1268  }
1269  }
1270  } else {
1271  String vplfile;
1272  if (output_flags & G_ASCII) {
1273  vplfile = getodir(O_VPL, errh) + "/" + font_name + ".vpl";
1274  output_pl(metrics, ps_name, boundary_char, finfo, true, vplfile, errh);
1275  update_odir(O_VPL, vplfile, errh);
1276  }
1277  if (output_flags & G_BINARY) {
1278  String tfm = getodir(O_TFM, errh) + "/" + font_name + ".tfm";
1279  String vf = getodir(O_VF, errh) + "/" + font_name + ".vf";
1280  output_tfm(metrics, ps_name, boundary_char, finfo, tfm, vf, vplfile, errh);
1281  }
1282  }
1283 
1284  // quit if no base needed
1285  metrics.make_base(257);
1286  if (!metrics.need_base())
1287  return;
1288 
1289  // output metrics
1290  double save_minimum_kern = minimum_kern;
1291  if (need_virtual)
1292  minimum_kern = 100000;
1293  if (output_flags & G_METRICS) {
1294  String plfile;
1295  if (output_flags & G_ASCII) {
1296  plfile = getodir(O_PL, errh) + "/" + base_font_name + ".pl";
1297  output_pl(metrics, ps_name, boundary_char, finfo, false, plfile, errh);
1298  update_odir(O_PL, plfile, errh);
1299  }
1300  if (output_flags & G_BINARY) {
1301  String tfm = getodir(O_TFM, errh) + "/" + base_font_name + ".tfm";
1302  output_tfm(metrics, ps_name, boundary_char, finfo, tfm, String(), plfile, errh);
1303  }
1304  }
1305  minimum_kern = save_minimum_kern;
1306 
1307  // print DVIPS map line
1308  if (errh->nerrors() == 0 && (output_flags & G_PSFONTSMAP)) {
1309  StringAccum sa;
1310  sa << base_font_name << ' ' << ps_name << " \"";
1311  if (extend)
1312  sa << extend << " ExtendFont ";
1313  if (slant)
1314  sa << slant << " SlantFont ";
1315  if (encoding_name)
1316  sa << encoding_name << " ReEncodeFont\" <[" << pathname_filename(encoding_file);
1317  else
1318  sa << "\"";
1319  sa << ' ' << dvips_include(ps_name, finfo, errh) << '\n';
1320  update_autofont_map(base_font_name, sa.take_string(), errh);
1321  // if virtual font, remove any map line for base font name
1322  if (base_font_name != font_name)
1324  }
1325 }
1326 
1327 
1328 enum { F_GSUB_TRY = 1, F_GSUB_PART = 2, F_GSUB_ALL = 4,
1332 
1333 static const char * const x_messages[] = {
1334  "% ignored, not supported by font",
1335  "% ignored, too complex for me",
1336  "complex substitutions from % ignored",
1337  "some complex substitutions from % ignored",
1338  "complex positionings from % ignored",
1339  "some complex positionings from % ignored",
1340 };
1341 
1342 static void
1344 {
1346  for (int i = 0; i < interesting_features.size(); i++) {
1348  int fu = feature_usage[f.value()];
1349  String ftext = errh->format("%<%s%>", f.text().c_str());
1350  if (fu == 0)
1351  x[X_UNUSED].push_back(ftext);
1352  else if ((fu & (F_GSUB_TRY | F_GPOS_TRY)) == fu)
1353  x[X_BOTH_NONE].push_back(ftext);
1354  else {
1355  if (fu & F_GSUB_TRY) {
1356  if ((fu & (F_GSUB_PART | F_GSUB_ALL)) == 0)
1357  x[X_GSUB_NONE].push_back(ftext);
1358  else if (fu & F_GSUB_PART)
1359  x[X_GSUB_PART].push_back(ftext);
1360  }
1361  if (fu & F_GPOS_TRY) {
1362  if ((fu & (F_GPOS_PART | F_GPOS_ALL)) == 0)
1363  x[X_GPOS_NONE].push_back(ftext);
1364  else if (fu & F_GPOS_PART)
1365  x[X_GPOS_PART].push_back(ftext);
1366  }
1367  }
1368  }
1369 
1370  for (int i = 0; i < X_COUNT; i++)
1371  if (x[i].size())
1372  goto found;
1373  return;
1374 
1375  found:
1376  for (int i = 0; i < X_COUNT; i++)
1377  if (x[i].size()) {
1378  StringAccum sa;
1379  const char* msg_pct = strchr(x_messages[i], '%');
1380  sa.append(x_messages[i], msg_pct - x_messages[i]);
1381  const char* sep = (x[i].size() > 2 ? ", " : " ");
1382  for (const String* a = x[i].begin(); a < x[i].end() - 1; a++)
1383  sa << *a << sep;
1384  sa << (x[i].size() > 1 ? "and " : "") << x[i].back()
1385  << (x[i].size() > 1 ? " features" : " feature") << (msg_pct+1);
1386  sa.append_break_lines(sa.take_string(), 58);
1387  errh->warning("%s", sa.c_str());
1388  }
1389 }
1390 
1392 
1393 static String
1394 main_dvips_map(const String &ps_name, const FontInfo &finfo, ErrorHandler *errh)
1395 {
1396  if (String fn = installed_type1(otf_filename, ps_name, (output_flags & G_TYPE1) != 0, errh))
1397  return "<" + pathname_filename(fn);
1398  if (!finfo.cff) {
1399  String ttf_fn, t42_fn;
1401  t42_fn = installed_type42(otf_filename, ps_name, (output_flags & G_TYPE42) != 0, errh);
1402  if (t42_fn && (!ttf_fn || (output_flags & G_TYPE42) != 0))
1403  return "<" + pathname_filename(t42_fn);
1404  else if (ttf_fn)
1405  return "<" + pathname_filename(ttf_fn);
1406  }
1407  return "<" + pathname_filename(otf_filename);
1408 }
1409 
1410 static void
1412  DvipsEncoding& dvipsenc, bool dvipsenc_literal,
1413  HashMap<uint32_t, int>& feature_usage,
1414  const Vector<PermString>& glyph_names, ErrorHandler* errh)
1415 {
1416  // find activated GSUB features
1417  OpenType::Gsub gsub(otf.table("GSUB"), &otf, errh);
1418  Vector<Lookup> lookups(gsub.nlookups(), Lookup());
1419  find_lookups(gsub.script_list(), gsub.feature_list(), lookups, errh);
1420 
1421  // find all characters that might result
1422  Vector<bool> used(glyph_names.size(), false);
1423  for (Metrics::Code c = 0; c < metrics.encoding_size(); ++c) {
1424  Metrics::Glyph g = metrics.glyph(c);
1425  if (g >= 0 && g < used.size())
1426  used[g] = true;
1427  }
1428  for (int i = 0; i < lookups.size(); ++i)
1429  if (lookups[i].used) {
1430  OpenType::GsubLookup l = gsub.lookup(i);
1431  l.mark_out_glyphs(gsub, used);
1432  }
1433  OpenType::Coverage used_coverage(used);
1434 
1435  // apply activated GSUB features
1437  for (int i = 0; i < lookups.size(); i++)
1438  if (lookups[i].used) {
1439  OpenType::GsubLookup l = gsub.lookup(i);
1440  subs.clear();
1441  bool understood = l.unparse_automatics(gsub, subs, used_coverage);
1442 
1443  // check for -ffina, which should apply only at the ends of words,
1444  // and -finit, which should apply only at the beginnings.
1445  OpenType::Tag feature = (lookups[i].features.size() == 1 ? lookups[i].features[0] : OpenType::Tag());
1446  if (feature == OpenType::Tag("fina") || feature == OpenType::Tag("fin2") || feature == OpenType::Tag("fin3")) {
1447  if (dvipsenc.boundary_char() < 0)
1448  errh->warning("%<-ffina%> requires a boundary character\n(The input encoding didn%,t specify a boundary character, but\nI need one to implement %<-ffina%> features correctly. Try\nthe %<--boundary-char%> option.)");
1449  else {
1450  int bg = metrics.boundary_glyph();
1451  for (int j = 0; j < subs.size(); j++)
1452  subs[j].add_outer_right(bg);
1453  }
1454  } else if (feature == OpenType::Tag("init")) {
1455  int bg = metrics.boundary_glyph();
1456  for (int j = 0; j < subs.size(); j++)
1457  subs[j].add_outer_left(bg);
1458  }
1459 
1460  //for (int subno = 0; subno < subs.size(); subno++) fprintf(stderr, "%5d\t%s\n", i, subs[subno].unparse().c_str());
1461 
1462  // figure out which glyph filter to use
1463  int nunderstood = metrics.apply(subs, !dvipsenc_literal, i, *lookups[i].filter, glyph_names);
1464 
1465  // mark as used
1466  int d = (understood && nunderstood == subs.size() ? F_GSUB_ALL : (nunderstood ? F_GSUB_PART : 0)) + F_GSUB_TRY;
1467  for (int j = 0; j < lookups[i].features.size(); j++)
1468  feature_usage.find_force(lookups[i].features[j].value()) |= d;
1469  }
1470 
1471  // apply alternate selectors
1472  if (metrics.altselectors() && !dvipsenc_literal) {
1473  // do lookups
1476  Vector<Lookup> alt_lookups(gsub.nlookups(), Lookup());
1477  find_lookups(gsub.script_list(), gsub.feature_list(), alt_lookups, ErrorHandler::silent_handler());
1479  for (int i = 0; i < alt_lookups.size(); i++)
1480  if (alt_lookups[i].used) {
1481  OpenType::GsubLookup l = gsub.lookup(i);
1482  alt_subs.clear();
1483  (void) l.unparse_automatics(gsub, alt_subs, used_coverage);
1484  metrics.apply_alternates(alt_subs, i, *alt_lookups[i].filter, glyph_names);
1485  }
1488  }
1489 }
1490 
1491 static bool
1493 {
1494  return std::find(interesting_features.begin(), interesting_features.end(),
1495  OpenType::Tag("kern")) != interesting_features.end();
1496 }
1497 
1498 static void
1500 {
1501  // if no GPOS "kern" lookups and "kern" requested, try "kern" table
1502  if (!kern_feature_requested())
1503  return;
1504  try {
1505  OpenType::KernTable kern(otf.table("kern"), errh);
1507  bool understood = kern.unparse_automatics(poss, errh);
1508  int nunderstood = metrics.apply(poss);
1509 
1510  // mark as used
1511  int d = (understood && nunderstood == poss.size() ? F_GPOS_ALL : (nunderstood ? F_GPOS_PART : 0)) + F_GPOS_TRY;
1512  feature_usage.find_force(OpenType::Tag("kern").value()) |= d;
1513  } catch (OpenType::BlankTable) {
1514  // nada
1515  } catch (OpenType::Error e) {
1516  errh->warning("kern %<%s%> error, continuing", e.description.c_str());
1517  }
1518 }
1519 
1520 static void
1522 {
1523  OpenType::Gpos gpos(otf.table("GPOS"), errh);
1524  Vector<Lookup> lookups(gpos.nlookups(), Lookup());
1525  find_lookups(gpos.script_list(), gpos.feature_list(), lookups, errh);
1526 
1527  // OpenType recommends that if GPOS exists, but the "kern" feature loads
1528  // no lookups, we use the TrueType "kern" table, if any.
1529  if (kern_feature_requested()) {
1530  OpenType::Tag kern_tag("kern");
1531  for (Lookup *l = lookups.begin(); l != lookups.end(); ++l)
1532  if (std::find(l->features.begin(), l->features.end(), kern_tag) != l->features.end())
1533  goto skip_ttf_kern;
1534  do_try_ttf_kern(metrics, otf, feature_usage, errh);
1535  skip_ttf_kern: ;
1536  }
1537 
1539  for (int i = 0; i < lookups.size(); i++)
1540  if (lookups[i].used) {
1541  OpenType::GposLookup l = gpos.lookup(i);
1542  poss.clear();
1543  bool understood = l.unparse_automatics(poss, errh);
1544  int nunderstood = metrics.apply(poss);
1545 
1546  // mark as used
1547  int d = (understood && nunderstood == poss.size() ? F_GPOS_ALL : (nunderstood ? F_GPOS_PART : 0)) + F_GPOS_TRY;
1548  for (int j = 0; j < lookups[i].features.size(); j++)
1549  feature_usage.find_force(lookups[i].features[j].value()) |= d;
1550  }
1551 }
1552 
1553 static void
1555  const DvipsEncoding &dvipsenc)
1556 {
1557  Transform font_xform;
1558  if (extend)
1559  font_xform.scale(extend, 1);
1560  if (slant)
1561  font_xform.shear(slant);
1562  CharstringBounds boundser(font_xform);
1563 
1564  double x_height = finfo.x_height(font_xform);
1565  double actual_slant = font_slant(finfo);
1566  int boundary_char = dvipsenc.boundary_char();
1567 
1568  double bounds[4], width;
1569 
1570  for (int code = 0; code < metrics.encoding_size(); code++)
1571  if (metrics.was_base_glyph(code)
1572  && code != boundary_char
1573  && char_bounds(bounds, width, finfo, font_xform, metrics.unicode(code))) {
1574  int left_sb = (bounds[0] < 0 ? (int) ceil(-bounds[0]) : 0);
1575  metrics.add_single_positioning(code, left_sb, 0, left_sb);
1576 
1577  if (skew_char >= 0 && code < 256) {
1578  double sheight = std::max(bounds[3], x_height) - 0.5 * x_height;
1579  double right_sb = std::max(bounds[2] - width, 0.0);
1580  double desired = left_sb + 0.5 * width + actual_slant * sheight + 0.25 * right_sb;
1581  double computed = 0.5 * (left_sb + width + right_sb);
1582  int skew = (int) (desired - computed);
1583  metrics.add_kern(code, skew_char, skew);
1584  }
1585  }
1586 }
1587 
1588 static void
1590  const DvipsEncoding &dvipsenc_in, bool dvipsenc_literal,
1591  ErrorHandler *errh)
1592 {
1593  FontInfo finfo(&otf, errh);
1594  if (!finfo.ok())
1595  return;
1596  if (!finfo.cff)
1597  errh->warning("TrueType-flavored font support is experimental");
1604 
1605  // save glyph names
1606  Vector<PermString> glyph_names;
1607  finfo.glyph_names(glyph_names);
1608  OpenType::debug_glyph_names = glyph_names;
1609 
1610  // set typeface name from font family name
1611  {
1612  String typeface = finfo.family_name();
1613 
1614  // make it reasonable for the shell
1615  StringAccum sa;
1616  for (int i = 0; i < typeface.length(); i++)
1617  if (isalnum((unsigned char) typeface[i]) || typeface[i] == '_' || typeface[i] == '-' || typeface[i] == '.' || typeface[i] == ',' || typeface[i] == '+')
1618  sa << typeface[i];
1619 
1620  set_typeface(sa.length() ? sa.take_string() : font_name, false);
1621  }
1622 
1623  // initialize encoding
1624  DvipsEncoding dvipsenc(dvipsenc_in); // make copy
1625  Metrics metrics(finfo.program(), finfo.nglyphs());
1626  // encode boundary glyph at 256; pretend its Unicode value is '\n'
1627  metrics.encode(256, '\n', metrics.boundary_glyph());
1628  if (dvipsenc_literal)
1629  dvipsenc.make_metrics(metrics, finfo, 0, true, errh);
1630  else {
1631  T1Secondary secondary(finfo, font_name, otf_filename);
1632  dvipsenc.make_metrics(metrics, finfo, &secondary, false, errh);
1633  }
1634 
1635  // maintain statistics about features
1636  HashMap<uint32_t, int> feature_usage(0);
1637 
1638  // apply activated GSUB features
1639  try {
1640  do_gsub(metrics, otf, dvipsenc, dvipsenc_literal, feature_usage, glyph_names, errh);
1641  } catch (OpenType::BlankTable) {
1642  // nada
1643  } catch (OpenType::Error e) {
1644  errh->warning("GSUB %<%s%> error, continuing", e.description.c_str());
1645  }
1646 
1647  // apply LIGKERN ligature commands to the result
1648  dvipsenc.apply_ligkern_lig(metrics, errh);
1649 
1650  // test fake ligature mechanism
1651  //metrics.add_threeligature('T', 'h', 'e', '0');
1652 
1653  // reencode characters to fit within 8 bytes (+ 1 for the boundary)
1654  if (!dvipsenc_literal)
1655  metrics.shrink_encoding(257, dvipsenc_in, errh);
1656 
1657  // apply activated GPOS features
1658  try {
1659  do_gpos(metrics, otf, feature_usage, errh);
1660  } catch (OpenType::BlankTable) {
1661  do_try_ttf_kern(metrics, otf, feature_usage, errh);
1662  } catch (OpenType::Error e) {
1663  errh->warning("GPOS %<%s%> error, continuing", e.description.c_str());
1664  }
1665 
1666  // apply LIGKERN kerning and POS positioning commands to the result
1667  dvipsenc.apply_ligkern_kern(metrics, errh);
1668  dvipsenc.apply_position(metrics, errh);
1669 
1670  // use prespecified raw fonts
1671  for (BaseEncoding **be = base_encodings.begin(); be != base_encodings.end(); be++)
1672  if (!(*be)->secondary) {
1673  Vector<int> mapp;
1674  (*be)->encoding.make_base_mappings(mapp, finfo);
1675  metrics.apply_base_encoding((*be)->font_name, (*be)->encoding, mapp);
1676  }
1677 
1678  // remove extra characters
1679  metrics.cut_encoding(257);
1680  //metrics.unparse();
1681  int boundary_char = dvipsenc.boundary_char();
1682 
1683  // apply letterspacing, if any
1684  if (letterspace)
1685  for (int code = 0; code < metrics.encoding_size(); code++)
1686  if (metrics.was_base_glyph(code) && code != boundary_char) {
1687  metrics.add_single_positioning(code, letterspace / 2, 0, letterspace);
1688  if (code < 256) {
1689  metrics.add_kern(code, 256, -letterspace / 2);
1690  metrics.add_kern(256, code, -letterspace / 2);
1691  }
1692  }
1693 
1694  // apply math letterspacing, if any
1695  if (math_spacing)
1696  do_math_spacing(metrics, finfo, dvipsenc);
1697 
1698  // reencode right components of boundary_glyph as boundary_char
1699  if (metrics.reencode_right_ligkern(256, boundary_char) > 0
1700  && boundary_char < 0) {
1701  errh->warning("no boundary character, ignoring some ligatures and/or kerns\n");
1702  errh->message("(You may want to try the --boundary-char option.)");
1703  }
1704 
1705  // report unused and underused features if any
1706  report_underused_features(feature_usage, errh);
1707 
1708  // figure out our FONTNAME
1709  if (!font_name) {
1710  // derive font name from OpenType font name
1711  font_name = finfo.postscript_name();
1712  if (encoding_file) {
1713  int slash = encoding_file.find_right('/') + 1;
1714  int dot = encoding_file.find_right('.');
1715  if (dot < slash) // includes dot < 0 case
1716  dot = encoding_file.length();
1717  font_name += String("--") + encoding_file.substring(slash, dot - slash);
1718  }
1719  if (interesting_scripts.size() != 2 || interesting_scripts[0] != OpenType::Tag("latn") || interesting_scripts[1].valid())
1720  for (int i = 0; i < interesting_scripts.size(); i += 2) {
1721  font_name += String("--S") + interesting_scripts[i].text();
1722  if (interesting_scripts[i+1].valid())
1723  font_name += String(".") + interesting_scripts[i+1].text();
1724  }
1725  for (int i = 0; i < interesting_features.size(); i++)
1726  if (feature_usage[interesting_features[i].value()])
1727  font_name += String("--F") + interesting_features[i].text();
1728  }
1729 
1730  // output encoding
1731  if (dvipsenc_literal) {
1732  out_encoding_name = dvipsenc_in.name();
1733  out_encoding_file = dvipsenc_in.filename();
1734  } else
1735  output_encoding(metrics, glyph_names, errh);
1736 
1737  // set up coding scheme
1738  if (metrics.coding_scheme())
1739  metrics.set_design_units(1);
1740  else
1741  metrics.set_coding_scheme(out_encoding_name);
1742 
1743  // force no type 1
1744  if (!finfo.cff && (output_flags & G_TYPE1)) {
1745  errh->warning("assuming --no-type1 since this font is TrueType-flavored");
1746  output_flags &= ~~G_TYPE1;
1747  }
1748 
1749  // output
1751  output_metrics(metrics, finfo.postscript_name(), dvipsenc.boundary_char(),
1752  finfo,
1755 }
1756 
1757 
1758 String
1759 installed_metrics_font_name(const String &base_font_name, const String &secondary)
1760 {
1761  for (BaseEncoding **be = base_encodings.begin(); be != base_encodings.end(); be++)
1762  if ((*be)->secondary == secondary && ::font_name == base_font_name)
1763  return (*be)->font_name;
1764  return String();
1765 }
1766 
1767 
1768 extern "C" {
1769 static int
1770 clp_parse_char(Clp_Parser *clp, const char *arg, int complain, void *)
1771 {
1772  if (arg[0] && !arg[1] && !isdigit((unsigned char) arg[0])) {
1773  clp->val.i = (unsigned char)arg[0];
1774  return 1;
1775  } else if (arg[0] == '-' || isdigit((unsigned char) arg[0])) {
1776  char *end;
1777  clp->val.i = strtol(arg, &end, 10);
1778  if (clp->val.i <= 255 && !*end)
1779  return 1;
1780  }
1781  if (complain)
1782  Clp_OptionError(clp, "'%O' expects a character, not '%s'", arg);
1783  return 0;
1784 }
1785 }
1786 
1787 static void
1789 {
1790  String str = read_file(filename, errh, true);
1791  String print_filename = (filename == "-" ? "<stdin>" : filename) + ":";
1792  int lineno = 1;
1793  str.c_str();
1794  const char *s_end = str.end();
1795  for (const char *s = str.begin(); s != s_end; ) {
1796  while (s != s_end && isspace((unsigned char) *s) && *s != '\n' && *s != '\r')
1797  s++;
1798  // skip comments and blank lines
1799  if (s != s_end && *s != '%' && *s != '#' && *s != '\n' && *s != '\r') {
1800  const char *w1 = s;
1801  while (s != s_end && !isspace((unsigned char) *s))
1802  s++;
1803  BaseEncoding *be = new BaseEncoding;
1804  be->font_name = str.substring(w1, s);
1805  while (s != s_end && isspace((unsigned char) *s) && *s != '\n' && *s != '\r')
1806  s++;
1807  const char *w2 = s;
1808  while (s != s_end && !isspace((unsigned char) *s))
1809  s++;
1810  String efile = str.substring(w2, s);
1811  while (s != s_end && isspace((unsigned char) *s) && *s != '\n' && *s != '\r')
1812  s++;
1813  if (s != s_end && !isspace((unsigned char) *s) && *s != '%' && *s != '#') {
1814  const char *w3 = s;
1815  while (s != s_end && !isspace((unsigned char) *s))
1816  s++;
1817  be->secondary = str.substring(w3, s);
1818  }
1819  LandmarkErrorHandler lerrh(errh, print_filename + String(lineno));
1820  int before = lerrh.nerrors();
1821  if (be->secondary)
1822  /* encoding ignored */;
1823  else if (!efile)
1824  lerrh.error("missing encoding name");
1825  else if (String path = locate_encoding(efile, errh))
1826  be->encoding.parse(path, true, true, &lerrh);
1827  else
1828  lerrh.error("encoding %<%s%> not found", efile.c_str());
1829  if (lerrh.nerrors() == before)
1830  base_encodings.push_back(be);
1831  else
1832  delete be;
1833  }
1834  while (s != s_end && *s != '\n' && *s != '\r')
1835  s++;
1836  if (s != s_end && *s == '\r')
1837  s++;
1838  if (s != s_end && *s == '\n')
1839  s++;
1840  lineno++;
1841  }
1842 }
1843 
1844 int
1845 main(int argc, char *argv[])
1846 {
1847 #ifndef WIN32
1848  handle_sigchld();
1849 #endif
1850  Clp_Parser *clp =
1851  Clp_NewParser(argc, (const char * const *)argv, sizeof(options) / sizeof(options[0]), options);
1854 #if HAVE_KPATHSEA
1855  kpsei_init(argv[0], "lcdftools");
1856 #endif
1857 #ifdef HAVE_CTIME
1858  {
1859  time_t t = time(0);
1860  char *c = ctime(&t);
1861  current_time = " on " + String(c).substring(0, -1); // get rid of \n
1862  }
1863 #endif
1864  for (int i = 0; i < argc; i++)
1865  invocation << (i ? " " : "") << argv[i];
1866 
1868  const char *input_file = 0;
1869  Vector<String> glyphlist_files;
1870  bool literal_encoding = false;
1871  bool have_encoding_file = false;
1874  Vector<String> unicoding;
1875  Vector<String> base_encoding_files;
1876  bool no_ecommand = false, default_ligkern = true;
1877  int warn_missing = -1;
1878  unsigned specified_output_flags = 0;
1880  const char* odirs[NUMODIR + 1];
1881  for (int i = 0; i <= NUMODIR; ++i) {
1882  odirs[i] = 0;
1883  }
1884 
1885  GlyphFilter current_substitution_filter;
1886  GlyphFilter current_alternate_filter;
1887  GlyphFilter* current_filter_ptr = &null_filter;
1888  Vector<GlyphFilter*> allocated_filters;
1889 
1890  while (1) {
1891  int opt = Clp_Next(clp);
1892  switch (opt) {
1893 
1894  case SCRIPT_OPT: {
1895  String arg = clp->vstr;
1896  int period = arg.find_left('.');
1897  OpenType::Tag scr(period <= 0 ? arg : arg.substring(0, period));
1898  if (scr.valid() && period > 0) {
1899  OpenType::Tag lang(arg.substring(period + 1));
1900  if (lang.valid()) {
1901  interesting_scripts.push_back(scr);
1902  interesting_scripts.push_back(lang);
1903  } else
1904  usage_error(errh, "bad language tag");
1905  } else if (scr.valid()) {
1906  interesting_scripts.push_back(scr);
1907  interesting_scripts.push_back(OpenType::Tag());
1908  } else
1909  usage_error(errh, "bad script tag");
1910  break;
1911  }
1912 
1913  case FEATURE_OPT: {
1914  OpenType::Tag t(clp->vstr);
1915  if (!t.valid())
1916  usage_error(errh, "bad feature tag");
1917  else if (feature_filters[t])
1918  usage_error(errh, "feature %<%s%> included twice", t.text().c_str());
1919  else {
1920  if (!current_filter_ptr) {
1921  current_filter_ptr = new GlyphFilter(current_substitution_filter + current_alternate_filter);
1922  allocated_filters.push_back(current_filter_ptr);
1923  }
1924  interesting_features.push_back(t);
1925  feature_filters.insert(t, current_filter_ptr);
1926  }
1927  break;
1928  }
1929 
1930  case LETTER_FEATURE_OPT: {
1931  OpenType::Tag t(clp->vstr);
1932  if (!t.valid())
1933  usage_error(errh, "bad feature tag");
1934  else if (feature_filters[t])
1935  usage_error(errh, "feature %<%s%> included twice", t.text().c_str());
1936  else {
1937  interesting_features.push_back(t);
1938  GlyphFilter* gf = new GlyphFilter;
1939  gf->add_substitution_filter("<Letter>", false, errh);
1940  *gf += current_alternate_filter;
1941  feature_filters.insert(t, gf);
1942  }
1943  break;
1944  }
1945 
1946  case SUBS_FILTER_OPT:
1947  current_substitution_filter = null_filter;
1948  /* fallthru */
1949  case EXCLUDE_SUBS_OPT:
1950  case INCLUDE_SUBS_OPT:
1951  current_substitution_filter.add_substitution_filter(clp->vstr, opt == EXCLUDE_SUBS_OPT, errh);
1952  current_filter_ptr = 0;
1953  break;
1954 
1955  case CLEAR_SUBS_OPT:
1956  current_substitution_filter = null_filter;
1957  current_filter_ptr = 0;
1958  break;
1959 
1960  case ENCODING_OPT:
1961  if (encoding_file)
1962  usage_error(errh, "encoding specified twice");
1963  encoding_file = clp->vstr;
1964  have_encoding_file = true;
1965  break;
1966 
1967  case LITERAL_ENCODING_OPT:
1968  if (encoding_file)
1969  usage_error(errh, "encoding specified twice");
1970  encoding_file = clp->vstr;
1971  have_encoding_file = true;
1972  literal_encoding = true;
1973  break;
1974 
1975  case BASE_ENCODINGS_OPT:
1976  base_encoding_files.push_back(clp->vstr);
1977  break;
1978 
1979  case EXTEND_OPT:
1980  if (extend)
1981  usage_error(errh, "extend value specified twice");
1982  extend = clp->val.d;
1983  break;
1984 
1985  case SLANT_OPT:
1986  if (slant)
1987  usage_error(errh, "slant value specified twice");
1988  slant = clp->val.d;
1989  break;
1990 
1991  case LETTERSPACE_OPT:
1992  if (letterspace)
1993  usage_error(errh, "letterspacing value specified twice");
1994  letterspace = clp->val.i;
1995  break;
1996 
1997  case SPACE_FACTOR_OPT:
1998  if (space_factor != 1)
1999  usage_error(errh, "space factor specified twice");
2000  space_factor = clp->val.d;
2001  break;
2002 
2003  case MATH_SPACING_OPT:
2004  math_spacing = !clp->negated;
2005  if (math_spacing && clp->have_val) {
2006  if (clp->val.i < 0 || clp->val.i > 255)
2007  usage_error(errh, "--math-spacing skew character must be between 0 and 255");
2008  skew_char = clp->val.i;
2009  }
2010  break;
2011 
2012  case DESIGN_SIZE_OPT:
2013  if (design_size > 0)
2014  usage_error(errh, "design size value specified twice");
2015  else if (clp->val.d <= 0)
2016  usage_error(errh, "design size must be > 0");
2017  design_size = clp->val.d;
2018  break;
2019 
2020  case LIGKERN_OPT:
2021  ligkern.push_back(clp->vstr);
2022  break;
2023 
2024  case POSITION_OPT:
2025  pos.push_back(clp->vstr);
2026  break;
2027 
2028  case WARN_MISSING_OPT:
2029  warn_missing = !clp->negated;
2030  break;
2031 
2032  case NO_ECOMMAND_OPT:
2033  no_ecommand = true;
2034  break;
2035 
2036  case DEFAULT_LIGKERN_OPT:
2037  default_ligkern = !clp->negated;
2038  break;
2039 
2040  case BOUNDARY_CHAR_OPT:
2041  ligkern.push_back(String("|| = ") + String(clp->val.i));
2042  break;
2043 
2044  case ALTSELECTOR_CHAR_OPT:
2045  ligkern.push_back(String("^^ = ") + String(clp->val.i));
2046  break;
2047 
2048  case ALTSELECTOR_FEATURE_OPT: {
2049  OpenType::Tag t(clp->vstr);
2050  if (!t.valid())
2051  usage_error(errh, "bad feature tag");
2052  else if (altselector_feature_filters[t])
2053  usage_error(errh, "altselector feature %<%s%> included twice", t.text().c_str());
2054  else {
2055  if (!current_filter_ptr) {
2056  current_filter_ptr = new GlyphFilter(current_substitution_filter + current_alternate_filter);
2057  allocated_filters.push_back(current_filter_ptr);
2058  }
2059  altselector_features.push_back(t);
2060  altselector_feature_filters.insert(t, current_filter_ptr);
2061  }
2062  break;
2063  }
2064 
2065  case ALTERNATES_FILTER_OPT:
2066  current_alternate_filter = null_filter;
2067  /* fallthru */
2070  current_alternate_filter.add_alternate_filter(clp->vstr, opt == EXCLUDE_ALTERNATES_OPT, errh);
2071  current_filter_ptr = 0;
2072  break;
2073 
2074  case CLEAR_ALTERNATES_OPT:
2075  current_alternate_filter = null_filter;
2076  current_filter_ptr = 0;
2077  break;
2078 
2079  case UNICODING_OPT:
2080  unicoding.push_back(clp->vstr);
2081  break;
2082 
2083  case CODINGSCHEME_OPT:
2084  if (codingscheme)
2085  usage_error(errh, "coding scheme specified twice");
2086  codingscheme = clp->vstr;
2087  if (codingscheme.length() > 39)
2088  errh->warning("only first 39 characters of coding scheme are significant");
2089  if (codingscheme.find_left('(') >= 0 || codingscheme.find_left(')') >= 0)
2090  usage_error(errh, "coding scheme cannot contain parentheses");
2091  break;
2092 
2093  case AUTOMATIC_OPT:
2094  automatic = !clp->negated;
2095  break;
2096 
2097  case VENDOR_OPT:
2098  if (!set_vendor(clp->vstr))
2099  usage_error(errh, "vendor name specified twice");
2100  break;
2101 
2102  case TYPEFACE_OPT:
2103  if (!set_typeface(clp->vstr, true))
2104  usage_error(errh, "typeface name specified twice");
2105  break;
2106 
2107  case VIRTUAL_OPT:
2108  if (clp->negated)
2109  output_flags &= ~~G_VMETRICS;
2110  else
2112  specified_output_flags |= G_VMETRICS;
2113  break;
2114 
2115  case NO_ENCODING_OPT:
2116  case NO_TYPE1_OPT:
2117  case NO_DOTLESSJ_OPT:
2118  case NO_UPDMAP_OPT:
2119  case UPDMAP_SYS_OPT:
2120  output_flags &= ~(opt - NO_OUTPUT_OPTS);
2121  specified_output_flags |= opt - NO_OUTPUT_OPTS;
2122  break;
2123 
2124  case TRUETYPE_OPT:
2125  case TYPE42_OPT:
2126  case UPDMAP_USER_OPT:
2127  if (!clp->negated)
2128  output_flags |= (opt - YES_OUTPUT_OPTS);
2129  else
2130  output_flags &= ~(opt - YES_OUTPUT_OPTS);
2131  specified_output_flags |= opt - YES_OUTPUT_OPTS;
2132  break;
2133 
2134  case OUTPUT_ENCODING_OPT:
2135  if (out_encoding_file)
2136  usage_error(errh, "encoding output file specified twice");
2137  out_encoding_file = (clp->have_val ? clp->vstr : "-");
2139  specified_output_flags = -1;
2140  break;
2141 
2142  case MINIMUM_KERN_OPT:
2143  minimum_kern = clp->val.d;
2144  break;
2145 
2146  case MAP_FILE_OPT:
2147  if (clp->negated)
2148  output_flags &= ~~G_PSFONTSMAP;
2149  else {
2151  if (!set_map_file(clp->vstr))
2152  usage_error(errh, "map file specified twice");
2153  }
2154  specified_output_flags |= G_PSFONTSMAP;
2155  break;
2156 
2157  case PL_OPT:
2158  if (clp->negated)
2159  output_flags &= ~~G_ASCII;
2160  else
2161  output_flags |= G_ASCII;
2162  specified_output_flags |= G_ASCII;
2163  break;
2164 
2165  case TFM_OPT:
2166  if (clp->negated)
2167  output_flags &= ~~G_BINARY;
2168  else
2170  specified_output_flags |= G_BINARY;
2171  break;
2172 
2173  case ENCODING_DIR_OPT:
2174  case TFM_DIR_OPT:
2175  case PL_DIR_OPT:
2176  case VF_DIR_OPT:
2177  case VPL_DIR_OPT:
2178  case TYPE1_DIR_OPT:
2179  case TRUETYPE_DIR_OPT:
2180  case TYPE42_DIR_OPT:
2181  case DIR_OPT:
2182  if (!odirs[opt - DIR_OPTS])
2183  odirs[opt - DIR_OPTS] = clp->vstr;
2184  else
2185  usage_error(errh, "%s directory specified twice", odirname(opt - DIR_OPTS));
2186  break;
2187 
2188  case FONT_NAME_OPT:
2189  font_name:
2190  if (font_name)
2191  usage_error(errh, "font name specified twice");
2192  font_name = clp->vstr;
2193  break;
2194 
2195  case FIXED_PITCH_OPT:
2196  override_is_fixed_pitch = true;
2197  is_fixed_pitch = !clp->negated;
2198  break;
2199 
2201  override_is_fixed_pitch = true;
2202  is_fixed_pitch = !!clp->negated;
2203  break;
2204 
2205  case ITALIC_ANGLE_OPT:
2206  override_italic_angle = true;
2207  italic_angle = clp->val.d;
2208  break;
2209 
2210  case GLYPHLIST_OPT:
2211  glyphlist_files.push_back(clp->vstr);
2212  break;
2213 
2214  case QUERY_FEATURES_OPT:
2215  usage_error(errh, "run %<otfinfo --query-features%> instead");
2216  break;
2217 
2218  case QUERY_SCRIPTS_OPT:
2219  usage_error(errh, "run %<otfinfo --query-scripts%> instead");
2220  break;
2221 
2222  case QUIET_OPT:
2223  if (clp->negated)
2225  else
2226  // 9.Nov.05 -- need a new SilentErrorHandler, because we use
2227  // the base SilentErrorHandler elsewhere to ignore errors
2228  errh = new SilentErrorHandler;
2229  break;
2230 
2231  case VERBOSE_OPT:
2232  verbose = !clp->negated;
2233  break;
2234 
2235  case NOCREATE_OPT:
2236  no_create = clp->negated;
2237  break;
2238 
2239  case FORCE_OPT:
2240  force = !clp->negated;
2241  break;
2242 
2243  case KPATHSEA_DEBUG_OPT:
2244 #if HAVE_KPATHSEA
2245  kpsei_set_debug_flags(clp->val.u);
2246 #else
2247  errh->warning("Not compiled with kpathsea!");
2248 #endif
2249  break;
2250 
2251  case X_HEIGHT_OPT: {
2252  char* ends;
2253  if (strcmp(clp->vstr, "auto") == 0)
2255  else if (strcmp(clp->vstr, "x") == 0)
2257  else if (strcmp(clp->vstr, "font") == 0
2258  || strcmp(clp->vstr, "os/2") == 0)
2260  else if ((x_height = strtod(clp->vstr, &ends)) >= 0
2261  && *ends == 0 && *clp->vstr != 0)
2263  else
2264  usage_error(errh, "bad --x-height option");
2265  break;
2266  }
2267 
2268  case VERSION_OPT:
2269  printf("otftotfm (LCDF typetools) %s\n", VERSION);
2270  printf("Copyright (C) 2002-2019 Eddie Kohler\n\
2271 This is free software; see the source for copying conditions.\n\
2272 There is NO warranty, not even for merchantability or fitness for a\n\
2273 particular purpose.\n");
2274  exit(0);
2275  break;
2276 
2277  case HELP_OPT:
2278  usage();
2279  exit(0);
2280  break;
2281 
2282  case Clp_NotOption:
2283  if (input_file && font_name)
2284  usage_error(errh, "too many arguments");
2285  else if (input_file)
2286  goto font_name;
2287  else
2288  input_file = clp->vstr;
2289  break;
2290 
2291  case Clp_Done:
2292  goto done;
2293 
2294  case Clp_BadOption:
2295  usage_error(errh, 0);
2296  break;
2297 
2298  default:
2299  break;
2300 
2301  }
2302  }
2303 
2304  done:
2305  // check for odd option combinations
2306  if (warn_missing > 0 && !(output_flags & G_VMETRICS))
2307  errh->warning("%<--warn-missing%> has no effect with %<--no-virtual%>");
2308  if (!(specified_output_flags & (G_BINARY | G_ASCII)))
2310 
2311  // set up file names
2312  if (!input_file)
2313  usage_error(errh, "no font filename provided");
2314  if (encoding_file == "-")
2315  encoding_file = "";
2316 
2317  // set up output directories
2318  if (odirs[NUMODIR]) {
2319  for (int i = 0; i < NUMODIR; ++i)
2320  if (!odirs[i])
2321  odirs[i] = odirs[NUMODIR];
2322  }
2323  for (int i = 0; i < NUMODIR; ++i)
2324  if (odirs[i])
2325  setodir(i, odirs[i]);
2326 
2327  // set up feature filters
2328  if (!altselector_features.size()) {
2329  if (!current_filter_ptr) {
2330  current_filter_ptr = new GlyphFilter(current_substitution_filter + current_alternate_filter);
2331  allocated_filters.push_back(current_filter_ptr);
2332  }
2333  altselector_features.push_back(OpenType::Tag("dlig"));
2334  altselector_feature_filters.insert(OpenType::Tag("dlig"), current_filter_ptr);
2335  altselector_features.push_back(OpenType::Tag("salt"));
2336  altselector_feature_filters.insert(OpenType::Tag("salt"), current_filter_ptr);
2337  } else if (!current_filter_ptr) {
2338  errh->warning("some filtering options ignored");
2339  errh->message("(--include-*, --exclude-*, and --*-filter options must occur\nbefore the feature options to which they should apply.)");
2340  }
2341 
2342  try {
2343  // read font
2345  if (errh->nerrors())
2346  exit(1);
2347 
2349  BailErrorHandler bail_errh(&cerrh);
2350 
2351  OpenType::Font otf(otf_data, &bail_errh);
2352  assert(otf.ok());
2353 
2354  // figure out scripts we care about
2355  if (!interesting_scripts.size()) {
2356  interesting_scripts.push_back(Efont::OpenType::Tag("latn"));
2358  }
2361 
2362  // find glyphlist
2363  if (!glyphlist_files.size()) {
2364 #if HAVE_KPATHSEA
2365  if (String g = kpsei_find_file("glyphlist.txt", KPSEI_FMT_MAP)) {
2366  glyphlist_files.push_back(g);
2367  if (verbose)
2368  errh->message("glyphlist.txt found with kpathsea at %s", g.c_str());
2369  } else
2370 #endif
2371  glyphlist_files.push_back(GLYPHLISTDIR "/glyphlist.txt");
2372 #if HAVE_KPATHSEA
2373  if (String g = kpsei_find_file("texglyphlist.txt", KPSEI_FMT_MAP)) {
2374  glyphlist_files.push_back(g);
2375  if (verbose)
2376  errh->message("texglyphlist.txt found with kpathsea at %s", g.c_str());
2377  } else
2378 #endif
2379  glyphlist_files.push_back(GLYPHLISTDIR "/texglyphlist.txt");
2380  }
2381 
2382  // read glyphlist
2383  for (String *g = glyphlist_files.begin(); g < glyphlist_files.end(); g++)
2384  if (String s = read_file(*g, errh, true))
2386 
2387  // read base encodings
2388  for (String *s = base_encoding_files.begin(); s < base_encoding_files.end(); s++)
2390 
2391  // read encoding
2392  DvipsEncoding dvipsenc;
2393  if (encoding_file) {
2395  dvipsenc.parse(path, no_ecommand, no_ecommand, errh);
2396  else
2397  errh->fatal("encoding %<%s%> not found", encoding_file.c_str());
2398  } else {
2399  String cff_data(otf.table("CFF"));
2400  if (!cff_data) {
2401  errh->error("explicit encoding required for TrueType fonts");
2402  errh->message("(Use %<-e ENCODING%> to choose an encoding. %<-e texnansx%> often works.)");
2403  exit(1);
2404  } else if (!have_encoding_file) {
2405  errh->warning("no encoding provided");
2406  errh->message("(Use %<-e ENCODING%> to choose an encoding. %<-e texnansx%> often works,\nor say %<-e -%> to turn off this warning.)");
2407  }
2408 
2409  // use encoding from font
2410  Cff cff(cff_data, otf.units_per_em(), &bail_errh);
2411  Cff::FontParent *font = cff.font(PermString(), &bail_errh);
2412  assert(cff.ok() && font->ok());
2413  if (Type1Encoding *t1e = font->type1_encoding()) {
2414  for (int i = 0; i < 256; i++)
2415  dvipsenc.encode(i, (*t1e)[i]);
2416  } else
2417  errh->fatal("font has no encoding, specify one explicitly");
2418  }
2419 
2420  // apply default ligkern commands
2421  if (default_ligkern)
2423 
2424  // apply command-line ligkern commands and coding scheme
2425  cerrh.set_landmark("--ligkern command");
2426  for (int i = 0; i < ligkern.size(); i++)
2427  dvipsenc.parse_ligkern(ligkern[i], 1, &cerrh);
2428  cerrh.set_landmark("--position command");
2429  for (int i = 0; i < pos.size(); i++)
2430  dvipsenc.parse_position(pos[i], 1, &cerrh);
2431  cerrh.set_landmark("--unicoding command");
2432  for (int i = 0; i < unicoding.size(); i++)
2433  dvipsenc.parse_unicoding(unicoding[i], 1, &cerrh);
2434  if (codingscheme)
2435  dvipsenc.set_coding_scheme(codingscheme);
2436  if (warn_missing >= 0)
2437  dvipsenc.set_warn_missing(warn_missing);
2438 
2439  do_file(input_file, otf, dvipsenc, literal_encoding, errh);
2440 
2441  } catch (OpenType::Error e) {
2442  errh->error("unhandled exception %<%s%>", e.description.c_str());
2443  }
2444 
2445  for (int i = 0; i < allocated_filters.size(); ++i)
2446  delete allocated_filters[i];
2447  Clp_DeleteParser(clp);
2448  return (errh->nerrors() == 0 ? 0 : 1);
2449 }
double __cdecl strtod(char const *_String, char **_EndPtr)
long __cdecl strtol(char const *_String, char **_EndPtr, int _Radix)
double __cdecl tan(double _X)
static int pr(int(*writeFunc)(void *stream, const char *data, int size), void *stream, const char *data)
Definition: HTMLGen.cc:249
long * ligkern
Definition: afm2tfm.c:1033
static int lineno
Definition: aftopl.c:19
#define kern
Definition: aptex-macros.h:386
#define width(a)
Definition: aptex-macros.h:198
#define name
#define w1
#define before
Definition: aptex-macros.h:256
static alpha_file read_file[16]
Definition: aptex.h:454
const char * odirname(int o)
Definition: automatic.cc:269
int update_autofont_map(const String &fontname, String mapline, ErrorHandler *errh)
Definition: automatic.cc:595
bool set_map_file(const String &s)
Definition: automatic.cc:365
String locate_encoding(String encfile, ErrorHandler *errh, bool literal)
Definition: automatic.cc:790
bool set_typeface(const String &s, bool override)
Definition: automatic.cc:176
String installed_truetype(const String &ttf_filename, bool allow_generate, ErrorHandler *errh)
Definition: automatic.cc:491
void update_odir(int o, String file, ErrorHandler *errh)
Definition: automatic.cc:291
String getodir(int o, ErrorHandler *errh)
Definition: automatic.cc:185
static String typeface
Definition: automatic.cc:66
String installed_type42(const String &ttf_filename, const String &ps_fontname, bool allow_generate, ErrorHandler *errh)
Definition: automatic.cc:542
bool set_vendor(const String &s)
Definition: automatic.cc:168
void setodir(int o, const String &value)
Definition: automatic.cc:262
String installed_type1(const String &otf_filename, const String &ps_fontname, bool allow_generate, ErrorHandler *errh)
Definition: automatic.cc:373
@ O_VPL
Definition: automatic.hh:7
@ O_ENCODING
Definition: automatic.hh:7
@ O_VF
Definition: automatic.hh:7
@ NUMODIR
Definition: automatic.hh:8
@ O_TFM
Definition: automatic.hh:7
@ O_PL
Definition: automatic.hh:7
#define bool
Definition: autosp.c:101
#define banner
Definition: bg5conv.c:1
short pos1(char c, char *s)
Definition: cfuncs.c:30
A stackable ErrorHandler that exits when errors occur.
Definition: error.hh:857
int parse_ligkern(const String &ligkern_text, int override, ErrorHandler *)
void apply_ligkern_kern(Metrics &, ErrorHandler *) const
void set_coding_scheme(const String &s)
const String & name() const
void apply_position(Metrics &, ErrorHandler *) const
void make_metrics(Metrics &, const FontInfo &, Secondary *, bool literal, ErrorHandler *)
int parse_position(const String &ligkern_text, int override, ErrorHandler *)
const String & filename() const
static void add_glyphlist(String)
void set_warn_missing(bool wm)
int boundary_char() const
int parse(String filename, bool ignore_ligkern, bool ignore_other, ErrorHandler *)
int parse_unicoding(const String &unicoding_text, int override, ErrorHandler *)
void apply_ligkern_lig(Metrics &, ErrorHandler *) const
void encode(int, PermString)
bool char_bounds(const CharstringContext &, bool shift=true)
Definition: t1bounds.cc:108
void mark(const Point &)
Definition: t1bounds.hh:75
void translate(double dx, double dy)
Definition: t1bounds.cc:121
Point transform(const Point &p) const
Definition: t1bounds.hh:90
bool output(double bb[4], double &width, bool use_cur_width=false) const
Definition: t1bounds.cc:128
static uint16_t u16(const unsigned char *s)
Definition: otfdata.hh:116
int length() const
Definition: otfdata.hh:73
String size_params(int fid, const Name &name, ErrorHandler *=0) const
Definition: otf.cc:573
int find(Tag, const Vector< int > &fids) const
Definition: otf.cc:611
unsigned units_per_em() const
Definition: otf.hh:62
String table(Tag tag) const
Definition: otf.cc:121
bool ok() const
Definition: otf.hh:54
const ScriptList & script_list() const
Definition: otfgpos.hh:15
GposLookup lookup(unsigned) const
Definition: otfgpos.cc:59
int nlookups() const
Definition: otfgpos.cc:53
const FeatureList & feature_list() const
Definition: otfgpos.hh:16
const FeatureList & feature_list() const
Definition: otfgsub.hh:16
const ScriptList & script_list() const
Definition: otfgsub.hh:15
int nlookups() const
Definition: otfgsub.cc:598
GsubLookup lookup(unsigned) const
Definition: otfgsub.cc:604
int features(Tag script, Tag langsys, int &required_fid, Vector< int > &fids, ErrorHandler *=0, bool clear_fids=true) const
Definition: otf.cc:474
uint32_t value() const
Definition: otf.hh:30
bool valid() const
Definition: otf.cc:305
Error reporting class.
Definition: error.hh:86
int error(const char *fmt,...)
Print an error message (level el_error).
Definition: error.cc:818
int nerrors() const
Return the number of errors reported via this handler.
Definition: error.hh:282
int xmessage(const String &str)
Print an annotated error message.
Definition: error.cc:891
static const char e_error[]
Definition: error.hh:115
static ErrorHandler * static_initialize(ErrorHandler *errh)
Initialize the ErrorHandler implementation.
Definition: error.cc:1019
int warning(const char *fmt,...)
Print a warning message (level el_warning).
Definition: error.cc:808
static ErrorHandler * silent_handler()
Return the global silent ErrorHandler.
Definition: error.hh:167
void message(const char *fmt,...)
Print an informational message (level el_info).
Definition: error.cc:799
void fatal(const char *fmt,...)
Print a fatal error message (level el_fatal).
Definition: error.cc:828
String format(const char *fmt,...)
Format an error string.
Definition: error.cc:777
static ErrorHandler * default_handler()
Return the default ErrorHandler.
Definition: error.hh:155
An ErrorHandler that prints error messages to a given file.
Definition: error.hh:640
int units_per_em() const
Definition: secondary.hh:31
int nglyphs() const
Definition: secondary.hh:27
bool glyph_names(Vector< PermString > &) const
Definition: secondary.cc:141
bool is_fixed_pitch() const
Definition: secondary.cc:195
bool ok() const
Definition: secondary.cc:132
@ x_height_os2
Definition: secondary.hh:48
@ x_height_x
Definition: secondary.hh:48
@ x_height_auto
Definition: secondary.hh:47
@ x_height_explicit
Definition: secondary.hh:47
double italic_angle() const
Definition: secondary.cc:207
void set_x_height(int source, double x_height)
Definition: secondary.hh:49
const Efont::Cff::Font * cff
Definition: secondary.hh:17
String family_name() const
Definition: secondary.cc:165
String postscript_name() const
Definition: secondary.cc:174
const Efont::CharstringProgram * program() const
Definition: secondary.cc:183
double x_height(const Transform &font_xform) const
Definition: secondary.cc:219
const Efont::OpenType::Font * otf
Definition: secondary.hh:13
void set_is_fixed_pitch(bool is_fixed_pitch)
Definition: secondary.hh:39
void set_italic_angle(double italic_angle)
Definition: secondary.hh:43
void add_substitution_filter(const String &, bool is_exclude, ErrorHandler *)
Definition: glyphfilter.cc:161
void add_alternate_filter(const String &, bool is_exclude, ErrorHandler *)
Definition: glyphfilter.cc:167
V & find_force(const K &, const V &)
Definition: hashmap.cc:124
A stackable ErrorHandler that adds a default landmark to error messages.
Definition: error.hh:830
void set_landmark(const String &landmark)
Set the default landmark applied to error messages.
Definition: error.hh:838
uint32_t tag
Definition: otfdescrip.cc:20
int Code
Definition: metrics.hh:12
Efont::OpenType::Glyph Glyph
Definition: metrics.hh:13
An ErrorHandler that does not report messages.
Definition: error.hh:592
Efficiently build up Strings from pieces.
Definition: straccum.hh:21
void adjust_length(int delta)
Adjust the StringAccum's length.
Definition: straccum.hh:416
const char * data() const
Return the contents of the StringAccum.
Definition: straccum.hh:249
String take_string()
Return a String object with this StringAccum's contents.
Definition: straccum.cc:197
int length() const
Return the length of the StringAccum.
Definition: straccum.hh:272
const char * c_str()
Null-terminate this StringAccum and return its data.
Definition: straccum.cc:122
void append_break_lines(const String &text, int linelen, const String &leftmargin=String())
Definition: straccum.cc:280
void clear()
Clear the StringAccum's comments.
Definition: straccum.hh:371
void append(char c)
Append character c to the StringAccum.
Definition: straccum.hh:451
char * reserve(int n)
Reserve space for at least n characters.
Definition: straccum.hh:391
void scale(double, double)
Definition: transform.cc:63
void shear(double)
Definition: transform.cc:111
Definition: vector.hh:17
void clear()
Definition: vector.hh:87
iterator begin()
Definition: vector.hh:48
Vector< T > & assign(size_type n, const T &e=T())
Definition: vector.cc:65
void push_back(const T &x)
Definition: vector.hh:102
size_type size() const
Definition: vector.hh:54
const T * const_iterator
Definition: vector.hh:30
iterator end()
Definition: vector.hh:50
Definition: Endian.h:47
#define strrchr
Definition: detex.c:67
void glyphs(int opcode)
Definition: disdvi.c:775
const char * program
Definition: dv2dt.c:152
#define R_OK
Definition: defs.h:31
int command
Definition: t4ht.c:934
#define fopen
Definition: xxstdio.h:21
#define fread
Definition: xxstdio.h:25
int strcmp()
Definition: coll.cpp:143
int printf()
int program_number
Flexible error handling classes.
const FcChar8 lang[6]
Definition: fcfreetype.c:56
int fcntl(int fd, int action,...)
Definition: fcntl.c:202
static void
Definition: fpif.c:118
mpz_t * f
Definition: gen-fib.c:34
#define s
Definition: afcover.h:80
#define t
Definition: afcover.h:96
#define w3
#define w2
static FIELD_PTR begin
Definition: genind.c:37
@ VERSION
Definition: genrb.cpp:69
#define dot
Definition: globals.h:56
__gmp_expr< mpf_t, __gmp_unary_expr< __gmp_expr< mpf_t, U >, __gmp_ceil_function > > ceil(const __gmp_expr< mpf_t, U > &expr)
Definition: gmpxx.h:3340
#define c(n)
Definition: gpos-common.c:150
#define a(n)
Definition: gpos-common.c:148
#define d(n)
Definition: gpos-common.c:151
#define SIGCHLD
Definition: gsftopk.c:143
int base
Definition: gsftopk.c:1502
#define strchr
Definition: gsftopk.c:59
#define memcmp(s1, s2, n)
Definition: gsftopk.c:66
#define memmove(d, s, n)
Definition: gsftopk.c:65
fix design_units
int computed
Definition: hints.c:77
assert(pcxLoadImage24((char *)((void *) 0), fp, pinfo, hdr))
char * kpsei_find_file(const char *name, int format)
Definition: kpseinterface.c:56
void kpsei_init(const char *argv0, const char *progname)
Definition: kpseinterface.c:32
void kpsei_set_debug_flags(unsigned flags)
Definition: kpseinterface.c:88
@ KPSEI_FMT_MAP
Definition: kpseinterface.h:11
#define SEEK_SET
Definition: jmemansi.c:26
char String
Definition: tttypes.h:35
small capitals from c petite p
Definition: afcover.h:72
small capitals from c petite p scientific i
Definition: afcover.h:80
xD9 x84 xD8 xAD xD9 x80 xF0 x90 xAC x9A xE0 xA7 xA6 xE0 xA7 xAA xF0 x91 x84 xA4 xF0 x91 x84 x89 xF0 x91 x84 x9B xF0 x90 x8A xAB xF0 x90 x8B x89 xE2 xB2 x9E xE2 xB2 x9F xD0 xBE xD0 x9E xF0 x90 x90 x84 xF0 x90 x90 xAC xE1 x83 x98 xE1 x83 x94 xE1 x83 x90 xE1 xB2 xBF xE2 xB0 x95 xE2 xB1 x85 xCE xBF xCE x9F xE0 xA8 xA0 xE0 xA8 xB0 xE0 xA9 xA6 Kayah xEA xA4 x8D xEA xA4 x80 Khmer xE1 xA7 xA1 xE1 xA7 xAA xE0 xBB x90 Latin Subscript xE2 x82 x92 xE2 x82 x80 xEA x93 xB3 xF0 x96 xB9 xA1 xF0 x96 xB9 x9B xF0 x96 xB9 xAF xE1 x80 x9D xE1 x80 x84 xE1 x80 x82 no script
Definition: afscript.h:271
CFF_Font cff
Definition: cffdrivr.c:701
void exit()
#define false
Definition: ftrandom.c:52
kerning y
Definition: ttdriver.c:212
T1_FIELD_DICT_FONTDICT family_name
Definition: t1tokens.h:30
unsigned int uint32_t
Definition: stdint.h:80
png_uint_32 md5[4]
Definition: png.c:2248
int errno
#define unlink(file)
Definition: config.h:413
#define HAVE_KPATHSEA
Definition: config.h:27
#define buf
@ render
Definition: spc_dvips.c:728
char * strstr()
#define fclose
Definition: debug.h:100
static int find(DIR *dp, char *name)
Definition: dirent.c:25
#define access
Definition: win32lib.h:59
#define O_CREAT
Definition: win32lib.h:170
#define fileno
Definition: win32lib.h:72
#define pclose(file)
Definition: win32lib.h:271
#define open
Definition: win32lib.h:86
#define close
Definition: win32lib.h:63
#define O_RDWR
Definition: win32lib.h:167
#define fprintf
Definition: mendex.h:64
#define Error
Definition: type1.c:126
#define transform(xusr, yusr, xdev, ydev)
Definition: type1.c:1420
static char * strerror(int errnum)
Definition: error.c:56
#define fabs(x)
Definition: cpascal.h:211
#define floor(x)
Definition: cpascal.h:52
#define error_message
Definition: ctangleboot.c:74
Code related to b fwrite(a, sizeof(char), b, stdout) @d C_printf(c
void md5_init(md5_state_t *pms)
Definition: md5.c:313
long time_t
Definition: types.h:18
#define sprintf
Definition: snprintf.c:44
#define isdigit(c)
Definition: snprintf.c:177
Clp_Parser * Clp_NewParser(int argc, const char *const *argv, int nopt, const Clp_Option *opt)
Create a new Clp_Parser.
Definition: clp.c:502
int Clp_OptionError(Clp_Parser *clp, const char *format,...)
Report a parser error.
Definition: clp.c:2279
int Clp_AddType(Clp_Parser *clp, int val_type, int flags, Clp_ValParseFunc parser, void *user_data)
Define a new value type for clp.
Definition: clp.c:1042
int Clp_Next(Clp_Parser *clp)
Parse and return the next argument from clp.
Definition: clp.c:1850
void Clp_DeleteParser(Clp_Parser *clp)
Destroy a Clp_Parser object.
Definition: clp.c:578
const char * Clp_ProgramName(Clp_Parser *clp)
Return clp's program name.
Definition: clp.c:1420
#define Clp_Negate
Option flag: option may be negated.
Definition: clp.h:139
#define Clp_BadOption
Clp_Next value: argument was an erroneous option.
Definition: clp.h:197
#define Clp_NotOption
Clp_Next value: argument was not an option.
Definition: clp.h:191
#define Clp_PreferredMatch
Option flag: prefer this option when matching.
Definition: clp.h:157
#define Clp_ValString
Option value is an arbitrary string.
Definition: clp.h:59
#define Clp_ValDouble
Option value is a double. Accepts a real number as defined by strtod().
Definition: clp.h:110
#define Clp_Optional
Option flag: value is optional.
Definition: clp.h:136
#define Clp_Done
Clp_Next value: there are no more arguments.
Definition: clp.h:194
#define Clp_ValInt
Option value is a signed int.
Definition: clp.h:78
const int * pos
Definition: combiners.h:905
hb_tag_t Tag
Definition: luaharfbuzz.h:17
#define boundary_char
Definition: mfluac.c:354
Vector< PermString > debug_glyph_names
Definition: otf.cc:32
float x
Definition: cordic.py:15
string fn
Definition: fc-lang.py:335
Definition: tfm.py:1
union value value
Definition: obx.h:44
static const Mapping features[]
Definition: otfdescrip.cc:537
String printable_filename(const String &s)
Definition: otfinfo.cc:179
String shell_quote(const String &str)
Definition: util.cc:104
int temporary_file(String &filename, ErrorHandler *errh)
Definition: util.cc:192
FILE * mypopen(const char *command, const char *type, ErrorHandler *errh)
Definition: util.cc:166
String pathname_filename(const String &path)
Definition: util.cc:77
void ignore_result(T result)
Definition: util.hh:33
@ G_TYPE1
Definition: util.hh:12
@ G_BINARY
Definition: util.hh:13
@ G_UPDMAP
Definition: util.hh:14
@ G_ASCII
Definition: util.hh:13
@ G_METRICS
Definition: util.hh:12
@ G_PSFONTSMAP
Definition: util.hh:13
@ G_TYPE42
Definition: util.hh:14
@ G_DOTLESSJ
Definition: util.hh:13
@ G_ENCODING
Definition: util.hh:12
@ G_VMETRICS
Definition: util.hh:12
@ G_TRUETYPE
Definition: util.hh:14
#define INCLUDE_SUBS_OPT
Definition: otftotfm.cc:99
#define HELP_OPT
Definition: otftotfm.cc:73
#define DEFAULT_LIGKERN_OPT
Definition: otftotfm.cc:96
static PermString::Initializer perm_initializer
Definition: otftotfm.cc:264
#define EXCLUDE_SUBS_OPT
Definition: otftotfm.cc:100
static String make_base_font_name(const String &font_name)
Definition: otftotfm.cc:472
static String encoding_file
Definition: otftotfm.cc:275
#define LETTER_FEATURE_OPT
Definition: otftotfm.cc:98
static double get_design_size(const FontInfo &finfo)
Definition: otftotfm.cc:478
static const char *const default_ligkerns
Definition: otftotfm.cc:246
int main(int argc, char *argv[])
Definition: otftotfm.cc:1845
void output_metrics(Metrics &metrics, const String &ps_name, int boundary_char, const FontInfo &finfo, const String &encoding_name, const String &encoding_file, const String &font_name, String(*dvips_include)(const String &ps_name, const FontInfo &, ErrorHandler *), ErrorHandler *errh)
Definition: otftotfm.cc:1238
#define FEATURE_OPT
Definition: otftotfm.cc:79
#define UNICODING_OPT
Definition: otftotfm.cc:87
#define FORCE_OPT
Definition: otftotfm.cc:122
#define PROPORTIONAL_WIDTH_OPT
Definition: otftotfm.cc:111
#define X_HEIGHT_OPT
Definition: otftotfm.cc:112
#define TYPE42_DIR_OPT
Definition: otftotfm.cc:137
#define KPATHSEA_DEBUG_OPT
Definition: otftotfm.cc:76
static void do_file(const String &otf_filename, const OpenType::Font &otf, const DvipsEncoding &dvipsenc_in, bool dvipsenc_literal, ErrorHandler *errh)
Definition: otftotfm.cc:1589
static bool override_is_fixed_pitch
Definition: otftotfm.cc:285
static String otf_filename
Definition: otftotfm.cc:1391
static const char *const digit_names[]
Definition: otftotfm.cc:518
static double slant
Definition: otftotfm.cc:278
bool no_create
Definition: otftotfm.cc:299
static void output_tfm(Metrics &metrics, const String &ps_name, int boundary_char, const FontInfo &finfo, String tfm_filename, String vf_filename, String pl_filename, ErrorHandler *errh)
Definition: otftotfm.cc:1160
#define YES_OUTPUT_OPTS
Definition: otftotfm.cc:148
void usage()
Definition: otftotfm.cc:320
#define DIR_OPTS
Definition: otftotfm.cc:130
#define BOUNDARY_CHAR_OPT
Definition: otftotfm.cc:88
#define BASE_ENCODINGS_OPT
Definition: otftotfm.cc:108
unsigned output_flags
Definition: otftotfm.cc:295
static int override_x_height
Definition: otftotfm.cc:289
static double space_factor
Definition: otftotfm.cc:282
#define TRUETYPE_DIR_OPT
Definition: otftotfm.cc:138
#define TRUETYPE_OPT
Definition: otftotfm.cc:149
static double extend
Definition: otftotfm.cc:277
static double italic_angle
Definition: otftotfm.cc:288
#define MAP_FILE_OPT
Definition: otftotfm.cc:127
#define QUIET_OPT
Definition: otftotfm.cc:116
static double max_printed_real
Definition: otftotfm.cc:528
static void do_math_spacing(Metrics &metrics, const FontInfo &finfo, const DvipsEncoding &dvipsenc)
Definition: otftotfm.cc:1554
static int skew_char
Definition: otftotfm.cc:284
static bool override_italic_angle
Definition: otftotfm.cc:287
bool force
Definition: otftotfm.cc:301
#define QUERY_FEATURES_OPT
Definition: otftotfm.cc:75
#define POSITION_OPT
Definition: otftotfm.cc:106
static void sigchld_handler(int s)
Definition: otftotfm.cc:422
#define FIXED_PITCH_OPT
Definition: otftotfm.cc:109
#define VPL_DIR_OPT
Definition: otftotfm.cc:135
#define NO_OUTPUT_OPTS
Definition: otftotfm.cc:141
#define EXCLUDE_ALTERNATES_OPT
Definition: otftotfm.cc:93
#define CHAR_OPTTYPE
Definition: otftotfm.cc:153
#define NO_TYPE1_OPT
Definition: otftotfm.cc:143
@ X_GSUB_PART
Definition: otftotfm.cc:1331
@ F_GPOS_ALL
Definition: otftotfm.cc:1329
@ X_GPOS_NONE
Definition: otftotfm.cc:1331
@ X_GSUB_NONE
Definition: otftotfm.cc:1330
@ X_GPOS_PART
Definition: otftotfm.cc:1331
@ F_GSUB_ALL
Definition: otftotfm.cc:1328
@ X_UNUSED
Definition: otftotfm.cc:1330
@ F_GPOS_PART
Definition: otftotfm.cc:1329
@ X_COUNT
Definition: otftotfm.cc:1331
@ F_GSUB_PART
Definition: otftotfm.cc:1328
@ X_BOTH_NONE
Definition: otftotfm.cc:1330
@ F_GPOS_TRY
Definition: otftotfm.cc:1329
@ F_GSUB_TRY
Definition: otftotfm.cc:1328
#define VF_DIR_OPT
Definition: otftotfm.cc:134
#define VERBOSE_OPT
Definition: otftotfm.cc:121
static void do_gsub(Metrics &metrics, const OpenType::Font &otf, DvipsEncoding &dvipsenc, bool dvipsenc_literal, HashMap< uint32_t, int > &feature_usage, const Vector< PermString > &glyph_names, ErrorHandler *errh)
Definition: otftotfm.cc:1411
#define WARN_MISSING_OPT
Definition: otftotfm.cc:107
#define SPACE_FACTOR_OPT
Definition: otftotfm.cc:104
static double design_size
Definition: otftotfm.cc:280
static String main_dvips_map(const String &ps_name, const FontInfo &finfo, ErrorHandler *errh)
Definition: otftotfm.cc:1394
static void handle_sigchld()
Definition: otftotfm.cc:433
static int clp_parse_char(Clp_Parser *clp, const char *arg, int complain, void *)
Definition: otftotfm.cc:1770
static const char * lig_context_str(int ctx)
Definition: otftotfm.cc:523
static bool kern_feature_requested()
Definition: otftotfm.cc:1492
static PermString dot_notdef(".notdef")
#define QUERY_SCRIPTS_OPT
Definition: otftotfm.cc:74
#define UPDMAP_SYS_OPT
Definition: otftotfm.cc:146
#define CLEAR_ALTERNATES_OPT
Definition: otftotfm.cc:94
String suffix_font_name(const String &font_name, const String &suffix)
Definition: otftotfm.cc:456
#define DESIGN_SIZE_OPT
Definition: otftotfm.cc:89
#define CODINGSCHEME_OPT
Definition: otftotfm.cc:86
#define TYPEFACE_OPT
Definition: otftotfm.cc:119
#define UPDMAP_USER_OPT
Definition: otftotfm.cc:151
static const char *const x_messages[]
Definition: otftotfm.cc:1333
static String otf_data
Definition: otftotfm.cc:303
#define GLYPHLIST_OPT
Definition: otftotfm.cc:117
#define PL_DIR_OPT
Definition: otftotfm.cc:133
static GlyphFilter null_filter
Definition: otftotfm.cc:270
#define TYPE42_OPT
Definition: otftotfm.cc:150
#define ENCODING_DIR_OPT
Definition: otftotfm.cc:131
#define LIGKERN_OPT
Definition: otftotfm.cc:85
#define NOCREATE_OPT
Definition: otftotfm.cc:120
static bool is_fixed_pitch
Definition: otftotfm.cc:286
#define NO_ECOMMAND_OPT
Definition: otftotfm.cc:97
#define CLEAR_SUBS_OPT
Definition: otftotfm.cc:101
#define AUTOMATIC_OPT
Definition: otftotfm.cc:114
static String out_encoding_name
Definition: otftotfm.cc:293
static String current_time
Definition: otftotfm.cc:261
#define SCRIPT_OPT
Definition: otftotfm.cc:78
#define MATH_SPACING_OPT
Definition: otftotfm.cc:105
static void output_pl(Metrics &metrics, const String &ps_name, int boundary_char, const FontInfo &finfo, bool vpl, const String &filename, ErrorHandler *errh)
Definition: otftotfm.cc:584
#define ITALIC_ANGLE_OPT
Definition: otftotfm.cc:110
static HashMap< Efont::OpenType::Tag, GlyphFilter * > altselector_feature_filters(0)
#define VIRTUAL_OPT
Definition: otftotfm.cc:124
#define SLANT_OPT
Definition: otftotfm.cc:83
#define TYPE1_DIR_OPT
Definition: otftotfm.cc:136
static int write_encoding_file(String &filename, const String &encoding_name, StringAccum &contents, ErrorHandler *errh)
Definition: otftotfm.cc:979
static bool math_spacing
Definition: otftotfm.cc:283
static HashMap< Efont::OpenType::Tag, GlyphFilter * > feature_filters(0)
#define LITERAL_ENCODING_OPT
Definition: otftotfm.cc:81
#define TFM_OPT
Definition: otftotfm.cc:126
static Vector< Efont::OpenType::Tag > interesting_features
Definition: otftotfm.cc:268
#define EXTEND_OPT
Definition: otftotfm.cc:82
#define VERSION_OPT
Definition: otftotfm.cc:72
#define FONT_NAME_OPT
Definition: otftotfm.cc:115
#define NO_ENCODING_OPT
Definition: otftotfm.cc:142
bool verbose
Definition: otftotfm.cc:298
double font_slant(const FontInfo &finfo)
Definition: otftotfm.cc:577
#define SUBS_FILTER_OPT
Definition: otftotfm.cc:102
static double x_height
Definition: otftotfm.cc:290
static void do_try_ttf_kern(Metrics &metrics, const OpenType::Font &otf, HashMap< uint32_t, int > &feature_usage, ErrorHandler *errh)
Definition: otftotfm.cc:1499
#define ENCODING_OPT
Definition: otftotfm.cc:80
#define NO_UPDMAP_OPT
Definition: otftotfm.cc:145
static double minimum_kern
Definition: otftotfm.cc:281
static Vector< Efont::OpenType::Tag > altselector_features
Definition: otftotfm.cc:269
#define NO_DOTLESSJ_OPT
Definition: otftotfm.cc:144
#define DIR_OPT
Definition: otftotfm.cc:139
static Vector< Efont::OpenType::Tag > interesting_scripts
Definition: otftotfm.cc:267
int letterspace
Definition: otftotfm.cc:279
#define ALTERNATES_FILTER_OPT
Definition: otftotfm.cc:103
static void parse_base_encodings(const String &filename, ErrorHandler *errh)
Definition: otftotfm.cc:1788
#define ALTSELECTOR_FEATURE_OPT
Definition: otftotfm.cc:95
static bool output_encoding(const Metrics &metrics, const Vector< PermString > &glyph_names, ErrorHandler *errh)
Definition: otftotfm.cc:1069
static StringAccum invocation
Definition: otftotfm.cc:262
String installed_metrics_font_name(const String &base_font_name, const String &secondary)
Definition: otftotfm.cc:1759
#define LETTERSPACE_OPT
Definition: otftotfm.cc:84
static void do_gpos(Metrics &metrics, const OpenType::Font &otf, HashMap< uint32_t, int > &feature_usage, ErrorHandler *errh)
Definition: otftotfm.cc:1521
#define INCLUDE_ALTERNATES_OPT
Definition: otftotfm.cc:92
#define MINIMUM_KERN_OPT
Definition: otftotfm.cc:90
static String font_name
Definition: otftotfm.cc:274
bool quiet
Definition: otftotfm.cc:300
static const char * program_name
Definition: otftotfm.cc:260
#define M_PI
Definition: otftotfm.cc:55
static String out_encoding_file
Definition: otftotfm.cc:292
void usage_error(ErrorHandler *errh, const char *error_message,...)
Definition: otftotfm.cc:307
bool automatic
Definition: otftotfm.cc:297
#define ALTSELECTOR_CHAR_OPT
Definition: otftotfm.cc:91
static Vector< BaseEncoding * > base_encodings
Definition: otftotfm.cc:276
#define VENDOR_OPT
Definition: otftotfm.cc:118
static void find_lookups(const OpenType::ScriptList &scripts, const OpenType::FeatureList &features, Vector< Lookup > &lookups, ErrorHandler *errh)
Definition: otftotfm.cc:930
static void report_underused_features(const HashMap< uint32_t, int > &feature_usage, ErrorHandler *errh)
Definition: otftotfm.cc:1343
#define PL_OPT
Definition: otftotfm.cc:125
#define OUTPUT_ENCODING_OPT
Definition: otftotfm.cc:128
#define TFM_DIR_OPT
Definition: otftotfm.cc:132
int k
Definition: otp-parser.c:70
#define max(a, b)
Definition: pbmto4425.c:11
#define print(s)
Definition: pbmtoln03.c:48
char * filename[256]
Definition: pbmtopk.c:46
char * codingscheme
Definition: pbmtopk.c:64
void results()
set set set set set set set macro pixldst1 abits if abits op else op endif endm macro pixldst2 abits if abits op else op endif endm macro pixldst4 abits if abits op else op endif endm macro pixldst0 abits op endm macro pixldst3 mem_operand op endm macro pixldst30 mem_operand op endm macro pixldst abits if abits elseif abits elseif abits elseif abits elseif abits pixldst0 abits else pixldst0 abits pixldst0 abits pixldst0 abits pixldst0 abits endif elseif abits else pixldst0 abits pixldst0 abits endif elseif abits else error unsupported bpp *numpix else pixst endif endm macro pixld1_s mem_operand if asr adds SRC_WIDTH_FIXED bpl add asl mov asr adds SRC_WIDTH_FIXED bpl add asl mov asr adds SRC_WIDTH_FIXED bpl add asl mov asr adds SRC_WIDTH_FIXED bpl add asl elseif asr adds SRC_WIDTH_FIXED bpl add asl mov asr adds SRC_WIDTH_FIXED bpl add asl else error unsupported endif endm macro pixld2_s mem_operand if mov asr add asl add asl mov asr sub UNIT_X add asl mov asr add asl add asl mov asr add UNIT_X add asl else pixld1_s mem_operand pixld1_s mem_operand endif endm macro pixld0_s mem_operand if asr adds SRC_WIDTH_FIXED bpl add asl elseif asr adds SRC_WIDTH_FIXED bpl add asl endif endm macro pixld_s_internal mem_operand if mem_operand pixld2_s mem_operand pixdeinterleave basereg elseif mem_operand elseif mem_operand elseif mem_operand elseif mem_operand pixld0_s mem_operand else pixld0_s mem_operand pixld0_s mem_operand pixld0_s mem_operand pixld0_s mem_operand endif elseif mem_operand else pixld0_s mem_operand pixld0_s mem_operand endif elseif mem_operand else error unsupported mem_operand if bpp mem_operand endif endm macro vuzp8 reg2 vuzp d d &reg2 endm macro vzip8 reg2 vzip d d &reg2 endm macro pixdeinterleave basereg basereg basereg basereg basereg endif endm macro pixinterleave basereg basereg basereg basereg basereg endif endm macro PF boost_increment endif if endif PF tst PF addne PF subne PF cmp ORIG_W if endif if endif if endif PF subge ORIG_W PF subges if endif if endif if endif endif endm macro cache_preload_simple endif if dst_r_bpp pld[DST_R, #(PREFETCH_DISTANCE_SIMPLE *dst_r_bpp/8)] endif if mask_bpp pld endif[MASK, #(PREFETCH_DISTANCE_SIMPLE *mask_bpp/8)] endif endif endm macro fetch_mask_pixblock pixld mask_basereg pixblock_size MASK endm macro ensure_destination_ptr_alignment process_pixblock_tail_head if beq irp skip1 beq endif SRC MASK if dst_r_bpp DST_R else add endif PF add sub src_basereg pixdeinterleave mask_basereg pixdeinterleave dst_r_basereg process_pixblock_head pixblock_size cache_preload_simple process_pixblock_tail pixinterleave dst_w_basereg irp beq endif process_pixblock_tail_head tst beq irp if pixblock_size chunk_size tst beq pixld_src SRC pixld MASK if DST_R else pixld DST_R endif if
const char * suffix
Definition: pkg_icu.cpp:27
static int filter
Definition: pnmtopng.c:113
static int size
Definition: ppmlabel.c:24
int g
Definition: ppmqvga.c:68
bstring c int memset(void *s, int c, int length)
static char * bg
Definition: pscolor.c:51
static char * hexdig
Definition: pstype1.c:127
time_t time()
char * ctime()
#define status
static char sep[2]
Definition: pdftoppm.cc:115
#define isspace(ch)
Definition: utype.h:87
#define isalnum(ch)
Definition: utype.h:84
#define GLYPHLISTDIR
Definition: config.h:184
void md5_update(MD5_CONTEXT *hd, const unsigned char *inbuf, size_t inlen)
Definition: md5.c:228
void md5_final_text(char *text_digest, MD5_CONTEXT *ctx)
Definition: md5.c:338
#define MD5_TEXT_DIGEST_SIZE
Definition: md5.h:30
static ErrorHandler * errh
Definition: main.cc:71
static int sort(lua_State *L)
Definition: ltablib.c:411
#define subs(p, n, t)
Definition: interp.c:107
FILE * fdopen(int, const char *)
static void complain(struct file *file)
Definition: remake.c:362
bool char_bounds(double bounds[4], double &width, const FontInfo &finfo, const Transform &transform, uint32_t uni)
Definition: secondary.cc:655
static UMutex lock
Definition: serv.cpp:336
#define str(s)
Definition: sh6.c:399
ShellFileEnvironment e
Definition: sh6.c:388
Click's StringAccum class, used to construct Strings efficiently from pieces.
DvipsEncoding encoding
Definition: otftotfm.cc:257
String secondary
Definition: otftotfm.cc:256
String font_name
Definition: otftotfm.cc:255
Option description.
Definition: clp.h:41
Command line parser.
Definition: clp.h:234
union Clp_Parser::@427 val
int have_val
Definition: clp.h:239
double d
Definition: clp.h:248
int negated
Definition: clp.h:237
int i
Definition: clp.h:244
unsigned u
Definition: clp.h:245
const char * vstr
Definition: clp.h:240
@ FONT
Definition: setting.hh:6
@ MOVE
Definition: setting.hh:6
@ SPECIAL
Definition: setting.hh:7
@ PUSH
Definition: setting.hh:6
@ RULE
Definition: setting.hh:6
@ SHOW
Definition: setting.hh:6
@ POP
Definition: setting.hh:6
A string of characters.
Definition: t1part.c:49
const char * c_str() const
Null-terminate the string.
Definition: string.hh:256
int find_right(char c, int start=0x7FFFFFFF) const
Search for a character in a string.
Definition: string.cc:518
String substring(const char *begin, const char *end) const
Return a substring of the current string starting at begin and ending before end.
Definition: string.hh:371
const_iterator begin() const
Return an iterator for the first character in the string.
Definition: string.hh:181
int length() const
Return the string's length.
Definition: string.hh:153
const_iterator end() const
Return an iterator for the end of the string.
Definition: string.hh:189
bool empty() const
Return true iff the string is empty.
Definition: string.hh:209
int find_left(char c, int start=0) const
Search for a character in a string.
Definition: string.cc:495
Definition: inftrees.h:24
Definition: pbmfont.h:11
Definition: afm2pl.c:145
Definition: dvips.h:235
Definition: strexpr.c:21
Definition: vf.c:59
pointer path
Definition: t1imager.h:36
int number
Definition: t1part.c:207
static String encoding_name
Definition: t1reencode.cc:64
#define FILE
Definition: t1stdio.h:34
#define feof(f)
Definition: t1stdio.h:109
#define ferror(f)
Definition: t1stdio.h:110
int j
Definition: t4ht.c:1589
void signal(SIGFPE, sig_err)
back
Definition: tex4ht.c:3533
val
Definition: tex4ht.c:3227
static void push_stack()
found
Definition: tex4ht.c:5000
return() int(((double) *(font_tbl[cur_fnt].wtbl+(int)(*(font_tbl[cur_fnt].char_wi+(int)(ch - font_tbl[cur_fnt].char_f)% 256)))/(double)(1L<< 20)) *(double) font_tbl[cur_fnt].scale)
struct Point Point
bool required
Definition: otftotfm.cc:923
Lookup()
Definition: otftotfm.cc:926
bool used
Definition: otftotfm.cc:922
Vector< OpenType::Tag > features
Definition: otftotfm.cc:924
GlyphFilter * filter
Definition: otftotfm.cc:925
Definition: obx.h:51
#define BUFSIZ
Definition: ps.c:61
#define va_start(pvar)
Definition: varargs.h:30
char * va_list
Definition: varargs.h:22
#define argv
Definition: xmain.c:270
#define argc
Definition: xmain.c:269
#define end(cp)
Definition: zic.c:71