Add option `-t' / `--ttfa-info' to front-ends.
[ttfautohint.git] / frontend / main.cpp
blob031030293f9e1c5c933dfcaadd153f51c52305b4
1 // main.cpp
3 // Copyright (C) 2011-2014 by Werner Lemberg.
4 //
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.
9 //
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'.
16 #ifdef BUILD_GUI
17 # ifndef _WIN32
18 # define CONSOLE_OUTPUT
19 # endif
20 #else
21 # define CONSOLE_OUTPUT
22 #endif
24 #include <config.h>
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <errno.h>
29 #include <string.h>
30 #include <getopt.h>
31 #include <limits.h>
32 #include <unistd.h>
34 #include <vector>
35 #include <string>
37 #if BUILD_GUI
38 # include <QApplication>
39 # include "maingui.h"
40 #else
41 # include "info.h"
42 #endif
44 #include <ttfautohint.h>
45 #include <numberset.h>
48 #ifdef _WIN32
49 # include <fcntl.h>
50 # define SET_BINARY(f) do { \
51 if (!isatty(fileno(f))) \
52 setmode(fileno(f), O_BINARY); \
53 } while (0)
54 #endif
56 #ifndef SET_BINARY
57 # define SET_BINARY(f) do {} while (0)
58 #endif
61 using namespace std;
64 // the available script tags and its descriptions are directly extracted
65 // from `ttfautohint-scripts.h'
66 typedef struct Script_Names_
68 const char* tag;
69 const char* description;
70 } Script_Names;
72 #undef SCRIPT
73 #define SCRIPT(s, S, d, h, sc1, sc2, sc3) \
74 {#s, d},
76 const Script_Names script_names[] =
78 #include <ttfautohint-scripts.h>
79 {NULL, NULL}
83 #ifndef BUILD_GUI
84 extern "C" {
86 typedef struct Progress_Data_
88 long last_sfnt;
89 bool begin;
90 int last_percent;
91 } Progress_Data;
94 int
95 progress(long curr_idx,
96 long num_glyphs,
97 long curr_sfnt,
98 long num_sfnts,
99 void* user)
101 Progress_Data* data = (Progress_Data*)user;
103 if (num_sfnts > 1 && curr_sfnt != data->last_sfnt)
105 fprintf(stderr, "subfont %ld of %ld\n", curr_sfnt + 1, num_sfnts);
106 data->last_sfnt = curr_sfnt;
107 data->last_percent = 0;
108 data->begin = true;
111 if (data->begin)
113 fprintf(stderr, " %ld glyphs\n"
114 " ", num_glyphs);
115 data->begin = false;
118 // print progress approx. every 10%
119 int curr_percent = curr_idx * 100 / num_glyphs;
120 int curr_diff = curr_percent - data->last_percent;
122 if (curr_diff >= 10)
124 fprintf(stderr, " %d%%", curr_percent);
125 data->last_percent = curr_percent - curr_percent % 10;
128 if (curr_idx + 1 == num_glyphs)
129 fprintf(stderr, "\n");
131 return 0;
135 typedef struct Error_Data_
137 const char* deltas_name;
138 } Error_Data;
141 void
142 err(TA_Error error,
143 const char* error_string,
144 unsigned int errlinenum,
145 const char* errline,
146 const char* errpos,
147 void* user)
149 Error_Data* data = static_cast<Error_Data*>(user);
151 if (!error)
152 return;
154 // We replace some terse error strings with more user-friendly versions.
155 if (error == TA_Err_Invalid_FreeType_Version)
156 fprintf(stderr,
157 "FreeType version 2.4.5 or higher is needed.\n"
158 "Perhaps using a wrong FreeType DLL?\n");
159 else if (error == TA_Err_Invalid_Font_Type)
160 fprintf(stderr,
161 "This font is not a valid font"
162 " in SFNT format with TrueType outlines.\n"
163 "In particular, CFF outlines are not supported.\n");
164 else if (error == TA_Err_Already_Processed)
165 fprintf(stderr,
166 "This font has already been processed with ttfautohint.\n");
167 else if (error == TA_Err_Missing_Legal_Permission)
168 fprintf(stderr,
169 "Bit 1 in the `fsType' field of the `OS/2' table is set:\n"
170 "This font must not be modified"
171 " without permission of the legal owner.\n"
172 "Use command line option `-i' to continue"
173 " if you have such a permission.\n");
174 else if (error == TA_Err_Missing_Unicode_CMap)
175 fprintf(stderr,
176 "No Unicode character map.\n");
177 else if (error == TA_Err_Missing_Symbol_CMap)
178 fprintf(stderr,
179 "No symbol character map.\n");
180 else if (error == TA_Err_Missing_Glyph)
181 fprintf(stderr,
182 "No glyph for a standard character"
183 " to derive standard width and height.\n"
184 "Please check the documentation for a list of"
185 " script-specific standard characters,\n"
186 "or use option `--symbol'.\n");
187 else
189 if (error < 0x100)
190 fprintf(stderr, "An error with code 0x%02x occurred"
191 " while autohinting fonts",
192 error);
193 else if (error >= 0x100 && error < 0x200)
195 fprintf(stderr, "An error with code 0x%03x occurred"
196 " while parsing the argument of option `-X'",
197 error);
198 fprintf(stderr, errline ? ":\n" : ".\n");
200 if (errline)
201 fprintf(stderr, " %s\n", errline);
202 if (errpos && errline)
203 fprintf(stderr, " %*s\n", int(errpos - errline + 1), "^");
205 else if (error >= 0x200 && error < 0x300)
207 fprintf(stderr, "%s:", data->deltas_name);
208 if (errlinenum)
209 fprintf(stderr, "%d:", errlinenum);
210 if (errpos && errline)
211 fprintf(stderr, "%d:", int(errpos - errline + 1));
212 if (error_string)
213 fprintf(stderr, " %s", error_string);
214 fprintf(stderr, " (0x%02X)\n", error);
215 if (errline)
216 fprintf(stderr, " %s\n", errline);
217 if (errpos && errline)
218 fprintf(stderr, " %*s\n", int(errpos - errline + 1), "^");
224 } // extern "C"
225 #endif // !BUILD_GUI
228 #ifdef CONSOLE_OUTPUT
229 static void
230 show_help(bool
231 #ifdef BUILD_GUI
233 #endif
235 bool is_error)
237 FILE* handle = is_error ? stderr : stdout;
239 fprintf(handle,
240 #ifdef BUILD_GUI
241 "Usage: ttfautohintGUI [OPTION]...\n"
242 "A GUI application to replace hints in a TrueType font.\n"
243 #else
244 "Usage: ttfautohint [OPTION]... [IN-FILE [OUT-FILE]]\n"
245 "Replace hints in TrueType font IN-FILE and write output to OUT-FILE.\n"
246 "If OUT-FILE is missing, standard output is used instead;\n"
247 "if IN-FILE is missing also, standard input and output are used.\n"
248 #endif
249 "\n"
250 "The new hints are based on FreeType's auto-hinter.\n"
251 "\n"
252 "This program is a simple front-end to the `ttfautohint' library.\n"
253 "\n");
255 fprintf(handle,
256 "Long options can be given with one or two dashes,\n"
257 "and with and without equal sign between option and argument.\n"
258 "This means that the following forms are acceptable:\n"
259 "`-foo=bar', `--foo=bar', `-foo bar', `--foo bar'.\n"
260 "\n"
261 "Mandatory arguments to long options are mandatory for short options too.\n"
262 #ifdef BUILD_GUI
263 "Options not related to Qt or X11 set default values.\n"
264 #endif
265 "\n"
268 fprintf(handle,
269 "Options:\n"
270 #ifndef BUILD_GUI
271 " --debug print debugging information\n"
272 #endif
273 " -c, --composites hint glyph composites also\n"
274 " -d, --dehint remove all hints\n"
275 " -D, --default-script=S set default OpenType script (default: latn)\n"
276 " -f, --fallback-script=S set fallback script (default: none)\n"
277 " -G, --hinting-limit=N switch off hinting above this PPEM value\n"
278 " (default: %d); value 0 means no limit\n"
279 " -h, --help display this help and exit\n"
280 " -H, --fallback-stem-width=N\n"
281 " set fallback stem width\n"
282 " (default: 50 font units at 2048 UPEM)\n"
283 #ifdef BUILD_GUI
284 " --help-all show Qt and X11 specific options also\n"
285 #endif
286 " -i, --ignore-restrictions override font license restrictions\n"
287 " -l, --hinting-range-min=N the minimum PPEM value for hint sets\n"
288 " (default: %d)\n"
289 #ifndef BUILD_GUI
290 " -m, --deltas-file=FILE get delta exceptions from FILE\n"
291 #endif
292 " -n, --no-info don't add ttfautohint info\n"
293 " to the version string(s) in the `name' table\n"
294 " -p, --adjust-subglyphs handle subglyph adjustments in exotic fonts\n",
295 TA_HINTING_LIMIT, TA_HINTING_RANGE_MIN);
296 fprintf(handle,
297 " -r, --hinting-range-max=N the maximum PPEM value for hint sets\n"
298 " (default: %d)\n"
299 " -s, --symbol input is symbol font\n"
300 " -t, --ttfa-table add TTFA information table\n"
301 " -v, --verbose show progress information\n"
302 " -V, --version print version information and exit\n"
303 " -w, --strong-stem-width=S use strong stem width routine for modes S,\n"
304 " where S is a string of up to three letters\n"
305 " with possible values `g' for grayscale,\n"
306 " `G' for GDI ClearType, and `D' for\n"
307 " DirectWrite ClearType (default: G)\n"
308 " -W, --windows-compatibility\n"
309 " add blue zones for `usWinAscent' and\n"
310 " `usWinDescent' to avoid clipping\n"
311 " -x, --increase-x-height=N increase x height for sizes in the range\n"
312 " 6<=PPEM<=N; value 0 switches off this feature\n"
313 " (default: %d)\n"
314 " -X, --x-height-snapping-exceptions=STRING\n"
315 " specify a comma-separated list of\n"
316 " x-height snapping exceptions, for example\n"
317 " \"-9, 13-17, 19\" (default: \"\")\n"
318 "\n",
319 TA_HINTING_RANGE_MAX, TA_INCREASE_X_HEIGHT);
321 #ifdef BUILD_GUI
322 if (all)
324 fprintf(handle,
325 "Qt Options:\n"
326 " --graphicssystem=SYSTEM\n"
327 " select a different graphics system backend\n"
328 " instead of the default one\n"
329 " (possible values: `raster', `opengl')\n"
330 " --reverse set layout direction to right-to-left\n");
331 fprintf(handle,
332 " --session=ID restore the application for the given ID\n"
333 " --style=STYLE set application GUI style\n"
334 " (possible values: motif, windows, platinum)\n"
335 " --stylesheet=SHEET apply the given Qt stylesheet\n"
336 " to the application widgets\n"
337 "\n");
339 fprintf(handle,
340 "X11 options:\n"
341 " --background=COLOR set the default background color\n"
342 " and an application palette\n"
343 " (light and dark shades are calculated)\n"
344 " --bg=COLOR same as --background\n"
345 " --btn=COLOR set the default button color\n"
346 " --button=COLOR same as --btn\n"
347 " --cmap use a private color map on an 8-bit display\n"
348 " --display=NAME use the given X-server display\n");
349 fprintf(handle,
350 " --fg=COLOR set the default foreground color\n"
351 " --fn=FONTNAME set the application font\n"
352 " --font=FONTNAME same as --fn\n"
353 " --foreground=COLOR same as --fg\n"
354 " --geometry=GEOMETRY set the client geometry of first window\n"
355 " --im=SERVER set the X Input Method (XIM) server\n"
356 " --inputstyle=STYLE set X Input Method input style\n"
357 " (possible values: onthespot, overthespot,\n"
358 " offthespot, root)\n");
359 fprintf(handle,
360 " --name=NAME set the application name\n"
361 " --ncols=COUNT limit the number of colors allocated\n"
362 " in the color cube on an 8-bit display,\n"
363 " if the application is using the\n"
364 " QApplication::ManyColor color specification\n"
365 " --title=TITLE set the application title (caption)\n"
366 " --visual=VISUAL force the application\n"
367 " to use the given visual on an 8-bit display\n"
368 " (only possible value: TrueColor)\n"
369 "\n");
371 #endif // BUILD_GUI
373 fprintf(handle,
374 "The program accepts both TTF and TTC files as input.\n"
375 "Use option -i only if you have a legal permission to modify the font.\n"
376 "The used PPEM value for option -p is FUnits per em, normally 2048.\n"
377 "With option -s, use default values for standard stem width and height,\n"
378 "otherwise they are derived from script-specific characters\n"
379 "resembling the shape of character `o'.\n"
380 "\n");
381 fprintf(handle,
382 "A hint set contains the optimal hinting for a certain PPEM value;\n"
383 "the larger the hint set range (as given by options -l and -r),\n"
384 "the more hint sets get computed, usually increasing the output font size.\n"
385 "The `gasp' table of the output file always enables grayscale hinting\n"
386 "for all sizes (limited by option -G, which is handled in the bytecode).\n"
387 "Increasing the value of -G does not increase the output font size.\n"
388 "\n");
389 fprintf(handle,
390 "Options -f and -D take a four-letter string that identifies a script.\n"
391 "Option -f sets the script used as a fallback for glyphs that have\n"
392 "character codes outside of known script ranges. Option -D sets the\n"
393 "default script for handling OpenType features. Possible values are\n"
394 "\n");
395 const Script_Names* sn = script_names;
396 for(;;)
398 fprintf(handle, " %s (%s)",
399 sn->tag, sn->description);
400 sn++;
401 if (sn->tag)
402 fprintf(handle, ",\n");
403 else
405 fprintf(handle, ".\n");
406 break;
409 fprintf(handle,
410 #ifndef BUILD_GUI
411 "\n"
412 "A delta exceptions file contains lines of the form\n"
413 "\n"
414 " [<subfont idx>] <glyph id> p <points> [x <shift>] [y <shift>] @ <ppems>\n"
415 "\n"
416 "to fine-tune point positions after hinting. <glyph id> is a glyph name\n"
417 "or index, <shift> is in px, <points> and <ppems> are ranges as with\n"
418 "option `-X'. `#' starts a line comment, which gets ignored.\n"
419 "Empty lines are ignored, too.\n"
420 #endif
421 "\n"
422 #ifdef BUILD_GUI
423 "A command-line version of this program is called `ttfautohint'.\n"
424 #else
425 "A GUI version of this program is called `ttfautohintGUI'.\n"
426 #endif
427 "\n"
428 "Report bugs to: freetype-devel@nongnu.org\n"
429 "ttfautohint home page: <http://www.freetype.org/ttfautohint>\n");
431 if (is_error)
432 exit(EXIT_FAILURE);
433 else
434 exit(EXIT_SUCCESS);
438 static void
439 show_version()
441 fprintf(stdout,
442 #ifdef BUILD_GUI
443 "ttfautohintGUI " VERSION "\n"
444 #else
445 "ttfautohint " VERSION "\n"
446 #endif
447 "Copyright (C) 2011-2014 Werner Lemberg <wl@gnu.org>.\n"
448 "License: FreeType License (FTL) or GNU GPLv2.\n"
449 "This is free software: you are free to change and redistribute it.\n"
450 "There is NO WARRANTY, to the extent permitted by law.\n");
452 exit(EXIT_SUCCESS);
454 #endif // CONSOLE_OUTPUT
458 main(int argc,
459 char** argv)
461 int hinting_range_min = 0;
462 int hinting_range_max = 0;
463 int hinting_limit = 0;
464 int increase_x_height = 0;
465 int fallback_stem_width = 0;
467 bool have_hinting_range_min = false;
468 bool have_hinting_range_max = false;
469 bool have_hinting_limit = false;
470 bool have_increase_x_height = false;
471 bool have_fallback_stem_width = false;
473 bool gray_strong_stem_width = false;
474 bool gdi_cleartype_strong_stem_width = true;
475 bool dw_cleartype_strong_stem_width = false;
477 bool ignore_restrictions = false;
478 bool windows_compatibility = false;
479 bool adjust_subglyphs = false;
480 bool hint_composites = false;
481 bool no_info = false;
482 bool TTFA_info = false;
483 bool symbol = false;
485 const char* default_script = NULL;
486 bool have_default_script = false;
487 const char* fallback_script = NULL;
488 bool have_fallback_script = false;
489 const char* x_height_snapping_exceptions_string = NULL;
490 bool have_x_height_snapping_exceptions_string = false;
492 bool dehint = false;
494 #ifndef BUILD_GUI
495 bool debug = false;
497 TA_Progress_Func progress_func = NULL;
498 TA_Error_Func err_func = err;
499 TA_Info_Func info_func = info;
501 const char* deltas_name = NULL;
502 #endif
504 // make GNU, Qt, and X11 command line options look the same;
505 // we allow `--foo=bar', `--foo bar', `-foo=bar', `-foo bar',
506 // and short options specific to ttfautohint
508 // set up a new argument string
509 vector<string> new_arg_string;
510 new_arg_string.push_back(argv[0]);
512 while (1)
514 // use pseudo short options for long-only options
515 enum
517 PASS_THROUGH = CHAR_MAX + 1,
518 HELP_ALL_OPTION,
519 DEBUG_OPTION
522 static struct option long_options[] =
524 {"help", no_argument, NULL, 'h'},
525 #ifdef BUILD_GUI
526 {"help-all", no_argument, NULL, HELP_ALL_OPTION},
527 #endif
529 // ttfautohint options
530 {"adjust-subglyphs", no_argument, NULL, 'p'},
531 {"composites", no_argument, NULL, 'c'},
532 #ifndef BUILD_GUI
533 {"debug", no_argument, NULL, DEBUG_OPTION},
534 #endif
535 {"default-script", required_argument, NULL, 'D'},
536 {"dehint", no_argument, NULL, 'd'},
537 #ifndef BUILD_GUI
538 {"deltas-file", required_argument, NULL, 'm'},
539 #endif
540 {"fallback-script", required_argument, NULL, 'f'},
541 {"fallback-stem-width", required_argument, NULL, 'H'},
542 {"hinting-limit", required_argument, NULL, 'G'},
543 {"hinting-range-max", required_argument, NULL, 'r'},
544 {"hinting-range-min", required_argument, NULL, 'l'},
545 {"ignore-restrictions", no_argument, NULL, 'i'},
546 {"increase-x-height", required_argument, NULL, 'x'},
547 {"no-info", no_argument, NULL, 'n'},
548 {"pre-hinting", no_argument, NULL, 'p'},
549 {"strong-stem-width", required_argument, NULL, 'w'},
550 {"symbol", no_argument, NULL, 's'},
551 {"ttfa-table", no_argument, NULL, 't'},
552 {"verbose", no_argument, NULL, 'v'},
553 {"version", no_argument, NULL, 'V'},
554 {"windows-compatibility", no_argument, NULL, 'W'},
555 {"x-height-snapping-exceptions", required_argument, NULL, 'X'},
557 // Qt options
558 {"graphicssystem", required_argument, NULL, PASS_THROUGH},
559 {"reverse", no_argument, NULL, PASS_THROUGH},
560 {"session", required_argument, NULL, PASS_THROUGH},
561 {"style", required_argument, NULL, PASS_THROUGH},
562 {"stylesheet", required_argument, NULL, PASS_THROUGH},
564 // X11 options
565 {"background", required_argument, NULL, PASS_THROUGH},
566 {"bg", required_argument, NULL, PASS_THROUGH},
567 {"btn", required_argument, NULL, PASS_THROUGH},
568 {"button", required_argument, NULL, PASS_THROUGH},
569 {"cmap", no_argument, NULL, PASS_THROUGH},
570 {"display", required_argument, NULL, PASS_THROUGH},
571 {"fg", required_argument, NULL, PASS_THROUGH},
572 {"fn", required_argument, NULL, PASS_THROUGH},
573 {"font", required_argument, NULL, PASS_THROUGH},
574 {"foreground", required_argument, NULL, PASS_THROUGH},
575 {"geometry", required_argument, NULL, PASS_THROUGH},
576 {"im", required_argument, NULL, PASS_THROUGH},
577 {"inputstyle", required_argument, NULL, PASS_THROUGH},
578 {"name", required_argument, NULL, PASS_THROUGH},
579 {"ncols", required_argument, NULL, PASS_THROUGH},
580 {"title", required_argument, NULL, PASS_THROUGH},
581 {"visual", required_argument, NULL, PASS_THROUGH},
583 {NULL, 0, NULL, 0}
586 int option_index;
587 int c = getopt_long_only(argc, argv,
588 #ifdef BUILD_GUI
589 "cdD:f:G:hH:il:npr:stVvw:Wx:X:",
590 #else
591 "cdD:f:G:hH:il:m:npr:stVvw:Wx:X:",
592 #endif
593 long_options, &option_index);
594 if (c == -1)
595 break;
597 switch (c)
599 case 'c':
600 hint_composites = true;
601 break;
603 case 'd':
604 dehint = true;
605 break;
607 case 'D':
608 default_script = optarg;
609 have_default_script = true;
610 break;
612 case 'f':
613 fallback_script = optarg;
614 have_fallback_script = true;
615 break;
617 case 'G':
618 hinting_limit = atoi(optarg);
619 have_hinting_limit = true;
620 break;
622 case 'h':
623 #ifdef CONSOLE_OUTPUT
624 show_help(false, false);
625 #endif
626 break;
628 case 'H':
629 fallback_stem_width = atoi(optarg);
630 have_fallback_stem_width = true;
631 break;
633 case 'i':
634 ignore_restrictions = true;
635 break;
637 case 'l':
638 hinting_range_min = atoi(optarg);
639 have_hinting_range_min = true;
640 break;
642 #ifndef BUILD_GUI
643 case 'm':
644 deltas_name = optarg;
645 break;
646 #endif
648 case 'n':
649 no_info = true;
650 break;
652 case 'p':
653 adjust_subglyphs = true;
654 break;
656 case 'r':
657 hinting_range_max = atoi(optarg);
658 have_hinting_range_max = true;
659 break;
661 case 's':
662 symbol = true;
663 break;
665 case 't':
666 TTFA_info = true;
667 break;
669 case 'v':
670 #ifndef BUILD_GUI
671 progress_func = progress;
672 #endif
673 break;
675 case 'V':
676 #ifdef CONSOLE_OUTPUT
677 show_version();
678 #endif
679 break;
681 case 'w':
682 gray_strong_stem_width = strchr(optarg, 'g') ? true : false;
683 gdi_cleartype_strong_stem_width = strchr(optarg, 'G') ? true : false;
684 dw_cleartype_strong_stem_width = strchr(optarg, 'D') ? true : false;
685 break;
687 case 'W':
688 windows_compatibility = true;
689 break;
691 case 'x':
692 increase_x_height = atoi(optarg);
693 have_increase_x_height = true;
694 break;
696 case 'X':
697 x_height_snapping_exceptions_string = optarg;
698 have_x_height_snapping_exceptions_string = true;
699 break;
701 #ifndef BUILD_GUI
702 case DEBUG_OPTION:
703 debug = true;
704 break;
705 #endif
707 #ifdef BUILD_GUI
708 case HELP_ALL_OPTION:
709 #ifdef CONSOLE_OUTPUT
710 show_help(true, false);
711 #endif
712 break;
713 #endif
715 case PASS_THROUGH:
717 // append argument with proper syntax for Qt
718 string arg;
719 arg += '-';
720 arg += long_options[option_index].name;
722 new_arg_string.push_back(arg);
723 if (optarg)
724 new_arg_string.push_back(optarg);
725 break;
728 default:
729 exit(EXIT_FAILURE);
733 if (dehint)
735 // -d makes ttfautohint ignore all other hinting options
736 have_default_script = false;
737 have_fallback_script = false;
738 have_fallback_stem_width = false;
739 have_hinting_range_max = false;
740 have_hinting_range_min = false;
741 have_hinting_limit = false;
742 have_increase_x_height = false;
743 have_x_height_snapping_exceptions_string = false;
746 if (!have_default_script)
747 default_script = "latn";
748 if (!have_fallback_script)
749 fallback_script = "none";
750 if (!have_hinting_range_min)
751 hinting_range_min = TA_HINTING_RANGE_MIN;
752 if (!have_hinting_range_max)
753 hinting_range_max = TA_HINTING_RANGE_MAX;
754 if (!have_hinting_limit)
755 hinting_limit = TA_HINTING_LIMIT;
756 if (!have_increase_x_height)
757 increase_x_height = TA_INCREASE_X_HEIGHT;
758 if (!have_x_height_snapping_exceptions_string)
759 x_height_snapping_exceptions_string = "";
760 if (!have_fallback_stem_width)
761 fallback_stem_width = 0; /* redundant, but avoids a compiler warning */
763 #ifndef BUILD_GUI
765 if (!isatty(fileno(stderr)) && !debug)
766 setvbuf(stderr, (char*)NULL, _IONBF, BUFSIZ);
768 if (hinting_range_min < 2)
770 fprintf(stderr, "The hinting range minimum must be at least 2\n");
771 exit(EXIT_FAILURE);
773 if (hinting_range_max < hinting_range_min)
775 fprintf(stderr, "The hinting range maximum must not be smaller"
776 " than the minimum (%d)\n",
777 hinting_range_min);
778 exit(EXIT_FAILURE);
780 if (hinting_limit != 0 && hinting_limit < hinting_range_max)
782 fprintf(stderr, "A non-zero hinting limit must not be smaller"
783 " than the hinting range maximum (%d)\n",
784 hinting_range_max);
785 exit(EXIT_FAILURE);
787 if (increase_x_height != 0 && increase_x_height < 6)
789 fprintf(stderr, "A non-zero x height increase limit"
790 " must be larger than or equal to 6\n");
791 exit(EXIT_FAILURE);
793 if (have_fallback_stem_width && fallback_stem_width <= 0)
795 fprintf(stderr, "The fallback stem width"
796 " must be a positive integer\n");
797 exit(EXIT_FAILURE);
800 if (have_default_script)
802 const Script_Names* sn;
804 for (sn = script_names; sn->tag; sn++)
805 if (!strcmp(default_script, sn->tag))
806 break;
807 if (!sn->tag)
809 fprintf(stderr, "Unknown script tag `%s'\n", default_script);
810 exit(EXIT_FAILURE);
814 if (have_fallback_script)
816 const Script_Names* sn;
818 for (sn = script_names; sn->tag; sn++)
819 if (!strcmp(fallback_script, sn->tag))
820 break;
821 if (!sn->tag)
823 fprintf(stderr, "Unknown script tag `%s'\n", fallback_script);
824 exit(EXIT_FAILURE);
828 if (symbol
829 && have_fallback_stem_width
830 && !strcmp(fallback_script, "none"))
831 fprintf(stderr,
832 "Warning: Setting a fallback stem width for a symbol font\n"
833 " without setting a fallback script has no effect\n");
835 int num_args = argc - optind;
837 if (num_args > 2)
838 show_help(false, true);
840 FILE* in;
841 if (num_args > 0)
843 in = fopen(argv[optind], "rb");
844 if (!in)
846 fprintf(stderr,
847 "The following error occurred while opening font `%s':\n"
848 "\n"
849 " %s\n",
850 argv[optind], strerror(errno));
851 exit(EXIT_FAILURE);
854 else
856 if (isatty(fileno(stdin)))
857 show_help(false, true);
858 in = stdin;
861 FILE* out;
862 if (num_args > 1)
864 if (!strcmp(argv[optind], argv[optind + 1]))
866 fprintf(stderr, "Input and output file names must not be identical\n");
867 exit(EXIT_FAILURE);
870 out = fopen(argv[optind + 1], "wb");
871 if (!out)
873 fprintf(stderr,
874 "The following error occurred while opening font `%s':\n"
875 "\n"
876 " %s\n",
877 argv[optind + 1], strerror(errno));
878 exit(EXIT_FAILURE);
881 else
883 if (isatty(fileno(stdout)))
884 show_help(false, true);
885 out = stdout;
888 FILE* deltas = NULL;
889 if (deltas_name)
891 deltas = fopen(deltas_name, "r");
892 if (!deltas)
894 fprintf(stderr,
895 "The following error occurred while open deltas file `%s':\n"
896 "\n"
897 " %s\n",
898 deltas_name, strerror(errno));
899 exit(EXIT_FAILURE);
902 else
903 deltas = NULL;
905 Progress_Data progress_data = {-1, 1, 0};
906 Error_Data error_data = {deltas_name};
907 Info_Data info_data;
909 if (no_info)
910 info_func = NULL;
911 else
913 info_data.data = NULL; // must be deallocated after use
914 info_data.data_wide = NULL; // must be deallocated after use
915 info_data.data_len = 0;
916 info_data.data_wide_len = 0;
918 info_data.deltas_name = deltas_name;
920 info_data.hinting_range_min = hinting_range_min;
921 info_data.hinting_range_max = hinting_range_max;
922 info_data.hinting_limit = hinting_limit;
924 info_data.gray_strong_stem_width = gray_strong_stem_width;
925 info_data.gdi_cleartype_strong_stem_width = gdi_cleartype_strong_stem_width;
926 info_data.dw_cleartype_strong_stem_width = dw_cleartype_strong_stem_width;
928 info_data.windows_compatibility = windows_compatibility;
929 info_data.adjust_subglyphs = adjust_subglyphs;
930 info_data.hint_composites = hint_composites;
931 info_data.increase_x_height = increase_x_height;
932 info_data.x_height_snapping_exceptions_string = x_height_snapping_exceptions_string;
933 info_data.fallback_stem_width = fallback_stem_width;
934 info_data.symbol = symbol;
935 info_data.TTFA_info = TTFA_info;
937 strncpy(info_data.default_script,
938 default_script,
939 sizeof (info_data.default_script));
940 strncpy(info_data.fallback_script,
941 fallback_script,
942 sizeof (info_data.fallback_script));
944 info_data.dehint = dehint;
946 int ret = build_version_string(&info_data);
947 if (ret == 1)
948 fprintf(stderr, "Warning: Can't allocate memory"
949 " for ttfautohint options string in `name' table\n");
950 else if (ret == 2)
951 fprintf(stderr, "Warning: ttfautohint options string"
952 " in `name' table too long\n");
955 if (in == stdin)
956 SET_BINARY(stdin);
957 if (out == stdout)
958 SET_BINARY(stdout);
960 TA_Error error =
961 TTF_autohint("in-file, out-file, deltas-file,"
962 "hinting-range-min, hinting-range-max, hinting-limit,"
963 "gray-strong-stem-width, gdi-cleartype-strong-stem-width,"
964 "dw-cleartype-strong-stem-width,"
965 "progress-callback, progress-callback-data,"
966 "error-callback, error-callback-data,"
967 "info-callback, info-callback-data,"
968 "ignore-restrictions, windows-compatibility,"
969 "adjust-subglyphs, hint-composites,"
970 "increase-x-height, x-height-snapping-exceptions,"
971 "fallback-stem-width, default-script, fallback-script,"
972 "symbol, dehint, debug, TTFA-info",
973 in, out, deltas,
974 hinting_range_min, hinting_range_max, hinting_limit,
975 gray_strong_stem_width, gdi_cleartype_strong_stem_width,
976 dw_cleartype_strong_stem_width,
977 progress_func, &progress_data,
978 err_func, &error_data,
979 info_func, &info_data,
980 ignore_restrictions, windows_compatibility,
981 adjust_subglyphs, hint_composites,
982 increase_x_height, x_height_snapping_exceptions_string,
983 fallback_stem_width, default_script, fallback_script,
984 symbol, dehint, debug, TTFA_info);
986 if (!no_info)
988 free(info_data.data);
989 free(info_data.data_wide);
992 if (in != stdin)
993 fclose(in);
994 if (out != stdout)
995 fclose(out);
996 if (deltas)
997 fclose(deltas);
999 exit(error ? EXIT_FAILURE : EXIT_SUCCESS);
1001 return 0; // never reached
1003 #else // BUILD_GUI
1005 int new_argc = new_arg_string.size();
1006 char** new_argv = new char*[new_argc];
1008 // construct new argc and argv variables from collected data
1009 for (int i = 0; i < new_argc; i++)
1010 new_argv[i] = const_cast<char*>(new_arg_string[i].data());
1012 QApplication app(new_argc, new_argv);
1013 app.setApplicationName("TTFautohint");
1014 app.setApplicationVersion(VERSION);
1015 app.setOrganizationName("FreeType");
1016 app.setOrganizationDomain("freetype.org");
1018 bool alternative_layout = false;
1020 // Display the window off the screen -- to get proper window dimensions
1021 // including the frame, the window manager must have a chance to
1022 // decorate it.
1024 // We don't want to change the default window positioning algorithm of
1025 // the platform's window manager, so we create the main GUI window
1026 // twice.
1028 // The original idea, however, was to simply move the off-screen window
1029 // back to the screen with
1031 // gui.move(100, 100);
1032 // gui.setAttribute(Qt::WA_Moved, false);
1033 // gui.show();
1035 // (unsetting the `WA_Moved' attribute makes the window manager handle
1036 // the previous call to `move' as a position suggestion instead of a
1037 // request). Unfortuntely, there seems to be a bug in Qt 4.8.4 which
1038 // prevents any effect of unsetting `WA_Moved' if `show' has already
1039 // been called.
1041 Main_GUI dummy(alternative_layout,
1042 hinting_range_min, hinting_range_max, hinting_limit,
1043 gray_strong_stem_width, gdi_cleartype_strong_stem_width,
1044 dw_cleartype_strong_stem_width, increase_x_height,
1045 x_height_snapping_exceptions_string, fallback_stem_width,
1046 ignore_restrictions, windows_compatibility, adjust_subglyphs,
1047 hint_composites, no_info, default_script, fallback_script,
1048 symbol, dehint, TTFA_info);
1050 dummy.move(-50000, -50000);
1051 dummy.show();
1053 // if the vertical size of our window is too large,
1054 // select a horizontal layout
1055 QRect screen(QApplication::desktop()->availableGeometry());
1056 if (dummy.frameGeometry().height() > screen.width())
1057 alternative_layout = true;
1060 Main_GUI gui(alternative_layout,
1061 hinting_range_min, hinting_range_max, hinting_limit,
1062 gray_strong_stem_width, gdi_cleartype_strong_stem_width,
1063 dw_cleartype_strong_stem_width, increase_x_height,
1064 x_height_snapping_exceptions_string, fallback_stem_width,
1065 ignore_restrictions, windows_compatibility, adjust_subglyphs,
1066 hint_composites, no_info, default_script, fallback_script,
1067 symbol, dehint, TTFA_info);
1068 gui.show();
1070 return app.exec();
1072 #endif // BUILD_GUI
1075 // end of main.cpp