SkGlyphCache - update core routines.

- Allows different methods for creating SkGlyphCaches
- Enables passing FontMetrics for cache creation.
- Removes VisitCache
- Removes VisitAll
- Introduces SkExclusiveStrikePtr which should
  replaces SkAutoGlyphCache with simpler mechanism.

BUG=skia:7515

Change-Id: Ibada35e3985335179d2cc8284a837fc525224c92
Reviewed-on: https://skia-review.googlesource.com/111063
Reviewed-by: Ben Wagner <bungeman@google.com>
Reviewed-by: Herb Derby <herb@google.com>
Commit-Queue: Herb Derby <herb@google.com>
This commit is contained in:
Herb Derby 2018-02-28 18:47:27 -05:00 committed by Skia Commit-Bot
parent 2a4f983c94
commit dfeb2aa13b
5 changed files with 182 additions and 156 deletions

View File

@ -365,6 +365,9 @@ private:
}; };
static SkFontStyle FromOldStyle(Style oldStyle); static SkFontStyle FromOldStyle(Style oldStyle);
static SkTypeface* GetDefaultTypeface(Style style = SkTypeface::kNormal); static SkTypeface* GetDefaultTypeface(Style style = SkTypeface::kNormal);
static SkTypeface* NormalizeTypeface(SkTypeface* typeface) {
return typeface != nullptr ? typeface : SkTypeface::GetDefaultTypeface();
}
friend class GrPathRendering; // GetDefaultTypeface friend class GrPathRendering; // GetDefaultTypeface
friend class SkGlyphCache; // GetDefaultTypeface friend class SkGlyphCache; // GetDefaultTypeface
friend class SkPaint; // GetDefaultTypeface friend class SkPaint; // GetDefaultTypeface

View File

@ -7,7 +7,6 @@
#include "SkGlyphCache.h" #include "SkGlyphCache.h"
#include "SkGlyphCache_Globals.h"
#include "SkGraphics.h" #include "SkGraphics.h"
#include "SkOnce.h" #include "SkOnce.h"
#include "SkPath.h" #include "SkPath.h"
@ -34,14 +33,12 @@ static SkGlyphCache_Globals& get_globals() {
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
SkGlyphCache::SkGlyphCache(const SkDescriptor* desc, std::unique_ptr<SkScalerContext> ctx) SkGlyphCache::SkGlyphCache(const SkDescriptor& desc, std::unique_ptr<SkScalerContext> ctx)
: fDesc(desc->copy()) : fDesc(desc.copy())
, fScalerContext(std::move(ctx)) { , fScalerContext(std::move(ctx))
SkASSERT(desc); {
SkASSERT(fScalerContext); SkASSERT(fScalerContext);
fPrev = fNext = nullptr;
fScalerContext->getFontMetrics(&fFontMetrics); fScalerContext->getFontMetrics(&fFontMetrics);
fMemoryUsed = sizeof(*this); fMemoryUsed = sizeof(*this);
@ -55,6 +52,10 @@ SkGlyphCache::~SkGlyphCache() {
}); });
} }
void SkGlyphCache::PurgeAll() {
get_globals().purgeAll();
}
SkGlyphCache::CharGlyphRec* SkGlyphCache::getCharGlyphRec(SkPackedUnicharID packedUnicharID) { SkGlyphCache::CharGlyphRec* SkGlyphCache::getCharGlyphRec(SkPackedUnicharID packedUnicharID) {
if (!fPackedUnicharIDToPackedGlyphID) { if (!fPackedUnicharIDToPackedGlyphID) {
fPackedUnicharIDToPackedGlyphID.reset(new CharGlyphRec[kHashCount]); fPackedUnicharIDToPackedGlyphID.reset(new CharGlyphRec[kHashCount]);
@ -102,6 +103,15 @@ int SkGlyphCache::countCachedGlyphs() const {
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
bool SkGlyphCache::isGlyphCached(SkGlyphID glyphID, SkFixed x, SkFixed y) const {
SkPackedGlyphID packedGlyphID{glyphID, x, y};
return fGlyphMap.find(packedGlyphID) != nullptr;
}
SkGlyph* SkGlyphCache::getRawGlyphByID(SkPackedGlyphID id) {
return lookupByPackedGlyphID(id, kNothing_MetricsType);
}
const SkGlyph& SkGlyphCache::getUnicharAdvance(SkUnichar charCode) { const SkGlyph& SkGlyphCache::getUnicharAdvance(SkUnichar charCode) {
VALIDATE(); VALIDATE();
return *this->lookupByChar(charCode, kJustAdvance_MetricsType); return *this->lookupByChar(charCode, kJustAdvance_MetricsType);
@ -170,7 +180,9 @@ SkGlyph* SkGlyphCache::allocateNewGlyph(SkPackedGlyphID packedGlyphID, MetricsTy
glyphPtr = fGlyphMap.set(glyph); glyphPtr = fGlyphMap.set(glyph);
} }
if (kJustAdvance_MetricsType == mtype) { if (kNothing_MetricsType == mtype) {
return glyphPtr;
} else if (kJustAdvance_MetricsType == mtype) {
fScalerContext->getAdvance(glyphPtr); fScalerContext->getAdvance(glyphPtr);
} else { } else {
SkASSERT(kFull_MetricsType == mtype); SkASSERT(kFull_MetricsType == mtype);
@ -469,92 +481,43 @@ void SkGlyphCache_Globals::purgeAll() {
this->internalPurge(fTotalMemoryUsed); this->internalPurge(fTotalMemoryUsed);
} }
/* This guy calls the visitor from within the mutext lock, so the visitor SkExclusiveStrikePtr SkGlyphCache::FindStrikeExclusive(const SkDescriptor& desc) {
cannot:
- take too much time
- try to acquire the mutext again
- call a fontscaler (which might call into the cache)
*/
SkGlyphCache* SkGlyphCache::VisitCache(SkTypeface* typeface,
const SkScalerContextEffects& effects,
const SkDescriptor* desc,
bool (*proc)(const SkGlyphCache*, void*),
void* context) {
if (!typeface) {
typeface = SkTypeface::GetDefaultTypeface();
}
SkASSERT(desc);
// Precondition: the typeface id must be the fFontID in the descriptor
SkDEBUGCODE(
uint32_t length = 0;
const SkScalerContextRec* rec = static_cast<const SkScalerContextRec*>(
desc->findEntry(kRec_SkDescriptorTag, &length));
SkASSERT(rec);
SkASSERT(length == sizeof(*rec));
SkASSERT(typeface->uniqueID() == rec->fFontID);
)
SkGlyphCache_Globals& globals = get_globals(); SkGlyphCache_Globals& globals = get_globals();
SkGlyphCache* cache; SkGlyphCache* cache;
SkAutoExclusive ac(globals.fLock);
{ for (cache = globals.internalGetHead(); cache != nullptr; cache = cache->fNext) {
SkAutoExclusive ac(globals.fLock); if (*cache->fDesc == desc) {
globals.internalDetachCache(cache);
globals.validate(); return SkExclusiveStrikePtr(cache);
for (cache = globals.internalGetHead(); cache != nullptr; cache = cache->fNext) {
if (*cache->fDesc == *desc) {
globals.internalDetachCache(cache);
if (!proc(cache, context)) {
globals.internalAttachCacheToHead(cache);
cache = nullptr;
}
return cache;
}
} }
} }
// Check if we can create a scaler-context before creating the glyphcache. return SkExclusiveStrikePtr(nullptr);
// If not, we may have exhausted OS/font resources, so try purging the }
// cache once and try again.
{
// pass true the first time, to notice if the scalercontext failed,
// so we can try the purge.
std::unique_ptr<SkScalerContext> ctx = typeface->createScalerContext(effects, desc, true);
if (!ctx) {
get_globals().purgeAll();
ctx = typeface->createScalerContext(effects, desc, false);
SkASSERT(ctx);
}
cache = new SkGlyphCache(desc, std::move(ctx));
}
AutoValidate av(cache); SkExclusiveStrikePtr SkGlyphCache::FindOrCreateStrikeExclusive(
const SkDescriptor& desc, const SkScalerContextEffects& effects, const SkTypeface& typeface) {
if (!proc(cache, context)) { // need to reattach auto creator = [&effects, &typeface](const SkDescriptor& descriptor, bool canFail) {
globals.attachCacheToHead(cache); return typeface.createScalerContext(effects, &descriptor, canFail);
cache = nullptr; };
} return FindOrCreateStrikeExclusive(desc, creator);
return cache;
} }
void SkGlyphCache::AttachCache(SkGlyphCache* cache) { void SkGlyphCache::AttachCache(SkGlyphCache* cache) {
SkASSERT(cache); SkGlyphCache_Globals::AttachCache(cache);
SkASSERT(cache->fNext == nullptr);
get_globals().attachCacheToHead(cache);
} }
static void dump_visitor(const SkGlyphCache& cache, void* context) { void SkGlyphCache::ForEachStrike(std::function<void(const SkGlyphCache&)> visitor) {
int* counter = (int*)context; SkGlyphCache_Globals& globals = get_globals();
int index = *counter; SkAutoExclusive ac(globals.fLock);
*counter += 1; SkGlyphCache* cache;
const SkScalerContextRec& rec = cache.getScalerContext()->getRec(); globals.validate();
SkDebugf("index %d\n", index); for (cache = globals.internalGetHead(); cache != nullptr; cache = cache->fNext) {
SkDebugf("%s", rec.dump().c_str()); visitor(*cache);
}
} }
void SkGlyphCache::Dump() { void SkGlyphCache::Dump() {
@ -565,30 +528,16 @@ void SkGlyphCache::Dump() {
SkGraphics::GetFontCacheCountUsed(), SkGraphics::GetFontCacheCountLimit()); SkGraphics::GetFontCacheCountUsed(), SkGraphics::GetFontCacheCountLimit());
int counter = 0; int counter = 0;
SkGlyphCache::VisitAll(dump_visitor, &counter);
}
static void sk_trace_dump_visitor(const SkGlyphCache& cache, void* context) { auto visitor = [&counter](const SkGlyphCache& cache) {
SkTraceMemoryDump* dump = static_cast<SkTraceMemoryDump*>(context); const SkScalerContextRec& rec = cache.getScalerContext()->getRec();
const SkTypeface* face = cache.getScalerContext()->getTypeface(); SkDebugf("index %d\n", counter);
const SkScalerContextRec& rec = cache.getScalerContext()->getRec(); SkDebugf("%s", rec.dump().c_str());
counter += 1;
};
SkString fontName; ForEachStrike(visitor);
face->getFamilyName(&fontName);
// Replace all special characters with '_'.
for (size_t index = 0; index < fontName.size(); ++index) {
if (!std::isalnum(fontName[index])) {
fontName[index] = '_';
}
}
SkString dumpName = SkStringPrintf("%s/%s_%d/%p",
gGlyphCacheDumpName, fontName.c_str(), rec.fFontID, &cache);
dump->dumpNumericValue(dumpName.c_str(), "size", "bytes", cache.getMemoryUsed());
dump->dumpNumericValue(dumpName.c_str(), "glyph_count", "objects", cache.countCachedGlyphs());
dump->setMemoryBacking(dumpName.c_str(), "malloc", nullptr);
} }
void SkGlyphCache::DumpMemoryStatistics(SkTraceMemoryDump* dump) { void SkGlyphCache::DumpMemoryStatistics(SkTraceMemoryDump* dump) {
@ -605,23 +554,53 @@ void SkGlyphCache::DumpMemoryStatistics(SkTraceMemoryDump* dump) {
return; return;
} }
SkGlyphCache::VisitAll(sk_trace_dump_visitor, dump); auto visitor = [&dump](const SkGlyphCache& cache) {
} const SkTypeface* face = cache.getScalerContext()->getTypeface();
const SkScalerContextRec& rec = cache.getScalerContext()->getRec();
void SkGlyphCache::VisitAll(Visitor visitor, void* context) { SkString fontName;
SkGlyphCache_Globals& globals = get_globals(); face->getFamilyName(&fontName);
SkAutoExclusive ac(globals.fLock); // Replace all special characters with '_'.
SkGlyphCache* cache; for (size_t index = 0; index < fontName.size(); ++index) {
if (!std::isalnum(fontName[index])) {
fontName[index] = '_';
}
}
globals.validate(); SkString dumpName = SkStringPrintf(
"%s/%s_%d/%p", gGlyphCacheDumpName, fontName.c_str(), rec.fFontID, &cache);
for (cache = globals.internalGetHead(); cache != nullptr; cache = cache->fNext) { dump->dumpNumericValue(dumpName.c_str(),
visitor(*cache, context); "size", "bytes", cache.getMemoryUsed());
} dump->dumpNumericValue(dumpName.c_str(),
"glyph_count", "objects", cache.countCachedGlyphs());
dump->setMemoryBacking(dumpName.c_str(), "malloc", nullptr);
};
ForEachStrike(visitor);
} }
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
SkGlyphCache_Globals::~SkGlyphCache_Globals() {
SkGlyphCache* cache = fHead;
while (cache) {
SkGlyphCache* next = cache->fNext;
delete cache;
cache = next;
}
}
void SkGlyphCache_Globals::AttachCache(SkGlyphCache* cache) {
if (cache == nullptr) {
return;
}
SkASSERT(cache->fNext == nullptr);
get_globals().attachCacheToHead(cache);
}
void SkGlyphCache_Globals::attachCacheToHead(SkGlyphCache* cache) { void SkGlyphCache_Globals::attachCacheToHead(SkGlyphCache* cache) {
SkAutoExclusive ac(fLock); SkAutoExclusive ac(fLock);
@ -806,6 +785,15 @@ void SkGraphics::PurgeFontCache() {
size_t SkGraphics::GetTLSFontCacheLimit() { return 0; } size_t SkGraphics::GetTLSFontCacheLimit() { return 0; }
void SkGraphics::SetTLSFontCacheLimit(size_t bytes) { } void SkGraphics::SetTLSFontCacheLimit(size_t bytes) { }
SkGlyphCache* SkGlyphCache::DetachCache(
SkTypeface* typeface, const SkScalerContextEffects& effects, const SkDescriptor* desc)
{
auto cache = FindOrCreateStrikeExclusive(
*desc, effects, *SkTypeface::NormalizeTypeface(typeface));
return cache.release();
}
SkGlyphCache* SkGlyphCache::DetachCacheUsingPaint(const SkPaint& paint, SkGlyphCache* SkGlyphCache::DetachCacheUsingPaint(const SkPaint& paint,
const SkSurfaceProps* surfaceProps, const SkSurfaceProps* surfaceProps,
SkScalerContextFlags scalerContextFlags, SkScalerContextFlags scalerContextFlags,

View File

@ -8,19 +8,21 @@
#define SkGlyphCache_DEFINED #define SkGlyphCache_DEFINED
#include "SkArenaAlloc.h" #include "SkArenaAlloc.h"
#include "SkBitmap.h"
#include "SkDescriptor.h" #include "SkDescriptor.h"
#include "SkGlyph.h" #include "SkGlyph.h"
#include "SkGlyphCache_Globals.h"
#include "SkPaint.h" #include "SkPaint.h"
#include "SkTHash.h" #include "SkTHash.h"
#include "SkScalerContext.h" #include "SkScalerContext.h"
#include "SkTemplates.h" #include "SkTemplates.h"
#include "SkTDArray.h"
#include <memory> #include <memory>
class SkTraceMemoryDump; class SkTraceMemoryDump;
class SkGlyphCache_Globals; class SkGlyphCache;
using SkExclusiveStrikePtr = std::unique_ptr<
SkGlyphCache,
SkFunctionWrapper<void, SkGlyphCache, SkGlyphCache_Globals::AttachCache>>;
/** \class SkGlyphCache /** \class SkGlyphCache
@ -30,10 +32,19 @@ class SkGlyphCache_Globals;
it and then adding it to the strike. it and then adding it to the strike.
The strikes are held in a global list, available to all threads. To interact with one, call The strikes are held in a global list, available to all threads. To interact with one, call
either VisitCache() or DetachCache(). either Find*() or (Deprecated)DetachCache().
The Find*Exclusive() method returns SkExclusiveStrikePtr, which releases exclusive ownership
when they go out of scope.
*/ */
class SkGlyphCache { class SkGlyphCache {
public: public:
/** Return true if glyph is cached. */
bool isGlyphCached(SkGlyphID glyphID, SkFixed x, SkFixed y) const;
/** Return a glyph that has no information if it is not already filled out. */
SkGlyph* getRawGlyphByID(SkPackedGlyphID);
/** Returns a glyph with valid fAdvance and fDevKern fields. The remaining fields may be /** Returns a glyph with valid fAdvance and fDevKern fields. The remaining fields may be
valid, but that is not guaranteed. If you require those, call getUnicharMetrics or valid, but that is not guaranteed. If you require those, call getUnicharMetrics or
getGlyphIDMetrics instead. getGlyphIDMetrics instead.
@ -112,19 +123,49 @@ public:
SkScalerContext* getScalerContext() const { return fScalerContext.get(); } SkScalerContext* getScalerContext() const { return fScalerContext.get(); }
/** Find a matching cache entry, and call proc() with it. If none is found create a new one.
If the proc() returns true, detach the cache and return it, otherwise leave it and return
nullptr.
*/
static SkGlyphCache* VisitCache(SkTypeface*, const SkScalerContextEffects&, const SkDescriptor*,
bool (*proc)(const SkGlyphCache*, void*),
void* context);
/** Given a strike that was returned by either VisitCache() or DetachCache() add it back into /** Given a strike that was returned by DetachCache() add it back into
the global cache list (after which the caller should not reference it anymore. the global cache list (after which the caller should not reference it anymore.
DEPRECATED - Use Find* and rely on RAII.
*/ */
static void AttachCache(SkGlyphCache*); static void AttachCache(SkGlyphCache*);
using AttachCacheFunctor = SkFunctionWrapper<void, SkGlyphCache, AttachCache>;
static SkExclusiveStrikePtr FindStrikeExclusive(const SkDescriptor& desc);
template <typename ScalerContextCreator>
static SkExclusiveStrikePtr FindOrCreateStrikeExclusive(
const SkDescriptor& desc, ScalerContextCreator&& creator)
{
auto cache = FindStrikeExclusive(desc);
if (cache == nullptr) {
cache = CreateStrikeExclusive(desc, creator);
}
return cache;
}
static SkExclusiveStrikePtr FindOrCreateStrikeExclusive(
const SkDescriptor& desc,
const SkScalerContextEffects& effects,
const SkTypeface& typeface);
template <typename ScalerContextCreator>
static SkExclusiveStrikePtr CreateStrikeExclusive(
const SkDescriptor& desc, ScalerContextCreator creator)
{
// Check if we can create a scaler-context before creating the glyphcache.
// If not, we may have exhausted OS/font resources, so try purging the
// cache once and try again
// pass true the first time, to notice if the scalercontext failed,
// so we can try the purge.
auto context = creator(desc, true/* can fail */);
if (!context) {
PurgeAll();
context = creator(desc, false/* must succeed */);
SkASSERT(context);
}
return SkExclusiveStrikePtr(new SkGlyphCache(desc, std::move(context)));
}
/** Detach a strike from the global cache matching the specified descriptor. Once detached, /** Detach a strike from the global cache matching the specified descriptor. Once detached,
it can be queried/modified by the current thread, and when finished, be reattached to the it can be queried/modified by the current thread, and when finished, be reattached to the
@ -132,11 +173,10 @@ public:
descriptor, a different strike will be generated. This is fine. It does mean we can have descriptor, a different strike will be generated. This is fine. It does mean we can have
more than 1 strike for the same descriptor, but that will eventually get purged, and the more than 1 strike for the same descriptor, but that will eventually get purged, and the
win is that different thread will never block each other while a strike is being used. win is that different thread will never block each other while a strike is being used.
DEPRECATED
*/ */
static SkGlyphCache* DetachCache(SkTypeface* typeface, const SkScalerContextEffects& effects, static SkGlyphCache* DetachCache(
const SkDescriptor* desc) { SkTypeface* typeface, const SkScalerContextEffects& effects, const SkDescriptor* desc);
return VisitCache(typeface, effects, desc, DetachProc, nullptr);
}
static SkGlyphCache* DetachCacheUsingPaint(const SkPaint& paint, static SkGlyphCache* DetachCacheUsingPaint(const SkPaint& paint,
const SkSurfaceProps* surfaceProps, const SkSurfaceProps* surfaceProps,
@ -150,8 +190,7 @@ public:
*/ */
static void DumpMemoryStatistics(SkTraceMemoryDump* dump); static void DumpMemoryStatistics(SkTraceMemoryDump* dump);
typedef void (*Visitor)(const SkGlyphCache&, void* context); static void ForEachStrike(std::function<void(const SkGlyphCache&)> visitor);
static void VisitAll(Visitor, void* context);
#ifdef SK_DEBUG #ifdef SK_DEBUG
void validate() const; void validate() const;
@ -182,14 +221,15 @@ private:
friend class SkGlyphCache_Globals; friend class SkGlyphCache_Globals;
enum MetricsType { enum MetricsType {
kNothing_MetricsType,
kJustAdvance_MetricsType, kJustAdvance_MetricsType,
kFull_MetricsType kFull_MetricsType
}; };
enum { enum {
kHashBits = 8, kHashBits = 8,
kHashCount = 1 << kHashBits, kHashCount = 1 << kHashBits,
kHashMask = kHashCount - 1 kHashMask = kHashCount - 1
}; };
struct CharGlyphRec { struct CharGlyphRec {
@ -197,9 +237,12 @@ private:
SkPackedGlyphID fPackedGlyphID; SkPackedGlyphID fPackedGlyphID;
}; };
SkGlyphCache(const SkDescriptor*, std::unique_ptr<SkScalerContext>); SkGlyphCache(const SkDescriptor& desc, std::unique_ptr<SkScalerContext> scaler);
~SkGlyphCache(); ~SkGlyphCache();
// Purge all the things.
static void PurgeAll();
// Return the SkGlyph* associated with MakeID. The id parameter is the // Return the SkGlyph* associated with MakeID. The id parameter is the
// combined glyph/x/y id generated by MakeID. If it is just a glyph id // combined glyph/x/y id generated by MakeID. If it is just a glyph id
// then x and y are assumed to be zero. // then x and y are assumed to be zero.
@ -212,8 +255,6 @@ private:
// of work using type. // of work using type.
SkGlyph* allocateNewGlyph(SkPackedGlyphID packedGlyphID, MetricsType type); SkGlyph* allocateNewGlyph(SkPackedGlyphID packedGlyphID, MetricsType type);
static bool DetachProc(const SkGlyphCache*, void*) { return true; }
// The id arg is a combined id generated by MakeID. // The id arg is a combined id generated by MakeID.
CharGlyphRec* getCharGlyphRec(SkPackedUnicharID id); CharGlyphRec* getCharGlyphRec(SkPackedUnicharID id);
@ -231,8 +272,8 @@ private:
static const SkGlyph::Intercept* MatchBounds(const SkGlyph* glyph, static const SkGlyph::Intercept* MatchBounds(const SkGlyph* glyph,
const SkScalar bounds[2]); const SkScalar bounds[2]);
SkGlyphCache* fNext; SkGlyphCache* fNext{nullptr};
SkGlyphCache* fPrev; SkGlyphCache* fPrev{nullptr};
const std::unique_ptr<SkDescriptor> fDesc; const std::unique_ptr<SkDescriptor> fDesc;
const std::unique_ptr<SkScalerContext> fScalerContext; const std::unique_ptr<SkScalerContext> fScalerContext;
SkPaint::FontMetrics fFontMetrics; SkPaint::FontMetrics fFontMetrics;
@ -253,7 +294,7 @@ private:
size_t fMemoryUsed; size_t fMemoryUsed;
}; };
class SkAutoGlyphCache : public std::unique_ptr<SkGlyphCache, SkGlyphCache::AttachCacheFunctor> { class SkAutoGlyphCache : public SkExclusiveStrikePtr {
public: public:
/** deprecated: use get() */ /** deprecated: use get() */
SkGlyphCache* getCache() const { return this->get(); } SkGlyphCache* getCache() const { return this->get(); }
@ -280,7 +321,7 @@ public:
SkGlyphCache::DetachCacheUsingPaint(paint, surfaceProps, scalerContextFlags, matrix)) SkGlyphCache::DetachCacheUsingPaint(paint, surfaceProps, scalerContextFlags, matrix))
{} {}
private: private:
using INHERITED = std::unique_ptr<SkGlyphCache, SkGlyphCache::AttachCacheFunctor>; using INHERITED = SkExclusiveStrikePtr;
}; };
class SkAutoGlyphCacheNoGamma : public SkAutoGlyphCache { class SkAutoGlyphCacheNoGamma : public SkAutoGlyphCache {

View File

@ -8,10 +8,10 @@
#ifndef SkGlyphCache_Globals_DEFINED #ifndef SkGlyphCache_Globals_DEFINED
#define SkGlyphCache_Globals_DEFINED #define SkGlyphCache_Globals_DEFINED
#include "SkGlyphCache.h"
#include "SkMutex.h" #include "SkMutex.h"
#include "SkSpinlock.h" #include "SkSpinlock.h"
#include "SkTLS.h"
class SkGlyphCache;
#ifndef SK_DEFAULT_FONT_CACHE_COUNT_LIMIT #ifndef SK_DEFAULT_FONT_CACHE_COUNT_LIMIT
#define SK_DEFAULT_FONT_CACHE_COUNT_LIMIT 2048 #define SK_DEFAULT_FONT_CACHE_COUNT_LIMIT 2048
@ -38,14 +38,9 @@ public:
fPointSizeLimit = SK_DEFAULT_FONT_CACHE_POINT_SIZE_LIMIT; fPointSizeLimit = SK_DEFAULT_FONT_CACHE_POINT_SIZE_LIMIT;
} }
~SkGlyphCache_Globals() { ~SkGlyphCache_Globals();
SkGlyphCache* cache = fHead;
while (cache) { static void AttachCache(SkGlyphCache* cache);
SkGlyphCache* next = cache->fNext;
delete cache;
cache = next;
}
}
mutable SkSpinlock fLock; mutable SkSpinlock fLock;

View File

@ -905,11 +905,6 @@ size_t SkPaint::breakText(const void* textD, size_t length, SkScalar maxWidth,
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
static bool FontMetricsCacheProc(const SkGlyphCache* cache, void* context) {
*(SkPaint::FontMetrics*)context = cache->getFontMetrics();
return false; // don't detach the cache
}
SkScalar SkPaint::getFontMetrics(FontMetrics* metrics, SkScalar zoom) const { SkScalar SkPaint::getFontMetrics(FontMetrics* metrics, SkScalar zoom) const {
SkCanonicalizePaint canon(*this); SkCanonicalizePaint canon(*this);
const SkPaint& paint = canon.getPaint(); const SkPaint& paint = canon.getPaint();
@ -932,7 +927,11 @@ SkScalar SkPaint::getFontMetrics(FontMetrics* metrics, SkScalar zoom) const {
auto desc = SkScalerContext::CreateDescriptorAndEffectsUsingPaint( auto desc = SkScalerContext::CreateDescriptorAndEffectsUsingPaint(
paint, nullptr, SkScalerContextFlags::kNone, zoomPtr, &ad, &effects); paint, nullptr, SkScalerContextFlags::kNone, zoomPtr, &ad, &effects);
SkGlyphCache::VisitCache(paint.getTypeface(), effects, desc, FontMetricsCacheProc, metrics); {
auto typeface = SkTypeface::NormalizeTypeface(paint.getTypeface());
auto cache = SkGlyphCache::FindOrCreateStrikeExclusive(*desc, effects, *typeface);
*metrics = cache->getFontMetrics();
}
if (scale) { if (scale) {
SkPaintPriv::ScaleFontMetrics(metrics, scale); SkPaintPriv::ScaleFontMetrics(metrics, scale);