freetype-commit
[Top][All Lists]
Advanced

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

[freetype2-demos] master 0a44f99 21/41: [ftinspect] Add SFNT `name` tabl


From: Werner Lemberg
Subject: [freetype2-demos] master 0a44f99 21/41: [ftinspect] Add SFNT `name` table retrieving.
Date: Mon, 3 Oct 2022 11:27:02 -0400 (EDT)

branch: master
commit 0a44f99bf66e75311110a15c85927c6e08da4b49
Author: Charlie Jiang <w@chariri.moe>
Commit: Werner Lemberg <wl@gnu.org>

    [ftinspect] Add SFNT `name` table retrieving.
    
    * src/ftinspect/engine/fontinfo.cpp, src/ftinspect/engine/fontinfo.hpp:
      New files, add `SFNTName` to retrieve `name` table.
      Conversions to `QString` from mainstream encodings are supported.
    
    * src/ftinspect/engine/engine.cpp, src/ftinspect/engine/engine.hpp:
      Add `currentFontSFNTNames` and retrieve the `name` table when loading the
      font. Also pass the SFNT name table when loading palettes.
    
    * src/ftinspect/engine/mmgx.cpp, src/ftinspect/engine/paletteinfo.cpp:
      Uncomment functional code to make use of the `name` table.
    
    * src/ftinspect/CMakeLists.txt, src/ftinspect/meson.build: Updated.
---
 src/ftinspect/CMakeLists.txt         |   1 +
 src/ftinspect/engine/engine.cpp      |   8 +-
 src/ftinspect/engine/engine.hpp      |   3 +
 src/ftinspect/engine/fontinfo.cpp    | 166 +++++++++++++++++++++++++++++++++++
 src/ftinspect/engine/fontinfo.hpp    |  61 +++++++++++++
 src/ftinspect/engine/mmgx.cpp        |  20 ++---
 src/ftinspect/engine/paletteinfo.cpp |  20 ++---
 src/ftinspect/meson.build            |   1 +
 8 files changed, 258 insertions(+), 22 deletions(-)

diff --git a/src/ftinspect/CMakeLists.txt b/src/ftinspect/CMakeLists.txt
index bbb9112..19c9591 100644
--- a/src/ftinspect/CMakeLists.txt
+++ b/src/ftinspect/CMakeLists.txt
@@ -25,6 +25,7 @@ add_executable(ftinspect
   "engine/rendering.cpp"
   "engine/paletteinfo.cpp"
   "engine/mmgx.cpp"
+  "engine/fontinfo.cpp"
 
   "glyphcomponents/glyphbitmap.cpp"
   "glyphcomponents/glyphoutline.cpp"
diff --git a/src/ftinspect/engine/engine.cpp b/src/ftinspect/engine/engine.cpp
index 9cf30b4..459f815 100644
--- a/src/ftinspect/engine/engine.cpp
+++ b/src/ftinspect/engine/engine.cpp
@@ -328,7 +328,9 @@ Engine::loadFont(int fontIndex,
     ftSize_ = NULL;
     curFamilyName_ = QString();
     curStyleName_ = QString();
+
     curPaletteInfos_.clear();
+    curSFNTNames_.clear();
   }
   else
   {
@@ -344,6 +346,8 @@ Engine::loadFont(int fontIndex,
       fontType_ = FontType_TrueType;
     else
       fontType_ = FontType_Other;
+
+    SFNTName::get(this, curSFNTNames_);
     loadPaletteInfos();
     curMMGXState_ = MMGXAxisInfo::get(this, curMMGXAxes_);
   }
@@ -850,8 +854,8 @@ Engine::loadPaletteInfos()
   // size never exceeds max val of ushort.
   curPaletteInfos_.reserve(paletteData_.num_palettes);
   for (int i = 0; i < paletteData_.num_palettes; ++i)
-    curPaletteInfos_.emplace_back(ftFallbackFace_, paletteData_, i, nullptr);
-    // no `NULL` here - we need `std::nullptr_t`
+    curPaletteInfos_.emplace_back(ftFallbackFace_, paletteData_, i,
+                                  &curSFNTNames_);
 }
 
 
diff --git a/src/ftinspect/engine/engine.hpp b/src/ftinspect/engine/engine.hpp
index 7b264d7..cba152e 100644
--- a/src/ftinspect/engine/engine.hpp
+++ b/src/ftinspect/engine/engine.hpp
@@ -8,6 +8,7 @@
 #include "fontfilemanager.hpp"
 
 #include "paletteinfo.hpp"
+#include "fontinfo.hpp"
 #include "mmgx.hpp"
 #include "rendering.hpp"
 
@@ -122,6 +123,7 @@ public:
   FT_Palette_Data& currentFontPaletteData() { return paletteData_; }
   MMGXState currentFontMMGXState() { return curMMGXState_; }
   std::vector<MMGXAxisInfo>& currentFontMMGXAxes() { return curMMGXAxes_; }
+  std::vector<SFNTName>& currentFontSFNTNames() { return curSFNTNames_; }
 
   QString glyphName(int glyphIndex);
   long numberOfFaces(int fontIndex);
@@ -211,6 +213,7 @@ private:
   std::vector<PaletteInfo> curPaletteInfos_;
   MMGXState curMMGXState_ = MMGXState::NoMMGX;
   std::vector<MMGXAxisInfo> curMMGXAxes_;
+  std::vector<SFNTName> curSFNTNames_;
 
   // basic objects
   FT_Library library_;
diff --git a/src/ftinspect/engine/fontinfo.cpp 
b/src/ftinspect/engine/fontinfo.cpp
new file mode 100644
index 0000000..3eb5b78
--- /dev/null
+++ b/src/ftinspect/engine/fontinfo.cpp
@@ -0,0 +1,166 @@
+// fontinfo.cpp
+
+// Copyright (C) 2022 by Charlie Jiang.
+
+#include "fontinfo.hpp"
+
+#include "engine.hpp"
+
+#include <memory>
+#include <utility>
+#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
+#include <QTextCodec>
+#else
+#include <QStringConverter>
+#include <QByteArrayView>
+#endif
+#include <freetype/ftmodapi.h>
+#include <freetype/ttnameid.h>
+
+
+void
+SFNTName::get(Engine* engine,
+              std::vector<SFNTName>& list)
+{
+  auto face = engine->currentFallbackFtFace();
+  if (!face || !FT_IS_SFNT(face))
+  {
+    list.clear();
+    return;
+  }
+  
+  auto newSize = FT_Get_Sfnt_Name_Count(face);
+  if (list.size() != static_cast<size_t>(newSize))
+    list.resize(newSize);
+
+  FT_SfntName sfntName;
+  FT_SfntLangTag langTag;
+  for (unsigned int i = 0; i < newSize; ++i)
+  {
+    FT_Get_Sfnt_Name(face, i, &sfntName);
+    auto& obj = list[i];
+    obj.platformID = sfntName.platform_id;
+    obj.encodingID = sfntName.encoding_id;
+    obj.languageID = sfntName.language_id;
+    obj.nameID = sfntName.name_id;
+
+    auto len = sfntName.string_len >= INT_MAX
+                 ? INT_MAX - 1
+                 : sfntName.string_len;
+    obj.strBuf = QByteArray(reinterpret_cast<const char*>(sfntName.string), 
+                            len);
+    obj.str = sfntNameToQString(sfntName, &obj.strValid);
+
+    if (obj.languageID >= 0x8000)
+    {
+      auto err = FT_Get_Sfnt_LangTag(face, obj.languageID, &langTag);
+      if (!err)
+        obj.langTag = utf16BEToQString(reinterpret_cast<char*>(langTag.string),
+                                       langTag.string_len);
+    }
+  }
+}
+
+
+QString
+SFNTName::sfntNameToQString(FT_SfntName const& sfntName, 
+                            bool* outSuccess)
+{
+  return sfntNameToQString(sfntName.platform_id, sfntName.encoding_id,
+                           reinterpret_cast<char const*>(sfntName.string),
+                           sfntName.string_len,
+                           outSuccess);
+}
+
+
+QString
+SFNTName::sfntNameToQString(SFNTName const& sfntName, bool* outSuccess)
+{
+  return sfntNameToQString(sfntName.platformID, sfntName.encodingID,
+                           sfntName.strBuf.data(), sfntName.strBuf.size(),
+                           outSuccess);
+}
+
+
+QString
+SFNTName::sfntNameToQString(unsigned short platformID,
+                            unsigned short encodingID,
+                            char const* str,
+                            size_t size,
+                            bool* outSuccess)
+{
+  // TODO not complete.
+  if (size >= INT_MAX - 1)
+    return "";
+
+  if (outSuccess)
+    *outSuccess = true;
+
+  switch (platformID)
+  {
+  case TT_PLATFORM_APPLE_UNICODE:
+    // All UTF-16BE.
+    return utf16BEToQString(str, size);
+  case TT_PLATFORM_MACINTOSH:
+    if (encodingID == TT_MAC_ID_ROMAN)
+      return QString::fromLatin1(str, static_cast<int>(size));
+
+    if (outSuccess)
+      *outSuccess = false;
+    return "<encoding unsupported>";
+  case TT_PLATFORM_ISO:
+    switch (encodingID)
+    {
+    case TT_ISO_ID_7BIT_ASCII:
+    case TT_ISO_ID_8859_1:
+      return QString::fromLatin1(str, static_cast<int>(size));
+    case TT_ISO_ID_10646:
+      return utf16BEToQString(str, size);
+    default:
+      if (outSuccess)
+        *outSuccess = false;
+      return "<encoding unsupported>";
+    }
+  case TT_PLATFORM_MICROSOFT:
+    switch (encodingID)
+    {
+      /* TT_MS_ID_SYMBOL_CS is Unicode, similar to PID/EID=3/1 */
+    case TT_MS_ID_SYMBOL_CS:
+    case TT_MS_ID_UNICODE_CS:
+    case TT_MS_ID_UCS_4: // This is UTF-16LE as well, according to MS doc
+      return utf16BEToQString(str, size);
+
+    default:
+      if (outSuccess)
+        *outSuccess = false;
+      return "<encoding unsupported>";
+    }
+  }
+
+  if (outSuccess)
+    *outSuccess = false;
+  return "<platform unsupported>";
+}
+
+
+#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
+QTextCodec* utf16BECodec = QTextCodec::codecForName("UTF-16BE");
+#else
+QStringDecoder utf16BECvt = (QStringDecoder(QStringDecoder::Utf16BE))(size);
+#endif
+
+QString
+SFNTName::utf16BEToQString(char const* str,
+                           size_t size)
+{
+#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
+  if (size >= INT_MAX)
+    size = INT_MAX - 1;
+  return utf16BECodec->toUnicode(str, static_cast<int>(size));
+#else
+  return utf16BECvt(QByteArrayView(reinterpret_cast<char*>(str), size));
+#endif
+}
+
+
+// end of fontinfo.cpp
diff --git a/src/ftinspect/engine/fontinfo.hpp 
b/src/ftinspect/engine/fontinfo.hpp
new file mode 100644
index 0000000..c1b9ff3
--- /dev/null
+++ b/src/ftinspect/engine/fontinfo.hpp
@@ -0,0 +1,61 @@
+// fontinfo.hpp
+
+// Copyright (C) 2022 by Charlie Jiang.
+
+#pragma once
+
+#include <set>
+#include <vector>
+#include <QByteArray>
+#include <QString>
+#include <freetype/freetype.h>
+#include <freetype/ftsnames.h>
+
+class Engine;
+struct SFNTName
+{
+  unsigned short nameID;
+  unsigned short platformID;
+  unsigned short encodingID;
+  unsigned short languageID;
+  QByteArray strBuf;
+  QString str;
+  QString langTag;
+  bool strValid = false;
+
+  static void get(Engine* engine,
+                  std::vector<SFNTName>& list);
+  static QString sfntNameToQString(FT_SfntName const& sfntName,
+                                   bool* outSuccess = NULL);
+  static QString sfntNameToQString(SFNTName const& sfntName,
+                                   bool* outSuccess = NULL);
+  static QString sfntNameToQString(unsigned short platformID,
+                                   unsigned short encodingID, 
+                                   char const* str, size_t size,
+                                   bool* outSuccess = NULL);
+  static QString utf16BEToQString(char const* str, size_t size);
+
+
+  friend bool
+  operator==(const SFNTName& lhs,
+             const SFNTName& rhs)
+  {
+    return lhs.nameID == rhs.nameID
+      && lhs.platformID == rhs.platformID
+      && lhs.encodingID == rhs.encodingID
+      && lhs.languageID == rhs.languageID
+      && lhs.strBuf == rhs.strBuf
+      && lhs.langTag == rhs.langTag;
+  }
+
+
+  friend bool
+  operator!=(const SFNTName& lhs,
+             const SFNTName& rhs)
+  {
+    return !(lhs == rhs);
+  }
+};
+
+
+// end of fontinfo.hpp
diff --git a/src/ftinspect/engine/mmgx.cpp b/src/ftinspect/engine/mmgx.cpp
index b978272..570d55f 100644
--- a/src/ftinspect/engine/mmgx.cpp
+++ b/src/ftinspect/engine/mmgx.cpp
@@ -39,7 +39,7 @@ MMGXAxisInfo::get(Engine* engine,
 
   infos.resize(mm->num_axis);
 
-  //auto& sfnt = engine->currentFontSFNTNames();
+  auto& sfnt = engine->currentFontSFNTNames();
   for (unsigned int i = 0; i < mm->num_axis; ++i)
   {
     auto& axis = mm->axis[i];
@@ -58,15 +58,15 @@ MMGXAxisInfo::get(Engine* engine,
     if (state == MMGXState::GX_OVF)
     {
       auto strid = mm->axis[i].strid;
-      //for (auto& obj : sfnt)
-      //{
-      //  if (obj.nameID == strid && obj.strValid)
-      //  {
-      //    info.name = obj.str;
-      //    nameSet = true;
-      //    break;
-      //  }
-      //}
+      for (auto& obj : sfnt)
+      {
+        if (obj.nameID == strid && obj.strValid)
+        {
+          info.name = obj.str;
+          nameSet = true;
+          break;
+        }
+      }
     }
 
     // XXX security flaw
diff --git a/src/ftinspect/engine/paletteinfo.cpp 
b/src/ftinspect/engine/paletteinfo.cpp
index 7abd2ae..302f3f7 100644
--- a/src/ftinspect/engine/paletteinfo.cpp
+++ b/src/ftinspect/engine/paletteinfo.cpp
@@ -4,7 +4,7 @@
 
 #include "paletteinfo.hpp"
 
-//#include "fontinfo.hpp"
+#include "fontinfo.hpp"
 
 PaletteInfo::PaletteInfo(FT_Face face, 
                          FT_Palette_Data& data, 
@@ -15,15 +15,15 @@ PaletteInfo::PaletteInfo(FT_Face face,
   if (sfntNames && data.palette_name_ids)
   {
     auto id = data.palette_name_ids[index];
-    name = "(unsupported)";
-    //for (auto& obj : *sfntNames)
-    //{
-    //  if (obj.nameID == id && obj.strValid)
-    //  {
-    //    name = obj.str;
-    //    break;
-    //  }
-    //}
+    name = "(invalid)";
+    for (auto& obj : *sfntNames)
+    {
+      if (obj.nameID == id && obj.strValid)
+      {
+        name = obj.str;
+        break;
+      }
+    }
   }
   else
     name = "(unnamed)";
diff --git a/src/ftinspect/meson.build b/src/ftinspect/meson.build
index 71450ab..405cff8 100644
--- a/src/ftinspect/meson.build
+++ b/src/ftinspect/meson.build
@@ -26,6 +26,7 @@ if qt5_dep.found()
     'engine/rendering.cpp',
     'engine/paletteinfo.cpp',
     'engine/mmgx.cpp',
+    'engine/fontinfo.cpp',
 
     'glyphcomponents/glyphbitmap.cpp',
     'glyphcomponents/glyphoutline.cpp',



reply via email to

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