Minor.
[ttfautohint.git] / frontend / main.cpp
blob70fa3eab35dd72e370e5d32db95b733f4c98baeb
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 void
136 err(TA_Error error,
137 const char* error_string,
138 unsigned int /* linenum */,
139 const char* line,
140 const char* errpos,
141 void* /* error_data */)
143 if (!error)
144 return;
146 // We replace some terse error strings with more user-friendly versions.
147 if (error == TA_Err_Invalid_FreeType_Version)
148 fprintf(stderr,
149 "FreeType version 2.4.5 or higher is needed.\n"
150 "Perhaps using a wrong FreeType DLL?\n");
151 else if (error == TA_Err_Invalid_Font_Type)
152 fprintf(stderr,
153 "This font is not a valid font"
154 " in SFNT format with TrueType outlines.\n"
155 "In particular, CFF outlines are not supported.\n");
156 else if (error == TA_Err_Already_Processed)
157 fprintf(stderr,
158 "This font has already been processed with ttfautohint.\n");
159 else if (error == TA_Err_Missing_Legal_Permission)
160 fprintf(stderr,
161 "Bit 1 in the `fsType' field of the `OS/2' table is set:\n"
162 "This font must not be modified"
163 " without permission of the legal owner.\n"
164 "Use command line option `-i' to continue"
165 " if you have such a permission.\n");
166 else if (error == TA_Err_Missing_Unicode_CMap)
167 fprintf(stderr,
168 "No Unicode character map.\n");
169 else if (error == TA_Err_Missing_Symbol_CMap)
170 fprintf(stderr,
171 "No symbol character map.\n");
172 else if (error == TA_Err_Missing_Glyph)
173 fprintf(stderr,
174 "No glyph for a standard character"
175 " to derive standard width and height.\n"
176 "Please check the documentation for a list of"
177 " script-specific standard characters,\n"
178 "or use option `--symbol'.\n");
179 else
181 if (error < 0x100)
182 fprintf(stderr, "An error with code 0x%02x occurred"
183 " while autohinting fonts",
184 error);
185 else if (error >= 0x100 && error < 0x200)
186 fprintf(stderr, "An error with code 0x%03x occurred"
187 " while parsing the argument of option `-X'",
188 error);
189 fprintf(stderr, (error_string || line) ? ":\n" : ".\n");
190 if (error_string)
191 fprintf(stderr, " %s\n", error_string);
192 if (line)
193 fprintf(stderr, " %s\n", line);
194 if (errpos && line)
195 fprintf(stderr, " %*s\n", int(errpos - line + 1), "^");
200 } // extern "C"
201 #endif // !BUILD_GUI
204 #ifdef CONSOLE_OUTPUT
205 static void
206 show_help(bool
207 #ifdef BUILD_GUI
209 #endif
211 bool is_error)
213 FILE* handle = is_error ? stderr : stdout;
215 fprintf(handle,
216 #ifdef BUILD_GUI
217 "Usage: ttfautohintGUI [OPTION]...\n"
218 "A GUI application to replace hints in a TrueType font.\n"
219 #else
220 "Usage: ttfautohint [OPTION]... [IN-FILE [OUT-FILE]]\n"
221 "Replace hints in TrueType font IN-FILE and write output to OUT-FILE.\n"
222 "If OUT-FILE is missing, standard output is used instead;\n"
223 "if IN-FILE is missing also, standard input and output are used.\n"
224 #endif
225 "\n"
226 "The new hints are based on FreeType's auto-hinter.\n"
227 "\n"
228 "This program is a simple front-end to the `ttfautohint' library.\n"
229 "\n");
231 fprintf(handle,
232 "Long options can be given with one or two dashes,\n"
233 "and with and without equal sign between option and argument.\n"
234 "This means that the following forms are acceptable:\n"
235 "`-foo=bar', `--foo=bar', `-foo bar', `--foo bar'.\n"
236 "\n"
237 "Mandatory arguments to long options are mandatory for short options too.\n"
238 #ifdef BUILD_GUI
239 "Options not related to Qt or X11 set default values.\n"
240 #endif
241 "\n"
244 fprintf(handle,
245 "Options:\n"
246 #ifndef BUILD_GUI
247 " --debug print debugging information\n"
248 #endif
249 " -c, --composites hint glyph composites also\n"
250 " -d, --dehint remove all hints\n"
251 " -D, --default-script=S set default OpenType script (default: latn)\n"
252 " -f, --fallback-script=S set fallback script (default: none)\n"
253 " -G, --hinting-limit=N switch off hinting above this PPEM value\n"
254 " (default: %d); value 0 means no limit\n"
255 " -h, --help display this help and exit\n"
256 " -H, --fallback-stem-width=N\n"
257 " set fallback stem width\n"
258 " (default: 50 font units at 2048 UPEM)\n"
259 #ifdef BUILD_GUI
260 " --help-all show Qt and X11 specific options also\n"
261 #endif
262 " -i, --ignore-restrictions override font license restrictions\n"
263 " -l, --hinting-range-min=N the minimum PPEM value for hint sets\n"
264 " (default: %d)\n"
265 #ifndef BUILD_GUI
266 " -m, --deltas-file=FILE get delta exceptions from FILE\n"
267 #endif
268 " -n, --no-info don't add ttfautohint info\n"
269 " to the version string(s) in the `name' table\n"
270 " -p, --adjust-subglyphs handle subglyph adjustments in exotic fonts\n",
271 TA_HINTING_LIMIT, TA_HINTING_RANGE_MIN);
272 fprintf(handle,
273 " -r, --hinting-range-max=N the maximum PPEM value for hint sets\n"
274 " (default: %d)\n"
275 " -s, --symbol input is symbol font\n"
276 " -v, --verbose show progress information\n"
277 " -V, --version print version information and exit\n"
278 " -w, --strong-stem-width=S use strong stem width routine for modes S,\n"
279 " where S is a string of up to three letters\n"
280 " with possible values `g' for grayscale,\n"
281 " `G' for GDI ClearType, and `D' for\n"
282 " DirectWrite ClearType (default: G)\n"
283 " -W, --windows-compatibility\n"
284 " add blue zones for `usWinAscent' and\n"
285 " `usWinDescent' to avoid clipping\n"
286 " -x, --increase-x-height=N increase x height for sizes in the range\n"
287 " 6<=PPEM<=N; value 0 switches off this feature\n"
288 " (default: %d)\n"
289 " -X, --x-height-snapping-exceptions=STRING\n"
290 " specify a comma-separated list of\n"
291 " x-height snapping exceptions, for example\n"
292 " \"-9, 13-17, 19\" (default: \"\")\n"
293 "\n",
294 TA_HINTING_RANGE_MAX, TA_INCREASE_X_HEIGHT);
296 #ifdef BUILD_GUI
297 if (all)
299 fprintf(handle,
300 "Qt Options:\n"
301 " --graphicssystem=SYSTEM\n"
302 " select a different graphics system backend\n"
303 " instead of the default one\n"
304 " (possible values: `raster', `opengl')\n"
305 " --reverse set layout direction to right-to-left\n");
306 fprintf(handle,
307 " --session=ID restore the application for the given ID\n"
308 " --style=STYLE set application GUI style\n"
309 " (possible values: motif, windows, platinum)\n"
310 " --stylesheet=SHEET apply the given Qt stylesheet\n"
311 " to the application widgets\n"
312 "\n");
314 fprintf(handle,
315 "X11 options:\n"
316 " --background=COLOR set the default background color\n"
317 " and an application palette\n"
318 " (light and dark shades are calculated)\n"
319 " --bg=COLOR same as --background\n"
320 " --btn=COLOR set the default button color\n"
321 " --button=COLOR same as --btn\n"
322 " --cmap use a private color map on an 8-bit display\n"
323 " --display=NAME use the given X-server display\n");
324 fprintf(handle,
325 " --fg=COLOR set the default foreground color\n"
326 " --fn=FONTNAME set the application font\n"
327 " --font=FONTNAME same as --fn\n"
328 " --foreground=COLOR same as --fg\n"
329 " --geometry=GEOMETRY set the client geometry of first window\n"
330 " --im=SERVER set the X Input Method (XIM) server\n"
331 " --inputstyle=STYLE set X Input Method input style\n"
332 " (possible values: onthespot, overthespot,\n"
333 " offthespot, root)\n");
334 fprintf(handle,
335 " --name=NAME set the application name\n"
336 " --ncols=COUNT limit the number of colors allocated\n"
337 " in the color cube on an 8-bit display,\n"
338 " if the application is using the\n"
339 " QApplication::ManyColor color specification\n"
340 " --title=TITLE set the application title (caption)\n"
341 " --visual=VISUAL force the application\n"
342 " to use the given visual on an 8-bit display\n"
343 " (only possible value: TrueColor)\n"
344 "\n");
346 #endif // BUILD_GUI
348 fprintf(handle,
349 "The program accepts both TTF and TTC files as input.\n"
350 "Use option -i only if you have a legal permission to modify the font.\n"
351 "The used PPEM value for option -p is FUnits per em, normally 2048.\n"
352 "With option -s, use default values for standard stem width and height,\n"
353 "otherwise they are derived from script-specific characters\n"
354 "resembling the shape of character `o'.\n"
355 "\n");
356 fprintf(handle,
357 "A hint set contains the optimal hinting for a certain PPEM value;\n"
358 "the larger the hint set range (as given by options -l and -r),\n"
359 "the more hint sets get computed, usually increasing the output font size.\n"
360 "The `gasp' table of the output file always enables grayscale hinting\n"
361 "for all sizes (limited by option -G, which is handled in the bytecode).\n"
362 "Increasing the value of -G does not increase the output font size.\n"
363 "\n");
364 fprintf(handle,
365 "Options -f and -D take a four-letter string that identifies a script.\n"
366 "Option -f sets the script used as a fallback for glyphs that have\n"
367 "character codes outside of known script ranges. Option -D sets the\n"
368 "default script for handling OpenType features. Possible values are\n"
369 "\n");
370 const Script_Names* sn = script_names;
371 for(;;)
373 fprintf(handle, " %s (%s)",
374 sn->tag, sn->description);
375 sn++;
376 if (sn->tag)
377 fprintf(handle, ",\n");
378 else
380 fprintf(handle, ".\n");
381 break;
384 fprintf(handle,
385 #ifndef BUILD_GUI
386 "\n"
387 "A delta exceptions file contains lines of the form\n"
388 "\n"
389 " [<subfont idx>] <glyph id> p <points> [x <shift>] [y <shift>] @ <ppems>\n"
390 "\n"
391 "to fine-tune point positions after hinting. <glyph id> is a glyph name\n"
392 "or index, <shift> is in px, <points> and <ppems> are ranges as with\n"
393 "option `-X'. `#' starts a line comment, which gets ignored.\n"
394 "Empty lines are ignored, too.\n"
395 #endif
396 "\n"
397 #ifdef BUILD_GUI
398 "A command-line version of this program is called `ttfautohint'.\n"
399 #else
400 "A GUI version of this program is called `ttfautohintGUI'.\n"
401 #endif
402 "\n"
403 "Report bugs to: freetype-devel@nongnu.org\n"
404 "ttfautohint home page: <http://www.freetype.org/ttfautohint>\n");
406 if (is_error)
407 exit(EXIT_FAILURE);
408 else
409 exit(EXIT_SUCCESS);
413 static void
414 show_version()
416 fprintf(stdout,
417 #ifdef BUILD_GUI
418 "ttfautohintGUI " VERSION "\n"
419 #else
420 "ttfautohint " VERSION "\n"
421 #endif
422 "Copyright (C) 2011-2014 Werner Lemberg <wl@gnu.org>.\n"
423 "License: FreeType License (FTL) or GNU GPLv2.\n"
424 "This is free software: you are free to change and redistribute it.\n"
425 "There is NO WARRANTY, to the extent permitted by law.\n");
427 exit(EXIT_SUCCESS);
429 #endif // CONSOLE_OUTPUT
433 main(int argc,
434 char** argv)
436 int hinting_range_min = 0;
437 int hinting_range_max = 0;
438 int hinting_limit = 0;
439 int increase_x_height = 0;
440 int fallback_stem_width = 0;
442 bool have_hinting_range_min = false;
443 bool have_hinting_range_max = false;
444 bool have_hinting_limit = false;
445 bool have_increase_x_height = false;
446 bool have_fallback_stem_width = false;
448 bool gray_strong_stem_width = false;
449 bool gdi_cleartype_strong_stem_width = true;
450 bool dw_cleartype_strong_stem_width = false;
452 bool ignore_restrictions = false;
453 bool windows_compatibility = false;
454 bool adjust_subglyphs = false;
455 bool hint_composites = false;
456 bool no_info = false;
457 bool symbol = false;
459 const char* default_script = NULL;
460 bool have_default_script = false;
461 const char* fallback_script = NULL;
462 bool have_fallback_script = false;
463 const char* x_height_snapping_exceptions_string = NULL;
464 bool have_x_height_snapping_exceptions_string = false;
466 bool dehint = false;
468 #ifndef BUILD_GUI
469 bool debug = false;
471 TA_Progress_Func progress_func = NULL;
472 TA_Error_Func err_func = err;
473 TA_Info_Func info_func = info;
475 const char* deltas_name = NULL;
476 #endif
478 // make GNU, Qt, and X11 command line options look the same;
479 // we allow `--foo=bar', `--foo bar', `-foo=bar', `-foo bar',
480 // and short options specific to ttfautohint
482 // set up a new argument string
483 vector<string> new_arg_string;
484 new_arg_string.push_back(argv[0]);
486 while (1)
488 // use pseudo short options for long-only options
489 enum
491 PASS_THROUGH = CHAR_MAX + 1,
492 HELP_ALL_OPTION,
493 DEBUG_OPTION
496 static struct option long_options[] =
498 {"help", no_argument, NULL, 'h'},
499 #ifdef BUILD_GUI
500 {"help-all", no_argument, NULL, HELP_ALL_OPTION},
501 #endif
503 // ttfautohint options
504 {"adjust-subglyphs", no_argument, NULL, 'p'},
505 {"composites", no_argument, NULL, 'c'},
506 #ifndef BUILD_GUI
507 {"debug", no_argument, NULL, DEBUG_OPTION},
508 #endif
509 {"default-script", required_argument, NULL, 'D'},
510 {"dehint", no_argument, NULL, 'd'},
511 #ifndef BUILD_GUI
512 {"deltas-file", required_argument, NULL, 'm'},
513 #endif
514 {"fallback-script", required_argument, NULL, 'f'},
515 {"hinting-limit", required_argument, NULL, 'G'},
516 {"hinting-range-max", required_argument, NULL, 'r'},
517 {"hinting-range-min", required_argument, NULL, 'l'},
518 {"ignore-restrictions", no_argument, NULL, 'i'},
519 {"increase-x-height", required_argument, NULL, 'x'},
520 {"no-info", no_argument, NULL, 'n'},
521 {"pre-hinting", no_argument, NULL, 'p'},
522 {"strong-stem-width", required_argument, NULL, 'w'},
523 {"symbol", no_argument, NULL, 's'},
524 {"fallback-stem-width", required_argument, NULL, 'H'},
525 {"verbose", no_argument, NULL, 'v'},
526 {"version", no_argument, NULL, 'V'},
527 {"windows-compatibility", no_argument, NULL, 'W'},
528 {"x-height-snapping-exceptions", required_argument, NULL, 'X'},
530 // Qt options
531 {"graphicssystem", required_argument, NULL, PASS_THROUGH},
532 {"reverse", no_argument, NULL, PASS_THROUGH},
533 {"session", required_argument, NULL, PASS_THROUGH},
534 {"style", required_argument, NULL, PASS_THROUGH},
535 {"stylesheet", required_argument, NULL, PASS_THROUGH},
537 // X11 options
538 {"background", required_argument, NULL, PASS_THROUGH},
539 {"bg", required_argument, NULL, PASS_THROUGH},
540 {"btn", required_argument, NULL, PASS_THROUGH},
541 {"button", required_argument, NULL, PASS_THROUGH},
542 {"cmap", no_argument, NULL, PASS_THROUGH},
543 {"display", required_argument, NULL, PASS_THROUGH},
544 {"fg", required_argument, NULL, PASS_THROUGH},
545 {"fn", required_argument, NULL, PASS_THROUGH},
546 {"font", required_argument, NULL, PASS_THROUGH},
547 {"foreground", required_argument, NULL, PASS_THROUGH},
548 {"geometry", required_argument, NULL, PASS_THROUGH},
549 {"im", required_argument, NULL, PASS_THROUGH},
550 {"inputstyle", required_argument, NULL, PASS_THROUGH},
551 {"name", required_argument, NULL, PASS_THROUGH},
552 {"ncols", required_argument, NULL, PASS_THROUGH},
553 {"title", required_argument, NULL, PASS_THROUGH},
554 {"visual", required_argument, NULL, PASS_THROUGH},
556 {NULL, 0, NULL, 0}
559 int option_index;
560 int c = getopt_long_only(argc, argv,
561 #ifdef BUILD_GUI
562 "cdD:f:G:hH:il:npr:stVvw:Wx:X:",
563 #else
564 "cdD:f:G:hH:il:m:npr:stVvw:Wx:X:",
565 #endif
566 long_options, &option_index);
567 if (c == -1)
568 break;
570 switch (c)
572 case 'c':
573 hint_composites = true;
574 break;
576 case 'd':
577 dehint = true;
578 break;
580 case 'D':
581 default_script = optarg;
582 have_default_script = true;
583 break;
585 case 'f':
586 fallback_script = optarg;
587 have_fallback_script = true;
588 break;
590 case 'G':
591 hinting_limit = atoi(optarg);
592 have_hinting_limit = true;
593 break;
595 case 'h':
596 #ifdef CONSOLE_OUTPUT
597 show_help(false, false);
598 #endif
599 break;
601 case 'H':
602 fallback_stem_width = atoi(optarg);
603 have_fallback_stem_width = true;
604 break;
606 case 'i':
607 ignore_restrictions = true;
608 break;
610 case 'l':
611 hinting_range_min = atoi(optarg);
612 have_hinting_range_min = true;
613 break;
615 #ifndef BUILD_GUI
616 case 'm':
617 deltas_name = optarg;
618 break;
619 #endif
621 case 'n':
622 no_info = true;
623 break;
625 case 'p':
626 adjust_subglyphs = true;
627 break;
629 case 'r':
630 hinting_range_max = atoi(optarg);
631 have_hinting_range_max = true;
632 break;
634 case 's':
635 symbol = true;
636 break;
638 case 'v':
639 #ifndef BUILD_GUI
640 progress_func = progress;
641 #endif
642 break;
644 case 'V':
645 #ifdef CONSOLE_OUTPUT
646 show_version();
647 #endif
648 break;
650 case 'w':
651 gray_strong_stem_width = strchr(optarg, 'g') ? true : false;
652 gdi_cleartype_strong_stem_width = strchr(optarg, 'G') ? true : false;
653 dw_cleartype_strong_stem_width = strchr(optarg, 'D') ? true : false;
654 break;
656 case 'W':
657 windows_compatibility = true;
658 break;
660 case 'x':
661 increase_x_height = atoi(optarg);
662 have_increase_x_height = true;
663 break;
665 case 'X':
666 x_height_snapping_exceptions_string = optarg;
667 have_x_height_snapping_exceptions_string = true;
668 break;
670 #ifndef BUILD_GUI
671 case DEBUG_OPTION:
672 debug = true;
673 break;
674 #endif
676 #ifdef BUILD_GUI
677 case HELP_ALL_OPTION:
678 #ifdef CONSOLE_OUTPUT
679 show_help(true, false);
680 #endif
681 break;
682 #endif
684 case PASS_THROUGH:
686 // append argument with proper syntax for Qt
687 string arg;
688 arg += '-';
689 arg += long_options[option_index].name;
691 new_arg_string.push_back(arg);
692 if (optarg)
693 new_arg_string.push_back(optarg);
694 break;
697 default:
698 exit(EXIT_FAILURE);
702 if (dehint)
704 // -d makes ttfautohint ignore all other hinting options
705 have_default_script = false;
706 have_fallback_script = false;
707 have_fallback_stem_width = false;
708 have_hinting_range_max = false;
709 have_hinting_range_min = false;
710 have_hinting_limit = false;
711 have_increase_x_height = false;
712 have_x_height_snapping_exceptions_string = false;
715 if (!have_default_script)
716 default_script = "latn";
717 if (!have_fallback_script)
718 fallback_script = "none";
719 if (!have_hinting_range_min)
720 hinting_range_min = TA_HINTING_RANGE_MIN;
721 if (!have_hinting_range_max)
722 hinting_range_max = TA_HINTING_RANGE_MAX;
723 if (!have_hinting_limit)
724 hinting_limit = TA_HINTING_LIMIT;
725 if (!have_increase_x_height)
726 increase_x_height = TA_INCREASE_X_HEIGHT;
727 if (!have_x_height_snapping_exceptions_string)
728 x_height_snapping_exceptions_string = "";
729 if (!have_fallback_stem_width)
730 fallback_stem_width = 0; /* redundant, but avoids a compiler warning */
732 #ifndef BUILD_GUI
734 if (!isatty(fileno(stderr)) && !debug)
735 setvbuf(stderr, (char*)NULL, _IONBF, BUFSIZ);
737 if (hinting_range_min < 2)
739 fprintf(stderr, "The hinting range minimum must be at least 2\n");
740 exit(EXIT_FAILURE);
742 if (hinting_range_max < hinting_range_min)
744 fprintf(stderr, "The hinting range maximum must not be smaller"
745 " than the minimum (%d)\n",
746 hinting_range_min);
747 exit(EXIT_FAILURE);
749 if (hinting_limit != 0 && hinting_limit < hinting_range_max)
751 fprintf(stderr, "A non-zero hinting limit must not be smaller"
752 " than the hinting range maximum (%d)\n",
753 hinting_range_max);
754 exit(EXIT_FAILURE);
756 if (increase_x_height != 0 && increase_x_height < 6)
758 fprintf(stderr, "A non-zero x height increase limit"
759 " must be larger than or equal to 6\n");
760 exit(EXIT_FAILURE);
762 if (have_fallback_stem_width && fallback_stem_width <= 0)
764 fprintf(stderr, "The fallback stem width"
765 " must be a positive integer\n");
766 exit(EXIT_FAILURE);
769 if (have_default_script)
771 const Script_Names* sn;
773 for (sn = script_names; sn->tag; sn++)
774 if (!strcmp(default_script, sn->tag))
775 break;
776 if (!sn->tag)
778 fprintf(stderr, "Unknown script tag `%s'\n", default_script);
779 exit(EXIT_FAILURE);
783 if (have_fallback_script)
785 const Script_Names* sn;
787 for (sn = script_names; sn->tag; sn++)
788 if (!strcmp(fallback_script, sn->tag))
789 break;
790 if (!sn->tag)
792 fprintf(stderr, "Unknown script tag `%s'\n", fallback_script);
793 exit(EXIT_FAILURE);
797 if (symbol
798 && have_fallback_stem_width
799 && !strcmp(fallback_script, "none"))
800 fprintf(stderr,
801 "Warning: Setting a fallback stem width for a symbol font\n"
802 " without setting a fallback script has no effect\n");
804 int num_args = argc - optind;
806 if (num_args > 2)
807 show_help(false, true);
809 FILE* in;
810 if (num_args > 0)
812 in = fopen(argv[optind], "rb");
813 if (!in)
815 fprintf(stderr,
816 "The following error occurred while opening font `%s':\n"
817 "\n"
818 " %s\n",
819 argv[optind], strerror(errno));
820 exit(EXIT_FAILURE);
823 else
825 if (isatty(fileno(stdin)))
826 show_help(false, true);
827 in = stdin;
830 FILE* out;
831 if (num_args > 1)
833 if (!strcmp(argv[optind], argv[optind + 1]))
835 fprintf(stderr, "Input and output file names must not be identical\n");
836 exit(EXIT_FAILURE);
839 out = fopen(argv[optind + 1], "wb");
840 if (!out)
842 fprintf(stderr,
843 "The following error occurred while opening font `%s':\n"
844 "\n"
845 " %s\n",
846 argv[optind + 1], strerror(errno));
847 exit(EXIT_FAILURE);
850 else
852 if (isatty(fileno(stdout)))
853 show_help(false, true);
854 out = stdout;
857 FILE* deltas = NULL;
858 if (deltas_name)
860 /* inspite of being a text file we open it in binary mode */
861 /* to make `TTF_autohint' handle different EOL conventions gracefully */
862 deltas = fopen(deltas_name, "rb");
863 if (!deltas)
865 fprintf(stderr,
866 "The following error occurred while open deltas file `%s':\n"
867 "\n"
868 " %s\n",
869 deltas_name, strerror(errno));
870 exit(EXIT_FAILURE);
873 else
874 deltas = NULL;
876 Progress_Data progress_data = {-1, 1, 0};
877 Info_Data info_data;
879 if (no_info)
880 info_func = NULL;
881 else
883 info_data.data = NULL; // must be deallocated after use
884 info_data.data_wide = NULL; // must be deallocated after use
885 info_data.data_len = 0;
886 info_data.data_wide_len = 0;
888 info_data.deltas_name = deltas_name;
890 info_data.hinting_range_min = hinting_range_min;
891 info_data.hinting_range_max = hinting_range_max;
892 info_data.hinting_limit = hinting_limit;
894 info_data.gray_strong_stem_width = gray_strong_stem_width;
895 info_data.gdi_cleartype_strong_stem_width = gdi_cleartype_strong_stem_width;
896 info_data.dw_cleartype_strong_stem_width = dw_cleartype_strong_stem_width;
898 info_data.windows_compatibility = windows_compatibility;
899 info_data.adjust_subglyphs = adjust_subglyphs;
900 info_data.hint_composites = hint_composites;
901 info_data.increase_x_height = increase_x_height;
902 info_data.x_height_snapping_exceptions_string = x_height_snapping_exceptions_string;
903 info_data.fallback_stem_width = fallback_stem_width;
904 info_data.symbol = symbol;
906 strncpy(info_data.default_script,
907 default_script,
908 sizeof (info_data.default_script));
909 strncpy(info_data.fallback_script,
910 fallback_script,
911 sizeof (info_data.fallback_script));
913 info_data.dehint = dehint;
915 int ret = build_version_string(&info_data);
916 if (ret == 1)
917 fprintf(stderr, "Warning: Can't allocate memory"
918 " for ttfautohint options string in `name' table\n");
919 else if (ret == 2)
920 fprintf(stderr, "Warning: ttfautohint options string"
921 " in `name' table too long\n");
924 if (in == stdin)
925 SET_BINARY(stdin);
926 if (out == stdout)
927 SET_BINARY(stdout);
929 TA_Error error =
930 TTF_autohint("in-file, out-file, deltas-file,"
931 "hinting-range-min, hinting-range-max, hinting-limit,"
932 "gray-strong-stem-width, gdi-cleartype-strong-stem-width,"
933 "dw-cleartype-strong-stem-width,"
934 "progress-callback, progress-callback-data,"
935 "error-callback,"
936 "info-callback, info-callback-data,"
937 "ignore-restrictions, windows-compatibility,"
938 "adjust-subglyphs, hint-composites,"
939 "increase-x-height, x-height-snapping-exceptions,"
940 "fallback-stem-width, default-script, fallback-script,"
941 "symbol, dehint, debug",
942 in, out, deltas,
943 hinting_range_min, hinting_range_max, hinting_limit,
944 gray_strong_stem_width, gdi_cleartype_strong_stem_width,
945 dw_cleartype_strong_stem_width,
946 progress_func, &progress_data,
947 err_func,
948 info_func, &info_data,
949 ignore_restrictions, windows_compatibility,
950 adjust_subglyphs, hint_composites,
951 increase_x_height, x_height_snapping_exceptions_string,
952 fallback_stem_width, default_script, fallback_script,
953 symbol, dehint, debug);
955 if (!no_info)
957 free(info_data.data);
958 free(info_data.data_wide);
961 if (in != stdin)
962 fclose(in);
963 if (out != stdout)
964 fclose(out);
965 if (deltas)
966 fclose(deltas);
968 exit(error ? EXIT_FAILURE : EXIT_SUCCESS);
970 return 0; // never reached
972 #else // BUILD_GUI
974 int new_argc = new_arg_string.size();
975 char** new_argv = new char*[new_argc];
977 // construct new argc and argv variables from collected data
978 for (int i = 0; i < new_argc; i++)
979 new_argv[i] = const_cast<char*>(new_arg_string[i].data());
981 QApplication app(new_argc, new_argv);
982 app.setApplicationName("TTFautohint");
983 app.setApplicationVersion(VERSION);
984 app.setOrganizationName("FreeType");
985 app.setOrganizationDomain("freetype.org");
987 bool alternative_layout = false;
989 // Display the window off the screen -- to get proper window dimensions
990 // including the frame, the window manager must have a chance to
991 // decorate it.
993 // We don't want to change the default window positioning algorithm of
994 // the platform's window manager, so we create the main GUI window
995 // twice.
997 // The original idea, however, was to simply move the off-screen window
998 // back to the screen with
1000 // gui.move(100, 100);
1001 // gui.setAttribute(Qt::WA_Moved, false);
1002 // gui.show();
1004 // (unsetting the `WA_Moved' attribute makes the window manager handle
1005 // the previous call to `move' as a position suggestion instead of a
1006 // request). Unfortuntely, there seems to be a bug in Qt 4.8.4 which
1007 // prevents any effect of unsetting `WA_Moved' if `show' has already
1008 // been called.
1010 Main_GUI dummy(alternative_layout,
1011 hinting_range_min, hinting_range_max, hinting_limit,
1012 gray_strong_stem_width, gdi_cleartype_strong_stem_width,
1013 dw_cleartype_strong_stem_width, increase_x_height,
1014 x_height_snapping_exceptions_string, fallback_stem_width,
1015 ignore_restrictions, windows_compatibility, adjust_subglyphs,
1016 hint_composites, no_info, default_script, fallback_script,
1017 symbol, dehint);
1019 dummy.move(-50000, -50000);
1020 dummy.show();
1022 // if the vertical size of our window is too large,
1023 // select a horizontal layout
1024 QRect screen(QApplication::desktop()->availableGeometry());
1025 if (dummy.frameGeometry().height() > screen.width())
1026 alternative_layout = true;
1029 Main_GUI gui(alternative_layout,
1030 hinting_range_min, hinting_range_max, hinting_limit,
1031 gray_strong_stem_width, gdi_cleartype_strong_stem_width,
1032 dw_cleartype_strong_stem_width, increase_x_height,
1033 x_height_snapping_exceptions_string, fallback_stem_width,
1034 ignore_restrictions, windows_compatibility, adjust_subglyphs,
1035 hint_composites, no_info, default_script, fallback_script,
1036 symbol, dehint);
1037 gui.show();
1039 return app.exec();
1041 #endif // BUILD_GUI
1044 // end of main.cpp