Add GPU perspective support for color emoji

Will also warp orthogonal bitmaps to handle skew and rotate transforms.

Bug: skia:7985
Change-Id: Ib0d5476dd68603354be90c8d404f1e5140d63a0c
Reviewed-on: https://skia-review.googlesource.com/129480
Commit-Queue: Jim Van Verth <jvanverth@google.com>
Reviewed-by: Brian Salomon <bsalomon@google.com>
diff --git a/src/gpu/effects/GrBitmapTextGeoProc.cpp b/src/gpu/effects/GrBitmapTextGeoProc.cpp
index 1412679..116e223 100644
--- a/src/gpu/effects/GrBitmapTextGeoProc.cpp
+++ b/src/gpu/effects/GrBitmapTextGeoProc.cpp
@@ -53,7 +53,7 @@
         }
 
         // Setup position
-        this->writeOutputPosition(vertBuilder, gpArgs, btgp.inPosition()->fName);
+        gpArgs->fPositionVar = btgp.inPosition()->asShaderVar();
 
         // emit transforms
         this->emitTransforms(vertBuilder,
@@ -102,7 +102,7 @@
                               GrProcessorKeyBuilder* b) {
         const GrBitmapTextGeoProc& btgp = proc.cast<GrBitmapTextGeoProc>();
         uint32_t key = 0;
-        key |= (btgp.usesLocalCoords() && btgp.localMatrix().hasPerspective()) ? 0x1 : 0x0;
+        key |= btgp.usesW() ? 0x1 : 0x0;
         key |= btgp.maskFormat() << 1;
         b->add32(key);
         b->add32(btgp.numTextureSamplers());
@@ -124,16 +124,20 @@
                                          const sk_sp<GrTextureProxy>* proxies,
                                          int numActiveProxies,
                                          const GrSamplerState& params, GrMaskFormat format,
-                                         const SkMatrix& localMatrix, bool usesLocalCoords)
+                                         const SkMatrix& localMatrix, bool usesW)
         : INHERITED(kGrBitmapTextGeoProc_ClassID)
         , fColor(color)
         , fLocalMatrix(localMatrix)
-        , fUsesLocalCoords(usesLocalCoords)
+        , fUsesW(usesW)
         , fInColor(nullptr)
         , fMaskFormat(format) {
     SkASSERT(numActiveProxies <= kMaxTextures);
 
-    fInPosition = &this->addVertexAttrib("inPosition", kFloat2_GrVertexAttribType);
+    if (usesW) {
+        fInPosition = &this->addVertexAttrib("inPosition", kFloat3_GrVertexAttribType);
+    } else {
+        fInPosition = &this->addVertexAttrib("inPosition", kFloat2_GrVertexAttribType);
+    }
 
     bool hasVertexColor = kA8_GrMaskFormat == fMaskFormat ||
                           kA565_GrMaskFormat == fMaskFormat;
diff --git a/src/gpu/effects/GrBitmapTextGeoProc.h b/src/gpu/effects/GrBitmapTextGeoProc.h
index 3b95f76..40ba855 100644
--- a/src/gpu/effects/GrBitmapTextGeoProc.h
+++ b/src/gpu/effects/GrBitmapTextGeoProc.h
@@ -26,10 +26,10 @@
                                            const sk_sp<GrTextureProxy>* proxies,
                                            int numActiveProxies,
                                            const GrSamplerState& p, GrMaskFormat format,
-                                           const SkMatrix& localMatrix, bool usesLocalCoords) {
+                                           const SkMatrix& localMatrix, bool usesW) {
         return sk_sp<GrGeometryProcessor>(
             new GrBitmapTextGeoProc(color, proxies, numActiveProxies, p, format,
-                                    localMatrix, usesLocalCoords));
+                                    localMatrix, usesW));
     }
 
     ~GrBitmapTextGeoProc() override {}
@@ -43,7 +43,7 @@
     GrColor color() const { return fColor; }
     bool hasVertexColor() const { return SkToBool(fInColor); }
     const SkMatrix& localMatrix() const { return fLocalMatrix; }
-    bool usesLocalCoords() const { return fUsesLocalCoords; }
+    bool usesW() const { return fUsesW; }
 
     void addNewProxies(const sk_sp<GrTextureProxy>*, int numActiveProxies, const GrSamplerState&);
 
@@ -56,11 +56,11 @@
 
     GrBitmapTextGeoProc(GrColor, const sk_sp<GrTextureProxy>* proxies, int numProxies,
                         const GrSamplerState& params, GrMaskFormat format,
-                        const SkMatrix& localMatrix, bool usesLocalCoords);
+                        const SkMatrix& localMatrix, bool usesW);
 
     GrColor          fColor;
     SkMatrix         fLocalMatrix;
-    bool             fUsesLocalCoords;
+    bool             fUsesW;
     TextureSampler   fTextureSamplers[kMaxTextures];
     const Attribute* fInPosition;
     const Attribute* fInColor;
diff --git a/src/gpu/ops/GrAtlasTextOp.cpp b/src/gpu/ops/GrAtlasTextOp.cpp
index 99af581..bb6675a 100644
--- a/src/gpu/ops/GrAtlasTextOp.cpp
+++ b/src/gpu/ops/GrAtlasTextOp.cpp
@@ -48,6 +48,8 @@
             fDFGPFlags |=
                     (kLCDBGRDistanceField_MaskType == fMaskType) ? kBGR_DistanceFieldEffectFlag : 0;
         }
+
+        fNeedsGlyphTransform = true;
     }
 }
 
@@ -239,21 +241,20 @@
     FlushInfo flushInfo;
     flushInfo.fPipeline =
             target->makePipeline(fSRGBFlags, std::move(fProcessors), target->detachAppliedClip());
-    SkDEBUGCODE(bool dfPerspective = false);
+    bool vmPerspective = fGeoData[0].fViewMatrix.hasPerspective();
     if (this->usesDistanceFields()) {
         flushInfo.fGeometryProcessor = this->setupDfProcessor(proxies, numActiveProxies);
-        SkDEBUGCODE(dfPerspective = fGeoData[0].fViewMatrix.hasPerspective());
     } else {
-        GrSamplerState samplerState = fHasScaledGlyphs ? GrSamplerState::ClampBilerp()
-                                                       : GrSamplerState::ClampNearest();
+        GrSamplerState samplerState = fNeedsGlyphTransform ? GrSamplerState::ClampBilerp()
+                                                           : GrSamplerState::ClampNearest();
         flushInfo.fGeometryProcessor = GrBitmapTextGeoProc::Make(
             this->color(), proxies, numActiveProxies, samplerState, maskFormat,
-            localMatrix, this->usesLocalCoords());
+            localMatrix, vmPerspective);
     }
 
     flushInfo.fGlyphsToFlush = 0;
     size_t vertexStride = flushInfo.fGeometryProcessor->getVertexStride();
-    SkASSERT(vertexStride == GrAtlasTextBlob::GetVertexStride(maskFormat, dfPerspective));
+    SkASSERT(vertexStride == GrAtlasTextBlob::GetVertexStride(maskFormat, vmPerspective));
 
     int glyphCount = this->numGlyphs();
     const GrBuffer* vertexBuffer;
@@ -291,11 +292,11 @@
             if (args.fClipRect.isEmpty()) {
                 memcpy(currVertex, result.fFirstVertex, vertexBytes);
             } else {
-                SkASSERT(!dfPerspective);
+                SkASSERT(!vmPerspective);
                 clip_quads(args.fClipRect, currVertex, result.fFirstVertex, vertexStride,
                            result.fGlyphsRegenerated);
             }
-            if (this->usesDistanceFields() && !args.fViewMatrix.isIdentity()) {
+            if (fNeedsGlyphTransform && !args.fViewMatrix.isIdentity()) {
                 // We always do the distance field view matrix transformation after copying rather
                 // than during blob vertex generation time in the blob as handling successive
                 // arbitrary transformations would be complicated and accumulate error.
@@ -346,8 +347,8 @@
                     proxies, numActiveProxies, GrSamplerState::ClampBilerp());
             }
         } else {
-            GrSamplerState samplerState = fHasScaledGlyphs ? GrSamplerState::ClampBilerp()
-                                                           : GrSamplerState::ClampNearest();
+            GrSamplerState samplerState = fNeedsGlyphTransform ? GrSamplerState::ClampBilerp()
+                                                               : GrSamplerState::ClampNearest();
             reinterpret_cast<GrBitmapTextGeoProc*>(gp)->addNewProxies(proxies, numActiveProxies,
                                                                       samplerState);
         }
@@ -385,6 +386,15 @@
         return false;
     }
 
+    if (fNeedsGlyphTransform != that->fNeedsGlyphTransform) {
+        return false;
+    }
+
+    if (fNeedsGlyphTransform &&
+        (thisFirstMatrix.hasPerspective() != thatFirstMatrix.hasPerspective())) {
+        return false;
+    }
+
     if (this->usesDistanceFields()) {
         if (fDFGPFlags != that->fDFGPFlags) {
             return false;
@@ -398,9 +408,6 @@
             return false;
         }
 
-        if (fHasScaledGlyphs != that->fHasScaledGlyphs) {
-            return false;
-        }
     }
 
     // Keep the batch vertex buffer size below 32K so we don't have to create a special one
diff --git a/src/gpu/ops/GrAtlasTextOp.h b/src/gpu/ops/GrAtlasTextOp.h
index 67474be..dd24c1a 100644
--- a/src/gpu/ops/GrAtlasTextOp.h
+++ b/src/gpu/ops/GrAtlasTextOp.h
@@ -42,7 +42,7 @@
 
     static std::unique_ptr<GrAtlasTextOp> MakeBitmap(
                                 GrPaint&& paint, GrMaskFormat maskFormat, int glyphCount,
-                                bool hasScaledGlyphs) {
+                                bool needsTransform) {
         std::unique_ptr<GrAtlasTextOp> op(new GrAtlasTextOp(std::move(paint)));
 
         switch (maskFormat) {
@@ -59,7 +59,7 @@
         op->fNumGlyphs = glyphCount;
         op->fGeoCount = 1;
         op->fLuminanceColor = 0;
-        op->fHasScaledGlyphs = hasScaledGlyphs;
+        op->fNeedsGlyphTransform = needsTransform;
         return op;
     }
 
@@ -186,7 +186,7 @@
         uint32_t fUsesLocalCoords : 1;
         uint32_t fCanCombineOnTouchOrOverlap : 1;
         uint32_t fUseGammaCorrectDistanceTable : 1;
-        uint32_t fHasScaledGlyphs : 1;
+        uint32_t fNeedsGlyphTransform : 1;
     };
     int fGeoCount;
     int fNumGlyphs;
diff --git a/src/gpu/ops/GrSmallPathRenderer.cpp b/src/gpu/ops/GrSmallPathRenderer.cpp
index 48de75a..cbf1f68 100644
--- a/src/gpu/ops/GrSmallPathRenderer.cpp
+++ b/src/gpu/ops/GrSmallPathRenderer.cpp
@@ -343,7 +343,7 @@
             flushInfo.fGeometryProcessor = GrBitmapTextGeoProc::Make(
                     this->color(), fAtlas->getProxies(), fAtlas->numActivePages(),
                     GrSamplerState::ClampNearest(), kA8_GrMaskFormat, invert,
-                    fHelper.usesLocalCoords());
+                    false);
         }
 
         // allocate vertices
diff --git a/src/gpu/text/GrAtlasTextBlob.cpp b/src/gpu/text/GrAtlasTextBlob.cpp
index 611abf7..f508c1f 100644
--- a/src/gpu/text/GrAtlasTextBlob.cpp
+++ b/src/gpu/text/GrAtlasTextBlob.cpp
@@ -113,10 +113,8 @@
     run.fInitialized = true;
 
     bool hasW = subRun->hasWCoord();
-    // DF glyphs drawn in perspective must always have a w coord.
-    SkASSERT(hasW || !subRun->drawAsDistanceFields() || !fInitialViewMatrix.hasPerspective());
-    // Non-DF glyphs should never have a w coord.
-    SkASSERT(!hasW || subRun->drawAsDistanceFields());
+    // glyphs drawn in perspective must always have a w coord.
+    SkASSERT(hasW || !fInitialViewMatrix.hasPerspective());
 
     size_t vertexStride = GetVertexStride(format, hasW);
 
@@ -153,7 +151,7 @@
     subRun->appendVertices(vertexStride);
     fGlyphs[subRun->glyphEndIndex()] = glyph;
     subRun->glyphAppended();
-    subRun->setHasScaledGlyphs(SK_Scalar1 != scale);
+    subRun->setNeedsTransform(!preTransformed);
 }
 
 void GrAtlasTextBlob::appendPathGlyph(int runIndex, const SkPath& path, SkScalar x, SkScalar y,
@@ -263,7 +261,7 @@
                 props, info.isAntiAliased(), info.hasUseLCDText());
     } else {
         op = GrAtlasTextOp::MakeBitmap(std::move(grPaint), format, glyphCount,
-                                       info.hasScaledGlyphs());
+                                       info.needsTransform());
     }
     GrAtlasTextOp::Geometry& geometry = op->geometry();
     geometry.fViewMatrix = viewMatrix;
@@ -352,9 +350,9 @@
             SkRect rtBounds = SkRect::MakeWH(target->width(), target->height());
             SkRRect clipRRect;
             GrAA aa;
-            // We can clip geometrically if we're not using SDFs or scaled glyphs,
+            // We can clip geometrically if we're not using SDFs or transformed glyphs,
             // and we have an axis-aligned rectangular non-AA clip
-            if (!info.drawAsDistanceFields() && !info.hasScaledGlyphs() &&
+            if (!info.drawAsDistanceFields() && !info.needsTransform() &&
                 clip.isRRect(rtBounds, &clipRRect, &aa) &&
                 clipRRect.isRect() && GrAA::kNo == aa) {
                 skipClip = true;
diff --git a/src/gpu/text/GrAtlasTextBlob.h b/src/gpu/text/GrAtlasTextBlob.h
index e3b7d40..2c656ad 100644
--- a/src/gpu/text/GrAtlasTextBlob.h
+++ b/src/gpu/text/GrAtlasTextBlob.h
@@ -149,6 +149,13 @@
         subRun.setHasWCoord(hasWCoord);
     }
 
+    // sets the last subrun of runIndex to use w values
+    void setSubRunHasW(int runIndex, bool hasWCoord) {
+        Run& run = fRuns[runIndex];
+        Run::SubRunInfo& subRun = run.fSubRunInfo.back();
+        subRun.setHasWCoord(hasWCoord);
+    }
+
     void setRunPaintFlags(int runIndex, uint16_t paintFlags) {
         fRuns[runIndex].fPaintFlags = paintFlags & Run::kPaintFlagsMask;
     }
@@ -188,15 +195,14 @@
     void appendPathGlyph(int runIndex, const SkPath& path,
                          SkScalar x, SkScalar y, SkScalar scale, bool preTransformed);
 
-    static size_t GetVertexStride(GrMaskFormat maskFormat, bool isDistanceFieldWithWCoord) {
+    static size_t GetVertexStride(GrMaskFormat maskFormat, bool hasWCoord) {
         switch (maskFormat) {
             case kA8_GrMaskFormat:
-                return isDistanceFieldWithWCoord ? kGrayTextDFPerspectiveVASize : kGrayTextVASize;
+                return hasWCoord ? kGrayTextDFPerspectiveVASize : kGrayTextVASize;
             case kARGB_GrMaskFormat:
-                SkASSERT(!isDistanceFieldWithWCoord);
-                return kColorTextVASize;
+                return hasWCoord ? kColorTextPerspectiveVASize : kColorTextVASize;
             default:
-                SkASSERT(!isDistanceFieldWithWCoord);
+                SkASSERT(!hasWCoord);
                 return kLCDTextVASize;
         }
     }
@@ -244,6 +250,7 @@
 
     // position + local coord
     static const size_t kColorTextVASize = sizeof(SkPoint) + sizeof(SkIPoint16);
+    static const size_t kColorTextPerspectiveVASize = sizeof(SkPoint3) + sizeof(SkIPoint16);
     static const size_t kGrayTextVASize = sizeof(SkPoint) + sizeof(GrColor) + sizeof(SkIPoint16);
     static const size_t kGrayTextDFPerspectiveVASize =
             sizeof(SkPoint3) + sizeof(GrColor) + sizeof(SkIPoint16);
@@ -432,11 +439,11 @@
                 fFlags  = hasW ? (fFlags | kHasWCoord_Flag) : fFlags & ~kHasWCoord_Flag;
             }
             bool hasWCoord() const { return SkToBool(fFlags & kHasWCoord_Flag); }
-            void setHasScaledGlyphs(bool hasScaledGlyphs) {
-                fFlags  = hasScaledGlyphs ? (fFlags | kHasScaledGlyphs_Flag)
-                                          : fFlags & ~kHasScaledGlyphs_Flag;
+            void setNeedsTransform(bool needsTransform) {
+                fFlags  = needsTransform ? (fFlags | kNeedsTransform_Flag)
+                                          : fFlags & ~kNeedsTransform_Flag;
             }
-            bool hasScaledGlyphs() const { return SkToBool(fFlags & kHasScaledGlyphs_Flag); }
+            bool needsTransform() const { return SkToBool(fFlags & kNeedsTransform_Flag); }
 
         private:
             enum Flag {
@@ -444,7 +451,7 @@
                 kUseLCDText_Flag = 0x02,
                 kAntiAliased_Flag = 0x04,
                 kHasWCoord_Flag = 0x08,
-                kHasScaledGlyphs_Flag = 0x10
+                kNeedsTransform_Flag = 0x10
             };
 
             GrDrawOpAtlas::BulkUseTokenUpdater fBulkUseToken;
diff --git a/src/gpu/text/GrAtlasTextBlobVertexRegenerator.cpp b/src/gpu/text/GrAtlasTextBlobVertexRegenerator.cpp
index e2d4fe1..a0a5f4d 100644
--- a/src/gpu/text/GrAtlasTextBlobVertexRegenerator.cpp
+++ b/src/gpu/text/GrAtlasTextBlobVertexRegenerator.cpp
@@ -282,7 +282,7 @@
                 code = strike->addGlyphToAtlas(fResourceProvider, fUploadTarget, fGlyphCache,
                                               fFullAtlasManager, glyph,
                                               fLazyCache->get(), fSubRun->maskFormat(),
-                                              fSubRun->hasScaledGlyphs());
+                                              fSubRun->needsTransform());
                 if (GrDrawOpAtlas::ErrorCode::kError == code) {
                     // Something horrible has happened - drop the op
                     return false;
diff --git a/src/gpu/text/GrAtlasTextContext.cpp b/src/gpu/text/GrAtlasTextContext.cpp
index 1f06cfe..6d62d80 100644
--- a/src/gpu/text/GrAtlasTextContext.cpp
+++ b/src/gpu/text/GrAtlasTextContext.cpp
@@ -390,7 +390,7 @@
                                                         glyph, SkScalarFloorToScalar(position.fX),
                                                         SkScalarFloorToScalar(position.fY),
                                                         paint.filteredPremulColor(), cache.get(),
-                                                        SK_Scalar1);
+                                                        SK_Scalar1, false);
                                      });
 }
 
@@ -428,7 +428,7 @@
                 BmpAppendGlyph(blob, runIndex, glyphCache, &currStrike, glyph,
                                SkScalarFloorToScalar(position.fX),
                                SkScalarFloorToScalar(position.fY),
-                               paint.filteredPremulColor(), cache.get(), SK_Scalar1);
+                               paint.filteredPremulColor(), cache.get(), SK_Scalar1, false);
             });
 }
 
@@ -529,7 +529,7 @@
                                         sk_sp<GrTextStrike>* strike,
                                         const SkGlyph& skGlyph, SkScalar sx, SkScalar sy,
                                         GrColor color, SkGlyphCache* skGlyphCache,
-                                        SkScalar textRatio) {
+                                        SkScalar textRatio, bool needsTransform) {
     if (!*strike) {
         *strike = grGlyphCache->getStrike(skGlyphCache);
     }
@@ -559,7 +559,7 @@
     SkRect glyphRect = SkRect::MakeXYWH(sx + dx, sy + dy, width, height);
 
     blob->appendGlyph(runIndex, glyphRect, color, *strike, glyph, skGlyphCache, skGlyph, sx, sy,
-                      textRatio, true);
+                      textRatio, !needsTransform);
 }
 
 void GrAtlasTextContext::SanitizeOptions(Options* options) {
@@ -847,38 +847,23 @@
 
 void GrAtlasTextContext::FallbackTextHelper::appendText(const SkGlyph& glyph, int count,
                                                         const char* text, SkPoint glyphPos) {
-    // can't handle perspective at the moment
-    if (fViewMatrix.hasPerspective()) {
-        return;
-    }
-
-    SkScalar maxDim;
-    if (fViewMatrix.isScaleTranslate()) {
-        maxDim = SkTMax(glyph.fWidth, glyph.fHeight)*fTextRatio;
-    } else {
-        SkRect glyphRect;
-        glyphRect.setXYWH(glyph.fLeft, glyph.fTop, glyph.fWidth, glyph.fHeight);
-        fViewMatrix.mapRect(&glyphRect);
-        maxDim = SkTMax(glyphRect.width(), glyphRect.height());
-        maxDim *= fTextRatio/fMaxScale;
-    }
-    if (!fUseScaledFallback) {
-        SkScalar scaledGlyphSize = maxDim * fMaxScale;
-        if (!fViewMatrix.hasPerspective() && scaledGlyphSize > fMaxTextSize) {
-            fUseScaledFallback = true;
+    SkScalar maxDim = SkTMax(glyph.fWidth, glyph.fHeight)*fTextRatio;
+    if (!fUseTransformedFallback) {
+        if (!fViewMatrix.isScaleTranslate() || maxDim*fMaxScale > fMaxTextSize) {
+            fUseTransformedFallback = true;
             fMaxTextSize -= 2;    // Subtract 2 to account for the bilerp pad around the glyph
         }
     }
 
     fFallbackTxt.append(count, text);
-    if (fUseScaledFallback) {
+    if (fUseTransformedFallback) {
         // If there's a glyph in the font that's particularly large, it's possible
         // that fScaledFallbackTextSize may end up minimizing too much. We'd rather skip
         // that glyph than make the others blurry, so we set a minimum size of half the
         // maximum text size to avoid this case.
-        SkScalar glyphTextSize = SkTMax(SkScalarFloorToScalar(fMaxTextSize*fTextSize / maxDim),
+        SkScalar glyphTextSize = SkTMax(SkScalarFloorToScalar(fTextSize * fMaxTextSize/maxDim),
                                         0.5f*fMaxTextSize);
-        fScaledFallbackTextSize = SkTMin(glyphTextSize, fScaledFallbackTextSize);
+        fTransformedFallbackTextSize = SkTMin(glyphTextSize, fTransformedFallbackTextSize);
     }
     *fFallbackPos.append() = glyphPos;
 }
@@ -889,31 +874,22 @@
                                                       const GrTextUtils::Paint& paint,
                                                       SkScalerContextFlags scalerContextFlags) {
     if (fFallbackTxt.count()) {
-        if (fViewMatrix.hasPerspective()) {
-            // TODO: handle perspective
-            return;
-        }
-
         blob->initOverride(runIndex);
         blob->setHasBitmap();
+        blob->setSubRunHasW(runIndex, fViewMatrix.hasPerspective());
         SkExclusiveStrikePtr cache;
         const SkPaint& skPaint = paint.skPaint();
         SkPaint::GlyphCacheProc glyphCacheProc =
             SkPaint::GetGlyphCacheProc(skPaint.getTextEncoding(), true);
         SkColor textColor = paint.filteredPremulColor();
         SkScalar textRatio = SK_Scalar1;
-        if (fUseScaledFallback) {
+        if (fUseTransformedFallback) {
             // Set up paint and matrix to scale glyphs
             SkPaint scaledPaint(skPaint);
-            scaledPaint.setTextSize(fScaledFallbackTextSize);
-            // remove maxScale from viewMatrix and move it into textRatio
-            // this keeps the base glyph size consistent regardless of matrix scale
-            SkMatrix modMatrix(fViewMatrix);
-            SkScalar invScale = SkScalarInvert(fMaxScale);
-            modMatrix.preScale(invScale, invScale);
-            textRatio = fTextSize * fMaxScale / fScaledFallbackTextSize;
+            scaledPaint.setTextSize(fTransformedFallbackTextSize);
+            textRatio = fTextSize / fTransformedFallbackTextSize;
             cache = blob->setupCache(runIndex, props, scalerContextFlags, scaledPaint,
-                                     &modMatrix);
+                                     &SkMatrix::I());
         } else {
             cache = blob->setupCache(runIndex, props, scalerContextFlags, paint,
                                      &fViewMatrix);
@@ -925,14 +901,14 @@
         SkPoint* glyphPos = fFallbackPos.begin();
         while (text < stop) {
             const SkGlyph& glyph = glyphCacheProc(cache.get(), &text);
-            fViewMatrix.mapPoints(glyphPos, 1);
-            if (!fUseScaledFallback) {
+            if (!fUseTransformedFallback) {
+                fViewMatrix.mapPoints(glyphPos, 1);
                 glyphPos->fX = SkScalarFloorToScalar(glyphPos->fX);
                 glyphPos->fY = SkScalarFloorToScalar(glyphPos->fY);
             }
             GrAtlasTextContext::BmpAppendGlyph(blob, runIndex, glyphCache, &currStrike, glyph,
                                                glyphPos->fX, glyphPos->fY, textColor,
-                                               cache.get(), textRatio);
+                                               cache.get(), textRatio, fUseTransformedFallback);
             glyphPos++;
         }
     }
diff --git a/src/gpu/text/GrAtlasTextContext.h b/src/gpu/text/GrAtlasTextContext.h
index e2531b3..aa6557c 100644
--- a/src/gpu/text/GrAtlasTextContext.h
+++ b/src/gpu/text/GrAtlasTextContext.h
@@ -85,8 +85,8 @@
             , fTextSize(pathPaint.getTextSize())
             , fMaxTextSize(glyphCache->getGlyphSizeLimit())
             , fTextRatio(textRatio)
-            , fScaledFallbackTextSize(fMaxTextSize)
-            , fUseScaledFallback(false) {
+            , fTransformedFallbackTextSize(fMaxTextSize)
+            , fUseTransformedFallback(false) {
             fMaxScale = viewMatrix.getMaxScale();
         }
 
@@ -102,9 +102,9 @@
         SkScalar fTextSize;
         SkScalar fMaxTextSize;
         SkScalar fTextRatio;
-        SkScalar fScaledFallbackTextSize;
+        SkScalar fTransformedFallbackTextSize;
         SkScalar fMaxScale;
-        bool fUseScaledFallback;
+        bool fUseTransformedFallback;
     };
 
     // sets up the descriptor on the blob and returns a detached cache.  Client must attach
@@ -184,7 +184,7 @@
 
     static void BmpAppendGlyph(GrAtlasTextBlob*, int runIndex, GrGlyphCache*,
                                sk_sp<GrTextStrike>*, const SkGlyph&, SkScalar sx, SkScalar sy,
-                               GrColor color, SkGlyphCache*, SkScalar textRatio);
+                               GrColor color, SkGlyphCache*, SkScalar textRatio, bool needsXform);
 
     static void DfAppendGlyph(GrAtlasTextBlob*, int runIndex, GrGlyphCache*,
                               sk_sp<GrTextStrike>*, const SkGlyph&, SkScalar sx, SkScalar sy,