Added Atlas listeners
Former-commit-id: a487b6ed53d9b97bfee27b28ba5523e43c1e9e7e
This commit is contained in:
parent
6885166dc5
commit
e3de7e6f3c
|
|
@ -10,31 +10,45 @@
|
||||||
#include <Nazara/Prerequesites.hpp>
|
#include <Nazara/Prerequesites.hpp>
|
||||||
#include <Nazara/Core/SparsePtr.hpp>
|
#include <Nazara/Core/SparsePtr.hpp>
|
||||||
#include <Nazara/Math/Rect.hpp>
|
#include <Nazara/Math/Rect.hpp>
|
||||||
#include <set>
|
#include <unordered_map>
|
||||||
|
|
||||||
class NzAbstractImage;
|
class NzAbstractImage;
|
||||||
class NzFont;
|
|
||||||
class NzImage;
|
class NzImage;
|
||||||
|
|
||||||
class NAZARA_API NzAbstractFontAtlas
|
class NAZARA_API NzAbstractFontAtlas
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
NzAbstractFontAtlas() = default;
|
class Listener;
|
||||||
|
|
||||||
|
NzAbstractFontAtlas();
|
||||||
virtual ~NzAbstractFontAtlas();
|
virtual ~NzAbstractFontAtlas();
|
||||||
|
|
||||||
|
void AddListener(Listener* font, void* userdata = nullptr) const;
|
||||||
|
|
||||||
virtual void Clear() = 0;
|
virtual void Clear() = 0;
|
||||||
virtual void Free(NzSparsePtr<const NzRectui> rects, NzSparsePtr<unsigned int> layers, unsigned int count) = 0;
|
virtual void Free(NzSparsePtr<const NzRectui> rects, NzSparsePtr<unsigned int> layers, unsigned int count) = 0;
|
||||||
virtual NzAbstractImage* GetLayer(unsigned int layerIndex) const = 0;
|
virtual NzAbstractImage* GetLayer(unsigned int layerIndex) const = 0;
|
||||||
virtual unsigned int GetLayerCount() const = 0;
|
virtual unsigned int GetLayerCount() const = 0;
|
||||||
virtual bool Insert(const NzImage& image, NzRectui* rect, bool* flipped, unsigned int* layerIndex) = 0;
|
virtual bool Insert(const NzImage& image, NzRectui* rect, bool* flipped, unsigned int* layerIndex) = 0;
|
||||||
void RegisterFont(NzFont* font);
|
|
||||||
void UnregisterFont(NzFont* font);
|
void RemoveListener(Listener* font) const;
|
||||||
|
|
||||||
|
class Listener
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Listener() = default;
|
||||||
|
virtual ~Listener();
|
||||||
|
|
||||||
|
virtual bool OnAtlasCleared(const NzAbstractFontAtlas* atlas, void* userdata);
|
||||||
|
virtual void OnAtlasReleased(const NzAbstractFontAtlas* atlas, void* userdata);
|
||||||
|
};
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void NotifyCleared();
|
void NotifyCleared();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::set<NzFont*> m_registredFonts;
|
mutable std::unordered_map<Listener*, void*> m_listeners;
|
||||||
|
bool m_listenersLocked;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // NAZARA_ABSTRACTFONTATLAS_HPP
|
#endif // NAZARA_ABSTRACTFONTATLAS_HPP
|
||||||
|
|
|
||||||
|
|
@ -29,7 +29,7 @@ using NzFontConstRef = NzResourceRef<const NzFont>;
|
||||||
using NzFontLoader = NzResourceLoader<NzFont, NzFontParams>;
|
using NzFontLoader = NzResourceLoader<NzFont, NzFontParams>;
|
||||||
using NzFontRef = NzResourceRef<NzFont>;
|
using NzFontRef = NzResourceRef<NzFont>;
|
||||||
|
|
||||||
class NAZARA_API NzFont : public NzResource, NzNonCopyable
|
class NAZARA_API NzFont : public NzResource, NzAbstractFontAtlas::Listener, NzNonCopyable
|
||||||
{
|
{
|
||||||
friend NzAbstractFontAtlas;
|
friend NzAbstractFontAtlas;
|
||||||
friend NzFontLoader;
|
friend NzFontLoader;
|
||||||
|
|
@ -108,7 +108,8 @@ class NAZARA_API NzFont : public NzResource, NzNonCopyable
|
||||||
using GlyphMap = std::unordered_map<char32_t, Glyph>;
|
using GlyphMap = std::unordered_map<char32_t, Glyph>;
|
||||||
|
|
||||||
nzUInt64 ComputeKey(unsigned int characterSize, nzUInt32 style) const;
|
nzUInt64 ComputeKey(unsigned int characterSize, nzUInt32 style) const;
|
||||||
void OnAtlasCleared();
|
bool OnAtlasCleared(const NzAbstractFontAtlas* atlas, void* userdata) override;
|
||||||
|
void OnAtlasReleased(const NzAbstractFontAtlas* atlas, void* userdata) override;
|
||||||
const Glyph& PrecacheGlyph(GlyphMap& glyphMap, unsigned int characterSize, nzUInt32 style, char32_t character) const;
|
const Glyph& PrecacheGlyph(GlyphMap& glyphMap, unsigned int characterSize, nzUInt32 style, char32_t character) const;
|
||||||
|
|
||||||
std::shared_ptr<NzAbstractFontAtlas> m_atlas;
|
std::shared_ptr<NzAbstractFontAtlas> m_atlas;
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,6 @@
|
||||||
#include <Nazara/Utility/AbstractImage.hpp>
|
#include <Nazara/Utility/AbstractImage.hpp>
|
||||||
#include <Nazara/Utility/Image.hpp>
|
#include <Nazara/Utility/Image.hpp>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <set>
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
class NAZARA_API NzGuillotineImageAtlas : public NzAbstractFontAtlas
|
class NAZARA_API NzGuillotineImageAtlas : public NzAbstractFontAtlas
|
||||||
|
|
@ -59,7 +58,6 @@ class NAZARA_API NzGuillotineImageAtlas : public NzAbstractFontAtlas
|
||||||
private:
|
private:
|
||||||
void ProcessGlyphQueue(Layer& layer) const;
|
void ProcessGlyphQueue(Layer& layer) const;
|
||||||
|
|
||||||
std::set<NzFont*> m_fonts;
|
|
||||||
mutable std::vector<Layer> m_layers;
|
mutable std::vector<Layer> m_layers;
|
||||||
NzGuillotineBinPack::FreeRectChoiceHeuristic m_rectChoiceHeuristic;
|
NzGuillotineBinPack::FreeRectChoiceHeuristic m_rectChoiceHeuristic;
|
||||||
NzGuillotineBinPack::GuillotineSplitHeuristic m_rectSplitHeuristic;
|
NzGuillotineBinPack::GuillotineSplitHeuristic m_rectSplitHeuristic;
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,63 @@
|
||||||
|
// Copyright (C) 2015 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/AbstractFontAtlas.hpp>
|
||||||
|
#include <Nazara/Utility/Font.hpp>
|
||||||
|
#include <Nazara/Utility/Debug.hpp>
|
||||||
|
|
||||||
|
NzAbstractFontAtlas::NzAbstractFontAtlas() :
|
||||||
|
m_listenersLocked(false)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
NzAbstractFontAtlas::~NzAbstractFontAtlas()
|
||||||
|
{
|
||||||
|
m_listenersLocked = true;
|
||||||
|
for (auto& pair : m_listeners)
|
||||||
|
pair.first->OnAtlasReleased(this, pair.second);
|
||||||
|
}
|
||||||
|
|
||||||
|
void NzAbstractFontAtlas::AddListener(Listener* listener, void* userdata) const
|
||||||
|
{
|
||||||
|
if (!m_listenersLocked)
|
||||||
|
m_listeners.insert(std::make_pair(listener, userdata));
|
||||||
|
}
|
||||||
|
|
||||||
|
void NzAbstractFontAtlas::RemoveListener(Listener* listener) const
|
||||||
|
{
|
||||||
|
if (!m_listenersLocked)
|
||||||
|
m_listeners.erase(listener);
|
||||||
|
}
|
||||||
|
|
||||||
|
void NzAbstractFontAtlas::NotifyCleared()
|
||||||
|
{
|
||||||
|
m_listenersLocked = true;
|
||||||
|
|
||||||
|
auto it = m_listeners.begin();
|
||||||
|
while (it != m_listeners.end())
|
||||||
|
{
|
||||||
|
if (!it->first->OnAtlasCleared(this, it->second))
|
||||||
|
m_listeners.erase(it++);
|
||||||
|
else
|
||||||
|
++it;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_listenersLocked = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
NzAbstractFontAtlas::Listener::~Listener() = default;
|
||||||
|
|
||||||
|
bool NzAbstractFontAtlas::Listener::OnAtlasCleared(const NzAbstractFontAtlas* atlas, void* userdata)
|
||||||
|
{
|
||||||
|
NazaraUnused(atlas);
|
||||||
|
NazaraUnused(userdata);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void NzAbstractFontAtlas::Listener::OnAtlasReleased(const NzAbstractFontAtlas* atlas, void* userdata)
|
||||||
|
{
|
||||||
|
NazaraUnused(atlas);
|
||||||
|
NazaraUnused(userdata);
|
||||||
|
}
|
||||||
|
|
@ -28,8 +28,11 @@ void NzFont::ClearGlyphCache()
|
||||||
{
|
{
|
||||||
if (m_atlas)
|
if (m_atlas)
|
||||||
{
|
{
|
||||||
if (m_atlas.use_count() > 1) // Au moins une autre police utilise cet atlas, on vire nos glyphes
|
if (m_atlas.unique())
|
||||||
|
m_atlas->Clear(); // Appellera OnAtlasCleared
|
||||||
|
else
|
||||||
{
|
{
|
||||||
|
// Au moins une autre police utilise cet atlas, on vire nos glyphes un par un
|
||||||
for (auto mapIt = m_glyphes.begin(); mapIt != m_glyphes.end(); ++mapIt)
|
for (auto mapIt = m_glyphes.begin(); mapIt != m_glyphes.end(); ++mapIt)
|
||||||
{
|
{
|
||||||
GlyphMap& glyphMap = mapIt->second;
|
GlyphMap& glyphMap = mapIt->second;
|
||||||
|
|
@ -40,12 +43,10 @@ void NzFont::ClearGlyphCache()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Destruction des glyphes mémorisés
|
// Destruction des glyphes mémorisés et notification
|
||||||
m_glyphes.clear();
|
m_glyphes.clear();
|
||||||
NotifyModified(ModificationCode_GlyphCacheCleared);
|
NotifyModified(ModificationCode_GlyphCacheCleared);
|
||||||
}
|
}
|
||||||
else
|
|
||||||
m_atlas->Clear();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -268,7 +269,12 @@ void NzFont::SetAtlas(std::shared_ptr<NzAbstractFontAtlas> atlas)
|
||||||
{
|
{
|
||||||
ClearGlyphCache();
|
ClearGlyphCache();
|
||||||
|
|
||||||
|
if (m_atlas)
|
||||||
|
m_atlas->RemoveListener(this);
|
||||||
|
|
||||||
m_atlas = atlas;
|
m_atlas = atlas;
|
||||||
|
if (m_atlas)
|
||||||
|
m_atlas->AddListener(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
void NzFont::SetGlyphBorder(unsigned int borderSize)
|
void NzFont::SetGlyphBorder(unsigned int borderSize)
|
||||||
|
|
@ -293,7 +299,10 @@ void NzFont::SetMinimumStepSize(unsigned int minimumStepSize)
|
||||||
|
|
||||||
nzUInt64 NzFont::ComputeKey(unsigned int characterSize, nzUInt32 style) const
|
nzUInt64 NzFont::ComputeKey(unsigned int characterSize, nzUInt32 style) const
|
||||||
{
|
{
|
||||||
|
// On prend le pas en compte
|
||||||
nzUInt64 sizePart = static_cast<nzUInt32>((characterSize/m_minimumSizeStep)*m_minimumSizeStep);
|
nzUInt64 sizePart = static_cast<nzUInt32>((characterSize/m_minimumSizeStep)*m_minimumSizeStep);
|
||||||
|
|
||||||
|
// Ainsi que le style (uniquement le gras et l'italique, les autres sont gérés par un TextDrawer)
|
||||||
nzUInt64 stylePart = 0;
|
nzUInt64 stylePart = 0;
|
||||||
|
|
||||||
if (style & nzTextStyle_Bold)
|
if (style & nzTextStyle_Bold)
|
||||||
|
|
@ -305,12 +314,43 @@ nzUInt64 NzFont::ComputeKey(unsigned int characterSize, nzUInt32 style) const
|
||||||
return (stylePart << 32) | sizePart;
|
return (stylePart << 32) | sizePart;
|
||||||
}
|
}
|
||||||
|
|
||||||
void NzFont::OnAtlasCleared()
|
bool NzFont::OnAtlasCleared(const NzAbstractFontAtlas* atlas, void* userdata)
|
||||||
{
|
{
|
||||||
|
NazaraUnused(atlas);
|
||||||
|
NazaraUnused(userdata);
|
||||||
|
|
||||||
|
#ifdef NAZARA_DEBUG
|
||||||
|
// Est-ce qu'il s'agit bien de notre atlas ?
|
||||||
|
if (m_atlas != atlas)
|
||||||
|
{
|
||||||
|
NazaraInternalError("Notified by a non-listening-to resource");
|
||||||
|
return false; // On ne veut plus être notifié par cette ressource, évidemment
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
// Notre atlas vient d'être vidé, détruisons le cache de glyphe
|
// Notre atlas vient d'être vidé, détruisons le cache de glyphe
|
||||||
m_glyphes.clear();
|
m_glyphes.clear();
|
||||||
|
|
||||||
NotifyModified(ModificationCode_GlyphCacheCleared);
|
NotifyModified(ModificationCode_GlyphCacheCleared);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void NzFont::OnAtlasReleased(const NzAbstractFontAtlas* atlas, void* userdata)
|
||||||
|
{
|
||||||
|
NazaraUnused(atlas);
|
||||||
|
NazaraUnused(userdata);
|
||||||
|
|
||||||
|
#ifdef NAZARA_DEBUG
|
||||||
|
// Est-ce qu'il s'agit bien de notre atlas ?
|
||||||
|
if (m_atlas != atlas)
|
||||||
|
{
|
||||||
|
NazaraInternalError("Notified by a non-listening-to resource");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Nous ne pouvons pas faire grand chose d'autre que se balancer une erreur à la tête de l'utilisateur avant un potentiel crash...
|
||||||
|
NazaraError("Atlas has been released while in use");
|
||||||
}
|
}
|
||||||
|
|
||||||
const NzFont::Glyph& NzFont::PrecacheGlyph(GlyphMap& glyphMap, unsigned int characterSize, nzUInt32 style, char32_t character) const
|
const NzFont::Glyph& NzFont::PrecacheGlyph(GlyphMap& glyphMap, unsigned int characterSize, nzUInt32 style, char32_t character) const
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue