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:
parent
2a4f983c94
commit
dfeb2aa13b
@ -365,6 +365,9 @@ private:
|
||||
};
|
||||
static SkFontStyle FromOldStyle(Style oldStyle);
|
||||
static SkTypeface* GetDefaultTypeface(Style style = SkTypeface::kNormal);
|
||||
static SkTypeface* NormalizeTypeface(SkTypeface* typeface) {
|
||||
return typeface != nullptr ? typeface : SkTypeface::GetDefaultTypeface();
|
||||
}
|
||||
friend class GrPathRendering; // GetDefaultTypeface
|
||||
friend class SkGlyphCache; // GetDefaultTypeface
|
||||
friend class SkPaint; // GetDefaultTypeface
|
||||
|
@ -7,7 +7,6 @@
|
||||
|
||||
|
||||
#include "SkGlyphCache.h"
|
||||
#include "SkGlyphCache_Globals.h"
|
||||
#include "SkGraphics.h"
|
||||
#include "SkOnce.h"
|
||||
#include "SkPath.h"
|
||||
@ -34,14 +33,12 @@ static SkGlyphCache_Globals& get_globals() {
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
SkGlyphCache::SkGlyphCache(const SkDescriptor* desc, std::unique_ptr<SkScalerContext> ctx)
|
||||
: fDesc(desc->copy())
|
||||
, fScalerContext(std::move(ctx)) {
|
||||
SkASSERT(desc);
|
||||
SkGlyphCache::SkGlyphCache(const SkDescriptor& desc, std::unique_ptr<SkScalerContext> ctx)
|
||||
: fDesc(desc.copy())
|
||||
, fScalerContext(std::move(ctx))
|
||||
{
|
||||
SkASSERT(fScalerContext);
|
||||
|
||||
fPrev = fNext = nullptr;
|
||||
|
||||
fScalerContext->getFontMetrics(&fFontMetrics);
|
||||
|
||||
fMemoryUsed = sizeof(*this);
|
||||
@ -55,6 +52,10 @@ SkGlyphCache::~SkGlyphCache() {
|
||||
});
|
||||
}
|
||||
|
||||
void SkGlyphCache::PurgeAll() {
|
||||
get_globals().purgeAll();
|
||||
}
|
||||
|
||||
SkGlyphCache::CharGlyphRec* SkGlyphCache::getCharGlyphRec(SkPackedUnicharID packedUnicharID) {
|
||||
if (!fPackedUnicharIDToPackedGlyphID) {
|
||||
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) {
|
||||
VALIDATE();
|
||||
return *this->lookupByChar(charCode, kJustAdvance_MetricsType);
|
||||
@ -170,7 +180,9 @@ SkGlyph* SkGlyphCache::allocateNewGlyph(SkPackedGlyphID packedGlyphID, MetricsTy
|
||||
glyphPtr = fGlyphMap.set(glyph);
|
||||
}
|
||||
|
||||
if (kJustAdvance_MetricsType == mtype) {
|
||||
if (kNothing_MetricsType == mtype) {
|
||||
return glyphPtr;
|
||||
} else if (kJustAdvance_MetricsType == mtype) {
|
||||
fScalerContext->getAdvance(glyphPtr);
|
||||
} else {
|
||||
SkASSERT(kFull_MetricsType == mtype);
|
||||
@ -469,92 +481,43 @@ void SkGlyphCache_Globals::purgeAll() {
|
||||
this->internalPurge(fTotalMemoryUsed);
|
||||
}
|
||||
|
||||
/* This guy calls the visitor from within the mutext lock, so the visitor
|
||||
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);
|
||||
)
|
||||
|
||||
SkExclusiveStrikePtr SkGlyphCache::FindStrikeExclusive(const SkDescriptor& desc) {
|
||||
SkGlyphCache_Globals& globals = get_globals();
|
||||
SkGlyphCache* cache;
|
||||
|
||||
{
|
||||
SkAutoExclusive ac(globals.fLock);
|
||||
|
||||
for (cache = globals.internalGetHead(); cache != nullptr; cache = cache->fNext) {
|
||||
if (*cache->fDesc == desc) {
|
||||
globals.internalDetachCache(cache);
|
||||
return SkExclusiveStrikePtr(cache);
|
||||
}
|
||||
}
|
||||
|
||||
return SkExclusiveStrikePtr(nullptr);
|
||||
}
|
||||
|
||||
SkExclusiveStrikePtr SkGlyphCache::FindOrCreateStrikeExclusive(
|
||||
const SkDescriptor& desc, const SkScalerContextEffects& effects, const SkTypeface& typeface) {
|
||||
auto creator = [&effects, &typeface](const SkDescriptor& descriptor, bool canFail) {
|
||||
return typeface.createScalerContext(effects, &descriptor, canFail);
|
||||
};
|
||||
return FindOrCreateStrikeExclusive(desc, creator);
|
||||
}
|
||||
|
||||
void SkGlyphCache::AttachCache(SkGlyphCache* cache) {
|
||||
SkGlyphCache_Globals::AttachCache(cache);
|
||||
}
|
||||
|
||||
void SkGlyphCache::ForEachStrike(std::function<void(const SkGlyphCache&)> visitor) {
|
||||
SkGlyphCache_Globals& globals = get_globals();
|
||||
SkAutoExclusive ac(globals.fLock);
|
||||
SkGlyphCache* cache;
|
||||
|
||||
globals.validate();
|
||||
|
||||
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;
|
||||
visitor(*cache);
|
||||
}
|
||||
return cache;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 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.
|
||||
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);
|
||||
|
||||
if (!proc(cache, context)) { // need to reattach
|
||||
globals.attachCacheToHead(cache);
|
||||
cache = nullptr;
|
||||
}
|
||||
return cache;
|
||||
}
|
||||
|
||||
void SkGlyphCache::AttachCache(SkGlyphCache* cache) {
|
||||
SkASSERT(cache);
|
||||
SkASSERT(cache->fNext == nullptr);
|
||||
|
||||
get_globals().attachCacheToHead(cache);
|
||||
}
|
||||
|
||||
static void dump_visitor(const SkGlyphCache& cache, void* context) {
|
||||
int* counter = (int*)context;
|
||||
int index = *counter;
|
||||
*counter += 1;
|
||||
|
||||
const SkScalerContextRec& rec = cache.getScalerContext()->getRec();
|
||||
|
||||
SkDebugf("index %d\n", index);
|
||||
SkDebugf("%s", rec.dump().c_str());
|
||||
}
|
||||
|
||||
void SkGlyphCache::Dump() {
|
||||
@ -565,30 +528,16 @@ void SkGlyphCache::Dump() {
|
||||
SkGraphics::GetFontCacheCountUsed(), SkGraphics::GetFontCacheCountLimit());
|
||||
|
||||
int counter = 0;
|
||||
SkGlyphCache::VisitAll(dump_visitor, &counter);
|
||||
}
|
||||
|
||||
static void sk_trace_dump_visitor(const SkGlyphCache& cache, void* context) {
|
||||
SkTraceMemoryDump* dump = static_cast<SkTraceMemoryDump*>(context);
|
||||
|
||||
const SkTypeface* face = cache.getScalerContext()->getTypeface();
|
||||
auto visitor = [&counter](const SkGlyphCache& cache) {
|
||||
const SkScalerContextRec& rec = cache.getScalerContext()->getRec();
|
||||
|
||||
SkString fontName;
|
||||
face->getFamilyName(&fontName);
|
||||
// Replace all special characters with '_'.
|
||||
for (size_t index = 0; index < fontName.size(); ++index) {
|
||||
if (!std::isalnum(fontName[index])) {
|
||||
fontName[index] = '_';
|
||||
}
|
||||
}
|
||||
SkDebugf("index %d\n", counter);
|
||||
SkDebugf("%s", rec.dump().c_str());
|
||||
counter += 1;
|
||||
};
|
||||
|
||||
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);
|
||||
ForEachStrike(visitor);
|
||||
}
|
||||
|
||||
void SkGlyphCache::DumpMemoryStatistics(SkTraceMemoryDump* dump) {
|
||||
@ -605,23 +554,53 @@ void SkGlyphCache::DumpMemoryStatistics(SkTraceMemoryDump* dump) {
|
||||
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();
|
||||
|
||||
SkString fontName;
|
||||
face->getFamilyName(&fontName);
|
||||
// Replace all special characters with '_'.
|
||||
for (size_t index = 0; index < fontName.size(); ++index) {
|
||||
if (!std::isalnum(fontName[index])) {
|
||||
fontName[index] = '_';
|
||||
}
|
||||
}
|
||||
|
||||
void SkGlyphCache::VisitAll(Visitor visitor, void* context) {
|
||||
SkGlyphCache_Globals& globals = get_globals();
|
||||
SkAutoExclusive ac(globals.fLock);
|
||||
SkGlyphCache* cache;
|
||||
SkString dumpName = SkStringPrintf(
|
||||
"%s/%s_%d/%p", gGlyphCacheDumpName, fontName.c_str(), rec.fFontID, &cache);
|
||||
|
||||
globals.validate();
|
||||
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);
|
||||
};
|
||||
|
||||
for (cache = globals.internalGetHead(); cache != nullptr; cache = cache->fNext) {
|
||||
visitor(*cache, context);
|
||||
}
|
||||
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) {
|
||||
SkAutoExclusive ac(fLock);
|
||||
|
||||
@ -806,6 +785,15 @@ void SkGraphics::PurgeFontCache() {
|
||||
size_t SkGraphics::GetTLSFontCacheLimit() { return 0; }
|
||||
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,
|
||||
const SkSurfaceProps* surfaceProps,
|
||||
SkScalerContextFlags scalerContextFlags,
|
||||
|
@ -8,19 +8,21 @@
|
||||
#define SkGlyphCache_DEFINED
|
||||
|
||||
#include "SkArenaAlloc.h"
|
||||
#include "SkBitmap.h"
|
||||
#include "SkDescriptor.h"
|
||||
#include "SkGlyph.h"
|
||||
#include "SkGlyphCache_Globals.h"
|
||||
#include "SkPaint.h"
|
||||
#include "SkTHash.h"
|
||||
#include "SkScalerContext.h"
|
||||
#include "SkTemplates.h"
|
||||
#include "SkTDArray.h"
|
||||
#include <memory>
|
||||
|
||||
class SkTraceMemoryDump;
|
||||
|
||||
class SkGlyphCache_Globals;
|
||||
class SkGlyphCache;
|
||||
using SkExclusiveStrikePtr = std::unique_ptr<
|
||||
SkGlyphCache,
|
||||
SkFunctionWrapper<void, SkGlyphCache, SkGlyphCache_Globals::AttachCache>>;
|
||||
|
||||
/** \class SkGlyphCache
|
||||
|
||||
@ -30,10 +32,19 @@ class SkGlyphCache_Globals;
|
||||
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
|
||||
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 {
|
||||
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
|
||||
valid, but that is not guaranteed. If you require those, call getUnicharMetrics or
|
||||
getGlyphIDMetrics instead.
|
||||
@ -112,19 +123,49 @@ public:
|
||||
|
||||
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.
|
||||
DEPRECATED - Use Find* and rely on RAII.
|
||||
*/
|
||||
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,
|
||||
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
|
||||
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.
|
||||
DEPRECATED
|
||||
*/
|
||||
static SkGlyphCache* DetachCache(SkTypeface* typeface, const SkScalerContextEffects& effects,
|
||||
const SkDescriptor* desc) {
|
||||
return VisitCache(typeface, effects, desc, DetachProc, nullptr);
|
||||
}
|
||||
static SkGlyphCache* DetachCache(
|
||||
SkTypeface* typeface, const SkScalerContextEffects& effects, const SkDescriptor* desc);
|
||||
|
||||
static SkGlyphCache* DetachCacheUsingPaint(const SkPaint& paint,
|
||||
const SkSurfaceProps* surfaceProps,
|
||||
@ -150,8 +190,7 @@ public:
|
||||
*/
|
||||
static void DumpMemoryStatistics(SkTraceMemoryDump* dump);
|
||||
|
||||
typedef void (*Visitor)(const SkGlyphCache&, void* context);
|
||||
static void VisitAll(Visitor, void* context);
|
||||
static void ForEachStrike(std::function<void(const SkGlyphCache&)> visitor);
|
||||
|
||||
#ifdef SK_DEBUG
|
||||
void validate() const;
|
||||
@ -182,6 +221,7 @@ private:
|
||||
friend class SkGlyphCache_Globals;
|
||||
|
||||
enum MetricsType {
|
||||
kNothing_MetricsType,
|
||||
kJustAdvance_MetricsType,
|
||||
kFull_MetricsType
|
||||
};
|
||||
@ -197,9 +237,12 @@ private:
|
||||
SkPackedGlyphID fPackedGlyphID;
|
||||
};
|
||||
|
||||
SkGlyphCache(const SkDescriptor*, std::unique_ptr<SkScalerContext>);
|
||||
SkGlyphCache(const SkDescriptor& desc, std::unique_ptr<SkScalerContext> scaler);
|
||||
~SkGlyphCache();
|
||||
|
||||
// Purge all the things.
|
||||
static void PurgeAll();
|
||||
|
||||
// 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
|
||||
// then x and y are assumed to be zero.
|
||||
@ -212,8 +255,6 @@ private:
|
||||
// of work using 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.
|
||||
CharGlyphRec* getCharGlyphRec(SkPackedUnicharID id);
|
||||
|
||||
@ -231,8 +272,8 @@ private:
|
||||
static const SkGlyph::Intercept* MatchBounds(const SkGlyph* glyph,
|
||||
const SkScalar bounds[2]);
|
||||
|
||||
SkGlyphCache* fNext;
|
||||
SkGlyphCache* fPrev;
|
||||
SkGlyphCache* fNext{nullptr};
|
||||
SkGlyphCache* fPrev{nullptr};
|
||||
const std::unique_ptr<SkDescriptor> fDesc;
|
||||
const std::unique_ptr<SkScalerContext> fScalerContext;
|
||||
SkPaint::FontMetrics fFontMetrics;
|
||||
@ -253,7 +294,7 @@ private:
|
||||
size_t fMemoryUsed;
|
||||
};
|
||||
|
||||
class SkAutoGlyphCache : public std::unique_ptr<SkGlyphCache, SkGlyphCache::AttachCacheFunctor> {
|
||||
class SkAutoGlyphCache : public SkExclusiveStrikePtr {
|
||||
public:
|
||||
/** deprecated: use get() */
|
||||
SkGlyphCache* getCache() const { return this->get(); }
|
||||
@ -280,7 +321,7 @@ public:
|
||||
SkGlyphCache::DetachCacheUsingPaint(paint, surfaceProps, scalerContextFlags, matrix))
|
||||
{}
|
||||
private:
|
||||
using INHERITED = std::unique_ptr<SkGlyphCache, SkGlyphCache::AttachCacheFunctor>;
|
||||
using INHERITED = SkExclusiveStrikePtr;
|
||||
};
|
||||
|
||||
class SkAutoGlyphCacheNoGamma : public SkAutoGlyphCache {
|
||||
|
@ -8,10 +8,10 @@
|
||||
#ifndef SkGlyphCache_Globals_DEFINED
|
||||
#define SkGlyphCache_Globals_DEFINED
|
||||
|
||||
#include "SkGlyphCache.h"
|
||||
#include "SkMutex.h"
|
||||
#include "SkSpinlock.h"
|
||||
#include "SkTLS.h"
|
||||
|
||||
class SkGlyphCache;
|
||||
|
||||
#ifndef SK_DEFAULT_FONT_CACHE_COUNT_LIMIT
|
||||
#define SK_DEFAULT_FONT_CACHE_COUNT_LIMIT 2048
|
||||
@ -38,14 +38,9 @@ public:
|
||||
fPointSizeLimit = SK_DEFAULT_FONT_CACHE_POINT_SIZE_LIMIT;
|
||||
}
|
||||
|
||||
~SkGlyphCache_Globals() {
|
||||
SkGlyphCache* cache = fHead;
|
||||
while (cache) {
|
||||
SkGlyphCache* next = cache->fNext;
|
||||
delete cache;
|
||||
cache = next;
|
||||
}
|
||||
}
|
||||
~SkGlyphCache_Globals();
|
||||
|
||||
static void AttachCache(SkGlyphCache* cache);
|
||||
|
||||
mutable SkSpinlock fLock;
|
||||
|
||||
|
@ -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 {
|
||||
SkCanonicalizePaint canon(*this);
|
||||
const SkPaint& paint = canon.getPaint();
|
||||
@ -932,7 +927,11 @@ SkScalar SkPaint::getFontMetrics(FontMetrics* metrics, SkScalar zoom) const {
|
||||
auto desc = SkScalerContext::CreateDescriptorAndEffectsUsingPaint(
|
||||
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) {
|
||||
SkPaintPriv::ScaleFontMetrics(metrics, scale);
|
||||
|
Loading…
Reference in New Issue
Block a user