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-3] [ftinspect] Add "Fon


From: Charlie Jiang (@cqjjjzr)
Subject: [Git][freetype/freetype-demos][gsoc-2022-chariri-3] [ftinspect] Add "Font Info" tab, and implement "General" tab.
Date: Sun, 14 Aug 2022 16:24:18 +0000

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

Commits:

  • 5e72aed4
    by Charlie Jiang at 2022-08-15T00:23:53+08:00
    [ftinspect] Add "Font Info" tab, and implement "General" tab.
    
    * src/ftinspect/panels/info.cpp, src/ftinspect/panels/info.hpp:
      Add `InfoTab` and implement the "General" subtab.
    
    * src/ftinspect/engine/fontinfo.cpp, src/ftinspect/engine/fontinfo.hpp:
      Add `FontBasicInfo`, `FontTypeEntries` and `FontFixedSize` to retrieve
      font infos.
    
    * src/ftinspect/models/fontinfomodels.cpp,
      src/ftinspect/models/fontinfomodels.hpp:
      Add custom `QAbstractTableModel` to display fixed sizes and char maps.
    
    * src/ftinspect/maingui.cpp, src/ftinspect/maingui.hpp: Included.
    
    * src/ftinspect/engine/engine.cpp, src/ftinspect/engine/engine.hpp:
      Add functions to expose current font index and size object.
    
    * src/ftinspect/engine/charmap.cpp, src/ftinspect/engine/charmap.hpp:
      Add format ID and language ID. Fix the `operator==`.
    
    * src/ftinspect/CMakeLists.txt, src/ftinspect/meson.build: Updated.
    

14 changed files:

Changes:

  • src/ftinspect/CMakeLists.txt
    ... ... @@ -25,6 +25,7 @@ add_executable(ftinspect
    25 25
       "engine/charmap.cpp"
    
    26 26
       "engine/paletteinfo.cpp"
    
    27 27
       "engine/stringrenderer.cpp"
    
    28
    +  "engine/fontinfo.cpp"
    
    28 29
     
    
    29 30
       "rendering/glyphbitmap.cpp"
    
    30 31
       "rendering/glyphoutline.cpp"
    
    ... ... @@ -42,11 +43,13 @@ add_executable(ftinspect
    42 43
       "widgets/charmapcombobox.cpp"
    
    43 44
     
    
    44 45
       "models/customcomboboxmodels.cpp"
    
    46
    +  "models/fontinfomodels.cpp"
    
    45 47
     
    
    46 48
       "panels/settingpanel.cpp"
    
    47 49
       "panels/singular.cpp"
    
    48 50
       "panels/continuous.cpp"
    
    49 51
       "panels/comparator.cpp"
    
    52
    +  "panels/info.cpp"
    
    50 53
       "panels/glyphdetails.cpp"
    
    51 54
     )
    
    52 55
     target_link_libraries(ftinspect
    

  • src/ftinspect/engine/charmap.cpp
    ... ... @@ -5,6 +5,8 @@
    5 5
     #include "charmap.hpp"
    
    6 6
     
    
    7 7
     #include <QHash>
    
    8
    +#include <freetype/freetype.h>
    
    9
    +#include <freetype/tttables.h>
    
    8 10
     
    
    9 11
     QHash<FT_Encoding, QString> encodingNamesCache;
    
    10 12
     QHash<FT_Encoding, QString>&
    
    ... ... @@ -37,7 +39,10 @@ encodingNames()
    37 39
     CharMapInfo::CharMapInfo(int index, FT_CharMap cmap)
    
    38 40
     : index(index), ptr(cmap),
    
    39 41
       encoding(cmap->encoding),
    
    40
    -  platformID(cmap->platform_id), encodingID(cmap->encoding_id),
    
    42
    +  platformID(cmap->platform_id),
    
    43
    +  encodingID(cmap->encoding_id),
    
    44
    +  formatID(FT_Get_CMap_Format(cmap)),
    
    45
    +  languageID(FT_Get_CMap_Language_ID(cmap)),
    
    41 46
       maxIndex(-1)
    
    42 47
     {
    
    43 48
       auto& names = encodingNames();
    

  • src/ftinspect/engine/charmap.hpp
    ... ... @@ -19,6 +19,8 @@ struct CharMapInfo
    19 19
       FT_Encoding encoding;
    
    20 20
       unsigned short platformID;
    
    21 21
       unsigned short encodingID;
    
    22
    +  long formatID;
    
    23
    +  unsigned long languageID;
    
    22 24
       QString* encodingName;
    
    23 25
     
    
    24 26
       // Actually this shouldn't go here, but for convenience...
    
    ... ... @@ -33,7 +35,13 @@ struct CharMapInfo
    33 35
       friend bool
    
    34 36
       operator==(const CharMapInfo& lhs, const CharMapInfo& rhs)
    
    35 37
       {
    
    36
    -    return lhs.index == rhs.index && lhs.encoding == rhs.encoding;
    
    38
    +    // omitting `ptr` by design!
    
    39
    +    return lhs.index == rhs.index
    
    40
    +           && lhs.encoding == rhs.encoding
    
    41
    +           && lhs.platformID == rhs.platformID
    
    42
    +           && lhs.encodingID == rhs.encodingID
    
    43
    +           && lhs.formatID == rhs.formatID
    
    44
    +           && lhs.languageID == rhs.languageID;
    
    37 45
       }
    
    38 46
     
    
    39 47
     
    

  • src/ftinspect/engine/engine.cpp
    ... ... @@ -283,6 +283,7 @@ Engine::loadFont(int fontIndex,
    283 283
     
    
    284 284
       update();
    
    285 285
     
    
    286
    +  curFontIndex_ = fontIndex;
    
    286 287
       auto id = FaceID(fontIndex, faceIndex, namedInstanceIndex);
    
    287 288
     
    
    288 289
       // search triplet (fontIndex, faceIndex, namedInstanceIndex)
    

  • src/ftinspect/engine/engine.hpp
    ... ... @@ -129,6 +129,8 @@ public:
    129 129
       double pointSize() { return pointSize_; }
    
    130 130
     
    
    131 131
       int numberOfOpenedFonts();
    
    132
    +  int currentFontIndex() { return curFontIndex_; }
    
    133
    +  FT_Size currentFtSize() { return ftSize_; }
    
    132 134
       int currentFontType() const { return fontType_; }
    
    133 135
       const QString& currentFamilyName() { return curFamilyName_; }
    
    134 136
       const QString& currentStyleName() { return curStyleName_; }
    
    ... ... @@ -215,6 +217,7 @@ private:
    215 217
     
    
    216 218
       FontFileManager fontFileManager_;
    
    217 219
     
    
    220
    +  int curFontIndex_ = -1;
    
    218 221
       QString curFamilyName_;
    
    219 222
       QString curStyleName_;
    
    220 223
       int curNumGlyphs_ = -1;
    

  • 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 <freetype/ftmodapi.h>
    
    10
    +#include <freetype/tttables.h>
    
    11
    +
    
    12
    +
    
    13
    +FontBasicInfo
    
    14
    +FontBasicInfo::get(Engine* engine)
    
    15
    +{
    
    16
    +  auto fontIndex = engine->currentFontIndex();
    
    17
    +  if (fontIndex < 0)
    
    18
    +    return {};
    
    19
    +  FontBasicInfo result;
    
    20
    +  result.numFaces = engine->numberOfFaces(fontIndex);
    
    21
    +
    
    22
    +  engine->reloadFont();
    
    23
    +  auto size = engine->currentFtSize();
    
    24
    +  if (!size)
    
    25
    +    return result;
    
    26
    +
    
    27
    +  auto face = size->face;
    
    28
    +  if (face->family_name)
    
    29
    +    result.familyName = QString(face->family_name);
    
    30
    +  if (face->style_name)
    
    31
    +    result.styleName = QString(face->style_name);
    
    32
    +
    
    33
    +  auto psName = FT_Get_Postscript_Name(face);
    
    34
    +  if (psName)
    
    35
    +    result.postscriptName = QString(psName);
    
    36
    +
    
    37
    +  auto head = static_cast<TT_Header*>(FT_Get_Sfnt_Table(face, FT_SFNT_HEAD));
    
    38
    +  if (head)
    
    39
    +  {
    
    40
    +    uint64_t createdTimestamp
    
    41
    +      = head->Created[1] | static_cast<uint64_t>(head->Created[0]) << 32;
    
    42
    +    uint64_t modifiedTimestamp
    
    43
    +      = head->Modified[1] | static_cast<uint64_t>(head->Modified[0]) << 32;
    
    44
    +    
    
    45
    +    result.createdTime
    
    46
    +      = QDateTime::fromSecsSinceEpoch(createdTimestamp, Qt::OffsetFromUTC)
    
    47
    +          .addSecs(-2082844800);
    
    48
    +    result.modifiedTime
    
    49
    +      = QDateTime::fromSecsSinceEpoch(modifiedTimestamp, Qt::OffsetFromUTC)
    
    50
    +          .addSecs(-2082844800);
    
    51
    +
    
    52
    +    auto revDouble = head->Font_Revision / 65536.0;
    
    53
    +    if (head->Font_Revision & 0xFFC0)
    
    54
    +      result.revision = QString::number(revDouble, 'g', 4);
    
    55
    +    else
    
    56
    +      result.revision = QString::number(revDouble, 'g', 2);
    
    57
    +  }
    
    58
    +
    
    59
    +  return result;
    
    60
    +}
    
    61
    +
    
    62
    +
    
    63
    +FontTypeEntries
    
    64
    +FontTypeEntries::get(Engine* engine)
    
    65
    +{
    
    66
    +  engine->reloadFont();
    
    67
    +  auto size = engine->currentFtSize();
    
    68
    +  if (!size)
    
    69
    +    return {};
    
    70
    +
    
    71
    +  auto face = size->face;
    
    72
    +
    
    73
    +  FontTypeEntries result = {};
    
    74
    +  result.driverName = QString(FT_FACE_DRIVER_NAME(face));
    
    75
    +  result.sfnt = FT_IS_SFNT(face);
    
    76
    +  result.scalable = FT_IS_SCALABLE(face);
    
    77
    +  if (result.scalable)
    
    78
    +    result.mmgx = FT_HAS_MULTIPLE_MASTERS(face);
    
    79
    +  else
    
    80
    +    result.mmgx = false;
    
    81
    +  result.fixedSizes = FT_HAS_FIXED_SIZES(face);
    
    82
    +  result.hasHorizontal = FT_HAS_HORIZONTAL(face);
    
    83
    +  result.hasVertical = FT_HAS_VERTICAL(face);
    
    84
    +  result.fixedWidth = FT_IS_FIXED_WIDTH(face);
    
    85
    +  result.glyphNames = FT_HAS_GLYPH_NAMES(face);
    
    86
    +
    
    87
    +  if (result.scalable)
    
    88
    +  {
    
    89
    +    result.emSize = face->units_per_EM;
    
    90
    +    result.globalBBox = face->bbox;
    
    91
    +    result.ascender = face->ascender;
    
    92
    +    result.descender = face->descender;
    
    93
    +    result.height = face->height;
    
    94
    +    result.maxAdvanceWidth = face->max_advance_width;
    
    95
    +    result.maxAdvanceHeight = face->max_advance_height;
    
    96
    +    result.underlinePos = face->underline_position;
    
    97
    +    result.underlineThickness = face->underline_thickness;
    
    98
    +  }
    
    99
    +
    
    100
    +  return result;
    
    101
    +}
    
    102
    +
    
    103
    +
    
    104
    +bool
    
    105
    +FontFixedSize::get(Engine* engine,
    
    106
    +                   std::vector<FontFixedSize>& list,
    
    107
    +                   const std::function<void()>& onUpdateNeeded)
    
    108
    +{
    
    109
    +  engine->reloadFont();
    
    110
    +  auto size = engine->currentFtSize();
    
    111
    +  if (!size)
    
    112
    +  {
    
    113
    +    if (list.empty())
    
    114
    +      return false;
    
    115
    +
    
    116
    +    onUpdateNeeded();
    
    117
    +    list.clear();
    
    118
    +    return true;
    
    119
    +  }
    
    120
    +
    
    121
    +  auto face = size->face;
    
    122
    +  auto changed = false;
    
    123
    +  if (list.size() != static_cast<size_t>(face->num_fixed_sizes))
    
    124
    +  {
    
    125
    +    changed = true;
    
    126
    +    onUpdateNeeded();
    
    127
    +    list.resize(face->num_fixed_sizes);
    
    128
    +  }
    
    129
    +
    
    130
    +  for (int i = 0; i < face->num_fixed_sizes; ++i)
    
    131
    +  {
    
    132
    +    FontFixedSize ffs = {};
    
    133
    +    auto bSize = face->available_sizes + i;
    
    134
    +    ffs.height = bSize->height;
    
    135
    +    ffs.width  = bSize->width;
    
    136
    +    ffs.size   = bSize->size / 64.0;
    
    137
    +    ffs.xPpem  = bSize->x_ppem / 64.0;
    
    138
    +    ffs.yPpem  = bSize->y_ppem / 64.0;
    
    139
    +    if (ffs != list[i])
    
    140
    +    {
    
    141
    +      
    
    142
    +      if (!changed)
    
    143
    +      {
    
    144
    +        onUpdateNeeded();
    
    145
    +        changed = true;
    
    146
    +      }
    
    147
    +      
    
    148
    +      list[i] = ffs;
    
    149
    +    }
    
    150
    +  }
    
    151
    +
    
    152
    +  return changed;
    
    153
    +}
    
    154
    +
    
    155
    +
    
    156
    +// 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 <QDateTime>
    
    8
    +#include <QString>
    
    9
    +#include <freetype/freetype.h>
    
    10
    +
    
    11
    +class Engine;
    
    12
    +
    
    13
    +struct SFNTNameTable
    
    14
    +{
    
    15
    +  
    
    16
    +};
    
    17
    +
    
    18
    +struct FontBasicInfo
    
    19
    +{
    
    20
    +  int numFaces = -1;
    
    21
    +  QString familyName;
    
    22
    +  QString styleName;
    
    23
    +  QString postscriptName;
    
    24
    +  QDateTime createdTime;
    
    25
    +  QDateTime modifiedTime;
    
    26
    +  QString revision;
    
    27
    +  QString copyright;
    
    28
    +  QString trademark;
    
    29
    +  QString manufacturer;
    
    30
    +
    
    31
    +  static FontBasicInfo get(Engine* engine);
    
    32
    +
    
    33
    +
    
    34
    +  // Oh, we have no C++20 :(
    
    35
    +  friend bool
    
    36
    +  operator==(const FontBasicInfo& lhs,
    
    37
    +             const FontBasicInfo& rhs)
    
    38
    +  {
    
    39
    +    return lhs.numFaces == rhs.numFaces
    
    40
    +      && lhs.familyName == rhs.familyName
    
    41
    +      && lhs.styleName == rhs.styleName
    
    42
    +      && lhs.postscriptName == rhs.postscriptName
    
    43
    +      && lhs.createdTime == rhs.createdTime
    
    44
    +      && lhs.modifiedTime == rhs.modifiedTime
    
    45
    +      && lhs.revision == rhs.revision
    
    46
    +      && lhs.copyright == rhs.copyright
    
    47
    +      && lhs.trademark == rhs.trademark
    
    48
    +      && lhs.manufacturer == rhs.manufacturer;
    
    49
    +  }
    
    50
    +
    
    51
    +
    
    52
    +  friend bool
    
    53
    +  operator!=(const FontBasicInfo& lhs,
    
    54
    +             const FontBasicInfo& rhs)
    
    55
    +  {
    
    56
    +    return !(lhs == rhs);
    
    57
    +  }
    
    58
    +};
    
    59
    +
    
    60
    +
    
    61
    +struct FontTypeEntries
    
    62
    +{
    
    63
    +  QString driverName;
    
    64
    +  bool sfnt          : 1;
    
    65
    +  bool scalable      : 1;
    
    66
    +  bool mmgx          : 1;
    
    67
    +  bool fixedSizes    : 1;
    
    68
    +  bool hasHorizontal : 1;
    
    69
    +  bool hasVertical   : 1;
    
    70
    +  bool fixedWidth    : 1;
    
    71
    +  bool glyphNames    : 1;
    
    72
    +
    
    73
    +  int emSize;
    
    74
    +  FT_BBox globalBBox;
    
    75
    +  int ascender;
    
    76
    +  int descender;
    
    77
    +  int height;
    
    78
    +  int maxAdvanceWidth;
    
    79
    +  int maxAdvanceHeight;
    
    80
    +  int underlinePos;
    
    81
    +  int underlineThickness;
    
    82
    +
    
    83
    +  static FontTypeEntries get(Engine* engine);
    
    84
    +
    
    85
    +
    
    86
    +  // Oh, we have no C++20 :(
    
    87
    +  friend bool
    
    88
    +  operator==(const FontTypeEntries& lhs,
    
    89
    +             const FontTypeEntries& rhs)
    
    90
    +  {
    
    91
    +    return lhs.driverName == rhs.driverName
    
    92
    +      && lhs.sfnt == rhs.sfnt
    
    93
    +      && lhs.scalable == rhs.scalable
    
    94
    +      && lhs.mmgx == rhs.mmgx
    
    95
    +      && lhs.fixedSizes == rhs.fixedSizes
    
    96
    +      && lhs.hasHorizontal == rhs.hasHorizontal
    
    97
    +      && lhs.hasVertical == rhs.hasVertical
    
    98
    +      && lhs.fixedWidth == rhs.fixedWidth
    
    99
    +      && lhs.glyphNames == rhs.glyphNames
    
    100
    +      && lhs.emSize == rhs.emSize
    
    101
    +      && lhs.globalBBox.xMax == rhs.globalBBox.xMax
    
    102
    +      && lhs.globalBBox.xMin == rhs.globalBBox.xMin
    
    103
    +      && lhs.globalBBox.yMax == rhs.globalBBox.yMax
    
    104
    +      && lhs.globalBBox.yMin == rhs.globalBBox.yMin
    
    105
    +      && lhs.ascender == rhs.ascender
    
    106
    +      && lhs.descender == rhs.descender
    
    107
    +      && lhs.height == rhs.height
    
    108
    +      && lhs.maxAdvanceWidth == rhs.maxAdvanceWidth
    
    109
    +      && lhs.maxAdvanceHeight == rhs.maxAdvanceHeight
    
    110
    +      && lhs.underlinePos == rhs.underlinePos
    
    111
    +      && lhs.underlineThickness == rhs.underlineThickness;
    
    112
    +  }
    
    113
    +
    
    114
    +
    
    115
    +  friend bool
    
    116
    +  operator!=(const FontTypeEntries& lhs,
    
    117
    +             const FontTypeEntries& rhs)
    
    118
    +  {
    
    119
    +    return !(lhs == rhs);
    
    120
    +  }
    
    121
    +};
    
    122
    +
    
    123
    +
    
    124
    +struct FontFixedSize
    
    125
    +{
    
    126
    +  short height;
    
    127
    +  short width;
    
    128
    +  double size;
    
    129
    +  double xPpem;
    
    130
    +  double yPpem;
    
    131
    +
    
    132
    +
    
    133
    +  // Returns that if the list is updated
    
    134
    +  // Using a callback because Qt needs `beginResetModel` to be called **before**
    
    135
    +  // the internal storage updates.
    
    136
    +  static bool get(Engine* engine,
    
    137
    +                  std::vector<FontFixedSize>& list,
    
    138
    +                  const std::function<void()>& onUpdateNeeded);
    
    139
    +
    
    140
    +
    
    141
    +  friend bool
    
    142
    +  operator==(const FontFixedSize& lhs,
    
    143
    +             const FontFixedSize& rhs)
    
    144
    +  {
    
    145
    +    return lhs.height == rhs.height
    
    146
    +      && lhs.width == rhs.width
    
    147
    +      && lhs.size == rhs.size
    
    148
    +      && lhs.xPpem == rhs.xPpem
    
    149
    +      && lhs.yPpem == rhs.yPpem;
    
    150
    +  }
    
    151
    +
    
    152
    +
    
    153
    +  friend bool
    
    154
    +  operator!=(const FontFixedSize& lhs,
    
    155
    +             const FontFixedSize& rhs)
    
    156
    +  {
    
    157
    +    return !(lhs == rhs);
    
    158
    +  }
    
    159
    +};
    
    160
    +
    
    161
    +
    
    162
    +// end of fontinfo.hpp

  • src/ftinspect/maingui.cpp
    ... ... @@ -240,6 +240,7 @@ MainGUI::createLayout()
    240 240
       continuousTab_ = new ContinuousTab(this, engine_,
    
    241 241
                                          glyphDetailsDockWidget_, glyphDetails_);
    
    242 242
       comparatorTab_ = new ComperatorTab(this, engine_);
    
    243
    +  infoTab_ = new InfoTab(this, engine_);
    
    243 244
     
    
    244 245
       tabWidget_ = new QTabWidget(this);
    
    245 246
     
    
    ... ... @@ -250,6 +251,8 @@ MainGUI::createLayout()
    250 251
       tabWidget_->addTab(continuousTab_, tr("Continuous View"));
    
    251 252
       tabs_.append(comparatorTab_);
    
    252 253
       tabWidget_->addTab(comparatorTab_, tr("Comparator View"));
    
    254
    +  tabs_.append(infoTab_);
    
    255
    +  tabWidget_->addTab(infoTab_, tr("Font Info"));
    
    253 256
       
    
    254 257
       tripletSelector_ = new TripletSelector(this, engine_);
    
    255 258
     
    

  • src/ftinspect/maingui.hpp
    ... ... @@ -11,6 +11,7 @@
    11 11
     #include "panels/singular.hpp"
    
    12 12
     #include "panels/continuous.hpp"
    
    13 13
     #include "panels/comparator.hpp"
    
    14
    +#include "panels/info.hpp"
    
    14 15
     #include "panels/glyphdetails.hpp"
    
    15 16
     
    
    16 17
     #include <QAction>
    
    ... ... @@ -112,6 +113,7 @@ private:
    112 113
       SingularTab* singularTab_;
    
    113 114
       ContinuousTab* continuousTab_;
    
    114 115
       ComperatorTab* comparatorTab_;
    
    116
    +  InfoTab* infoTab_;
    
    115 117
     
    
    116 118
       QDockWidget* glyphDetailsDockWidget_;
    
    117 119
       GlyphDetails* glyphDetails_;
    

  • src/ftinspect/meson.build
    ... ... @@ -26,6 +26,7 @@ if qt5_dep.found()
    26 26
         'engine/charmap.cpp',
    
    27 27
         'engine/paletteinfo.cpp',
    
    28 28
         'engine/stringrenderer.cpp',
    
    29
    +    'engine/fontinfo.cpp',
    
    29 30
     
    
    30 31
         'rendering/glyphbitmap.cpp',
    
    31 32
         'rendering/glyphoutline.cpp',
    
    ... ... @@ -42,12 +43,14 @@ if qt5_dep.found()
    42 43
         'widgets/charmapcombobox.cpp',
    
    43 44
     
    
    44 45
         'models/customcomboboxmodels.cpp',
    
    46
    +    'models/fontinfomodels.cpp',
    
    45 47
     
    
    46 48
         'panels/settingpanel.cpp',
    
    47 49
         'panels/singular.cpp',
    
    48 50
         'panels/continuous.cpp',
    
    49 51
         'panels/comparator.cpp',
    
    50 52
         'panels/glyphdetails.cpp',
    
    53
    +    'panels/info.cpp',
    
    51 54
     
    
    52 55
         'ftinspect.cpp',
    
    53 56
         'maingui.cpp',
    
    ... ... @@ -65,11 +68,13 @@ if qt5_dep.found()
    65 68
           'rendering/glyphbitmap.hpp',
    
    66 69
           'rendering/glyphcontinuous.hpp',
    
    67 70
           'models/customcomboboxmodels.hpp',
    
    71
    +      'models/fontinfomodels.hpp',
    
    68 72
           'panels/settingpanel.hpp',
    
    69 73
           'panels/singular.hpp',
    
    70 74
           'panels/continuous.hpp',
    
    71 75
           'panels/comparator.hpp',
    
    72 76
           'panels/glyphdetails.hpp',
    
    77
    +      'panels/info.hpp',
    
    73 78
           'maingui.hpp',
    
    74 79
         ],
    
    75 80
         dependencies: qt5_dep)
    

  • src/ftinspect/models/fontinfomodels.cpp
    1
    +// fontinfomodels.cpp
    
    2
    +
    
    3
    +// Copyright (C) 2022 by Charlie Jiang.
    
    4
    +
    
    5
    +#include "fontinfomodels.hpp"
    
    6
    +
    
    7
    +int
    
    8
    +FixedSizeInfoModel::rowCount(const QModelIndex& parent) const
    
    9
    +{
    
    10
    +  if (parent.isValid())
    
    11
    +    return 0;
    
    12
    +  return static_cast<int>(storage_.size());
    
    13
    +}
    
    14
    +
    
    15
    +
    
    16
    +int
    
    17
    +FixedSizeInfoModel::columnCount(const QModelIndex& parent) const
    
    18
    +{
    
    19
    +  if (parent.isValid())
    
    20
    +    return 0;
    
    21
    +  return FSIM_Max;
    
    22
    +}
    
    23
    +
    
    24
    +
    
    25
    +QVariant
    
    26
    +FixedSizeInfoModel::data(const QModelIndex& index,
    
    27
    +                          int role) const
    
    28
    +{
    
    29
    +  if (index.row() < 0 || index.column() < 0)
    
    30
    +    return {};
    
    31
    +  auto r = static_cast<size_t>(index.row());
    
    32
    +  if (role != Qt::DisplayRole || r > storage_.size())
    
    33
    +    return {};
    
    34
    +
    
    35
    +  auto& obj = storage_[r];
    
    36
    +  switch (static_cast<Columns>(index.column()))
    
    37
    +  {
    
    38
    +  case FSIM_Index:
    
    39
    +    return index.row();
    
    40
    +  case FSIM_Height:
    
    41
    +    return obj.height;
    
    42
    +  case FSIM_Width:
    
    43
    +    return obj.width;
    
    44
    +  case FSIM_Size:
    
    45
    +    return obj.size;
    
    46
    +  case FSIM_XPpem:
    
    47
    +    return obj.xPpem;
    
    48
    +  case FSIM_YPpem:
    
    49
    +    return obj.yPpem;
    
    50
    +  default:
    
    51
    +    break;
    
    52
    +  }
    
    53
    +
    
    54
    +  return {};
    
    55
    +}
    
    56
    +
    
    57
    +
    
    58
    +QVariant
    
    59
    +FixedSizeInfoModel::headerData(int section,
    
    60
    +                                Qt::Orientation orientation,
    
    61
    +                                int role) const
    
    62
    +{
    
    63
    +  if (role != Qt::DisplayRole || orientation != Qt::Horizontal)
    
    64
    +    return {};
    
    65
    +
    
    66
    +  switch (static_cast<Columns>(section))
    
    67
    +  {
    
    68
    +  case FSIM_Index:
    
    69
    +    return tr("#");
    
    70
    +  case FSIM_Height:
    
    71
    +    return tr("Height");
    
    72
    +  case FSIM_Width:
    
    73
    +    return tr("Width");
    
    74
    +  case FSIM_Size:
    
    75
    +    return tr("Size");
    
    76
    +  case FSIM_XPpem:
    
    77
    +    return tr("X ppem");
    
    78
    +  case FSIM_YPpem:
    
    79
    +    return tr("Y ppem");
    
    80
    +  default:
    
    81
    +    break;
    
    82
    +  }
    
    83
    +
    
    84
    +  return {};
    
    85
    +}
    
    86
    +
    
    87
    +
    
    88
    +int
    
    89
    +CharMapInfoModel::rowCount(const QModelIndex& parent) const
    
    90
    +{
    
    91
    +  if (parent.isValid())
    
    92
    +    return 0;
    
    93
    +  return static_cast<int>(storage_.size());
    
    94
    +}
    
    95
    +
    
    96
    +
    
    97
    +int
    
    98
    +CharMapInfoModel::columnCount(const QModelIndex& parent) const
    
    99
    +{
    
    100
    +  if (parent.isValid())
    
    101
    +    return 0;
    
    102
    +  return CMIM_Max;
    
    103
    +}
    
    104
    +
    
    105
    +
    
    106
    +QVariant
    
    107
    +CharMapInfoModel::data(const QModelIndex& index,
    
    108
    +                       int role) const
    
    109
    +{
    
    110
    +  // TODO reduce duplication
    
    111
    +  if (index.row() < 0 || index.column() < 0)
    
    112
    +    return {};
    
    113
    +  auto r = static_cast<size_t>(index.row());
    
    114
    +  if (role != Qt::DisplayRole || r > storage_.size())
    
    115
    +    return {};
    
    116
    +
    
    117
    +  auto& obj = storage_[r];
    
    118
    +  switch (static_cast<Columns>(index.column()))
    
    119
    +  {
    
    120
    +  case CMIM_Index: 
    
    121
    +    return index.row();
    
    122
    +  case CMIM_Encoding:
    
    123
    +    return *obj.encodingName;
    
    124
    +  case CMIM_PlatformID: 
    
    125
    +    return obj.platformID;
    
    126
    +  case CMIM_EncodingID: 
    
    127
    +    return obj.encodingID;
    
    128
    +  case CMIM_FormatID: 
    
    129
    +    return static_cast<long long>(obj.formatID);
    
    130
    +  case CMIM_LanguageID:
    
    131
    +    return static_cast<unsigned long long>(obj.languageID);
    
    132
    +  case CMIM_MaxIndex: 
    
    133
    +    return obj.maxIndex;
    
    134
    +  default:
    
    135
    +    break;
    
    136
    +  }
    
    137
    +
    
    138
    +  return {};
    
    139
    +}
    
    140
    +
    
    141
    +
    
    142
    +QVariant
    
    143
    +CharMapInfoModel::headerData(int section,
    
    144
    +                             Qt::Orientation orientation,
    
    145
    +                             int role) const
    
    146
    +{
    
    147
    +  if (role != Qt::DisplayRole || orientation != Qt::Horizontal)
    
    148
    +    return {};
    
    149
    +
    
    150
    +  switch (static_cast<Columns>(section))
    
    151
    +  {
    
    152
    +  case CMIM_Index:
    
    153
    +    return "#";
    
    154
    +  case CMIM_Encoding:
    
    155
    +    return "Encoding";
    
    156
    +  case CMIM_PlatformID:
    
    157
    +    return "Platform ID";
    
    158
    +  case CMIM_EncodingID:
    
    159
    +    return "Encoding ID";
    
    160
    +  case CMIM_FormatID:
    
    161
    +    return "Format ID";
    
    162
    +  case CMIM_LanguageID:
    
    163
    +    return "Language ID";
    
    164
    +  case CMIM_MaxIndex:
    
    165
    +    return "Max Code Point";
    
    166
    +  default:
    
    167
    +    break;
    
    168
    +  }
    
    169
    +
    
    170
    +  return {};
    
    171
    +}
    
    172
    +
    
    173
    +
    
    174
    +// end of fontinfomodels.cpp

  • src/ftinspect/models/fontinfomodels.hpp
    1
    +// fontinfomodels.hpp
    
    2
    +
    
    3
    +// Copyright (C) 2022 by Charlie Jiang.
    
    4
    +
    
    5
    +#pragma once
    
    6
    +
    
    7
    +#include "../engine/fontinfo.hpp"
    
    8
    +#include "../engine/charmap.hpp"
    
    9
    +
    
    10
    +#include <vector>
    
    11
    +#include <QAbstractTableModel>
    
    12
    +
    
    13
    +class FixedSizeInfoModel
    
    14
    +: public QAbstractTableModel
    
    15
    +{
    
    16
    +  Q_OBJECT
    
    17
    +public:
    
    18
    +  explicit FixedSizeInfoModel(QObject* parent) : QAbstractTableModel(parent) {}
    
    19
    +  ~FixedSizeInfoModel() override = default;
    
    20
    +
    
    21
    +  int rowCount(const QModelIndex& parent) const override;
    
    22
    +  int columnCount(const QModelIndex& parent) const override;
    
    23
    +  QVariant data(const QModelIndex& index,
    
    24
    +                int role) const override;
    
    25
    +  QVariant headerData(int section,
    
    26
    +                      Qt::Orientation orientation,
    
    27
    +                      int role) const override;
    
    28
    +
    
    29
    +  // Since we need to call `beginResetModel` right before updating, and need to
    
    30
    +  // call `endResetModel` after the internal storage is changed
    
    31
    +  // The model should be updated on-demand, and the internal storage is updated
    
    32
    +  // from `FontFixedSize::get`, we provide a callback for `get` to ensure the
    
    33
    +  // `beginResetModel` is called before the storage is changed,
    
    34
    +  // and the caller is responsible to call `endResetModel` according to `get`'s
    
    35
    +  // return value.
    
    36
    +  void beginModelUpdate() { beginResetModel(); }
    
    37
    +  void endModelUpdate() { endResetModel(); }
    
    38
    +  std::vector<FontFixedSize>& storage() { return storage_; }
    
    39
    +
    
    40
    +  enum Columns : int
    
    41
    +  {
    
    42
    +    FSIM_Index  = 0,
    
    43
    +    FSIM_Height = 1,
    
    44
    +    FSIM_Width  = 2,
    
    45
    +    FSIM_Size   = 3,
    
    46
    +    FSIM_XPpem  = 4,
    
    47
    +    FSIM_YPpem  = 5,
    
    48
    +    FSIM_Max
    
    49
    +  };
    
    50
    +
    
    51
    +private:
    
    52
    +  // Don't let the item count exceed INT_MAX!
    
    53
    +  std::vector<FontFixedSize> storage_;
    
    54
    +};
    
    55
    +
    
    56
    +
    
    57
    +class CharMapInfoModel
    
    58
    +: public QAbstractTableModel
    
    59
    +{
    
    60
    +  Q_OBJECT
    
    61
    +public:
    
    62
    +  explicit CharMapInfoModel(QObject* parent) : QAbstractTableModel(parent) {}
    
    63
    +  ~CharMapInfoModel() override = default;
    
    64
    +
    
    65
    +  int rowCount(const QModelIndex& parent) const override;
    
    66
    +  int columnCount(const QModelIndex& parent) const override;
    
    67
    +  QVariant data(const QModelIndex& index,
    
    68
    +                int role) const override;
    
    69
    +  QVariant headerData(int section,
    
    70
    +                      Qt::Orientation orientation,
    
    71
    +                      int role) const override;
    
    72
    +
    
    73
    +  // Same to `FixedSizeInfoModel`
    
    74
    +  void beginModelUpdate() { beginResetModel(); }
    
    75
    +  void endModelUpdate() { endResetModel(); }
    
    76
    +  std::vector<CharMapInfo>& storage() { return storage_; }
    
    77
    +
    
    78
    +  enum Columns : int
    
    79
    +  {
    
    80
    +    CMIM_Index      = 0,
    
    81
    +    CMIM_Encoding   = 1,
    
    82
    +    CMIM_PlatformID = 2,
    
    83
    +    CMIM_EncodingID = 3,
    
    84
    +    CMIM_FormatID   = 4,
    
    85
    +    CMIM_LanguageID = 5,
    
    86
    +    CMIM_MaxIndex   = 6,
    
    87
    +    CMIM_Max
    
    88
    +  };
    
    89
    +
    
    90
    +private:
    
    91
    +  // Don't let the item count exceed INT_MAX!
    
    92
    +  std::vector<CharMapInfo> storage_;
    
    93
    +};
    
    94
    +
    
    95
    +
    
    96
    +// end of fontinfomodels.hpp

  • src/ftinspect/panels/info.cpp
    1
    +// info.cpp
    
    2
    +
    
    3
    +// Copyright (C) 2022 by Charlie Jiang.
    
    4
    +
    
    5
    +#include "info.hpp"
    
    6
    +
    
    7
    +#include "../uihelper.hpp"
    
    8
    +#include "../engine/engine.hpp"
    
    9
    +
    
    10
    +#include <QStringList>
    
    11
    +#include <QHeaderView>
    
    12
    +
    
    13
    +InfoTab::InfoTab(QWidget* parent,
    
    14
    +                 Engine* engine)
    
    15
    +: QWidget(parent), engine_(engine)
    
    16
    +{
    
    17
    +  createLayout();
    
    18
    +}
    
    19
    +
    
    20
    +
    
    21
    +void
    
    22
    +InfoTab::reloadFont()
    
    23
    +{
    
    24
    +  for (auto tab : tabs_)
    
    25
    +    tab->reloadFont();
    
    26
    +}
    
    27
    +
    
    28
    +
    
    29
    +void
    
    30
    +InfoTab::createLayout()
    
    31
    +{
    
    32
    +  generalTab_ = new GeneralInfoTab(this, engine_);
    
    33
    +  sfntTab_ = new SFNTInfoTab(this, engine_);
    
    34
    +  postScriptTab_ = new PostScriptInfoTab(this, engine_);
    
    35
    +  mmgxTab_ = new MMGXInfoTab(this, engine_);
    
    36
    +
    
    37
    +  tab_ = new QTabWidget(this);
    
    38
    +  tab_->addTab(generalTab_, tr("General"));
    
    39
    +  tab_->addTab(sfntTab_, tr("SFNT"));
    
    40
    +  tab_->addTab(postScriptTab_, tr("PostScript"));
    
    41
    +  tab_->addTab(mmgxTab_, tr("MM/GX"));
    
    42
    +
    
    43
    +  tabs_.append(generalTab_);
    
    44
    +  tabs_.append(sfntTab_);
    
    45
    +  tabs_.append(postScriptTab_);
    
    46
    +  tabs_.append(mmgxTab_);
    
    47
    +
    
    48
    +  layout_ = new QHBoxLayout;
    
    49
    +  layout_->addWidget(tab_);
    
    50
    +
    
    51
    +  setLayout(layout_);
    
    52
    +}
    
    53
    +
    
    54
    +
    
    55
    +GeneralInfoTab::GeneralInfoTab(QWidget* parent,
    
    56
    +                               Engine* engine)
    
    57
    +: QWidget(parent), engine_(engine)
    
    58
    +{
    
    59
    +  createLayout();
    
    60
    +}
    
    61
    +
    
    62
    +
    
    63
    +void
    
    64
    +GeneralInfoTab::reloadFont()
    
    65
    +{
    
    66
    +  auto basicInfo = FontBasicInfo::get(engine_);
    
    67
    +  // don't update when unnecessary
    
    68
    +  if (basicInfo != oldFontBasicInfo_) 
    
    69
    +  {
    
    70
    +    oldFontBasicInfo_ = basicInfo;
    
    71
    +    if (basicInfo.numFaces < 0)
    
    72
    +      numFacesLabel_->clear();
    
    73
    +    else
    
    74
    +      numFacesLabel_->setText(QString::number(basicInfo.numFaces));
    
    75
    +    
    
    76
    +          familyLabel_->setText(basicInfo.familyName);
    
    77
    +           styleLabel_->setText(basicInfo.styleName);
    
    78
    +      postscriptLabel_->setText(basicInfo.postscriptName);
    
    79
    +        revisionLabel_->setText(basicInfo.revision);
    
    80
    +       copyrightLabel_->setText(basicInfo.copyright);
    
    81
    +       trademarkLabel_->setText(basicInfo.trademark);
    
    82
    +    manufacturerLabel_->setText(basicInfo.manufacturer);
    
    83
    +    
    
    84
    +    createdLabel_->setText(
    
    85
    +        basicInfo.createdTime.toString("yyyy-MM-dd hh:mm:ss t"));
    
    86
    +    modifiedLabel_->setText(
    
    87
    +        basicInfo.modifiedTime.toString("yyyy-MM-dd hh:mm:ss t"));
    
    88
    +  }
    
    89
    +
    
    90
    +  auto fontTypeEntries = FontTypeEntries::get(engine_);
    
    91
    +
    
    92
    +  if (fontTypeEntries != oldFontTypeEntries_)
    
    93
    +  {
    
    94
    +    oldFontTypeEntries_ = fontTypeEntries;
    
    95