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"
120 "If OUT-FILE is missing, standard output is used instead;\n"
121 "if IN-FILE is missing also, standard input and output are used.\n"
124 "The new hints are based on FreeType's auto-hinter.\n"
126 "This program is a simple front-end to the `ttfautohint' library.\n"
130 "Long options can be given with one or two dashes,\n"
131 "and with and without equal sign between option and argument.\n"
132 "This means that the following forms are acceptable:\n"
133 "`-foo=bar', `--foo=bar', `-foo bar', `--foo bar'.\n"
135 "Mandatory arguments to long options are mandatory for short options too.\n"
137 "Options not related to Qt or X11 set default values.\n"
145 " --debug print debugging information\n"
147 " -c, --components hint glyph components separately\n"
148 " -f, --latin-fallback set fallback script to latin\n"
149 " -G, --hinting-limit=N switch off hinting above this PPEM value\n"
150 " (default: %d); value 0 means no limit\n"
151 " -h, --help display this help and exit\n"
153 " --help-all show Qt and X11 specific options also\n"
155 " -i, --ignore-restrictions override font license restrictions\n"
156 " -l, --hinting-range-min=N the minimum PPEM value for hint sets\n"
158 " -n --no-info don't add ttfautohint info\n"
159 " to the version string(s) in the `name' table\n"
160 " -p, --pre-hinting apply original hints in advance\n",
161 TA_HINTING_LIMIT
, TA_HINTING_RANGE_MIN
);
163 " -r, --hinting-range-max=N the maximum PPEM value for hint sets\n"
165 " -s, --symbol input is symbol font\n"
166 " -v, --verbose show progress information\n"
167 " -V, --version print version information and exit\n"
168 " -w, --strong-stem-width=S use strong stem width routine for modes S,\n"
169 " where S is a string of up to three letters\n"
170 " with possible values `g' for grayscale,\n"
171 " `G' for GDI ClearType, and `D' for\n"
172 " DirectWrite ClearType (default: G)\n"
173 " -x, --increase-x-height=N increase x height for sizes in the range\n"
174 " 6<=PPEM<=N; value 0 switches off this feature\n"
176 " -X, --x-height-snapping-exceptions=STRING\n"
177 " specify a comma-separated list of\n"
178 " x-height snapping exceptions\n"
180 TA_HINTING_RANGE_MAX
, TA_INCREASE_X_HEIGHT
);
187 " --graphicssystem=SYSTEM\n"
188 " select a different graphics system backend\n"
189 " instead of the default one\n"
190 " (possible values: `raster', `opengl')\n"
191 " --reverse set layout direction to right-to-left\n");
193 " --session=ID restore the application for the given ID\n"
194 " --style=STYLE set application GUI style\n"
195 " (possible values: motif, windows, platinum)\n"
196 " --stylesheet=SHEET apply the given Qt stylesheet\n"
197 " to the application widgets\n"
202 " --background=COLOR set the default background color\n"
203 " and an application palette\n"
204 " (light and dark shades are calculated)\n"
205 " --bg=COLOR same as --background\n"
206 " --btn=COLOR set the default button color\n"
207 " --button=COLOR same as --btn\n"
208 " --cmap use a private color map on an 8-bit display\n"
209 " --display=NAME use the given X-server display\n");
211 " --fg=COLOR set the default foreground color\n"
212 " --fn=FONTNAME set the application font\n"
213 " --font=FONTNAME same as --fn\n"
214 " --foreground=COLOR same as --fg\n"
215 " --geometry=GEOMETRY set the client geometry of first window\n"
216 " --im=SERVER set the X Input Method (XIM) server\n"
217 " --inputstyle=STYLE set X Input Method input style\n"
218 " (possible values: onthespot, overthespot,\n"
219 " offthespot, root)\n");
221 " --name=NAME set the application name\n"
222 " --ncols=COUNT limit the number of colors allocated\n"
223 " in the color cube on an 8-bit display,\n"
224 " if the application is using the\n"
225 " QApplication::ManyColor color specification\n"
226 " --title=TITLE set the application title (caption)\n"
227 " --visual=VISUAL force the application\n"
228 " to use the given visual on an 8-bit display\n"
229 " (only possible value: TrueColor)\n"
235 "The program accepts both TTF and TTC files as input.\n"
236 "Use option -i only if you have a legal permission to modify the font.\n"
237 "If option -f is not set, glyphs not in the latin range stay unhinted.\n"
238 "The used PPEM value for option -p is FUnits per em, normally 2048.\n"
239 "With option -s, use default values for standard stem width and height,\n"
240 "otherwise they are derived from latin character `o'.\n"
243 "A hint set contains the optimal hinting for a certain PPEM value;\n"
244 "the larger the hint set range, the more hint sets get computed,\n"
245 "usually increasing the output font size. Note, however,\n"
246 "that the `gasp' table of the output file enables grayscale hinting\n"
247 "for all sizes (limited by option -G which is handled in the bytecode).\n"
251 "A command-line version of this program is called `ttfautohint'.\n"
253 "A GUI version of this program is called `ttfautohintGUI'.\n"
256 "Report bugs to: freetype-devel@nongnu.org\n"
257 "ttfautohint home page: <http://www.freetype.org/ttfautohint>\n");
271 "ttfautohintGUI " VERSION
"\n"
273 "ttfautohint " VERSION
"\n"
275 "Copyright (C) 2011-2012 Werner Lemberg <wl@gnu.org>.\n"
276 "License: FreeType License (FTL) or GNU GPLv2.\n"
277 "This is free software: you are free to change and redistribute it.\n"
278 "There is NO WARRANTY, to the extent permitted by law.\n");
282 #endif // CONSOLE_OUTPUT
289 int hinting_range_min
= 0;
290 int hinting_range_max
= 0;
291 int hinting_limit
= 0;
292 int increase_x_height
= 0;
293 bool have_hinting_range_min
= false;
294 bool have_hinting_range_max
= false;
295 bool have_hinting_limit
= false;
296 bool have_increase_x_height
= false;
298 bool gray_strong_stem_width
= false;
299 bool gdi_cleartype_strong_stem_width
= true;
300 bool dw_cleartype_strong_stem_width
= false;
302 bool ignore_restrictions
= false;
303 bool pre_hinting
= false;
304 bool hint_with_components
= true;
305 bool no_info
= false;
306 int latin_fallback
= 0; // leave it as int; this probably gets extended
312 TA_Progress_Func progress_func
= NULL
;
313 TA_Info_Func info_func
= info
;
316 // make GNU, Qt, and X11 command line options look the same;
317 // we allow `--foo=bar', `--foo bar', `-foo=bar', `-foo bar',
318 // and short options specific to ttfautohint
320 // set up a new argument string
321 vector
<string
> new_arg_string
;
322 new_arg_string
.push_back(argv
[0]);
326 // use pseudo short options for long-only options
329 PASS_THROUGH
= CHAR_MAX
+ 1,
334 static struct option long_options
[] =
336 {"help", no_argument
, NULL
, 'h'},
338 {"help-all", no_argument
, NULL
, HELP_ALL_OPTION
},
341 // ttfautohint options
342 {"components", no_argument
, NULL
, 'c'},
344 {"debug", no_argument
, NULL
, DEBUG_OPTION
},
346 {"hinting-limit", required_argument
, NULL
, 'G'},
347 {"hinting-range-max", required_argument
, NULL
, 'r'},
348 {"hinting-range-min", required_argument
, NULL
, 'l'},
349 {"ignore-restrictions", no_argument
, NULL
, 'i'},
350 {"increase-x-height", required_argument
, NULL
, 'x'},
351 {"latin-fallback", no_argument
, NULL
, 'f'},
352 {"no-info", no_argument
, NULL
, 'n'},
353 {"pre-hinting", no_argument
, NULL
, 'p'},
354 {"strong-stem-width", required_argument
, NULL
, 'w'},
355 {"symbol", no_argument
, NULL
, 's'},
356 {"verbose", no_argument
, NULL
, 'v'},
357 {"version", no_argument
, NULL
, 'V'},
358 {"x-height-snapping-exceptions", required_argument
, NULL
, 'X'},
361 {"graphicssystem", required_argument
, NULL
, PASS_THROUGH
},
362 {"reverse", no_argument
, NULL
, PASS_THROUGH
},
363 {"session", required_argument
, NULL
, PASS_THROUGH
},
364 {"style", required_argument
, NULL
, PASS_THROUGH
},
365 {"stylesheet", required_argument
, NULL
, PASS_THROUGH
},
368 {"background", required_argument
, NULL
, PASS_THROUGH
},
369 {"bg", required_argument
, NULL
, PASS_THROUGH
},
370 {"btn", required_argument
, NULL
, PASS_THROUGH
},
371 {"button", required_argument
, NULL
, PASS_THROUGH
},
372 {"cmap", no_argument
, NULL
, PASS_THROUGH
},
373 {"display", required_argument
, NULL
, PASS_THROUGH
},
374 {"fg", required_argument
, NULL
, PASS_THROUGH
},
375 {"fn", required_argument
, NULL
, PASS_THROUGH
},
376 {"font", required_argument
, NULL
, PASS_THROUGH
},
377 {"foreground", required_argument
, NULL
, PASS_THROUGH
},
378 {"geometry", required_argument
, NULL
, PASS_THROUGH
},
379 {"im", required_argument
, NULL
, PASS_THROUGH
},
380 {"inputstyle", required_argument
, NULL
, PASS_THROUGH
},
381 {"name", required_argument
, NULL
, PASS_THROUGH
},
382 {"ncols", required_argument
, NULL
, PASS_THROUGH
},
383 {"title", required_argument
, NULL
, PASS_THROUGH
},
384 {"visual", required_argument
, NULL
, PASS_THROUGH
},
390 int c
= getopt_long_only(argc
, argv
, "cfG:hil:npr:stVvx:X:w:",
391 long_options
, &option_index
);
398 hint_with_components
= false;
406 hinting_limit
= atoi(optarg
);
407 have_hinting_limit
= true;
411 #ifdef CONSOLE_OUTPUT
412 show_help(false, false);
417 ignore_restrictions
= true;
421 hinting_range_min
= atoi(optarg
);
422 have_hinting_range_min
= true;
434 hinting_range_max
= atoi(optarg
);
435 have_hinting_range_max
= true;
444 progress_func
= progress
;
449 #ifdef CONSOLE_OUTPUT
455 gray_strong_stem_width
= strchr(optarg
, 'g') ? true : false;
456 gdi_cleartype_strong_stem_width
= strchr(optarg
, 'G') ? true : false;
457 dw_cleartype_strong_stem_width
= strchr(optarg
, 'D') ? true : false;
461 increase_x_height
= atoi(optarg
);
462 have_increase_x_height
= true;
466 #ifdef CONSOLE_OUTPUT
467 fprintf(stderr
, "Option `-x' not implemented yet\n");
478 case HELP_ALL_OPTION
:
479 #ifdef CONSOLE_OUTPUT
480 show_help(true, false);
487 // append argument with proper syntax for Qt
490 arg
+= long_options
[option_index
].name
;
492 new_arg_string
.push_back(arg
);
494 new_arg_string
.push_back(optarg
);
503 if (!have_hinting_range_min
)
504 hinting_range_min
= TA_HINTING_RANGE_MIN
;
505 if (!have_hinting_range_max
)
506 hinting_range_max
= TA_HINTING_RANGE_MAX
;
507 if (!have_hinting_limit
)
508 hinting_limit
= TA_HINTING_LIMIT
;
509 if (!have_increase_x_height
)
510 increase_x_height
= TA_INCREASE_X_HEIGHT
;
514 if (hinting_range_min
< 2)
516 fprintf(stderr
, "The hinting range minimum must be at least 2\n");
519 if (hinting_range_max
< hinting_range_min
)
521 fprintf(stderr
, "The hinting range maximum must not be smaller"
522 " than the minimum (%d)\n",
526 if (hinting_limit
!= 0 && hinting_limit
< hinting_range_max
)
528 fprintf(stderr
, "A non-zero hinting limit must not be smaller"
529 " than the hinting range maximum (%d)\n",
533 if (increase_x_height
!= 0 && increase_x_height
< 6)
535 fprintf(stderr
, "A non-zero x height increase limit"
536 " must be larger than or equal to 6\n");
540 int num_args
= argc
- optind
;
543 show_help(false, true);
548 out
= fopen(argv
[optind
+ 1], "wb");
551 fprintf(stderr
, "The following error occurred while opening font `%s':\n"
554 argv
[optind
+ 1], strerror(errno
));
564 in
= fopen(argv
[optind
], "rb");
567 fprintf(stderr
, "The following error occurred while opening font `%s':\n"
570 argv
[optind
], strerror(errno
));
577 unsigned char version_data
[128];
578 unsigned char version_data_wide
[256];
580 const unsigned char* error_string
;
581 Progress_Data progress_data
= {-1, 1, 0};
588 info_data
.data
= version_data
;
589 info_data
.data_wide
= version_data_wide
;
591 info_data
.hinting_range_min
= hinting_range_min
;
592 info_data
.hinting_range_max
= hinting_range_max
;
593 info_data
.hinting_limit
= hinting_limit
;
595 info_data
.gray_strong_stem_width
= gray_strong_stem_width
;
596 info_data
.gdi_cleartype_strong_stem_width
= gdi_cleartype_strong_stem_width
;
597 info_data
.dw_cleartype_strong_stem_width
= dw_cleartype_strong_stem_width
;
599 info_data
.pre_hinting
= pre_hinting
;
600 info_data
.hint_with_components
= hint_with_components
;
601 info_data
.increase_x_height
= increase_x_height
;
602 info_data
.latin_fallback
= latin_fallback
;
603 info_data
.symbol
= symbol
;
605 build_version_string(&info_data
);
609 TTF_autohint("in-file, out-file,"
610 "hinting-range-min, hinting-range-max, hinting-limit,"
611 "gray-strong-stem-width, gdi-cleartype-strong-stem-width,"
612 "dw-cleartype-strong-stem-width,"
614 "progress-callback, progress-callback-data,"
615 "info-callback, info-callback-data,"
616 "ignore-restrictions, pre-hinting, hint-with-components,"
617 "increase-x-height, fallback-script, symbol,"
620 hinting_range_min
, hinting_range_max
, hinting_limit
,
621 gray_strong_stem_width
, gdi_cleartype_strong_stem_width
,
622 dw_cleartype_strong_stem_width
,
624 progress_func
, &progress_data
,
625 info_func
, &info_data
,
626 ignore_restrictions
, pre_hinting
, hint_with_components
,
627 increase_x_height
, latin_fallback
, symbol
,
632 if (error
== TA_Err_Invalid_FreeType_Version
)
634 "FreeType version 2.4.5 or higher is needed.\n"
635 "Perhaps using a wrong FreeType DLL?\n");
636 else if (error
== TA_Err_Invalid_Font_Type
)
638 "This font is not a valid font"
639 " in SFNT format with TrueType outlines.\n"
640 "In particular, CFF outlines are not supported.\n");
641 else if (error
== TA_Err_Already_Processed
)
643 "This font has already been processed with ttfautohint.\n");
644 else if (error
== TA_Err_Missing_Legal_Permission
)
646 "Bit 1 in the `fsType' field of the `OS/2' table is set:\n"
647 "This font must not be modified"
648 " without permission of the legal owner.\n"
649 "Use command line option `-i' to continue"
650 " if you have such a permission.\n");
651 else if (error
== TA_Err_Missing_Unicode_CMap
)
653 "No Unicode character map.\n");
654 else if (error
== TA_Err_Missing_Symbol_CMap
)
656 "No symbol character map.\n");
657 else if (error
== TA_Err_Missing_Glyph
)
659 "No glyph for the key character"
660 " to derive standard width and height.\n"
661 "For the latin script, this key character is `o' (U+006F).\n");
664 "Error code `0x%02x' while autohinting font:\n"
665 " %s\n", error
, error_string
);
674 return 0; // never reached
678 int new_argc
= new_arg_string
.size();
679 char** new_argv
= new char*[new_argc
];
681 // construct new argc and argv variables from collected data
682 for (int i
= 0; i
< new_argc
; i
++)
683 new_argv
[i
] = const_cast<char*>(new_arg_string
[i
].data());
685 QApplication
app(new_argc
, new_argv
);
686 app
.setApplicationName("TTFautohint");
687 app
.setApplicationVersion(VERSION
);
688 app
.setOrganizationName("FreeType");
689 app
.setOrganizationDomain("freetype.org");
691 Main_GUI
gui(hinting_range_min
, hinting_range_max
, hinting_limit
,
692 gray_strong_stem_width
, gdi_cleartype_strong_stem_width
,
693 dw_cleartype_strong_stem_width
,
694 increase_x_height
, ignore_restrictions
, pre_hinting
,
695 hint_with_components
, no_info
, latin_fallback
, symbol
);