3 // Copyright (C) 2012-2014 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.
26 #include <ttfautohint.h>
29 // XXX Qt 4.8 bug: locale->quoteString("foo")
30 // inserts wrongly encoded quote characters
31 // into rich text QString
32 #if HAVE_QT_QUOTESTRING
33 # define QUOTE_STRING(x) locale->quoteString(x)
34 # define QUOTE_STRING_LITERAL(x) locale->quoteString(x)
36 # define QUOTE_STRING(x) "\"" + x + "\""
37 # define QUOTE_STRING_LITERAL(x) "\"" x "\""
41 // Shorthand for `tr' using a local `TRDOMAIN'.
42 #define Tr(text) QCoreApplication::translate(TRDOMAIN, text)
45 // the available script tags and its descriptions are directly extracted
46 // from `ttfautohint-scripts.h'
47 typedef struct Script_Names_
50 const char* description
;
54 #define SCRIPT(s, S, d, h, sc1, sc2, sc3) \
57 const Script_Names script_names
[] =
59 #include <ttfautohint-scripts.h>
65 // a: Add ttf&autohint Info
66 // b: Add TTFA info ta&ble
67 // c: x Height In&crease Limit / No x Height In&crease
69 // e: Control Instructions Fil&e
71 // g: Stron&g Stem Width and Positioning
74 // j: Ad&just Subglyphs
75 // k: Fallbac&k Stem Width / Default Fallbac&k Stem Width
76 // l: Hinting &Limit / No Hinting &Limit
77 // m: Hint Co&mposites
78 // n: Hint Set Range Mi&nimum
80 // p: Windows Com&patibility
83 // s: Fallback &Script
84 // t: x Height Snapping Excep&tions
87 // w: &Watch Input Files
88 // x: Hint Set Range Ma&ximum
92 Main_GUI::Main_GUI(bool horizontal_layout
,
100 const char* exceptions
,
109 const char* fallback
,
113 : hinting_range_min(range_min
),
114 hinting_range_max(range_max
),
115 hinting_limit(limit
),
116 gray_strong_stem_width(gray
),
117 gdi_cleartype_strong_stem_width(gdi
),
118 dw_cleartype_strong_stem_width(dw
),
119 increase_x_height(increase
),
120 x_height_snapping_exceptions_string(exceptions
),
121 fallback_stem_width(stem_width
),
122 ignore_restrictions(ignore
),
123 windows_compatibility(wincomp
),
124 adjust_subglyphs(adjust
),
125 hint_composites(composites
),
127 detailed_info(detailed
),
134 // map default script tag to an index,
135 // replacing an invalid one with the default value
136 int latn_script_idx
= 0;
137 for (i
= 0; script_names
[i
].tag
; i
++)
139 if (!strcmp("latn", script_names
[i
].tag
))
141 if (!strcmp(dflt
, script_names
[i
].tag
))
144 default_script_idx
= script_names
[i
].tag
? i
: latn_script_idx
;
146 // map fallback script tag to an index,
147 // replacing an invalid one with the default value
148 int none_script_idx
= 0;
149 for (i
= 0; script_names
[i
].tag
; i
++)
151 if (!strcmp("none", script_names
[i
].tag
))
153 if (!strcmp(fallback
, script_names
[i
].tag
))
156 fallback_script_idx
= script_names
[i
].tag
? i
: none_script_idx
;
158 x_height_snapping_exceptions
= NULL
;
160 // if file watching is active, we regularly poll the file status
161 timer
= new QTimer(this);
162 timer
->setInterval(1000);
163 fileinfo_input_file
.setCaching(false);
164 fileinfo_control_file
.setCaching(false);
166 // XXX register translations somewhere and loop over them
167 if (QLocale::system().name() == "en_US")
168 locale
= new QLocale
;
170 locale
= new QLocale(QLocale::C
);
172 // For real numbers (both parsing and displaying) we only use `.' as the
173 // decimal separator; similarly, we don't want localized formats like a
174 // thousands separator for any number.
175 setlocale(LC_NUMERIC
, "C");
177 create_layout(horizontal_layout
);
178 create_connections();
186 setUnifiedTitleAndToolBarOnMac(true);
190 Main_GUI::~Main_GUI()
192 number_set_free(x_height_snapping_exceptions
);
199 Main_GUI::closeEvent(QCloseEvent
* event
)
209 QMessageBox::about(this,
210 tr("About TTFautohint"),
211 tr("<p>This is <b>TTFautohint</b> version %1<br>"
212 " Copyright %2 2011-2014<br>"
213 " by Werner Lemberg <tt><wl@gnu.org></tt></p>"
215 "<p><b>TTFautohint</b> adds new auto-generated hints"
216 " to a TrueType font or TrueType collection.</p>"
219 " <a href='http://git.savannah.gnu.org/cgit/freetype/freetype2.git/tree/docs/FTL.TXT'>FreeType"
220 " License (FTL)</a> or"
221 " <a href='http://git.savannah.gnu.org/cgit/freetype/freetype2.git/tree/docs/GPLv2.TXT'>GNU"
229 Main_GUI::browse_input()
231 // XXX remember last directory
232 QString file
= QFileDialog::getOpenFileName(
234 tr("Open Input File"),
238 input_line
->setText(QDir::toNativeSeparators(file
));
243 Main_GUI::browse_output()
245 // XXX remember last directory
246 QString file
= QFileDialog::getSaveFileName(
248 tr("Open Output File"),
253 output_line
->setText(QDir::toNativeSeparators(file
));
258 Main_GUI::browse_control()
260 // XXX remember last directory
261 QString file
= QFileDialog::getOpenFileName(
263 tr("Open Control INstructions File"),
268 control_line
->setText(QDir::toNativeSeparators(file
));
273 Main_GUI::check_min()
275 int min
= min_box
->value();
276 int max
= max_box
->value();
277 int limit
= limit_box
->value();
279 max_box
->setValue(min
);
281 limit_box
->setValue(min
);
286 Main_GUI::check_max()
288 int min
= min_box
->value();
289 int max
= max_box
->value();
290 int limit
= limit_box
->value();
292 min_box
->setValue(max
);
294 limit_box
->setValue(max
);
299 Main_GUI::check_limit()
301 int min
= min_box
->value();
302 int max
= max_box
->value();
303 int limit
= limit_box
->value();
305 max_box
->setValue(limit
);
307 min_box
->setValue(limit
);
312 Main_GUI::check_dehint()
314 if (dehint_box
->isChecked())
316 min_label
->setEnabled(false);
317 min_box
->setEnabled(false);
319 max_label
->setEnabled(false);
320 max_box
->setEnabled(false);
322 default_label
->setEnabled(false);
323 default_box
->setEnabled(false);
324 fallback_label
->setEnabled(false);
325 fallback_box
->setEnabled(false);
327 no_limit_box
->setEnabled(false);
328 limit_label
->setEnabled(false);
329 limit_box
->setEnabled(false);
331 no_increase_box
->setEnabled(false);
332 increase_label
->setEnabled(false);
333 increase_box
->setEnabled(false);
335 snapping_label
->setEnabled(false);
336 snapping_line
->setEnabled(false);
338 default_stem_width_box
->setEnabled(false);
339 stem_width_label
->setEnabled(false);
340 stem_width_box
->setEnabled(false);
342 wincomp_box
->setEnabled(false);
343 adjust_box
->setEnabled(false);
344 hint_box
->setEnabled(false);
345 symbol_box
->setEnabled(false);
347 stem_label
->setEnabled(false);
348 gray_box
->setEnabled(false);
349 gdi_box
->setEnabled(false);
350 dw_box
->setEnabled(false);
354 min_label
->setEnabled(true);
355 min_box
->setEnabled(true);
357 max_label
->setEnabled(true);
358 max_box
->setEnabled(true);
360 default_label
->setEnabled(true);
361 default_box
->setEnabled(true);
362 fallback_label
->setEnabled(true);
363 fallback_box
->setEnabled(true);
365 no_limit_box
->setEnabled(true);
368 no_increase_box
->setEnabled(true);
371 snapping_label
->setEnabled(true);
372 snapping_line
->setEnabled(true);
374 default_stem_width_box
->setEnabled(true);
375 check_default_stem_width();
377 wincomp_box
->setEnabled(true);
378 adjust_box
->setEnabled(true);
379 hint_box
->setEnabled(true);
380 symbol_box
->setEnabled(true);
382 stem_label
->setEnabled(true);
383 gray_box
->setEnabled(true);
384 gdi_box
->setEnabled(true);
385 dw_box
->setEnabled(true);
391 Main_GUI::check_no_limit()
393 if (no_limit_box
->isChecked())
395 limit_label
->setEnabled(false);
396 limit_label
->setText(limit_label_text
);
397 limit_box
->setEnabled(false);
398 no_limit_box
->setText(no_limit_box_text_with_key
);
402 limit_label
->setEnabled(true);
403 limit_label
->setText(limit_label_text_with_key
);
404 limit_box
->setEnabled(true);
405 no_limit_box
->setText(no_limit_box_text
);
411 Main_GUI::check_no_increase()
413 if (no_increase_box
->isChecked())
415 increase_label
->setEnabled(false);
416 increase_label
->setText(increase_label_text
);
417 increase_box
->setEnabled(false);
418 no_increase_box
->setText(no_increase_box_text_with_key
);
422 increase_label
->setEnabled(true);
423 increase_label
->setText(increase_label_text_with_key
);
424 increase_box
->setEnabled(true);
425 no_increase_box
->setText(no_increase_box_text
);
431 Main_GUI::check_default_stem_width()
433 if (default_stem_width_box
->isChecked())
435 stem_width_label
->setEnabled(false);
436 stem_width_label
->setText(stem_width_label_text
);
437 stem_width_box
->setEnabled(false);
438 default_stem_width_box
->setText(default_stem_width_box_text_with_key
);
442 stem_width_label
->setEnabled(true);
443 stem_width_label
->setText(stem_width_label_text_with_key
);
444 stem_width_box
->setEnabled(true);
445 default_stem_width_box
->setText(default_stem_width_box_text
);
451 Main_GUI::check_run()
453 if (input_line
->text().isEmpty() || output_line
->text().isEmpty())
454 run_button
->setEnabled(false);
456 run_button
->setEnabled(true);
461 Main_GUI::absolute_input()
463 QString input_name
= QDir::fromNativeSeparators(input_line
->text());
464 if (!input_name
.isEmpty()
465 && QDir::isRelativePath(input_name
))
467 QDir
cur_path(QDir::currentPath() + "/" + input_name
);
468 input_line
->setText(QDir::toNativeSeparators(cur_path
.absolutePath()));
474 Main_GUI::absolute_output()
476 QString output_name
= QDir::fromNativeSeparators(output_line
->text());
477 if (!output_name
.isEmpty()
478 && QDir::isRelativePath(output_name
))
480 QDir
cur_path(QDir::currentPath() + "/" + output_name
);
481 output_line
->setText(QDir::toNativeSeparators(cur_path
.absolutePath()));
487 Main_GUI::absolute_control()
489 QString control_name
= QDir::fromNativeSeparators(control_line
->text());
490 if (!control_name
.isEmpty()
491 && QDir::isRelativePath(control_name
))
493 QDir
cur_path(QDir::currentPath() + "/" + control_name
);
494 control_line
->setText(QDir::toNativeSeparators(cur_path
.absolutePath()));
500 Main_GUI::check_number_set()
502 QString text
= snapping_line
->text();
505 // construct ASCII string from arbitrary Unicode data;
506 // the idea is to accept, say, CJK fullwidth digits also
507 for (int i
= 0; i
< text
.size(); i
++)
509 QChar c
= text
.at(i
);
511 int digit
= c
.digitValue();
513 qs
+= QString::number(digit
);
514 else if (c
.isSpace())
516 // U+30FC KATAGANA-HIRAGANA PROLONGED SOUND MARK is assigned
517 // to the `-' key in some Japanese input methods
518 else if (c
.category() == QChar::Punctuation_Dash
519 || c
== QChar(0x30FC))
521 // various Unicode COMMA characters,
522 // including representation forms
523 else if (c
== QChar(',')
524 || c
== QChar(0x055D)
525 || c
== QChar(0x060C)
526 || c
== QChar(0x07F8)
527 || c
== QChar(0x1363)
528 || c
== QChar(0x1802)
529 || c
== QChar(0x1808)
530 || c
== QChar(0x3001)
531 || c
== QChar(0xA4FE)
532 || c
== QChar(0xA60D)
533 || c
== QChar(0xA6F5)
534 || c
== QChar(0xFE10)
535 || c
== QChar(0xFE11)
536 || c
== QChar(0xFE50)
537 || c
== QChar(0xFE51)
538 || c
== QChar(0xFF0C)
539 || c
== QChar(0xFF64))
542 qs
+= c
; // we do error handling below
545 if (x_height_snapping_exceptions
)
546 number_set_free(x_height_snapping_exceptions
);
548 QByteArray str
= qs
.toLocal8Bit();
549 const char* s
= number_set_parse(str
.constData(),
550 &x_height_snapping_exceptions
,
554 statusBar()->setStyleSheet("color: red;");
555 if (x_height_snapping_exceptions
== NUMBERSET_ALLOCATION_ERROR
)
556 statusBar()->showMessage(
557 tr("allocation error"));
558 else if (x_height_snapping_exceptions
== NUMBERSET_INVALID_CHARACTER
)
559 statusBar()->showMessage(
560 tr("invalid character (use digits, dashes, commas, and spaces)"));
561 else if (x_height_snapping_exceptions
== NUMBERSET_OVERFLOW
)
562 statusBar()->showMessage(
564 else if (x_height_snapping_exceptions
== NUMBERSET_INVALID_RANGE
)
565 statusBar()->showMessage(
566 tr("invalid range (minimum is 6, maximum is 32767)"));
567 else if (x_height_snapping_exceptions
== NUMBERSET_OVERLAPPING_RANGES
)
568 statusBar()->showMessage(
569 tr("overlapping ranges"));
570 else if (x_height_snapping_exceptions
== NUMBERSET_NOT_ASCENDING
)
571 statusBar()->showMessage(
572 tr("values und ranges must be specified in ascending order"));
574 snapping_line
->setText(qs
);
575 snapping_line
->setFocus(Qt::OtherFocusReason
);
576 snapping_line
->setCursorPosition(s
- str
.constData());
578 x_height_snapping_exceptions
= NULL
;
582 // normalize if there is no error
583 char* new_str
= number_set_show(x_height_snapping_exceptions
,
585 snapping_line
->setText(new_str
);
592 Main_GUI::clear_status_bar()
594 statusBar()->clearMessage();
595 statusBar()->setStyleSheet("");
600 Main_GUI::check_filenames(const QString
& input_name
,
601 const QString
& output_name
,
602 const QString
& control_name
)
604 if (!QFile::exists(input_name
))
606 QMessageBox::warning(
609 tr("The file %1 cannot be found.")
610 .arg(QUOTE_STRING(QDir::toNativeSeparators(input_name
))),
616 if (input_name
== output_name
)
618 QMessageBox::warning(
621 tr("Input and output file names must be different."),
627 // silently overwrite if watching is active
628 if (QFile::exists(output_name
) && !timer
->isActive())
630 int ret
= QMessageBox::warning(
633 tr("The file %1 already exists.\n"
635 .arg(QUOTE_STRING(QDir::toNativeSeparators(output_name
))),
636 QMessageBox::Yes
| QMessageBox::No
,
638 if (ret
== QMessageBox::No
)
642 if (!control_name
.isEmpty() && !QFile::exists(control_name
))
644 QMessageBox::warning(
647 tr("The file %1 cannot be found.")
648 .arg(QUOTE_STRING(QDir::toNativeSeparators(control_name
))),
659 Main_GUI::open_files(const QString
& input_name
,
661 const QString
& output_name
,
663 const QString
& control_name
,
666 const int buf_len
= 1024;
669 *in
= fopen(qPrintable(input_name
), "rb");
672 strerror_r(errno
, buf
, buf_len
);
673 QMessageBox::warning(
676 tr("The following error occurred while opening input file %1:\n")
677 .arg(QUOTE_STRING(QDir::toNativeSeparators(input_name
)))
678 + QString::fromLocal8Bit(buf
),
684 *out
= fopen(qPrintable(output_name
), "wb");
687 strerror_r(errno
, buf
, buf_len
);
688 QMessageBox::warning(
691 tr("The following error occurred while opening output file %1:\n")
692 .arg(QUOTE_STRING(QDir::toNativeSeparators(output_name
)))
693 + QString::fromLocal8Bit(buf
),
699 if (!control_name
.isEmpty())
701 *control
= fopen(qPrintable(control_name
), "r");
704 strerror_r(errno
, buf
, buf_len
);
705 QMessageBox::warning(
708 tr("The following error occurred"
709 " while opening control instructions file %1:\n")
710 .arg(QUOTE_STRING(QDir::toNativeSeparators(control_name
)))
711 + QString::fromLocal8Bit(buf
),
725 Main_GUI::check_watch()
727 if (!watch_box
->isChecked())
729 // the timer gets started in the `run' function
734 Main_GUI::watch_files()
736 if (fileinfo_input_file
.exists()
737 && fileinfo_input_file
.isReadable()
738 && fileinfo_control_file
.exists()
739 && fileinfo_control_file
.isReadable())
741 QDateTime modified_input
= fileinfo_input_file
.lastModified();
742 QDateTime modified_control
= fileinfo_control_file
.lastModified();
743 if (modified_input
> datetime_input_file
744 || modified_control
> datetime_control_file
)
745 run(); // this function sets `datetime_XXX'
748 run(); // let this routine handle all errors
754 struct GUI_Progress_Data
758 QProgressDialog
* dialog
;
763 #define TRDOMAIN "GuiProgress"
766 gui_progress(long curr_idx
,
772 GUI_Progress_Data
* data
= static_cast<GUI_Progress_Data
*>(user
);
774 if (num_sfnts
> 1 && curr_sfnt
!= data
->last_sfnt
)
776 data
->dialog
->setLabelText(Tr("Auto-hinting subfont %1 of %2"
777 " with %3 glyphs...")
782 if (curr_sfnt
+ 1 == num_sfnts
)
784 data
->dialog
->setAutoReset(true);
785 data
->dialog
->setAutoClose(true);
789 data
->dialog
->setAutoReset(false);
790 data
->dialog
->setAutoClose(false);
793 data
->last_sfnt
= curr_sfnt
;
800 data
->dialog
->setLabelText(Tr("Auto-hinting %1 glyphs...")
802 data
->dialog
->setMaximum(num_glyphs
- 1);
807 data
->dialog
->setValue(curr_idx
);
809 if (data
->dialog
->wasCanceled())
816 struct GUI_Error_Data
821 QString control_name
;
822 int* ignore_restrictions_p
;
828 #define TRDOMAIN "GuiError"
831 gui_error(TA_Error error
,
832 const char* error_string
,
833 unsigned int errlinenum
,
838 GUI_Error_Data
* data
= static_cast<GUI_Error_Data
*>(user
);
839 QLocale
* locale
= data
->locale
; // for QUOTE_STRING_LITERAL
844 if (error
== TA_Err_Canceled
)
846 else if (error
== TA_Err_Invalid_FreeType_Version
)
847 QMessageBox::critical(
850 Tr("FreeType version 2.4.5 or higher is needed.\n"
851 "Are you perhaps using a wrong FreeType DLL?"),
854 else if (error
== TA_Err_Invalid_Font_Type
)
855 QMessageBox::warning(
858 Tr("This font is not a valid font"
859 " in SFNT format with TrueType outlines.\n"
860 "In particular, CFF outlines are not supported."),
863 else if (error
== TA_Err_Already_Processed
)
864 QMessageBox::warning(
867 Tr("This font has already been processed by TTFautohint."),
870 else if (error
== TA_Err_Missing_Legal_Permission
)
872 int yesno
= QMessageBox::warning(
875 Tr("Bit 1 in the %1 field of the %2 table is set:"
876 " This font must not be modified"
877 " without permission of the legal owner.\n"
878 "Do you have such a permission?")
879 .arg(QUOTE_STRING_LITERAL("fsType"))
880 .arg(QUOTE_STRING_LITERAL("OS/2")),
881 QMessageBox::Yes
| QMessageBox::No
,
883 if (yesno
== QMessageBox::Yes
)
885 *data
->ignore_restrictions_p
= true;
889 else if (error
== TA_Err_Missing_Unicode_CMap
)
890 QMessageBox::warning(
893 Tr("The input font doesn't contain a Unicode character map.\n"
894 "Maybe you haven't set the %1 checkbox?")
895 .arg(QUOTE_STRING_LITERAL(Tr("Symbol Font"))),
898 else if (error
== TA_Err_Missing_Symbol_CMap
)
899 QMessageBox::warning(
902 Tr("The input font does neither contain a symbol"
903 " nor a character map."),
906 else if (error
== TA_Err_Missing_Glyph
)
907 QMessageBox::warning(
910 Tr("No glyph for a standard character"
911 " to derive standard width and height.\n"
912 "Please check the documentation for a list of"
913 " script-specific standard characters.\n"
915 "Set the %1 checkbox if you want to circumvent this test.")
916 .arg(QUOTE_STRING_LITERAL(Tr("Symbol Font"))),
919 else if (error
>= 0x200 && error
< 0x300)
920 QMessageBox::warning(
923 QString::fromLocal8Bit("%1:%2:%3: %4 (0x%5)<br>"
926 .arg(data
->control_name
)
928 .arg(int(errpos
- errline
+ 1))
930 .arg(error
, 2, 16, QLatin1Char('0'))
932 .arg('^', int(errpos
- errline
+ 1))
933 .replace(" ", " "),
937 QMessageBox::warning(
940 Tr("Error code 0x%1 while autohinting font:\n")
941 .arg(error
, 2, 16, QLatin1Char('0'))
942 + QString::fromLocal8Bit(error_string
),
946 if (QFile::exists(data
->output_name
)
947 && remove(qPrintable(data
->output_name
)))
949 const int buf_len
= 1024;
952 strerror_r(errno
, buf
, buf_len
);
953 QMessageBox::warning(
956 Tr("The following error occurred while removing output file %1:\n")
957 .arg(QUOTE_STRING(QDir::toNativeSeparators(data
->output_name
)))
958 + QString::fromLocal8Bit(buf
),
970 statusBar()->clearMessage();
972 QString input_name
= QDir::fromNativeSeparators(input_line
->text());
973 QString output_name
= QDir::fromNativeSeparators(output_line
->text());
974 QString control_name
= QDir::fromNativeSeparators(control_line
->text());
975 if (!check_filenames(input_name
, output_name
, control_name
))
981 // we need C file descriptors for communication with TTF_autohint
987 if (!open_files(input_name
, &input
,
988 output_name
, &output
,
989 control_name
, &control
))
995 QProgressDialog dialog
;
996 dialog
.setCancelButtonText(tr("Cancel"));
997 dialog
.setMinimumDuration(1000);
998 dialog
.setWindowModality(Qt::WindowModal
);
1000 TA_Info_Func info_func
= info
;
1001 GUI_Progress_Data gui_progress_data
= {-1, true, &dialog
};
1002 GUI_Error_Data gui_error_data
= {this, locale
, output_name
, control_name
,
1003 &ignore_restrictions
, false};
1005 fileinfo_input_file
.setFile(input_name
);
1006 fileinfo_control_file
.setFile(control_name
);
1008 Info_Data info_data
;
1010 info_data
.info_string
= NULL
; // must be deallocated after use
1011 info_data
.info_string_wide
= NULL
; // must be deallocated after use
1012 info_data
.info_string_len
= 0;
1013 info_data
.info_string_wide_len
= 0;
1015 info_data
.control_name
= qPrintable(fileinfo_control_file
.fileName());
1017 info_data
.hinting_range_min
= min_box
->value();
1018 info_data
.hinting_range_max
= max_box
->value();
1019 info_data
.hinting_limit
= no_limit_box
->isChecked()
1021 : limit_box
->value();
1023 info_data
.gray_strong_stem_width
= gray_box
->isChecked();
1024 info_data
.gdi_cleartype_strong_stem_width
= gdi_box
->isChecked();
1025 info_data
.dw_cleartype_strong_stem_width
= dw_box
->isChecked();
1027 info_data
.increase_x_height
= no_increase_box
->isChecked()
1029 : increase_box
->value();
1030 info_data
.x_height_snapping_exceptions_string
=
1031 qPrintable(x_height_snapping_exceptions_string
);
1032 info_data
.fallback_stem_width
= default_stem_width_box
->isChecked()
1034 : stem_width_box
->value();
1036 info_data
.windows_compatibility
= wincomp_box
->isChecked();
1037 info_data
.adjust_subglyphs
= adjust_box
->isChecked();
1038 info_data
.hint_composites
= hint_box
->isChecked();
1039 info_data
.symbol
= symbol_box
->isChecked();
1040 info_data
.detailed
= info_box
->currentIndex() == 2;
1041 info_data
.dehint
= dehint_box
->isChecked();
1042 info_data
.TTFA_info
= TTFA_box
->isChecked();
1044 strncpy(info_data
.default_script
,
1045 script_names
[default_box
->currentIndex()].tag
,
1046 sizeof (info_data
.default_script
));
1047 strncpy(info_data
.fallback_script
,
1048 script_names
[fallback_box
->currentIndex()].tag
,
1049 sizeof (info_data
.fallback_script
));
1051 if (info_box
->currentIndex())
1053 int ret
= build_version_string(&info_data
);
1055 QMessageBox::information(
1058 tr("Can't allocate memory for <b>TTFautohint</b> options string"
1059 " in <i>name</i> table."),
1063 QMessageBox::information(
1066 tr("<b>TTFautohint</b> options string"
1067 " in <i>name</i> table too long."),
1074 if (info_data
.symbol
1075 && info_data
.fallback_stem_width
1076 && !strcmp(info_data
.fallback_script
, "none"))
1077 QMessageBox::information(
1080 tr("Setting a fallback stem width for a symbol font"
1081 " without setting a fallback script has no effect."),
1085 datetime_input_file
= fileinfo_input_file
.lastModified();
1086 datetime_control_file
= fileinfo_control_file
.lastModified();
1088 QByteArray snapping_string
= snapping_line
->text().toLocal8Bit();
1091 TTF_autohint("in-file, out-file, control-file,"
1092 "hinting-range-min, hinting-range-max,"
1094 "gray-strong-stem-width,"
1095 "gdi-cleartype-strong-stem-width,"
1096 "dw-cleartype-strong-stem-width,"
1097 "progress-callback, progress-callback-data,"
1098 "error-callback, error-callback-data,"
1099 "info-callback, info-callback-data,"
1100 "ignore-restrictions,"
1101 "windows-compatibility,"
1104 "increase-x-height,"
1105 "x-height-snapping-exceptions, fallback-stem-width,"
1106 "default-script, fallback-script,"
1107 "symbol, dehint, TTFA-info",
1108 input
, output
, control
,
1109 info_data
.hinting_range_min
, info_data
.hinting_range_max
,
1110 info_data
.hinting_limit
,
1111 info_data
.gray_strong_stem_width
,
1112 info_data
.gdi_cleartype_strong_stem_width
,
1113 info_data
.dw_cleartype_strong_stem_width
,
1114 gui_progress
, &gui_progress_data
,
1115 gui_error
, &gui_error_data
,
1116 info_func
, &info_data
,
1117 ignore_restrictions
,
1118 info_data
.windows_compatibility
,
1119 info_data
.adjust_subglyphs
,
1120 info_data
.hint_composites
,
1121 info_data
.increase_x_height
,
1122 snapping_string
.constData(), info_data
.fallback_stem_width
,
1123 info_data
.default_script
, info_data
.fallback_script
,
1124 info_data
.symbol
, info_data
.dehint
, info_data
.TTFA_info
);
1126 if (info_box
->currentIndex())
1128 free(info_data
.info_string
);
1129 free(info_data
.info_string_wide
);
1139 // retry if there is a user request to do so (handled in `gui_error')
1140 if (gui_error_data
.retry
)
1147 statusBar()->showMessage(tr("Auto-hinting finished")
1149 + QDateTime::currentDateTime()
1150 .toString(Qt::TextDate
)
1153 // we have successfully processed a file;
1154 // start file watching now if requested
1155 if (watch_box
->isChecked())
1161 // XXX distances are specified in pixels,
1162 // making the layout dependent on the output device resolution
1164 Main_GUI::create_layout(bool horizontal_layout
)
1169 QCompleter
* completer
= new QCompleter(this);
1170 QFileSystemModel
* model
= new QFileSystemModel(completer
);
1171 model
->setRootPath(QDir::rootPath());
1172 completer
->setModel(model
);
1174 input_label
= new QLabel(tr("&Input File:"));
1175 input_line
= new Drag_Drop_Line_Edit(DRAG_DROP_TRUETYPE
);
1176 input_button
= new QPushButton(tr("Browse..."));
1177 input_label
->setBuddy(input_line
);
1178 // enforce rich text to get nice word wrapping
1179 input_label
->setToolTip(
1180 tr("<b></b>The input file, either a TrueType font (TTF),"
1181 " TrueType collection (TTC), or a TrueType-based OpenType font."));
1182 input_line
->setCompleter(completer
);
1184 output_label
= new QLabel(tr("&Output File:"));
1185 output_line
= new Drag_Drop_Line_Edit(DRAG_DROP_TRUETYPE
);
1186 output_button
= new QPushButton(tr("Browse..."));
1187 output_label
->setBuddy(output_line
);
1188 output_label
->setToolTip(
1189 tr("<b></b>The output file, which will be essentially identical"
1190 " to the input font but will contain new, generated hints."));
1191 output_line
->setCompleter(completer
);
1193 control_label
= new QLabel(tr("Control Instructions Fil&e:"));
1194 control_line
= new Drag_Drop_Line_Edit(DRAG_DROP_ANY
);
1195 control_button
= new QPushButton(tr("Browse..."));
1196 control_label
->setBuddy(control_line
);
1197 control_label
->setToolTip(
1198 tr("<p>An optional control instructions file to tweak hinting."
1199 " This text file contains entries"
1200 " of one of the following syntax forms"
1201 " (with brackets indicating optional elements).<br>"
1203 " [ <i>subfont-idx</i> ]"
1204 " <i>glyph-id</i>"
1205 " <tt>left</tt> | <tt>right</tt> <i>points</i>"
1206 " [ <tt>(</tt><i>left-offset</i><tt>,"
1207 "</tt><i>right-offset</i><tt>)</tt> ]<br>"
1208 " [ <i>subfont-idx</i> ]"
1209 " <i>glyph-id</i>"
1210 " <tt>nodir</tt> <i>points</i><br>"
1211 " [ <i>subfont-idx</i> ]"
1212 " <i>glyph-id</i>"
1213 " <tt>touch</tt> | <tt>point</tt> <i>points</i>"
1214 " [ <tt>xshift</tt> <i>shift</i> ]"
1215 " [ <tt>yshift</tt> <i>shift</i> ]"
1216 " <tt>@</tt> <i>ppems</i><br>"
1218 "<i>subfont-idx</i> gives the subfont index in a TTC,"
1219 " <i>glyph-id</i> is a glyph name or index.<br>"
1220 "<tt>left</tt> (<tt>right</tt>) creates one-point segments"
1221 " with direction left (right), possibly having a width (in font units)"
1222 " given by <i>left-offset</i> and <i>right-offset</i>"
1223 " relative to the corresponding points.<br>"
1224 "<tt>nodir</tt> removes points from horizontal segments,"
1225 " making them <i>weak</i> points.<br>"
1226 "<tt>touch </tt> (<tt>point</tt>) defines delta exceptions"
1227 " to be applied before (after) the final"
1228 " <tt>IUP</tt> bytecode instructions."
1229 " <tt>touch</tt> also touches points, making them <i>strong</i>."
1230 " In ClearType mode, <tt>point</tt> and <tt>xshift</tt>"
1231 " have no effect.<br>"
1232 "x and y <i>shift</i> values are in the range [-1;1],"
1233 " rounded to multiples of 1/8px.<br>"
1234 "<i>points</i> and <i>ppems</i> are ranges for point indices"
1235 " and ppem values as with x height snapping exceptions.<br>"
1236 "Keywords <tt>left</tt>, <tt>right</tt>, <tt>nodir</tt>,"
1237 " <tt>point</tt>, <tt>touch</tt>, <tt>xshift</tt>, and"
1238 " <tt>yshift</tt> can be abbreviated as <tt>l</tt>, <tt>r</tt>,"
1239 " <tt>n</tt>, <tt>p</tt>, <tt>t</tt>, <tt>x</tt>, and <tt>y</tt>,"
1240 " respectively.<br>"
1241 "Control instruction entries are separated"
1242 " by character <tt>;</tt> or by a newline.<br>"
1243 "A trailing character <tt>\\</tt> continues the current line"
1244 " on the next line.<br>"
1245 "<tt>#</tt> starts a line comment, which gets ignored."
1246 " Empty lines are ignored, too.</p>"
1249 " <tt>Q left 38 (-70,20)</tt><br>"
1250 " <tt>Adieresis touch 3-6 yshift 0.25 @ 13</tt>"));
1251 control_line
->setCompleter(completer
);
1256 min_label
= new QLabel(tr("Hint Set Range Mi&nimum:"));
1257 min_box
= new QSpinBox
;
1258 min_label
->setBuddy(min_box
);
1259 min_label
->setToolTip(
1260 tr("The minimum PPEM value of the range for which"
1261 " <b>TTFautohint</b> computes <i>hint sets</i>."
1262 " A hint set for a given PPEM value hints this size optimally."
1263 " The larger the range, the more hint sets are considered,"
1264 " usually increasing the size of the bytecode.<br>"
1265 "Note that changing this range doesn't influence"
1266 " the <i>gasp</i> table:"
1267 " Hinting is enabled for all sizes."));
1268 min_box
->setKeyboardTracking(false);
1269 min_box
->setRange(2, 10000);
1271 max_label
= new QLabel(tr("Hint Set Range Ma&ximum:"));
1272 max_box
= new QSpinBox
;
1273 max_label
->setBuddy(max_box
);
1274 max_label
->setToolTip(
1275 tr("The maximum PPEM value of the range for which"
1276 " <b>TTFautohint</b> computes <i>hint sets</i>."
1277 " A hint set for a given PPEM value hints this size optimally."
1278 " The larger the range, the more hint sets are considered,"
1279 " usually increasing the size of the bytecode.<br>"
1280 "Note that changing this range doesn't influence"
1281 " the <i>gasp</i> table:"
1282 " Hinting is enabled for all sizes."));
1283 max_box
->setKeyboardTracking(false);
1284 max_box
->setRange(2, 10000);
1287 // OpenType default script
1289 default_label
= new QLabel(tr("Defa&ult Script:"));
1290 default_box
= new QComboBox
;
1291 default_label
->setBuddy(default_box
);
1292 default_label
->setToolTip(
1293 tr("This sets the default script for OpenType features:"
1294 " After applying all features that are handled specially"
1295 " (for example small caps or superscript glyphs),"
1296 " <b>TTFautohint</b> uses this value for the remaining features."));
1297 for (int i
= 0; script_names
[i
].tag
; i
++)
1299 // XXX: how to provide translations?
1300 default_box
->insertItem(i
,
1302 .arg(script_names
[i
].tag
)
1303 .arg(script_names
[i
].description
));
1307 // hinting and fallback controls
1309 fallback_label
= new QLabel(tr("Fallback &Script:"));
1310 fallback_box
= new QComboBox
;
1311 fallback_label
->setBuddy(fallback_box
);
1312 fallback_label
->setToolTip(
1313 tr("This sets the fallback script for glyphs"
1314 " that <b>TTFautohint</b> can't map to a script automatically."));
1315 for (int i
= 0; script_names
[i
].tag
; i
++)
1317 // XXX: how to provide translations?
1318 fallback_box
->insertItem(i
,
1320 .arg(script_names
[i
].tag
)
1321 .arg(script_names
[i
].description
));
1327 limit_label_text_with_key
= tr("Hinting &Limit:");
1328 limit_label_text
= tr("Hinting Limit:");
1329 limit_label
= new QLabel(limit_label_text_with_key
);
1330 limit_box
= new QSpinBox
;
1331 limit_label
->setBuddy(limit_box
);
1332 limit_label
->setToolTip(
1333 tr("Switch off hinting for PPEM values exceeding this limit."
1334 " Changing this value does not influence the size of the bytecode.<br>"
1335 "Note that <b>TTFautohint</b> handles this feature"
1336 " in the output font's bytecode and not in the <i>gasp</i> table."));
1337 limit_box
->setKeyboardTracking(false);
1338 limit_box
->setRange(2, 10000);
1340 no_limit_box_text_with_key
= tr("No Hinting &Limit");
1341 no_limit_box_text
= tr("No Hinting Limit");
1342 no_limit_box
= new QCheckBox(no_limit_box_text
, this);
1343 no_limit_box
->setToolTip(
1344 tr("If switched on, <b>TTFautohint</b> adds no hinting limit"
1345 " to the bytecode.<br>"
1346 "For testing only."));
1349 // x height increase limit
1351 increase_label_text_with_key
= tr("x Height In&crease Limit:");
1352 increase_label_text
= tr("x Height Increase Limit:");
1353 increase_label
= new QLabel(increase_label_text_with_key
);
1354 increase_box
= new QSpinBox
;
1355 increase_label
->setBuddy(increase_box
);
1356 increase_label
->setToolTip(
1357 tr("For PPEM values in the range 5 < PPEM < <i>n</i>,"
1358 " where <i>n</i> is the value selected by this spin box,"
1359 " round up the font's x height much more often than normally.<br>"
1360 "Use this if holes in letters like <i>e</i> get filled,"
1362 increase_box
->setKeyboardTracking(false);
1363 increase_box
->setRange(6, 10000);
1365 no_increase_box_text_with_key
= tr("No x Height In&crease");
1366 no_increase_box_text
= tr("No x Height Increase");
1367 no_increase_box
= new QCheckBox(no_increase_box_text
, this);
1368 no_increase_box
->setToolTip(
1369 tr("If switched on,"
1370 " <b>TTFautohint</b> does not increase the x height."));
1373 // x height snapping exceptions
1375 snapping_label
= new QLabel(tr("x Height Snapping Excep&tions:"));
1376 snapping_line
= new Tooltip_Line_Edit
;
1377 snapping_label
->setBuddy(snapping_line
);
1378 snapping_label
->setToolTip(
1379 tr("<p>A list of comma separated PPEM values or value ranges"
1380 " at which no x height snapping shall be applied"
1381 " (x height snapping usually slightly increases"
1382 " the size of all glyphs).</p>"
1385 " <tt>2, 3-5, 12-17</tt><br>"
1386 " <tt>-20, 40-</tt>"
1387 " (meaning PPEM ≤ 20 or PPEM ≥ 40)<br>"
1388 " <tt>-</tt> (meaning all possible PPEM values)"));
1391 // fallback stem width
1393 stem_width_label_text_with_key
= tr("Fallbac&k Stem Width:");
1394 stem_width_label_text
= tr("Fallback Stem Width:");
1395 stem_width_label
= new QLabel(stem_width_label_text_with_key
);
1396 stem_width_box
= new QSpinBox
;
1397 stem_width_label
->setBuddy(stem_width_box
);
1398 stem_width_label
->setToolTip(
1399 tr("Set horizontal stem width (in font units) for all scripts"
1400 " that lack proper standard characters in the font.<br>"
1401 "If not set, <b>TTFautohint</b> uses a hard-coded default value."));
1402 stem_width_box
->setKeyboardTracking(false);
1403 stem_width_box
->setRange(1, 10000);
1405 default_stem_width_box_text_with_key
= tr("Default Fallbac&k Stem Width");
1406 default_stem_width_box_text
= tr("Default Fallback Stem Width");
1407 default_stem_width_box
= new QCheckBox(default_stem_width_box_text
, this);
1408 default_stem_width_box
->setToolTip(
1409 tr("If switched on, <b>TTFautohint</b> uses a default value"
1410 " for the fallback stem width (50 font units at 2048 UPEM)."));
1415 wincomp_box
= new QCheckBox(tr("Windows Com&patibility"), this);
1416 wincomp_box
->setToolTip(
1417 tr("If switched on, add two artificial blue zones positioned at the"
1418 " <tt>usWinAscent</tt> and <tt>usWinDescent</tt> values"
1419 " (from the font's <i>OS/2</i> table)."
1420 " This option, usually in combination"
1421 " with value <tt>-</tt> (a single dash)"
1422 " for the <i>x Height Snapping Exceptions</i> option,"
1423 " should be used if those two <i>OS/2</i> values are tight,"
1424 " and you are experiencing clipping during rendering."));
1426 adjust_box
= new QCheckBox(tr("Ad&just Subglyphs"), this);
1427 adjust_box
->setToolTip(
1428 tr("If switched on, the original bytecode of the input font"
1429 " gets applied (at EM size, usually 2048ppem)"
1430 " to derive the glyph outlines for <b>TTFautohint</b>.<br>"
1431 "Use this option only if subglyphs"
1432 " are incorrectly scaled and shifted.<br>"
1433 "Note that the original bytecode will always be discarded."));
1435 hint_box
= new QCheckBox(tr("Hint Co&mposites")
1436 + " ", this); // make label wider
1437 hint_box
->setToolTip(
1438 tr("If switched on, <b>TTFautohint</b> hints composite glyphs"
1439 " as a whole, including subglyphs."
1440 " Otherwise, glyph components get hinted separately.<br>"
1441 "Deactivating this flag reduces the bytecode size enormously,"
1442 " however, it might yield worse results."));
1444 symbol_box
= new QCheckBox(tr("S&ymbol Font"), this);
1445 symbol_box
->setToolTip(
1446 tr("If switched on, <b>TTFautohint</b> accepts fonts"
1447 " that don't contain a single standard character"
1448 " for any of the supported scripts.<br>"
1449 "Use this for symbol or dingbat fonts, for example."));
1451 dehint_box
= new QCheckBox(tr("&Dehint"), this);
1452 dehint_box
->setToolTip(
1453 tr("If set, remove all hints from the font.<br>"
1454 "For testing only."));
1456 info_label
= new QLabel(tr("ttf&autohint Info:"));
1457 info_box
= new QComboBox
;
1458 info_label
->setBuddy(info_box
);
1459 info_label
->setToolTip(
1460 tr("Specify which information about <b>TTFautohint</b>"
1461 " and its calling parameters gets added to the version string(s)"
1462 " (name ID 5) in the <i>name</i> table."));
1463 info_box
->insertItem(0, tr("None"));
1464 info_box
->insertItem(1, tr("Version"));
1465 info_box
->insertItem(2, tr("Version and Parameters"));
1467 TTFA_box
= new QCheckBox(tr("Add TTFA Info Ta&ble"), this);
1468 TTFA_box
->setToolTip(
1469 tr("If switched on, an SFNT table called <i>TTFA</i>"
1470 " gets added to the output font,"
1471 " holding a dump of all parameters."
1472 " In particular, it lists all control instructions."));
1475 // stem width and positioning
1477 stem_label
= new QLabel(tr("Stron&g Stem Width and Positioning:"));
1478 stem_label
->setToolTip(
1479 tr("<b>TTFautohint</b> provides two different hinting algorithms"
1480 " that can be selected for various hinting modes."
1482 "<p><i>strong</i> (checkbox set):"
1483 " Position horizontal stems and snap stem widths"
1484 " to integer pixel values. While making the output look crisper,"
1485 " outlines become more distorted.</p>"
1487 "<p><i>smooth</i> (checkbox not set):"
1488 " Use discrete values for horizontal stems and stem widths."
1489 " This only slightly increases the contrast"
1490 " but avoids larger outline distortion.</p>"));
1492 gray_box
= new QCheckBox(tr("Grayscale"), this);
1493 gray_box
->setToolTip(
1494 tr("<b></b>Grayscale rendering, no ClearType activated."));
1495 stem_label
->setBuddy(gray_box
);
1497 gdi_box
= new QCheckBox(tr("GDI ClearType"), this);
1498 gdi_box
->setToolTip(
1499 tr("GDI ClearType rendering,"
1500 " introduced in 2000 for Windows XP.<br>"
1501 "The rasterizer version (as returned by the"
1502 " GETINFO bytecode instruction) is in the range"
1503 " 36 ≤ version < 38, and ClearType is enabled.<br>"
1504 "Along the vertical axis, this mode behaves like B/W rendering."));
1506 dw_box
= new QCheckBox(tr("DW ClearType"), this);
1508 tr("DirectWrite ClearType rendering,"
1509 " introduced in 2008 for Windows Vista.<br>"
1510 "The rasterizer version (as returned by the"
1511 " GETINFO bytecode instruction) is ≥ 38,"
1512 " ClearType is enabled, and subpixel positioning is enabled also.<br>"
1513 "Smooth rendering along the vertical axis."));
1518 watch_box
= new QCheckBox(tr("&Watch Input Files"), this);
1519 watch_box
->setToolTip(
1520 tr("If switched on, <b>TTFautohint</b> automatically re-runs"
1521 " the hinting process as soon as an input file"
1522 " (either the font or the control instructions file) is modified.<br>"
1523 "Pressing the %1 button starts watching.<br>"
1524 "If an error occurs, watching stops and must be restarted"
1525 " with the %1 button.")
1526 .arg(QUOTE_STRING_LITERAL(tr("Run"))));
1528 run_button
= new QPushButton(" "
1530 + " "); // make label wider
1532 if (horizontal_layout
)
1533 create_horizontal_layout();
1535 create_vertical_layout();
1539 // XXX distances are specified in pixels,
1540 // making the layout dependent on the output device resolution
1542 Main_GUI::create_vertical_layout()
1545 QGridLayout
* file_layout
= new QGridLayout
;
1547 file_layout
->addWidget(input_label
, 0, 0, Qt::AlignRight
);
1548 file_layout
->addWidget(input_line
, 0, 1);
1549 file_layout
->addWidget(input_button
, 0, 2);
1551 file_layout
->setRowStretch(1, 1);
1553 file_layout
->addWidget(output_label
, 2, 0, Qt::AlignRight
);
1554 file_layout
->addWidget(output_line
, 2, 1);
1555 file_layout
->addWidget(output_button
, 2, 2);
1557 file_layout
->setRowStretch(3, 1);
1559 file_layout
->addWidget(control_label
, 4, 0, Qt::AlignRight
);
1560 file_layout
->addWidget(control_line
, 4, 1);
1561 file_layout
->addWidget(control_button
, 4, 2);
1564 QGridLayout
* run_layout
= new QGridLayout
;
1566 run_layout
->addWidget(watch_box
, 0, 1);
1567 run_layout
->addWidget(run_button
, 0, 3, Qt::AlignRight
);
1568 run_layout
->setColumnStretch(0, 1);
1569 run_layout
->setColumnStretch(2, 2);
1574 QGridLayout
* gui_layout
= new QGridLayout
;
1575 QFrame
* hline
= new QFrame
;
1576 hline
->setFrameShape(QFrame::HLine
);
1577 int row
= 0; // this counter simplifies inserting new items
1579 gui_layout
->setRowMinimumHeight(row
, 10); // XXX urgh, pixels...
1580 gui_layout
->setRowStretch(row
++, 1);
1582 gui_layout
->addLayout(file_layout
, row
, 0, row
, -1);
1583 gui_layout
->setRowStretch(row
++, 1);
1585 gui_layout
->addWidget(hline
, row
, 0, row
, -1);
1586 gui_layout
->setRowStretch(row
++, 1);
1588 gui_layout
->setRowMinimumHeight(row
, 20); // XXX urgh, pixels...
1589 gui_layout
->setRowStretch(row
++, 1);
1591 gui_layout
->addWidget(min_label
, row
, 0, Qt::AlignRight
);
1592 gui_layout
->addWidget(min_box
, row
++, 1, Qt::AlignLeft
);
1593 gui_layout
->addWidget(max_label
, row
, 0, Qt::AlignRight
);
1594 gui_layout
->addWidget(max_box
, row
++, 1, Qt::AlignLeft
);
1596 gui_layout
->setRowMinimumHeight(row
, 20); // XXX urgh, pixels...
1597 gui_layout
->setRowStretch(row
++, 1);
1599 gui_layout
->addWidget(default_label
, row
, 0, Qt::AlignRight
);
1600 gui_layout
->addWidget(default_box
, row
++, 1, Qt::AlignLeft
);
1601 gui_layout
->addWidget(fallback_label
, row
, 0, Qt::AlignRight
);
1602 gui_layout
->addWidget(fallback_box
, row
++, 1, Qt::AlignLeft
);
1604 gui_layout
->setRowMinimumHeight(row
, 20); // XXX urgh, pixels...
1605 gui_layout
->setRowStretch(row
++, 1);
1607 gui_layout
->addWidget(limit_label
, row
, 0, Qt::AlignRight
);
1608 gui_layout
->addWidget(limit_box
, row
++, 1, Qt::AlignLeft
);
1609 gui_layout
->addWidget(no_limit_box
, row
++, 1);
1611 gui_layout
->addWidget(increase_label
, row
, 0, Qt::AlignRight
);
1612 gui_layout
->addWidget(increase_box
, row
++, 1, Qt::AlignLeft
);
1613 gui_layout
->addWidget(no_increase_box
, row
++, 1);
1615 gui_layout
->addWidget(snapping_label
, row
, 0, Qt::AlignRight
);
1616 gui_layout
->addWidget(snapping_line
, row
++, 1, Qt::AlignLeft
);
1618 gui_layout
->addWidget(stem_width_label
, row
, 0, Qt::AlignRight
);
1619 gui_layout
->addWidget(stem_width_box
, row
++, 1, Qt::AlignLeft
);
1620 gui_layout
->addWidget(default_stem_width_box
, row
++, 1);
1622 gui_layout
->setRowMinimumHeight(row
, 20); // XXX urgh, pixels...
1623 gui_layout
->setRowStretch(row
++, 1);
1625 gui_layout
->addWidget(wincomp_box
, row
++, 1);
1626 gui_layout
->addWidget(adjust_box
, row
++, 1);
1627 gui_layout
->addWidget(hint_box
, row
++, 1);
1628 gui_layout
->addWidget(symbol_box
, row
++, 1);
1629 gui_layout
->addWidget(dehint_box
, row
++, 1);
1631 gui_layout
->addWidget(info_label
, row
, 0, Qt::AlignRight
);
1632 gui_layout
->addWidget(info_box
, row
++, 1, Qt::AlignLeft
);
1633 gui_layout
->addWidget(TTFA_box
, row
++, 1);
1635 gui_layout
->setRowMinimumHeight(row
, 20); // XXX urgh, pixels...
1636 gui_layout
->setRowStretch(row
++, 1);
1638 gui_layout
->addWidget(stem_label
, row
, 0, Qt::AlignRight
);
1639 gui_layout
->addWidget(gray_box
, row
++, 1);
1640 gui_layout
->addWidget(gdi_box
, row
++, 1);
1641 gui_layout
->addWidget(dw_box
, row
++, 1);
1643 gui_layout
->setRowMinimumHeight(row
, 30); // XXX urgh, pixels...
1644 gui_layout
->setRowStretch(row
++, 1);
1646 gui_layout
->addLayout(run_layout
, row
, 0, row
, -1);
1648 // create dummy widget to register layout
1649 QWidget
* main_widget
= new QWidget
;
1650 main_widget
->setLayout(gui_layout
);
1651 setCentralWidget(main_widget
);
1652 setWindowTitle("TTFautohint");
1656 // XXX distances are specified in pixels,
1657 // making the layout dependent on the output device resolution
1659 Main_GUI::create_horizontal_layout()
1662 QGridLayout
* file_layout
= new QGridLayout
;
1664 file_layout
->addWidget(input_label
, 0, 0, Qt::AlignRight
);
1665 file_layout
->addWidget(input_line
, 0, 1);
1666 file_layout
->addWidget(input_button
, 0, 2);
1668 file_layout
->setRowStretch(1, 1);
1670 file_layout
->addWidget(output_label
, 2, 0, Qt::AlignRight
);
1671 file_layout
->addWidget(output_line
, 2, 1);
1672 file_layout
->addWidget(output_button
, 2, 2);
1674 file_layout
->setRowStretch(3, 1);
1676 file_layout
->addWidget(control_label
, 4, 0, Qt::AlignRight
);
1677 file_layout
->addWidget(control_line
, 4, 1);
1678 file_layout
->addWidget(control_button
, 4, 2);
1681 QGridLayout
* run_layout
= new QGridLayout
;
1683 run_layout
->addWidget(watch_box
, 0, 1);
1684 run_layout
->addWidget(run_button
, 0, 3, Qt::AlignRight
);
1685 run_layout
->setColumnStretch(0, 2);
1686 run_layout
->setColumnStretch(2, 3);
1687 run_layout
->setColumnStretch(4, 1);
1692 QGridLayout
* gui_layout
= new QGridLayout
;
1693 QFrame
* hline
= new QFrame
;
1694 hline
->setFrameShape(QFrame::HLine
);
1695 int row
= 0; // this counter simplifies inserting new items
1698 gui_layout
->setColumnMinimumWidth(0, 10); // XXX urgh, pixels...
1699 gui_layout
->setColumnStretch(0, 1);
1702 gui_layout
->setRowMinimumHeight(row
, 10); // XXX urgh, pixels...
1703 gui_layout
->setRowStretch(row
++, 1);
1705 gui_layout
->addLayout(file_layout
, row
, 0, row
, -1);
1706 gui_layout
->setRowStretch(row
++, 1);
1708 gui_layout
->addWidget(hline
, row
, 0, row
, -1);
1709 gui_layout
->setRowStretch(row
++, 1);
1711 gui_layout
->setRowMinimumHeight(row
, 20); // XXX urgh, pixels...
1712 gui_layout
->setRowStretch(row
++, 1);
1714 gui_layout
->addWidget(min_label
, row
, 1, Qt::AlignRight
);
1715 gui_layout
->addWidget(min_box
, row
++, 2, Qt::AlignLeft
);
1716 gui_layout
->addWidget(max_label
, row
, 1, Qt::AlignRight
);
1717 gui_layout
->addWidget(max_box
, row
++, 2, Qt::AlignLeft
);
1719 gui_layout
->setRowMinimumHeight(row
, 20); // XXX urgh, pixels...
1720 gui_layout
->setRowStretch(row
++, 1);
1722 gui_layout
->addWidget(default_label
, row
, 1, Qt::AlignRight
);
1723 gui_layout
->addWidget(default_box
, row
++, 2, Qt::AlignLeft
);
1724 gui_layout
->addWidget(fallback_label
, row
, 1, Qt::AlignRight
);
1725 gui_layout
->addWidget(fallback_box
, row
++, 2, Qt::AlignLeft
);
1727 gui_layout
->setRowMinimumHeight(row
, 20); // XXX urgh, pixels...
1728 gui_layout
->setRowStretch(row
++, 1);
1730 gui_layout
->addWidget(limit_label
, row
, 1, Qt::AlignRight
);
1731 gui_layout
->addWidget(limit_box
, row
++, 2, Qt::AlignLeft
);
1732 gui_layout
->addWidget(no_limit_box
, row
++, 2);
1734 gui_layout
->addWidget(increase_label
, row
, 1, Qt::AlignRight
);
1735 gui_layout
->addWidget(increase_box
, row
++, 2, Qt::AlignLeft
);
1736 gui_layout
->addWidget(no_increase_box
, row
++, 2);
1738 gui_layout
->addWidget(snapping_label
, row
, 1, Qt::AlignRight
);
1739 gui_layout
->addWidget(snapping_line
, row
++, 2, Qt::AlignLeft
);
1741 gui_layout
->addWidget(stem_width_label
, row
, 1, Qt::AlignRight
);
1742 gui_layout
->addWidget(stem_width_box
, row
++, 2, Qt::AlignLeft
);
1743 gui_layout
->addWidget(default_stem_width_box
, row
++, 2);
1745 gui_layout
->setRowMinimumHeight(row
, 30); // XXX urgh, pixels...
1746 gui_layout
->setRowStretch(row
++, 1);
1748 gui_layout
->addLayout(run_layout
, row
, 0, row
, -1);
1751 gui_layout
->setColumnMinimumWidth(3, 20); // XXX urgh, pixels...
1752 gui_layout
->setColumnStretch(3, 1);
1756 gui_layout
->addWidget(wincomp_box
, row
++, 4);
1757 gui_layout
->addWidget(adjust_box
, row
++, 4);
1758 gui_layout
->addWidget(hint_box
, row
++, 4);
1759 gui_layout
->addWidget(symbol_box
, row
++, 4);
1760 gui_layout
->addWidget(dehint_box
, row
++, 4);
1762 gui_layout
->addWidget(info_label
, row
, 3, Qt::AlignRight
);
1763 gui_layout
->addWidget(info_box
, row
++, 4, Qt::AlignLeft
);
1764 gui_layout
->addWidget(TTFA_box
, row
++, 4);
1766 gui_layout
->setRowMinimumHeight(row
, 20); // XXX urgh, pixels...
1767 gui_layout
->setRowStretch(row
++, 1);
1769 gui_layout
->addWidget(stem_label
, row
++, 4);
1771 QGridLayout
* stem_layout
= new QGridLayout
;
1772 stem_layout
->setColumnMinimumWidth(0, 20); // XXX urgh, pixels...
1773 stem_layout
->addWidget(gray_box
, 0, 1);
1774 stem_layout
->addWidget(gdi_box
, 1, 1);
1775 stem_layout
->addWidget(dw_box
, 2, 1);
1777 gui_layout
->addLayout(stem_layout
, row
, 4, 3, 1);
1781 gui_layout
->setColumnMinimumWidth(5, 10); // XXX urgh, pixels...
1782 gui_layout
->setColumnStretch(5, 1);
1784 // create dummy widget to register layout
1785 QWidget
* main_widget
= new QWidget
;
1786 main_widget
->setLayout(gui_layout
);
1787 setCentralWidget(main_widget
);
1788 setWindowTitle("TTFautohint");
1793 Main_GUI::create_connections()
1795 connect(input_button
, SIGNAL(clicked()), this,
1796 SLOT(browse_input()));
1797 connect(output_button
, SIGNAL(clicked()), this,
1798 SLOT(browse_output()));
1799 connect(control_button
, SIGNAL(clicked()), this,
1800 SLOT(browse_control()));
1802 connect(input_line
, SIGNAL(textChanged(QString
)), this,
1804 connect(output_line
, SIGNAL(textChanged(QString
)), this,
1807 connect(input_line
, SIGNAL(editingFinished()), this,
1808 SLOT(absolute_input()));
1809 connect(output_line
, SIGNAL(editingFinished()), this,
1810 SLOT(absolute_output()));
1811 connect(control_line
, SIGNAL(editingFinished()), this,
1812 SLOT(absolute_control()));
1814 connect(min_box
, SIGNAL(valueChanged(int)), this,
1816 connect(max_box
, SIGNAL(valueChanged(int)), this,
1819 connect(limit_box
, SIGNAL(valueChanged(int)), this,
1820 SLOT(check_limit()));
1821 connect(no_limit_box
, SIGNAL(clicked()), this,
1822 SLOT(check_no_limit()));
1824 connect(no_increase_box
, SIGNAL(clicked()), this,
1825 SLOT(check_no_increase()));
1827 connect(snapping_line
, SIGNAL(editingFinished()), this,
1828 SLOT(check_number_set()));
1829 connect(snapping_line
, SIGNAL(textEdited(QString
)), this,
1830 SLOT(clear_status_bar()));
1832 connect(default_stem_width_box
, SIGNAL(clicked()), this,
1833 SLOT(check_default_stem_width()));
1835 connect(dehint_box
, SIGNAL(clicked()), this,
1836 SLOT(check_dehint()));
1838 connect(timer
, SIGNAL(timeout()), this,
1839 SLOT(watch_files()));
1841 connect(watch_box
, SIGNAL(clicked()), this,
1842 SLOT(check_watch()));
1844 connect(run_button
, SIGNAL(clicked()), this,
1850 Main_GUI::create_actions()
1852 exit_act
= new QAction(tr("E&xit"), this);
1853 exit_act
->setShortcuts(QKeySequence::Quit
);
1854 connect(exit_act
, SIGNAL(triggered()), this, SLOT(close()));
1856 about_act
= new QAction(tr("&About"), this);
1857 connect(about_act
, SIGNAL(triggered()), this, SLOT(about()));
1859 about_Qt_act
= new QAction(tr("About &Qt"), this);
1860 connect(about_Qt_act
, SIGNAL(triggered()), qApp
, SLOT(aboutQt()));
1865 Main_GUI::create_menus()
1867 file_menu
= menuBar()->addMenu(tr("&File"));
1868 file_menu
->addAction(exit_act
);
1870 help_menu
= menuBar()->addMenu(tr("&Help"));
1871 help_menu
->addAction(about_act
);
1872 help_menu
->addAction(about_Qt_act
);
1877 Main_GUI::create_status_bar()
1879 statusBar()->showMessage("");
1884 Main_GUI::set_defaults()
1886 min_box
->setValue(hinting_range_min
);
1887 max_box
->setValue(hinting_range_max
);
1889 default_box
->setCurrentIndex(default_script_idx
);
1890 fallback_box
->setCurrentIndex(fallback_script_idx
);
1892 limit_box
->setValue(hinting_limit
? hinting_limit
: hinting_range_max
);
1893 // handle command line option `--hinting-limit=0'
1896 hinting_limit
= max_box
->value();
1897 no_limit_box
->setChecked(true);
1900 increase_box
->setValue(increase_x_height
? increase_x_height
1901 : TA_INCREASE_X_HEIGHT
);
1902 // handle command line option `--increase-x-height=0'
1903 if (!increase_x_height
)
1905 increase_x_height
= TA_INCREASE_X_HEIGHT
;
1906 no_increase_box
->setChecked(true);
1909 snapping_line
->setText(x_height_snapping_exceptions_string
);
1911 if (fallback_stem_width
)
1912 stem_width_box
->setValue(fallback_stem_width
);
1915 stem_width_box
->setValue(50);
1916 default_stem_width_box
->setChecked(true);
1919 if (windows_compatibility
)
1920 wincomp_box
->setChecked(true);
1921 if (adjust_subglyphs
)
1922 adjust_box
->setChecked(true);
1923 if (hint_composites
)
1924 hint_box
->setChecked(true);
1926 symbol_box
->setChecked(true);
1928 dehint_box
->setChecked(true);
1930 info_box
->setCurrentIndex(0);
1931 else if (detailed_info
)
1932 info_box
->setCurrentIndex(2);
1934 info_box
->setCurrentIndex(1);
1936 TTFA_box
->setChecked(true);
1938 if (gray_strong_stem_width
)
1939 gray_box
->setChecked(true);
1940 if (gdi_cleartype_strong_stem_width
)
1941 gdi_box
->setChecked(true);
1942 if (dw_cleartype_strong_stem_width
)
1943 dw_box
->setChecked(true);
1945 run_button
->setEnabled(false);
1952 check_no_increase();
1955 // do this last since it disables almost everything
1961 Main_GUI::read_settings()
1964 // QPoint pos = settings.value("pos", QPoint(200, 200)).toPoint();
1965 // QSize size = settings.value("size", QSize(400, 400)).toSize();
1972 Main_GUI::write_settings()
1975 // settings.setValue("pos", pos());
1976 // settings.setValue("size", size());
1979 // end of maingui.cpp