Move glyph cache and descriptor functions off of SkPaint

BUG=skia:7515

Change-Id: If17b157db1077a9a3c0f9efd03929f62a3486419
Reviewed-on: https://skia-review.googlesource.com/98841
Reviewed-by: Mike Klein <mtklein@chromium.org>
Commit-Queue: Herb Derby <herb@google.com>
diff --git a/src/core/SkGlyphCache.cpp b/src/core/SkGlyphCache.cpp
index 9ddf70c..16f1863 100644
--- a/src/core/SkGlyphCache.cpp
+++ b/src/core/SkGlyphCache.cpp
@@ -5,6 +5,7 @@
  * found in the LICENSE file.
  */
 
+
 #include "SkGlyphCache.h"
 #include "SkGlyphCache_Globals.h"
 #include "SkGraphics.h"
@@ -810,3 +811,16 @@
 // TODO(herb): clean up TLS apis.
 size_t SkGraphics::GetTLSFontCacheLimit() { return 0; }
 void SkGraphics::SetTLSFontCacheLimit(size_t bytes) { }
+
+SkGlyphCache* SkGlyphCache::DetachCacheUsingPaint(const SkPaint& paint,
+                                                  const SkSurfaceProps* surfaceProps,
+                                                  SkScalerContextFlags scalerContextFlags,
+                                                  const SkMatrix* deviceMatrix) {
+    SkAutoDescriptor ad;
+    SkScalerContextEffects effects;
+
+    auto desc = SkScalerContext::CreateDescriptorAndEffectsUsingPaint(
+        paint, surfaceProps, scalerContextFlags, deviceMatrix, &ad, &effects);
+
+    return SkGlyphCache::DetachCache(paint.getTypeface(), effects, desc);
+}
diff --git a/src/core/SkGlyphCache.h b/src/core/SkGlyphCache.h
index 834db7a..052e072 100644
--- a/src/core/SkGlyphCache.h
+++ b/src/core/SkGlyphCache.h
@@ -138,6 +138,11 @@
         return VisitCache(typeface, effects, desc, DetachProc, nullptr);
     }
 
+    static SkGlyphCache* DetachCacheUsingPaint(const SkPaint& paint,
+                                               const SkSurfaceProps* surfaceProps,
+                                               SkScalerContextFlags scalerContextFlags,
+                                               const SkMatrix* deviceMatrix);
+
     static void Dump();
 
     /** Dump memory usage statistics of all the attaches caches in the process using the
@@ -262,15 +267,17 @@
     SkAutoGlyphCache(const SkPaint& paint,
                      const SkSurfaceProps* surfaceProps,
                      const SkMatrix* matrix)
-        : INHERITED(paint.detachCache(surfaceProps,
-                                      SkScalerContextFlags::kFakeGammaAndBoostContrast,
-                                      matrix))
+        : INHERITED(
+        SkGlyphCache::DetachCacheUsingPaint(
+            paint, surfaceProps,
+            SkScalerContextFlags::kFakeGammaAndBoostContrast, matrix))
     {}
     SkAutoGlyphCache(const SkPaint& paint,
                      const SkSurfaceProps* surfaceProps,
                      SkScalerContextFlags scalerContextFlags,
                      const SkMatrix* matrix)
-        : INHERITED(paint.detachCache(surfaceProps, scalerContextFlags, matrix))
+        : INHERITED(
+            SkGlyphCache::DetachCacheUsingPaint(paint, surfaceProps, scalerContextFlags, matrix))
     {}
 private:
     using INHERITED = std::unique_ptr<SkGlyphCache, SkGlyphCache::AttachCacheFunctor>;
diff --git a/src/core/SkPaint.cpp b/src/core/SkPaint.cpp
index 0686c3b..2e5d22c 100644
--- a/src/core/SkPaint.cpp
+++ b/src/core/SkPaint.cpp
@@ -398,11 +398,6 @@
 #include "SkGlyphCache.h"
 #include "SkUtils.h"
 
-static void DetachDescProc(SkTypeface* typeface, const SkScalerContextEffects& effects,
-                           const SkDescriptor* desc, void* context) {
-    *((SkGlyphCache**)context) = SkGlyphCache::DetachCache(typeface, effects, desc);
-}
-
 int SkPaint::textToGlyphs(const void* textData, size_t byteLength, uint16_t glyphs[]) const {
     if (byteLength == 0) {
         return 0;
@@ -915,11 +910,6 @@
     return false;   // don't detach the cache
 }
 
-static void FontMetricsDescProc(SkTypeface* typeface, const SkScalerContextEffects& effects,
-                                const SkDescriptor* desc, void* context) {
-    SkGlyphCache::VisitCache(typeface, effects, desc, FontMetricsCacheProc, context);
-}
-
 SkScalar SkPaint::getFontMetrics(FontMetrics* metrics, SkScalar zoom) const {
     SkCanonicalizePaint canon(*this);
     const SkPaint& paint = canon.getPaint();
@@ -936,8 +926,13 @@
         metrics = &storage;
     }
 
-    paint.descriptorProc(nullptr, SkScalerContextFlags::kNone, zoomPtr,
-                         FontMetricsDescProc, metrics);
+    SkAutoDescriptor ad;
+    SkScalerContextEffects effects;
+
+    auto desc = SkScalerContext::CreateDescriptorAndEffectsUsingPaint(
+        paint, nullptr, SkScalerContextFlags::kNone, zoomPtr, &ad, &effects);
+
+    SkGlyphCache::VisitCache(paint.getTypeface(), effects, desc, FontMetricsCacheProc, metrics);
 
     if (scale) {
         SkPaintPriv::ScaleFontMetrics(metrics, scale);
@@ -1217,31 +1212,6 @@
     return bounds;
 }
 
-static SkMask::Format compute_mask_format(const SkPaint& paint) {
-    uint32_t flags = paint.getFlags();
-
-    // Antialiasing being disabled trumps all other settings.
-    if (!(flags & SkPaint::kAntiAlias_Flag)) {
-        return SkMask::kBW_Format;
-    }
-
-    if (flags & SkPaint::kLCDRenderText_Flag) {
-        return SkMask::kLCD16_Format;
-    }
-
-    return SkMask::kA8_Format;
-}
-
-// if linear-text is on, then we force hinting to be off (since that's sort of
-// the point of linear-text.
-static SkPaint::Hinting computeHinting(const SkPaint& paint) {
-    SkPaint::Hinting h = paint.getHinting();
-    if (paint.isLinearText()) {
-        h = SkPaint::kNo_Hinting;
-    }
-    return h;
-}
-
 // return true if the paint is just a single color (i.e. not a shader). If its
 // a shader, then we can't compute a const luminance for it :(
 static bool justAColor(const SkPaint& paint, SkColor* color) {
@@ -1270,250 +1240,6 @@
 
 #define assert_byte(x)  SkASSERT(0 == ((x) >> 8))
 
-// Beyond this size, LCD doesn't appreciably improve quality, but it always
-// cost more RAM and draws slower, so we set a cap.
-#ifndef SK_MAX_SIZE_FOR_LCDTEXT
-    #define SK_MAX_SIZE_FOR_LCDTEXT    48
-#endif
-
-const SkScalar gMaxSize2ForLCDText = SK_MAX_SIZE_FOR_LCDTEXT * SK_MAX_SIZE_FOR_LCDTEXT;
-
-static bool too_big_for_lcd(const SkScalerContextRec& rec, bool checkPost2x2) {
-    if (checkPost2x2) {
-        SkScalar area = rec.fPost2x2[0][0] * rec.fPost2x2[1][1] -
-                        rec.fPost2x2[1][0] * rec.fPost2x2[0][1];
-        area *= rec.fTextSize * rec.fTextSize;
-        return area > gMaxSize2ForLCDText;
-    } else {
-        return rec.fTextSize > SK_MAX_SIZE_FOR_LCDTEXT;
-    }
-}
-
-/*
- *  Return the scalar with only limited fractional precision. Used to consolidate matrices
- *  that vary only slightly when we create our key into the font cache, since the font scaler
- *  typically returns the same looking resuts for tiny changes in the matrix.
- */
-static SkScalar sk_relax(SkScalar x) {
-    SkScalar n = SkScalarRoundToScalar(x * 1024);
-    return n / 1024.0f;
-}
-
-void SkScalerContext::MakeRecAndEffects(const SkPaint& paint,
-                                        const SkSurfaceProps* surfaceProps,
-                                        const SkMatrix* deviceMatrix,
-                                        SkScalerContextFlags scalerContextFlags,
-                                        SkScalerContextRec* rec,
-                                        SkScalerContextEffects* effects) {
-    SkASSERT(deviceMatrix == nullptr || !deviceMatrix->hasPerspective());
-
-    SkTypeface* typeface = paint.getTypeface();
-    if (nullptr == typeface) {
-        typeface = SkTypeface::GetDefaultTypeface();
-    }
-    rec->fFontID = typeface->uniqueID();
-    rec->fTextSize = paint.getTextSize();
-    rec->fPreScaleX = paint.getTextScaleX();
-    rec->fPreSkewX  = paint.getTextSkewX();
-
-    bool checkPost2x2 = false;
-
-    if (deviceMatrix) {
-        const SkMatrix::TypeMask mask = deviceMatrix->getType();
-        if (mask & SkMatrix::kScale_Mask) {
-            rec->fPost2x2[0][0] = sk_relax(deviceMatrix->getScaleX());
-            rec->fPost2x2[1][1] = sk_relax(deviceMatrix->getScaleY());
-            checkPost2x2 = true;
-        } else {
-            rec->fPost2x2[0][0] = rec->fPost2x2[1][1] = SK_Scalar1;
-        }
-        if (mask & SkMatrix::kAffine_Mask) {
-            rec->fPost2x2[0][1] = sk_relax(deviceMatrix->getSkewX());
-            rec->fPost2x2[1][0] = sk_relax(deviceMatrix->getSkewY());
-            checkPost2x2 = true;
-        } else {
-            rec->fPost2x2[0][1] = rec->fPost2x2[1][0] = 0;
-        }
-    } else {
-        rec->fPost2x2[0][0] = rec->fPost2x2[1][1] = SK_Scalar1;
-        rec->fPost2x2[0][1] = rec->fPost2x2[1][0] = 0;
-    }
-
-    SkPaint::Style  style = paint.getStyle();
-    SkScalar        strokeWidth = paint.getStrokeWidth();
-
-    unsigned flags = 0;
-
-    if (paint.isFakeBoldText()) {
-#ifdef SK_USE_FREETYPE_EMBOLDEN
-        flags |= SkScalerContext::kEmbolden_Flag;
-#else
-        SkScalar fakeBoldScale = SkScalarInterpFunc(paint.getTextSize(),
-                                                    kStdFakeBoldInterpKeys,
-                                                    kStdFakeBoldInterpValues,
-                                                    kStdFakeBoldInterpLength);
-        SkScalar extra = paint.getTextSize() * fakeBoldScale;
-
-        if (style == SkPaint::kFill_Style) {
-            style = SkPaint::kStrokeAndFill_Style;
-            strokeWidth = extra;    // ignore paint's strokeWidth if it was "fill"
-        } else {
-            strokeWidth += extra;
-        }
-#endif
-    }
-
-    if (paint.isDevKernText()) {
-        flags |= SkScalerContext::kDevKernText_Flag;
-    }
-
-    if (style != SkPaint::kFill_Style && strokeWidth > 0) {
-        rec->fFrameWidth = strokeWidth;
-        rec->fMiterLimit = paint.getStrokeMiter();
-        rec->fStrokeJoin = SkToU8(paint.getStrokeJoin());
-        rec->fStrokeCap = SkToU8(paint.getStrokeCap());
-
-        if (style == SkPaint::kStrokeAndFill_Style) {
-            flags |= SkScalerContext::kFrameAndFill_Flag;
-        }
-    } else {
-        rec->fFrameWidth = 0;
-        rec->fMiterLimit = 0;
-        rec->fStrokeJoin = 0;
-        rec->fStrokeCap = 0;
-    }
-
-    rec->fMaskFormat = SkToU8(compute_mask_format(paint));
-
-    if (SkMask::kLCD16_Format == rec->fMaskFormat) {
-        if (too_big_for_lcd(*rec, checkPost2x2)) {
-            rec->fMaskFormat = SkMask::kA8_Format;
-            flags |= SkScalerContext::kGenA8FromLCD_Flag;
-        } else {
-            SkPixelGeometry geometry = surfaceProps
-                                     ? surfaceProps->pixelGeometry()
-                                     : SkSurfacePropsDefaultPixelGeometry();
-            switch (geometry) {
-                case kUnknown_SkPixelGeometry:
-                    // eeek, can't support LCD
-                    rec->fMaskFormat = SkMask::kA8_Format;
-                    flags |= SkScalerContext::kGenA8FromLCD_Flag;
-                    break;
-                case kRGB_H_SkPixelGeometry:
-                    // our default, do nothing.
-                    break;
-                case kBGR_H_SkPixelGeometry:
-                    flags |= SkScalerContext::kLCD_BGROrder_Flag;
-                    break;
-                case kRGB_V_SkPixelGeometry:
-                    flags |= SkScalerContext::kLCD_Vertical_Flag;
-                    break;
-                case kBGR_V_SkPixelGeometry:
-                    flags |= SkScalerContext::kLCD_Vertical_Flag;
-                    flags |= SkScalerContext::kLCD_BGROrder_Flag;
-                    break;
-            }
-        }
-    }
-
-    if (paint.isEmbeddedBitmapText()) {
-        flags |= SkScalerContext::kEmbeddedBitmapText_Flag;
-    }
-    if (paint.isSubpixelText()) {
-        flags |= SkScalerContext::kSubpixelPositioning_Flag;
-    }
-    if (paint.isAutohinted()) {
-        flags |= SkScalerContext::kForceAutohinting_Flag;
-    }
-    if (paint.isVerticalText()) {
-        flags |= SkScalerContext::kVertical_Flag;
-    }
-    if (paint.getFlags() & SkPaint::kGenA8FromLCD_Flag) {
-        flags |= SkScalerContext::kGenA8FromLCD_Flag;
-    }
-    rec->fFlags = SkToU16(flags);
-
-    // these modify fFlags, so do them after assigning fFlags
-    rec->setHinting(computeHinting(paint));
-
-    rec->setLuminanceColor(paint.computeLuminanceColor());
-
-    // For now always set the paint gamma equal to the device gamma.
-    // The math in SkMaskGamma can handle them being different,
-    // but it requires superluminous masks when
-    // Ex : deviceGamma(x) < paintGamma(x) and x is sufficiently large.
-    rec->setDeviceGamma(SK_GAMMA_EXPONENT);
-    rec->setPaintGamma(SK_GAMMA_EXPONENT);
-
-#ifdef SK_GAMMA_CONTRAST
-    rec->setContrast(SK_GAMMA_CONTRAST);
-#else
-     // A value of 0.5 for SK_GAMMA_CONTRAST appears to be a good compromise.
-     // With lower values small text appears washed out (though correctly so).
-     // With higher values lcd fringing is worse and the smoothing effect of
-     // partial coverage is diminished.
-    rec->setContrast(0.5f);
-#endif
-
-    rec->fReservedAlign = 0;
-
-    // Allow the fonthost to modify our rec before we use it as a key into the
-    // cache. This way if we're asking for something that they will ignore,
-    // they can modify our rec up front, so we don't create duplicate cache
-    // entries.
-    typeface->onFilterRec(rec);
-
-    if (!SkToBool(scalerContextFlags & SkScalerContextFlags::kFakeGamma)) {
-        rec->ignoreGamma();
-    }
-    if (!SkToBool(scalerContextFlags & SkScalerContextFlags::kBoostContrast)) {
-        rec->setContrast(0);
-    }
-
-    new (effects) SkScalerContextEffects{paint};
-    if (effects->fPathEffect) {
-        rec->fMaskFormat = SkMask::kA8_Format;  // force antialiasing when we do the scan conversion
-        // seems like we could support kLCD as well at this point...
-    }
-    if (effects->fMaskFilter) {
-        // force antialiasing with maskfilters
-        rec->fMaskFormat = SkMask::kA8_Format;
-        // Pre-blend is not currently applied to filtered text.
-        // The primary filter is blur, for which contrast makes no sense,
-        // and for which the destination guess error is more visible.
-        // Also, all existing users of blur have calibrated for linear.
-        rec->ignorePreBlend();
-    }
-
-     // If we're asking for A8, we force the colorlum to be gray, since that
-     // limits the number of unique entries, and the scaler will only look at
-     // the lum of one of them.
-    switch (rec->fMaskFormat) {
-        case SkMask::kLCD16_Format: {
-            // filter down the luminance color to a finite number of bits
-            SkColor color = rec->getLuminanceColor();
-            rec->setLuminanceColor(SkMaskGamma::CanonicalColor(color));
-            break;
-        }
-        case SkMask::kA8_Format: {
-            // filter down the luminance to a single component, since A8 can't
-            // use per-component information
-            SkColor color = rec->getLuminanceColor();
-            U8CPU lum = SkComputeLuminance(SkColorGetR(color),
-                                           SkColorGetG(color),
-                                           SkColorGetB(color));
-            // reduce to our finite number of bits
-            color = SkColorSetRGB(lum, lum, lum);
-            rec->setLuminanceColor(SkMaskGamma::CanonicalColor(color));
-            break;
-        }
-        case SkMask::kBW_Format:
-            // No need to differentiate gamma or apply contrast if we're BW
-            rec->ignorePreBlend();
-            break;
-    }
-}
-
 /**
  * In order to call cachedDeviceLuminance, cachedPaintLuminance, or
  * cachedMaskGamma the caller must hold the gMaskGammaCacheMutex and continue
@@ -1548,46 +1274,6 @@
     return *gMaskGamma;
 }
 
-void SkPaint::getScalerContextDescriptor(SkScalerContextEffects* effects,
-                                         SkAutoDescriptor* ad,
-                                         const SkSurfaceProps* surfaceProps,
-                                         uint32_t scalerContextFlags,
-                                         const SkMatrix* deviceMatrix) const {
-    SkScalerContextRec rec;
-
-    SkScalerContext::MakeRecAndEffects(
-            *this, surfaceProps, deviceMatrix, (SkScalerContextFlags)scalerContextFlags, &rec, effects);
-    auto alloc = [ad](size_t size) {
-        ad->reset(size);
-        return ad->getDesc();
-    };
-    SkScalerContext::CreateDescriptorGivenRecAndEffects(rec, *effects, alloc);
-}
-
-void SkPaint::descriptorProc(const SkSurfaceProps* surfaceProps,
-                             uint32_t scalerContextFlags,
-                             const SkMatrix* deviceMatrix,
-                             void (*proc)(SkTypeface*, const SkScalerContextEffects&,
-                                          const SkDescriptor*, void*),
-                             void* context) const {
-    SkAutoDescriptor ad;
-    SkScalerContextEffects effects;
-
-    this->getScalerContextDescriptor(&effects, &ad, surfaceProps, scalerContextFlags,
-                                     deviceMatrix);
-
-    auto desc = ad.getDesc();
-    proc(fTypeface.get(), effects, desc, context);
-}
-
-SkGlyphCache* SkPaint::detachCache(const SkSurfaceProps* surfaceProps,
-                                   uint32_t scalerContextFlags,
-                                   const SkMatrix* deviceMatrix) const {
-    SkGlyphCache* cache;
-    this->descriptorProc(surfaceProps, scalerContextFlags, deviceMatrix, DetachDescProc, &cache);
-    return cache;
-}
-
 
 /**
  * Expands fDeviceGamma, fPaintGamma, fContrast, and fLumBits into a mask pre-blend.
@@ -1632,106 +1318,6 @@
     return true;
 }
 
-size_t SkScalerContext::CalculateSizeAndFlatten(
-        const SkScalerContextRec& rec,
-        const SkScalerContextEffects& effects,
-        SkBinaryWriteBuffer* pathEffectBuffer,
-        SkBinaryWriteBuffer* maskFilterBuffer) {
-    size_t descSize = sizeof(rec);
-    int entryCount = 1;
-
-    if (effects.fPathEffect) {
-        effects.fPathEffect->flatten(*pathEffectBuffer);
-        descSize += pathEffectBuffer->bytesWritten();
-        entryCount += 1;
-    }
-    if (effects.fMaskFilter) {
-        effects.fMaskFilter->flatten(*maskFilterBuffer);
-        descSize += maskFilterBuffer->bytesWritten();
-        entryCount += 1;
-    }
-
-    descSize += SkDescriptor::ComputeOverhead(entryCount);
-    return descSize;
-}
-
-#ifdef SK_DEBUG
-#define TEST_DESC
-#endif
-
-#ifdef TEST_DESC
-static void test_desc(const SkScalerContextRec& rec,
-                      const SkScalerContextEffects& effects,
-                      SkBinaryWriteBuffer* peBuffer,
-                      SkBinaryWriteBuffer* mfBuffer,
-                      const SkDescriptor* desc) {
-    // Check that we completely write the bytes in desc (our key), and that
-    // there are no uninitialized bytes. If there were, then we would get
-    // false-misses (or worse, false-hits) in our fontcache.
-    //
-    // We do this buy filling 2 others, one with 0s and the other with 1s
-    // and create those, and then check that all 3 are identical.
-    SkAutoDescriptor    ad1(desc->getLength());
-    SkAutoDescriptor    ad2(desc->getLength());
-    SkDescriptor*       desc1 = ad1.getDesc();
-    SkDescriptor*       desc2 = ad2.getDesc();
-
-    memset(desc1, 0x00, desc->getLength());
-    memset(desc2, 0xFF, desc->getLength());
-
-    desc1->init();
-    desc2->init();
-    desc1->addEntry(kRec_SkDescriptorTag, sizeof(rec), &rec);
-    desc2->addEntry(kRec_SkDescriptorTag, sizeof(rec), &rec);
-
-    auto add_flattenable = [](SkDescriptor* desc, uint32_t tag,
-                              SkBinaryWriteBuffer* buffer) {
-        buffer->writeToMemory(desc->addEntry(tag, buffer->bytesWritten(), nullptr));
-    };
-
-    if (effects.fPathEffect) {
-        add_flattenable(desc1, kPathEffect_SkDescriptorTag, peBuffer);
-        add_flattenable(desc2, kPathEffect_SkDescriptorTag, peBuffer);
-    }
-    if (effects.fMaskFilter) {
-        add_flattenable(desc1, kMaskFilter_SkDescriptorTag, mfBuffer);
-        add_flattenable(desc2, kMaskFilter_SkDescriptorTag, mfBuffer);
-    }
-
-    SkASSERT(desc->getLength() == desc1->getLength());
-    SkASSERT(desc->getLength() == desc2->getLength());
-    desc1->computeChecksum();
-    desc2->computeChecksum();
-    SkASSERT(!memcmp(desc, desc1, desc->getLength()));
-    SkASSERT(!memcmp(desc, desc2, desc->getLength()));
-}
-#endif
-
-void SkScalerContext::GenerateDescriptor(const SkScalerContextRec& rec,
-                                         const SkScalerContextEffects& effects,
-                                         SkBinaryWriteBuffer* pathEffectBuffer,
-                                         SkBinaryWriteBuffer* maskFilterBuffer,
-                                         SkDescriptor* desc) {
-    desc->init();
-    desc->addEntry(kRec_SkDescriptorTag, sizeof(rec), &rec);
-
-    auto add = [&desc](uint32_t tag, SkBinaryWriteBuffer* buffer) {
-        buffer->writeToMemory(desc->addEntry(tag, buffer->bytesWritten(), nullptr));
-    };
-
-    if (effects.fPathEffect) {
-        add(kPathEffect_SkDescriptorTag, pathEffectBuffer);
-    }
-    if (effects.fMaskFilter) {
-        add(kMaskFilter_SkDescriptorTag, maskFilterBuffer);
-    }
-
-    desc->computeChecksum();
-    #ifdef TEST_DESC
-        test_desc(rec, effects, pathEffectBuffer, maskFilterBuffer, desc);
-    #endif
-}
-
 ///////////////////////////////////////////////////////////////////////////////
 
 #include "SkStream.h"
@@ -2171,7 +1757,9 @@
     }
 
     // SRGBTODO: Is this correct?
-    fCache = fPaint.detachCache(nullptr, SkScalerContextFlags::kFakeGammaAndBoostContrast, nullptr);
+    fCache = SkGlyphCache::DetachCacheUsingPaint(fPaint, nullptr,
+                                                 SkScalerContextFlags::kFakeGammaAndBoostContrast,
+                                                 nullptr);
 
     SkPaint::Style  style = SkPaint::kFill_Style;
     sk_sp<SkPathEffect> pe;
diff --git a/src/core/SkScalerContext.cpp b/src/core/SkScalerContext.cpp
index d082232..f1ac9c1 100644
--- a/src/core/SkScalerContext.cpp
+++ b/src/core/SkScalerContext.cpp
@@ -5,6 +5,8 @@
  * found in the LICENSE file.
  */
 
+#include "SkGlyphCache.h"
+#include "SkPaint.h"
 #include "SkScalerContext.h"
 
 #include "SkAutoMalloc.h"
@@ -23,6 +25,8 @@
 #include "SkReadBuffer.h"
 #include "SkStroke.h"
 #include "SkStrokeRec.h"
+#include "SkSurfacePriv.h"
+#include "SkTextFormatParams.h"
 #include "SkWriteBuffer.h"
 
 void SkGlyph::toMask(SkMask* mask) const {
@@ -835,3 +839,418 @@
     }
     return c;
 }
+
+/*
+ *  Return the scalar with only limited fractional precision. Used to consolidate matrices
+ *  that vary only slightly when we create our key into the font cache, since the font scaler
+ *  typically returns the same looking resuts for tiny changes in the matrix.
+ */
+static SkScalar sk_relax(SkScalar x) {
+    SkScalar n = SkScalarRoundToScalar(x * 1024);
+    return n / 1024.0f;
+}
+
+static SkMask::Format compute_mask_format(const SkPaint& paint) {
+    uint32_t flags = paint.getFlags();
+
+    // Antialiasing being disabled trumps all other settings.
+    if (!(flags & SkPaint::kAntiAlias_Flag)) {
+        return SkMask::kBW_Format;
+    }
+
+    if (flags & SkPaint::kLCDRenderText_Flag) {
+        return SkMask::kLCD16_Format;
+    }
+
+    return SkMask::kA8_Format;
+}
+
+// Beyond this size, LCD doesn't appreciably improve quality, but it always
+// cost more RAM and draws slower, so we set a cap.
+#ifndef SK_MAX_SIZE_FOR_LCDTEXT
+    #define SK_MAX_SIZE_FOR_LCDTEXT    48
+#endif
+
+const SkScalar gMaxSize2ForLCDText = SK_MAX_SIZE_FOR_LCDTEXT * SK_MAX_SIZE_FOR_LCDTEXT;
+
+static bool too_big_for_lcd(const SkScalerContextRec& rec, bool checkPost2x2) {
+    if (checkPost2x2) {
+        SkScalar area = rec.fPost2x2[0][0] * rec.fPost2x2[1][1] -
+                        rec.fPost2x2[1][0] * rec.fPost2x2[0][1];
+        area *= rec.fTextSize * rec.fTextSize;
+        return area > gMaxSize2ForLCDText;
+    } else {
+        return rec.fTextSize > SK_MAX_SIZE_FOR_LCDTEXT;
+    }
+}
+
+// if linear-text is on, then we force hinting to be off (since that's sort of
+// the point of linear-text.
+static SkPaint::Hinting computeHinting(const SkPaint& paint) {
+    SkPaint::Hinting h = paint.getHinting();
+    if (paint.isLinearText()) {
+        h = SkPaint::kNo_Hinting;
+    }
+    return h;
+}
+
+// The only reason this is not file static is because it needs the context of SkScalerContext to
+// access SkPaint::computeLuminanceColor.
+void SkScalerContext::MakeRecAndEffects(const SkPaint& paint,
+                                        const SkSurfaceProps* surfaceProps,
+                                        const SkMatrix* deviceMatrix,
+                                        SkScalerContextFlags scalerContextFlags,
+                                        SkScalerContextRec* rec,
+                                        SkScalerContextEffects* effects) {
+    SkASSERT(deviceMatrix == nullptr || !deviceMatrix->hasPerspective());
+
+    SkTypeface* typeface = paint.getTypeface();
+    if (nullptr == typeface) {
+        typeface = SkTypeface::GetDefaultTypeface();
+    }
+    rec->fFontID = typeface->uniqueID();
+    rec->fTextSize = paint.getTextSize();
+    rec->fPreScaleX = paint.getTextScaleX();
+    rec->fPreSkewX  = paint.getTextSkewX();
+
+    bool checkPost2x2 = false;
+
+    if (deviceMatrix) {
+        const SkMatrix::TypeMask mask = deviceMatrix->getType();
+        if (mask & SkMatrix::kScale_Mask) {
+            rec->fPost2x2[0][0] = sk_relax(deviceMatrix->getScaleX());
+            rec->fPost2x2[1][1] = sk_relax(deviceMatrix->getScaleY());
+            checkPost2x2 = true;
+        } else {
+            rec->fPost2x2[0][0] = rec->fPost2x2[1][1] = SK_Scalar1;
+        }
+        if (mask & SkMatrix::kAffine_Mask) {
+            rec->fPost2x2[0][1] = sk_relax(deviceMatrix->getSkewX());
+            rec->fPost2x2[1][0] = sk_relax(deviceMatrix->getSkewY());
+            checkPost2x2 = true;
+        } else {
+            rec->fPost2x2[0][1] = rec->fPost2x2[1][0] = 0;
+        }
+    } else {
+        rec->fPost2x2[0][0] = rec->fPost2x2[1][1] = SK_Scalar1;
+        rec->fPost2x2[0][1] = rec->fPost2x2[1][0] = 0;
+    }
+
+    SkPaint::Style  style = paint.getStyle();
+    SkScalar        strokeWidth = paint.getStrokeWidth();
+
+    unsigned flags = 0;
+
+    if (paint.isFakeBoldText()) {
+#ifdef SK_USE_FREETYPE_EMBOLDEN
+        flags |= SkScalerContext::kEmbolden_Flag;
+#else
+        SkScalar fakeBoldScale = SkScalarInterpFunc(paint.getTextSize(),
+                                                    kStdFakeBoldInterpKeys,
+                                                    kStdFakeBoldInterpValues,
+                                                    kStdFakeBoldInterpLength);
+        SkScalar extra = paint.getTextSize() * fakeBoldScale;
+
+        if (style == SkPaint::kFill_Style) {
+            style = SkPaint::kStrokeAndFill_Style;
+            strokeWidth = extra;    // ignore paint's strokeWidth if it was "fill"
+        } else {
+            strokeWidth += extra;
+        }
+#endif
+    }
+
+    if (paint.isDevKernText()) {
+        flags |= SkScalerContext::kDevKernText_Flag;
+    }
+
+    if (style != SkPaint::kFill_Style && strokeWidth > 0) {
+        rec->fFrameWidth = strokeWidth;
+        rec->fMiterLimit = paint.getStrokeMiter();
+        rec->fStrokeJoin = SkToU8(paint.getStrokeJoin());
+        rec->fStrokeCap = SkToU8(paint.getStrokeCap());
+
+        if (style == SkPaint::kStrokeAndFill_Style) {
+            flags |= SkScalerContext::kFrameAndFill_Flag;
+        }
+    } else {
+        rec->fFrameWidth = 0;
+        rec->fMiterLimit = 0;
+        rec->fStrokeJoin = 0;
+        rec->fStrokeCap = 0;
+    }
+
+    rec->fMaskFormat = SkToU8(compute_mask_format(paint));
+
+    if (SkMask::kLCD16_Format == rec->fMaskFormat) {
+        if (too_big_for_lcd(*rec, checkPost2x2)) {
+            rec->fMaskFormat = SkMask::kA8_Format;
+            flags |= SkScalerContext::kGenA8FromLCD_Flag;
+        } else {
+            SkPixelGeometry geometry = surfaceProps
+                                       ? surfaceProps->pixelGeometry()
+                                       : SkSurfacePropsDefaultPixelGeometry();
+            switch (geometry) {
+                case kUnknown_SkPixelGeometry:
+                    // eeek, can't support LCD
+                    rec->fMaskFormat = SkMask::kA8_Format;
+                    flags |= SkScalerContext::kGenA8FromLCD_Flag;
+                    break;
+                case kRGB_H_SkPixelGeometry:
+                    // our default, do nothing.
+                    break;
+                case kBGR_H_SkPixelGeometry:
+                    flags |= SkScalerContext::kLCD_BGROrder_Flag;
+                    break;
+                case kRGB_V_SkPixelGeometry:
+                    flags |= SkScalerContext::kLCD_Vertical_Flag;
+                    break;
+                case kBGR_V_SkPixelGeometry:
+                    flags |= SkScalerContext::kLCD_Vertical_Flag;
+                    flags |= SkScalerContext::kLCD_BGROrder_Flag;
+                    break;
+            }
+        }
+    }
+
+    if (paint.isEmbeddedBitmapText()) {
+        flags |= SkScalerContext::kEmbeddedBitmapText_Flag;
+    }
+    if (paint.isSubpixelText()) {
+        flags |= SkScalerContext::kSubpixelPositioning_Flag;
+    }
+    if (paint.isAutohinted()) {
+        flags |= SkScalerContext::kForceAutohinting_Flag;
+    }
+    if (paint.isVerticalText()) {
+        flags |= SkScalerContext::kVertical_Flag;
+    }
+    if (paint.getFlags() & SkPaint::kGenA8FromLCD_Flag) {
+        flags |= SkScalerContext::kGenA8FromLCD_Flag;
+    }
+    rec->fFlags = SkToU16(flags);
+
+    // these modify fFlags, so do them after assigning fFlags
+    rec->setHinting(computeHinting(paint));
+
+    rec->setLuminanceColor(paint.computeLuminanceColor());
+
+    // For now always set the paint gamma equal to the device gamma.
+    // The math in SkMaskGamma can handle them being different,
+    // but it requires superluminous masks when
+    // Ex : deviceGamma(x) < paintGamma(x) and x is sufficiently large.
+    rec->setDeviceGamma(SK_GAMMA_EXPONENT);
+    rec->setPaintGamma(SK_GAMMA_EXPONENT);
+
+#ifdef SK_GAMMA_CONTRAST
+    rec->setContrast(SK_GAMMA_CONTRAST);
+#else
+    // A value of 0.5 for SK_GAMMA_CONTRAST appears to be a good compromise.
+    // With lower values small text appears washed out (though correctly so).
+    // With higher values lcd fringing is worse and the smoothing effect of
+    // partial coverage is diminished.
+    rec->setContrast(0.5f);
+#endif
+
+    rec->fReservedAlign = 0;
+
+    // Allow the fonthost to modify our rec before we use it as a key into the
+    // cache. This way if we're asking for something that they will ignore,
+    // they can modify our rec up front, so we don't create duplicate cache
+    // entries.
+    typeface->onFilterRec(rec);
+
+    if (!SkToBool(scalerContextFlags & SkScalerContextFlags::kFakeGamma)) {
+        rec->ignoreGamma();
+    }
+    if (!SkToBool(scalerContextFlags & SkScalerContextFlags::kBoostContrast)) {
+        rec->setContrast(0);
+    }
+
+    new (effects) SkScalerContextEffects{paint};
+    if (effects->fPathEffect) {
+        rec->fMaskFormat = SkMask::kA8_Format;  // force antialiasing when we do the scan conversion
+        // seems like we could support kLCD as well at this point...
+    }
+    if (effects->fMaskFilter) {
+        // force antialiasing with maskfilters
+        rec->fMaskFormat = SkMask::kA8_Format;
+        // Pre-blend is not currently applied to filtered text.
+        // The primary filter is blur, for which contrast makes no sense,
+        // and for which the destination guess error is more visible.
+        // Also, all existing users of blur have calibrated for linear.
+        rec->ignorePreBlend();
+    }
+
+    // If we're asking for A8, we force the colorlum to be gray, since that
+    // limits the number of unique entries, and the scaler will only look at
+    // the lum of one of them.
+    switch (rec->fMaskFormat) {
+        case SkMask::kLCD16_Format: {
+            // filter down the luminance color to a finite number of bits
+            SkColor color = rec->getLuminanceColor();
+            rec->setLuminanceColor(SkMaskGamma::CanonicalColor(color));
+            break;
+        }
+        case SkMask::kA8_Format: {
+            // filter down the luminance to a single component, since A8 can't
+            // use per-component information
+            SkColor color = rec->getLuminanceColor();
+            U8CPU lum = SkComputeLuminance(SkColorGetR(color),
+                                           SkColorGetG(color),
+                                           SkColorGetB(color));
+            // reduce to our finite number of bits
+            color = SkColorSetRGB(lum, lum, lum);
+            rec->setLuminanceColor(SkMaskGamma::CanonicalColor(color));
+            break;
+        }
+        case SkMask::kBW_Format:
+            // No need to differentiate gamma or apply contrast if we're BW
+            rec->ignorePreBlend();
+            break;
+    }
+}
+
+
+SkDescriptor* SkScalerContext::CreateDescriptorAndEffectsUsingPaint(
+    const SkPaint& paint, const SkSurfaceProps* surfaceProps,
+    SkScalerContextFlags scalerContextFlags,
+    const SkMatrix* deviceMatrix, SkAutoDescriptor* ad,
+    SkScalerContextEffects* effects) {
+
+    SkScalerContextRec rec;
+    MakeRecAndEffects(paint, surfaceProps, deviceMatrix, scalerContextFlags, &rec, effects);
+    return AutoDescriptorGivenRecAndEffects(rec, *effects, ad);
+}
+
+static size_t calculate_size_and_flatten(
+    const SkScalerContextRec& rec,
+    const SkScalerContextEffects& effects,
+    SkBinaryWriteBuffer* pathEffectBuffer,
+    SkBinaryWriteBuffer* maskFilterBuffer)
+{
+    size_t descSize = sizeof(rec);
+    int entryCount = 1;
+
+    if (effects.fPathEffect) {
+        effects.fPathEffect->flatten(*pathEffectBuffer);
+        descSize += pathEffectBuffer->bytesWritten();
+        entryCount += 1;
+    }
+    if (effects.fMaskFilter) {
+        effects.fMaskFilter->flatten(*maskFilterBuffer);
+        descSize += maskFilterBuffer->bytesWritten();
+        entryCount += 1;
+    }
+
+    descSize += SkDescriptor::ComputeOverhead(entryCount);
+    return descSize;
+}
+
+#ifdef SK_DEBUG
+  #define TEST_DESC
+#endif
+
+#ifdef TEST_DESC
+static void test_desc(const SkScalerContextRec& rec,
+                      const SkScalerContextEffects& effects,
+                      SkBinaryWriteBuffer* peBuffer,
+                      SkBinaryWriteBuffer* mfBuffer,
+                      const SkDescriptor* desc) {
+    // Check that we completely write the bytes in desc (our key), and that
+    // there are no uninitialized bytes. If there were, then we would get
+    // false-misses (or worse, false-hits) in our fontcache.
+    //
+    // We do this buy filling 2 others, one with 0s and the other with 1s
+    // and create those, and then check that all 3 are identical.
+    SkAutoDescriptor    ad1(desc->getLength());
+    SkAutoDescriptor    ad2(desc->getLength());
+    SkDescriptor*       desc1 = ad1.getDesc();
+    SkDescriptor*       desc2 = ad2.getDesc();
+
+    memset(desc1, 0x00, desc->getLength());
+    memset(desc2, 0xFF, desc->getLength());
+
+    desc1->init();
+    desc2->init();
+    desc1->addEntry(kRec_SkDescriptorTag, sizeof(rec), &rec);
+    desc2->addEntry(kRec_SkDescriptorTag, sizeof(rec), &rec);
+
+    auto add_flattenable = [](SkDescriptor* desc, uint32_t tag,
+                              SkBinaryWriteBuffer* buffer) {
+        buffer->writeToMemory(desc->addEntry(tag, buffer->bytesWritten(), nullptr));
+    };
+
+    if (effects.fPathEffect) {
+        add_flattenable(desc1, kPathEffect_SkDescriptorTag, peBuffer);
+        add_flattenable(desc2, kPathEffect_SkDescriptorTag, peBuffer);
+    }
+    if (effects.fMaskFilter) {
+        add_flattenable(desc1, kMaskFilter_SkDescriptorTag, mfBuffer);
+        add_flattenable(desc2, kMaskFilter_SkDescriptorTag, mfBuffer);
+    }
+
+    SkASSERT(desc->getLength() == desc1->getLength());
+    SkASSERT(desc->getLength() == desc2->getLength());
+    desc1->computeChecksum();
+    desc2->computeChecksum();
+    SkASSERT(!memcmp(desc, desc1, desc->getLength()));
+    SkASSERT(!memcmp(desc, desc2, desc->getLength()));
+}
+#endif
+
+void generate_descriptor(
+    const SkScalerContextRec& rec,
+    const SkScalerContextEffects& effects,
+    SkBinaryWriteBuffer* pathEffectBuffer,
+    SkBinaryWriteBuffer* maskFilterBuffer,
+    SkDescriptor* desc)
+{
+    desc->init();
+    desc->addEntry(kRec_SkDescriptorTag, sizeof(rec), &rec);
+
+    auto add = [&desc](uint32_t tag, SkBinaryWriteBuffer* buffer) {
+        buffer->writeToMemory(desc->addEntry(tag, buffer->bytesWritten(), nullptr));
+    };
+
+    if (effects.fPathEffect) {
+        add(kPathEffect_SkDescriptorTag, pathEffectBuffer);
+    }
+    if (effects.fMaskFilter) {
+        add(kMaskFilter_SkDescriptorTag, maskFilterBuffer);
+    }
+
+    desc->computeChecksum();
+#ifdef TEST_DESC
+    test_desc(rec, effects, pathEffectBuffer, maskFilterBuffer, desc);
+#endif
+}
+
+SkDescriptor* SkScalerContext::AutoDescriptorGivenRecAndEffects(
+    const SkScalerContextRec& rec,
+    const SkScalerContextEffects& effects,
+    SkAutoDescriptor* ad)
+{
+    SkBinaryWriteBuffer peBuffer, mfBuffer;
+
+    ad->reset(calculate_size_and_flatten(rec, effects, &peBuffer, &mfBuffer));
+
+    generate_descriptor(rec, effects, &peBuffer, &mfBuffer, ad->getDesc());
+
+    return ad->getDesc();
+}
+
+std::unique_ptr<SkDescriptor> SkScalerContext::DescriptorGivenRecAndEffects(
+    const SkScalerContextRec& rec,
+    const SkScalerContextEffects& effects)
+{
+    SkBinaryWriteBuffer peBuffer, mfBuffer;
+
+    auto desc = SkDescriptor::Alloc(calculate_size_and_flatten(rec, effects, &peBuffer, &mfBuffer));
+
+    generate_descriptor(rec, effects, &peBuffer, &mfBuffer, desc.get());
+
+    return desc;
+}
+
+
diff --git a/src/core/SkScalerContext.h b/src/core/SkScalerContext.h
index 90cac5d..05d1263 100644
--- a/src/core/SkScalerContext.h
+++ b/src/core/SkScalerContext.h
@@ -8,6 +8,8 @@
 #ifndef SkScalerContext_DEFINED
 #define SkScalerContext_DEFINED
 
+#include <memory>
+
 #include "SkGlyph.h"
 #include "SkMask.h"
 #include "SkMaskFilter.h"
@@ -17,6 +19,7 @@
 #include "SkTypeface.h"
 #include "SkWriteBuffer.h"
 
+class SkAutoDescriptor;
 class SkDescriptor;
 class SkMaskFilter;
 class SkPathEffect;
@@ -46,7 +49,6 @@
     kY_SkAxisAlignment
 };
 
-
 /*
  *  To allow this to be forward-declared, it must be its own typename, rather
  *  than a nested struct inside SkScalerContext (where it started).
@@ -280,11 +282,14 @@
                                   SkScalerContextRec* rec,
                                   SkScalerContextEffects* effects);
 
-    template <typename A>
-    static auto CreateDescriptorGivenRecAndEffects(
-            const SkScalerContextRec &rec,
-            const SkScalerContextEffects &effects,
-            A alloc) -> decltype(alloc((size_t)0));
+    static SkDescriptor* AutoDescriptorGivenRecAndEffects(
+        const SkScalerContextRec& rec,
+        const SkScalerContextEffects& effects,
+        SkAutoDescriptor* ad);
+
+    static std::unique_ptr<SkDescriptor> DescriptorGivenRecAndEffects(
+        const SkScalerContextRec& rec,
+        const SkScalerContextEffects& effects);
 
     static SkMaskGamma::PreBlend GetMaskPreBlend(const SkScalerContextRec& rec);
 
@@ -300,6 +305,12 @@
     */
     SkAxisAlignment computeAxisAlignmentForHText();
 
+    static SkDescriptor* CreateDescriptorAndEffectsUsingPaint(
+        const SkPaint& paint, const SkSurfaceProps* surfaceProps,
+        SkScalerContextFlags scalerContextFlags,
+        const SkMatrix* deviceMatrix, SkAutoDescriptor* ad,
+        SkScalerContextEffects* effects);
+
 protected:
     SkScalerContextRec fRec;
 
@@ -353,16 +364,6 @@
     void forceOffGenerateImageFromPath() { fGenerateImageFromPath = false; }
 
 private:
-    static size_t CalculateSizeAndFlatten(const SkScalerContextRec& rec,
-                                          const SkScalerContextEffects& effects,
-                                          SkBinaryWriteBuffer* pathEffectBuffer,
-                                          SkBinaryWriteBuffer* maskFilterBuffer);
-    static void GenerateDescriptor(const SkScalerContextRec& rec,
-                                   const SkScalerContextEffects& effects,
-                                   SkBinaryWriteBuffer* pathEffectBuffer,
-                                   SkBinaryWriteBuffer* maskFilterBuffer,
-                                   SkDescriptor* desc);
-
     friend class SkRandomScalerContext; // For debug purposes
 
     // never null
@@ -389,22 +390,6 @@
     const SkMaskGamma::PreBlend fPreBlendForFilter;
 };
 
-template <typename A>
-inline auto SkScalerContext::CreateDescriptorGivenRecAndEffects(
-        const SkScalerContextRec &rec,
-        const SkScalerContextEffects &effects,
-        A alloc) -> decltype(alloc((size_t)0))  {
-
-    SkBinaryWriteBuffer peBuffer, mfBuffer;
-
-    auto desc = alloc(CalculateSizeAndFlatten(rec, effects, &peBuffer, &mfBuffer));
-
-    GenerateDescriptor(rec, effects, &peBuffer, &mfBuffer, &(*desc));
-
-    return desc;
-}
-
-
 #define kRec_SkDescriptorTag            SkSetFourByteTag('s', 'r', 'e', 'c')
 #define kPathEffect_SkDescriptorTag     SkSetFourByteTag('p', 't', 'h', 'e')
 #define kMaskFilter_SkDescriptorTag     SkSetFourByteTag('m', 's', 'k', 'f')
diff --git a/src/core/SkTypeface.cpp b/src/core/SkTypeface.cpp
index b47f8c3..d3191e2d 100644
--- a/src/core/SkTypeface.cpp
+++ b/src/core/SkTypeface.cpp
@@ -341,16 +341,15 @@
 
     SkScalerContextRec rec;
     SkScalerContextEffects effects;
+
     SkScalerContext::MakeRecAndEffects(
         paint, nullptr, nullptr, SkScalerContextFlags::kNone, &rec, &effects);
 
-    SkAutoDescriptor ad(sizeof(rec) + SkDescriptor::ComputeOverhead(1));
-    SkDescriptor*    desc = ad.getDesc();
-    desc->init();
-    desc->addEntry(kRec_SkDescriptorTag, sizeof(rec), &rec);
-
+    SkAutoDescriptor ad;
     SkScalerContextEffects noeffects;
-    std::unique_ptr<SkScalerContext> ctx = this->createScalerContext(noeffects, desc, true);
+    SkScalerContext::AutoDescriptorGivenRecAndEffects(rec, noeffects, &ad);
+
+    std::unique_ptr<SkScalerContext> ctx = this->createScalerContext(noeffects, ad.getDesc(), true);
     if (!ctx) {
         return false;
     }
diff --git a/src/gpu/text/GrAtlasTextBlob.cpp b/src/gpu/text/GrAtlasTextBlob.cpp
index 7fce4ba..887addd 100644
--- a/src/gpu/text/GrAtlasTextBlob.cpp
+++ b/src/gpu/text/GrAtlasTextBlob.cpp
@@ -59,7 +59,8 @@
     SkAutoDescriptor* desc = run->fOverrideDescriptor.get() ? run->fOverrideDescriptor.get() :
                                                               &run->fDescriptor;
     SkScalerContextEffects effects;
-    skPaint.getScalerContextDescriptor(&effects, desc, &props, scalerContextFlags, viewMatrix);
+    SkScalerContext::CreateDescriptorAndEffectsUsingPaint(
+        skPaint, &props, scalerContextFlags, viewMatrix, desc, &effects);
     run->fTypeface.reset(SkSafeRef(skPaint.getTypeface()));
     run->fPathEffect = sk_ref_sp(effects.fPathEffect);
     run->fMaskFilter = sk_ref_sp(effects.fMaskFilter);
diff --git a/src/gpu/text/GrAtlasTextContext.cpp b/src/gpu/text/GrAtlasTextContext.cpp
index 41c4646..1dce4e0 100644
--- a/src/gpu/text/GrAtlasTextContext.cpp
+++ b/src/gpu/text/GrAtlasTextContext.cpp
@@ -602,8 +602,8 @@
     SkScalerContextEffects effects;
     // We apply the fake-gamma by altering the distance in the shader, so we ignore the
     // passed-in scaler context flags. (It's only used when we fall-back to bitmap text).
-    skPaint.getScalerContextDescriptor(&effects, &desc, &props, SkScalerContextFlags::kNone,
-                                       nullptr);
+    SkScalerContext::CreateDescriptorAndEffectsUsingPaint(
+        skPaint, &props, SkScalerContextFlags::kNone, nullptr, &desc, &effects);
     SkGlyphCache* origPaintCache =
             SkGlyphCache::DetachCache(skPaint.getTypeface(), effects, desc.getDesc());
 
diff --git a/src/gpu/text/GrStencilAndCoverTextContext.cpp b/src/gpu/text/GrStencilAndCoverTextContext.cpp
index 2170f0a..5c45f22 100644
--- a/src/gpu/text/GrStencilAndCoverTextContext.cpp
+++ b/src/gpu/text/GrStencilAndCoverTextContext.cpp
@@ -605,8 +605,9 @@
 
 SkGlyphCache* GrStencilAndCoverTextContext::TextRun::getGlyphCache() const {
     if (!fDetachedGlyphCache) {
-        fDetachedGlyphCache = fFont.detachCache(nullptr, SkScalerContextFlags::kNone,
-                                                nullptr);
+        fDetachedGlyphCache = SkGlyphCache::DetachCacheUsingPaint(fFont, nullptr,
+                                                                  SkScalerContextFlags::kNone,
+                                                                  nullptr);
     }
     return fDetachedGlyphCache;
 }