Synchronize with FreeType.
[ttfautohint.git] / frontend / main.cpp
blob1a0e15a40167f5d3e47a91a6c11f29448b043baa
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;
134 } // extern "C"
135 #endif // !BUILD_GUI
138 #ifdef CONSOLE_OUTPUT
139 static void
140 show_help(bool
141 #ifdef BUILD_GUI
143 #endif
145 bool is_error)
147 FILE* handle = is_error ? stderr : stdout;
149 fprintf(handle,
150 #ifdef BUILD_GUI
151 "Usage: ttfautohintGUI [OPTION]...\n"
152 "A GUI application to replace hints in a TrueType font.\n"
153 #else
154 "Usage: ttfautohint [OPTION]... [IN-FILE [OUT-FILE]]\n"
155 "Replace hints in TrueType font IN-FILE and write output to OUT-FILE.\n"
156 "If OUT-FILE is missing, standard output is used instead;\n"
157 "if IN-FILE is missing also, standard input and output are used.\n"
158 #endif
159 "\n"
160 "The new hints are based on FreeType's auto-hinter.\n"
161 "\n"
162 "This program is a simple front-end to the `ttfautohint' library.\n"
163 "\n");
165 fprintf(handle,
166 "Long options can be given with one or two dashes,\n"
167 "and with and without equal sign between option and argument.\n"
168 "This means that the following forms are acceptable:\n"
169 "`-foo=bar', `--foo=bar', `-foo bar', `--foo bar'.\n"
170 "\n"
171 "Mandatory arguments to long options are mandatory for short options too.\n"
172 #ifdef BUILD_GUI
173 "Options not related to Qt or X11 set default values.\n"
174 #endif
175 "\n"
178 fprintf(handle,
179 "Options:\n"
180 #ifndef BUILD_GUI
181 " --debug print debugging information\n"
182 #endif
183 " -c, --composites hint glyph composites also\n"
184 " -d, --dehint remove all hints\n"
185 " -D, --default-script=S set default OpenType script (default: latn)\n"
186 " -f, --fallback-script=S set fallback script (default: none)\n"
187 " -G, --hinting-limit=N switch off hinting above this PPEM value\n"
188 " (default: %d); value 0 means no limit\n"
189 " -h, --help display this help and exit\n"
190 #ifdef BUILD_GUI
191 " --help-all show Qt and X11 specific options also\n"
192 #endif
193 " -i, --ignore-restrictions override font license restrictions\n"
194 " -l, --hinting-range-min=N the minimum PPEM value for hint sets\n"
195 " (default: %d)\n"
196 " -n, --no-info don't add ttfautohint info\n"
197 " to the version string(s) in the `name' table\n"
198 " -p, --pre-hinting apply original hints in advance\n",
199 TA_HINTING_LIMIT, TA_HINTING_RANGE_MIN);
200 fprintf(handle,
201 " -r, --hinting-range-max=N the maximum PPEM value for hint sets\n"
202 " (default: %d)\n"
203 " -s, --symbol input is symbol font\n"
204 " -v, --verbose show progress information\n"
205 " -V, --version print version information and exit\n"
206 " -w, --strong-stem-width=S use strong stem width routine for modes S,\n"
207 " where S is a string of up to three letters\n"
208 " with possible values `g' for grayscale,\n"
209 " `G' for GDI ClearType, and `D' for\n"
210 " DirectWrite ClearType (default: G)\n"
211 " -W, --windows-compatibility\n"
212 " add blue zones for `usWinAscent' and\n"
213 " `usWinDescent' to avoid clipping\n"
214 " -x, --increase-x-height=N increase x height for sizes in the range\n"
215 " 6<=PPEM<=N; value 0 switches off this feature\n"
216 " (default: %d)\n"
217 " -X, --x-height-snapping-exceptions=STRING\n"
218 " specify a comma-separated list of\n"
219 " x-height snapping exceptions, for example\n"
220 " \"-9, 13-17, 19\" (default: \"\")\n"
221 "\n",
222 TA_HINTING_RANGE_MAX, TA_INCREASE_X_HEIGHT);
224 #ifdef BUILD_GUI
225 if (all)
227 fprintf(handle,
228 "Qt Options:\n"
229 " --graphicssystem=SYSTEM\n"
230 " select a different graphics system backend\n"
231 " instead of the default one\n"
232 " (possible values: `raster', `opengl')\n"
233 " --reverse set layout direction to right-to-left\n");
234 fprintf(handle,
235 " --session=ID restore the application for the given ID\n"
236 " --style=STYLE set application GUI style\n"
237 " (possible values: motif, windows, platinum)\n"
238 " --stylesheet=SHEET apply the given Qt stylesheet\n"
239 " to the application widgets\n"
240 "\n");
242 fprintf(handle,
243 "X11 options:\n"
244 " --background=COLOR set the default background color\n"
245 " and an application palette\n"
246 " (light and dark shades are calculated)\n"
247 " --bg=COLOR same as --background\n"
248 " --btn=COLOR set the default button color\n"
249 " --button=COLOR same as --btn\n"
250 " --cmap use a private color map on an 8-bit display\n"
251 " --display=NAME use the given X-server display\n");
252 fprintf(handle,
253 " --fg=COLOR set the default foreground color\n"
254 " --fn=FONTNAME set the application font\n"
255 " --font=FONTNAME same as --fn\n"
256 " --foreground=COLOR same as --fg\n"
257 " --geometry=GEOMETRY set the client geometry of first window\n"
258 " --im=SERVER set the X Input Method (XIM) server\n"
259 " --inputstyle=STYLE set X Input Method input style\n"
260 " (possible values: onthespot, overthespot,\n"
261 " offthespot, root)\n");
262 fprintf(handle,
263 " --name=NAME set the application name\n"
264 " --ncols=COUNT limit the number of colors allocated\n"
265 " in the color cube on an 8-bit display,\n"
266 " if the application is using the\n"
267 " QApplication::ManyColor color specification\n"
268 " --title=TITLE set the application title (caption)\n"
269 " --visual=VISUAL force the application\n"
270 " to use the given visual on an 8-bit display\n"
271 " (only possible value: TrueColor)\n"
272 "\n");
274 #endif // BUILD_GUI
276 fprintf(handle,
277 "The program accepts both TTF and TTC files as input.\n"
278 "Use option -i only if you have a legal permission to modify the font.\n"
279 "The used PPEM value for option -p is FUnits per em, normally 2048.\n"
280 "With option -s, use default values for standard stem width and height,\n"
281 "otherwise they are derived from script-specific characters\n"
282 "resembling the shape of character `o'.\n"
283 "\n");
284 fprintf(handle,
285 "A hint set contains the optimal hinting for a certain PPEM value;\n"
286 "the larger the hint set range, the more hint sets get computed,\n"
287 "usually increasing the output font size. Note, however,\n"
288 "that the `gasp' table of the output file enables grayscale hinting\n"
289 "for all sizes (limited by option -G, which is handled in the bytecode).\n"
290 "\n");
291 fprintf(handle,
292 "Options -f and -D take a four-letter string that identifies a script.\n"
293 "Option -f sets the script used as a fallback for glyphs that have\n"
294 "character codes outside of known script ranges. Option -D sets the\n"
295 "default script for handling OpenType features. Possible values are\n"
296 "\n");
297 const Script_Names* sn = script_names;
298 for(;;)
300 fprintf(handle, " %s (%s)",
301 sn->tag, sn->description);
302 sn++;
303 if (sn->tag)
304 fprintf(handle, ",\n");
305 else
307 fprintf(handle, ".\n");
308 break;
311 fprintf(handle,
312 "\n"
313 #ifdef BUILD_GUI
314 "A command-line version of this program is called `ttfautohint'.\n"
315 #else
316 "A GUI version of this program is called `ttfautohintGUI'.\n"
317 #endif
318 "\n"
319 "Report bugs to: freetype-devel@nongnu.org\n"
320 "ttfautohint home page: <http://www.freetype.org/ttfautohint>\n");
322 if (is_error)
323 exit(EXIT_FAILURE);
324 else
325 exit(EXIT_SUCCESS);
329 static void
330 show_version()
332 fprintf(stdout,
333 #ifdef BUILD_GUI
334 "ttfautohintGUI " VERSION "\n"
335 #else
336 "ttfautohint " VERSION "\n"
337 #endif
338 "Copyright (C) 2011-2014 Werner Lemberg <wl@gnu.org>.\n"
339 "License: FreeType License (FTL) or GNU GPLv2.\n"
340 "This is free software: you are free to change and redistribute it.\n"
341 "There is NO WARRANTY, to the extent permitted by law.\n");
343 exit(EXIT_SUCCESS);
345 #endif // CONSOLE_OUTPUT
349 main(int argc,
350 char** argv)
352 int hinting_range_min = 0;
353 int hinting_range_max = 0;
354 int hinting_limit = 0;
355 int increase_x_height = 0;
356 bool have_hinting_range_min = false;
357 bool have_hinting_range_max = false;
358 bool have_hinting_limit = false;
359 bool have_increase_x_height = false;
361 bool gray_strong_stem_width = false;
362 bool gdi_cleartype_strong_stem_width = true;
363 bool dw_cleartype_strong_stem_width = false;
365 bool ignore_restrictions = false;
366 bool windows_compatibility = false;
367 bool pre_hinting = false;
368 bool hint_composites = false;
369 bool no_info = false;
370 bool symbol = false;
372 const char* default_script = NULL;
373 bool have_default_script = false;
374 const char* fallback_script = NULL;
375 bool have_fallback_script = false;
376 const char* x_height_snapping_exceptions_string = NULL;
377 bool have_x_height_snapping_exceptions_string = false;
379 bool dehint = false;
381 #ifndef BUILD_GUI
382 bool debug = false;
384 TA_Progress_Func progress_func = NULL;
385 TA_Info_Func info_func = info;
386 #endif
388 // make GNU, Qt, and X11 command line options look the same;
389 // we allow `--foo=bar', `--foo bar', `-foo=bar', `-foo bar',
390 // and short options specific to ttfautohint
392 // set up a new argument string
393 vector<string> new_arg_string;
394 new_arg_string.push_back(argv[0]);
396 while (1)
398 // use pseudo short options for long-only options
399 enum
401 PASS_THROUGH = CHAR_MAX + 1,
402 HELP_ALL_OPTION,
403 DEBUG_OPTION
406 static struct option long_options[] =
408 {"help", no_argument, NULL, 'h'},
409 #ifdef BUILD_GUI
410 {"help-all", no_argument, NULL, HELP_ALL_OPTION},
411 #endif
413 // ttfautohint options
414 {"composites", no_argument, NULL, 'c'},
415 #ifndef BUILD_GUI
416 {"debug", no_argument, NULL, DEBUG_OPTION},
417 #endif
418 {"default-script", required_argument, NULL, 'D'},
419 {"dehint", no_argument, NULL, 'd'},
420 {"fallback-script", required_argument, NULL, 'f'},
421 {"hinting-limit", required_argument, NULL, 'G'},
422 {"hinting-range-max", required_argument, NULL, 'r'},
423 {"hinting-range-min", required_argument, NULL, 'l'},
424 {"ignore-restrictions", no_argument, NULL, 'i'},
425 {"increase-x-height", required_argument, NULL, 'x'},
426 {"no-info", no_argument, NULL, 'n'},
427 {"pre-hinting", no_argument, NULL, 'p'},
428 {"strong-stem-width", required_argument, NULL, 'w'},
429 {"symbol", no_argument, NULL, 's'},
430 {"verbose", no_argument, NULL, 'v'},
431 {"version", no_argument, NULL, 'V'},
432 {"windows-compatibility", no_argument, NULL, 'W'},
433 {"x-height-snapping-exceptions", required_argument, NULL, 'X'},
435 // Qt options
436 {"graphicssystem", required_argument, NULL, PASS_THROUGH},
437 {"reverse", no_argument, NULL, PASS_THROUGH},
438 {"session", required_argument, NULL, PASS_THROUGH},
439 {"style", required_argument, NULL, PASS_THROUGH},
440 {"stylesheet", required_argument, NULL, PASS_THROUGH},
442 // X11 options
443 {"background", required_argument, NULL, PASS_THROUGH},
444 {"bg", required_argument, NULL, PASS_THROUGH},
445 {"btn", required_argument, NULL, PASS_THROUGH},
446 {"button", required_argument, NULL, PASS_THROUGH},
447 {"cmap", no_argument, NULL, PASS_THROUGH},
448 {"display", required_argument, NULL, PASS_THROUGH},
449 {"fg", required_argument, NULL, PASS_THROUGH},
450 {"fn", required_argument, NULL, PASS_THROUGH},
451 {"font", required_argument, NULL, PASS_THROUGH},
452 {"foreground", required_argument, NULL, PASS_THROUGH},
453 {"geometry", required_argument, NULL, PASS_THROUGH},
454 {"im", required_argument, NULL, PASS_THROUGH},
455 {"inputstyle", required_argument, NULL, PASS_THROUGH},
456 {"name", required_argument, NULL, PASS_THROUGH},
457 {"ncols", required_argument, NULL, PASS_THROUGH},
458 {"title", required_argument, NULL, PASS_THROUGH},
459 {"visual", required_argument, NULL, PASS_THROUGH},
461 {NULL, 0, NULL, 0}
464 int option_index;
465 int c = getopt_long_only(argc, argv, "cdD:f:G:hil:npr:stVvw:Wx:X:",
466 long_options, &option_index);
467 if (c == -1)
468 break;
470 switch (c)
472 case 'c':
473 hint_composites = true;
474 break;
476 case 'd':
477 dehint = true;
478 break;
480 case 'D':
481 default_script = optarg;
482 have_default_script = true;
483 break;
485 case 'f':
486 fallback_script = optarg;
487 have_fallback_script = true;
488 break;
490 case 'G':
491 hinting_limit = atoi(optarg);
492 have_hinting_limit = true;
493 break;
495 case 'h':
496 #ifdef CONSOLE_OUTPUT
497 show_help(false, false);
498 #endif
499 break;
501 case 'i':
502 ignore_restrictions = true;
503 break;
505 case 'l':
506 hinting_range_min = atoi(optarg);
507 have_hinting_range_min = true;
508 break;
510 case 'n':
511 no_info = true;
512 break;
514 case 'p':
515 pre_hinting = true;
516 break;
518 case 'r':
519 hinting_range_max = atoi(optarg);
520 have_hinting_range_max = true;
521 break;
523 case 's':
524 symbol = true;
525 break;
527 case 'v':
528 #ifndef BUILD_GUI
529 progress_func = progress;
530 #endif
531 break;
533 case 'V':
534 #ifdef CONSOLE_OUTPUT
535 show_version();
536 #endif
537 break;
539 case 'w':
540 gray_strong_stem_width = strchr(optarg, 'g') ? true : false;
541 gdi_cleartype_strong_stem_width = strchr(optarg, 'G') ? true : false;
542 dw_cleartype_strong_stem_width = strchr(optarg, 'D') ? true : false;
543 break;
545 case 'W':
546 windows_compatibility = true;
547 break;
549 case 'x':
550 increase_x_height = atoi(optarg);
551 have_increase_x_height = true;
552 break;
554 case 'X':
555 x_height_snapping_exceptions_string = optarg;
556 have_x_height_snapping_exceptions_string = true;
557 break;
559 #ifndef BUILD_GUI
560 case DEBUG_OPTION:
561 debug = true;
562 break;
563 #endif
565 #ifdef BUILD_GUI
566 case HELP_ALL_OPTION:
567 #ifdef CONSOLE_OUTPUT
568 show_help(true, false);
569 #endif
570 break;
571 #endif
573 case PASS_THROUGH:
575 // append argument with proper syntax for Qt
576 string arg;
577 arg += '-';
578 arg += long_options[option_index].name;
580 new_arg_string.push_back(arg);
581 if (optarg)
582 new_arg_string.push_back(optarg);
583 break;
586 default:
587 exit(EXIT_FAILURE);
591 if (dehint)
593 // -d makes ttfautohint ignore all other hinting options
594 have_default_script = false;
595 have_fallback_script = false;
596 have_hinting_range_min = false;
597 have_hinting_range_max = false;
598 have_hinting_limit = false;
599 have_increase_x_height = false;
600 have_x_height_snapping_exceptions_string = false;
603 if (!have_default_script)
604 default_script = "latn";
605 if (!have_fallback_script)
606 fallback_script = "none";
607 if (!have_hinting_range_min)
608 hinting_range_min = TA_HINTING_RANGE_MIN;
609 if (!have_hinting_range_max)
610 hinting_range_max = TA_HINTING_RANGE_MAX;
611 if (!have_hinting_limit)
612 hinting_limit = TA_HINTING_LIMIT;
613 if (!have_increase_x_height)
614 increase_x_height = TA_INCREASE_X_HEIGHT;
615 if (!have_x_height_snapping_exceptions_string)
616 x_height_snapping_exceptions_string = "";
618 #ifndef BUILD_GUI
620 if (!isatty(fileno(stderr)) && !debug)
621 setvbuf(stderr, (char*)NULL, _IONBF, BUFSIZ);
623 if (hinting_range_min < 2)
625 fprintf(stderr, "The hinting range minimum must be at least 2\n");
626 exit(EXIT_FAILURE);
628 if (hinting_range_max < hinting_range_min)
630 fprintf(stderr, "The hinting range maximum must not be smaller"
631 " than the minimum (%d)\n",
632 hinting_range_min);
633 exit(EXIT_FAILURE);
635 if (hinting_limit != 0 && hinting_limit < hinting_range_max)
637 fprintf(stderr, "A non-zero hinting limit must not be smaller"
638 " than the hinting range maximum (%d)\n",
639 hinting_range_max);
640 exit(EXIT_FAILURE);
642 if (increase_x_height != 0 && increase_x_height < 6)
644 fprintf(stderr, "A non-zero x height increase limit"
645 " must be larger than or equal to 6\n");
646 exit(EXIT_FAILURE);
649 number_range* x_height_snapping_exceptions = NULL;
651 if (have_x_height_snapping_exceptions_string)
653 const char* s;
656 s = number_set_parse(x_height_snapping_exceptions_string,
657 &x_height_snapping_exceptions,
658 6, 0x7FFF);
659 if (*s)
661 if (x_height_snapping_exceptions == NUMBERSET_ALLOCATION_ERROR)
662 fprintf(stderr, "Allocation error while scanning"
663 " x height snapping exceptions\n");
664 else {
665 if (x_height_snapping_exceptions == NUMBERSET_INVALID_CHARACTER)
666 fprintf(stderr, "Invalid character");
667 else if (x_height_snapping_exceptions == NUMBERSET_OVERFLOW)
668 fprintf(stderr, "Overflow");
669 else if (x_height_snapping_exceptions == NUMBERSET_INVALID_RANGE)
670 fprintf(stderr, "Invalid range");
671 else if (x_height_snapping_exceptions == NUMBERSET_OVERLAPPING_RANGES)
672 fprintf(stderr, "Overlapping ranges");
673 else if (x_height_snapping_exceptions == NUMBERSET_NOT_ASCENDING)
674 fprintf(stderr, "Values und ranges must be ascending");
675 fprintf(stderr, " in x height snapping exceptions:\n"
676 " \"%s\"\n"
677 " %*s\n",
678 x_height_snapping_exceptions_string,
679 int(s - x_height_snapping_exceptions_string + 1),
680 "^");
682 exit(EXIT_FAILURE);
686 if (have_default_script)
688 const Script_Names* sn;
690 for (sn = script_names; sn->tag; sn++)
691 if (!strcmp(default_script, sn->tag))
692 break;
693 if (!sn->tag)
695 fprintf(stderr, "Unknown script tag `%s'\n", default_script);
696 exit(EXIT_FAILURE);
700 if (have_fallback_script)
702 const Script_Names* sn;
704 for (sn = script_names; sn->tag; sn++)
705 if (!strcmp(fallback_script, sn->tag))
706 break;
707 if (!sn->tag)
709 fprintf(stderr, "Unknown script tag `%s'\n", fallback_script);
710 exit(EXIT_FAILURE);
714 int num_args = argc - optind;
716 if (num_args > 2)
717 show_help(false, true);
719 FILE* in;
720 if (num_args > 0)
722 in = fopen(argv[optind], "rb");
723 if (!in)
725 fprintf(stderr, "The following error occurred while opening font `%s':\n"
726 "\n"
727 " %s\n",
728 argv[optind], strerror(errno));
729 exit(EXIT_FAILURE);
732 else
734 if (isatty(fileno(stdin)))
735 show_help(false, true);
736 in = stdin;
739 FILE* out;
740 if (num_args > 1)
742 if (!strcmp(argv[optind], argv[optind + 1]))
744 fprintf(stderr, "Input and output file names must not be identical\n");
745 exit(EXIT_FAILURE);
748 out = fopen(argv[optind + 1], "wb");
749 if (!out)
751 fprintf(stderr, "The following error occurred while opening font `%s':\n"
752 "\n"
753 " %s\n",
754 argv[optind + 1], strerror(errno));
755 exit(EXIT_FAILURE);
758 else
760 if (isatty(fileno(stdout)))
761 show_help(false, true);
762 out = stdout;
765 const unsigned char* error_string;
766 Progress_Data progress_data = {-1, 1, 0};
767 Info_Data info_data;
769 if (no_info)
770 info_func = NULL;
771 else
773 info_data.data = NULL; // must be deallocated after use
774 info_data.data_wide = NULL; // must be deallocated after use
775 info_data.data_len = 0;
776 info_data.data_wide_len = 0;
778 info_data.hinting_range_min = hinting_range_min;
779 info_data.hinting_range_max = hinting_range_max;
780 info_data.hinting_limit = hinting_limit;
782 info_data.gray_strong_stem_width = gray_strong_stem_width;
783 info_data.gdi_cleartype_strong_stem_width = gdi_cleartype_strong_stem_width;
784 info_data.dw_cleartype_strong_stem_width = dw_cleartype_strong_stem_width;
786 info_data.windows_compatibility = windows_compatibility;
787 info_data.pre_hinting = pre_hinting;
788 info_data.hint_composites = hint_composites;
789 info_data.increase_x_height = increase_x_height;
790 info_data.x_height_snapping_exceptions = x_height_snapping_exceptions;
791 info_data.symbol = symbol;
793 strncpy(info_data.default_script,
794 default_script,
795 sizeof (info_data.default_script));
796 strncpy(info_data.fallback_script,
797 fallback_script,
798 sizeof (info_data.fallback_script));
800 info_data.dehint = dehint;
802 int ret = build_version_string(&info_data);
803 if (ret == 1)
804 fprintf(stderr, "Warning: Can't allocate memory"
805 " for ttfautohint options string in `name' table\n");
806 else if (ret == 2)
807 fprintf(stderr, "Warning: ttfautohint options string"
808 " in `name' table too long\n");
811 if (in == stdin)
812 SET_BINARY(stdin);
813 if (out == stdout)
814 SET_BINARY(stdout);
816 TA_Error error =
817 TTF_autohint("in-file, out-file,"
818 "hinting-range-min, hinting-range-max, hinting-limit,"
819 "gray-strong-stem-width, gdi-cleartype-strong-stem-width,"
820 "dw-cleartype-strong-stem-width,"
821 "error-string,"
822 "progress-callback, progress-callback-data,"
823 "info-callback, info-callback-data,"
824 "ignore-restrictions, windows-compatibility,"
825 "pre-hinting, hint-composites,"
826 "increase-x-height, x-height-snapping-exceptions,"
827 "default-script, fallback-script, symbol,"
828 "dehint, debug",
829 in, out,
830 hinting_range_min, hinting_range_max, hinting_limit,
831 gray_strong_stem_width, gdi_cleartype_strong_stem_width,
832 dw_cleartype_strong_stem_width,
833 &error_string,
834 progress_func, &progress_data,
835 info_func, &info_data,
836 ignore_restrictions, windows_compatibility,
837 pre_hinting, hint_composites,
838 increase_x_height, x_height_snapping_exceptions_string,
839 default_script, fallback_script, symbol,
840 dehint, debug);
842 if (!no_info)
844 free(info_data.data);
845 free(info_data.data_wide);
848 number_set_free(x_height_snapping_exceptions);
850 if (error)
852 if (error == TA_Err_Invalid_FreeType_Version)
853 fprintf(stderr,
854 "FreeType version 2.4.5 or higher is needed.\n"
855 "Perhaps using a wrong FreeType DLL?\n");
856 else if (error == TA_Err_Invalid_Font_Type)
857 fprintf(stderr,
858 "This font is not a valid font"
859 " in SFNT format with TrueType outlines.\n"
860 "In particular, CFF outlines are not supported.\n");
861 else if (error == TA_Err_Already_Processed)
862 fprintf(stderr,
863 "This font has already been processed with ttfautohint.\n");
864 else if (error == TA_Err_Missing_Legal_Permission)
865 fprintf(stderr,
866 "Bit 1 in the `fsType' field of the `OS/2' table is set:\n"
867 "This font must not be modified"
868 " without permission of the legal owner.\n"
869 "Use command line option `-i' to continue"
870 " if you have such a permission.\n");
871 else if (error == TA_Err_Missing_Unicode_CMap)
872 fprintf(stderr,
873 "No Unicode character map.\n");
874 else if (error == TA_Err_Missing_Symbol_CMap)
875 fprintf(stderr,
876 "No symbol character map.\n");
877 else if (error == TA_Err_Missing_Glyph)
878 fprintf(stderr,
879 "No glyph for a standard character"
880 " to derive standard width and height.\n"
881 "Please check the documentation for a list of"
882 " script-specific standard characters,\n"
883 "or use option `--symbol'.\n");
884 else
885 fprintf(stderr,
886 "Error code `0x%02x' while autohinting font:\n"
887 " %s\n", error, error_string);
888 exit(EXIT_FAILURE);
891 if (in != stdin)
892 fclose(in);
893 if (out != stdout)
894 fclose(out);
896 exit(EXIT_SUCCESS);
898 return 0; // never reached
900 #else // BUILD_GUI
902 int new_argc = new_arg_string.size();
903 char** new_argv = new char*[new_argc];
905 // construct new argc and argv variables from collected data
906 for (int i = 0; i < new_argc; i++)
907 new_argv[i] = const_cast<char*>(new_arg_string[i].data());
909 QApplication app(new_argc, new_argv);
910 app.setApplicationName("TTFautohint");
911 app.setApplicationVersion(VERSION);
912 app.setOrganizationName("FreeType");
913 app.setOrganizationDomain("freetype.org");
915 bool alternative_layout = false;
917 // Display the window off the screen -- to get proper window dimensions
918 // including the frame, the window manager must have a chance to
919 // decorate it.
921 // We don't want to change the default window positioning algorithm of
922 // the platform's window manager, so we create the main GUI window
923 // twice.
925 // The original idea, however, was to simply move the off-screen window
926 // back to the screen with
928 // gui.move(100, 100);
929 // gui.setAttribute(Qt::WA_Moved, false);
930 // gui.show();
932 // (unsetting the `WA_Moved' attribute makes the window manager handle
933 // the previous call to `move' as a position suggestion instead of a
934 // request). Unfortuntely, there seems to be a bug in Qt 4.8.4 which
935 // prevents any effect of unsetting `WA_Moved' if `show' has already
936 // been called.
938 Main_GUI dummy(alternative_layout,
939 hinting_range_min, hinting_range_max, hinting_limit,
940 gray_strong_stem_width, gdi_cleartype_strong_stem_width,
941 dw_cleartype_strong_stem_width, increase_x_height,
942 x_height_snapping_exceptions_string,
943 ignore_restrictions, windows_compatibility, pre_hinting,
944 hint_composites, no_info, default_script, fallback_script,
945 symbol, dehint);
947 dummy.move(-50000, -50000);
948 dummy.show();
950 // if the vertical size of our window is too large,
951 // select a horizontal layout
952 QRect screen(QApplication::desktop()->availableGeometry());
953 if (dummy.frameGeometry().height() > screen.width())
954 alternative_layout = true;
957 Main_GUI gui(alternative_layout,
958 hinting_range_min, hinting_range_max, hinting_limit,
959 gray_strong_stem_width, gdi_cleartype_strong_stem_width,
960 dw_cleartype_strong_stem_width, increase_x_height,
961 x_height_snapping_exceptions_string,
962 ignore_restrictions, windows_compatibility, pre_hinting,
963 hint_composites, no_info, default_script, fallback_script,
964 symbol, dehint);
965 gui.show();
967 return app.exec();
969 #endif // BUILD_GUI
972 // end of main.cpp