parent
59d80dbe6d
commit
548ede4613
|
|
@ -218,6 +218,7 @@ Nazara Engine:
|
||||||
- ⚠ OBJLoader flips UV by default, fixing a lot of models UV
|
- ⚠ OBJLoader flips UV by default, fixing a lot of models UV
|
||||||
- On Windows, Thread::Set(Current)Name now uses `SetThreadDescription` Win32 function if possible instead of triggering a debugger exception. MinGW builds will use this if available too.
|
- On Windows, Thread::Set(Current)Name now uses `SetThreadDescription` Win32 function if possible instead of triggering a debugger exception. MinGW builds will use this if available too.
|
||||||
- ⚠ Removed Texture(const Image\*) constructor, use Texture::LoadFromImage instead
|
- ⚠ Removed Texture(const Image\*) constructor, use Texture::LoadFromImage instead
|
||||||
|
- ⚠ TextDrawers now use floating-point internally and to exposes their Bounds (AbstractTextDrawer::GetBounds() now returns a Rectf)
|
||||||
|
|
||||||
Nazara Development Kit:
|
Nazara Development Kit:
|
||||||
- Added ImageWidget (#139)
|
- Added ImageWidget (#139)
|
||||||
|
|
|
||||||
|
|
@ -102,7 +102,7 @@ namespace Nz
|
||||||
mutable std::unordered_map<RenderKey, RenderIndices, HashRenderKey> m_renderInfos;
|
mutable std::unordered_map<RenderKey, RenderIndices, HashRenderKey> m_renderInfos;
|
||||||
mutable std::vector<VertexStruct_XY_Color_UV> m_localVertices;
|
mutable std::vector<VertexStruct_XY_Color_UV> m_localVertices;
|
||||||
Color m_color;
|
Color m_color;
|
||||||
Recti m_localBounds;
|
Rectf m_localBounds;
|
||||||
float m_scale;
|
float m_scale;
|
||||||
|
|
||||||
static TextSpriteLibrary::LibraryMap s_library;
|
static TextSpriteLibrary::LibraryMap s_library;
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,7 @@ namespace Nz
|
||||||
|
|
||||||
inline TextSprite::TextSprite() :
|
inline TextSprite::TextSprite() :
|
||||||
m_color(Color::White),
|
m_color(Color::White),
|
||||||
m_localBounds(Nz::Recti::Zero()),
|
m_localBounds(Nz::Rectf::Zero()),
|
||||||
m_scale(1.f)
|
m_scale(1.f)
|
||||||
{
|
{
|
||||||
ResetMaterials(1U);
|
ResetMaterials(1U);
|
||||||
|
|
|
||||||
|
|
@ -29,7 +29,7 @@ namespace Nz
|
||||||
|
|
||||||
virtual void Clear() = 0;
|
virtual void Clear() = 0;
|
||||||
|
|
||||||
virtual const Recti& GetBounds() const = 0;
|
virtual const Rectf& GetBounds() const = 0;
|
||||||
virtual Font* GetFont(std::size_t index) const = 0;
|
virtual Font* GetFont(std::size_t index) const = 0;
|
||||||
virtual std::size_t GetFontCount() const = 0;
|
virtual std::size_t GetFontCount() const = 0;
|
||||||
virtual const Glyph& GetGlyph(std::size_t index) const = 0;
|
virtual const Glyph& GetGlyph(std::size_t index) const = 0;
|
||||||
|
|
|
||||||
|
|
@ -43,7 +43,7 @@ namespace Nz
|
||||||
inline const String& GetBlockText(std::size_t index) const;
|
inline const String& GetBlockText(std::size_t index) const;
|
||||||
|
|
||||||
inline BlockRef GetBlock(std::size_t index);
|
inline BlockRef GetBlock(std::size_t index);
|
||||||
const Recti& GetBounds() const override;
|
const Rectf& GetBounds() const override;
|
||||||
inline unsigned int GetDefaultCharacterSize() const;
|
inline unsigned int GetDefaultCharacterSize() const;
|
||||||
inline const Color& GetDefaultColor() const;
|
inline const Color& GetDefaultColor() const;
|
||||||
inline const FontRef& GetDefaultFont() const;
|
inline const FontRef& GetDefaultFont() const;
|
||||||
|
|
@ -86,14 +86,11 @@ namespace Nz
|
||||||
|
|
||||||
static constexpr std::size_t InvalidBlockIndex = std::numeric_limits<std::size_t>::max();
|
static constexpr std::size_t InvalidBlockIndex = std::numeric_limits<std::size_t>::max();
|
||||||
|
|
||||||
//static RichTextDrawer Draw(const String& str, unsigned int characterSize, TextStyleFlags style = TextStyle_Regular, const Color& color = Color::White);
|
|
||||||
//static RichTextDrawer Draw(Font* font, const String& str, unsigned int characterSize, TextStyleFlags style = TextStyle_Regular, const Color& color = Color::White);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
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;
|
void AppendNewLine(const Font* font, unsigned int characterSize, std::size_t glyphIndex, float glyphPosition) const;
|
||||||
inline void ClearGlyphs() const;
|
inline void ClearGlyphs() const;
|
||||||
inline void ConnectFontSlots();
|
inline void ConnectFontSlots();
|
||||||
inline void DisconnectFontSlots();
|
inline void DisconnectFontSlots();
|
||||||
|
|
@ -145,14 +142,13 @@ namespace Nz
|
||||||
std::vector<FontData> m_fonts;
|
std::vector<FontData> m_fonts;
|
||||||
mutable std::vector<Glyph> m_glyphs;
|
mutable std::vector<Glyph> m_glyphs;
|
||||||
mutable std::vector<Line> m_lines;
|
mutable std::vector<Line> m_lines;
|
||||||
mutable Rectf m_workingBounds;
|
mutable Rectf m_bounds;
|
||||||
mutable Recti m_bounds;
|
mutable Vector2f m_drawPos;
|
||||||
mutable Vector2ui m_drawPos;
|
|
||||||
mutable bool m_glyphUpdated;
|
mutable bool m_glyphUpdated;
|
||||||
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;
|
mutable float m_lastSeparatorPosition;
|
||||||
};
|
};
|
||||||
|
|
||||||
class RichTextDrawer::BlockRef
|
class RichTextDrawer::BlockRef
|
||||||
|
|
|
||||||
|
|
@ -148,7 +148,7 @@ namespace Nz
|
||||||
m_lines.clear();
|
m_lines.clear();
|
||||||
m_glyphs.clear();
|
m_glyphs.clear();
|
||||||
m_glyphUpdated = true;
|
m_glyphUpdated = true;
|
||||||
m_workingBounds.MakeZero(); //< Compute bounds as float to speedup bounds computation (as casting between floats and integers is costly)
|
m_bounds.MakeZero(); //< Compute bounds as float to speedup bounds computation (as casting between floats and integers is costly)
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void RichTextDrawer::ConnectFontSlots()
|
inline void RichTextDrawer::ConnectFontSlots()
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,7 @@ namespace Nz
|
||||||
|
|
||||||
void Clear() override;
|
void Clear() override;
|
||||||
|
|
||||||
const Recti& GetBounds() const override;
|
const Rectf& GetBounds() const override;
|
||||||
inline unsigned int GetCharacterSize() const;
|
inline unsigned int GetCharacterSize() const;
|
||||||
inline const Color& GetColor() const;
|
inline const Color& GetColor() const;
|
||||||
inline Font* GetFont() const;
|
inline Font* GetFont() const;
|
||||||
|
|
@ -38,6 +38,7 @@ namespace Nz
|
||||||
std::size_t GetGlyphCount() const override;
|
std::size_t GetGlyphCount() const override;
|
||||||
const Line& GetLine(std::size_t index) const override;
|
const Line& GetLine(std::size_t index) const override;
|
||||||
std::size_t GetLineCount() const override;
|
std::size_t GetLineCount() const override;
|
||||||
|
inline float GetLineHeight() const;
|
||||||
float GetMaxLineWidth() const override;
|
float GetMaxLineWidth() const override;
|
||||||
inline const Color& GetOutlineColor() const;
|
inline const Color& GetOutlineColor() const;
|
||||||
inline float GetOutlineThickness() const;
|
inline float GetOutlineThickness() const;
|
||||||
|
|
@ -64,7 +65,7 @@ namespace Nz
|
||||||
|
|
||||||
private:
|
private:
|
||||||
inline void AppendNewLine() const;
|
inline void AppendNewLine() const;
|
||||||
void AppendNewLine(std::size_t glyphIndex, unsigned int glyphPosition) const;
|
void AppendNewLine(std::size_t glyphIndex, float glyphPosition) const;
|
||||||
|
|
||||||
void ClearGlyphs() const;
|
void ClearGlyphs() const;
|
||||||
|
|
||||||
|
|
@ -74,6 +75,8 @@ namespace Nz
|
||||||
bool GenerateGlyph(Glyph& glyph, char32_t character, float outlineThickness, bool lineWrap, Nz::Color color, int renderOrder, int* advance) const;
|
bool GenerateGlyph(Glyph& glyph, char32_t character, float outlineThickness, bool lineWrap, Nz::Color color, int renderOrder, int* advance) const;
|
||||||
void GenerateGlyphs(const String& text) const;
|
void GenerateGlyphs(const String& text) const;
|
||||||
|
|
||||||
|
inline float GetLineHeight(const Font::SizeInfo& sizeInfo) const;
|
||||||
|
|
||||||
inline void InvalidateColor();
|
inline void InvalidateColor();
|
||||||
inline void InvalidateGlyphs();
|
inline void InvalidateGlyphs();
|
||||||
|
|
||||||
|
|
@ -94,20 +97,19 @@ namespace Nz
|
||||||
NazaraSlot(Font, OnFontRelease, m_fontReleaseSlot);
|
NazaraSlot(Font, OnFontRelease, m_fontReleaseSlot);
|
||||||
|
|
||||||
mutable std::size_t m_lastSeparatorGlyph;
|
mutable std::size_t m_lastSeparatorGlyph;
|
||||||
mutable unsigned int m_lastSeparatorPosition;
|
|
||||||
mutable std::vector<Glyph> m_glyphs;
|
mutable std::vector<Glyph> m_glyphs;
|
||||||
mutable std::vector<Line> m_lines;
|
mutable std::vector<Line> m_lines;
|
||||||
Color m_color;
|
Color m_color;
|
||||||
Color m_outlineColor;
|
Color m_outlineColor;
|
||||||
FontRef m_font;
|
FontRef m_font;
|
||||||
mutable Rectf m_workingBounds;
|
mutable Rectf m_bounds;
|
||||||
mutable Recti m_bounds;
|
|
||||||
String m_text;
|
String m_text;
|
||||||
TextStyleFlags m_style;
|
TextStyleFlags m_style;
|
||||||
mutable UInt32 m_previousCharacter;
|
mutable UInt32 m_previousCharacter;
|
||||||
mutable Vector2ui m_drawPos;
|
mutable Vector2f m_drawPos;
|
||||||
mutable bool m_colorUpdated;
|
mutable bool m_colorUpdated;
|
||||||
mutable bool m_glyphUpdated;
|
mutable bool m_glyphUpdated;
|
||||||
|
mutable float m_lastSeparatorPosition;
|
||||||
float m_maxLineWidth;
|
float m_maxLineWidth;
|
||||||
float m_outlineThickness;
|
float m_outlineThickness;
|
||||||
unsigned int m_characterSize;
|
unsigned int m_characterSize;
|
||||||
|
|
|
||||||
|
|
@ -61,6 +61,12 @@ namespace Nz
|
||||||
return m_font;
|
return m_font;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline float SimpleTextDrawer::GetLineHeight() const
|
||||||
|
{
|
||||||
|
NazaraAssert(m_font, "SimpleTextDrawer has no font");
|
||||||
|
return GetLineHeight(m_font->GetSizeInfo(m_characterSize));
|
||||||
|
}
|
||||||
|
|
||||||
inline const Color& SimpleTextDrawer::GetOutlineColor() const
|
inline const Color& SimpleTextDrawer::GetOutlineColor() const
|
||||||
{
|
{
|
||||||
return m_outlineColor;
|
return m_outlineColor;
|
||||||
|
|
@ -205,7 +211,11 @@ namespace Nz
|
||||||
|
|
||||||
// Update slot pointers (TODO: Improve the way of doing this)
|
// Update slot pointers (TODO: Improve the way of doing this)
|
||||||
ConnectFontSlots();
|
ConnectFontSlots();
|
||||||
drawer.DisconnectFontSlots();
|
if (m_font)
|
||||||
|
{
|
||||||
|
drawer.DisconnectFontSlots();
|
||||||
|
ConnectFontSlots();
|
||||||
|
}
|
||||||
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
@ -265,6 +275,27 @@ namespace Nz
|
||||||
AppendNewLine(InvalidGlyph, 0);
|
AppendNewLine(InvalidGlyph, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline void SimpleTextDrawer::ConnectFontSlots()
|
||||||
|
{
|
||||||
|
m_atlasChangedSlot.Connect(m_font->OnFontAtlasChanged, this, &SimpleTextDrawer::OnFontInvalidated);
|
||||||
|
m_atlasLayerChangedSlot.Connect(m_font->OnFontAtlasLayerChanged, this, &SimpleTextDrawer::OnFontAtlasLayerChanged);
|
||||||
|
m_fontReleaseSlot.Connect(m_font->OnFontRelease, this, &SimpleTextDrawer::OnFontRelease);
|
||||||
|
m_glyphCacheClearedSlot.Connect(m_font->OnFontGlyphCacheCleared, this, &SimpleTextDrawer::OnFontInvalidated);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void SimpleTextDrawer::DisconnectFontSlots()
|
||||||
|
{
|
||||||
|
m_atlasChangedSlot.Disconnect();
|
||||||
|
m_atlasLayerChangedSlot.Disconnect();
|
||||||
|
m_fontReleaseSlot.Disconnect();
|
||||||
|
m_glyphCacheClearedSlot.Disconnect();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline float SimpleTextDrawer::GetLineHeight(const Font::SizeInfo& sizeInfo) const
|
||||||
|
{
|
||||||
|
return float(sizeInfo.lineHeight);
|
||||||
|
}
|
||||||
|
|
||||||
inline void SimpleTextDrawer::InvalidateColor()
|
inline void SimpleTextDrawer::InvalidateColor()
|
||||||
{
|
{
|
||||||
m_colorUpdated = false;
|
m_colorUpdated = false;
|
||||||
|
|
|
||||||
|
|
@ -215,9 +215,8 @@ namespace Nz
|
||||||
|
|
||||||
void TextSprite::MakeBoundingVolume() const
|
void TextSprite::MakeBoundingVolume() const
|
||||||
{
|
{
|
||||||
Rectf bounds(m_localBounds);
|
Vector2f max = m_scale * m_localBounds.GetMaximum();
|
||||||
Vector2f max = m_scale * bounds.GetMaximum();
|
Vector2f min = m_scale * m_localBounds.GetMinimum();
|
||||||
Vector2f min = m_scale * bounds.GetMinimum();
|
|
||||||
|
|
||||||
m_boundingVolume.Set(min.x * Vector3f::Right() + min.y * Vector3f::Down(), max.x * Vector3f::Right() + max.y * Vector3f::Down());
|
m_boundingVolume.Set(min.x * Vector3f::Right() + min.y * Vector3f::Down(), max.x * Vector3f::Right() + max.y * Vector3f::Down());
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -110,7 +110,7 @@ namespace Nz
|
||||||
ClearGlyphs();
|
ClearGlyphs();
|
||||||
}
|
}
|
||||||
|
|
||||||
const Recti& RichTextDrawer::GetBounds() const
|
const Rectf& RichTextDrawer::GetBounds() const
|
||||||
{
|
{
|
||||||
if (!m_glyphUpdated)
|
if (!m_glyphUpdated)
|
||||||
UpdateGlyphs();
|
UpdateGlyphs();
|
||||||
|
|
@ -260,7 +260,6 @@ namespace Nz
|
||||||
m_glyphs = std::move(m_glyphs);
|
m_glyphs = std::move(m_glyphs);
|
||||||
m_lines = std::move(m_lines);
|
m_lines = std::move(m_lines);
|
||||||
m_glyphUpdated = std::move(m_glyphUpdated);
|
m_glyphUpdated = std::move(m_glyphUpdated);
|
||||||
m_workingBounds = std::move(m_workingBounds);
|
|
||||||
|
|
||||||
drawer.DisconnectFontSlots();
|
drawer.DisconnectFontSlots();
|
||||||
ConnectFontSlots();
|
ConnectFontSlots();
|
||||||
|
|
@ -268,21 +267,21 @@ namespace Nz
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
void RichTextDrawer::AppendNewLine(const Font* font, unsigned int characterSize, std::size_t glyphIndex, unsigned int glyphPosition) const
|
void RichTextDrawer::AppendNewLine(const Font* font, unsigned int characterSize, std::size_t glyphIndex, float glyphPosition) const
|
||||||
{
|
{
|
||||||
// Ensure we're appending from last line
|
// Ensure we're appending from last line
|
||||||
Line& lastLine = m_lines.back();
|
Line& lastLine = m_lines.back();
|
||||||
|
|
||||||
const Font::SizeInfo& sizeInfo = font->GetSizeInfo(characterSize);
|
const Font::SizeInfo& sizeInfo = font->GetSizeInfo(characterSize);
|
||||||
|
|
||||||
unsigned int previousDrawPos = m_drawPos.x;
|
float previousDrawPos = m_drawPos.x;
|
||||||
|
|
||||||
// Reset cursor
|
// Reset cursor
|
||||||
m_drawPos.x = 0;
|
m_drawPos.x = 0;
|
||||||
m_drawPos.y += sizeInfo.lineHeight;
|
m_drawPos.y += sizeInfo.lineHeight;
|
||||||
m_lastSeparatorGlyph = InvalidGlyph;
|
m_lastSeparatorGlyph = InvalidGlyph;
|
||||||
|
|
||||||
m_workingBounds.ExtendTo(lastLine.bounds);
|
m_bounds.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 });
|
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)
|
if (glyphIndex != InvalidGlyph && glyphIndex > lastLine.glyphIndex)
|
||||||
|
|
@ -310,10 +309,10 @@ namespace Nz
|
||||||
|
|
||||||
lastLine.bounds.width -= lastLine.bounds.GetMaximum().x - glyphPosition;
|
lastLine.bounds.width -= lastLine.bounds.GetMaximum().x - glyphPosition;
|
||||||
|
|
||||||
// Regenerate working bounds
|
// Regenerate bounds
|
||||||
m_workingBounds.MakeZero();
|
m_bounds.MakeZero();
|
||||||
for (std::size_t i = 0; i < m_lines.size(); ++i)
|
for (auto& line : m_lines)
|
||||||
m_workingBounds.ExtendTo(m_lines[i].bounds);
|
m_bounds.ExtendTo(line.bounds);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -403,16 +402,16 @@ namespace Nz
|
||||||
previousCharacter = character;
|
previousCharacter = character;
|
||||||
|
|
||||||
bool whitespace = true;
|
bool whitespace = true;
|
||||||
int advance = 0;
|
float advance = 0.f;
|
||||||
switch (character)
|
switch (character)
|
||||||
{
|
{
|
||||||
case ' ':
|
case ' ':
|
||||||
case '\n':
|
case '\n':
|
||||||
advance = sizeInfo.spaceAdvance;
|
advance = float(sizeInfo.spaceAdvance);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case '\t':
|
case '\t':
|
||||||
advance = sizeInfo.spaceAdvance * 4;
|
advance = float(sizeInfo.spaceAdvance) * 4.f;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
|
@ -423,27 +422,26 @@ namespace Nz
|
||||||
Glyph glyph;
|
Glyph glyph;
|
||||||
if (!whitespace)
|
if (!whitespace)
|
||||||
{
|
{
|
||||||
if (!GenerateGlyph(glyph, character, 0.f, true, font, color, style, characterSize, 0, &advance))
|
int iAdvance;
|
||||||
|
if (!GenerateGlyph(glyph, character, 0.f, true, font, color, style, characterSize, 0, &iAdvance))
|
||||||
continue; // Glyph failed to load, just skip it (can't do much)
|
continue; // Glyph failed to load, just skip it (can't do much)
|
||||||
|
|
||||||
|
advance = float(iAdvance);
|
||||||
|
|
||||||
if (outlineThickness > 0.f)
|
if (outlineThickness > 0.f)
|
||||||
{
|
{
|
||||||
Glyph outlineGlyph;
|
Glyph outlineGlyph;
|
||||||
if (GenerateGlyph(outlineGlyph, character, outlineThickness, false, font, outlineColor, style, characterSize, -1, nullptr))
|
if (GenerateGlyph(outlineGlyph, character, outlineThickness, false, font, outlineColor, style, characterSize, -1, nullptr))
|
||||||
{
|
|
||||||
m_glyphs.push_back(outlineGlyph);
|
m_glyphs.push_back(outlineGlyph);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
float glyphAdvance = float(advance);
|
if (ShouldLineWrap(advance))
|
||||||
|
|
||||||
if (ShouldLineWrap(glyphAdvance))
|
|
||||||
AppendNewLine(font, characterSize, 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(m_drawPos.x, m_lines.back().bounds.y, advance, float(sizeInfo.lineHeight));
|
||||||
|
|
||||||
glyph.corners[0].Set(glyph.bounds.GetCorner(RectCorner_LeftTop));
|
glyph.corners[0].Set(glyph.bounds.GetCorner(RectCorner_LeftTop));
|
||||||
glyph.corners[1].Set(glyph.bounds.GetCorner(RectCorner_RightTop));
|
glyph.corners[1].Set(glyph.bounds.GetCorner(RectCorner_RightTop));
|
||||||
|
|
@ -475,9 +473,7 @@ namespace Nz
|
||||||
m_glyphs.push_back(glyph);
|
m_glyphs.push_back(glyph);
|
||||||
}
|
}
|
||||||
|
|
||||||
m_workingBounds.ExtendTo(m_lines.back().bounds);
|
m_bounds.ExtendTo(m_lines.back().bounds);
|
||||||
|
|
||||||
m_bounds.Set(Rectf(std::floor(m_workingBounds.x), std::floor(m_workingBounds.y), std::ceil(m_workingBounds.width), std::ceil(m_workingBounds.height)));
|
|
||||||
|
|
||||||
m_glyphUpdated = true;
|
m_glyphUpdated = true;
|
||||||
}
|
}
|
||||||
|
|
@ -553,7 +549,7 @@ namespace Nz
|
||||||
else
|
else
|
||||||
m_lines.emplace_back(Line{ Rectf::Zero(), 0 });
|
m_lines.emplace_back(Line{ Rectf::Zero(), 0 });
|
||||||
|
|
||||||
m_drawPos.Set(0, firstBlock.characterSize);
|
m_drawPos.Set(0, float(firstBlock.characterSize));
|
||||||
|
|
||||||
for (const Block& block : m_blocks)
|
for (const Block& block : m_blocks)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,7 @@ namespace Nz
|
||||||
ClearGlyphs();
|
ClearGlyphs();
|
||||||
}
|
}
|
||||||
|
|
||||||
const Recti& SimpleTextDrawer::GetBounds() const
|
const Rectf& SimpleTextDrawer::GetBounds() const
|
||||||
{
|
{
|
||||||
if (!m_glyphUpdated)
|
if (!m_glyphUpdated)
|
||||||
UpdateGlyphs();
|
UpdateGlyphs();
|
||||||
|
|
@ -76,22 +76,22 @@ namespace Nz
|
||||||
return m_maxLineWidth;
|
return m_maxLineWidth;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SimpleTextDrawer::AppendNewLine(std::size_t glyphIndex, unsigned int glyphPosition) const
|
void SimpleTextDrawer::AppendNewLine(std::size_t glyphIndex, float glyphPosition) const
|
||||||
{
|
{
|
||||||
// Ensure we're appending from last line
|
// Ensure we're appending from last line
|
||||||
Line& lastLine = m_lines.back();
|
Line& lastLine = m_lines.back();
|
||||||
|
|
||||||
const Font::SizeInfo& sizeInfo = m_font->GetSizeInfo(m_characterSize);
|
float previousDrawPos = m_drawPos.x;
|
||||||
|
|
||||||
unsigned int previousDrawPos = m_drawPos.x;
|
float lineHeight = GetLineHeight();
|
||||||
|
|
||||||
// Reset cursor
|
// Reset cursor
|
||||||
m_drawPos.x = 0;
|
m_drawPos.x = 0.f;
|
||||||
m_drawPos.y += sizeInfo.lineHeight;
|
m_drawPos.y += lineHeight;
|
||||||
m_lastSeparatorGlyph = InvalidGlyph;
|
m_lastSeparatorGlyph = InvalidGlyph;
|
||||||
|
|
||||||
m_workingBounds.ExtendTo(lastLine.bounds);
|
m_bounds.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 });
|
m_lines.emplace_back(Line{ Rectf(0.f, lineHeight * m_lines.size(), 0.f, lineHeight), m_glyphs.size() + 1 });
|
||||||
|
|
||||||
if (glyphIndex != InvalidGlyph && glyphIndex > lastLine.glyphIndex)
|
if (glyphIndex != InvalidGlyph && glyphIndex > lastLine.glyphIndex)
|
||||||
{
|
{
|
||||||
|
|
@ -102,12 +102,12 @@ namespace Nz
|
||||||
{
|
{
|
||||||
Glyph& glyph = m_glyphs[i];
|
Glyph& glyph = m_glyphs[i];
|
||||||
glyph.bounds.x -= glyphPosition;
|
glyph.bounds.x -= glyphPosition;
|
||||||
glyph.bounds.y += sizeInfo.lineHeight;
|
glyph.bounds.y += lineHeight;
|
||||||
|
|
||||||
for (auto& corner : glyph.corners)
|
for (auto& corner : glyph.corners)
|
||||||
{
|
{
|
||||||
corner.x -= glyphPosition;
|
corner.x -= glyphPosition;
|
||||||
corner.y += sizeInfo.lineHeight;
|
corner.y += lineHeight;
|
||||||
}
|
}
|
||||||
|
|
||||||
newLine.bounds.ExtendTo(glyph.bounds);
|
newLine.bounds.ExtendTo(glyph.bounds);
|
||||||
|
|
@ -118,10 +118,10 @@ namespace Nz
|
||||||
|
|
||||||
lastLine.bounds.width -= lastLine.bounds.GetMaximum().x - glyphPosition;
|
lastLine.bounds.width -= lastLine.bounds.GetMaximum().x - glyphPosition;
|
||||||
|
|
||||||
// Regenerate working bounds
|
// Regenerate bounds
|
||||||
m_workingBounds.MakeZero();
|
m_bounds.MakeZero();
|
||||||
for (std::size_t i = 0; i < m_lines.size(); ++i)
|
for (auto& line : m_lines)
|
||||||
m_workingBounds.ExtendTo(m_lines[i].bounds);
|
m_bounds.ExtendTo(line.bounds);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -129,36 +129,19 @@ namespace Nz
|
||||||
{
|
{
|
||||||
m_bounds.MakeZero();
|
m_bounds.MakeZero();
|
||||||
m_colorUpdated = true;
|
m_colorUpdated = true;
|
||||||
m_drawPos.Set(0, m_characterSize); //< Our draw "cursor"
|
m_drawPos.Set(0, float(m_characterSize)); //< Our draw "cursor"
|
||||||
m_lastSeparatorGlyph = InvalidGlyph;
|
m_lastSeparatorGlyph = InvalidGlyph;
|
||||||
m_lines.clear();
|
m_lines.clear();
|
||||||
m_glyphs.clear();
|
m_glyphs.clear();
|
||||||
m_glyphUpdated = true;
|
m_glyphUpdated = true;
|
||||||
m_previousCharacter = 0;
|
m_previousCharacter = 0;
|
||||||
m_workingBounds.MakeZero(); //< Compute bounds as float to speedup bounds computation (as casting between floats and integers is costly)
|
|
||||||
|
|
||||||
if (m_font)
|
if (m_font)
|
||||||
m_lines.emplace_back(Line{Rectf(0.f, 0.f, 0.f, float(m_font->GetSizeInfo(m_characterSize).lineHeight)), 0});
|
m_lines.emplace_back(Line{Rectf(0.f, 0.f, 0.f, GetLineHeight()), 0});
|
||||||
else
|
else
|
||||||
m_lines.emplace_back(Line{Rectf::Zero(), 0});
|
m_lines.emplace_back(Line{Rectf::Zero(), 0});
|
||||||
}
|
}
|
||||||
|
|
||||||
void SimpleTextDrawer::ConnectFontSlots()
|
|
||||||
{
|
|
||||||
m_atlasChangedSlot.Connect(m_font->OnFontAtlasChanged, this, &SimpleTextDrawer::OnFontInvalidated);
|
|
||||||
m_atlasLayerChangedSlot.Connect(m_font->OnFontAtlasLayerChanged, this, &SimpleTextDrawer::OnFontAtlasLayerChanged);
|
|
||||||
m_fontReleaseSlot.Connect(m_font->OnFontRelease, this, &SimpleTextDrawer::OnFontRelease);
|
|
||||||
m_glyphCacheClearedSlot.Connect(m_font->OnFontGlyphCacheCleared, this, &SimpleTextDrawer::OnFontInvalidated);
|
|
||||||
}
|
|
||||||
|
|
||||||
void SimpleTextDrawer::DisconnectFontSlots()
|
|
||||||
{
|
|
||||||
m_atlasChangedSlot.Disconnect();
|
|
||||||
m_atlasLayerChangedSlot.Disconnect();
|
|
||||||
m_fontReleaseSlot.Disconnect();
|
|
||||||
m_glyphCacheClearedSlot.Disconnect();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool SimpleTextDrawer::GenerateGlyph(Glyph& glyph, char32_t character, float outlineThickness, bool lineWrap, Nz::Color color, int renderOrder, int* advance) const
|
bool SimpleTextDrawer::GenerateGlyph(Glyph& glyph, char32_t character, float outlineThickness, bool lineWrap, Nz::Color color, int renderOrder, int* advance) const
|
||||||
{
|
{
|
||||||
const Font::Glyph& fontGlyph = m_font->GetGlyph(m_characterSize, m_style, outlineThickness, character);
|
const Font::Glyph& fontGlyph = m_font->GetGlyph(m_characterSize, m_style, outlineThickness, character);
|
||||||
|
|
@ -223,16 +206,16 @@ namespace Nz
|
||||||
m_previousCharacter = character;
|
m_previousCharacter = character;
|
||||||
|
|
||||||
bool whitespace = true;
|
bool whitespace = true;
|
||||||
int advance = 0;
|
float advance = 0.f;
|
||||||
switch (character)
|
switch (character)
|
||||||
{
|
{
|
||||||
case ' ':
|
case ' ':
|
||||||
case '\n':
|
case '\n':
|
||||||
advance = sizeInfo.spaceAdvance;
|
advance = float(sizeInfo.spaceAdvance);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case '\t':
|
case '\t':
|
||||||
advance = sizeInfo.spaceAdvance * 4;
|
advance = float(sizeInfo.spaceAdvance) * 4.f;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
|
@ -243,27 +226,26 @@ namespace Nz
|
||||||
Glyph glyph;
|
Glyph glyph;
|
||||||
if (!whitespace)
|
if (!whitespace)
|
||||||
{
|
{
|
||||||
if (!GenerateGlyph(glyph, character, 0.f, true, m_color, 0, &advance))
|
int iAdvance;
|
||||||
|
if (!GenerateGlyph(glyph, character, 0.f, true, m_color, 0, &iAdvance))
|
||||||
continue; // Glyph failed to load, just skip it (can't do much)
|
continue; // Glyph failed to load, just skip it (can't do much)
|
||||||
|
|
||||||
|
advance = float(iAdvance);
|
||||||
|
|
||||||
if (m_outlineThickness > 0.f)
|
if (m_outlineThickness > 0.f)
|
||||||
{
|
{
|
||||||
Glyph outlineGlyph;
|
Glyph outlineGlyph;
|
||||||
if (GenerateGlyph(outlineGlyph, character, m_outlineThickness, false, m_outlineColor, -1, nullptr))
|
if (GenerateGlyph(outlineGlyph, character, m_outlineThickness, false, m_outlineColor, -1, nullptr))
|
||||||
{
|
|
||||||
m_glyphs.push_back(outlineGlyph);
|
m_glyphs.push_back(outlineGlyph);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
float glyphAdvance = advance;
|
if (ShouldLineWrap(advance))
|
||||||
|
|
||||||
if (ShouldLineWrap(glyphAdvance))
|
|
||||||
AppendNewLine(m_lastSeparatorGlyph, m_lastSeparatorPosition);
|
AppendNewLine(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(m_drawPos.x, m_lines.back().bounds.y, advance, GetLineHeight(sizeInfo));
|
||||||
|
|
||||||
glyph.corners[0].Set(glyph.bounds.GetCorner(RectCorner_LeftTop));
|
glyph.corners[0].Set(glyph.bounds.GetCorner(RectCorner_LeftTop));
|
||||||
glyph.corners[1].Set(glyph.bounds.GetCorner(RectCorner_RightTop));
|
glyph.corners[1].Set(glyph.bounds.GetCorner(RectCorner_RightTop));
|
||||||
|
|
@ -295,9 +277,7 @@ namespace Nz
|
||||||
m_glyphs.push_back(glyph);
|
m_glyphs.push_back(glyph);
|
||||||
}
|
}
|
||||||
|
|
||||||
m_workingBounds.ExtendTo(m_lines.back().bounds);
|
m_bounds.ExtendTo(m_lines.back().bounds);
|
||||||
|
|
||||||
m_bounds.Set(Rectf(std::floor(m_workingBounds.x), std::floor(m_workingBounds.y), std::ceil(m_workingBounds.width), std::ceil(m_workingBounds.height)));
|
|
||||||
|
|
||||||
m_colorUpdated = true;
|
m_colorUpdated = true;
|
||||||
m_glyphUpdated = true;
|
m_glyphUpdated = true;
|
||||||
|
|
@ -316,7 +296,7 @@ namespace Nz
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Update atlas layer pointer
|
// Update atlas layer pointer
|
||||||
// Note: This can happen while updating
|
// Note: This can happen while updating glyphs
|
||||||
for (Glyph& glyph : m_glyphs)
|
for (Glyph& glyph : m_glyphs)
|
||||||
{
|
{
|
||||||
if (glyph.atlas == oldLayer)
|
if (glyph.atlas == oldLayer)
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue