1
0
Fork 0
mirror of https://github.com/juce-framework/JUCE.git synced 2026-01-10 23:44:24 +00:00

RenderingHelpers: Reduce templating of GlyphCache

This commit is contained in:
reuk 2024-02-28 13:04:41 +00:00
parent f5017be881
commit bc654f8007
No known key found for this signature in database
GPG key ID: FCB43929F012EE5C
2 changed files with 82 additions and 86 deletions

View file

@ -35,49 +35,6 @@
namespace juce::RenderingHelpers
{
template <typename Context>
void drawGlyphImpl (Context& context, int glyphNumber, const AffineTransform& trans)
{
using GlyphCacheType = typename Context::GlyphCacheType;
using EdgeTableRegionType = typename Context::EdgeTableRegionType;
if (context.clip == nullptr)
return;
if (trans.isOnlyTranslation() && ! context.transform.isRotated)
{
auto& cache = GlyphCacheType::getInstance();
const Point pos (trans.getTranslationX(), trans.getTranslationY());
if (context.transform.isOnlyTranslated)
{
cache.drawGlyph (context, context.font, glyphNumber, pos + context.transform.offset.toFloat());
}
else
{
auto f = context.font;
f.setHeight (f.getHeight() * context.transform.complexTransform.mat11);
auto xScale = context.transform.complexTransform.mat00 / context.transform.complexTransform.mat11;
if (std::abs (xScale - 1.0f) > 0.01f)
f.setHorizontalScale (xScale);
cache.drawGlyph (context, f, glyphNumber, context.transform.transformed (pos));
}
}
else
{
const auto fontHeight = context.font.getHeight();
const auto fontTransform = AffineTransform::scale (fontHeight * context.font.getHorizontalScale(),
fontHeight).followedBy (trans);
const auto fullTransform = context.transform.getTransformWith (fontTransform);
if (auto et = rawToUniquePtr (context.font.getTypefacePtr()->getEdgeTableForGlyph (glyphNumber, fullTransform, fontHeight)))
context.fillShape (*new EdgeTableRegionType (*et), false);
}
}
JUCE_BEGIN_IGNORE_WARNINGS_MSVC (4127)
//==============================================================================
@ -185,12 +142,48 @@ public:
bool isOnlyTranslated = true, isRotated = false;
};
//==============================================================================
/** Caches a glyph as an edge-table.
@tags{Graphics}
*/
class CachedGlyphEdgeTable : public ReferenceCountedObject
{
public:
CachedGlyphEdgeTable() = default;
template <class RendererType>
void draw (RendererType& state, Point<float> 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> 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.
@tags{Graphics}
*/
template <class CachedGlyphType, class RenderTargetType>
class GlyphCache : private DeletedAtShutdown
{
public:
@ -224,6 +217,7 @@ public:
misses = 0;
}
template <class RenderTargetType>
void drawGlyph (RenderTargetType& target, const Font& font, const int glyphNumber, Point<float> pos)
{
if (auto glyph = findOrCreateGlyph (font, glyphNumber))
@ -234,11 +228,11 @@ public:
}
private:
ReferenceCountedArray<CachedGlyphType> glyphs;
ReferenceCountedArray<CachedGlyphEdgeTable> glyphs;
Atomic<int> accessCounter, hits, misses;
CriticalSection lock;
ReferenceCountedObjectPtr<CachedGlyphType> findOrCreateGlyph (const Font& font, int glyphNumber)
ReferenceCountedObjectPtr<CachedGlyphEdgeTable> findOrCreateGlyph (const Font& font, int glyphNumber)
{
const ScopedLock sl (lock);
@ -255,7 +249,7 @@ private:
return g;
}
ReferenceCountedObjectPtr<CachedGlyphType> findExistingGlyph (const Font& font, int glyphNumber) const noexcept
ReferenceCountedObjectPtr<CachedGlyphEdgeTable> findExistingGlyph (const Font& font, int glyphNumber) const noexcept
{
for (auto g : glyphs)
if (g->glyph == glyphNumber && g->font == font)
@ -264,7 +258,7 @@ private:
return {};
}
ReferenceCountedObjectPtr<CachedGlyphType> getGlyphForReuse()
ReferenceCountedObjectPtr<CachedGlyphEdgeTable> getGlyphForReuse()
{
if (hits.get() + misses.get() > glyphs.size() * 16)
{
@ -287,12 +281,12 @@ private:
glyphs.ensureStorageAllocated (glyphs.size() + num);
while (--num >= 0)
glyphs.add (new CachedGlyphType());
glyphs.add (new CachedGlyphEdgeTable());
}
CachedGlyphType* findLeastRecentlyUsedGlyph() const noexcept
CachedGlyphEdgeTable* findLeastRecentlyUsedGlyph() const noexcept
{
CachedGlyphType* oldest = nullptr;
CachedGlyphEdgeTable* oldest = nullptr;
auto oldestCounter = std::numeric_limits<int>::max();
for (auto* g : glyphs)
@ -317,41 +311,47 @@ private:
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (GlyphCache)
};
//==============================================================================
/** Caches a glyph as an edge-table.
@tags{Graphics}
*/
class CachedGlyphEdgeTable : public ReferenceCountedObject
template <typename Context>
void drawGlyphImpl (Context& context, int glyphNumber, const AffineTransform& trans)
{
public:
CachedGlyphEdgeTable() = default;
using EdgeTableRegionType = typename Context::EdgeTableRegionType;
template <class RendererType>
void draw (RendererType& state, Point<float> pos) const
if (context.clip == nullptr)
return;
if (trans.isOnlyTranslation() && ! context.transform.isRotated)
{
if (edgeTable != nullptr)
state.fillEdgeTable (*edgeTable, pos.x, roundToInt (pos.y));
}
auto& cache = RenderingHelpers::GlyphCache::getInstance();
const Point pos (trans.getTranslationX(), trans.getTranslationY());
void generate (const Font& newFont, int glyphNumber)
if (context.transform.isOnlyTranslated)
{
cache.drawGlyph (context, context.font, glyphNumber, pos + context.transform.offset.toFloat());
}
else
{
auto f = context.font;
f.setHeight (f.getHeight() * context.transform.complexTransform.mat11);
auto xScale = context.transform.complexTransform.mat00 / context.transform.complexTransform.mat11;
if (std::abs (xScale - 1.0f) > 0.01f)
f.setHorizontalScale (xScale);
cache.drawGlyph (context, f, glyphNumber, context.transform.transformed (pos));
}
}
else
{
font = newFont;
auto typeface = newFont.getTypefacePtr();
glyph = glyphNumber;
const auto fontHeight = context.font.getHeight();
const auto fontTransform = AffineTransform::scale (fontHeight * context.font.getHorizontalScale(),
fontHeight).followedBy (trans);
const auto fullTransform = context.transform.getTransformWith (fontTransform);
auto fontHeight = font.getHeight();
edgeTable.reset (typeface->getEdgeTableForGlyph (glyphNumber,
AffineTransform::scale (fontHeight * font.getHorizontalScale(),
fontHeight), fontHeight));
if (auto et = rawToUniquePtr (context.font.getTypefacePtr()->getEdgeTableForGlyph (glyphNumber, fullTransform, fontHeight)))
context.fillShape (*new EdgeTableRegionType (*et), false);
}
Font font;
std::unique_ptr<EdgeTable> edgeTable;
int glyph = 0, lastAccessCount = 0;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (CachedGlyphEdgeTable)
};
}
//==============================================================================
/** Calculates the alpha values and positions for rendering the edges of a
@ -2570,11 +2570,9 @@ public:
}
}
using GlyphCacheType = GlyphCache<CachedGlyphEdgeTable, SoftwareRendererSavedState>;
static void clearGlyphCache()
{
GlyphCacheType::getInstance().reset();
GlyphCache::getInstance().reset();
}
//==============================================================================

View file

@ -1753,15 +1753,13 @@ struct SavedState final : public RenderingHelpers::SavedStateBase<SavedState>
}
}
using GlyphCacheType = RenderingHelpers::GlyphCache<RenderingHelpers::CachedGlyphEdgeTable<SavedState>, SavedState>;
void drawGlyph (int glyphNumber, const AffineTransform& trans)
{
if (clip != nullptr)
{
if (trans.isOnlyTranslation() && ! transform.isRotated)
{
auto& cache = GlyphCacheType::getInstance();
auto& cache = RenderingHelpers::GlyphCache::getInstance();
Point<float> pos (trans.getTranslationX(), trans.getTranslationY());
if (transform.isOnlyTranslated)
@ -1937,7 +1935,7 @@ private:
static void clearOpenGLGlyphCacheCallback()
{
SavedState::GlyphCacheType::getInstance().reset();
RenderingHelpers::GlyphCache::getInstance().reset();
}
static std::unique_ptr<LowLevelGraphicsContext> createOpenGLContext (const Target& target)