Remove Utility module and move its content to Core and TextRenderer modules
This commit is contained in:
committed by
Jérôme Leclercq
parent
965a00182c
commit
e64c2b036e
66
include/Nazara/TextRenderer/AbstractTextDrawer.hpp
Normal file
66
include/Nazara/TextRenderer/AbstractTextDrawer.hpp
Normal file
@@ -0,0 +1,66 @@
|
||||
// Copyright (C) 2024 Jérôme "SirLynix" Leclercq (lynix680@gmail.com)
|
||||
// This file is part of the "Nazara Engine - Text renderer"
|
||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef NAZARA_TEXTRENDERER_ABSTRACTTEXTDRAWER_HPP
|
||||
#define NAZARA_TEXTRENDERER_ABSTRACTTEXTDRAWER_HPP
|
||||
|
||||
#include <NazaraUtils/Prerequisites.hpp>
|
||||
#include <Nazara/Core/Color.hpp>
|
||||
#include <Nazara/Math/Rect.hpp>
|
||||
#include <Nazara/Math/Vector2.hpp>
|
||||
#include <Nazara/TextRenderer/Config.hpp>
|
||||
#include <memory>
|
||||
|
||||
namespace Nz
|
||||
{
|
||||
class AbstractImage;
|
||||
class Font;
|
||||
|
||||
class NAZARA_TEXTRENDERER_API AbstractTextDrawer
|
||||
{
|
||||
public:
|
||||
struct Glyph;
|
||||
struct Line;
|
||||
|
||||
AbstractTextDrawer() = default;
|
||||
virtual ~AbstractTextDrawer();
|
||||
|
||||
virtual void Clear() = 0;
|
||||
|
||||
virtual const Rectf& GetBounds() const = 0;
|
||||
virtual const std::shared_ptr<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;
|
||||
virtual std::size_t GetGlyphCount() const = 0;
|
||||
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
|
||||
{
|
||||
Color color;
|
||||
Rectf bounds;
|
||||
Rectui atlasRect;
|
||||
Vector2f corners[4];
|
||||
AbstractImage* atlas;
|
||||
bool flipped;
|
||||
int renderOrder;
|
||||
};
|
||||
|
||||
struct Line
|
||||
{
|
||||
Rectf bounds;
|
||||
std::size_t glyphIndex;
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
#include <Nazara/TextRenderer/AbstractTextDrawer.inl>
|
||||
|
||||
#endif // NAZARA_TEXTRENDERER_ABSTRACTTEXTDRAWER_HPP
|
||||
22
include/Nazara/TextRenderer/AbstractTextDrawer.inl
Normal file
22
include/Nazara/TextRenderer/AbstractTextDrawer.inl
Normal file
@@ -0,0 +1,22 @@
|
||||
// Copyright (C) 2024 Jérôme "SirLynix" Leclercq (lynix680@gmail.com)
|
||||
// This file is part of the "Nazara Engine - Text renderer"
|
||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||
|
||||
#include <Nazara/TextRenderer/Debug.hpp>
|
||||
|
||||
namespace Nz
|
||||
{
|
||||
inline std::size_t AbstractTextDrawer::GetLineGlyphCount(std::size_t index) const
|
||||
{
|
||||
std::size_t lineCount = GetLineCount();
|
||||
const auto& lineInfo = GetLine(index);
|
||||
if (index == lineCount - 1)
|
||||
return GetGlyphCount() - lineInfo.glyphIndex;
|
||||
|
||||
const auto& nextLineInfo = GetLine(index + 1);
|
||||
|
||||
return nextLineInfo.glyphIndex - lineInfo.glyphIndex;
|
||||
}
|
||||
}
|
||||
|
||||
#include <Nazara/TextRenderer/DebugOff.hpp>
|
||||
45
include/Nazara/TextRenderer/Config.hpp
Normal file
45
include/Nazara/TextRenderer/Config.hpp
Normal file
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
Nazara Engine - Platform module
|
||||
|
||||
Copyright (C) 2024 Jérôme "SirLynix" Leclercq (lynix680@gmail.com)
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
this software and associated documentation files (the "Software"), to deal in
|
||||
the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do
|
||||
so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef NAZARA_TEXTRENDERER_CONFIG_HPP
|
||||
#define NAZARA_TEXTRENDERER_CONFIG_HPP
|
||||
|
||||
/// Each modification of a parameter needs a recompilation of the module
|
||||
|
||||
// Activate the security tests based on the code (Advised for development)
|
||||
#define NAZARA_TEXTRENDERER_SAFE 1
|
||||
|
||||
#if defined(NAZARA_STATIC)
|
||||
#define NAZARA_TEXTRENDERER_API
|
||||
#else
|
||||
#ifdef NAZARA_TEXTRENDERER_BUILD
|
||||
#define NAZARA_TEXTRENDERER_API NAZARA_EXPORT
|
||||
#else
|
||||
#define NAZARA_TEXTRENDERER_API NAZARA_IMPORT
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#endif // NAZARA_TEXTRENDERER_CONFIG_HPP
|
||||
17
include/Nazara/TextRenderer/ConfigCheck.hpp
Normal file
17
include/Nazara/TextRenderer/ConfigCheck.hpp
Normal file
@@ -0,0 +1,17 @@
|
||||
// Copyright (C) 2024 Jérôme "SirLynix" Leclercq (lynix680@gmail.com)
|
||||
// This file is part of the "Nazara Engine - Text renderer"
|
||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef NAZARA_TEXTRENDERER_CONFIGCHECK_HPP
|
||||
#define NAZARA_TEXTRENDERER_CONFIGCHECK_HPP
|
||||
|
||||
/// This file is used to check the constant values defined in Config.hpp
|
||||
|
||||
#include <type_traits>
|
||||
#define NazaraCheckTypeAndVal(name, type, op, val, err) static_assert(std::is_ ##type <decltype(name)>::value && name op val, #type err)
|
||||
|
||||
#undef NazaraCheckTypeAndVal
|
||||
|
||||
#endif // NAZARA_TEXTRENDERER_CONFIGCHECK_HPP
|
||||
5
include/Nazara/TextRenderer/Debug.hpp
Normal file
5
include/Nazara/TextRenderer/Debug.hpp
Normal file
@@ -0,0 +1,5 @@
|
||||
// Copyright (C) 2024 Jérôme "SirLynix" Leclercq (lynix680@gmail.com)
|
||||
// This file is part of the "Nazara Engine - Text renderer"
|
||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||
|
||||
// no header guards
|
||||
5
include/Nazara/TextRenderer/DebugOff.hpp
Normal file
5
include/Nazara/TextRenderer/DebugOff.hpp
Normal file
@@ -0,0 +1,5 @@
|
||||
// Copyright (C) 2024 Jérôme "SirLynix" Leclercq (lynix680@gmail.com)
|
||||
// This file is part of the "Nazara Engine - Text renderer"
|
||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||
|
||||
// no header guards
|
||||
160
include/Nazara/TextRenderer/Font.hpp
Normal file
160
include/Nazara/TextRenderer/Font.hpp
Normal file
@@ -0,0 +1,160 @@
|
||||
// Copyright (C) 2024 Jérôme "SirLynix" Leclercq (lynix680@gmail.com)
|
||||
// This file is part of the "Nazara Engine - Text renderer"
|
||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||
|
||||
///TODO: FontManager ?
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef NAZARA_TEXTRENDERER_FONT_HPP
|
||||
#define NAZARA_TEXTRENDERER_FONT_HPP
|
||||
|
||||
#include <NazaraUtils/Prerequisites.hpp>
|
||||
#include <Nazara/Core/AbstractAtlas.hpp>
|
||||
#include <Nazara/Core/Enums.hpp>
|
||||
#include <Nazara/Core/ObjectLibrary.hpp>
|
||||
#include <Nazara/Core/Resource.hpp>
|
||||
#include <Nazara/Core/ResourceLoader.hpp>
|
||||
#include <Nazara/Core/ResourceParameters.hpp>
|
||||
#include <Nazara/TextRenderer/Config.hpp>
|
||||
#include <memory>
|
||||
#include <unordered_map>
|
||||
|
||||
namespace Nz
|
||||
{
|
||||
struct NAZARA_TEXTRENDERER_API FontParams : ResourceParameters
|
||||
{
|
||||
bool IsValid() const;
|
||||
};
|
||||
|
||||
class Font;
|
||||
class FontData;
|
||||
|
||||
struct FontGlyph;
|
||||
|
||||
using FontLibrary = ObjectLibrary<Font>;
|
||||
using FontLoader = ResourceLoader<Font, FontParams>;
|
||||
|
||||
class NAZARA_TEXTRENDERER_API Font : public Resource
|
||||
{
|
||||
friend FontLibrary;
|
||||
friend FontLoader;
|
||||
friend class TextRenderer;
|
||||
|
||||
public:
|
||||
struct Glyph;
|
||||
struct SizeInfo;
|
||||
using Params = FontParams;
|
||||
|
||||
Font();
|
||||
Font(const Font&) = delete;
|
||||
Font(Font&&) = delete;
|
||||
~Font();
|
||||
|
||||
void ClearGlyphCache();
|
||||
void ClearKerningCache();
|
||||
void ClearSizeInfoCache();
|
||||
|
||||
bool Create(std::unique_ptr<FontData> data);
|
||||
void Destroy();
|
||||
|
||||
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, TextStyleFlags style, float outlineThickness) const;
|
||||
std::size_t GetCachedGlyphCount() const;
|
||||
std::string GetFamilyName() const;
|
||||
int GetKerning(unsigned int characterSize, char32_t first, char32_t second) 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;
|
||||
std::string GetStyleName() const;
|
||||
|
||||
bool IsValid() const;
|
||||
|
||||
bool Precache(unsigned int characterSize, TextStyleFlags style, float outlineThickness, char32_t character) const;
|
||||
bool Precache(unsigned int characterSize, TextStyleFlags style, float outlineThickness, std::string_view characterSet) const;
|
||||
|
||||
void SetAtlas(std::shared_ptr<AbstractAtlas> atlas);
|
||||
void SetGlyphBorder(unsigned int borderSize);
|
||||
void SetMinimumStepSize(unsigned int minimumStepSize);
|
||||
|
||||
Font& operator=(const Font&) = delete;
|
||||
Font& operator=(Font&&) = delete;
|
||||
|
||||
static std::shared_ptr<AbstractAtlas> GetDefaultAtlas();
|
||||
static const std::shared_ptr<Font>& GetDefault();
|
||||
static unsigned int GetDefaultGlyphBorder();
|
||||
static unsigned int GetDefaultMinimumStepSize();
|
||||
|
||||
static std::shared_ptr<Font> OpenFromFile(const std::filesystem::path& filePath, const FontParams& params = FontParams());
|
||||
static std::shared_ptr<Font> OpenFromMemory(const void* data, std::size_t size, const FontParams& params = FontParams());
|
||||
static std::shared_ptr<Font> OpenFromStream(Stream& stream, const FontParams& params = FontParams());
|
||||
|
||||
static void SetDefaultAtlas(std::shared_ptr<AbstractAtlas> atlas);
|
||||
static void SetDefaultGlyphBorder(unsigned int borderSize);
|
||||
static void SetDefaultMinimumStepSize(unsigned int minimumStepSize);
|
||||
|
||||
struct Glyph
|
||||
{
|
||||
std::size_t layerIndex;
|
||||
Recti aabb;
|
||||
Rectui atlasRect;
|
||||
bool requireFauxBold;
|
||||
bool requireFauxItalic;
|
||||
bool flipped;
|
||||
bool valid;
|
||||
float fauxOutlineThickness;
|
||||
int advance;
|
||||
};
|
||||
|
||||
struct SizeInfo
|
||||
{
|
||||
int spaceAdvance;
|
||||
unsigned int lineHeight;
|
||||
float underlinePosition;
|
||||
float underlineThickness;
|
||||
};
|
||||
|
||||
// Signals:
|
||||
NazaraSignal(OnFontAtlasChanged, const Font* /*font*/);
|
||||
NazaraSignal(OnFontAtlasLayerChanged, const Font* /*font*/, AbstractImage* /*oldLayer*/, AbstractImage* /*newLayer*/);
|
||||
NazaraSignal(OnFontDestroy, const Font* /*font*/);
|
||||
NazaraSignal(OnFontGlyphCacheCleared, const Font* /*font*/);
|
||||
NazaraSignal(OnFontKerningCacheCleared, const Font* /*font*/);
|
||||
NazaraSignal(OnFontRelease, const Font* /*font*/);
|
||||
NazaraSignal(OnFontSizeInfoCacheCleared, const Font* /*font*/);
|
||||
|
||||
private:
|
||||
using GlyphMap = std::unordered_map<char32_t, Glyph>;
|
||||
|
||||
UInt64 ComputeKey(unsigned int characterSize, TextStyleFlags style, float outlineThickness) const;
|
||||
void OnAtlasCleared(const AbstractAtlas* atlas);
|
||||
void OnAtlasLayerChange(const AbstractAtlas* atlas, AbstractImage* oldLayer, AbstractImage* newLayer);
|
||||
const Glyph& PrecacheGlyph(GlyphMap& glyphMap, unsigned int characterSize, TextStyleFlags style, float outlineThickness, char32_t character) const;
|
||||
|
||||
static bool Initialize();
|
||||
static void Uninitialize();
|
||||
|
||||
NazaraSlot(AbstractAtlas, OnAtlasCleared, m_atlasClearedSlot);
|
||||
NazaraSlot(AbstractAtlas, OnAtlasLayerChange, m_atlasLayerChangeSlot);
|
||||
|
||||
std::shared_ptr<AbstractAtlas> m_atlas;
|
||||
std::unique_ptr<FontData> m_data;
|
||||
mutable std::unordered_map<UInt64, std::unordered_map<UInt64, int>> m_kerningCache;
|
||||
mutable std::unordered_map<UInt64, GlyphMap> m_glyphes;
|
||||
mutable std::unordered_map<UInt64, SizeInfo> m_sizeInfoCache;
|
||||
unsigned int m_glyphBorder;
|
||||
unsigned int m_minimumStepSize;
|
||||
|
||||
static std::shared_ptr<AbstractAtlas> s_defaultAtlas;
|
||||
static std::shared_ptr<Font> s_defaultFont;
|
||||
static unsigned int s_defaultGlyphBorder;
|
||||
static unsigned int s_defaultMinimumStepSize;
|
||||
};
|
||||
}
|
||||
|
||||
#include <Nazara/TextRenderer/Font.inl>
|
||||
|
||||
#endif // NAZARA_TEXTRENDERER_FONT_HPP
|
||||
12
include/Nazara/TextRenderer/Font.inl
Normal file
12
include/Nazara/TextRenderer/Font.inl
Normal file
@@ -0,0 +1,12 @@
|
||||
// Copyright (C) 2024 Jérôme "SirLynix" Leclercq (lynix680@gmail.com)
|
||||
// This file is part of the "Nazara Engine - Text renderer"
|
||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||
|
||||
#include <memory>
|
||||
#include <Nazara/TextRenderer/Debug.hpp>
|
||||
|
||||
namespace Nz
|
||||
{
|
||||
}
|
||||
|
||||
#include <Nazara/TextRenderer/DebugOff.hpp>
|
||||
44
include/Nazara/TextRenderer/FontData.hpp
Normal file
44
include/Nazara/TextRenderer/FontData.hpp
Normal file
@@ -0,0 +1,44 @@
|
||||
// Copyright (C) 2024 Jérôme "SirLynix" Leclercq (lynix680@gmail.com)
|
||||
// This file is part of the "Nazara Engine - Text renderer"
|
||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef NAZARA_TEXTRENDERER_FONTDATA_HPP
|
||||
#define NAZARA_TEXTRENDERER_FONTDATA_HPP
|
||||
|
||||
#include <NazaraUtils/Prerequisites.hpp>
|
||||
#include <Nazara/Core/Enums.hpp>
|
||||
#include <Nazara/TextRenderer/Config.hpp>
|
||||
#include <string>
|
||||
|
||||
namespace Nz
|
||||
{
|
||||
struct FontGlyph;
|
||||
|
||||
class NAZARA_TEXTRENDERER_API FontData
|
||||
{
|
||||
public:
|
||||
FontData() = default;
|
||||
virtual ~FontData();
|
||||
|
||||
virtual bool ExtractGlyph(unsigned int characterSize, char32_t character, TextStyleFlags style, float outlineThickness, FontGlyph* dst) = 0;
|
||||
|
||||
virtual std::string GetFamilyName() const = 0;
|
||||
virtual std::string GetStyleName() const = 0;
|
||||
|
||||
virtual bool HasKerning() const = 0;
|
||||
|
||||
virtual bool IsScalable() const = 0;
|
||||
|
||||
virtual int QueryKerning(unsigned int characterSize, char32_t first, char32_t second) const = 0;
|
||||
virtual unsigned int QueryLineHeight(unsigned int characterSize) const = 0;
|
||||
virtual float QueryUnderlinePosition(unsigned int characterSize) const = 0;
|
||||
virtual float QueryUnderlineThickness(unsigned int characterSize) const = 0;
|
||||
|
||||
virtual bool SupportsOutline(float outlineThickness) const = 0;
|
||||
virtual bool SupportsStyle(TextStyleFlags style) const = 0;
|
||||
};
|
||||
}
|
||||
|
||||
#endif // NAZARA_TEXTRENDERER_FONTDATA_HPP
|
||||
22
include/Nazara/TextRenderer/FontGlyph.hpp
Normal file
22
include/Nazara/TextRenderer/FontGlyph.hpp
Normal file
@@ -0,0 +1,22 @@
|
||||
// Copyright (C) 2024 Jérôme "SirLynix" Leclercq (lynix680@gmail.com)
|
||||
// This file is part of the "Nazara Engine - Text renderer"
|
||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef NAZARA_TEXTRENDERER_FONTGLYPH_HPP
|
||||
#define NAZARA_TEXTRENDERER_FONTGLYPH_HPP
|
||||
|
||||
#include <Nazara/Core/Image.hpp>
|
||||
|
||||
namespace Nz
|
||||
{
|
||||
struct FontGlyph
|
||||
{
|
||||
Image image;
|
||||
Recti aabb;
|
||||
int advance;
|
||||
};
|
||||
}
|
||||
|
||||
#endif // NAZARA_TEXTRENDERER_FONTGLYPH_HPP
|
||||
80
include/Nazara/TextRenderer/RichTextBuilder.hpp
Normal file
80
include/Nazara/TextRenderer/RichTextBuilder.hpp
Normal file
@@ -0,0 +1,80 @@
|
||||
// Copyright (C) 2024 Jérôme "SirLynix" Leclercq (lynix680@gmail.com)
|
||||
// This file is part of the "Nazara Engine - Text renderer"
|
||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef NAZARA_TEXTRENDERER_RICHTEXTBUILDER_HPP
|
||||
#define NAZARA_TEXTRENDERER_RICHTEXTBUILDER_HPP
|
||||
|
||||
#include <NazaraUtils/Prerequisites.hpp>
|
||||
#include <Nazara/Core/Enums.hpp>
|
||||
#include <Nazara/TextRenderer/Font.hpp>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
namespace Nz
|
||||
{
|
||||
class Font;
|
||||
|
||||
template<typename T>
|
||||
class RichTextBuilder
|
||||
{
|
||||
public:
|
||||
struct CharacterSizeWrapper;
|
||||
struct CharacterSpacingOffsetWrapper;
|
||||
struct LineSpacingOffsetWrapper;
|
||||
struct OutlineColorWrapper;
|
||||
struct OutlineThicknessWrapper;
|
||||
|
||||
RichTextBuilder(T& richText);
|
||||
RichTextBuilder(T* richText);
|
||||
RichTextBuilder(const RichTextBuilder&) = delete;
|
||||
RichTextBuilder(RichTextBuilder&&) = delete;
|
||||
~RichTextBuilder() = default;
|
||||
|
||||
inline RichTextBuilder& AppendText(std::string_view text);
|
||||
|
||||
inline RichTextBuilder& SetCharacterSize(unsigned int characterSize);
|
||||
inline RichTextBuilder& SetCharacterSpacingOffset(float offset);
|
||||
inline RichTextBuilder& SetLineSpacingOffset(float offset);
|
||||
inline RichTextBuilder& SetTextColor(const Color& color);
|
||||
inline RichTextBuilder& SetTextFont(const std::shared_ptr<Font>& font);
|
||||
inline RichTextBuilder& SetTextOutlineColor(const Color& color);
|
||||
inline RichTextBuilder& SetTextOutlineThickness(float thickness);
|
||||
inline RichTextBuilder& SetTextStyle(TextStyleFlags style);
|
||||
|
||||
RichTextBuilder& operator=(const RichTextBuilder&) = delete;
|
||||
RichTextBuilder& operator=(RichTextBuilder&&) = delete;
|
||||
|
||||
inline RichTextBuilder& operator<<(const Color& textColor);
|
||||
inline RichTextBuilder& operator<<(const std::shared_ptr<Font>& font);
|
||||
inline RichTextBuilder& operator<<(std::string_view str);
|
||||
inline RichTextBuilder& operator<<(CharacterSizeWrapper characterSize);
|
||||
inline RichTextBuilder& operator<<(CharacterSpacingOffsetWrapper characterSpacingOffset);
|
||||
inline RichTextBuilder& operator<<(LineSpacingOffsetWrapper lineSpacing);
|
||||
inline RichTextBuilder& operator<<(OutlineColorWrapper outlineColor);
|
||||
inline RichTextBuilder& operator<<(OutlineThicknessWrapper outlineThickness);
|
||||
inline RichTextBuilder& operator<<(TextStyleFlags textStyle);
|
||||
|
||||
static inline CharacterSizeWrapper CharacterSize(unsigned int characterSize);
|
||||
static inline CharacterSpacingOffsetWrapper CharacterSpacingOffset(unsigned int spacingOffset);
|
||||
static inline LineSpacingOffsetWrapper LineSpacingOffset(float spacingOffset);
|
||||
static inline OutlineColorWrapper OutlineColor(const Color& color);
|
||||
static inline OutlineThicknessWrapper OutlineThickness(float thickness);
|
||||
|
||||
struct CharacterSizeWrapper { unsigned int characterSize; };
|
||||
struct CharacterSpacingOffsetWrapper { float spacingOffset; };
|
||||
struct LineSpacingOffsetWrapper { float spacingOffset; };
|
||||
struct OutlineColorWrapper { const Color& color; };
|
||||
struct OutlineThicknessWrapper { float thickness; };
|
||||
|
||||
private:
|
||||
T& m_richText;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#include <Nazara/TextRenderer/RichTextBuilder.inl>
|
||||
|
||||
#endif // NAZARA_TEXTRENDERER_RICHTEXTBUILDER_HPP
|
||||
169
include/Nazara/TextRenderer/RichTextBuilder.inl
Normal file
169
include/Nazara/TextRenderer/RichTextBuilder.inl
Normal file
@@ -0,0 +1,169 @@
|
||||
// Copyright (C) 2024 Jérôme "SirLynix" Leclercq (lynix680@gmail.com)
|
||||
// This file is part of the "Nazara Engine - Text renderer"
|
||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||
|
||||
#include <Nazara/TextRenderer/Debug.hpp>
|
||||
|
||||
namespace Nz
|
||||
{
|
||||
template<typename T>
|
||||
RichTextBuilder<T>::RichTextBuilder(T& richText) :
|
||||
m_richText(richText)
|
||||
{
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
RichTextBuilder<T>::RichTextBuilder(T* richText) :
|
||||
m_richText(*richText)
|
||||
{
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
RichTextBuilder<T>& RichTextBuilder<T>::AppendText(std::string_view text)
|
||||
{
|
||||
m_richText.AppendText(text);
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
RichTextBuilder<T>& RichTextBuilder<T>::SetCharacterSize(unsigned int characterSize)
|
||||
{
|
||||
m_richText.SetCharacterSize(characterSize);
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
RichTextBuilder<T>& RichTextBuilder<T>::SetCharacterSpacingOffset(float offset)
|
||||
{
|
||||
m_richText.SetCharacterSpacingOffset(offset);
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
RichTextBuilder<T>& RichTextBuilder<T>::SetLineSpacingOffset(float offset)
|
||||
{
|
||||
m_richText.SetLineSpacingOffset(offset);
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
RichTextBuilder<T>& RichTextBuilder<T>::SetTextColor(const Color& color)
|
||||
{
|
||||
m_richText.SetTextColor(color);
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
RichTextBuilder<T>& RichTextBuilder<T>::SetTextFont(const std::shared_ptr<Font>& font)
|
||||
{
|
||||
m_richText.SetTextFont(font);
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
RichTextBuilder<T>& RichTextBuilder<T>::SetTextOutlineColor(const Color& color)
|
||||
{
|
||||
m_richText.SetTextOutlineColor(color);
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
RichTextBuilder<T>& RichTextBuilder<T>::SetTextOutlineThickness(float thickness)
|
||||
{
|
||||
m_richText.SetTextOutlineThickness(thickness);
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
RichTextBuilder<T>& RichTextBuilder<T>::SetTextStyle(TextStyleFlags style)
|
||||
{
|
||||
m_richText.SetTextStyle(style);
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
RichTextBuilder<T>& RichTextBuilder<T>::operator<<(const Color& textColor)
|
||||
{
|
||||
return SetTextColor(textColor);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
RichTextBuilder<T>& RichTextBuilder<T>::operator<<(const std::shared_ptr<Font>& font)
|
||||
{
|
||||
return SetTextFont(font);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
RichTextBuilder<T>& RichTextBuilder<T>::operator<<(std::string_view str)
|
||||
{
|
||||
return AppendText(str);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
RichTextBuilder<T>& RichTextBuilder<T>::operator<<(CharacterSizeWrapper characterSize)
|
||||
{
|
||||
return SetCharacterSize(characterSize.characterSize);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
RichTextBuilder<T>& RichTextBuilder<T>::operator<<(CharacterSpacingOffsetWrapper characterSpacingOffset)
|
||||
{
|
||||
return SetCharacterSpacingOffset(characterSpacingOffset.spacingOffset);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
RichTextBuilder<T>& RichTextBuilder<T>::operator<<(LineSpacingOffsetWrapper lineSpacing)
|
||||
{
|
||||
return SetLineSpacingOffset(lineSpacing.spacingOffset);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
RichTextBuilder<T>& RichTextBuilder<T>::operator<<(OutlineColorWrapper outlineColor)
|
||||
{
|
||||
return SetTextOutlineColor(outlineColor.color);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
RichTextBuilder<T>& RichTextBuilder<T>::operator<<(OutlineThicknessWrapper outlineThickness)
|
||||
{
|
||||
return SetTextOutlineThickness(outlineThickness.thickness);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
RichTextBuilder<T>& RichTextBuilder<T>::operator<<(TextStyleFlags textStyle)
|
||||
{
|
||||
return SetTextStyle(textStyle);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
auto RichTextBuilder<T>::CharacterSize(unsigned int characterSize) -> CharacterSizeWrapper
|
||||
{
|
||||
return { characterSize };
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
auto RichTextBuilder<T>::CharacterSpacingOffset(unsigned int spacingOffset) -> CharacterSpacingOffsetWrapper
|
||||
{
|
||||
return { spacingOffset };
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
auto RichTextBuilder<T>::LineSpacingOffset(float spacingOffset) -> LineSpacingOffsetWrapper
|
||||
{
|
||||
return { spacingOffset };
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
auto RichTextBuilder<T>::OutlineColor(const Color& color) -> OutlineColorWrapper
|
||||
{
|
||||
return { color };
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
auto RichTextBuilder<T>::OutlineThickness(float thickness) -> OutlineThicknessWrapper
|
||||
{
|
||||
return { thickness };
|
||||
}
|
||||
}
|
||||
|
||||
#include <Nazara/TextRenderer/DebugOff.hpp>
|
||||
212
include/Nazara/TextRenderer/RichTextDrawer.hpp
Normal file
212
include/Nazara/TextRenderer/RichTextDrawer.hpp
Normal file
@@ -0,0 +1,212 @@
|
||||
// Copyright (C) 2024 Jérôme "SirLynix" Leclercq (lynix680@gmail.com)
|
||||
// This file is part of the "Nazara Engine - Text renderer"
|
||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef NAZARA_TEXTRENDERER_RICHTEXTDRAWER_HPP
|
||||
#define NAZARA_TEXTRENDERER_RICHTEXTDRAWER_HPP
|
||||
|
||||
#include <NazaraUtils/Prerequisites.hpp>
|
||||
#include <Nazara/Core/Enums.hpp>
|
||||
#include <Nazara/TextRenderer/AbstractTextDrawer.hpp>
|
||||
#include <Nazara/TextRenderer/Font.hpp>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace Nz
|
||||
{
|
||||
class NAZARA_TEXTRENDERER_API RichTextDrawer : public AbstractTextDrawer
|
||||
{
|
||||
public:
|
||||
class BlockRef;
|
||||
|
||||
RichTextDrawer();
|
||||
RichTextDrawer(const RichTextDrawer& drawer);
|
||||
RichTextDrawer(RichTextDrawer&& drawer) noexcept;
|
||||
~RichTextDrawer();
|
||||
|
||||
BlockRef AppendText(std::string_view 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 std::shared_ptr<Font>& GetBlockFont(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 std::string& GetBlockText(std::size_t index) const;
|
||||
|
||||
inline BlockRef GetBlock(std::size_t index);
|
||||
const Rectf& GetBounds() const override;
|
||||
inline unsigned int GetCharacterSize() const;
|
||||
inline float GetCharacterSpacingOffset() const;
|
||||
inline float GetLineSpacingOffset() const;
|
||||
const std::shared_ptr<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 const Color& GetTextColor() const;
|
||||
inline const std::shared_ptr<Font>& GetTextFont() const;
|
||||
inline const Color& GetTextOutlineColor() const;
|
||||
inline float GetTextOutlineThickness() const;
|
||||
inline TextStyleFlags GetTextStyle() const;
|
||||
|
||||
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, std::shared_ptr<Font> 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, std::string str);
|
||||
|
||||
inline void SetCharacterSize(unsigned int characterSize);
|
||||
inline void SetCharacterSpacingOffset(float offset);
|
||||
inline void SetLineSpacingOffset(float offset);
|
||||
inline void SetTextColor(const Color& color);
|
||||
inline void SetTextFont(const std::shared_ptr<Font>& font);
|
||||
inline void SetTextOutlineColor(const Color& color);
|
||||
inline void SetTextOutlineThickness(float thickness);
|
||||
inline void SetTextStyle(TextStyleFlags style);
|
||||
|
||||
void SetMaxLineWidth(float lineWidth) override;
|
||||
|
||||
RichTextDrawer& operator=(const RichTextDrawer& drawer);
|
||||
RichTextDrawer& operator=(RichTextDrawer&& drawer) noexcept;
|
||||
|
||||
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, std::string_view 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 std::shared_ptr<Font>& 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;
|
||||
std::string text;
|
||||
Color color;
|
||||
Color outlineColor;
|
||||
TextStyleFlags style;
|
||||
float characterSpacingOffset;
|
||||
float lineSpacingOffset;
|
||||
float outlineThickness;
|
||||
unsigned int characterSize;
|
||||
};
|
||||
|
||||
struct FontData
|
||||
{
|
||||
std::shared_ptr<Font> font;
|
||||
std::size_t useCount = 0;
|
||||
|
||||
NazaraSlot(Font, OnFontAtlasChanged, atlasChangedSlot);
|
||||
NazaraSlot(Font, OnFontAtlasLayerChanged, atlasLayerChangedSlot);
|
||||
NazaraSlot(Font, OnFontGlyphCacheCleared, glyphCacheClearedSlot);
|
||||
NazaraSlot(Font, OnFontRelease, fontReleaseSlot);
|
||||
};
|
||||
|
||||
Color m_currentColor;
|
||||
Color m_currentOutlineColor;
|
||||
TextStyleFlags m_currentStyle;
|
||||
std::shared_ptr<Font> m_currentFont;
|
||||
mutable std::size_t m_lastSeparatorGlyph;
|
||||
std::unordered_map<std::shared_ptr<Font>, 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_currentCharacterSpacingOffset;
|
||||
float m_currentLineSpacingOffset;
|
||||
float m_currentOutlineThickness;
|
||||
float m_maxLineWidth;
|
||||
unsigned int m_currentCharacterSize;
|
||||
mutable float m_lastSeparatorPosition;
|
||||
};
|
||||
|
||||
class RichTextDrawer::BlockRef
|
||||
{
|
||||
friend RichTextDrawer;
|
||||
|
||||
public:
|
||||
BlockRef(const BlockRef&) = default;
|
||||
BlockRef(BlockRef&&) = delete;
|
||||
~BlockRef() = default;
|
||||
|
||||
inline float GetCharacterSpacingOffset() const;
|
||||
inline unsigned int GetCharacterSize() const;
|
||||
inline Color GetColor() const;
|
||||
inline std::size_t GetFirstGlyphIndex() const;
|
||||
inline const std::shared_ptr<Font>& GetFont() const;
|
||||
inline float GetLineSpacingOffset() const;
|
||||
inline Color GetOutlineColor() const;
|
||||
inline float GetOutlineThickness() const;
|
||||
inline TextStyleFlags GetStyle() const;
|
||||
inline const std::string& GetText() const;
|
||||
|
||||
inline void SetCharacterSpacingOffset(float offset);
|
||||
inline void SetCharacterSize(unsigned int size);
|
||||
inline void SetColor(Color color);
|
||||
inline void SetFont(std::shared_ptr<Font> font);
|
||||
inline void SetLineSpacingOffset(float offset);
|
||||
inline void SetOutlineColor(Color color);
|
||||
inline void SetOutlineThickness(float thickness);
|
||||
inline void SetStyle(TextStyleFlags style);
|
||||
inline void SetText(std::string text);
|
||||
|
||||
BlockRef& operator=(const BlockRef&) = delete;
|
||||
BlockRef& operator=(BlockRef&&) = delete;
|
||||
|
||||
private:
|
||||
inline BlockRef(RichTextDrawer& drawer, std::size_t index);
|
||||
|
||||
std::size_t m_blockIndex;
|
||||
RichTextDrawer& m_drawer;
|
||||
};
|
||||
}
|
||||
|
||||
#include <Nazara/TextRenderer/RichTextDrawer.inl>
|
||||
|
||||
#endif // NAZARA_TEXTRENDERER_RICHTEXTDRAWER_HPP
|
||||
623
include/Nazara/TextRenderer/RichTextDrawer.inl
Normal file
623
include/Nazara/TextRenderer/RichTextDrawer.inl
Normal file
@@ -0,0 +1,623 @@
|
||||
// Copyright (C) 2024 Jérôme "SirLynix" Leclercq (lynix680@gmail.com)
|
||||
// This file is part of the "Nazara Engine - Text renderer"
|
||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||
|
||||
#include <Nazara/TextRenderer/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 std::shared_ptr<Font>& 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::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 std::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::GetCharacterSize() const
|
||||
{
|
||||
return m_currentCharacterSize;
|
||||
}
|
||||
|
||||
inline float RichTextDrawer::GetCharacterSpacingOffset() const
|
||||
{
|
||||
return m_currentCharacterSpacingOffset;
|
||||
}
|
||||
|
||||
inline float RichTextDrawer::GetLineSpacingOffset() const
|
||||
{
|
||||
return m_currentLineSpacingOffset;
|
||||
}
|
||||
|
||||
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 = Rectf::Zero(); //< Compute bounds as float to speedup bounds computation (as casting between floats and integers is costly)
|
||||
m_lastSeparatorGlyph = InvalidGlyph;
|
||||
m_lines.clear();
|
||||
m_glyphs.clear();
|
||||
m_glyphUpdated = true;
|
||||
}
|
||||
|
||||
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 std::shared_ptr<Font>& 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 const Color& RichTextDrawer::GetTextColor() const
|
||||
{
|
||||
return m_currentColor;
|
||||
}
|
||||
|
||||
inline const std::shared_ptr<Font>& RichTextDrawer::GetTextFont() const
|
||||
{
|
||||
return m_currentFont;
|
||||
}
|
||||
|
||||
inline const Color& RichTextDrawer::GetTextOutlineColor() const
|
||||
{
|
||||
return m_currentOutlineColor;
|
||||
}
|
||||
|
||||
inline float RichTextDrawer::GetTextOutlineThickness() const
|
||||
{
|
||||
return m_currentOutlineThickness;
|
||||
}
|
||||
|
||||
inline TextStyleFlags RichTextDrawer::GetTextStyle() const
|
||||
{
|
||||
return m_currentStyle;
|
||||
}
|
||||
|
||||
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, std::shared_ptr<Font> 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, std::string str)
|
||||
{
|
||||
NazaraAssert(index < m_blocks.size(), "Invalid block index");
|
||||
|
||||
std::size_t previousLength = m_blocks[index].text.size(); //< FIXME: Count Unicode glyphs
|
||||
|
||||
m_blocks[index].text = std::move(str);
|
||||
|
||||
std::size_t newLength = m_blocks[index].text.size(); //< FIXME: Count Unicode glyphs
|
||||
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::SetCharacterSize(unsigned int characterSize)
|
||||
{
|
||||
m_currentCharacterSize = characterSize;
|
||||
}
|
||||
|
||||
inline void RichTextDrawer::SetCharacterSpacingOffset(float offset)
|
||||
{
|
||||
m_currentCharacterSpacingOffset = offset;
|
||||
}
|
||||
|
||||
inline void RichTextDrawer::SetLineSpacingOffset(float offset)
|
||||
{
|
||||
m_currentLineSpacingOffset = offset;
|
||||
}
|
||||
|
||||
inline void RichTextDrawer::SetTextColor(const Color& color)
|
||||
{
|
||||
m_currentColor = color;
|
||||
}
|
||||
|
||||
inline void RichTextDrawer::SetTextFont(const std::shared_ptr<Font>& font)
|
||||
{
|
||||
m_currentFont = font;
|
||||
}
|
||||
|
||||
inline void RichTextDrawer::SetTextOutlineColor(const Color& color)
|
||||
{
|
||||
m_currentOutlineColor = color;
|
||||
}
|
||||
|
||||
inline void RichTextDrawer::SetTextOutlineThickness(float thickness)
|
||||
{
|
||||
m_currentOutlineThickness = thickness;
|
||||
}
|
||||
|
||||
inline void RichTextDrawer::SetTextStyle(TextStyleFlags style)
|
||||
{
|
||||
m_currentStyle = 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, GetTextColor, GetStyle, GetText, SetFont
|
||||
*/
|
||||
inline const std::shared_ptr<Font>& 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 GetTextColor, GetTextFont, 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, GetTextColor, 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, GetTextColor, 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, GetTextColor, GetTextFont, 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, GetTextColor, GetTextFont, GetStyle, SetText
|
||||
*/
|
||||
inline const std::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 GetTextColor, 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, SetTextColor, SetStyle, SetText
|
||||
*/
|
||||
inline void RichTextDrawer::BlockRef::SetFont(std::shared_ptr<Font> 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, SetTextColor, SetTextFont, 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, SetTextColor, 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, SetTextColor, 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, SetTextColor, SetTextFont, 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, SetTextColor, SetTextFont, SetTextStyle
|
||||
*/
|
||||
inline void RichTextDrawer::BlockRef::SetText(std::string text)
|
||||
{
|
||||
m_drawer.SetBlockText(m_blockIndex, std::move(text));
|
||||
}
|
||||
}
|
||||
|
||||
#include <Nazara/TextRenderer/DebugOff.hpp>
|
||||
126
include/Nazara/TextRenderer/SimpleTextDrawer.hpp
Normal file
126
include/Nazara/TextRenderer/SimpleTextDrawer.hpp
Normal file
@@ -0,0 +1,126 @@
|
||||
// Copyright (C) 2024 Jérôme "SirLynix" Leclercq (lynix680@gmail.com)
|
||||
// This file is part of the "Nazara Engine - Text renderer"
|
||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef NAZARA_TEXTRENDERER_SIMPLETEXTDRAWER_HPP
|
||||
#define NAZARA_TEXTRENDERER_SIMPLETEXTDRAWER_HPP
|
||||
|
||||
#include <NazaraUtils/Prerequisites.hpp>
|
||||
#include <Nazara/Core/Enums.hpp>
|
||||
#include <Nazara/TextRenderer/AbstractTextDrawer.hpp>
|
||||
#include <Nazara/TextRenderer/Font.hpp>
|
||||
#include <vector>
|
||||
|
||||
namespace Nz
|
||||
{
|
||||
class NAZARA_TEXTRENDERER_API SimpleTextDrawer : public AbstractTextDrawer
|
||||
{
|
||||
public:
|
||||
inline SimpleTextDrawer();
|
||||
inline SimpleTextDrawer(const SimpleTextDrawer& drawer);
|
||||
inline SimpleTextDrawer(SimpleTextDrawer&& drawer) noexcept;
|
||||
~SimpleTextDrawer() = default;
|
||||
|
||||
inline void AppendText(std::string_view str);
|
||||
|
||||
void Clear() override;
|
||||
|
||||
const Rectf& GetBounds() const override;
|
||||
inline float GetCharacterSpacingOffset() const;
|
||||
inline unsigned int GetCharacterSize() const;
|
||||
const std::shared_ptr<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;
|
||||
inline float GetLineHeight() const;
|
||||
inline float GetLineSpacingOffset() const;
|
||||
float GetMaxLineWidth() const override;
|
||||
|
||||
inline const std::string& GetText() const;
|
||||
inline const Color& GetTextColor() const;
|
||||
inline const std::shared_ptr<Font>& GetTextFont() const;
|
||||
inline const Color& GetTextOutlineColor() const;
|
||||
inline float GetTextOutlineThickness() const;
|
||||
inline TextStyleFlags GetTextStyle() const;
|
||||
|
||||
inline void SetCharacterSpacingOffset(float offset);
|
||||
inline void SetCharacterSize(unsigned int characterSize);
|
||||
inline void SetLineSpacingOffset(float offset);
|
||||
inline void SetMaxLineWidth(float lineWidth) override;
|
||||
inline void SetText(std::string str);
|
||||
inline void SetTextColor(const Color& color);
|
||||
inline void SetTextFont(std::shared_ptr<Font> font);
|
||||
inline void SetTextOutlineColor(const Color& color);
|
||||
inline void SetTextOutlineThickness(float thickness);
|
||||
inline void SetTextStyle(TextStyleFlags style);
|
||||
|
||||
inline SimpleTextDrawer& operator=(const SimpleTextDrawer& drawer);
|
||||
inline SimpleTextDrawer& operator=(SimpleTextDrawer&& drawer) noexcept;
|
||||
|
||||
static inline SimpleTextDrawer Draw(std::string str, unsigned int characterSize, TextStyleFlags style = TextStyle_Regular, const Color& color = Color::White());
|
||||
static inline SimpleTextDrawer Draw(std::string str, unsigned int characterSize, TextStyleFlags style, const Color& color, float outlineThickness, const Color& outlineColor);
|
||||
static inline SimpleTextDrawer Draw(const std::shared_ptr<Font>& font, std::string str, unsigned int characterSize, TextStyleFlags style = TextStyle_Regular, const Color& color = Color::White());
|
||||
static inline SimpleTextDrawer Draw(const std::shared_ptr<Font>& font, std::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;
|
||||
|
||||
inline void ConnectFontSlots();
|
||||
inline void DisconnectFontSlots();
|
||||
|
||||
bool GenerateGlyph(Glyph& glyph, char32_t character, float outlineThickness, bool lineWrap, Color color, int renderOrder, int* advance) const;
|
||||
void GenerateGlyphs(std::string_view 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);
|
||||
|
||||
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;
|
||||
std::string m_text;
|
||||
Color m_color;
|
||||
Color m_outlineColor;
|
||||
std::shared_ptr<Font> m_font;
|
||||
mutable Rectf m_bounds;
|
||||
TextStyleFlags m_style;
|
||||
mutable UInt32 m_previousCharacter;
|
||||
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/TextRenderer/SimpleTextDrawer.inl>
|
||||
|
||||
#endif // NAZARA_TEXTRENDERER_SIMPLETEXTDRAWER_HPP
|
||||
384
include/Nazara/TextRenderer/SimpleTextDrawer.inl
Normal file
384
include/Nazara/TextRenderer/SimpleTextDrawer.inl
Normal file
@@ -0,0 +1,384 @@
|
||||
// Copyright (C) 2024 Jérôme "SirLynix" Leclercq (lynix680@gmail.com)
|
||||
// This file is part of the "Nazara Engine - Text renderer"
|
||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||
|
||||
#include <Nazara/TextRenderer/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)
|
||||
{
|
||||
SetTextFont(Font::GetDefault());
|
||||
}
|
||||
|
||||
inline SimpleTextDrawer::SimpleTextDrawer(const SimpleTextDrawer& drawer) :
|
||||
m_text(drawer.m_text),
|
||||
m_color(drawer.m_color),
|
||||
m_outlineColor(drawer.m_outlineColor),
|
||||
m_style(drawer.m_style),
|
||||
m_colorUpdated(false),
|
||||
m_glyphUpdated(false),
|
||||
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)
|
||||
{
|
||||
SetTextFont(drawer.m_font);
|
||||
}
|
||||
|
||||
inline SimpleTextDrawer::SimpleTextDrawer(SimpleTextDrawer&& drawer) noexcept
|
||||
{
|
||||
operator=(std::move(drawer));
|
||||
}
|
||||
|
||||
inline void SimpleTextDrawer::AppendText(std::string_view 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 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 std::string& SimpleTextDrawer::GetText() const
|
||||
{
|
||||
return m_text;
|
||||
}
|
||||
|
||||
inline const Color& SimpleTextDrawer::GetTextColor() const
|
||||
{
|
||||
return m_color;
|
||||
}
|
||||
|
||||
inline const std::shared_ptr<Font>& SimpleTextDrawer::GetTextFont() const
|
||||
{
|
||||
return m_font;
|
||||
}
|
||||
|
||||
inline const Color& SimpleTextDrawer::GetTextOutlineColor() const
|
||||
{
|
||||
return m_outlineColor;
|
||||
}
|
||||
|
||||
inline float SimpleTextDrawer::GetTextOutlineThickness() const
|
||||
{
|
||||
return m_outlineThickness;
|
||||
}
|
||||
|
||||
inline TextStyleFlags SimpleTextDrawer::GetTextStyle() const
|
||||
{
|
||||
return m_style;
|
||||
}
|
||||
|
||||
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::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::SetText(std::string str)
|
||||
{
|
||||
if (m_text != str)
|
||||
{
|
||||
m_text = std::move(str);
|
||||
|
||||
InvalidateGlyphs();
|
||||
}
|
||||
}
|
||||
|
||||
inline void SimpleTextDrawer::SetTextColor(const Color& color)
|
||||
{
|
||||
if (m_color != color)
|
||||
{
|
||||
m_color = color;
|
||||
|
||||
InvalidateColor();
|
||||
}
|
||||
}
|
||||
|
||||
inline void SimpleTextDrawer::SetTextFont(std::shared_ptr<Font> font)
|
||||
{
|
||||
if (m_font != font)
|
||||
{
|
||||
m_font = std::move(font);
|
||||
|
||||
if (m_font)
|
||||
ConnectFontSlots();
|
||||
else
|
||||
DisconnectFontSlots();
|
||||
|
||||
InvalidateGlyphs();
|
||||
}
|
||||
}
|
||||
|
||||
inline void SimpleTextDrawer::SetTextOutlineColor(const Color& color)
|
||||
{
|
||||
if (m_outlineColor != color)
|
||||
{
|
||||
m_outlineColor = color;
|
||||
|
||||
InvalidateColor();
|
||||
}
|
||||
}
|
||||
|
||||
inline void SimpleTextDrawer::SetTextOutlineThickness(float thickness)
|
||||
{
|
||||
if (m_outlineThickness != thickness)
|
||||
{
|
||||
NazaraAssert(thickness >= 0.f, "Thickness must be zero or positive");
|
||||
|
||||
m_outlineThickness = thickness;
|
||||
|
||||
InvalidateGlyphs();
|
||||
}
|
||||
}
|
||||
|
||||
inline void SimpleTextDrawer::SetTextStyle(TextStyleFlags style)
|
||||
{
|
||||
if (m_style != style)
|
||||
{
|
||||
m_style = style;
|
||||
|
||||
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;
|
||||
|
||||
SetTextFont(drawer.m_font);
|
||||
InvalidateGlyphs();
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline SimpleTextDrawer& SimpleTextDrawer::operator=(SimpleTextDrawer&& drawer) noexcept
|
||||
{
|
||||
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(std::string str, unsigned int characterSize, TextStyleFlags style, const Color& color)
|
||||
{
|
||||
SimpleTextDrawer drawer;
|
||||
drawer.SetCharacterSize(characterSize);
|
||||
drawer.SetTextColor(color);
|
||||
drawer.SetTextStyle(style);
|
||||
drawer.SetText(std::move(str));
|
||||
|
||||
return drawer;
|
||||
}
|
||||
|
||||
inline SimpleTextDrawer SimpleTextDrawer::Draw(std::string str, unsigned int characterSize, TextStyleFlags style, const Color& color, float outlineThickness, const Color& outlineColor)
|
||||
{
|
||||
SimpleTextDrawer drawer;
|
||||
drawer.SetCharacterSize(characterSize);
|
||||
drawer.SetTextColor(color);
|
||||
drawer.SetTextOutlineColor(outlineColor);
|
||||
drawer.SetTextOutlineThickness(outlineThickness);
|
||||
drawer.SetTextStyle(style);
|
||||
drawer.SetText(std::move(str));
|
||||
|
||||
return drawer;
|
||||
}
|
||||
|
||||
inline SimpleTextDrawer SimpleTextDrawer::Draw(const std::shared_ptr<Font>& font, std::string str, unsigned int characterSize, TextStyleFlags style, const Color& color)
|
||||
{
|
||||
SimpleTextDrawer drawer;
|
||||
drawer.SetCharacterSize(characterSize);
|
||||
drawer.SetTextColor(color);
|
||||
drawer.SetTextFont(font);
|
||||
drawer.SetTextStyle(style);
|
||||
drawer.SetText(std::move(str));
|
||||
|
||||
return drawer;
|
||||
}
|
||||
|
||||
inline SimpleTextDrawer SimpleTextDrawer::Draw(const std::shared_ptr<Font>& font, std::string str, unsigned int characterSize, TextStyleFlags style, const Color& color, float outlineThickness, const Color& outlineColor)
|
||||
{
|
||||
SimpleTextDrawer drawer;
|
||||
drawer.SetCharacterSize(characterSize);
|
||||
drawer.SetTextColor(color);
|
||||
drawer.SetTextFont(font);
|
||||
drawer.SetTextOutlineColor(outlineColor);
|
||||
drawer.SetTextOutlineThickness(outlineThickness);
|
||||
drawer.SetTextStyle(style);
|
||||
drawer.SetText(std::move(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/TextRenderer/DebugOff.hpp>
|
||||
39
include/Nazara/TextRenderer/TextRenderer.hpp
Normal file
39
include/Nazara/TextRenderer/TextRenderer.hpp
Normal file
@@ -0,0 +1,39 @@
|
||||
// Copyright (C) 2024 Jérôme "SirLynix" Leclercq (lynix680@gmail.com)
|
||||
// This file is part of the "Nazara Engine - Text renderer"
|
||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef NAZARA_TEXTRENDERER_HPP
|
||||
#define NAZARA_TEXTRENDERER_HPP
|
||||
|
||||
#include <NazaraUtils/Prerequisites.hpp>
|
||||
#include <Nazara/Core/Core.hpp>
|
||||
#include <Nazara/TextRenderer/Config.hpp>
|
||||
#include <Nazara/TextRenderer/Font.hpp>
|
||||
|
||||
namespace Nz
|
||||
{
|
||||
class NAZARA_TEXTRENDERER_API TextRenderer : public ModuleBase<TextRenderer>
|
||||
{
|
||||
friend ModuleBase;
|
||||
|
||||
public:
|
||||
using Dependencies = TypeList<Core>;
|
||||
|
||||
struct Config {};
|
||||
|
||||
TextRenderer(Config /*config*/);
|
||||
~TextRenderer();
|
||||
|
||||
FontLoader& GetFontLoader();
|
||||
const FontLoader& GetFontLoader() const;
|
||||
|
||||
private:
|
||||
FontLoader m_fontLoader;
|
||||
|
||||
static TextRenderer* s_instance;
|
||||
};
|
||||
}
|
||||
|
||||
#endif // NAZARA_TEXTRENDERER_HPP
|
||||
Reference in New Issue
Block a user