From 3a874f1ea6d1fcfdfb2c8d04343a38365603a55e Mon Sep 17 00:00:00 2001 From: ohyzha Date: Thu, 23 Jan 2025 13:21:02 +0200 Subject: [PATCH] reduce spacing between multiple lines --- examples/ExampleApps/TextExampleApp.cpp | 4 +- openVulkanoCpp/Scene/TextDrawable.cpp | 73 +++++++++++++++++++++++-- openVulkanoCpp/Scene/TextDrawable.hpp | 2 + 3 files changed, 74 insertions(+), 5 deletions(-) diff --git a/examples/ExampleApps/TextExampleApp.cpp b/examples/ExampleApps/TextExampleApp.cpp index 0e76db8..0558dc4 100644 --- a/examples/ExampleApps/TextExampleApp.cpp +++ b/examples/ExampleApps/TextExampleApp.cpp @@ -108,7 +108,9 @@ namespace OpenVulkano } else if (i == 1) { - t = new TextDrawable(msdfMetadataInfo, texts[j].second); + TextConfig cfg = texts[j].second; + cfg.minimalSpacingBetweenMultipleLines = false; + t = new TextDrawable(msdfMetadataInfo, cfg); } else if (i == 2) { diff --git a/openVulkanoCpp/Scene/TextDrawable.cpp b/openVulkanoCpp/Scene/TextDrawable.cpp index a140294..0181f6a 100644 --- a/openVulkanoCpp/Scene/TextDrawable.cpp +++ b/openVulkanoCpp/Scene/TextDrawable.cpp @@ -79,6 +79,55 @@ namespace OpenVulkano::Scene return m_atlasData->GetGlyphs().begin()->first; } + std::vector TextDrawable::GetHeightsBetweenLines(const std::string& text) const + { + if (!m_cfg.minimalSpacingBetweenMultipleLines) + { + return {}; + } + const std::map& symbols = m_atlasData->GetGlyphs(); + const uint32_t fallbackGlyph = GetFallbackGlyph(); + std::vector heightBetweenLines; + float currentLineHeightAboveBaseline = 0; + float currentLineHeightBelowBaseline = 0; + float prevLineHeightBelowBaseline = -INFINITY; + float extraOffset = m_atlasData->GetAtlasType().IsBitmap() ? 0.1 : 0.05; + bool isMultiline = false; + + for (auto begin = text.begin(), end = text.end(); begin != end;) + { + uint32_t c = utf8::next(begin, end); + if (c == '\n') + { + isMultiline = true; + if (prevLineHeightBelowBaseline != -INFINITY) + { + heightBetweenLines.push_back(std::abs(prevLineHeightBelowBaseline) + + std::abs(currentLineHeightAboveBaseline) + extraOffset); + prevLineHeightBelowBaseline = currentLineHeightBelowBaseline; + } + prevLineHeightBelowBaseline = currentLineHeightBelowBaseline; + currentLineHeightAboveBaseline = currentLineHeightBelowBaseline = 0; + continue; + } + + if (!symbols.contains(c)) + { + c = fallbackGlyph; + } + const GlyphInfo& info = symbols.at(c); + currentLineHeightAboveBaseline = std::max(currentLineHeightAboveBaseline, info.pos[2].y); + currentLineHeightBelowBaseline = std::min(currentLineHeightBelowBaseline, -info.pos[0].y); + } + + if (isMultiline && text.back() != '\n') + { + heightBetweenLines.push_back(std::abs(prevLineHeightBelowBaseline) + + std::abs(currentLineHeightAboveBaseline) + extraOffset); + } + return heightBetweenLines; + } + void TextDrawable::GenerateText(const std::string& text, const Math::Vector2f& pos) { if (text.empty()) return; @@ -93,16 +142,26 @@ namespace OpenVulkano::Scene const std::map& symbols = m_atlasData->GetGlyphs(); double cursorX = pos.x; - const double lineHeight = m_atlasData->GetLineHeight(); double posY = pos.y; Math::Vector2f bmin(pos), bmax(pos); float prevGlyphXBound = -INFINITY; + int currentLine = 0; + const std::vector heightsBetweenLines = GetHeightsBetweenLines(text); + for (auto begin = text.begin(), end = text.end(); begin != end;) { uint32_t c = utf8::next(begin, end); if (c == '\n') { - posY -= lineHeight; + // use fixed line height + if (heightsBetweenLines.empty()) + { + posY -= m_atlasData->GetLineHeight(); + } + else + { + posY -= heightsBetweenLines[currentLine++]; + } prevGlyphXBound = -INFINITY; cursorX = pos.x; continue; @@ -129,8 +188,14 @@ namespace OpenVulkano::Scene { vertices->position[i].x = info.pos[i].x + cursorX + offset; vertices->uv[i] = info.uv[i]; - if (i < 2) vertices->position[i].y = posY - info.pos[i].y; - else vertices->position[i].y = posY + info.pos[i].y; + if (i < 2) + { + vertices->position[i].y = posY - info.pos[i].y; + } + else + { + vertices->position[i].y = posY + info.pos[i].y; + } vertices->color = m_cfg.textColor; vertices->background = m_cfg.backgroundColor; } diff --git a/openVulkanoCpp/Scene/TextDrawable.hpp b/openVulkanoCpp/Scene/TextDrawable.hpp index a57dc18..cad19dc 100644 --- a/openVulkanoCpp/Scene/TextDrawable.hpp +++ b/openVulkanoCpp/Scene/TextDrawable.hpp @@ -21,6 +21,7 @@ namespace OpenVulkano::Scene { Math::Vector4uc textColor = { 255, 255, 255, 255 }; Math::Vector4uc backgroundColor = { 0, 255, 0, 0 }; + bool minimalSpacingBetweenMultipleLines = true; }; struct TextGlyphVertex @@ -41,6 +42,7 @@ namespace OpenVulkano::Scene TextConfig m_cfg; uint32_t GetFallbackGlyph() const; + std::vector GetHeightsBetweenLines(const std::string& text) const; public: TextDrawable(const TextConfig& config = TextConfig());