diff --git a/include/Nazara/Utility/RichTextDrawer.hpp b/include/Nazara/Utility/RichTextDrawer.hpp index c8b59ffe2..2a1709d8c 100644 --- a/include/Nazara/Utility/RichTextDrawer.hpp +++ b/include/Nazara/Utility/RichTextDrawer.hpp @@ -93,15 +93,16 @@ namespace Nz struct Block; inline void AppendNewLine(const Font* font, unsigned int characterSize) const; + void AppendNewLine(const Font* font, unsigned int characterSize, std::size_t glyphIndex, unsigned int glyphPosition) const; inline void ClearGlyphs() const; inline void ConnectFontSlots(); inline void DisconnectFontSlots(); bool GenerateGlyph(Glyph& glyph, char32_t character, float outlineThickness, bool lineWrap, const Font* font, const Color& color, TextStyleFlags style, unsigned int characterSize, int renderOrder, int* advance) const; void GenerateGlyphs(const Font* font, const Color& color, TextStyleFlags style, unsigned int characterSize, const Color& outlineColor, float outlineThickness, const String& text) const; inline std::size_t HandleFontAddition(const FontRef& font); - inline void ReleaseFont(std::size_t fontIndex); - inline void InvalidateGlyphs(); + inline void ReleaseFont(std::size_t fontIndex); + inline bool ShouldLineWrap(float size) const; void OnFontAtlasLayerChanged(const Font* font, AbstractImage* oldLayer, AbstractImage* newLayer); void OnFontInvalidated(const Font* font); @@ -109,6 +110,8 @@ namespace Nz void UpdateGlyphs() const; + static constexpr std::size_t InvalidGlyph = std::numeric_limits::max(); + struct Block { std::size_t fontIndex; @@ -136,6 +139,7 @@ namespace Nz Color m_defaultOutlineColor; TextStyleFlags m_defaultStyle; FontRef m_defaultFont; + mutable std::size_t m_lastSeparatorGlyph; std::unordered_map m_fontIndexes; std::vector m_blocks; std::vector m_fonts; @@ -148,6 +152,7 @@ namespace Nz float m_defaultOutlineThickness; float m_maxLineWidth; unsigned int m_defaultCharacterSize; + mutable unsigned int m_lastSeparatorPosition; }; class RichTextDrawer::BlockRef diff --git a/include/Nazara/Utility/RichTextDrawer.inl b/include/Nazara/Utility/RichTextDrawer.inl index d17db9ae1..e2916d475 100644 --- a/include/Nazara/Utility/RichTextDrawer.inl +++ b/include/Nazara/Utility/RichTextDrawer.inl @@ -138,22 +138,13 @@ namespace Nz inline void RichTextDrawer::AppendNewLine(const Font* font, unsigned int characterSize) const { - // Ensure we're appending from last line - Line& lastLine = m_lines.back(); - - const Font::SizeInfo& sizeInfo = font->GetSizeInfo(characterSize); - - // Reset cursor - m_drawPos.x = 0; - m_drawPos.y += sizeInfo.lineHeight; - - m_workingBounds.ExtendTo(lastLine.bounds); - m_lines.emplace_back(Line{ Rectf(0.f, float(sizeInfo.lineHeight * m_lines.size()), 0.f, float(sizeInfo.lineHeight)), m_glyphs.size() + 1 }); + AppendNewLine(font, characterSize, InvalidGlyph, 0); } inline void RichTextDrawer::ClearGlyphs() const { m_bounds.MakeZero(); + m_lastSeparatorGlyph = InvalidGlyph; m_lines.clear(); m_glyphs.clear(); m_glyphUpdated = true; @@ -223,6 +214,14 @@ namespace Nz } } + inline bool RichTextDrawer::ShouldLineWrap(float size) const + { + if (m_lines.back().glyphIndex > m_glyphs.size()) + return false; + + return m_lines.back().bounds.GetMaximum().x + size > m_maxLineWidth; + } + inline bool RichTextDrawer::HasBlocks() const { return !m_blocks.empty(); diff --git a/include/Nazara/Utility/SimpleTextDrawer.hpp b/include/Nazara/Utility/SimpleTextDrawer.hpp index 8e6fa8f4b..7533cfd23 100644 --- a/include/Nazara/Utility/SimpleTextDrawer.hpp +++ b/include/Nazara/Utility/SimpleTextDrawer.hpp @@ -72,7 +72,7 @@ namespace Nz void OnFontAtlasLayerChanged(const Font* font, AbstractImage* oldLayer, AbstractImage* newLayer); void OnFontInvalidated(const Font* font); void OnFontRelease(const Font* object); - bool ShouldLineWrap(Glyph& glyph, float size, bool checkFirstGlyph = true) const; + bool ShouldLineWrap(float size) const; void UpdateGlyphColor() const; void UpdateGlyphs() const; diff --git a/src/Nazara/Utility/RichTextDrawer.cpp b/src/Nazara/Utility/RichTextDrawer.cpp index 6e9e514cc..98c145474 100644 --- a/src/Nazara/Utility/RichTextDrawer.cpp +++ b/src/Nazara/Utility/RichTextDrawer.cpp @@ -268,6 +268,55 @@ namespace Nz return *this; } + void RichTextDrawer::AppendNewLine(const Font* font, unsigned int characterSize, std::size_t glyphIndex, unsigned int glyphPosition) const + { + // Ensure we're appending from last line + Line& lastLine = m_lines.back(); + + const Font::SizeInfo& sizeInfo = font->GetSizeInfo(characterSize); + + unsigned int previousDrawPos = m_drawPos.x; + + // Reset cursor + m_drawPos.x = 0; + m_drawPos.y += sizeInfo.lineHeight; + m_lastSeparatorGlyph = InvalidGlyph; + + m_workingBounds.ExtendTo(lastLine.bounds); + m_lines.emplace_back(Line{ Rectf(0.f, float(sizeInfo.lineHeight * m_lines.size()), 0.f, float(sizeInfo.lineHeight)), m_glyphs.size() + 1 }); + + if (glyphIndex != InvalidGlyph && glyphIndex > lastLine.glyphIndex) + { + Line& newLine = m_lines.back(); + newLine.glyphIndex = glyphIndex; + + for (std::size_t i = glyphIndex; i < m_glyphs.size(); ++i) + { + Glyph& glyph = m_glyphs[i]; + glyph.bounds.x -= glyphPosition; + glyph.bounds.y += sizeInfo.lineHeight; + + for (auto& corner : glyph.corners) + { + corner.x -= glyphPosition; + corner.y += sizeInfo.lineHeight; + } + + newLine.bounds.ExtendTo(glyph.bounds); + } + + assert(previousDrawPos >= glyphPosition); + m_drawPos.x += previousDrawPos - glyphPosition; + + lastLine.bounds.width -= lastLine.bounds.GetMaximum().x - glyphPosition; + + // Regenerate working bounds + m_workingBounds.MakeZero(); + for (std::size_t i = 0; i < m_lines.size(); ++i) + m_workingBounds.ExtendTo(m_lines[i].bounds); + } + } + bool RichTextDrawer::GenerateGlyph(Glyph& glyph, char32_t character, float outlineThickness, bool lineWrap, const Font* font, const Color& color, TextStyleFlags style, unsigned int characterSize, int renderOrder, int* advance) const { const Font::Glyph& fontGlyph = font->GetGlyph(characterSize, style, outlineThickness, character); @@ -281,8 +330,8 @@ namespace Nz glyph.bounds.Set(fontGlyph.aabb); - //if (lineWrap && ShouldLineWrap(glyph, glyph.bounds.width)) - // AppendNewLine(m_lastSeparatorGlyph, m_lastSeparatorPosition); + if (lineWrap && ShouldLineWrap(glyph.bounds.width)) + AppendNewLine(font, characterSize, m_lastSeparatorGlyph, m_lastSeparatorPosition); glyph.bounds.x += m_drawPos.x; glyph.bounds.y += m_drawPos.y; @@ -337,7 +386,7 @@ namespace Nz corner.y += heightDifference; } - m_drawPos.y += heightDifference; + m_drawPos.y += static_cast(heightDifference); m_lines.back().bounds.height += heightDifference; } /*if (firstFont.font) @@ -388,10 +437,10 @@ namespace Nz } else { - float glyphAdvance = advance; + float glyphAdvance = float(advance); - //if (ShouldLineWrap(glyph, glyphAdvance)) - // AppendNewLine(m_lastSeparatorGlyph, m_lastSeparatorPosition); + if (ShouldLineWrap(glyphAdvance)) + AppendNewLine(font, characterSize, m_lastSeparatorGlyph, m_lastSeparatorPosition); glyph.atlas = nullptr; glyph.bounds.Set(float(m_drawPos.x), m_lines.back().bounds.y, glyphAdvance, float(sizeInfo.lineHeight)); @@ -417,11 +466,11 @@ namespace Nz break; } - /*if (whitespace) + if (whitespace) { m_lastSeparatorGlyph = m_glyphs.size(); m_lastSeparatorPosition = m_drawPos.x; - }*/ + } m_glyphs.push_back(glyph); } diff --git a/src/Nazara/Utility/SimpleTextDrawer.cpp b/src/Nazara/Utility/SimpleTextDrawer.cpp index aca74968d..5f5357dbc 100644 --- a/src/Nazara/Utility/SimpleTextDrawer.cpp +++ b/src/Nazara/Utility/SimpleTextDrawer.cpp @@ -311,7 +311,7 @@ namespace Nz void SimpleTextDrawer::AppendNewLine() const { - AppendNewLine(InvalidGlyph, 0.f); + AppendNewLine(InvalidGlyph, 0); } void SimpleTextDrawer::AppendNewLine(std::size_t glyphIndex, unsigned int glyphPosition) const @@ -354,7 +354,7 @@ namespace Nz assert(previousDrawPos >= glyphPosition); m_drawPos.x += previousDrawPos - glyphPosition; - lastLine.bounds.width -= lastLine.bounds.GetMaximum().x - m_lastSeparatorPosition; + lastLine.bounds.width -= lastLine.bounds.GetMaximum().x - glyphPosition; // Regenerate working bounds m_workingBounds.MakeZero(); @@ -410,7 +410,7 @@ namespace Nz glyph.bounds.Set(fontGlyph.aabb); - if (lineWrap && ShouldLineWrap(glyph, glyph.bounds.width)) + if (lineWrap && ShouldLineWrap(glyph.bounds.width)) AppendNewLine(m_lastSeparatorGlyph, m_lastSeparatorPosition); glyph.bounds.x += m_drawPos.x; @@ -497,7 +497,7 @@ namespace Nz { float glyphAdvance = advance; - if (ShouldLineWrap(glyph, glyphAdvance)) + if (ShouldLineWrap(glyphAdvance)) AppendNewLine(m_lastSeparatorGlyph, m_lastSeparatorPosition); glyph.atlas = nullptr; @@ -593,9 +593,9 @@ namespace Nz SetFont(nullptr); } - bool SimpleTextDrawer::ShouldLineWrap(Glyph& glyph, float size, bool checkFirstGlyph) const + bool SimpleTextDrawer::ShouldLineWrap(float size) const { - if (checkFirstGlyph && m_lines.back().glyphIndex > m_glyphs.size()) + if (m_lines.back().glyphIndex > m_glyphs.size()) return false; return m_lines.back().bounds.GetMaximum().x + size > m_maxLineWidth;