Minor.
[ttfautohint.git] / frontend / main.cpp
blobc73a4202fb0f17ff66b34147deeb80a39e88e822
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>
33 #include <locale.h>
35 #include <vector>
36 #include <string>
38 #if BUILD_GUI
39 # include <QApplication>
40 # include "maingui.h"
41 #else
42 # include "info.h"
43 #endif
45 #include <ttfautohint.h>
46 #include <numberset.h>
49 #ifdef _WIN32
50 # include <fcntl.h>
51 # define SET_BINARY(f) do { \
52 if (!isatty(fileno(f))) \
53 setmode(fileno(f), O_BINARY); \
54 } while (0)
55 #endif
57 #ifndef SET_BINARY
58 # define SET_BINARY(f) do {} while (0)
59 #endif
62 using namespace std;
65 // the available script tags and its descriptions are directly extracted
66 // from `ttfautohint-scripts.h'
67 typedef struct Script_Names_
69 const char* tag;
70 const char* description;
71 } Script_Names;
73 #undef SCRIPT
74 #define SCRIPT(s, S, d, h, sc1, sc2, sc3) \
75 {#s, d},
77 const Script_Names script_names[] =
79 #include <ttfautohint-scripts.h>
80 {NULL, NULL}
84 #ifndef BUILD_GUI
85 extern "C" {
87 typedef struct Progress_Data_
89 long last_sfnt;
90 bool begin;
91 int last_percent;
92 } Progress_Data;
95 int
96 progress(long curr_idx,
97 long num_glyphs,
98 long curr_sfnt,
99 long num_sfnts,
100 void* user)
102 Progress_Data* data = (Progress_Data*)user;
104 if (num_sfnts > 1 && curr_sfnt != data->last_sfnt)
106 fprintf(stderr, "subfont %ld of %ld\n", curr_sfnt + 1, num_sfnts);
107 data->last_sfnt = curr_sfnt;
108 data->last_percent = 0;
109 data->begin = true;
112 if (data->begin)
114 fprintf(stderr, " %ld glyphs\n"
115 " ", num_glyphs);
116 data->begin = false;
119 // print progress approx. every 10%
120 int curr_percent = curr_idx * 100 / num_glyphs;
121 int curr_diff = curr_percent - data->last_percent;
123 if (curr_diff >= 10)
125 fprintf(stderr, " %d%%", curr_percent);
126 data->last_percent = curr_percent - curr_percent % 10;
129 if (curr_idx + 1 == num_glyphs)
130 fprintf(stderr, "\n");
132 return 0;
136 typedef struct Error_Data_
138 const char* control_name;
139 } Error_Data;
142 void
143 err(TA_Error error,
144 const char* error_string,
145 unsigned int errlinenum,
146 const char* errline,
147 const char* errpos,
148 void* user)
150 Error_Data* data = static_cast<Error_Data*>(user);
152 if (!error)
153 return;
155 // We replace some terse error strings with more user-friendly versions.
156 if (error == TA_Err_Invalid_FreeType_Version)
157 fprintf(stderr,
158 "FreeType version 2.4.5 or higher is needed.\n"
159 "Perhaps using a wrong FreeType DLL?\n");
160 else if (error == TA_Err_Invalid_Font_Type)
161 fprintf(stderr,
162 "This font is not a valid font"
163 " in SFNT format with TrueType outlines.\n"
164 "In particular, CFF outlines are not supported.\n");
165 else if (error == TA_Err_Already_Processed)
166 fprintf(stderr,
167 "This font has already been processed with ttfautohint.\n");
168 else if (error == TA_Err_Missing_Legal_Permission)
169 fprintf(stderr,
170 "Bit 1 in the `fsType' field of the `OS/2' table is set:\n"
171 "This font must not be modified"
172 " without permission of the legal owner.\n"
173 "Use command line option `-i' to continue"
174 " if you have such a permission.\n");
175 else if (error == TA_Err_Missing_Unicode_CMap)
176 fprintf(stderr,
177 "No Unicode character map.\n");
178 else if (error == TA_Err_Missing_Symbol_CMap)
179 fprintf(stderr,
180 "No symbol character map.\n");
181 else if (error == TA_Err_Missing_Glyph)
182 fprintf(stderr,
183 "No glyph for a standard character"
184 " to derive standard width and height.\n"
185 "Please check the documentation for a list of"
186 " script-specific standard characters,\n"
187 "or use option `--symbol'.\n");
188 else
190 if (error < 0x100)
191 fprintf(stderr, "An error with code 0x%02x occurred"
192 " while autohinting fonts",
193 error);
194 else if (error >= 0x100 && error < 0x200)
196 fprintf(stderr, "An error with code 0x%03x occurred"
197 " while parsing the argument of option `-X'",
198 error);
199 fprintf(stderr, errline ? ":\n" : ".\n");
201 if (errline)
202 fprintf(stderr, " %s\n", errline);
203 if (errpos && errline)
204 fprintf(stderr, " %*s\n", int(errpos - errline + 1), "^");
206 else if (error >= 0x200 && error < 0x300)
208 fprintf(stderr, "%s:", data->control_name);
209 if (errlinenum)
210 fprintf(stderr, "%d:", errlinenum);
211 if (errpos && errline)
212 fprintf(stderr, "%d:", int(errpos - errline + 1));
213 if (error_string)
214 fprintf(stderr, " %s", error_string);
215 fprintf(stderr, " (0x%02X)\n", error);
216 if (errline)
217 fprintf(stderr, " %s\n", errline);
218 if (errpos && errline)
219 fprintf(stderr, " %*s\n", int(errpos - errline + 1), "^");
225 } // extern "C"
226 #endif // !BUILD_GUI
229 #ifdef CONSOLE_OUTPUT
230 static void
231 show_help(bool
232 #ifdef BUILD_GUI
234 #endif
236 bool is_error)
238 FILE* handle = is_error ? stderr : stdout;
240 fprintf(handle,
241 #ifdef BUILD_GUI
242 "Usage: ttfautohintGUI [OPTION]...\n"
243 "A GUI application to replace hints in a TrueType font.\n"
244 #else
245 "Usage: ttfautohint [OPTION]... [IN-FILE [OUT-FILE]]\n"
246 "Replace hints in TrueType font IN-FILE and write output to OUT-FILE.\n"
247 "If OUT-FILE is missing, standard output is used instead;\n"
248 "if IN-FILE is missing also, standard input and output are used.\n"
249 #endif
250 "\n"
251 "The new hints are based on FreeType's auto-hinter.\n"
252 "\n"
253 "This program is a simple front-end to the `ttfautohint' library.\n"
254 "\n");
256 fprintf(handle,
257 "Long options can be given with one or two dashes,\n"
258 "and with and without equal sign between option and argument.\n"
259 "This means that the following forms are acceptable:\n"
260 "`-foo=bar', `--foo=bar', `-foo bar', `--foo bar'.\n"
261 "\n"
262 "Mandatory arguments to long options are mandatory for short options too.\n"
263 #ifdef BUILD_GUI
264 "Options not related to Qt or X11 set default values.\n"
265 #endif
266 "\n"
269 fprintf(handle,
270 "Options:\n"
271 #ifndef BUILD_GUI
272 " --debug print debugging information\n"
273 #endif
274 " -c, --composites hint glyph composites also\n"
275 " -d, --dehint remove all hints\n"
276 " -D, --default-script=S set default OpenType script (default: latn)\n"
277 " -f, --fallback-script=S set fallback script (default: none)\n"
278 " -G, --hinting-limit=N switch off hinting above this PPEM value\n"
279 " (default: %d); value 0 means no limit\n"
280 " -h, --help display this help and exit\n"
281 " -H, --fallback-stem-width=N\n"
282 " set fallback stem width\n"
283 " (default: 50 font units at 2048 UPEM)\n"
284 #ifdef BUILD_GUI
285 " --help-all show Qt and X11 specific options also\n"
286 #endif
287 " -i, --ignore-restrictions override font license restrictions\n"
288 " -l, --hinting-range-min=N the minimum PPEM value for hint sets\n"
289 " (default: %d)\n"
290 #ifndef BUILD_GUI
291 " -m, --control-file=FILE get control instructions from FILE\n"
292 #endif
293 " -n, --no-info don't add ttfautohint info\n"
294 " to the version string(s) in the `name' table\n"
295 " -p, --adjust-subglyphs handle subglyph adjustments in exotic fonts\n",
296 TA_HINTING_LIMIT, TA_HINTING_RANGE_MIN);
297 fprintf(handle,
298 " -r, --hinting-range-max=N the maximum PPEM value for hint sets\n"
299 " (default: %d)\n"
300 " -s, --symbol input is symbol font\n"
301 " -t, --ttfa-table add TTFA information table\n"
302 " -v, --verbose show progress information\n"
303 " -V, --version print version information and exit\n"
304 " -w, --strong-stem-width=S use strong stem width routine for modes S,\n"
305 " where S is a string of up to three letters\n"
306 " with possible values `g' for grayscale,\n"
307 " `G' for GDI ClearType, and `D' for\n"
308 " DirectWrite ClearType (default: G)\n"
309 " -W, --windows-compatibility\n"
310 " add blue zones for `usWinAscent' and\n"
311 " `usWinDescent' to avoid clipping\n"
312 " -x, --increase-x-height=N increase x height for sizes in the range\n"
313 " 6<=PPEM<=N; value 0 switches off this feature\n"
314 " (default: %d)\n"
315 " -X, --x-height-snapping-exceptions=STRING\n"
316 " specify a comma-separated list of\n"
317 " x-height snapping exceptions, for example\n"
318 " \"-9, 13-17, 19\" (default: \"\")\n"
319 "\n",
320 TA_HINTING_RANGE_MAX, TA_INCREASE_X_HEIGHT);
322 #ifdef BUILD_GUI
323 if (all)
325 fprintf(handle,
326 "Qt Options:\n"
327 " --graphicssystem=SYSTEM\n"
328 " select a different graphics system backend\n"
329 " instead of the default one\n"
330 " (possible values: `raster', `opengl')\n"
331 " --reverse set layout direction to right-to-left\n");
332 fprintf(handle,
333 " --session=ID restore the application for the given ID\n"
334 " --style=STYLE set application GUI style\n"
335 " (possible values: motif, windows, platinum)\n"
336 " --stylesheet=SHEET apply the given Qt stylesheet\n"
337 " to the application widgets\n"
338 "\n");
340 fprintf(handle,
341 "X11 options:\n"
342 " --background=COLOR set the default background color\n"
343 " and an application palette\n"
344 " (light and dark shades are calculated)\n"
345 " --bg=COLOR same as --background\n"
346 " --btn=COLOR set the default button color\n"
347 " --button=COLOR same as --btn\n"
348 " --cmap use a private color map on an 8-bit display\n"
349 " --display=NAME use the given X-server display\n");
350 fprintf(handle,
351 " --fg=COLOR set the default foreground color\n"
352 " --fn=FONTNAME set the application font\n"
353 " --font=FONTNAME same as --fn\n"
354 " --foreground=COLOR same as --fg\n"
355 " --geometry=GEOMETRY set the client geometry of first window\n"
356 " --im=SERVER set the X Input Method (XIM) server\n"
357 " --inputstyle=STYLE set X Input Method input style\n"
358 " (possible values: onthespot, overthespot,\n"
359 " offthespot, root)\n");
360 fprintf(handle,
361 " --name=NAME set the application name\n"
362 " --ncols=COUNT limit the number of colors allocated\n"
363 " in the color cube on an 8-bit display,\n"
364 " if the application is using the\n"
365 " QApplication::ManyColor color specification\n"
366 " --title=TITLE set the application title (caption)\n"
367 " --visual=VISUAL force the application\n"
368 " to use the given visual on an 8-bit display\n"
369 " (only possible value: TrueColor)\n"
370 "\n");
372 #endif // BUILD_GUI
374 fprintf(handle,
375 "The program accepts both TTF and TTC files as input.\n"
376 "Use option -i only if you have a legal permission to modify the font.\n"
377 "The used PPEM value for option -p is FUnits per em, normally 2048.\n"
378 "With option -s, use default values for standard stem width and height,\n"
379 "otherwise they are derived from script-specific characters\n"
380 "resembling the shape of character `o'.\n"
381 "\n");
382 fprintf(handle,
383 "A hint set contains the optimal hinting for a certain PPEM value;\n"
384 "the larger the hint set range (as given by options -l and -r),\n"
385 "the more hint sets get computed, usually increasing the output font size.\n"
386 "The `gasp' table of the output file always enables grayscale hinting\n"
387 "for all sizes (limited by option -G, which is handled in the bytecode).\n"
388 "Increasing the value of -G does not increase the output font size.\n"
389 "\n");
390 fprintf(handle,
391 "Options -f and -D take a four-letter string that identifies a script.\n"
392 "Option -f sets the script used as a fallback for glyphs that have\n"
393 "character codes outside of known script ranges. Option -D sets the\n"
394 "default script for handling OpenType features. Possible values are\n"
395 "\n");
396 const Script_Names* sn = script_names;
397 for(;;)
399 fprintf(handle, " %s (%s)",
400 sn->tag, sn->description);
401 sn++;
402 if (sn->tag)
403 fprintf(handle, ",\n");
404 else
406 fprintf(handle, ".\n");
407 break;
410 fprintf(handle,
411 #ifndef BUILD_GUI
412 "\n"
413 "A control instructions file contains entries of the form\n"
414 "\n"
415 " [<subfont idx>] <glyph id> l|r|n <points>\n"
416 "\n"
417 "or\n"
418 "\n"
419 " [<subfont idx>] <glyph id> p <points> [x <shift>] [y <shift>] @ <ppems>\n"
420 "\n"
421 "`l' (`r', `n') changes point directions to left (right, no direction).\n"
422 "`p' applies delta exceptions to the specified points.\n"
423 "\n"
424 "<glyph id> is a glyph name or index, <shift> is a real number in px,\n"
425 "<points> and <ppems> are integer ranges as with option `-X'.\n"
426 "`#' starts a line comment, which gets ignored.\n"
427 "Empty lines are ignored, too.\n"
428 #endif
429 "\n"
430 #ifdef BUILD_GUI
431 "A command-line version of this program is called `ttfautohint'.\n"
432 #else
433 "A GUI version of this program is called `ttfautohintGUI'.\n"
434 #endif
435 "\n"
436 "Report bugs to: freetype-devel@nongnu.org\n"
437 "ttfautohint home page: <http://www.freetype.org/ttfautohint>\n");
439 if (is_error)
440 exit(EXIT_FAILURE);
441 else
442 exit(EXIT_SUCCESS);
446 static void
447 show_version()
449 fprintf(stdout,
450 #ifdef BUILD_GUI
451 "ttfautohintGUI " VERSION "\n"
452 #else
453 "ttfautohint " VERSION "\n"
454 #endif
455 "Copyright (C) 2011-2014 Werner Lemberg <wl@gnu.org>.\n"
456 "License: FreeType License (FTL) or GNU GPLv2.\n"
457 "This is free software: you are free to change and redistribute it.\n"
458 "There is NO WARRANTY, to the extent permitted by law.\n");
460 exit(EXIT_SUCCESS);
462 #endif // CONSOLE_OUTPUT
466 main(int argc,
467 char** argv)
469 int hinting_range_min = 0;
470 int hinting_range_max = 0;
471 int hinting_limit = 0;
472 int increase_x_height = 0;
473 int fallback_stem_width = 0;
475 bool have_hinting_range_min = false;
476 bool have_hinting_range_max = false;
477 bool have_hinting_limit = false;
478 bool have_increase_x_height = false;
479 bool have_fallback_stem_width = false;
481 bool gray_strong_stem_width = false;
482 bool gdi_cleartype_strong_stem_width = true;
483 bool dw_cleartype_strong_stem_width = false;
485 bool ignore_restrictions = false;
486 bool windows_compatibility = false;
487 bool adjust_subglyphs = false;
488 bool hint_composites = false;
489 bool no_info = false;
490 bool TTFA_info = false;
491 bool symbol = false;
493 const char* default_script = NULL;
494 bool have_default_script = false;
495 const char* fallback_script = NULL;
496 bool have_fallback_script = false;
497 const char* x_height_snapping_exceptions_string = NULL;
498 bool have_x_height_snapping_exceptions_string = false;
500 bool dehint = false;
502 #ifndef BUILD_GUI
503 bool debug = false;
505 TA_Progress_Func progress_func = NULL;
506 TA_Error_Func err_func = err;
507 TA_Info_Func info_func = info;
509 const char* control_name = NULL;
510 #endif
512 // For real numbers (both parsing and displaying) we only use `.' as the
513 // decimal separator; similarly, we don't want localized formats like a
514 // thousands separator for any number.
515 setlocale(LC_NUMERIC, "C");
517 // make GNU, Qt, and X11 command line options look the same;
518 // we allow `--foo=bar', `--foo bar', `-foo=bar', `-foo bar',
519 // and short options specific to ttfautohint
521 // set up a new argument string
522 vector<string> new_arg_string;
523 new_arg_string.push_back(argv[0]);
525 while (1)
527 // use pseudo short options for long-only options
528 enum
530 PASS_THROUGH = CHAR_MAX + 1,
531 HELP_ALL_OPTION,
532 DEBUG_OPTION
535 static struct option long_options[] =
537 {"help", no_argument, NULL, 'h'},
538 #ifdef BUILD_GUI
539 {"help-all", no_argument, NULL, HELP_ALL_OPTION},
540 #endif
542 // ttfautohint options
543 {"adjust-subglyphs", no_argument, NULL, 'p'},
544 {"composites", no_argument, NULL, 'c'},
545 #ifndef BUILD_GUI
546 {"control-file", required_argument, NULL, 'm'},
547 {"debug", no_argument, NULL, DEBUG_OPTION},
548 #endif
549 {"default-script", required_argument, NULL, 'D'},
550 {"dehint", no_argument, NULL, 'd'},
551 {"fallback-script", required_argument, NULL, 'f'},
552 {"fallback-stem-width", required_argument, NULL, 'H'},
553 {"hinting-limit", required_argument, NULL, 'G'},
554 {"hinting-range-max", required_argument, NULL, 'r'},
555 {"hinting-range-min", required_argument, NULL, 'l'},
556 {"ignore-restrictions", no_argument, NULL, 'i'},
557 {"increase-x-height", required_argument, NULL, 'x'},
558 {"no-info", no_argument, NULL, 'n'},
559 {"pre-hinting", no_argument, NULL, 'p'},
560 {"strong-stem-width", required_argument, NULL, 'w'},
561 {"symbol", no_argument, NULL, 's'},
562 {"ttfa-table", no_argument, NULL, 't'},
563 {"verbose", no_argument, NULL, 'v'},
564 {"version", no_argument, NULL, 'V'},
565 {"windows-compatibility", no_argument, NULL, 'W'},
566 {"x-height-snapping-exceptions", required_argument, NULL, 'X'},
568 // Qt options
569 {"graphicssystem", required_argument, NULL, PASS_THROUGH},
570 {"reverse", no_argument, NULL, PASS_THROUGH},
571 {"session", required_argument, NULL, PASS_THROUGH},
572 {"style", required_argument, NULL, PASS_THROUGH},
573 {"stylesheet", required_argument, NULL, PASS_THROUGH},
575 // X11 options
576 {"background", required_argument, NULL, PASS_THROUGH},
577 {"bg", required_argument, NULL, PASS_THROUGH},
578 {"btn", required_argument, NULL, PASS_THROUGH},
579 {"button", required_argument, NULL, PASS_THROUGH},
580 {"cmap", no_argument, NULL, PASS_THROUGH},
581 {"display", required_argument, NULL, PASS_THROUGH},
582 {"fg", required_argument, NULL, PASS_THROUGH},
583 {"fn", required_argument, NULL, PASS_THROUGH},
584 {"font", required_argument, NULL, PASS_THROUGH},
585 {"foreground", required_argument, NULL, PASS_THROUGH},
586 {"geometry", required_argument, NULL, PASS_THROUGH},
587 {"im", required_argument, NULL, PASS_THROUGH},
588 {"inputstyle", required_argument, NULL, PASS_THROUGH},
589 {"name", required_argument, NULL, PASS_THROUGH},
590 {"ncols", required_argument, NULL, PASS_THROUGH},
591 {"title", required_argument, NULL, PASS_THROUGH},
592 {"visual", required_argument, NULL, PASS_THROUGH},
594 {NULL, 0, NULL, 0}
597 int option_index;
598 int c = getopt_long_only(argc, argv,
599 #ifdef BUILD_GUI
600 "cdD:f:G:hH:il:npr:stVvw:Wx:X:",
601 #else
602 "cdD:f:G:hH:il:m:npr:stVvw:Wx:X:",
603 #endif
604 long_options, &option_index);
605 if (c == -1)
606 break;
608 switch (c)
610 case 'c':
611 hint_composites = true;
612 break;
614 case 'd':
615 dehint = true;
616 break;
618 case 'D':
619 default_script = optarg;
620 have_default_script = true;
621 break;
623 case 'f':
624 fallback_script = optarg;
625 have_fallback_script = true;
626 break;
628 case 'G':
629 hinting_limit = atoi(optarg);
630 have_hinting_limit = true;
631 break;
633 case 'h':
634 #ifdef CONSOLE_OUTPUT
635 show_help(false, false);
636 #endif
637 break;
639 case 'H':
640 fallback_stem_width = atoi(optarg);
641 have_fallback_stem_width = true;
642 break;
644 case 'i':
645 ignore_restrictions = true;
646 break;
648 case 'l':
649 hinting_range_min = atoi(optarg);
650 have_hinting_range_min = true;
651 break;
653 #ifndef BUILD_GUI
654 case 'm':
655 control_name = optarg;
656 break;
657 #endif
659 case 'n':
660 no_info = true;
661 break;
663 case 'p':
664 adjust_subglyphs = true;
665 break;
667 case 'r':
668 hinting_range_max = atoi(optarg);
669 have_hinting_range_max = true;
670 break;
672 case 's':
673 symbol = true;
674 break;
676 case 't':
677 TTFA_info = true;
678 break;
680 case 'v':
681 #ifndef BUILD_GUI
682 progress_func = progress;
683 #endif
684 break;
686 case 'V':
687 #ifdef CONSOLE_OUTPUT
688 show_version();
689 #endif
690 break;
692 case 'w':
693 gray_strong_stem_width = strchr(optarg, 'g') ? true : false;
694 gdi_cleartype_strong_stem_width = strchr(optarg, 'G') ? true : false;
695 dw_cleartype_strong_stem_width = strchr(optarg, 'D') ? true : false;
696 break;
698 case 'W':
699 windows_compatibility = true;
700 break;
702 case 'x':
703 increase_x_height = atoi(optarg);
704 have_increase_x_height = true;
705 break;
707 case 'X':
708 x_height_snapping_exceptions_string = optarg;
709 have_x_height_snapping_exceptions_string = true;
710 break;
712 #ifndef BUILD_GUI
713 case DEBUG_OPTION:
714 debug = true;
715 break;
716 #endif
718 #ifdef BUILD_GUI
719 case HELP_ALL_OPTION:
720 #ifdef CONSOLE_OUTPUT
721 show_help(true, false);
722 #endif
723 break;
724 #endif
726 case PASS_THROUGH:
728 // append argument with proper syntax for Qt
729 string arg;
730 arg += '-';
731 arg += long_options[option_index].name;
733 new_arg_string.push_back(arg);
734 if (optarg)
735 new_arg_string.push_back(optarg);
736 break;
739 default:
740 exit(EXIT_FAILURE);
744 if (dehint)
746 // -d makes ttfautohint ignore all other hinting options
747 have_default_script = false;
748 have_fallback_script = false;
749 have_fallback_stem_width = false;
750 have_hinting_range_max = false;
751 have_hinting_range_min = false;
752 have_hinting_limit = false;
753 have_increase_x_height = false;
754 have_x_height_snapping_exceptions_string = false;
757 if (!have_default_script)
758 default_script = "latn";
759 if (!have_fallback_script)
760 fallback_script = "none";
761 if (!have_hinting_range_min)
762 hinting_range_min = TA_HINTING_RANGE_MIN;
763 if (!have_hinting_range_max)
764 hinting_range_max = TA_HINTING_RANGE_MAX;
765 if (!have_hinting_limit)
766 hinting_limit = TA_HINTING_LIMIT;
767 if (!have_increase_x_height)
768 increase_x_height = TA_INCREASE_X_HEIGHT;
769 if (!have_x_height_snapping_exceptions_string)
770 x_height_snapping_exceptions_string = "";
771 if (!have_fallback_stem_width)
772 fallback_stem_width = 0; /* redundant, but avoids a compiler warning */
774 #ifndef BUILD_GUI
776 if (!isatty(fileno(stderr)) && !debug)
777 setvbuf(stderr, (char*)NULL, _IONBF, BUFSIZ);
779 if (hinting_range_min < 2)
781 fprintf(stderr, "The hinting range minimum must be at least 2\n");
782 exit(EXIT_FAILURE);
784 if (hinting_range_max < hinting_range_min)
786 fprintf(stderr, "The hinting range maximum must not be smaller"
787 " than the minimum (%d)\n",
788 hinting_range_min);
789 exit(EXIT_FAILURE);
791 if (hinting_limit != 0 && hinting_limit < hinting_range_max)
793 fprintf(stderr, "A non-zero hinting limit must not be smaller"
794 " than the hinting range maximum (%d)\n",
795 hinting_range_max);
796 exit(EXIT_FAILURE);
798 if (increase_x_height != 0 && increase_x_height < 6)
800 fprintf(stderr, "A non-zero x height increase limit"
801 " must be larger than or equal to 6\n");
802 exit(EXIT_FAILURE);
804 if (have_fallback_stem_width && fallback_stem_width <= 0)
806 fprintf(stderr, "The fallback stem width"
807 " must be a positive integer\n");
808 exit(EXIT_FAILURE);
811 if (have_default_script)
813 const Script_Names* sn;
815 for (sn = script_names; sn->tag; sn++)
816 if (!strcmp(default_script, sn->tag))
817 break;
818 if (!sn->tag)
820 fprintf(stderr, "Unknown script tag `%s'\n", default_script);
821 exit(EXIT_FAILURE);
825 if (have_fallback_script)
827 const Script_Names* sn;
829 for (sn = script_names; sn->tag; sn++)
830 if (!strcmp(fallback_script, sn->tag))
831 break;
832 if (!sn->tag)
834 fprintf(stderr, "Unknown script tag `%s'\n", fallback_script);
835 exit(EXIT_FAILURE);
839 if (symbol
840 && have_fallback_stem_width
841 && !strcmp(fallback_script, "none"))
842 fprintf(stderr,
843 "Warning: Setting a fallback stem width for a symbol font\n"
844 " without setting a fallback script has no effect\n");
846 int num_args = argc - optind;
848 if (num_args > 2)
849 show_help(false, true);
851 FILE* in;
852 if (num_args > 0)
854 in = fopen(argv[optind], "rb");
855 if (!in)
857 fprintf(stderr,
858 "The following error occurred while opening font `%s':\n"
859 "\n"
860 " %s\n",
861 argv[optind], strerror(errno));
862 exit(EXIT_FAILURE);
865 else
867 if (isatty(fileno(stdin)))
868 show_help(false, true);
869 in = stdin;
872 FILE* out;
873 if (num_args > 1)
875 if (!strcmp(argv[optind], argv[optind + 1]))
877 fprintf(stderr, "Input and output file names must not be identical\n");
878 exit(EXIT_FAILURE);
881 out = fopen(argv[optind + 1], "wb");
882 if (!out)
884 fprintf(stderr,
885 "The following error occurred while opening font `%s':\n"
886 "\n"
887 " %s\n",
888 argv[optind + 1], strerror(errno));
889 exit(EXIT_FAILURE);
892 else
894 if (isatty(fileno(stdout)))
895 show_help(false, true);
896 out = stdout;
899 FILE* control = NULL;
900 if (control_name)
902 control = fopen(control_name, "r");
903 if (!control)
905 fprintf(stderr,
906 "The following error occurred while open control file `%s':\n"
907 "\n"
908 " %s\n",
909 control_name, strerror(errno));
910 exit(EXIT_FAILURE);
913 else
914 control = NULL;
916 Progress_Data progress_data = {-1, 1, 0};
917 Error_Data error_data = {control_name};
918 Info_Data info_data;
920 if (no_info)
921 info_func = NULL;
922 else
924 info_data.data = NULL; // must be deallocated after use
925 info_data.data_wide = NULL; // must be deallocated after use
926 info_data.data_len = 0;
927 info_data.data_wide_len = 0;
929 info_data.control_name = control_name;
931 info_data.hinting_range_min = hinting_range_min;
932 info_data.hinting_range_max = hinting_range_max;
933 info_data.hinting_limit = hinting_limit;
935 info_data.gray_strong_stem_width = gray_strong_stem_width;
936 info_data.gdi_cleartype_strong_stem_width = gdi_cleartype_strong_stem_width;
937 info_data.dw_cleartype_strong_stem_width = dw_cleartype_strong_stem_width;
939 info_data.windows_compatibility = windows_compatibility;
940 info_data.adjust_subglyphs = adjust_subglyphs;
941 info_data.hint_composites = hint_composites;
942 info_data.increase_x_height = increase_x_height;
943 info_data.x_height_snapping_exceptions_string = x_height_snapping_exceptions_string;
944 info_data.fallback_stem_width = fallback_stem_width;
945 info_data.symbol = symbol;
946 info_data.TTFA_info = TTFA_info;
948 strncpy(info_data.default_script,
949 default_script,
950 sizeof (info_data.default_script));
951 strncpy(info_data.fallback_script,
952 fallback_script,
953 sizeof (info_data.fallback_script));
955 info_data.dehint = dehint;
957 int ret = build_version_string(&info_data);
958 if (ret == 1)
959 fprintf(stderr, "Warning: Can't allocate memory"
960 " for ttfautohint options string in `name' table\n");
961 else if (ret == 2)
962 fprintf(stderr, "Warning: ttfautohint options string"
963 " in `name' table too long\n");
966 if (in == stdin)
967 SET_BINARY(stdin);
968 if (out == stdout)
969 SET_BINARY(stdout);
971 TA_Error error =
972 TTF_autohint("in-file, out-file, control-file,"
973 "hinting-range-min, hinting-range-max, hinting-limit,"
974 "gray-strong-stem-width, gdi-cleartype-strong-stem-width,"
975 "dw-cleartype-strong-stem-width,"
976 "progress-callback, progress-callback-data,"
977 "error-callback, error-callback-data,"
978 "info-callback, info-callback-data,"
979 "ignore-restrictions, windows-compatibility,"
980 "adjust-subglyphs, hint-composites,"
981 "increase-x-height, x-height-snapping-exceptions,"
982 "fallback-stem-width, default-script, fallback-script,"
983 "symbol, dehint, debug, TTFA-info",
984 in, out, control,
985 hinting_range_min, hinting_range_max, hinting_limit,
986 gray_strong_stem_width, gdi_cleartype_strong_stem_width,
987 dw_cleartype_strong_stem_width,
988 progress_func, &progress_data,
989 err_func, &error_data,
990 info_func, &info_data,
991 ignore_restrictions, windows_compatibility,
992 adjust_subglyphs, hint_composites,
993 increase_x_height, x_height_snapping_exceptions_string,
994 fallback_stem_width, default_script, fallback_script,
995 symbol, dehint, debug, TTFA_info);
997 if (!no_info)
999 free(info_data.data);
1000 free(info_data.data_wide);
1003 if (in != stdin)
1004 fclose(in);
1005 if (out != stdout)
1006 fclose(out);
1007 if (control)
1008 fclose(control);
1010 exit(error ? EXIT_FAILURE : EXIT_SUCCESS);
1012 return 0; // never reached
1014 #else // BUILD_GUI
1016 int new_argc = new_arg_string.size();
1017 char** new_argv = new char*[new_argc];
1019 // construct new argc and argv variables from collected data
1020 for (int i = 0; i < new_argc; i++)
1021 new_argv[i] = const_cast<char*>(new_arg_string[i].data());
1023 QApplication app(new_argc, new_argv);
1024 app.setApplicationName("TTFautohint");
1025 app.setApplicationVersion(VERSION);
1026 app.setOrganizationName("FreeType");
1027 app.setOrganizationDomain("freetype.org");
1029 bool alternative_layout = false;
1031 // Display the window off the screen -- to get proper window dimensions
1032 // including the frame, the window manager must have a chance to
1033 // decorate it.
1035 // We don't want to change the default window positioning algorithm of
1036 // the platform's window manager, so we create the main GUI window
1037 // twice.
1039 // The original idea, however, was to simply move the off-screen window
1040 // back to the screen with
1042 // gui.move(100, 100);
1043 // gui.setAttribute(Qt::WA_Moved, false);
1044 // gui.show();
1046 // (unsetting the `WA_Moved' attribute makes the window manager handle
1047 // the previous call to `move' as a position suggestion instead of a
1048 // request). Unfortuntely, there seems to be a bug in Qt 4.8.4 which
1049 // prevents any effect of unsetting `WA_Moved' if `show' has already
1050 // been called.
1052 Main_GUI dummy(alternative_layout,
1053 hinting_range_min, hinting_range_max, hinting_limit,
1054 gray_strong_stem_width, gdi_cleartype_strong_stem_width,
1055 dw_cleartype_strong_stem_width, increase_x_height,
1056 x_height_snapping_exceptions_string, fallback_stem_width,
1057 ignore_restrictions, windows_compatibility, adjust_subglyphs,
1058 hint_composites, no_info, default_script, fallback_script,
1059 symbol, dehint, TTFA_info);
1061 dummy.move(-50000, -50000);
1062 dummy.show();
1064 // if the vertical size of our window is too large,
1065 // select a horizontal layout
1066 QRect screen(QApplication::desktop()->availableGeometry());
1067 if (dummy.frameGeometry().height() > screen.width())
1068 alternative_layout = true;
1071 Main_GUI gui(alternative_layout,
1072 hinting_range_min, hinting_range_max, hinting_limit,
1073 gray_strong_stem_width, gdi_cleartype_strong_stem_width,
1074 dw_cleartype_strong_stem_width, increase_x_height,
1075 x_height_snapping_exceptions_string, fallback_stem_width,
1076 ignore_restrictions, windows_compatibility, adjust_subglyphs,
1077 hint_composites, no_info, default_script, fallback_script,
1078 symbol, dehint, TTFA_info);
1079 gui.show();
1081 return app.exec();
1083 #endif // BUILD_GUI
1086 // end of main.cpp