Regularize SkGlyphCache creation.

This allows no need for downcasting for specialized use
of SkScalerContext for the remote case. This allows
cache priming to be used in a single process.

BUG=skia:7515

Change-Id: I963a50e36af9deef5a3414fc8a4c94ccfc38deaf
Reviewed-on: https://skia-review.googlesource.com/115121
Reviewed-by: Ben Wagner <bungeman@google.com>
Commit-Queue: Herb Derby <herb@google.com>
This commit is contained in:
Herb Derby 2018-03-19 15:39:16 -04:00 committed by Skia Commit-Bot
parent b0ca84f3a8
commit aeb425dbf1
6 changed files with 64 additions and 68 deletions

View File

@ -33,15 +33,15 @@ static SkGlyphCache_Globals& get_globals() {
}
///////////////////////////////////////////////////////////////////////////////
SkGlyphCache::SkGlyphCache(const SkDescriptor& desc, std::unique_ptr<SkScalerContext> ctx)
: fDesc(desc.copy())
, fScalerContext(std::move(ctx))
SkGlyphCache::SkGlyphCache(
const SkDescriptor& desc,
std::unique_ptr<SkScalerContext> scaler,
const SkPaint::FontMetrics& fontMetrics)
: fDesc{desc.copy()}
, fScalerContext{std::move(scaler)}
, fFontMetrics(fontMetrics)
{
SkASSERT(fScalerContext);
fScalerContext->getFontMetrics(&fFontMetrics);
SkASSERT(fScalerContext != nullptr);
fMemoryUsed = sizeof(*this);
}
@ -53,10 +53,6 @@ SkGlyphCache::~SkGlyphCache() {
});
}
void SkGlyphCache::PurgeAll() {
get_globals().purgeAll();
}
SkGlyphCache::CharGlyphRec* SkGlyphCache::getCharGlyphRec(SkPackedUnicharID packedUnicharID) {
if (!fPackedUnicharIDToPackedGlyphID) {
fPackedUnicharIDToPackedGlyphID.reset(new CharGlyphRec[kHashCount]);
@ -497,12 +493,32 @@ SkExclusiveStrikePtr SkGlyphCache::FindStrikeExclusive(const SkDescriptor& desc)
return SkExclusiveStrikePtr(nullptr);
}
std::unique_ptr<SkScalerContext> SkGlyphCache::CreateScalerContext(
const SkDescriptor& desc,
const SkScalerContextEffects& effects,
const SkTypeface& typeface) {
auto scaler = typeface.createScalerContext(effects, &desc, true /* can fail */);
// 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,
if (scaler == nullptr) {
get_globals().purgeAll();
scaler = typeface.createScalerContext(effects, &desc, false /* must succeed */);
}
return scaler;
}
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);
auto cache = SkGlyphCache::FindStrikeExclusive(desc);
if (cache == nullptr) {
auto scaler = CreateScalerContext(desc, effects, typeface);
cache = SkGlyphCache::CreateStrikeExclusive(desc, std::move(scaler));
}
return cache;
}
SkExclusiveStrikePtr SkGlyphCache::FindOrCreateStrikeExclusive(
@ -522,6 +538,21 @@ SkExclusiveStrikePtr SkGlyphCache::FindOrCreateStrikeExclusive(
return FindOrCreateStrikeExclusive(*desc, effects, *tf);
}
SkExclusiveStrikePtr SkGlyphCache::CreateStrikeExclusive(
const SkDescriptor& desc,
std::unique_ptr<SkScalerContext> scaler,
SkPaint::FontMetrics* maybeMetrics)
{
SkPaint::FontMetrics fontMetrics;
if (maybeMetrics != nullptr) {
fontMetrics = *maybeMetrics;
} else {
scaler->getFontMetrics(&fontMetrics);
}
return SkExclusiveStrikePtr(new SkGlyphCache(desc, std::move(scaler), fontMetrics));
}
void SkGlyphCache::ForEachStrike(std::function<void(const SkGlyphCache&)> visitor) {
SkGlyphCache_Globals& globals = get_globals();
SkAutoExclusive ac(globals.fLock);

View File

@ -126,21 +126,15 @@ public:
void dump() const;
static std::unique_ptr<SkScalerContext> CreateScalerContext(
const SkDescriptor& desc,
const SkScalerContextEffects& effects,
const SkTypeface& typeface);
SkScalerContext* getScalerContext() const { return fScalerContext.get(); }
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,
@ -157,24 +151,10 @@ public:
paint, nullptr, SkScalerContextFlags::kFakeGammaAndBoostContrast, nullptr);
}
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)));
}
const SkDescriptor& desc,
std::unique_ptr<SkScalerContext> scaler,
SkPaint::FontMetrics* maybeMetrics = nullptr);
static void Dump();
@ -230,12 +210,10 @@ private:
SkPackedGlyphID fPackedGlyphID;
};
SkGlyphCache(const SkDescriptor& desc, std::unique_ptr<SkScalerContext> scaler);
SkGlyphCache(const SkDescriptor& desc, std::unique_ptr<SkScalerContext> scaler,
const SkPaint::FontMetrics&);
~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.

View File

@ -805,6 +805,10 @@ std::unique_ptr<SkScalerContext> SkTypeface::createScalerContext(
c = skstd::make_unique<SkScalerContext_Empty>(sk_ref_sp(const_cast<SkTypeface*>(this)),
effects, desc);
}
// !allowFailure implies c != nullptr
SkASSERT(c || allowFailure);
return c;
}

View File

@ -31,11 +31,7 @@ void SkScalerContextProxy::generatePath(SkGlyphID glyphID, SkPath* path) {
}
void SkScalerContextProxy::generateFontMetrics(SkPaint::FontMetrics* metrics) {
if (!fHaveFontMetrics) {
fRemote->generateFontMetrics(*this->typefaceProxy(), this->getRec(), &fFontMetrics);
}
fHaveFontMetrics = true;
*metrics = fFontMetrics;
fRemote->generateFontMetrics(*this->typefaceProxy(), this->getRec(), metrics);
}
SkTypefaceProxy* SkScalerContextProxy::typefaceProxy() {

View File

@ -47,11 +47,6 @@ public:
const SkDescriptor* desc,
SkRemoteScalerContext* rsc);
void setFontMetrics(const SkPaint::FontMetrics& fontMetrics) {
fFontMetrics = fontMetrics;
fHaveFontMetrics = true;
}
protected:
unsigned generateGlyphCount(void) override { SK_ABORT("Should never be called."); return 0;}
uint16_t generateCharToGlyph(SkUnichar uni) override {
@ -75,8 +70,6 @@ private:
SkArenaAlloc fAlloc{kMinAllocAmount};
SkRemoteScalerContext* const fRemote;
bool fHaveFontMetrics{false};
SkPaint::FontMetrics fFontMetrics;
typedef SkScalerContext INHERITED;
};

View File

@ -774,14 +774,8 @@ static void prepopulate_cache(
// TODO: implement effects handling.
SkScalerContextEffects effects;
if ((strike = SkGlyphCache::FindStrikeExclusive(*desc)) == nullptr) {
auto creator = [&effects, &tf, &fontMetrics](
const SkDescriptor& descriptor, bool canFail)
{
auto scaler = tf->createScalerContext(effects, &descriptor, canFail);
((SkScalerContextProxy*)scaler.get())->setFontMetrics(*fontMetrics);
return scaler;
};
strike = SkGlyphCache::CreateStrikeExclusive(*desc,creator);
auto scaler = SkGlyphCache::CreateScalerContext(*desc, effects, *tf);
strike = SkGlyphCache::CreateStrikeExclusive(*desc, std::move(scaler), fontMetrics);
}
#if INSTRUMENT
std::cout << std::hex << "prepop cache " << (intptr_t)cache