Remove requestedStyle from SkTypefaceCache.

The typeface cache contains typefaces which can be compared against to
determine if an already known typeface will work instead of creating a
new typeface id. This is primarily for sharing scaler contexts. How that
typeface was requested is not relevant to this comparison, so don't cache
it. Request caching must be handled separately.

GOLD_TRYBOT_URL= https://gold.skia.org/search2?unt=true&query=source_type%3Dgm&master=false&issue=1879423002

Review URL: https://codereview.chromium.org/1879423002
This commit is contained in:
bungeman 2016-04-14 08:04:45 -07:00 committed by Commit bot
parent b2a4dc6a35
commit 82a455f0e9
8 changed files with 106 additions and 67 deletions

View File

@ -15,46 +15,29 @@
SkTypefaceCache::SkTypefaceCache() {}
SkTypefaceCache::~SkTypefaceCache() {
const Rec* curr = fArray.begin();
const Rec* stop = fArray.end();
while (curr < stop) {
curr->fFace->unref();
curr += 1;
}
}
void SkTypefaceCache::add(SkTypeface* face, const SkFontStyle& requestedStyle) {
if (fArray.count() >= TYPEFACE_CACHE_LIMIT) {
void SkTypefaceCache::add(SkTypeface* face) {
if (fTypefaces.count() >= TYPEFACE_CACHE_LIMIT) {
this->purge(TYPEFACE_CACHE_LIMIT >> 2);
}
Rec* rec = fArray.append();
rec->fFace = SkRef(face);
rec->fRequestedStyle = requestedStyle;
fTypefaces.emplace_back(SkRef(face));
}
SkTypeface* SkTypefaceCache::findByProcAndRef(FindProc proc, void* ctx) const {
const Rec* curr = fArray.begin();
const Rec* stop = fArray.end();
while (curr < stop) {
SkTypeface* currFace = curr->fFace;
if (proc(currFace, curr->fRequestedStyle, ctx)) {
return SkRef(currFace);
for (const sk_sp<SkTypeface>& typeface : fTypefaces) {
if (proc(typeface.get(), ctx)) {
return SkRef(typeface.get());
}
curr += 1;
}
return nullptr;
}
void SkTypefaceCache::purge(int numToPurge) {
int count = fArray.count();
int count = fTypefaces.count();
int i = 0;
while (i < count) {
SkTypeface* face = fArray[i].fFace;
if (face->unique()) {
face->unref();
fArray.remove(i);
if (fTypefaces[i]->unique()) {
fTypefaces.removeShuffle(i);
--count;
if (--numToPurge == 0) {
return;
@ -66,7 +49,7 @@ void SkTypefaceCache::purge(int numToPurge) {
}
void SkTypefaceCache::purgeAll() {
this->purge(fArray.count());
this->purge(fTypefaces.count());
}
///////////////////////////////////////////////////////////////////////////////
@ -83,15 +66,14 @@ SkFontID SkTypefaceCache::NewFontID() {
SK_DECLARE_STATIC_MUTEX(gMutex);
void SkTypefaceCache::Add(SkTypeface* face, const SkFontStyle& requestedStyle) {
void SkTypefaceCache::Add(SkTypeface* face) {
SkAutoMutexAcquire ama(gMutex);
Get().add(face, requestedStyle);
Get().add(face);
}
SkTypeface* SkTypefaceCache::FindByProcAndRef(FindProc proc, void* ctx) {
SkAutoMutexAcquire ama(gMutex);
SkTypeface* typeface = Get().findByProcAndRef(proc, ctx);
return typeface;
return Get().findByProcAndRef(proc, ctx);
}
void SkTypefaceCache::PurgeAll() {
@ -102,16 +84,19 @@ void SkTypefaceCache::PurgeAll() {
///////////////////////////////////////////////////////////////////////////////
#ifdef SK_DEBUG
static bool DumpProc(SkTypeface* face, const SkFontStyle& s, void* ctx) {
SkDebugf("SkTypefaceCache: face %p fontID %d weight %d width %d style %d refcnt %d\n",
face, face->uniqueID(), s.weight(), s.width(), s.slant(), face->getRefCnt());
static bool DumpProc(SkTypeface* face, void* ctx) {
SkString n;
face->getFamilyName(&n);
SkFontStyle s = face->fontStyle();
SkFontID id = face->uniqueID();
SkDebugf("SkTypefaceCache: face %p fontID %d weight %d width %d style %d refcnt %d name %s\n",
face, id, s.weight(), s.width(), s.slant(), face->getRefCnt(), n.c_str());
return false;
}
#endif
void SkTypefaceCache::Dump() {
#ifdef SK_DEBUG
SkAutoMutexAcquire ama(gMutex);
(void)Get().findByProcAndRef(DumpProc, nullptr);
#endif
}

View File

@ -10,27 +10,20 @@
#ifndef SkTypefaceCache_DEFINED
#define SkTypefaceCache_DEFINED
#include "SkRefCnt.h"
#include "SkTypeface.h"
#include "SkTDArray.h"
/* TODO
* Provide std way to cache name+requestedStyle aliases to the same typeface.
*
* The current mechanism ends up create a diff typeface for each one, even if
* they map to the same internal obj (e.g. CTFontRef on the mac)
*/
#include "SkTArray.h"
class SkTypefaceCache {
public:
SkTypefaceCache();
~SkTypefaceCache();
/**
* Callback for FindByProc. Returns true if the given typeface is a match
* for the given context. The passed typeface is owned by the cache and is
* not additionally ref()ed. The typeface may be in the disposed state.
*/
typedef bool(*FindProc)(SkTypeface*, const SkFontStyle&, void* context);
typedef bool(*FindProc)(SkTypeface*, void* context);
/**
* Add a typeface to the cache. This ref()s the typeface, so that the
@ -38,7 +31,7 @@ public:
* whose refcnt is 1 (meaning only the cache is an owner) will be
* unref()ed.
*/
void add(SkTypeface*, const SkFontStyle& requested);
void add(SkTypeface*);
/**
* Iterate through the cache, calling proc(typeface, ctx) with each
@ -63,7 +56,7 @@ public:
// These are static wrappers around a global instance of a cache.
static void Add(SkTypeface*, const SkFontStyle& requested);
static void Add(SkTypeface*);
static SkTypeface* FindByProcAndRef(FindProc proc, void* ctx);
static void PurgeAll();
@ -77,11 +70,7 @@ private:
void purge(int count);
struct Rec {
SkTypeface* fFace;
SkFontStyle fRequestedStyle;
};
SkTDArray<Rec> fArray;
SkTArray<sk_sp<SkTypeface>> fTypefaces;
};
#endif

View File

@ -58,7 +58,7 @@ SkFontConfigInterface* SkFontHost_fontconfig_ref_global() {
///////////////////////////////////////////////////////////////////////////////
static bool find_by_FontIdentity(SkTypeface* cachedTypeface, const SkFontStyle&, void* ctx) {
static bool find_by_FontIdentity(SkTypeface* cachedTypeface, void* ctx) {
typedef SkFontConfigInterface::FontIdentity FontIdentity;
FontConfigTypeface* cachedFCTypeface = static_cast<FontConfigTypeface*>(cachedTypeface);
FontIdentity* identity = static_cast<FontIdentity*>(ctx);
@ -196,7 +196,7 @@ SkTypeface* FontConfigTypeface::LegacyCreateTypeface(const char requestedFamilyN
if (!face) {
face = FontConfigTypeface::Create(outStyle, identity, outFamilyName);
// Add this FontIdentity to the FontIdentity cache.
SkTypefaceCache::Add(face, outStyle);
SkTypefaceCache::Add(face);
}
// Add this request to the request cache.
SkFontHostRequestCache::Add(face, request.release());

View File

@ -486,7 +486,7 @@ static SkTypeface* NewFromFontRef(CTFontRef fontRef, CFTypeRef resourceRef, bool
return new SkTypeface_Mac(fontRef, resourceRef, style, isFixedPitch, isLocalStream);
}
static bool find_by_CTFontRef(SkTypeface* cached, const SkFontStyle&, void* context) {
static bool find_by_CTFontRef(SkTypeface* cached, void* context) {
CTFontRef self = (CTFontRef)context;
CTFontRef other = ((SkTypeface_Mac*)cached)->fFontRef;
@ -546,7 +546,7 @@ static SkTypeface* NewFromName(const char familyName[], const SkFontStyle& theSt
return face;
}
face = NewFromFontRef(ctFont.release(), nullptr, false);
SkTypefaceCache::Add(face, face->fontStyle());
SkTypefaceCache::Add(face);
return face;
}
@ -583,7 +583,7 @@ SkTypeface* SkCreateTypefaceFromCTFont(CTFontRef fontRef, CFTypeRef resourceRef)
CFRetain(resourceRef);
}
face = NewFromFontRef(fontRef, resourceRef, false);
SkTypefaceCache::Add(face, face->fontStyle());
SkTypefaceCache::Add(face);
return face;
}
@ -2166,7 +2166,7 @@ static SkTypeface* createFromDesc(CTFontDescriptorRef desc) {
}
face = NewFromFontRef(ctFont.release(), nullptr, false);
SkTypefaceCache::Add(face, face->fontStyle());
SkTypefaceCache::Add(face);
return face;
}

View File

@ -308,13 +308,11 @@ static const LOGFONT& get_default_font() {
return gDefaultFont;
}
static bool FindByLogFont(SkTypeface* face, const SkFontStyle& requestedStyle, void* ctx) {
static bool FindByLogFont(SkTypeface* face, void* ctx) {
LogFontTypeface* lface = static_cast<LogFontTypeface*>(face);
const LOGFONT* lf = reinterpret_cast<const LOGFONT*>(ctx);
return lface &&
get_style(lface->fLogFont) == requestedStyle &&
!memcmp(&lface->fLogFont, lf, sizeof(LOGFONT));
return !memcmp(&lface->fLogFont, lf, sizeof(LOGFONT));
}
/**
@ -327,7 +325,7 @@ SkTypeface* SkCreateTypefaceFromLOGFONT(const LOGFONT& origLF) {
SkTypeface* face = SkTypefaceCache::FindByProcAndRef(FindByLogFont, &lf);
if (nullptr == face) {
face = LogFontTypeface::Create(lf);
SkTypefaceCache::Add(face, get_style(lf));
SkTypefaceCache::Add(face);
}
return face;
}

View File

@ -605,7 +605,7 @@ class SkFontMgr_fontconfig : public SkFontMgr {
sizes.begin(), names.count());
}
static bool FindByFcPattern(SkTypeface* cached, const SkFontStyle&, void* ctx) {
static bool FindByFcPattern(SkTypeface* cached, void* ctx) {
SkTypeface_fontconfig* cshFace = static_cast<SkTypeface_fontconfig*>(cached);
FcPattern* ctxPattern = static_cast<FcPattern*>(ctx);
return FcTrue == FcPatternEqual(cshFace->fPattern, ctxPattern);
@ -624,7 +624,7 @@ class SkFontMgr_fontconfig : public SkFontMgr {
FcPatternReference(pattern);
face = SkTypeface_fontconfig::Create(pattern);
if (face) {
fTFCache.add(face, SkFontStyle());
fTFCache.add(face);
}
}
return face;

View File

@ -353,7 +353,7 @@ struct ProtoDWriteTypeface {
IDWriteFontFamily* fDWriteFontFamily;
};
static bool FindByDWriteFont(SkTypeface* cached, const SkFontStyle&, void* ctx) {
static bool FindByDWriteFont(SkTypeface* cached, void* ctx) {
DWriteFontTypeface* cshFace = reinterpret_cast<DWriteFontTypeface*>(cached);
ProtoDWriteTypeface* ctxFace = reinterpret_cast<ProtoDWriteTypeface*>(ctx);
bool same;
@ -457,7 +457,7 @@ SkTypeface* SkFontMgr_DirectWrite::createTypefaceFromDWriteFont(
if (nullptr == face) {
face = DWriteFontTypeface::Create(fFactory.get(), fontFace, font, fontFamily);
if (face) {
fTFCache.add(face, get_style(font));
fTFCache.add(face);
}
}
return face;

View File

@ -5,7 +5,9 @@
* found in the LICENSE file.
*/
#include "SkRefCnt.h"
#include "SkTypeface.h"
#include "SkTypefaceCache.h"
#include "Test.h"
DEF_TEST(Typeface, reporter) {
@ -24,3 +26,68 @@ DEF_TEST(Typeface, reporter) {
REPORTER_ASSERT(reporter, nullptr == t3.get());
#endif
}
class SkEmptyTypeface : public SkTypeface {
public:
static sk_sp<SkTypeface> Create(SkFontID id) { return sk_sp<SkTypeface>(new SkEmptyTypeface(id)); }
protected:
SkEmptyTypeface(SkFontID id) : SkTypeface(SkFontStyle(), id, true) { }
SkStreamAsset* onOpenStream(int* ttcIndex) const override { return nullptr; }
SkScalerContext* onCreateScalerContext(const SkScalerContextEffects&,
const SkDescriptor*) const override {
return nullptr;
}
void onFilterRec(SkScalerContextRec*) const override { }
virtual SkAdvancedTypefaceMetrics* onGetAdvancedTypefaceMetrics(
PerGlyphInfo,
const uint32_t*, uint32_t) const override { return nullptr; }
void onGetFontDescriptor(SkFontDescriptor*, bool*) const override { }
virtual int onCharsToGlyphs(const void* chars, Encoding encoding,
uint16_t glyphs[], int glyphCount) const override {
SK_ABORT("unimplemented");
return 0;
}
int onCountGlyphs() const override { return 0; };
int onGetUPEM() const override { return 0; };
void onGetFamilyName(SkString* familyName) const override { familyName->reset(); }
SkTypeface::LocalizedStrings* onCreateFamilyNameIterator() const override {
SK_ABORT("unimplemented");
return nullptr;
};
int onGetTableTags(SkFontTableTag tags[]) const override { return 0; }
size_t onGetTableData(SkFontTableTag, size_t, size_t, void*) const override { return 0; }
};
static bool count_proc(SkTypeface* face, void* ctx) {
int* count = static_cast<int*>(ctx);
*count = *count + 1;
return false;
}
static int count(skiatest::Reporter* reporter, const SkTypefaceCache& cache) {
int count = 0;
SkTypeface* none = cache.findByProcAndRef(count_proc, &count);
REPORTER_ASSERT(reporter, none == nullptr);
return count;
}
DEF_TEST(TypefaceCache, reporter) {
sk_sp<SkTypeface> t1(SkEmptyTypeface::Create(1));
{
SkTypefaceCache cache;
REPORTER_ASSERT(reporter, count(reporter, cache) == 0);
{
sk_sp<SkTypeface> t0(SkEmptyTypeface::Create(0));
cache.add(t0.get());
REPORTER_ASSERT(reporter, count(reporter, cache) == 1);
cache.add(t1.get());
REPORTER_ASSERT(reporter, count(reporter, cache) == 2);
cache.purgeAll();
REPORTER_ASSERT(reporter, count(reporter, cache) == 2);
}
REPORTER_ASSERT(reporter, count(reporter, cache) == 2);
cache.purgeAll();
REPORTER_ASSERT(reporter, count(reporter, cache) == 1);
}
REPORTER_ASSERT(reporter, t1->unique());
}