Remove unused structure members.
[ttfautohint.git] / frontend / maingui.cpp
blob8258b16fbf0c848cf9d91db942106009df69d0d7
1 // maingui.cpp
3 // Copyright (C) 2012-2016 by Werner Lemberg.
4 //
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.
9 //
10 // The file `COPYING' mentioned in the previous paragraph is distributed
11 // with the ttfautohint library.
14 #include <config.h>
16 #include <string.h>
17 #include <stdio.h>
18 #include <errno.h>
19 #include <locale.h>
21 #include <QtGui>
23 #include "info.h"
24 #include "maingui.h"
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)
35 #else
36 # define QUOTE_STRING(x) "\"" + x + "\""
37 # define QUOTE_STRING_LITERAL(x) "\"" x "\""
38 #endif
41 // Shorthand for `tr' using a local `TRDOMAIN'.
42 #define Tr(text) QCoreApplication::translate(TRDOMAIN, text)
45 typedef struct Tag_Names_
47 const char* tag;
48 const char* description;
49 } Tag_Names;
52 // the available script tags and its descriptions are directly extracted
53 // from `ttfautohint-scripts.h'
54 #undef SCRIPT
55 #define SCRIPT(s, S, d, h, H, ss) \
56 {#s, d},
58 const Tag_Names script_names[] =
60 #include <ttfautohint-scripts.h>
61 {NULL, NULL}
65 // the available feature tags and its descriptions are directly extracted
66 // from `ttfautohint-coverages.h'
67 #undef COVERAGE
68 #define COVERAGE(n, N, d, t, t1, t2, t3, t4) \
69 {#t, d},
71 const Tag_Names feature_names[] =
73 #include <ttfautohint-coverages.h>
74 {NULL, NULL}
78 // used hotkeys:
79 // a: Add ttf&autohint Info
80 // b: Add TTFA info ta&ble
81 // c: x Height In&crease Limit / No x Height In&crease
82 // d: &Dehint
83 // e: Control Instructions Fil&e
84 // f: &File (menu)
85 // g: Stron&g Stem Width and Positioning
86 // h: &Help (menu)
87 // i: &Input File
88 // j: Ad&just Subglyphs
89 // k: Fallbac&k Script
90 // l: Hinting &Limit / No Hinting &Limit
91 // m: Hint Co&mposites
92 // n: Hint Set Range Mi&nimum
93 // o: &Output File
94 // p: Windows Com&patibility
95 // q: --
96 // r: &Run
97 // s: Fallback &Stem Width / Default Fallback &Stem Width
98 // t: x Height Snapping Excep&tions
99 // u: Defa&ult Script
100 // v: --
101 // w: &Watch Input Files
102 // x: Hint Set Range Ma&ximum
103 // y: S&ymbol Font
104 // z: --
106 Main_GUI::Main_GUI(bool horizontal_layout,
107 int range_min,
108 int range_max,
109 int limit,
110 bool gray,
111 bool gdi,
112 bool dw,
113 int increase,
114 const char* exceptions,
115 int stem_width,
116 bool ignore,
117 bool wincomp,
118 bool adjust,
119 bool composites,
120 bool no,
121 bool detailed,
122 const char* dflt,
123 const char* fallback,
124 bool scaling,
125 const char* suffix,
126 bool symb,
127 bool dh,
128 bool TTFA)
129 : hinting_range_min(range_min),
130 hinting_range_max(range_max),
131 hinting_limit(limit),
132 gray_strong_stem_width(gray),
133 gdi_cleartype_strong_stem_width(gdi),
134 dw_cleartype_strong_stem_width(dw),
135 increase_x_height(increase),
136 x_height_snapping_exceptions_string(exceptions),
137 fallback_stem_width(stem_width),
138 ignore_restrictions(ignore),
139 windows_compatibility(wincomp),
140 adjust_subglyphs(adjust),
141 hint_composites(composites),
142 no_info(no),
143 detailed_info(detailed),
144 fallback_scaling(scaling),
145 family_suffix(suffix),
146 symbol(symb),
147 dehint(dh),
148 TTFA_info(TTFA),
149 // constants
150 fallback_do_scale(1),
151 fallback_do_hint(0)
153 int i;
155 for (i = 0; script_names[i].tag; i++)
157 if (!strcmp("latn", script_names[i].tag))
158 latn_script_idx = i;
159 if (!strcmp("none", script_names[i].tag))
160 none_script_idx = i;
163 // map default script and fallback script tags to indices
164 for (i = 0; script_names[i].tag; i++)
165 if (!strcmp(dflt, script_names[i].tag))
166 break;
167 default_script_idx = script_names[i].tag ? i : latn_script_idx;
169 for (i = 0; script_names[i].tag; i++)
170 if (!strcmp(fallback, script_names[i].tag))
171 break;
172 fallback_script_idx = script_names[i].tag ? i : none_script_idx;
174 x_height_snapping_exceptions = NULL;
176 // if the current input files have been updated
177 // we wait a given time interval, then we reload the files
178 file_watcher = new QFileSystemWatcher(this);
179 timer = new QTimer(this);
180 timer->setInterval(1000); // XXX make this configurable
181 timer->setSingleShot(true);
182 fileinfo_input_file.setCaching(false);
183 fileinfo_control_file.setCaching(false);
185 // XXX register translations somewhere and loop over them
186 if (QLocale::system().name() == "en_US")
187 locale = new QLocale;
188 else
189 locale = new QLocale(QLocale::C);
191 // For real numbers (both parsing and displaying) we only use `.' as the
192 // decimal separator; similarly, we don't want localized formats like a
193 // thousands separator for any number.
194 setlocale(LC_NUMERIC, "C");
196 create_layout(horizontal_layout);
197 create_connections();
198 create_actions();
199 create_menus();
200 create_status_bar();
202 set_defaults();
203 read_settings();
205 setUnifiedTitleAndToolBarOnMac(true);
209 Main_GUI::~Main_GUI()
211 number_set_free(x_height_snapping_exceptions);
215 // overloading
217 void
218 Main_GUI::closeEvent(QCloseEvent* event)
220 write_settings();
221 event->accept();
225 void
226 Main_GUI::about()
228 QMessageBox::about(this,
229 tr("About TTFautohint"),
230 tr("<p>This is <b>TTFautohint</b> version %1<br>"
231 " Copyright %2 2011-2016<br>"
232 " by Werner Lemberg <tt>&lt;wl@gnu.org&gt;</tt></p>"
234 "<p><b>TTFautohint</b> adds new auto-generated hints"
235 " to a TrueType font or TrueType collection.</p>"
237 "<p>License:"
238 " <a href='http://git.savannah.gnu.org/cgit/freetype/freetype2.git/tree/docs/FTL.TXT'>FreeType"
239 " License (FTL)</a> or"
240 " <a href='http://git.savannah.gnu.org/cgit/freetype/freetype2.git/tree/docs/GPLv2.TXT'>GNU"
241 " GPLv2</a></p>")
242 .arg(VERSION)
243 .arg(QChar(0xA9)));
247 void
248 Main_GUI::browse_input()
250 // XXX remember last directory
251 QString file = QFileDialog::getOpenFileName(
252 this,
253 tr("Open Input File"),
254 QDir::homePath(),
255 "");
257 if (!file.isEmpty())
258 input_line->setText(QDir::toNativeSeparators(file));
262 void
263 Main_GUI::browse_output()
265 // XXX remember last directory
266 QString file = QFileDialog::getSaveFileName(
267 this,
268 tr("Open Output File"),
269 QDir::homePath(),
270 "");
272 if (!file.isEmpty())
273 output_line->setText(QDir::toNativeSeparators(file));
277 void
278 Main_GUI::browse_control()
280 // XXX remember last directory
281 QString file = QFileDialog::getOpenFileName(
282 this,
283 tr("Open Control INstructions File"),
284 QDir::homePath(),
285 "");
287 if (!file.isEmpty())
288 control_line->setText(QDir::toNativeSeparators(file));
292 void
293 Main_GUI::check_min()
295 int min = min_box->value();
296 int max = max_box->value();
297 int limit = limit_box->value();
298 if (min > max)
299 max_box->setValue(min);
300 if (min > limit)
301 limit_box->setValue(min);
305 void
306 Main_GUI::check_max()
308 int min = min_box->value();
309 int max = max_box->value();
310 int limit = limit_box->value();
311 if (max < min)
312 min_box->setValue(max);
313 if (max > limit)
314 limit_box->setValue(max);
318 void
319 Main_GUI::check_limit()
321 int min = min_box->value();
322 int max = max_box->value();
323 int limit = limit_box->value();
324 if (limit < max)
325 max_box->setValue(limit);
326 if (limit < min)
327 min_box->setValue(limit);
331 void
332 Main_GUI::check_dehint()
334 if (dehint_box->isChecked())
336 min_label->setEnabled(false);
337 min_box->setEnabled(false);
339 max_label->setEnabled(false);
340 max_box->setEnabled(false);
342 default_label->setEnabled(false);
343 default_box->setEnabled(false);
344 fallback_label->setEnabled(false);
345 fallback_hint_or_scale_box->setEnabled(false);
346 fallback_box->setEnabled(false);
348 no_limit_box->setEnabled(false);
349 limit_label->setEnabled(false);
350 limit_box->setEnabled(false);
352 no_increase_box->setEnabled(false);
353 increase_label->setEnabled(false);
354 increase_box->setEnabled(false);
356 snapping_label->setEnabled(false);
357 snapping_line->setEnabled(false);
359 default_stem_width_box->setEnabled(false);
360 stem_width_label->setEnabled(false);
361 stem_width_box->setEnabled(false);
363 wincomp_box->setEnabled(false);
364 adjust_box->setEnabled(false);
365 hint_box->setEnabled(false);
366 symbol_box->setEnabled(false);
368 stem_label->setEnabled(false);
369 gray_box->setEnabled(false);
370 gdi_box->setEnabled(false);
371 dw_box->setEnabled(false);
373 else
375 min_label->setEnabled(true);
376 min_box->setEnabled(true);
378 max_label->setEnabled(true);
379 max_box->setEnabled(true);
381 default_label->setEnabled(true);
382 default_box->setEnabled(true);
383 fallback_label->setEnabled(true);
384 fallback_hint_or_scale_box->setEnabled(true);
385 fallback_box->setEnabled(true);
387 no_limit_box->setEnabled(true);
388 check_no_limit();
390 no_increase_box->setEnabled(true);
391 check_no_increase();
393 snapping_label->setEnabled(true);
394 snapping_line->setEnabled(true);
396 default_stem_width_box->setEnabled(true);
397 check_default_stem_width();
399 wincomp_box->setEnabled(true);
400 adjust_box->setEnabled(true);
401 hint_box->setEnabled(true);
402 symbol_box->setEnabled(true);
404 stem_label->setEnabled(true);
405 gray_box->setEnabled(true);
406 gdi_box->setEnabled(true);
407 dw_box->setEnabled(true);
412 void
413 Main_GUI::check_no_limit()
415 if (no_limit_box->isChecked())
417 limit_label->setEnabled(false);
418 limit_label->setText(limit_label_text);
419 limit_box->setEnabled(false);
420 no_limit_box->setText(no_limit_box_text_with_key);
422 else
424 limit_label->setEnabled(true);
425 limit_label->setText(limit_label_text_with_key);
426 limit_box->setEnabled(true);
427 no_limit_box->setText(no_limit_box_text);
432 void
433 Main_GUI::check_no_increase()
435 if (no_increase_box->isChecked())
437 increase_label->setEnabled(false);
438 increase_label->setText(increase_label_text);
439 increase_box->setEnabled(false);
440 no_increase_box->setText(no_increase_box_text_with_key);
442 else
444 increase_label->setEnabled(true);
445 increase_label->setText(increase_label_text_with_key);
446 increase_box->setEnabled(true);
447 no_increase_box->setText(no_increase_box_text);
452 void
453 Main_GUI::check_default_stem_width()
455 if (default_stem_width_box->isChecked())
457 stem_width_label->setEnabled(false);
458 stem_width_label->setText(stem_width_label_text);
459 stem_width_box->setEnabled(false);
460 default_stem_width_box->setText(default_stem_width_box_text_with_key);
462 else
464 stem_width_label->setEnabled(true);
465 stem_width_label->setText(stem_width_label_text_with_key);
466 stem_width_box->setEnabled(true);
467 default_stem_width_box->setText(default_stem_width_box_text);
472 void
473 Main_GUI::check_run()
475 if (input_line->text().isEmpty() || output_line->text().isEmpty())
476 run_button->setEnabled(false);
477 else
478 run_button->setEnabled(true);
482 void
483 Main_GUI::absolute_input()
485 QString input_name = QDir::fromNativeSeparators(input_line->text());
486 if (!input_name.isEmpty()
487 && QDir::isRelativePath(input_name))
489 QDir cur_path(QDir::currentPath() + "/" + input_name);
490 input_line->setText(QDir::toNativeSeparators(cur_path.absolutePath()));
495 void
496 Main_GUI::absolute_output()
498 QString output_name = QDir::fromNativeSeparators(output_line->text());
499 if (!output_name.isEmpty()
500 && QDir::isRelativePath(output_name))
502 QDir cur_path(QDir::currentPath() + "/" + output_name);
503 output_line->setText(QDir::toNativeSeparators(cur_path.absolutePath()));
508 void
509 Main_GUI::absolute_control()
511 QString control_name = QDir::fromNativeSeparators(control_line->text());
512 if (!control_name.isEmpty()
513 && QDir::isRelativePath(control_name))
515 QDir cur_path(QDir::currentPath() + "/" + control_name);
516 control_line->setText(QDir::toNativeSeparators(cur_path.absolutePath()));
521 void
522 Main_GUI::check_number_set()
524 QString text = snapping_line->text();
525 QString qs;
527 // construct ASCII string from arbitrary Unicode data;
528 // the idea is to accept, say, CJK fullwidth digits also
529 for (int i = 0; i < text.size(); i++)
531 QChar c = text.at(i);
533 int digit = c.digitValue();
534 if (digit >= 0)
535 qs += QString::number(digit);
536 else if (c.isSpace())
537 qs += ' ';
538 // U+30FC KATAGANA-HIRAGANA PROLONGED SOUND MARK is assigned
539 // to the `-' key in some Japanese input methods
540 else if (c.category() == QChar::Punctuation_Dash
541 || c == QChar(0x30FC))
542 qs += '-';
543 // various Unicode COMMA characters,
544 // including representation forms
545 else if (c == QChar(',')
546 || c == QChar(0x055D)
547 || c == QChar(0x060C)
548 || c == QChar(0x07F8)
549 || c == QChar(0x1363)
550 || c == QChar(0x1802)
551 || c == QChar(0x1808)
552 || c == QChar(0x3001)
553 || c == QChar(0xA4FE)
554 || c == QChar(0xA60D)
555 || c == QChar(0xA6F5)
556 || c == QChar(0xFE10)
557 || c == QChar(0xFE11)
558 || c == QChar(0xFE50)
559 || c == QChar(0xFE51)
560 || c == QChar(0xFF0C)
561 || c == QChar(0xFF64))
562 qs += ',';
563 else
564 qs += c; // we do error handling below
567 if (x_height_snapping_exceptions)
568 number_set_free(x_height_snapping_exceptions);
570 QByteArray str = qs.toLocal8Bit();
571 const char* s = number_set_parse(str.constData(),
572 &x_height_snapping_exceptions,
573 6, 0x7FFF);
574 if (s && *s)
576 statusBar()->setStyleSheet("color: red;");
577 if (x_height_snapping_exceptions == NUMBERSET_ALLOCATION_ERROR)
578 statusBar()->showMessage(
579 tr("allocation error"));
580 else if (x_height_snapping_exceptions == NUMBERSET_INVALID_CHARACTER)
581 statusBar()->showMessage(
582 tr("invalid character (use digits, dashes, commas, and spaces)"));
583 else if (x_height_snapping_exceptions == NUMBERSET_OVERFLOW)
584 statusBar()->showMessage(
585 tr("overflow"));
586 else if (x_height_snapping_exceptions == NUMBERSET_INVALID_RANGE)
587 statusBar()->showMessage(
588 tr("invalid range (minimum is 6, maximum is 32767)"));
589 else if (x_height_snapping_exceptions == NUMBERSET_OVERLAPPING_RANGES)
590 statusBar()->showMessage(
591 tr("overlapping ranges"));
592 else if (x_height_snapping_exceptions == NUMBERSET_NOT_ASCENDING)
593 statusBar()->showMessage(
594 tr("values und ranges must be specified in ascending order"));
596 snapping_line->setText(qs);
597 snapping_line->setFocus(Qt::OtherFocusReason);
598 snapping_line->setCursorPosition(s - str.constData());
600 x_height_snapping_exceptions = NULL;
602 else
604 // normalize if there is no error
605 char* new_str = number_set_show(x_height_snapping_exceptions,
606 6, 0x7FFF);
607 snapping_line->setText(new_str);
608 free(new_str);
613 void
614 Main_GUI::check_family_suffix()
616 QString text = family_suffix_line->text();
617 const char* s = qPrintable(text);
619 if (const char* pos = ::check_family_suffix(s))
621 statusBar()->setStyleSheet("color: red;");
622 statusBar()->showMessage(
623 tr("invalid character (use printable ASCII except %()/<>[]{})"));
624 family_suffix_line->setFocus(Qt::OtherFocusReason);
625 family_suffix_line->setCursorPosition(pos - s);
630 void
631 Main_GUI::clear_status_bar()
633 statusBar()->clearMessage();
634 statusBar()->setStyleSheet("");
639 Main_GUI::check_filenames(const QString& input_name,
640 const QString& output_name,
641 const QString& control_name)
643 if (!QFile::exists(input_name))
645 QMessageBox::warning(
646 this,
647 "TTFautohint",
648 tr("The file %1 cannot be found.")
649 .arg(QUOTE_STRING(QDir::toNativeSeparators(input_name))),
650 QMessageBox::Ok,
651 QMessageBox::Ok);
652 return 0;
655 if (input_name == output_name)
657 QMessageBox::warning(
658 this,
659 "TTFautohint",
660 tr("Input and output file names must be different."),
661 QMessageBox::Ok,
662 QMessageBox::Ok);
663 return 0;
666 // silently overwrite if watching is active
667 if (QFile::exists(output_name) && !watch_box->isChecked())
669 int ret = QMessageBox::warning(
670 this,
671 "TTFautohint",
672 tr("The file %1 already exists.\n"
673 "Overwrite?")
674 .arg(QUOTE_STRING(QDir::toNativeSeparators(output_name))),
675 QMessageBox::Yes | QMessageBox::No,
676 QMessageBox::No);
677 if (ret == QMessageBox::No)
678 return 0;
681 if (!control_name.isEmpty() && !QFile::exists(control_name))
683 QMessageBox::warning(
684 this,
685 "TTFautohint",
686 tr("The file %1 cannot be found.")
687 .arg(QUOTE_STRING(QDir::toNativeSeparators(control_name))),
688 QMessageBox::Ok,
689 QMessageBox::Ok);
690 return 0;
693 return 1;
698 Main_GUI::open_files(const QString& input_name,
699 FILE** in,
700 const QString& output_name,
701 FILE** out,
702 const QString& control_name,
703 FILE** control)
705 const int buf_len = 1024;
706 char buf[buf_len];
708 *in = fopen(qPrintable(input_name), "rb");
709 if (!*in)
711 strerror_r(errno, buf, buf_len);
712 QMessageBox::warning(
713 this,
714 "TTFautohint",
715 tr("The following error occurred while opening input file %1:\n")
716 .arg(QUOTE_STRING(QDir::toNativeSeparators(input_name)))
717 + QString::fromLocal8Bit(buf),
718 QMessageBox::Ok,
719 QMessageBox::Ok);
720 return 0;
723 *out = fopen(qPrintable(output_name), "wb");
724 if (!*out)
726 strerror_r(errno, buf, buf_len);
727 QMessageBox::warning(
728 this,
729 "TTFautohint",
730 tr("The following error occurred while opening output file %1:\n")
731 .arg(QUOTE_STRING(QDir::toNativeSeparators(output_name)))
732 + QString::fromLocal8Bit(buf),
733 QMessageBox::Ok,
734 QMessageBox::Ok);
735 return 0;
738 if (!control_name.isEmpty())
740 *control = fopen(qPrintable(control_name), "r");
741 if (!*control)
743 strerror_r(errno, buf, buf_len);
744 QMessageBox::warning(
745 this,
746 "TTFautohint",
747 tr("The following error occurred"
748 " while opening control instructions file %1:\n")
749 .arg(QUOTE_STRING(QDir::toNativeSeparators(control_name)))
750 + QString::fromLocal8Bit(buf),
751 QMessageBox::Ok,
752 QMessageBox::Ok);
753 return 0;
756 else
757 *control = NULL;
759 return 1;
763 void
764 Main_GUI::check_watch()
766 if (watch_box->isChecked())
768 // file watching gets started in the `run' function
769 check = DoCheck;
771 else
772 stop_watching();
776 void
777 Main_GUI::start_timer()
779 // we delay the file watching action, mainly to ensure
780 // that newly generated files have been completely written to disk
781 check = CheckNow;
782 timer->start();
786 void
787 Main_GUI::stop_watching()
789 check = DoCheck;
790 if (!fileinfo_input_file.fileName().isEmpty())
791 file_watcher->removePath(fileinfo_input_file.fileName());
792 if (!fileinfo_control_file.fileName().isEmpty())
793 file_watcher->removePath(fileinfo_control_file.fileName());
797 void
798 Main_GUI::watch_files()
800 if (fileinfo_input_file.exists()
801 && fileinfo_input_file.isReadable()
802 && (fileinfo_control_file.fileName().isEmpty()
803 ? true
804 : (fileinfo_control_file.exists()
805 && fileinfo_control_file.isReadable())))
807 QDateTime modified_input = fileinfo_input_file.lastModified();
808 QDateTime modified_control = fileinfo_control_file.lastModified();
809 // XXX make this configurable
810 if (datetime_input_file.msecsTo(modified_input) > 1000
811 || datetime_control_file.msecsTo(modified_control) > 1000)
813 check = CheckNow;
814 run(); // this function sets `datetime_XXX'
816 else
818 // restart timer for symlinks
819 if (watch_box->isChecked())
821 if (fileinfo_input_file.isSymLink()
822 || fileinfo_control_file.isSymLink())
823 timer->start();
827 else
829 if (check == DoCheck)
830 check = CheckLater;
831 else if (check == CheckLater)
832 check = CheckNow;
834 run(); // let this routine handle all errors
839 extern "C" {
841 struct GUI_Progress_Data
843 long last_sfnt;
844 bool begin;
845 QProgressDialog* dialog;
849 #undef TRDOMAIN
850 #define TRDOMAIN "GuiProgress"
852 static int
853 gui_progress(long curr_idx,
854 long num_glyphs,
855 long curr_sfnt,
856 long num_sfnts,
857 void* user)
859 GUI_Progress_Data* data = static_cast<GUI_Progress_Data*>(user);
861 if (num_sfnts > 1 && curr_sfnt != data->last_sfnt)
863 data->dialog->setLabelText(Tr("Auto-hinting subfont %1 of %2"
864 " with %3 glyphs...")
865 .arg(curr_sfnt + 1)
866 .arg(num_sfnts)
867 .arg(num_glyphs));
869 if (curr_sfnt + 1 == num_sfnts)
871 data->dialog->setAutoReset(true);
872 data->dialog->setAutoClose(true);
874 else
876 data->dialog->setAutoReset(false);
877 data->dialog->setAutoClose(false);
880 data->last_sfnt = curr_sfnt;
881 data->begin = true;
884 if (data->begin)
886 if (num_sfnts == 1)
887 data->dialog->setLabelText(Tr("Auto-hinting %1 glyphs...")
888 .arg(num_glyphs));
889 data->dialog->setMaximum(num_glyphs - 1);
891 data->begin = false;
894 data->dialog->setValue(curr_idx);
896 if (data->dialog->wasCanceled())
897 return 1;
899 return 0;
903 struct GUI_Error_Data
905 Main_GUI* gui;
906 QLocale* locale;
907 QString output_name;
908 QString control_name;
909 int* ignore_restrictions_p;
910 bool retry;
914 #undef TRDOMAIN
915 #define TRDOMAIN "GuiError"
917 static void
918 gui_error(TA_Error error,
919 const char* error_string,
920 unsigned int errlinenum,
921 const char* errline,
922 const char* errpos,
923 void* user)
925 GUI_Error_Data* data = static_cast<GUI_Error_Data*>(user);
926 QLocale* locale = data->locale; // for QUOTE_STRING_LITERAL
928 if (!error)
929 return;
931 if (error == TA_Err_Canceled)
933 else if (error == TA_Err_Invalid_FreeType_Version)
934 QMessageBox::critical(
935 data->gui,
936 "TTFautohint",
937 Tr("FreeType version 2.4.5 or higher is needed.\n"
938 "Are you perhaps using a wrong FreeType DLL?"),
939 QMessageBox::Ok,
940 QMessageBox::Ok);
941 else if (error == TA_Err_Invalid_Font_Type)
942 QMessageBox::warning(
943 data->gui,
944 "TTFautohint",
945 Tr("This font is not a valid font"
946 " in SFNT format with TrueType outlines.\n"
947 "In particular, CFF outlines are not supported."),
948 QMessageBox::Ok,
949 QMessageBox::Ok);
950 else if (error == TA_Err_Already_Processed)
951 QMessageBox::warning(
952 data->gui,
953 "TTFautohint",
954 Tr("This font has already been processed by TTFautohint."),
955 QMessageBox::Ok,
956 QMessageBox::Ok);
957 else if (error == TA_Err_Missing_Legal_Permission)
959 int yesno = QMessageBox::warning(
960 data->gui,
961 "TTFautohint",
962 Tr("Bit 1 in the %1 field of the %2 table is set:"
963 " This font must not be modified"
964 " without permission of the legal owner.\n"
965 "Do you have such a permission?")
966 .arg(QUOTE_STRING_LITERAL("fsType"))
967 .arg(QUOTE_STRING_LITERAL("OS/2")),
968 QMessageBox::Yes | QMessageBox::No,
969 QMessageBox::No);
970 if (yesno == QMessageBox::Yes)
972 *data->ignore_restrictions_p = true;
973 data->retry = true;
976 else if (error == TA_Err_Missing_Unicode_CMap)
977 QMessageBox::warning(
978 data->gui,
979 "TTFautohint",
980 Tr("The input font doesn't contain a Unicode character map.\n"
981 "Maybe you haven't set the %1 checkbox?")
982 .arg(QUOTE_STRING_LITERAL(Tr("Symbol Font"))),
983 QMessageBox::Ok,
984 QMessageBox::Ok);
985 else if (error == TA_Err_Missing_Symbol_CMap)
986 QMessageBox::warning(
987 data->gui,
988 "TTFautohint",
989 Tr("The input font does neither contain a symbol"
990 " nor a character map."),
991 QMessageBox::Ok,
992 QMessageBox::Ok);
993 else if (error == TA_Err_Missing_Glyph)
994 QMessageBox::warning(
995 data->gui,
996 "TTFautohint",
997 Tr("No glyph for a standard character"
998 " to derive standard width and height.\n"
999 "Please check the documentation for a list of"
1000 " script-specific standard characters.\n"
1001 "\n"
1002 "Set the %1 checkbox if you want to circumvent this test.")
1003 .arg(QUOTE_STRING_LITERAL(Tr("Symbol Font"))),
1004 QMessageBox::Ok,
1005 QMessageBox::Ok);
1006 else if (error >= 0x200 && error < 0x300)
1007 QMessageBox::warning(
1008 data->gui,
1009 "TTFautohint",
1010 QString::fromLocal8Bit("%1:%2:%3: %4 (0x%5)<br>"
1011 "<tt> %6<br>"
1012 " %7</tt>")
1013 .arg(data->control_name)
1014 .arg(errlinenum)
1015 .arg(int(errpos - errline + 1))
1016 .arg(error_string)
1017 .arg(error, 2, 16, QLatin1Char('0'))
1018 .arg(errline)
1019 .arg('^', int(errpos - errline + 1))
1020 .replace(" ", "&nbsp;"),
1021 QMessageBox::Ok,
1022 QMessageBox::Ok);
1023 else
1024 QMessageBox::warning(
1025 data->gui,
1026 "TTFautohint",
1027 Tr("Error code 0x%1 while autohinting font:\n")
1028 .arg(error, 2, 16, QLatin1Char('0'))
1029 + QString::fromLocal8Bit(error_string),
1030 QMessageBox::Ok,
1031 QMessageBox::Ok);
1033 if (QFile::exists(data->output_name)
1034 && remove(qPrintable(data->output_name)))
1036 const int buf_len = 1024;
1037 char buf[buf_len];
1039 strerror_r(errno, buf, buf_len);
1040 QMessageBox::warning(
1041 data->gui,
1042 "TTFautohint",
1043 Tr("The following error occurred while removing output file %1:\n")
1044 .arg(QUOTE_STRING(QDir::toNativeSeparators(data->output_name)))
1045 + QString::fromLocal8Bit(buf),
1046 QMessageBox::Ok,
1047 QMessageBox::Ok);
1051 } // extern "C"
1054 void
1055 Main_GUI::run()
1057 clear_status_bar();
1059 if (check == CheckLater)
1061 timer->start();
1062 return;
1065 QString input_name = QDir::fromNativeSeparators(input_line->text());
1066 QString output_name = QDir::fromNativeSeparators(output_line->text());
1067 QString control_name = QDir::fromNativeSeparators(control_line->text());
1068 if (!check_filenames(input_name, output_name, control_name))
1070 stop_watching();
1071 return;
1074 // we need C file descriptors for communication with TTF_autohint
1075 FILE* input;
1076 FILE* output;
1077 FILE* control;
1079 again:
1080 if (!open_files(input_name, &input,
1081 output_name, &output,
1082 control_name, &control))
1084 stop_watching();
1085 return;
1088 QProgressDialog dialog;
1089 dialog.setCancelButtonText(tr("Cancel"));
1090 dialog.setMinimumDuration(1000);
1091 dialog.setWindowModality(Qt::WindowModal);
1093 TA_Info_Func info_func = info;
1094 TA_Info_Post_Func info_post_func = info_post;
1095 GUI_Progress_Data gui_progress_data = {-1, true, &dialog};
1096 GUI_Error_Data gui_error_data = {this, locale, output_name, control_name,
1097 &ignore_restrictions, false};
1099 fileinfo_input_file.setFile(input_name);
1100 fileinfo_control_file.setFile(control_name);
1102 Info_Data info_data;
1104 info_data.info_string = NULL; // must be deallocated after use
1105 info_data.info_string_wide = NULL; // must be deallocated after use
1106 info_data.info_string_len = 0;
1107 info_data.info_string_wide_len = 0;
1109 info_data.control_name = qPrintable(fileinfo_control_file.fileName());
1111 info_data.hinting_range_min = min_box->value();
1112 info_data.hinting_range_max = max_box->value();
1113 info_data.hinting_limit = no_limit_box->isChecked()
1115 : limit_box->value();
1117 info_data.gray_strong_stem_width = gray_box->isChecked();
1118 info_data.gdi_cleartype_strong_stem_width = gdi_box->isChecked();
1119 info_data.dw_cleartype_strong_stem_width = dw_box->isChecked();
1121 info_data.increase_x_height = no_increase_box->isChecked()
1123 : increase_box->value();
1124 info_data.x_height_snapping_exceptions_string =
1125 qPrintable(x_height_snapping_exceptions_string);
1127 info_data.family_suffix =
1128 family_suffix_line->text().toLocal8Bit().constData();
1129 info_data.family_data_head = NULL;
1131 info_data.fallback_stem_width = default_stem_width_box->isChecked()
1133 : stem_width_box->value();
1135 info_data.windows_compatibility = wincomp_box->isChecked();
1136 info_data.adjust_subglyphs = adjust_box->isChecked();
1137 info_data.hint_composites = hint_box->isChecked();
1138 info_data.symbol = symbol_box->isChecked();
1139 info_data.fallback_scaling = fallback_hint_or_scale_box->currentIndex();
1140 info_data.no_info = info_box->currentIndex() == 0;
1141 info_data.detailed_info = info_box->currentIndex() == 2;
1142 info_data.dehint = dehint_box->isChecked();
1143 info_data.TTFA_info = TTFA_box->isChecked();
1145 strncpy(info_data.default_script,
1146 script_names[default_box->currentIndex()].tag,
1147 sizeof (info_data.default_script));
1148 strncpy(info_data.fallback_script,
1149 script_names[fallback_box->currentIndex()].tag,
1150 sizeof (info_data.fallback_script));
1152 if (info_box->currentIndex())
1154 int ret = build_version_string(&info_data);
1155 if (ret == 1)
1156 QMessageBox::information(
1157 this,
1158 "TTFautohint",
1159 tr("Can't allocate memory for <b>TTFautohint</b> options string"
1160 " in <i>name</i> table."),
1161 QMessageBox::Ok,
1162 QMessageBox::Ok);
1163 else if (ret == 2)
1164 QMessageBox::information(
1165 this,
1166 "TTFautohint",
1167 tr("<b>TTFautohint</b> options string"
1168 " in <i>name</i> table too long."),
1169 QMessageBox::Ok,
1170 QMessageBox::Ok);
1173 if (!*info_data.family_suffix)
1174 info_post_func = NULL;
1176 if (info_data.symbol
1177 && info_data.fallback_stem_width
1178 && info_data.fallback_scaling)
1179 QMessageBox::information(
1180 this,
1181 "TTFautohint",
1182 tr("Setting a fallback stem width for a symbol font"
1183 " with fallback scaling only has no effect."),
1184 QMessageBox::Ok,
1185 QMessageBox::Ok);
1187 datetime_input_file = fileinfo_input_file.lastModified();
1188 datetime_control_file = fileinfo_control_file.lastModified();
1190 QByteArray snapping_string = snapping_line->text().toLocal8Bit();
1192 TA_Error error =
1193 TTF_autohint("in-file, out-file, control-file,"
1194 "hinting-range-min, hinting-range-max,"
1195 "hinting-limit,"
1196 "gray-strong-stem-width,"
1197 "gdi-cleartype-strong-stem-width,"
1198 "dw-cleartype-strong-stem-width,"
1199 "progress-callback, progress-callback-data,"
1200 "error-callback, error-callback-data,"
1201 "info-callback, info-post-callback, info-callback-data,"
1202 "ignore-restrictions,"
1203 "windows-compatibility,"
1204 "adjust-subglyphs,"
1205 "hint-composites,"
1206 "increase-x-height,"
1207 "x-height-snapping-exceptions, fallback-stem-width,"
1208 "default-script,"
1209 "fallback-script, fallback-scaling,"
1210 "symbol, dehint, TTFA-info",
1211 input, output, control,
1212 info_data.hinting_range_min, info_data.hinting_range_max,
1213 info_data.hinting_limit,
1214 info_data.gray_strong_stem_width,
1215 info_data.gdi_cleartype_strong_stem_width,
1216 info_data.dw_cleartype_strong_stem_width,
1217 gui_progress, &gui_progress_data,
1218 gui_error, &gui_error_data,
1219 info_func, info_post_func, &info_data,
1220 ignore_restrictions,
1221 info_data.windows_compatibility,
1222 info_data.adjust_subglyphs,
1223 info_data.hint_composites,
1224 info_data.increase_x_height,
1225 snapping_string.constData(), info_data.fallback_stem_width,
1226 info_data.default_script,
1227 info_data.fallback_script, info_data.fallback_scaling,
1228 info_data.symbol, info_data.dehint, info_data.TTFA_info);
1230 if (info_box->currentIndex())
1232 free(info_data.info_string);
1233 free(info_data.info_string_wide);
1236 fclose(input);
1237 fclose(output);
1238 if (control)
1239 fclose(control);
1241 if (error)
1243 // retry if there is a user request to do so (handled in `gui_error')
1244 if (gui_error_data.retry)
1245 goto again;
1247 stop_watching();
1249 else
1251 statusBar()->showMessage(tr("Auto-hinting finished")
1252 + " ("
1253 + QDateTime::currentDateTime()
1254 .toString(Qt::TextDate)
1255 + ").");
1257 // we have successfully processed a file;
1258 // start file watching now if requested
1259 if (watch_box->isChecked())
1261 check = DoCheck;
1263 // Qt's file watcher doesn't handle symlinks;
1264 // we thus fall back to polling
1265 if (fileinfo_input_file.isSymLink()
1266 || fileinfo_control_file.isSymLink())
1267 timer->start();
1268 else
1270 file_watcher->addPath(input_name);
1271 file_watcher->addPath(control_name);
1278 // XXX distances are specified in pixels,
1279 // making the layout dependent on the output device resolution
1280 void
1281 Main_GUI::create_layout(bool horizontal_layout)
1284 // file stuff
1286 QCompleter* completer = new QCompleter(this);
1287 QFileSystemModel* model = new QFileSystemModel(completer);
1288 model->setRootPath(QDir::rootPath());
1289 completer->setModel(model);
1291 input_label = new QLabel(tr("&Input File:"));
1292 input_line = new Drag_Drop_Line_Edit(DRAG_DROP_TRUETYPE);
1293 input_button = new QPushButton(tr("Browse..."));
1294 input_label->setBuddy(input_line);
1295 // enforce rich text to get nice word wrapping
1296 input_label->setToolTip(
1297 tr("<b></b>The input file, either a TrueType font (TTF),"
1298 " TrueType collection (TTC), or a TrueType-based OpenType font."));
1299 input_line->setCompleter(completer);
1301 output_label = new QLabel(tr("&Output File:"));
1302 output_line = new Drag_Drop_Line_Edit(DRAG_DROP_TRUETYPE);
1303 output_button = new QPushButton(tr("Browse..."));
1304 output_label->setBuddy(output_line);
1305 output_label->setToolTip(
1306 tr("<b></b>The output file, which will be essentially identical"
1307 " to the input font but will contain new, generated hints."));
1308 output_line->setCompleter(completer);
1310 control_label = new QLabel(tr("Control Instructions Fil&e:"));
1311 control_line = new Drag_Drop_Line_Edit(DRAG_DROP_ANY);
1312 control_button = new QPushButton(tr("Browse..."));
1313 control_label->setBuddy(control_line);
1314 // we use the non-breaking hyphen U+2011 (&#8209;) where necessary
1315 QString tooltip_string =
1316 tr("<p>An optional control instructions file to tweak hinting"
1317 " and to override glyph assignments to styles."
1318 " This text file contains entries"
1319 " of one of the following syntax forms"
1320 " (with brackets indicating optional elements).<br>"
1321 "&nbsp;<br>"
1323 "&nbsp;&nbsp;[&nbsp;<i>subfont&#8209;idx</i>&nbsp;]"
1324 "&nbsp;&nbsp;<i>script</i>"
1325 "&nbsp;&nbsp;<i>feature</i>"
1326 "&nbsp;&nbsp;<tt>@</tt>&nbsp;<i>glyph&#8209;ids</i><br>"
1328 "&nbsp;&nbsp;[&nbsp;<i>subfont&#8209;idx</i>&nbsp;]"
1329 "&nbsp;&nbsp;<i>glyph&#8209;id</i>"
1330 "&nbsp;&nbsp;<tt>left</tt>&nbsp;|&nbsp;<tt>right</tt>&nbsp;<i>points</i>"
1331 "&nbsp;&nbsp;[&nbsp;<tt>(</tt><i>left&#8209;offset</i><tt>,"
1332 "</tt><i>right&#8209;offset</i><tt>)</tt>&nbsp;]<br>"
1334 "&nbsp;&nbsp;[&nbsp;<i>subfont&#8209;idx</i>&nbsp;]"
1335 "&nbsp;&nbsp;<i>glyph&#8209;id</i>"
1336 "&nbsp;&nbsp;<tt>nodir</tt>&nbsp;<i>points</i><br>"
1338 "&nbsp;&nbsp;[&nbsp;<i>subfont&#8209;idx</i>&nbsp;]"
1339 "&nbsp;&nbsp;<i>glyph&#8209;id</i>"
1340 "&nbsp;&nbsp;<tt>touch</tt>&nbsp;|&nbsp;<tt>point</tt>&nbsp;<i>points</i>"
1341 "&nbsp;&nbsp;[&nbsp;<tt>xshift</tt>&nbsp;<i>shift</i>&nbsp;]"
1342 "&nbsp;&nbsp;[&nbsp;<tt>yshift</tt>&nbsp;<i>shift</i>&nbsp;]"
1343 "&nbsp;&nbsp;<tt>@</tt>&nbsp;<i>ppems</i><br>"
1344 "&nbsp;<br>"
1346 "<i>subfont&#8209;idx</i> gives the subfont index in a TTC,"
1347 " <i>glyph&#8209;id</i> is a glyph name or index.<br>"
1348 "&nbsp;<br>"
1350 "<i>script</i> and <i>feature</i> are four-letter tags"
1351 " that define a style the <i>glyph&#8209;ids</i> are assigned to."
1352 " <i>glyph&#8209;ids</i> is a comma-separated list of"
1353 " <i>glyph&#8209;id</i> values and value ranges.<br>");
1355 tooltip_string += tr("Possible values for <i>script</i> are ");
1356 const Tag_Names* sn = script_names;
1357 for(;;)
1359 tooltip_string += QString::fromLocal8Bit("<tt>%1</tt> (%2)")
1360 .arg(sn->tag)
1361 .arg(sn->description);
1362 sn++;
1363 if (sn->tag)
1364 tooltip_string += ", ";
1365 else
1367 tooltip_string += ".<br>";
1368 break;
1372 tooltip_string += tr("Possible values for <i>feature</i> are ");
1373 const Tag_Names* fn = feature_names;
1374 for(;;)
1376 tooltip_string += QString::fromLocal8Bit("<tt>%1</tt> (%2)")
1377 .arg(fn->tag)
1378 .arg(fn->description);
1379 fn++;
1380 if (fn->tag)
1381 tooltip_string += ", ";
1382 else
1384 tooltip_string += ".<br>";
1385 break;
1389 tooltip_string += "&nbsp;<br>";
1391 tooltip_string +=
1392 tr("<tt>left</tt> (<tt>right</tt>) creates one-point segments"
1393 " with direction left (right), possibly having a width (in font units)"
1394 " given by <i>left&#8209;offset</i> and <i>right&#8209;offset</i>"
1395 " relative to the corresponding points.<br>"
1396 "&nbsp;<br>"
1398 "<tt>nodir</tt> removes points from horizontal segments,"
1399 " making them <i>weak</i> points.<br>"
1400 "&nbsp;<br>"
1402 "<tt>touch </tt> (<tt>point</tt>) defines delta exceptions"
1403 " to be applied before (after) the final"
1404 " <tt>IUP</tt> bytecode instructions."
1405 " <tt>touch</tt> also touches points, making them <i>strong</i>."
1406 " In ClearType mode, <tt>point</tt> and <tt>xshift</tt>"
1407 " have no effect.<br>"
1408 "&nbsp;<br>"
1410 "x and y <i>shift</i> values are in the range [-1;1],"
1411 " rounded to multiples of 1/8px.<br>"
1413 "<i>points</i> and <i>ppems</i> are ranges for point indices"
1414 " and ppem values as with x&nbsp;height snapping exceptions.<br>"
1416 "Keywords <tt>left</tt>, <tt>right</tt>, <tt>nodir</tt>,"
1417 " <tt>point</tt>, <tt>touch</tt>, <tt>xshift</tt>, and"
1418 " <tt>yshift</tt> can be abbreviated as <tt>l</tt>, <tt>r</tt>,"
1419 " <tt>n</tt>, <tt>p</tt>, <tt>t</tt>, <tt>x</tt>, and <tt>y</tt>,"
1420 " respectively.<br>"
1422 "Control instruction entries are separated"
1423 " by character&nbsp;<tt>;</tt> or by a newline.<br>"
1425 "A trailing character&nbsp;<tt>\\</tt> continues the current line"
1426 " on the next line.<br>"
1428 "<tt>#</tt> starts a line comment, which gets ignored."
1429 " Empty lines are ignored, too.</p>"
1431 "Examples:<br>"
1432 "&nbsp;&nbsp;<tt>cyrl sups @ one.sups-nine.sups, zero.sups</tt><br>"
1433 "&nbsp;&nbsp;<tt>Q left 38 (-70,20)</tt><br>"
1434 "&nbsp;&nbsp;<tt>Adieresis touch 3-6 yshift 0.25 @ 13</tt>");
1436 control_label->setToolTip(tooltip_string);
1437 control_line->setCompleter(completer);
1440 // minmax controls
1442 min_label = new QLabel(tr("Hint Set Range Mi&nimum:"));
1443 min_box = new QSpinBox;
1444 min_label->setBuddy(min_box);
1445 min_label->setToolTip(
1446 tr("The minimum PPEM value of the range for which"
1447 " <b>TTFautohint</b> computes <i>hint sets</i>."
1448 " A hint set for a given PPEM value hints this size optimally."
1449 " The larger the range, the more hint sets are considered,"
1450 " usually increasing the size of the bytecode.<br>"
1451 "Note that changing this range doesn't influence"
1452 " the <i>gasp</i> table:"
1453 " Hinting is enabled for all sizes."));
1454 min_box->setKeyboardTracking(false);
1455 min_box->setRange(2, 10000);
1457 max_label = new QLabel(tr("Hint Set Range Ma&ximum:"));
1458 max_box = new QSpinBox;
1459 max_label->setBuddy(max_box);
1460 max_label->setToolTip(
1461 tr("The maximum PPEM value of the range for which"
1462 " <b>TTFautohint</b> computes <i>hint sets</i>."
1463 " A hint set for a given PPEM value hints this size optimally."
1464 " The larger the range, the more hint sets are considered,"
1465 " usually increasing the size of the bytecode.<br>"
1466 "Note that changing this range doesn't influence"
1467 " the <i>gasp</i> table:"
1468 " Hinting is enabled for all sizes."));
1469 max_box->setKeyboardTracking(false);
1470 max_box->setRange(2, 10000);
1473 // OpenType default script
1475 default_label = new QLabel(tr("Defa&ult Script:"));
1476 default_box = new QComboBox;
1477 default_label->setBuddy(default_box);
1478 default_label->setToolTip(
1479 tr("This sets the default script for OpenType features:"
1480 " After applying all features that are handled specially"
1481 " (for example small caps or superscript glyphs),"
1482 " <b>TTFautohint</b> uses this value for the remaining features."));
1483 for (int i = 0; script_names[i].tag; i++)
1485 // XXX: how to provide translations?
1486 default_box->insertItem(i,
1487 QString("%1 (%2)")
1488 .arg(script_names[i].tag)
1489 .arg(script_names[i].description));
1493 // hinting and fallback controls
1495 fallback_label = new QLabel(tr("Fallbac&k Script"));
1496 fallback_hint_or_scale_box = new QComboBox;
1497 fallback_box = new QComboBox;
1498 fallback_label->setBuddy(fallback_hint_or_scale_box);
1499 fallback_label->setToolTip(
1500 tr("This sets the fallback script for glyphs"
1501 " that <b>TTFautohint</b> can't map to a script automatically."
1502 " Either hinting with the script's blue zone values"
1503 " or simple scaling with the script's scaling value"
1504 " can be selected."));
1505 fallback_hint_or_scale_box->insertItem(fallback_do_scale, tr("Scaling:"));
1506 fallback_hint_or_scale_box->insertItem(fallback_do_hint, tr("Hinting:"));
1507 for (int i = 0; script_names[i].tag; i++)
1509 // XXX: how to provide translations?
1510 fallback_box->insertItem(i,
1511 QString("%1 (%2)")
1512 .arg(script_names[i].tag)
1513 .arg(script_names[i].description));
1517 // hinting limit
1519 limit_label_text_with_key = tr("Hinting &Limit:");
1520 limit_label_text = tr("Hinting Limit:");
1521 limit_label = new QLabel(limit_label_text_with_key);
1522 limit_box = new QSpinBox;
1523 limit_label->setBuddy(limit_box);
1524 limit_label->setToolTip(
1525 tr("Switch off hinting for PPEM values exceeding this limit."
1526 " Changing this value does not influence the size of the bytecode.<br>"
1527 "Note that <b>TTFautohint</b> handles this feature"
1528 " in the output font's bytecode and not in the <i>gasp</i> table."));
1529 limit_box->setKeyboardTracking(false);
1530 limit_box->setRange(2, 10000);
1532 no_limit_box_text_with_key = tr("No Hinting &Limit");
1533 no_limit_box_text = tr("No Hinting Limit");
1534 no_limit_box = new QCheckBox(no_limit_box_text);
1535 no_limit_box->setToolTip(
1536 tr("If switched on, <b>TTFautohint</b> adds no hinting limit"
1537 " to the bytecode.<br>"
1538 "For testing only."));
1541 // x height increase limit
1543 increase_label_text_with_key = tr("x Height In&crease Limit:");
1544 increase_label_text = tr("x Height Increase Limit:");
1545 increase_label = new QLabel(increase_label_text_with_key);
1546 increase_box = new QSpinBox;
1547 increase_label->setBuddy(increase_box);
1548 increase_label->setToolTip(
1549 tr("For PPEM values in the range 6&nbsp;&le; PPEM &le;&nbsp;<i>n</i>,"
1550 " where <i>n</i> is the value selected by this spin box,"
1551 " round up the font's x&nbsp;height much more often than normally.<br>"
1552 "Use this if holes in letters like <i>e</i> get filled,"
1553 " for example."));
1554 increase_box->setKeyboardTracking(false);
1555 increase_box->setRange(6, 10000);
1557 no_increase_box_text_with_key = tr("No x Height In&crease");
1558 no_increase_box_text = tr("No x Height Increase");
1559 no_increase_box = new QCheckBox(no_increase_box_text);
1560 no_increase_box->setToolTip(
1561 tr("If switched on,"
1562 " <b>TTFautohint</b> does not increase the x&nbsp;height."));
1565 // x height snapping exceptions
1567 snapping_label = new QLabel(tr("x Height Snapping Excep&tions:"));
1568 snapping_line = new Tooltip_Line_Edit;
1569 snapping_label->setBuddy(snapping_line);
1570 snapping_label->setToolTip(
1571 tr("<p>A list of comma separated PPEM values or value ranges"
1572 " at which no x&nbsp;height snapping shall be applied"
1573 " (x&nbsp;height snapping usually slightly increases"
1574 " the size of all glyphs).</p>"
1576 "Examples:<br>"
1577 "&nbsp;&nbsp;<tt>2, 3-5, 12-17</tt><br>"
1578 "&nbsp;&nbsp;<tt>-20, 40-</tt>"
1579 " (meaning PPEM &le; 20 or PPEM &ge; 40)<br>"
1580 "&nbsp;&nbsp;<tt>-</tt> (meaning all possible PPEM values)"));
1583 // family suffix
1585 family_suffix_label = new QLabel(tr("Family Suffix&:"));
1586 family_suffix_line = new Tooltip_Line_Edit;
1587 family_suffix_label->setBuddy(family_suffix_line);
1588 family_suffix_label->setToolTip(
1589 tr("A string that gets appended to the family name entries"
1590 " (name IDs 1, 4, 6, 16, and&nbsp;21)"
1591 " in the font's <i>name</i> table.<br>"
1592 "Mainly for testing purposes, enabling the operating system"
1593 " to display fonts simultaneously that are hinted"
1594 " with different <b>TTFautohint</b> parameters."));
1597 // fallback stem width
1599 stem_width_label_text_with_key = tr("Fallback &Stem Width:");
1600 stem_width_label_text = tr("Fallback Stem Width:");
1601 stem_width_label = new QLabel(stem_width_label_text_with_key);
1602 stem_width_box = new QSpinBox;
1603 stem_width_label->setBuddy(stem_width_box);
1604 stem_width_label->setToolTip(
1605 tr("Set horizontal stem width (in font units) for all scripts"
1606 " that lack proper standard characters in the font.<br>"
1607 "If not set, <b>TTFautohint</b> uses a hard-coded default value."));
1608 stem_width_box->setKeyboardTracking(false);
1609 stem_width_box->setRange(1, 10000);
1611 default_stem_width_box_text_with_key = tr("Default Fallback &Stem Width");
1612 default_stem_width_box_text = tr("Default Fallback Stem Width");
1613 default_stem_width_box = new QCheckBox(default_stem_width_box_text);
1614 default_stem_width_box->setToolTip(
1615 tr("If switched on, <b>TTFautohint</b> uses a default value"
1616 " for the fallback stem width (50 font units at 2048 UPEM)."));
1619 // flags
1621 wincomp_box = new QCheckBox(tr("Windows Com&patibility"));
1622 wincomp_box->setToolTip(
1623 tr("If switched on, add two artificial blue zones positioned at the"
1624 " <tt>usWinAscent</tt> and <tt>usWinDescent</tt> values"
1625 " (from the font's <i>OS/2</i> table)."
1626 " This option, usually in combination"
1627 " with value <tt>-</tt> (a single dash)"
1628 " for the <i>x&nbsp;Height Snapping Exceptions</i> option,"
1629 " should be used if those two <i>OS/2</i> values are tight,"
1630 " and you are experiencing clipping during rendering."));
1632 adjust_box = new QCheckBox(tr("Ad&just Subglyphs"));
1633 adjust_box->setToolTip(
1634 tr("If switched on, the original bytecode of the input font"
1635 " gets applied (at EM size, usually 2048ppem)"
1636 " to derive the glyph outlines for <b>TTFautohint</b>.<br>"
1637 "Use this option only if subglyphs"
1638 " are incorrectly scaled and shifted.<br>"
1639 "Note that the original bytecode will always be discarded."));
1641 hint_box = new QCheckBox(tr("Hint Co&mposites")
1642 + " "); // make label wider
1643 hint_box->setToolTip(
1644 tr("If switched on, <b>TTFautohint</b> hints composite glyphs"
1645 " as a whole, including subglyphs."
1646 " Otherwise, glyph components get hinted separately.<br>"
1647 "Deactivating this flag reduces the bytecode size enormously,"
1648 " however, it might yield worse results."));
1650 symbol_box = new QCheckBox(tr("S&ymbol Font"));
1651 symbol_box->setToolTip(
1652 tr("If switched on, <b>TTFautohint</b> accepts fonts"
1653 " that don't contain a single standard character"
1654 " for any of the supported scripts.<br>"
1655 "Use this for symbol or dingbat fonts, for example."));
1657 dehint_box = new QCheckBox(tr("&Dehint"));
1658 dehint_box->setToolTip(
1659 tr("If set, remove all hints from the font.<br>"
1660 "For testing only."));
1662 info_label = new QLabel(tr("ttf&autohint Info:"));
1663 info_box = new QComboBox;
1664 info_label->setBuddy(info_box);
1665 info_label->setToolTip(
1666 tr("Specify which information about <b>TTFautohint</b>"
1667 " and its calling parameters gets added to the version string(s)"
1668 " (name ID&nbsp;5) in the <i>name</i> table."));
1669 info_box->insertItem(0, tr("None"));
1670 info_box->insertItem(1, tr("Version"));
1671 info_box->insertItem(2, tr("Version and Parameters"));
1673 TTFA_box = new QCheckBox(tr("Add TTFA Info Ta&ble"));
1674 TTFA_box->setToolTip(
1675 tr("If switched on, an SFNT table called <i>TTFA</i>"
1676 " gets added to the output font,"
1677 " holding a dump of all parameters."
1678 " In particular, it lists all control instructions."));
1681 // stem width and positioning
1683 stem_label = new QLabel(tr("Stron&g Stem Width and Positioning:"));
1684 stem_label->setToolTip(
1685 tr("<b>TTFautohint</b> provides two different hinting algorithms"
1686 " that can be selected for various hinting modes."
1688 "<p><i>strong</i> (checkbox set):"
1689 " Position horizontal stems and snap stem widths"
1690 " to integer pixel values. While making the output look crisper,"
1691 " outlines become more distorted.</p>"
1693 "<p><i>smooth</i> (checkbox not set):"
1694 " Use discrete values for horizontal stems and stem widths."
1695 " This only slightly increases the contrast"
1696 " but avoids larger outline distortion.</p>"));
1698 gray_box = new QCheckBox(tr("Grayscale"));
1699 gray_box->setToolTip(
1700 tr("<b></b>Grayscale rendering, no ClearType activated."));
1701 stem_label->setBuddy(gray_box);
1703 gdi_box = new QCheckBox(tr("GDI ClearType"));
1704 gdi_box->setToolTip(
1705 tr("GDI ClearType rendering,"
1706 " introduced in 2000 for Windows XP.<br>"
1707 "The rasterizer version (as returned by the"
1708 " GETINFO bytecode instruction) is in the range"
1709 " 36&nbsp;&le; version &lt;&nbsp;38, and ClearType is enabled.<br>"
1710 "Along the vertical axis, this mode behaves like B/W rendering."));
1712 dw_box = new QCheckBox(tr("DW ClearType"));
1713 dw_box->setToolTip(
1714 tr("DirectWrite ClearType rendering,"
1715 " introduced in 2008 for Windows Vista.<br>"
1716 "The rasterizer version (as returned by the"
1717 " GETINFO bytecode instruction) is &ge;&nbsp;38,"
1718 " ClearType is enabled, and subpixel positioning is enabled also.<br>"
1719 "Smooth rendering along the vertical axis."));
1722 // running
1724 watch_box = new QCheckBox(tr("&Watch Input Files"));
1725 watch_box->setToolTip(
1726 tr("If switched on, <b>TTFautohint</b> automatically re-runs"
1727 " the hinting process as soon as an input file"
1728 " (either the font or the control instructions file) is modified.<br>"
1729 "Pressing the %1 button starts watching.<br>"
1730 "If an error occurs, watching stops and must be restarted"
1731 " with the %1 button.")
1732 .arg(QUOTE_STRING_LITERAL(tr("Run"))));
1734 run_button = new QPushButton(" "
1735 + tr("&Run")
1736 + " "); // make label wider
1738 if (horizontal_layout)
1739 create_horizontal_layout();
1740 else
1741 create_vertical_layout();
1745 // XXX distances are specified in pixels,
1746 // making the layout dependent on the output device resolution
1747 void
1748 Main_GUI::create_vertical_layout()
1750 // top area
1751 QGridLayout* file_layout = new QGridLayout;
1753 file_layout->addWidget(input_label, 0, 0, Qt::AlignRight);
1754 file_layout->addWidget(input_line, 0, 1);
1755 file_layout->addWidget(input_button, 0, 2);
1757 file_layout->setRowStretch(1, 1);
1759 file_layout->addWidget(output_label, 2, 0, Qt::AlignRight);
1760 file_layout->addWidget(output_line, 2, 1);
1761 file_layout->addWidget(output_button, 2, 2);
1763 file_layout->setRowStretch(3, 1);
1765 file_layout->addWidget(control_label, 4, 0, Qt::AlignRight);
1766 file_layout->addWidget(control_line, 4, 1);
1767 file_layout->addWidget(control_button, 4, 2);
1769 // bottom area
1770 QGridLayout* run_layout = new QGridLayout;
1772 run_layout->addWidget(watch_box, 0, 1);
1773 run_layout->addWidget(run_button, 0, 3, Qt::AlignRight);
1774 run_layout->setColumnStretch(0, 1);
1775 run_layout->setColumnStretch(2, 2);
1778 // the whole gui
1780 QGridLayout* gui_layout = new QGridLayout;
1781 QFrame* hline = new QFrame;
1782 hline->setFrameShape(QFrame::HLine);
1783 int row = 0; // this counter simplifies inserting new items
1785 gui_layout->setRowMinimumHeight(row, 10); // XXX urgh, pixels...
1786 gui_layout->setRowStretch(row++, 1);
1788 gui_layout->addLayout(file_layout, row, 0, row, -1);
1789 gui_layout->setRowStretch(row++, 1);
1791 gui_layout->addWidget(hline, row, 0, row, -1);
1792 gui_layout->setRowStretch(row++, 1);
1794 gui_layout->setRowMinimumHeight(row, 20); // XXX urgh, pixels...
1795 gui_layout->setRowStretch(row++, 1);
1797 gui_layout->addWidget(min_label, row, 0, Qt::AlignRight);
1798 gui_layout->addWidget(min_box, row++, 1, Qt::AlignLeft);
1799 gui_layout->addWidget(max_label, row, 0, Qt::AlignRight);
1800 gui_layout->addWidget(max_box, row++, 1, Qt::AlignLeft);
1802 gui_layout->setRowMinimumHeight(row, 20); // XXX urgh, pixels...
1803 gui_layout->setRowStretch(row++, 1);
1805 gui_layout->addWidget(default_label, row, 0, Qt::AlignRight);
1806 gui_layout->addWidget(default_box, row++, 1, Qt::AlignLeft);
1808 QGridLayout* fallback_layout = new QGridLayout;
1809 fallback_layout->addWidget(fallback_label, 0, 0, Qt::AlignRight);
1810 fallback_layout->addWidget(fallback_hint_or_scale_box, 0, 1, Qt::AlignLeft);
1812 gui_layout->addLayout(fallback_layout, row++, 0, Qt::AlignRight);
1813 gui_layout->addWidget(fallback_box, row++, 1, Qt::AlignLeft);
1815 gui_layout->setRowMinimumHeight(row, 20); // XXX urgh, pixels...
1816 gui_layout->setRowStretch(row++, 1);
1818 gui_layout->addWidget(limit_label, row, 0, Qt::AlignRight);
1819 gui_layout->addWidget(limit_box, row++, 1, Qt::AlignLeft);
1820 gui_layout->addWidget(no_limit_box, row++, 1);
1822 gui_layout->addWidget(increase_label, row, 0, Qt::AlignRight);
1823 gui_layout->addWidget(increase_box, row++, 1, Qt::AlignLeft);
1824 gui_layout->addWidget(no_increase_box, row++, 1);
1826 gui_layout->addWidget(snapping_label, row, 0, Qt::AlignRight);
1827 gui_layout->addWidget(snapping_line, row++, 1, Qt::AlignLeft);
1829 gui_layout->addWidget(stem_width_label, row, 0, Qt::AlignRight);
1830 gui_layout->addWidget(stem_width_box, row++, 1, Qt::AlignLeft);
1831 gui_layout->addWidget(default_stem_width_box, row++, 1);
1833 gui_layout->setRowMinimumHeight(row, 20); // XXX urgh, pixels...
1834 gui_layout->setRowStretch(row++, 1);
1836 gui_layout->addWidget(wincomp_box, row++, 1);
1837 gui_layout->addWidget(adjust_box, row++, 1);
1838 gui_layout->addWidget(hint_box, row++, 1);
1839 gui_layout->addWidget(symbol_box, row++, 1);
1840 gui_layout->addWidget(dehint_box, row++, 1);
1842 gui_layout->addWidget(info_label, row, 0, Qt::AlignRight);
1843 gui_layout->addWidget(info_box, row++, 1, Qt::AlignLeft);
1844 gui_layout->addWidget(TTFA_box, row++, 1);
1845 gui_layout->addWidget(family_suffix_label, row, 0, Qt::AlignRight);
1846 gui_layout->addWidget(family_suffix_line, row++, 1, Qt::AlignLeft);
1848 gui_layout->setRowMinimumHeight(row, 20); // XXX urgh, pixels...
1849 gui_layout->setRowStretch(row++, 1);
1851 gui_layout->addWidget(stem_label, row, 0, Qt::AlignRight);
1852 gui_layout->addWidget(gray_box, row++, 1);
1853 gui_layout->addWidget(gdi_box, row++, 1);
1854 gui_layout->addWidget(dw_box, row++, 1);
1856 gui_layout->setRowMinimumHeight(row, 30); // XXX urgh, pixels...
1857 gui_layout->setRowStretch(row++, 1);
1859 gui_layout->addLayout(run_layout, row, 0, row, -1);
1861 // create dummy widget to register layout
1862 QWidget* main_widget = new QWidget;
1863 main_widget->setLayout(gui_layout);
1864 setCentralWidget(main_widget);
1865 setWindowTitle("TTFautohint");
1869 // XXX distances are specified in pixels,
1870 // making the layout dependent on the output device resolution
1871 void
1872 Main_GUI::create_horizontal_layout()
1874 // top area
1875 QGridLayout* file_layout = new QGridLayout;
1877 file_layout->addWidget(input_label, 0, 0, Qt::AlignRight);
1878 file_layout->addWidget(input_line, 0, 1);
1879 file_layout->addWidget(input_button, 0, 2);
1881 file_layout->setRowStretch(1, 1);
1883 file_layout->addWidget(output_label, 2, 0, Qt::AlignRight);
1884 file_layout->addWidget(output_line, 2, 1);
1885 file_layout->addWidget(output_button, 2, 2);
1887 file_layout->setRowStretch(3, 1);
1889 file_layout->addWidget(control_label, 4, 0, Qt::AlignRight);
1890 file_layout->addWidget(control_line, 4, 1);
1891 file_layout->addWidget(control_button, 4, 2);
1893 // bottom area
1894 QGridLayout* run_layout = new QGridLayout;
1896 run_layout->addWidget(watch_box, 0, 1);
1897 run_layout->addWidget(run_button, 0, 3, Qt::AlignRight);
1898 run_layout->setColumnStretch(0, 2);
1899 run_layout->setColumnStretch(2, 3);
1900 run_layout->setColumnStretch(4, 1);
1903 // the whole gui
1905 QGridLayout* gui_layout = new QGridLayout;
1906 QFrame* hline = new QFrame;
1907 hline->setFrameShape(QFrame::HLine);
1908 int row = 0; // this counter simplifies inserting new items
1910 // margin
1911 gui_layout->setColumnMinimumWidth(0, 10); // XXX urgh, pixels...
1912 gui_layout->setColumnStretch(0, 1);
1914 // left
1915 gui_layout->setRowMinimumHeight(row, 10); // XXX urgh, pixels...
1916 gui_layout->setRowStretch(row++, 1);
1918 gui_layout->addLayout(file_layout, row, 0, row, -1);
1919 gui_layout->setRowStretch(row++, 1);
1921 gui_layout->addWidget(hline, row, 0, row, -1);
1922 gui_layout->setRowStretch(row++, 1);
1924 gui_layout->setRowMinimumHeight(row, 20); // XXX urgh, pixels...
1925 gui_layout->setRowStretch(row++, 1);
1927 gui_layout->addWidget(min_label, row, 1, Qt::AlignRight);
1928 gui_layout->addWidget(min_box, row++, 2, Qt::AlignLeft);
1929 gui_layout->addWidget(max_label, row, 1, Qt::AlignRight);
1930 gui_layout->addWidget(max_box, row++, 2, Qt::AlignLeft);
1932 gui_layout->setRowMinimumHeight(row, 20); // XXX urgh, pixels...
1933 gui_layout->setRowStretch(row++, 1);
1935 gui_layout->addWidget(default_label, row, 1, Qt::AlignRight);
1936 gui_layout->addWidget(default_box, row++, 2, Qt::AlignLeft);
1938 QGridLayout* fallback_layout = new QGridLayout;
1939 fallback_layout->addWidget(fallback_label, 0, 0, Qt::AlignRight);
1940 fallback_layout->addWidget(fallback_hint_or_scale_box, 0, 1, Qt::AlignLeft);
1942 gui_layout->addLayout(fallback_layout, row, 1, Qt::AlignRight);
1943 gui_layout->addWidget(fallback_box, row++, 2, Qt::AlignLeft);
1945 gui_layout->setRowMinimumHeight(row, 20); // XXX urgh, pixels...
1946 gui_layout->setRowStretch(row++, 1);
1948 gui_layout->addWidget(limit_label, row, 1, Qt::AlignRight);
1949 gui_layout->addWidget(limit_box, row++, 2, Qt::AlignLeft);
1950 gui_layout->addWidget(no_limit_box, row++, 2);
1952 gui_layout->addWidget(increase_label, row, 1, Qt::AlignRight);
1953 gui_layout->addWidget(increase_box, row++, 2, Qt::AlignLeft);
1954 gui_layout->addWidget(no_increase_box, row++, 2);
1956 gui_layout->addWidget(snapping_label, row, 1, Qt::AlignRight);
1957 gui_layout->addWidget(snapping_line, row++, 2, Qt::AlignLeft);
1959 gui_layout->addWidget(stem_width_label, row, 1, Qt::AlignRight);
1960 gui_layout->addWidget(stem_width_box, row++, 2, Qt::AlignLeft);
1961 gui_layout->addWidget(default_stem_width_box, row++, 2);
1963 gui_layout->setRowMinimumHeight(row, 30); // XXX urgh, pixels...
1964 gui_layout->setRowStretch(row++, 1);
1966 gui_layout->addLayout(run_layout, row, 0, row, -1);
1968 // column separator
1969 gui_layout->setColumnMinimumWidth(3, 20); // XXX urgh, pixels...
1970 gui_layout->setColumnStretch(3, 1);
1972 // right
1973 row = 4;
1974 gui_layout->addWidget(wincomp_box, row++, 4);
1975 gui_layout->addWidget(adjust_box, row++, 4);
1976 gui_layout->addWidget(hint_box, row++, 4);
1977 gui_layout->addWidget(symbol_box, row++, 4);
1978 gui_layout->addWidget(dehint_box, row++, 4);
1980 gui_layout->addWidget(info_label, row, 3, Qt::AlignRight);
1981 gui_layout->addWidget(info_box, row++, 4, Qt::AlignLeft);
1982 gui_layout->addWidget(TTFA_box, row++, 4);
1983 gui_layout->addWidget(family_suffix_label, row, 3, Qt::AlignRight);
1984 gui_layout->addWidget(family_suffix_line, row++, 4, Qt::AlignLeft);
1986 gui_layout->setRowMinimumHeight(row, 20); // XXX urgh, pixels...
1987 gui_layout->setRowStretch(row++, 1);
1989 gui_layout->addWidget(stem_label, row++, 4);
1991 QGridLayout* stem_layout = new QGridLayout;
1992 stem_layout->setColumnMinimumWidth(0, 20); // XXX urgh, pixels...
1993 stem_layout->addWidget(gray_box, 0, 1);
1994 stem_layout->addWidget(gdi_box, 1, 1);
1995 stem_layout->addWidget(dw_box, 2, 1);
1997 gui_layout->addLayout(stem_layout, row, 4, 3, 1);
1998 row += 3;
2000 // margin
2001 gui_layout->setColumnMinimumWidth(5, 10); // XXX urgh, pixels...
2002 gui_layout->setColumnStretch(5, 1);
2004 // create dummy widget to register layout
2005 QWidget* main_widget = new QWidget;
2006 main_widget->setLayout(gui_layout);
2007 setCentralWidget(main_widget);
2008 setWindowTitle("TTFautohint");
2012 void
2013 Main_GUI::create_connections()
2015 connect(input_button, SIGNAL(clicked()),
2016 SLOT(browse_input()));
2017 connect(output_button, SIGNAL(clicked()),
2018 SLOT(browse_output()));
2019 connect(control_button, SIGNAL(clicked()),
2020 SLOT(browse_control()));
2022 connect(input_line, SIGNAL(textChanged(QString)),
2023 SLOT(check_run()));
2024 connect(output_line, SIGNAL(textChanged(QString)),
2025 SLOT(check_run()));
2027 connect(input_line, SIGNAL(editingFinished()),
2028 SLOT(absolute_input()));
2029 connect(output_line, SIGNAL(editingFinished()),
2030 SLOT(absolute_output()));
2031 connect(control_line, SIGNAL(editingFinished()),
2032 SLOT(absolute_control()));
2034 connect(min_box, SIGNAL(valueChanged(int)),
2035 SLOT(check_min()));
2036 connect(max_box, SIGNAL(valueChanged(int)),
2037 SLOT(check_max()));
2039 connect(limit_box, SIGNAL(valueChanged(int)),
2040 SLOT(check_limit()));
2041 connect(no_limit_box, SIGNAL(clicked()),
2042 SLOT(check_no_limit()));
2044 connect(no_increase_box, SIGNAL(clicked()),
2045 SLOT(check_no_increase()));
2047 connect(snapping_line, SIGNAL(editingFinished()),
2048 SLOT(check_number_set()));
2049 connect(snapping_line, SIGNAL(textEdited(QString)),
2050 SLOT(clear_status_bar()));
2052 connect(family_suffix_line, SIGNAL(editingFinished()),
2053 SLOT(check_family_suffix()));
2054 connect(family_suffix_line, SIGNAL(textEdited(QString)),
2055 SLOT(clear_status_bar()));
2057 connect(default_stem_width_box, SIGNAL(clicked()),
2058 SLOT(check_default_stem_width()));
2060 connect(dehint_box, SIGNAL(clicked()),
2061 SLOT(check_dehint()));
2063 connect(file_watcher, SIGNAL(fileChanged(const QString&)),
2064 SLOT(start_timer()));
2065 connect(timer, SIGNAL(timeout()),
2066 SLOT(watch_files()));
2068 connect(watch_box, SIGNAL(clicked()),
2069 SLOT(check_watch()));
2071 connect(run_button, SIGNAL(clicked()),
2072 SLOT(run()));
2076 void
2077 Main_GUI::create_actions()
2079 exit_act = new QAction(tr("E&xit"), this);
2080 exit_act->setShortcuts(QKeySequence::Quit);
2081 connect(exit_act, SIGNAL(triggered()), SLOT(close()));
2083 about_act = new QAction(tr("&About"), this);
2084 connect(about_act, SIGNAL(triggered()), SLOT(about()));
2086 about_Qt_act = new QAction(tr("About &Qt"), this);
2087 connect(about_Qt_act, SIGNAL(triggered()), qApp, SLOT(aboutQt()));
2091 void
2092 Main_GUI::create_menus()
2094 file_menu = menuBar()->addMenu(tr("&File"));
2095 file_menu->addAction(exit_act);
2097 help_menu = menuBar()->addMenu(tr("&Help"));
2098 help_menu->addAction(about_act);
2099 help_menu->addAction(about_Qt_act);
2103 void
2104 Main_GUI::create_status_bar()
2106 statusBar()->showMessage("");
2110 void
2111 Main_GUI::set_defaults()
2113 min_box->setValue(hinting_range_min);
2114 max_box->setValue(hinting_range_max);
2116 default_box->setCurrentIndex(default_script_idx);
2117 fallback_hint_or_scale_box->setCurrentIndex(fallback_scaling);
2118 fallback_box->setCurrentIndex(fallback_script_idx);
2120 limit_box->setValue(hinting_limit ? hinting_limit : hinting_range_max);
2121 // handle command line option `--hinting-limit=0'
2122 if (!hinting_limit)
2124 hinting_limit = max_box->value();
2125 no_limit_box->setChecked(true);
2128 increase_box->setValue(increase_x_height ? increase_x_height
2129 : TA_INCREASE_X_HEIGHT);
2130 // handle command line option `--increase-x-height=0'
2131 if (!increase_x_height)
2133 increase_x_height = TA_INCREASE_X_HEIGHT;
2134 no_increase_box->setChecked(true);
2137 snapping_line->setText(x_height_snapping_exceptions_string);
2138 family_suffix_line->setText(family_suffix);
2140 if (fallback_stem_width)
2141 stem_width_box->setValue(fallback_stem_width);
2142 else
2144 stem_width_box->setValue(50);
2145 default_stem_width_box->setChecked(true);
2148 if (windows_compatibility)
2149 wincomp_box->setChecked(true);
2150 if (adjust_subglyphs)
2151 adjust_box->setChecked(true);
2152 if (hint_composites)
2153 hint_box->setChecked(true);
2154 if (symbol)
2155 symbol_box->setChecked(true);
2156 if (dehint)
2157 dehint_box->setChecked(true);
2158 if (no_info)
2159 info_box->setCurrentIndex(0);
2160 else if (detailed_info)
2161 info_box->setCurrentIndex(2);
2162 else
2163 info_box->setCurrentIndex(1);
2164 if (TTFA_info)
2165 TTFA_box->setChecked(true);
2167 if (gray_strong_stem_width)
2168 gray_box->setChecked(true);
2169 if (gdi_cleartype_strong_stem_width)
2170 gdi_box->setChecked(true);
2171 if (dw_cleartype_strong_stem_width)
2172 dw_box->setChecked(true);
2174 run_button->setEnabled(false);
2176 check_min();
2177 check_max();
2178 check_limit();
2180 check_no_limit();
2181 check_no_increase();
2182 check_number_set();
2184 check_watch();
2186 // do this last since it disables almost everything
2187 check_dehint();
2191 void
2192 Main_GUI::read_settings()
2194 QSettings settings;
2195 // QPoint pos = settings.value("pos", QPoint(200, 200)).toPoint();
2196 // QSize size = settings.value("size", QSize(400, 400)).toSize();
2197 // resize(size);
2198 // move(pos);
2202 void
2203 Main_GUI::write_settings()
2205 QSettings settings;
2206 // settings.setValue("pos", pos());
2207 // settings.setValue("size", size());
2210 // end of maingui.cpp