Move scaler context fallback to GDI
The GDI Typeface is the only one that can fail to make a
scaler context. Move all the logic to the GDI specific code.
Change-Id: I50a0a58529bb44625068244e6ae27e54bccd9f67
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/269913
Commit-Queue: Herb Derby <herb@google.com>
Reviewed-by: Herb Derby <herb@google.com>
Reviewed-by: Ben Wagner <bungeman@google.com>
diff --git a/include/core/SkTypeface.h b/include/core/SkTypeface.h
index 64a6898..3ace52f 100644
--- a/include/core/SkTypeface.h
+++ b/include/core/SkTypeface.h
@@ -320,13 +320,11 @@
std::unique_ptr<SkFontData> makeFontData() const;
/**
- * Return a scalercontext for the given descriptor. If this fails, then
- * if allowFailure is true, this returns NULL, else it returns a
+ * Return a scalercontext for the given descriptor. It may return a
* dummy scalercontext that will not crash, but will draw nothing.
*/
std::unique_ptr<SkScalerContext> createScalerContext(const SkScalerContextEffects&,
- const SkDescriptor*,
- bool allowFailure = false) const;
+ const SkDescriptor*) const;
/**
* Return a rectangle (scaled to 1-pt) that represents the union of the bounds of all
@@ -361,6 +359,7 @@
/** Sets the font style. If used, must be called in the constructor. */
void setFontStyle(SkFontStyle style) { fStyle = style; }
+ // Must return a valid scaler context. It can not return nullptr.
virtual SkScalerContext* onCreateScalerContext(const SkScalerContextEffects&,
const SkDescriptor*) const = 0;
virtual void onFilterRec(SkScalerContextRec*) const = 0;
diff --git a/src/core/SkRemoteGlyphCache.cpp b/src/core/SkRemoteGlyphCache.cpp
index 2d2b6d1..46f09b1 100644
--- a/src/core/SkRemoteGlyphCache.cpp
+++ b/src/core/SkRemoteGlyphCache.cpp
@@ -952,7 +952,7 @@
// glyphs here anyway, and the desc is still correct since it includes the serialized
// effects.
SkScalerContextEffects effects;
- auto scaler = SkStrikeCache::CreateScalerContext(*client_desc, effects, *tf);
+ auto scaler = tf->createScalerContext(effects, client_desc);
strike = fStrikeCache->createStrikeExclusive(
*client_desc, std::move(scaler), &fontMetrics,
std::make_unique<DiscardableStrikePinner>(
diff --git a/src/core/SkScalerContext.cpp b/src/core/SkScalerContext.cpp
index 930692b..987ebb5 100644
--- a/src/core/SkScalerContext.cpp
+++ b/src/core/SkScalerContext.cpp
@@ -863,53 +863,13 @@
SkColorSetRGB(SkColorGetR(c), SkColorGetG(c), SkColorGetB(c)));
}
-///////////////////////////////////////////////////////////////////////////////
-
-class SkScalerContext_Empty : public SkScalerContext {
-public:
- SkScalerContext_Empty(sk_sp<SkTypeface> typeface, const SkScalerContextEffects& effects,
- const SkDescriptor* desc)
- : SkScalerContext(std::move(typeface), effects, desc) {}
-
-protected:
- unsigned generateGlyphCount() override {
- return 0;
- }
- bool generateAdvance(SkGlyph* glyph) override {
- glyph->zeroMetrics();
- return true;
- }
- void generateMetrics(SkGlyph* glyph) override {
- glyph->fMaskFormat = fRec.fMaskFormat;
- glyph->zeroMetrics();
- }
- void generateImage(const SkGlyph& glyph) override {}
- bool generatePath(SkGlyphID glyph, SkPath* path) override {
- path->reset();
- return false;
- }
- void generateFontMetrics(SkFontMetrics* metrics) override {
- if (metrics) {
- sk_bzero(metrics, sizeof(*metrics));
- }
- }
-};
-
extern SkScalerContext* SkCreateColorScalerContext(const SkDescriptor* desc);
std::unique_ptr<SkScalerContext> SkTypeface::createScalerContext(
- const SkScalerContextEffects& effects, const SkDescriptor* desc, bool allowFailure) const
-{
- std::unique_ptr<SkScalerContext> c(this->onCreateScalerContext(effects, desc));
- if (!c && !allowFailure) {
- c = std::make_unique<SkScalerContext_Empty>(sk_ref_sp(const_cast<SkTypeface*>(this)),
- effects, desc);
- }
-
- // !allowFailure implies c != nullptr
- SkASSERT(c || allowFailure);
-
- return c;
+ const SkScalerContextEffects& effects, const SkDescriptor* desc) const {
+ auto answer = std::unique_ptr<SkScalerContext>{this->onCreateScalerContext(effects, desc)};
+ SkASSERT(answer != nullptr);
+ return answer;
}
/*
@@ -1198,6 +1158,42 @@
return size >= calculate_size_and_flatten(rec, effects, &buf);
}
+SkScalerContext* SkScalerContext::MakeEmptyContext(
+ sk_sp<SkTypeface> typeface, const SkScalerContextEffects& effects,
+ const SkDescriptor* desc) {
+ class SkScalerContext_Empty : public SkScalerContext {
+ public:
+ SkScalerContext_Empty(sk_sp<SkTypeface> typeface, const SkScalerContextEffects& effects,
+ const SkDescriptor* desc)
+ : SkScalerContext(std::move(typeface), effects, desc) {}
+
+ protected:
+ unsigned generateGlyphCount() override {
+ return 0;
+ }
+ bool generateAdvance(SkGlyph* glyph) override {
+ glyph->zeroMetrics();
+ return true;
+ }
+ void generateMetrics(SkGlyph* glyph) override {
+ glyph->fMaskFormat = fRec.fMaskFormat;
+ glyph->zeroMetrics();
+ }
+ void generateImage(const SkGlyph& glyph) override {}
+ bool generatePath(SkGlyphID glyph, SkPath* path) override {
+ path->reset();
+ return false;
+ }
+ void generateFontMetrics(SkFontMetrics* metrics) override {
+ if (metrics) {
+ sk_bzero(metrics, sizeof(*metrics));
+ }
+ }
+ };
+
+ return new SkScalerContext_Empty{std::move(typeface), effects, desc};
+}
+
diff --git a/src/core/SkScalerContext.h b/src/core/SkScalerContext.h
index fc4f941..735ea19 100644
--- a/src/core/SkScalerContext.h
+++ b/src/core/SkScalerContext.h
@@ -323,6 +323,10 @@
static SkDescriptor* MakeDescriptorForPaths(SkFontID fontID,
SkAutoDescriptor* ad);
+ static SkScalerContext* MakeEmptyContext(
+ sk_sp<SkTypeface> typeface, const SkScalerContextEffects& effects,
+ const SkDescriptor* desc);
+
static SkDescriptor* AutoDescriptorGivenRecAndEffects(
const SkScalerContextRec& rec,
const SkScalerContextEffects& effects,
diff --git a/src/core/SkStrikeCache.cpp b/src/core/SkStrikeCache.cpp
index f90caa2..98733f7 100644
--- a/src/core/SkStrikeCache.cpp
+++ b/src/core/SkStrikeCache.cpp
@@ -140,23 +140,6 @@
}
}
-std::unique_ptr<SkScalerContext> SkStrikeCache::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) {
- PurgeAll();
- scaler = typeface.createScalerContext(effects, &desc, false /* must succeed */);
- }
- return scaler;
-}
-
SkExclusiveStrikePtr SkStrikeCache::findOrCreateStrikeExclusive(
const SkDescriptor& desc, const SkScalerContextEffects& effects, const SkTypeface& typeface)
{
@@ -168,7 +151,7 @@
const SkTypeface& typeface) -> Node* {
Node* node = this->findAndDetachStrike(desc);
if (node == nullptr) {
- auto scaler = CreateScalerContext(desc, effects, typeface);
+ auto scaler = typeface.createScalerContext(effects, &desc);
node = this->createStrike(desc, std::move(scaler));
}
return node;
diff --git a/src/core/SkStrikeCache.h b/src/core/SkStrikeCache.h
index db5ee6b..89035bd 100644
--- a/src/core/SkStrikeCache.h
+++ b/src/core/SkStrikeCache.h
@@ -86,9 +86,6 @@
const SkScalerContextEffects& effects,
const SkTypeface& typeface) override;
- static std::unique_ptr<SkScalerContext> CreateScalerContext(
- const SkDescriptor&, const SkScalerContextEffects&, const SkTypeface&);
-
static void PurgeAll();
static void ValidateGlyphCacheDataSize();
static void Dump();
diff --git a/src/core/SkTypeface.cpp b/src/core/SkTypeface.cpp
index 69e5de6..2cfa6b7 100644
--- a/src/core/SkTypeface.cpp
+++ b/src/core/SkTypeface.cpp
@@ -14,6 +14,7 @@
#include "src/core/SkAdvancedTypefaceMetrics.h"
#include "src/core/SkEndian.h"
#include "src/core/SkFontDescriptor.h"
+#include "src/core/SkScalerContext.h"
#include "src/core/SkSurfacePriv.h"
#include "src/core/SkTypefaceCache.h"
#include "src/sfnt/SkOTTable_OS_2.h"
@@ -47,9 +48,10 @@
sk_sp<SkTypeface> onMakeClone(const SkFontArguments& args) const override {
return sk_ref_sp(this);
}
- SkScalerContext* onCreateScalerContext(const SkScalerContextEffects&,
- const SkDescriptor*) const override {
- return nullptr;
+ SkScalerContext* onCreateScalerContext(const SkScalerContextEffects& effects,
+ const SkDescriptor* desc) const override {
+ return SkScalerContext::MakeEmptyContext(
+ sk_ref_sp(const_cast<SkEmptyTypeface*>(this)), effects, desc);
}
void onFilterRec(SkScalerContextRec*) const override { }
std::unique_ptr<SkAdvancedTypefaceMetrics> onGetAdvancedMetrics() const override {
@@ -401,10 +403,7 @@
SkScalerContextEffects noeffects;
SkScalerContext::AutoDescriptorGivenRecAndEffects(rec, noeffects, &ad);
- std::unique_ptr<SkScalerContext> ctx = this->createScalerContext(noeffects, ad.getDesc(), true);
- if (!ctx) {
- return false;
- }
+ std::unique_ptr<SkScalerContext> ctx = this->createScalerContext(noeffects, ad.getDesc());
SkFontMetrics fm;
ctx->getFontMetrics(&fm);
diff --git a/src/ports/SkFontHost_FreeType.cpp b/src/ports/SkFontHost_FreeType.cpp
index ef240c7..e18b286 100644
--- a/src/ports/SkFontHost_FreeType.cpp
+++ b/src/ports/SkFontHost_FreeType.cpp
@@ -701,7 +701,8 @@
auto c = std::make_unique<SkScalerContext_FreeType>(
sk_ref_sp(const_cast<SkTypeface_FreeType*>(this)), effects, desc);
if (!c->success()) {
- return nullptr;
+ return SkScalerContext::MakeEmptyContext(
+ sk_ref_sp(const_cast<SkTypeface_FreeType*>(this)), effects, desc);
}
return c.release();
}
diff --git a/src/ports/SkFontHost_win.cpp b/src/ports/SkFontHost_win.cpp
index 1fa12c9..bc0f07f 100644
--- a/src/ports/SkFontHost_win.cpp
+++ b/src/ports/SkFontHost_win.cpp
@@ -26,6 +26,7 @@
#include "src/core/SkGlyph.h"
#include "src/core/SkLeanWindows.h"
#include "src/core/SkMaskGamma.h"
+#include "src/core/SkStrikeCache.h"
#include "src/core/SkTypefaceCache.h"
#include "src/core/SkUtils.h"
#include "src/sfnt/SkOTTable_OS_2.h"
@@ -2028,7 +2029,14 @@
auto ctx = std::make_unique<SkScalerContext_GDI>(
sk_ref_sp(const_cast<LogFontTypeface*>(this)), effects, desc);
if (!ctx->isValid()) {
- return nullptr;
+ ctx.reset();
+ SkStrikeCache::PurgeAll();
+ ctx = std::make_unique<SkScalerContext_GDI>(
+ sk_ref_sp(const_cast<LogFontTypeface*>(this)), effects, desc);
+ if (!ctx->isValid()) {
+ return SkScalerContext::MakeEmptyContext(
+ sk_ref_sp(const_cast<LogFontTypeface*>(this)), effects, desc);
+ }
}
return ctx.release();
}
diff --git a/tests/FontMgrTest.cpp b/tests/FontMgrTest.cpp
index f63920b..ffeb05e 100644
--- a/tests/FontMgrTest.cpp
+++ b/tests/FontMgrTest.cpp
@@ -11,6 +11,7 @@
#include "include/core/SkStream.h"
#include "include/core/SkTypeface.h"
#include "src/core/SkAdvancedTypefaceMetrics.h"
+#include "src/core/SkScalerContext.h"
#include "tests/Test.h"
#include "tools/flags/CommandLineFlags.h"
@@ -127,9 +128,10 @@
sk_sp<SkTypeface> onMakeClone(const SkFontArguments& args) const override {
return sk_ref_sp(this);
}
- SkScalerContext* onCreateScalerContext(const SkScalerContextEffects&,
- const SkDescriptor*) const override {
- return nullptr;
+ SkScalerContext* onCreateScalerContext(const SkScalerContextEffects& effects,
+ const SkDescriptor* desc) const override {
+ return SkScalerContext::MakeEmptyContext(
+ sk_ref_sp(const_cast<TestTypeface*>(this)), effects, desc);
}
void onFilterRec(SkScalerContextRec*) const override { }
std::unique_ptr<SkAdvancedTypefaceMetrics> onGetAdvancedMetrics() const override {
diff --git a/tests/SkRemoteGlyphCacheTest.cpp b/tests/SkRemoteGlyphCacheTest.cpp
index c3b21c2..64a6823 100644
--- a/tests/SkRemoteGlyphCacheTest.cpp
+++ b/tests/SkRemoteGlyphCacheTest.cpp
@@ -857,7 +857,7 @@
SkMatrix::I(), &rec, &effects);
auto desc = SkScalerContext::AutoDescriptorGivenRecAndEffects(rec, effects, &ad);
- auto context = serverTf->createScalerContext(effects, desc, false);
+ auto context = serverTf->createScalerContext(effects, desc);
SkGlyph glyph{lostGlyphID};
context->getMetrics(&glyph);
realMask = glyph.maskFormat();
diff --git a/tools/fonts/TestEmptyTypeface.h b/tools/fonts/TestEmptyTypeface.h
index 3d61762..a340ffe 100644
--- a/tools/fonts/TestEmptyTypeface.h
+++ b/tools/fonts/TestEmptyTypeface.h
@@ -11,6 +11,7 @@
#include "include/core/SkStream.h"
#include "include/core/SkTypeface.h"
#include "src/core/SkAdvancedTypefaceMetrics.h"
+#include "src/core/SkScalerContext.h"
class TestEmptyTypeface : public SkTypeface {
public:
@@ -23,9 +24,11 @@
sk_sp<SkTypeface> onMakeClone(const SkFontArguments& args) const override {
return sk_ref_sp(this);
}
- SkScalerContext* onCreateScalerContext(const SkScalerContextEffects&,
- const SkDescriptor*) const override {
- return nullptr;
+ SkScalerContext* onCreateScalerContext(const SkScalerContextEffects& effects,
+ const SkDescriptor* desc) const override {
+ return SkScalerContext::MakeEmptyContext(
+ sk_ref_sp(const_cast<TestEmptyTypeface*>(this)), effects, desc);
+
}
void onFilterRec(SkScalerContextRec*) const override {}
std::unique_ptr<SkAdvancedTypefaceMetrics> onGetAdvancedMetrics() const override {