Update copyright years not catchable by `update-copyright'.
[ttfautohint.git] / frontend / main.cpp
blobd1ac04667b8cfaa38350db434c2e88a8306e9865
1 // main.cpp
3 // Copyright (C) 2011-2018 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 #ifdef BUILD_GUI
39 # include <QApplication>
40 # include "maingui.h"
41 #else
42 # include <ft2build.h>
43 # include FT_FREETYPE_H
44 # include FT_TRUETYPE_TABLES_H // for option `-T'
45 # include "info.h"
46 #endif
48 #include <ttfautohint.h>
49 #include <numberset.h>
52 #ifndef BUILD_GUI
53 # ifdef _WIN32
54 # include <fcntl.h>
55 # define SET_BINARY(f) do { \
56 if (!isatty(fileno(f))) \
57 setmode(fileno(f), O_BINARY); \
58 } while (0)
59 # endif
61 # ifndef SET_BINARY
62 # define SET_BINARY(f) do {} while (0)
63 # endif
64 #endif
67 using namespace std;
70 typedef struct Tag_Names_
72 const char* tag;
73 const char* description;
74 } Tag_Names;
77 // the available script tags and its descriptions are directly extracted
78 // from `ttfautohint-scripts.h'
79 #undef SCRIPT
80 #define SCRIPT(s, S, d, h, H, ss) \
81 {#s, d},
83 const Tag_Names script_names[] =
85 #include <ttfautohint-scripts.h>
86 {NULL, NULL}
90 #ifndef BUILD_GUI
91 // the available feature tags and its descriptions are directly extracted
92 // from `ttfautohint-coverages.h'
93 # undef COVERAGE
94 # define COVERAGE(n, N, d, t, t1, t2, t3, t4) \
95 {#t, d},
97 const Tag_Names feature_names[] =
99 #include <ttfautohint-coverages.h>
100 {NULL, NULL}
102 #endif
105 #ifndef BUILD_GUI
106 extern "C" {
108 typedef struct Progress_Data_
110 long last_sfnt;
111 bool begin;
112 int last_percent;
113 } Progress_Data;
116 static int
117 progress(long curr_idx,
118 long num_glyphs,
119 long curr_sfnt,
120 long num_sfnts,
121 void* user)
123 Progress_Data* data = (Progress_Data*)user;
125 if (num_sfnts > 1 && curr_sfnt != data->last_sfnt)
127 fprintf(stderr, "subfont %ld of %ld\n", curr_sfnt + 1, num_sfnts);
128 data->last_sfnt = curr_sfnt;
129 data->last_percent = 0;
130 data->begin = true;
133 if (data->begin)
135 fprintf(stderr, " %ld glyphs\n"
136 " ", num_glyphs);
137 data->begin = false;
140 // print progress approx. every 10%
141 int curr_percent = int(curr_idx * 100 / num_glyphs);
142 int curr_diff = curr_percent - data->last_percent;
144 if (curr_diff >= 10)
146 fprintf(stderr, " %d%%", curr_percent);
147 data->last_percent = curr_percent - curr_percent % 10;
150 if (curr_idx + 1 == num_glyphs)
151 fprintf(stderr, "\n");
153 return 0;
157 typedef struct Error_Data_
159 const char* control_name;
160 } Error_Data;
163 static void
164 err(TA_Error error,
165 const char* error_string,
166 unsigned int errlinenum,
167 const char* errline,
168 const char* errpos,
169 void* user)
171 Error_Data* data = static_cast<Error_Data*>(user);
173 if (!error)
174 return;
176 // We replace some terse error strings with more user-friendly versions.
177 if (error == TA_Err_Invalid_FreeType_Version)
178 fprintf(stderr,
179 "FreeType version 2.4.5 or higher is needed.\n"
180 "Perhaps using a wrong FreeType DLL?\n");
181 else if (error == TA_Err_Invalid_Font_Type)
182 fprintf(stderr,
183 "This font is not a valid font"
184 " in SFNT format with TrueType outlines.\n"
185 "In particular, CFF outlines are not supported.\n");
186 else if (error == TA_Err_Already_Processed)
187 fprintf(stderr,
188 "This font has already been processed with ttfautohint.\n");
189 else if (error == TA_Err_Missing_Legal_Permission)
190 fprintf(stderr,
191 "Bit 1 in the `fsType' field of the `OS/2' table is set:\n"
192 "This font must not be modified"
193 " without permission of the legal owner.\n"
194 "Use command line option `-i' to continue"
195 " if you have such a permission.\n");
196 else if (error == TA_Err_Missing_Unicode_CMap)
197 fprintf(stderr,
198 "No Unicode character map.\n");
199 else if (error == TA_Err_Missing_Symbol_CMap)
200 fprintf(stderr,
201 "No symbol character map.\n");
202 else if (error == TA_Err_Missing_Glyph)
203 fprintf(stderr,
204 "No glyph for a standard character"
205 " to derive standard width and height.\n"
206 "Please check the documentation for a list of"
207 " script-specific standard characters,\n"
208 "or use option `--symbol'.\n");
209 else
211 if (error < 0x100)
213 fprintf(stderr, "An error with code 0x%02x occurred"
214 " while autohinting fonts\n",
215 error);
216 if (error_string)
217 fprintf(stderr, " %s", error_string);
219 else if (error >= 0x100 && error < 0x200)
221 fprintf(stderr, "An error with code 0x%03x occurred"
222 " while parsing the argument of option `-X'",
223 error);
224 fprintf(stderr, errline ? ":\n" : ".\n");
226 if (errline)
227 fprintf(stderr, " %s\n", errline);
228 if (errpos && errline)
229 fprintf(stderr, " %*s\n", int(errpos - errline + 1), "^");
231 else if (error >= 0x200 && error < 0x300)
233 fprintf(stderr, "%s:", data->control_name);
234 if (errlinenum)
235 fprintf(stderr, "%d:", errlinenum);
236 if (errpos && errline)
237 fprintf(stderr, "%d:", int(errpos - errline + 1));
238 if (error_string)
239 fprintf(stderr, " %s", error_string);
240 fprintf(stderr, " (0x%02X)\n", error);
241 if (errline)
242 fprintf(stderr, " %s\n", errline);
243 if (errpos && errline)
244 fprintf(stderr, " %*s\n", int(errpos - errline + 1), "^");
246 else if (error >= 0x300 && error < 0x400)
248 error -= 0x300;
249 fprintf(stderr, "An error with code 0x%02x occurred"
250 " while loading the reference font\n",
251 error);
252 if (error_string)
253 fprintf(stderr, " %s", error_string);
259 } // extern "C"
260 #endif // !BUILD_GUI
263 #ifdef CONSOLE_OUTPUT
264 static void
265 show_help(bool
266 #ifdef BUILD_GUI
268 #endif
270 bool is_error)
272 FILE* handle = is_error ? stderr : stdout;
274 fprintf(handle,
275 #ifdef BUILD_GUI
276 "Usage: ttfautohintGUI [OPTION]...\n"
277 "A GUI application to replace hints in a TrueType font.\n"
278 #else
279 "Usage: ttfautohint [OPTION]... [IN-FILE [OUT-FILE]]\n"
280 "Replace hints in TrueType font IN-FILE and write output to OUT-FILE.\n"
281 "If OUT-FILE is missing, standard output is used instead;\n"
282 "if IN-FILE is missing also, standard input and output are used.\n"
283 #endif
284 "\n"
285 "The new hints are based on FreeType's auto-hinter.\n"
286 "\n"
287 "This program is a simple front-end to the `ttfautohint' library.\n"
288 "\n");
290 fprintf(handle,
291 "Long options can be given with one or two dashes,\n"
292 "and with and without equal sign between option and argument.\n"
293 "This means that the following forms are acceptable:\n"
294 "`-foo=bar', `--foo=bar', `-foo bar', `--foo bar'.\n"
295 "\n"
296 "Mandatory arguments to long options are mandatory for short options too.\n"
297 #ifdef BUILD_GUI
298 "Options not related to Qt or X11 set default values.\n"
299 #endif
300 "\n"
303 fprintf(handle,
304 "Options:\n"
305 #ifndef BUILD_GUI
306 " --debug print debugging information\n"
307 #endif
308 " -a, --stem-width-mode=S select stem width mode for grayscale, GDI\n"
309 " ClearType, and DW ClearType, where S is a\n"
310 " string of three letters with possible values\n"
311 " `n' for natural, `q' for quantized, and `s'\n"
312 " for strong (default: qsq)\n"
313 " -c, --composites hint glyph composites also\n"
314 " -d, --dehint remove all hints\n"
315 " -D, --default-script=S set default OpenType script (default: latn)\n"
316 " -f, --fallback-script=S set fallback script (default: none)\n"
317 " -F, --family-suffix=S append suffix to the family name string(s)\n"
318 " in the `name' table\n"
319 " -G, --hinting-limit=N switch off hinting above this PPEM value\n"
320 " (default: %d); value 0 means no limit\n"
321 " -h, --help display this help and exit\n"
322 " -H, --fallback-stem-width=N\n"
323 " set fallback stem width\n"
324 " (default: 50 font units at 2048 UPEM)\n"
325 #ifdef BUILD_GUI
326 " --help-all show Qt and X11 specific options also\n"
327 #endif
328 " -i, --ignore-restrictions override font license restrictions\n"
329 " -I, --detailed-info add detailed ttfautohint info\n"
330 " to the version string(s) in the `name' table\n"
331 " -l, --hinting-range-min=N the minimum PPEM value for hint sets\n"
332 " (default: %d)\n"
333 #ifndef BUILD_GUI
334 " -m, --control-file=FILE get control instructions from FILE\n"
335 #endif
336 " -n, --no-info don't add ttfautohint info\n"
337 " to the version string(s) in the `name' table\n"
338 " -p, --adjust-subglyphs handle subglyph adjustments in exotic fonts\n",
339 TA_HINTING_LIMIT, TA_HINTING_RANGE_MIN);
340 fprintf(handle,
341 " -r, --hinting-range-max=N the maximum PPEM value for hint sets\n"
342 " (default: %d)\n"
343 #ifndef BUILD_GUI
344 " -R, --reference=FILE derive blue zones from reference font FILE\n"
345 #endif
346 " -s, --symbol input is symbol font\n"
347 " -S, --fallback-scaling use fallback scaling, not hinting\n"
348 " -t, --ttfa-table add TTFA information table\n"
349 #ifndef BUILD_GUI
350 " -T, --ttfa-info display TTFA table in IN-FILE and exit\n"
351 #endif
352 " -v, --verbose show progress information\n"
353 " -V, --version print version information and exit\n"
354 " -W, --windows-compatibility\n"
355 " add blue zones for `usWinAscent' and\n"
356 " `usWinDescent' to avoid clipping\n"
357 " -x, --increase-x-height=N increase x height for sizes in the range\n"
358 " 6<=PPEM<=N; value 0 switches off this feature\n"
359 " (default: %d)\n"
360 " -X, --x-height-snapping-exceptions=STRING\n"
361 " specify a comma-separated list of\n"
362 " x-height snapping exceptions, for example\n"
363 " \"-9, 13-17, 19\" (default: \"\")\n"
364 #ifndef BUILD_GUI
365 " -Z, --reference-index=N face index of reference font (default: 0)\n"
366 #endif
367 "\n",
368 TA_HINTING_RANGE_MAX, TA_INCREASE_X_HEIGHT);
370 #ifdef BUILD_GUI
371 if (all)
373 fprintf(handle,
374 "Qt Options:\n"
375 " --graphicssystem=SYSTEM\n"
376 " select a different graphics system backend\n"
377 " instead of the default one\n"
378 " (possible values: `raster', `opengl')\n"
379 " --reverse set layout direction to right-to-left\n");
380 fprintf(handle,
381 " --session=ID restore the application for the given ID\n"
382 " --style=STYLE set application GUI style\n"
383 " (possible values: motif, windows, platinum)\n"
384 " --stylesheet=SHEET apply the given Qt stylesheet\n"
385 " to the application widgets\n"
386 "\n");
388 fprintf(handle,
389 "X11 options:\n"
390 " --background=COLOR set the default background color\n"
391 " and an application palette\n"
392 " (light and dark shades are calculated)\n"
393 " --bg=COLOR same as --background\n"
394 " --btn=COLOR set the default button color\n"
395 " --button=COLOR same as --btn\n"
396 " --cmap use a private color map on an 8-bit display\n"
397 " --display=NAME use the given X-server display\n");
398 fprintf(handle,
399 " --fg=COLOR set the default foreground color\n"
400 " --fn=FONTNAME set the application font\n"
401 " --font=FONTNAME same as --fn\n"
402 " --foreground=COLOR same as --fg\n"
403 " --geometry=GEOMETRY set the client geometry of first window\n"
404 " --im=SERVER set the X Input Method (XIM) server\n"
405 " --inputstyle=STYLE set X Input Method input style\n"
406 " (possible values: onthespot, overthespot,\n"
407 " offthespot, root)\n");
408 fprintf(handle,
409 " --name=NAME set the application name\n"
410 " --ncols=COUNT limit the number of colors allocated\n"
411 " in the color cube on an 8-bit display,\n"
412 " if the application is using the\n"
413 " QApplication::ManyColor color specification\n"
414 " --title=TITLE set the application title (caption)\n"
415 " --visual=VISUAL force the application\n"
416 " to use the given visual on an 8-bit display\n"
417 " (only possible value: TrueColor)\n"
418 "\n");
420 #endif // BUILD_GUI
422 fprintf(handle,
423 "The program accepts both TTF and TTC files as input.\n"
424 "Use option -i only if you have a legal permission to modify the font.\n"
425 "The used PPEM value for option -p is FUnits per em, normally 2048.\n"
426 "With option -s, use default values for standard stem width and height,\n"
427 "otherwise they are derived from script-specific characters\n"
428 "resembling the shape of character `o'.\n"
429 "\n");
430 fprintf(handle,
431 "A hint set contains the optimal hinting for a certain PPEM value;\n"
432 "the larger the hint set range (as given by options -l and -r),\n"
433 "the more hint sets get computed, usually increasing the output font size.\n"
434 "The `gasp' table of the output file always enables grayscale hinting\n"
435 "for all sizes (limited by option -G, which is handled in the bytecode).\n"
436 "Increasing the value of -G does not increase the output font size.\n"
437 "\n");
438 fprintf(handle,
439 "Options -f and -D take a four-letter string that identifies a script.\n"
440 "Option -f sets the script used as a fallback for glyphs that can't be\n"
441 "associated with a known script. By default, such glyphs are hinted;\n"
442 "if option -S is set, they are scaled only instead. Option -D sets the\n"
443 "default script for handling OpenType features.\n"
444 "\n"
445 "Possible four-letter string values are\n"
446 "\n");
447 const Tag_Names* sn = script_names;
448 for(;;)
450 fprintf(handle, " %s (%s)",
451 sn->tag, sn->description);
452 sn++;
453 if (sn->tag)
454 fprintf(handle, ",\n");
455 else
457 fprintf(handle, ".\n");
458 break;
461 fprintf(handle,
462 #ifndef BUILD_GUI
463 "\n"
464 "A control instructions file contains entries of the form\n"
465 "\n"
466 " [<font idx>] <script> <feature> @ <glyph ids>\n"
467 "\n"
468 " [<font idx>] <script> <feature> w <stem widths>\n"
469 "\n"
470 " [<font idx>] <glyph id> l|r <points> [(<left offset>,<right offset>)]\n"
471 "\n"
472 " [<font idx>] <glyph id> n <points>\n"
473 "\n"
474 " [<font idx>] <glyph id> t|p <points> [x <shift>] [y <shift>] @ <ppems>\n"
475 "\n"
476 "<font idx> is the current subfont, <glyph id> is a glyph name or index,\n"
477 "<glyph ids> is a set of <glyph id>s, <stem widths> is an unordered set of\n"
478 "integer stem widths in font units, <shift> is a real number in px,\n"
479 "<points> and <ppems> are integer ranges as with option `-X'.\n"
480 "\n"
481 "<script> and <feature> are four-letter tags that define a style\n"
482 "the <glyph ids> are assigned to; possible values for <script> are the same\n"
483 "as with option -D, possible values for <feature> are\n"
484 "\n");
485 const Tag_Names* fn = feature_names;
486 for(;;)
488 fprintf(handle, " %s (%s)",
489 fn->tag, fn->description);
490 fn++;
491 if (fn->tag)
492 fprintf(handle, ",\n");
493 else
495 fprintf(handle, ".\n");
496 break;
499 fprintf(handle,
500 "\n"
501 "`w' assigns stem widths to a style; the first value sets the default.\n"
502 "`l' (`r') creates one-point segments with direction left (right).\n"
503 "<left offset> and <right offset> specify offsets (in font units)\n"
504 "relative to the corresponding points to give the segments a length.\n"
505 "`n' removes points from horizontal segments, making them `weak' points.\n"
506 "`t' (`p') applies delta exceptions to the given points before (after) IUP.\n"
507 "\n"
508 "`#' starts a line comment, which gets ignored.\n"
509 "Empty lines are ignored, too.\n"
510 "\n"
511 "Key letters `l', `r', `n', `p', `t', `w', `x', and `y'\n"
512 "have the verbose aliases `left', `right', `nodir', `point', `touch',\n"
513 "`width', `xshift', and `yshift', respectively.\n"
514 #endif
515 "\n"
516 #ifdef BUILD_GUI
517 "A command-line version of this program is called `ttfautohint'.\n"
518 #else
519 "A GUI version of this program is called `ttfautohintGUI'.\n"
520 #endif
521 "\n"
522 "Report bugs to: freetype-devel@nongnu.org\n"
523 "\n"
524 "ttfautohint home page: <http://www.freetype.org/ttfautohint>\n");
526 if (is_error)
527 exit(EXIT_FAILURE);
528 else
529 exit(EXIT_SUCCESS);
533 static void
534 show_version()
536 fprintf(stdout,
537 #ifdef BUILD_GUI
538 "ttfautohintGUI " VERSION "\n"
539 #else
540 "ttfautohint " VERSION "\n"
541 #endif
542 "Copyright (C) 2011-2018 Werner Lemberg <wl@gnu.org>.\n"
543 "License: FreeType License (FTL) or GNU GPLv2.\n"
544 "This is free software: you are free to change and redistribute it.\n"
545 "There is NO WARRANTY, to the extent permitted by law.\n");
547 exit(EXIT_SUCCESS);
549 #endif // CONSOLE_OUTPUT
552 #ifndef BUILD_GUI
554 typedef const struct FT_error_
556 int err_code;
557 const char* err_msg;
558 } FT_error;
560 static FT_error FT_errors[] =
562 #undef __FTERRORS_H__
563 #define FT_ERRORDEF(e, v, s) { e, s },
564 #define FT_ERROR_START_LIST {
565 #define FT_ERROR_END_LIST { 0, NULL } };
566 #include FT_ERRORS_H
569 static const char*
570 FT_get_error_message(FT_Error error)
572 FT_error* e = FT_errors;
574 while (e->err_code || e->err_msg)
576 if (e->err_code == error)
577 return e->err_msg;
578 e++;
581 return NULL;
585 #define BUF_SIZE 0x10000
587 #define TTAG_TTFA FT_MAKE_TAG('T', 'T', 'F', 'A')
589 static void
590 display_TTFA(FILE* in)
592 FT_Byte buf[BUF_SIZE];
593 FT_Byte* in_buf;
594 size_t in_len = 0;
595 size_t read_bytes;
597 if (in == stdin)
598 SET_BINARY(stdin);
600 in_buf = (FT_Byte*)malloc(BUF_SIZE);
601 if (!in_buf)
603 fprintf(stderr, "Can't allocate enough memory.\n");
604 exit(EXIT_FAILURE);
607 while ((read_bytes = fread(buf, 1, BUF_SIZE, in)) > 0)
609 FT_Byte* in_buf_new = (FT_Byte*)realloc(in_buf, in_len + read_bytes);
610 if (!in_buf_new)
612 fprintf(stderr, "Can't reallocate enough memory.\n");
613 exit(EXIT_FAILURE);
615 else
616 in_buf = in_buf_new;
618 memcpy(in_buf + in_len, buf, read_bytes);
620 in_len += read_bytes;
623 if (ferror(in))
625 fprintf(stderr, "Stream error while handling input font.\n");
626 exit(EXIT_FAILURE);
629 FT_Library library = NULL;
630 FT_Face face = NULL;
631 FT_Error error;
633 error = FT_Init_FreeType(&library);
634 if (error)
636 fprintf(stderr, "Can't initialize FreeType library:\n"
637 "%s\n",
638 FT_get_error_message(error));
639 exit(EXIT_FAILURE);
642 // in a TTC, a `TTFA' table is part of the first subfont,
643 // thus we can simply pass 0 as the face index
644 error = FT_New_Memory_Face(library, in_buf, (FT_Long)in_len, 0, &face);
645 if (error)
647 fprintf(stderr, "Can't open input font:\n"
648 "%s\n",
649 FT_get_error_message(error));
650 exit(EXIT_FAILURE);
653 FT_Byte* ttfa_buf = NULL;
654 FT_ULong ttfa_len = 0;
656 error = FT_Load_Sfnt_Table(face, TTAG_TTFA, 0, NULL, &ttfa_len);
657 if (error)
659 fprintf(stderr, "No `TTFA' table in font.\n");
660 goto Exit;
663 ttfa_buf = (FT_Byte*)malloc(ttfa_len);
664 if (!ttfa_buf)
666 fprintf(stderr, "Can't allocate enough memory.\n");
667 exit(EXIT_FAILURE);
670 error = FT_Load_Sfnt_Table(face, TTAG_TTFA, 0, ttfa_buf, &ttfa_len);
671 if (error)
673 fprintf(stderr, "Error loading `TTFA' table:\n"
674 "%s\n",
675 FT_get_error_message(error));
676 exit(EXIT_FAILURE);
679 fprintf(stdout, "%s", ttfa_buf);
681 Exit:
682 FT_Done_Face(face);
683 FT_Done_FreeType(library);
685 free(in_buf);
686 free(ttfa_buf);
687 if (in != stdin)
688 fclose(in);
690 exit(EXIT_SUCCESS);
692 #endif
696 main(int argc,
697 char** argv)
699 int hinting_range_min = 0;
700 int hinting_range_max = 0;
701 int hinting_limit = 0;
702 int increase_x_height = 0;
703 int fallback_stem_width = 0;
705 bool have_hinting_range_min = false;
706 bool have_hinting_range_max = false;
707 bool have_hinting_limit = false;
708 bool have_increase_x_height = false;
709 bool have_fallback_stem_width = false;
711 int gray_stem_width_mode = TA_STEM_WIDTH_MODE_QUANTIZED;
712 int gdi_cleartype_stem_width_mode = TA_STEM_WIDTH_MODE_STRONG;
713 int dw_cleartype_stem_width_mode = TA_STEM_WIDTH_MODE_QUANTIZED;
715 #ifndef BUILD_GUI
716 bool have_option_w = false;
717 #endif
719 bool ignore_restrictions = false;
720 bool windows_compatibility = false;
721 bool adjust_subglyphs = false;
722 bool hint_composites = false;
723 bool no_info = false;
724 bool detailed_info = false;
725 bool TTFA_info = false;
726 #ifndef BUILD_GUI
727 bool show_TTFA_info = false;
728 #endif
729 bool symbol = false;
730 bool fallback_scaling = false;
732 const char* default_script = NULL;
733 bool have_default_script = false;
734 const char* fallback_script = NULL;
735 bool have_fallback_script = false;
736 const char* x_height_snapping_exceptions_string = NULL;
737 bool have_x_height_snapping_exceptions_string = false;
738 const char* family_suffix = NULL;
739 bool have_family_suffix = false;
741 bool dehint = false;
743 #ifndef BUILD_GUI
744 bool debug = false;
746 TA_Progress_Func progress_func = NULL;
747 TA_Error_Func err_func = err;
748 TA_Info_Func info_func = info;
749 TA_Info_Post_Func info_post_func = info_post;
751 const char* control_name = NULL;
752 const char* reference_name = NULL;
753 int reference_index = 0;
755 unsigned long long epoch = ULLONG_MAX;
756 #endif
758 // For real numbers (both parsing and displaying) we only use `.' as the
759 // decimal separator; similarly, we don't want localized formats like a
760 // thousands separator for any number.
761 setlocale(LC_NUMERIC, "C");
763 // make GNU, Qt, and X11 command line options look the same;
764 // we allow `--foo=bar', `--foo bar', `-foo=bar', `-foo bar',
765 // and short options specific to ttfautohint
767 // set up a new argument string
768 vector<string> new_arg_string;
769 new_arg_string.push_back(argv[0]);
771 while (1)
773 // use pseudo short options for long-only options
774 enum
776 PASS_THROUGH = CHAR_MAX + 1,
777 HELP_ALL_OPTION,
778 DEBUG_OPTION
781 static struct option long_options[] =
783 {"help", no_argument, NULL, 'h'},
784 #ifdef BUILD_GUI
785 {"help-all", no_argument, NULL, HELP_ALL_OPTION},
786 #endif
788 // ttfautohint options
789 {"adjust-subglyphs", no_argument, NULL, 'p'},
790 {"composites", no_argument, NULL, 'c'},
791 #ifndef BUILD_GUI
792 {"control-file", required_argument, NULL, 'm'},
793 {"debug", no_argument, NULL, DEBUG_OPTION},
794 #endif
795 {"default-script", required_argument, NULL, 'D'},
796 {"dehint", no_argument, NULL, 'd'},
797 {"detailed-info", no_argument, NULL, 'I'},
798 {"fallback-scaling", no_argument, NULL, 'S'},
799 {"fallback-script", required_argument, NULL, 'f'},
800 {"fallback-stem-width", required_argument, NULL, 'H'},
801 {"family-suffix", required_argument, NULL, 'F'},
802 {"hinting-limit", required_argument, NULL, 'G'},
803 {"hinting-range-max", required_argument, NULL, 'r'},
804 {"hinting-range-min", required_argument, NULL, 'l'},
805 {"ignore-restrictions", no_argument, NULL, 'i'},
806 {"increase-x-height", required_argument, NULL, 'x'},
807 {"no-info", no_argument, NULL, 'n'},
808 {"pre-hinting", no_argument, NULL, 'p'},
809 #ifndef BUILD_GUI
810 {"reference", required_argument, NULL, 'R'},
811 {"reference-index", required_argument, NULL, 'Z'},
812 #endif
813 {"stem-width-mode", required_argument, NULL, 'a'},
814 {"strong-stem-width", required_argument, NULL, 'w'},
815 {"symbol", no_argument, NULL, 's'},
816 {"ttfa-table", no_argument, NULL, 't'},
817 #ifndef BUILD_GUI
818 {"ttfa-info", no_argument, NULL, 'T'},
819 #endif
820 {"verbose", no_argument, NULL, 'v'},
821 {"version", no_argument, NULL, 'V'},
822 {"windows-compatibility", no_argument, NULL, 'W'},
823 {"x-height-snapping-exceptions", required_argument, NULL, 'X'},
825 // Qt options
826 {"graphicssystem", required_argument, NULL, PASS_THROUGH},
827 {"reverse", no_argument, NULL, PASS_THROUGH},
828 {"session", required_argument, NULL, PASS_THROUGH},
829 {"style", required_argument, NULL, PASS_THROUGH},
830 {"stylesheet", required_argument, NULL, PASS_THROUGH},
832 // X11 options
833 {"background", required_argument, NULL, PASS_THROUGH},
834 {"bg", required_argument, NULL, PASS_THROUGH},
835 {"btn", required_argument, NULL, PASS_THROUGH},
836 {"button", required_argument, NULL, PASS_THROUGH},
837 {"cmap", no_argument, NULL, PASS_THROUGH},
838 {"display", required_argument, NULL, PASS_THROUGH},
839 {"fg", required_argument, NULL, PASS_THROUGH},
840 {"fn", required_argument, NULL, PASS_THROUGH},
841 {"font", required_argument, NULL, PASS_THROUGH},
842 {"foreground", required_argument, NULL, PASS_THROUGH},
843 {"geometry", required_argument, NULL, PASS_THROUGH},
844 {"im", required_argument, NULL, PASS_THROUGH},
845 {"inputstyle", required_argument, NULL, PASS_THROUGH},
846 {"name", required_argument, NULL, PASS_THROUGH},
847 {"ncols", required_argument, NULL, PASS_THROUGH},
848 {"title", required_argument, NULL, PASS_THROUGH},
849 {"visual", required_argument, NULL, PASS_THROUGH},
851 {NULL, 0, NULL, 0}
854 int option_index;
855 int c = getopt_long_only(argc, argv,
856 #ifdef BUILD_GUI
857 "a:cdD:f:F:G:hH:iIl:npr:sStvVw:Wx:X:",
858 #else
859 "a:cdD:f:F:G:hH:iIl:m:npr:R:sStTvVw:Wx:X:Z:",
860 #endif
861 long_options, &option_index);
862 if (c == -1)
863 break;
865 switch (c)
867 case 'a':
868 if (strlen(optarg) != 3)
870 fprintf(stderr, "Stem width mode string must consist of exactly"
871 " three letters\n");
872 exit(EXIT_FAILURE);
875 switch (optarg[0])
877 case 'n':
878 gray_stem_width_mode = TA_STEM_WIDTH_MODE_NATURAL;
879 break;
880 case 'q':
881 gray_stem_width_mode = TA_STEM_WIDTH_MODE_QUANTIZED;
882 break;
883 case 's':
884 gray_stem_width_mode = TA_STEM_WIDTH_MODE_STRONG;
885 break;
886 default:
887 fprintf(stderr, "Stem width mode letter for grayscale rendering"
888 " must be `n', `q', or `s'\n");
889 exit(EXIT_FAILURE);
892 switch (optarg[1])
894 case 'n':
895 gdi_cleartype_stem_width_mode = TA_STEM_WIDTH_MODE_NATURAL;
896 break;
897 case 'q':
898 gdi_cleartype_stem_width_mode = TA_STEM_WIDTH_MODE_QUANTIZED;
899 break;
900 case 's':
901 gdi_cleartype_stem_width_mode = TA_STEM_WIDTH_MODE_STRONG;
902 break;
903 default:
904 fprintf(stderr, "Stem width mode letter for GDI ClearType rendering"
905 " must be `n', `q', or `s'\n");
906 exit(EXIT_FAILURE);
909 switch (optarg[2])
911 case 'n':
912 dw_cleartype_stem_width_mode = TA_STEM_WIDTH_MODE_NATURAL;
913 break;
914 case 'q':
915 dw_cleartype_stem_width_mode = TA_STEM_WIDTH_MODE_QUANTIZED;
916 break;
917 case 's':
918 dw_cleartype_stem_width_mode = TA_STEM_WIDTH_MODE_STRONG;
919 break;
920 default:
921 fprintf(stderr, "Stem width mode letter for DW ClearType rendering"
922 " must be `n', `q', or `s'\n");
923 exit(EXIT_FAILURE);
926 break;
928 case 'c':
929 hint_composites = true;
930 break;
932 case 'd':
933 dehint = true;
934 break;
936 case 'D':
937 default_script = optarg;
938 have_default_script = true;
939 break;
941 case 'f':
942 fallback_script = optarg;
943 have_fallback_script = true;
944 break;
946 case 'F':
947 family_suffix = optarg;
948 have_family_suffix = true;
949 break;
951 case 'G':
952 hinting_limit = atoi(optarg);
953 have_hinting_limit = true;
954 break;
956 case 'h':
957 #ifdef CONSOLE_OUTPUT
958 show_help(false, false);
959 #endif
960 break;
962 case 'H':
963 fallback_stem_width = atoi(optarg);
964 have_fallback_stem_width = true;
965 break;
967 case 'i':
968 ignore_restrictions = true;
969 break;
971 case 'I':
972 detailed_info = true;
973 no_info = false;
974 break;
976 case 'l':
977 hinting_range_min = atoi(optarg);
978 have_hinting_range_min = true;
979 break;
981 #ifndef BUILD_GUI
982 case 'm':
983 control_name = optarg;
984 break;
985 #endif
987 case 'n':
988 no_info = true;
989 detailed_info = false;
990 break;
992 case 'p':
993 adjust_subglyphs = true;
994 break;
996 case 'r':
997 hinting_range_max = atoi(optarg);
998 have_hinting_range_max = true;
999 break;
1001 #ifndef BUILD_GUI
1002 case 'R':
1003 reference_name = optarg;
1004 break;
1005 #endif
1007 case 's':
1008 symbol = true;
1009 break;
1011 case 'S':
1012 fallback_scaling = true;
1013 break;
1015 case 't':
1016 TTFA_info = true;
1017 break;
1019 #ifndef BUILD_GUI
1020 case 'T':
1021 show_TTFA_info = true;
1022 break;
1023 #endif
1025 case 'v':
1026 #ifndef BUILD_GUI
1027 progress_func = progress;
1028 #endif
1029 break;
1031 case 'V':
1032 #ifdef CONSOLE_OUTPUT
1033 show_version();
1034 #endif
1035 break;
1037 case 'w':
1038 gray_stem_width_mode = strchr(optarg, 'g')
1039 ? TA_STEM_WIDTH_MODE_STRONG
1040 : TA_STEM_WIDTH_MODE_QUANTIZED;
1041 gdi_cleartype_stem_width_mode = strchr(optarg, 'G')
1042 ? TA_STEM_WIDTH_MODE_STRONG
1043 : TA_STEM_WIDTH_MODE_QUANTIZED;
1044 dw_cleartype_stem_width_mode = strchr(optarg, 'D')
1045 ? TA_STEM_WIDTH_MODE_STRONG
1046 : TA_STEM_WIDTH_MODE_QUANTIZED;
1047 #ifndef BUILD_GUI
1048 have_option_w = true;
1049 #endif
1050 break;
1052 case 'W':
1053 windows_compatibility = true;
1054 break;
1056 case 'x':
1057 increase_x_height = atoi(optarg);
1058 have_increase_x_height = true;
1059 break;
1061 case 'X':
1062 x_height_snapping_exceptions_string = optarg;
1063 have_x_height_snapping_exceptions_string = true;
1064 break;
1066 #ifndef BUILD_GUI
1067 case 'Z':
1068 reference_index = atoi(optarg);
1069 break;
1070 #endif
1072 #ifndef BUILD_GUI
1073 case DEBUG_OPTION:
1074 debug = true;
1075 break;
1076 #endif
1078 #ifdef BUILD_GUI
1079 case HELP_ALL_OPTION:
1080 #ifdef CONSOLE_OUTPUT
1081 show_help(true, false);
1082 #endif
1083 break;
1084 #endif
1086 case PASS_THROUGH:
1088 // append argument with proper syntax for Qt
1089 string arg;
1090 arg += '-';
1091 arg += long_options[option_index].name;
1093 new_arg_string.push_back(arg);
1094 if (optarg)
1095 new_arg_string.push_back(optarg);
1096 break;
1099 default:
1100 exit(EXIT_FAILURE);
1104 if (dehint)
1106 // -d makes ttfautohint ignore all other hinting options
1107 have_default_script = false;
1108 have_fallback_script = false;
1109 have_fallback_stem_width = false;
1110 have_hinting_limit = false;
1111 have_hinting_range_max = false;
1112 have_hinting_range_min = false;
1113 have_increase_x_height = false;
1114 have_x_height_snapping_exceptions_string = false;
1117 #ifndef BUILD_GUI
1118 if (show_TTFA_info)
1120 // -T makes ttfautohint ignore even more options
1121 have_default_script = false;
1122 have_fallback_script = false;
1123 have_fallback_stem_width = false;
1124 have_family_suffix = false;
1125 have_hinting_limit = false;
1126 have_hinting_range_max = false;
1127 have_hinting_range_min = false;
1128 have_increase_x_height = false;
1129 have_x_height_snapping_exceptions_string = false;
1130 debug = false;
1132 #endif
1134 if (!have_default_script)
1135 default_script = "latn";
1136 if (!have_fallback_script)
1137 fallback_script = "none";
1138 if (!have_hinting_range_min)
1139 hinting_range_min = TA_HINTING_RANGE_MIN;
1140 if (!have_hinting_range_max)
1141 hinting_range_max = TA_HINTING_RANGE_MAX;
1142 if (!have_hinting_limit)
1143 hinting_limit = TA_HINTING_LIMIT;
1144 if (!have_increase_x_height)
1145 increase_x_height = TA_INCREASE_X_HEIGHT;
1146 if (!have_x_height_snapping_exceptions_string)
1147 x_height_snapping_exceptions_string = "";
1148 if (!have_fallback_stem_width)
1149 fallback_stem_width = 0; // redundant, but avoids a compiler warning
1150 if (!have_family_suffix)
1151 family_suffix = "";
1153 #ifndef BUILD_GUI
1155 // check SOURE_DATE_EPOCH environment variable
1156 const char* source_date_epoch = getenv("SOURCE_DATE_EPOCH");
1157 if (source_date_epoch)
1159 char* endptr;
1160 errno = 0;
1162 epoch = strtoull(source_date_epoch, &endptr, 10);
1163 if ((errno == ERANGE && (epoch == ULLONG_MAX
1164 || epoch == 0))
1165 || (errno != 0
1166 && epoch == 0))
1168 fprintf(stderr,
1169 "Environment variable `SOURCE_DATE_EPOCH' ignored:\n"
1170 " strtoull: %s\n",
1171 strerror(errno));
1172 epoch = ULLONG_MAX;
1174 else if (endptr == source_date_epoch)
1176 fprintf(stderr,
1177 "Environment variable `SOURCE_DATE_EPOCH' ignored:\n"
1178 " No digits were found: %s\n",
1179 endptr);
1180 epoch = ULLONG_MAX;
1182 else if (*endptr != '\0')
1184 fprintf(stderr,
1185 "Environment variable `SOURCE_DATE_EPOCH' ignored:\n"
1186 " Trailing garbage: %s\n",
1187 endptr);
1188 epoch = ULLONG_MAX;
1190 else if (epoch > ULONG_MAX)
1192 fprintf(stderr,
1193 "Environment variable `SOURCE_DATE_EPOCH' ignored\n"
1194 " value must be smaller than or equal to %lu\n"
1195 " but was found to be %llu\n",
1196 ULONG_MAX, epoch);
1197 epoch = ULLONG_MAX;
1201 if (have_option_w)
1202 fprintf(stderr,
1203 "Warning: Option `-w' is deprecated!"
1204 " Use option `-a' instead\n");
1206 if (!isatty(fileno(stderr)) && !debug)
1207 setvbuf(stderr, (char*)NULL, _IONBF, BUFSIZ);
1209 if (hinting_range_min < 2)
1211 fprintf(stderr, "The hinting range minimum must be at least 2\n");
1212 exit(EXIT_FAILURE);
1214 if (hinting_range_max < hinting_range_min)
1216 fprintf(stderr, "The hinting range maximum must not be smaller"
1217 " than the minimum (%d)\n",
1218 hinting_range_min);
1219 exit(EXIT_FAILURE);
1221 if (hinting_limit != 0 && hinting_limit < hinting_range_max)
1223 fprintf(stderr, "A non-zero hinting limit must not be smaller"
1224 " than the hinting range maximum (%d)\n",
1225 hinting_range_max);
1226 exit(EXIT_FAILURE);
1228 if (increase_x_height != 0 && increase_x_height < 6)
1230 fprintf(stderr, "A non-zero x height increase limit"
1231 " must be larger than or equal to 6\n");
1232 exit(EXIT_FAILURE);
1234 if (have_fallback_stem_width && fallback_stem_width <= 0)
1236 fprintf(stderr, "The fallback stem width"
1237 " must be a positive integer\n");
1238 exit(EXIT_FAILURE);
1241 if (have_default_script)
1243 const Tag_Names* sn;
1245 for (sn = script_names; sn->tag; sn++)
1246 if (!strcmp(default_script, sn->tag))
1247 break;
1248 if (!sn->tag)
1250 fprintf(stderr, "Unknown script tag `%s'\n", default_script);
1251 exit(EXIT_FAILURE);
1255 if (have_fallback_script)
1257 const Tag_Names* sn;
1259 for (sn = script_names; sn->tag; sn++)
1260 if (!strcmp(fallback_script, sn->tag))
1261 break;
1262 if (!sn->tag)
1264 fprintf(stderr, "Unknown script tag `%s'\n", fallback_script);
1265 exit(EXIT_FAILURE);
1269 if (symbol
1270 && have_fallback_stem_width
1271 && fallback_scaling)
1272 fprintf(stderr,
1273 "Warning: Setting a fallback stem width for a symbol font\n"
1274 " with fallback scaling only has no effect\n");
1276 if (const char* pos = check_family_suffix(family_suffix))
1278 fprintf(stderr,
1279 "Invalid character in family suffix:\n"
1280 " %s\n"
1281 " %*s\n",
1282 family_suffix,
1283 int(pos - family_suffix + 1), "^");
1284 exit(EXIT_FAILURE);
1287 int num_args = argc - optind;
1289 if (num_args > 2)
1290 show_help(false, true);
1292 FILE* in;
1293 if (num_args > 0)
1295 in = fopen(argv[optind], "rb");
1296 if (!in)
1298 fprintf(stderr,
1299 "The following error occurred while opening font `%s':\n"
1300 "\n"
1301 " %s\n",
1302 argv[optind], strerror(errno));
1303 exit(EXIT_FAILURE);
1306 else
1308 if (isatty(fileno(stdin)))
1309 show_help(false, true);
1310 in = stdin;
1313 if (show_TTFA_info)
1314 display_TTFA(in); // this function doesn't return
1316 FILE* out;
1317 if (num_args > 1)
1319 if (!strcmp(argv[optind], argv[optind + 1]))
1321 fprintf(stderr, "Input and output file names must not be identical\n");
1322 exit(EXIT_FAILURE);
1325 out = fopen(argv[optind + 1], "wb");
1326 if (!out)
1328 fprintf(stderr,
1329 "The following error occurred while opening font `%s':\n"
1330 "\n"
1331 " %s\n",
1332 argv[optind + 1], strerror(errno));
1333 exit(EXIT_FAILURE);
1336 else
1338 if (isatty(fileno(stdout)))
1339 show_help(false, true);
1340 out = stdout;
1343 FILE* control = NULL;
1344 if (control_name)
1346 control = fopen(control_name, "r");
1347 if (!control)
1349 fprintf(stderr,
1350 "The following error occurred"
1351 " while opening control file `%s':\n"
1352 "\n"
1353 " %s\n",
1354 control_name, strerror(errno));
1355 exit(EXIT_FAILURE);
1358 else
1359 control = NULL;
1361 FILE* reference = NULL;
1362 if (reference_name)
1364 reference = fopen(reference_name, "r");
1365 if (!reference)
1367 fprintf(stderr,
1368 "The following error occurred"
1369 " while opening reference font `%s':\n"
1370 "\n"
1371 " %s\n",
1372 reference_name, strerror(errno));
1373 exit(EXIT_FAILURE);
1376 if (reference_index != 0)
1378 FT_Library library = NULL;
1379 FT_Face face = NULL;
1380 FT_Error error;
1382 error = FT_Init_FreeType(&library);
1383 if (error)
1385 fprintf(stderr, "Can't initialize FreeType library:\n"
1386 "%s\n",
1387 FT_get_error_message(error));
1388 exit(EXIT_FAILURE);
1391 error = FT_New_Face(library, reference_name, -1, &face);
1392 if (error)
1394 fprintf(stderr, "Can't check number of faces in reference font:\n"
1395 "%s\n",
1396 FT_get_error_message(error));
1397 exit(EXIT_FAILURE);
1400 if (reference_index < 0
1401 || reference_index >= face->num_faces)
1403 fprintf(stderr, "Face index for reference font must be"
1404 " in the range [0;%ld]\n",
1405 face->num_faces - 1);
1406 exit(EXIT_FAILURE);
1409 FT_Done_Face(face);
1410 FT_Done_FreeType(library);
1413 else
1414 reference = NULL;
1416 Progress_Data progress_data = {-1, 1, 0};
1417 Error_Data error_data = {control_name};
1418 Info_Data info_data;
1420 if (!*family_suffix)
1421 info_post_func = NULL;
1423 info_data.no_info = no_info;
1424 info_data.detailed_info = detailed_info;
1425 info_data.info_string = NULL; // must be deallocated after use
1426 info_data.info_string_wide = NULL; // must be deallocated after use
1427 info_data.info_string_len = 0;
1428 info_data.info_string_wide_len = 0;
1430 info_data.control_name = control_name;
1431 info_data.reference_name = reference_name;
1432 info_data.reference_index = reference_index;
1434 info_data.hinting_range_min = hinting_range_min;
1435 info_data.hinting_range_max = hinting_range_max;
1436 info_data.hinting_limit = hinting_limit;
1438 info_data.gray_stem_width_mode = gray_stem_width_mode;
1439 info_data.gdi_cleartype_stem_width_mode = gdi_cleartype_stem_width_mode;
1440 info_data.dw_cleartype_stem_width_mode = dw_cleartype_stem_width_mode;
1442 info_data.windows_compatibility = windows_compatibility;
1443 info_data.adjust_subglyphs = adjust_subglyphs;
1444 info_data.hint_composites = hint_composites;
1445 info_data.increase_x_height = increase_x_height;
1446 info_data.x_height_snapping_exceptions_string = x_height_snapping_exceptions_string;
1447 info_data.family_suffix = family_suffix;
1448 info_data.family_data_head = NULL;
1449 info_data.fallback_stem_width = fallback_stem_width;
1450 info_data.symbol = symbol;
1451 info_data.fallback_scaling = fallback_scaling;
1452 info_data.TTFA_info = TTFA_info;
1454 strncpy(info_data.default_script,
1455 default_script,
1456 sizeof (info_data.default_script));
1457 strncpy(info_data.fallback_script,
1458 fallback_script,
1459 sizeof (info_data.fallback_script));
1461 info_data.dehint = dehint;
1463 if (!no_info)
1465 int ret = build_version_string(&info_data);
1466 if (ret == 1)
1467 fprintf(stderr, "Warning: Can't allocate memory"
1468 " for ttfautohint options string in `name' table\n");
1469 else if (ret == 2)
1470 fprintf(stderr, "Warning: ttfautohint options string"
1471 " in `name' table too long\n");
1474 if (in == stdin)
1475 SET_BINARY(stdin);
1476 if (out == stdout)
1477 SET_BINARY(stdout);
1479 TA_Error error =
1480 TTF_autohint("in-file, out-file, control-file,"
1481 "reference-file, reference-index, reference-name,"
1482 "hinting-range-min, hinting-range-max, hinting-limit,"
1483 "gray-stem-width-mode, gdi-cleartype-stem-width-mode,"
1484 "dw-cleartype-stem-width-mode,"
1485 "progress-callback, progress-callback-data,"
1486 "error-callback, error-callback-data,"
1487 "info-callback, info-post-callback, info-callback-data,"
1488 "ignore-restrictions, windows-compatibility,"
1489 "adjust-subglyphs, hint-composites,"
1490 "increase-x-height, x-height-snapping-exceptions,"
1491 "fallback-stem-width, default-script,"
1492 "fallback-script, fallback-scaling,"
1493 "symbol, dehint, debug, TTFA-info, epoch",
1494 in, out, control,
1495 reference, reference_index, reference_name,
1496 hinting_range_min, hinting_range_max, hinting_limit,
1497 gray_stem_width_mode, gdi_cleartype_stem_width_mode,
1498 dw_cleartype_stem_width_mode,
1499 progress_func, &progress_data,
1500 err_func, &error_data,
1501 info_func, info_post_func, &info_data,
1502 ignore_restrictions, windows_compatibility,
1503 adjust_subglyphs, hint_composites,
1504 increase_x_height, x_height_snapping_exceptions_string,
1505 fallback_stem_width, default_script,
1506 fallback_script, fallback_scaling,
1507 symbol, dehint, debug, TTFA_info, epoch);
1509 if (!no_info)
1511 free(info_data.info_string);
1512 free(info_data.info_string_wide);
1515 if (in != stdin)
1516 fclose(in);
1517 if (out != stdout)
1518 fclose(out);
1519 if (control)
1520 fclose(control);
1521 if (reference)
1522 fclose(reference);
1524 exit(error ? EXIT_FAILURE : EXIT_SUCCESS);
1526 return 0; // never reached
1528 #else // BUILD_GUI
1530 int new_argc = (int)new_arg_string.size();
1531 char** new_argv = new char*[new_argc];
1533 // construct new argc and argv variables from collected data
1534 for (unsigned int i = 0; i < (unsigned int)new_argc; i++)
1535 new_argv[i] = const_cast<char*>(new_arg_string[i].data());
1537 QApplication app(new_argc, new_argv);
1538 app.setApplicationName("TTFautohint");
1539 app.setApplicationVersion(VERSION);
1540 app.setOrganizationName("FreeType");
1541 app.setOrganizationDomain("freetype.org");
1543 bool alternative_layout = false;
1545 // Display the window off the screen -- to get proper window dimensions
1546 // including the frame, the window manager must have a chance to
1547 // decorate it.
1549 // We don't want to change the default window positioning algorithm of
1550 // the platform's window manager, so we create the main GUI window
1551 // twice.
1553 // The original idea, however, was to simply move the off-screen window
1554 // back to the screen with
1556 // gui.move(100, 100);
1557 // gui.setAttribute(Qt::WA_Moved, false);
1558 // gui.show();
1560 // (unsetting the `WA_Moved' attribute makes the window manager handle
1561 // the previous call to `move' as a position suggestion instead of a
1562 // request). Unfortuntely, there seems to be a bug in Qt 4.8.4 which
1563 // prevents any effect of unsetting `WA_Moved' if `show' has already
1564 // been called.
1566 Main_GUI dummy(alternative_layout,
1567 hinting_range_min, hinting_range_max, hinting_limit,
1568 gray_stem_width_mode, gdi_cleartype_stem_width_mode,
1569 dw_cleartype_stem_width_mode, increase_x_height,
1570 x_height_snapping_exceptions_string, fallback_stem_width,
1571 ignore_restrictions, windows_compatibility, adjust_subglyphs,
1572 hint_composites, no_info, detailed_info,
1573 default_script, fallback_script, fallback_scaling,
1574 family_suffix, symbol, dehint, TTFA_info);
1576 dummy.move(-50000, -50000);
1577 dummy.show();
1579 // if the vertical size of our window is too large,
1580 // select a horizontal layout
1581 QRect screen(QApplication::desktop()->availableGeometry());
1582 if (dummy.frameGeometry().height() > screen.height())
1583 alternative_layout = true;
1586 Main_GUI gui(alternative_layout,
1587 hinting_range_min, hinting_range_max, hinting_limit,
1588 gray_stem_width_mode, gdi_cleartype_stem_width_mode,
1589 dw_cleartype_stem_width_mode, increase_x_height,
1590 x_height_snapping_exceptions_string, fallback_stem_width,
1591 ignore_restrictions, windows_compatibility, adjust_subglyphs,
1592 hint_composites, no_info, detailed_info,
1593 default_script, fallback_script, fallback_scaling,
1594 family_suffix, symbol, dehint, TTFA_info);
1595 gui.show();
1597 return app.exec();
1599 #endif // BUILD_GUI
1602 // end of main.cpp