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] 9 commits: [ftinspec


From: Charlie Jiang (@cqjjjzr)
Subject: [Git][freetype/freetype-demos][gsoc-2022-chariri-3] 9 commits: [ftinspect] Add composite glyphs info tab.
Date: Sun, 28 Aug 2022 06:22:00 +0000

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

Commits:

  • a1b171f9
    by Charlie Jiang at 2022-08-28T13:29:42+08:00
    [ftinspect] Add composite glyphs info tab.
    
    Not tested for nested glyphs.
    
    * src/ftinspect/models/fontinfomodels.cpp,
      src/ftinspect/models/fontinfomodels.hpp:
      Add `CompositeGlyphsInfoModel` as a lazily loaded tree model.
    
    * src/ftinspect/panels/info.cpp, src/ftinspect/panels/info.hpp:
      Implement the `CompositeGlyphsTab` and integrate into the `InfoTab`.
    
    * src/ftinspect/engine/fontinfo.cpp, src/ftinspect/engine/fontinfo.hpp:
      Add `CompositeGlyphInfo` to retrieve composite glyph info from the `glyf`
      table.
    
    * src/ftinspect/maingui.cpp: Connect event for switching to singular.
    
    * src/ftinspect/engine/engine.cpp, src/ftinspect/engine/engine.hpp:
      Add `currentFontHasGlyphName`.
    
    * src/ftinspect/engine/fontfilemanager.cpp,
      src/ftinspect/engine/fontfilemanager.hpp:
      Add getter to check if current font reload is caused by periodic reload of
      symbolic files. Don't reload the composite glyphs in such case.
    
  • c93a74f4
    by Charlie Jiang at 2022-08-28T13:30:42+08:00
    * src/ftinspect/panels/singular.cpp: Adjust initial zoom factor.
    
  • 3575e6e5
    by Charlie Jiang at 2022-08-28T13:39:47+08:00
    * src/ftinspect/maingui.cpp: Use min size hint for initial window size.
    
  • b49f5ac8
    by Charlie Jiang at 2022-08-28T13:41:16+08:00
    * src/ftinspect/panels/settingpanel.cpp: Set gamma slider steps.
    
  • cc61ce5a
    by Charlie Jiang at 2022-08-28T13:43:38+08:00
    * src/ftinspect/panels/continuous.cpp: Hide the details pane when...
    
    switching to the singular tab.
    
  • 0a8df748
    by Charlie Jiang at 2022-08-28T14:04:04+08:00
    [ftinspect] Add preset settings to comparators view.
    
    * src/ftinspect/panels/comparator.cpp: Set presets based on index.
    
    * src/ftinspect/panels/settingpanel.cpp,
      src/ftinspect/panels/settingpanel.hpp: Add `setDefaultsPreset` values.
    
  • 212821d5
    by Charlie Jiang at 2022-08-28T14:06:26+08:00
    * src/ftinspect/panels/continuous.cpp: Disable kerning for "All Glyphs".
    
  • 612b5f7c
    by Charlie Jiang at 2022-08-28T14:08:21+08:00
    * src/ftinspect/maingui.cpp: Stop setting panels' tab bars from being...
    
    shifted right in the comparator view.
    
  • 1c468180
    by Charlie Jiang at 2022-08-28T14:20:52+08:00
    [ftinspect] Improve fore/background color setting.
    
    Now they're shown in the comparator view as well, and an indicator for
    current color is shown.
    
    * src/ftinspect/panels/settingpanel.cpp,
      src/ftinspect/panels/settingpanel.hpp: As described.
    

16 changed files:

Changes:

  • src/ftinspect/engine/engine.cpp
    ... ... @@ -560,6 +560,15 @@ Engine::currentFontFixedSizes()
    560 560
     }
    
    561 561
     
    
    562 562
     
    
    563
    +bool
    
    564
    +Engine::currentFontHasGlyphName()
    
    565
    +{
    
    566
    +  if (!ftFallbackFace_)
    
    567
    +    return false;
    
    568
    +  return FT_HAS_GLYPH_NAMES(ftFallbackFace_);
    
    569
    +}
    
    570
    +
    
    571
    +
    
    563 572
     QString
    
    564 573
     Engine::glyphName(int index)
    
    565 574
     {
    

  • src/ftinspect/engine/engine.hpp
    ... ... @@ -122,6 +122,7 @@ public:
    122 122
       const QString& currentFamilyName() { return curFamilyName_; }
    
    123 123
       const QString& currentStyleName() { return curStyleName_; }
    
    124 124
       int currentFontNumberOfGlyphs() { return curNumGlyphs_; }
    
    125
    +  bool currentFontHasGlyphName();
    
    125 126
     
    
    126 127
       QString glyphName(int glyphIndex);
    
    127 128
       long numberOfFaces(int fontIndex);
    

  • src/ftinspect/engine/fontfilemanager.cpp
    ... ... @@ -17,9 +17,9 @@ FontFileManager::FontFileManager()
    17 17
       watchTimer_->setInterval(1000);
    
    18 18
     
    
    19 19
       connect(fontWatcher_, &QFileSystemWatcher::fileChanged,
    
    20
    -          this, &FontFileManager::onTimerOrWatcherFire);
    
    20
    +          this, &FontFileManager::onWatcherFire);
    
    21 21
       connect(watchTimer_, &QTimer::timeout,
    
    22
    -          this, &FontFileManager::onTimerOrWatcherFire);
    
    22
    +          this, &FontFileManager::onTimerFire);
    
    23 23
     }
    
    24 24
     
    
    25 25
     
    
    ... ... @@ -137,11 +137,20 @@ FontFileManager::loadFromCommandLine()
    137 137
     
    
    138 138
     
    
    139 139
     void
    
    140
    -FontFileManager::onTimerOrWatcherFire()
    
    140
    +FontFileManager::onWatcherFire()
    
    141 141
     {
    
    142 142
       watchTimer_->stop();
    
    143 143
       emit currentFileChanged();
    
    144 144
     }
    
    145 145
     
    
    146 146
     
    
    147
    +void
    
    148
    +FontFileManager::onTimerFire()
    
    149
    +{
    
    150
    +  periodicUpdating_ = true;
    
    151
    +  onWatcherFire();
    
    152
    +  periodicUpdating_ = false;
    
    153
    +}
    
    154
    +
    
    155
    +
    
    147 156
     // end of fontfilemanager.hpp

  • src/ftinspect/engine/fontfilemanager.hpp
    ... ... @@ -31,16 +31,21 @@ public:
    31 31
       void timerStart();
    
    32 32
       void loadFromCommandLine();
    
    33 33
     
    
    34
    +  bool currentReloadDueToPeriodicUpdate() { return periodicUpdating_; }
    
    35
    +
    
    34 36
     signals:
    
    35 37
       void currentFileChanged();
    
    36 38
     
    
    37 39
     private slots:
    
    38
    -  void onTimerOrWatcherFire();
    
    40
    +  void onTimerFire();
    
    41
    +  void onWatcherFire();
    
    39 42
     
    
    40 43
     private:
    
    41 44
       QList<QFileInfo> fontFileNameList_;
    
    42 45
       QFileSystemWatcher* fontWatcher_;
    
    43 46
       QTimer* watchTimer_;
    
    47
    +
    
    48
    +  bool periodicUpdating_ = false;
    
    44 49
     };
    
    45 50
     
    
    46 51
     
    

  • src/ftinspect/engine/fontinfo.cpp
    ... ... @@ -571,4 +571,126 @@ SFNTTableInfo::getForAll(Engine* engine,
    571 571
     }
    
    572 572
     
    
    573 573
     
    
    574
    +void
    
    575
    +CompositeGlyphInfo::get(Engine* engine, 
    
    576
    +                        std::vector<CompositeGlyphInfo>& list)
    
    577
    +{
    
    578
    +  list.clear();
    
    579
    +  engine->reloadFont();
    
    580
    +  auto face = engine->currentFallbackFtFace();
    
    581
    +  if (!face || !FT_IS_SFNT(face))
    
    582
    +  {
    
    583
    +    if (list.empty())
    
    584
    +      return;
    
    585
    +  }
    
    586
    +
    
    587
    +  // We're not using the FreeType's subglyph APIs, but directly reading from
    
    588
    +  // the `glyf` table since it's faster
    
    589
    +  auto head = static_cast<TT_Header*>(FT_Get_Sfnt_Table(face, FT_SFNT_HEAD));
    
    590
    +  auto maxp
    
    591
    +    = static_cast<TT_MaxProfile*>(FT_Get_Sfnt_Table(face, FT_SFNT_MAXP));
    
    592
    +  if (!head || !maxp)
    
    593
    +    return;
    
    594
    +
    
    595
    +  FT_ULong locaLength = head->Index_To_Loc_Format ? 4 * maxp->numGlyphs + 4
    
    596
    +                                                  : 2 * maxp->numGlyphs + 2;
    
    597
    +  std::unique_ptr<unsigned char[]> locaBufferGuard(
    
    598
    +    new unsigned char[locaLength]);
    
    599
    +  auto offset = locaBufferGuard.get();
    
    600
    +  auto error = FT_Load_Sfnt_Table(face, TTAG_loca, 0, offset, &locaLength);
    
    601
    +  if (error)
    
    602
    +    return;
    
    603
    +
    
    604
    +  FT_ULong glyfLength = 0;
    
    605
    +  error = FT_Load_Sfnt_Table(face, TTAG_glyf, 0, NULL, &glyfLength);
    
    606
    +  if (error || !glyfLength)
    
    607
    +    return;
    
    608
    +
    
    609
    +  std::unique_ptr<unsigned char[]> glyfBufferGuard(
    
    610
    +    new unsigned char[glyfLength]);
    
    611
    +  auto buffer = glyfBufferGuard.get();
    
    612
    +  error = FT_Load_Sfnt_Table(face, TTAG_glyf, 0, buffer, &glyfLength);
    
    613
    +  if (error)
    
    614
    +    return;
    
    615
    +
    
    616
    +  for (size_t i = 0; i < maxp->numGlyphs; i++)
    
    617
    +  {
    
    618
    +    FT_UInt32  loc, end;
    
    619
    +    if (head->Index_To_Loc_Format)
    
    620
    +    {
    
    621
    +      loc = static_cast<FT_UInt32>(offset[4 * i    ]) << 24 |
    
    622
    +            static_cast<FT_UInt32>(offset[4 * i + 1]) << 16 |
    
    623
    +            static_cast<FT_UInt32>(offset[4 * i + 2]) << 8  |
    
    624
    +            static_cast<FT_UInt32>(offset[4 * i + 3])       ;
    
    625
    +      end = static_cast<FT_UInt32>(offset[4 * i + 4]) << 24 |
    
    626
    +            static_cast<FT_UInt32>(offset[4 * i + 5]) << 16 |
    
    627
    +            static_cast<FT_UInt32>(offset[4 * i + 6]) << 8  |
    
    628
    +            static_cast<FT_UInt32>(offset[4 * i + 7])       ;
    
    629
    +    }
    
    630
    +    else
    
    631
    +    {
    
    632
    +      loc = static_cast<FT_UInt32>(offset[2 * i    ]) << 9 |
    
    633
    +            static_cast<FT_UInt32>(offset[2 * i + 1]) << 1 ;
    
    634
    +      end = static_cast<FT_UInt32>(offset[2 * i + 2]) << 9 |
    
    635
    +            static_cast<FT_UInt32>(offset[2 * i + 3]) << 1 ;
    
    636
    +    }
    
    637
    +
    
    638
    +    if (end > glyfLength)
    
    639
    +      end = glyfLength;
    
    640
    +
    
    641
    +    if (loc + 16 > end)
    
    642
    +      continue;
    
    643
    +
    
    644
    +    auto len = static_cast<FT_Int16>(buffer[loc] << 8 | buffer[loc + 1]);
    
    645
    +    loc += 10;  // skip header
    
    646
    +    if (len >= 0) // not a composite one
    
    647
    +      continue;
    
    648
    +
    
    649
    +    std::vector<SubGlyph> subglyphs;
    
    650
    +
    
    651
    +    while (true)
    
    652
    +    {
    
    653
    +      if (loc + 6 > end)
    
    654
    +        break;
    
    655
    +      auto flags = static_cast<FT_UInt16>(buffer[loc] << 8 | buffer[loc + 1]);
    
    656
    +      loc += 2;
    
    657
    +      auto index = static_cast<FT_UInt16>(buffer[loc] << 8 | buffer[loc + 1]);
    
    658
    +      loc += 2;
    
    659
    +      FT_Int16 arg1, arg2;
    
    660
    +
    
    661
    +      // https://docs.microsoft.com/en-us/typography/opentype/spec/glyf#composite-glyph-description
    
    662
    +      if (flags & 0x0001)
    
    663
    +      {
    
    664
    +        arg1 = static_cast<FT_Int16>(buffer[loc] << 8 | buffer[loc + 1]);
    
    665
    +        loc += 2;
    
    666
    +        arg2 = static_cast<FT_Int16>(buffer[loc] << 8 | buffer[loc + 1]);
    
    667
    +        loc += 2;
    
    668
    +      }
    
    669
    +      else
    
    670
    +      {
    
    671
    +        arg1 = buffer[loc];
    
    672
    +        arg2 = buffer[loc + 1];
    
    673
    +        loc += 2;
    
    674
    +      }
    
    675
    +      if (flags & 0x0008)
    
    676
    +        loc += 2;
    
    677
    +      else if (flags & 0x0040)
    
    678
    +        loc += 4;
    
    679
    +      else if (flags & 0x0080)
    
    680
    +        loc += 8;
    
    681
    +
    
    682
    +      subglyphs.emplace_back(index, flags,
    
    683
    +                             flags & 0x0002 ? SubGlyph::PT_Offset
    
    684
    +                                            : SubGlyph::PT_Align,
    
    685
    +                             std::pair<short, short>(arg1, arg2));
    
    686
    +
    
    687
    +      if (!(flags & 0x0020))
    
    688
    +        break;
    
    689
    +    }
    
    690
    +
    
    691
    +    list.emplace_back(static_cast<int>(i), std::move(subglyphs));
    
    692
    +  }
    
    693
    +}
    
    694
    +
    
    695
    +
    
    574 696
     // end of fontinfo.cpp

  • src/ftinspect/engine/fontinfo.hpp
    ... ... @@ -244,6 +244,86 @@ struct FontFixedSize
    244 244
     };
    
    245 245
     
    
    246 246
     
    
    247
    +struct CompositeGlyphInfo
    
    248
    +{
    
    249
    +  struct SubGlyph
    
    250
    +  {
    
    251
    +    enum PositionType
    
    252
    +    {
    
    253
    +      PT_Offset, // Child's points are added with a xy-offset
    
    254
    +      PT_Align // One point of the child is aligned with one point of the parent
    
    255
    +    };
    
    256
    +    unsigned short index;
    
    257
    +    unsigned short flag;
    
    258
    +    PositionType positionType;
    
    259
    +    // For PT_Offset: <deltaX, deltaY>
    
    260
    +    // For PT_Align:  <childPoint, parentPoint>
    
    261
    +    std::pair<short, short> position;
    
    262
    +
    
    263
    +    SubGlyph(unsigned short index,
    
    264
    +             unsigned short flag,
    
    265
    +             PositionType positionType,
    
    266
    +             std::pair<short, short> position)
    
    267
    +    : index(index),
    
    268
    +      flag(flag),
    
    269
    +      positionType(positionType),
    
    270
    +      position(std::move(position))
    
    271
    +    { }
    
    272
    +
    
    273
    +
    
    274
    +    friend bool
    
    275
    +    operator==(const SubGlyph& lhs,
    
    276
    +               const SubGlyph& rhs)
    
    277
    +    {
    
    278
    +      return lhs.index == rhs.index
    
    279
    +        && lhs.flag == rhs.flag
    
    280
    +        && lhs.positionType == rhs.positionType
    
    281
    +        && lhs.position == rhs.position;
    
    282
    +    }
    
    283
    +
    
    284
    +
    
    285
    +    friend bool
    
    286
    +    operator!=(const SubGlyph& lhs,
    
    287
    +               const SubGlyph& rhs)
    
    288
    +    {
    
    289
    +      return !(lhs == rhs);
    
    290
    +    }
    
    291
    +  };
    
    292
    +
    
    293
    +
    
    294
    +  int index;
    
    295
    +  std::vector<SubGlyph> subglyphs;
    
    296
    +
    
    297
    +
    
    298
    +  CompositeGlyphInfo(short index,
    
    299
    +                     std::vector<SubGlyph> subglyphs)
    
    300
    +  : index(index),
    
    301
    +    subglyphs(std::move(subglyphs))
    
    302
    +  { }
    
    303
    +
    
    304
    +
    
    305
    +  friend bool
    
    306
    +  operator==(const CompositeGlyphInfo& lhs,
    
    307
    +             const CompositeGlyphInfo& rhs)
    
    308
    +  {
    
    309
    +    return lhs.index == rhs.index
    
    310
    +      && lhs.subglyphs == rhs.subglyphs;
    
    311
    +  }
    
    312
    +
    
    313
    +
    
    314
    +  friend bool
    
    315
    +  operator!=(const CompositeGlyphInfo& lhs,
    
    316
    +             const CompositeGlyphInfo& rhs)
    
    317
    +  {
    
    318
    +    return !(lhs == rhs);
    
    319
    +  }
    
    320
    +
    
    321
    +
    
    322
    +  // expensive
    
    323
    +  static void get(Engine* engine, std::vector<CompositeGlyphInfo>& list);
    
    324
    +};
    
    325
    +
    
    326
    +
    
    247 327
     QString* mapSFNTNameIDToName(unsigned short nameID);
    
    248 328
     QString* mapTTPlatformIDToName(unsigned short platformID);
    
    249 329
     QString* mapTTEncodingIDToName(unsigned short platformID,
    

  • src/ftinspect/maingui.cpp
    ... ... @@ -171,8 +171,9 @@ MainGUI::switchTab()
    171 171
       auto isComparator = current == comparatorTab_;
    
    172 172
     
    
    173 173
       if (isComparator)
    
    174
    -    tabWidget_->setStyleSheet(QString("QTabWidget::tab-bar {left: %1 px;}")
    
    175
    -                              .arg(leftWidget_->width()));
    
    174
    +    tabWidget_->setStyleSheet(
    
    175
    +      QString("QTabWidget#mainTab::tab-bar {left: %1 px;}")
    
    176
    +      .arg(leftWidget_->width()));
    
    176 177
       else
    
    177 178
         tabWidget_->setStyleSheet("");
    
    178 179
       
    
    ... ... @@ -271,6 +272,7 @@ MainGUI::createLayout()
    271 272
       infoTab_ = new InfoTab(this, engine_);
    
    272 273
     
    
    273 274
       tabWidget_ = new QTabWidget(this);
    
    275
    +  tabWidget_->setObjectName("mainTab"); // for stylesheet
    
    274 276
     
    
    275 277
       // Note those two list must be in sync
    
    276 278
       tabs_.append(singularTab_);
    
    ... ... @@ -320,7 +322,8 @@ MainGUI::createLayout()
    320 322
     
    
    321 323
       ftinspectLayout_->setSizeConstraint(QLayout::SetNoConstraint);
    
    322 324
       layout()->setSizeConstraint(QLayout::SetNoConstraint);
    
    323
    -  resize(1400 * logicalDpiX() / 96, 700 * logicalDpiY() / 96);
    
    325
    +  resize(ftinspectWidget_->minimumSizeHint().width(),
    
    326
    +         700 * logicalDpiY() / 96);
    
    324 327
     
    
    325 328
       statusBar()->hide(); // remove the extra space
    
    326 329
       setCentralWidget(ftinspectWidget_);
    
    ... ... @@ -344,6 +347,8 @@ MainGUI::createConnections()
    344 347
     
    
    345 348
       connect(continuousTab_, &ContinuousTab::switchToSingular,
    
    346 349
               this, &MainGUI::switchToSingular);
    
    350
    +  connect(infoTab_, &InfoTab::switchToSingular,
    
    351
    +          [&](int index) { switchToSingular(index, -1); });
    
    347 352
     }
    
    348 353
     
    
    349 354
     
    

  • src/ftinspect/models/fontinfomodels.cpp
    ... ... @@ -3,6 +3,7 @@
    3 3
     // Copyright (C) 2022 by Charlie Jiang.
    
    4 4
     
    
    5 5
     #include "fontinfomodels.hpp"
    
    6
    +#include "../engine/engine.hpp"
    
    6 7
     
    
    7 8
     int
    
    8 9
     FixedSizeInfoModel::rowCount(const QModelIndex& parent) const
    
    ... ... @@ -463,4 +464,219 @@ MMGXAxisInfoModel::headerData(int section,
    463 464
     }
    
    464 465
     
    
    465 466
     
    
    467
    +int
    
    468
    +CompositeGlyphsInfoModel::rowCount(const QModelIndex& parent) const
    
    469
    +{
    
    470
    +  if (!parent.isValid())
    
    471
    +    return static_cast<int>(glyphs_.size());
    
    472
    +  auto id = parent.internalId();
    
    473
    +  if (id < 0 || id >= nodes_.size())
    
    474
    +    return 0;
    
    475
    +  auto gid = nodes_[id].glyphIndex;
    
    476
    +  auto iter = glyphMapper_.find(gid);
    
    477
    +  if (iter == glyphMapper_.end())
    
    478
    +    return 0;
    
    479
    +  if (iter->second > glyphs_.size())
    
    480
    +    return 0;
    
    481
    +  return static_cast<int>(glyphs_[iter->second]. subglyphs.size());
    
    482
    +}
    
    483
    +
    
    484
    +
    
    485
    +int
    
    486
    +CompositeGlyphsInfoModel::columnCount(const QModelIndex& parent) const
    
    487
    +{
    
    488
    +  return CGIM_Max;
    
    489
    +}
    
    490
    +
    
    491
    +
    
    492
    +QModelIndex
    
    493
    +CompositeGlyphsInfoModel::index(int row,
    
    494
    +                                int column,
    
    495
    +                                const QModelIndex& parent) const
    
    496
    +{
    
    497
    +  long long parentIdx = -1;
    
    498
    +  if (parent.isValid()) // Not top-level
    
    499
    +    parentIdx = static_cast<long long>(parent.internalId());
    
    500
    +  if (parentIdx < 0)
    
    501
    +    parentIdx = -1;
    
    502
    +  // find existing node by row and parent index, -1 for top-level
    
    503
    +  auto lookupPair = std::pair<int, long long>(row, parentIdx);
    
    504
    +
    
    505
    +  auto iter = nodeLookup_.find(lookupPair);
    
    506
    +  if (iter != nodeLookup_.end())
    
    507
    +  {
    
    508
    +    if (iter->second < 0 || static_cast<size_t>(iter->second) >= nodes_.size())
    
    509
    +      return {};
    
    510
    +    return createIndex(row, column, iter->second);
    
    511
    +  }
    
    512
    +
    
    513
    +  int id = -1;
    
    514
    +  CompositeGlyphInfo::SubGlyph const* sgInfo = nullptr;
    
    515
    +  if (!parent.isValid()) // top-level nodes
    
    516
    +    id = glyphs_[row].index;
    
    517
    +  else if (parent.internalId() < glyphs_.size())
    
    518
    +  {
    
    519
    +    auto& sg = glyphs_[parent.internalId()].subglyphs;
    
    520
    +    if (row < 0 || static_cast<size_t>(row) >= sg.size())
    
    521
    +      return {};
    
    522
    +    id = sg[row].index;
    
    523
    +    sgInfo = &sg[row];
    
    524
    +  }
    
    525
    +
    
    526
    +  if (id < 0)
    
    527
    +    return {};
    
    528
    +  
    
    529
    +  InfoNode node = {
    
    530
    +    parentIdx,
    
    531
    +    row, id,
    
    532
    +    sgInfo
    
    533
    +  };
    
    534
    +  nodes_.push_back(node);
    
    535
    +  nodeLookup_.emplace(std::pair<int, long long>(row, parentIdx),
    
    536
    +                      nodes_.size() - 1);
    
    537
    +
    
    538
    +  return createIndex(row, column, nodes_.size() - 1);
    
    539
    +}
    
    540
    +
    
    541
    +
    
    542
    +QModelIndex
    
    543
    +CompositeGlyphsInfoModel::parent(const QModelIndex& child) const
    
    544
    +{
    
    545
    +  if (!child.isValid())
    
    546
    +    return {};
    
    547
    +
    
    548
    +  auto id = static_cast<long long>(child.internalId());
    
    549
    +  if (id < 0 || static_cast<size_t>(id) >= nodes_.size())
    
    550
    +    return {};
    
    551
    +
    
    552
    +  auto pid = nodes_[id].parentNodeIndex;
    
    553
    +  if (pid < 0 || static_cast<size_t>(pid) >= nodes_.size())
    
    554
    +    return {};
    
    555
    +
    
    556
    +  auto& p = nodes_[pid];
    
    557
    +  return createIndex(p.indexInParent, 0, pid);
    
    558
    +}
    
    559
    +
    
    560
    +
    
    561
    +QVariant
    
    562
    +CompositeGlyphsInfoModel::data(const QModelIndex& index,
    
    563
    +                               int role) const
    
    564
    +{
    
    565
    +  if (!index.isValid())
    
    566
    +    return {};
    
    567
    +
    
    568
    +  auto id = index.internalId();
    
    569
    +  if (id >= nodes_.size())
    
    570
    +    return {};
    
    571
    +  auto& n = nodes_[id];
    
    572
    +  auto glyphIdx = n.glyphIndex;
    
    573
    +
    
    574
    +  if (role == Qt::ToolTipRole && index.column() == CGIM_Position)
    
    575
    +  {
    
    576
    +    if (!n.subGlyphInfo)
    
    577
    +      return {};
    
    578
    +    auto pos = n.subGlyphInfo->position;
    
    579
    +    switch (n.subGlyphInfo->positionType)
    
    580
    +    {
    
    581
    +    case CompositeGlyphInfo::SubGlyph::PT_Offset:
    
    582
    +      return QString("Add a offset (%1, %2) to the subglyph's points")
    
    583
    +          .arg(pos.first)
    
    584
    +          .arg(pos.second);
    
    585
    +    case CompositeGlyphInfo::SubGlyph::PT_Align:
    
    586
    +      return QString("Align parent's point %1 to subglyph's point %2")
    
    587
    +          .arg(pos.first)
    
    588
    +          .arg(pos.second);
    
    589
    +    }
    
    590
    +    return {};
    
    591
    +  }
    
    592
    +
    
    593
    +  if (role != Qt::DisplayRole)
    
    594
    +    return {};
    
    595
    +
    
    596
    +  switch (static_cast<Columns>(index.column()))
    
    597
    +  {
    
    598
    +  case CGIM_Glyph:
    
    599
    +    if (engine_->currentFontHasGlyphName())
    
    600
    +      return QString("%1 <%2>").arg(glyphIdx).arg(engine_->glyphName(glyphIdx));
    
    601
    +    return QString::number(glyphIdx);
    
    602
    +  case CGIM_Flag:
    
    603
    +    if (!n.subGlyphInfo)
    
    604
    +      return {};
    
    605
    +    return QString::number(n.subGlyphInfo->flag, 16).rightJustified(4, '0');
    
    606
    +  case CGIM_Position:
    
    607
    +  {
    
    608
    +    if (!n.subGlyphInfo)
    
    609
    +      return {};
    
    610
    +    auto pos = n.subGlyphInfo->position;
    
    611
    +    switch (n.subGlyphInfo->positionType)
    
    612
    +    {
    
    613
    +    case CompositeGlyphInfo::SubGlyph::PT_Offset:
    
    614
    +      return QString("Offset (%1, %2)").arg(pos.first).arg(pos.second);
    
    615
    +    case CompositeGlyphInfo::SubGlyph::PT_Align:
    
    616
    +      return QString("Align %1 -> %2").arg(pos.first).arg(pos.second);
    
    617
    +    }
    
    618
    +  }
    
    619
    +  }
    
    620
    +
    
    621
    +  return {};
    
    622
    +}
    
    623
    +
    
    624
    +
    
    625
    +QVariant
    
    626
    +CompositeGlyphsInfoModel::headerData(int section,
    
    627
    +                                     Qt::Orientation orientation,
    
    628
    +                                     int role) const
    
    629
    +{
    
    630
    +  if (role != Qt::DisplayRole)
    
    631
    +    return {};
    
    632
    +  if (orientation != Qt::Horizontal)
    
    633
    +    return {};
    
    634
    +
    
    635
    +  switch (static_cast<Columns>(section))
    
    636
    +  {
    
    637
    +  case CGIM_Glyph:
    
    638
    +    return tr("Glyph");
    
    639
    +  case CGIM_Flag:
    
    640
    +    return tr("Flags");
    
    641
    +  case CGIM_Position:
    
    642
    +    return tr("Position");
    
    643
    +  }
    
    644
    +  return {};
    
    645
    +}
    
    646
    +
    
    647
    +
    
    648
    +int
    
    649
    +CompositeGlyphsInfoModel::glyphIndexFromIndex(const QModelIndex& idx)
    
    650
    +{
    
    651
    +  if (!idx.isValid())
    
    652
    +    return -1;
    
    653
    +
    
    654
    +  auto id = idx.internalId();
    
    655
    +  if (id >= nodes_.size())
    
    656
    +    return -1;
    
    657
    +  auto& n = nodes_[id];
    
    658
    +  return n.glyphIndex;
    
    659
    +}
    
    660
    +
    
    661
    +
    
    662
    +void
    
    663
    +CompositeGlyphsInfoModel::beginModelUpdate()
    
    664
    +{
    
    665
    +  beginResetModel();
    
    666
    +  glyphs_.clear();
    
    667
    +  nodeLookup_.clear();
    
    668
    +  nodes_.clear();
    
    669
    +}
    
    670
    +
    
    671
    +
    
    672
    +void
    
    673
    +CompositeGlyphsInfoModel::endModelUpdate()
    
    674
    +{
    
    675
    +  glyphMapper_.clear();
    
    676
    +  for (size_t i = 0; i < glyphs_.size(); i++)
    
    677
    +    glyphMapper_.emplace(glyphs_[i].index, i);
    
    678
    +  endResetModel();
    
    679
    +}
    
    680
    +
    
    681
    +
    
    466 682
     // end of fontinfomodels.cpp

  • src/ftinspect/models/fontinfomodels.hpp
    ... ... @@ -9,6 +9,7 @@
    9 9
     #include "../engine/mmgx.hpp"
    
    10 10
     
    
    11 11
     #include <vector>
    
    12
    +#include <unordered_map>
    
    12 13
     #include <QAbstractTableModel>
    
    13 14
     
    
    14 15
     class FixedSizeInfoModel
    
    ... ... @@ -203,4 +204,82 @@ private:
    203 204
     };
    
    204 205
     
    
    205 206
     
    
    207
    +struct LookupPairHash
    
    208
    +{
    
    209
    +public:
    
    210
    +  std::size_t
    
    211
    +  operator()(const std::pair<int, long long>& p) const
    
    212
    +  {
    
    213
    +    std::size_t seed = 0x291FEEA8;
    
    214
    +    seed ^= (seed << 6) + (seed >> 2) + 0x25F3E86D
    
    215
    +            + static_cast<std::size_t>(p.first);
    
    216
    +    seed ^= (seed << 6) + (seed >> 2) + 0x436E6B92
    
    217
    +            + static_cast<std::size_t>(p.second);
    
    218
    +    return seed;
    
    219
    +  }
    
    220
    +};
    
    221
    +
    
    222
    +
    
    223
    +// A tree model, so much more complicated.
    
    224
    +class CompositeGlyphsInfoModel : public QAbstractItemModel
    
    225
    +{
    
    226
    +  Q_OBJECT
    
    227
    +public:
    
    228
    +  // A lazily created info node.
    
    229
    +  struct InfoNode
    
    230
    +  {
    
    231
    +    long long parentNodeIndex;
    
    232
    +    int indexInParent;
    
    233
    +    int glyphIndex;
    
    234
    +    CompositeGlyphInfo::SubGlyph const* subGlyphInfo;
    
    235
    +  };
    
    236
    +
    
    237
    +  explicit CompositeGlyphsInfoModel(QObject* parent, Engine* engine)
    
    238
    +      : QAbstractItemModel(parent), engine_(engine)
    
    239
    +  {
    
    240
    +  }
    
    241
    +
    
    242
    +  ~CompositeGlyphsInfoModel() override = default;
    
    243
    +
    
    244
    +  int rowCount(const QModelIndex& parent) const override;
    
    245
    +  int columnCount(const QModelIndex& parent) const override;
    
    246
    +  QModelIndex index(int row, int column,
    
    247
    +                    const QModelIndex& parent) const override;
    
    248
    +  QModelIndex parent(const QModelIndex& child) const override;
    
    249
    +  QVariant data(const QModelIndex& index, int role) const override;
    
    250
    +  QVariant headerData(int section, Qt::Orientation orientation,
    
    251
    +                      int role) const override;
    
    252
    +  int glyphIndexFromIndex(const QModelIndex& idx);
    
    253
    +
    
    254
    +  void beginModelUpdate();
    
    255
    +  void endModelUpdate();
    
    256
    +  std::vector<CompositeGlyphInfo>& storage() { return glyphs_; }
    
    257
    +
    
    258
    +  enum Columns : int
    
    259
    +  {
    
    260
    +    CGIM_Glyph = 0, // TODO: transformation, scale? consider more flags?
    
    261
    +    CGIM_Flag = 1,
    
    262
    +    CGIM_Position = 2,
    
    263
    +    CGIM_Max
    
    264
    +  };
    
    265
    +
    
    266
    +private:
    
    267
    +  Engine* engine_;
    
    268
    +  /*
    
    269
    +   * Take care of 3 types of index:
    
    270
    +   * 1. Glyph Index in Font File
    
    271
    +   * 2. Glyph Index in `glyphs_` - often called as "glyph info index"
    
    272
    +   * 3. Node Index
    
    273
    +   */
    
    274
    +  std::vector<CompositeGlyphInfo> glyphs_;
    
    275
    +  std::unordered_map<int, size_t> glyphMapper_;
    
    276
    +  // map <row, parentId> to node
    
    277
    +  // the internal id of `QModelIndex` is the node's index
    
    278
    +  mutable std::unordered_map<std::pair<int, long long>,
    
    279
    +                             long long, LookupPairHash>
    
    280
    +          nodeLookup_;
    
    281
    +  mutable std::vector<InfoNode> nodes_;
    
    282
    +};
    
    283
    +
    
    284
    +
    
    206 285
     // end of fontinfomodels.hpp

  • src/ftinspect/panels/comparator.cpp
    ... ... @@ -98,6 +98,7 @@ ComperatorTab::createLayout()
    98 98
         auto frame = new QFrame(this);
    
    99 99
         auto canvas = new GlyphContinuous(frame, engine_);
    
    100 100
         auto settingPanel = new SettingPanel(this, engine_, true);
    
    101
    +    settingPanel->setDefaultsPreset(i);
    
    101 102
     
    
    102 103
         sizeSelector_->installEventFilterForWidget(canvas);
    
    103 104
     
    

  • src/ftinspect/panels/continuous.cpp
    ... ... @@ -161,6 +161,14 @@ ContinuousTab::checkModeSource()
    161 161
       indexSelector_->setEnabled(src == GlyphContinuous::SRC_AllGlyphs);
    
    162 162
       sourceTextEdit_->setEnabled(isText);
    
    163 163
       sampleStringSelector_->setEnabled(isText);
    
    164
    +
    
    165
    +  {
    
    166
    +    QSignalBlocker blocker(kerningCheckBox_);
    
    167
    +    kerningCheckBox_->setEnabled(isText);
    
    168
    +    if (!isText)
    
    169
    +      kerningCheckBox_->setChecked(false);
    
    170
    +  }
    
    171
    +  
    
    164 172
       canvas_->setSource(src);
    
    165 173
     
    
    166 174
       {
    
    ... ... @@ -548,7 +556,12 @@ ContinuousTab::createConnections()
    548 556
       sizeSelector_->installEventFilterForWidget(this);
    
    549 557
     
    
    550 558
       connect(glyphDetails_, &GlyphDetails::switchToSingular,
    
    551
    -          [&] (int index) { switchToSingular(index, -1); });
    
    559
    +          [&] (int index)
    
    560
    +          {
    
    561
    +            switchToSingular(index, -1);
    
    562
    +            if (glyphDetailsWidget_->isFloating())
    
    563
    +              glyphDetailsWidget_->hide();
    
    564
    +          });
    
    552 565
     }
    
    553 566
     
    
    554 567
     
    

  • src/ftinspect/panels/info.cpp
    ... ... @@ -22,6 +22,7 @@ InfoTab::InfoTab(QWidget* parent,
    22 22
     : QWidget(parent), engine_(engine)
    
    23 23
     {
    
    24 24
       createLayout();
    
    25
    +  createConnections();
    
    25 26
     }
    
    26 27
     
    
    27 28
     
    
    ... ... @@ -40,17 +41,19 @@ InfoTab::createLayout()
    40 41
       sfntTab_ = new SFNTInfoTab(this, engine_);
    
    41 42
       postScriptTab_ = new PostScriptInfoTab(this, engine_);
    
    42 43
       mmgxTab_ = new MMGXInfoTab(this, engine_);
    
    44
    +  compositeGlyphsTab_ = new CompositeGlyphsTab(this, engine_);
    
    43 45
     
    
    44 46
       tab_ = new QTabWidget(this);
    
    45 47
       tab_->addTab(generalTab_, tr("General"));
    
    46 48
       tab_->addTab(sfntTab_, tr("SFNT"));
    
    47 49
       tab_->addTab(postScriptTab_, tr("PostScript"));
    
    48 50
       tab_->addTab(mmgxTab_, tr("MM/GX"));
    
    51
    +  tab_->addTab(compositeGlyphsTab_, tr("Composite Glyphs"));
    
    49 52
     
    
    50 53
       tabs_.append(generalTab_);
    
    51 54
       tabs_.append(sfntTab_);
    
    52 55
       tabs_.append(postScriptTab_);
    
    53
    -  tabs_.append(mmgxTab_);
    
    56
    +  tabs_.append(compositeGlyphsTab_);
    
    54 57
     
    
    55 58
       layout_ = new QHBoxLayout;
    
    56 59
       layout_->addWidget(tab_);
    
    ... ... @@ -59,6 +62,14 @@ InfoTab::createLayout()
    59 62
     }
    
    60 63
     
    
    61 64
     
    
    65
    +void
    
    66
    +InfoTab::createConnections()
    
    67
    +{
    
    68
    +  connect(compositeGlyphsTab_, &CompositeGlyphsTab::switchToSingular,
    
    69
    +          this, &InfoTab::switchToSingular);
    
    70
    +}
    
    71
    +
    
    72
    +
    
    62 73
     GeneralInfoTab::GeneralInfoTab(QWidget* parent,
    
    63 74
                                    Engine* engine)
    
    64 75
     : QWidget(parent), engine_(engine)
    
    ... ... @@ -919,4 +930,89 @@ MMGXInfoTab::createLayout()
    919 930
     }
    
    920 931
     
    
    921 932
     
    
    933
    +CompositeGlyphsTab::CompositeGlyphsTab(QWidget* parent,
    
    934
    +                                       Engine* engine)
    
    935
    +: QWidget(parent), engine_(engine)
    
    936
    +{
    
    937
    +  createLayout();
    
    938
    +  createConnections();
    
    939
    +}
    
    940
    +
    
    941
    +
    
    942
    +void
    
    943
    +CompositeGlyphsTab::reloadFont()
    
    944
    +{
    
    945
    +  if (engine_->fontFileManager().currentReloadDueToPeriodicUpdate())
    
    946
    +    return;
    
    947
    +  forceReloadFont();
    
    948
    +}
    
    949
    +
    
    950
    +
    
    951
    +void
    
    952
    +CompositeGlyphsTab::createLayout()
    
    953
    +{
    
    954
    +  compositeGlyphCountPromptLabel_ = new QLabel(tr("Composite Glyphs Count:"));
    
    955
    +  compositeGlyphCountLabel_ = new QLabel(this);
    
    956
    +  forceRefreshButton_ = new QPushButton(tr("Force Refresh"), this);
    
    957
    +  compositeTreeView_ = new QTreeView(this);
    
    958
    +
    
    959
    +  compositeModel_ = new CompositeGlyphsInfoModel(this, engine_);
    
    960
    +  compositeTreeView_->setModel(compositeModel_);
    
    961
    +
    
    962
    +  forceRefreshButton_->setToolTip(tr(
    
    963
    +    "Force refresh the tree view.\n"
    
    964
    +    "Note that periodic reloading of fonts loaded from symbolic links won't\n"
    
    965
    +    "trigger automatically refreshing, so you need to manually reload."));
    
    966
    +
    
    967
    +  // Layouting
    
    968
    +  countLayout_ = new QHBoxLayout;
    
    969
    +  countLayout_->addWidget(compositeGlyphCountPromptLabel_);
    
    970
    +  countLayout_->addWidget(compositeGlyphCountLabel_);
    
    971
    +  countLayout_->addWidget(forceRefreshButton_);
    
    972
    +  countLayout_->addStretch(1);
    
    973
    +
    
    974
    +  mainLayout_ = new QVBoxLayout;
    
    975
    +  mainLayout_->addLayout(countLayout_);
    
    976
    +  mainLayout_->addWidget(compositeTreeView_);
    
    977
    +
    
    978
    +  setLayout(mainLayout_);
    
    979
    +}
    
    980
    +
    
    981
    +
    
    982
    +void
    
    983
    +CompositeGlyphsTab::createConnections()
    
    984
    +{
    
    985
    +  connect(forceRefreshButton_, &QPushButton::clicked,
    
    986
    +          this, &CompositeGlyphsTab::forceReloadFont);
    
    987
    +  connect(compositeTreeView_, &QTreeView::doubleClicked,
    
    988
    +          this, &CompositeGlyphsTab::treeRowDoubleClicked);
    
    989
    +}
    
    990
    +
    
    991
    +
    
    992
    +void
    
    993
    +CompositeGlyphsTab::forceReloadFont()
    
    994
    +{
    
    995
    +  std::vector<CompositeGlyphInfo> list;
    
    996
    +  CompositeGlyphInfo::get(engine_, list);
    
    997
    +  if (list == compositeModel_->storage())
    
    998
    +    return;
    
    999
    +  compositeModel_->beginModelUpdate();
    
    1000
    +  compositeModel_->storage() = list;
    
    1001
    +  compositeModel_->endModelUpdate();
    
    1002
    +
    
    1003
    +  compositeGlyphCountLabel_->setText(
    
    1004
    +    QString::number(compositeModel_->storage().size()));
    
    1005
    +}
    
    1006
    +
    
    1007
    +
    
    1008
    +void
    
    1009
    +CompositeGlyphsTab::treeRowDoubleClicked(const QModelIndex& idx)
    
    1010
    +{
    
    1011
    +  auto gidx = compositeModel_->glyphIndexFromIndex(idx);
    
    1012
    +  if (gidx < 0)
    
    1013
    +    return;
    
    1014
    +  emit switchToSingular(gidx);
    
    1015
    +}
    
    1016
    +
    
    1017
    +
    
    922 1018
     // end of info.cpp

  • src/ftinspect/panels/info.hpp
    ... ... @@ -20,13 +20,14 @@
    20 20
     #include <QLabel>
    
    21 21
     #include <QGroupBox>
    
    22 22
     #include <QTableView>
    
    23
    -#include <QStackedLayout>
    
    23
    +#include <QTreeView>
    
    24 24
     
    
    25 25
     class Engine;
    
    26 26
     class GeneralInfoTab;
    
    27 27
     class SFNTInfoTab;
    
    28 28
     class PostScriptInfoTab;
    
    29 29
     class MMGXInfoTab;
    
    30
    +class CompositeGlyphsTab;
    
    30 31
     
    
    31 32
     class InfoTab
    
    32 33
     : public QWidget, public AbstractTab
    
    ... ... @@ -39,19 +40,24 @@ public:
    39 40
       void repaintGlyph() override {}
    
    40 41
       void reloadFont() override;
    
    41 42
     
    
    43
    +signals:
    
    44
    +  void switchToSingular(int glyphIndex);
    
    45
    +
    
    42 46
     private:
    
    43 47
       Engine* engine_;
    
    44 48
     
    
    45 49
       QVector<AbstractTab*> tabs_;
    
    46
    -  GeneralInfoTab*    generalTab_;
    
    47
    -  SFNTInfoTab*       sfntTab_;
    
    48
    -  PostScriptInfoTab* postScriptTab_;
    
    49
    -  MMGXInfoTab*       mmgxTab_;
    
    50
    +  GeneralInfoTab*     generalTab_;
    
    51
    +  SFNTInfoTab*        sfntTab_;
    
    52
    +  PostScriptInfoTab*  postScriptTab_;
    
    53
    +  MMGXInfoTab*        mmgxTab_;
    
    54
    +  CompositeGlyphsTab* compositeGlyphsTab_;
    
    50 55
     
    
    51 56
       QTabWidget* tab_;
    
    52 57
       QHBoxLayout* layout_;
    
    53 58
     
    
    54 59
       void createLayout();
    
    60
    +  void createConnections();
    
    55 61
     };
    
    56 62
     
    
    57 63
     
    
    ... ... @@ -285,4 +291,37 @@ private:
    285 291
     };
    
    286 292
     
    
    287 293
     
    
    294
    +class CompositeGlyphsTab
    
    295
    +: public QWidget, public AbstractTab
    
    296
    +{
    
    297
    +  Q_OBJECT
    
    298
    +public:
    
    299
    +  CompositeGlyphsTab(QWidget* parent, Engine* engine);
    
    300
    +  ~CompositeGlyphsTab() override = default;
    
    301
    +
    
    302
    +  void repaintGlyph() override {}
    
    303
    +  void reloadFont() override;
    
    304
    +
    
    305
    +signals:
    
    306
    +  void switchToSingular(int glyphIndex);
    
    307
    +
    
    308
    +private:
    
    309
    +  Engine* engine_;
    
    310
    +
    
    311
    +  LabelPair(compositeGlyphCount)
    
    312
    +  QPushButton* forceRefreshButton_;
    
    313
    +  QTreeView* compositeTreeView_;
    
    314
    +  CompositeGlyphsInfoModel* compositeModel_;
    
    315
    +
    
    316
    +  QHBoxLayout* countLayout_;
    
    317
    +  QVBoxLayout* mainLayout_;
    
    318
    +
    
    319
    +  void createLayout();
    
    320
    +  void createConnections();
    
    321
    +
    
    322
    +  void forceReloadFont();
    
    323
    +  void treeRowDoubleClicked(const QModelIndex& idx);
    
    324
    +};
    
    325
    +
    
    326
    +
    
    288 327
     // end of info.hpp

  • src/ftinspect/panels/settingpanel.cpp
    ... ... @@ -49,6 +49,30 @@ SettingPanel::lsbRsbDeltaEnabled()
    49 49
     }
    
    50 50
     
    
    51 51
     
    
    52
    +void
    
    53
    +SettingPanel::setDefaultsPreset(int preset)
    
    54
    +{
    
    55
    +  if (preset < 0)
    
    56
    +    preset = 0;
    
    57
    +  preset %= 3;
    
    58
    +  switch (preset)
    
    59
    +  {
    
    60
    +  case 0:
    
    61
    +    hintingCheckBox_->setChecked(true);
    
    62
    +    autoHintingCheckBox_->setChecked(false);
    
    63
    +    break;
    
    64
    +  case 1:
    
    65
    +    hintingCheckBox_->setChecked(true);
    
    66
    +    autoHintingCheckBox_->setChecked(true);
    
    67
    +    break;
    
    68
    +  case 2:
    
    69
    +    hintingCheckBox_->setChecked(false);
    
    70
    +    autoHintingCheckBox_->setChecked(false);
    
    71
    +    break;
    
    72
    +  }
    
    73
    +}
    
    74
    +
    
    75
    +
    
    52 76
     void
    
    53 77
     SettingPanel::checkAllSettings()
    
    54 78
     {
    
    ... ... @@ -174,6 +198,7 @@ SettingPanel::openBackgroundPicker()
    174 198
       if (result.isValid())
    
    175 199
       {
    
    176 200
         backgroundColor_ = result;
    
    201
    +    resetColorBlocks();
    
    177 202
         emit repaintNeeded();
    
    178 203
       }
    
    179 204
     }
    
    ... ... @@ -189,6 +214,7 @@ SettingPanel::openForegroundPicker()
    189 214
       if (result.isValid())
    
    190 215
       {
    
    191 216
         foregroundColor_ = result;
    
    217
    +    resetColorBlocks();
    
    192 218
         emit repaintNeeded();
    
    193 219
       }
    
    194 220
     }
    
    ... ... @@ -204,6 +230,24 @@ SettingPanel::updateGamma()
    204 230
     }
    
    205 231
     
    
    206 232
     
    
    233
    +void
    
    234
    +SettingPanel::resetColorBlocks()
    
    235
    +{
    
    236
    +  foregroundBlock_->setStyleSheet(
    
    237
    +    QString("QWidget {background-color: rgba(%1, %2, %3, %4);}")
    
    238
    +      .arg(foregroundColor_.red())
    
    239
    +      .arg(foregroundColor_.blue())
    
    240
    +      .arg(foregroundColor_.green())
    
    241
    +      .arg(foregroundColor_.alpha()));
    
    242
    +  backgroundBlock_->setStyleSheet(
    
    243
    +    QString("QWidget {background-color: rgba(%1, %2, %3, %4);}")
    
    244
    +      .arg(backgroundColor_.red())
    
    245
    +      .arg(backgroundColor_.blue())
    
    246
    +      .arg(backgroundColor_.green())
    
    247
    +      .arg(backgroundColor_.alpha()));
    
    248
    +}
    
    249
    +
    
    250
    +
    
    207 251
     void
    
    208 252
     SettingPanel::checkHintingMode()
    
    209 253
     {
    
    ... ... @@ -427,13 +471,10 @@ SettingPanel::createConnections()
    427 471
                 this, &SettingPanel::repaintNeeded);
    
    428 472
       }
    
    429 473
     
    
    430
    -  if (!comparatorMode_)
    
    431
    -  {
    
    432
    -    connect(backgroundButton_, &QPushButton::clicked,
    
    433
    -            this, &SettingPanel::openBackgroundPicker);
    
    434
    -    connect(foregroundButton_, &QPushButton::clicked,
    
    435
    -            this, &SettingPanel::openForegroundPicker);
    
    436
    -  }
    
    474
    +  connect(backgroundButton_, &QPushButton::clicked,
    
    475
    +          this, &SettingPanel::openBackgroundPicker);
    
    476
    +  connect(foregroundButton_, &QPushButton::clicked,
    
    477
    +          this, &SettingPanel::openForegroundPicker);
    
    437 478
     
    
    438 479
       connect(mmgxPanel_, &SettingPanelMMGX::mmgxCoordsChanged,
    
    439 480
               this, &SettingPanel::fontReloadNeeded);
    
    ... ... @@ -518,16 +559,25 @@ SettingPanel::createLayout()
    518 559
       gammaSlider_->setRange(0, 30); // in 1/10th
    
    519 560
       gammaSlider_->setTickPosition(QSlider::TicksBelow);
    
    520 561
       gammaSlider_->setTickInterval(5);
    
    562
    +  gammaSlider_->setPageStep(1);
    
    563
    +  gammaSlider_->setSingleStep(1);
    
    521 564
       gammaLabel_->setBuddy(gammaSlider_);
    
    522 565
       gammaValueLabel_ = new QLabel(this);
    
    523 566
     
    
    524 567
       mmgxPanel_ = new SettingPanelMMGX(this, engine_);
    
    525 568
     
    
    526
    -  if (!comparatorMode_)
    
    527
    -  {
    
    528
    -    backgroundButton_ = new QPushButton(tr("Background"), this);
    
    529
    -    foregroundButton_ = new QPushButton(tr("Foreground"), this);
    
    530
    -  }
    
    569
    +  backgroundButton_ = new QPushButton(tr("Background"), this);
    
    570
    +  foregroundButton_ = new QPushButton(tr("Foreground"), this);
    
    571
    +
    
    572
    +  backgroundBlock_ = new QFrame(this);
    
    573
    +  backgroundBlock_->setFrameStyle(QFrame::Box);
    
    574
    +  backgroundBlock_->setLineWidth(1);
    
    575
    +  backgroundBlock_->setFixedWidth(18);
    
    576
    +
    
    577
    +  foregroundBlock_ = new QFrame(this);
    
    578
    +  foregroundBlock_->setFrameStyle(QFrame::Box);
    
    579
    +  foregroundBlock_->setLineWidth(1);
    
    580
    +  foregroundBlock_->setFixedWidth(18);
    
    531 581
     
    
    532 582
       generalTab_ = new QWidget(this);
    
    533 583
     
    
    ... ... @@ -571,11 +621,8 @@ SettingPanel::createLayout()
    571 621
           tr("Enable LSB/RSB delta positioning (only valid when hinting is "
    
    572 622
              "enabled)."));
    
    573 623
       }
    
    574
    -  if (!comparatorMode_)
    
    575
    -  {
    
    576
    -    backgroundButton_->setToolTip(tr("Set canvas background color."));
    
    577
    -    foregroundButton_->setToolTip(tr("Set text color."));
    
    578
    -  }
    
    624
    +  backgroundButton_->setToolTip(tr("Set canvas background color."));
    
    625
    +  foregroundButton_->setToolTip(tr("Set text color."));
    
    579 626
     
    
    580 627
       // Layouting
    
    581 628
       if (debugMode_)
    
    ... ... @@ -593,6 +640,12 @@ SettingPanel::createLayout()
    593 640
       gammaLayout_->addWidget(gammaSlider_);
    
    594 641
       gammaLayout_->addWidget(gammaValueLabel_);
    
    595 642
     
    
    643
    +  colorPickerLayout_ = new QHBoxLayout;
    
    644
    +  colorPickerLayout_->addWidget(backgroundBlock_);
    
    645
    +  colorPickerLayout_->addWidget(backgroundButton_, 1);
    
    646
    +  colorPickerLayout_->addWidget(foregroundButton_, 1);
    
    647
    +  colorPickerLayout_->addWidget(foregroundBlock_);
    
    648
    +
    
    596 649
       if (comparatorMode_)
    
    597 650
         createLayoutComperator();
    
    598 651
       else
    
    ... ... @@ -632,12 +685,7 @@ SettingPanel::createLayoutNormal()
    632 685
                             new QSpacerItem(0, 20, QSizePolicy::Minimum,
    
    633 686
                                             QSizePolicy::MinimumExpanding));
    
    634 687
     
    
    635
    -  colorPickerLayout_ = new QHBoxLayout;
    
    636
    -  colorPickerLayout_->addWidget(backgroundButton_, 1);
    
    637
    -  colorPickerLayout_->addWidget(foregroundButton_, 1);
    
    638
    -  generalTabLayout_->addLayout(colorPickerLayout_,
    
    639
    -                               generalTabLayout_->rowCount(), 0, 1, 2);
    
    640
    -
    
    688
    +  gridLayout2ColAddLayout(generalTabLayout_, colorPickerLayout_);
    
    641 689
       gridLayout2ColAddLayout(generalTabLayout_, gammaLayout_);
    
    642 690
       gridLayout2ColAddWidget(generalTabLayout_, stemDarkeningCheckBox_);
    
    643 691
       gridLayout2ColAddWidget(generalTabLayout_, embeddedBitmapCheckBox_);
    
    ... ... @@ -686,6 +734,7 @@ SettingPanel::createLayoutComperator()
    686 734
       gridLayout2ColAddWidget(hintingRenderingTabLayout_, stemDarkeningCheckBox_);
    
    687 735
     
    
    688 736
       // General
    
    737
    +  gridLayout2ColAddLayout(generalTabLayout_, colorPickerLayout_);
    
    689 738
       gridLayout2ColAddWidget(generalTabLayout_, embeddedBitmapCheckBox_);
    
    690 739
       gridLayout2ColAddWidget(generalTabLayout_, colorLayerCheckBox_);
    
    691 740
       gridLayout2ColAddWidget(generalTabLayout_, 
    
    ... ... @@ -755,6 +804,7 @@ SettingPanel::setDefaults()
    755 804
       // These need to be set even in Comperator mode.
    
    756 805
       backgroundColor_ = Qt::white;
    
    757 806
       foregroundColor_ = Qt::black;
    
    807
    +  resetColorBlocks();
    
    758 808
     
    
    759 809
       gammaSlider_->setValue(18); // 1.8
    
    760 810
       updateGamma();
    

  • src/ftinspect/panels/settingpanel.hpp
    ... ... @@ -38,6 +38,7 @@ public:
    38 38
       int antiAliasingModeIndex();
    
    39 39
       bool kerningEnabled();
    
    40 40
       bool lsbRsbDeltaEnabled();
    
    41
    +  void setDefaultsPreset(int preset);
    
    41 42
     
    
    42 43
     signals:
    
    43 44
       void fontReloadNeeded();
    
    ... ... @@ -111,6 +112,8 @@ private:
    111 112
     
    
    112 113
       QPushButton* backgroundButton_;
    
    113 114
       QPushButton* foregroundButton_;
    
    115
    +  QFrame* backgroundBlock_;
    
    116
    +  QFrame* foregroundBlock_;
    
    114 117
     
    
    115 118
       QVBoxLayout* mainLayout_;
    
    116 119
       QGridLayout* generalTabLayout_;
    
    ... ... @@ -135,6 +138,7 @@ private:
    135 138
       void openBackgroundPicker();
    
    136 139
       void openForegroundPicker();
    
    137 140
       void updateGamma();
    
    141
    +  void resetColorBlocks();
    
    138 142
     };
    
    139 143
     
    
    140 144
     
    

  • src/ftinspect/panels/singular.cpp
    ... ... @@ -276,7 +276,7 @@ SingularTab::resizeEvent(QResizeEvent* event)
    276 276
     
    
    277 277
       auto viewSize = glyphView_->size();
    
    278 278
       auto minViewSide = std::min(viewSize.height(), viewSize.width());
    
    279
    -  zoomSpinBox_->setValue(static_cast<int>(minViewSide / size * 0.9));
    
    279
    +  zoomSpinBox_->setValue(static_cast<int>(minViewSide / size * 0.7));
    
    280 280
     }
    
    281 281
     
    
    282 282
     
    


  • reply via email to

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