3 // Copyright (C) 2011-2012 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
37 # include <QApplication>
43 #include <ttfautohint.h>
51 typedef struct Progress_Data_
60 progress(long curr_idx
,
66 Progress_Data
* data
= (Progress_Data
*)user
;
68 if (num_sfnts
> 1 && curr_sfnt
!= data
->last_sfnt
)
70 fprintf(stderr
, "subfont %ld of %ld\n", curr_sfnt
+ 1, num_sfnts
);
71 data
->last_sfnt
= curr_sfnt
;
77 fprintf(stderr
, " %ld glyphs\n"
82 // print progress approx. every 10%
83 int curr_percent
= curr_idx
* 100 / num_glyphs
;
84 int curr_diff
= curr_percent
- data
->last_percent
;
88 fprintf(stderr
, " %d%%", curr_percent
);
89 data
->last_percent
= curr_percent
- curr_percent
% 10;
92 if (curr_idx
+ 1 == num_glyphs
)
93 fprintf(stderr
, "\n");
102 #ifdef CONSOLE_OUTPUT
111 FILE* handle
= is_error
? stderr
: stdout
;
115 "Usage: ttfautohintGUI [OPTION]...\n"
116 "A GUI application to replace hints in a TrueType font.\n"
118 "Usage: ttfautohint [OPTION]... IN-FILE OUT-FILE\n"
119 "Replace hints in TrueType font IN-FILE and write output to OUT-FILE.\n"
121 "The new hints are based on FreeType's autohinter.\n"
123 "This program is a simple front-end to the `ttfautohint' library.\n"
127 "Long options can be given with one or two dashes,\n"
128 "and with and without equal sign between option and argument.\n"
129 "This means that the following forms are acceptable:\n"
130 "`-foo=bar', `--foo=bar', `-foo bar', `--foo bar'.\n"
132 "Mandatory arguments to long options are mandatory for short options too.\n"
134 "Options not related to Qt or X11 set default values.\n"
142 " --debug print debugging information\n"
144 " -c, --components hint glyph components separately\n"
145 " -f, --latin-fallback set fallback script to latin\n"
146 " -G, --hinting-limit=N switch off hinting above this PPEM value\n"
147 " (default: %d); value 0 means no limit\n"
148 " -h, --help display this help and exit\n"
150 " --help-all show Qt and X11 specific options also\n"
152 " -i, --ignore-restrictions override font license restrictions\n"
153 " -l, --hinting-range-min=N the minimum PPEM value for hint sets\n"
155 " -n --no-info don't add ttfautohint info\n"
156 " to the version string(s) in the `name' table\n"
157 " -p, --pre-hinting apply original hints in advance\n",
158 TA_HINTING_LIMIT
, TA_HINTING_RANGE_MIN
);
160 " -r, --hinting-range-max=N the maximum PPEM value for hint sets\n"
162 " -s, --symbol input is symbol font\n"
163 " -v, --verbose show progress information\n"
164 " -V, --version print version information and exit\n"
165 " -w, --strong-stem-width=S use strong stem width routine for modes S,\n"
166 " where S is a string of up to three letters\n"
167 " with possible values `g' for grayscale,\n"
168 " `G' for GDI ClearType, and `D' for\n"
169 " DirectWrite ClearType (default: G)\n"
170 " -x, --increase-x-height=N increase x height for sizes in the range\n"
171 " 6<=PPEM<=N; value 0 switches off this feature\n"
173 " -X, --x-height-snapping-exceptions=STRING\n"
174 " specify a comma-separated list of\n"
175 " x-height snapping exceptions\n"
177 TA_HINTING_RANGE_MAX
, TA_INCREASE_X_HEIGHT
);
184 " --graphicssystem=SYSTEM\n"
185 " select a different graphics system backend\n"
186 " instead of the default one\n"
187 " (possible values: `raster', `opengl')\n"
188 " --reverse set layout direction to right-to-left\n");
190 " --session=ID restore the application for the given ID\n"
191 " --style=STYLE set application GUI style\n"
192 " (possible values: motif, windows, platinum)\n"
193 " --stylesheet=SHEET apply the given Qt stylesheet\n"
194 " to the application widgets\n"
199 " --background=COLOR set the default background color\n"
200 " and an application palette\n"
201 " (light and dark shades are calculated)\n"
202 " --bg=COLOR same as --background\n"
203 " --btn=COLOR set the default button color\n"
204 " --button=COLOR same as --btn\n"
205 " --cmap use a private color map on an 8-bit display\n"
206 " --display=NAME use the given X-server display\n");
208 " --fg=COLOR set the default foreground color\n"
209 " --fn=FONTNAME set the application font\n"
210 " --font=FONTNAME same as --fn\n"
211 " --foreground=COLOR same as --fg\n"
212 " --geometry=GEOMETRY set the client geometry of first window\n"
213 " --im=SERVER set the X Input Method (XIM) server\n"
214 " --inputstyle=STYLE set X Input Method input style\n"
215 " (possible values: onthespot, overthespot,\n"
216 " offthespot, root)\n");
218 " --name=NAME set the application name\n"
219 " --ncols=COUNT limit the number of colors allocated\n"
220 " in the color cube on an 8-bit display,\n"
221 " if the application is using the\n"
222 " QApplication::ManyColor color specification\n"
223 " --title=TITLE set the application title (caption)\n"
224 " --visual=VISUAL force the application\n"
225 " to use the given visual on an 8-bit display\n"
226 " (only possible value: TrueColor)\n"
232 "The program accepts both TTF and TTC files as input.\n"
233 "Use option -i only if you have a legal permission to modify the font.\n"
234 "If option -f is not set, glyphs not in the latin range stay unhinted.\n"
235 "The used PPEM value for option -p is FUnits per em, normally 2048.\n"
236 "With option -s, use default values for standard stem width and height,\n"
237 "otherwise they are derived from latin character `o'.\n"
240 "A hint set contains the optimal hinting for a certain PPEM value;\n"
241 "the larger the hint set range, the more hint sets get computed,\n"
242 "usually increasing the output font size. Note, however,\n"
243 "that the `gasp' table of the output file enables grayscale hinting\n"
244 "for all sizes (limited by option -G which is handled in the bytecode).\n"
248 "A command-line version of this program is called `ttfautohint'.\n"
250 "A GUI version of this program is called `ttfautohintGUI'.\n"
253 "Report bugs to: freetype-devel@nongnu.org\n"
254 "ttfautohint home page: <http://www.freetype.org/ttfautohint>\n");
268 "ttfautohintGUI " VERSION
"\n"
270 "ttfautohint " VERSION
"\n"
272 "Copyright (C) 2011-2012 Werner Lemberg <wl@gnu.org>.\n"
273 "License: FreeType License (FTL) or GNU GPLv2.\n"
274 "This is free software: you are free to change and redistribute it.\n"
275 "There is NO WARRANTY, to the extent permitted by law.\n");
279 #endif // CONSOLE_OUTPUT
286 int hinting_range_min
= 0;
287 int hinting_range_max
= 0;
288 int hinting_limit
= 0;
289 int increase_x_height
= 0;
290 bool have_hinting_range_min
= false;
291 bool have_hinting_range_max
= false;
292 bool have_hinting_limit
= false;
293 bool have_increase_x_height
= false;
295 bool gray_strong_stem_width
= false;
296 bool gdi_cleartype_strong_stem_width
= true;
297 bool dw_cleartype_strong_stem_width
= false;
299 bool ignore_restrictions
= false;
300 bool pre_hinting
= false;
301 bool hint_with_components
= true;
302 bool no_info
= false;
303 int latin_fallback
= 0; // leave it as int; this probably gets extended
309 TA_Progress_Func progress_func
= NULL
;
310 TA_Info_Func info_func
= info
;
313 // make GNU, Qt, and X11 command line options look the same;
314 // we allow `--foo=bar', `--foo bar', `-foo=bar', `-foo bar',
315 // and short options specific to ttfautohint
317 // set up a new argument string
318 vector
<string
> new_arg_string
;
319 new_arg_string
.push_back(argv
[0]);
323 // use pseudo short options for long-only options
326 PASS_THROUGH
= CHAR_MAX
+ 1,
331 static struct option long_options
[] =
333 {"help", no_argument
, NULL
, 'h'},
335 {"help-all", no_argument
, NULL
, HELP_ALL_OPTION
},
338 // ttfautohint options
339 {"components", no_argument
, NULL
, 'c'},
341 {"debug", no_argument
, NULL
, DEBUG_OPTION
},
343 {"hinting-limit", required_argument
, NULL
, 'G'},
344 {"hinting-range-max", required_argument
, NULL
, 'r'},
345 {"hinting-range-min", required_argument
, NULL
, 'l'},
346 {"ignore-restrictions", no_argument
, NULL
, 'i'},
347 {"increase-x-height", required_argument
, NULL
, 'x'},
348 {"latin-fallback", no_argument
, NULL
, 'f'},
349 {"no-info", no_argument
, NULL
, 'n'},
350 {"pre-hinting", no_argument
, NULL
, 'p'},
351 {"strong-stem-width", required_argument
, NULL
, 'w'},
352 {"symbol", no_argument
, NULL
, 's'},
353 {"verbose", no_argument
, NULL
, 'v'},
354 {"version", no_argument
, NULL
, 'V'},
355 {"x-height-snapping-exceptions", required_argument
, NULL
, 'X'},
358 {"graphicssystem", required_argument
, NULL
, PASS_THROUGH
},
359 {"reverse", no_argument
, NULL
, PASS_THROUGH
},
360 {"session", required_argument
, NULL
, PASS_THROUGH
},
361 {"style", required_argument
, NULL
, PASS_THROUGH
},
362 {"stylesheet", required_argument
, NULL
, PASS_THROUGH
},
365 {"background", required_argument
, NULL
, PASS_THROUGH
},
366 {"bg", required_argument
, NULL
, PASS_THROUGH
},
367 {"btn", required_argument
, NULL
, PASS_THROUGH
},
368 {"button", required_argument
, NULL
, PASS_THROUGH
},
369 {"cmap", no_argument
, NULL
, PASS_THROUGH
},
370 {"display", required_argument
, NULL
, PASS_THROUGH
},
371 {"fg", required_argument
, NULL
, PASS_THROUGH
},
372 {"fn", required_argument
, NULL
, PASS_THROUGH
},
373 {"font", required_argument
, NULL
, PASS_THROUGH
},
374 {"foreground", required_argument
, NULL
, PASS_THROUGH
},
375 {"geometry", required_argument
, NULL
, PASS_THROUGH
},
376 {"im", required_argument
, NULL
, PASS_THROUGH
},
377 {"inputstyle", required_argument
, NULL
, PASS_THROUGH
},
378 {"name", required_argument
, NULL
, PASS_THROUGH
},
379 {"ncols", required_argument
, NULL
, PASS_THROUGH
},
380 {"title", required_argument
, NULL
, PASS_THROUGH
},
381 {"visual", required_argument
, NULL
, PASS_THROUGH
},
387 int c
= getopt_long_only(argc
, argv
, "cfG:hil:npr:stVvx:X:w:",
388 long_options
, &option_index
);
395 hint_with_components
= false;
403 hinting_limit
= atoi(optarg
);
404 have_hinting_limit
= true;
408 #ifdef CONSOLE_OUTPUT
409 show_help(false, false);
414 ignore_restrictions
= true;
418 hinting_range_min
= atoi(optarg
);
419 have_hinting_range_min
= true;
431 hinting_range_max
= atoi(optarg
);
432 have_hinting_range_max
= true;
441 progress_func
= progress
;
446 #ifdef CONSOLE_OUTPUT
452 gray_strong_stem_width
= strchr(optarg
, 'g') ? true : false;
453 gdi_cleartype_strong_stem_width
= strchr(optarg
, 'G') ? true : false;
454 dw_cleartype_strong_stem_width
= strchr(optarg
, 'D') ? true : false;
458 increase_x_height
= atoi(optarg
);
459 have_increase_x_height
= true;
463 #ifdef CONSOLE_OUTPUT
464 fprintf(stderr
, "Option `-x' not implemented yet\n");
475 case HELP_ALL_OPTION
:
476 #ifdef CONSOLE_OUTPUT
477 show_help(true, false);
484 // append argument with proper syntax for Qt
487 arg
+= long_options
[option_index
].name
;
489 new_arg_string
.push_back(arg
);
491 new_arg_string
.push_back(optarg
);
500 if (!have_hinting_range_min
)
501 hinting_range_min
= TA_HINTING_RANGE_MIN
;
502 if (!have_hinting_range_max
)
503 hinting_range_max
= TA_HINTING_RANGE_MAX
;
504 if (!have_hinting_limit
)
505 hinting_limit
= TA_HINTING_LIMIT
;
506 if (!have_increase_x_height
)
507 increase_x_height
= TA_INCREASE_X_HEIGHT
;
511 if (hinting_range_min
< 2)
513 fprintf(stderr
, "The hinting range minimum must be at least 2\n");
516 if (hinting_range_max
< hinting_range_min
)
518 fprintf(stderr
, "The hinting range maximum must not be smaller"
519 " than the minimum (%d)\n",
523 if (hinting_limit
!= 0 && hinting_limit
< hinting_range_max
)
525 fprintf(stderr
, "A non-zero hinting limit must not be smaller"
526 " than the hinting range maximum (%d)\n",
530 if (increase_x_height
!= 0 && increase_x_height
< 6)
532 fprintf(stderr
, "A non-zero x height increase limit"
533 " must be larger than or equal to 6\n");
537 // on the console we need in and out file arguments
538 if (argc
- optind
!= 2)
539 show_help(false, true);
541 FILE* in
= fopen(argv
[optind
], "rb");
544 fprintf(stderr
, "The following error occurred while opening font `%s':\n"
547 argv
[optind
], strerror(errno
));
551 FILE* out
= fopen(argv
[optind
+ 1], "wb");
554 fprintf(stderr
, "The following error occurred while opening font `%s':\n"
557 argv
[optind
+ 1], strerror(errno
));
561 unsigned char version_data
[128];
562 unsigned char version_data_wide
[256];
564 const unsigned char* error_string
;
565 Progress_Data progress_data
= {-1, 1, 0};
572 info_data
.data
= version_data
;
573 info_data
.data_wide
= version_data_wide
;
575 info_data
.hinting_range_min
= hinting_range_min
;
576 info_data
.hinting_range_max
= hinting_range_max
;
577 info_data
.hinting_limit
= hinting_limit
;
579 info_data
.gray_strong_stem_width
= gray_strong_stem_width
;
580 info_data
.gdi_cleartype_strong_stem_width
= gdi_cleartype_strong_stem_width
;
581 info_data
.dw_cleartype_strong_stem_width
= dw_cleartype_strong_stem_width
;
583 info_data
.pre_hinting
= pre_hinting
;
584 info_data
.hint_with_components
= hint_with_components
;
585 info_data
.increase_x_height
= increase_x_height
;
586 info_data
.latin_fallback
= latin_fallback
;
587 info_data
.symbol
= symbol
;
589 build_version_string(&info_data
);
593 TTF_autohint("in-file, out-file,"
594 "hinting-range-min, hinting-range-max, hinting-limit,"
595 "gray-strong-stem-width, gdi-cleartype-strong-stem-width,"
596 "dw-cleartype-strong-stem-width,"
598 "progress-callback, progress-callback-data,"
599 "info-callback, info-callback-data,"
600 "ignore-restrictions, pre-hinting, hint-with-components,"
601 "increase-x-height, fallback-script, symbol,"
604 hinting_range_min
, hinting_range_max
, hinting_limit
,
605 gray_strong_stem_width
, gdi_cleartype_strong_stem_width
,
606 dw_cleartype_strong_stem_width
,
608 progress_func
, &progress_data
,
609 info_func
, &info_data
,
610 ignore_restrictions
, pre_hinting
, hint_with_components
,
611 increase_x_height
, latin_fallback
, symbol
,
616 if (error
== TA_Err_Invalid_FreeType_Version
)
618 "FreeType version 2.4.5 or higher is needed.\n"
619 "Perhaps using a wrong FreeType DLL?\n");
620 else if (error
== TA_Err_Invalid_Font_Type
)
622 "This font is not a valid font"
623 " in SFNT format with TrueType outlines.\n"
624 "In particular, CFF outlines are not supported.\n");
625 else if (error
== TA_Err_Already_Processed
)
627 "This font has already been processed with ttfautohint.\n");
628 else if (error
== TA_Err_Missing_Legal_Permission
)
630 "Bit 1 in the `fsType' field of the `OS/2' table is set:\n"
631 "This font must not be modified"
632 " without permission of the legal owner.\n"
633 "Use command line option `-i' to continue"
634 " if you have such a permission.\n");
635 else if (error
== TA_Err_Missing_Unicode_CMap
)
637 "No Unicode character map.\n");
638 else if (error
== TA_Err_Missing_Symbol_CMap
)
640 "No symbol character map.\n");
641 else if (error
== TA_Err_Missing_Glyph
)
643 "No glyph for the key character"
644 " to derive standard width and height.\n"
645 "For the latin script, this key character is `o' (U+006F).\n");
648 "Error code `0x%02x' while autohinting font:\n"
649 " %s\n", error
, error_string
);
658 return 0; // never reached
662 int new_argc
= new_arg_string
.size();
663 char** new_argv
= new char*[new_argc
];
665 // construct new argc and argv variables from collected data
666 for (int i
= 0; i
< new_argc
; i
++)
667 new_argv
[i
] = const_cast<char*>(new_arg_string
[i
].data());
669 QApplication
app(new_argc
, new_argv
);
670 app
.setApplicationName("TTFautohint");
671 app
.setApplicationVersion(VERSION
);
672 app
.setOrganizationName("FreeType");
673 app
.setOrganizationDomain("freetype.org");
675 Main_GUI
gui(hinting_range_min
, hinting_range_max
, hinting_limit
,
676 gray_strong_stem_width
, gdi_cleartype_strong_stem_width
,
677 dw_cleartype_strong_stem_width
,
678 increase_x_height
, ignore_restrictions
, pre_hinting
,
679 hint_with_components
, no_info
, latin_fallback
, symbol
);