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: Delta &Exception File
71 // g: Stron&g Stem Width and Positioning
74 // j: Ad&just Subglyphs
75 // b: 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 Comp&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
,
108 const char* fallback
,
112 : hinting_range_min(range_min
),
113 hinting_range_max(range_max
),
114 hinting_limit(limit
),
115 gray_strong_stem_width(gray
),
116 gdi_cleartype_strong_stem_width(gdi
),
117 dw_cleartype_strong_stem_width(dw
),
118 increase_x_height(increase
),
119 x_height_snapping_exceptions_string(exceptions
),
120 fallback_stem_width(stem_width
),
121 ignore_restrictions(ignore
),
122 windows_compatibility(wincomp
),
123 adjust_subglyphs(adjust
),
124 hint_composites(composites
),
132 // map default script tag to an index,
133 // replacing an invalid one with the default value
134 int latn_script_idx
= 0;
135 for (i
= 0; script_names
[i
].tag
; i
++)
137 if (!strcmp("latn", script_names
[i
].tag
))
139 if (!strcmp(dflt
, script_names
[i
].tag
))
142 default_script_idx
= script_names
[i
].tag
? i
: latn_script_idx
;
144 // map fallback script tag to an index,
145 // replacing an invalid one with the default value
146 int none_script_idx
= 0;
147 for (i
= 0; script_names
[i
].tag
; i
++)
149 if (!strcmp("none", script_names
[i
].tag
))
151 if (!strcmp(fallback
, script_names
[i
].tag
))
154 fallback_script_idx
= script_names
[i
].tag
? i
: none_script_idx
;
156 x_height_snapping_exceptions
= NULL
;
158 // if file watching is active, we regularly poll the file status
159 timer
= new QTimer(this);
160 timer
->setInterval(1000);
161 fileinfo_input_file
.setCaching(false);
162 fileinfo_deltas_file
.setCaching(false);
164 // XXX register translations somewhere and loop over them
165 if (QLocale::system().name() == "en_US")
166 locale
= new QLocale
;
168 locale
= new QLocale(QLocale::C
);
170 // For real numbers (both parsing and displaying) we only use `.' as the
171 // decimal separator; similarly, we don't want localized formats like a
172 // thousands separator for any number.
173 setlocale(LC_NUMERIC
, "C");
175 create_layout(horizontal_layout
);
176 create_connections();
184 setUnifiedTitleAndToolBarOnMac(true);
188 Main_GUI::~Main_GUI()
190 number_set_free(x_height_snapping_exceptions
);
197 Main_GUI::closeEvent(QCloseEvent
* event
)
207 QMessageBox::about(this,
208 tr("About TTFautohint"),
209 tr("<p>This is <b>TTFautohint</b> version %1<br>"
210 " Copyright %2 2011-2014<br>"
211 " by Werner Lemberg <tt><wl@gnu.org></tt></p>"
213 "<p><b>TTFautohint</b> adds new auto-generated hints"
214 " to a TrueType font or TrueType collection.</p>"
217 " <a href='http://git.savannah.gnu.org/cgit/freetype/freetype2.git/tree/docs/FTL.TXT'>FreeType"
218 " License (FTL)</a> or"
219 " <a href='http://git.savannah.gnu.org/cgit/freetype/freetype2.git/tree/docs/GPLv2.TXT'>GNU"
227 Main_GUI::browse_input()
229 // XXX remember last directory
230 QString file
= QFileDialog::getOpenFileName(
232 tr("Open Input File"),
236 input_line
->setText(QDir::toNativeSeparators(file
));
241 Main_GUI::browse_output()
243 // XXX remember last directory
244 QString file
= QFileDialog::getSaveFileName(
246 tr("Open Output File"),
251 output_line
->setText(QDir::toNativeSeparators(file
));
256 Main_GUI::browse_deltas()
258 // XXX remember last directory
259 QString file
= QFileDialog::getOpenFileName(
261 tr("Open Delta Exceptions File"),
266 deltas_line
->setText(QDir::toNativeSeparators(file
));
271 Main_GUI::check_min()
273 int min
= min_box
->value();
274 int max
= max_box
->value();
275 int limit
= limit_box
->value();
277 max_box
->setValue(min
);
279 limit_box
->setValue(min
);
284 Main_GUI::check_max()
286 int min
= min_box
->value();
287 int max
= max_box
->value();
288 int limit
= limit_box
->value();
290 min_box
->setValue(max
);
292 limit_box
->setValue(max
);
297 Main_GUI::check_limit()
299 int min
= min_box
->value();
300 int max
= max_box
->value();
301 int limit
= limit_box
->value();
303 max_box
->setValue(limit
);
305 min_box
->setValue(limit
);
310 Main_GUI::check_dehint()
312 if (dehint_box
->isChecked())
314 min_label
->setEnabled(false);
315 min_box
->setEnabled(false);
317 max_label
->setEnabled(false);
318 max_box
->setEnabled(false);
320 default_label
->setEnabled(false);
321 default_box
->setEnabled(false);
322 fallback_label
->setEnabled(false);
323 fallback_box
->setEnabled(false);
325 no_limit_box
->setEnabled(false);
326 limit_label
->setEnabled(false);
327 limit_box
->setEnabled(false);
329 no_increase_box
->setEnabled(false);
330 increase_label
->setEnabled(false);
331 increase_box
->setEnabled(false);
333 snapping_label
->setEnabled(false);
334 snapping_line
->setEnabled(false);
336 default_stem_width_box
->setEnabled(false);
337 stem_width_label
->setEnabled(false);
338 stem_width_box
->setEnabled(false);
340 wincomp_box
->setEnabled(false);
341 adjust_box
->setEnabled(false);
342 hint_box
->setEnabled(false);
343 symbol_box
->setEnabled(false);
345 stem_label
->setEnabled(false);
346 gray_box
->setEnabled(false);
347 gdi_box
->setEnabled(false);
348 dw_box
->setEnabled(false);
352 min_label
->setEnabled(true);
353 min_box
->setEnabled(true);
355 max_label
->setEnabled(true);
356 max_box
->setEnabled(true);
358 default_label
->setEnabled(true);
359 default_box
->setEnabled(true);
360 fallback_label
->setEnabled(true);
361 fallback_box
->setEnabled(true);
363 no_limit_box
->setEnabled(true);
366 no_increase_box
->setEnabled(true);
369 snapping_label
->setEnabled(true);
370 snapping_line
->setEnabled(true);
372 default_stem_width_box
->setEnabled(true);
373 check_default_stem_width();
375 wincomp_box
->setEnabled(true);
376 adjust_box
->setEnabled(true);
377 hint_box
->setEnabled(true);
378 symbol_box
->setEnabled(true);
380 stem_label
->setEnabled(true);
381 gray_box
->setEnabled(true);
382 gdi_box
->setEnabled(true);
383 dw_box
->setEnabled(true);
389 Main_GUI::check_no_limit()
391 if (no_limit_box
->isChecked())
393 limit_label
->setEnabled(false);
394 limit_label
->setText(limit_label_text
);
395 limit_box
->setEnabled(false);
396 no_limit_box
->setText(no_limit_box_text_with_key
);
400 limit_label
->setEnabled(true);
401 limit_label
->setText(limit_label_text_with_key
);
402 limit_box
->setEnabled(true);
403 no_limit_box
->setText(no_limit_box_text
);
409 Main_GUI::check_no_increase()
411 if (no_increase_box
->isChecked())
413 increase_label
->setEnabled(false);
414 increase_label
->setText(increase_label_text
);
415 increase_box
->setEnabled(false);
416 no_increase_box
->setText(no_increase_box_text_with_key
);
420 increase_label
->setEnabled(true);
421 increase_label
->setText(increase_label_text_with_key
);
422 increase_box
->setEnabled(true);
423 no_increase_box
->setText(no_increase_box_text
);
429 Main_GUI::check_default_stem_width()
431 if (default_stem_width_box
->isChecked())
433 stem_width_label
->setEnabled(false);
434 stem_width_label
->setText(stem_width_label_text
);
435 stem_width_box
->setEnabled(false);
436 default_stem_width_box
->setText(default_stem_width_box_text_with_key
);
440 stem_width_label
->setEnabled(true);
441 stem_width_label
->setText(stem_width_label_text_with_key
);
442 stem_width_box
->setEnabled(true);
443 default_stem_width_box
->setText(default_stem_width_box_text
);
449 Main_GUI::check_run()
451 if (input_line
->text().isEmpty() || output_line
->text().isEmpty())
452 run_button
->setEnabled(false);
454 run_button
->setEnabled(true);
459 Main_GUI::absolute_input()
461 QString input_name
= QDir::fromNativeSeparators(input_line
->text());
462 if (!input_name
.isEmpty()
463 && QDir::isRelativePath(input_name
))
465 QDir
cur_path(QDir::currentPath() + "/" + input_name
);
466 input_line
->setText(QDir::toNativeSeparators(cur_path
.absolutePath()));
472 Main_GUI::absolute_output()
474 QString output_name
= QDir::fromNativeSeparators(output_line
->text());
475 if (!output_name
.isEmpty()
476 && QDir::isRelativePath(output_name
))
478 QDir
cur_path(QDir::currentPath() + "/" + output_name
);
479 output_line
->setText(QDir::toNativeSeparators(cur_path
.absolutePath()));
485 Main_GUI::absolute_deltas()
487 QString deltas_name
= QDir::fromNativeSeparators(deltas_line
->text());
488 if (!deltas_name
.isEmpty()
489 && QDir::isRelativePath(deltas_name
))
491 QDir
cur_path(QDir::currentPath() + "/" + deltas_name
);
492 deltas_line
->setText(QDir::toNativeSeparators(cur_path
.absolutePath()));
498 Main_GUI::check_number_set()
500 QString text
= snapping_line
->text();
503 // construct ASCII string from arbitrary Unicode data;
504 // the idea is to accept, say, CJK fullwidth digits also
505 for (int i
= 0; i
< text
.size(); i
++)
507 QChar c
= text
.at(i
);
509 int digit
= c
.digitValue();
511 qs
+= QString::number(digit
);
512 else if (c
.isSpace())
514 // U+30FC KATAGANA-HIRAGANA PROLONGED SOUND MARK is assigned
515 // to the `-' key in some Japanese input methods
516 else if (c
.category() == QChar::Punctuation_Dash
517 || c
== QChar(0x30FC))
519 // various Unicode COMMA characters,
520 // including representation forms
521 else if (c
== QChar(',')
522 || c
== QChar(0x055D)
523 || c
== QChar(0x060C)
524 || c
== QChar(0x07F8)
525 || c
== QChar(0x1363)
526 || c
== QChar(0x1802)
527 || c
== QChar(0x1808)
528 || c
== QChar(0x3001)
529 || c
== QChar(0xA4FE)
530 || c
== QChar(0xA60D)
531 || c
== QChar(0xA6F5)
532 || c
== QChar(0xFE10)
533 || c
== QChar(0xFE11)
534 || c
== QChar(0xFE50)
535 || c
== QChar(0xFE51)
536 || c
== QChar(0xFF0C)
537 || c
== QChar(0xFF64))
540 qs
+= c
; // we do error handling below
543 if (x_height_snapping_exceptions
)
544 number_set_free(x_height_snapping_exceptions
);
546 QByteArray str
= qs
.toLocal8Bit();
547 const char* s
= number_set_parse(str
.constData(),
548 &x_height_snapping_exceptions
,
552 statusBar()->setStyleSheet("color: red;");
553 if (x_height_snapping_exceptions
== NUMBERSET_ALLOCATION_ERROR
)
554 statusBar()->showMessage(
555 tr("allocation error"));
556 else if (x_height_snapping_exceptions
== NUMBERSET_INVALID_CHARACTER
)
557 statusBar()->showMessage(
558 tr("invalid character (use digits, dashes, commas, and spaces)"));
559 else if (x_height_snapping_exceptions
== NUMBERSET_OVERFLOW
)
560 statusBar()->showMessage(
562 else if (x_height_snapping_exceptions
== NUMBERSET_INVALID_RANGE
)
563 statusBar()->showMessage(
564 tr("invalid range (minimum is 6, maximum is 32767)"));
565 else if (x_height_snapping_exceptions
== NUMBERSET_OVERLAPPING_RANGES
)
566 statusBar()->showMessage(
567 tr("overlapping ranges"));
568 else if (x_height_snapping_exceptions
== NUMBERSET_NOT_ASCENDING
)
569 statusBar()->showMessage(
570 tr("values und ranges must be specified in ascending order"));
572 snapping_line
->setText(qs
);
573 snapping_line
->setFocus(Qt::OtherFocusReason
);
574 snapping_line
->setCursorPosition(s
- str
.constData());
576 x_height_snapping_exceptions
= NULL
;
580 // normalize if there is no error
581 char* new_str
= number_set_show(x_height_snapping_exceptions
,
583 snapping_line
->setText(new_str
);
590 Main_GUI::clear_status_bar()
592 statusBar()->clearMessage();
593 statusBar()->setStyleSheet("");
598 Main_GUI::check_filenames(const QString
& input_name
,
599 const QString
& output_name
,
600 const QString
& deltas_name
)
602 if (!QFile::exists(input_name
))
604 QMessageBox::warning(
607 tr("The file %1 cannot be found.")
608 .arg(QUOTE_STRING(QDir::toNativeSeparators(input_name
))),
614 if (input_name
== output_name
)
616 QMessageBox::warning(
619 tr("Input and output file names must be different."),
625 // silently overwrite if watching is active
626 if (QFile::exists(output_name
) && !timer
->isActive())
628 int ret
= QMessageBox::warning(
631 tr("The file %1 already exists.\n"
633 .arg(QUOTE_STRING(QDir::toNativeSeparators(output_name
))),
634 QMessageBox::Yes
| QMessageBox::No
,
636 if (ret
== QMessageBox::No
)
640 if (!deltas_name
.isEmpty() && !QFile::exists(deltas_name
))
642 QMessageBox::warning(
645 tr("The file %1 cannot be found.")
646 .arg(QUOTE_STRING(QDir::toNativeSeparators(deltas_name
))),
657 Main_GUI::open_files(const QString
& input_name
,
659 const QString
& output_name
,
661 const QString
& deltas_name
,
664 const int buf_len
= 1024;
667 *in
= fopen(qPrintable(input_name
), "rb");
670 strerror_r(errno
, buf
, buf_len
);
671 QMessageBox::warning(
674 tr("The following error occurred while opening input file %1:\n")
675 .arg(QUOTE_STRING(QDir::toNativeSeparators(input_name
)))
676 + QString::fromLocal8Bit(buf
),
682 *out
= fopen(qPrintable(output_name
), "wb");
685 strerror_r(errno
, buf
, buf_len
);
686 QMessageBox::warning(
689 tr("The following error occurred while opening output file %1:\n")
690 .arg(QUOTE_STRING(QDir::toNativeSeparators(output_name
)))
691 + QString::fromLocal8Bit(buf
),
697 if (!deltas_name
.isEmpty())
699 *deltas
= fopen(qPrintable(deltas_name
), "r");
702 strerror_r(errno
, buf
, buf_len
);
703 QMessageBox::warning(
706 tr("The following error occurred"
707 " while opening delta exceptions file %1:\n")
708 .arg(QUOTE_STRING(QDir::toNativeSeparators(deltas_name
)))
709 + QString::fromLocal8Bit(buf
),
721 Main_GUI::check_watch()
723 if (!watch_box
->isChecked())
725 // the timer gets started in the `run' function
730 Main_GUI::watch_files()
732 if (fileinfo_input_file
.exists()
733 && fileinfo_input_file
.isReadable()
734 && fileinfo_deltas_file
.exists()
735 && fileinfo_deltas_file
.isReadable())
737 QDateTime modified_input
= fileinfo_input_file
.lastModified();
738 QDateTime modified_deltas
= fileinfo_deltas_file
.lastModified();
739 if (modified_input
> datetime_input_file
740 || modified_deltas
> datetime_deltas_file
)
741 run(); // this function sets `datetime_XXX'
744 run(); // let this routine handle all errors
750 struct GUI_Progress_Data
754 QProgressDialog
* dialog
;
759 #define TRDOMAIN "GuiProgress"
762 gui_progress(long curr_idx
,
768 GUI_Progress_Data
* data
= static_cast<GUI_Progress_Data
*>(user
);
770 if (num_sfnts
> 1 && curr_sfnt
!= data
->last_sfnt
)
772 data
->dialog
->setLabelText(Tr("Auto-hinting subfont %1 of %2"
773 " with %3 glyphs...")
778 if (curr_sfnt
+ 1 == num_sfnts
)
780 data
->dialog
->setAutoReset(true);
781 data
->dialog
->setAutoClose(true);
785 data
->dialog
->setAutoReset(false);
786 data
->dialog
->setAutoClose(false);
789 data
->last_sfnt
= curr_sfnt
;
796 data
->dialog
->setLabelText(Tr("Auto-hinting %1 glyphs...")
798 data
->dialog
->setMaximum(num_glyphs
- 1);
803 data
->dialog
->setValue(curr_idx
);
805 if (data
->dialog
->wasCanceled())
812 struct GUI_Error_Data
818 int* ignore_restrictions_p
;
824 #define TRDOMAIN "GuiError"
827 gui_error(TA_Error error
,
828 const char* error_string
,
829 unsigned int errlinenum
,
834 GUI_Error_Data
* data
= static_cast<GUI_Error_Data
*>(user
);
835 QLocale
* locale
= data
->locale
; // for QUOTE_STRING_LITERAL
840 if (error
== TA_Err_Canceled
)
842 else if (error
== TA_Err_Invalid_FreeType_Version
)
843 QMessageBox::critical(
846 Tr("FreeType version 2.4.5 or higher is needed.\n"
847 "Are you perhaps using a wrong FreeType DLL?"),
850 else if (error
== TA_Err_Invalid_Font_Type
)
851 QMessageBox::warning(
854 Tr("This font is not a valid font"
855 " in SFNT format with TrueType outlines.\n"
856 "In particular, CFF outlines are not supported."),
859 else if (error
== TA_Err_Already_Processed
)
860 QMessageBox::warning(
863 Tr("This font has already been processed by TTFautohint."),
866 else if (error
== TA_Err_Missing_Legal_Permission
)
868 int yesno
= QMessageBox::warning(
871 Tr("Bit 1 in the %1 field of the %2 table is set:"
872 " This font must not be modified"
873 " without permission of the legal owner.\n"
874 "Do you have such a permission?")
875 .arg(QUOTE_STRING_LITERAL("fsType"))
876 .arg(QUOTE_STRING_LITERAL("OS/2")),
877 QMessageBox::Yes
| QMessageBox::No
,
879 if (yesno
== QMessageBox::Yes
)
881 *data
->ignore_restrictions_p
= true;
885 else if (error
== TA_Err_Missing_Unicode_CMap
)
886 QMessageBox::warning(
889 Tr("The input font doesn't contain a Unicode character map.\n"
890 "Maybe you haven't set the %1 checkbox?")
891 .arg(QUOTE_STRING_LITERAL(Tr("Symbol Font"))),
894 else if (error
== TA_Err_Missing_Symbol_CMap
)
895 QMessageBox::warning(
898 Tr("The input font does neither contain a symbol"
899 " nor a character map."),
902 else if (error
== TA_Err_Missing_Glyph
)
903 QMessageBox::warning(
906 Tr("No glyph for a standard character"
907 " to derive standard width and height.\n"
908 "Please check the documentation for a list of"
909 " script-specific standard characters.\n"
911 "Set the %1 checkbox if you want to circumvent this test.")
912 .arg(QUOTE_STRING_LITERAL(Tr("Symbol Font"))),
915 else if (error
>= 0x200 && error
< 0x300)
916 QMessageBox::warning(
919 QString::fromLocal8Bit("%1:%2:%3: %4 (0x%5)<br>"
922 .arg(data
->deltas_name
)
924 .arg(int(errpos
- errline
+ 1))
926 .arg(error
, 2, 16, QLatin1Char('0'))
928 .arg('^', int(errpos
- errline
+ 1))
929 .replace(" ", " "),
933 QMessageBox::warning(
936 Tr("Error code 0x%1 while autohinting font:\n")
937 .arg(error
, 2, 16, QLatin1Char('0'))
938 + QString::fromLocal8Bit(error_string
),
942 if (QFile::exists(data
->output_name
)
943 && remove(qPrintable(data
->output_name
)))
945 const int buf_len
= 1024;
948 strerror_r(errno
, buf
, buf_len
);
949 QMessageBox::warning(
952 Tr("The following error occurred while removing output file %1:\n")
953 .arg(QUOTE_STRING(QDir::toNativeSeparators(data
->output_name
)))
954 + QString::fromLocal8Bit(buf
),
966 statusBar()->clearMessage();
968 QString input_name
= QDir::fromNativeSeparators(input_line
->text());
969 QString output_name
= QDir::fromNativeSeparators(output_line
->text());
970 QString deltas_name
= QDir::fromNativeSeparators(deltas_line
->text());
971 if (!check_filenames(input_name
, output_name
, deltas_name
))
977 // we need C file descriptors for communication with TTF_autohint
983 if (!open_files(input_name
, &input
,
984 output_name
, &output
,
985 deltas_name
, &deltas
))
991 QProgressDialog dialog
;
992 dialog
.setCancelButtonText(tr("Cancel"));
993 dialog
.setMinimumDuration(1000);
994 dialog
.setWindowModality(Qt::WindowModal
);
996 TA_Info_Func info_func
= info
;
997 GUI_Progress_Data gui_progress_data
= {-1, true, &dialog
};
998 GUI_Error_Data gui_error_data
= {this, locale
, output_name
, deltas_name
,
999 &ignore_restrictions
, false};
1001 fileinfo_input_file
.setFile(input_name
);
1002 fileinfo_deltas_file
.setFile(deltas_name
);
1004 Info_Data info_data
;
1006 info_data
.data
= NULL
; // must be deallocated after use
1007 info_data
.data_wide
= NULL
; // must be deallocated after use
1008 info_data
.data_len
= 0;
1009 info_data
.data_wide_len
= 0;
1011 info_data
.deltas_name
= qPrintable(fileinfo_deltas_file
.fileName());
1013 info_data
.hinting_range_min
= min_box
->value();
1014 info_data
.hinting_range_max
= max_box
->value();
1015 info_data
.hinting_limit
= no_limit_box
->isChecked()
1017 : limit_box
->value();
1019 info_data
.gray_strong_stem_width
= gray_box
->isChecked();
1020 info_data
.gdi_cleartype_strong_stem_width
= gdi_box
->isChecked();
1021 info_data
.dw_cleartype_strong_stem_width
= dw_box
->isChecked();
1023 info_data
.increase_x_height
= no_increase_box
->isChecked()
1025 : increase_box
->value();
1026 info_data
.x_height_snapping_exceptions_string
=
1027 qPrintable(x_height_snapping_exceptions_string
);
1028 info_data
.fallback_stem_width
= default_stem_width_box
->isChecked()
1030 : stem_width_box
->value();
1032 info_data
.windows_compatibility
= wincomp_box
->isChecked();
1033 info_data
.adjust_subglyphs
= adjust_box
->isChecked();
1034 info_data
.hint_composites
= hint_box
->isChecked();
1035 info_data
.symbol
= symbol_box
->isChecked();
1036 info_data
.dehint
= dehint_box
->isChecked();
1037 info_data
.TTFA_info
= TTFA_box
->isChecked();
1039 strncpy(info_data
.default_script
,
1040 script_names
[default_box
->currentIndex()].tag
,
1041 sizeof (info_data
.default_script
));
1042 strncpy(info_data
.fallback_script
,
1043 script_names
[fallback_box
->currentIndex()].tag
,
1044 sizeof (info_data
.fallback_script
));
1046 if (info_box
->isChecked())
1048 int ret
= build_version_string(&info_data
);
1050 QMessageBox::information(
1053 tr("Can't allocate memory for <b>TTFautohint</b> options string"
1054 " in <i>name</i> table."),
1058 QMessageBox::information(
1061 tr("<b>TTFautohint</b> options string"
1062 " in <i>name</i> table too long."),
1069 if (info_data
.symbol
1070 && info_data
.fallback_stem_width
1071 && !strcmp(info_data
.fallback_script
, "none"))
1072 QMessageBox::information(
1075 tr("Setting a fallback stem width for a symbol font"
1076 " without setting a fallback script has no effect."),
1080 datetime_input_file
= fileinfo_input_file
.lastModified();
1081 datetime_deltas_file
= fileinfo_deltas_file
.lastModified();
1083 QByteArray snapping_string
= snapping_line
->text().toLocal8Bit();
1086 TTF_autohint("in-file, out-file, deltas-file,"
1087 "hinting-range-min, hinting-range-max,"
1089 "gray-strong-stem-width,"
1090 "gdi-cleartype-strong-stem-width,"
1091 "dw-cleartype-strong-stem-width,"
1092 "progress-callback, progress-callback-data,"
1093 "error-callback, error-callback-data,"
1094 "info-callback, info-callback-data,"
1095 "ignore-restrictions,"
1096 "windows-compatibility,"
1099 "increase-x-height,"
1100 "x-height-snapping-exceptions, fallback-stem-width,"
1101 "default-script, fallback-script,"
1102 "symbol, dehint, TTFA-info",
1103 input
, output
, deltas
,
1104 info_data
.hinting_range_min
, info_data
.hinting_range_max
,
1105 info_data
.hinting_limit
,
1106 info_data
.gray_strong_stem_width
,
1107 info_data
.gdi_cleartype_strong_stem_width
,
1108 info_data
.dw_cleartype_strong_stem_width
,
1109 gui_progress
, &gui_progress_data
,
1110 gui_error
, &gui_error_data
,
1111 info_func
, &info_data
,
1112 ignore_restrictions
,
1113 info_data
.windows_compatibility
,
1114 info_data
.adjust_subglyphs
,
1115 info_data
.hint_composites
,
1116 info_data
.increase_x_height
,
1117 snapping_string
.constData(), info_data
.fallback_stem_width
,
1118 info_data
.default_script
, info_data
.fallback_script
,
1119 info_data
.symbol
, info_data
.dehint
, info_data
.TTFA_info
);
1121 if (info_box
->isChecked())
1123 free(info_data
.data
);
1124 free(info_data
.data_wide
);
1134 // retry if there is a user request to do so (handled in `gui_error')
1135 if (gui_error_data
.retry
)
1142 statusBar()->showMessage(tr("Auto-hinting finished")
1144 + QDateTime::currentDateTime()
1145 .toString(Qt::TextDate
)
1148 // we have successfully processed a file;
1149 // start file watching now if requested
1150 if (watch_box
->isChecked())
1156 // XXX distances are specified in pixels,
1157 // making the layout dependent on the output device resolution
1159 Main_GUI::create_layout(bool horizontal_layout
)
1164 QCompleter
* completer
= new QCompleter(this);
1165 QFileSystemModel
* model
= new QFileSystemModel(completer
);
1166 model
->setRootPath(QDir::rootPath());
1167 completer
->setModel(model
);
1169 input_label
= new QLabel(tr("&Input File:"));
1170 input_line
= new Drag_Drop_Line_Edit(DRAG_DROP_TRUETYPE
);
1171 input_button
= new QPushButton(tr("Browse..."));
1172 input_label
->setBuddy(input_line
);
1173 // enforce rich text to get nice word wrapping
1174 input_label
->setToolTip(
1175 tr("<b></b>The input file, either a TrueType font (TTF),"
1176 " TrueType collection (TTC), or a TrueType-based OpenType font."));
1177 input_line
->setCompleter(completer
);
1179 output_label
= new QLabel(tr("&Output File:"));
1180 output_line
= new Drag_Drop_Line_Edit(DRAG_DROP_TRUETYPE
);
1181 output_button
= new QPushButton(tr("Browse..."));
1182 output_label
->setBuddy(output_line
);
1183 output_label
->setToolTip(
1184 tr("<b></b>The output file, which will be essentially identical"
1185 " to the input font but will contain new, generated hints."));
1186 output_line
->setCompleter(completer
);
1188 deltas_label
= new QLabel(tr("Delta &Exception File:"));
1189 deltas_line
= new Drag_Drop_Line_Edit(DRAG_DROP_ANY
);
1190 deltas_button
= new QPushButton(tr("Browse..."));
1191 deltas_label
->setBuddy(deltas_line
);
1192 deltas_label
->setToolTip(
1193 tr("<p>An optional delta exceptions file to fine-tune point positions"
1194 " after hinting, using DELTAP TrueType instructions."
1195 " This text file contains lines of the form<br>"
1197 " [ <i>subfont-idx</i> ]"
1198 " <i>glyph-id</i>"
1199 " <tt>p</tt> <i>points</i>"
1200 " [ <tt>x</tt> <i>shift</i> ]"
1201 " [ <tt>y</tt> <i>shift</i> ]"
1202 " <tt>@</tt> <i>ppems</i><br>"
1204 "<i>subfont-idx</i> gives the subfont index in a TTC,"
1205 " <i>glyph-id</i> is a glyph name or index,"
1206 " the x and y <i>shift</i> values are in the range [-1;1],"
1207 " rounded to multiples of 1/8px,"
1208 " <i>points</i> and <i>ppems</i> are ranges for point indices"
1209 " and ppem values as with x height snapping exceptions.<br>"
1210 "<tt>#</tt> starts a line comment, which gets ignored."
1211 " Empty lines are ignored, too.</p>"
1214 " <tt>Adieresis p 3-6 y 0.25 @ 13</tt>"));
1215 deltas_line
->setCompleter(completer
);
1220 min_label
= new QLabel(tr("Hint Set Range Mi&nimum:"));
1221 min_box
= new QSpinBox
;
1222 min_label
->setBuddy(min_box
);
1223 min_label
->setToolTip(
1224 tr("The minimum PPEM value of the range for which"
1225 " <b>TTFautohint</b> computes <i>hint sets</i>."
1226 " A hint set for a given PPEM value hints this size optimally."
1227 " The larger the range, the more hint sets are considered,"
1228 " usually increasing the size of the bytecode.<br>"
1229 "Note that changing this range doesn't influence"
1230 " the <i>gasp</i> table:"
1231 " Hinting is enabled for all sizes."));
1232 min_box
->setKeyboardTracking(false);
1233 min_box
->setRange(2, 10000);
1235 max_label
= new QLabel(tr("Hint Set Range Ma&ximum:"));
1236 max_box
= new QSpinBox
;
1237 max_label
->setBuddy(max_box
);
1238 max_label
->setToolTip(
1239 tr("The maximum PPEM value of the range for which"
1240 " <b>TTFautohint</b> computes <i>hint sets</i>."
1241 " A hint set for a given PPEM value hints this size optimally."
1242 " The larger the range, the more hint sets are considered,"
1243 " usually increasing the size of the bytecode.<br>"
1244 "Note that changing this range doesn't influence"
1245 " the <i>gasp</i> table:"
1246 " Hinting is enabled for all sizes."));
1247 max_box
->setKeyboardTracking(false);
1248 max_box
->setRange(2, 10000);
1251 // OpenType default script
1253 default_label
= new QLabel(tr("Defa&ult Script:"));
1254 default_box
= new QComboBox
;
1255 default_label
->setBuddy(default_box
);
1256 default_label
->setToolTip(
1257 tr("This sets the default script for OpenType features:"
1258 " After applying all features that are handled specially"
1259 " (for example small caps or superscript glyphs),"
1260 " <b>TTFautohint</b> uses this value for the remaining features."));
1261 for (int i
= 0; script_names
[i
].tag
; i
++)
1263 // XXX: how to provide translations?
1264 default_box
->insertItem(i
,
1266 .arg(script_names
[i
].tag
)
1267 .arg(script_names
[i
].description
));
1271 // hinting and fallback controls
1273 fallback_label
= new QLabel(tr("Fallback &Script:"));
1274 fallback_box
= new QComboBox
;
1275 fallback_label
->setBuddy(fallback_box
);
1276 fallback_label
->setToolTip(
1277 tr("This sets the fallback script for glyphs"
1278 " that <b>TTFautohint</b> can't map to a script automatically."));
1279 for (int i
= 0; script_names
[i
].tag
; i
++)
1281 // XXX: how to provide translations?
1282 fallback_box
->insertItem(i
,
1284 .arg(script_names
[i
].tag
)
1285 .arg(script_names
[i
].description
));
1291 limit_label_text_with_key
= tr("Hinting &Limit:");
1292 limit_label_text
= tr("Hinting Limit:");
1293 limit_label
= new QLabel(limit_label_text_with_key
);
1294 limit_box
= new QSpinBox
;
1295 limit_label
->setBuddy(limit_box
);
1296 limit_label
->setToolTip(
1297 tr("Switch off hinting for PPEM values exceeding this limit."
1298 " Changing this value does not influence the size of the bytecode.<br>"
1299 "Note that <b>TTFautohint</b> handles this feature"
1300 " in the output font's bytecode and not in the <i>gasp</i> table."));
1301 limit_box
->setKeyboardTracking(false);
1302 limit_box
->setRange(2, 10000);
1304 no_limit_box_text_with_key
= tr("No Hinting &Limit");
1305 no_limit_box_text
= tr("No Hinting Limit");
1306 no_limit_box
= new QCheckBox(no_limit_box_text
, this);
1307 no_limit_box
->setToolTip(
1308 tr("If switched on, <b>TTFautohint</b> adds no hinting limit"
1309 " to the bytecode.<br>"
1310 "For testing only."));
1313 // x height increase limit
1315 increase_label_text_with_key
= tr("x Height In&crease Limit:");
1316 increase_label_text
= tr("x Height Increase Limit:");
1317 increase_label
= new QLabel(increase_label_text_with_key
);
1318 increase_box
= new QSpinBox
;
1319 increase_label
->setBuddy(increase_box
);
1320 increase_label
->setToolTip(
1321 tr("For PPEM values in the range 5 < PPEM < <i>n</i>,"
1322 " where <i>n</i> is the value selected by this spin box,"
1323 " round up the font's x height much more often than normally.<br>"
1324 "Use this if holes in letters like <i>e</i> get filled,"
1326 increase_box
->setKeyboardTracking(false);
1327 increase_box
->setRange(6, 10000);
1329 no_increase_box_text_with_key
= tr("No x Height In&crease");
1330 no_increase_box_text
= tr("No x Height Increase");
1331 no_increase_box
= new QCheckBox(no_increase_box_text
, this);
1332 no_increase_box
->setToolTip(
1333 tr("If switched on,"
1334 " <b>TTFautohint</b> does not increase the x height."));
1337 // x height snapping exceptions
1339 snapping_label
= new QLabel(tr("x Height Snapping Excep&tions:"));
1340 snapping_line
= new Tooltip_Line_Edit
;
1341 snapping_label
->setBuddy(snapping_line
);
1342 snapping_label
->setToolTip(
1343 tr("<p>A list of comma separated PPEM values or value ranges"
1344 " at which no x height snapping shall be applied"
1345 " (x height snapping usually slightly increases"
1346 " the size of all glyphs).</p>"
1349 " <tt>2, 3-5, 12-17</tt><br>"
1350 " <tt>-20, 40-</tt>"
1351 " (meaning PPEM ≤ 20 or PPEM ≥ 40)<br>"
1352 " <tt>-</tt> (meaning all possible PPEM values)"));
1355 // fallback stem width
1357 stem_width_label_text_with_key
= tr("Fallbac&k Stem Width:");
1358 stem_width_label_text
= tr("Fallback Stem Width:");
1359 stem_width_label
= new QLabel(stem_width_label_text_with_key
);
1360 stem_width_box
= new QSpinBox
;
1361 stem_width_label
->setBuddy(stem_width_box
);
1362 stem_width_label
->setToolTip(
1363 tr("Set horizontal stem width (in font units) for all scripts"
1364 " that lack proper standard characters in the font.<br>"
1365 "If not set, <b>TTFautohint</b> uses a hard-coded default value."));
1366 stem_width_box
->setKeyboardTracking(false);
1367 stem_width_box
->setRange(1, 10000);
1369 default_stem_width_box_text_with_key
= tr("Default Fallbac&k Stem Width");
1370 default_stem_width_box_text
= tr("Default Fallback Stem Width");
1371 default_stem_width_box
= new QCheckBox(default_stem_width_box_text
, this);
1372 default_stem_width_box
->setToolTip(
1373 tr("If switched on, <b>TTFautohint</b> uses a default value"
1374 " for the fallback stem width (50 font units at 2048 UPEM)."));
1379 wincomp_box
= new QCheckBox(tr("Windows Com&patibility"), this);
1380 wincomp_box
->setToolTip(
1381 tr("If switched on, add two artificial blue zones positioned at the"
1382 " <tt>usWinAscent</tt> and <tt>usWinDescent</tt> values"
1383 " (from the font's <i>OS/2</i> table)."
1384 " This option, usually in combination"
1385 " with value <tt>-</tt> (a single dash)"
1386 " for the <i>x Height Snapping Exceptions</i> option,"
1387 " should be used if those two <i>OS/2</i> values are tight,"
1388 " and you are experiencing clipping during rendering."));
1390 adjust_box
= new QCheckBox(tr("Ad&just Subglyphs"), this);
1391 adjust_box
->setToolTip(
1392 tr("If switched on, the original bytecode of the input font"
1393 " gets applied (at EM size, usually 2048ppem)"
1394 " to derive the glyph outlines for <b>TTFautohint</b>.<br>"
1395 "Use this option only if subglyphs"
1396 " are incorrectly scaled and shifted.<br>"
1397 "Note that the original bytecode will always be discarded."));
1399 hint_box
= new QCheckBox(tr("Hint Co&mposites")
1400 + " ", this); // make label wider
1401 hint_box
->setToolTip(
1402 tr("If switched on, <b>TTFautohint</b> hints composite glyphs"
1403 " as a whole, including subglyphs."
1404 " Otherwise, glyph components get hinted separately.<br>"
1405 "Deactivating this flag reduces the bytecode size enormously,"
1406 " however, it might yield worse results."));
1408 symbol_box
= new QCheckBox(tr("S&ymbol Font"), this);
1409 symbol_box
->setToolTip(
1410 tr("If switched on, <b>TTFautohint</b> accepts fonts"
1411 " that don't contain a single standard character"
1412 " for any of the supported scripts.<br>"
1413 "Use this for symbol or dingbat fonts, for example."));
1415 dehint_box
= new QCheckBox(tr("&Dehint"), this);
1416 dehint_box
->setToolTip(
1417 tr("If set, remove all hints from the font.<br>"
1418 "For testing only."));
1420 info_box
= new QCheckBox(tr("Add ttf&autohint Info"), this);
1421 info_box
->setToolTip(
1422 tr("If switched on, information about <b>TTFautohint</b>"
1423 " and its calling parameters are added to the version string(s)"
1424 " (name ID 5) in the <i>name</i> table."));
1426 TTFA_box
= new QCheckBox(tr("Add TTFA Info Ta&ble"), this);
1427 TTFA_box
->setToolTip(
1428 tr("If switched on, an SFNT table called <tt>TTFA</tt>"
1429 " gets added to the output font,"
1430 " holding a dump of all parameters."
1431 " In particular, it lists all delta exceptions."));
1434 // stem width and positioning
1436 stem_label
= new QLabel(tr("Stron&g Stem Width and Positioning:"));
1437 stem_label
->setToolTip(
1438 tr("<b>TTFautohint</b> provides two different hinting algorithms"
1439 " that can be selected for various hinting modes."
1441 "<p><i>strong</i> (checkbox set):"
1442 " Position horizontal stems and snap stem widths"
1443 " to integer pixel values. While making the output look crisper,"
1444 " outlines become more distorted.</p>"
1446 "<p><i>smooth</i> (checkbox not set):"
1447 " Use discrete values for horizontal stems and stem widths."
1448 " This only slightly increases the contrast"
1449 " but avoids larger outline distortion.</p>"));
1451 gray_box
= new QCheckBox(tr("Grayscale"), this);
1452 gray_box
->setToolTip(
1453 tr("<b></b>Grayscale rendering, no ClearType activated."));
1454 stem_label
->setBuddy(gray_box
);
1456 gdi_box
= new QCheckBox(tr("GDI ClearType"), this);
1457 gdi_box
->setToolTip(
1458 tr("GDI ClearType rendering,"
1459 " introduced in 2000 for Windows XP.<br>"
1460 "The rasterizer version (as returned by the"
1461 " GETINFO bytecode instruction) is in the range"
1462 " 36 ≤ version < 38, and ClearType is enabled.<br>"
1463 "Along the vertical axis, this mode behaves like B/W rendering."));
1465 dw_box
= new QCheckBox(tr("DW ClearType"), this);
1467 tr("DirectWrite ClearType rendering,"
1468 " introduced in 2008 for Windows Vista.<br>"
1469 "The rasterizer version (as returned by the"
1470 " GETINFO bytecode instruction) is ≥ 38,"
1471 " ClearType is enabled, and subpixel positioning is enabled also.<br>"
1472 "Smooth rendering along the vertical axis."));
1477 watch_box
= new QCheckBox(tr("&Watch Input Files"), this);
1478 watch_box
->setToolTip(
1479 tr("If switched on, <b>TTFautohint</b> automatically re-runs"
1480 " the hinting process as soon as an input file"
1481 " (either the font or the delta exceptions file) is modified.<br>"
1482 "Pressing the %1 button starts watching.<br>"
1483 "If an error occurs, watching stops and must be restarted"
1484 " with the %1 button.")
1485 .arg(QUOTE_STRING_LITERAL(tr("Run"))));
1487 run_button
= new QPushButton(" "
1489 + " "); // make label wider
1491 if (horizontal_layout
)
1492 create_horizontal_layout();
1494 create_vertical_layout();
1498 // XXX distances are specified in pixels,
1499 // making the layout dependent on the output device resolution
1501 Main_GUI::create_vertical_layout()
1504 QGridLayout
* file_layout
= new QGridLayout
;
1506 file_layout
->addWidget(input_label
, 0, 0, Qt::AlignRight
);
1507 file_layout
->addWidget(input_line
, 0, 1);
1508 file_layout
->addWidget(input_button
, 0, 2);
1510 file_layout
->setRowStretch(1, 1);
1512 file_layout
->addWidget(output_label
, 2, 0, Qt::AlignRight
);
1513 file_layout
->addWidget(output_line
, 2, 1);
1514 file_layout
->addWidget(output_button
, 2, 2);
1516 file_layout
->setRowStretch(3, 1);
1518 file_layout
->addWidget(deltas_label
, 4, 0, Qt::AlignRight
);
1519 file_layout
->addWidget(deltas_line
, 4, 1);
1520 file_layout
->addWidget(deltas_button
, 4, 2);
1523 QGridLayout
* run_layout
= new QGridLayout
;
1525 run_layout
->addWidget(watch_box
, 0, 1);
1526 run_layout
->addWidget(run_button
, 0, 3, Qt::AlignRight
);
1527 run_layout
->setColumnStretch(0, 1);
1528 run_layout
->setColumnStretch(2, 2);
1533 QGridLayout
* gui_layout
= new QGridLayout
;
1534 QFrame
* hline
= new QFrame
;
1535 hline
->setFrameShape(QFrame::HLine
);
1536 int row
= 0; // this counter simplifies inserting new items
1538 gui_layout
->setRowMinimumHeight(row
, 10); // XXX urgh, pixels...
1539 gui_layout
->setRowStretch(row
++, 1);
1541 gui_layout
->addLayout(file_layout
, row
, 0, row
, -1);
1542 gui_layout
->setRowStretch(row
++, 1);
1544 gui_layout
->addWidget(hline
, row
, 0, row
, -1);
1545 gui_layout
->setRowStretch(row
++, 1);
1547 gui_layout
->setRowMinimumHeight(row
, 20); // XXX urgh, pixels...
1548 gui_layout
->setRowStretch(row
++, 1);
1550 gui_layout
->addWidget(min_label
, row
, 0, Qt::AlignRight
);
1551 gui_layout
->addWidget(min_box
, row
++, 1, Qt::AlignLeft
);
1552 gui_layout
->addWidget(max_label
, row
, 0, Qt::AlignRight
);
1553 gui_layout
->addWidget(max_box
, row
++, 1, Qt::AlignLeft
);
1555 gui_layout
->setRowMinimumHeight(row
, 20); // XXX urgh, pixels...
1556 gui_layout
->setRowStretch(row
++, 1);
1558 gui_layout
->addWidget(default_label
, row
, 0, Qt::AlignRight
);
1559 gui_layout
->addWidget(default_box
, row
++, 1, Qt::AlignLeft
);
1560 gui_layout
->addWidget(fallback_label
, row
, 0, Qt::AlignRight
);
1561 gui_layout
->addWidget(fallback_box
, row
++, 1, Qt::AlignLeft
);
1563 gui_layout
->setRowMinimumHeight(row
, 20); // XXX urgh, pixels...
1564 gui_layout
->setRowStretch(row
++, 1);
1566 gui_layout
->addWidget(limit_label
, row
, 0, Qt::AlignRight
);
1567 gui_layout
->addWidget(limit_box
, row
++, 1, Qt::AlignLeft
);
1568 gui_layout
->addWidget(no_limit_box
, row
++, 1);
1570 gui_layout
->addWidget(increase_label
, row
, 0, Qt::AlignRight
);
1571 gui_layout
->addWidget(increase_box
, row
++, 1, Qt::AlignLeft
);
1572 gui_layout
->addWidget(no_increase_box
, row
++, 1);
1574 gui_layout
->addWidget(snapping_label
, row
, 0, Qt::AlignRight
);
1575 gui_layout
->addWidget(snapping_line
, row
++, 1, Qt::AlignLeft
);
1577 gui_layout
->addWidget(stem_width_label
, row
, 0, Qt::AlignRight
);
1578 gui_layout
->addWidget(stem_width_box
, row
++, 1, Qt::AlignLeft
);
1579 gui_layout
->addWidget(default_stem_width_box
, row
++, 1);
1581 gui_layout
->setRowMinimumHeight(row
, 20); // XXX urgh, pixels...
1582 gui_layout
->setRowStretch(row
++, 1);
1584 gui_layout
->addWidget(wincomp_box
, row
++, 1);
1585 gui_layout
->addWidget(adjust_box
, row
++, 1);
1586 gui_layout
->addWidget(hint_box
, row
++, 1);
1587 gui_layout
->addWidget(symbol_box
, row
++, 1);
1588 gui_layout
->addWidget(dehint_box
, row
++, 1);
1589 gui_layout
->addWidget(info_box
, row
++, 1);
1590 gui_layout
->addWidget(TTFA_box
, row
++, 1);
1592 gui_layout
->setRowMinimumHeight(row
, 20); // XXX urgh, pixels...
1593 gui_layout
->setRowStretch(row
++, 1);
1595 gui_layout
->addWidget(stem_label
, row
, 0, Qt::AlignRight
);
1596 gui_layout
->addWidget(gray_box
, row
++, 1);
1597 gui_layout
->addWidget(gdi_box
, row
++, 1);
1598 gui_layout
->addWidget(dw_box
, row
++, 1);
1600 gui_layout
->setRowMinimumHeight(row
, 30); // XXX urgh, pixels...
1601 gui_layout
->setRowStretch(row
++, 1);
1603 gui_layout
->addLayout(run_layout
, row
, 0, row
, -1);
1605 // create dummy widget to register layout
1606 QWidget
* main_widget
= new QWidget
;
1607 main_widget
->setLayout(gui_layout
);
1608 setCentralWidget(main_widget
);
1609 setWindowTitle("TTFautohint");
1613 // XXX distances are specified in pixels,
1614 // making the layout dependent on the output device resolution
1616 Main_GUI::create_horizontal_layout()
1619 QGridLayout
* file_layout
= new QGridLayout
;
1621 file_layout
->addWidget(input_label
, 0, 0, Qt::AlignRight
);
1622 file_layout
->addWidget(input_line
, 0, 1);
1623 file_layout
->addWidget(input_button
, 0, 2);
1625 file_layout
->setRowStretch(1, 1);
1627 file_layout
->addWidget(output_label
, 2, 0, Qt::AlignRight
);
1628 file_layout
->addWidget(output_line
, 2, 1);
1629 file_layout
->addWidget(output_button
, 2, 2);
1631 file_layout
->setRowStretch(3, 1);
1633 file_layout
->addWidget(deltas_label
, 4, 0, Qt::AlignRight
);
1634 file_layout
->addWidget(deltas_line
, 4, 1);
1635 file_layout
->addWidget(deltas_button
, 4, 2);
1638 QGridLayout
* run_layout
= new QGridLayout
;
1640 run_layout
->addWidget(watch_box
, 0, 1);
1641 run_layout
->addWidget(run_button
, 0, 3, Qt::AlignRight
);
1642 run_layout
->setColumnStretch(0, 2);
1643 run_layout
->setColumnStretch(2, 3);
1644 run_layout
->setColumnStretch(4, 1);
1649 QGridLayout
* gui_layout
= new QGridLayout
;
1650 QFrame
* hline
= new QFrame
;
1651 hline
->setFrameShape(QFrame::HLine
);
1652 int row
= 0; // this counter simplifies inserting new items
1655 gui_layout
->setColumnMinimumWidth(0, 10); // XXX urgh, pixels...
1656 gui_layout
->setColumnStretch(0, 1);
1659 gui_layout
->setRowMinimumHeight(row
, 10); // XXX urgh, pixels...
1660 gui_layout
->setRowStretch(row
++, 1);
1662 gui_layout
->addLayout(file_layout
, row
, 0, row
, -1);
1663 gui_layout
->setRowStretch(row
++, 1);
1665 gui_layout
->addWidget(hline
, row
, 0, row
, -1);
1666 gui_layout
->setRowStretch(row
++, 1);
1668 gui_layout
->setRowMinimumHeight(row
, 20); // XXX urgh, pixels...
1669 gui_layout
->setRowStretch(row
++, 1);
1671 gui_layout
->addWidget(min_label
, row
, 1, Qt::AlignRight
);
1672 gui_layout
->addWidget(min_box
, row
++, 2, Qt::AlignLeft
);
1673 gui_layout
->addWidget(max_label
, row
, 1, Qt::AlignRight
);
1674 gui_layout
->addWidget(max_box
, row
++, 2, Qt::AlignLeft
);
1676 gui_layout
->setRowMinimumHeight(row
, 20); // XXX urgh, pixels...
1677 gui_layout
->setRowStretch(row
++, 1);
1679 gui_layout
->addWidget(default_label
, row
, 1, Qt::AlignRight
);
1680 gui_layout
->addWidget(default_box
, row
++, 2, Qt::AlignLeft
);
1681 gui_layout
->addWidget(fallback_label
, row
, 1, Qt::AlignRight
);
1682 gui_layout
->addWidget(fallback_box
, row
++, 2, Qt::AlignLeft
);
1684 gui_layout
->setRowMinimumHeight(row
, 20); // XXX urgh, pixels...
1685 gui_layout
->setRowStretch(row
++, 1);
1687 gui_layout
->addWidget(limit_label
, row
, 1, Qt::AlignRight
);
1688 gui_layout
->addWidget(limit_box
, row
++, 2, Qt::AlignLeft
);
1689 gui_layout
->addWidget(no_limit_box
, row
++, 2);
1691 gui_layout
->addWidget(increase_label
, row
, 1, Qt::AlignRight
);
1692 gui_layout
->addWidget(increase_box
, row
++, 2, Qt::AlignLeft
);
1693 gui_layout
->addWidget(no_increase_box
, row
++, 2);
1695 gui_layout
->addWidget(snapping_label
, row
, 1, Qt::AlignRight
);
1696 gui_layout
->addWidget(snapping_line
, row
++, 2, Qt::AlignLeft
);
1698 gui_layout
->addWidget(stem_width_label
, row
, 1, Qt::AlignRight
);
1699 gui_layout
->addWidget(stem_width_box
, row
++, 2, Qt::AlignLeft
);
1700 gui_layout
->addWidget(default_stem_width_box
, row
++, 2);
1702 gui_layout
->setRowMinimumHeight(row
, 30); // XXX urgh, pixels...
1703 gui_layout
->setRowStretch(row
++, 1);
1705 gui_layout
->addLayout(run_layout
, row
, 0, row
, -1);
1708 gui_layout
->setColumnMinimumWidth(3, 20); // XXX urgh, pixels...
1709 gui_layout
->setColumnStretch(3, 1);
1713 gui_layout
->addWidget(wincomp_box
, row
++, 4);
1714 gui_layout
->addWidget(adjust_box
, row
++, 4);
1715 gui_layout
->addWidget(hint_box
, row
++, 4);
1716 gui_layout
->addWidget(symbol_box
, row
++, 4);
1717 gui_layout
->addWidget(dehint_box
, row
++, 4);
1718 gui_layout
->addWidget(info_box
, row
++, 4);
1719 gui_layout
->addWidget(TTFA_box
, row
++, 4);
1721 gui_layout
->setRowMinimumHeight(row
, 20); // XXX urgh, pixels...
1722 gui_layout
->setRowStretch(row
++, 1);
1724 gui_layout
->addWidget(stem_label
, row
++, 4);
1726 QGridLayout
* stem_layout
= new QGridLayout
;
1727 stem_layout
->setColumnMinimumWidth(0, 20); // XXX urgh, pixels...
1728 stem_layout
->addWidget(gray_box
, 0, 1);
1729 stem_layout
->addWidget(gdi_box
, 1, 1);
1730 stem_layout
->addWidget(dw_box
, 2, 1);
1732 gui_layout
->addLayout(stem_layout
, row
, 4, 3, 1);
1736 gui_layout
->setColumnMinimumWidth(5, 10); // XXX urgh, pixels...
1737 gui_layout
->setColumnStretch(5, 1);
1739 // create dummy widget to register layout
1740 QWidget
* main_widget
= new QWidget
;
1741 main_widget
->setLayout(gui_layout
);
1742 setCentralWidget(main_widget
);
1743 setWindowTitle("TTFautohint");
1748 Main_GUI::create_connections()
1750 connect(input_button
, SIGNAL(clicked()), this,
1751 SLOT(browse_input()));
1752 connect(output_button
, SIGNAL(clicked()), this,
1753 SLOT(browse_output()));
1754 connect(deltas_button
, SIGNAL(clicked()), this,
1755 SLOT(browse_deltas()));
1757 connect(input_line
, SIGNAL(textChanged(QString
)), this,
1759 connect(output_line
, SIGNAL(textChanged(QString
)), this,
1762 connect(input_line
, SIGNAL(editingFinished()), this,
1763 SLOT(absolute_input()));
1764 connect(output_line
, SIGNAL(editingFinished()), this,
1765 SLOT(absolute_output()));
1766 connect(deltas_line
, SIGNAL(editingFinished()), this,
1767 SLOT(absolute_deltas()));
1769 connect(min_box
, SIGNAL(valueChanged(int)), this,
1771 connect(max_box
, SIGNAL(valueChanged(int)), this,
1774 connect(limit_box
, SIGNAL(valueChanged(int)), this,
1775 SLOT(check_limit()));
1776 connect(no_limit_box
, SIGNAL(clicked()), this,
1777 SLOT(check_no_limit()));
1779 connect(no_increase_box
, SIGNAL(clicked()), this,
1780 SLOT(check_no_increase()));
1782 connect(snapping_line
, SIGNAL(editingFinished()), this,
1783 SLOT(check_number_set()));
1784 connect(snapping_line
, SIGNAL(textEdited(QString
)), this,
1785 SLOT(clear_status_bar()));
1787 connect(default_stem_width_box
, SIGNAL(clicked()), this,
1788 SLOT(check_default_stem_width()));
1790 connect(dehint_box
, SIGNAL(clicked()), this,
1791 SLOT(check_dehint()));
1793 connect(timer
, SIGNAL(timeout()), this,
1794 SLOT(watch_files()));
1796 connect(watch_box
, SIGNAL(clicked()), this,
1797 SLOT(check_watch()));
1799 connect(run_button
, SIGNAL(clicked()), this,
1805 Main_GUI::create_actions()
1807 exit_act
= new QAction(tr("E&xit"), this);
1808 exit_act
->setShortcuts(QKeySequence::Quit
);
1809 connect(exit_act
, SIGNAL(triggered()), this, SLOT(close()));
1811 about_act
= new QAction(tr("&About"), this);
1812 connect(about_act
, SIGNAL(triggered()), this, SLOT(about()));
1814 about_Qt_act
= new QAction(tr("About &Qt"), this);
1815 connect(about_Qt_act
, SIGNAL(triggered()), qApp
, SLOT(aboutQt()));
1820 Main_GUI::create_menus()
1822 file_menu
= menuBar()->addMenu(tr("&File"));
1823 file_menu
->addAction(exit_act
);
1825 help_menu
= menuBar()->addMenu(tr("&Help"));
1826 help_menu
->addAction(about_act
);
1827 help_menu
->addAction(about_Qt_act
);
1832 Main_GUI::create_status_bar()
1834 statusBar()->showMessage("");
1839 Main_GUI::set_defaults()
1841 min_box
->setValue(hinting_range_min
);
1842 max_box
->setValue(hinting_range_max
);
1844 default_box
->setCurrentIndex(default_script_idx
);
1845 fallback_box
->setCurrentIndex(fallback_script_idx
);
1847 limit_box
->setValue(hinting_limit
? hinting_limit
: hinting_range_max
);
1848 // handle command line option `--hinting-limit=0'
1851 hinting_limit
= max_box
->value();
1852 no_limit_box
->setChecked(true);
1855 increase_box
->setValue(increase_x_height
? increase_x_height
1856 : TA_INCREASE_X_HEIGHT
);
1857 // handle command line option `--increase-x-height=0'
1858 if (!increase_x_height
)
1860 increase_x_height
= TA_INCREASE_X_HEIGHT
;
1861 no_increase_box
->setChecked(true);
1864 snapping_line
->setText(x_height_snapping_exceptions_string
);
1866 if (fallback_stem_width
)
1867 stem_width_box
->setValue(fallback_stem_width
);
1870 stem_width_box
->setValue(50);
1871 default_stem_width_box
->setChecked(true);
1874 if (windows_compatibility
)
1875 wincomp_box
->setChecked(true);
1876 if (adjust_subglyphs
)
1877 adjust_box
->setChecked(true);
1878 if (hint_composites
)
1879 hint_box
->setChecked(true);
1881 symbol_box
->setChecked(true);
1883 dehint_box
->setChecked(true);
1885 info_box
->setChecked(true);
1887 info_box
->setChecked(true);
1889 if (gray_strong_stem_width
)
1890 gray_box
->setChecked(true);
1891 if (gdi_cleartype_strong_stem_width
)
1892 gdi_box
->setChecked(true);
1893 if (dw_cleartype_strong_stem_width
)
1894 dw_box
->setChecked(true);
1896 run_button
->setEnabled(false);
1903 check_no_increase();
1906 // do this last since it disables almost everything
1912 Main_GUI::read_settings()
1915 // QPoint pos = settings.value("pos", QPoint(200, 200)).toPoint();
1916 // QSize size = settings.value("size", QSize(400, 400)).toSize();
1923 Main_GUI::write_settings()
1926 // settings.setValue("pos", pos());
1927 // settings.setValue("size", size());
1930 // end of maingui.cpp