[gui] Handle defaults and command line options in a separate function.
[ttfautohint.git] / frontend / maingui.cpp
blob5984e5bca750b1e47c10db3e887256375f7618f7
1 // maingui.cpp
3 // Copyright (C) 2012 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>
20 #include <QtGui>
22 #include "info.h"
23 #include "maingui.h"
25 #include <ttfautohint.h>
28 // XXX Qt 4.8 bug: locale->quoteString("foo")
29 // inserts wrongly encoded quote characters
30 // into rich text QString
31 #if HAVE_QT_QUOTESTRING
32 # define QUOTE_STRING(x) locale->quoteString(x)
33 # define QUOTE_STRING_LITERAL(x) locale->quoteString(x)
34 #else
35 # define QUOTE_STRING(x) "\"" + x + "\""
36 # define QUOTE_STRING_LITERAL(x) "\"" x "\""
37 #endif
40 Main_GUI::Main_GUI(int range_min,
41 int range_max,
42 int limit,
43 bool gray,
44 bool gdi,
45 bool dw,
46 int increase,
47 bool ignore,
48 bool wincomp,
49 bool pre,
50 bool components,
51 bool no,
52 int fallback,
53 bool symb)
54 : hinting_range_min(range_min),
55 hinting_range_max(range_max),
56 hinting_limit(limit),
57 gray_strong_stem_width(gray),
58 gdi_cleartype_strong_stem_width(gdi),
59 dw_cleartype_strong_stem_width(dw),
60 increase_x_height(increase),
61 ignore_restrictions(ignore),
62 windows_compatibility(wincomp),
63 pre_hinting(pre),
64 hint_with_components(components),
65 no_info(no),
66 latin_fallback(fallback),
67 symbol(symb)
69 create_layout();
70 create_connections();
71 create_actions();
72 create_menus();
73 create_status_bar();
75 set_defaults();
76 read_settings();
78 setUnifiedTitleAndToolBarOnMac(true);
80 // XXX register translations somewhere and loop over them
81 if (QLocale::system().name() == "en_US")
82 locale = new QLocale;
83 else
84 locale = new QLocale(QLocale::C);
88 // overloading
90 void
91 Main_GUI::closeEvent(QCloseEvent* event)
93 write_settings();
94 event->accept();
98 void
99 Main_GUI::about()
101 QMessageBox::about(this,
102 tr("About TTFautohint"),
103 tr("<p>This is <b>TTFautohint</b> version %1<br>"
104 " Copyright %2 2011-2012<br>"
105 " by Werner Lemberg <tt>&lt;wl@gnu.org&gt;</tt></p>"
107 "<p><b>TTFautohint</b> adds new auto-generated hints"
108 " to a TrueType font or TrueType collection.</p>"
110 "<p>License:"
111 " <a href='http://www.freetype.org/FTL.TXT'>FreeType"
112 " License (FTL)</a> or"
113 " <a href='http://www.freetype.org/GPL.TXT'>GNU"
114 " GPLv2</a></p>")
115 .arg(VERSION)
116 .arg(QChar(0xA9)));
120 void
121 Main_GUI::browse_input()
123 // XXX remember last directory
124 QString file = QFileDialog::getOpenFileName(
125 this,
126 tr("Open Input File"),
127 QDir::homePath(),
128 "");
129 if (!file.isEmpty())
130 input_line->setText(QDir::toNativeSeparators(file));
134 void
135 Main_GUI::browse_output()
137 // XXX remember last directory
138 QString file = QFileDialog::getSaveFileName(
139 this,
140 tr("Open Output File"),
141 QDir::homePath(),
142 "");
144 if (!file.isEmpty())
145 output_line->setText(QDir::toNativeSeparators(file));
149 void
150 Main_GUI::check_min()
152 int min = min_box->value();
153 int max = max_box->value();
154 int limit = limit_box->value();
155 if (min > max)
156 max_box->setValue(min);
157 if (min > limit)
158 limit_box->setValue(min);
162 void
163 Main_GUI::check_max()
165 int min = min_box->value();
166 int max = max_box->value();
167 int limit = limit_box->value();
168 if (max < min)
169 min_box->setValue(max);
170 if (max > limit)
171 limit_box->setValue(max);
175 void
176 Main_GUI::check_limit()
178 int min = min_box->value();
179 int max = max_box->value();
180 int limit = limit_box->value();
181 if (limit < max)
182 max_box->setValue(limit);
183 if (limit < min)
184 min_box->setValue(limit);
188 void
189 Main_GUI::check_no_limit()
191 if (no_limit_box->isChecked())
193 limit_label->setEnabled(false);
194 limit_box->setEnabled(false);
196 else
198 limit_label->setEnabled(true);
199 limit_box->setEnabled(true);
204 void
205 Main_GUI::check_no_increase()
207 if (no_increase_box->isChecked())
209 increase_label->setEnabled(false);
210 increase_box->setEnabled(false);
212 else
214 increase_label->setEnabled(true);
215 increase_box->setEnabled(true);
220 void
221 Main_GUI::check_run()
223 if (input_line->text().isEmpty() || output_line->text().isEmpty())
224 run_button->setEnabled(false);
225 else
226 run_button->setEnabled(true);
230 void
231 Main_GUI::absolute_input()
233 QString input_name = QDir::fromNativeSeparators(input_line->text());
234 if (!input_name.isEmpty()
235 && QDir::isRelativePath(input_name))
237 QDir cur_path(QDir::currentPath() + "/" + input_name);
238 input_line->setText(QDir::toNativeSeparators(cur_path.absolutePath()));
243 void
244 Main_GUI::absolute_output()
246 QString output_name = QDir::fromNativeSeparators(output_line->text());
247 if (!output_name.isEmpty()
248 && QDir::isRelativePath(output_name))
250 QDir cur_path(QDir::currentPath() + "/" + output_name);
251 output_line->setText(QDir::toNativeSeparators(cur_path.absolutePath()));
257 Main_GUI::check_filenames(const QString& input_name,
258 const QString& output_name)
260 if (!QFile::exists(input_name))
262 QMessageBox::warning(
263 this,
264 "TTFautohint",
265 tr("The file %1 cannot be found.")
266 .arg(QUOTE_STRING(QDir::toNativeSeparators(input_name))),
267 QMessageBox::Ok,
268 QMessageBox::Ok);
269 return 0;
272 if (input_name == output_name)
274 QMessageBox::warning(
275 this,
276 "TTFautohint",
277 tr("Input and output file names must be different."),
278 QMessageBox::Ok,
279 QMessageBox::Ok);
280 return 0;
283 if (QFile::exists(output_name))
285 int ret = QMessageBox::warning(
286 this,
287 "TTFautohint",
288 tr("The file %1 already exists.\n"
289 "Overwrite?")
290 .arg(QUOTE_STRING(QDir::toNativeSeparators(output_name))),
291 QMessageBox::Yes | QMessageBox::No,
292 QMessageBox::No);
293 if (ret == QMessageBox::No)
294 return 0;
297 return 1;
302 Main_GUI::open_files(const QString& input_name,
303 FILE** in,
304 const QString& output_name,
305 FILE** out)
307 const int buf_len = 1024;
308 char buf[buf_len];
310 *in = fopen(qPrintable(input_name), "rb");
311 if (!*in)
313 strerror_r(errno, buf, buf_len);
314 QMessageBox::warning(
315 this,
316 "TTFautohint",
317 tr("The following error occurred while opening input file %1:\n")
318 .arg(QUOTE_STRING(QDir::toNativeSeparators(input_name)))
319 + QString::fromLocal8Bit(buf),
320 QMessageBox::Ok,
321 QMessageBox::Ok);
322 return 0;
325 *out = fopen(qPrintable(output_name), "wb");
326 if (!*out)
328 strerror_r(errno, buf, buf_len);
329 QMessageBox::warning(
330 this,
331 "TTFautohint",
332 tr("The following error occurred while opening output file %1:\n")
333 .arg(QUOTE_STRING(QDir::toNativeSeparators(output_name)))
334 + QString::fromLocal8Bit(buf),
335 QMessageBox::Ok,
336 QMessageBox::Ok);
337 return 0;
340 return 1;
344 extern "C" {
346 struct GUI_Progress_Data
348 long last_sfnt;
349 bool begin;
350 QProgressDialog* dialog;
355 gui_progress(long curr_idx,
356 long num_glyphs,
357 long curr_sfnt,
358 long num_sfnts,
359 void* user)
361 GUI_Progress_Data* data = (GUI_Progress_Data*)user;
363 if (num_sfnts > 1 && curr_sfnt != data->last_sfnt)
365 data->dialog->setLabelText(QCoreApplication::translate(
366 "GuiProgress",
367 "Auto-hinting subfont %1 of %2"
368 " with %3 glyphs...")
369 .arg(curr_sfnt + 1)
370 .arg(num_sfnts)
371 .arg(num_glyphs));
373 if (curr_sfnt + 1 == num_sfnts)
375 data->dialog->setAutoReset(true);
376 data->dialog->setAutoClose(true);
378 else
380 data->dialog->setAutoReset(false);
381 data->dialog->setAutoClose(false);
384 data->last_sfnt = curr_sfnt;
385 data->begin = true;
388 if (data->begin)
390 if (num_sfnts == 1)
391 data->dialog->setLabelText(QCoreApplication::translate(
392 "GuiProgress",
393 "Auto-hinting %1 glyphs...")
394 .arg(num_glyphs));
395 data->dialog->setMaximum(num_glyphs - 1);
397 data->begin = false;
400 data->dialog->setValue(curr_idx);
402 if (data->dialog->wasCanceled())
403 return 1;
405 return 0;
408 } // extern "C"
411 // return value 1 indicates a retry
414 Main_GUI::handle_error(TA_Error error,
415 const unsigned char* error_string,
416 QString output_name)
418 int ret = 0;
420 if (error == TA_Err_Canceled)
422 else if (error == TA_Err_Invalid_FreeType_Version)
423 QMessageBox::critical(
424 this,
425 "TTFautohint",
426 tr("FreeType version 2.4.5 or higher is needed.\n"
427 "Are you perhaps using a wrong FreeType DLL?"),
428 QMessageBox::Ok,
429 QMessageBox::Ok);
430 else if (error == TA_Err_Invalid_Font_Type)
431 QMessageBox::warning(
432 this,
433 "TTFautohint",
434 tr("This font is not a valid font"
435 " in SFNT format with TrueType outlines.\n"
436 "In particular, CFF outlines are not supported."),
437 QMessageBox::Ok,
438 QMessageBox::Ok);
439 else if (error == TA_Err_Already_Processed)
440 QMessageBox::warning(
441 this,
442 "TTFautohint",
443 tr("This font has already been processed by TTFautohint."),
444 QMessageBox::Ok,
445 QMessageBox::Ok);
446 else if (error == TA_Err_Missing_Legal_Permission)
448 int yesno = QMessageBox::warning(
449 this,
450 "TTFautohint",
451 tr("Bit 1 in the %1 field of the %2 table is set:"
452 " This font must not be modified"
453 " without permission of the legal owner.\n"
454 "Do you have such a permission?")
455 .arg(QUOTE_STRING_LITERAL("fsType"))
456 .arg(QUOTE_STRING_LITERAL("OS/2")),
457 QMessageBox::Yes | QMessageBox::No,
458 QMessageBox::No);
459 if (yesno == QMessageBox::Yes)
461 ignore_restrictions = true;
462 ret = 1;
465 else if (error == TA_Err_Missing_Unicode_CMap)
466 QMessageBox::warning(
467 this,
468 "TTFautohint",
469 tr("No Unicode character map."),
470 QMessageBox::Ok,
471 QMessageBox::Ok);
472 else if (error == TA_Err_Missing_Symbol_CMap)
473 QMessageBox::warning(
474 this,
475 "TTFautohint",
476 tr("No symbol character map."),
477 QMessageBox::Ok,
478 QMessageBox::Ok);
479 else if (error == TA_Err_Missing_Glyph)
480 QMessageBox::warning(
481 this,
482 "TTFautohint",
483 tr("No glyph for the key character"
484 " to derive standard stem width and height.\n"
485 "For the latin script, this key character is %1 (U+006F).\n"
486 "\n"
487 "Set the %2 checkbox if you want to circumvent this test.")
488 .arg(QUOTE_STRING_LITERAL("o"))
489 .arg(QUOTE_STRING_LITERAL("symbol")),
490 QMessageBox::Ok,
491 QMessageBox::Ok);
492 else
493 QMessageBox::warning(
494 this,
495 "TTFautohint",
496 tr("Error code 0x%1 while autohinting font:\n")
497 .arg(error, 2, 16, QLatin1Char('0'))
498 + QString::fromLocal8Bit((const char*)error_string),
499 QMessageBox::Ok,
500 QMessageBox::Ok);
502 if (QFile::exists(output_name) && remove(qPrintable(output_name)))
504 const int buf_len = 1024;
505 char buf[buf_len];
507 strerror_r(errno, buf, buf_len);
508 QMessageBox::warning(
509 this,
510 "TTFautohint",
511 tr("The following error occurred while removing output file %1:\n")
512 .arg(QUOTE_STRING(QDir::toNativeSeparators(output_name)))
513 + QString::fromLocal8Bit(buf),
514 QMessageBox::Ok,
515 QMessageBox::Ok);
518 return ret;
522 void
523 Main_GUI::run()
525 statusBar()->clearMessage();
527 QString input_name = QDir::fromNativeSeparators(input_line->text());
528 QString output_name = QDir::fromNativeSeparators(output_line->text());
529 if (!check_filenames(input_name, output_name))
530 return;
532 // we need C file descriptors for communication with TTF_autohint
533 FILE* input;
534 FILE* output;
536 again:
537 if (!open_files(input_name, &input, output_name, &output))
538 return;
540 QProgressDialog dialog;
541 dialog.setCancelButtonText(tr("Cancel"));
542 dialog.setMinimumDuration(1000);
543 dialog.setWindowModality(Qt::WindowModal);
545 const unsigned char* error_string;
546 TA_Info_Func info_func = info;
547 GUI_Progress_Data gui_progress_data = {-1, true, &dialog};
548 Info_Data info_data;
550 info_data.data = NULL; // must be deallocated after use
551 info_data.data_wide = NULL; // must be deallocated after use
552 info_data.data_len = 0;
553 info_data.data_wide_len = 0;
555 info_data.hinting_range_min = min_box->value();
556 info_data.hinting_range_max = max_box->value();
557 info_data.hinting_limit = no_limit_box->isChecked()
559 : limit_box->value();
561 info_data.gray_strong_stem_width = gray_box->isChecked();
562 info_data.gdi_cleartype_strong_stem_width = gdi_box->isChecked();
563 info_data.dw_cleartype_strong_stem_width = dw_box->isChecked();
565 info_data.increase_x_height = no_increase_box->isChecked()
567 : increase_box->value();
569 info_data.windows_compatibility = wincomp_box->isChecked();
570 info_data.pre_hinting = pre_box->isChecked();
571 info_data.hint_with_components = hint_box->isChecked();
572 info_data.latin_fallback = fallback_box->currentIndex();
573 info_data.symbol = symbol_box->isChecked();
575 if (info_box->isChecked())
577 int ret = build_version_string(&info_data);
578 if (ret == 1)
579 QMessageBox::information(
580 this,
581 "TTFautohint",
582 tr("Can't allocate memory for <b>TTFautohint</b> options string"
583 " in <i>name</i> table."),
584 QMessageBox::Ok,
585 QMessageBox::Ok);
586 else if (ret == 2)
587 QMessageBox::information(
588 this,
589 "TTFautohint",
590 tr("<b>TTFautohint</b> options string"
591 " in <i>name</i> table too long."),
592 QMessageBox::Ok,
593 QMessageBox::Ok);
595 else
596 info_func = NULL;
598 TA_Error error =
599 TTF_autohint("in-file, out-file,"
600 "hinting-range-min, hinting-range-max,"
601 "hinting-limit,"
602 "gray-strong-stem-width,"
603 "gdi-cleartype-strong-stem-width,"
604 "dw-cleartype-strong-stem-width,"
605 "error-string,"
606 "progress-callback, progress-callback-data,"
607 "info-callback, info-callback-data,"
608 "ignore-restrictions,"
609 "windows-compatibility,"
610 "pre-hinting,"
611 "hint-with-components,"
612 "increase-x-height,"
613 "fallback-script, symbol",
614 input, output,
615 info_data.hinting_range_min, info_data.hinting_range_max,
616 info_data.hinting_limit,
617 info_data.gray_strong_stem_width,
618 info_data.gdi_cleartype_strong_stem_width,
619 info_data.dw_cleartype_strong_stem_width,
620 &error_string,
621 gui_progress, &gui_progress_data,
622 info_func, &info_data,
623 ignore_restrictions,
624 info_data.windows_compatibility,
625 info_data.pre_hinting,
626 info_data.hint_with_components,
627 info_data.increase_x_height,
628 info_data.latin_fallback, info_data.symbol);
630 if (info_box->isChecked())
632 free(info_data.data);
633 free(info_data.data_wide);
636 fclose(input);
637 fclose(output);
639 if (error)
641 if (handle_error(error, error_string, output_name))
642 goto again;
644 else
645 statusBar()->showMessage(tr("Auto-hinting finished."));
649 // XXX distances are specified in pixels,
650 // making the layout dependent on the output device resolution
651 void
652 Main_GUI::create_layout()
655 // file stuff
657 QCompleter* completer = new QCompleter(this);
658 QFileSystemModel* model = new QFileSystemModel(completer);
659 model->setRootPath(QDir::rootPath());
660 completer->setModel(model);
662 QLabel* input_label = new QLabel(tr("&Input File:"));
663 input_line = new Line_Edit;
664 input_button = new QPushButton(tr("Browse..."));
665 input_label->setBuddy(input_line);
666 // enforce rich text to get nice word wrapping
667 input_label->setToolTip(
668 tr("<b></b>The input file, either a TrueType font (TTF),"
669 " TrueType collection (TTC), or a TrueType-based OpenType font."));
670 input_line->setCompleter(completer);
672 QLabel* output_label = new QLabel(tr("&Output File:"));
673 output_line = new Line_Edit;
674 output_button = new QPushButton(tr("Browse..."));
675 output_label->setBuddy(output_line);
676 output_label->setToolTip(
677 tr("<b></b>The output file, which will be essentially identical"
678 " to the input font but will contain new, generated hints."));
679 output_line->setCompleter(completer);
681 // layout
682 QGridLayout* file_layout = new QGridLayout;
684 file_layout->addWidget(input_label, 0, 0, Qt::AlignRight);
685 file_layout->addWidget(input_line, 0, 1);
686 file_layout->addWidget(input_button, 0, 2);
688 file_layout->setRowStretch(1, 1);
690 file_layout->addWidget(output_label, 2, 0, Qt::AlignRight);
691 file_layout->addWidget(output_line, 2, 1);
692 file_layout->addWidget(output_button, 2, 2);
695 // minmax controls
697 QLabel* min_label = new QLabel(tr("Hint Set Range Mi&nimum:"));
698 min_box = new QSpinBox;
699 min_label->setBuddy(min_box);
700 min_label->setToolTip(
701 tr("The minimum PPEM value of the range for which"
702 " <b>TTFautohint</b> computes <i>hint sets</i>."
703 " A hint set for a given PPEM value hints this size optimally."
704 " The larger the range, the more hint sets are considered,"
705 " usually increasing the size of the bytecode.<br>"
706 "Note that changing this range doesn't influence"
707 " the <i>gasp</i> table:"
708 " Hinting is enabled for all sizes."));
709 min_box->setKeyboardTracking(false);
710 min_box->setRange(2, 10000);
712 QLabel* max_label = new QLabel(tr("Hint Set Range Ma&ximum:"));
713 max_box = new QSpinBox;
714 max_label->setBuddy(max_box);
715 max_label->setToolTip(
716 tr("The maximum PPEM value of the range for which"
717 " <b>TTFautohint</b> computes <i>hint sets</i>."
718 " A hint set for a given PPEM value hints this size optimally."
719 " The larger the range, the more hint sets are considered,"
720 " usually increasing the size of the bytecode.<br>"
721 "Note that changing this range doesn't influence"
722 " the <i>gasp</i> table:"
723 " Hinting is enabled for all sizes."));
724 max_box->setKeyboardTracking(false);
725 max_box->setRange(2, 10000);
728 // hinting and fallback controls
730 QLabel* fallback_label = new QLabel(tr("Fallback &Script:"));
731 fallback_box = new QComboBox;
732 fallback_label->setBuddy(fallback_box);
733 fallback_label->setToolTip(
734 tr("This sets the fallback script module for glyphs"
735 " which <b>TTFautohint</b> can't map to a script automatically."));
736 fallback_box->insertItem(0, tr("None"));
737 fallback_box->insertItem(1, tr("Latin"));
740 // hinting limit
742 limit_label = new QLabel(tr("Hinting &Limit:"));
743 limit_box = new QSpinBox;
744 limit_label->setBuddy(limit_box);
745 limit_label->setToolTip(
746 tr("Make <b>TTFautohint</b> add bytecode to the output font so that"
747 " sizes larger than this PPEM value are not hinted"
748 " (regardless of the values in the <i>gasp</i> table)."));
749 limit_box->setKeyboardTracking(false);
750 limit_box->setRange(2, 10000);
752 no_limit_box = new QCheckBox(tr("No Hinting Limit"), this);
753 no_limit_box->setToolTip(
754 tr("If switched on, <b>TTFautohint</b> adds no hinting limit"
755 " to the bytecode."));
758 // x height increase limit
760 increase_label = new QLabel(tr("x Height In&crease Limit:"));
761 increase_box = new QSpinBox;
762 increase_label->setBuddy(increase_box);
763 increase_label->setToolTip(
764 tr("For PPEM values in the range 5&nbsp;&lt; PPEM &lt;&nbsp;<i>n</i>,"
765 " where <i>n</i> is the value selected by this spin box,"
766 " round up the font's x&nbsp;height much more often than normally.<br>"
767 "Use this if holes in letters like <i>e</i> get filled,"
768 " for example."));
769 increase_box->setKeyboardTracking(false);
770 increase_box->setRange(6, 10000);
772 no_increase_box = new QCheckBox(tr("No x Height Increase"), this);
773 no_increase_box->setToolTip(
774 tr("If switched on,"
775 " <b>TTFautohint</b> does not increase the x&nbsp;height."));
778 // flags
780 wincomp_box = new QCheckBox(tr("Windows Com&patibility"), this);
781 wincomp_box->setToolTip(
782 tr("If switched on, add two artificial blue zones positioned at the"
783 " <tt>usWinAscent</tt> and <tt>usWinDescent</tt> values"
784 " (from the font's <i>OS/2</i> table)."
785 " Use this if those values are tight,"
786 " and you are experiencing clipping during rendering."));
788 pre_box = new QCheckBox(tr("Pr&e-hinting"), this);
789 pre_box->setToolTip(
790 tr("If switched on, the original bytecode of the input font"
791 " gets applied before <b>TTFautohint</b> starts processing"
792 " the outlines of the glyphs."));
794 hint_box = new QCheckBox(tr("Hint With Co&mponents")
795 + " ", this); // make label wider
796 hint_box->setToolTip(
797 tr("If switched on, <b>TTFautohint</b> hints composite glyphs"
798 " as a whole, including subglyphs."
799 " Otherwise, glyph components get hinted separately.<br>"
800 "Deactivating this flag reduces the bytecode size enormously,"
801 " however, it might yield worse results."));
803 symbol_box = new QCheckBox(tr("S&ymbol Font"), this);
804 symbol_box->setToolTip(
805 tr("If switched on, <b>TTFautohint</b> uses default values"
806 " for standard stem width and height"
807 " instead of deriving these values from the input font.<br>"
808 "Use this for fonts which don't contain glyphs"
809 " of a (supported) script."));
811 info_box = new QCheckBox(tr("Add ttf&autohint Info"), this);
812 info_box->setToolTip(
813 tr("If switched on, information about <b>TTFautohint</b>"
814 " and its calling parameters are added to the version string(s)"
815 " (name ID&nbsp;5) in the <i>name</i> table."));
818 // stem width and positioning
820 QLabel* stem_label = new QLabel(tr("Strong Stem &Width and Positioning:"));
821 stem_label->setToolTip(
822 tr("<b>TTFautohint</b> provides two different hinting algorithms"
823 " which can be selected for various hinting modes."
825 "<p><i>strong:</i> Position horizontal stems and snap stem widths"
826 " to integer pixel values. While making the output look crisper,"
827 " outlines become more distorted.</p>"
829 "<p><i>smooth:</i> Use discrete values for horizontal stems"
830 " and stem widths. This only slightly increases the contrast"
831 " but avoids larger outline distortion.</p>"));
833 gray_box = new QCheckBox(tr("Grayscale"), this);
834 gray_box->setToolTip(
835 tr("<b></b>Grayscale rendering, no ClearType activated."));
836 stem_label->setBuddy(gray_box);
838 gdi_box = new QCheckBox(tr("GDI ClearType"), this);
839 gdi_box->setToolTip(
840 tr("GDI ClearType rendering,"
841 " introduced in 2000 for Windows XP.<br>"
842 "The rasterizer version (as returned by the"
843 " GETINFO bytecode instruction) is in the range"
844 " 36&nbsp;&le; version &lt;&nbsp;38, and ClearType is enabled.<br>"
845 "Along the vertical axis, this mode behaves like B/W rendering."));
847 dw_box = new QCheckBox(tr("DW ClearType"), this);
848 dw_box->setToolTip(
849 tr("DirectWrite ClearType rendering,"
850 " introduced in 2008 for Windows Vista.<br>"
851 "The rasterizer version (as returned by the"
852 " GETINFO bytecode instruction) is &ge;&nbsp;38,"
853 " ClearType is enabled, and subpixel positioning is enabled also.<br>"
854 "Smooth rendering along the vertical axis."));
857 // running
859 run_button = new QPushButton(" "
860 + tr("&Run")
861 + " "); // make label wider
864 // the whole gui
866 QGridLayout* gui_layout = new QGridLayout;
867 QFrame* hline = new QFrame;
868 hline->setFrameShape(QFrame::HLine);
869 int row = 0; // this counter simplifies inserting new items
871 gui_layout->setRowMinimumHeight(row, 10); // XXX urgh, pixels...
872 gui_layout->setRowStretch(row++, 1);
874 gui_layout->addLayout(file_layout, row, 0, row, -1);
875 gui_layout->setRowStretch(row++, 1);
877 gui_layout->addWidget(hline, row, 0, row, -1);
878 gui_layout->setRowStretch(row++, 1);
880 gui_layout->setRowMinimumHeight(row, 20); // XXX urgh, pixels...
881 gui_layout->setRowStretch(row++, 1);
883 gui_layout->addWidget(min_label, row, 0, Qt::AlignRight);
884 gui_layout->addWidget(min_box, row++, 1, Qt::AlignLeft);
885 gui_layout->addWidget(max_label, row, 0, Qt::AlignRight);
886 gui_layout->addWidget(max_box, row++, 1, Qt::AlignLeft);
888 gui_layout->setRowMinimumHeight(row, 20); // XXX urgh, pixels...
889 gui_layout->setRowStretch(row++, 1);
891 gui_layout->addWidget(fallback_label, row, 0, Qt::AlignRight);
892 gui_layout->addWidget(fallback_box, row++, 1, Qt::AlignLeft);
894 gui_layout->setRowMinimumHeight(row, 20); // XXX urgh, pixels...
895 gui_layout->setRowStretch(row++, 1);
897 gui_layout->addWidget(limit_label, row, 0, Qt::AlignRight);
898 gui_layout->addWidget(limit_box, row++, 1, Qt::AlignLeft);
899 gui_layout->addWidget(no_limit_box, row++, 1);
901 gui_layout->addWidget(increase_label, row, 0, Qt::AlignRight);
902 gui_layout->addWidget(increase_box, row++, 1, Qt::AlignLeft);
903 gui_layout->addWidget(no_increase_box, row++, 1);
905 gui_layout->setRowMinimumHeight(row, 20); // XXX urgh, pixels...
906 gui_layout->setRowStretch(row++, 1);
908 gui_layout->addWidget(wincomp_box, row++, 1);
909 gui_layout->addWidget(pre_box, row++, 1);
910 gui_layout->addWidget(hint_box, row++, 1);
911 gui_layout->addWidget(symbol_box, row++, 1);
912 gui_layout->addWidget(info_box, row++, 1);
914 gui_layout->setRowMinimumHeight(row, 20); // XXX urgh, pixels...
915 gui_layout->setRowStretch(row++, 1);
917 gui_layout->addWidget(stem_label, row, 0, Qt::AlignRight);
918 gui_layout->addWidget(gray_box, row++, 1);
919 gui_layout->addWidget(gdi_box, row++, 1);
920 gui_layout->addWidget(dw_box, row++, 1);
922 gui_layout->setRowMinimumHeight(row, 20); // XXX urgh, pixels...
923 gui_layout->setRowStretch(row++, 1);
925 gui_layout->addWidget(run_button, row++, 1, Qt::AlignRight);
927 // create dummy widget to register layout
928 QWidget* main_widget = new QWidget;
929 main_widget->setLayout(gui_layout);
930 setCentralWidget(main_widget);
931 setWindowTitle("TTFautohint");
935 void
936 Main_GUI::create_connections()
938 connect(input_button, SIGNAL(clicked()), this,
939 SLOT(browse_input()));
940 connect(output_button, SIGNAL(clicked()), this,
941 SLOT(browse_output()));
943 connect(input_line, SIGNAL(textChanged(QString)), this,
944 SLOT(check_run()));
945 connect(output_line, SIGNAL(textChanged(QString)), this,
946 SLOT(check_run()));
948 connect(input_line, SIGNAL(editingFinished()), this,
949 SLOT(absolute_input()));
950 connect(output_line, SIGNAL(editingFinished()), this,
951 SLOT(absolute_output()));
953 connect(min_box, SIGNAL(valueChanged(int)), this,
954 SLOT(check_min()));
955 connect(max_box, SIGNAL(valueChanged(int)), this,
956 SLOT(check_max()));
958 connect(limit_box, SIGNAL(valueChanged(int)), this,
959 SLOT(check_limit()));
960 connect(no_limit_box, SIGNAL(clicked()), this,
961 SLOT(check_no_limit()));
963 connect(no_increase_box, SIGNAL(clicked()), this,
964 SLOT(check_no_increase()));
966 connect(run_button, SIGNAL(clicked()), this,
967 SLOT(run()));
971 void
972 Main_GUI::create_actions()
974 exit_act = new QAction(tr("E&xit"), this);
975 exit_act->setShortcuts(QKeySequence::Quit);
976 connect(exit_act, SIGNAL(triggered()), this, SLOT(close()));
978 about_act = new QAction(tr("&About"), this);
979 connect(about_act, SIGNAL(triggered()), this, SLOT(about()));
981 about_Qt_act = new QAction(tr("About &Qt"), this);
982 connect(about_Qt_act, SIGNAL(triggered()), qApp, SLOT(aboutQt()));
986 void
987 Main_GUI::create_menus()
989 file_menu = menuBar()->addMenu(tr("&File"));
990 file_menu->addAction(exit_act);
992 help_menu = menuBar()->addMenu(tr("&Help"));
993 help_menu->addAction(about_act);
994 help_menu->addAction(about_Qt_act);
998 void
999 Main_GUI::create_status_bar()
1001 statusBar()->showMessage("");
1005 void
1006 Main_GUI::set_defaults()
1008 min_box->setValue(hinting_range_min);
1009 max_box->setValue(hinting_range_max);
1011 fallback_box->setCurrentIndex(latin_fallback);
1013 limit_box->setValue(hinting_limit ? hinting_limit : hinting_range_max);
1014 // handle command line option `--hinting-limit=0'
1015 if (!hinting_limit)
1017 hinting_limit = max_box->value();
1018 no_limit_box->setChecked(true);
1021 increase_box->setValue(increase_x_height ? increase_x_height
1022 : TA_INCREASE_X_HEIGHT);
1023 // handle command line option `--increase-x-height=0'
1024 if (!increase_x_height)
1026 increase_x_height = TA_INCREASE_X_HEIGHT;
1027 no_increase_box->setChecked(true);
1030 if (windows_compatibility)
1031 wincomp_box->setChecked(true);
1032 if (pre_hinting)
1033 pre_box->setChecked(true);
1034 if (hint_with_components)
1035 hint_box->setChecked(true);
1036 if (symbol)
1037 symbol_box->setChecked(true);
1038 if (!no_info)
1039 info_box->setChecked(true);
1041 if (gray_strong_stem_width)
1042 gray_box->setChecked(true);
1043 if (gdi_cleartype_strong_stem_width)
1044 gdi_box->setChecked(true);
1045 if (dw_cleartype_strong_stem_width)
1046 dw_box->setChecked(true);
1048 run_button->setEnabled(false);
1050 check_min();
1051 check_max();
1052 check_limit();
1054 check_no_limit();
1055 check_no_increase();
1059 void
1060 Main_GUI::read_settings()
1062 QSettings settings;
1063 // QPoint pos = settings.value("pos", QPoint(200, 200)).toPoint();
1064 // QSize size = settings.value("size", QSize(400, 400)).toSize();
1065 // resize(size);
1066 // move(pos);
1070 void
1071 Main_GUI::write_settings()
1073 QSettings settings;
1074 // settings.setValue("pos", pos());
1075 // settings.setValue("size", size());
1078 // end of maingui.cpp