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 SFNT


From: Charlie Jiang (@cqjjjzr)
Subject: [Git][freetype/freetype-demos][gsoc-2022-chariri-3] [ftinspect] Add SFNT Tables to Font Info tab.
Date: Thu, 18 Aug 2022 16:52:52 +0000

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

Commits:

  • 1afa70cb
    by Charlie Jiang at 2022-08-19T00:52:36+08:00
    [ftinspect] Add SFNT Tables to Font Info tab.
    
    The SFNT Tables read *all tables from the file*, so we can know which faces
    are sharing one table. This implemented by reading the file directly and
    parse the SFNT headers without FreeType.
    
    WIP: Lots of check and sanitizing aren't done.
    
    * src/ftinspect/engine/fontinfo.cpp, src/ftinspect/engine/fontinfo.hpp:
      Add `SFNTTableInfo`.
    
    * src/ftinspect/models/fontinfomodels.cpp,
      src/ftinspect/models/fontinfomodels.pp:
      Add `SFNTTableInfoModel`, tackle tag endianness issue.
    
    * src/ftinspect/panels/info.cpp, src/ftinspect/panels/info.hpp:
      Integrate `SFNTTableInfoModel`.
    
    * src/ftinspect/engine/engine.cpp, src/ftinspect/engine/engine.hpp:
      Add `curSFNTTablesValid_` and `curSFNTTables_`. Retrieve the SFNT table
      info lazily and add getters.
    

8 changed files:

Changes:

  • src/ftinspect/engine/engine.cpp
    ... ... @@ -282,6 +282,7 @@ Engine::loadFont(int fontIndex,
    282 282
       fontType_ = FontType_Other;
    
    283 283
     
    
    284 284
       update();
    
    285
    +  curSFNTTablesValid_ = false;
    
    285 286
     
    
    286 287
       curFontIndex_ = fontIndex;
    
    287 288
       auto id = FaceID(fontIndex, faceIndex, namedInstanceIndex);
    
    ... ... @@ -491,6 +492,19 @@ Engine::currentFontPSPrivateInfo(PS_PrivateRec& outInfo)
    491 492
     }
    
    492 493
     
    
    493 494
     
    
    495
    +std::vector<SFNTTableInfo>&
    
    496
    +Engine::currentFontSFNTTableInfo()
    
    497
    +{
    
    498
    +  if (!curSFNTTablesValid_)
    
    499
    +  {
    
    500
    +    SFNTTableInfo::getForAll(this, curSFNTTables_);
    
    501
    +    curSFNTTablesValid_ = true;
    
    502
    +  }
    
    503
    +
    
    504
    +  return curSFNTTables_;
    
    505
    +}
    
    506
    +
    
    507
    +
    
    494 508
     QString
    
    495 509
     Engine::glyphName(int index)
    
    496 510
     {
    

  • src/ftinspect/engine/engine.hpp
    ... ... @@ -161,6 +161,7 @@ public:
    161 161
       std::vector<SFNTName>& currentFontSFNTNames() { return curSFNTNames_; }
    
    162 162
       MMGXState currentFontMMGXState() { return curMMGXState_; }
    
    163 163
       std::vector<MMGXAxisInfo>& currentFontMMGXAxes() { return curMMGXAxes_; }
    
    164
    +  std::vector<SFNTTableInfo>& currentFontSFNTTableInfo();
    
    164 165
       FontFileManager& fontFileManager() { return fontFileManager_; }
    
    165 166
       EngineDefaultValues& engineDefaults() { return engineDefaults_; }
    
    166 167
       bool antiAliasingEnabled() { return antiAliasingEnabled_; }
    
    ... ... @@ -233,6 +234,9 @@ private:
    233 234
       std::vector<CharMapInfo> curCharMaps_;
    
    234 235
       std::vector<PaletteInfo> curPaletteInfos_;
    
    235 236
       std::vector<MMGXAxisInfo> curMMGXAxes_;
    
    237
    +
    
    238
    +  bool curSFNTTablesValid_ = false;
    
    239
    +  std::vector<SFNTTableInfo> curSFNTTables_;
    
    236 240
       MMGXState curMMGXState_ = MMGXState::NoMMGX;
    
    237 241
     
    
    238 242
       FT_Library library_;
    

  • src/ftinspect/engine/fontinfo.cpp
    ... ... @@ -6,7 +6,9 @@
    6 6
     
    
    7 7
     #include "engine.hpp"
    
    8 8
     
    
    9
    +#include <map>
    
    9 10
     #include <unordered_map>
    
    11
    +#include <memory>
    
    10 12
     #include <utility>
    
    11 13
     #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
    
    12 14
     #include <QTextCodec>
    
    ... ... @@ -17,11 +19,18 @@
    17 19
     #include <freetype/ftmodapi.h>
    
    18 20
     #include <freetype/ttnameid.h>
    
    19 21
     #include <freetype/tttables.h>
    
    22
    +#include <freetype/tttags.h>
    
    23
    +
    
    24
    +#ifdef _MSC_VER // To use intrin
    
    25
    +#define WIN32_LEAN_AND_MEAN
    
    26
    +#include <Windows.h>
    
    27
    +#include <intrin.h>
    
    28
    +#endif
    
    20 29
     
    
    21 30
     
    
    22 31
     void
    
    23 32
     SFNTName::get(Engine* engine,
    
    24
    -  std::vector<SFNTName>& list)
    
    33
    +              std::vector<SFNTName>& list)
    
    25 34
     {
    
    26 35
       auto size = engine->currentFtSize();
    
    27 36
       if (!size || !FT_IS_SFNT(size->face))
    
    ... ... @@ -369,4 +378,202 @@ FontFixedSize::get(Engine* engine,
    369 378
     }
    
    370 379
     
    
    371 380
     
    
    381
    +struct TTCHeaderRec
    
    382
    +{
    
    383
    +  uint32_t ttcTag;
    
    384
    +  uint16_t majorVersion;
    
    385
    +  uint16_t minorVersion;
    
    386
    +  uint32_t numFonts;
    
    387
    +};
    
    388
    +
    
    389
    +
    
    390
    +struct SFNTHeaderRec
    
    391
    +{
    
    392
    +  uint32_t formatTag;
    
    393
    +  uint16_t numTables;
    
    394
    +  // There'll be some padding, but it doesn't matter.
    
    395
    +};
    
    396
    +
    
    397
    +
    
    398
    +struct TTTableRec
    
    399
    +{
    
    400
    +  uint32_t tag;
    
    401
    +  uint32_t checksum;
    
    402
    +  uint32_t offset;
    
    403
    +  uint32_t length;
    
    404
    +};
    
    405
    +
    
    406
    +
    
    407
    +uint32_t
    
    408
    +bigEndianToNative(uint32_t n)
    
    409
    +{
    
    410
    +#ifdef _MSC_VER
    
    411
    +  #if REG_DWORD == REG_DWORD_LITTLE_ENDIAN
    
    412
    +    return _byteswap_ulong(n);
    
    413
    +  #else
    
    414
    +    return n;
    
    415
    +  #endif
    
    416
    +#else
    
    417
    +  auto np = reinterpret_cast<unsigned char*>(&n);
    
    418
    +
    
    419
    +  return (static_cast<uint32_t>(np[0]) << 24)
    
    420
    +         | (static_cast<uint32_t>(np[1]) << 16)
    
    421
    +         | (static_cast<uint32_t>(np[2]) << 8)
    
    422
    +         | (static_cast<uint32_t>(np[3]));
    
    423
    +#endif
    
    424
    +}
    
    425
    +
    
    426
    +
    
    427
    +uint16_t
    
    428
    +bigEndianToNative(uint16_t n)
    
    429
    +{
    
    430
    +#ifdef _MSC_VER
    
    431
    +#if REG_DWORD == REG_DWORD_LITTLE_ENDIAN
    
    432
    +  return _byteswap_ushort(n);
    
    433
    +#else
    
    434
    +  return n;
    
    435
    +#endif
    
    436
    +#else
    
    437
    +  auto np = reinterpret_cast<unsigned char*>(&n);
    
    438
    +
    
    439
    +  return static_cast<uint16_t>((static_cast<uint16_t>(np[0]) << 8)
    
    440
    +                               | (static_cast<uint16_t>(np[1])));
    
    441
    +#endif
    
    442
    +}
    
    443
    +
    
    444
    +
    
    445
    +void readSingleFace(QFile& file,
    
    446
    +                    uint32_t offset,
    
    447
    +                    unsigned faceIndex,
    
    448
    +                    std::vector<TTTableRec>& tempTables,
    
    449
    +                    std::map<unsigned long, SFNTTableInfo>& result)
    
    450
    +{
    
    451
    +  if (!file.seek(offset))
    
    452
    +    return;
    
    453
    +
    
    454
    +  SFNTHeaderRec sfntHeader = {};
    
    455
    +  if (file.read(reinterpret_cast<char*>(&sfntHeader), 
    
    456
    +                sizeof(SFNTHeaderRec))
    
    457
    +      != sizeof(SFNTHeaderRec))
    
    458
    +    return;
    
    459
    +  sfntHeader.formatTag = bigEndianToNative(sfntHeader.formatTag);
    
    460
    +  sfntHeader.numTables = bigEndianToNative(sfntHeader.numTables);
    
    461
    +
    
    462
    +  unsigned short validEntries = sfntHeader.numTables;
    
    463
    +  
    
    464
    +  if (sfntHeader.formatTag != TTAG_OTTO)
    
    465
    +  {
    
    466
    +    // TODO check SFNT Header
    
    467
    +    //checkSFNTHeader();
    
    468
    +  }
    
    469
    +
    
    470
    +  if (!file.seek(offset + 12))
    
    471
    +    return;
    
    472
    +
    
    473
    +  tempTables.resize(validEntries);
    
    474
    +  auto desiredLen = static_cast<long long>(validEntries * sizeof(TTTableRec));
    
    475
    +  auto readLen = file.read(reinterpret_cast<char*>(tempTables.data()), desiredLen);
    
    476
    +  if (readLen != desiredLen)
    
    477
    +    return;
    
    478
    +
    
    479
    +  for (auto& t : tempTables)
    
    480
    +  {
    
    481
    +    t.tag = bigEndianToNative(t.tag);
    
    482
    +    t.offset = bigEndianToNative(t.offset);
    
    483
    +    t.checksum = bigEndianToNative(t.checksum);
    
    484
    +    t.length = bigEndianToNative(t.length);
    
    485
    +
    
    486
    +    auto it = result.find(t.offset);
    
    487
    +    if (it == result.end())
    
    488
    +    {
    
    489
    +      auto emplaced = result.emplace(t.offset, SFNTTableInfo());
    
    490
    +      it = emplaced.first;
    
    491
    +
    
    492
    +      auto& info = it->second;
    
    493
    +      info.tag = t.tag;
    
    494
    +      info.length = t.length;
    
    495
    +      info.offset = t.offset;
    
    496
    +      info.sharedFaces.emplace(faceIndex);
    
    497
    +      info.valid = true;
    
    498
    +    }
    
    499
    +    else
    
    500
    +    {
    
    501
    +      it->second.sharedFaces.emplace(faceIndex);
    
    502
    +      // TODO check
    
    503
    +    }
    
    504
    +  }
    
    505
    +}
    
    506
    +
    
    507
    +
    
    508
    +void
    
    509
    +SFNTTableInfo::getForAll(Engine* engine,
    
    510
    +                         std::vector<SFNTTableInfo>& infos)
    
    511
    +{
    
    512
    +  infos.clear();
    
    513
    +  auto size = engine->currentFtSize();
    
    514
    +  if (!size || !FT_IS_SFNT(size->face))
    
    515
    +    return;
    
    516
    +
    
    517
    +  auto index = engine->currentFontIndex();
    
    518
    +  auto& mgr = engine->fontFileManager();
    
    519
    +  if (index < 0 || index >= mgr.size())
    
    520
    +    return;
    
    521
    +
    
    522
    +  auto& fileInfo = mgr[index];
    
    523
    +  QFile file(fileInfo.filePath());
    
    524
    +  if (!file.open(QIODevice::ReadOnly))
    
    525
    +    return;
    
    526
    +
    
    527
    +  auto fileSize = file.size();
    
    528
    +  if (fileSize < 12)
    
    529
    +    return;
    
    530
    +
    
    531
    +  std::vector<TTTableRec> tables;
    
    532
    +  std::map<unsigned long, SFNTTableInfo> result;
    
    533
    +
    
    534
    +  TTCHeaderRec ttcHeader = {};
    
    535
    +  auto readLen = file.read(reinterpret_cast<char*>(&ttcHeader),
    
    536
    +                           sizeof(TTCHeaderRec));
    
    537
    +
    
    538
    +  if (readLen != sizeof(TTCHeaderRec))
    
    539
    +    return;
    
    540
    +
    
    541
    +  ttcHeader.ttcTag = bigEndianToNative(ttcHeader.ttcTag);
    
    542
    +  ttcHeader.majorVersion = bigEndianToNative(ttcHeader.majorVersion);
    
    543
    +  ttcHeader.minorVersion = bigEndianToNative(ttcHeader.minorVersion);
    
    544
    +  ttcHeader.numFonts = bigEndianToNative(ttcHeader.numFonts);
    
    545
    +
    
    546
    +  if (ttcHeader.ttcTag == TTAG_ttcf
    
    547
    +      && (ttcHeader.majorVersion == 2 || ttcHeader.majorVersion == 1))
    
    548
    +  {
    
    549
    +    // Valid TTC file
    
    550
    +    std::unique_ptr<unsigned> offsets(new unsigned[ttcHeader.numFonts]);
    
    551
    +    auto desiredLen = static_cast<long long>(ttcHeader.numFonts
    
    552
    +                                             * sizeof(unsigned));
    
    553
    +    readLen = file.read(reinterpret_cast<char*>(offsets.get()), desiredLen);
    
    554
    +    if (readLen != desiredLen)
    
    555
    +      return;
    
    556
    +    
    
    557
    +    for (unsigned faceIndex = 0; 
    
    558
    +        faceIndex < ttcHeader.numFonts; 
    
    559
    +        faceIndex++)
    
    560
    +    {
    
    561
    +      auto offset = bigEndianToNative(offsets.get()[faceIndex]);
    
    562
    +      readSingleFace(file, offset, faceIndex, tables, result);
    
    563
    +    }
    
    564
    +  }
    
    565
    +  else
    
    566
    +  {
    
    567
    +    // Not TTC file, try single SFNT
    
    568
    +    if (!file.seek(0))
    
    569
    +      return;
    
    570
    +    readSingleFace(file, 0, 0, tables, result);
    
    571
    +  }
    
    572
    +
    
    573
    +  infos.reserve(result.size());
    
    574
    +  for (auto& pr : result)
    
    575
    +    infos.emplace_back(std::move(pr.second));
    
    576
    +}
    
    577
    +
    
    578
    +
    
    372 579
     // end of fontinfo.cpp

  • src/ftinspect/engine/fontinfo.hpp
    ... ... @@ -4,6 +4,7 @@
    4 4
     
    
    5 5
     #pragma once
    
    6 6
     
    
    7
    +#include <set>
    
    7 8
     #include <QDateTime>
    
    8 9
     #include <QByteArray>
    
    9 10
     #include <QString>
    
    ... ... @@ -13,6 +14,38 @@
    13 14
     
    
    14 15
     class Engine;
    
    15 16
     
    
    17
    +struct SFNTTableInfo
    
    18
    +{
    
    19
    +  unsigned long tag = 0;
    
    20
    +  unsigned long offset = 0;
    
    21
    +  unsigned long length = 0;
    
    22
    +  bool valid = false;
    
    23
    +  std::set<unsigned long> sharedFaces;
    
    24
    +
    
    25
    +  static void getForAll(Engine* engine, std::vector<SFNTTableInfo>& infos);
    
    26
    +
    
    27
    +
    
    28
    +  friend bool
    
    29
    +  operator==(const SFNTTableInfo& lhs,
    
    30
    +             const SFNTTableInfo& rhs)
    
    31
    +  {
    
    32
    +    return lhs.tag == rhs.tag
    
    33
    +      && lhs.offset == rhs.offset
    
    34
    +      && lhs.length == rhs.length
    
    35
    +      && lhs.valid == rhs.valid
    
    36
    +      && lhs.sharedFaces == rhs.sharedFaces;
    
    37
    +  }
    
    38
    +
    
    39
    +
    
    40
    +  friend bool
    
    41
    +  operator!=(const SFNTTableInfo& lhs,
    
    42
    +             const SFNTTableInfo& rhs)
    
    43
    +  {
    
    44
    +    return !(lhs == rhs);
    
    45
    +  }
    
    46
    +};
    
    47
    +
    
    48
    +
    
    16 49
     struct SFNTName
    
    17 50
     {
    
    18 51
       unsigned short nameID;
    

  • src/ftinspect/models/fontinfomodels.cpp
    ... ... @@ -270,6 +270,113 @@ SFNTNameModel::headerData(int section,
    270 270
     }
    
    271 271
     
    
    272 272
     
    
    273
    +QString
    
    274
    +tagToString(unsigned long tag)
    
    275
    +{
    
    276
    +  QString str(4, '0');
    
    277
    +  str[0] = static_cast<char>(tag >> 24);
    
    278
    +  str[1] = static_cast<char>(tag >> 16);
    
    279
    +  str[2] = static_cast<char>(tag >> 8);
    
    280
    +  str[3] = static_cast<char>(tag);
    
    281
    +  return str;
    
    282
    +}
    
    283
    +
    
    284
    +
    
    285
    +int
    
    286
    +SFNTTableInfoModel::rowCount(const QModelIndex& parent) const
    
    287
    +{
    
    288
    +  if (parent.isValid())
    
    289
    +    return 0;
    
    290
    +  return static_cast<int>(storage_.size());
    
    291
    +}
    
    292
    +
    
    293
    +
    
    294
    +int
    
    295
    +SFNTTableInfoModel::columnCount(const QModelIndex& parent) const
    
    296
    +{
    
    297
    +  if (parent.isValid())
    
    298
    +    return 0;
    
    299
    +  return STIM_Max;
    
    300
    +}
    
    301
    +
    
    302
    +
    
    303
    +QVariant
    
    304
    +SFNTTableInfoModel::data(const QModelIndex& index,
    
    305
    +                         int role) const
    
    306
    +{
    
    307
    +  if (index.row() < 0 || index.column() < 0)
    
    308
    +    return {};
    
    309
    +  auto r = static_cast<size_t>(index.row());
    
    310
    +  if (role != Qt::DisplayRole || r > storage_.size())
    
    311
    +    return {};
    
    312
    +
    
    313
    +  auto& obj = storage_[r];
    
    314
    +  switch (static_cast<Columns>(index.column()))
    
    315
    +  {
    
    316
    +  case STIM_Tag:
    
    317
    +    return tagToString(obj.tag);
    
    318
    +  case STIM_Offset:
    
    319
    +    return static_cast<unsigned long long>(obj.offset);
    
    320
    +  case STIM_Length:
    
    321
    +    return static_cast<unsigned long long>(obj.length);
    
    322
    +  case STIM_Valid:
    
    323
    +    return obj.valid;
    
    324
    +  case STIM_SharedFaces:
    
    325
    +    if (obj.sharedFaces.empty())
    
    326
    +      return "[]";
    
    327
    +  {
    
    328
    +    auto result = QString('[') + QString::number(*obj.sharedFaces.begin());
    
    329
    +    for (auto it = std::next(obj.sharedFaces.begin());
    
    330
    +         it != obj.sharedFaces.end();
    
    331
    +         ++it)
    
    332
    +    {
    
    333
    +      auto xStr = QString::number(*it);
    
    334
    +      result.reserve(result.length() + xStr.length() + 2);
    
    335
    +      result += ", ";
    
    336
    +      result += xStr;
    
    337
    +    }
    
    338
    +    result += ']';
    
    339
    +    return result;
    
    340
    +  }
    
    341
    +  default:
    
    342
    +    break;
    
    343
    +  }
    
    344
    +
    
    345
    +  return {};
    
    346
    +}
    
    347
    +
    
    348
    +
    
    349
    +QVariant
    
    350
    +SFNTTableInfoModel::headerData(int section,
    
    351
    +                               Qt::Orientation orientation,
    
    352
    +                               int role) const
    
    353
    +{
    
    354
    +  if (role != Qt::DisplayRole)
    
    355
    +    return {};
    
    356
    +  if (orientation == Qt::Vertical)
    
    357
    +    return section;
    
    358
    +  if (orientation != Qt::Horizontal)
    
    359
    +    return {};
    
    360
    +
    
    361
    +  switch (static_cast<Columns>(section))
    
    362
    +  {
    
    363
    +  case STIM_Tag:
    
    364
    +    return "Tag";
    
    365
    +  case STIM_Offset:
    
    366
    +    return "Offset";
    
    367
    +  case STIM_Length:
    
    368
    +    return "Length";
    
    369
    +  case STIM_Valid:
    
    370
    +    return "Valid";
    
    371
    +  case STIM_SharedFaces:
    
    372
    +    return "Subfont Indices";
    
    373
    +  default:;
    
    374
    +  }
    
    375
    +
    
    376
    +  return {};
    
    377
    +}
    
    378
    +
    
    379
    +
    
    273 380
     int
    
    274 381
     MMGXAxisInfoModel::rowCount(const QModelIndex& parent) const
    
    275 382
     {
    
    ... ... @@ -302,11 +409,7 @@ MMGXAxisInfoModel::data(const QModelIndex& index,
    302 409
       switch (static_cast<Columns>(index.column()))
    
    303 410
       {
    
    304 411
       case MAIM_Tag:
    
    305
    -  {
    
    306
    -    auto str = QString::fromUtf8(reinterpret_cast<const char*>(&obj.tag), 4);
    
    307
    -    std::reverse(str.begin(), str.end());
    
    308
    -    return str;
    
    309
    -  }
    
    412
    +    return tagToString(obj.tag);
    
    310 413
       case MAIM_Minimum:
    
    311 414
         return obj.minimum;
    
    312 415
       case MAIM_Default:
    

  • src/ftinspect/models/fontinfomodels.hpp
    ... ... @@ -128,6 +128,43 @@ private:
    128 128
     };
    
    129 129
     
    
    130 130
     
    
    131
    +class SFNTTableInfoModel
    
    132
    +: public QAbstractTableModel
    
    133
    +{
    
    134
    +  Q_OBJECT
    
    135
    +public:
    
    136
    +  explicit SFNTTableInfoModel(QObject* parent) : QAbstractTableModel(parent) {}
    
    137
    +  ~SFNTTableInfoModel() override = default;
    
    138
    +
    
    139
    +  int rowCount(const QModelIndex& parent) const override;
    
    140
    +  int columnCount(const QModelIndex& parent) const override;
    
    141
    +  QVariant data(const QModelIndex& index,
    
    142
    +                int role) const override;
    
    143
    +  QVariant headerData(int section,
    
    144
    +                      Qt::Orientation orientation,
    
    145
    +                      int role) const override;
    
    146
    +
    
    147
    +  // Same to `FixedSizeInfoModel`
    
    148
    +  void beginModelUpdate() { beginResetModel(); }
    
    149
    +  void endModelUpdate() { endResetModel(); }
    
    150
    +  std::vector<SFNTTableInfo>& storage() { return storage_; }
    
    151
    +
    
    152
    +  enum Columns : int
    
    153
    +  {
    
    154
    +    STIM_Tag = 0,
    
    155
    +    STIM_Offset,
    
    156
    +    STIM_Length,
    
    157
    +    STIM_Valid,
    
    158
    +    STIM_SharedFaces,
    
    159
    +    STIM_Max
    
    160
    +  };
    
    161
    +
    
    162
    +private:
    
    163
    +  // Don't let the item count exceed INT_MAX!
    
    164
    +  std::vector<SFNTTableInfo> storage_;
    
    165
    +};
    
    166
    +
    
    167
    +
    
    131 168
     class MMGXAxisInfoModel
    
    132 169
     : public QAbstractTableModel
    
    133 170
     {
    

  • src/ftinspect/panels/info.cpp
    ... ... @@ -424,6 +424,13 @@ SFNTInfoTab::reloadFont()
    424 424
         sfntNamesModel_->storage() = engine_->currentFontSFNTNames();
    
    425 425
         sfntNamesModel_->endModelUpdate();
    
    426 426
       }
    
    427
    +
    
    428
    +  if (engine_->currentFontSFNTTableInfo() != sfntTablesModel_->storage())
    
    429
    +  {
    
    430
    +    sfntTablesModel_->beginModelUpdate();
    
    431
    +    sfntTablesModel_->storage() = engine_->currentFontSFNTTableInfo();
    
    432
    +    sfntTablesModel_->endModelUpdate();
    
    433
    +  }
    
    427 434
     }
    
    428 435
     
    
    429 436
     
    
    ... ... @@ -444,10 +451,13 @@ SFNTInfoTab::createLayout()
    444 451
       header->setSectionResizeMode(QHeaderView::Fixed);
    
    445 452
       sfntNamesTable_->horizontalHeader()->setStretchLastSection(true);
    
    446 453
     
    
    454
    +  sfntTablesModel_ = new SFNTTableInfoModel(this);
    
    455
    +  sfntTablesTable_->setModel(sfntTablesModel_);
    
    447 456
       header = sfntTablesTable_->verticalHeader();
    
    448 457
       // This will force the minimal size to be used
    
    449 458
       header->setDefaultSectionSize(0);
    
    450 459
       header->setSectionResizeMode(QHeaderView::Fixed);
    
    460
    +  sfntTablesTable_->horizontalHeader()->setStretchLastSection(true);
    
    451 461
     
    
    452 462
       sfntNamesLayout_ = new QHBoxLayout;
    
    453 463
       sfntTablesLayout_ = new QHBoxLayout;
    

  • src/ftinspect/panels/info.hpp
    ... ... @@ -172,6 +172,7 @@ private:
    172 172
       QTableView* sfntTablesTable_;
    
    173 173
     
    
    174 174
       SFNTNameModel* sfntNamesModel_;
    
    175
    +  SFNTTableInfoModel* sfntTablesModel_;
    
    175 176
     
    
    176 177
       QHBoxLayout* sfntNamesLayout_;
    
    177 178
       QHBoxLayout* sfntTablesLayout_;
    


  • reply via email to

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