Initialize properties of `globals' object.
[ttfautohint.git] / frontend / maingui.cpp
blob4f14d5a5b481b713afdeff19f6e565b0e62baeff
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 read_settings();
77 setUnifiedTitleAndToolBarOnMac(true);
79 // XXX register translations somewhere and loop over them
80 if (QLocale::system().name() == "en_US")
81 locale = new QLocale;
82 else
83 locale = new QLocale(QLocale::C);
87 // overloading
89 void
90 Main_GUI::closeEvent(QCloseEvent* event)
92 write_settings();
93 event->accept();
97 void
98 Main_GUI::about()
100 QMessageBox::about(this,
101 tr("About TTFautohint"),
102 tr("<p>This is <b>TTFautohint</b> version %1<br>"
103 " Copyright %2 2011-2012<br>"
104 " by Werner Lemberg <tt>&lt;wl@gnu.org&gt;</tt></p>"
106 "<p><b>TTFautohint</b> adds new auto-generated hints"
107 " to a TrueType font or TrueType collection.</p>"
109 "<p>License:"
110 " <a href='http://www.freetype.org/FTL.TXT'>FreeType"
111 " License (FTL)</a> or"
112 " <a href='http://www.freetype.org/GPL.TXT'>GNU"
113 " GPLv2</a></p>")
114 .arg(VERSION)
115 .arg(QChar(0xA9)));
119 void
120 Main_GUI::browse_input()
122 // XXX remember last directory
123 QString file = QFileDialog::getOpenFileName(
124 this,
125 tr("Open Input File"),
126 QDir::homePath(),
127 "");
128 if (!file.isEmpty())
129 input_line->setText(QDir::toNativeSeparators(file));
133 void
134 Main_GUI::browse_output()
136 // XXX remember last directory
137 QString file = QFileDialog::getSaveFileName(
138 this,
139 tr("Open Output File"),
140 QDir::homePath(),
141 "");
143 if (!file.isEmpty())
144 output_line->setText(QDir::toNativeSeparators(file));
148 void
149 Main_GUI::check_min()
151 int min = min_box->value();
152 int max = max_box->value();
153 int limit = limit_box->value();
154 if (min > max)
155 max_box->setValue(min);
156 if (min > limit)
157 limit_box->setValue(min);
161 void
162 Main_GUI::check_max()
164 int min = min_box->value();
165 int max = max_box->value();
166 int limit = limit_box->value();
167 if (max < min)
168 min_box->setValue(max);
169 if (max > limit)
170 limit_box->setValue(max);
174 void
175 Main_GUI::check_limit()
177 int min = min_box->value();
178 int max = max_box->value();
179 int limit = limit_box->value();
180 if (limit < max)
181 max_box->setValue(limit);
182 if (limit < min)
183 min_box->setValue(limit);
187 void
188 Main_GUI::check_no_limit()
190 if (no_limit_box->isChecked())
192 limit_label->setEnabled(false);
193 limit_box->setEnabled(false);
195 else
197 limit_label->setEnabled(true);
198 limit_box->setEnabled(true);
203 void
204 Main_GUI::check_no_increase()
206 if (no_increase_box->isChecked())
208 increase_label->setEnabled(false);
209 increase_box->setEnabled(false);
211 else
213 increase_label->setEnabled(true);
214 increase_box->setEnabled(true);
219 void
220 Main_GUI::check_run()
222 if (input_line->text().isEmpty() || output_line->text().isEmpty())
223 run_button->setEnabled(false);
224 else
225 run_button->setEnabled(true);
229 void
230 Main_GUI::absolute_input()
232 QString input_name = QDir::fromNativeSeparators(input_line->text());
233 if (!input_name.isEmpty()
234 && QDir::isRelativePath(input_name))
236 QDir cur_path(QDir::currentPath() + "/" + input_name);
237 input_line->setText(QDir::toNativeSeparators(cur_path.absolutePath()));
242 void
243 Main_GUI::absolute_output()
245 QString output_name = QDir::fromNativeSeparators(output_line->text());
246 if (!output_name.isEmpty()
247 && QDir::isRelativePath(output_name))
249 QDir cur_path(QDir::currentPath() + "/" + output_name);
250 output_line->setText(QDir::toNativeSeparators(cur_path.absolutePath()));
256 Main_GUI::check_filenames(const QString& input_name,
257 const QString& output_name)
259 if (!QFile::exists(input_name))
261 QMessageBox::warning(
262 this,
263 "TTFautohint",
264 tr("The file %1 cannot be found.")
265 .arg(QUOTE_STRING(QDir::toNativeSeparators(input_name))),
266 QMessageBox::Ok,
267 QMessageBox::Ok);
268 return 0;
271 if (input_name == output_name)
273 QMessageBox::warning(
274 this,
275 "TTFautohint",
276 tr("Input and output file names must be different."),
277 QMessageBox::Ok,
278 QMessageBox::Ok);
279 return 0;
282 if (QFile::exists(output_name))
284 int ret = QMessageBox::warning(
285 this,
286 "TTFautohint",
287 tr("The file %1 already exists.\n"
288 "Overwrite?")
289 .arg(QUOTE_STRING(QDir::toNativeSeparators(output_name))),
290 QMessageBox::Yes | QMessageBox::No,
291 QMessageBox::No);
292 if (ret == QMessageBox::No)
293 return 0;
296 return 1;
301 Main_GUI::open_files(const QString& input_name,
302 FILE** in,
303 const QString& output_name,
304 FILE** out)
306 const int buf_len = 1024;
307 char buf[buf_len];
309 *in = fopen(qPrintable(input_name), "rb");
310 if (!*in)
312 strerror_r(errno, buf, buf_len);
313 QMessageBox::warning(
314 this,
315 "TTFautohint",
316 tr("The following error occurred while opening input file %1:\n")
317 .arg(QUOTE_STRING(QDir::toNativeSeparators(input_name)))
318 + QString::fromLocal8Bit(buf),
319 QMessageBox::Ok,
320 QMessageBox::Ok);
321 return 0;
324 *out = fopen(qPrintable(output_name), "wb");
325 if (!*out)
327 strerror_r(errno, buf, buf_len);
328 QMessageBox::warning(
329 this,
330 "TTFautohint",
331 tr("The following error occurred while opening output file %1:\n")
332 .arg(QUOTE_STRING(QDir::toNativeSeparators(output_name)))
333 + QString::fromLocal8Bit(buf),
334 QMessageBox::Ok,
335 QMessageBox::Ok);
336 return 0;
339 return 1;
343 extern "C" {
345 struct GUI_Progress_Data
347 long last_sfnt;
348 bool begin;
349 QProgressDialog* dialog;
354 gui_progress(long curr_idx,
355 long num_glyphs,
356 long curr_sfnt,
357 long num_sfnts,
358 void* user)
360 GUI_Progress_Data* data = (GUI_Progress_Data*)user;
362 if (num_sfnts > 1 && curr_sfnt != data->last_sfnt)
364 data->dialog->setLabelText(QCoreApplication::translate(
365 "GuiProgress",
366 "Auto-hinting subfont %1 of %2"
367 " with %3 glyphs...")
368 .arg(curr_sfnt + 1)
369 .arg(num_sfnts)
370 .arg(num_glyphs));
372 if (curr_sfnt + 1 == num_sfnts)
374 data->dialog->setAutoReset(true);
375 data->dialog->setAutoClose(true);
377 else
379 data->dialog->setAutoReset(false);
380 data->dialog->setAutoClose(false);
383 data->last_sfnt = curr_sfnt;
384 data->begin = true;
387 if (data->begin)
389 if (num_sfnts == 1)
390 data->dialog->setLabelText(QCoreApplication::translate(
391 "GuiProgress",
392 "Auto-hinting %1 glyphs...")
393 .arg(num_glyphs));
394 data->dialog->setMaximum(num_glyphs - 1);
396 data->begin = false;
399 data->dialog->setValue(curr_idx);
401 if (data->dialog->wasCanceled())
402 return 1;
404 return 0;
407 } // extern "C"
410 // return value 1 indicates a retry
413 Main_GUI::handle_error(TA_Error error,
414 const unsigned char* error_string,
415 QString output_name)
417 int ret = 0;
419 if (error == TA_Err_Canceled)
421 else if (error == TA_Err_Invalid_FreeType_Version)
422 QMessageBox::critical(
423 this,
424 "TTFautohint",
425 tr("FreeType version 2.4.5 or higher is needed.\n"
426 "Are you perhaps using a wrong FreeType DLL?"),
427 QMessageBox::Ok,
428 QMessageBox::Ok);
429 else if (error == TA_Err_Invalid_Font_Type)
430 QMessageBox::warning(
431 this,
432 "TTFautohint",
433 tr("This font is not a valid font"
434 " in SFNT format with TrueType outlines.\n"
435 "In particular, CFF outlines are not supported."),
436 QMessageBox::Ok,
437 QMessageBox::Ok);
438 else if (error == TA_Err_Already_Processed)
439 QMessageBox::warning(
440 this,
441 "TTFautohint",
442 tr("This font has already been processed by TTFautohint."),
443 QMessageBox::Ok,
444 QMessageBox::Ok);
445 else if (error == TA_Err_Missing_Legal_Permission)
447 int yesno = QMessageBox::warning(
448 this,
449 "TTFautohint",
450 tr("Bit 1 in the %1 field of the %2 table is set:"
451 " This font must not be modified"
452 " without permission of the legal owner.\n"
453 "Do you have such a permission?")
454 .arg(QUOTE_STRING_LITERAL("fsType"))
455 .arg(QUOTE_STRING_LITERAL("OS/2")),
456 QMessageBox::Yes | QMessageBox::No,
457 QMessageBox::No);
458 if (yesno == QMessageBox::Yes)
460 ignore_restrictions = true;
461 ret = 1;
464 else if (error == TA_Err_Missing_Unicode_CMap)
465 QMessageBox::warning(
466 this,
467 "TTFautohint",
468 tr("No Unicode character map."),
469 QMessageBox::Ok,
470 QMessageBox::Ok);
471 else if (error == TA_Err_Missing_Symbol_CMap)
472 QMessageBox::warning(
473 this,
474 "TTFautohint",
475 tr("No symbol character map."),
476 QMessageBox::Ok,
477 QMessageBox::Ok);
478 else if (error == TA_Err_Missing_Glyph)
479 QMessageBox::warning(
480 this,
481 "TTFautohint",
482 tr("No glyph for the key character"
483 " to derive standard stem width and height.\n"
484 "For the latin script, this key character is %1 (U+006F).\n"
485 "\n"
486 "Set the %2 checkbox if you want to circumvent this test.")
487 .arg(QUOTE_STRING_LITERAL("o"))
488 .arg(QUOTE_STRING_LITERAL("symbol")),
489 QMessageBox::Ok,
490 QMessageBox::Ok);
491 else
492 QMessageBox::warning(
493 this,
494 "TTFautohint",
495 tr("Error code 0x%1 while autohinting font:\n")
496 .arg(error, 2, 16, QLatin1Char('0'))
497 + QString::fromLocal8Bit((const char*)error_string),
498 QMessageBox::Ok,
499 QMessageBox::Ok);
501 if (QFile::exists(output_name) && remove(qPrintable(output_name)))
503 const int buf_len = 1024;
504 char buf[buf_len];
506 strerror_r(errno, buf, buf_len);
507 QMessageBox::warning(
508 this,
509 "TTFautohint",
510 tr("The following error occurred while removing output file %1:\n")
511 .arg(QUOTE_STRING(QDir::toNativeSeparators(output_name)))
512 + QString::fromLocal8Bit(buf),
513 QMessageBox::Ok,
514 QMessageBox::Ok);
517 return ret;
521 void
522 Main_GUI::run()
524 statusBar()->clearMessage();
526 QString input_name = QDir::fromNativeSeparators(input_line->text());
527 QString output_name = QDir::fromNativeSeparators(output_line->text());
528 if (!check_filenames(input_name, output_name))
529 return;
531 // we need C file descriptors for communication with TTF_autohint
532 FILE* input;
533 FILE* output;
535 again:
536 if (!open_files(input_name, &input, output_name, &output))
537 return;
539 unsigned char version_data[128];
540 unsigned char version_data_wide[256];
542 QProgressDialog dialog;
543 dialog.setCancelButtonText(tr("Cancel"));
544 dialog.setMinimumDuration(1000);
545 dialog.setWindowModality(Qt::WindowModal);
547 const unsigned char* error_string;
548 TA_Info_Func info_func = info;
549 GUI_Progress_Data gui_progress_data = {-1, true, &dialog};
550 Info_Data info_data;
552 info_data.data = version_data;
553 info_data.data_wide = version_data_wide;
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())
576 build_version_string(&info_data);
577 else
578 info_func = NULL;
580 TA_Error error =
581 TTF_autohint("in-file, out-file,"
582 "hinting-range-min, hinting-range-max,"
583 "hinting-limit,"
584 "gray-strong-stem-width,"
585 "gdi-cleartype-strong-stem-width,"
586 "dw-cleartype-strong-stem-width,"
587 "error-string,"
588 "progress-callback, progress-callback-data,"
589 "info-callback, info-callback-data,"
590 "ignore-restrictions,"
591 "windows-compatibility,"
592 "pre-hinting,"
593 "hint-with-components,"
594 "increase-x-height,"
595 "fallback-script, symbol",
596 input, output,
597 info_data.hinting_range_min, info_data.hinting_range_max,
598 info_data.hinting_limit,
599 info_data.gray_strong_stem_width,
600 info_data.gdi_cleartype_strong_stem_width,
601 info_data.dw_cleartype_strong_stem_width,
602 &error_string,
603 gui_progress, &gui_progress_data,
604 info_func, &info_data,
605 ignore_restrictions,
606 info_data.windows_compatibility,
607 info_data.pre_hinting,
608 info_data.hint_with_components,
609 info_data.increase_x_height,
610 info_data.latin_fallback, info_data.symbol);
612 fclose(input);
613 fclose(output);
615 if (error)
617 if (handle_error(error, error_string, output_name))
618 goto again;
620 else
621 statusBar()->showMessage(tr("Auto-hinting finished."));
625 // XXX distances are specified in pixels,
626 // making the layout dependent on the output device resolution
627 void
628 Main_GUI::create_layout()
631 // file stuff
633 QCompleter* completer = new QCompleter(this);
634 QFileSystemModel* model = new QFileSystemModel(completer);
635 model->setRootPath(QDir::rootPath());
636 completer->setModel(model);
638 QLabel* input_label = new QLabel(tr("&Input File:"));
639 input_line = new Line_Edit;
640 input_button = new QPushButton(tr("Browse..."));
641 input_label->setBuddy(input_line);
642 // enforce rich text to get nice word wrapping
643 input_label->setToolTip(
644 tr("<b></b>The input file, either a TrueType font (TTF),"
645 " TrueType collection (TTC), or a TrueType-based OpenType font."));
646 input_line->setCompleter(completer);
648 QLabel* output_label = new QLabel(tr("&Output File:"));
649 output_line = new Line_Edit;
650 output_button = new QPushButton(tr("Browse..."));
651 output_label->setBuddy(output_line);
652 output_label->setToolTip(
653 tr("<b></b>The output file, which will be essentially identical"
654 " to the input font but will contain new, generated hints."));
655 output_line->setCompleter(completer);
657 // layout
658 QGridLayout* file_layout = new QGridLayout;
660 file_layout->addWidget(input_label, 0, 0, Qt::AlignRight);
661 file_layout->addWidget(input_line, 0, 1);
662 file_layout->addWidget(input_button, 0, 2);
664 file_layout->setRowStretch(1, 1);
666 file_layout->addWidget(output_label, 2, 0, Qt::AlignRight);
667 file_layout->addWidget(output_line, 2, 1);
668 file_layout->addWidget(output_button, 2, 2);
671 // minmax controls
673 QLabel* min_label = new QLabel(tr("Hint Set Range Mi&nimum:"));
674 min_box = new QSpinBox;
675 min_label->setBuddy(min_box);
676 min_label->setToolTip(
677 tr("The minimum PPEM value of the range for which"
678 " <b>TTFautohint</b> computes <i>hint sets</i>."
679 " A hint set for a given PPEM value hints this size optimally."
680 " The larger the range, the more hint sets are considered,"
681 " usually increasing the size of the bytecode.<br>"
682 "Note that changing this range doesn't influence"
683 " the <i>gasp</i> table:"
684 " Hinting is enabled for all sizes."));
685 min_box->setKeyboardTracking(false);
686 min_box->setRange(2, 10000);
687 min_box->setValue(hinting_range_min);
689 QLabel* max_label = new QLabel(tr("Hint Set Range Ma&ximum:"));
690 max_box = new QSpinBox;
691 max_label->setBuddy(max_box);
692 max_label->setToolTip(
693 tr("The maximum PPEM value of the range for which"
694 " <b>TTFautohint</b> computes <i>hint sets</i>."
695 " A hint set for a given PPEM value hints this size optimally."
696 " The larger the range, the more hint sets are considered,"
697 " usually increasing the size of the bytecode.<br>"
698 "Note that changing this range doesn't influence"
699 " the <i>gasp</i> table:"
700 " Hinting is enabled for all sizes."));
701 max_box->setKeyboardTracking(false);
702 max_box->setRange(2, 10000);
703 max_box->setValue(hinting_range_max);
706 // hinting and fallback controls
708 QLabel* fallback_label = new QLabel(tr("Fallback &Script:"));
709 fallback_box = new QComboBox;
710 fallback_label->setBuddy(fallback_box);
711 fallback_label->setToolTip(
712 tr("This sets the fallback script module for glyphs"
713 " which <b>TTFautohint</b> can't map to a script automatically."));
714 fallback_box->insertItem(0, tr("None"));
715 fallback_box->insertItem(1, tr("Latin"));
716 fallback_box->setCurrentIndex(latin_fallback);
719 // hinting limit
721 limit_label = new QLabel(tr("Hinting &Limit:"));
722 limit_box = new QSpinBox;
723 limit_label->setBuddy(limit_box);
724 limit_label->setToolTip(
725 tr("Make <b>TTFautohint</b> add bytecode to the output font so that"
726 " sizes larger than this PPEM value are not hinted"
727 " (regardless of the values in the <i>gasp</i> table)."));
728 limit_box->setKeyboardTracking(false);
729 limit_box->setRange(2, 10000);
730 limit_box->setValue(hinting_limit ? hinting_limit : hinting_range_max);
732 no_limit_box = new QCheckBox(tr("No Hinting Limit"), this);
733 no_limit_box->setToolTip(
734 tr("If switched on, <b>TTFautohint</b> adds no hinting limit"
735 " to the bytecode."));
737 // handle command line option `--hinting-limit=0'
738 if (!hinting_limit)
740 hinting_limit = max_box->value();
741 no_limit_box->setChecked(true);
745 // x height increase limit
747 increase_label = new QLabel(tr("x Height In&crease Limit:"));
748 increase_box = new QSpinBox;
749 increase_label->setBuddy(increase_box);
750 increase_label->setToolTip(
751 tr("For PPEM values in the range 5&nbsp;&lt; PPEM &lt;&nbsp;<i>n</i>,"
752 " where <i>n</i> is the value selected by this spin box,"
753 " round up the font's x&nbsp;height much more often than normally.<br>"
754 "Use this if holes in letters like <i>e</i> get filled,"
755 " for example."));
756 increase_box->setKeyboardTracking(false);
757 increase_box->setRange(6, 10000);
758 increase_box->setValue(increase_x_height ? increase_x_height
759 : TA_INCREASE_X_HEIGHT);
761 no_increase_box = new QCheckBox(tr("No x Height Increase"), this);
762 no_increase_box->setToolTip(
763 tr("If switched on,"
764 " <b>TTFautohint</b> does not increase the x&nbsp;height."));
766 // handle command line option `--increase-x-height=0'
767 if (!increase_x_height)
769 increase_x_height = TA_INCREASE_X_HEIGHT;
770 no_increase_box->setChecked(true);
773 check_min();
774 check_max();
775 check_limit();
777 check_no_limit();
778 check_no_increase();
781 // flags
783 wincomp_box = new QCheckBox(tr("Windows Com&patibility"), this);
784 wincomp_box->setToolTip(
785 tr("If switched on, add two artificial blue zones positioned at the"
786 " <tt>usWinAscent</tt> and <tt>usWinDescent</tt> values"
787 " (from the font's <i>OS/2</i> table)."
788 " Use this if those values are tight,"
789 " and you are experiencing clipping during rendering."));
790 if (windows_compatibility)
791 wincomp_box->setChecked(true);
793 pre_box = new QCheckBox(tr("Pr&e-hinting"), this);
794 pre_box->setToolTip(
795 tr("If switched on, the original bytecode of the input font"
796 " gets applied before <b>TTFautohint</b> starts processing"
797 " the outlines of the glyphs."));
798 if (pre_hinting)
799 pre_box->setChecked(true);
801 hint_box = new QCheckBox(tr("Hint &With Components")
802 + " ", this); // make label wider
803 hint_box->setToolTip(
804 tr("If switched on, <b>TTFautohint</b> hints composite glyphs"
805 " as a whole, including subglyphs."
806 " Otherwise, glyph components get hinted separately.<br>"
807 "Deactivating this flag reduces the bytecode size enormously,"
808 " however, it might yield worse results."));
809 if (hint_with_components)
810 hint_box->setChecked(true);
812 symbol_box = new QCheckBox(tr("S&ymbol Font"), this);
813 symbol_box->setToolTip(
814 tr("If switched on, <b>TTFautohint</b> uses default values"
815 " for standard stem width and height"
816 " instead of deriving these values from the input font.<br>"
817 "Use this for fonts which don't contain glyphs"
818 " of a (supported) script."));
819 if (symbol)
820 symbol_box->setChecked(true);
822 info_box = new QCheckBox(tr("Add ttf&autohint Info"), this);
823 info_box->setToolTip(
824 tr("If switched on, information about <b>TTFautohint</b>"
825 " and its calling parameters are added to the version string(s)"
826 " (name ID&nbsp;5) in the <i>name</i> table."));
827 if (!no_info)
828 info_box->setChecked(true);
831 // stem width and positioning
833 QLabel* stem_label = new QLabel(tr("Strong Stem &Width and Positioning:"));
834 stem_label->setToolTip(
835 tr("<b>TTFautohint</b> provides two different hinting algorithms"
836 " which can be selected for various hinting modes."
838 "<p><i>strong:</i> Position horizontal stems and snap stem widths"
839 " to integer pixel values. While making the output look crisper,"
840 " outlines become more distorted.</p>"
842 "<p><i>smooth:</i> Use discrete values for horizontal stems"
843 " and stem widths. This only slightly increases the contrast"
844 " but avoids larger outline distortion.</p>"));
846 gray_box = new QCheckBox(tr("Grayscale"), this);
847 gray_box->setToolTip(
848 tr("<b></b>Grayscale rendering, no ClearType activated."));
849 if (gray_strong_stem_width)
850 gray_box->setChecked(true);
852 stem_label->setBuddy(gray_box);
854 gdi_box = new QCheckBox(tr("GDI ClearType"), this);
855 gdi_box->setToolTip(
856 tr("GDI ClearType rendering,"
857 " introduced in 2000 for Windows XP.<br>"
858 "The rasterizer version (as returned by the"
859 " GETINFO bytecode instruction) is in the range"
860 " 36&nbsp;&le; version &lt;&nbsp;38, and ClearType is enabled.<br>"
861 "Along the vertical axis, this mode behaves like B/W rendering."));
862 if (gdi_cleartype_strong_stem_width)
863 gdi_box->setChecked(true);
865 dw_box = new QCheckBox(tr("DW ClearType"), this);
866 dw_box->setToolTip(
867 tr("DirectWrite ClearType rendering,"
868 " introduced in 2008 for Windows Vista.<br>"
869 "The rasterizer version (as returned by the"
870 " GETINFO bytecode instruction) is &ge;&nbsp;38,"
871 " ClearType is enabled, and subpixel positioning is enabled also.<br>"
872 "Smooth rendering along the vertical axis."));
873 if (dw_cleartype_strong_stem_width)
874 dw_box->setChecked(true);
877 // running
879 run_button = new QPushButton(" "
880 + tr("&Run")
881 + " "); // make label wider
882 run_button->setEnabled(false);
885 // the whole gui
887 QGridLayout* gui_layout = new QGridLayout;
888 QFrame* hline = new QFrame;
889 hline->setFrameShape(QFrame::HLine);
890 int row = 0; // this counter simplifies inserting new items
892 gui_layout->setRowMinimumHeight(row, 10); // XXX urgh, pixels...
893 gui_layout->setRowStretch(row++, 1);
895 gui_layout->addLayout(file_layout, row, 0, row, -1);
896 gui_layout->setRowStretch(row++, 1);
898 gui_layout->addWidget(hline, row, 0, row, -1);
899 gui_layout->setRowStretch(row++, 1);
901 gui_layout->setRowMinimumHeight(row, 20); // XXX urgh, pixels...
902 gui_layout->setRowStretch(row++, 1);
904 gui_layout->addWidget(min_label, row, 0, Qt::AlignRight);
905 gui_layout->addWidget(min_box, row++, 1, Qt::AlignLeft);
906 gui_layout->addWidget(max_label, row, 0, Qt::AlignRight);
907 gui_layout->addWidget(max_box, row++, 1, Qt::AlignLeft);
909 gui_layout->setRowMinimumHeight(row, 20); // XXX urgh, pixels...
910 gui_layout->setRowStretch(row++, 1);
912 gui_layout->addWidget(fallback_label, row, 0, Qt::AlignRight);
913 gui_layout->addWidget(fallback_box, row++, 1, Qt::AlignLeft);
915 gui_layout->setRowMinimumHeight(row, 20); // XXX urgh, pixels...
916 gui_layout->setRowStretch(row++, 1);
918 gui_layout->addWidget(limit_label, row, 0, Qt::AlignRight);
919 gui_layout->addWidget(limit_box, row++, 1, Qt::AlignLeft);
920 gui_layout->addWidget(no_limit_box, row++, 1);
922 gui_layout->addWidget(increase_label, row, 0, Qt::AlignRight);
923 gui_layout->addWidget(increase_box, row++, 1, Qt::AlignLeft);
924 gui_layout->addWidget(no_increase_box, row++, 1);
926 gui_layout->setRowMinimumHeight(row, 20); // XXX urgh, pixels...
927 gui_layout->setRowStretch(row++, 1);
929 gui_layout->addWidget(wincomp_box, row++, 1);
930 gui_layout->addWidget(pre_box, row++, 1);
931 gui_layout->addWidget(hint_box, row++, 1);
932 gui_layout->addWidget(symbol_box, row++, 1);
933 gui_layout->addWidget(info_box, row++, 1);
935 gui_layout->setRowMinimumHeight(row, 20); // XXX urgh, pixels...
936 gui_layout->setRowStretch(row++, 1);
938 gui_layout->addWidget(stem_label, row, 0, Qt::AlignRight);
939 gui_layout->addWidget(gray_box, row++, 1);
940 gui_layout->addWidget(gdi_box, row++, 1);
941 gui_layout->addWidget(dw_box, row++, 1);
943 gui_layout->setRowMinimumHeight(row, 20); // XXX urgh, pixels...
944 gui_layout->setRowStretch(row++, 1);
946 gui_layout->addWidget(run_button, row++, 1, Qt::AlignRight);
948 // create dummy widget to register layout
949 QWidget* main_widget = new QWidget;
950 main_widget->setLayout(gui_layout);
951 setCentralWidget(main_widget);
952 setWindowTitle("TTFautohint");
956 void
957 Main_GUI::create_connections()
959 connect(input_button, SIGNAL(clicked()), this,
960 SLOT(browse_input()));
961 connect(output_button, SIGNAL(clicked()), this,
962 SLOT(browse_output()));
964 connect(input_line, SIGNAL(textChanged(QString)), this,
965 SLOT(check_run()));
966 connect(output_line, SIGNAL(textChanged(QString)), this,
967 SLOT(check_run()));
969 connect(input_line, SIGNAL(editingFinished()), this,
970 SLOT(absolute_input()));
971 connect(output_line, SIGNAL(editingFinished()), this,
972 SLOT(absolute_output()));
974 connect(min_box, SIGNAL(valueChanged(int)), this,
975 SLOT(check_min()));
976 connect(max_box, SIGNAL(valueChanged(int)), this,
977 SLOT(check_max()));
979 connect(limit_box, SIGNAL(valueChanged(int)), this,
980 SLOT(check_limit()));
981 connect(no_limit_box, SIGNAL(clicked()), this,
982 SLOT(check_no_limit()));
984 connect(no_increase_box, SIGNAL(clicked()), this,
985 SLOT(check_no_increase()));
987 connect(run_button, SIGNAL(clicked()), this,
988 SLOT(run()));
992 void
993 Main_GUI::create_actions()
995 exit_act = new QAction(tr("E&xit"), this);
996 exit_act->setShortcuts(QKeySequence::Quit);
997 connect(exit_act, SIGNAL(triggered()), this, SLOT(close()));
999 about_act = new QAction(tr("&About"), this);
1000 connect(about_act, SIGNAL(triggered()), this, SLOT(about()));
1002 about_Qt_act = new QAction(tr("About &Qt"), this);
1003 connect(about_Qt_act, SIGNAL(triggered()), qApp, SLOT(aboutQt()));
1007 void
1008 Main_GUI::create_menus()
1010 file_menu = menuBar()->addMenu(tr("&File"));
1011 file_menu->addAction(exit_act);
1013 help_menu = menuBar()->addMenu(tr("&Help"));
1014 help_menu->addAction(about_act);
1015 help_menu->addAction(about_Qt_act);
1019 void
1020 Main_GUI::create_status_bar()
1022 statusBar()->showMessage("");
1026 void
1027 Main_GUI::read_settings()
1029 QSettings settings;
1030 // QPoint pos = settings.value("pos", QPoint(200, 200)).toPoint();
1031 // QSize size = settings.value("size", QSize(400, 400)).toSize();
1032 // resize(size);
1033 // move(pos);
1037 void
1038 Main_GUI::write_settings()
1040 QSettings settings;
1041 // settings.setValue("pos", pos());
1042 // settings.setValue("size", size());
1045 // end of maingui.cpp