From fdea7ce0ba89ec57290248ea37bdb16cd57f417d Mon Sep 17 00:00:00 2001 From: Georg Hagen Date: Sun, 2 Mar 2025 19:25:41 +0100 Subject: [PATCH] More font rendering cleanup --- .../Scene/Text/BitmapFontAtlasGenerator.cpp | 7 +--- .../Scene/Text/BitmapFontAtlasGenerator.hpp | 22 ++++++---- .../Scene/Text/FontAtlasGeneratorBase.cpp | 5 +++ .../Scene/Text/FontAtlasGeneratorBase.hpp | 6 +++ .../Scene/Text/IFontAtlasGenerator.hpp | 14 ++++--- .../Scene/Text/SdfFontAtlasGenerator.cpp | 42 ++++--------------- .../Scene/Text/SdfFontAtlasGenerator.hpp | 23 +++++----- 7 files changed, 52 insertions(+), 67 deletions(-) diff --git a/openVulkanoCpp/Scene/Text/BitmapFontAtlasGenerator.cpp b/openVulkanoCpp/Scene/Text/BitmapFontAtlasGenerator.cpp index ed78093..94842aa 100644 --- a/openVulkanoCpp/Scene/Text/BitmapFontAtlasGenerator.cpp +++ b/openVulkanoCpp/Scene/Text/BitmapFontAtlasGenerator.cpp @@ -11,11 +11,6 @@ namespace OpenVulkano::Scene { - void BitmapFontAtlasGenerator::GenerateAtlas(const std::string& fontFile, const std::set& charset) - { - GenerateAtlas(Utils::ReadFile(fontFile), charset); - } - void BitmapFontAtlasGenerator::GenerateAtlas(const Array& fontData, const std::set& charset) { Generate(fontData.AsBytes(), charset); @@ -88,7 +83,7 @@ namespace OpenVulkano::Scene // 2) render glyph in FillGlyphsInfo with FT_LOAD_RENDER | FT_LOAD_TARGET_LCD mode; // 3) take into account all mentioned things above for proper mapping. FT_GlyphSlot slot = face->glyph; - GlyphForPacking& glyph = allGlyphs.emplace_back(codepoint, ScaleGlyphSize(slot->bitmap.width, slot->bitmap.rows)); + allGlyphs.emplace_back(codepoint, ScaleGlyphSize(slot->bitmap.width, slot->bitmap.rows)); area += slot->bitmap.rows * slot->bitmap.width; } std::sort(allGlyphs.begin(), allGlyphs.end(), diff --git a/openVulkanoCpp/Scene/Text/BitmapFontAtlasGenerator.hpp b/openVulkanoCpp/Scene/Text/BitmapFontAtlasGenerator.hpp index a6030bd..f7669b5 100644 --- a/openVulkanoCpp/Scene/Text/BitmapFontAtlasGenerator.hpp +++ b/openVulkanoCpp/Scene/Text/BitmapFontAtlasGenerator.hpp @@ -15,13 +15,13 @@ namespace OpenVulkano::Scene class FontPixelSizeConfig { public: - FontPixelSizeConfig(float size = 24.f, float dpi = 72.f, bool isPixelSize = true) + FontPixelSizeConfig(const float size = 24.f, const float dpi = 72.f, const bool isPixelSize = true) : m_size(size), m_dpi(dpi), m_isPixelSize(isPixelSize) { } - void SetSize(float size) { m_size = size; } - void SetDpi(float dpi) { m_dpi = dpi; } - void SetIsPixelSize(bool isPixelSize) { m_isPixelSize = isPixelSize; } + void SetSize(const float size) { m_size = size; } + void SetDpi(const float dpi) { m_dpi = dpi; } + void SetIsPixelSize(const bool isPixelSize) { m_isPixelSize = isPixelSize; } [[nodiscard]] float GetSize() const { return m_size; } [[nodiscard]] float GetDpi() const { return m_dpi; } [[nodiscard]] bool GetIsPixelSize() const { return m_isPixelSize; } @@ -34,6 +34,9 @@ namespace OpenVulkano::Scene class BitmapFontAtlasGenerator : public FontAtlasGeneratorBase { + FontPixelSizeConfig m_pixelSizeConfig; + SubpixelLayout m_subpixelLayout; + public: BitmapFontAtlasGenerator(FontPixelSizeConfig config = FontPixelSizeConfig(), std::optional subpixelLayout = std::nullopt) @@ -42,18 +45,21 @@ namespace OpenVulkano::Scene , m_subpixelLayout(subpixelLayout.value_or(SubpixelLayout::UNKNOWN)) { } - [[deprecated]] void GenerateAtlas(const std::string& fontFile, const std::set& charset) override; + void GenerateAtlas(const Array& fontData, const std::set& charset) override; + private: void Generate(const std::span& fontData, const std::set& chset); + void FillGlyphsInfo(const std::vector& allGlyphs, const FtFaceRecPtr& face, double scaleFactor); + void FillSubpixelData(const FT_Bitmap& bitmap, const GlyphForPacking& glyph); + FT_Int32 GetGlyphRenderMode() const; + // tmp function Math::Vector2ui ScaleGlyphSize(unsigned int w, unsigned int h) const; + std::pair, double> InitGlyphsForPacking(const std::set& chset, const FtFaceRecPtr& face); - private: - FontPixelSizeConfig m_pixelSizeConfig; - SubpixelLayout m_subpixelLayout; }; } diff --git a/openVulkanoCpp/Scene/Text/FontAtlasGeneratorBase.cpp b/openVulkanoCpp/Scene/Text/FontAtlasGeneratorBase.cpp index 669965d..59cc09d 100644 --- a/openVulkanoCpp/Scene/Text/FontAtlasGeneratorBase.cpp +++ b/openVulkanoCpp/Scene/Text/FontAtlasGeneratorBase.cpp @@ -11,6 +11,11 @@ namespace OpenVulkano::Scene { + void IFontAtlasGenerator::GenerateAtlas(const std::filesystem::path& fontFile, const std::set& charset) + { + GenerateAtlas(Utils::ReadFile(fontFile), charset); + } + std::pair FontAtlasGeneratorBase::InitFreetype(const std::span& data) { diff --git a/openVulkanoCpp/Scene/Text/FontAtlasGeneratorBase.hpp b/openVulkanoCpp/Scene/Text/FontAtlasGeneratorBase.hpp index 8165b37..cf4489e 100644 --- a/openVulkanoCpp/Scene/Text/FontAtlasGeneratorBase.hpp +++ b/openVulkanoCpp/Scene/Text/FontAtlasGeneratorBase.hpp @@ -22,14 +22,20 @@ namespace OpenVulkano::Scene public: FontAtlasGeneratorBase(const int channelsCount) : m_channelsCount(channelsCount) {} + [[nodiscard]] const std::shared_ptr& GetAtlas() const final { return m_atlasData; } + [[nodiscard]] int GetAtlasChannelsCount() const { return m_channelsCount; } + static size_t LoadAllGlyphs(std::set& chars, const std::span& fontData) { auto [lib, face] = InitFreetype(fontData); return LoadAllGlyphs(chars, face); } + static size_t LoadAllGlyphs(std::set& chars, const FtFaceRecPtr& face); protected: void SetGlyphData(GlyphInfo& info, Math::Vector2d bearing, Math::Vector2d size, const Math::AABB& aabb, double advance); + [[nodiscard]] static std::string GetFreetypeErrorDescription(FT_Error error); + [[nodiscard]] static std::pair InitFreetype(const std::span& data); }; } \ No newline at end of file diff --git a/openVulkanoCpp/Scene/Text/IFontAtlasGenerator.hpp b/openVulkanoCpp/Scene/Text/IFontAtlasGenerator.hpp index 4b5544e..d997a7a 100644 --- a/openVulkanoCpp/Scene/Text/IFontAtlasGenerator.hpp +++ b/openVulkanoCpp/Scene/Text/IFontAtlasGenerator.hpp @@ -6,11 +6,10 @@ #pragma once -#include -#include -#include +#include "Base/Wrapper.hpp" +#include "Data/Containers/Array.hpp" +#include #include -#include namespace OpenVulkano::Scene { @@ -20,8 +19,11 @@ namespace OpenVulkano::Scene { public: virtual ~IFontAtlasGenerator() = default; - [[deprecated]] virtual void GenerateAtlas(const std::string& fontFile, const std::set& charset) = 0; + + void GenerateAtlas(const std::filesystem::path& fontFile, const std::set& charset); + virtual void GenerateAtlas(const Array& fontData, const std::set& charset) = 0; - virtual const std::shared_ptr& GetAtlas() const = 0; + + virtual const Ptr& GetAtlas() const = 0; }; } diff --git a/openVulkanoCpp/Scene/Text/SdfFontAtlasGenerator.cpp b/openVulkanoCpp/Scene/Text/SdfFontAtlasGenerator.cpp index 0d81ba2..de76dd2 100644 --- a/openVulkanoCpp/Scene/Text/SdfFontAtlasGenerator.cpp +++ b/openVulkanoCpp/Scene/Text/SdfFontAtlasGenerator.cpp @@ -17,12 +17,6 @@ namespace OpenVulkano::Scene SdfFontAtlasGeneratorConfig SdfFontAtlasGeneratorConfig::sdfDefaultConfig = { 42, 1.0, 5 }; SdfFontAtlasGeneratorConfig SdfFontAtlasGeneratorConfig::msdfDefaultConfig = { 32, 1.0, 3 }; - template - void SdfFontAtlasGeneratorGeneric::GenerateAtlas(const std::string& fontFile, const std::set& inCs) - { - GenerateAtlas(Utils::ReadFile(fontFile), inCs); - } - template SdfFontAtlasGeneratorGeneric::SdfFontAtlasGeneratorGeneric() : FontAtlasGeneratorBase(Channels) { if constexpr (Channels == 1) m_config = SdfFontAtlasGeneratorConfig::sdfDefaultConfig; @@ -39,7 +33,7 @@ namespace OpenVulkano::Scene std::set fallback; if (inCs.empty()) { - FontAtlasGeneratorBase::LoadAllGlyphs(fallback, fontData.AsBytes()); + LoadAllGlyphs(fallback, fontData.AsBytes()); } const auto& charset = inCs.empty() ? fallback : inCs; std::for_each(charset.begin(), charset.end(), [&](uint32_t unicode) { s.add(unicode); }); @@ -47,43 +41,21 @@ namespace OpenVulkano::Scene } template - void SdfFontAtlasGeneratorGeneric::GenerateAtlas(const std::string& fontFile, const msdf_atlas::Charset& charset) + void SdfFontAtlasGeneratorGeneric::GenerateAtlas(const std::filesystem::path& fontFile, const msdf_atlas::Charset& charset) { - // TODO: dynamic atlas and add only those symbols which are not present yet in current atlas - msdfgen::FreetypeHandle* ft; - msdfgen::FontHandle* font; - InitFreetypeFromFile(ft, font, fontFile); - Generate(ft, font, charset); + auto data = Utils::ReadFile(fontFile); + GenerateAtlas(reinterpret_cast(data.Data()), data.Size(), charset); } template void SdfFontAtlasGeneratorGeneric::GenerateAtlas(const msdfgen::byte* fontData, int length, const msdf_atlas::Charset& charset) - { + { // TODO: dynamic atlas and add only those symbols which are not present yet in current atlas msdfgen::FreetypeHandle* ft; msdfgen::FontHandle* font; InitFreetypeFromBuffer(ft, font, fontData, length); Generate(ft, font, charset); } - template - void SdfFontAtlasGeneratorGeneric::InitFreetypeFromFile(msdfgen::FreetypeHandle*& ft, - msdfgen::FontHandle*& font, - const std::string& fontFile) - { - ft = msdfgen::initializeFreetype(); - if (!ft) - { - throw std::runtime_error("Failed to initialize freetype"); - } - font = loadFont(ft, fontFile.data()); - if (!font) - { - deinitializeFreetype(ft); - ft = nullptr; - throw std::runtime_error(fmt::format("Failed to load font from file {0}", fontFile.data())); - } - } - template void SdfFontAtlasGeneratorGeneric::InitFreetypeFromBuffer(msdfgen::FreetypeHandle*& ft, msdfgen::FontHandle*& font, @@ -113,7 +85,7 @@ namespace OpenVulkano::Scene if constexpr (Channels == 3) { - const double maxCornerAngle = 3.0; + constexpr double maxCornerAngle = 3.0; for (msdf_atlas::GlyphGeometry& glyph : glyphsGeometry) { glyph.edgeColoring(&msdfgen::edgeColoringByDistance, maxCornerAngle, 0); @@ -162,7 +134,7 @@ namespace OpenVulkano::Scene } else { - const msdfgen::BitmapConstRef& storage = generator.atlasStorage(); + const msdfgen::BitmapConstRef& storage = generator.atlasStorage(); memcpy(m_atlasData->GetTexture()->textureBuffer, storage.pixels, width * height); } diff --git a/openVulkanoCpp/Scene/Text/SdfFontAtlasGenerator.hpp b/openVulkanoCpp/Scene/Text/SdfFontAtlasGenerator.hpp index 1ed6bd2..de95d05 100644 --- a/openVulkanoCpp/Scene/Text/SdfFontAtlasGenerator.hpp +++ b/openVulkanoCpp/Scene/Text/SdfFontAtlasGenerator.hpp @@ -12,14 +12,11 @@ #include #include #include -#include -#include #include #define MSDFGEN_AVAILABLE 1 namespace OpenVulkano::Scene { - struct SdfFontAtlasGeneratorConfig { static SdfFontAtlasGeneratorConfig sdfDefaultConfig; @@ -32,32 +29,34 @@ namespace OpenVulkano::Scene template class SdfFontAtlasGeneratorGeneric final : public FontAtlasGeneratorBase { - private: using SdfGenerator = msdf_atlas::ImmediateAtlasGenerator>; using MsdfGenerator = msdf_atlas::ImmediateAtlasGenerator>; + public: - using Generator = std::conditional::type; + using Generator = typename std::conditional::type; using Config = SdfFontAtlasGeneratorConfig; + static constexpr int channelsCount = (Channels == 1 ? 1 : 4); + SdfFontAtlasGeneratorGeneric(); - [[deprecated]] void GenerateAtlas(const std::string& fontFile, const std::set& charset) override; + void GenerateAtlas(const Array& fontData, const std::set& charset) override; - [[deprecated]] void GenerateAtlas(const std::string& fontFile, - const msdf_atlas::Charset& charset = msdf_atlas::Charset::ASCII); - void GenerateAtlas(const msdfgen::byte* fontData, int length, - const msdf_atlas::Charset& charset = msdf_atlas::Charset::ASCII); + + void GenerateAtlas(const std::filesystem::path& fontFile, const msdf_atlas::Charset& charset = msdf_atlas::Charset::ASCII); + void GenerateAtlas(const msdfgen::byte* fontData, int length, const msdf_atlas::Charset& charset = msdf_atlas::Charset::ASCII); + void SetGeneratorConfig(const Config& config) { m_config = config; } Config& GetGeneratorConfig() { return m_config; } private: - void InitFreetypeFromFile(msdfgen::FreetypeHandle*& ft, msdfgen::FontHandle*& font, const std::string& file); void InitFreetypeFromBuffer(msdfgen::FreetypeHandle*& ft, msdfgen::FontHandle*& font, const msdfgen::byte* fontData, int length); void Generate(msdfgen::FreetypeHandle* ft, msdfgen::FontHandle* font, const msdf_atlas::Charset& chset); - private: + Config m_config; }; + using SdfFontAtlasGenerator = SdfFontAtlasGeneratorGeneric<1>; using MsdfFontAtlasGenerator = SdfFontAtlasGeneratorGeneric<3>; }