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.
25 #include <ttfautohint.h>
28 // XXX Qt 4.8 bug: locale->quoteString("foo")
29 // inserts wrongly encoded quote characters
30 // into rich text QString
31 #if HAVE_QT_QUOTESTRING
32 # define QUOTE_STRING(x) locale->quoteString(x)
33 # define QUOTE_STRING_LITERAL(x) locale->quoteString(x)
35 # define QUOTE_STRING(x) "\"" + x + "\""
36 # define QUOTE_STRING_LITERAL(x) "\"" x "\""
40 // Shorthand for `tr' using a local `TRDOMAIN'.
41 #define Tr(text) QCoreApplication::translate(TRDOMAIN, text)
44 // the available script tags and its descriptions are directly extracted
45 // from `ttfautohint-scripts.h'
46 typedef struct Script_Names_
49 const char* description
;
53 #define SCRIPT(s, S, d, h, sc1, sc2, sc3) \
56 const Script_Names script_names
[] =
58 #include <ttfautohint-scripts.h>
63 Main_GUI::Main_GUI(bool horizontal_layout
,
71 const char* exceptions
,
82 : hinting_range_min(range_min
),
83 hinting_range_max(range_max
),
85 gray_strong_stem_width(gray
),
86 gdi_cleartype_strong_stem_width(gdi
),
87 dw_cleartype_strong_stem_width(dw
),
88 increase_x_height(increase
),
89 x_height_snapping_exceptions_string(exceptions
),
90 fallback_stem_width(stem_width
),
91 ignore_restrictions(ignore
),
92 windows_compatibility(wincomp
),
93 adjust_subglyphs(adjust
),
94 hint_composites(composites
),
101 // map default script tag to an index,
102 // replacing an invalid one with the default value
103 int latn_script_idx
= 0;
104 for (i
= 0; script_names
[i
].tag
; i
++)
106 if (!strcmp("latn", script_names
[i
].tag
))
108 if (!strcmp(dflt
, script_names
[i
].tag
))
111 default_script_idx
= script_names
[i
].tag
? i
: latn_script_idx
;
113 // map fallback script tag to an index,
114 // replacing an invalid one with the default value
115 int none_script_idx
= 0;
116 for (i
= 0; script_names
[i
].tag
; i
++)
118 if (!strcmp("none", script_names
[i
].tag
))
120 if (!strcmp(fallback
, script_names
[i
].tag
))
123 fallback_script_idx
= script_names
[i
].tag
? i
: none_script_idx
;
125 x_height_snapping_exceptions
= NULL
;
127 // if file watching is active, we regularly poll the file status
128 timer
= new QTimer(this);
129 timer
->setInterval(1000);
130 fileinfo_input_file
.setCaching(false);
131 fileinfo_deltas_file
.setCaching(false);
133 create_layout(horizontal_layout
);
134 create_connections();
142 setUnifiedTitleAndToolBarOnMac(true);
144 // XXX register translations somewhere and loop over them
145 if (QLocale::system().name() == "en_US")
146 locale
= new QLocale
;
148 locale
= new QLocale(QLocale::C
);
152 Main_GUI::~Main_GUI()
154 number_set_free(x_height_snapping_exceptions
);
161 Main_GUI::closeEvent(QCloseEvent
* event
)
171 QMessageBox::about(this,
172 tr("About TTFautohint"),
173 tr("<p>This is <b>TTFautohint</b> version %1<br>"
174 " Copyright %2 2011-2014<br>"
175 " by Werner Lemberg <tt><wl@gnu.org></tt></p>"
177 "<p><b>TTFautohint</b> adds new auto-generated hints"
178 " to a TrueType font or TrueType collection.</p>"
181 " <a href='http://git.savannah.gnu.org/cgit/freetype/freetype2.git/tree/docs/FTL.TXT'>FreeType"
182 " License (FTL)</a> or"
183 " <a href='http://git.savannah.gnu.org/cgit/freetype/freetype2.git/tree/docs/GPLv2.TXT'>GNU"
191 Main_GUI::browse_input()
193 // XXX remember last directory
194 QString file
= QFileDialog::getOpenFileName(
196 tr("Open Input File"),
200 input_line
->setText(QDir::toNativeSeparators(file
));
205 Main_GUI::browse_output()
207 // XXX remember last directory
208 QString file
= QFileDialog::getSaveFileName(
210 tr("Open Output File"),
215 output_line
->setText(QDir::toNativeSeparators(file
));
220 Main_GUI::browse_deltas()
222 // XXX remember last directory
223 QString file
= QFileDialog::getOpenFileName(
225 tr("Open Delta Exceptions File"),
230 deltas_line
->setText(QDir::toNativeSeparators(file
));
235 Main_GUI::check_min()
237 int min
= min_box
->value();
238 int max
= max_box
->value();
239 int limit
= limit_box
->value();
241 max_box
->setValue(min
);
243 limit_box
->setValue(min
);
248 Main_GUI::check_max()
250 int min
= min_box
->value();
251 int max
= max_box
->value();
252 int limit
= limit_box
->value();
254 min_box
->setValue(max
);
256 limit_box
->setValue(max
);
261 Main_GUI::check_limit()
263 int min
= min_box
->value();
264 int max
= max_box
->value();
265 int limit
= limit_box
->value();
267 max_box
->setValue(limit
);
269 min_box
->setValue(limit
);
274 Main_GUI::check_dehint()
276 if (dehint_box
->isChecked())
278 min_label
->setEnabled(false);
279 min_box
->setEnabled(false);
281 max_label
->setEnabled(false);
282 max_box
->setEnabled(false);
284 default_label
->setEnabled(false);
285 default_box
->setEnabled(false);
286 fallback_label
->setEnabled(false);
287 fallback_box
->setEnabled(false);
289 no_limit_box
->setEnabled(false);
290 limit_label
->setEnabled(false);
291 limit_box
->setEnabled(false);
293 no_increase_box
->setEnabled(false);
294 increase_label
->setEnabled(false);
295 increase_box
->setEnabled(false);
297 snapping_label
->setEnabled(false);
298 snapping_line
->setEnabled(false);
300 default_stem_width_box
->setEnabled(false);
301 stem_width_label
->setEnabled(false);
302 stem_width_box
->setEnabled(false);
304 wincomp_box
->setEnabled(false);
305 adjust_box
->setEnabled(false);
306 hint_box
->setEnabled(false);
307 symbol_box
->setEnabled(false);
309 stem_label
->setEnabled(false);
310 gray_box
->setEnabled(false);
311 gdi_box
->setEnabled(false);
312 dw_box
->setEnabled(false);
316 min_label
->setEnabled(true);
317 min_box
->setEnabled(true);
319 max_label
->setEnabled(true);
320 max_box
->setEnabled(true);
322 default_label
->setEnabled(true);
323 default_box
->setEnabled(true);
324 fallback_label
->setEnabled(true);
325 fallback_box
->setEnabled(true);
327 no_limit_box
->setEnabled(true);
330 no_increase_box
->setEnabled(true);
333 snapping_label
->setEnabled(true);
334 snapping_line
->setEnabled(true);
336 default_stem_width_box
->setEnabled(true);
337 check_default_stem_width();
339 wincomp_box
->setEnabled(true);
340 adjust_box
->setEnabled(true);
341 hint_box
->setEnabled(true);
342 symbol_box
->setEnabled(true);
344 stem_label
->setEnabled(true);
345 gray_box
->setEnabled(true);
346 gdi_box
->setEnabled(true);
347 dw_box
->setEnabled(true);
353 Main_GUI::check_no_limit()
355 if (no_limit_box
->isChecked())
357 limit_label
->setEnabled(false);
358 limit_label
->setText(limit_label_text
);
359 limit_box
->setEnabled(false);
360 no_limit_box
->setText(no_limit_box_text_with_key
);
364 limit_label
->setEnabled(true);
365 limit_label
->setText(limit_label_text_with_key
);
366 limit_box
->setEnabled(true);
367 no_limit_box
->setText(no_limit_box_text
);
373 Main_GUI::check_no_increase()
375 if (no_increase_box
->isChecked())
377 increase_label
->setEnabled(false);
378 increase_label
->setText(increase_label_text
);
379 increase_box
->setEnabled(false);
380 no_increase_box
->setText(no_increase_box_text_with_key
);
384 increase_label
->setEnabled(true);
385 increase_label
->setText(increase_label_text_with_key
);
386 increase_box
->setEnabled(true);
387 no_increase_box
->setText(no_increase_box_text
);
393 Main_GUI::check_default_stem_width()
395 if (default_stem_width_box
->isChecked())
397 stem_width_label
->setEnabled(false);
398 stem_width_label
->setText(stem_width_label_text
);
399 stem_width_box
->setEnabled(false);
400 default_stem_width_box
->setText(default_stem_width_box_text_with_key
);
404 stem_width_label
->setEnabled(true);
405 stem_width_label
->setText(stem_width_label_text_with_key
);
406 stem_width_box
->setEnabled(true);
407 default_stem_width_box
->setText(default_stem_width_box_text
);
413 Main_GUI::check_run()
415 if (input_line
->text().isEmpty() || output_line
->text().isEmpty())
416 run_button
->setEnabled(false);
418 run_button
->setEnabled(true);
423 Main_GUI::absolute_input()
425 QString input_name
= QDir::fromNativeSeparators(input_line
->text());
426 if (!input_name
.isEmpty()
427 && QDir::isRelativePath(input_name
))
429 QDir
cur_path(QDir::currentPath() + "/" + input_name
);
430 input_line
->setText(QDir::toNativeSeparators(cur_path
.absolutePath()));
436 Main_GUI::absolute_output()
438 QString output_name
= QDir::fromNativeSeparators(output_line
->text());
439 if (!output_name
.isEmpty()
440 && QDir::isRelativePath(output_name
))
442 QDir
cur_path(QDir::currentPath() + "/" + output_name
);
443 output_line
->setText(QDir::toNativeSeparators(cur_path
.absolutePath()));
449 Main_GUI::absolute_deltas()
451 QString deltas_name
= QDir::fromNativeSeparators(deltas_line
->text());
452 if (!deltas_name
.isEmpty()
453 && QDir::isRelativePath(deltas_name
))
455 QDir
cur_path(QDir::currentPath() + "/" + deltas_name
);
456 deltas_line
->setText(QDir::toNativeSeparators(cur_path
.absolutePath()));
462 Main_GUI::check_number_set()
464 QString text
= snapping_line
->text();
467 // construct ASCII string from arbitrary Unicode data;
468 // the idea is to accept, say, CJK fullwidth digits also
469 for (int i
= 0; i
< text
.size(); i
++)
471 QChar c
= text
.at(i
);
473 int digit
= c
.digitValue();
475 qs
+= QString::number(digit
);
476 else if (c
.isSpace())
478 // U+30FC KATAGANA-HIRAGANA PROLONGED SOUND MARK is assigned
479 // to the `-' key in some Japanese input methods
480 else if (c
.category() == QChar::Punctuation_Dash
481 || c
== QChar(0x30FC))
483 // various Unicode COMMA characters,
484 // including representation forms
485 else if (c
== QChar(',')
486 || c
== QChar(0x055D)
487 || c
== QChar(0x060C)
488 || c
== QChar(0x07F8)
489 || c
== QChar(0x1363)
490 || c
== QChar(0x1802)
491 || c
== QChar(0x1808)
492 || c
== QChar(0x3001)
493 || c
== QChar(0xA4FE)
494 || c
== QChar(0xA60D)
495 || c
== QChar(0xA6F5)
496 || c
== QChar(0xFE10)
497 || c
== QChar(0xFE11)
498 || c
== QChar(0xFE50)
499 || c
== QChar(0xFE51)
500 || c
== QChar(0xFF0C)
501 || c
== QChar(0xFF64))
504 qs
+= c
; // we do error handling below
507 if (x_height_snapping_exceptions
)
508 number_set_free(x_height_snapping_exceptions
);
510 QByteArray str
= qs
.toLocal8Bit();
511 const char* s
= number_set_parse(str
.constData(),
512 &x_height_snapping_exceptions
,
516 statusBar()->setStyleSheet("color: red;");
517 if (x_height_snapping_exceptions
== NUMBERSET_ALLOCATION_ERROR
)
518 statusBar()->showMessage(
519 tr("allocation error"));
520 else if (x_height_snapping_exceptions
== NUMBERSET_INVALID_CHARACTER
)
521 statusBar()->showMessage(
522 tr("invalid character (use digits, dashes, commas, and spaces)"));
523 else if (x_height_snapping_exceptions
== NUMBERSET_OVERFLOW
)
524 statusBar()->showMessage(
526 else if (x_height_snapping_exceptions
== NUMBERSET_INVALID_RANGE
)
527 statusBar()->showMessage(
528 tr("invalid range (minimum is 6, maximum is 32767)"));
529 else if (x_height_snapping_exceptions
== NUMBERSET_OVERLAPPING_RANGES
)
530 statusBar()->showMessage(
531 tr("overlapping ranges"));
532 else if (x_height_snapping_exceptions
== NUMBERSET_NOT_ASCENDING
)
533 statusBar()->showMessage(
534 tr("values und ranges must be specified in ascending order"));
536 snapping_line
->setText(qs
);
537 snapping_line
->setFocus(Qt::OtherFocusReason
);
538 snapping_line
->setCursorPosition(s
- str
.constData());
540 x_height_snapping_exceptions
= NULL
;
544 // normalize if there is no error
545 char* new_str
= number_set_show(x_height_snapping_exceptions
,
547 snapping_line
->setText(new_str
);
554 Main_GUI::clear_status_bar()
556 statusBar()->clearMessage();
557 statusBar()->setStyleSheet("");
562 Main_GUI::check_filenames(const QString
& input_name
,
563 const QString
& output_name
,
564 const QString
& deltas_name
)
566 if (!QFile::exists(input_name
))
568 QMessageBox::warning(
571 tr("The file %1 cannot be found.")
572 .arg(QUOTE_STRING(QDir::toNativeSeparators(input_name
))),
578 if (input_name
== output_name
)
580 QMessageBox::warning(
583 tr("Input and output file names must be different."),
589 // silently overwrite if watching is active
590 if (QFile::exists(output_name
) && !timer
->isActive())
592 int ret
= QMessageBox::warning(
595 tr("The file %1 already exists.\n"
597 .arg(QUOTE_STRING(QDir::toNativeSeparators(output_name
))),
598 QMessageBox::Yes
| QMessageBox::No
,
600 if (ret
== QMessageBox::No
)
604 if (!deltas_name
.isEmpty() && !QFile::exists(deltas_name
))
606 QMessageBox::warning(
609 tr("The file %1 cannot be found.")
610 .arg(QUOTE_STRING(QDir::toNativeSeparators(deltas_name
))),
621 Main_GUI::open_files(const QString
& input_name
,
623 const QString
& output_name
,
625 const QString
& deltas_name
,
628 const int buf_len
= 1024;
631 *in
= fopen(qPrintable(input_name
), "rb");
634 strerror_r(errno
, buf
, buf_len
);
635 QMessageBox::warning(
638 tr("The following error occurred while opening input file %1:\n")
639 .arg(QUOTE_STRING(QDir::toNativeSeparators(input_name
)))
640 + QString::fromLocal8Bit(buf
),
646 *out
= fopen(qPrintable(output_name
), "wb");
649 strerror_r(errno
, buf
, buf_len
);
650 QMessageBox::warning(
653 tr("The following error occurred while opening output file %1:\n")
654 .arg(QUOTE_STRING(QDir::toNativeSeparators(output_name
)))
655 + QString::fromLocal8Bit(buf
),
661 // inspite of being a text file we open it in binary mode
662 // to make `TTF_autohint' handle different EOL conventions gracefully
663 if (!deltas_name
.isEmpty())
665 *deltas
= fopen(qPrintable(deltas_name
), "rb");
668 strerror_r(errno
, buf
, buf_len
);
669 QMessageBox::warning(
672 tr("The following error occurred"
673 " while opening delta exceptions file %1:\n")
674 .arg(QUOTE_STRING(QDir::toNativeSeparators(deltas_name
)))
675 + QString::fromLocal8Bit(buf
),
687 Main_GUI::check_watch()
689 if (!watch_box
->isChecked())
691 // the timer gets started in the `run' function
696 Main_GUI::watch_files()
698 if (fileinfo_input_file
.exists()
699 && fileinfo_input_file
.isReadable()
700 && fileinfo_deltas_file
.exists()
701 && fileinfo_deltas_file
.isReadable())
703 QDateTime modified_input
= fileinfo_input_file
.lastModified();
704 QDateTime modified_deltas
= fileinfo_deltas_file
.lastModified();
705 if (modified_input
> datetime_input_file
706 || modified_deltas
> datetime_deltas_file
)
707 run(); // this function sets `datetime_XXX'
710 run(); // let this routine handle all errors
716 struct GUI_Progress_Data
720 QProgressDialog
* dialog
;
725 #define TRDOMAIN "GuiProgress"
728 gui_progress(long curr_idx
,
734 GUI_Progress_Data
* data
= static_cast<GUI_Progress_Data
*>(user
);
736 if (num_sfnts
> 1 && curr_sfnt
!= data
->last_sfnt
)
738 data
->dialog
->setLabelText(Tr("Auto-hinting subfont %1 of %2"
739 " with %3 glyphs...")
744 if (curr_sfnt
+ 1 == num_sfnts
)
746 data
->dialog
->setAutoReset(true);
747 data
->dialog
->setAutoClose(true);
751 data
->dialog
->setAutoReset(false);
752 data
->dialog
->setAutoClose(false);
755 data
->last_sfnt
= curr_sfnt
;
762 data
->dialog
->setLabelText(Tr("Auto-hinting %1 glyphs...")
764 data
->dialog
->setMaximum(num_glyphs
- 1);
769 data
->dialog
->setValue(curr_idx
);
771 if (data
->dialog
->wasCanceled())
778 struct GUI_Error_Data
784 int* ignore_restrictions_p
;
790 #define TRDOMAIN "GuiError"
793 gui_error(TA_Error error
,
794 const char* error_string
,
795 unsigned int errlinenum
,
800 GUI_Error_Data
* data
= static_cast<GUI_Error_Data
*>(user
);
801 QLocale
* locale
= data
->locale
; // for QUOTE_STRING_LITERAL
806 if (error
== TA_Err_Canceled
)
808 else if (error
== TA_Err_Invalid_FreeType_Version
)
809 QMessageBox::critical(
812 Tr("FreeType version 2.4.5 or higher is needed.\n"
813 "Are you perhaps using a wrong FreeType DLL?"),
816 else if (error
== TA_Err_Invalid_Font_Type
)
817 QMessageBox::warning(
820 Tr("This font is not a valid font"
821 " in SFNT format with TrueType outlines.\n"
822 "In particular, CFF outlines are not supported."),
825 else if (error
== TA_Err_Already_Processed
)
826 QMessageBox::warning(
829 Tr("This font has already been processed by TTFautohint."),
832 else if (error
== TA_Err_Missing_Legal_Permission
)
834 int yesno
= QMessageBox::warning(
837 Tr("Bit 1 in the %1 field of the %2 table is set:"
838 " This font must not be modified"
839 " without permission of the legal owner.\n"
840 "Do you have such a permission?")
841 .arg(QUOTE_STRING_LITERAL("fsType"))
842 .arg(QUOTE_STRING_LITERAL("OS/2")),
843 QMessageBox::Yes
| QMessageBox::No
,
845 if (yesno
== QMessageBox::Yes
)
847 *data
->ignore_restrictions_p
= true;
851 else if (error
== TA_Err_Missing_Unicode_CMap
)
852 QMessageBox::warning(
855 Tr("The input font doesn't contain a Unicode character map.\n"
856 "Maybe you haven't set the %1 checkbox?")
857 .arg(QUOTE_STRING_LITERAL(Tr("Symbol Font"))),
860 else if (error
== TA_Err_Missing_Symbol_CMap
)
861 QMessageBox::warning(
864 Tr("The input font does neither contain a symbol"
865 " nor a character map."),
868 else if (error
== TA_Err_Missing_Glyph
)
869 QMessageBox::warning(
872 Tr("No glyph for a standard character"
873 " to derive standard width and height.\n"
874 "Please check the documentation for a list of"
875 " script-specific standard characters.\n"
877 "Set the %1 checkbox if you want to circumvent this test.")
878 .arg(QUOTE_STRING_LITERAL(Tr("Symbol Font"))),
881 else if (error
>= 0x200 && error
< 0x300)
882 QMessageBox::warning(
885 QString::fromLocal8Bit("%1:%2: %3 (0x%4)<br>"
888 .arg(data
->deltas_name
)
891 .arg(error
, 2, 16, QLatin1Char('0'))
893 .arg('^', int(errpos
- errline
+ 1))
894 .replace(" ", " "),
898 QMessageBox::warning(
901 Tr("Error code 0x%1 while autohinting font:\n")
902 .arg(error
, 2, 16, QLatin1Char('0'))
903 + QString::fromLocal8Bit(error_string
),
907 if (QFile::exists(data
->output_name
)
908 && remove(qPrintable(data
->output_name
)))
910 const int buf_len
= 1024;
913 strerror_r(errno
, buf
, buf_len
);
914 QMessageBox::warning(
917 Tr("The following error occurred while removing output file %1:\n")
918 .arg(QUOTE_STRING(QDir::toNativeSeparators(data
->output_name
)))
919 + QString::fromLocal8Bit(buf
),
931 statusBar()->clearMessage();
933 QString input_name
= QDir::fromNativeSeparators(input_line
->text());
934 QString output_name
= QDir::fromNativeSeparators(output_line
->text());
935 QString deltas_name
= QDir::fromNativeSeparators(deltas_line
->text());
936 if (!check_filenames(input_name
, output_name
, deltas_name
))
942 // we need C file descriptors for communication with TTF_autohint
948 if (!open_files(input_name
, &input
,
949 output_name
, &output
,
950 deltas_name
, &deltas
))
956 QProgressDialog dialog
;
957 dialog
.setCancelButtonText(tr("Cancel"));
958 dialog
.setMinimumDuration(1000);
959 dialog
.setWindowModality(Qt::WindowModal
);
961 TA_Info_Func info_func
= info
;
962 GUI_Progress_Data gui_progress_data
= {-1, true, &dialog
};
963 GUI_Error_Data gui_error_data
= { this, locale
, output_name
, deltas_name
,
964 &ignore_restrictions
, false };
967 info_data
.data
= NULL
; // must be deallocated after use
968 info_data
.data_wide
= NULL
; // must be deallocated after use
969 info_data
.data_len
= 0;
970 info_data
.data_wide_len
= 0;
972 info_data
.hinting_range_min
= min_box
->value();
973 info_data
.hinting_range_max
= max_box
->value();
974 info_data
.hinting_limit
= no_limit_box
->isChecked()
976 : limit_box
->value();
978 info_data
.gray_strong_stem_width
= gray_box
->isChecked();
979 info_data
.gdi_cleartype_strong_stem_width
= gdi_box
->isChecked();
980 info_data
.dw_cleartype_strong_stem_width
= dw_box
->isChecked();
982 info_data
.increase_x_height
= no_increase_box
->isChecked()
984 : increase_box
->value();
985 info_data
.x_height_snapping_exceptions_string
=
986 qPrintable(x_height_snapping_exceptions_string
);
987 info_data
.fallback_stem_width
= default_stem_width_box
->isChecked()
989 : stem_width_box
->value();
991 info_data
.windows_compatibility
= wincomp_box
->isChecked();
992 info_data
.adjust_subglyphs
= adjust_box
->isChecked();
993 info_data
.hint_composites
= hint_box
->isChecked();
994 info_data
.symbol
= symbol_box
->isChecked();
995 info_data
.dehint
= dehint_box
->isChecked();
997 strncpy(info_data
.default_script
,
998 script_names
[default_box
->currentIndex()].tag
,
999 sizeof (info_data
.default_script
));
1000 strncpy(info_data
.fallback_script
,
1001 script_names
[fallback_box
->currentIndex()].tag
,
1002 sizeof (info_data
.fallback_script
));
1004 if (info_box
->isChecked())
1006 int ret
= build_version_string(&info_data
);
1008 QMessageBox::information(
1011 tr("Can't allocate memory for <b>TTFautohint</b> options string"
1012 " in <i>name</i> table."),
1016 QMessageBox::information(
1019 tr("<b>TTFautohint</b> options string"
1020 " in <i>name</i> table too long."),
1027 if (info_data
.symbol
1028 && info_data
.fallback_stem_width
1029 && !strcmp(info_data
.fallback_script
, "none"))
1030 QMessageBox::information(
1033 tr("Setting a fallback stem width for a symbol font"
1034 " without setting a fallback script has no effect."),
1038 fileinfo_input_file
.setFile(input_name
);
1039 fileinfo_deltas_file
.setFile(deltas_name
);
1040 datetime_input_file
= fileinfo_input_file
.lastModified();
1041 datetime_deltas_file
= fileinfo_deltas_file
.lastModified();
1043 QByteArray snapping_string
= snapping_line
->text().toLocal8Bit();
1046 TTF_autohint("in-file, out-file, deltas-file,"
1047 "hinting-range-min, hinting-range-max,"
1049 "gray-strong-stem-width,"
1050 "gdi-cleartype-strong-stem-width,"
1051 "dw-cleartype-strong-stem-width,"
1052 "progress-callback, progress-callback-data,"
1053 "error-callback, error-callback-data,"
1054 "info-callback, info-callback-data,"
1055 "ignore-restrictions,"
1056 "windows-compatibility,"
1059 "increase-x-height,"
1060 "x-height-snapping-exceptions, fallback-stem-width,"
1061 "default-script, fallback-script,"
1063 input
, output
, deltas
,
1064 info_data
.hinting_range_min
, info_data
.hinting_range_max
,
1065 info_data
.hinting_limit
,
1066 info_data
.gray_strong_stem_width
,
1067 info_data
.gdi_cleartype_strong_stem_width
,
1068 info_data
.dw_cleartype_strong_stem_width
,
1069 gui_progress
, &gui_progress_data
,
1070 gui_error
, &gui_error_data
,
1071 info_func
, &info_data
,
1072 ignore_restrictions
,
1073 info_data
.windows_compatibility
,
1074 info_data
.adjust_subglyphs
,
1075 info_data
.hint_composites
,
1076 info_data
.increase_x_height
,
1077 snapping_string
.constData(), info_data
.fallback_stem_width
,
1078 info_data
.default_script
, info_data
.fallback_script
,
1079 info_data
.symbol
, info_data
.dehint
);
1081 if (info_box
->isChecked())
1083 free(info_data
.data
);
1084 free(info_data
.data_wide
);
1094 // retry if there is a user request to do so (handled in `gui_error')
1095 if (gui_error_data
.retry
)
1102 statusBar()->showMessage(tr("Auto-hinting finished")
1104 + QDateTime::currentDateTime()
1105 .toString(Qt::TextDate
)
1108 // we have successfully processed a file;
1109 // start file watching now if requested
1110 if (watch_box
->isChecked())
1116 // XXX distances are specified in pixels,
1117 // making the layout dependent on the output device resolution
1119 Main_GUI::create_layout(bool horizontal_layout
)
1124 QCompleter
* completer
= new QCompleter(this);
1125 QFileSystemModel
* model
= new QFileSystemModel(completer
);
1126 model
->setRootPath(QDir::rootPath());
1127 completer
->setModel(model
);
1129 input_label
= new QLabel(tr("&Input File:"));
1130 input_line
= new Drag_Drop_Line_Edit(DRAG_DROP_TRUETYPE
);
1131 input_button
= new QPushButton(tr("Browse..."));
1132 input_label
->setBuddy(input_line
);
1133 // enforce rich text to get nice word wrapping
1134 input_label
->setToolTip(
1135 tr("<b></b>The input file, either a TrueType font (TTF),"
1136 " TrueType collection (TTC), or a TrueType-based OpenType font."));
1137 input_line
->setCompleter(completer
);
1139 output_label
= new QLabel(tr("&Output File:"));
1140 output_line
= new Drag_Drop_Line_Edit(DRAG_DROP_TRUETYPE
);
1141 output_button
= new QPushButton(tr("Browse..."));
1142 output_label
->setBuddy(output_line
);
1143 output_label
->setToolTip(
1144 tr("<b></b>The output file, which will be essentially identical"
1145 " to the input font but will contain new, generated hints."));
1146 output_line
->setCompleter(completer
);
1148 deltas_label
= new QLabel(tr("Delta &Exception File:"));
1149 deltas_line
= new Drag_Drop_Line_Edit(DRAG_DROP_ANY
);
1150 deltas_button
= new QPushButton(tr("Browse..."));
1151 deltas_label
->setBuddy(deltas_line
);
1152 deltas_label
->setToolTip(
1153 tr("<p>An optional delta exceptions file to fine-tune point positions"
1154 " after hinting, using DELTAP TrueType instructions."
1155 " This text file contains lines of the form<br>"
1157 " [ <i>subfont-idx</i> ]"
1158 " <i>glyph-id</i>"
1159 " <tt>p</tt> <i>points</i>"
1160 " [ <tt>x</tt> <i>shift</i> ]"
1161 " [ <tt>y</tt> <i>shift</i> ]"
1162 " <tt>@</tt> <i>ppems</i><br>"
1164 "<i>subfont-idx</i> gives the subfont index in a TTC,"
1165 " <i>glyph-id</i> is a glyph name or index,"
1166 " the x and y <i>shift</i> values are in the range [-1;1],"
1167 " rounded to multiples of 1/8px,"
1168 " <i>points</i> and <i>ppems</i> are ranges for point indices"
1169 " and ppem values as with x height snapping exceptions.<br>"
1170 "<tt>#</tt> starts a line comment, which gets ignored."
1171 " Empty lines are ignored, too.</p>"
1174 " <tt>Adieresis p 3-6 y 0.25 @ 13</tt>"));
1175 deltas_line
->setCompleter(completer
);
1180 min_label
= new QLabel(tr("Hint Set Range Mi&nimum:"));
1181 min_box
= new QSpinBox
;
1182 min_label
->setBuddy(min_box
);
1183 min_label
->setToolTip(
1184 tr("The minimum PPEM value of the range for which"
1185 " <b>TTFautohint</b> computes <i>hint sets</i>."
1186 " A hint set for a given PPEM value hints this size optimally."
1187 " The larger the range, the more hint sets are considered,"
1188 " usually increasing the size of the bytecode.<br>"
1189 "Note that changing this range doesn't influence"
1190 " the <i>gasp</i> table:"
1191 " Hinting is enabled for all sizes."));
1192 min_box
->setKeyboardTracking(false);
1193 min_box
->setRange(2, 10000);
1195 max_label
= new QLabel(tr("Hint Set Range Ma&ximum:"));
1196 max_box
= new QSpinBox
;
1197 max_label
->setBuddy(max_box
);
1198 max_label
->setToolTip(
1199 tr("The maximum PPEM value of the range for which"
1200 " <b>TTFautohint</b> computes <i>hint sets</i>."
1201 " A hint set for a given PPEM value hints this size optimally."
1202 " The larger the range, the more hint sets are considered,"
1203 " usually increasing the size of the bytecode.<br>"
1204 "Note that changing this range doesn't influence"
1205 " the <i>gasp</i> table:"
1206 " Hinting is enabled for all sizes."));
1207 max_box
->setKeyboardTracking(false);
1208 max_box
->setRange(2, 10000);
1211 // OpenType default script
1213 default_label
= new QLabel(tr("Defa&ult Script:"));
1214 default_box
= new QComboBox
;
1215 default_label
->setBuddy(default_box
);
1216 default_label
->setToolTip(
1217 tr("This sets the default script for OpenType features:"
1218 " After applying all features that are handled specially"
1219 " (for example small caps or superscript glyphs),"
1220 " <b>TTFautohint</b> uses this value for the remaining features."));
1221 for (int i
= 0; script_names
[i
].tag
; i
++)
1223 // XXX: how to provide translations?
1224 default_box
->insertItem(i
,
1226 .arg(script_names
[i
].tag
)
1227 .arg(script_names
[i
].description
));
1231 // hinting and fallback controls
1233 fallback_label
= new QLabel(tr("Fallback &Script:"));
1234 fallback_box
= new QComboBox
;
1235 fallback_label
->setBuddy(fallback_box
);
1236 fallback_label
->setToolTip(
1237 tr("This sets the fallback script for glyphs"
1238 " that <b>TTFautohint</b> can't map to a script automatically."));
1239 for (int i
= 0; script_names
[i
].tag
; i
++)
1241 // XXX: how to provide translations?
1242 fallback_box
->insertItem(i
,
1244 .arg(script_names
[i
].tag
)
1245 .arg(script_names
[i
].description
));
1251 limit_label_text_with_key
= tr("Hinting &Limit:");
1252 limit_label_text
= tr("Hinting Limit:");
1253 limit_label
= new QLabel(limit_label_text_with_key
);
1254 limit_box
= new QSpinBox
;
1255 limit_label
->setBuddy(limit_box
);
1256 limit_label
->setToolTip(
1257 tr("Switch off hinting for PPEM values exceeding this limit."
1258 " Changing this value does not influence the size of the bytecode.<br>"
1259 "Note that <b>TTFautohint</b> handles this feature"
1260 " in the output font's bytecode and not in the <i>gasp</i> table."));
1261 limit_box
->setKeyboardTracking(false);
1262 limit_box
->setRange(2, 10000);
1264 no_limit_box_text_with_key
= tr("No Hinting &Limit");
1265 no_limit_box_text
= tr("No Hinting Limit");
1266 no_limit_box
= new QCheckBox(no_limit_box_text
, this);
1267 no_limit_box
->setToolTip(
1268 tr("If switched on, <b>TTFautohint</b> adds no hinting limit"
1269 " to the bytecode.<br>"
1270 "For testing only."));
1273 // x height increase limit
1275 increase_label_text_with_key
= tr("x Height In&crease Limit:");
1276 increase_label_text
= tr("x Height Increase Limit:");
1277 increase_label
= new QLabel(increase_label_text_with_key
);
1278 increase_box
= new QSpinBox
;
1279 increase_label
->setBuddy(increase_box
);
1280 increase_label
->setToolTip(
1281 tr("For PPEM values in the range 5 < PPEM < <i>n</i>,"
1282 " where <i>n</i> is the value selected by this spin box,"
1283 " round up the font's x height much more often than normally.<br>"
1284 "Use this if holes in letters like <i>e</i> get filled,"
1286 increase_box
->setKeyboardTracking(false);
1287 increase_box
->setRange(6, 10000);
1289 no_increase_box_text_with_key
= tr("No x Height In&crease");
1290 no_increase_box_text
= tr("No x Height Increase");
1291 no_increase_box
= new QCheckBox(no_increase_box_text
, this);
1292 no_increase_box
->setToolTip(
1293 tr("If switched on,"
1294 " <b>TTFautohint</b> does not increase the x height."));
1297 // x height snapping exceptions
1299 snapping_label
= new QLabel(tr("x Height Snapping Excep&tions:"));
1300 snapping_line
= new Tooltip_Line_Edit
;
1301 snapping_label
->setBuddy(snapping_line
);
1302 snapping_label
->setToolTip(
1303 tr("<p>A list of comma separated PPEM values or value ranges"
1304 " at which no x height snapping shall be applied"
1305 " (x height snapping usually slightly increases"
1306 " the size of all glyphs).</p>"
1309 " <tt>2, 3-5, 12-17</tt><br>"
1310 " <tt>-20, 40-</tt>"
1311 " (meaning PPEM ≤ 20 or PPEM ≥ 40)<br>"
1312 " <tt>-</tt> (meaning all possible PPEM values)"));
1315 // fallback stem width
1317 stem_width_label_text_with_key
= tr("Fall&back Stem Width:");
1318 stem_width_label_text
= tr("Fallback Stem Width:");
1319 stem_width_label
= new QLabel(stem_width_label_text_with_key
);
1320 stem_width_box
= new QSpinBox
;
1321 stem_width_label
->setBuddy(stem_width_box
);
1322 stem_width_label
->setToolTip(
1323 tr("Set horizontal stem width (in font units) for all scripts"
1324 " that lack proper standard characters in the font.<br>"
1325 "If not set, <b>TTFautohint</b> uses a hard-coded default value."));
1326 stem_width_box
->setKeyboardTracking(false);
1327 stem_width_box
->setRange(1, 10000);
1329 default_stem_width_box_text_with_key
= tr("Default Fall&back Stem Width");
1330 default_stem_width_box_text
= tr("Default Fallback Stem Width");
1331 default_stem_width_box
= new QCheckBox(default_stem_width_box_text
, this);
1332 default_stem_width_box
->setToolTip(
1333 tr("If switched on, <b>TTFautohint</b> uses a default value"
1334 " for the fallback stem width (50 font units at 2048 UPEM)."));
1339 wincomp_box
= new QCheckBox(tr("Windows Com&patibility"), this);
1340 wincomp_box
->setToolTip(
1341 tr("If switched on, add two artificial blue zones positioned at the"
1342 " <tt>usWinAscent</tt> and <tt>usWinDescent</tt> values"
1343 " (from the font's <i>OS/2</i> table)."
1344 " This option, usually in combination"
1345 " with value <tt>-</tt> (a single dash)"
1346 " for the <i>x Height Snapping Exceptions</i> option,"
1347 " should be used if those two <i>OS/2</i> values are tight,"
1348 " and you are experiencing clipping during rendering."));
1350 adjust_box
= new QCheckBox(tr("Ad&just Subglyphs"), this);
1351 adjust_box
->setToolTip(
1352 tr("If switched on, the original bytecode of the input font"
1353 " gets applied (at EM size, usually 2048ppem)"
1354 " to derive the glyph outlines for <b>TTFautohint</b>.<br>"
1355 "Use this option only if subglyphs"
1356 " are incorrectly scaled and shifted.<br>"
1357 "Note that the original bytecode will always be discarded."));
1359 hint_box
= new QCheckBox(tr("Hint Co&mposites")
1360 + " ", this); // make label wider
1361 hint_box
->setToolTip(
1362 tr("If switched on, <b>TTFautohint</b> hints composite glyphs"
1363 " as a whole, including subglyphs."
1364 " Otherwise, glyph components get hinted separately.<br>"
1365 "Deactivating this flag reduces the bytecode size enormously,"
1366 " however, it might yield worse results."));
1368 symbol_box
= new QCheckBox(tr("S&ymbol Font"), this);
1369 symbol_box
->setToolTip(
1370 tr("If switched on, <b>TTFautohint</b> accepts fonts"
1371 " that don't contain a single standard character"
1372 " for any of the supported scripts.<br>"
1373 "Use this for symbol or dingbat fonts, for example."));
1375 dehint_box
= new QCheckBox(tr("&Dehint"), this);
1376 dehint_box
->setToolTip(
1377 tr("If set, remove all hints from the font.<br>"
1378 "For testing only."));
1380 info_box
= new QCheckBox(tr("Add ttf&autohint Info"), this);
1381 info_box
->setToolTip(
1382 tr("If switched on, information about <b>TTFautohint</b>"
1383 " and its calling parameters are added to the version string(s)"
1384 " (name ID 5) in the <i>name</i> table."));
1387 // stem width and positioning
1389 stem_label
= new QLabel(tr("Stron&g Stem Width and Positioning:"));
1390 stem_label
->setToolTip(
1391 tr("<b>TTFautohint</b> provides two different hinting algorithms"
1392 " that can be selected for various hinting modes."
1394 "<p><i>strong</i> (checkbox set):"
1395 " Position horizontal stems and snap stem widths"
1396 " to integer pixel values. While making the output look crisper,"
1397 " outlines become more distorted.</p>"
1399 "<p><i>smooth</i> (checkbox not set):"
1400 " Use discrete values for horizontal stems and stem widths."
1401 " This only slightly increases the contrast"
1402 " but avoids larger outline distortion.</p>"));
1404 gray_box
= new QCheckBox(tr("Grayscale"), this);
1405 gray_box
->setToolTip(
1406 tr("<b></b>Grayscale rendering, no ClearType activated."));
1407 stem_label
->setBuddy(gray_box
);
1409 gdi_box
= new QCheckBox(tr("GDI ClearType"), this);
1410 gdi_box
->setToolTip(
1411 tr("GDI ClearType rendering,"
1412 " introduced in 2000 for Windows XP.<br>"
1413 "The rasterizer version (as returned by the"
1414 " GETINFO bytecode instruction) is in the range"
1415 " 36 ≤ version < 38, and ClearType is enabled.<br>"
1416 "Along the vertical axis, this mode behaves like B/W rendering."));
1418 dw_box
= new QCheckBox(tr("DW ClearType"), this);
1420 tr("DirectWrite ClearType rendering,"
1421 " introduced in 2008 for Windows Vista.<br>"
1422 "The rasterizer version (as returned by the"
1423 " GETINFO bytecode instruction) is ≥ 38,"
1424 " ClearType is enabled, and subpixel positioning is enabled also.<br>"
1425 "Smooth rendering along the vertical axis."));
1430 watch_box
= new QCheckBox(tr("&Watch Input Files"), this);
1431 watch_box
->setToolTip(
1432 tr("If switched on, <b>TTFautohint</b> automatically re-runs"
1433 " the hinting process as soon as an input file"
1434 " (either the font or the delta exceptions file) is modified.<br>"
1435 "Pressing the %1 button starts watching.<br>"
1436 "If an error occurs, watching stops and must be restarted"
1437 " with the %1 button.")
1438 .arg(QUOTE_STRING_LITERAL(tr("Run"))));
1440 run_button
= new QPushButton(" "
1442 + " "); // make label wider
1444 if (horizontal_layout
)
1445 create_horizontal_layout();
1447 create_vertical_layout();
1451 // XXX distances are specified in pixels,
1452 // making the layout dependent on the output device resolution
1454 Main_GUI::create_vertical_layout()
1457 QGridLayout
* file_layout
= new QGridLayout
;
1459 file_layout
->addWidget(input_label
, 0, 0, Qt::AlignRight
);
1460 file_layout
->addWidget(input_line
, 0, 1);
1461 file_layout
->addWidget(input_button
, 0, 2);
1463 file_layout
->setRowStretch(1, 1);
1465 file_layout
->addWidget(output_label
, 2, 0, Qt::AlignRight
);
1466 file_layout
->addWidget(output_line
, 2, 1);
1467 file_layout
->addWidget(output_button
, 2, 2);
1469 file_layout
->setRowStretch(3, 1);
1471 file_layout
->addWidget(deltas_label
, 4, 0, Qt::AlignRight
);
1472 file_layout
->addWidget(deltas_line
, 4, 1);
1473 file_layout
->addWidget(deltas_button
, 4, 2);
1476 QGridLayout
* run_layout
= new QGridLayout
;
1478 run_layout
->addWidget(watch_box
, 0, 1);
1479 run_layout
->addWidget(run_button
, 0, 3, Qt::AlignRight
);
1480 run_layout
->setColumnStretch(0, 1);
1481 run_layout
->setColumnStretch(2, 2);
1486 QGridLayout
* gui_layout
= new QGridLayout
;
1487 QFrame
* hline
= new QFrame
;
1488 hline
->setFrameShape(QFrame::HLine
);
1489 int row
= 0; // this counter simplifies inserting new items
1491 gui_layout
->setRowMinimumHeight(row
, 10); // XXX urgh, pixels...
1492 gui_layout
->setRowStretch(row
++, 1);
1494 gui_layout
->addLayout(file_layout
, row
, 0, row
, -1);
1495 gui_layout
->setRowStretch(row
++, 1);
1497 gui_layout
->addWidget(hline
, row
, 0, row
, -1);
1498 gui_layout
->setRowStretch(row
++, 1);
1500 gui_layout
->setRowMinimumHeight(row
, 20); // XXX urgh, pixels...
1501 gui_layout
->setRowStretch(row
++, 1);
1503 gui_layout
->addWidget(min_label
, row
, 0, Qt::AlignRight
);
1504 gui_layout
->addWidget(min_box
, row
++, 1, Qt::AlignLeft
);
1505 gui_layout
->addWidget(max_label
, row
, 0, Qt::AlignRight
);
1506 gui_layout
->addWidget(max_box
, row
++, 1, Qt::AlignLeft
);
1508 gui_layout
->setRowMinimumHeight(row
, 20); // XXX urgh, pixels...
1509 gui_layout
->setRowStretch(row
++, 1);
1511 gui_layout
->addWidget(default_label
, row
, 0, Qt::AlignRight
);
1512 gui_layout
->addWidget(default_box
, row
++, 1, Qt::AlignLeft
);
1513 gui_layout
->addWidget(fallback_label
, row
, 0, Qt::AlignRight
);
1514 gui_layout
->addWidget(fallback_box
, row
++, 1, Qt::AlignLeft
);
1516 gui_layout
->setRowMinimumHeight(row
, 20); // XXX urgh, pixels...
1517 gui_layout
->setRowStretch(row
++, 1);
1519 gui_layout
->addWidget(limit_label
, row
, 0, Qt::AlignRight
);
1520 gui_layout
->addWidget(limit_box
, row
++, 1, Qt::AlignLeft
);
1521 gui_layout
->addWidget(no_limit_box
, row
++, 1);
1523 gui_layout
->addWidget(increase_label
, row
, 0, Qt::AlignRight
);
1524 gui_layout
->addWidget(increase_box
, row
++, 1, Qt::AlignLeft
);
1525 gui_layout
->addWidget(no_increase_box
, row
++, 1);
1527 gui_layout
->addWidget(snapping_label
, row
, 0, Qt::AlignRight
);
1528 gui_layout
->addWidget(snapping_line
, row
++, 1, Qt::AlignLeft
);
1530 gui_layout
->addWidget(stem_width_label
, row
, 0, Qt::AlignRight
);
1531 gui_layout
->addWidget(stem_width_box
, row
++, 1, Qt::AlignLeft
);
1532 gui_layout
->addWidget(default_stem_width_box
, row
++, 1);
1534 gui_layout
->setRowMinimumHeight(row
, 20); // XXX urgh, pixels...
1535 gui_layout
->setRowStretch(row
++, 1);
1537 gui_layout
->addWidget(wincomp_box
, row
++, 1);
1538 gui_layout
->addWidget(adjust_box
, row
++, 1);
1539 gui_layout
->addWidget(hint_box
, row
++, 1);
1540 gui_layout
->addWidget(symbol_box
, row
++, 1);
1541 gui_layout
->addWidget(dehint_box
, row
++, 1);
1542 gui_layout
->addWidget(info_box
, row
++, 1);
1544 gui_layout
->setRowMinimumHeight(row
, 20); // XXX urgh, pixels...
1545 gui_layout
->setRowStretch(row
++, 1);
1547 gui_layout
->addWidget(stem_label
, row
, 0, Qt::AlignRight
);
1548 gui_layout
->addWidget(gray_box
, row
++, 1);
1549 gui_layout
->addWidget(gdi_box
, row
++, 1);
1550 gui_layout
->addWidget(dw_box
, row
++, 1);
1552 gui_layout
->setRowMinimumHeight(row
, 30); // XXX urgh, pixels...
1553 gui_layout
->setRowStretch(row
++, 1);
1555 gui_layout
->addLayout(run_layout
, row
, 0, row
, -1);
1557 // create dummy widget to register layout
1558 QWidget
* main_widget
= new QWidget
;
1559 main_widget
->setLayout(gui_layout
);
1560 setCentralWidget(main_widget
);
1561 setWindowTitle("TTFautohint");
1565 // XXX distances are specified in pixels,
1566 // making the layout dependent on the output device resolution
1568 Main_GUI::create_horizontal_layout()
1571 QGridLayout
* file_layout
= new QGridLayout
;
1573 file_layout
->addWidget(input_label
, 0, 0, Qt::AlignRight
);
1574 file_layout
->addWidget(input_line
, 0, 1);
1575 file_layout
->addWidget(input_button
, 0, 2);
1577 file_layout
->setRowStretch(1, 1);
1579 file_layout
->addWidget(output_label
, 2, 0, Qt::AlignRight
);
1580 file_layout
->addWidget(output_line
, 2, 1);
1581 file_layout
->addWidget(output_button
, 2, 2);
1583 file_layout
->setRowStretch(3, 1);
1585 file_layout
->addWidget(deltas_label
, 4, 0, Qt::AlignRight
);
1586 file_layout
->addWidget(deltas_line
, 4, 1);
1587 file_layout
->addWidget(deltas_button
, 4, 2);
1590 QGridLayout
* run_layout
= new QGridLayout
;
1592 run_layout
->addWidget(watch_box
, 0, 1);
1593 run_layout
->addWidget(run_button
, 0, 3, Qt::AlignRight
);
1594 run_layout
->setColumnStretch(0, 2);
1595 run_layout
->setColumnStretch(2, 3);
1596 run_layout
->setColumnStretch(4, 1);
1601 QGridLayout
* gui_layout
= new QGridLayout
;
1602 QFrame
* hline
= new QFrame
;
1603 hline
->setFrameShape(QFrame::HLine
);
1604 int row
= 0; // this counter simplifies inserting new items
1607 gui_layout
->setColumnMinimumWidth(0, 10); // XXX urgh, pixels...
1608 gui_layout
->setColumnStretch(0, 1);
1611 gui_layout
->setRowMinimumHeight(row
, 10); // XXX urgh, pixels...
1612 gui_layout
->setRowStretch(row
++, 1);
1614 gui_layout
->addLayout(file_layout
, row
, 0, row
, -1);
1615 gui_layout
->setRowStretch(row
++, 1);
1617 gui_layout
->addWidget(hline
, row
, 0, row
, -1);
1618 gui_layout
->setRowStretch(row
++, 1);
1620 gui_layout
->setRowMinimumHeight(row
, 20); // XXX urgh, pixels...
1621 gui_layout
->setRowStretch(row
++, 1);
1623 gui_layout
->addWidget(min_label
, row
, 1, Qt::AlignRight
);
1624 gui_layout
->addWidget(min_box
, row
++, 2, Qt::AlignLeft
);
1625 gui_layout
->addWidget(max_label
, row
, 1, Qt::AlignRight
);
1626 gui_layout
->addWidget(max_box
, row
++, 2, Qt::AlignLeft
);
1628 gui_layout
->setRowMinimumHeight(row
, 20); // XXX urgh, pixels...
1629 gui_layout
->setRowStretch(row
++, 1);
1631 gui_layout
->addWidget(default_label
, row
, 1, Qt::AlignRight
);
1632 gui_layout
->addWidget(default_box
, row
++, 2, Qt::AlignLeft
);
1633 gui_layout
->addWidget(fallback_label
, row
, 1, Qt::AlignRight
);
1634 gui_layout
->addWidget(fallback_box
, row
++, 2, Qt::AlignLeft
);
1636 gui_layout
->setRowMinimumHeight(row
, 20); // XXX urgh, pixels...
1637 gui_layout
->setRowStretch(row
++, 1);
1639 gui_layout
->addWidget(limit_label
, row
, 1, Qt::AlignRight
);
1640 gui_layout
->addWidget(limit_box
, row
++, 2, Qt::AlignLeft
);
1641 gui_layout
->addWidget(no_limit_box
, row
++, 2);
1643 gui_layout
->addWidget(increase_label
, row
, 1, Qt::AlignRight
);
1644 gui_layout
->addWidget(increase_box
, row
++, 2, Qt::AlignLeft
);
1645 gui_layout
->addWidget(no_increase_box
, row
++, 2);
1647 gui_layout
->addWidget(snapping_label
, row
, 1, Qt::AlignRight
);
1648 gui_layout
->addWidget(snapping_line
, row
++, 2, Qt::AlignLeft
);
1650 gui_layout
->addWidget(stem_width_label
, row
, 1, Qt::AlignRight
);
1651 gui_layout
->addWidget(stem_width_box
, row
++, 2, Qt::AlignLeft
);
1652 gui_layout
->addWidget(default_stem_width_box
, row
++, 2);
1654 gui_layout
->setRowMinimumHeight(row
, 30); // XXX urgh, pixels...
1655 gui_layout
->setRowStretch(row
++, 1);
1657 gui_layout
->addLayout(run_layout
, row
, 0, row
, -1);
1660 gui_layout
->setColumnMinimumWidth(3, 20); // XXX urgh, pixels...
1661 gui_layout
->setColumnStretch(3, 1);
1665 gui_layout
->addWidget(wincomp_box
, row
++, 4);
1666 gui_layout
->addWidget(adjust_box
, row
++, 4);
1667 gui_layout
->addWidget(hint_box
, row
++, 4);
1668 gui_layout
->addWidget(symbol_box
, row
++, 4);
1669 gui_layout
->addWidget(dehint_box
, row
++, 4);
1670 gui_layout
->addWidget(info_box
, row
++, 4);
1672 gui_layout
->setRowMinimumHeight(row
, 20); // XXX urgh, pixels...
1673 gui_layout
->setRowStretch(row
++, 1);
1675 gui_layout
->addWidget(stem_label
, row
++, 4);
1677 QGridLayout
* stem_layout
= new QGridLayout
;
1678 stem_layout
->setColumnMinimumWidth(0, 20); // XXX urgh, pixels...
1679 stem_layout
->addWidget(gray_box
, 0, 1);
1680 stem_layout
->addWidget(gdi_box
, 1, 1);
1681 stem_layout
->addWidget(dw_box
, 2, 1);
1683 gui_layout
->addLayout(stem_layout
, row
, 4, 3, 1);
1687 gui_layout
->setColumnMinimumWidth(5, 10); // XXX urgh, pixels...
1688 gui_layout
->setColumnStretch(5, 1);
1690 // create dummy widget to register layout
1691 QWidget
* main_widget
= new QWidget
;
1692 main_widget
->setLayout(gui_layout
);
1693 setCentralWidget(main_widget
);
1694 setWindowTitle("TTFautohint");
1699 Main_GUI::create_connections()
1701 connect(input_button
, SIGNAL(clicked()), this,
1702 SLOT(browse_input()));
1703 connect(output_button
, SIGNAL(clicked()), this,
1704 SLOT(browse_output()));
1705 connect(deltas_button
, SIGNAL(clicked()), this,
1706 SLOT(browse_deltas()));
1708 connect(input_line
, SIGNAL(textChanged(QString
)), this,
1710 connect(output_line
, SIGNAL(textChanged(QString
)), this,
1713 connect(input_line
, SIGNAL(editingFinished()), this,
1714 SLOT(absolute_input()));
1715 connect(output_line
, SIGNAL(editingFinished()), this,
1716 SLOT(absolute_output()));
1717 connect(deltas_line
, SIGNAL(editingFinished()), this,
1718 SLOT(absolute_deltas()));
1720 connect(min_box
, SIGNAL(valueChanged(int)), this,
1722 connect(max_box
, SIGNAL(valueChanged(int)), this,
1725 connect(limit_box
, SIGNAL(valueChanged(int)), this,
1726 SLOT(check_limit()));
1727 connect(no_limit_box
, SIGNAL(clicked()), this,
1728 SLOT(check_no_limit()));
1730 connect(no_increase_box
, SIGNAL(clicked()), this,
1731 SLOT(check_no_increase()));
1733 connect(snapping_line
, SIGNAL(editingFinished()), this,
1734 SLOT(check_number_set()));
1735 connect(snapping_line
, SIGNAL(textEdited(QString
)), this,
1736 SLOT(clear_status_bar()));
1738 connect(default_stem_width_box
, SIGNAL(clicked()), this,
1739 SLOT(check_default_stem_width()));
1741 connect(dehint_box
, SIGNAL(clicked()), this,
1742 SLOT(check_dehint()));
1744 connect(timer
, SIGNAL(timeout()), this,
1745 SLOT(watch_files()));
1747 connect(watch_box
, SIGNAL(clicked()), this,
1748 SLOT(check_watch()));
1750 connect(run_button
, SIGNAL(clicked()), this,
1756 Main_GUI::create_actions()
1758 exit_act
= new QAction(tr("E&xit"), this);
1759 exit_act
->setShortcuts(QKeySequence::Quit
);
1760 connect(exit_act
, SIGNAL(triggered()), this, SLOT(close()));
1762 about_act
= new QAction(tr("&About"), this);
1763 connect(about_act
, SIGNAL(triggered()), this, SLOT(about()));
1765 about_Qt_act
= new QAction(tr("About &Qt"), this);
1766 connect(about_Qt_act
, SIGNAL(triggered()), qApp
, SLOT(aboutQt()));
1771 Main_GUI::create_menus()
1773 file_menu
= menuBar()->addMenu(tr("&File"));
1774 file_menu
->addAction(exit_act
);
1776 help_menu
= menuBar()->addMenu(tr("&Help"));
1777 help_menu
->addAction(about_act
);
1778 help_menu
->addAction(about_Qt_act
);
1783 Main_GUI::create_status_bar()
1785 statusBar()->showMessage("");
1790 Main_GUI::set_defaults()
1792 min_box
->setValue(hinting_range_min
);
1793 max_box
->setValue(hinting_range_max
);
1795 default_box
->setCurrentIndex(default_script_idx
);
1796 fallback_box
->setCurrentIndex(fallback_script_idx
);
1798 limit_box
->setValue(hinting_limit
? hinting_limit
: hinting_range_max
);
1799 // handle command line option `--hinting-limit=0'
1802 hinting_limit
= max_box
->value();
1803 no_limit_box
->setChecked(true);
1806 increase_box
->setValue(increase_x_height
? increase_x_height
1807 : TA_INCREASE_X_HEIGHT
);
1808 // handle command line option `--increase-x-height=0'
1809 if (!increase_x_height
)
1811 increase_x_height
= TA_INCREASE_X_HEIGHT
;
1812 no_increase_box
->setChecked(true);
1815 snapping_line
->setText(x_height_snapping_exceptions_string
);
1817 if (fallback_stem_width
)
1818 stem_width_box
->setValue(fallback_stem_width
);
1821 stem_width_box
->setValue(50);
1822 default_stem_width_box
->setChecked(true);
1825 if (windows_compatibility
)
1826 wincomp_box
->setChecked(true);
1827 if (adjust_subglyphs
)
1828 adjust_box
->setChecked(true);
1829 if (hint_composites
)
1830 hint_box
->setChecked(true);
1832 symbol_box
->setChecked(true);
1834 dehint_box
->setChecked(true);
1836 info_box
->setChecked(true);
1838 if (gray_strong_stem_width
)
1839 gray_box
->setChecked(true);
1840 if (gdi_cleartype_strong_stem_width
)
1841 gdi_box
->setChecked(true);
1842 if (dw_cleartype_strong_stem_width
)
1843 dw_box
->setChecked(true);
1845 run_button
->setEnabled(false);
1852 check_no_increase();
1855 // do this last since it disables almost everything
1861 Main_GUI::read_settings()
1864 // QPoint pos = settings.value("pos", QPoint(200, 200)).toPoint();
1865 // QSize size = settings.value("size", QSize(400, 400)).toSize();
1872 Main_GUI::write_settings()
1875 // settings.setValue("pos", pos());
1876 // settings.setValue("size", size());
1879 // end of maingui.cpp