freetype-commit
[Top][All Lists]
Advanced

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

[Git][freetype/freetype-demos][gsoc-2022-chariri-final] 3 commits: [ftin


From: Charlie Jiang (@cqjjjzr)
Subject: [Git][freetype/freetype-demos][gsoc-2022-chariri-final] 3 commits: [ftinspect] Add auxiliary lines for the grid view.
Date: Sun, 04 Sep 2022 16:21:17 +0000

Charlie Jiang pushed to branch gsoc-2022-chariri-final at FreeType / FreeType Demo Programs

Commits:

  • ecf1cc2b
    by Charlie Jiang at 2022-09-05T00:20:09+08:00
    [ftinspect] Add auxiliary lines for the grid view.
    
    The aux lines will show advance and asc/descender.
    
    * src/ftinspect/glyphcomponents/grid.cpp,
      src/ftinspect/glyphcomponents/grid.hpp: Implement aux lines.
    
    * src/ftinspect/engine/engine.cpp, src/ftinspect/engine/engine.hpp:
      Add `currentSizeAscDescPx`.
    
    * src/ftinspect/panels/singular.cpp, src/ftinspect/panels/singular.hpp:
      Pass parameters to the `Grid` graphics item.
    
  • e944d974
    by Charlie Jiang at 2022-09-05T00:20:23+08:00
    [ftinspect] Support MM/GX.
    
    * src/ftinspect/panels/settingpanelmmgx.cpp,
      src/ftinspect/panels/settingpanelmmgx.hpp:
      Add GUI widgets for MM/GX settings.
    
    * src/ftinspect/engine/mmgx.cpp, src/ftinspect/engine/mmgx.hpp:
      Add `MMGXAxisInfo` to retrieve axes info. However, the SFNT name table
      isn't implemented, so the SFNT based axis names are unavailable.
    
    * src/ftinspect/engine/engine.cpp, src/ftinspect/engine/engine.hpp:
      Add `applyMMGXDesignCoords`. Add getters `currentFontMMGXState` and
      `currentFontMMGXAxes`. Info is retrieved when loading font.
    
    * src/ftinspect/panels/settingpanel.cpp,
      src/ftinspect/panels/settingpanel.hpp: Uncomment functional code.
      Remove `checkHintingMode` and `checkStemDarkening`. Applying of delayed
      settings is taken care by the `MainGUI`. So emitting `fontReloadNeeded`
      simply will do the work.
    
    * src/ftinspect/maingui.cpp: Don't reset the cache so aggressively.
    
    * src/ftinspect/CMakeLists.txt, src/ftinspect/meson.build: Updated.
    
  • b7f587e3
    by Charlie Jiang at 2022-09-05T00:20:23+08:00
    [ftinspect] Add SFNT `name` table retrieving.
    
    * src/ftinspect/engine/fontinfo.cpp, src/ftinspect/engine/fontinfo.hpp:
      New files, add `SFNTName` to retrieve `name` table.
      Conversions to `QString` from mainstream encodings are supported.
    
    * src/ftinspect/engine/engine.cpp, src/ftinspect/engine/engine.hpp:
      Add `currentFontSFNTNames` and retrieve the `name` table when loading the
      font. Also pass the SFNT name table when loading palettes.
    
    * src/ftinspect/engine/mmgx.cpp, src/ftinspect/engine/paletteinfo.cpp:
      Uncomment functional code to make use of the `name` table.
    
    * src/ftinspect/CMakeLists.txt, src/ftinspect/meson.build: Updated.
    

17 changed files:

Changes:

  • src/ftinspect/CMakeLists.txt
    ... ... @@ -24,6 +24,8 @@ add_executable(ftinspect
    24 24
       "engine/fontfilemanager.cpp"
    
    25 25
       "engine/rendering.cpp"
    
    26 26
       "engine/paletteinfo.cpp"
    
    27
    +  "engine/mmgx.cpp"
    
    28
    +  "engine/fontinfo.cpp"
    
    27 29
     
    
    28 30
       "glyphcomponents/glyphbitmap.cpp"
    
    29 31
       "glyphcomponents/glyphoutline.cpp"
    
    ... ... @@ -40,6 +42,7 @@ add_executable(ftinspect
    40 42
       "models/customcomboboxmodels.cpp"
    
    41 43
     
    
    42 44
       "panels/settingpanel.cpp"
    
    45
    +  "panels/settingpanelmmgx.cpp"
    
    43 46
       "panels/singular.cpp"
    
    44 47
     )
    
    45 48
     target_link_libraries(ftinspect
    

  • src/ftinspect/engine/engine.cpp
    ... ... @@ -11,6 +11,7 @@
    11 11
     #include <freetype/ftmodapi.h>
    
    12 12
     #include <freetype/ftdriver.h>
    
    13 13
     #include <freetype/ftlcdfil.h>
    
    14
    +#include <freetype/ftmm.h>
    
    14 15
     
    
    15 16
     
    
    16 17
     /////////////////////////////////////////////////////////////////////////////
    
    ... ... @@ -327,6 +328,7 @@ Engine::loadFont(int fontIndex,
    327 328
         ftSize_ = NULL;
    
    328 329
         curFamilyName_ = QString();
    
    329 330
         curStyleName_ = QString();
    
    331
    +    curSFNTNames_.clear();
    
    330 332
       }
    
    331 333
       else
    
    332 334
       {
    
    ... ... @@ -342,7 +344,10 @@ Engine::loadFont(int fontIndex,
    342 344
           fontType_ = FontType_TrueType;
    
    343 345
         else
    
    344 346
           fontType_ = FontType_Other;
    
    347
    +
    
    348
    +    SFNTName::get(this, curSFNTNames_);
    
    345 349
         loadPaletteInfos();
    
    350
    +    curMMGXState_ = MMGXAxisInfo::get(this, curMMGXAxes_);
    
    346 351
       }
    
    347 352
     
    
    348 353
       curNumGlyphs_ = numGlyphs;
    
    ... ... @@ -458,6 +463,14 @@ Engine::currentFontFixedSizes()
    458 463
     }
    
    459 464
     
    
    460 465
     
    
    466
    +std::pair<int, int>
    
    467
    +Engine::currentSizeAscDescPx()
    
    468
    +{
    
    469
    +  return { ftSize_->metrics.ascender >> 6,
    
    470
    +           ftSize_->metrics.descender >> 6 };
    
    471
    +}
    
    472
    +
    
    473
    +
    
    461 474
     QString
    
    462 475
     Engine::glyphName(int index)
    
    463 476
     {
    
    ... ... @@ -649,6 +662,19 @@ Engine::setStemDarkening(bool darkening)
    649 662
     }
    
    650 663
     
    
    651 664
     
    
    665
    +void
    
    666
    +Engine::applyMMGXDesignCoords(FT_Fixed* coords,
    
    667
    +                              size_t count)
    
    668
    +{
    
    669
    +  if (!ftSize_)
    
    670
    +    return;
    
    671
    +  if (count >= UINT_MAX)
    
    672
    +    count = UINT_MAX - 1;
    
    673
    +  FT_Set_Var_Design_Coordinates(ftSize_->face,
    
    674
    +                                static_cast<unsigned>(count), coords);
    
    675
    +}
    
    676
    +
    
    677
    +
    
    652 678
     void
    
    653 679
     Engine::update()
    
    654 680
     {
    
    ... ... @@ -826,8 +852,8 @@ Engine::loadPaletteInfos()
    826 852
       // size never exceeds max val of ushort.
    
    827 853
       curPaletteInfos_.reserve(paletteData_.num_palettes);
    
    828 854
       for (int i = 0; i < paletteData_.num_palettes; ++i)
    
    829
    -    curPaletteInfos_.emplace_back(ftFallbackFace_, paletteData_, i, nullptr);
    
    830
    -    // no `NULL` here - we need `std::nullptr_t`
    
    855
    +    curPaletteInfos_.emplace_back(ftFallbackFace_, paletteData_, i,
    
    856
    +                                  &curSFNTNames_);
    
    831 857
     }
    
    832 858
     
    
    833 859
     
    

  • src/ftinspect/engine/engine.hpp
    ... ... @@ -8,6 +8,8 @@
    8 8
     #include "fontfilemanager.hpp"
    
    9 9
     
    
    10 10
     #include "paletteinfo.hpp"
    
    11
    +#include "fontinfo.hpp"
    
    12
    +#include "mmgx.hpp"
    
    11 13
     #include "rendering.hpp"
    
    12 14
     
    
    13 15
     #include <memory>
    
    ... ... @@ -119,6 +121,9 @@ public:
    119 121
       std::vector<PaletteInfo>& currentFontPalettes() { return curPaletteInfos_; }
    
    120 122
       FT_Color* currentPalette() { return palette_; }
    
    121 123
       FT_Palette_Data& currentFontPaletteData() { return paletteData_; }
    
    124
    +  MMGXState currentFontMMGXState() { return curMMGXState_; }
    
    125
    +  std::vector<MMGXAxisInfo>& currentFontMMGXAxes() { return curMMGXAxes_; }
    
    126
    +  std::vector<SFNTName>& currentFontSFNTNames() { return curSFNTNames_; }
    
    122 127
     
    
    123 128
       QString glyphName(int glyphIndex);
    
    124 129
       long numberOfFaces(int fontIndex);
    
    ... ... @@ -132,6 +137,8 @@ public:
    132 137
       bool currentFontHasColorLayers();
    
    133 138
       std::vector<int> currentFontFixedSizes();
    
    134 139
     
    
    140
    +  std::pair<int, int> currentSizeAscDescPx();
    
    141
    +
    
    135 142
       // (settings)
    
    136 143
       int dpi() { return dpi_; }
    
    137 144
       FTC_ImageType imageType() { return &imageType_; }
    
    ... ... @@ -181,7 +188,8 @@ public:
    181 188
       void setTTInterpreterVersion(int version);
    
    182 189
     
    
    183 190
       void setStemDarkening(bool darkening);
    
    184
    -  
    
    191
    +  void applyMMGXDesignCoords(FT_Fixed* coords, size_t count);
    
    192
    +
    
    185 193
       //////// Misc
    
    186 194
     
    
    187 195
       friend FT_Error faceRequester(FTC_FaceID,
    
    ... ... @@ -198,11 +206,14 @@ private:
    198 206
     
    
    199 207
       // font info
    
    200 208
       int curFontIndex_ = -1;
    
    209
    +  int fontType_;
    
    201 210
       QString curFamilyName_;
    
    202 211
       QString curStyleName_;
    
    203 212
       int curNumGlyphs_ = -1;
    
    204 213
       std::vector<PaletteInfo> curPaletteInfos_;
    
    205
    -  int fontType_;
    
    214
    +  MMGXState curMMGXState_ = MMGXState::NoMMGX;
    
    215
    +  std::vector<MMGXAxisInfo> curMMGXAxes_;
    
    216
    +  std::vector<SFNTName> curSFNTNames_;
    
    206 217
     
    
    207 218
       // basic objects
    
    208 219
       FT_Library library_;
    

  • src/ftinspect/engine/fontinfo.cpp
    1
    +// fontinfo.cpp
    
    2
    +
    
    3
    +// Copyright (C) 2022 by Charlie Jiang.
    
    4
    +
    
    5
    +#include "fontinfo.hpp"
    
    6
    +
    
    7
    +#include "engine.hpp"
    
    8
    +
    
    9
    +#include <memory>
    
    10
    +#include <utility>
    
    11
    +#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
    
    12
    +#include <QTextCodec>
    
    13
    +#else
    
    14
    +#include <QStringConverter>
    
    15
    +#include <QByteArrayView>
    
    16
    +#endif
    
    17
    +#include <freetype/ftmodapi.h>
    
    18
    +#include <freetype/ttnameid.h>
    
    19
    +
    
    20
    +
    
    21
    +void
    
    22
    +SFNTName::get(Engine* engine,
    
    23
    +              std::vector<SFNTName>& list)
    
    24
    +{
    
    25
    +  auto face = engine->currentFallbackFtFace();
    
    26
    +  if (!face || !FT_IS_SFNT(face))
    
    27
    +  {
    
    28
    +    list.clear();
    
    29
    +    return;
    
    30
    +  }
    
    31
    +  
    
    32
    +  auto newSize = FT_Get_Sfnt_Name_Count(face);
    
    33
    +  if (list.size() != static_cast<size_t>(newSize))
    
    34
    +    list.resize(newSize);
    
    35
    +
    
    36
    +  FT_SfntName sfntName;
    
    37
    +  FT_SfntLangTag langTag;
    
    38
    +  for (unsigned int i = 0; i < newSize; ++i)
    
    39
    +  {
    
    40
    +    FT_Get_Sfnt_Name(face, i, &sfntName);
    
    41
    +    auto& obj = list[i];
    
    42
    +    obj.platformID = sfntName.platform_id;
    
    43
    +    obj.encodingID = sfntName.encoding_id;
    
    44
    +    obj.languageID = sfntName.language_id;
    
    45
    +    obj.nameID = sfntName.name_id;
    
    46
    +
    
    47
    +    auto len = sfntName.string_len >= INT_MAX
    
    48
    +                 ? INT_MAX - 1
    
    49
    +                 : sfntName.string_len;
    
    50
    +    obj.strBuf = QByteArray(reinterpret_cast<const char*>(sfntName.string), 
    
    51
    +                            len);
    
    52
    +    obj.str = sfntNameToQString(sfntName, &obj.strValid);
    
    53
    +
    
    54
    +    if (obj.languageID >= 0x8000)
    
    55
    +    {
    
    56
    +      auto err = FT_Get_Sfnt_LangTag(face, obj.languageID, &langTag);
    
    57
    +      if (!err)
    
    58
    +        obj.langTag = utf16BEToQString(reinterpret_cast<char*>(langTag.string),
    
    59
    +                                       langTag.string_len);
    
    60
    +    }
    
    61
    +  }
    
    62
    +}
    
    63
    +
    
    64
    +
    
    65
    +QString
    
    66
    +SFNTName::sfntNameToQString(FT_SfntName const& sfntName, 
    
    67
    +                            bool* outSuccess)
    
    68
    +{
    
    69
    +  return sfntNameToQString(sfntName.platform_id, sfntName.encoding_id,
    
    70
    +                           reinterpret_cast<char const*>(sfntName.string),
    
    71
    +                           sfntName.string_len,
    
    72
    +                           outSuccess);
    
    73
    +}
    
    74
    +
    
    75
    +
    
    76
    +QString
    
    77
    +SFNTName::sfntNameToQString(SFNTName const& sfntName, bool* outSuccess)
    
    78
    +{
    
    79
    +  return sfntNameToQString(sfntName.platformID, sfntName.encodingID,
    
    80
    +                           sfntName.strBuf.data(), sfntName.strBuf.size(),
    
    81
    +                           outSuccess);
    
    82
    +}
    
    83
    +
    
    84
    +
    
    85
    +QString
    
    86
    +SFNTName::sfntNameToQString(unsigned short platformID,
    
    87
    +                            unsigned short encodingID,
    
    88
    +                            char const* str,
    
    89
    +                            size_t size,
    
    90
    +                            bool* outSuccess)
    
    91
    +{
    
    92
    +  // TODO not complete.
    
    93
    +  if (size >= INT_MAX - 1)
    
    94
    +    return "";
    
    95
    +
    
    96
    +  if (outSuccess)
    
    97
    +    *outSuccess = true;
    
    98
    +
    
    99
    +  switch (platformID)
    
    100
    +  {
    
    101
    +  case TT_PLATFORM_APPLE_UNICODE:
    
    102
    +    // All UTF-16BE.
    
    103
    +    return utf16BEToQString(str, size);
    
    104
    +  case TT_PLATFORM_MACINTOSH:
    
    105
    +    if (encodingID == TT_MAC_ID_ROMAN)
    
    106
    +      return QString::fromLatin1(str, static_cast<int>(size));
    
    107
    +
    
    108
    +    if (outSuccess)
    
    109
    +      *outSuccess = false;
    
    110
    +    return "<encoding unsupported>";
    
    111
    +  case TT_PLATFORM_ISO:
    
    112
    +    switch (encodingID)
    
    113
    +    {
    
    114
    +    case TT_ISO_ID_7BIT_ASCII:
    
    115
    +    case TT_ISO_ID_8859_1:
    
    116
    +      return QString::fromLatin1(str, static_cast<int>(size));
    
    117
    +    case TT_ISO_ID_10646:
    
    118
    +      return utf16BEToQString(str, size);
    
    119
    +    default:
    
    120
    +      if (outSuccess)
    
    121
    +        *outSuccess = false;
    
    122
    +      return "<encoding unsupported>";
    
    123
    +    }
    
    124
    +  case TT_PLATFORM_MICROSOFT:
    
    125
    +    switch (encodingID)
    
    126
    +    {
    
    127
    +      /* TT_MS_ID_SYMBOL_CS is Unicode, similar to PID/EID=3/1 */
    
    128
    +    case TT_MS_ID_SYMBOL_CS:
    
    129
    +    case TT_MS_ID_UNICODE_CS:
    
    130
    +    case TT_MS_ID_UCS_4: // This is UTF-16LE as well, according to MS doc
    
    131
    +      return utf16BEToQString(str, size);
    
    132
    +
    
    133
    +    default:
    
    134
    +      if (outSuccess)
    
    135
    +        *outSuccess = false;
    
    136
    +      return "<encoding unsupported>";
    
    137
    +    }
    
    138
    +  }
    
    139
    +
    
    140
    +  if (outSuccess)
    
    141
    +    *outSuccess = false;
    
    142
    +  return "<platform unsupported>";
    
    143
    +}
    
    144
    +
    
    145
    +
    
    146
    +#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
    
    147
    +QTextCodec* utf16BECodec = QTextCodec::codecForName("UTF-16BE");
    
    148
    +#else
    
    149
    +QStringDecoder utf16BECvt = (QStringDecoder(QStringDecoder::Utf16BE))(size);
    
    150
    +#endif
    
    151
    +
    
    152
    +QString
    
    153
    +SFNTName::utf16BEToQString(char const* str,
    
    154
    +                           size_t size)
    
    155
    +{
    
    156
    +#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
    
    157
    +  if (size >= INT_MAX)
    
    158
    +    size = INT_MAX - 1;
    
    159
    +  return utf16BECodec->toUnicode(str, static_cast<int>(size));
    
    160
    +#else
    
    161
    +  return utf16BECvt(QByteArrayView(reinterpret_cast<char*>(str), size));
    
    162
    +#endif
    
    163
    +}
    
    164
    +
    
    165
    +
    
    166
    +// end of fontinfo.cpp

  • src/ftinspect/engine/fontinfo.hpp
    1
    +// fontinfo.hpp
    
    2
    +
    
    3
    +// Copyright (C) 2022 by Charlie Jiang.
    
    4
    +
    
    5
    +#pragma once
    
    6
    +
    
    7
    +#include <set>
    
    8
    +#include <vector>
    
    9
    +#include <QByteArray>
    
    10
    +#include <QString>
    
    11
    +#include <freetype/freetype.h>
    
    12
    +#include <freetype/ftsnames.h>
    
    13
    +
    
    14
    +class Engine;
    
    15
    +struct SFNTName
    
    16
    +{
    
    17
    +  unsigned short nameID;
    
    18
    +  unsigned short platformID;
    
    19
    +  unsigned short encodingID;
    
    20
    +  unsigned short languageID;
    
    21
    +  QByteArray strBuf;
    
    22
    +  QString str;
    
    23
    +  QString langTag;
    
    24
    +  bool strValid = false;
    
    25
    +
    
    26
    +  static void get(Engine* engine,
    
    27
    +                  std::vector<SFNTName>& list);
    
    28
    +  static QString sfntNameToQString(FT_SfntName const& sfntName,
    
    29
    +                                   bool* outSuccess = NULL);
    
    30
    +  static QString sfntNameToQString(SFNTName const& sfntName,
    
    31
    +                                   bool* outSuccess = NULL);
    
    32
    +  static QString sfntNameToQString(unsigned short platformID,
    
    33
    +                                   unsigned short encodingID, 
    
    34
    +                                   char const* str, size_t size,
    
    35
    +                                   bool* outSuccess = NULL);
    
    36
    +  static QString utf16BEToQString(char const* str, size_t size);
    
    37
    +
    
    38
    +
    
    39
    +  friend bool
    
    40
    +  operator==(const SFNTName& lhs,
    
    41
    +             const SFNTName& rhs)
    
    42
    +  {
    
    43
    +    return lhs.nameID == rhs.nameID
    
    44
    +      && lhs.platformID == rhs.platformID
    
    45
    +      && lhs.encodingID == rhs.encodingID
    
    46
    +      && lhs.languageID == rhs.languageID
    
    47
    +      && lhs.strBuf == rhs.strBuf
    
    48
    +      && lhs.langTag == rhs.langTag;
    
    49
    +  }
    
    50
    +
    
    51
    +
    
    52
    +  friend bool
    
    53
    +  operator!=(const SFNTName& lhs,
    
    54
    +             const SFNTName& rhs)
    
    55
    +  {
    
    56
    +    return !(lhs == rhs);
    
    57
    +  }
    
    58
    +};
    
    59
    +
    
    60
    +
    
    61
    +// end of fontinfo.hpp

  • src/ftinspect/engine/mmgx.cpp
    1
    +// mmgx.cpp
    
    2
    +
    
    3
    +// Copyright (C) 2022 by Charlie Jiang.
    
    4
    +
    
    5
    +#include "mmgx.hpp"
    
    6
    +
    
    7
    +#include "engine.hpp"
    
    8
    +
    
    9
    +#include <freetype/ftmm.h>
    
    10
    +
    
    11
    +
    
    12
    +MMGXState
    
    13
    +MMGXAxisInfo::get(Engine* engine,
    
    14
    +                  std::vector<MMGXAxisInfo>& infos)
    
    15
    +{
    
    16
    +  auto face = engine->currentFallbackFtFace();
    
    17
    +  if (!face)
    
    18
    +  {
    
    19
    +    infos.clear();
    
    20
    +    return MMGXState::NoMMGX;
    
    21
    +  }
    
    22
    +
    
    23
    +  if (!FT_HAS_MULTIPLE_MASTERS(face))
    
    24
    +  {
    
    25
    +    infos.clear();
    
    26
    +    return MMGXState::NoMMGX;
    
    27
    +  }
    
    28
    +
    
    29
    +  FT_Multi_Master dummy;
    
    30
    +  auto error = FT_Get_Multi_Master(face, &dummy);
    
    31
    +  auto state = error ? MMGXState::GX_OVF : MMGXState::MM;
    
    32
    +  
    
    33
    +  FT_MM_Var* mm;
    
    34
    +  if (FT_Get_MM_Var(face, &mm))
    
    35
    +  {
    
    36
    +    infos.clear();
    
    37
    +    return state;
    
    38
    +  }
    
    39
    +
    
    40
    +  infos.resize(mm->num_axis);
    
    41
    +
    
    42
    +  auto& sfnt = engine->currentFontSFNTNames();
    
    43
    +  for (unsigned int i = 0; i < mm->num_axis; ++i)
    
    44
    +  {
    
    45
    +    auto& axis = mm->axis[i];
    
    46
    +    auto& info = infos[i];
    
    47
    +    info.maximum = axis.maximum / 65536.0;
    
    48
    +    info.minimum = axis.minimum / 65536.0;
    
    49
    +    info.def = axis.def / 65536.0;
    
    50
    +    info.tag = axis.tag;
    
    51
    +    info.isMM = state == MMGXState::MM;
    
    52
    +
    
    53
    +    unsigned int flags = 0;
    
    54
    +    FT_Get_Var_Axis_Flags(mm, i, &flags);
    
    55
    +    info.hidden = (flags & FT_VAR_AXIS_FLAG_HIDDEN) != 0;
    
    56
    +
    
    57
    +    auto nameSet = false;
    
    58
    +    if (state == MMGXState::GX_OVF)
    
    59
    +    {
    
    60
    +      auto strid = mm->axis[i].strid;
    
    61
    +      for (auto& obj : sfnt)
    
    62
    +      {
    
    63
    +        if (obj.nameID == strid && obj.strValid)
    
    64
    +        {
    
    65
    +          info.name = obj.str;
    
    66
    +          nameSet = true;
    
    67
    +          break;
    
    68
    +        }
    
    69
    +      }
    
    70
    +    }
    
    71
    +
    
    72
    +    // XXX security flaw
    
    73
    +    if (!nameSet)
    
    74
    +      info.name = QString(axis.name);
    
    75
    +  }
    
    76
    +
    
    77
    +  FT_Done_MM_Var(face->glyph->library, mm);
    
    78
    +
    
    79
    +  return state;
    
    80
    +}
    
    81
    +
    
    82
    +
    
    83
    +// end of mmgx.cpp

  • src/ftinspect/engine/mmgx.hpp
    1
    +// mmgx.hpp
    
    2
    +
    
    3
    +// Copyright (C) 2022 by Charlie Jiang.
    
    4
    +
    
    5
    +#pragma once
    
    6
    +
    
    7
    +#include <vector>
    
    8
    +#include <QString>
    
    9
    +
    
    10
    +class Engine;
    
    11
    +
    
    12
    +enum class MMGXState
    
    13
    +{
    
    14
    +  NoMMGX,
    
    15
    +  MM,     // Adobe MM
    
    16
    +  GX_OVF, // GX or OpenType variable fonts
    
    17
    +};
    
    18
    +
    
    19
    +struct MMGXAxisInfo
    
    20
    +{
    
    21
    +  QString name;
    
    22
    +  unsigned long tag;
    
    23
    +
    
    24
    +  double minimum;
    
    25
    +  double maximum;
    
    26
    +  double def;
    
    27
    +
    
    28
    +  bool hidden;
    
    29
    +  bool isMM;
    
    30
    +
    
    31
    +  static MMGXState get(Engine* engine, std::vector<MMGXAxisInfo>& infos);
    
    32
    +
    
    33
    +
    
    34
    +  friend bool
    
    35
    +  operator==(const MMGXAxisInfo& lhs,
    
    36
    +             const MMGXAxisInfo& rhs)
    
    37
    +  {
    
    38
    +    return lhs.name == rhs.name
    
    39
    +      && lhs.tag == rhs.tag
    
    40
    +      && lhs.minimum == rhs.minimum
    
    41
    +      && lhs.maximum == rhs.maximum
    
    42
    +      && lhs.def == rhs.def
    
    43
    +      && lhs.hidden == rhs.hidden
    
    44
    +      && lhs.isMM == rhs.isMM;
    
    45
    +  }
    
    46
    +
    
    47
    +
    
    48
    +  friend bool
    
    49
    +  operator!=(const MMGXAxisInfo& lhs,
    
    50
    +             const MMGXAxisInfo& rhs)
    
    51
    +  {
    
    52
    +    return !(lhs == rhs);
    
    53
    +  }
    
    54
    +};
    
    55
    +
    
    56
    +
    
    57
    +// end of mmgx.hpp

  • src/ftinspect/engine/paletteinfo.cpp
    ... ... @@ -4,7 +4,7 @@
    4 4
     
    
    5 5
     #include "paletteinfo.hpp"
    
    6 6
     
    
    7
    -//#include "fontinfo.hpp"
    
    7
    +#include "fontinfo.hpp"
    
    8 8
     
    
    9 9
     PaletteInfo::PaletteInfo(FT_Face face, 
    
    10 10
                              FT_Palette_Data& data, 
    
    ... ... @@ -15,15 +15,15 @@ PaletteInfo::PaletteInfo(FT_Face face,
    15 15
       if (sfntNames && data.palette_name_ids)
    
    16 16
       {
    
    17 17
         auto id = data.palette_name_ids[index];
    
    18
    -    name = "(unsupported)";
    
    19
    -    //for (auto& obj : *sfntNames)
    
    20
    -    //{
    
    21
    -    //  if (obj.nameID == id && obj.strValid)
    
    22
    -    //  {
    
    23
    -    //    name = obj.str;
    
    24
    -    //    break;
    
    25
    -    //  }
    
    26
    -    //}
    
    18
    +    name = "(invalid)";
    
    19
    +    for (auto& obj : *sfntNames)
    
    20
    +    {
    
    21
    +      if (obj.nameID == id && obj.strValid)
    
    22
    +      {
    
    23
    +        name = obj.str;
    
    24
    +        break;
    
    25
    +      }
    
    26
    +    }
    
    27 27
       }
    
    28 28
       else
    
    29 29
         name = "(unnamed)";
    

  • src/ftinspect/glyphcomponents/grid.cpp
    ... ... @@ -119,7 +119,15 @@ Grid::paint(QPainter* painter,
    119 119
     
    
    120 120
       if (showAuxLines_)
    
    121 121
       {
    
    122
    -    // TODO: impl
    
    122
    +    painter->setPen(gb->ascDescAuxPen);
    
    123
    +    painter->drawLine(minX, ascender_,
    
    124
    +                      maxX, ascender_);
    
    125
    +    painter->drawLine(minX, descender_,
    
    126
    +                      maxX, descender_);
    
    127
    +
    
    128
    +    painter->setPen(gb->advanceAuxPen);
    
    129
    +    painter->drawLine(advance_, minY,
    
    130
    +                      advance_, maxY);
    
    123 131
       }
    
    124 132
     }
    
    125 133
     
    
    ... ... @@ -133,4 +141,19 @@ Grid::setShowGrid(bool showGrid, bool showAuxLines)
    133 141
     }
    
    134 142
     
    
    135 143
     
    
    144
    +void
    
    145
    +Grid::updateParameters(int ascenderPx,
    
    146
    +                       int descenderPx,
    
    147
    +                       int advancePx)
    
    148
    +{
    
    149
    +  // Need to flip the Y coord (originally Cartesian)
    
    150
    +  ascender_ = -ascenderPx;
    
    151
    +  descender_ = -descenderPx;
    
    152
    +  advance_ = advancePx;
    
    153
    +
    
    154
    +  if (showAuxLines_)
    
    155
    +    update();
    
    156
    +}
    
    157
    +
    
    158
    +
    
    136 159
     // end of grid.cpp

  • src/ftinspect/glyphcomponents/grid.hpp
    ... ... @@ -20,6 +20,7 @@ public:
    20 20
                  QWidget* widget) override;
    
    21 21
     
    
    22 22
       void setShowGrid(bool showGrid, bool showAuxLines);
    
    23
    +  void updateParameters(int ascenderPx, int descenderPx, int advancePx);
    
    23 24
     
    
    24 25
       void updateRect(); // there's no signal/slots for QGraphicsItem.
    
    25 26
     
    
    ... ... @@ -30,6 +31,9 @@ private:
    30 31
     
    
    31 32
       bool showGrid_ = true;
    
    32 33
       bool showAuxLines_ = false;
    
    34
    +
    
    35
    +  int ascender_ = 0, descender_ = 0;
    
    36
    +  int advance_ = 0;
    
    33 37
     };
    
    34 38
     
    
    35 39
     
    

  • src/ftinspect/maingui.cpp
    ... ... @@ -180,7 +180,7 @@ MainGUI::repaintCurrentTab()
    180 180
     void
    
    181 181
     MainGUI::reloadCurrentTabFont()
    
    182 182
     {
    
    183
    -  engine_->resetCache();
    
    183
    +  settingPanel_->applyDelayedSettings(); // This will reset the cache.
    
    184 184
       applySettings();
    
    185 185
       auto index = tabWidget_->currentIndex();
    
    186 186
       if (index >= 0 && static_cast<size_t>(index) < tabs_.size())
    
    ... ... @@ -192,7 +192,6 @@ void
    192 192
     MainGUI::applySettings()
    
    193 193
     {
    
    194 194
       settingPanel_->applySettings();
    
    195
    -  settingPanel_->applyDelayedSettings();
    
    196 195
     }
    
    197 196
     
    
    198 197
     
    

  • src/ftinspect/meson.build
    ... ... @@ -25,6 +25,8 @@ if qt5_dep.found()
    25 25
         'engine/fontfilemanager.cpp',
    
    26 26
         'engine/rendering.cpp',
    
    27 27
         'engine/paletteinfo.cpp',
    
    28
    +    'engine/mmgx.cpp',
    
    29
    +    'engine/fontinfo.cpp',
    
    28 30
     
    
    29 31
         'glyphcomponents/glyphbitmap.cpp',
    
    30 32
         'glyphcomponents/glyphoutline.cpp',
    
    ... ... @@ -41,6 +43,7 @@ if qt5_dep.found()
    41 43
         'models/customcomboboxmodels.cpp',
    
    42 44
     
    
    43 45
         'panels/settingpanel.cpp',
    
    46
    +    'panels/settingpanelmmgx.cpp',
    
    44 47
         'panels/singular.cpp',
    
    45 48
     
    
    46 49
         'ftinspect.cpp',
    
    ... ... @@ -58,6 +61,7 @@ if qt5_dep.found()
    58 61
           'maingui.hpp',
    
    59 62
           'models/customcomboboxmodels.hpp',
    
    60 63
           'panels/settingpanel.hpp',
    
    64
    +      'panels/settingpanelmmgx.hpp',
    
    61 65
           'panels/singular.hpp',
    
    62 66
         ],
    
    63 67
         dependencies: qt5_dep)
    

  • src/ftinspect/panels/settingpanel.cpp
    ... ... @@ -99,16 +99,6 @@ SettingPanel::checkHinting()
    99 99
     }
    
    100 100
     
    
    101 101
     
    
    102
    -void
    
    103
    -SettingPanel::checkHintingMode()
    
    104
    -{
    
    105
    -  //if (!comparatorMode_)
    
    106
    -  applyDelayedSettings();
    
    107
    -
    
    108
    -  emit fontReloadNeeded();
    
    109
    -}
    
    110
    -
    
    111
    -
    
    112 102
     void
    
    113 103
     SettingPanel::checkAutoHinting()
    
    114 104
     {
    
    ... ... @@ -193,16 +183,6 @@ SettingPanel::checkPalette()
    193 183
     }
    
    194 184
     
    
    195 185
     
    
    196
    -void
    
    197
    -SettingPanel::checkStemDarkening()
    
    198
    -{
    
    199
    -  //if (!comparatorMode_)
    
    200
    -  applyDelayedSettings();
    
    201
    -
    
    202
    -  emit fontReloadNeeded();
    
    203
    -}
    
    204
    -
    
    205
    -
    
    206 186
     void
    
    207 187
     SettingPanel::openBackgroundPicker()
    
    208 188
     {
    
    ... ... @@ -339,7 +319,7 @@ SettingPanel::onFontChanged()
    339 319
       paletteComboBox_->setEnabled(colorLayerCheckBox_->isChecked()
    
    340 320
                                    && paletteComboBox_->count() > 0);
    
    341 321
       populatePalettes();
    
    342
    -  //mmgxPanel_->reloadFont();
    
    322
    +  mmgxPanel_->reloadFont();
    
    343 323
       blockSignals(blockState);
    
    344 324
     
    
    345 325
       // Place this after `blockSignals` to let the signals emitted normally
    
    ... ... @@ -389,7 +369,7 @@ SettingPanel::applySettings()
    389 369
     
    
    390 370
       engine_->renderingEngine()->setForeground(foregroundColor_.rgba());
    
    391 371
       engine_->renderingEngine()->setBackground(backgroundColor_.rgba());
    
    392
    -  //mmgxPanel_->applySettings();
    
    372
    +  mmgxPanel_->applySettings();
    
    393 373
     }
    
    394 374
     
    
    395 375
     
    
    ... ... @@ -481,8 +461,7 @@ SettingPanel::createLayout()
    481 461
       gammaLabel_->setBuddy(gammaSlider_);
    
    482 462
       gammaValueLabel_ = new QLabel(this);
    
    483 463
     
    
    484
    -  // TODO: MM/GX
    
    485
    -  mmgxPanel_ = new QWidget(this);
    
    464
    +  mmgxPanel_ = new SettingPanelMMGX(this, engine_);
    
    486 465
     
    
    487 466
       backgroundButton_ = new QPushButton(tr("Background"), this);
    
    488 467
       foregroundButton_ = new QPushButton(tr("Foreground"), this);
    
    ... ... @@ -622,7 +601,7 @@ SettingPanel::createConnections()
    622 601
       // use `qOverload` here to prevent ambiguity.
    
    623 602
       connect(hintingModeComboBox_, 
    
    624 603
               QOverload<int>::of(&QComboBox::currentIndexChanged),
    
    625
    -          this, &SettingPanel::checkHintingMode);
    
    604
    +          this, &SettingPanel::fontReloadNeeded);
    
    626 605
       connect(antiAliasingComboBox_,
    
    627 606
               QOverload<int>::of(&QComboBox::currentIndexChanged),
    
    628 607
               this, &SettingPanel::checkAntiAliasing);
    
    ... ... @@ -656,7 +635,7 @@ SettingPanel::createConnections()
    656 635
       connect(embeddedBitmapCheckBox_, &QCheckBox::clicked,
    
    657 636
               this, &SettingPanel::fontReloadNeeded);
    
    658 637
       connect(stemDarkeningCheckBox_, &QCheckBox::clicked,
    
    659
    -          this, &SettingPanel::checkStemDarkening);
    
    638
    +          this, &SettingPanel::fontReloadNeeded);
    
    660 639
       connect(colorLayerCheckBox_, &QCheckBox::clicked,
    
    661 640
               this, &SettingPanel::checkPalette);
    
    662 641
     
    
    ... ... @@ -664,6 +643,9 @@ SettingPanel::createConnections()
    664 643
               this, &SettingPanel::openBackgroundPicker);
    
    665 644
       connect(foregroundButton_, &QPushButton::clicked,
    
    666 645
               this, &SettingPanel::openForegroundPicker);
    
    646
    +
    
    647
    +  connect(mmgxPanel_, &SettingPanelMMGX::mmgxCoordsChanged,
    
    648
    +          this, &SettingPanel::fontReloadNeeded);
    
    667 649
     }
    
    668 650
     
    
    669 651
     
    

  • src/ftinspect/panels/settingpanel.hpp
    ... ... @@ -6,6 +6,7 @@
    6 6
     
    
    7 7
     #include "../engine/engine.hpp"
    
    8 8
     #include "../models/customcomboboxmodels.hpp"
    
    9
    +#include "settingpanelmmgx.hpp"
    
    9 10
     
    
    10 11
     #include <QWidget>
    
    11 12
     #include <QTabWidget>
    
    ... ... @@ -54,8 +55,7 @@ private:
    54 55
     
    
    55 56
       QWidget* generalTab_;
    
    56 57
       QWidget* hintingRenderingTab_;
    
    57
    -  //SettingPanelMMGX* mmgxPanel_;
    
    58
    -  QWidget* mmgxPanel_;
    
    58
    +  SettingPanelMMGX* mmgxPanel_;
    
    59 59
     
    
    60 60
       QLabel* gammaLabel_;
    
    61 61
       QLabel* gammaValueLabel_;
    
    ... ... @@ -113,11 +113,9 @@ private:
    113 113
     
    
    114 114
       void checkAllSettings();
    
    115 115
       void checkHinting();
    
    116
    -  void checkHintingMode();
    
    117 116
       void checkAutoHinting();
    
    118 117
       void checkAntiAliasing();
    
    119 118
       void checkPalette();
    
    120
    -  void checkStemDarkening();
    
    121 119
     
    
    122 120
       void openBackgroundPicker();
    
    123 121
       void openForegroundPicker();
    

  • src/ftinspect/panels/settingpanelmmgx.cpp
    1
    +// settingpanelmmgx.cpp
    
    2
    +
    
    3
    +// Copyright (C) 2022 by Charlie Jiang.
    
    4
    +
    
    5
    +#include "settingpanelmmgx.hpp"
    
    6
    +
    
    7
    +#include <QScrollBar>
    
    8
    +
    
    9
    +#include "../engine/engine.hpp"
    
    10
    +#include "../uihelper.hpp"
    
    11
    +
    
    12
    +SettingPanelMMGX::SettingPanelMMGX(QWidget* parent,
    
    13
    +                                   Engine* engine)
    
    14
    +: QWidget(parent),
    
    15
    +  engine_(engine)
    
    16
    +{
    
    17
    +  createLayout();
    
    18
    +  createConnections();
    
    19
    +}
    
    20
    +
    
    21
    +
    
    22
    +void
    
    23
    +SettingPanelMMGX::reloadFont()
    
    24
    +{
    
    25
    +  setEnabled(engine_->currentFontMMGXState() != MMGXState::NoMMGX);
    
    26
    +  if (currentAxes_ == engine_->currentFontMMGXAxes())
    
    27
    +    return;
    
    28
    +
    
    29
    +  currentAxes_ = engine_->currentFontMMGXAxes();
    
    30
    +
    
    31
    +  auto newSize = currentAxes_.size();
    
    32
    +  auto oldSize = itemWidgets_.size();
    
    33
    +  auto minSize = std::min(newSize, oldSize);
    
    34
    +
    
    35
    +  // This won't trigger unexpected updating since signals are blocked
    
    36
    +  for (size_t i = 0; i < minSize; ++i)
    
    37
    +    itemWidgets_[i]->updateInfo(currentAxes_[i]);
    
    38
    +
    
    39
    +  if (newSize < oldSize)
    
    40
    +  {
    
    41
    +    for (size_t i = newSize; i < oldSize; ++i)
    
    42
    +    {
    
    43
    +      auto w = itemWidgets_[i];
    
    44
    +      disconnect(w);
    
    45
    +      listLayout_->removeWidget(w);
    
    46
    +      delete w;
    
    47
    +    }
    
    48
    +    itemWidgets_.resize(newSize);
    
    49
    +  }
    
    50
    +  else if (newSize > oldSize)
    
    51
    +  {
    
    52
    +    itemWidgets_.resize(newSize);
    
    53
    +    for (size_t i = oldSize; i < newSize; ++i)
    
    54
    +    {
    
    55
    +      auto w = new MMGXSettingItem(this);
    
    56
    +      itemWidgets_[i] = w;
    
    57
    +      w->updateInfo(currentAxes_[i]);
    
    58
    +      listLayout_->addWidget(w);
    
    59
    +      connect(w, &MMGXSettingItem::valueChanged,
    
    60
    +              [this, i] { itemChanged(i); });
    
    61
    +    }
    
    62
    +  }
    
    63
    +  checkHidden();
    
    64
    +  retrieveValues();
    
    65
    +  applySettings();
    
    66
    +}
    
    67
    +
    
    68
    +
    
    69
    +void
    
    70
    +SettingPanelMMGX::applySettings()
    
    71
    +{
    
    72
    +  engine_->reloadFont();
    
    73
    +  engine_->applyMMGXDesignCoords(currentValues_.data(),
    
    74
    +                                 currentValues_.size());
    
    75
    +}
    
    76
    +
    
    77
    +
    
    78
    +void
    
    79
    +SettingPanelMMGX::checkHidden()
    
    80
    +{
    
    81
    +  if (itemWidgets_.size() < currentAxes_.size())
    
    82
    +    return; // This should never happen!
    
    83
    +  for (int i = 0; static_cast<size_t>(i) < currentAxes_.size(); ++i)
    
    84
    +    itemWidgets_[i]->setVisible(showHiddenCheckBox_->isChecked()
    
    85
    +                                || !currentAxes_[i].hidden);
    
    86
    +}
    
    87
    +
    
    88
    +
    
    89
    +void
    
    90
    +SettingPanelMMGX::createLayout()
    
    91
    +{
    
    92
    +  showHiddenCheckBox_ = new QCheckBox(tr("Show Hidden"), this);
    
    93
    +  groupingCheckBox_ = new QCheckBox(tr("Grouping"), this);
    
    94
    +  resetDefaultButton_ = new QPushButton(tr("Reset Default"), this);
    
    95
    +  itemsListWidget_ = new QWidget(this);
    
    96
    +  scrollArea_ = new UnboundScrollArea(this);
    
    97
    +
    
    98
    +  scrollArea_->setWidget(itemsListWidget_);
    
    99
    +  scrollArea_->setWidgetResizable(true);
    
    100
    +  itemsListWidget_->setAutoFillBackground(false);
    
    101
    +
    
    102
    +  mainLayout_ = new QVBoxLayout;
    
    103
    +  listLayout_ = new QVBoxLayout;
    
    104
    +  listWrapperLayout_ = new QVBoxLayout;
    
    105
    +
    
    106
    +  listLayout_->setSpacing(0);
    
    107
    +  listLayout_->setContentsMargins(0, 0, 0, 0);
    
    108
    +  itemsListWidget_->setContentsMargins(0, 0, 0, 0);
    
    109
    +
    
    110
    +  itemsListWidget_->setLayout(listWrapperLayout_);
    
    111
    +
    
    112
    +  listWrapperLayout_->addLayout(listLayout_);
    
    113
    +  listWrapperLayout_->addStretch(1);
    
    114
    +
    
    115
    +  mainLayout_->addWidget(showHiddenCheckBox_);
    
    116
    +  mainLayout_->addWidget(groupingCheckBox_);
    
    117
    +  mainLayout_->addWidget(resetDefaultButton_);
    
    118
    +  mainLayout_->addWidget(scrollArea_, 1);
    
    119
    +
    
    120
    +  setLayout(mainLayout_);
    
    121
    +}
    
    122
    +
    
    123
    +
    
    124
    +void
    
    125
    +SettingPanelMMGX::createConnections()
    
    126
    +{
    
    127
    +  connect(showHiddenCheckBox_, &QCheckBox::clicked,
    
    128
    +          this, &SettingPanelMMGX::checkHidden);
    
    129
    +  connect(resetDefaultButton_, &QCheckBox::clicked,
    
    130
    +          this, &SettingPanelMMGX::resetDefaultClicked);
    
    131
    +  connect(groupingCheckBox_, &QCheckBox::clicked,
    
    132
    +          this, &SettingPanelMMGX::checkGrouping);
    
    133
    +}
    
    134
    +
    
    135
    +
    
    136
    +void
    
    137
    +SettingPanelMMGX::retrieveValues()
    
    138
    +{
    
    139
    +  currentValues_.resize(currentAxes_.size());
    
    140
    +  for (unsigned i = 0; i < currentAxes_.size(); ++i)
    
    141
    +    currentValues_[i] = itemWidgets_[i]->value();
    
    142
    +}
    
    143
    +
    
    144
    +
    
    145
    +void
    
    146
    +SettingPanelMMGX::itemChanged(size_t index)
    
    147
    +{
    
    148
    +  if (groupingCheckBox_->isChecked()
    
    149
    +      && index < currentAxes_.size() && index < itemWidgets_.size())
    
    150
    +  {
    
    151
    +    auto tag = currentAxes_[index].tag;
    
    152
    +    auto value = itemWidgets_[index]->value();
    
    153
    +    for (size_t i = 0; i < itemWidgets_.size(); ++i)
    
    154
    +      if (i != index && currentAxes_[i].tag == tag)
    
    155
    +        itemWidgets_[i]->setValue(value);
    
    156
    +  }
    
    157
    +
    
    158
    +  retrieveValues();
    
    159
    +  emit mmgxCoordsChanged();
    
    160
    +}
    
    161
    +
    
    162
    +
    
    163
    +void
    
    164
    +SettingPanelMMGX::resetDefaultClicked()
    
    165
    +{
    
    166
    +  for (auto w : itemWidgets_)
    
    167
    +    w->resetDefault();
    
    168
    +
    
    169
    +  retrieveValues();
    
    170
    +  emit mmgxCoordsChanged();
    
    171
    +}
    
    172
    +
    
    173
    +
    
    174
    +void
    
    175
    +SettingPanelMMGX::checkGrouping()
    
    176
    +{
    
    177
    +  if (!groupingCheckBox_->isChecked())
    
    178
    +    return;
    
    179
    +  auto maxIndex = std::max(itemWidgets_.size(), currentAxes_.size());
    
    180
    +  for (size_t i = maxIndex - 1; ; --i)
    
    181
    +  {
    
    182
    +    if (!currentAxes_[i].hidden)
    
    183
    +    {
    
    184
    +      auto tag = currentAxes_[i].tag;
    
    185
    +      auto value = itemWidgets_[i]->value();
    
    186
    +      for (size_t j = 0; j < maxIndex; ++j)
    
    187
    +        if (j != i && currentAxes_[j].tag == tag)
    
    188
    +          itemWidgets_[j]->setValue(value);
    
    189
    +    }
    
    190
    +
    
    191
    +    if (i == 0)
    
    192
    +      break;
    
    193
    +  }
    
    194
    +
    
    195
    +  retrieveValues();
    
    196
    +  emit mmgxCoordsChanged();
    
    197
    +}
    
    198
    +
    
    199
    +
    
    200
    +MMGXSettingItem::MMGXSettingItem(QWidget* parent)
    
    201
    +: QFrame(parent)
    
    202
    +{
    
    203
    +  createLayout();
    
    204
    +  createConnections();
    
    205
    +}
    
    206
    +
    
    207
    +
    
    208
    +void
    
    209
    +MMGXSettingItem::updateInfo(MMGXAxisInfo& info)
    
    210
    +{
    
    211
    +  axisInfo_ = info;
    
    212
    +  valueValidator_->setRange(info.minimum, info.maximum, 10);
    
    213
    +
    
    214
    +  if (info.hidden)
    
    215
    +    nameLabel_->setText("<i>" + info.name + "</i>");
    
    216
    +  else
    
    217
    +    nameLabel_->setText(info.name);
    
    218
    +
    
    219
    +  // To keep things simple, we will use 1/1024 of the span between the min and
    
    220
    +  // max as one step on the slider.
    
    221
    +
    
    222
    +  slider_->setMinimum(0);
    
    223
    +  slider_->setTickInterval(1);
    
    224
    +  slider_->setMaximum(1024);
    
    225
    +
    
    226
    +  resetDefault();
    
    227
    +}
    
    228
    +
    
    229
    +
    
    230
    +void
    
    231
    +MMGXSettingItem::setValue(FT_Fixed value)
    
    232
    +{
    
    233
    +  actualValue_ = value;
    
    234
    +  updateSlider();
    
    235
    +  updateLineEdit();
    
    236
    +}
    
    237
    +
    
    238
    +
    
    239
    +void
    
    240
    +MMGXSettingItem::resetDefault()
    
    241
    +{
    
    242
    +  setValue(static_cast<FT_Fixed>(axisInfo_.def * 65536.0));
    
    243
    +}
    
    244
    +
    
    245
    +
    
    246
    +void
    
    247
    +MMGXSettingItem::createLayout()
    
    248
    +{
    
    249
    +  nameLabel_ = new QLabel(this);
    
    250
    +
    
    251
    +  // 1/1024 = 0.0009765625
    
    252
    +  valueValidator_ = new QDoubleValidator(0, 0, 10, this);
    
    253
    +  valueValidator_->setNotation(QDoubleValidator::StandardNotation);
    
    254
    +
    
    255
    +  valueLineEdit_ = new QLineEdit("0", this);
    
    256
    +  valueLineEdit_->setValidator(valueValidator_);
    
    257
    +
    
    258
    +  slider_ = new QSlider(this);
    
    259
    +  slider_->setOrientation(Qt::Horizontal);
    
    260
    +
    
    261
    +  resetDefaultButton_ = new QPushButton(this);
    
    262
    +  resetDefaultButton_->setText(tr("Def"));
    
    263
    +  setButtonNarrowest(resetDefaultButton_);
    
    264
    +
    
    265
    +  nameLabel_->setToolTip(tr("Axis name or tag"));
    
    266
    +  slider_->setToolTip(
    
    267
    +    tr("Axis value (max precision: 1/1024 of the value range)"));
    
    268
    +  valueLineEdit_->setToolTip(tr("Axis value"));
    
    269
    +  resetDefaultButton_->setToolTip(tr("Reset axis to default"));
    
    270
    +
    
    271
    +  mainLayout_ = new QGridLayout();
    
    272
    +
    
    273
    +  mainLayout_->addWidget(nameLabel_, 0, 0, 1, 2);
    
    274
    +  mainLayout_->addWidget(slider_, 1, 0, 1, 2);
    
    275
    +  mainLayout_->addWidget(valueLineEdit_, 2, 0, 1, 1, Qt::AlignVCenter);
    
    276
    +  mainLayout_->addWidget(resetDefaultButton_, 2, 1, 1, 1, Qt::AlignVCenter);
    
    277
    +
    
    278
    +  mainLayout_->setSpacing(4);
    
    279
    +  mainLayout_->setContentsMargins(4, 4, 4, 4);
    
    280
    +  setContentsMargins(0, 0, 0, 0);
    
    281
    +  setLayout(mainLayout_);
    
    282
    +  setFrameShape(StyledPanel);
    
    283
    +}
    
    284
    +
    
    285
    +
    
    286
    +void
    
    287
    +MMGXSettingItem::createConnections()
    
    288
    +{
    
    289
    +  connect(slider_, &QSlider::valueChanged,
    
    290
    +          this, &MMGXSettingItem::sliderValueChanged);
    
    291
    +  connect(valueLineEdit_, &QLineEdit::editingFinished,
    
    292
    +          this, &MMGXSettingItem::lineEditChanged);
    
    293
    +  connect(resetDefaultButton_, &QToolButton::clicked,
    
    294
    +          this, &MMGXSettingItem::resetDefaultSingle);
    
    295
    +}
    
    296
    +
    
    297
    +
    
    298
    +void
    
    299
    +MMGXSettingItem::sliderValueChanged()
    
    300
    +{
    
    301
    +  auto value = slider_->value() / 1024.0
    
    302
    +               * (axisInfo_.maximum - axisInfo_.minimum)
    
    303
    +               + axisInfo_.minimum;
    
    304
    +  actualValue_ = static_cast<FT_Fixed>(value * 65536.0);
    
    305
    +
    
    306
    +  if (axisInfo_.isMM)
    
    307
    +    actualValue_ = FT_RoundFix(actualValue_);
    
    308
    +
    
    309
    +  updateLineEdit();
    
    310
    +  emit valueChanged();
    
    311
    +}
    
    312
    +
    
    313
    +
    
    314
    +void
    
    315
    +MMGXSettingItem::lineEditChanged()
    
    316
    +{
    
    317
    +  bool succ = false;
    
    318
    +  auto newValue = valueLineEdit_->text().toDouble(&succ);
    
    319
    +  if (!succ || newValue > axisInfo_.maximum || newValue < axisInfo_.minimum)
    
    320
    +  {
    
    321
    +    updateLineEdit();
    
    322
    +    return;
    
    323
    +  }
    
    324
    +
    
    325
    +  actualValue_ = static_cast<FT_Fixed>(newValue / 65536.0);
    
    326
    +
    
    327
    +  updateSlider();
    
    328
    +  emit valueChanged();
    
    329
    +}
    
    330
    +
    
    331
    +
    
    332
    +void
    
    333
    +MMGXSettingItem::updateLineEdit()
    
    334
    +{
    
    335
    +  QSignalBlocker blocker(valueLineEdit_);
    
    336
    +  valueLineEdit_->setText(QString::number(actualValue_ / 65536.0));
    
    337
    +}
    
    338
    +
    
    339
    +
    
    340
    +void
    
    341
    +MMGXSettingItem::updateSlider()
    
    342
    +{
    
    343
    +  QSignalBlocker blocker(slider_);
    
    344
    +  slider_->setValue(
    
    345
    +    static_cast<int>((actualValue_ / 65536.0 - axisInfo_.minimum)
    
    346
    +                     / (axisInfo_.maximum - axisInfo_.minimum)
    
    347
    +                     * 1024));
    
    348
    +}
    
    349
    +
    
    350
    +
    
    351
    +void
    
    352
    +MMGXSettingItem::resetDefaultSingle()
    
    353
    +{
    
    354
    +  resetDefault();
    
    355
    +  emit valueChanged();
    
    356
    +}
    
    357
    +
    
    358
    +
    
    359
    +// end of settingpanelmmgx.cpp

  • src/ftinspect/panels/settingpanelmmgx.hpp
    1
    +// settingpanelmmgx.hpp
    
    2
    +
    
    3
    +// Copyright (C) 2022 by Charlie Jiang.
    
    4
    +
    
    5
    +#pragma once
    
    6
    +
    
    7
    +#include "../engine/mmgx.hpp"
    
    8
    +#include "../widgets/customwidgets.hpp"
    
    9
    +
    
    10
    +#include <QWidget>
    
    11
    +#include <QGridLayout>
    
    12
    +#include <QBoxLayout>
    
    13
    +#include <QCheckBox>
    
    14
    +#include <QScrollArea>
    
    15
    +#include <QLineEdit>
    
    16
    +#include <QSlider>
    
    17
    +#include <QFrame>
    
    18
    +#include <QPushButton>
    
    19
    +#include <QToolButton>
    
    20
    +#include <QLabel>
    
    21
    +#include <QDoubleValidator>
    
    22
    +
    
    23
    +#include <freetype/fttypes.h>
    
    24
    +
    
    25
    +class Engine;
    
    26
    +
    
    27
    +class MMGXSettingItem;
    
    28
    +class SettingPanelMMGX
    
    29
    +: public QWidget
    
    30
    +{
    
    31
    +  Q_OBJECT
    
    32
    +public:
    
    33
    +  SettingPanelMMGX(QWidget* parent, Engine* engine);
    
    34
    +  ~SettingPanelMMGX() override = default;
    
    35
    +
    
    36
    +  void reloadFont();
    
    37
    +  void applySettings();
    
    38
    +  void checkHidden();
    
    39
    +  std::vector<FT_Fixed>& mmgxCoords() { return currentValues_; }
    
    40
    +
    
    41
    +signals:
    
    42
    +  void mmgxCoordsChanged();
    
    43
    +
    
    44
    +private:
    
    45
    +  Engine* engine_;
    
    46
    +
    
    47
    +  QCheckBox* showHiddenCheckBox_;
    
    48
    +  QCheckBox* groupingCheckBox_;
    
    49
    +  QPushButton* resetDefaultButton_;
    
    50
    +  QWidget* itemsListWidget_;
    
    51
    +  UnboundScrollArea* scrollArea_;
    
    52
    +  std::vector<MMGXSettingItem*> itemWidgets_;
    
    53
    +
    
    54
    +  QVBoxLayout* mainLayout_;
    
    55
    +  QVBoxLayout* listLayout_;
    
    56
    +  QVBoxLayout* listWrapperLayout_;
    
    57
    +
    
    58
    +  std::vector<FT_Fixed> currentValues_;
    
    59
    +  std::vector<MMGXAxisInfo> currentAxes_;
    
    60
    +
    
    61
    +  void createLayout();
    
    62
    +  void createConnections();
    
    63
    +
    
    64
    +  void retrieveValues();
    
    65
    +  void itemChanged(size_t index);
    
    66
    +  void resetDefaultClicked();
    
    67
    +  void checkGrouping();
    
    68
    +};
    
    69
    +
    
    70
    +
    
    71
    +class MMGXSettingItem
    
    72
    +: public QFrame
    
    73
    +{
    
    74
    +  Q_OBJECT
    
    75
    +public:
    
    76
    +  MMGXSettingItem(QWidget* parent);
    
    77
    +  ~MMGXSettingItem() override = default;
    
    78
    +
    
    79
    +  void updateInfo(MMGXAxisInfo& info);
    
    80
    +  FT_Fixed value() { return actualValue_; }
    
    81
    +  void setValue(FT_Fixed value);
    
    82
    +  void resetDefault();
    
    83
    +
    
    84
    +signals:
    
    85
    +  void valueChanged();
    
    86
    +
    
    87
    +private:
    
    88
    +  QLabel* nameLabel_;
    
    89
    +  QSlider* slider_;
    
    90
    +  QPushButton* resetDefaultButton_;
    
    91
    +  QLineEdit* valueLineEdit_;
    
    92
    +  QDoubleValidator* valueValidator_;
    
    93
    +
    
    94
    +  QGridLayout* mainLayout_;
    
    95
    +
    
    96
    +  FT_Fixed actualValue_;
    
    97
    +  MMGXAxisInfo axisInfo_;
    
    98
    +
    
    99
    +  void createLayout();
    
    100
    +  void createConnections();
    
    101
    +  void sliderValueChanged();
    
    102
    +  void lineEditChanged();
    
    103
    +  void updateLineEdit();
    
    104
    +  void updateSlider();
    
    105
    +  void resetDefaultSingle();
    
    106
    +};
    
    107
    +
    
    108
    +
    
    109
    +// end of settingpanelmmgx.hpp

  • src/ftinspect/panels/singular.cpp
    ... ... @@ -131,7 +131,14 @@ SingularTab::drawGlyph()
    131 131
             glyphScene_->addItem(currentGlyphPointNumbersItem_);
    
    132 132
           }
    
    133 133
         }
    
    134
    +
    
    135
    +    engine_->reloadFont();
    
    136
    +    auto ascDesc = engine_->currentSizeAscDescPx();
    
    137
    +    gridItem_->updateParameters(ascDesc.first, ascDesc.second,
    
    138
    +                                glyph->advance.x >> 16);
    
    134 139
       }
    
    140
    +  else
    
    141
    +    gridItem_->updateParameters(0, 0, 0);
    
    135 142
     
    
    136 143
       glyphScene_->update();
    
    137 144
     }
    


  • reply via email to

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