3 // Copyright (C) 2011-2013 by Werner Lemberg.
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.
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'.
18 # define CONSOLE_OUTPUT
21 # define CONSOLE_OUTPUT
38 # include <QApplication>
44 #include <ttfautohint.h>
45 #include <numberset.h>
50 # define SET_BINARY(f) do { \
51 if (!isatty(fileno(f))) \
52 setmode(fileno(f), O_BINARY); \
57 # define SET_BINARY(f) do {} while (0)
67 typedef struct Progress_Data_
76 progress(long curr_idx
,
82 Progress_Data
* data
= (Progress_Data
*)user
;
84 if (num_sfnts
> 1 && curr_sfnt
!= data
->last_sfnt
)
86 fprintf(stderr
, "subfont %ld of %ld\n", curr_sfnt
+ 1, num_sfnts
);
87 data
->last_sfnt
= curr_sfnt
;
88 data
->last_percent
= 0;
94 fprintf(stderr
, " %ld glyphs\n"
99 // print progress approx. every 10%
100 int curr_percent
= curr_idx
* 100 / num_glyphs
;
101 int curr_diff
= curr_percent
- data
->last_percent
;
105 fprintf(stderr
, " %d%%", curr_percent
);
106 data
->last_percent
= curr_percent
- curr_percent
% 10;
109 if (curr_idx
+ 1 == num_glyphs
)
110 fprintf(stderr
, "\n");
119 #ifdef CONSOLE_OUTPUT
128 FILE* handle
= is_error
? stderr
: stdout
;
132 "Usage: ttfautohintGUI [OPTION]...\n"
133 "A GUI application to replace hints in a TrueType font.\n"
135 "Usage: ttfautohint [OPTION]... [IN-FILE [OUT-FILE]]\n"
136 "Replace hints in TrueType font IN-FILE and write output to OUT-FILE.\n"
137 "If OUT-FILE is missing, standard output is used instead;\n"
138 "if IN-FILE is missing also, standard input and output are used.\n"
141 "The new hints are based on FreeType's auto-hinter.\n"
143 "This program is a simple front-end to the `ttfautohint' library.\n"
147 "Long options can be given with one or two dashes,\n"
148 "and with and without equal sign between option and argument.\n"
149 "This means that the following forms are acceptable:\n"
150 "`-foo=bar', `--foo=bar', `-foo bar', `--foo bar'.\n"
152 "Mandatory arguments to long options are mandatory for short options too.\n"
154 "Options not related to Qt or X11 set default values.\n"
162 " --debug print debugging information\n"
164 " -c, --components hint glyph components separately\n"
165 " -f, --latin-fallback set fallback script to latin\n"
166 " -G, --hinting-limit=N switch off hinting above this PPEM value\n"
167 " (default: %d); value 0 means no limit\n"
168 " -h, --help display this help and exit\n"
170 " --help-all show Qt and X11 specific options also\n"
172 " -i, --ignore-restrictions override font license restrictions\n"
173 " -l, --hinting-range-min=N the minimum PPEM value for hint sets\n"
175 " -n, --no-info don't add ttfautohint info\n"
176 " to the version string(s) in the `name' table\n"
177 " -p, --pre-hinting apply original hints in advance\n",
178 TA_HINTING_LIMIT
, TA_HINTING_RANGE_MIN
);
180 " -r, --hinting-range-max=N the maximum PPEM value for hint sets\n"
182 " -s, --symbol input is symbol font\n"
183 " -v, --verbose show progress information\n"
184 " -V, --version print version information and exit\n"
185 " -w, --strong-stem-width=S use strong stem width routine for modes S,\n"
186 " where S is a string of up to three letters\n"
187 " with possible values `g' for grayscale,\n"
188 " `G' for GDI ClearType, and `D' for\n"
189 " DirectWrite ClearType (default: G)\n"
190 " -W, --windows-compatibility\n"
191 " add blue zones for `usWinAscent' and\n"
192 " `usWinDescent' to avoid clipping\n"
193 " -x, --increase-x-height=N increase x height for sizes in the range\n"
194 " 6<=PPEM<=N; value 0 switches off this feature\n"
196 " -X, --x-height-snapping-exceptions=STRING\n"
197 " specify a comma-separated list of\n"
198 " x-height snapping exceptions, for example\n"
199 " \"-9, 13-17, 19\" (default: \"\")\n"
201 TA_HINTING_RANGE_MAX
, TA_INCREASE_X_HEIGHT
);
208 " --graphicssystem=SYSTEM\n"
209 " select a different graphics system backend\n"
210 " instead of the default one\n"
211 " (possible values: `raster', `opengl')\n"
212 " --reverse set layout direction to right-to-left\n");
214 " --session=ID restore the application for the given ID\n"
215 " --style=STYLE set application GUI style\n"
216 " (possible values: motif, windows, platinum)\n"
217 " --stylesheet=SHEET apply the given Qt stylesheet\n"
218 " to the application widgets\n"
223 " --background=COLOR set the default background color\n"
224 " and an application palette\n"
225 " (light and dark shades are calculated)\n"
226 " --bg=COLOR same as --background\n"
227 " --btn=COLOR set the default button color\n"
228 " --button=COLOR same as --btn\n"
229 " --cmap use a private color map on an 8-bit display\n"
230 " --display=NAME use the given X-server display\n");
232 " --fg=COLOR set the default foreground color\n"
233 " --fn=FONTNAME set the application font\n"
234 " --font=FONTNAME same as --fn\n"
235 " --foreground=COLOR same as --fg\n"
236 " --geometry=GEOMETRY set the client geometry of first window\n"
237 " --im=SERVER set the X Input Method (XIM) server\n"
238 " --inputstyle=STYLE set X Input Method input style\n"
239 " (possible values: onthespot, overthespot,\n"
240 " offthespot, root)\n");
242 " --name=NAME set the application name\n"
243 " --ncols=COUNT limit the number of colors allocated\n"
244 " in the color cube on an 8-bit display,\n"
245 " if the application is using the\n"
246 " QApplication::ManyColor color specification\n"
247 " --title=TITLE set the application title (caption)\n"
248 " --visual=VISUAL force the application\n"
249 " to use the given visual on an 8-bit display\n"
250 " (only possible value: TrueColor)\n"
256 "The program accepts both TTF and TTC files as input.\n"
257 "Use option -i only if you have a legal permission to modify the font.\n"
258 "If option -f is not set, glyphs not in the latin range stay unhinted.\n"
259 "The used PPEM value for option -p is FUnits per em, normally 2048.\n"
260 "With option -s, use default values for standard stem width and height,\n"
261 "otherwise they are derived from latin character `o'.\n"
264 "A hint set contains the optimal hinting for a certain PPEM value;\n"
265 "the larger the hint set range, the more hint sets get computed,\n"
266 "usually increasing the output font size. Note, however,\n"
267 "that the `gasp' table of the output file enables grayscale hinting\n"
268 "for all sizes (limited by option -G which is handled in the bytecode).\n"
272 "A command-line version of this program is called `ttfautohint'.\n"
274 "A GUI version of this program is called `ttfautohintGUI'.\n"
277 "Report bugs to: freetype-devel@nongnu.org\n"
278 "ttfautohint home page: <http://www.freetype.org/ttfautohint>\n");
292 "ttfautohintGUI " VERSION
"\n"
294 "ttfautohint " VERSION
"\n"
296 "Copyright (C) 2011-2013 Werner Lemberg <wl@gnu.org>.\n"
297 "License: FreeType License (FTL) or GNU GPLv2.\n"
298 "This is free software: you are free to change and redistribute it.\n"
299 "There is NO WARRANTY, to the extent permitted by law.\n");
303 #endif // CONSOLE_OUTPUT
310 int hinting_range_min
= 0;
311 int hinting_range_max
= 0;
312 int hinting_limit
= 0;
313 int increase_x_height
= 0;
314 bool have_hinting_range_min
= false;
315 bool have_hinting_range_max
= false;
316 bool have_hinting_limit
= false;
317 bool have_increase_x_height
= false;
319 bool gray_strong_stem_width
= false;
320 bool gdi_cleartype_strong_stem_width
= true;
321 bool dw_cleartype_strong_stem_width
= false;
323 bool ignore_restrictions
= false;
324 bool windows_compatibility
= false;
325 bool pre_hinting
= false;
326 bool hint_with_components
= true;
327 bool no_info
= false;
328 int latin_fallback
= 0; // leave it as int; this probably gets extended
331 const char* x_height_snapping_exceptions_string
= NULL
;
332 bool have_x_height_snapping_exceptions_string
= false;
337 TA_Progress_Func progress_func
= NULL
;
338 TA_Info_Func info_func
= info
;
341 // make GNU, Qt, and X11 command line options look the same;
342 // we allow `--foo=bar', `--foo bar', `-foo=bar', `-foo bar',
343 // and short options specific to ttfautohint
345 // set up a new argument string
346 vector
<string
> new_arg_string
;
347 new_arg_string
.push_back(argv
[0]);
351 // use pseudo short options for long-only options
354 PASS_THROUGH
= CHAR_MAX
+ 1,
359 static struct option long_options
[] =
361 {"help", no_argument
, NULL
, 'h'},
363 {"help-all", no_argument
, NULL
, HELP_ALL_OPTION
},
366 // ttfautohint options
367 {"components", no_argument
, NULL
, 'c'},
369 {"debug", no_argument
, NULL
, DEBUG_OPTION
},
371 {"hinting-limit", required_argument
, NULL
, 'G'},
372 {"hinting-range-max", required_argument
, NULL
, 'r'},
373 {"hinting-range-min", required_argument
, NULL
, 'l'},
374 {"ignore-restrictions", no_argument
, NULL
, 'i'},
375 {"increase-x-height", required_argument
, NULL
, 'x'},
376 {"latin-fallback", no_argument
, NULL
, 'f'},
377 {"no-info", no_argument
, NULL
, 'n'},
378 {"pre-hinting", no_argument
, NULL
, 'p'},
379 {"strong-stem-width", required_argument
, NULL
, 'w'},
380 {"symbol", no_argument
, NULL
, 's'},
381 {"verbose", no_argument
, NULL
, 'v'},
382 {"version", no_argument
, NULL
, 'V'},
383 {"windows-compatibility", no_argument
, NULL
, 'W'},
384 {"x-height-snapping-exceptions", required_argument
, NULL
, 'X'},
387 {"graphicssystem", required_argument
, NULL
, PASS_THROUGH
},
388 {"reverse", no_argument
, NULL
, PASS_THROUGH
},
389 {"session", required_argument
, NULL
, PASS_THROUGH
},
390 {"style", required_argument
, NULL
, PASS_THROUGH
},
391 {"stylesheet", required_argument
, NULL
, PASS_THROUGH
},
394 {"background", required_argument
, NULL
, PASS_THROUGH
},
395 {"bg", required_argument
, NULL
, PASS_THROUGH
},
396 {"btn", required_argument
, NULL
, PASS_THROUGH
},
397 {"button", required_argument
, NULL
, PASS_THROUGH
},
398 {"cmap", no_argument
, NULL
, PASS_THROUGH
},
399 {"display", required_argument
, NULL
, PASS_THROUGH
},
400 {"fg", required_argument
, NULL
, PASS_THROUGH
},
401 {"fn", required_argument
, NULL
, PASS_THROUGH
},
402 {"font", required_argument
, NULL
, PASS_THROUGH
},
403 {"foreground", required_argument
, NULL
, PASS_THROUGH
},
404 {"geometry", required_argument
, NULL
, PASS_THROUGH
},
405 {"im", required_argument
, NULL
, PASS_THROUGH
},
406 {"inputstyle", required_argument
, NULL
, PASS_THROUGH
},
407 {"name", required_argument
, NULL
, PASS_THROUGH
},
408 {"ncols", required_argument
, NULL
, PASS_THROUGH
},
409 {"title", required_argument
, NULL
, PASS_THROUGH
},
410 {"visual", required_argument
, NULL
, PASS_THROUGH
},
416 int c
= getopt_long_only(argc
, argv
, "cfG:hil:npr:stVvw:Wx:X:",
417 long_options
, &option_index
);
424 hint_with_components
= false;
432 hinting_limit
= atoi(optarg
);
433 have_hinting_limit
= true;
437 #ifdef CONSOLE_OUTPUT
438 show_help(false, false);
443 ignore_restrictions
= true;
447 hinting_range_min
= atoi(optarg
);
448 have_hinting_range_min
= true;
460 hinting_range_max
= atoi(optarg
);
461 have_hinting_range_max
= true;
470 progress_func
= progress
;
475 #ifdef CONSOLE_OUTPUT
481 gray_strong_stem_width
= strchr(optarg
, 'g') ? true : false;
482 gdi_cleartype_strong_stem_width
= strchr(optarg
, 'G') ? true : false;
483 dw_cleartype_strong_stem_width
= strchr(optarg
, 'D') ? true : false;
487 windows_compatibility
= true;
491 increase_x_height
= atoi(optarg
);
492 have_increase_x_height
= true;
496 x_height_snapping_exceptions_string
= optarg
;
497 have_x_height_snapping_exceptions_string
= true;
507 case HELP_ALL_OPTION
:
508 #ifdef CONSOLE_OUTPUT
509 show_help(true, false);
516 // append argument with proper syntax for Qt
519 arg
+= long_options
[option_index
].name
;
521 new_arg_string
.push_back(arg
);
523 new_arg_string
.push_back(optarg
);
532 if (!have_hinting_range_min
)
533 hinting_range_min
= TA_HINTING_RANGE_MIN
;
534 if (!have_hinting_range_max
)
535 hinting_range_max
= TA_HINTING_RANGE_MAX
;
536 if (!have_hinting_limit
)
537 hinting_limit
= TA_HINTING_LIMIT
;
538 if (!have_increase_x_height
)
539 increase_x_height
= TA_INCREASE_X_HEIGHT
;
540 if (!have_x_height_snapping_exceptions_string
)
541 x_height_snapping_exceptions_string
= "";
545 if (!isatty(fileno(stderr
)) && !debug
)
546 setvbuf(stderr
, (char*)NULL
, _IONBF
, BUFSIZ
);
548 if (hinting_range_min
< 2)
550 fprintf(stderr
, "The hinting range minimum must be at least 2\n");
553 if (hinting_range_max
< hinting_range_min
)
555 fprintf(stderr
, "The hinting range maximum must not be smaller"
556 " than the minimum (%d)\n",
560 if (hinting_limit
!= 0 && hinting_limit
< hinting_range_max
)
562 fprintf(stderr
, "A non-zero hinting limit must not be smaller"
563 " than the hinting range maximum (%d)\n",
567 if (increase_x_height
!= 0 && increase_x_height
< 6)
569 fprintf(stderr
, "A non-zero x height increase limit"
570 " must be larger than or equal to 6\n");
574 number_range
* x_height_snapping_exceptions
= NULL
;
576 if (have_x_height_snapping_exceptions_string
)
581 s
= number_set_parse(x_height_snapping_exceptions_string
,
582 &x_height_snapping_exceptions
,
586 if (x_height_snapping_exceptions
== NUMBERSET_ALLOCATION_ERROR
)
587 fprintf(stderr
, "Allocation error while scanning"
588 " x height snapping exceptions\n");
590 if (x_height_snapping_exceptions
== NUMBERSET_INVALID_CHARACTER
)
591 fprintf(stderr
, "Invalid character");
592 else if (x_height_snapping_exceptions
== NUMBERSET_OVERFLOW
)
593 fprintf(stderr
, "Overflow");
594 else if (x_height_snapping_exceptions
== NUMBERSET_INVALID_RANGE
)
595 fprintf(stderr
, "Invalid range");
596 else if (x_height_snapping_exceptions
== NUMBERSET_OVERLAPPING_RANGES
)
597 fprintf(stderr
, "Overlapping ranges");
598 else if (x_height_snapping_exceptions
== NUMBERSET_NOT_ASCENDING
)
599 fprintf(stderr
, "Values und ranges must be ascending");
600 fprintf(stderr
, " in x height snapping exceptions:\n"
603 x_height_snapping_exceptions_string
,
604 s
- x_height_snapping_exceptions_string
+ 1, "^");
610 int num_args
= argc
- optind
;
613 show_help(false, true);
618 in
= fopen(argv
[optind
], "rb");
621 fprintf(stderr
, "The following error occurred while opening font `%s':\n"
624 argv
[optind
], strerror(errno
));
630 if (isatty(fileno(stdin
)))
631 show_help(false, true);
638 if (!strcmp(argv
[optind
], argv
[optind
+ 1]))
640 fprintf(stderr
, "Input and output file names must not be identical\n");
644 out
= fopen(argv
[optind
+ 1], "wb");
647 fprintf(stderr
, "The following error occurred while opening font `%s':\n"
650 argv
[optind
+ 1], strerror(errno
));
656 if (isatty(fileno(stdout
)))
657 show_help(false, true);
661 const unsigned char* error_string
;
662 Progress_Data progress_data
= {-1, 1, 0};
669 info_data
.data
= NULL
; // must be deallocated after use
670 info_data
.data_wide
= NULL
; // must be deallocated after use
671 info_data
.data_len
= 0;
672 info_data
.data_wide_len
= 0;
674 info_data
.hinting_range_min
= hinting_range_min
;
675 info_data
.hinting_range_max
= hinting_range_max
;
676 info_data
.hinting_limit
= hinting_limit
;
678 info_data
.gray_strong_stem_width
= gray_strong_stem_width
;
679 info_data
.gdi_cleartype_strong_stem_width
= gdi_cleartype_strong_stem_width
;
680 info_data
.dw_cleartype_strong_stem_width
= dw_cleartype_strong_stem_width
;
682 info_data
.windows_compatibility
= windows_compatibility
;
683 info_data
.pre_hinting
= pre_hinting
;
684 info_data
.hint_with_components
= hint_with_components
;
685 info_data
.increase_x_height
= increase_x_height
;
686 info_data
.x_height_snapping_exceptions
= x_height_snapping_exceptions
;
687 info_data
.latin_fallback
= latin_fallback
;
688 info_data
.symbol
= symbol
;
690 int ret
= build_version_string(&info_data
);
692 fprintf(stderr
, "Warning: Can't allocate memory"
693 " for ttfautohint options string in `name' table\n");
695 fprintf(stderr
, "Warning: ttfautohint options string"
696 " in `name' table too long\n");
705 TTF_autohint("in-file, out-file,"
706 "hinting-range-min, hinting-range-max, hinting-limit,"
707 "gray-strong-stem-width, gdi-cleartype-strong-stem-width,"
708 "dw-cleartype-strong-stem-width,"
710 "progress-callback, progress-callback-data,"
711 "info-callback, info-callback-data,"
712 "ignore-restrictions, windows-compatibility,"
713 "pre-hinting, hint-with-components,"
714 "increase-x-height, x-height-snapping-exceptions,"
715 "fallback-script, symbol,"
718 hinting_range_min
, hinting_range_max
, hinting_limit
,
719 gray_strong_stem_width
, gdi_cleartype_strong_stem_width
,
720 dw_cleartype_strong_stem_width
,
722 progress_func
, &progress_data
,
723 info_func
, &info_data
,
724 ignore_restrictions
, windows_compatibility
,
725 pre_hinting
, hint_with_components
,
726 increase_x_height
, x_height_snapping_exceptions_string
,
727 latin_fallback
, symbol
,
732 free(info_data
.data
);
733 free(info_data
.data_wide
);
736 number_set_free(x_height_snapping_exceptions
);
740 if (error
== TA_Err_Invalid_FreeType_Version
)
742 "FreeType version 2.4.5 or higher is needed.\n"
743 "Perhaps using a wrong FreeType DLL?\n");
744 else if (error
== TA_Err_Invalid_Font_Type
)
746 "This font is not a valid font"
747 " in SFNT format with TrueType outlines.\n"
748 "In particular, CFF outlines are not supported.\n");
749 else if (error
== TA_Err_Already_Processed
)
751 "This font has already been processed with ttfautohint.\n");
752 else if (error
== TA_Err_Missing_Legal_Permission
)
754 "Bit 1 in the `fsType' field of the `OS/2' table is set:\n"
755 "This font must not be modified"
756 " without permission of the legal owner.\n"
757 "Use command line option `-i' to continue"
758 " if you have such a permission.\n");
759 else if (error
== TA_Err_Missing_Unicode_CMap
)
761 "No Unicode character map.\n");
762 else if (error
== TA_Err_Missing_Symbol_CMap
)
764 "No symbol character map.\n");
765 else if (error
== TA_Err_Missing_Glyph
)
767 "No glyph for the key character"
768 " to derive standard width and height.\n"
769 "For the latin script, this key character is `o' (U+006F).\n");
772 "Error code `0x%02x' while autohinting font:\n"
773 " %s\n", error
, error_string
);
784 return 0; // never reached
788 int new_argc
= new_arg_string
.size();
789 char** new_argv
= new char*[new_argc
];
791 // construct new argc and argv variables from collected data
792 for (int i
= 0; i
< new_argc
; i
++)
793 new_argv
[i
] = const_cast<char*>(new_arg_string
[i
].data());
795 QApplication
app(new_argc
, new_argv
);
796 app
.setApplicationName("TTFautohint");
797 app
.setApplicationVersion(VERSION
);
798 app
.setOrganizationName("FreeType");
799 app
.setOrganizationDomain("freetype.org");
801 Main_GUI
gui(hinting_range_min
, hinting_range_max
, hinting_limit
,
802 gray_strong_stem_width
, gdi_cleartype_strong_stem_width
,
803 dw_cleartype_strong_stem_width
, increase_x_height
,
804 x_height_snapping_exceptions_string
,
805 ignore_restrictions
, windows_compatibility
, pre_hinting
,
806 hint_with_components
, no_info
, latin_fallback
, symbol
);