More fixes for error message handling.
[ttfautohint.git] / frontend / main.cpp
blobc11829a0a9998b872993608e65cd95d423025c5f
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 " -v, --verbose show progress information\n"
301 " -V, --version print version information and exit\n"
302 " -w, --strong-stem-width=S use strong stem width routine for modes S,\n"
303 " where S is a string of up to three letters\n"
304 " with possible values `g' for grayscale,\n"
305 " `G' for GDI ClearType, and `D' for\n"
306 " DirectWrite ClearType (default: G)\n"
307 " -W, --windows-compatibility\n"
308 " add blue zones for `usWinAscent' and\n"
309 " `usWinDescent' to avoid clipping\n"
310 " -x, --increase-x-height=N increase x height for sizes in the range\n"
311 " 6<=PPEM<=N; value 0 switches off this feature\n"
312 " (default: %d)\n"
313 " -X, --x-height-snapping-exceptions=STRING\n"
314 " specify a comma-separated list of\n"
315 " x-height snapping exceptions, for example\n"
316 " \"-9, 13-17, 19\" (default: \"\")\n"
317 "\n",
318 TA_HINTING_RANGE_MAX, TA_INCREASE_X_HEIGHT);
320 #ifdef BUILD_GUI
321 if (all)
323 fprintf(handle,
324 "Qt Options:\n"
325 " --graphicssystem=SYSTEM\n"
326 " select a different graphics system backend\n"
327 " instead of the default one\n"
328 " (possible values: `raster', `opengl')\n"
329 " --reverse set layout direction to right-to-left\n");
330 fprintf(handle,
331 " --session=ID restore the application for the given ID\n"
332 " --style=STYLE set application GUI style\n"
333 " (possible values: motif, windows, platinum)\n"
334 " --stylesheet=SHEET apply the given Qt stylesheet\n"
335 " to the application widgets\n"
336 "\n");
338 fprintf(handle,
339 "X11 options:\n"
340 " --background=COLOR set the default background color\n"
341 " and an application palette\n"
342 " (light and dark shades are calculated)\n"
343 " --bg=COLOR same as --background\n"
344 " --btn=COLOR set the default button color\n"
345 " --button=COLOR same as --btn\n"
346 " --cmap use a private color map on an 8-bit display\n"
347 " --display=NAME use the given X-server display\n");
348 fprintf(handle,
349 " --fg=COLOR set the default foreground color\n"
350 " --fn=FONTNAME set the application font\n"
351 " --font=FONTNAME same as --fn\n"
352 " --foreground=COLOR same as --fg\n"
353 " --geometry=GEOMETRY set the client geometry of first window\n"
354 " --im=SERVER set the X Input Method (XIM) server\n"
355 " --inputstyle=STYLE set X Input Method input style\n"
356 " (possible values: onthespot, overthespot,\n"
357 " offthespot, root)\n");
358 fprintf(handle,
359 " --name=NAME set the application name\n"
360 " --ncols=COUNT limit the number of colors allocated\n"
361 " in the color cube on an 8-bit display,\n"
362 " if the application is using the\n"
363 " QApplication::ManyColor color specification\n"
364 " --title=TITLE set the application title (caption)\n"
365 " --visual=VISUAL force the application\n"
366 " to use the given visual on an 8-bit display\n"
367 " (only possible value: TrueColor)\n"
368 "\n");
370 #endif // BUILD_GUI
372 fprintf(handle,
373 "The program accepts both TTF and TTC files as input.\n"
374 "Use option -i only if you have a legal permission to modify the font.\n"
375 "The used PPEM value for option -p is FUnits per em, normally 2048.\n"
376 "With option -s, use default values for standard stem width and height,\n"
377 "otherwise they are derived from script-specific characters\n"
378 "resembling the shape of character `o'.\n"
379 "\n");
380 fprintf(handle,
381 "A hint set contains the optimal hinting for a certain PPEM value;\n"
382 "the larger the hint set range (as given by options -l and -r),\n"
383 "the more hint sets get computed, usually increasing the output font size.\n"
384 "The `gasp' table of the output file always enables grayscale hinting\n"
385 "for all sizes (limited by option -G, which is handled in the bytecode).\n"
386 "Increasing the value of -G does not increase the output font size.\n"
387 "\n");
388 fprintf(handle,
389 "Options -f and -D take a four-letter string that identifies a script.\n"
390 "Option -f sets the script used as a fallback for glyphs that have\n"
391 "character codes outside of known script ranges. Option -D sets the\n"
392 "default script for handling OpenType features. Possible values are\n"
393 "\n");
394 const Script_Names* sn = script_names;
395 for(;;)
397 fprintf(handle, " %s (%s)",
398 sn->tag, sn->description);
399 sn++;
400 if (sn->tag)
401 fprintf(handle, ",\n");
402 else
404 fprintf(handle, ".\n");
405 break;
408 fprintf(handle,
409 #ifndef BUILD_GUI
410 "\n"
411 "A delta exceptions file contains lines of the form\n"
412 "\n"
413 " [<subfont idx>] <glyph id> p <points> [x <shift>] [y <shift>] @ <ppems>\n"
414 "\n"
415 "to fine-tune point positions after hinting. <glyph id> is a glyph name\n"
416 "or index, <shift> is in px, <points> and <ppems> are ranges as with\n"
417 "option `-X'. `#' starts a line comment, which gets ignored.\n"
418 "Empty lines are ignored, too.\n"
419 #endif
420 "\n"
421 #ifdef BUILD_GUI
422 "A command-line version of this program is called `ttfautohint'.\n"
423 #else
424 "A GUI version of this program is called `ttfautohintGUI'.\n"
425 #endif
426 "\n"
427 "Report bugs to: freetype-devel@nongnu.org\n"
428 "ttfautohint home page: <http://www.freetype.org/ttfautohint>\n");
430 if (is_error)
431 exit(EXIT_FAILURE);
432 else
433 exit(EXIT_SUCCESS);
437 static void
438 show_version()
440 fprintf(stdout,
441 #ifdef BUILD_GUI
442 "ttfautohintGUI " VERSION "\n"
443 #else
444 "ttfautohint " VERSION "\n"
445 #endif
446 "Copyright (C) 2011-2014 Werner Lemberg <wl@gnu.org>.\n"
447 "License: FreeType License (FTL) or GNU GPLv2.\n"
448 "This is free software: you are free to change and redistribute it.\n"
449 "There is NO WARRANTY, to the extent permitted by law.\n");
451 exit(EXIT_SUCCESS);
453 #endif // CONSOLE_OUTPUT
457 main(int argc,
458 char** argv)
460 int hinting_range_min = 0;
461 int hinting_range_max = 0;
462 int hinting_limit = 0;
463 int increase_x_height = 0;
464 int fallback_stem_width = 0;
466 bool have_hinting_range_min = false;
467 bool have_hinting_range_max = false;
468 bool have_hinting_limit = false;
469 bool have_increase_x_height = false;
470 bool have_fallback_stem_width = false;
472 bool gray_strong_stem_width = false;
473 bool gdi_cleartype_strong_stem_width = true;
474 bool dw_cleartype_strong_stem_width = false;
476 bool ignore_restrictions = false;
477 bool windows_compatibility = false;
478 bool adjust_subglyphs = false;
479 bool hint_composites = false;
480 bool no_info = false;
481 bool symbol = false;
483 const char* default_script = NULL;
484 bool have_default_script = false;
485 const char* fallback_script = NULL;
486 bool have_fallback_script = false;
487 const char* x_height_snapping_exceptions_string = NULL;
488 bool have_x_height_snapping_exceptions_string = false;
490 bool dehint = false;
492 #ifndef BUILD_GUI
493 bool debug = false;
495 TA_Progress_Func progress_func = NULL;
496 TA_Error_Func err_func = err;
497 TA_Info_Func info_func = info;
499 const char* deltas_name = NULL;
500 #endif
502 // make GNU, Qt, and X11 command line options look the same;
503 // we allow `--foo=bar', `--foo bar', `-foo=bar', `-foo bar',
504 // and short options specific to ttfautohint
506 // set up a new argument string
507 vector<string> new_arg_string;
508 new_arg_string.push_back(argv[0]);
510 while (1)
512 // use pseudo short options for long-only options
513 enum
515 PASS_THROUGH = CHAR_MAX + 1,
516 HELP_ALL_OPTION,
517 DEBUG_OPTION
520 static struct option long_options[] =
522 {"help", no_argument, NULL, 'h'},
523 #ifdef BUILD_GUI
524 {"help-all", no_argument, NULL, HELP_ALL_OPTION},
525 #endif
527 // ttfautohint options
528 {"adjust-subglyphs", no_argument, NULL, 'p'},
529 {"composites", no_argument, NULL, 'c'},
530 #ifndef BUILD_GUI
531 {"debug", no_argument, NULL, DEBUG_OPTION},
532 #endif
533 {"default-script", required_argument, NULL, 'D'},
534 {"dehint", no_argument, NULL, 'd'},
535 #ifndef BUILD_GUI
536 {"deltas-file", required_argument, NULL, 'm'},
537 #endif
538 {"fallback-script", required_argument, NULL, 'f'},
539 {"hinting-limit", required_argument, NULL, 'G'},
540 {"hinting-range-max", required_argument, NULL, 'r'},
541 {"hinting-range-min", required_argument, NULL, 'l'},
542 {"ignore-restrictions", no_argument, NULL, 'i'},
543 {"increase-x-height", required_argument, NULL, 'x'},
544 {"no-info", no_argument, NULL, 'n'},
545 {"pre-hinting", no_argument, NULL, 'p'},
546 {"strong-stem-width", required_argument, NULL, 'w'},
547 {"symbol", no_argument, NULL, 's'},
548 {"fallback-stem-width", required_argument, NULL, 'H'},
549 {"verbose", no_argument, NULL, 'v'},
550 {"version", no_argument, NULL, 'V'},
551 {"windows-compatibility", no_argument, NULL, 'W'},
552 {"x-height-snapping-exceptions", required_argument, NULL, 'X'},
554 // Qt options
555 {"graphicssystem", required_argument, NULL, PASS_THROUGH},
556 {"reverse", no_argument, NULL, PASS_THROUGH},
557 {"session", required_argument, NULL, PASS_THROUGH},
558 {"style", required_argument, NULL, PASS_THROUGH},
559 {"stylesheet", required_argument, NULL, PASS_THROUGH},
561 // X11 options
562 {"background", required_argument, NULL, PASS_THROUGH},
563 {"bg", required_argument, NULL, PASS_THROUGH},
564 {"btn", required_argument, NULL, PASS_THROUGH},
565 {"button", required_argument, NULL, PASS_THROUGH},
566 {"cmap", no_argument, NULL, PASS_THROUGH},
567 {"display", required_argument, NULL, PASS_THROUGH},
568 {"fg", required_argument, NULL, PASS_THROUGH},
569 {"fn", required_argument, NULL, PASS_THROUGH},
570 {"font", required_argument, NULL, PASS_THROUGH},
571 {"foreground", required_argument, NULL, PASS_THROUGH},
572 {"geometry", required_argument, NULL, PASS_THROUGH},
573 {"im", required_argument, NULL, PASS_THROUGH},
574 {"inputstyle", required_argument, NULL, PASS_THROUGH},
575 {"name", required_argument, NULL, PASS_THROUGH},
576 {"ncols", required_argument, NULL, PASS_THROUGH},
577 {"title", required_argument, NULL, PASS_THROUGH},
578 {"visual", required_argument, NULL, PASS_THROUGH},
580 {NULL, 0, NULL, 0}
583 int option_index;
584 int c = getopt_long_only(argc, argv,
585 #ifdef BUILD_GUI
586 "cdD:f:G:hH:il:npr:stVvw:Wx:X:",
587 #else
588 "cdD:f:G:hH:il:m:npr:stVvw:Wx:X:",
589 #endif
590 long_options, &option_index);
591 if (c == -1)
592 break;
594 switch (c)
596 case 'c':
597 hint_composites = true;
598 break;
600 case 'd':
601 dehint = true;
602 break;
604 case 'D':
605 default_script = optarg;
606 have_default_script = true;
607 break;
609 case 'f':
610 fallback_script = optarg;
611 have_fallback_script = true;
612 break;
614 case 'G':
615 hinting_limit = atoi(optarg);
616 have_hinting_limit = true;
617 break;
619 case 'h':
620 #ifdef CONSOLE_OUTPUT
621 show_help(false, false);
622 #endif
623 break;
625 case 'H':
626 fallback_stem_width = atoi(optarg);
627 have_fallback_stem_width = true;
628 break;
630 case 'i':
631 ignore_restrictions = true;
632 break;
634 case 'l':
635 hinting_range_min = atoi(optarg);
636 have_hinting_range_min = true;
637 break;
639 #ifndef BUILD_GUI
640 case 'm':
641 deltas_name = optarg;
642 break;
643 #endif
645 case 'n':
646 no_info = true;
647 break;
649 case 'p':
650 adjust_subglyphs = true;
651 break;
653 case 'r':
654 hinting_range_max = atoi(optarg);
655 have_hinting_range_max = true;
656 break;
658 case 's':
659 symbol = true;
660 break;
662 case 'v':
663 #ifndef BUILD_GUI
664 progress_func = progress;
665 #endif
666 break;
668 case 'V':
669 #ifdef CONSOLE_OUTPUT
670 show_version();
671 #endif
672 break;
674 case 'w':
675 gray_strong_stem_width = strchr(optarg, 'g') ? true : false;
676 gdi_cleartype_strong_stem_width = strchr(optarg, 'G') ? true : false;
677 dw_cleartype_strong_stem_width = strchr(optarg, 'D') ? true : false;
678 break;
680 case 'W':
681 windows_compatibility = true;
682 break;
684 case 'x':
685 increase_x_height = atoi(optarg);
686 have_increase_x_height = true;
687 break;
689 case 'X':
690 x_height_snapping_exceptions_string = optarg;
691 have_x_height_snapping_exceptions_string = true;
692 break;
694 #ifndef BUILD_GUI
695 case DEBUG_OPTION:
696 debug = true;
697 break;
698 #endif
700 #ifdef BUILD_GUI
701 case HELP_ALL_OPTION:
702 #ifdef CONSOLE_OUTPUT
703 show_help(true, false);
704 #endif
705 break;
706 #endif
708 case PASS_THROUGH:
710 // append argument with proper syntax for Qt
711 string arg;
712 arg += '-';
713 arg += long_options[option_index].name;
715 new_arg_string.push_back(arg);
716 if (optarg)
717 new_arg_string.push_back(optarg);
718 break;
721 default:
722 exit(EXIT_FAILURE);
726 if (dehint)
728 // -d makes ttfautohint ignore all other hinting options
729 have_default_script = false;
730 have_fallback_script = false;
731 have_fallback_stem_width = false;
732 have_hinting_range_max = false;
733 have_hinting_range_min = false;
734 have_hinting_limit = false;
735 have_increase_x_height = false;
736 have_x_height_snapping_exceptions_string = false;
739 if (!have_default_script)
740 default_script = "latn";
741 if (!have_fallback_script)
742 fallback_script = "none";
743 if (!have_hinting_range_min)
744 hinting_range_min = TA_HINTING_RANGE_MIN;
745 if (!have_hinting_range_max)
746 hinting_range_max = TA_HINTING_RANGE_MAX;
747 if (!have_hinting_limit)
748 hinting_limit = TA_HINTING_LIMIT;
749 if (!have_increase_x_height)
750 increase_x_height = TA_INCREASE_X_HEIGHT;
751 if (!have_x_height_snapping_exceptions_string)
752 x_height_snapping_exceptions_string = "";
753 if (!have_fallback_stem_width)
754 fallback_stem_width = 0; /* redundant, but avoids a compiler warning */
756 #ifndef BUILD_GUI
758 if (!isatty(fileno(stderr)) && !debug)
759 setvbuf(stderr, (char*)NULL, _IONBF, BUFSIZ);
761 if (hinting_range_min < 2)
763 fprintf(stderr, "The hinting range minimum must be at least 2\n");
764 exit(EXIT_FAILURE);
766 if (hinting_range_max < hinting_range_min)
768 fprintf(stderr, "The hinting range maximum must not be smaller"
769 " than the minimum (%d)\n",
770 hinting_range_min);
771 exit(EXIT_FAILURE);
773 if (hinting_limit != 0 && hinting_limit < hinting_range_max)
775 fprintf(stderr, "A non-zero hinting limit must not be smaller"
776 " than the hinting range maximum (%d)\n",
777 hinting_range_max);
778 exit(EXIT_FAILURE);
780 if (increase_x_height != 0 && increase_x_height < 6)
782 fprintf(stderr, "A non-zero x height increase limit"
783 " must be larger than or equal to 6\n");
784 exit(EXIT_FAILURE);
786 if (have_fallback_stem_width && fallback_stem_width <= 0)
788 fprintf(stderr, "The fallback stem width"
789 " must be a positive integer\n");
790 exit(EXIT_FAILURE);
793 if (have_default_script)
795 const Script_Names* sn;
797 for (sn = script_names; sn->tag; sn++)
798 if (!strcmp(default_script, sn->tag))
799 break;
800 if (!sn->tag)
802 fprintf(stderr, "Unknown script tag `%s'\n", default_script);
803 exit(EXIT_FAILURE);
807 if (have_fallback_script)
809 const Script_Names* sn;
811 for (sn = script_names; sn->tag; sn++)
812 if (!strcmp(fallback_script, sn->tag))
813 break;
814 if (!sn->tag)
816 fprintf(stderr, "Unknown script tag `%s'\n", fallback_script);
817 exit(EXIT_FAILURE);
821 if (symbol
822 && have_fallback_stem_width
823 && !strcmp(fallback_script, "none"))
824 fprintf(stderr,
825 "Warning: Setting a fallback stem width for a symbol font\n"
826 " without setting a fallback script has no effect\n");
828 int num_args = argc - optind;
830 if (num_args > 2)
831 show_help(false, true);
833 FILE* in;
834 if (num_args > 0)
836 in = fopen(argv[optind], "rb");
837 if (!in)
839 fprintf(stderr,
840 "The following error occurred while opening font `%s':\n"
841 "\n"
842 " %s\n",
843 argv[optind], strerror(errno));
844 exit(EXIT_FAILURE);
847 else
849 if (isatty(fileno(stdin)))
850 show_help(false, true);
851 in = stdin;
854 FILE* out;
855 if (num_args > 1)
857 if (!strcmp(argv[optind], argv[optind + 1]))
859 fprintf(stderr, "Input and output file names must not be identical\n");
860 exit(EXIT_FAILURE);
863 out = fopen(argv[optind + 1], "wb");
864 if (!out)
866 fprintf(stderr,
867 "The following error occurred while opening font `%s':\n"
868 "\n"
869 " %s\n",
870 argv[optind + 1], strerror(errno));
871 exit(EXIT_FAILURE);
874 else
876 if (isatty(fileno(stdout)))
877 show_help(false, true);
878 out = stdout;
881 FILE* deltas = NULL;
882 if (deltas_name)
884 deltas = fopen(deltas_name, "r");
885 if (!deltas)
887 fprintf(stderr,
888 "The following error occurred while open deltas file `%s':\n"
889 "\n"
890 " %s\n",
891 deltas_name, strerror(errno));
892 exit(EXIT_FAILURE);
895 else
896 deltas = NULL;
898 Progress_Data progress_data = {-1, 1, 0};
899 Error_Data error_data = {deltas_name};
900 Info_Data info_data;
902 if (no_info)
903 info_func = NULL;
904 else
906 info_data.data = NULL; // must be deallocated after use
907 info_data.data_wide = NULL; // must be deallocated after use
908 info_data.data_len = 0;
909 info_data.data_wide_len = 0;
911 info_data.deltas_name = deltas_name;
913 info_data.hinting_range_min = hinting_range_min;
914 info_data.hinting_range_max = hinting_range_max;
915 info_data.hinting_limit = hinting_limit;
917 info_data.gray_strong_stem_width = gray_strong_stem_width;
918 info_data.gdi_cleartype_strong_stem_width = gdi_cleartype_strong_stem_width;
919 info_data.dw_cleartype_strong_stem_width = dw_cleartype_strong_stem_width;
921 info_data.windows_compatibility = windows_compatibility;
922 info_data.adjust_subglyphs = adjust_subglyphs;
923 info_data.hint_composites = hint_composites;
924 info_data.increase_x_height = increase_x_height;
925 info_data.x_height_snapping_exceptions_string = x_height_snapping_exceptions_string;
926 info_data.fallback_stem_width = fallback_stem_width;
927 info_data.symbol = symbol;
929 strncpy(info_data.default_script,
930 default_script,
931 sizeof (info_data.default_script));
932 strncpy(info_data.fallback_script,
933 fallback_script,
934 sizeof (info_data.fallback_script));
936 info_data.dehint = dehint;
938 int ret = build_version_string(&info_data);
939 if (ret == 1)
940 fprintf(stderr, "Warning: Can't allocate memory"
941 " for ttfautohint options string in `name' table\n");
942 else if (ret == 2)
943 fprintf(stderr, "Warning: ttfautohint options string"
944 " in `name' table too long\n");
947 if (in == stdin)
948 SET_BINARY(stdin);
949 if (out == stdout)
950 SET_BINARY(stdout);
952 TA_Error error =
953 TTF_autohint("in-file, out-file, deltas-file,"
954 "hinting-range-min, hinting-range-max, hinting-limit,"
955 "gray-strong-stem-width, gdi-cleartype-strong-stem-width,"
956 "dw-cleartype-strong-stem-width,"
957 "progress-callback, progress-callback-data,"
958 "error-callback, error-callback-data,"
959 "info-callback, info-callback-data,"
960 "ignore-restrictions, windows-compatibility,"
961 "adjust-subglyphs, hint-composites,"
962 "increase-x-height, x-height-snapping-exceptions,"
963 "fallback-stem-width, default-script, fallback-script,"
964 "symbol, dehint, debug",
965 in, out, deltas,
966 hinting_range_min, hinting_range_max, hinting_limit,
967 gray_strong_stem_width, gdi_cleartype_strong_stem_width,
968 dw_cleartype_strong_stem_width,
969 progress_func, &progress_data,
970 err_func, &error_data,
971 info_func, &info_data,
972 ignore_restrictions, windows_compatibility,
973 adjust_subglyphs, hint_composites,
974 increase_x_height, x_height_snapping_exceptions_string,
975 fallback_stem_width, default_script, fallback_script,
976 symbol, dehint, debug);
978 if (!no_info)
980 free(info_data.data);
981 free(info_data.data_wide);
984 if (in != stdin)
985 fclose(in);
986 if (out != stdout)
987 fclose(out);
988 if (deltas)
989 fclose(deltas);
991 exit(error ? EXIT_FAILURE : EXIT_SUCCESS);
993 return 0; // never reached
995 #else // BUILD_GUI
997 int new_argc = new_arg_string.size();
998 char** new_argv = new char*[new_argc];
1000 // construct new argc and argv variables from collected data
1001 for (int i = 0; i < new_argc; i++)
1002 new_argv[i] = const_cast<char*>(new_arg_string[i].data());
1004 QApplication app(new_argc, new_argv);
1005 app.setApplicationName("TTFautohint");
1006 app.setApplicationVersion(VERSION);
1007 app.setOrganizationName("FreeType");
1008 app.setOrganizationDomain("freetype.org");
1010 bool alternative_layout = false;
1012 // Display the window off the screen -- to get proper window dimensions
1013 // including the frame, the window manager must have a chance to
1014 // decorate it.
1016 // We don't want to change the default window positioning algorithm of
1017 // the platform's window manager, so we create the main GUI window
1018 // twice.
1020 // The original idea, however, was to simply move the off-screen window
1021 // back to the screen with
1023 // gui.move(100, 100);
1024 // gui.setAttribute(Qt::WA_Moved, false);
1025 // gui.show();
1027 // (unsetting the `WA_Moved' attribute makes the window manager handle
1028 // the previous call to `move' as a position suggestion instead of a
1029 // request). Unfortuntely, there seems to be a bug in Qt 4.8.4 which
1030 // prevents any effect of unsetting `WA_Moved' if `show' has already
1031 // been called.
1033 Main_GUI dummy(alternative_layout,
1034 hinting_range_min, hinting_range_max, hinting_limit,
1035 gray_strong_stem_width, gdi_cleartype_strong_stem_width,
1036 dw_cleartype_strong_stem_width, increase_x_height,
1037 x_height_snapping_exceptions_string, fallback_stem_width,
1038 ignore_restrictions, windows_compatibility, adjust_subglyphs,
1039 hint_composites, no_info, default_script, fallback_script,
1040 symbol, dehint);
1042 dummy.move(-50000, -50000);
1043 dummy.show();
1045 // if the vertical size of our window is too large,
1046 // select a horizontal layout
1047 QRect screen(QApplication::desktop()->availableGeometry());
1048 if (dummy.frameGeometry().height() > screen.width())
1049 alternative_layout = true;
1052 Main_GUI gui(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);
1060 gui.show();
1062 return app.exec();
1064 #endif // BUILD_GUI
1067 // end of main.cpp