From d31497c850f8db690ffe9ba53c508198b838224d Mon Sep 17 00:00:00 2001 From: Dan Paulat Date: Fri, 13 Aug 2021 22:10:20 -0500 Subject: [PATCH] Parse font family and subfamily --- scwx-qt/source/scwx/qt/util/font.cpp | 98 ++++++++++++++++++++++++++-- 1 file changed, 94 insertions(+), 4 deletions(-) diff --git a/scwx-qt/source/scwx/qt/util/font.cpp b/scwx-qt/source/scwx/qt/util/font.cpp index ac32106c..08134697 100644 --- a/scwx-qt/source/scwx/qt/util/font.cpp +++ b/scwx-qt/source/scwx/qt/util/font.cpp @@ -1,10 +1,20 @@ +// No suitable standard C++ replacement +#define _SILENCE_CXX17_CODECVT_HEADER_DEPRECATION_WARNING + #include +#include #include #include #include #include +#include + +#include +#include FT_FREETYPE_H +#include FT_SFNT_NAMES_H +#include FT_TRUETYPE_IDS_H // #include (exclude opengl.h) #include @@ -14,6 +24,12 @@ #include #include +#ifdef WIN32 +# include +#else +# include +#endif + namespace scwx { namespace qt @@ -67,6 +83,8 @@ static constexpr float POINT_SCALE = 1.0f / BASE_POINT_SIZE; static std::unordered_map> fontMap_; +static void ParseSfntName(const FT_SfntName& sfntName, std::string& str); + class FontImpl { public: @@ -83,8 +101,16 @@ public: } } + void ParseNames(FT_Face face); + const std::string resource_; + struct + { + std::string fontFamily_; + std::string fontSubfamily_; + } fontData_; + ftgl::texture_atlas_t* atlas_; std::unordered_map glyphs_; }; @@ -216,6 +242,8 @@ GLuint Font::GenerateTexture(gl::OpenGLFunctions& gl) std::shared_ptr Font::Create(const std::string& resource) { + BOOST_LOG_TRIVIAL(debug) << logPrefix_ << "Loading font file: " << resource; + std::shared_ptr font = nullptr; boost::timer::cpu_timer timer; @@ -229,8 +257,7 @@ std::shared_ptr Font::Create(const std::string& resource) fontFile.open(QIODevice::ReadOnly); if (!fontFile.isOpen()) { - BOOST_LOG_TRIVIAL(error) - << logPrefix_ << "Could not read font file: " << resource; + BOOST_LOG_TRIVIAL(error) << logPrefix_ << "Could not read font file"; return font; } @@ -241,6 +268,8 @@ std::shared_ptr Font::Create(const std::string& resource) ftgl::texture_font_t* textureFont = ftgl::texture_font_new_from_memory( font->p->atlas_, BASE_POINT_SIZE, fontData.constData(), fontData.size()); + font->p->ParseNames(textureFont->face); + textureFont->rendermode = ftgl::RENDER_SIGNED_DISTANCE_FIELD; timer.start(); @@ -268,8 +297,8 @@ std::shared_ptr Font::Create(const std::string& resource) } } - BOOST_LOG_TRIVIAL(debug) << logPrefix_ << "Font \"" << resource - << "\" loaded in " << timer.format(6, "%ws"); + BOOST_LOG_TRIVIAL(debug) + << logPrefix_ << "Font loaded in " << timer.format(6, "%ws"); texture_font_delete(textureFont); @@ -281,6 +310,67 @@ std::shared_ptr Font::Create(const std::string& resource) return font; } +void FontImpl::ParseNames(FT_Face face) +{ + FT_SfntName sfntName; + FT_Error error; + + FT_UInt nameCount = FT_Get_Sfnt_Name_Count(face); + + for (FT_UInt i = 0; i < nameCount; i++) + { + error = FT_Get_Sfnt_Name(face, i, &sfntName); + + if (error == 0) + { + switch (sfntName.name_id) + { + case TT_NAME_ID_FONT_FAMILY: + ParseSfntName(sfntName, fontData_.fontFamily_); + break; + + case TT_NAME_ID_FONT_SUBFAMILY: + ParseSfntName(sfntName, fontData_.fontSubfamily_); + break; + } + } + } + + BOOST_LOG_TRIVIAL(debug) + << logPrefix_ << "Font family: " << fontData_.fontFamily_ << " (" + << fontData_.fontSubfamily_ << ")"; +} + +static void ParseSfntName(const FT_SfntName& sfntName, std::string& str) +{ + if (str.empty()) + { + if (sfntName.platform_id == TT_PLATFORM_MICROSOFT && + sfntName.encoding_id == TT_MS_ID_UNICODE_CS) + { + char16_t* tempString = new char16_t[sfntName.string_len / 2]; + memcpy(tempString, sfntName.string, sfntName.string_len); + + for (size_t j = 0; j < sfntName.string_len / 2; j++) + { + tempString[j] = ntohs(tempString[j]); + } + + str = + std::wstring_convert, char16_t> {} + .to_bytes(tempString, tempString + sfntName.string_len / 2); + + delete[] tempString; + } + else if (sfntName.platform_id == TT_PLATFORM_MACINTOSH && + sfntName.encoding_id == TT_MAC_ID_ROMAN) + { + str = std::string(reinterpret_cast(sfntName.string), + sfntName.string_len); + } + } +} + } // namespace util } // namespace qt } // namespace scwx