freetype-commit
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[freetype2-demos] gsoc-2022-chariri-final ac751de3 5/6: [ftinspect] Use


From: Werner Lemberg
Subject: [freetype2-demos] gsoc-2022-chariri-final ac751de3 5/6: [ftinspect] Use custom `QAbstractListModel` instead of manually mapping.
Date: Fri, 2 Sep 2022 01:19:24 -0400 (EDT)

branch: gsoc-2022-chariri-final
commit ac751de384299cde1a3b3870cef6374aa389fc44
Author: Charlie Jiang <w@chariri.moe>
Commit: Charlie Jiang <w@chariri.moe>

    [ftinspect] Use custom `QAbstractListModel` instead of manually mapping.
    
    In `maingui.cpp`, mapping between `QComboBox` indices and actual FreeType
    values was done manually. The enabled statuses of individual ComboBox items
    were also maintained in `maingui.cpp`.
    
    In this commit, those code was moved to seperate custom classes
    implementating `QAbstractListModel`. All mapping was done there.
    Enable/Disable states was maintained in the classes as well.
    By doing this, the reason why some items were disabled was made more clear
    and explicit. Adding more items is easier.
    
    The `QComboBoxx` custom widget is no longer needed since disable flag can
    be provided by the custom model by overriding the `flags` function.
    
    `SimpleComboBoxModel` is a basic class for Key-Value-DisplayName mapping.
    Other models could extend this class if no complicated mapping (e.g.
    `HintingModeComboBoxModel`) is needed.
    
    * src/ftinspect/models/customcomboboxmodels.cpp,
      src/ftinspect/models/customcomboboxmodels.cpp: New files.
    
    * src/ftinspect/engine/engine.cpp, src/ftinspect/engine/engine.hpp:
      `Engine` now accepts "load target" value of certain anti-aliasing mode
      instead of the anti-aliasing enum value. The mapping was moved into
      `AntiAliasingComboBoxModel`.
    
    * src/ftinspect/maingui.cpp, src/ftinspect/maingui.hpp: Move all mappings
      and enabled/disabled statuses to separate models.
      Remove mapping `QHash`es. Use `QComboBox` instead of `QComboBoxx`.
    
    * src/ftinspect/meson.build, src/ftinspect/CMakeLists.txt: Updated.
---
 src/ftinspect/CMakeLists.txt                  |   2 +
 src/ftinspect/engine/engine.cpp               |  31 +--
 src/ftinspect/engine/engine.hpp               |  18 +-
 src/ftinspect/maingui.cpp                     | 194 +++++++----------
 src/ftinspect/maingui.hpp                     |  31 +--
 src/ftinspect/meson.build                     |   5 +-
 src/ftinspect/models/customcomboboxmodels.cpp | 292 ++++++++++++++++++++++++++
 src/ftinspect/models/customcomboboxmodels.hpp | 217 +++++++++++++++++++
 8 files changed, 600 insertions(+), 190 deletions(-)

diff --git a/src/ftinspect/CMakeLists.txt b/src/ftinspect/CMakeLists.txt
index 9f46be53..a49d652c 100644
--- a/src/ftinspect/CMakeLists.txt
+++ b/src/ftinspect/CMakeLists.txt
@@ -32,6 +32,8 @@ add_executable(ftinspect
   "widgets/qgraphicsviewx.cpp"
   "widgets/qpushbuttonx.cpp"
   "widgets/qspinboxx.cpp"
+
+  "models/customcomboboxmodels.cpp"
 )
 target_link_libraries(ftinspect
   Qt5::Core Qt5::Widgets
diff --git a/src/ftinspect/engine/engine.cpp b/src/ftinspect/engine/engine.cpp
index 877015c0..1e6fa168 100644
--- a/src/ftinspect/engine/engine.cpp
+++ b/src/ftinspect/engine/engine.cpp
@@ -459,40 +459,15 @@ Engine::update()
 
   if (doHinting_)
   {
-    unsigned long target;
-
-    if (antiAliasingMode_ == AntiAliasing_None)
-      target = FT_LOAD_TARGET_MONO;
-    else
-    {
-      switch (antiAliasingMode_)
-      {
-      case AntiAliasing_Light:
-        target = FT_LOAD_TARGET_LIGHT;
-        break;
-
-      case AntiAliasing_LCD:
-      case AntiAliasing_LCD_BGR:
-        target = FT_LOAD_TARGET_LCD;
-        break;
-
-      case AntiAliasing_LCD_Vertical:
-      case AntiAliasing_LCD_Vertical_BGR:
-        target = FT_LOAD_TARGET_LCD_V;
-        break;
-
-      default:
-        target = FT_LOAD_TARGET_NORMAL;
-      }
-    }
-
+    // TODO Differentiate RGB/BGR here?
+    unsigned long target = antiAliasingTarget_;
     loadFlags_ |= target;
   }
   else
   {
     loadFlags_ |= FT_LOAD_NO_HINTING;
 
-    if (antiAliasingMode_ == AntiAliasing_None)
+    if (antiAliasingTarget_ | FT_LOAD_TARGET_MONO)
       loadFlags_ |= FT_LOAD_MONOCHROME;
   }
 
diff --git a/src/ftinspect/engine/engine.hpp b/src/ftinspect/engine/engine.hpp
index 2a7ec245..664c4b98 100644
--- a/src/ftinspect/engine/engine.hpp
+++ b/src/ftinspect/engine/engine.hpp
@@ -42,9 +42,6 @@ class Engine
 {
 public:
   //////// Nested definitions (forward decl)
-
-  // TODO these would be dropped with custom QAbstractItemModel
-  enum AntiAliasing : int;
   enum FontType : int;
 
   struct EngineDefaultValues
@@ -117,7 +114,7 @@ public:
   }
   void setShowSegments(bool showSegments) { showSegments_ = showSegments; }
   void setGamma(double gamma) { gamma_ = gamma; }
-  void setAntiAliasingMode(AntiAliasing mode) { antiAliasingMode_ = mode; }
+  void setAntiAliasingTarget(int target) { antiAliasingTarget_ = target; }
 
   // Note: These 3 functions now takes actual mode/version from FreeType,
   // instead of values from enum in MainGUI!
@@ -165,7 +162,7 @@ private:
   bool doVerticalHinting_;
   bool doBlueZoneHinting_;
   bool showSegments_;
-  AntiAliasing antiAliasingMode_;
+  int antiAliasingTarget_;
 
   double gamma_;
 
@@ -176,17 +173,6 @@ private:
 public:
 
   /// Actual definition
-  
-  enum AntiAliasing : int
-  {
-    AntiAliasing_None,
-    AntiAliasing_Normal,
-    AntiAliasing_Light,
-    AntiAliasing_LCD,
-    AntiAliasing_LCD_BGR,
-    AntiAliasing_LCD_Vertical,
-    AntiAliasing_LCD_Vertical_BGR
-  };
 
   // XXX cover all available modules
   enum FontType : int
diff --git a/src/ftinspect/maingui.cpp b/src/ftinspect/maingui.cpp
index 026b6566..c3da9417 100644
--- a/src/ftinspect/maingui.cpp
+++ b/src/ftinspect/maingui.cpp
@@ -218,8 +218,10 @@ MainGUI::applySettings()
 
   engine_->setGamma(gammaSlider_->value());
 
-  engine_->setAntiAliasingMode(static_cast<Engine::AntiAliasing>(
-      antiAliasingComboBoxx_->currentIndex()));
+  engine_->setAntiAliasingTarget(
+    antiAliasingComboBoxModel_
+      ->indexToValue(antiAliasingComboBox_->currentIndex())
+      .loadFlag);
 }
 
 
@@ -238,45 +240,29 @@ MainGUI::checkHinting()
   {
     if (engine_->currentFontType() == Engine::FontType_CFF)
     {
-      for (int i = 0; i < hintingModeComboBoxx_->count(); i++)
-      {
-        if (hintingModesCFFHash_.key(i, -1) != -1)
-          hintingModeComboBoxx_->setItemEnabled(i, true);
-        else
-          hintingModeComboBoxx_->setItemEnabled(i, false);
-      }
-
-      hintingModeComboBoxx_->setCurrentIndex(currentCFFHintingMode_);
+      hintingModeComboBoxModel_->setCurrentEngineType(
+        HintingModeComboBoxModel::HintingEngineType_CFF, false); // XXX tricky
+      hintingModeComboBox_->setCurrentIndex(currentCFFHintingMode_);
     }
     else if (engine_->currentFontType() == Engine::FontType_TrueType)
     {
-      for (int i = 0; i < hintingModeComboBoxx_->count(); i++)
-      {
-        if (hintingModesTrueTypeHash_.key(i, -1) != -1)
-          hintingModeComboBoxx_->setItemEnabled(i, true);
-        else
-          hintingModeComboBoxx_->setItemEnabled(i, false);
-      }
-
-      hintingModeComboBoxx_->setCurrentIndex(currentTTInterpreterVersion_);
+      hintingModeComboBoxModel_->setCurrentEngineType( // XXX tricky
+        HintingModeComboBoxModel::HintingEngineType_TrueType, false);
+      hintingModeComboBox_->setCurrentIndex(currentTTInterpreterVersion_);
     }
     else
     {
       hintingModeLabel_->setEnabled(false);
-      hintingModeComboBoxx_->setEnabled(false);
+      hintingModeComboBox_->setEnabled(false);
     }
 
-    for (int i = 0; i < hintingModesAlwaysDisabled_.size(); i++)
-      hintingModeComboBoxx_->setItemEnabled(hintingModesAlwaysDisabled_[i],
-                                           false);
-
     autoHintingCheckBox_->setEnabled(true);
     checkAutoHinting();
   }
   else
   {
     hintingModeLabel_->setEnabled(false);
-    hintingModeComboBoxx_->setEnabled(false);
+    hintingModeComboBox_->setEnabled(false);
 
     autoHintingCheckBox_->setEnabled(false);
     horizontalHintingCheckBox_->setEnabled(false);
@@ -284,7 +270,11 @@ MainGUI::checkHinting()
     blueZoneHintingCheckBox_->setEnabled(false);
     segmentDrawingCheckBox_->setEnabled(false);
 
-    antiAliasingComboBoxx_->setItemEnabled(Engine::AntiAliasing_Light, false);
+    antiAliasingComboBoxModel_->setLightAntiAliasingEnabled(false);
+    if (antiAliasingComboBox_->currentIndex()
+      == AntiAliasingComboBoxModel::AntiAliasing_Light)
+      antiAliasingComboBox_->setCurrentIndex(
+        AntiAliasingComboBoxModel::AntiAliasing_Normal);
   }
 
   drawGlyph();
@@ -294,16 +284,18 @@ MainGUI::checkHinting()
 void
 MainGUI::checkHintingMode()
 {
-  int index = hintingModeComboBoxx_->currentIndex();
+  int index = hintingModeComboBox_->currentIndex();
 
   if (engine_->currentFontType() == Engine::FontType_CFF)
   {
-    engine_->setCFFHintingMode(hintingModesCFFHash_.key(index));
+    engine_->setCFFHintingMode(
+      hintingModeComboBoxModel_->indexToCFFMode(index));
     currentCFFHintingMode_ = index;
   }
   else if (engine_->currentFontType() == Engine::FontType_TrueType)
   {
-    engine_->setTTInterpreterVersion(hintingModesTrueTypeHash_.key(index));
+    engine_->setTTInterpreterVersion(
+      hintingModeComboBoxModel_->indexToTTInterpreterVersion(index));
     currentTTInterpreterVersion_ = index;
   }
 
@@ -318,14 +310,14 @@ MainGUI::checkAutoHinting()
   if (autoHintingCheckBox_->isChecked())
   {
     hintingModeLabel_->setEnabled(false);
-    hintingModeComboBoxx_->setEnabled(false);
+    hintingModeComboBox_->setEnabled(false);
 
     horizontalHintingCheckBox_->setEnabled(true);
     verticalHintingCheckBox_->setEnabled(true);
     blueZoneHintingCheckBox_->setEnabled(true);
     segmentDrawingCheckBox_->setEnabled(true);
 
-    antiAliasingComboBoxx_->setItemEnabled(Engine::AntiAliasing_Light, true);
+    antiAliasingComboBoxModel_->setLightAntiAliasingEnabled(true);
   }
   else
   {
@@ -333,7 +325,7 @@ MainGUI::checkAutoHinting()
         || engine_->currentFontType() == Engine::FontType_TrueType)
     {
       hintingModeLabel_->setEnabled(true);
-      hintingModeComboBoxx_->setEnabled(true);
+      hintingModeComboBox_->setEnabled(true);
     }
 
     horizontalHintingCheckBox_->setEnabled(false);
@@ -341,10 +333,12 @@ MainGUI::checkAutoHinting()
     blueZoneHintingCheckBox_->setEnabled(false);
     segmentDrawingCheckBox_->setEnabled(false);
 
-    antiAliasingComboBoxx_->setItemEnabled(Engine::AntiAliasing_Light, false);
+    antiAliasingComboBoxModel_->setLightAntiAliasingEnabled(false);
 
-    if (antiAliasingComboBoxx_->currentIndex() == Engine::AntiAliasing_Light)
-      antiAliasingComboBoxx_->setCurrentIndex(Engine::AntiAliasing_Normal);
+    if (antiAliasingComboBox_->currentIndex()
+        == AntiAliasingComboBoxModel::AntiAliasing_Light)
+      antiAliasingComboBox_->setCurrentIndex(
+          AntiAliasingComboBoxModel::AntiAliasing_Normal);
   }
 
   drawGlyph();
@@ -354,11 +348,11 @@ MainGUI::checkAutoHinting()
 void
 MainGUI::checkAntiAliasing()
 {
-  int index = antiAliasingComboBoxx_->currentIndex();
+  int index = antiAliasingComboBox_->currentIndex();
 
-  if (index == Engine::AntiAliasing_None
-      || index == Engine::AntiAliasing_Normal
-      || index == Engine::AntiAliasing_Light)
+  if (index == AntiAliasingComboBoxModel::AntiAliasing_None
+      || index == AntiAliasingComboBoxModel::AntiAliasing_Normal
+      || index == AntiAliasingComboBoxModel::AntiAliasing_Light)
   {
     lcdFilterLabel_->setEnabled(false);
     lcdFilterComboBox_->setEnabled(false);
@@ -377,7 +371,8 @@ void
 MainGUI::checkLcdFilter()
 {
   int index = lcdFilterComboBox_->currentIndex();
-  engine_->setLcdFilter(lcdFilterHash_.key(index));
+  engine_->setLcdFilter(static_cast<FT_LcdFilter>(
+    lcdFilterComboboxModel_->indexToValue(index)));
 }
 
 
@@ -684,7 +679,8 @@ MainGUI::drawGlyph()
     {
       // XXX support LCD
       FT_Pixel_Mode pixelMode = FT_PIXEL_MODE_GRAY;
-      if (antiAliasingComboBoxx_->currentIndex() == Engine::AntiAliasing_None)
+      if (antiAliasingComboBox_->currentIndex()
+          == AntiAliasingComboBoxModel::AntiAliasing_None)
         pixelMode = FT_PIXEL_MODE_MONO;
 
       currentGlyphBitmapItem_ = new GlyphBitmap(outline,
@@ -732,18 +728,11 @@ MainGUI::createLayout()
 
   hintingModeLabel_ = new QLabel(tr("Hinting Mode"));
   hintingModeLabel_->setAlignment(Qt::AlignRight);
-  hintingModeComboBoxx_ = new QComboBoxx;
-  hintingModeComboBoxx_->insertItem(HintingMode_TrueType_v35,
-                                   tr("TrueType v35"));
-  hintingModeComboBoxx_->insertItem(HintingMode_TrueType_v38,
-                                   tr("TrueType v38"));
-  hintingModeComboBoxx_->insertItem(HintingMode_TrueType_v40,
-                                   tr("TrueType v40"));
-  hintingModeComboBoxx_->insertItem(HintingMode_CFF_FreeType,
-                                   tr("CFF (FreeType)"));
-  hintingModeComboBoxx_->insertItem(HintingMode_CFF_Adobe,
-                                   tr("CFF (Adobe)"));
-  hintingModeLabel_->setBuddy(hintingModeComboBoxx_);
+
+  hintingModeComboBoxModel_ = new HintingModeComboBoxModel(this);
+  hintingModeComboBox_ = new QComboBox;
+  hintingModeComboBox_->setModel(hintingModeComboBoxModel_);
+  hintingModeLabel_->setBuddy(hintingModeComboBox_);
 
   autoHintingCheckBox_ = new QCheckBox(tr("Auto-Hinting"));
   horizontalHintingCheckBox_ = new QCheckBox(tr("Horizontal Hinting"));
@@ -753,30 +742,18 @@ MainGUI::createLayout()
 
   antiAliasingLabel_ = new QLabel(tr("Anti-Aliasing"));
   antiAliasingLabel_->setAlignment(Qt::AlignRight);
-  antiAliasingComboBoxx_ = new QComboBoxx;
-  antiAliasingComboBoxx_->insertItem(Engine::AntiAliasing_None,
-                                    tr("None"));
-  antiAliasingComboBoxx_->insertItem(Engine::AntiAliasing_Normal,
-                                    tr("Normal"));
-  antiAliasingComboBoxx_->insertItem(Engine::AntiAliasing_Light,
-                                    tr("Light"));
-  antiAliasingComboBoxx_->insertItem(Engine::AntiAliasing_LCD,
-                                    tr("LCD (RGB)"));
-  antiAliasingComboBoxx_->insertItem(Engine::AntiAliasing_LCD_BGR,
-                                    tr("LCD (BGR)"));
-  antiAliasingComboBoxx_->insertItem(Engine::AntiAliasing_LCD_Vertical,
-                                    tr("LCD (vert. RGB)"));
-  antiAliasingComboBoxx_->insertItem(Engine::AntiAliasing_LCD_Vertical_BGR,
-                                    tr("LCD (vert. BGR)"));
-  antiAliasingLabel_->setBuddy(antiAliasingComboBoxx_);
+
+  antiAliasingComboBoxModel_ = new AntiAliasingComboBoxModel(this);
+  antiAliasingComboBox_ = new QComboBox;
+  antiAliasingComboBox_->setModel(antiAliasingComboBoxModel_);
+  antiAliasingLabel_->setBuddy(antiAliasingComboBox_);
 
   lcdFilterLabel_ = new QLabel(tr("LCD Filter"));
   lcdFilterLabel_->setAlignment(Qt::AlignRight);
+
+  lcdFilterComboboxModel_ = new LCDFilterComboBoxModel(this);
   lcdFilterComboBox_ = new QComboBox;
-  lcdFilterComboBox_->insertItem(LCDFilter_Default, tr("Default"));
-  lcdFilterComboBox_->insertItem(LCDFilter_Light, tr("Light"));
-  lcdFilterComboBox_->insertItem(LCDFilter_None, tr("None"));
-  lcdFilterComboBox_->insertItem(LCDFilter_Legacy, tr("Legacy"));
+  lcdFilterComboBox_->setModel(lcdFilterComboboxModel_);
   lcdFilterLabel_->setBuddy(lcdFilterComboBox_);
 
   int width;
@@ -790,11 +767,11 @@ MainGUI::createLayout()
 
   // ensure that all items in combo boxes fit completely;
   // also make all combo boxes have the same width
-  width = hintingModeComboBoxx_->minimumSizeHint().width();
-  width = qMax(antiAliasingComboBoxx_->minimumSizeHint().width(), width);
+  width = hintingModeComboBox_->minimumSizeHint().width();
+  width = qMax(antiAliasingComboBox_->minimumSizeHint().width(), width);
   width = qMax(lcdFilterComboBox_->minimumSizeHint().width(), width);
-  hintingModeComboBoxx_->setMinimumWidth(width);
-  antiAliasingComboBoxx_->setMinimumWidth(width);
+  hintingModeComboBox_->setMinimumWidth(width);
+  antiAliasingComboBox_->setMinimumWidth(width);
   lcdFilterComboBox_->setMinimumWidth(width);
 
   gammaLabel_ = new QLabel(tr("Gamma"));
@@ -815,7 +792,7 @@ MainGUI::createLayout()
 
   hintingModeLayout_ = new QHBoxLayout;
   hintingModeLayout_->addWidget(hintingModeLabel_);
-  hintingModeLayout_->addWidget(hintingModeComboBoxx_);
+  hintingModeLayout_->addWidget(hintingModeComboBox_);
 
   horizontalHintingLayout_ = new QHBoxLayout;
   horizontalHintingLayout_->addSpacing(20); // XXX px
@@ -835,7 +812,7 @@ MainGUI::createLayout()
 
   antiAliasingLayout_ = new QHBoxLayout;
   antiAliasingLayout_->addWidget(antiAliasingLabel_);
-  antiAliasingLayout_->addWidget(antiAliasingComboBoxx_);
+  antiAliasingLayout_->addWidget(antiAliasingComboBox_);
 
   lcdFilterLayout_ = new QHBoxLayout;
   lcdFilterLayout_->addWidget(lcdFilterLabel_);
@@ -1038,9 +1015,9 @@ MainGUI::createConnections()
   connect(hintingCheckBox_, SIGNAL(clicked()),
           SLOT(checkHinting()));
 
-  connect(hintingModeComboBoxx_, SIGNAL(currentIndexChanged(int)),
+  connect(hintingModeComboBox_, SIGNAL(currentIndexChanged(int)),
           SLOT(checkHintingMode()));
-  connect(antiAliasingComboBoxx_, SIGNAL(currentIndexChanged(int)),
+  connect(antiAliasingComboBox_, SIGNAL(currentIndexChanged(int)),
           SLOT(checkAntiAliasing()));
   connect(lcdFilterComboBox_, SIGNAL(currentIndexChanged(int)),
           SLOT(checkLcdFilter()));
@@ -1167,43 +1144,14 @@ MainGUI::createStatusBar()
 void
 MainGUI::setDefaults()
 {
-  // set up mappings between property values and combo box indices
-  hintingModesTrueTypeHash_[TT_INTERPRETER_VERSION_35] = 
HintingMode_TrueType_v35;
-  hintingModesTrueTypeHash_[TT_INTERPRETER_VERSION_38] = 
HintingMode_TrueType_v38;
-  hintingModesTrueTypeHash_[TT_INTERPRETER_VERSION_40] = 
HintingMode_TrueType_v40;
-
-  hintingModesCFFHash_[FT_HINTING_FREETYPE] = HintingMode_CFF_FreeType;
-  hintingModesCFFHash_[FT_HINTING_ADOBE] = HintingMode_CFF_Adobe;
-
-  lcdFilterHash_[FT_LCD_FILTER_DEFAULT] = LCDFilter_Default;
-  lcdFilterHash_[FT_LCD_FILTER_LIGHT] = LCDFilter_Light;
-  lcdFilterHash_[FT_LCD_FILTER_NONE] = LCDFilter_None;
-  lcdFilterHash_[FT_LCD_FILTER_LEGACY] = LCDFilter_Legacy;
-
   Engine::EngineDefaultValues& defaults = engine_->engineDefaults();
 
-  // make copies and remove existing elements...
-  QHash<int, int> hmTTHash = hintingModesTrueTypeHash_;
-  if (hmTTHash.contains(defaults.ttInterpreterVersionDefault))
-    hmTTHash.remove(defaults.ttInterpreterVersionDefault);
-  if (hmTTHash.contains(defaults.ttInterpreterVersionOther))
-    hmTTHash.remove(defaults.ttInterpreterVersionOther);
-  if (hmTTHash.contains(defaults.ttInterpreterVersionOther1))
-    hmTTHash.remove(defaults.ttInterpreterVersionOther1);
-
-  QHash<int, int> hmCFFHash = hintingModesCFFHash_;
-  if (hmCFFHash.contains(defaults.cffHintingEngineDefault))
-    hmCFFHash.remove(defaults.cffHintingEngineDefault);
-  if (hmCFFHash.contains(defaults.cffHintingEngineOther))
-    hmCFFHash.remove(defaults.cffHintingEngineOther);
-
-  // ... to construct a list of always disabled hinting mode combo box items
-  hintingModesAlwaysDisabled_ = hmTTHash.values();
-  hintingModesAlwaysDisabled_ += hmCFFHash.values();
-
-  for (int i = 0; i < hintingModesAlwaysDisabled_.size(); i++)
-    hintingModeComboBoxx_->setItemEnabled(hintingModesAlwaysDisabled_[i],
-                                         false);
+  hintingModeComboBoxModel_->setSupportedModes(
+    { defaults.ttInterpreterVersionDefault,
+      defaults.ttInterpreterVersionOther,
+      defaults.ttInterpreterVersionOther1 },
+    { defaults.cffHintingEngineDefault, 
+      defaults.cffHintingEngineOther });
 
   // the next four values always non-negative
   currentFontIndex_ = 0;
@@ -1212,14 +1160,18 @@ MainGUI::setDefaults()
   currentGlyphIndex_ = 0;
 
   currentCFFHintingMode_
-    = hintingModesCFFHash_[defaults.cffHintingEngineDefault];
+    = hintingModeComboBoxModel_->cffModeToIndex(
+    defaults.cffHintingEngineDefault);
   currentTTInterpreterVersion_
-    = hintingModesTrueTypeHash_[defaults.ttInterpreterVersionDefault];
+    = hintingModeComboBoxModel_->ttInterpreterVersionToIndex(
+        defaults.ttInterpreterVersionDefault);
 
   hintingCheckBox_->setChecked(true);
 
-  antiAliasingComboBoxx_->setCurrentIndex(Engine::AntiAliasing_Normal);
-  lcdFilterComboBox_->setCurrentIndex(LCDFilter_Light);
+  antiAliasingComboBox_->setCurrentIndex(
+    AntiAliasingComboBoxModel::AntiAliasing_Normal);
+  lcdFilterComboBox_->setCurrentIndex(
+    LCDFilterComboBoxModel::LCDFilter_Light);
 
   horizontalHintingCheckBox_->setChecked(true);
   verticalHintingCheckBox_->setChecked(true);
diff --git a/src/ftinspect/maingui.hpp b/src/ftinspect/maingui.hpp
index e54d220e..536f702f 100644
--- a/src/ftinspect/maingui.hpp
+++ b/src/ftinspect/maingui.hpp
@@ -14,6 +14,7 @@
 #include "widgets/qgraphicsviewx.hpp"
 #include "widgets/qpushbuttonx.hpp"
 #include "widgets/qspinboxx.hpp"
+#include "models/customcomboboxmodels.hpp"
 
 #include <QAction>
 #include <QCheckBox>
@@ -132,8 +133,12 @@ private:
   QCheckBox *showPointsCheckBox_;
   QCheckBox *verticalHintingCheckBox_;
 
-  QComboBoxx *antiAliasingComboBoxx_;
-  QComboBoxx *hintingModeComboBoxx_;
+  AntiAliasingComboBoxModel* antiAliasingComboBoxModel_;
+  HintingModeComboBoxModel* hintingModeComboBoxModel_;
+  LCDFilterComboBoxModel* lcdFilterComboboxModel_;
+
+  QComboBox *antiAliasingComboBox_;
+  QComboBox *hintingModeComboBox_;
   QComboBox *lcdFilterComboBox_;
   QComboBox *unitsComboBox_;
 
@@ -145,10 +150,6 @@ private:
   QGridLayout *fontLayout;
   QGridLayout *infoRightLayout;
 
-  QHash<int, int> hintingModesTrueTypeHash_;
-  QHash<int, int> hintingModesCFFHash_;
-  QHash<FT_LcdFilter, int> lcdFilterHash_;
-
   QHBoxLayout *antiAliasingLayout_;
   QHBoxLayout *blueZoneHintingLayout_;
   QHBoxLayout *ftinspectLayout_;
@@ -175,8 +176,6 @@ private:
   QLabel *sizeLabel_;
   QLabel *zoomLabel_;
 
-  QList<int> hintingModesAlwaysDisabled_;
-
   QLocale *locale_;
 
   QMenu *menuFile_;
@@ -230,22 +229,6 @@ private:
   QWidget *rightWidget_;
   QWidget *mmgxTabWidget_;
 
-  // TODO these would be dropped with custom QAbstractItemModel
-  enum HintingMode
-  {
-    HintingMode_TrueType_v35,
-    HintingMode_TrueType_v38,
-    HintingMode_TrueType_v40,
-    HintingMode_CFF_FreeType,
-    HintingMode_CFF_Adobe
-  };
-  enum LCDFilter
-  {
-    LCDFilter_Default,
-    LCDFilter_Light,
-    LCDFilter_None,
-    LCDFilter_Legacy
-  };
   enum Units
   {
     Units_px,
diff --git a/src/ftinspect/meson.build b/src/ftinspect/meson.build
index 892aff29..1191f910 100644
--- a/src/ftinspect/meson.build
+++ b/src/ftinspect/meson.build
@@ -35,9 +35,11 @@ if qt5_dep.found()
     'widgets/qpushbuttonx.cpp',
     'widgets/qspinboxx.cpp',
 
+    'models/customcomboboxmodels.cpp',
+
     'ftinspect.cpp',
     'maingui.cpp',
-  ])
+])
 
   moc_files = qt5.preprocess(
     moc_headers: [
@@ -47,6 +49,7 @@ if qt5_dep.found()
       'widgets/qpushbuttonx.hpp',
       'widgets/qspinboxx.hpp',
       'maingui.hpp',
+      'models/customcomboboxmodels.hpp',
     ],
     dependencies: qt5_dep)
 
diff --git a/src/ftinspect/models/customcomboboxmodels.cpp 
b/src/ftinspect/models/customcomboboxmodels.cpp
new file mode 100644
index 00000000..4e4f5d49
--- /dev/null
+++ b/src/ftinspect/models/customcomboboxmodels.cpp
@@ -0,0 +1,292 @@
+// customcomboboxmodels.cpp
+
+// Copyright (C) 2022 by Charlie Jiang.
+
+
+#include "customcomboboxmodels.hpp"
+
+#include <QApplication>
+#include <QPalette>
+#include <freetype/ftdriver.h>
+#include <freetype/ftlcdfil.h>
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// HintingModeComboBoxModel
+//
+/////////////////////////////////////////////////////////////////////////////
+
+HintingModeComboBoxModel::HintingModeComboBoxModel(QObject* parent)
+: QAbstractListModel(parent)
+{
+  items_[HintingMode_TrueType_v35] = {
+    HintingEngineType_TrueType,
+    HintingMode_TrueType_v35,
+    TT_INTERPRETER_VERSION_35,
+    false, false,
+    "TrueType v35"
+  };
+  items_[HintingMode_TrueType_v38] = {
+    HintingEngineType_TrueType,
+    HintingMode_TrueType_v38,
+    TT_INTERPRETER_VERSION_38,
+    false, false,
+    "TrueType v38"
+  };
+  items_[HintingMode_TrueType_v40] = {
+    HintingEngineType_TrueType,
+    HintingMode_TrueType_v40,
+    TT_INTERPRETER_VERSION_40,
+    false, false,
+    "TrueType v40"
+  };
+
+  items_[HintingMode_CFF_FreeType] = {
+    HintingEngineType_CFF,
+    HintingMode_CFF_FreeType,
+    FT_HINTING_FREETYPE,
+    false, false,
+    "CFF (FreeType)"
+  };
+  items_[HintingMode_CFF_Adobe] = {
+    HintingEngineType_CFF,
+    HintingMode_CFF_Adobe,
+    FT_HINTING_ADOBE,
+    false, false,
+    "CFF (Adobe)"
+  };
+}
+
+
+int
+HintingModeComboBoxModel::rowCount(const QModelIndex& parent) const
+{
+  return items_.size();
+}
+
+
+QVariant
+HintingModeComboBoxModel::data(const QModelIndex& index,
+  int role) const
+{
+  int r = index.row();
+  if (r < 0 || r >= items_.size())
+    return QVariant {};
+  HintingModeItem const& item = items_[r];
+
+  switch (role)
+  {
+  case Qt::DisplayRole:
+    return item.displayName;
+  case Qt::ForegroundRole:
+    if (item.enabled && item.supported)
+      return QVariant {};
+    else
+      return QApplication::palette().color(QPalette::Disabled, 
+                                           QPalette::Text);
+  default:
+    return QVariant {};
+  }
+}
+
+
+Qt::ItemFlags
+HintingModeComboBoxModel::flags(const QModelIndex& index) const
+{
+  int r = index.row();
+  if (r < 0 || r >= items_.size())
+    return Qt::ItemFlags {}; // not selectable, not enabled
+  HintingModeItem const& item = items_[r];
+
+  if (item.enabled && item.supported)
+    return Qt::ItemIsEnabled | Qt::ItemIsSelectable;
+
+  return Qt::ItemFlags {};
+}
+
+
+int
+HintingModeComboBoxModel::indexToValueForType(int index,
+                                              HintingEngineType type) const
+{
+  if (index < 0 || index >= items_.size())
+    return -1;
+  HintingModeItem const& item = items_[index];
+  if (!item.supported || !item.enabled || item.type != type)
+    return -1;
+  return item.value;
+}
+
+
+int
+HintingModeComboBoxModel::valueToIndexForType(int value,
+                                              HintingEngineType type) const
+{
+  for (const auto& item : items_)
+  {
+    if (item.type == type && item.value == value)
+      return item.key;
+  }
+  return -1;
+}
+
+
+int
+HintingModeComboBoxModel::indexToTTInterpreterVersion(int index) const
+{
+  return indexToValueForType(index, HintingEngineType_TrueType);
+}
+
+
+int
+HintingModeComboBoxModel::indexToCFFMode(int index) const
+{
+  return indexToValueForType(index, HintingEngineType_CFF);
+}
+
+
+int
+HintingModeComboBoxModel::cffModeToIndex(int mode) const
+{
+  return valueToIndexForType(mode, HintingEngineType_CFF);
+}
+
+
+int
+HintingModeComboBoxModel::ttInterpreterVersionToIndex(int version) const
+{
+  return valueToIndexForType(version, HintingEngineType_TrueType);
+}
+
+
+void
+HintingModeComboBoxModel::setSupportedModes(QList<int> supportedTTIVersions,
+                                            QList<int> supportedCFFModes)
+{
+  for (auto& item : items_)
+  {
+    if (item.type == HintingEngineType_TrueType)
+      item.supported = supportedTTIVersions.contains(item.value);
+    else if (item.type == HintingEngineType_CFF)
+      item.supported = supportedCFFModes.contains(item.value);
+    else
+      item.supported = false;
+  }
+}
+
+
+void
+HintingModeComboBoxModel::setCurrentEngineType(HintingEngineType type, 
+                                               bool tricky)
+{
+  for (auto& item : items_)
+    if (!tricky)
+      item.enabled = item.supported && item.type == type;
+    else
+      item.enabled = item.supported && item.key == HintingMode_TrueType_v35;
+}
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// LCDFilterComboBoxModel
+//
+/////////////////////////////////////////////////////////////////////////////
+
+
+LCDFilterComboBoxModel::LCDFilterComboBoxModel(QObject* parent)
+: QAbstractListModel(parent)
+{
+  items_[LCDFilter_Default] = {
+    FT_LCD_FILTER_DEFAULT,
+    "Default"
+  };
+  items_[LCDFilter_Light] = {
+    FT_LCD_FILTER_LIGHT,
+    "Light"
+  };
+  items_[LCDFilter_None] = {
+    FT_LCD_FILTER_NONE,
+    "None"
+  };
+  items_[LCDFilter_Legacy] = {
+    FT_LCD_FILTER_LEGACY,
+    "Legacy"
+  };
+}
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// AntiAliasingComboBoxModel
+//
+/////////////////////////////////////////////////////////////////////////////
+
+
+AntiAliasingComboBoxModel::AntiAliasingComboBoxModel(QObject* parent)
+: QAbstractListModel(parent)
+{
+  items_[AntiAliasing_None] = {
+    {FT_LOAD_TARGET_MONO, FT_RENDER_MODE_MONO, false},
+    "None"
+  };
+  items_[AntiAliasing_Normal] = {
+    {FT_LOAD_TARGET_NORMAL, FT_RENDER_MODE_NORMAL, false},
+    "Normal"
+  };
+  items_[AntiAliasing_Light] = {
+    {FT_LOAD_TARGET_LIGHT, FT_RENDER_MODE_LIGHT, false},
+    "Light"
+  };
+  items_[AntiAliasing_Light_SubPixel] = {
+    {FT_LOAD_TARGET_LIGHT, FT_RENDER_MODE_LIGHT, false},
+    "Light (Sub Pixel)"
+  };
+  items_[AntiAliasing_LCD] = {
+    {FT_LOAD_TARGET_LCD, FT_RENDER_MODE_LCD, false},
+    "LCD (RGB)"
+  };
+  items_[AntiAliasing_LCD_BGR] = {
+    {FT_LOAD_TARGET_LCD, FT_RENDER_MODE_LCD, true},
+    "LCD (BGR)"
+  };
+  items_[AntiAliasing_LCD_Vertical] = {
+    {FT_LOAD_TARGET_LCD_V, FT_RENDER_MODE_LCD_V, false},
+    "LCD (vert. RGB)"
+  };
+  items_[AntiAliasing_LCD_Vertical_BGR] = {
+    {FT_LOAD_TARGET_LCD_V, FT_RENDER_MODE_LCD_V, true},
+    "LCD (vert. BGR)"
+  };
+
+  lightAntiAliasingEnabled_ = true;
+}
+
+
+QVariant
+AntiAliasingComboBoxModel::data(const QModelIndex& index,
+                                int role) const
+{
+  auto row = index.row();
+  if (role == Qt::ForegroundRole)
+    if ((row == AntiAliasing_Light || row == AntiAliasing_Light_SubPixel)
+        && !lightAntiAliasingEnabled_)
+      return QApplication::palette().color(QPalette::Disabled, 
+                                           QPalette::Text);
+  return SimpleComboBoxModelImpl::data(index, role);
+}
+
+
+Qt::ItemFlags
+AntiAliasingComboBoxModel::flags(const QModelIndex& index) const
+{
+  auto row = index.row();
+  if ((row == AntiAliasing_Light || row == AntiAliasing_Light_SubPixel)
+      && !lightAntiAliasingEnabled_)
+    return Qt::ItemFlags {};
+  return Qt::ItemIsSelectable | Qt::ItemIsEnabled;
+}
+
+
+// end of ttsettingscomboboxmodel.cpp
diff --git a/src/ftinspect/models/customcomboboxmodels.hpp 
b/src/ftinspect/models/customcomboboxmodels.hpp
new file mode 100644
index 00000000..3b851a5a
--- /dev/null
+++ b/src/ftinspect/models/customcomboboxmodels.hpp
@@ -0,0 +1,217 @@
+// customcomboboxmodels.hpp
+
+// Copyright (C) 2022 by Charlie Jiang.
+
+
+#pragma once
+
+#include <QAbstractListModel>
+#include <QHash>
+
+class HintingModeComboBoxModel
+: public QAbstractListModel
+{
+  Q_OBJECT
+public:
+  enum HintingEngineType : int;
+  enum HintingMode : int;
+  struct HintingModeItem
+  {
+    HintingEngineType type;
+    HintingMode key;
+    int value;
+    bool enabled;
+    bool supported;
+    QString displayName;
+  };
+
+  explicit HintingModeComboBoxModel(QObject* parent);
+  ~HintingModeComboBoxModel() override = default;
+
+  int rowCount(const QModelIndex& parent) const override;
+  QVariant data(const QModelIndex& index,
+                int role) const override;
+  Qt::ItemFlags flags(const QModelIndex& index) const override;
+
+  int indexToTTInterpreterVersion(int index) const;
+  int indexToCFFMode(int index) const;
+  int cffModeToIndex(int mode) const;
+  int ttInterpreterVersionToIndex(int version) const;
+
+  void setSupportedModes(QList<int> supportedTTIVersions,
+                         QList<int> supportedCFFModes);
+  void setCurrentEngineType(HintingEngineType type, bool tricky);
+
+private:
+  QHash<int, HintingModeItem> items_;
+
+  int indexToValueForType(int index,
+                          HintingEngineType type) const;
+  int valueToIndexForType(int value,
+                          HintingEngineType type) const;
+
+public:
+  // Note: Ensure related funcs are also changed when
+  // these enums are changed!
+  enum HintingEngineType : int
+  {
+    HintingEngineType_TrueType,
+    HintingEngineType_CFF
+  };
+
+  enum HintingMode : int
+  {
+    HintingMode_TrueType_v35 = 0,
+    HintingMode_TrueType_v38,
+    HintingMode_TrueType_v40,
+    HintingMode_CFF_FreeType,
+    HintingMode_CFF_Adobe
+  };
+};
+
+
+// A simple key-displayName-value model for QComboBox.
+template <class T>
+class SimpleComboBoxModelImpl
+{
+public:
+  struct ComboBoxItem
+  {
+    T value;
+    QString displayName;
+  };
+
+  SimpleComboBoxModelImpl() {}
+  virtual ~SimpleComboBoxModelImpl() = default;
+
+  virtual int
+  rowCount(const QModelIndex& parent) const
+  {
+    return items_.size();
+  }
+
+
+  virtual QVariant
+  data(const QModelIndex& index,
+                int role) const
+  {
+    if (role != Qt::DisplayRole)
+      return QVariant{};
+
+    int r = index.row();
+    if (r < 0 || r >= items_.size())
+      return QVariant{};
+    return items_[r].displayName;
+  }
+
+
+  virtual T
+  indexToValue(int index)
+  {
+    if (index < 0 || index >= items_.size())
+      return T();
+    return items_[index].value;
+  }
+
+protected:
+  QHash<int, ComboBoxItem> items_;
+};
+
+
+class LCDFilterComboBoxModel
+: public QAbstractListModel,
+  public SimpleComboBoxModelImpl<int>
+{
+  Q_OBJECT
+public:
+  enum LCDFilter : int;
+  struct LCDFilterItem
+  {
+    int value;
+    QString displayName;
+  };
+
+
+  explicit LCDFilterComboBoxModel(QObject* parent);
+  ~LCDFilterComboBoxModel() override = default;
+
+
+  int rowCount(const QModelIndex& parent) const override
+  {
+    return SimpleComboBoxModelImpl::rowCount(parent);
+  }
+
+
+  QVariant
+  data(const QModelIndex& index,
+       int role) const override
+  {
+    return SimpleComboBoxModelImpl::data(index, role);
+  }
+
+public:
+  enum LCDFilter : int
+  {
+    LCDFilter_Default,
+    LCDFilter_Light,
+    LCDFilter_None,
+    LCDFilter_Legacy
+  };
+};
+
+
+struct AASetting
+{
+  // No default value for braced init - No C++14, what a pain!
+  int loadFlag;
+  int renderMode;
+  bool isBGR;
+};
+
+
+class AntiAliasingComboBoxModel
+: public QAbstractListModel,
+  public SimpleComboBoxModelImpl<AASetting>
+{
+  Q_OBJECT
+public:
+  enum AntiAliasing : int;
+
+  explicit AntiAliasingComboBoxModel(QObject* parent);
+  ~AntiAliasingComboBoxModel() override = default;
+  
+  QVariant data(const QModelIndex& index,
+                int role) const;
+  Qt::ItemFlags flags(const QModelIndex& index) const;
+
+
+  int rowCount(const QModelIndex& parent) const override
+  {
+    return SimpleComboBoxModelImpl::rowCount(parent);
+  }
+
+
+  void setLightAntiAliasingEnabled(bool enabled)
+  {
+    lightAntiAliasingEnabled_ = enabled;
+  }
+
+private:
+  bool lightAntiAliasingEnabled_;
+
+public:
+  enum AntiAliasing : int
+  {
+    AntiAliasing_None,
+    AntiAliasing_Normal,
+    AntiAliasing_Light,
+    AntiAliasing_Light_SubPixel,
+    AntiAliasing_LCD,
+    AntiAliasing_LCD_BGR,
+    AntiAliasing_LCD_Vertical,
+    AntiAliasing_LCD_Vertical_BGR
+  };
+};
+
+
+// end of ttsettingscomboboxmodel.hpp



reply via email to

[Prev in Thread] Current Thread [Next in Thread]