Fix RichTextDrawer ignoring max line width
This commit is contained in:
parent
453c7a7e77
commit
fcfcc94c49
|
|
@ -93,15 +93,16 @@ namespace Nz
|
||||||
struct Block;
|
struct Block;
|
||||||
|
|
||||||
inline void AppendNewLine(const Font* font, unsigned int characterSize) const;
|
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 ClearGlyphs() const;
|
||||||
inline void ConnectFontSlots();
|
inline void ConnectFontSlots();
|
||||||
inline void DisconnectFontSlots();
|
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;
|
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;
|
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 std::size_t HandleFontAddition(const FontRef& font);
|
||||||
inline void ReleaseFont(std::size_t fontIndex);
|
|
||||||
|
|
||||||
inline void InvalidateGlyphs();
|
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 OnFontAtlasLayerChanged(const Font* font, AbstractImage* oldLayer, AbstractImage* newLayer);
|
||||||
void OnFontInvalidated(const Font* font);
|
void OnFontInvalidated(const Font* font);
|
||||||
|
|
@ -109,6 +110,8 @@ namespace Nz
|
||||||
|
|
||||||
void UpdateGlyphs() const;
|
void UpdateGlyphs() const;
|
||||||
|
|
||||||
|
static constexpr std::size_t InvalidGlyph = std::numeric_limits<std::size_t>::max();
|
||||||
|
|
||||||
struct Block
|
struct Block
|
||||||
{
|
{
|
||||||
std::size_t fontIndex;
|
std::size_t fontIndex;
|
||||||
|
|
@ -136,6 +139,7 @@ namespace Nz
|
||||||
Color m_defaultOutlineColor;
|
Color m_defaultOutlineColor;
|
||||||
TextStyleFlags m_defaultStyle;
|
TextStyleFlags m_defaultStyle;
|
||||||
FontRef m_defaultFont;
|
FontRef m_defaultFont;
|
||||||
|
mutable std::size_t m_lastSeparatorGlyph;
|
||||||
std::unordered_map<FontRef, std::size_t> m_fontIndexes;
|
std::unordered_map<FontRef, std::size_t> m_fontIndexes;
|
||||||
std::vector<Block> m_blocks;
|
std::vector<Block> m_blocks;
|
||||||
std::vector<FontData> m_fonts;
|
std::vector<FontData> m_fonts;
|
||||||
|
|
@ -148,6 +152,7 @@ namespace Nz
|
||||||
float m_defaultOutlineThickness;
|
float m_defaultOutlineThickness;
|
||||||
float m_maxLineWidth;
|
float m_maxLineWidth;
|
||||||
unsigned int m_defaultCharacterSize;
|
unsigned int m_defaultCharacterSize;
|
||||||
|
mutable unsigned int m_lastSeparatorPosition;
|
||||||
};
|
};
|
||||||
|
|
||||||
class RichTextDrawer::BlockRef
|
class RichTextDrawer::BlockRef
|
||||||
|
|
|
||||||
|
|
@ -138,22 +138,13 @@ namespace Nz
|
||||||
|
|
||||||
inline void RichTextDrawer::AppendNewLine(const Font* font, unsigned int characterSize) const
|
inline void RichTextDrawer::AppendNewLine(const Font* font, unsigned int characterSize) const
|
||||||
{
|
{
|
||||||
// Ensure we're appending from last line
|
AppendNewLine(font, characterSize, InvalidGlyph, 0);
|
||||||
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 });
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void RichTextDrawer::ClearGlyphs() const
|
inline void RichTextDrawer::ClearGlyphs() const
|
||||||
{
|
{
|
||||||
m_bounds.MakeZero();
|
m_bounds.MakeZero();
|
||||||
|
m_lastSeparatorGlyph = InvalidGlyph;
|
||||||
m_lines.clear();
|
m_lines.clear();
|
||||||
m_glyphs.clear();
|
m_glyphs.clear();
|
||||||
m_glyphUpdated = true;
|
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
|
inline bool RichTextDrawer::HasBlocks() const
|
||||||
{
|
{
|
||||||
return !m_blocks.empty();
|
return !m_blocks.empty();
|
||||||
|
|
|
||||||
|
|
@ -72,7 +72,7 @@ namespace Nz
|
||||||
void OnFontAtlasLayerChanged(const Font* font, AbstractImage* oldLayer, AbstractImage* newLayer);
|
void OnFontAtlasLayerChanged(const Font* font, AbstractImage* oldLayer, AbstractImage* newLayer);
|
||||||
void OnFontInvalidated(const Font* font);
|
void OnFontInvalidated(const Font* font);
|
||||||
void OnFontRelease(const Font* object);
|
void OnFontRelease(const Font* object);
|
||||||
bool ShouldLineWrap(Glyph& glyph, float size, bool checkFirstGlyph = true) const;
|
bool ShouldLineWrap(float size) const;
|
||||||
void UpdateGlyphColor() const;
|
void UpdateGlyphColor() const;
|
||||||
void UpdateGlyphs() const;
|
void UpdateGlyphs() const;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -268,6 +268,55 @@ namespace Nz
|
||||||
return *this;
|
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
|
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);
|
const Font::Glyph& fontGlyph = font->GetGlyph(characterSize, style, outlineThickness, character);
|
||||||
|
|
@ -281,8 +330,8 @@ namespace Nz
|
||||||
|
|
||||||
glyph.bounds.Set(fontGlyph.aabb);
|
glyph.bounds.Set(fontGlyph.aabb);
|
||||||
|
|
||||||
//if (lineWrap && ShouldLineWrap(glyph, glyph.bounds.width))
|
if (lineWrap && ShouldLineWrap(glyph.bounds.width))
|
||||||
// AppendNewLine(m_lastSeparatorGlyph, m_lastSeparatorPosition);
|
AppendNewLine(font, characterSize, m_lastSeparatorGlyph, m_lastSeparatorPosition);
|
||||||
|
|
||||||
glyph.bounds.x += m_drawPos.x;
|
glyph.bounds.x += m_drawPos.x;
|
||||||
glyph.bounds.y += m_drawPos.y;
|
glyph.bounds.y += m_drawPos.y;
|
||||||
|
|
@ -337,7 +386,7 @@ namespace Nz
|
||||||
corner.y += heightDifference;
|
corner.y += heightDifference;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_drawPos.y += heightDifference;
|
m_drawPos.y += static_cast<unsigned int>(heightDifference);
|
||||||
m_lines.back().bounds.height += heightDifference;
|
m_lines.back().bounds.height += heightDifference;
|
||||||
}
|
}
|
||||||
/*if (firstFont.font)
|
/*if (firstFont.font)
|
||||||
|
|
@ -388,10 +437,10 @@ namespace Nz
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
float glyphAdvance = advance;
|
float glyphAdvance = float(advance);
|
||||||
|
|
||||||
//if (ShouldLineWrap(glyph, glyphAdvance))
|
if (ShouldLineWrap(glyphAdvance))
|
||||||
// AppendNewLine(m_lastSeparatorGlyph, m_lastSeparatorPosition);
|
AppendNewLine(font, characterSize, m_lastSeparatorGlyph, m_lastSeparatorPosition);
|
||||||
|
|
||||||
glyph.atlas = nullptr;
|
glyph.atlas = nullptr;
|
||||||
glyph.bounds.Set(float(m_drawPos.x), m_lines.back().bounds.y, glyphAdvance, float(sizeInfo.lineHeight));
|
glyph.bounds.Set(float(m_drawPos.x), m_lines.back().bounds.y, glyphAdvance, float(sizeInfo.lineHeight));
|
||||||
|
|
@ -417,11 +466,11 @@ namespace Nz
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*if (whitespace)
|
if (whitespace)
|
||||||
{
|
{
|
||||||
m_lastSeparatorGlyph = m_glyphs.size();
|
m_lastSeparatorGlyph = m_glyphs.size();
|
||||||
m_lastSeparatorPosition = m_drawPos.x;
|
m_lastSeparatorPosition = m_drawPos.x;
|
||||||
}*/
|
}
|
||||||
|
|
||||||
m_glyphs.push_back(glyph);
|
m_glyphs.push_back(glyph);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -311,7 +311,7 @@ namespace Nz
|
||||||
|
|
||||||
void SimpleTextDrawer::AppendNewLine() const
|
void SimpleTextDrawer::AppendNewLine() const
|
||||||
{
|
{
|
||||||
AppendNewLine(InvalidGlyph, 0.f);
|
AppendNewLine(InvalidGlyph, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SimpleTextDrawer::AppendNewLine(std::size_t glyphIndex, unsigned int glyphPosition) const
|
void SimpleTextDrawer::AppendNewLine(std::size_t glyphIndex, unsigned int glyphPosition) const
|
||||||
|
|
@ -354,7 +354,7 @@ namespace Nz
|
||||||
assert(previousDrawPos >= glyphPosition);
|
assert(previousDrawPos >= glyphPosition);
|
||||||
m_drawPos.x += 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
|
// Regenerate working bounds
|
||||||
m_workingBounds.MakeZero();
|
m_workingBounds.MakeZero();
|
||||||
|
|
@ -410,7 +410,7 @@ namespace Nz
|
||||||
|
|
||||||
glyph.bounds.Set(fontGlyph.aabb);
|
glyph.bounds.Set(fontGlyph.aabb);
|
||||||
|
|
||||||
if (lineWrap && ShouldLineWrap(glyph, glyph.bounds.width))
|
if (lineWrap && ShouldLineWrap(glyph.bounds.width))
|
||||||
AppendNewLine(m_lastSeparatorGlyph, m_lastSeparatorPosition);
|
AppendNewLine(m_lastSeparatorGlyph, m_lastSeparatorPosition);
|
||||||
|
|
||||||
glyph.bounds.x += m_drawPos.x;
|
glyph.bounds.x += m_drawPos.x;
|
||||||
|
|
@ -497,7 +497,7 @@ namespace Nz
|
||||||
{
|
{
|
||||||
float glyphAdvance = advance;
|
float glyphAdvance = advance;
|
||||||
|
|
||||||
if (ShouldLineWrap(glyph, glyphAdvance))
|
if (ShouldLineWrap(glyphAdvance))
|
||||||
AppendNewLine(m_lastSeparatorGlyph, m_lastSeparatorPosition);
|
AppendNewLine(m_lastSeparatorGlyph, m_lastSeparatorPosition);
|
||||||
|
|
||||||
glyph.atlas = nullptr;
|
glyph.atlas = nullptr;
|
||||||
|
|
@ -593,9 +593,9 @@ namespace Nz
|
||||||
SetFont(nullptr);
|
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 false;
|
||||||
|
|
||||||
return m_lines.back().bounds.GetMaximum().x + size > m_maxLineWidth;
|
return m_lines.back().bounds.GetMaximum().x + size > m_maxLineWidth;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue