3 // Copyright (C) 2011-2016 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
39 # include <QApplication>
42 # include <ft2build.h>
43 # include FT_FREETYPE_H
44 # include FT_TRUETYPE_TABLES_H // for option `-T'
48 #include <ttfautohint.h>
49 #include <numberset.h>
54 # define SET_BINARY(f) do { \
55 if (!isatty(fileno(f))) \
56 setmode(fileno(f), O_BINARY); \
61 # define SET_BINARY(f) do {} while (0)
68 typedef struct Tag_Names_
71 const char* description
;
75 // the available script tags and its descriptions are directly extracted
76 // from `ttfautohint-scripts.h'
78 #define SCRIPT(s, S, d, h, H, ss) \
81 const Tag_Names script_names
[] =
83 #include <ttfautohint-scripts.h>
88 // the available feature tags and its descriptions are directly extracted
89 // from `ttfautohint-coverages.h'
91 #define COVERAGE(n, N, d, t, t1, t2, t3, t4) \
94 const Tag_Names feature_names
[] =
96 #include <ttfautohint-coverages.h>
104 typedef struct Progress_Data_
113 progress(long curr_idx
,
119 Progress_Data
* data
= (Progress_Data
*)user
;
121 if (num_sfnts
> 1 && curr_sfnt
!= data
->last_sfnt
)
123 fprintf(stderr
, "subfont %ld of %ld\n", curr_sfnt
+ 1, num_sfnts
);
124 data
->last_sfnt
= curr_sfnt
;
125 data
->last_percent
= 0;
131 fprintf(stderr
, " %ld glyphs\n"
136 // print progress approx. every 10%
137 int curr_percent
= curr_idx
* 100 / num_glyphs
;
138 int curr_diff
= curr_percent
- data
->last_percent
;
142 fprintf(stderr
, " %d%%", curr_percent
);
143 data
->last_percent
= curr_percent
- curr_percent
% 10;
146 if (curr_idx
+ 1 == num_glyphs
)
147 fprintf(stderr
, "\n");
153 typedef struct Error_Data_
155 const char* control_name
;
161 const char* error_string
,
162 unsigned int errlinenum
,
167 Error_Data
* data
= static_cast<Error_Data
*>(user
);
172 // We replace some terse error strings with more user-friendly versions.
173 if (error
== TA_Err_Invalid_FreeType_Version
)
175 "FreeType version 2.4.5 or higher is needed.\n"
176 "Perhaps using a wrong FreeType DLL?\n");
177 else if (error
== TA_Err_Invalid_Font_Type
)
179 "This font is not a valid font"
180 " in SFNT format with TrueType outlines.\n"
181 "In particular, CFF outlines are not supported.\n");
182 else if (error
== TA_Err_Already_Processed
)
184 "This font has already been processed with ttfautohint.\n");
185 else if (error
== TA_Err_Missing_Legal_Permission
)
187 "Bit 1 in the `fsType' field of the `OS/2' table is set:\n"
188 "This font must not be modified"
189 " without permission of the legal owner.\n"
190 "Use command line option `-i' to continue"
191 " if you have such a permission.\n");
192 else if (error
== TA_Err_Missing_Unicode_CMap
)
194 "No Unicode character map.\n");
195 else if (error
== TA_Err_Missing_Symbol_CMap
)
197 "No symbol character map.\n");
198 else if (error
== TA_Err_Missing_Glyph
)
200 "No glyph for a standard character"
201 " to derive standard width and height.\n"
202 "Please check the documentation for a list of"
203 " script-specific standard characters,\n"
204 "or use option `--symbol'.\n");
208 fprintf(stderr
, "An error with code 0x%02x occurred"
209 " while autohinting fonts\n",
211 else if (error
>= 0x100 && error
< 0x200)
213 fprintf(stderr
, "An error with code 0x%03x occurred"
214 " while parsing the argument of option `-X'",
216 fprintf(stderr
, errline
? ":\n" : ".\n");
219 fprintf(stderr
, " %s\n", errline
);
220 if (errpos
&& errline
)
221 fprintf(stderr
, " %*s\n", int(errpos
- errline
+ 1), "^");
223 else if (error
>= 0x200 && error
< 0x300)
225 fprintf(stderr
, "%s:", data
->control_name
);
227 fprintf(stderr
, "%d:", errlinenum
);
228 if (errpos
&& errline
)
229 fprintf(stderr
, "%d:", int(errpos
- errline
+ 1));
231 fprintf(stderr
, " %s", error_string
);
232 fprintf(stderr
, " (0x%02X)\n", error
);
234 fprintf(stderr
, " %s\n", errline
);
235 if (errpos
&& errline
)
236 fprintf(stderr
, " %*s\n", int(errpos
- errline
+ 1), "^");
246 #ifdef CONSOLE_OUTPUT
255 FILE* handle
= is_error
? stderr
: stdout
;
259 "Usage: ttfautohintGUI [OPTION]...\n"
260 "A GUI application to replace hints in a TrueType font.\n"
262 "Usage: ttfautohint [OPTION]... [IN-FILE [OUT-FILE]]\n"
263 "Replace hints in TrueType font IN-FILE and write output to OUT-FILE.\n"
264 "If OUT-FILE is missing, standard output is used instead;\n"
265 "if IN-FILE is missing also, standard input and output are used.\n"
268 "The new hints are based on FreeType's auto-hinter.\n"
270 "This program is a simple front-end to the `ttfautohint' library.\n"
274 "Long options can be given with one or two dashes,\n"
275 "and with and without equal sign between option and argument.\n"
276 "This means that the following forms are acceptable:\n"
277 "`-foo=bar', `--foo=bar', `-foo bar', `--foo bar'.\n"
279 "Mandatory arguments to long options are mandatory for short options too.\n"
281 "Options not related to Qt or X11 set default values.\n"
289 " --debug print debugging information\n"
291 " -c, --composites hint glyph composites also\n"
292 " -d, --dehint remove all hints\n"
293 " -D, --default-script=S set default OpenType script (default: latn)\n"
294 " -f, --fallback-script=S set fallback script (default: none)\n"
295 " -F, --family-suffix=S append suffix to the family name string(s)\n"
296 " in the `name' table\n"
297 " -G, --hinting-limit=N switch off hinting above this PPEM value\n"
298 " (default: %d); value 0 means no limit\n"
299 " -h, --help display this help and exit\n"
300 " -H, --fallback-stem-width=N\n"
301 " set fallback stem width\n"
302 " (default: 50 font units at 2048 UPEM)\n"
304 " --help-all show Qt and X11 specific options also\n"
306 " -i, --ignore-restrictions override font license restrictions\n"
307 " -I, --detailed-info add detailed ttfautohint info\n"
308 " to the version string(s) in the `name' table\n"
309 " -l, --hinting-range-min=N the minimum PPEM value for hint sets\n"
312 " -m, --control-file=FILE get control instructions from FILE\n"
314 " -n, --no-info don't add ttfautohint info\n"
315 " to the version string(s) in the `name' table\n"
316 " -p, --adjust-subglyphs handle subglyph adjustments in exotic fonts\n",
317 TA_HINTING_LIMIT
, TA_HINTING_RANGE_MIN
);
319 " -r, --hinting-range-max=N the maximum PPEM value for hint sets\n"
321 " -s, --symbol input is symbol font\n"
322 " -S, --fallback-scaling use fallback scaling, not hinting\n"
323 " -t, --ttfa-table add TTFA information table\n"
325 " -T, --ttfa-info display TTFA table in IN-FILE and exit\n"
327 " -v, --verbose show progress information\n"
328 " -V, --version print version information and exit\n"
329 " -w, --strong-stem-width=S use strong stem width routine for modes S,\n"
330 " where S is a string of up to three letters\n"
331 " with possible values `g' for grayscale,\n"
332 " `G' for GDI ClearType, and `D' for\n"
333 " DirectWrite ClearType (default: G)\n"
334 " -W, --windows-compatibility\n"
335 " add blue zones for `usWinAscent' and\n"
336 " `usWinDescent' to avoid clipping\n"
337 " -x, --increase-x-height=N increase x height for sizes in the range\n"
338 " 6<=PPEM<=N; value 0 switches off this feature\n"
340 " -X, --x-height-snapping-exceptions=STRING\n"
341 " specify a comma-separated list of\n"
342 " x-height snapping exceptions, for example\n"
343 " \"-9, 13-17, 19\" (default: \"\")\n"
345 TA_HINTING_RANGE_MAX
, TA_INCREASE_X_HEIGHT
);
352 " --graphicssystem=SYSTEM\n"
353 " select a different graphics system backend\n"
354 " instead of the default one\n"
355 " (possible values: `raster', `opengl')\n"
356 " --reverse set layout direction to right-to-left\n");
358 " --session=ID restore the application for the given ID\n"
359 " --style=STYLE set application GUI style\n"
360 " (possible values: motif, windows, platinum)\n"
361 " --stylesheet=SHEET apply the given Qt stylesheet\n"
362 " to the application widgets\n"
367 " --background=COLOR set the default background color\n"
368 " and an application palette\n"
369 " (light and dark shades are calculated)\n"
370 " --bg=COLOR same as --background\n"
371 " --btn=COLOR set the default button color\n"
372 " --button=COLOR same as --btn\n"
373 " --cmap use a private color map on an 8-bit display\n"
374 " --display=NAME use the given X-server display\n");
376 " --fg=COLOR set the default foreground color\n"
377 " --fn=FONTNAME set the application font\n"
378 " --font=FONTNAME same as --fn\n"
379 " --foreground=COLOR same as --fg\n"
380 " --geometry=GEOMETRY set the client geometry of first window\n"
381 " --im=SERVER set the X Input Method (XIM) server\n"
382 " --inputstyle=STYLE set X Input Method input style\n"
383 " (possible values: onthespot, overthespot,\n"
384 " offthespot, root)\n");
386 " --name=NAME set the application name\n"
387 " --ncols=COUNT limit the number of colors allocated\n"
388 " in the color cube on an 8-bit display,\n"
389 " if the application is using the\n"
390 " QApplication::ManyColor color specification\n"
391 " --title=TITLE set the application title (caption)\n"
392 " --visual=VISUAL force the application\n"
393 " to use the given visual on an 8-bit display\n"
394 " (only possible value: TrueColor)\n"
400 "The program accepts both TTF and TTC files as input.\n"
401 "Use option -i only if you have a legal permission to modify the font.\n"
402 "The used PPEM value for option -p is FUnits per em, normally 2048.\n"
403 "With option -s, use default values for standard stem width and height,\n"
404 "otherwise they are derived from script-specific characters\n"
405 "resembling the shape of character `o'.\n"
408 "A hint set contains the optimal hinting for a certain PPEM value;\n"
409 "the larger the hint set range (as given by options -l and -r),\n"
410 "the more hint sets get computed, usually increasing the output font size.\n"
411 "The `gasp' table of the output file always enables grayscale hinting\n"
412 "for all sizes (limited by option -G, which is handled in the bytecode).\n"
413 "Increasing the value of -G does not increase the output font size.\n"
416 "Options -f and -D take a four-letter string that identifies a script.\n"
417 "Option -f sets the script used as a fallback for glyphs that can't be\n"
418 "associated with a known script. By default, such glyphs are hinted;\n"
419 "if option -S is set, they are scaled only instead. Option -D sets the\n"
420 "default script for handling OpenType features.\n"
422 "Possible four-letter string values are\n"
424 const Tag_Names
* sn
= script_names
;
427 fprintf(handle
, " %s (%s)",
428 sn
->tag
, sn
->description
);
431 fprintf(handle
, ",\n");
434 fprintf(handle
, ".\n");
441 "A control instructions file contains entries of the form\n"
443 " [<font idx>] <script> <feature> @ <glyph ids>\n"
445 " [<font idx>] <glyph id> l|r <points> [(<left offset>,<right offset>)]\n"
447 " [<font idx>] <glyph id> n <points>\n"
449 " [<font idx>] <glyph id> t|p <points> [x <shift>] [y <shift>] @ <ppems>\n"
451 "<font idx> is the current subfont, <glyph id> is a glyph name or index,\n"
452 "<glyph ids> is a set of <glyph id>s, <shift> is a real number in px,\n"
453 "<points> and <ppems> are integer ranges as with option `-X'.\n"
455 "<script> and <feature> are four-letter tags that define a style\n"
456 "the <glyph ids> are assigned to; possible values for <script> are the same\n"
457 "as with option -D, possible values for <feature> are\n"
459 const Tag_Names
* fn
= feature_names
;
462 fprintf(handle
, " %s (%s)",
463 fn
->tag
, fn
->description
);
466 fprintf(handle
, ",\n");
469 fprintf(handle
, ".\n");
475 "`l' (`r') creates one-point segments with direction left (right).\n"
476 "<left offset> and <right offset> specify offsets (in font units)\n"
477 "relative to the corresponding points to give the segments a length.\n"
478 "`n' removes points from horizontal segments, making them `weak' points.\n"
479 "`t' (`p') applies delta exceptions to the given points before (after) IUP.\n"
481 "`#' starts a line comment, which gets ignored.\n"
482 "Empty lines are ignored, too.\n"
484 "Key letters `l', `r', `n', `p', `t', `x', and `y' have the verbose aliases\n"
485 "`left', `right', `nodir', `point', `touch', `xshift', and `yshift'.\n"
489 "A command-line version of this program is called `ttfautohint'.\n"
491 "A GUI version of this program is called `ttfautohintGUI'.\n"
494 "Report bugs to: freetype-devel@nongnu.org\n"
496 "ttfautohint home page: <http://www.freetype.org/ttfautohint>\n");
510 "ttfautohintGUI " VERSION
"\n"
512 "ttfautohint " VERSION
"\n"
514 "Copyright (C) 2011-2016 Werner Lemberg <wl@gnu.org>.\n"
515 "License: FreeType License (FTL) or GNU GPLv2.\n"
516 "This is free software: you are free to change and redistribute it.\n"
517 "There is NO WARRANTY, to the extent permitted by law.\n");
521 #endif // CONSOLE_OUTPUT
526 typedef const struct FT_error_
532 static FT_error FT_errors
[] =
534 #undef __FTERRORS_H__
535 #define FT_ERRORDEF(e, v, s) { e, s },
536 #define FT_ERROR_START_LIST {
537 #define FT_ERROR_END_LIST { 0, NULL } };
542 FT_get_error_message(FT_Error error
)
544 FT_error
* e
= FT_errors
;
546 while (e
->err_code
|| e
->err_msg
)
548 if (e
->err_code
== error
)
557 #define BUF_SIZE 0x10000
559 #define TTAG_TTFA FT_MAKE_TAG('T', 'T', 'F', 'A')
562 display_TTFA(FILE* in
)
564 FT_Byte buf
[BUF_SIZE
];
572 in_buf
= (FT_Byte
*)malloc(BUF_SIZE
);
575 fprintf(stderr
, "Can't allocate enough memory.\n");
579 while ((read_bytes
= fread(buf
, 1, BUF_SIZE
, in
)) > 0)
581 FT_Byte
* in_buf_new
= (FT_Byte
*)realloc(in_buf
, in_len
+ read_bytes
);
584 fprintf(stderr
, "Can't reallocate enough memory.\n");
590 memcpy(in_buf
+ in_len
, buf
, read_bytes
);
592 in_len
+= read_bytes
;
597 fprintf(stderr
, "Stream error while handling input font.\n");
605 error
= FT_Init_FreeType(&library
);
608 fprintf(stderr
, "Can't initialize FreeType library:\n"
609 "%s\n", FT_get_error_message(error
));
613 // in a TTC, a `TTFA' table is part of the first subfont,
614 // thus we can simply pass 0 as the face index
615 error
= FT_New_Memory_Face(library
, in_buf
, (FT_Long
)in_len
, 0, &face
);
618 fprintf(stderr
, "Can't open input font:\n"
619 "%s\n", FT_get_error_message(error
));
623 FT_Byte
* ttfa_buf
= NULL
;
624 FT_ULong ttfa_len
= 0;
626 error
= FT_Load_Sfnt_Table(face
, TTAG_TTFA
, 0, NULL
, &ttfa_len
);
629 fprintf(stderr
, "No `TTFA' table in font.\n");
633 ttfa_buf
= (FT_Byte
*)malloc(ttfa_len
);
636 fprintf(stderr
, "Can't allocate enough memory.\n");
640 error
= FT_Load_Sfnt_Table(face
, TTAG_TTFA
, 0, ttfa_buf
, &ttfa_len
);
643 fprintf(stderr
, "Error loading `TTFA' table:\n"
644 "%s\n", FT_get_error_message(error
));
648 fprintf(stdout
, "%s", ttfa_buf
);
652 FT_Done_FreeType(library
);
668 int hinting_range_min
= 0;
669 int hinting_range_max
= 0;
670 int hinting_limit
= 0;
671 int increase_x_height
= 0;
672 int fallback_stem_width
= 0;
674 bool have_hinting_range_min
= false;
675 bool have_hinting_range_max
= false;
676 bool have_hinting_limit
= false;
677 bool have_increase_x_height
= false;
678 bool have_fallback_stem_width
= false;
680 bool gray_strong_stem_width
= false;
681 bool gdi_cleartype_strong_stem_width
= true;
682 bool dw_cleartype_strong_stem_width
= false;
684 bool ignore_restrictions
= false;
685 bool windows_compatibility
= false;
686 bool adjust_subglyphs
= false;
687 bool hint_composites
= false;
688 bool no_info
= false;
689 bool detailed_info
= false;
690 bool TTFA_info
= false;
692 bool show_TTFA_info
= false;
695 bool fallback_scaling
= false;
697 const char* default_script
= NULL
;
698 bool have_default_script
= false;
699 const char* fallback_script
= NULL
;
700 bool have_fallback_script
= false;
701 const char* x_height_snapping_exceptions_string
= NULL
;
702 bool have_x_height_snapping_exceptions_string
= false;
703 const char* family_suffix
= NULL
;
704 bool have_family_suffix
= false;
711 TA_Progress_Func progress_func
= NULL
;
712 TA_Error_Func err_func
= err
;
713 TA_Info_Func info_func
= info
;
714 TA_Info_Post_Func info_post_func
= info_post
;
716 const char* control_name
= NULL
;
718 unsigned long long epoch
= ULLONG_MAX
;
721 // For real numbers (both parsing and displaying) we only use `.' as the
722 // decimal separator; similarly, we don't want localized formats like a
723 // thousands separator for any number.
724 setlocale(LC_NUMERIC
, "C");
726 // make GNU, Qt, and X11 command line options look the same;
727 // we allow `--foo=bar', `--foo bar', `-foo=bar', `-foo bar',
728 // and short options specific to ttfautohint
730 // set up a new argument string
731 vector
<string
> new_arg_string
;
732 new_arg_string
.push_back(argv
[0]);
736 // use pseudo short options for long-only options
739 PASS_THROUGH
= CHAR_MAX
+ 1,
744 static struct option long_options
[] =
746 {"help", no_argument
, NULL
, 'h'},
748 {"help-all", no_argument
, NULL
, HELP_ALL_OPTION
},
751 // ttfautohint options
752 {"adjust-subglyphs", no_argument
, NULL
, 'p'},
753 {"composites", no_argument
, NULL
, 'c'},
755 {"control-file", required_argument
, NULL
, 'm'},
756 {"debug", no_argument
, NULL
, DEBUG_OPTION
},
758 {"default-script", required_argument
, NULL
, 'D'},
759 {"dehint", no_argument
, NULL
, 'd'},
760 {"detailed-info", no_argument
, NULL
, 'I'},
761 {"fallback-scaling", no_argument
, NULL
, 'S'},
762 {"fallback-script", required_argument
, NULL
, 'f'},
763 {"fallback-stem-width", required_argument
, NULL
, 'H'},
764 {"family-suffix", required_argument
, NULL
, 'F'},
765 {"hinting-limit", required_argument
, NULL
, 'G'},
766 {"hinting-range-max", required_argument
, NULL
, 'r'},
767 {"hinting-range-min", required_argument
, NULL
, 'l'},
768 {"ignore-restrictions", no_argument
, NULL
, 'i'},
769 {"increase-x-height", required_argument
, NULL
, 'x'},
770 {"no-info", no_argument
, NULL
, 'n'},
771 {"pre-hinting", no_argument
, NULL
, 'p'},
772 {"strong-stem-width", required_argument
, NULL
, 'w'},
773 {"symbol", no_argument
, NULL
, 's'},
774 {"ttfa-table", no_argument
, NULL
, 't'},
776 {"ttfa-info", no_argument
, NULL
, 'T'},
778 {"verbose", no_argument
, NULL
, 'v'},
779 {"version", no_argument
, NULL
, 'V'},
780 {"windows-compatibility", no_argument
, NULL
, 'W'},
781 {"x-height-snapping-exceptions", required_argument
, NULL
, 'X'},
784 {"graphicssystem", required_argument
, NULL
, PASS_THROUGH
},
785 {"reverse", no_argument
, NULL
, PASS_THROUGH
},
786 {"session", required_argument
, NULL
, PASS_THROUGH
},
787 {"style", required_argument
, NULL
, PASS_THROUGH
},
788 {"stylesheet", required_argument
, NULL
, PASS_THROUGH
},
791 {"background", required_argument
, NULL
, PASS_THROUGH
},
792 {"bg", required_argument
, NULL
, PASS_THROUGH
},
793 {"btn", required_argument
, NULL
, PASS_THROUGH
},
794 {"button", required_argument
, NULL
, PASS_THROUGH
},
795 {"cmap", no_argument
, NULL
, PASS_THROUGH
},
796 {"display", required_argument
, NULL
, PASS_THROUGH
},
797 {"fg", required_argument
, NULL
, PASS_THROUGH
},
798 {"fn", required_argument
, NULL
, PASS_THROUGH
},
799 {"font", required_argument
, NULL
, PASS_THROUGH
},
800 {"foreground", required_argument
, NULL
, PASS_THROUGH
},
801 {"geometry", required_argument
, NULL
, PASS_THROUGH
},
802 {"im", required_argument
, NULL
, PASS_THROUGH
},
803 {"inputstyle", required_argument
, NULL
, PASS_THROUGH
},
804 {"name", required_argument
, NULL
, PASS_THROUGH
},
805 {"ncols", required_argument
, NULL
, PASS_THROUGH
},
806 {"title", required_argument
, NULL
, PASS_THROUGH
},
807 {"visual", required_argument
, NULL
, PASS_THROUGH
},
813 int c
= getopt_long_only(argc
, argv
,
815 "cdD:f:F:G:hH:iIl:npr:sStvVw:Wx:X:",
817 "cdD:f:F:G:hH:iIl:m:npr:sStTvVw:Wx:X:",
819 long_options
, &option_index
);
826 hint_composites
= true;
834 default_script
= optarg
;
835 have_default_script
= true;
839 fallback_script
= optarg
;
840 have_fallback_script
= true;
844 family_suffix
= optarg
;
845 have_family_suffix
= true;
849 hinting_limit
= atoi(optarg
);
850 have_hinting_limit
= true;
854 #ifdef CONSOLE_OUTPUT
855 show_help(false, false);
860 fallback_stem_width
= atoi(optarg
);
861 have_fallback_stem_width
= true;
865 ignore_restrictions
= true;
869 detailed_info
= true;
874 hinting_range_min
= atoi(optarg
);
875 have_hinting_range_min
= true;
880 control_name
= optarg
;
886 detailed_info
= false;
890 adjust_subglyphs
= true;
894 hinting_range_max
= atoi(optarg
);
895 have_hinting_range_max
= true;
903 fallback_scaling
= true;
912 show_TTFA_info
= true;
916 progress_func
= progress
;
921 #ifdef CONSOLE_OUTPUT
927 gray_strong_stem_width
= strchr(optarg
, 'g') ? true : false;
928 gdi_cleartype_strong_stem_width
= strchr(optarg
, 'G') ? true : false;
929 dw_cleartype_strong_stem_width
= strchr(optarg
, 'D') ? true : false;
933 windows_compatibility
= true;
937 increase_x_height
= atoi(optarg
);
938 have_increase_x_height
= true;
942 x_height_snapping_exceptions_string
= optarg
;
943 have_x_height_snapping_exceptions_string
= true;
953 case HELP_ALL_OPTION
:
954 #ifdef CONSOLE_OUTPUT
955 show_help(true, false);
962 // append argument with proper syntax for Qt
965 arg
+= long_options
[option_index
].name
;
967 new_arg_string
.push_back(arg
);
969 new_arg_string
.push_back(optarg
);
980 // -d makes ttfautohint ignore all other hinting options
981 have_default_script
= false;
982 have_fallback_script
= false;
983 have_fallback_stem_width
= false;
984 have_hinting_range_max
= false;
985 have_hinting_range_min
= false;
986 have_hinting_limit
= false;
987 have_increase_x_height
= false;
988 have_x_height_snapping_exceptions_string
= false;
994 // -T makes ttfautohint ignore even more options
995 have_default_script
= false;
996 have_fallback_script
= false;
997 have_fallback_stem_width
= false;
998 have_hinting_range_max
= false;
999 have_hinting_range_min
= false;
1000 have_hinting_limit
= false;
1001 have_increase_x_height
= false;
1002 have_x_height_snapping_exceptions_string
= false;
1003 have_family_suffix
= false;
1008 if (!have_default_script
)
1009 default_script
= "latn";
1010 if (!have_fallback_script
)
1011 fallback_script
= "none";
1012 if (!have_hinting_range_min
)
1013 hinting_range_min
= TA_HINTING_RANGE_MIN
;
1014 if (!have_hinting_range_max
)
1015 hinting_range_max
= TA_HINTING_RANGE_MAX
;
1016 if (!have_hinting_limit
)
1017 hinting_limit
= TA_HINTING_LIMIT
;
1018 if (!have_increase_x_height
)
1019 increase_x_height
= TA_INCREASE_X_HEIGHT
;
1020 if (!have_x_height_snapping_exceptions_string
)
1021 x_height_snapping_exceptions_string
= "";
1022 if (!have_fallback_stem_width
)
1023 fallback_stem_width
= 0; // redundant, but avoids a compiler warning
1024 if (!have_family_suffix
)
1029 // check SOURE_DATE_EPOCH environment variable
1030 const char* source_date_epoch
= getenv("SOURCE_DATE_EPOCH");
1031 if (source_date_epoch
)
1036 epoch
= strtoull(source_date_epoch
, &endptr
, 10);
1037 if ((errno
== ERANGE
&& (epoch
== ULLONG_MAX
1043 "Environment variable `SOURCE_DATE_EPOCH' ignored:\n"
1048 else if (endptr
== source_date_epoch
)
1051 "Environment variable `SOURCE_DATE_EPOCH' ignored:\n"
1052 " No digits were found: %s\n",
1056 else if (*endptr
!= '\0')
1059 "Environment variable `SOURCE_DATE_EPOCH' ignored:\n"
1060 " Trailing garbage: %s\n",
1064 else if (epoch
> ULONG_MAX
)
1067 "Environment variable `SOURCE_DATE_EPOCH' ignored\n"
1068 " value must be smaller than or equal to %lu\n"
1069 " but was found to be %llu\n",
1075 if (!isatty(fileno(stderr
)) && !debug
)
1076 setvbuf(stderr
, (char*)NULL
, _IONBF
, BUFSIZ
);
1078 if (hinting_range_min
< 2)
1080 fprintf(stderr
, "The hinting range minimum must be at least 2\n");
1083 if (hinting_range_max
< hinting_range_min
)
1085 fprintf(stderr
, "The hinting range maximum must not be smaller"
1086 " than the minimum (%d)\n",
1090 if (hinting_limit
!= 0 && hinting_limit
< hinting_range_max
)
1092 fprintf(stderr
, "A non-zero hinting limit must not be smaller"
1093 " than the hinting range maximum (%d)\n",
1097 if (increase_x_height
!= 0 && increase_x_height
< 6)
1099 fprintf(stderr
, "A non-zero x height increase limit"
1100 " must be larger than or equal to 6\n");
1103 if (have_fallback_stem_width
&& fallback_stem_width
<= 0)
1105 fprintf(stderr
, "The fallback stem width"
1106 " must be a positive integer\n");
1110 if (have_default_script
)
1112 const Tag_Names
* sn
;
1114 for (sn
= script_names
; sn
->tag
; sn
++)
1115 if (!strcmp(default_script
, sn
->tag
))
1119 fprintf(stderr
, "Unknown script tag `%s'\n", default_script
);
1124 if (have_fallback_script
)
1126 const Tag_Names
* sn
;
1128 for (sn
= script_names
; sn
->tag
; sn
++)
1129 if (!strcmp(fallback_script
, sn
->tag
))
1133 fprintf(stderr
, "Unknown script tag `%s'\n", fallback_script
);
1139 && have_fallback_stem_width
1140 && fallback_scaling
)
1142 "Warning: Setting a fallback stem width for a symbol font\n"
1143 " with fallback scaling only has no effect\n");
1145 if (const char* pos
= check_family_suffix(family_suffix
))
1148 "Invalid character in family suffix:\n"
1152 int(pos
- family_suffix
+ 1), "^");
1156 int num_args
= argc
- optind
;
1159 show_help(false, true);
1164 in
= fopen(argv
[optind
], "rb");
1168 "The following error occurred while opening font `%s':\n"
1171 argv
[optind
], strerror(errno
));
1177 if (isatty(fileno(stdin
)))
1178 show_help(false, true);
1183 display_TTFA(in
); // this function doesn't return
1188 if (!strcmp(argv
[optind
], argv
[optind
+ 1]))
1190 fprintf(stderr
, "Input and output file names must not be identical\n");
1194 out
= fopen(argv
[optind
+ 1], "wb");
1198 "The following error occurred while opening font `%s':\n"
1201 argv
[optind
+ 1], strerror(errno
));
1207 if (isatty(fileno(stdout
)))
1208 show_help(false, true);
1212 FILE* control
= NULL
;
1215 control
= fopen(control_name
, "r");
1219 "The following error occurred while open control file `%s':\n"
1222 control_name
, strerror(errno
));
1229 Progress_Data progress_data
= {-1, 1, 0};
1230 Error_Data error_data
= {control_name
};
1231 Info_Data info_data
;
1233 if (!*family_suffix
)
1234 info_post_func
= NULL
;
1236 info_data
.no_info
= no_info
;
1237 info_data
.detailed_info
= detailed_info
;
1238 info_data
.info_string
= NULL
; // must be deallocated after use
1239 info_data
.info_string_wide
= NULL
; // must be deallocated after use
1240 info_data
.info_string_len
= 0;
1241 info_data
.info_string_wide_len
= 0;
1243 info_data
.control_name
= control_name
;
1245 info_data
.hinting_range_min
= hinting_range_min
;
1246 info_data
.hinting_range_max
= hinting_range_max
;
1247 info_data
.hinting_limit
= hinting_limit
;
1249 info_data
.gray_strong_stem_width
= gray_strong_stem_width
;
1250 info_data
.gdi_cleartype_strong_stem_width
= gdi_cleartype_strong_stem_width
;
1251 info_data
.dw_cleartype_strong_stem_width
= dw_cleartype_strong_stem_width
;
1253 info_data
.windows_compatibility
= windows_compatibility
;
1254 info_data
.adjust_subglyphs
= adjust_subglyphs
;
1255 info_data
.hint_composites
= hint_composites
;
1256 info_data
.increase_x_height
= increase_x_height
;
1257 info_data
.x_height_snapping_exceptions_string
= x_height_snapping_exceptions_string
;
1258 info_data
.family_suffix
= family_suffix
;
1259 info_data
.family_data_head
= NULL
;
1260 info_data
.fallback_stem_width
= fallback_stem_width
;
1261 info_data
.symbol
= symbol
;
1262 info_data
.fallback_scaling
= fallback_scaling
;
1263 info_data
.TTFA_info
= TTFA_info
;
1265 strncpy(info_data
.default_script
,
1267 sizeof (info_data
.default_script
));
1268 strncpy(info_data
.fallback_script
,
1270 sizeof (info_data
.fallback_script
));
1272 info_data
.dehint
= dehint
;
1276 int ret
= build_version_string(&info_data
);
1278 fprintf(stderr
, "Warning: Can't allocate memory"
1279 " for ttfautohint options string in `name' table\n");
1281 fprintf(stderr
, "Warning: ttfautohint options string"
1282 " in `name' table too long\n");
1291 TTF_autohint("in-file, out-file, control-file,"
1292 "hinting-range-min, hinting-range-max, hinting-limit,"
1293 "gray-strong-stem-width, gdi-cleartype-strong-stem-width,"
1294 "dw-cleartype-strong-stem-width,"
1295 "progress-callback, progress-callback-data,"
1296 "error-callback, error-callback-data,"
1297 "info-callback, info-post-callback, info-callback-data,"
1298 "ignore-restrictions, windows-compatibility,"
1299 "adjust-subglyphs, hint-composites,"
1300 "increase-x-height, x-height-snapping-exceptions,"
1301 "fallback-stem-width, default-script,"
1302 "fallback-script, fallback-scaling,"
1303 "symbol, dehint, debug, TTFA-info, epoch",
1305 hinting_range_min
, hinting_range_max
, hinting_limit
,
1306 gray_strong_stem_width
, gdi_cleartype_strong_stem_width
,
1307 dw_cleartype_strong_stem_width
,
1308 progress_func
, &progress_data
,
1309 err_func
, &error_data
,
1310 info_func
, info_post_func
, &info_data
,
1311 ignore_restrictions
, windows_compatibility
,
1312 adjust_subglyphs
, hint_composites
,
1313 increase_x_height
, x_height_snapping_exceptions_string
,
1314 fallback_stem_width
, default_script
,
1315 fallback_script
, fallback_scaling
,
1316 symbol
, dehint
, debug
, TTFA_info
, epoch
);
1320 free(info_data
.info_string
);
1321 free(info_data
.info_string_wide
);
1331 exit(error
? EXIT_FAILURE
: EXIT_SUCCESS
);
1333 return 0; // never reached
1337 int new_argc
= (int)new_arg_string
.size();
1338 char** new_argv
= new char*[new_argc
];
1340 // construct new argc and argv variables from collected data
1341 for (int i
= 0; i
< new_argc
; i
++)
1342 new_argv
[i
] = const_cast<char*>(new_arg_string
[i
].data());
1344 QApplication
app(new_argc
, new_argv
);
1345 app
.setApplicationName("TTFautohint");
1346 app
.setApplicationVersion(VERSION
);
1347 app
.setOrganizationName("FreeType");
1348 app
.setOrganizationDomain("freetype.org");
1350 bool alternative_layout
= false;
1352 // Display the window off the screen -- to get proper window dimensions
1353 // including the frame, the window manager must have a chance to
1356 // We don't want to change the default window positioning algorithm of
1357 // the platform's window manager, so we create the main GUI window
1360 // The original idea, however, was to simply move the off-screen window
1361 // back to the screen with
1363 // gui.move(100, 100);
1364 // gui.setAttribute(Qt::WA_Moved, false);
1367 // (unsetting the `WA_Moved' attribute makes the window manager handle
1368 // the previous call to `move' as a position suggestion instead of a
1369 // request). Unfortuntely, there seems to be a bug in Qt 4.8.4 which
1370 // prevents any effect of unsetting `WA_Moved' if `show' has already
1373 Main_GUI
dummy(alternative_layout
,
1374 hinting_range_min
, hinting_range_max
, hinting_limit
,
1375 gray_strong_stem_width
, gdi_cleartype_strong_stem_width
,
1376 dw_cleartype_strong_stem_width
, increase_x_height
,
1377 x_height_snapping_exceptions_string
, fallback_stem_width
,
1378 ignore_restrictions
, windows_compatibility
, adjust_subglyphs
,
1379 hint_composites
, no_info
, detailed_info
,
1380 default_script
, fallback_script
, fallback_scaling
,
1381 family_suffix
, symbol
, dehint
, TTFA_info
);
1383 dummy
.move(-50000, -50000);
1386 // if the vertical size of our window is too large,
1387 // select a horizontal layout
1388 QRect
screen(QApplication::desktop()->availableGeometry());
1389 if (dummy
.frameGeometry().height() > screen
.height())
1390 alternative_layout
= true;
1393 Main_GUI
gui(alternative_layout
,
1394 hinting_range_min
, hinting_range_max
, hinting_limit
,
1395 gray_strong_stem_width
, gdi_cleartype_strong_stem_width
,
1396 dw_cleartype_strong_stem_width
, increase_x_height
,
1397 x_height_snapping_exceptions_string
, fallback_stem_width
,
1398 ignore_restrictions
, windows_compatibility
, adjust_subglyphs
,
1399 hint_composites
, no_info
, detailed_info
,
1400 default_script
, fallback_script
, fallback_scaling
,
1401 family_suffix
, symbol
, dehint
, TTFA_info
);