From c40da067cd9df0ccfd7784070a8331af2f0f388b Mon Sep 17 00:00:00 2001 From: reuk Date: Wed, 28 Feb 2024 13:44:35 +0000 Subject: [PATCH] RenderingHelpers: Implement GlyphCache in terms of LruCache --- .../contexts/juce_GraphicsContext.cpp | 5 - modules/juce_graphics/fonts/juce_LruCache.h | 2 +- modules/juce_graphics/juce_graphics.cpp | 1 - modules/juce_graphics/juce_graphics.h | 1 + .../native/juce_RenderingHelpers.h | 163 +++++------------- 5 files changed, 43 insertions(+), 129 deletions(-) diff --git a/modules/juce_graphics/contexts/juce_GraphicsContext.cpp b/modules/juce_graphics/contexts/juce_GraphicsContext.cpp index 205697c78f..58cbf9a5b6 100644 --- a/modules/juce_graphics/contexts/juce_GraphicsContext.cpp +++ b/modules/juce_graphics/contexts/juce_GraphicsContext.cpp @@ -35,11 +35,6 @@ namespace juce { -struct GraphicsFontHelpers -{ - static auto compareFont (const Font& a, const Font& b) { return Font::compare (a, b); } -}; - static auto operator< (const Font& a, const Font& b) { return GraphicsFontHelpers::compareFont (a, b); diff --git a/modules/juce_graphics/fonts/juce_LruCache.h b/modules/juce_graphics/fonts/juce_LruCache.h index 96ab860533..cf50c7a66c 100644 --- a/modules/juce_graphics/fonts/juce_LruCache.h +++ b/modules/juce_graphics/fonts/juce_LruCache.h @@ -40,7 +40,7 @@ class LruCache { public: template - Value get (Key key, Fn&& fn) + const Value& get (Key key, Fn&& fn) { if (const auto iter = map.find (key); iter != map.end()) { diff --git a/modules/juce_graphics/juce_graphics.cpp b/modules/juce_graphics/juce_graphics.cpp index 11fbc88664..87b661a3dc 100644 --- a/modules/juce_graphics/juce_graphics.cpp +++ b/modules/juce_graphics/juce_graphics.cpp @@ -120,7 +120,6 @@ //============================================================================== #include "fonts/juce_FunctionPointerDestructor.h" -#include "fonts/juce_LruCache.h" #include "colour/juce_Colour.cpp" #include "colour/juce_ColourGradient.cpp" diff --git a/modules/juce_graphics/juce_graphics.h b/modules/juce_graphics/juce_graphics.h index dcadec03a7..524c594b4d 100644 --- a/modules/juce_graphics/juce_graphics.h +++ b/modules/juce_graphics/juce_graphics.h @@ -150,6 +150,7 @@ namespace juce #include "images/juce_Image.h" #include "images/juce_ScaledImage.h" #include "colour/juce_FillType.h" +#include "fonts/juce_LruCache.h" #include "native/juce_RenderingHelpers.h" #include "contexts/juce_LowLevelGraphicsSoftwareRenderer.h" #include "contexts/juce_LowLevelGraphicsPostScriptRenderer.h" diff --git a/modules/juce_graphics/native/juce_RenderingHelpers.h b/modules/juce_graphics/native/juce_RenderingHelpers.h index b6c86c493b..07994b9119 100644 --- a/modules/juce_graphics/native/juce_RenderingHelpers.h +++ b/modules/juce_graphics/native/juce_RenderingHelpers.h @@ -32,6 +32,14 @@ ============================================================================== */ +namespace juce +{ + struct GraphicsFontHelpers + { + static auto compareFont (const Font& a, const Font& b) { return Font::compare (a, b); } + }; +} + namespace juce::RenderingHelpers { @@ -142,43 +150,6 @@ public: bool isOnlyTranslated = true, isRotated = false; }; -//============================================================================== -/** Caches a glyph as an edge-table. - - @tags{Graphics} -*/ -class CachedGlyphEdgeTable : public ReferenceCountedObject -{ -public: - CachedGlyphEdgeTable() = default; - - template - void draw (RendererType& state, Point pos) const - { - if (edgeTable != nullptr) - state.fillEdgeTable (*edgeTable, pos.x, roundToInt (pos.y)); - } - - void generate (const Font& newFont, int glyphNumber) - { - font = newFont; - glyph = glyphNumber; - - auto fontHeight = font.getHeight(); - auto typeface = newFont.getTypefacePtr(); - edgeTable.reset (typeface->getEdgeTableForGlyph (glyphNumber, - AffineTransform::scale (fontHeight * font.getHorizontalScale(), - fontHeight), - fontHeight)); - } - - Font font; - std::unique_ptr edgeTable; - int glyph = 0, lastAccessCount = 0; - - JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (CachedGlyphEdgeTable) -}; - //============================================================================== /** Holds a cache of recently-used glyph objects of some type. @@ -187,10 +158,7 @@ public: class GlyphCache : private DeletedAtShutdown { public: - GlyphCache() - { - reset(); - } + GlyphCache() = default; ~GlyphCache() override { @@ -210,98 +178,49 @@ public: //============================================================================== void reset() { - const ScopedLock sl (lock); - glyphs.clear(); - addNewGlyphSlots (120); - hits = 0; - misses = 0; + const ScopedLock sl { lock }; + cache = {}; } template void drawGlyph (RenderTargetType& target, const Font& font, const int glyphNumber, Point pos) { - if (auto glyph = findOrCreateGlyph (font, glyphNumber)) + const ScopedLock sl { lock }; + const auto& table = cache.get (Key { font, glyphNumber }, [] (const auto& key) { - glyph->lastAccessCount = ++accessCounter; - glyph->draw (target, pos); - } + auto fontHeight = key.font.getHeight(); + auto typeface = key.font.getTypefacePtr(); + return rawToUniquePtr (typeface->getEdgeTableForGlyph (key.glyph, + AffineTransform::scale (fontHeight * key.font.getHorizontalScale(), + fontHeight), + fontHeight)); + }); + + if (table != nullptr) + target.fillEdgeTable (*table, pos.x, roundToInt (pos.y)); } private: - ReferenceCountedArray glyphs; - Atomic accessCounter, hits, misses; + struct Key + { + Font font; + int glyph; + + bool operator< (const Key& other) const + { + if (glyph < other.glyph) + return true; + + if (other.glyph < glyph) + return false; + + return GraphicsFontHelpers::compareFont (font, other.font); + } + }; + + LruCache> cache; CriticalSection lock; - ReferenceCountedObjectPtr findOrCreateGlyph (const Font& font, int glyphNumber) - { - const ScopedLock sl (lock); - - if (auto g = findExistingGlyph (font, glyphNumber)) - { - ++hits; - return g; - } - - ++misses; - auto g = getGlyphForReuse(); - jassert (g != nullptr); - g->generate (font, glyphNumber); - return g; - } - - ReferenceCountedObjectPtr findExistingGlyph (const Font& font, int glyphNumber) const noexcept - { - for (auto g : glyphs) - if (g->glyph == glyphNumber && g->font == font) - return *g; - - return {}; - } - - ReferenceCountedObjectPtr getGlyphForReuse() - { - if (hits.get() + misses.get() > glyphs.size() * 16) - { - if (misses.get() * 2 > hits.get()) - addNewGlyphSlots (32); - - hits = 0; - misses = 0; - } - - if (auto g = findLeastRecentlyUsedGlyph()) - return *g; - - addNewGlyphSlots (32); - return glyphs.getLast(); - } - - void addNewGlyphSlots (int num) - { - glyphs.ensureStorageAllocated (glyphs.size() + num); - - while (--num >= 0) - glyphs.add (new CachedGlyphEdgeTable()); - } - - CachedGlyphEdgeTable* findLeastRecentlyUsedGlyph() const noexcept - { - CachedGlyphEdgeTable* oldest = nullptr; - auto oldestCounter = std::numeric_limits::max(); - - for (auto* g : glyphs) - { - if (g->lastAccessCount <= oldestCounter - && g->getReferenceCount() == 1) - { - oldestCounter = g->lastAccessCount; - oldest = g; - } - } - - return oldest; - } - static GlyphCache*& getSingletonPointer() noexcept { static GlyphCache* g = nullptr;