3 // Copyright (C) 2011-2012 by Werner Lemberg.
5 // This file is part of the ttfautohint library, and may only be used,
6 // modified, and distributed under the terms given in `COPYING'. By
7 // continuing to use, modify, or distribute this file you indicate that you
8 // have read `COPYING' and understand and accept it fully.
10 // The file `COPYING' mentioned in the previous paragraph is distributed
11 // with the ttfautohint library.
14 // This program is a wrapper for `TTF_autohint'.
18 # define CONSOLE_OUTPUT
21 # define CONSOLE_OUTPUT
37 # include <QApplication>
43 #include <ttfautohint.h>
51 typedef struct Progress_Data_
60 progress(long curr_idx
,
66 Progress_Data
* data
= (Progress_Data
*)user
;
68 if (num_sfnts
> 1 && curr_sfnt
!= data
->last_sfnt
)
70 fprintf(stderr
, "subfont %ld of %ld\n", curr_sfnt
+ 1, num_sfnts
);
71 data
->last_sfnt
= curr_sfnt
;
77 fprintf(stderr
, " %ld glyphs\n"
82 // print progress approx. every 10%
83 int curr_percent
= curr_idx
* 100 / num_glyphs
;
84 int curr_diff
= curr_percent
- data
->last_percent
;
88 fprintf(stderr
, " %d%%", curr_percent
);
89 data
->last_percent
= curr_percent
- curr_percent
% 10;
92 if (curr_idx
+ 1 == num_glyphs
)
93 fprintf(stderr
, "\n");
102 #ifdef CONSOLE_OUTPUT
111 FILE* handle
= is_error
? stderr
: stdout
;
115 "Usage: ttfautohintGUI [OPTION]...\n"
116 "A GUI application to replace hints in a TrueType font.\n"
118 "Usage: ttfautohint [OPTION]... IN-FILE OUT-FILE\n"
119 "Replace hints in TrueType font IN-FILE and write output to OUT-FILE.\n"
121 "The new hints are based on FreeType's autohinter.\n"
123 "This program is a simple front-end to the `ttfautohint' library.\n"
127 "Long options can be given with one or two dashes,\n"
128 "and with and without equal sign between option and argument.\n"
129 "This means that the following forms are acceptable:\n"
130 "`-foo=bar', `--foo=bar', `-foo bar', `--foo bar'.\n"
132 "Mandatory arguments to long options are mandatory for short options too.\n"
134 "Options not related to Qt or X11 set default values.\n"
141 " -f, --latin-fallback set fallback script to latin\n"
142 " -G, --hinting-limit=N switch off hinting above this PPEM value\n"
143 " (default: %d); value 0 means no limit\n"
144 " -h, --help display this help and exit\n"
146 " --help-all show Qt and X11 specific options also\n"
148 " -i, --ignore-restrictions override font license restrictions\n"
149 " -l, --hinting-range-min=N the minimum PPEM value for hint sets\n"
151 " -n --no-info don't add ttfautohint info\n"
152 " to the version string(s) in the `name' table\n"
153 " -p, --pre-hinting apply original hints in advance\n",
154 TA_HINTING_LIMIT
, TA_HINTING_RANGE_MIN
);
156 " -r, --hinting-range-max=N the maximum PPEM value for hint sets\n"
158 " -s, --symbol input is symbol font\n"
159 " -v, --verbose show progress information\n"
160 " -V, --version print version information and exit\n"
161 " -w, --strong-stem-width=S use strong stem width routine for modes S,\n"
162 " where S is a string of up to three letters\n"
163 " with possible values `g' for grayscale,\n"
164 " `G' for GDI ClearType, and `D' for\n"
165 " DirectWrite ClearType (default: G)\n"
166 " -x, --increase-x-height=N increase x height for sizes in the range\n"
167 " 6<=PPEM<=N; value 0 switches off this feature\n"
169 " -X, --x-height-snapping-exceptions=STRING\n"
170 " specify a comma-separated list of\n"
171 " x-height snapping exceptions\n"
173 TA_HINTING_RANGE_MAX
, TA_INCREASE_X_HEIGHT
);
180 " --graphicssystem=SYSTEM\n"
181 " select a different graphics system backend\n"
182 " instead of the default one\n"
183 " (possible values: `raster', `opengl')\n"
184 " --reverse set layout direction to right-to-left\n");
186 " --session=ID restore the application for the given ID\n"
187 " --style=STYLE set application GUI style\n"
188 " (possible values: motif, windows, platinum)\n"
189 " --stylesheet=SHEET apply the given Qt stylesheet\n"
190 " to the application widgets\n"
195 " --background=COLOR set the default background color\n"
196 " and an application palette\n"
197 " (light and dark shades are calculated)\n"
198 " --bg=COLOR same as --background\n"
199 " --btn=COLOR set the default button color\n"
200 " --button=COLOR same as --btn\n"
201 " --cmap use a private color map on an 8-bit display\n"
202 " --display=NAME use the given X-server display\n");
204 " --fg=COLOR set the default foreground color\n"
205 " --fn=FONTNAME set the application font\n"
206 " --font=FONTNAME same as --fn\n"
207 " --foreground=COLOR same as --fg\n"
208 " --geometry=GEOMETRY set the client geometry of first window\n"
209 " --im=SERVER set the X Input Method (XIM) server\n"
210 " --inputstyle=STYLE set X Input Method input style\n"
211 " (possible values: onthespot, overthespot,\n"
212 " offthespot, root)\n");
214 " --name=NAME set the application name\n"
215 " --ncols=COUNT limit the number of colors allocated\n"
216 " in the color cube on an 8-bit display,\n"
217 " if the application is using the\n"
218 " QApplication::ManyColor color specification\n"
219 " --title=TITLE set the application title (caption)\n"
220 " --visual=VISUAL force the application\n"
221 " to use the given visual on an 8-bit display\n"
222 " (only possible value: TrueColor)\n"
228 "The program accepts both TTF and TTC files as input.\n"
229 "Use option -i only if you have a legal permission to modify the font.\n"
230 "If option -f is not set, glyphs not in the latin range stay unhinted.\n"
231 "The used PPEM value for option -p is FUnits per em, normally 2048.\n"
232 "With option -s, use default values for standard stem width and height,\n"
233 "otherwise they are derived from latin character `o'.\n"
236 "A hint set contains the optimal hinting for a certain PPEM value;\n"
237 "the larger the hint set range, the more hint sets get computed,\n"
238 "usually increasing the output font size. Note, however,\n"
239 "that the `gasp' table of the output file enables grayscale hinting\n"
240 "for all sizes (limited by option -G which is handled in the bytecode).\n"
244 "A command-line version of this program is called `ttfautohint'.\n"
246 "A GUI version of this program is called `ttfautohintGUI'.\n"
249 "Report bugs to: freetype-devel@nongnu.org\n"
250 "ttfautohint home page: <http://www.freetype.org/ttfautohint>\n");
264 "ttfautohintGUI " VERSION
"\n"
266 "ttfautohint " VERSION
"\n"
268 "Copyright (C) 2011-2012 Werner Lemberg <wl@gnu.org>.\n"
269 "License: FreeType License (FTL) or GNU GPLv2.\n"
270 "This is free software: you are free to change and redistribute it.\n"
271 "There is NO WARRANTY, to the extent permitted by law.\n");
275 #endif // CONSOLE_OUTPUT
282 int hinting_range_min
= 0;
283 int hinting_range_max
= 0;
284 int hinting_limit
= 0;
285 int increase_x_height
= 0;
286 bool have_hinting_range_min
= false;
287 bool have_hinting_range_max
= false;
288 bool have_hinting_limit
= false;
289 bool have_increase_x_height
= false;
291 bool gray_strong_stem_width
= false;
292 bool gdi_cleartype_strong_stem_width
= true;
293 bool dw_cleartype_strong_stem_width
= false;
295 bool ignore_restrictions
= false;
296 bool pre_hinting
= false;
297 bool no_info
= false;
298 int latin_fallback
= 0; // leave it as int; this probably gets extended
302 TA_Progress_Func progress_func
= NULL
;
303 TA_Info_Func info_func
= info
;
306 // make GNU, Qt, and X11 command line options look the same;
307 // we allow `--foo=bar', `--foo bar', `-foo=bar', `-foo bar',
308 // and short options specific to ttfautohint
310 // set up a new argument string
311 vector
<string
> new_arg_string
;
312 new_arg_string
.push_back(argv
[0]);
316 // use pseudo short options for long-only options
319 PASS_THROUGH
= CHAR_MAX
+ 1,
323 static struct option long_options
[] =
325 {"help", no_argument
, NULL
, 'h'},
327 {"help-all", no_argument
, NULL
, HELP_ALL_OPTION
},
330 // ttfautohint options
331 {"hinting-limit", required_argument
, NULL
, 'G'},
332 {"hinting-range-max", required_argument
, NULL
, 'r'},
333 {"hinting-range-min", required_argument
, NULL
, 'l'},
334 {"ignore-restrictions", no_argument
, NULL
, 'i'},
335 {"increase-x-height", required_argument
, NULL
, 'x'},
336 {"latin-fallback", no_argument
, NULL
, 'f'},
337 {"no-info", no_argument
, NULL
, 'n'},
338 {"pre-hinting", no_argument
, NULL
, 'p'},
339 {"strong-stem-width", required_argument
, NULL
, 'w'},
340 {"symbol", no_argument
, NULL
, 's'},
341 {"verbose", no_argument
, NULL
, 'v'},
342 {"version", no_argument
, NULL
, 'V'},
343 {"x-height-snapping-exceptions", required_argument
, NULL
, 'X'},
346 {"graphicssystem", required_argument
, NULL
, PASS_THROUGH
},
347 {"reverse", no_argument
, NULL
, PASS_THROUGH
},
348 {"session", required_argument
, NULL
, PASS_THROUGH
},
349 {"style", required_argument
, NULL
, PASS_THROUGH
},
350 {"stylesheet", required_argument
, NULL
, PASS_THROUGH
},
353 {"background", required_argument
, NULL
, PASS_THROUGH
},
354 {"bg", required_argument
, NULL
, PASS_THROUGH
},
355 {"btn", required_argument
, NULL
, PASS_THROUGH
},
356 {"button", required_argument
, NULL
, PASS_THROUGH
},
357 {"cmap", no_argument
, NULL
, PASS_THROUGH
},
358 {"display", required_argument
, NULL
, PASS_THROUGH
},
359 {"fg", required_argument
, NULL
, PASS_THROUGH
},
360 {"fn", required_argument
, NULL
, PASS_THROUGH
},
361 {"font", required_argument
, NULL
, PASS_THROUGH
},
362 {"foreground", required_argument
, NULL
, PASS_THROUGH
},
363 {"geometry", required_argument
, NULL
, PASS_THROUGH
},
364 {"im", required_argument
, NULL
, PASS_THROUGH
},
365 {"inputstyle", required_argument
, NULL
, PASS_THROUGH
},
366 {"name", required_argument
, NULL
, PASS_THROUGH
},
367 {"ncols", required_argument
, NULL
, PASS_THROUGH
},
368 {"title", required_argument
, NULL
, PASS_THROUGH
},
369 {"visual", required_argument
, NULL
, PASS_THROUGH
},
375 int c
= getopt_long_only(argc
, argv
, "fG:hil:npr:stVvx:X:w:",
376 long_options
, &option_index
);
387 hinting_limit
= atoi(optarg
);
388 have_hinting_limit
= true;
392 #ifdef CONSOLE_OUTPUT
393 show_help(false, false);
398 ignore_restrictions
= true;
402 hinting_range_min
= atoi(optarg
);
403 have_hinting_range_min
= true;
415 hinting_range_max
= atoi(optarg
);
416 have_hinting_range_max
= true;
425 progress_func
= progress
;
430 #ifdef CONSOLE_OUTPUT
436 gray_strong_stem_width
= strchr(optarg
, 'g') ? true : false;
437 gdi_cleartype_strong_stem_width
= strchr(optarg
, 'G') ? true : false;
438 dw_cleartype_strong_stem_width
= strchr(optarg
, 'D') ? true : false;
442 increase_x_height
= atoi(optarg
);
443 have_increase_x_height
= true;
447 #ifdef CONSOLE_OUTPUT
448 fprintf(stderr
, "Option `-x' not implemented yet\n");
452 case HELP_ALL_OPTION
:
453 #ifdef CONSOLE_OUTPUT
454 show_help(true, false);
460 // append argument with proper syntax for Qt
463 arg
+= long_options
[option_index
].name
;
465 new_arg_string
.push_back(arg
);
467 new_arg_string
.push_back(optarg
);
476 if (!have_hinting_range_min
)
477 hinting_range_min
= TA_HINTING_RANGE_MIN
;
478 if (!have_hinting_range_max
)
479 hinting_range_max
= TA_HINTING_RANGE_MAX
;
480 if (!have_hinting_limit
)
481 hinting_limit
= TA_HINTING_LIMIT
;
482 if (!have_increase_x_height
)
483 increase_x_height
= TA_INCREASE_X_HEIGHT
;
487 if (hinting_range_min
< 2)
489 fprintf(stderr
, "The hinting range minimum must be at least 2\n");
492 if (hinting_range_max
< hinting_range_min
)
494 fprintf(stderr
, "The hinting range maximum must not be smaller"
495 " than the minimum (%d)\n",
499 if (hinting_limit
!= 0 && hinting_limit
< hinting_range_max
)
501 fprintf(stderr
, "A non-zero hinting limit must not be smaller"
502 " than the hinting range maximum (%d)\n",
506 if (increase_x_height
!= 0
507 && (increase_x_height
< 6 || increase_x_height
> 20))
509 fprintf(stderr
, "A non-zero x height increase limit"
510 " must be in the range 6-20\n");
514 // on the console we need in and out file arguments
515 if (argc
- optind
!= 2)
516 show_help(false, true);
518 FILE* in
= fopen(argv
[optind
], "rb");
521 fprintf(stderr
, "The following error occurred while opening font `%s':\n"
524 argv
[optind
], strerror(errno
));
528 FILE* out
= fopen(argv
[optind
+ 1], "wb");
531 fprintf(stderr
, "The following error occurred while opening font `%s':\n"
534 argv
[optind
+ 1], strerror(errno
));
538 unsigned char version_data
[128];
539 unsigned char version_data_wide
[256];
541 const unsigned char* error_string
;
542 Progress_Data progress_data
= {-1, 1, 0};
549 info_data
.data
= version_data
;
550 info_data
.data_wide
= version_data_wide
;
552 info_data
.hinting_range_min
= hinting_range_min
;
553 info_data
.hinting_range_max
= hinting_range_max
;
554 info_data
.hinting_limit
= hinting_limit
;
556 info_data
.gray_strong_stem_width
= gray_strong_stem_width
;
557 info_data
.gdi_cleartype_strong_stem_width
= gdi_cleartype_strong_stem_width
;
558 info_data
.dw_cleartype_strong_stem_width
= dw_cleartype_strong_stem_width
;
560 info_data
.pre_hinting
= pre_hinting
;
561 info_data
.increase_x_height
= increase_x_height
;
562 info_data
.latin_fallback
= latin_fallback
;
563 info_data
.symbol
= symbol
;
565 build_version_string(&info_data
);
569 TTF_autohint("in-file, out-file,"
570 "hinting-range-min, hinting-range-max, hinting-limit,"
571 "gray-strong-stem-width, gdi-cleartype-strong-stem-width,"
572 "dw-cleartype-strong-stem-width,"
574 "progress-callback, progress-callback-data,"
575 "info-callback, info-callback-data,"
576 "ignore-restrictions, pre-hinting, increase-x-height,"
577 "fallback-script, symbol",
579 hinting_range_min
, hinting_range_max
, hinting_limit
,
580 gray_strong_stem_width
, gdi_cleartype_strong_stem_width
,
581 dw_cleartype_strong_stem_width
,
583 progress_func
, &progress_data
,
584 info_func
, &info_data
,
585 ignore_restrictions
, pre_hinting
, increase_x_height
,
586 latin_fallback
, symbol
);
590 if (error
== TA_Err_Invalid_FreeType_Version
)
592 "FreeType version 2.4.5 or higher is needed.\n"
593 "Perhaps using a wrong FreeType DLL?\n");
594 else if (error
== TA_Err_Invalid_Font_Type
)
596 "This font is not a valid font"
597 " in SFNT format with TrueType outlines.\n"
598 "In particular, CFF outlines are not supported.\n");
599 else if (error
== TA_Err_Already_Processed
)
601 "This font has already been processed with ttfautohint.\n");
602 else if (error
== TA_Err_Missing_Legal_Permission
)
604 "Bit 1 in the `fsType' field of the `OS/2' table is set:\n"
605 "This font must not be modified"
606 " without permission of the legal owner.\n"
607 "Use command line option `-i' to continue"
608 " if you have such a permission.\n");
609 else if (error
== TA_Err_Missing_Unicode_CMap
)
611 "No Unicode character map.\n");
612 else if (error
== TA_Err_Missing_Glyph
)
614 "No glyph for the key character"
615 " to derive standard width and height.\n"
616 "For the latin script, this key character is `o' (U+006F).\n");
619 "Error code `0x%02x' while autohinting font:\n"
620 " %s\n", error
, error_string
);
629 return 0; // never reached
633 int new_argc
= new_arg_string
.size();
634 char** new_argv
= new char*[new_argc
];
636 // construct new argc and argv variables from collected data
637 for (int i
= 0; i
< new_argc
; i
++)
638 new_argv
[i
] = const_cast<char*>(new_arg_string
[i
].data());
640 QApplication
app(new_argc
, new_argv
);
641 app
.setApplicationName("TTFautohint");
642 app
.setApplicationVersion(VERSION
);
643 app
.setOrganizationName("FreeType");
644 app
.setOrganizationDomain("freetype.org");
646 Main_GUI
gui(hinting_range_min
, hinting_range_max
, hinting_limit
,
647 gray_strong_stem_width
, gdi_cleartype_strong_stem_width
,
648 dw_cleartype_strong_stem_width
,
649 increase_x_height
, ignore_restrictions
, pre_hinting
,
650 no_info
, latin_fallback
, symbol
);