Merge branch 'master' into vulkan

This commit is contained in:
Lynix
2020-02-23 00:46:48 +01:00
382 changed files with 50494 additions and 5037 deletions

View File

@@ -22,6 +22,8 @@ namespace Nz
{
public:
AbstractAtlas() = default;
AbstractAtlas(const AbstractAtlas&) = delete;
AbstractAtlas(AbstractAtlas&&) noexcept = default;
virtual ~AbstractAtlas();
virtual void Clear() = 0;
@@ -31,6 +33,9 @@ namespace Nz
virtual UInt32 GetStorage() const = 0;
virtual bool Insert(const Image& image, Rectui* rect, bool* flipped, unsigned int* layerIndex) = 0;
AbstractAtlas& operator=(const AbstractAtlas&) = delete;
AbstractAtlas& operator=(AbstractAtlas&&) noexcept = default;
// Signals:
NazaraSignal(OnAtlasCleared, const AbstractAtlas* /*atlas*/);
NazaraSignal(OnAtlasLayerChange, const AbstractAtlas* /*atlas*/, AbstractImage* /*oldLayer*/, AbstractImage* /*newLayer*/);

View File

@@ -27,7 +27,9 @@ namespace Nz
AbstractTextDrawer() = default;
virtual ~AbstractTextDrawer();
virtual const Recti& GetBounds() const = 0;
virtual void Clear() = 0;
virtual const Rectf& GetBounds() const = 0;
virtual Font* GetFont(std::size_t index) const = 0;
virtual std::size_t GetFontCount() const = 0;
virtual const Glyph& GetGlyph(std::size_t index) const = 0;
@@ -35,6 +37,9 @@ namespace Nz
virtual const Line& GetLine(std::size_t index) const = 0;
virtual std::size_t GetLineCount() const = 0;
inline std::size_t GetLineGlyphCount(std::size_t index) const;
virtual float GetMaxLineWidth() const = 0;
virtual void SetMaxLineWidth(float lineWidth) = 0;
struct Glyph
{
@@ -44,6 +49,7 @@ namespace Nz
Vector2f corners[4];
AbstractImage* atlas;
bool flipped;
int renderOrder;
};
struct Line

View File

@@ -83,15 +83,15 @@ namespace Nz
bool IsLoopPointInterpolationEnabled() const;
bool IsValid() const;
bool LoadFromFile(const String& filePath, const AnimationParams& params = AnimationParams());
bool LoadFromMemory(const void* data, std::size_t size, const AnimationParams& params = AnimationParams());
bool LoadFromStream(Stream& stream, const AnimationParams& params = AnimationParams());
void RemoveSequence(const String& sequenceName);
void RemoveSequence(UInt32 index);
template<typename... Args> static AnimationRef New(Args&&... args);
static AnimationRef LoadFromFile(const String& filePath, const AnimationParams& params = AnimationParams());
static AnimationRef LoadFromMemory(const void* data, std::size_t size, const AnimationParams& params = AnimationParams());
static AnimationRef LoadFromStream(Stream& stream, const AnimationParams& params = AnimationParams());
// Signals:
NazaraSignal(OnAnimationDestroy, const Animation* /*animation*/);
NazaraSignal(OnAnimationRelease, const Animation* /*animation*/);

View File

@@ -330,18 +330,26 @@ namespace Nz
TextAlign_Max = TextAlign_Right
};
enum TextStyleFlags
enum TextStyle
{
TextStyle_Regular = 0x0,
TextStyle_Bold,
TextStyle_Italic,
TextStyle_StrikeThrough,
TextStyle_Underlined,
TextStyle_Bold = 0x1,
TextStyle_Italic = 0x2,
TextStyle_StrikeThrough = 0x4,
TextStyle_Underlined = 0x8,
TextStyle_Max = TextStyle_Underlined*2-1
TextStyle_Max = TextStyle_Underlined
};
template<>
struct EnumAsFlags<TextStyle>
{
static constexpr TextStyle max = TextStyle_Max;
};
using TextStyleFlags = Flags<TextStyle>;
constexpr TextStyleFlags TextStyle_Regular = 0;
enum VertexComponent
{
VertexComponent_Unused = -1,

View File

@@ -16,6 +16,7 @@
#include <Nazara/Core/ResourceLoader.hpp>
#include <Nazara/Core/ResourceParameters.hpp>
#include <Nazara/Utility/AbstractAtlas.hpp>
#include <Nazara/Utility/Enums.hpp>
#include <memory>
#include <unordered_map>
@@ -58,14 +59,14 @@ namespace Nz
bool Create(FontData* data);
void Destroy();
bool ExtractGlyph(unsigned int characterSize, char32_t character, UInt32 style, FontGlyph* glyph) const;
bool ExtractGlyph(unsigned int characterSize, char32_t character, TextStyleFlags style, float outlineThickness, FontGlyph* glyph) const;
const std::shared_ptr<AbstractAtlas>& GetAtlas() const;
std::size_t GetCachedGlyphCount(unsigned int characterSize, UInt32 style) const;
std::size_t GetCachedGlyphCount(unsigned int characterSize, TextStyleFlags style, float outlineThickness) const;
std::size_t GetCachedGlyphCount() const;
String GetFamilyName() const;
int GetKerning(unsigned int characterSize, char32_t first, char32_t second) const;
const Glyph& GetGlyph(unsigned int characterSize, UInt32 style, char32_t character) const;
const Glyph& GetGlyph(unsigned int characterSize, TextStyleFlags style, float outlineThickness, char32_t character) const;
unsigned int GetGlyphBorder() const;
unsigned int GetMinimumStepSize() const;
const SizeInfo& GetSizeInfo(unsigned int characterSize) const;
@@ -73,13 +74,8 @@ namespace Nz
bool IsValid() const;
bool Precache(unsigned int characterSize, UInt32 style, char32_t character) const;
bool Precache(unsigned int characterSize, UInt32 style, const String& characterSet) const;
// Open
bool OpenFromFile(const String& filePath, const FontParams& params = FontParams());
bool OpenFromMemory(const void* data, std::size_t size, const FontParams& params = FontParams());
bool OpenFromStream(Stream& stream, const FontParams& params = FontParams());
bool Precache(unsigned int characterSize, TextStyleFlags style, float outlineThickness, char32_t character) const;
bool Precache(unsigned int characterSize, TextStyleFlags style, float outlineThickness, const String& characterSet) const;
void SetAtlas(const std::shared_ptr<AbstractAtlas>& atlas);
void SetGlyphBorder(unsigned int borderSize);
@@ -93,6 +89,10 @@ namespace Nz
static unsigned int GetDefaultGlyphBorder();
static unsigned int GetDefaultMinimumStepSize();
static FontRef OpenFromFile(const String& filePath, const FontParams& params = FontParams());
static FontRef OpenFromMemory(const void* data, std::size_t size, const FontParams& params = FontParams());
static FontRef OpenFromStream(Stream& stream, const FontParams& params = FontParams());
template<typename... Args> static FontRef New(Args&&... args);
static void SetDefaultAtlas(const std::shared_ptr<AbstractAtlas>& atlas);
@@ -107,6 +107,7 @@ namespace Nz
bool requireFauxItalic;
bool flipped;
bool valid;
float fauxOutlineThickness;
int advance;
unsigned int layerIndex;
};
@@ -131,11 +132,11 @@ namespace Nz
private:
using GlyphMap = std::unordered_map<char32_t, Glyph>;
UInt64 ComputeKey(unsigned int characterSize, UInt32 style) const;
UInt64 ComputeKey(unsigned int characterSize, TextStyleFlags style, float outlineThickness) const;
void OnAtlasCleared(const AbstractAtlas* atlas);
void OnAtlasLayerChange(const AbstractAtlas* atlas, AbstractImage* oldLayer, AbstractImage* newLayer);
void OnAtlasRelease(const AbstractAtlas* atlas);
const Glyph& PrecacheGlyph(GlyphMap& glyphMap, unsigned int characterSize, UInt32 style, char32_t character) const;
const Glyph& PrecacheGlyph(GlyphMap& glyphMap, unsigned int characterSize, TextStyleFlags style, float outlineThickness, char32_t character) const;
static bool Initialize();
static void Uninitialize();

View File

@@ -10,6 +10,7 @@
#include <Nazara/Prerequisites.hpp>
#include <Nazara/Core/String.hpp>
#include <Nazara/Utility/Config.hpp>
#include <Nazara/Utility/Enums.hpp>
namespace Nz
{
@@ -21,7 +22,7 @@ namespace Nz
FontData() = default;
virtual ~FontData();
virtual bool ExtractGlyph(unsigned int characterSize, char32_t character, UInt32 style, FontGlyph* dst) = 0;
virtual bool ExtractGlyph(unsigned int characterSize, char32_t character, TextStyleFlags style, float outlineThickness, FontGlyph* dst) = 0;
virtual String GetFamilyName() const = 0;
virtual String GetStyleName() const = 0;
@@ -35,7 +36,8 @@ namespace Nz
virtual float QueryUnderlinePosition(unsigned int characterSize) const = 0;
virtual float QueryUnderlineThickness(unsigned int characterSize) const = 0;
virtual bool SupportsStyle(UInt32 style) const = 0;
virtual bool SupportsOutline(float outlineThickness) const = 0;
virtual bool SupportsStyle(TextStyleFlags style) const = 0;
};
}

View File

@@ -21,7 +21,9 @@ namespace Nz
{
public:
GuillotineImageAtlas();
virtual ~GuillotineImageAtlas();
GuillotineImageAtlas(const GuillotineImageAtlas&) = delete;
GuillotineImageAtlas(GuillotineImageAtlas&&) noexcept = default;
~GuillotineImageAtlas() = default;
void Clear() override;
@@ -38,6 +40,9 @@ namespace Nz
void SetRectChoiceHeuristic(GuillotineBinPack::FreeRectChoiceHeuristic heuristic);
void SetRectSplitHeuristic(GuillotineBinPack::GuillotineSplitHeuristic heuristic);
GuillotineImageAtlas& operator=(const GuillotineImageAtlas&) = delete;
GuillotineImageAtlas& operator=(GuillotineImageAtlas&&) noexcept = default;
protected:
struct Layer;

View File

@@ -63,7 +63,7 @@ namespace Nz
bool Convert(PixelFormatType format);
void Copy(const Image& source, const Boxui& srcBox, const Vector3ui& dstPos);
void Copy(const Image* source, const Boxui& srcBox, const Vector3ui& dstPos);
bool Create(ImageType type, PixelFormatType format, unsigned int width, unsigned int height, unsigned int depth = 1, UInt8 levelCount = 1);
void Destroy();
@@ -93,23 +93,6 @@ namespace Nz
bool IsValid() const;
// Load
bool LoadFromFile(const String& filePath, const ImageParams& params = ImageParams());
bool LoadFromMemory(const void* data, std::size_t size, const ImageParams& params = ImageParams());
bool LoadFromStream(Stream& stream, const ImageParams& params = ImageParams());
// LoadArray
bool LoadArrayFromFile(const String& filePath, const ImageParams& imageParams = ImageParams(), const Vector2ui& atlasSize = Vector2ui(2, 2));
bool LoadArrayFromImage(const Image& image, const Vector2ui& atlasSize = Vector2ui(2, 2));
bool LoadArrayFromMemory(const void* data, std::size_t size, const ImageParams& imageParams = ImageParams(), const Vector2ui& atlasSize = Vector2ui(2, 2));
bool LoadArrayFromStream(Stream& stream, const ImageParams& imageParams = ImageParams(), const Vector2ui& atlasSize = Vector2ui(2, 2));
// LoadCubemap
bool LoadCubemapFromFile(const String& filePath, const ImageParams& imageParams = ImageParams(), const CubemapParams& cubemapParams = CubemapParams());
bool LoadCubemapFromImage(const Image& image, const CubemapParams& params = CubemapParams());
bool LoadCubemapFromMemory(const void* data, std::size_t size, const ImageParams& imageParams = ImageParams(), const CubemapParams& cubemapParams = CubemapParams());
bool LoadCubemapFromStream(Stream& stream, const ImageParams& imageParams = ImageParams(), const CubemapParams& cubemapParams = CubemapParams());
// LoadFace
bool LoadFaceFromFile(CubemapFace face, const String& filePath, const ImageParams& params = ImageParams());
bool LoadFaceFromMemory(CubemapFace face, const void* data, std::size_t size, const ImageParams& params = ImageParams());
@@ -133,6 +116,24 @@ namespace Nz
static void Copy(UInt8* destination, const UInt8* source, PixelFormatType format, unsigned int width, unsigned int height, unsigned int depth = 1, unsigned int dstWidth = 0, unsigned int dstHeight = 0, unsigned int srcWidth = 0, unsigned int srcHeight = 0);
static UInt8 GetMaxLevel(unsigned int width, unsigned int height, unsigned int depth = 1);
static UInt8 GetMaxLevel(ImageType type, unsigned int width, unsigned int height, unsigned int depth = 1);
// Load
static ImageRef LoadFromFile(const String& filePath, const ImageParams& params = ImageParams());
static ImageRef LoadFromMemory(const void* data, std::size_t size, const ImageParams& params = ImageParams());
static ImageRef LoadFromStream(Stream& stream, const ImageParams& params = ImageParams());
// LoadArray
static ImageRef LoadArrayFromFile(const String& filePath, const ImageParams& imageParams = ImageParams(), const Vector2ui& atlasSize = Vector2ui(2, 2));
static ImageRef LoadArrayFromImage(const Image* image, const Vector2ui& atlasSize = Vector2ui(2, 2));
static ImageRef LoadArrayFromMemory(const void* data, std::size_t size, const ImageParams& imageParams = ImageParams(), const Vector2ui& atlasSize = Vector2ui(2, 2));
static ImageRef LoadArrayFromStream(Stream& stream, const ImageParams& imageParams = ImageParams(), const Vector2ui& atlasSize = Vector2ui(2, 2));
// LoadCubemap
static ImageRef LoadCubemapFromFile(const String& filePath, const ImageParams& imageParams = ImageParams(), const CubemapParams& cubemapParams = CubemapParams());
static ImageRef LoadCubemapFromImage(const Image* image, const CubemapParams& params = CubemapParams());
static ImageRef LoadCubemapFromMemory(const void* data, std::size_t size, const ImageParams& imageParams = ImageParams(), const CubemapParams& cubemapParams = CubemapParams());
static ImageRef LoadCubemapFromStream(Stream& stream, const ImageParams& imageParams = ImageParams(), const CubemapParams& cubemapParams = CubemapParams());
template<typename... Args> static ImageRef New(Args&&... args);
struct SharedImage

View File

@@ -60,6 +60,7 @@ namespace Nz
static constexpr const char* StencilTest = "MatStencilTest";
static constexpr const char* StencilZFail = "MatStencilZFail";
static constexpr const char* Transform = "MatTransform";
static constexpr const char* VertexColor = "MatVertexColor";
};
}

View File

@@ -128,10 +128,6 @@ namespace Nz
bool IsAnimable() const;
bool IsValid() const;
bool LoadFromFile(const String& filePath, const MeshParams& params = MeshParams());
bool LoadFromMemory(const void* data, std::size_t size, const MeshParams& params = MeshParams());
bool LoadFromStream(Stream& stream, const MeshParams& params = MeshParams());
void Recenter();
void RemoveSubMesh(const String& identifier);
@@ -149,6 +145,10 @@ namespace Nz
Mesh& operator=(const Mesh&) = delete;
Mesh& operator=(Mesh&&) = delete;
static MeshRef LoadFromFile(const String& filePath, const MeshParams& params = MeshParams());
static MeshRef LoadFromMemory(const void* data, std::size_t size, const MeshParams& params = MeshParams());
static MeshRef LoadFromStream(Stream& stream, const MeshParams& params = MeshParams());
template<typename... Args> static MeshRef New(Args&&... args);
// Signals:

View File

@@ -41,10 +41,10 @@ namespace Nz
virtual Vector3f GetLeft() const;
virtual NodeType GetNodeType() const;
const Node* GetParent() const;
Vector3f GetPosition(CoordSys coordSys = CoordSys_Global) const;
Vector3f GetPosition(CoordSys coordSys = CoordSys_Local) const;
virtual Vector3f GetRight() const;
Quaternionf GetRotation(CoordSys coordSys = CoordSys_Global) const;
Vector3f GetScale(CoordSys coordSys = CoordSys_Global) const;
Quaternionf GetRotation(CoordSys coordSys = CoordSys_Local) const;
Vector3f GetScale(CoordSys coordSys = CoordSys_Local) const;
const Matrix4f& GetTransformMatrix() const;
virtual Vector3f GetUp() const;
@@ -75,6 +75,7 @@ namespace Nz
void SetPosition(const Vector3f& translation, CoordSys coordSys = CoordSys_Local);
void SetPosition(float translationX, float translationY, float translationZ = 0.f, CoordSys coordSys = CoordSys_Local);
void SetRotation(const Quaternionf& quat, CoordSys coordSys = CoordSys_Local);
void SetScale(const Vector2f& scale, CoordSys coordSys = CoordSys_Local);
void SetScale(const Vector3f& scale, CoordSys coordSys = CoordSys_Local);
void SetScale(float scale, CoordSys coordSys = CoordSys_Local);
void SetScale(float scaleX, float scaleY, float scaleZ = 1.f, CoordSys coordSys = CoordSys_Local);
@@ -105,6 +106,8 @@ namespace Nz
virtual void UpdateDerived() const;
virtual void UpdateTransformMatrix() const;
static Quaternionf ScaleQuaternion(const Vector3f& scale, Quaternionf quaternion);
mutable std::vector<Node*> m_childs;
mutable Matrix4f m_transformMatrix;
mutable Quaternionf m_derivedRotation;

View File

@@ -0,0 +1,212 @@
// Copyright (C) 2016 Jérôme Leclercq
// This file is part of the "Nazara Engine - Utility module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#pragma once
#ifndef NAZARA_RICHTEXTDRAWER_HPP
#define NAZARA_RICHTEXTDRAWER_HPP
#include <Nazara/Prerequisites.hpp>
#include <Nazara/Core/String.hpp>
#include <Nazara/Utility/AbstractTextDrawer.hpp>
#include <Nazara/Utility/Enums.hpp>
#include <Nazara/Utility/Font.hpp>
#include <vector>
namespace Nz
{
class NAZARA_UTILITY_API RichTextDrawer : public AbstractTextDrawer
{
public:
class BlockRef;
RichTextDrawer();
RichTextDrawer(const RichTextDrawer& drawer);
RichTextDrawer(RichTextDrawer&& drawer);
~RichTextDrawer();
BlockRef AppendText(const String& str, bool forceNewBlock = false);
void Clear() override;
inline std::size_t FindBlock(std::size_t glyphIndex) const;
inline unsigned int GetBlockCharacterSize(std::size_t index) const;
inline float GetBlockCharacterSpacingOffset(std::size_t index) const;
inline const Color& GetBlockColor(std::size_t index) const;
inline std::size_t GetBlockCount() const;
inline std::size_t GetBlockFirstGlyphIndex(std::size_t index) const;
inline const FontRef& GetBlockFont(std::size_t index) const;
inline float GetBlockLineHeight(std::size_t index) const;
inline float GetBlockLineSpacingOffset(std::size_t index) const;
inline const Color& GetBlockOutlineColor(std::size_t index) const;
inline float GetBlockOutlineThickness(std::size_t index) const;
inline TextStyleFlags GetBlockStyle(std::size_t index) const;
inline const String& GetBlockText(std::size_t index) const;
inline BlockRef GetBlock(std::size_t index);
const Rectf& GetBounds() const override;
inline unsigned int GetDefaultCharacterSize() const;
inline float GetDefaultCharacterSpacingOffset() const;
inline const Color& GetDefaultColor() const;
inline const FontRef& GetDefaultFont() const;
inline float GetDefaultLineSpacingOffset() const;
inline const Color& GetDefaultOutlineColor() const;
inline float GetDefaultOutlineThickness() const;
inline TextStyleFlags GetDefaultStyle() const;
Font* GetFont(std::size_t index) const override;
std::size_t GetFontCount() const override;
const Glyph& GetGlyph(std::size_t index) const override;
std::size_t GetGlyphCount() const override;
const Line& GetLine(std::size_t index) const override;
std::size_t GetLineCount() const override;
float GetMaxLineWidth() const override;
inline bool HasBlocks() const;
void MergeBlocks();
void RemoveBlock(std::size_t index);
inline void SetBlockCharacterSize(std::size_t index, unsigned int characterSize);
inline void SetBlockCharacterSpacingOffset(std::size_t index, float offset);
inline void SetBlockColor(std::size_t index, const Color& color);
inline void SetBlockFont(std::size_t index, FontRef font);
inline void SetBlockLineSpacingOffset(std::size_t index, float offset);
inline void SetBlockOutlineColor(std::size_t index, const Color& color);
inline void SetBlockOutlineThickness(std::size_t index, float thickness);
inline void SetBlockStyle(std::size_t index, TextStyleFlags style);
inline void SetBlockText(std::size_t index, String str);
inline void SetDefaultCharacterSize(unsigned int characterSize);
inline void SetDefaultCharacterSpacingOffset(float offset);
inline void SetDefaultColor(const Color& color);
inline void SetDefaultFont(const FontRef& font);
inline void SetDefaultLineSpacingOffset(float offset);
inline void SetDefaultOutlineColor(const Color& color);
inline void SetDefaultOutlineThickness(float thickness);
inline void SetDefaultStyle(TextStyleFlags style);
void SetMaxLineWidth(float lineWidth) override;
RichTextDrawer& operator=(const RichTextDrawer& drawer);
RichTextDrawer& operator=(RichTextDrawer&& drawer);
static constexpr std::size_t InvalidBlockIndex = std::numeric_limits<std::size_t>::max();
private:
struct Block;
inline void AppendNewLine(const Font* font, unsigned int characterSize, float lineSpacingOffset) const;
void AppendNewLine(const Font* font, unsigned int characterSize, float lineSpacingOffset, std::size_t glyphIndex, float 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, float lineSpacingOffset, 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 characterSpacingOffset, float lineSpacingOffset, float outlineThickness, const String& text) const;
inline float GetLineHeight(const Block& block) const;
inline float GetLineHeight(float lineSpacingOffset, const Font::SizeInfo& sizeInfo) const;
inline std::size_t HandleFontAddition(const FontRef& font);
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);
void OnFontRelease(const Font* object);
void UpdateGlyphs() const;
static constexpr std::size_t InvalidGlyph = std::numeric_limits<std::size_t>::max();
struct Block
{
std::size_t fontIndex;
std::size_t glyphIndex;
Color color;
Color outlineColor;
String text;
TextStyleFlags style;
float characterSpacingOffset;
float lineSpacingOffset;
float outlineThickness;
unsigned int characterSize;
};
struct FontData
{
FontRef font;
std::size_t useCount = 0;
NazaraSlot(Font, OnFontAtlasChanged, atlasChangedSlot);
NazaraSlot(Font, OnFontAtlasLayerChanged, atlasLayerChangedSlot);
NazaraSlot(Font, OnFontGlyphCacheCleared, glyphCacheClearedSlot);
NazaraSlot(Font, OnFontRelease, fontReleaseSlot);
};
Color m_defaultColor;
Color m_defaultOutlineColor;
TextStyleFlags m_defaultStyle;
FontRef m_defaultFont;
mutable std::size_t m_lastSeparatorGlyph;
std::unordered_map<FontRef, std::size_t> m_fontIndexes;
std::vector<Block> m_blocks;
std::vector<FontData> m_fonts;
mutable std::vector<Glyph> m_glyphs;
mutable std::vector<Line> m_lines;
mutable Rectf m_bounds;
mutable Vector2f m_drawPos;
mutable bool m_glyphUpdated;
float m_defaultCharacterSpacingOffset;
float m_defaultLineSpacingOffset;
float m_defaultOutlineThickness;
float m_maxLineWidth;
unsigned int m_defaultCharacterSize;
mutable float m_lastSeparatorPosition;
};
class RichTextDrawer::BlockRef
{
friend RichTextDrawer;
public:
BlockRef(const BlockRef&) = default;
BlockRef(BlockRef&&) = default;
~BlockRef() = default;
inline float GetCharacterSpacingOffset() const;
inline unsigned int GetCharacterSize() const;
inline Color GetColor() const;
inline std::size_t GetFirstGlyphIndex() const;
inline const FontRef& GetFont() const;
inline float GetLineSpacingOffset() const;
inline Color GetOutlineColor() const;
inline float GetOutlineThickness() const;
inline TextStyleFlags GetStyle() const;
inline const String& GetText() const;
inline void SetCharacterSpacingOffset(float offset);
inline void SetCharacterSize(unsigned int size);
inline void SetColor(Color color);
inline void SetFont(FontRef font);
inline void SetLineSpacingOffset(float offset);
inline void SetOutlineColor(Color color);
inline void SetOutlineThickness(float thickness);
inline void SetStyle(TextStyleFlags style);
inline void SetText(const String& text);
BlockRef& operator=(const BlockRef&) = default;
BlockRef& operator=(BlockRef&&) = default;
private:
inline BlockRef(RichTextDrawer& drawer, std::size_t index);
std::size_t m_blockIndex;
RichTextDrawer& m_drawer;
};
}
#include <Nazara/Utility/RichTextDrawer.inl>
#endif // NAZARA_RICHTEXTDRAWER_HPP

View File

@@ -0,0 +1,631 @@
// Copyright (C) 2016 Jérôme Leclercq
// This file is part of the "Nazara Engine - Utility module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Utility/RichTextDrawer.hpp>
#include <Nazara/Utility/Debug.hpp>
namespace Nz
{
inline std::size_t RichTextDrawer::FindBlock(std::size_t glyphIndex) const
{
auto it = m_blocks.begin();
for (; it != m_blocks.end(); ++it)
{
if (it->glyphIndex > glyphIndex)
break;
}
assert(it != m_blocks.begin());
return std::distance(m_blocks.begin(), it) - 1;
/*
// Binary search
std::size_t count = m_blocks.size();
std::size_t step;
std::size_t i = InvalidBlockIndex;
std::size_t first = 0;
std::size_t last = count;
while (count > 0)
{
i = first;
step = count / 2;
i += step;
if (m_blocks[i].glyphIndex < glyphIndex)
{
first = ++i;
count -= step + 1;
}
else
count = step;
}
return i;*/
}
inline auto RichTextDrawer::GetBlock(std::size_t index) -> BlockRef
{
NazaraAssert(index < m_blocks.size(), "Invalid block index");
return BlockRef(*this, index);
}
inline unsigned int RichTextDrawer::GetBlockCharacterSize(std::size_t index) const
{
NazaraAssert(index < m_blocks.size(), "Invalid block index");
return m_blocks[index].characterSize;
}
inline float RichTextDrawer::GetBlockCharacterSpacingOffset(std::size_t index) const
{
NazaraAssert(index < m_blocks.size(), "Invalid block index");
return m_blocks[index].characterSpacingOffset;
}
inline const Color& RichTextDrawer::GetBlockColor(std::size_t index) const
{
NazaraAssert(index < m_blocks.size(), "Invalid block index");
return m_blocks[index].color;
}
inline std::size_t RichTextDrawer::GetBlockCount() const
{
return m_blocks.size();
}
inline std::size_t RichTextDrawer::GetBlockFirstGlyphIndex(std::size_t index) const
{
NazaraAssert(index < m_blocks.size(), "Invalid block index");
return m_blocks[index].glyphIndex;
}
inline const FontRef& RichTextDrawer::GetBlockFont(std::size_t index) const
{
NazaraAssert(index < m_blocks.size(), "Invalid block index");
std::size_t fontIndex = m_blocks[index].fontIndex;
assert(fontIndex < m_fonts.size());
return m_fonts[fontIndex].font;
}
inline float RichTextDrawer::GetBlockLineHeight(std::size_t index) const
{
NazaraAssert(index < m_blocks.size(), "Invalid block index");
return m_blocks[index].lineSpacingOffset;
}
inline float RichTextDrawer::GetBlockLineSpacingOffset(std::size_t index) const
{
NazaraAssert(index < m_blocks.size(), "Invalid block index");
return m_blocks[index].lineSpacingOffset;
}
inline const Color& RichTextDrawer::GetBlockOutlineColor(std::size_t index) const
{
NazaraAssert(index < m_blocks.size(), "Invalid block index");
return m_blocks[index].outlineColor;
}
inline float RichTextDrawer::GetBlockOutlineThickness(std::size_t index) const
{
NazaraAssert(index < m_blocks.size(), "Invalid block index");
return m_blocks[index].outlineThickness;
}
inline TextStyleFlags RichTextDrawer::GetBlockStyle(std::size_t index) const
{
NazaraAssert(index < m_blocks.size(), "Invalid block index");
return m_blocks[index].style;
}
inline const String& RichTextDrawer::GetBlockText(std::size_t index) const
{
NazaraAssert(index < m_blocks.size(), "Invalid block index");
return m_blocks[index].text;
}
inline unsigned int RichTextDrawer::GetDefaultCharacterSize() const
{
return m_defaultCharacterSize;
}
inline float RichTextDrawer::GetDefaultCharacterSpacingOffset() const
{
return m_defaultCharacterSpacingOffset;
}
inline const Color& RichTextDrawer::GetDefaultColor() const
{
return m_defaultColor;
}
inline const FontRef& RichTextDrawer::GetDefaultFont() const
{
return m_defaultFont;
}
inline float RichTextDrawer::GetDefaultLineSpacingOffset() const
{
return m_defaultLineSpacingOffset;
}
inline const Color& RichTextDrawer::GetDefaultOutlineColor() const
{
return m_defaultOutlineColor;
}
inline float RichTextDrawer::GetDefaultOutlineThickness() const
{
return m_defaultOutlineThickness;
}
inline TextStyleFlags RichTextDrawer::GetDefaultStyle() const
{
return m_defaultStyle;
}
inline void RichTextDrawer::AppendNewLine(const Font* font, unsigned int characterSize, float lineSpacingOffset) const
{
AppendNewLine(font, characterSize, lineSpacingOffset, InvalidGlyph, 0);
}
inline void RichTextDrawer::ClearGlyphs() const
{
m_bounds.MakeZero();
m_lastSeparatorGlyph = InvalidGlyph;
m_lines.clear();
m_glyphs.clear();
m_glyphUpdated = true;
m_bounds.MakeZero(); //< Compute bounds as float to speedup bounds computation (as casting between floats and integers is costly)
}
inline void RichTextDrawer::ConnectFontSlots()
{
for (auto& fontData : m_fonts)
{
fontData.atlasChangedSlot.Connect(fontData.font->OnFontAtlasChanged, this, &RichTextDrawer::OnFontInvalidated);
fontData.atlasLayerChangedSlot.Connect(fontData.font->OnFontAtlasLayerChanged, this, &RichTextDrawer::OnFontAtlasLayerChanged);
fontData.fontReleaseSlot.Connect(fontData.font->OnFontDestroy, this, &RichTextDrawer::OnFontRelease);
fontData.glyphCacheClearedSlot.Connect(fontData.font->OnFontGlyphCacheCleared, this, &RichTextDrawer::OnFontInvalidated);
}
}
inline void RichTextDrawer::DisconnectFontSlots()
{
for (auto& fontData : m_fonts)
{
fontData.atlasChangedSlot.Disconnect();
fontData.atlasLayerChangedSlot.Disconnect();
fontData.fontReleaseSlot.Disconnect();
fontData.glyphCacheClearedSlot.Disconnect();
}
}
inline float RichTextDrawer::GetLineHeight(const Block& block) const
{
assert(block.fontIndex < m_fonts.size());
const FontData& fontData = m_fonts[block.fontIndex];
return GetLineHeight(block.lineSpacingOffset, fontData.font->GetSizeInfo(block.characterSize));
}
inline float RichTextDrawer::GetLineHeight(float lineSpacingOffset, const Font::SizeInfo& sizeInfo) const
{
return float(sizeInfo.lineHeight) + lineSpacingOffset;
}
inline std::size_t RichTextDrawer::HandleFontAddition(const FontRef& font)
{
auto it = m_fontIndexes.find(font);
if (it == m_fontIndexes.end())
{
std::size_t fontIndex = m_fonts.size();
m_fonts.emplace_back();
auto& fontData = m_fonts.back();
fontData.font = font;
fontData.atlasChangedSlot.Connect(font->OnFontAtlasChanged, this, &RichTextDrawer::OnFontInvalidated);
fontData.atlasLayerChangedSlot.Connect(font->OnFontAtlasLayerChanged, this, &RichTextDrawer::OnFontAtlasLayerChanged);
fontData.fontReleaseSlot.Connect(font->OnFontDestroy, this, &RichTextDrawer::OnFontRelease);
fontData.glyphCacheClearedSlot.Connect(font->OnFontGlyphCacheCleared, this, &RichTextDrawer::OnFontInvalidated);
it = m_fontIndexes.emplace(font, fontIndex).first;
}
return it->second;
}
inline void RichTextDrawer::ReleaseFont(std::size_t fontIndex)
{
assert(fontIndex < m_fonts.size());
FontData& fontData = m_fonts[fontIndex];
assert(fontData.useCount > 0);
if (--fontData.useCount == 0)
{
// Shift font indexes
m_fontIndexes.erase(fontData.font);
for (auto& fontIndexe : m_fontIndexes)
{
if (fontIndexe.second > fontIndex)
fontIndexe.second--;
}
m_fonts.erase(m_fonts.begin() + fontIndex);
}
}
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();
}
inline void RichTextDrawer::SetBlockCharacterSize(std::size_t index, unsigned int characterSize)
{
NazaraAssert(index < m_blocks.size(), "Invalid block index");
m_blocks[index].characterSize = characterSize;
InvalidateGlyphs();
}
inline void RichTextDrawer::SetBlockCharacterSpacingOffset(std::size_t index, float offset)
{
NazaraAssert(index < m_blocks.size(), "Invalid block index");
m_blocks[index].characterSpacingOffset = offset;
InvalidateGlyphs();
}
inline void RichTextDrawer::SetBlockColor(std::size_t index, const Color& color)
{
NazaraAssert(index < m_blocks.size(), "Invalid block index");
m_blocks[index].color = color;
InvalidateGlyphs();
}
inline void RichTextDrawer::SetBlockFont(std::size_t index, FontRef font)
{
NazaraAssert(index < m_blocks.size(), "Invalid block index");
std::size_t fontIndex = HandleFontAddition(font);
std::size_t oldFontIndex = m_blocks[index].fontIndex;
if (oldFontIndex != fontIndex)
{
ReleaseFont(oldFontIndex);
m_fonts[fontIndex].useCount++;
m_blocks[index].fontIndex = fontIndex;
}
InvalidateGlyphs();
}
inline void RichTextDrawer::SetBlockLineSpacingOffset(std::size_t index, float offset)
{
NazaraAssert(index < m_blocks.size(), "Invalid block index");
m_blocks[index].lineSpacingOffset = offset;
InvalidateGlyphs();
}
inline void RichTextDrawer::SetBlockOutlineColor(std::size_t index, const Color& color)
{
NazaraAssert(index < m_blocks.size(), "Invalid block index");
m_blocks[index].outlineColor = color;
InvalidateGlyphs();
}
inline void RichTextDrawer::SetBlockOutlineThickness(std::size_t index, float thickness)
{
NazaraAssert(index < m_blocks.size(), "Invalid block index");
m_blocks[index].outlineThickness = thickness;
InvalidateGlyphs();
}
inline void RichTextDrawer::SetBlockStyle(std::size_t index, TextStyleFlags style)
{
NazaraAssert(index < m_blocks.size(), "Invalid block index");
m_blocks[index].style = style;
InvalidateGlyphs();
}
inline void RichTextDrawer::SetBlockText(std::size_t index, String str)
{
NazaraAssert(index < m_blocks.size(), "Invalid block index");
std::size_t previousLength = m_blocks[index].text.GetLength();
m_blocks[index].text = std::move(str);
std::size_t newLength = m_blocks[index].text.GetLength();
if (newLength != previousLength)
{
std::size_t delta = newLength - previousLength; //< Underflow allowed
for (std::size_t i = index + 1; i < m_blocks.size(); ++i)
m_blocks[i].glyphIndex += delta;
}
InvalidateGlyphs();
}
inline void RichTextDrawer::SetDefaultCharacterSize(unsigned int characterSize)
{
m_defaultCharacterSize = characterSize;
}
inline void RichTextDrawer::SetDefaultCharacterSpacingOffset(float offset)
{
m_defaultCharacterSpacingOffset = offset;
}
inline void RichTextDrawer::SetDefaultColor(const Color& color)
{
m_defaultColor = color;
}
inline void RichTextDrawer::SetDefaultFont(const FontRef& font)
{
m_defaultFont = font;
}
inline void RichTextDrawer::SetDefaultLineSpacingOffset(float offset)
{
m_defaultLineSpacingOffset = offset;
}
inline void RichTextDrawer::SetDefaultOutlineColor(const Color& color)
{
m_defaultOutlineColor = color;
}
inline void RichTextDrawer::SetDefaultOutlineThickness(float thickness)
{
m_defaultOutlineThickness = thickness;
}
inline void RichTextDrawer::SetDefaultStyle(TextStyleFlags style)
{
m_defaultStyle = style;
}
inline void RichTextDrawer::InvalidateGlyphs()
{
m_glyphUpdated = false;
}
/*!
* \class Nz::RichTextDrawer::BlockRef
* \brief Helper class representing a block inside a RichTextDrawer, allowing easier access.
*
* \warning This class is meant for temporary use, moving or destroying the RichTextDrawer or one of its blocks invalidates all BlockRef
*/
inline RichTextDrawer::BlockRef::BlockRef(RichTextDrawer& drawer, std::size_t index) :
m_blockIndex(index),
m_drawer(drawer)
{
}
/*!
* Returns the character spacing offset used for the characters of the referenced block
* \return The referenced block character size
*
* \see GetColor, GetFont, GetStyle, GetText, SetCharacterSize
*/
inline float RichTextDrawer::BlockRef::GetCharacterSpacingOffset() const
{
return m_drawer.GetBlockCharacterSpacingOffset(m_blockIndex);
}
/*!
* Returns the character size used for the characters of the referenced block
* \return The referenced block character size
*
* \see GetColor, GetFont, GetStyle, GetText, SetCharacterSize
*/
inline unsigned int RichTextDrawer::BlockRef::GetCharacterSize() const
{
return m_drawer.GetBlockCharacterSize(m_blockIndex);
}
/*!
* Returns the color used for the characters of the referenced block
* \return The referenced block color
*
* \see GetCharacterSize, GetFont, GetStyle, GetText, SetColor
*/
inline Color RichTextDrawer::BlockRef::GetColor() const
{
return m_drawer.GetBlockColor(m_blockIndex);
}
/*!
* Returns the font used for the characters of the referenced block
* \return A reference on the referenced block font
*
* \see GetCharacterSize, GetColor, GetStyle, GetText, SetFont
*/
inline const FontRef& RichTextDrawer::BlockRef::GetFont() const
{
return m_drawer.GetBlockFont(m_blockIndex);
}
/*!
* Returns the line spacing offset used for the characters of the referenced block
* \return The referenced block character size
*
* \see GetColor, GetFont, GetStyle, GetText, SetCharacterSize
*/
inline float RichTextDrawer::BlockRef::GetLineSpacingOffset() const
{
return m_drawer.GetBlockLineSpacingOffset(m_blockIndex);
}
/*!
* Returns the outline color used for the characters of the referenced block
* \return The referenced block outline color
*
* \see GetCharacterSize, GetColor, GetStyle, GetText, SetFont
*/
inline Color RichTextDrawer::BlockRef::GetOutlineColor() const
{
return m_drawer.GetBlockOutlineColor(m_blockIndex);
}
/*!
* Returns the outline thickness used for the characters of the referenced block
* \return The referenced block outline thickness
*
* \see GetCharacterSize, GetColor, GetStyle, GetText, SetFont
*/
inline float RichTextDrawer::BlockRef::GetOutlineThickness() const
{
return m_drawer.GetBlockOutlineThickness(m_blockIndex);
}
/*!
* Returns the style flags used for the characters of the referenced block
* \return The referenced block style flags (see TextStyleFlags)
*
* \see GetCharacterSize, GetColor, GetFont, GetText, SetStyle
*/
inline TextStyleFlags RichTextDrawer::BlockRef::GetStyle() const
{
return m_drawer.GetBlockStyle(m_blockIndex);
}
/*!
* Returns the first glyph index at which starts the referenced block
* \return The first glyph index concerned by this block
*
* \see GetText
*/
inline std::size_t RichTextDrawer::BlockRef::GetFirstGlyphIndex() const
{
return m_drawer.GetBlockFirstGlyphIndex(m_blockIndex);
}
/*!
* Returns the text of the referenced block
* \return The referenced block text
*
* \see GetCharacterSize, GetColor, GetFont, GetStyle, SetText
*/
inline const String& RichTextDrawer::BlockRef::GetText() const
{
return m_drawer.GetBlockText(m_blockIndex);
}
/*!
* Changes the character spacing offset of the referenced block characters
* \remark This invalidates the drawer and will force a (complete or partial, depending on the block index) glyph regeneration to occur.
*
* \see GetCharacterSpacingOffset, SetColor, SetFont, SetStyle, SetText
*/
inline void RichTextDrawer::BlockRef::SetCharacterSpacingOffset(float offset)
{
m_drawer.SetBlockCharacterSpacingOffset(m_blockIndex, offset);
}
/*!
* Changes the character size of the referenced block characters
* \remark This invalidates the drawer and will force a (complete or partial, depending on the block index) glyph regeneration to occur.
*
* \see GetCharacterSize, SetColor, SetFont, SetStyle, SetText
*/
inline void RichTextDrawer::BlockRef::SetCharacterSize(unsigned int size)
{
m_drawer.SetBlockCharacterSize(m_blockIndex, size);
}
/*!
* Changes the color of the referenced block characters
* \remark This is the only property that can be changed without forcing a glyph regeneration
*
* \see GetColor, SetCharacterSize, SetFont, SetStyle, SetText
*/
inline void RichTextDrawer::BlockRef::SetColor(Color color)
{
m_drawer.SetBlockColor(m_blockIndex, color);
}
/*!
* Changes the font of the referenced block characters
* \remark This invalidates the drawer and will force a (complete or partial, depending on the block index) glyph regeneration to occur.
*
* \see GetCharacterSize, SetCharacterSize, SetColor, SetStyle, SetText
*/
inline void RichTextDrawer::BlockRef::SetFont(FontRef font)
{
m_drawer.SetBlockFont(m_blockIndex, std::move(font));
}
/*!
* Changes the line spacing offset of the referenced block characters
* \remark This invalidates the drawer and will force a (complete or partial, depending on the block index) glyph regeneration to occur.
*
* \see GetLineSpacingOffset, SetColor, SetFont, SetStyle, SetText
*/
inline void RichTextDrawer::BlockRef::SetLineSpacingOffset(float offset)
{
m_drawer.SetBlockLineSpacingOffset(m_blockIndex, offset);
}
/*!
* Changes the outline color of the referenced block characters
* \remark This invalidates the drawer and will force a (complete or partial, depending on the block index) glyph regeneration to occur.
*
* \see GetCharacterSize, SetCharacterSize, SetColor, SetStyle, SetText
*/
inline void RichTextDrawer::BlockRef::SetOutlineColor(Color color)
{
m_drawer.SetBlockOutlineColor(m_blockIndex, std::move(color));
}
/*!
* Changes the outline thickness of the referenced block characters
* \remark This invalidates the drawer and will force a (complete or partial, depending on the block index) glyph regeneration to occur.
*
* \see GetCharacterSize, SetCharacterSize, SetColor, SetStyle, SetText
*/
inline void RichTextDrawer::BlockRef::SetOutlineThickness(float thickness)
{
m_drawer.SetBlockOutlineThickness(m_blockIndex, thickness);
}
/*!
* Changes the style flags of the referenced block characters
* \remark This invalidates the drawer and will force a (complete or partial, depending on the block index) glyph regeneration to occur.
*
* \see GetStyle, SetCharacterSize, SetColor, SetFont, SetText
*/
inline void RichTextDrawer::BlockRef::SetStyle(TextStyleFlags style)
{
m_drawer.SetBlockStyle(m_blockIndex, style);
}
/*!
* Changes the text of the referenced block
* \remark This invalidates the drawer and will force a (complete or partial, depending on the block index) glyph regeneration to occur.
*
* \see GetText, SetCharacterSize, SetColor, SetFont, SetStyle
*/
inline void RichTextDrawer::BlockRef::SetText(const String& text)
{
m_drawer.SetBlockText(m_blockIndex, text);
}
}
#include <Nazara/Utility/DebugOff.hpp>

View File

@@ -19,70 +19,108 @@ namespace Nz
class NAZARA_UTILITY_API SimpleTextDrawer : public AbstractTextDrawer
{
public:
SimpleTextDrawer();
SimpleTextDrawer(const SimpleTextDrawer& drawer);
SimpleTextDrawer(SimpleTextDrawer&& drawer);
virtual ~SimpleTextDrawer();
inline SimpleTextDrawer();
inline SimpleTextDrawer(const SimpleTextDrawer& drawer);
inline SimpleTextDrawer(SimpleTextDrawer&& drawer);
~SimpleTextDrawer() = default;
void AppendText(const String& str);
inline void AppendText(const String& str);
void Clear();
void Clear() override;
const Recti& GetBounds() const override;
unsigned int GetCharacterSize() const;
const Color& GetColor() const;
Font* GetFont() const;
const Rectf& GetBounds() const override;
inline float GetCharacterSpacingOffset() const;
inline unsigned int GetCharacterSize() const;
inline const Color& GetColor() const;
inline Font* GetFont() const;
Font* GetFont(std::size_t index) const override;
std::size_t GetFontCount() const override;
const Glyph& GetGlyph(std::size_t index) const override;
std::size_t GetGlyphCount() const override;
const Line& GetLine(std::size_t index) const override;
std::size_t GetLineCount() const override;
UInt32 GetStyle() const;
const String& GetText() const;
inline float GetLineHeight() const;
inline float GetLineSpacingOffset() const;
float GetMaxLineWidth() const override;
inline const Color& GetOutlineColor() const;
inline float GetOutlineThickness() const;
inline TextStyleFlags GetStyle() const;
inline const String& GetText() const;
void SetCharacterSize(unsigned int characterSize);
void SetColor(const Color& color);
void SetFont(Font* font);
void SetStyle(UInt32 style);
void SetText(const String& str);
inline void SetCharacterSpacingOffset(float offset);
inline void SetCharacterSize(unsigned int characterSize);
inline void SetColor(const Color& color);
inline void SetFont(Font* font);
inline void SetLineSpacingOffset(float offset);
inline void SetMaxLineWidth(float lineWidth) override;
inline void SetOutlineColor(const Color& color);
inline void SetOutlineThickness(float thickness);
inline void SetStyle(TextStyleFlags style);
inline void SetText(const String& str);
SimpleTextDrawer& operator=(const SimpleTextDrawer& drawer);
SimpleTextDrawer& operator=(SimpleTextDrawer&& drawer);
inline SimpleTextDrawer& operator=(const SimpleTextDrawer& drawer);
inline SimpleTextDrawer& operator=(SimpleTextDrawer&& drawer);
static SimpleTextDrawer Draw(const String& str, unsigned int characterSize, UInt32 style = TextStyle_Regular, const Color& color = Color::White);
static SimpleTextDrawer Draw(Font* font, const String& str, unsigned int characterSize, UInt32 style = TextStyle_Regular, const Color& color = Color::White);
static inline SimpleTextDrawer Draw(const String& str, unsigned int characterSize, TextStyleFlags style = TextStyle_Regular, const Color& color = Color::White);
static inline SimpleTextDrawer Draw(const String& str, unsigned int characterSize, TextStyleFlags style, const Color& color, float outlineThickness, const Color& outlineColor);
static inline SimpleTextDrawer Draw(Font* font, const String& str, unsigned int characterSize, TextStyleFlags style = TextStyle_Regular, const Color& color = Color::White);
static inline SimpleTextDrawer Draw(Font* font, const String& str, unsigned int characterSize, TextStyleFlags style, const Color& color, float outlineThickness, const Color& outlineColor);
private:
inline void AppendNewLine() const;
void AppendNewLine(std::size_t glyphIndex, float glyphPosition) const;
void ClearGlyphs() const;
void ConnectFontSlots();
void DisconnectFontSlots();
inline void ConnectFontSlots();
inline void DisconnectFontSlots();
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;
inline float GetLineHeight(const Font::SizeInfo& sizeInfo) const;
inline void InvalidateColor();
inline void InvalidateGlyphs();
void OnFontAtlasLayerChanged(const Font* font, AbstractImage* oldLayer, AbstractImage* newLayer);
void OnFontInvalidated(const Font* font);
void OnFontRelease(const Font* object);
void UpdateGlyphColor() const;
void UpdateGlyphs() const;
inline bool ShouldLineWrap(float size) const;
inline void UpdateGlyphColor() const;
inline void UpdateGlyphs() const;
static constexpr std::size_t InvalidGlyph = std::numeric_limits<std::size_t>::max();
NazaraSlot(Font, OnFontAtlasChanged, m_atlasChangedSlot);
NazaraSlot(Font, OnFontAtlasLayerChanged, m_atlasLayerChangedSlot);
NazaraSlot(Font, OnFontGlyphCacheCleared, m_glyphCacheClearedSlot);
NazaraSlot(Font, OnFontRelease, m_fontReleaseSlot);
mutable std::size_t m_lastSeparatorGlyph;
mutable std::vector<Glyph> m_glyphs;
mutable std::vector<Line> m_lines;
Color m_color;
Color m_outlineColor;
FontRef m_font;
mutable Rectf m_workingBounds;
mutable Recti m_bounds;
mutable Rectf m_bounds;
String m_text;
TextStyleFlags m_style;
mutable UInt32 m_previousCharacter;
UInt32 m_style;
mutable Vector2ui m_drawPos;
mutable Vector2f m_drawPos;
mutable bool m_colorUpdated;
mutable bool m_glyphUpdated;
mutable float m_lastSeparatorPosition;
float m_characterSpacingOffset;
float m_lineSpacingOffset;
float m_maxLineWidth;
float m_outlineThickness;
unsigned int m_characterSize;
};
}
#include <Nazara/Utility/SimpleTextDrawer.inl>
#endif // NAZARA_SIMPLETEXTDRAWER_HPP

View File

@@ -0,0 +1,385 @@
// Copyright (C) 2017 Jérôme Leclercq
// This file is part of the "Nazara Engine - Utility module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Utility/SimpleTextDrawer.hpp>
#include <Nazara/Utility/Debug.hpp>
namespace Nz
{
inline SimpleTextDrawer::SimpleTextDrawer() :
m_color(Color::White),
m_outlineColor(Color::Black),
m_style(TextStyle_Regular),
m_colorUpdated(true),
m_glyphUpdated(true),
m_characterSpacingOffset(0.f),
m_lineSpacingOffset(0.f),
m_maxLineWidth(std::numeric_limits<float>::infinity()),
m_outlineThickness(0.f),
m_characterSize(24)
{
SetFont(Font::GetDefault());
}
inline SimpleTextDrawer::SimpleTextDrawer(const SimpleTextDrawer& drawer) :
m_color(drawer.m_color),
m_text(drawer.m_text),
m_style(drawer.m_style),
m_colorUpdated(false),
m_glyphUpdated(false),
m_outlineColor(drawer.m_outlineColor),
m_characterSpacingOffset(drawer.m_characterSpacingOffset),
m_lineSpacingOffset(drawer.m_lineSpacingOffset),
m_maxLineWidth(drawer.m_maxLineWidth),
m_outlineThickness(drawer.m_outlineThickness),
m_characterSize(drawer.m_characterSize)
{
SetFont(drawer.m_font);
}
inline SimpleTextDrawer::SimpleTextDrawer(SimpleTextDrawer&& drawer)
{
operator=(std::move(drawer));
}
inline void SimpleTextDrawer::AppendText(const String& str)
{
m_text.Append(str);
if (m_glyphUpdated)
GenerateGlyphs(str);
}
inline float SimpleTextDrawer::GetCharacterSpacingOffset() const
{
return m_characterSpacingOffset;
}
inline unsigned int SimpleTextDrawer::GetCharacterSize() const
{
return m_characterSize;
}
inline const Color& SimpleTextDrawer::GetColor() const
{
return m_color;
}
inline Font* SimpleTextDrawer::GetFont() const
{
return m_font;
}
inline float SimpleTextDrawer::GetLineHeight() const
{
NazaraAssert(m_font, "SimpleTextDrawer has no font");
return GetLineHeight(m_font->GetSizeInfo(m_characterSize));
}
inline float SimpleTextDrawer::GetLineSpacingOffset() const
{
return m_lineSpacingOffset;
}
inline const Color& SimpleTextDrawer::GetOutlineColor() const
{
return m_outlineColor;
}
inline float SimpleTextDrawer::GetOutlineThickness() const
{
return m_outlineThickness;
}
inline TextStyleFlags SimpleTextDrawer::GetStyle() const
{
return m_style;
}
inline const String& SimpleTextDrawer::GetText() const
{
return m_text;
}
inline void SimpleTextDrawer::SetCharacterSpacingOffset(float offset)
{
if (m_characterSpacingOffset != offset)
{
m_characterSpacingOffset = offset;
InvalidateGlyphs();
}
}
inline void SimpleTextDrawer::SetCharacterSize(unsigned int characterSize)
{
if (m_characterSize != characterSize)
{
m_characterSize = characterSize;
InvalidateGlyphs();
}
}
inline void SimpleTextDrawer::SetColor(const Color& color)
{
if (m_color != color)
{
m_color = color;
InvalidateColor();
}
}
inline void SimpleTextDrawer::SetFont(Font* font)
{
if (m_font != font)
{
m_font = font;
if (m_font)
ConnectFontSlots();
else
DisconnectFontSlots();
InvalidateGlyphs();
}
}
inline void SimpleTextDrawer::SetLineSpacingOffset(float offset)
{
if (m_lineSpacingOffset != offset)
{
m_lineSpacingOffset = offset;
InvalidateGlyphs();
}
}
inline void SimpleTextDrawer::SetMaxLineWidth(float lineWidth)
{
if (m_maxLineWidth != lineWidth)
{
NazaraAssert(lineWidth > 0.f, "Max line width must be positive");
m_maxLineWidth = lineWidth;
InvalidateGlyphs();
}
}
inline void SimpleTextDrawer::SetOutlineColor(const Color& color)
{
if (m_outlineColor != color)
{
m_outlineColor = color;
InvalidateColor();
}
}
inline void SimpleTextDrawer::SetOutlineThickness(float thickness)
{
if (m_outlineThickness != thickness)
{
NazaraAssert(thickness >= 0.f, "Thickness must be zero or positive");
m_outlineThickness = thickness;
InvalidateGlyphs();
}
}
inline void SimpleTextDrawer::SetStyle(TextStyleFlags style)
{
if (m_style != style)
{
m_style = style;
InvalidateGlyphs();
}
}
inline void SimpleTextDrawer::SetText(const String& str)
{
if (m_text != str)
{
m_text = str;
InvalidateGlyphs();
}
}
inline SimpleTextDrawer& SimpleTextDrawer::operator=(const SimpleTextDrawer& drawer)
{
m_characterSize = drawer.m_characterSize;
m_characterSpacingOffset = drawer.m_characterSpacingOffset;
m_color = drawer.m_color;
m_lineSpacingOffset = drawer.m_lineSpacingOffset;
m_maxLineWidth = drawer.m_maxLineWidth;
m_outlineColor = drawer.m_outlineColor;
m_outlineThickness = drawer.m_outlineThickness;
m_style = drawer.m_style;
m_text = drawer.m_text;
SetFont(drawer.m_font);
InvalidateGlyphs();
return *this;
}
inline SimpleTextDrawer& SimpleTextDrawer::operator=(SimpleTextDrawer&& drawer)
{
DisconnectFontSlots();
m_bounds = std::move(drawer.m_bounds);
m_colorUpdated = std::move(drawer.m_colorUpdated);
m_characterSize = std::move(drawer.m_characterSize);
m_characterSpacingOffset = drawer.m_characterSpacingOffset;
m_color = std::move(drawer.m_color);
m_glyphs = std::move(drawer.m_glyphs);
m_glyphUpdated = std::move(drawer.m_glyphUpdated);
m_font = std::move(drawer.m_font);
m_lineSpacingOffset = drawer.m_lineSpacingOffset;
m_maxLineWidth = drawer.m_maxLineWidth;
m_outlineColor = std::move(drawer.m_outlineColor);
m_outlineThickness = std::move(drawer.m_outlineThickness);
m_style = std::move(drawer.m_style);
m_text = std::move(drawer.m_text);
// Update slot pointers (TODO: Improve the way of doing this)
if (m_font)
{
drawer.DisconnectFontSlots();
ConnectFontSlots();
}
return *this;
}
inline SimpleTextDrawer SimpleTextDrawer::Draw(const String& str, unsigned int characterSize, TextStyleFlags style, const Color& color)
{
SimpleTextDrawer drawer;
drawer.SetCharacterSize(characterSize);
drawer.SetColor(color);
drawer.SetStyle(style);
drawer.SetText(str);
return drawer;
}
inline SimpleTextDrawer SimpleTextDrawer::Draw(const String& str, unsigned int characterSize, TextStyleFlags style, const Color& color, float outlineThickness, const Color& outlineColor)
{
SimpleTextDrawer drawer;
drawer.SetCharacterSize(characterSize);
drawer.SetColor(color);
drawer.SetOutlineColor(outlineColor);
drawer.SetOutlineThickness(outlineThickness);
drawer.SetStyle(style);
drawer.SetText(str);
return drawer;
}
inline SimpleTextDrawer SimpleTextDrawer::Draw(Font* font, const String& str, unsigned int characterSize, TextStyleFlags style, const Color& color)
{
SimpleTextDrawer drawer;
drawer.SetCharacterSize(characterSize);
drawer.SetColor(color);
drawer.SetFont(font);
drawer.SetStyle(style);
drawer.SetText(str);
return drawer;
}
inline SimpleTextDrawer SimpleTextDrawer::Draw(Font* font, const String& str, unsigned int characterSize, TextStyleFlags style, const Color& color, float outlineThickness, const Color& outlineColor)
{
SimpleTextDrawer drawer;
drawer.SetCharacterSize(characterSize);
drawer.SetColor(color);
drawer.SetFont(font);
drawer.SetOutlineColor(outlineColor);
drawer.SetOutlineThickness(outlineThickness);
drawer.SetStyle(style);
drawer.SetText(str);
return drawer;
}
inline void SimpleTextDrawer::AppendNewLine() const
{
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) + m_lineSpacingOffset;
}
inline void SimpleTextDrawer::InvalidateColor()
{
m_colorUpdated = false;
}
inline void SimpleTextDrawer::InvalidateGlyphs()
{
m_glyphUpdated = false;
}
inline bool SimpleTextDrawer::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 void SimpleTextDrawer::UpdateGlyphColor() const
{
if (m_outlineThickness > 0.f)
{
for (std::size_t glyphIndex = 0; glyphIndex < m_glyphs.size(); ++glyphIndex)
{
Glyph& glyph = m_glyphs[glyphIndex];
if (glyphIndex % 2 == 0)
glyph.color = m_outlineColor;
else
glyph.color = m_color;
}
}
else
{
for (Glyph& glyph : m_glyphs)
glyph.color = m_color;
}
m_colorUpdated = true;
}
inline void SimpleTextDrawer::UpdateGlyphs() const
{
NazaraAssert(m_font && m_font->IsValid(), "Invalid font");
ClearGlyphs();
GenerateGlyphs(m_text);
}
}
#include <Nazara/Utility/DebugOff.hpp>