Delay SkPaint->GrPaint conversion in text rendering.

This fixes an issue where color filters aren't correctly applied to color glyphs. Instead we apply the filter to the SkPaint's color which is correct for mask glyphs only.

Add color filter and alpha + various effects to coloremoji gm

Change-Id: If77dece71d43468fec65499857eaaaedb56428e9
Reviewed-on: https://skia-review.googlesource.com/6891
Commit-Queue: Brian Salomon <bsalomon@google.com>
Reviewed-by: Jim Van Verth <jvanverth@google.com>
diff --git a/src/gpu/text/GrAtlasTextBlob.cpp b/src/gpu/text/GrAtlasTextBlob.cpp
index 5e3b4bf..321c4a6 100644
--- a/src/gpu/text/GrAtlasTextBlob.cpp
+++ b/src/gpu/text/GrAtlasTextBlob.cpp
@@ -6,7 +6,6 @@
  */
 
 #include "GrAtlasTextBlob.h"
-
 #include "GrBlurUtils.h"
 #include "GrContext.h"
 #include "GrPipelineBuilder.h"
@@ -169,14 +168,14 @@
     fBigGlyphs.push_back(GrAtlasTextBlob::BigGlyph(*glyph->fPath, x, y, scale, treatAsBMP));
 }
 
-bool GrAtlasTextBlob::mustRegenerate(const SkPaint& paint,
-                                     GrColor color, const SkMaskFilter::BlurRec& blurRec,
+bool GrAtlasTextBlob::mustRegenerate(const GrTextUtils::Paint& paint,
+                                     const SkMaskFilter::BlurRec& blurRec,
                                      const SkMatrix& viewMatrix, SkScalar x, SkScalar y) {
     // If we have LCD text then our canonical color will be set to transparent, in this case we have
     // to regenerate the blob on any color change
     // We use the grPaint to get any color filter effects
     if (fKey.fCanonicalColor == SK_ColorTRANSPARENT &&
-        fPaintColor != color) {
+        fFilteredPaintColor != paint.filteredSkColor()) {
         return true;
     }
 
@@ -198,9 +197,9 @@
 
     // Similarly, we only cache one version for each style
     if (fKey.fStyle != SkPaint::kFill_Style &&
-        (fStrokeInfo.fFrameWidth != paint.getStrokeWidth() ||
-         fStrokeInfo.fMiterLimit != paint.getStrokeMiter() ||
-         fStrokeInfo.fJoin != paint.getStrokeJoin())) {
+        (fStrokeInfo.fFrameWidth != paint.skPaint().getStrokeWidth() ||
+         fStrokeInfo.fMiterLimit != paint.skPaint().getStrokeMiter() ||
+         fStrokeInfo.fJoin != paint.skPaint().getStrokeJoin())) {
         return true;
     }
 
@@ -256,27 +255,14 @@
 
 inline std::unique_ptr<GrDrawOp> GrAtlasTextBlob::makeOp(
         const Run::SubRunInfo& info, int glyphCount, int run, int subRun,
-        const SkMatrix& viewMatrix, SkScalar x, SkScalar y, GrColor color, const SkPaint& skPaint,
+        const SkMatrix& viewMatrix, SkScalar x, SkScalar y, const GrTextUtils::Paint& paint,
         const SkSurfaceProps& props, const GrDistanceFieldAdjustTable* distanceAdjustTable,
         bool useGammaCorrectDistanceTable, GrAtlasGlyphCache* cache) {
     GrMaskFormat format = info.maskFormat();
-    GrColor subRunColor;
-    if (kARGB_GrMaskFormat == format) {
-        uint8_t paintAlpha = skPaint.getAlpha();
-        subRunColor = SkColorSetARGB(paintAlpha, paintAlpha, paintAlpha, paintAlpha);
-    } else {
-        subRunColor = color;
-    }
 
     std::unique_ptr<GrAtlasTextOp> op;
     if (info.drawAsDistanceFields()) {
-        SkColor filteredColor;
-        SkColorFilter* colorFilter = skPaint.getColorFilter();
-        if (colorFilter) {
-            filteredColor = colorFilter->filterColor(skPaint.getColor());
-        } else {
-            filteredColor = skPaint.getColor();
-        }
+        SkColor filteredColor = paint.filteredSkColor();
         bool useBGR = SkPixelGeometryIsBGR(props.pixelGeometry());
         op = GrAtlasTextOp::MakeDistanceField(glyphCount, cache, distanceAdjustTable,
                                               useGammaCorrectDistanceTable, filteredColor,
@@ -289,7 +275,8 @@
     geometry.fBlob = SkRef(this);
     geometry.fRun = run;
     geometry.fSubRun = subRun;
-    geometry.fColor = subRunColor;
+    geometry.fColor =
+            info.maskFormat() == kARGB_GrMaskFormat ? GrColor_WHITE : paint.filteredPremulGrColor();
     geometry.fX = x;
     geometry.fY = y;
     op->init();
@@ -297,27 +284,27 @@
     return std::move(op);
 }
 
-inline void GrAtlasTextBlob::flushRun(GrRenderTargetContext* rtc, GrPaint&& grPaint,
-                                      const GrClip& clip, int run, const SkMatrix& viewMatrix,
-                                      SkScalar x, SkScalar y, const SkPaint& skPaint,
-                                      const SkSurfaceProps& props,
+inline void GrAtlasTextBlob::flushRun(GrRenderTargetContext* rtc, const GrClip& clip, int run,
+                                      const SkMatrix& viewMatrix, SkScalar x, SkScalar y,
+                                      const GrTextUtils::Paint& paint, const SkSurfaceProps& props,
                                       const GrDistanceFieldAdjustTable* distanceAdjustTable,
                                       GrAtlasGlyphCache* cache) {
     int lastRun = fRuns[run].fSubRunInfo.count() - 1;
     for (int subRun = 0; subRun <= lastRun; subRun++) {
         const Run::SubRunInfo& info = fRuns[run].fSubRunInfo[subRun];
+        GrPaint grPaint;
+        if (!paint.toGrPaint(info.maskFormat(), rtc, viewMatrix, &grPaint)) {
+            continue;
+        }
         int glyphCount = info.glyphCount();
         if (0 == glyphCount) {
             continue;
         }
 
-        GrColor color = grPaint.getColor();
-
         std::unique_ptr<GrDrawOp> op(this->makeOp(info, glyphCount, run, subRun, viewMatrix, x, y,
-                                                  color, skPaint, props, distanceAdjustTable,
+                                                  paint, props, distanceAdjustTable,
                                                   rtc->isGammaCorrect(), cache));
-        GrPipelineBuilder pipelineBuilder(GrPaint::MoveOrClone(grPaint, subRun < lastRun),
-                                          GrAAType::kNone);
+        GrPipelineBuilder pipelineBuilder(std::move(grPaint), GrAAType::kNone);
 
         rtc->addDrawOp(pipelineBuilder, clip, std::move(op));
     }
@@ -343,9 +330,8 @@
     }
 }
 
-
 void GrAtlasTextBlob::flushBigGlyphs(GrContext* context, GrRenderTargetContext* rtc,
-                                     const GrClip& clip, const SkPaint& skPaint,
+                                     const GrClip& clip, const SkPaint& paint,
                                      const SkMatrix& viewMatrix, SkScalar x, SkScalar y,
                                      const SkIRect& clipBounds) {
     SkScalar transX, transY;
@@ -360,46 +346,39 @@
             ctm.postConcat(viewMatrix);
         }
 
-        GrBlurUtils::drawPathWithMaskFilter(context, rtc, clip, bigGlyph.fPath,
-                                            skPaint, ctm, nullptr, clipBounds, false);
+        GrBlurUtils::drawPathWithMaskFilter(context, rtc, clip, bigGlyph.fPath, paint, ctm, nullptr,
+                                            clipBounds, false);
     }
 }
 
 void GrAtlasTextBlob::flushRunAsPaths(GrContext* context, GrRenderTargetContext* rtc,
-                                      const SkSurfaceProps& props,
-                                      const SkTextBlobRunIterator& it,
-                                      const GrClip& clip, const SkPaint& skPaint,
+                                      const SkSurfaceProps& props, const SkTextBlobRunIterator& it,
+                                      const GrClip& clip, const GrTextUtils::Paint& paint,
                                       SkDrawFilter* drawFilter, const SkMatrix& viewMatrix,
                                       const SkIRect& clipBounds, SkScalar x, SkScalar y) {
-    SkPaint runPaint = skPaint;
-
     size_t textLen = it.glyphCount() * sizeof(uint16_t);
     const SkPoint& offset = it.offset();
 
-    it.applyFontToPaint(&runPaint);
-
-    if (drawFilter && !drawFilter->filter(&runPaint, SkDrawFilter::kText_Type)) {
+    GrTextUtils::RunPaint runPaint(&paint, drawFilter, props);
+    if (!runPaint.modifyForRun(it)) {
         return;
     }
 
-    runPaint.setFlags(GrTextUtils::FilterTextFlags(props, runPaint));
-
     switch (it.positioning()) {
         case SkTextBlob::kDefault_Positioning:
             GrTextUtils::DrawTextAsPath(context, rtc, clip, runPaint, viewMatrix,
-                                        (const char *)it.glyphs(),
-                                        textLen, x + offset.x(), y + offset.y(), clipBounds);
+                                        (const char*)it.glyphs(), textLen, x + offset.x(),
+                                        y + offset.y(), clipBounds);
             break;
         case SkTextBlob::kHorizontal_Positioning:
             GrTextUtils::DrawPosTextAsPath(context, rtc, props, clip, runPaint, viewMatrix,
-                                           (const char*)it.glyphs(),
-                                           textLen, it.pos(), 1, SkPoint::Make(x, y + offset.y()),
-                                           clipBounds);
+                                           (const char*)it.glyphs(), textLen, it.pos(), 1,
+                                           SkPoint::Make(x, y + offset.y()), clipBounds);
             break;
         case SkTextBlob::kFull_Positioning:
             GrTextUtils::DrawPosTextAsPath(context, rtc, props, clip, runPaint, viewMatrix,
-                                           (const char*)it.glyphs(),
-                                           textLen, it.pos(), 2, SkPoint::Make(x, y), clipBounds);
+                                           (const char*)it.glyphs(), textLen, it.pos(), 2,
+                                           SkPoint::Make(x, y), clipBounds);
             break;
     }
 }
@@ -407,49 +386,47 @@
 void GrAtlasTextBlob::flushCached(GrContext* context, GrRenderTargetContext* rtc,
                                   const SkTextBlob* blob, const SkSurfaceProps& props,
                                   const GrDistanceFieldAdjustTable* distanceAdjustTable,
-                                  const SkPaint& skPaint, GrPaint&& grPaint,
-                                  SkDrawFilter* drawFilter, const GrClip& clip,
-                                  const SkMatrix& viewMatrix, const SkIRect& clipBounds, SkScalar x,
-                                  SkScalar y) {
+                                  const GrTextUtils::Paint& paint, SkDrawFilter* drawFilter,
+                                  const GrClip& clip, const SkMatrix& viewMatrix,
+                                  const SkIRect& clipBounds, SkScalar x, SkScalar y) {
     // We loop through the runs of the blob, flushing each.  If any run is too large, then we flush
     // it as paths
     SkTextBlobRunIterator it(blob);
     for (int run = 0; !it.done(); it.next(), run++) {
         if (fRuns[run].fDrawAsPaths) {
-            this->flushRunAsPaths(context, rtc, props, it, clip, skPaint,
-                                  drawFilter, viewMatrix, clipBounds, x, y);
+            this->flushRunAsPaths(context, rtc, props, it, clip, paint, drawFilter, viewMatrix,
+                                  clipBounds, x, y);
             continue;
         }
-        this->flushRun(rtc, GrPaint::MoveOrClone(grPaint, !it.done()), clip, run, viewMatrix, x, y,
-                       skPaint, props, distanceAdjustTable, context->getAtlasGlyphCache());
+        this->flushRun(rtc, clip, run, viewMatrix, x, y, paint, props, distanceAdjustTable,
+                       context->getAtlasGlyphCache());
     }
 
     // Now flush big glyphs
-    this->flushBigGlyphs(context, rtc, clip, skPaint, viewMatrix, x, y, clipBounds);
+    this->flushBigGlyphs(context, rtc, clip, paint, viewMatrix, x, y, clipBounds);
 }
 
 void GrAtlasTextBlob::flushThrowaway(GrContext* context, GrRenderTargetContext* rtc,
                                      const SkSurfaceProps& props,
                                      const GrDistanceFieldAdjustTable* distanceAdjustTable,
-                                     const SkPaint& skPaint, GrPaint&& grPaint, const GrClip& clip,
+                                     const GrTextUtils::Paint& paint, const GrClip& clip,
                                      const SkMatrix& viewMatrix, const SkIRect& clipBounds,
                                      SkScalar x, SkScalar y) {
     for (int run = 0; run < fRunCount; run++) {
-        this->flushRun(rtc, GrPaint::MoveOrClone(grPaint, run + 1 != fRunCount), clip, run,
-                       viewMatrix, x, y, skPaint, props, distanceAdjustTable,
+        this->flushRun(rtc, clip, run, viewMatrix, x, y, paint, props, distanceAdjustTable,
                        context->getAtlasGlyphCache());
     }
 
     // Now flush big glyphs
-    this->flushBigGlyphs(context, rtc, clip, skPaint, viewMatrix, x, y, clipBounds);
+    this->flushBigGlyphs(context, rtc, clip, paint, viewMatrix, x, y, clipBounds);
 }
 
 std::unique_ptr<GrDrawOp> GrAtlasTextBlob::test_makeOp(
         int glyphCount, int run, int subRun, const SkMatrix& viewMatrix, SkScalar x, SkScalar y,
-        GrColor color, const SkPaint& skPaint, const SkSurfaceProps& props,
+        const GrTextUtils::Paint& paint, const SkSurfaceProps& props,
         const GrDistanceFieldAdjustTable* distanceAdjustTable, GrAtlasGlyphCache* cache) {
     const GrAtlasTextBlob::Run::SubRunInfo& info = fRuns[run].fSubRunInfo[subRun];
-    return this->makeOp(info, glyphCount, run, subRun, viewMatrix, x, y, color, skPaint, props,
+    return this->makeOp(info, glyphCount, run, subRun, viewMatrix, x, y, paint, props,
                         distanceAdjustTable, false, cache);
 }