[SkTextBlob] Merge run font data at draw time.

R=bungeman@google.com, reed@google.com

Author: fmalita@chromium.org

Review URL: https://codereview.chromium.org/496773002
diff --git a/expectations/gm/ignored-tests.txt b/expectations/gm/ignored-tests.txt
index ad48ccd..df6af6e 100644
--- a/expectations/gm/ignored-tests.txt
+++ b/expectations/gm/ignored-tests.txt
@@ -41,3 +41,6 @@
 gradients_view_perspective
 drawbitmaprect
 drawbitmapmatrix
+
+# To be rebaselined (fmalita)
+textblob
diff --git a/gm/textblob.cpp b/gm/textblob.cpp
index e7a0a1d..6837363 100644
--- a/gm/textblob.cpp
+++ b/gm/textblob.cpp
@@ -31,21 +31,33 @@
         { { 1024,   kPoint_Pos, 1 }, { 0,   kPoint_Pos, 0 }, { 0,   kPoint_Pos, 0 } },
     },
     {
-        { { 4, kDefault_Pos, 1},     { 4, kDefault_Pos, 1},  { 4, kDefault_Pos, 1} },
-        { { 4,  kScalar_Pos, 1},     { 4,  kScalar_Pos, 1},  { 4,  kScalar_Pos, 1} },
-        { { 4,   kPoint_Pos, 1},     { 4,   kPoint_Pos, 1},  { 4,   kPoint_Pos, 1} },
+        { { 4, kDefault_Pos, 1 },     { 4, kDefault_Pos, 1 },  { 4, kDefault_Pos, 1 } },
+        { { 4,  kScalar_Pos, 1 },     { 4,  kScalar_Pos, 1 },  { 4,  kScalar_Pos, 1 } },
+        { { 4,   kPoint_Pos, 1 },     { 4,   kPoint_Pos, 1 },  { 4,   kPoint_Pos, 1 } },
     },
 
     {
-        { { 4, kDefault_Pos, 1},     { 4, kDefault_Pos, 1},  { 4,  kScalar_Pos, 1} },
-        { { 4,  kScalar_Pos, 1},     { 4,  kScalar_Pos, 1},  { 4,   kPoint_Pos, 1} },
-        { { 4,   kPoint_Pos, 1},     { 4,   kPoint_Pos, 1},  { 4, kDefault_Pos, 1} },
+        { { 4, kDefault_Pos, 1 },     { 4, kDefault_Pos, 1 },  { 4,  kScalar_Pos, 1 } },
+        { { 4,  kScalar_Pos, 1 },     { 4,  kScalar_Pos, 1 },  { 4,   kPoint_Pos, 1 } },
+        { { 4,   kPoint_Pos, 1 },     { 4,   kPoint_Pos, 1 },  { 4, kDefault_Pos, 1 } },
     },
 
     {
-        { { 4, kDefault_Pos, 1},     { 4,  kScalar_Pos, 1},  { 4,   kPoint_Pos, 1} },
-        { { 4,  kScalar_Pos, 1},     { 4,   kPoint_Pos, 1},  { 4, kDefault_Pos, 1} },
-        { { 4,   kPoint_Pos, 1},     { 4, kDefault_Pos, 1},  { 4,  kScalar_Pos, 1} },
+        { { 4, kDefault_Pos, 1 },     { 4,  kScalar_Pos, 1 },  { 4,   kPoint_Pos, 1 } },
+        { { 4,  kScalar_Pos, 1 },     { 4,   kPoint_Pos, 1 },  { 4, kDefault_Pos, 1 } },
+        { { 4,   kPoint_Pos, 1 },     { 4, kDefault_Pos, 1 },  { 4,  kScalar_Pos, 1 } },
+    },
+
+    {
+        { { 4, kDefault_Pos, .75f },     { 4, kDefault_Pos, 1 },  { 4,  kScalar_Pos, 1.25f } },
+        { { 4,  kScalar_Pos, .75f },     { 4,  kScalar_Pos, 1 },  { 4,   kPoint_Pos, 1.25f } },
+        { { 4,   kPoint_Pos, .75f },     { 4,   kPoint_Pos, 1 },  { 4, kDefault_Pos, 1.25f } },
+    },
+
+    {
+        { { 4, kDefault_Pos, 1 },     { 4,  kScalar_Pos, .75f },  { 4,   kPoint_Pos, 1.25f } },
+        { { 4,  kScalar_Pos, 1 },     { 4,   kPoint_Pos, .75f },  { 4, kDefault_Pos, 1.25f } },
+        { { 4,   kPoint_Pos, 1 },     { 4, kDefault_Pos, .75f },  { 4,  kScalar_Pos, 1.25f } },
     },
 };
 
@@ -74,14 +86,9 @@
 
     virtual void onDraw(SkCanvas* canvas) SK_OVERRIDE {
         for (unsigned b = 0; b < SK_ARRAY_COUNT(blobConfigs); ++b) {
-            SkAutoTUnref<const SkTextBlob> blob(makeBlob(b));
+            SkAutoTUnref<const SkTextBlob> blob(this->makeBlob(b));
 
             SkPaint p;
-            p.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
-            p.setTextSize(kFontSize);
-            p.setAntiAlias(true);
-            p.setSubpixelText(true);
-
             SkPoint offset = SkPoint::Make(SkIntToScalar(10 + 300 * (b % 2)),
                                            SkIntToScalar(20 + 150 * (b / 2)));
 
@@ -102,6 +109,8 @@
 
         SkPaint font;
         font.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
+        font.setAntiAlias(true);
+        font.setSubpixelText(true);
 
         for (unsigned l = 0; l < SK_ARRAY_COUNT(blobConfigs[blobIndex]); ++l) {
             unsigned currentGlyph = 0;
diff --git a/include/core/SkTextBlob.h b/include/core/SkTextBlob.h
index cf07b70..d1b2e0f 100644
--- a/include/core/SkTextBlob.h
+++ b/include/core/SkTextBlob.h
@@ -47,7 +47,7 @@
         const uint16_t* glyphs() const;
         const SkScalar* pos() const;
         const SkPoint& offset() const;
-        const SkPaint& font() const;
+        void applyFontToPaint(SkPaint*) const;
         GlyphPositioning positioning() const;
 
     private:
diff --git a/src/core/SkCanvas.cpp b/src/core/SkCanvas.cpp
index 5a694db..af25b46 100644
--- a/src/core/SkCanvas.cpp
+++ b/src/core/SkCanvas.cpp
@@ -2226,20 +2226,24 @@
         this->translate(x, y);
     }
 
+    SkPaint runPaint = paint;
     SkTextBlob::RunIterator it(blob);
     while (!it.done()) {
         size_t textLen = it.glyphCount() * sizeof(uint16_t);
         const SkPoint& offset = it.offset();
+        // applyFontToPaint() always overwrites the exact same attributes,
+        // so it is safe to not re-seed the paint.
+        it.applyFontToPaint(&runPaint);
 
         switch (it.positioning()) {
         case SkTextBlob::kDefault_Positioning:
-            this->drawText(it.glyphs(), textLen, offset.x(), offset.y(), paint);
+            this->drawText(it.glyphs(), textLen, offset.x(), offset.y(), runPaint);
             break;
         case SkTextBlob::kHorizontal_Positioning:
-            this->drawPosTextH(it.glyphs(), textLen, it.pos(), offset.y(), paint);
+            this->drawPosTextH(it.glyphs(), textLen, it.pos(), offset.y(), runPaint);
             break;
         case SkTextBlob::kFull_Positioning:
-            this->drawPosText(it.glyphs(), textLen, (const SkPoint*)it.pos(), paint);
+            this->drawPosText(it.glyphs(), textLen, (const SkPoint*)it.pos(), runPaint);
             break;
         default:
             SkFAIL("unhandled positioning mode");
diff --git a/src/core/SkTextBlob.cpp b/src/core/SkTextBlob.cpp
index 551d988..ded801a 100644
--- a/src/core/SkTextBlob.cpp
+++ b/src/core/SkTextBlob.cpp
@@ -61,16 +61,39 @@
     return (*fBlob->fRuns)[fIndex].offset;
 }
 
-const SkPaint& SkTextBlob::RunIterator::font() const {
-    SkASSERT(!this->done());
-    return (*fBlob->fRuns)[fIndex].font;
-}
-
 SkTextBlob::GlyphPositioning SkTextBlob::RunIterator::positioning() const {
     SkASSERT(!this->done());
     return (*fBlob->fRuns)[fIndex].positioning;
 }
 
+void SkTextBlob::RunIterator::applyFontToPaint(SkPaint* paint) const {
+    SkASSERT(!this->done());
+
+    const SkPaint& font = (*fBlob->fRuns)[fIndex].font;
+
+    paint->setTypeface(font.getTypeface());
+    paint->setTextEncoding(font.getTextEncoding());
+    paint->setTextSize(font.getTextSize());
+    paint->setTextScaleX(font.getTextScaleX());
+    paint->setTextSkewX(font.getTextSkewX());
+    paint->setHinting(font.getHinting());
+
+    uint32_t flagsMask = SkPaint::kAntiAlias_Flag
+                       | SkPaint::kUnderlineText_Flag
+                       | SkPaint::kStrikeThruText_Flag
+                       | SkPaint::kFakeBoldText_Flag
+                       | SkPaint::kLinearText_Flag
+                       | SkPaint::kSubpixelText_Flag
+                       | SkPaint::kDevKernText_Flag
+                       | SkPaint::kLCDRenderText_Flag
+                       | SkPaint::kEmbeddedBitmapText_Flag
+                       | SkPaint::kAutoHinting_Flag
+                       | SkPaint::kVerticalText_Flag
+                       | SkPaint::kGenA8FromLCD_Flag
+                       | SkPaint::kDistanceFieldTextTEMP_Flag;
+    paint->setFlags((paint->getFlags() & ~flagsMask) | (font.getFlags() & flagsMask));
+}
+
 SkTextBlobBuilder::SkTextBlobBuilder(unsigned runs)
     : fRuns(NULL)
     , fDeferredBounds(false) {