use SkFont in a lot of places

Bug: skia:
Change-Id: I86df3f650eb5bb0219b3251ef5f8e95403838bba
Reviewed-on: https://skia-review.googlesource.com/c/172482
Reviewed-by: Mike Reed <reed@google.com>
Commit-Queue: Mike Reed <reed@google.com>
diff --git a/bench/TextBlobBench.cpp b/bench/TextBlobBench.cpp
index b517d26..d0d9b04 100644
--- a/bench/TextBlobBench.cpp
+++ b/bench/TextBlobBench.cpp
@@ -8,6 +8,7 @@
 #include "Benchmark.h"
 #include "Resources.h"
 #include "SkCanvas.h"
+#include "SkFont.h"
 #include "SkPaint.h"
 #include "SkRandom.h"
 #include "SkStream.h"
@@ -26,22 +27,19 @@
     SkTextBlobBench() {}
 
     void onDelayedSetup() override {
-        fPaint.setTypeface(sk_tool_utils::create_portable_typeface("serif", SkFontStyle()));
-        fPaint.setTextEncoding(SkPaint::kUTF8_TextEncoding);
+        fFont.setTypeface(sk_tool_utils::create_portable_typeface("serif", SkFontStyle()));
+        fFont.setSubpixel(true);
 
         // This text seems representative in both length and letter frequency.
         const char* text = "Keep your sentences short, but not overly so.";
 
-        fGlyphs.setCount(fPaint.textToGlyphs(text, strlen(text), nullptr));
-        fPaint.textToGlyphs(text, strlen(text), fGlyphs.begin());
-
-        fPaint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
-        fPaint.setSubpixelText(true);
+        fGlyphs.setCount(fFont.countText(text, strlen(text), kUTF8_SkTextEncoding));
+        fFont.textToGlyphs(text, strlen(text), kUTF8_SkTextEncoding, fGlyphs.begin(), fGlyphs.count());
     }
 
     sk_sp<SkTextBlob> makeBlob() {
         const SkTextBlobBuilder::RunBuffer& run =
-            fBuilder.allocRunPosH(fPaint, fGlyphs.count(), 10, nullptr);
+            fBuilder.allocRunPosH(fFont, fGlyphs.count(), 10, nullptr);
         for (int i = 0; i < fGlyphs.count(); i++) {
             run.glyphs[i] = fGlyphs[i];
             run.   pos[i] = (i+1) * 10.125;
@@ -50,9 +48,9 @@
     }
 
 private:
-    SkTextBlobBuilder    fBuilder;
-    SkPaint              fPaint;
-    SkTDArray<uint16_t>  fGlyphs;
+    SkTextBlobBuilder   fBuilder;
+    SkFont              fFont;
+    SkTDArray<uint16_t> fGlyphs;
 
     typedef Benchmark INHERITED;
 };
diff --git a/fuzz/FuzzCanvas.cpp b/fuzz/FuzzCanvas.cpp
index 1df50b6..aea7405 100644
--- a/fuzz/FuzzCanvas.cpp
+++ b/fuzz/FuzzCanvas.cpp
@@ -892,16 +892,16 @@
                                                                      kFull_SkFontHinting));
 }
 
-static void fuzz_paint_text_encoding(Fuzz* fuzz, SkPaint* paint) {
-    paint->setTextEncoding(make_fuzz_t_range<SkPaint::TextEncoding>(fuzz, 0, 3));
+static SkTextEncoding fuzz_paint_text_encoding(Fuzz* fuzz) {
+    return make_fuzz_t_range<SkTextEncoding>(fuzz, 0, 3);
 }
 
 constexpr int kMaxGlyphCount = 30;
 
-static SkTDArray<uint8_t> make_fuzz_text(Fuzz* fuzz, const SkPaint& paint) {
+static SkTDArray<uint8_t> make_fuzz_text(Fuzz* fuzz, const SkFont& font, SkTextEncoding encoding) {
     SkTDArray<uint8_t> array;
-    if (SkPaint::kGlyphID_TextEncoding == paint.getTextEncoding()) {
-        int glyphRange = paint.getTypeface() ? paint.getTypeface()->countGlyphs()
+    if (kGlyphID_SkTextEncoding == encoding) {
+        int glyphRange = font.getTypeface() ? font.getTypeface()->countGlyphs()
                                              : SkTypeface::MakeDefault()->countGlyphs();
         if (glyphRange == 0) {
             // Some fuzzing environments have no fonts, so empty array is the best
@@ -941,8 +941,8 @@
             }
         }
     }
-    switch (paint.getTextEncoding()) {
-        case SkPaint::kUTF8_TextEncoding: {
+    switch (encoding) {
+        case kUTF8_SkTextEncoding: {
             size_t utf8len = 0;
             for (int j = 0; j < length; ++j) {
                 utf8len += SkUTF::ToUTF8(buffer[j], nullptr);
@@ -952,7 +952,7 @@
                 ptr += SkUTF::ToUTF8(buffer[j], ptr);
             }
         } break;
-        case SkPaint::kUTF16_TextEncoding: {
+        case kUTF16_SkTextEncoding: {
             size_t utf16len = 0;
             for (int j = 0; j < length; ++j) {
                 utf16len += SkUTF::ToUTF16(buffer[j]);
@@ -962,7 +962,7 @@
                 ptr += SkUTF::ToUTF16(buffer[j], ptr);
             }
         } break;
-        case SkPaint::kUTF32_TextEncoding:
+        case kUTF32_SkTextEncoding:
             memcpy(array.append(length * sizeof(SkUnichar)), buffer, length * sizeof(SkUnichar));
             break;
         default:
@@ -972,17 +972,21 @@
     return array;
 }
 
+static SkTDArray<uint8_t> make_fuzz_text(Fuzz* fuzz, const SkPaint& paint) {
+    return make_fuzz_text(fuzz, SkFont::LEGACY_ExtractFromPaint(paint),
+                          (SkTextEncoding)paint.getTextEncoding());
+}
+
 static sk_sp<SkTextBlob> make_fuzz_textblob(Fuzz* fuzz) {
     SkTextBlobBuilder textBlobBuilder;
     int8_t runCount;
     fuzz->nextRange(&runCount, (int8_t)1, (int8_t)8);
     while (runCount-- > 0) {
-        SkPaint paint;
-        fuzz_paint_text_encoding(fuzz, &paint);
-        paint.setAntiAlias(make_fuzz_t<bool>(fuzz));
-        paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
-        SkTDArray<uint8_t> text = make_fuzz_text(fuzz, paint);
-        int glyphCount = paint.countText(text.begin(), SkToSizeT(text.count()));
+        SkFont font;
+        SkTextEncoding encoding = fuzz_paint_text_encoding(fuzz);
+        font.setEdging(make_fuzz_t<bool>(fuzz) ? SkFont::Edging::kAlias : SkFont::Edging::kAntiAlias);
+        SkTDArray<uint8_t> text = make_fuzz_text(fuzz, font, encoding);
+        int glyphCount = font.countText(text.begin(), SkToSizeT(text.count()), encoding);
         SkASSERT(glyphCount <= kMaxGlyphCount);
         SkScalar x, y;
         const SkTextBlobBuilder::RunBuffer* buffer;
@@ -992,19 +996,19 @@
             case 0:
                 fuzz->next(&x, &y);
                 // TODO: Test other variations of this.
-                buffer = &textBlobBuilder.allocRun(paint, glyphCount, x, y);
+                buffer = &textBlobBuilder.allocRun(font, glyphCount, x, y);
                 memcpy(buffer->glyphs, text.begin(), SkToSizeT(text.count()));
                 break;
             case 1:
                 fuzz->next(&y);
                 // TODO: Test other variations of this.
-                buffer = &textBlobBuilder.allocRunPosH(paint, glyphCount, y);
+                buffer = &textBlobBuilder.allocRunPosH(font, glyphCount, y);
                 memcpy(buffer->glyphs, text.begin(), SkToSizeT(text.count()));
                 fuzz->nextN(buffer->pos, glyphCount);
                 break;
             case 2:
                 // TODO: Test other variations of this.
-                buffer = &textBlobBuilder.allocRunPos(paint, glyphCount);
+                buffer = &textBlobBuilder.allocRunPos(font, glyphCount);
                 memcpy(buffer->glyphs, text.begin(), SkToSizeT(text.count()));
                 fuzz->nextN(buffer->pos, glyphCount * 2);
                 break;
@@ -1460,7 +1464,7 @@
             case 45: {
                 fuzz_paint(fuzz, &paint, depth - 1);
                 fuzz_paint_text(fuzz, &paint);
-                fuzz_paint_text_encoding(fuzz, &paint);
+                paint.setTextEncoding(fuzz_paint_text_encoding(fuzz));
                 SkScalar x, y;
                 fuzz->next(&x, &y);
                 SkTDArray<uint8_t> text = make_fuzz_text(fuzz, paint);
@@ -1470,7 +1474,7 @@
             case 46: {
                 fuzz_paint(fuzz, &paint, depth - 1);
                 fuzz_paint_text(fuzz, &paint);
-                fuzz_paint_text_encoding(fuzz, &paint);
+                paint.setTextEncoding(fuzz_paint_text_encoding(fuzz));
                 SkTDArray<uint8_t> text = make_fuzz_text(fuzz, paint);
                 int glyphCount = paint.countText(text.begin(), SkToSizeT(text.count()));
                 if (glyphCount < 1) {
@@ -1491,7 +1495,7 @@
             case 47: {
                 fuzz_paint(fuzz, &paint, depth - 1);
                 fuzz_paint_text(fuzz, &paint);
-                fuzz_paint_text_encoding(fuzz, &paint);
+                paint.setTextEncoding(fuzz_paint_text_encoding(fuzz));
                 SkTDArray<uint8_t> text = make_fuzz_text(fuzz, paint);
                 int glyphCount = paint.countText(text.begin(), SkToSizeT(text.count()));
                 SkAutoTMalloc<SkScalar> widths(glyphCount);
@@ -1525,7 +1529,7 @@
             case 50: {
                 fuzz_paint(fuzz, &paint, depth - 1);
                 fuzz_paint_text(fuzz, &paint);
-                fuzz_paint_text_encoding(fuzz, &paint);
+                paint.setTextEncoding(fuzz_paint_text_encoding(fuzz));
                 SkTDArray<uint8_t> text = make_fuzz_text(fuzz, paint);
                 SkRSXform rSXform[kMaxGlyphCount];
                 int glyphCount = paint.countText(text.begin(), SkToSizeT(text.count()));
diff --git a/gm/textbloblooper.cpp b/gm/textbloblooper.cpp
index eef65a4..49ee649 100644
--- a/gm/textbloblooper.cpp
+++ b/gm/textbloblooper.cpp
@@ -25,26 +25,23 @@
 constexpr int kHeight = 700;
 
 // Unlike the variant in sk_tool_utils, this version positions the glyphs on a diagonal
-static void add_to_text_blob(SkTextBlobBuilder* builder, const char* text, const SkPaint& origPaint,
+static void add_to_text_blob(SkTextBlobBuilder* builder, const char* text, const SkFont& font,
                              SkScalar x, SkScalar y) {
-    SkPaint paint(origPaint);
     SkTDArray<uint16_t> glyphs;
 
     size_t len = strlen(text);
-    glyphs.append(paint.textToGlyphs(text, len, nullptr));
-    paint.textToGlyphs(text, len, glyphs.begin());
+    glyphs.append(font.countText(text, len, kUTF8_SkTextEncoding));
+    font.textToGlyphs(text, len, kUTF8_SkTextEncoding, glyphs.begin(), glyphs.count());
 
-    const SkScalar advanceX = paint.getTextSize() * 0.85f;
-    const SkScalar advanceY = paint.getTextSize() * 1.5f;
+    const SkScalar advanceX = font.getSize() * 0.85f;
+    const SkScalar advanceY = font.getSize() * 1.5f;
 
     SkTDArray<SkScalar> pos;
     for (unsigned i = 0; i < len; ++i) {
         *pos.append() = x + i * advanceX;
         *pos.append() = y + i * (advanceY / len);
     }
-
-    paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
-    const SkTextBlobBuilder::RunBuffer& run = builder->allocRunPos(paint, glyphs.count());
+    const SkTextBlobBuilder::RunBuffer& run = builder->allocRunPos(font, glyphs.count());
     memcpy(run.glyphs, glyphs.begin(), glyphs.count() * sizeof(uint16_t));
     memcpy(run.pos, pos.begin(), len * sizeof(SkScalar) * 2);
 }
@@ -141,14 +138,13 @@
         SkTextBlobBuilder builder;
 
         // LCD
-        SkPaint paint;
-        paint.setTextSize(32);
+        SkFont font;
+        font.setSize(32);
         const char* text = "The quick brown fox jumps over the lazy dog";
-        paint.setSubpixelText(true);
-        paint.setLCDRenderText(true);
-        paint.setAntiAlias(true);
-        sk_tool_utils::set_portable_typeface(&paint);
-        add_to_text_blob(&builder, text, paint, 0, 0);
+        font.setSubpixel(true);
+        font.setEdging(SkFont::Edging::kSubpixelAntiAlias);
+        font.setTypeface(sk_tool_utils::create_portable_typeface());
+        add_to_text_blob(&builder, text, font, 0, 0);
         fBlob = builder.make();
 
         // create a looper which sandwhiches an effect in two normal draws
diff --git a/include/core/SkFont.h b/include/core/SkFont.h
index baca98c..ade29f3 100644
--- a/include/core/SkFont.h
+++ b/include/core/SkFont.h
@@ -65,6 +65,8 @@
     */
     SkFont(sk_sp<SkTypeface> typeface, SkScalar size, SkScalar scaleX, SkScalar skewX);
 
+    bool operator==(const SkFont&);
+
     /** If true, instructs the font manager to always hint glyphs.
         Returned value is only meaningful if platform uses FreeType as the font manager.
 
@@ -366,6 +368,9 @@
     */
     void LEGACY_applyToPaint(SkPaint* paint) const;
     /** Deprecated.
+     */
+    void LEGACY_applyPaintFlags(uint32_t paintFlags);
+    /** Deprecated.
     */
     static SkFont LEGACY_ExtractFromPaint(const SkPaint& paint);
 
diff --git a/include/core/SkPaint.h b/include/core/SkPaint.h
index aae66a0..71492d3 100644
--- a/include/core/SkPaint.h
+++ b/include/core/SkPaint.h
@@ -948,6 +948,10 @@
                          kGlyphID_TextEncoding
     */
     void setTextEncoding(TextEncoding encoding);
+    // Experimental
+    void setTextEncoding(SkTextEncoding encoding) {
+        this->setTextEncoding((TextEncoding)encoding);
+    }
 
 #ifdef SK_SUPPORT_LEGACY_FONTMETRICS_IN_PAINT
     /**
diff --git a/modules/sksg/src/SkSGText.cpp b/modules/sksg/src/SkSGText.cpp
index 81a9093..4d57b10 100644
--- a/modules/sksg/src/SkSGText.cpp
+++ b/modules/sksg/src/SkSGText.cpp
@@ -45,12 +45,12 @@
 SkRect Text::onRevalidate(InvalidationController*, const SkMatrix&) {
     // TODO: we could potentially track invals which don't require rebuilding the blob.
 
-    SkPaint font;
-    font.setFlags(fFlags);
+    SkFont font;
+    font.LEGACY_applyPaintFlags(fFlags);
     font.setTypeface(fTypeface);
-    font.setTextSize(fSize);
-    font.setTextScaleX(fScaleX);
-    font.setTextSkewX(fSkewX);
+    font.setSize(fSize);
+    font.setScaleX(fScaleX);
+    font.setSkewX(fSkewX);
     font.setHinting(fHinting);
 
     // N.B.: fAlign is applied externally (in alignedPosition()), because
@@ -58,11 +58,10 @@
     //  2) SkPaint::Align is slated for deprecation.
 
     // First, convert to glyphIDs.
-    font.setTextEncoding(SkPaint::kUTF8_TextEncoding);
     SkSTArray<256, SkGlyphID, true> glyphs;
-    glyphs.reset(font.textToGlyphs(fText.c_str(), fText.size(), nullptr));
-    SkAssertResult(font.textToGlyphs(fText.c_str(), fText.size(), glyphs.begin()) == glyphs.count());
-    font.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
+    glyphs.reset(font.countText(fText.c_str(), fText.size(), kUTF8_SkTextEncoding));
+    SkAssertResult(font.textToGlyphs(fText.c_str(), fText.size(), kUTF8_SkTextEncoding,
+                                     glyphs.begin(), glyphs.count()));
 
     // Next, build the cached blob.
     SkTextBlobBuilder builder;
diff --git a/src/core/SkFont.cpp b/src/core/SkFont.cpp
index 4adae47..538efa6 100644
--- a/src/core/SkFont.cpp
+++ b/src/core/SkFont.cpp
@@ -40,6 +40,16 @@
 
 SkFont::SkFont() : SkFont(nullptr, kDefault_Size) {}
 
+bool SkFont::operator==(const SkFont& b) {
+    return  fTypeface.get() == b.fTypeface.get() &&
+            fSize           == b.fSize &&
+            fScaleX         == b.fScaleX &&
+            fSkewX          == b.fSkewX &&
+            fFlags          == b.fFlags &&
+            fEdging         == b.fEdging &&
+            fHinting        == b.fHinting;
+}
+
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
 static inline uint32_t set_clear_mask(uint32_t bits, bool cond, uint32_t mask) {
@@ -363,35 +373,39 @@
 }
 
 SkFont SkFont::LEGACY_ExtractFromPaint(const SkPaint& paint) {
-    uint32_t flags = 0;
-    if (paint.isEmbeddedBitmapText()) {
-        flags |= kEmbeddedBitmaps_PrivFlag;
-    }
-    if (paint.isFakeBoldText()) {
-        flags |= kEmbolden_PrivFlag;
-    }
-    if (paint.isAutohinted()) {
-        flags |= kForceAutoHinting_PrivFlag;
-    }
-    if (paint.isSubpixelText()) {
-        flags |= kSubpixel_PrivFlag;
-    }
-    if (paint.isLinearText()) {
-        flags |= kLinearMetrics_PrivFlag;
-    }
-
-    Edging edging = Edging::kAlias;
-    if (paint.isAntiAlias()) {
-        edging = Edging::kAntiAlias;
-        if (paint.isLCDRenderText()) {
-            edging = Edging::kSubpixelAntiAlias;
-        }
-    }
-
     SkFont font(sk_ref_sp(paint.getTypeface()), paint.getTextSize(), paint.getTextScaleX(),
                 paint.getTextSkewX());
-    font.fFlags = flags;
-    font.setEdging(edging);
+    font.LEGACY_applyPaintFlags(paint.getFlags());
     font.setHinting((SkFontHinting)paint.getHinting());
     return font;
 }
+
+void SkFont::LEGACY_applyPaintFlags(uint32_t paintFlags) {
+    uint32_t flags = 0;
+    if (paintFlags & SkPaint::kEmbeddedBitmapText_Flag) {
+        flags |= kEmbeddedBitmaps_PrivFlag;
+    }
+    if (paintFlags & SkPaint::kFakeBoldText_Flag) {
+        flags |= kEmbolden_PrivFlag;
+    }
+    if (paintFlags & SkPaint::kAutoHinting_Flag) {
+        flags |= kForceAutoHinting_PrivFlag;
+    }
+    if (paintFlags & SkPaint::kSubpixelText_Flag) {
+        flags |= kSubpixel_PrivFlag;
+    }
+    if (paintFlags & SkPaint::kLinearText_Flag) {
+        flags |= kLinearMetrics_PrivFlag;
+    }
+    fFlags = flags;
+
+    Edging edging = Edging::kAlias;
+    if (paintFlags & SkPaint::kAntiAlias_Flag) {
+        edging = Edging::kAntiAlias;
+        if (paintFlags & SkPaint::kLCDRenderText_Flag) {
+            edging = Edging::kSubpixelAntiAlias;
+        }
+    }
+    this->setEdging(edging);
+}
+
diff --git a/src/core/SkTextBlob.cpp b/src/core/SkTextBlob.cpp
index 627e2de..eadb07c 100644
--- a/src/core/SkTextBlob.cpp
+++ b/src/core/SkTextBlob.cpp
@@ -769,10 +769,8 @@
     SkTextBlobBuilder blobBuilder;
     if (!glyphRunList.empty()) {
         auto run = glyphRunList[0];
-        SkPaint blobPaint(legacyPaint);
-        blobPaint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
 
-        auto runData = blobBuilder.allocRunPos(blobPaint, run.runSize());
+        auto runData = blobBuilder.allocRunPos(font, run.runSize());
         run.filloutGlyphsAndPositions(runData.glyphs, (SkPoint *)runData.pos);
     }
 
diff --git a/tests/GlyphRunTest.cpp b/tests/GlyphRunTest.cpp
index a3153fc..f92b113 100644
--- a/tests/GlyphRunTest.cpp
+++ b/tests/GlyphRunTest.cpp
@@ -58,12 +58,10 @@
 
     auto tf = SkTypeface::MakeFromName("monospace", SkFontStyle());
 
-    SkPaint font;
+    SkFont font;
     font.setTypeface(tf);
-    font.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
-    font.setStyle(SkPaint::kFill_Style);
     font.setHinting(kNormal_SkFontHinting);
-    font.setTextSize(1u);
+    font.setSize(1u);
 
     SkTextBlobBuilder blobBuilder;
     for (int runNum = 0; runNum < runCount; runNum++) {
@@ -79,11 +77,10 @@
 
     auto blob = blobBuilder.make();
 
-    SkPaint paint;
-    paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
-
     SkGlyphRunBuilder runBuilder;
-    runBuilder.drawTextBlob(font, *blob, SkPoint::Make(0, 0));
+    SkPaint legacy_paint;
+    font.LEGACY_applyToPaint(&legacy_paint);
+    runBuilder.drawTextBlob(legacy_paint, *blob, SkPoint::Make(0, 0));
 
     auto runList = runBuilder.useGlyphRunList();
 
diff --git a/tests/SerializationTest.cpp b/tests/SerializationTest.cpp
index 32320cd..7d4df08 100644
--- a/tests/SerializationTest.cpp
+++ b/tests/SerializationTest.cpp
@@ -745,8 +745,7 @@
 }
 
 DEF_TEST(WriteBuffer_external_memory_textblob, reporter) {
-    SkPaint font;
-    font.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
+    SkFont font;
     font.setTypeface(SkTypeface::MakeDefault());
 
     SkTextBlobBuilder builder;
diff --git a/tests/SkRemoteGlyphCacheTest.cpp b/tests/SkRemoteGlyphCacheTest.cpp
index 6e7160f..4b9f347 100644
--- a/tests/SkRemoteGlyphCacheTest.cpp
+++ b/tests/SkRemoteGlyphCacheTest.cpp
@@ -68,14 +68,12 @@
 };
 
 sk_sp<SkTextBlob> buildTextBlob(sk_sp<SkTypeface> tf, int glyphCount) {
-    SkPaint font;
+    SkFont font;
     font.setTypeface(tf);
-    font.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
-    font.setStyle(SkPaint::kFill_Style);
     font.setHinting(kNormal_SkFontHinting);
-    font.setTextSize(1u);
-    font.setAntiAlias(true);
-    font.setSubpixelText(true);
+    font.setSize(1u);
+    font.setEdging(SkFont::Edging::kAntiAlias);
+    font.setSubpixel(true);
 
     SkTextBlobBuilder builder;
     SkRect bounds = SkRect::MakeWH(10, 10);
diff --git a/tests/TextBlobTest.cpp b/tests/TextBlobTest.cpp
index 158b0b9..94c7fa5 100644
--- a/tests/TextBlobTest.cpp
+++ b/tests/TextBlobTest.cpp
@@ -102,8 +102,7 @@
     // This unit test verifies blob bounds computation.
     static void TestBounds(skiatest::Reporter* reporter) {
         SkTextBlobBuilder builder;
-        SkPaint font;
-        font.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
+        SkFont font;
 
         // Explicit bounds.
         {
@@ -155,19 +154,15 @@
         {
             // Exercise the empty bounds path, and ensure that RunRecord-aligned pos buffers
             // don't trigger asserts (http://crbug.com/542643).
-            SkPaint p;
-            p.setTextSize(0);
-            p.setTextEncoding(SkPaint::kUTF8_TextEncoding);
+            SkFont font;
+            font.setSize(0);
 
             const char* txt = "BOOO";
             const size_t txtLen = strlen(txt);
-            const int glyphCount = p.textToGlyphs(txt, txtLen, nullptr);
+            const int glyphCount = font.countText(txt, txtLen, kUTF8_SkTextEncoding);
+            const SkTextBlobBuilder::RunBuffer& buffer = builder.allocRunPos(font, glyphCount);
 
-            p.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
-            const SkTextBlobBuilder::RunBuffer& buffer = builder.allocRunPos(p, glyphCount);
-
-            p.setTextEncoding(SkPaint::kUTF8_TextEncoding);
-            p.textToGlyphs(txt, txtLen, buffer.glyphs);
+            font.textToGlyphs(txt, txtLen, kUTF8_SkTextEncoding, buffer.glyphs, glyphCount);
 
             memset(buffer.pos, 0, sizeof(SkScalar) * glyphCount * 2);
             sk_sp<SkTextBlob> blob(builder.make());
@@ -177,38 +172,34 @@
 
     // Verify that text-related properties are captured in run paints.
     static void TestPaintProps(skiatest::Reporter* reporter) {
-        SkPaint font;
-        font.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
-
+        SkFont font;
         // Kitchen sink font.
-        font.setTextSize(42);
-        font.setTextScaleX(4.2f);
-        font.setTypeface(SkTypeface::MakeDefault());
-        font.setTextSkewX(0.42f);
+        font.setSize(42);
+        font.setScaleX(4.2f);
+        font.setTypeface(sk_tool_utils::create_portable_typeface());
+        font.setSkewX(0.42f);
         font.setHinting(kFull_SkFontHinting);
-        font.setAntiAlias(true);
-        font.setFakeBoldText(true);
-        font.setLinearText(true);
-        font.setSubpixelText(true);
-        font.setLCDRenderText(true);
-        font.setEmbeddedBitmapText(true);
-        font.setAutohinted(true);
+        font.setEdging(SkFont::Edging::kSubpixelAntiAlias);
+        font.setEmbolden(true);
+        font.setLinearMetrics(true);
+        font.setSubpixel(true);
+        font.setEmbeddedBitmaps(true);
+        font.setForceAutoHinting(true);
 
         // Ensure we didn't pick default values by mistake.
-        SkPaint defaultPaint;
-        REPORTER_ASSERT(reporter, defaultPaint.getTextSize() != font.getTextSize());
-        REPORTER_ASSERT(reporter, defaultPaint.getTextScaleX() != font.getTextScaleX());
-        REPORTER_ASSERT(reporter, defaultPaint.getTypeface() != font.getTypeface());
-        REPORTER_ASSERT(reporter, defaultPaint.getTextSkewX() != font.getTextSkewX());
-        REPORTER_ASSERT(reporter, defaultPaint.getHinting() != font.getHinting());
-        REPORTER_ASSERT(reporter, defaultPaint.isAntiAlias() != font.isAntiAlias());
-        REPORTER_ASSERT(reporter, defaultPaint.isFakeBoldText() != font.isFakeBoldText());
-        REPORTER_ASSERT(reporter, defaultPaint.isLinearText() != font.isLinearText());
-        REPORTER_ASSERT(reporter, defaultPaint.isSubpixelText() != font.isSubpixelText());
-        REPORTER_ASSERT(reporter, defaultPaint.isLCDRenderText() != font.isLCDRenderText());
+        SkFont defaultFont;
+        REPORTER_ASSERT(reporter, defaultFont.getSize() != font.getSize());
+        REPORTER_ASSERT(reporter, defaultFont.getScaleX() != font.getScaleX());
+        REPORTER_ASSERT(reporter, defaultFont.getTypeface() != font.getTypeface());
+        REPORTER_ASSERT(reporter, defaultFont.getSkewX() != font.getSkewX());
+        REPORTER_ASSERT(reporter, defaultFont.getHinting() != font.getHinting());
+        REPORTER_ASSERT(reporter, defaultFont.getEdging() != font.getEdging());
+        REPORTER_ASSERT(reporter, defaultFont.isEmbolden() != font.isEmbolden());
+        REPORTER_ASSERT(reporter, defaultFont.isLinearMetrics() != font.isLinearMetrics());
+        REPORTER_ASSERT(reporter, defaultFont.isSubpixel() != font.isSubpixel());
         REPORTER_ASSERT(reporter,
-                        defaultPaint.isEmbeddedBitmapText() != font.isEmbeddedBitmapText());
-        REPORTER_ASSERT(reporter, defaultPaint.isAutohinted() != font.isAutohinted());
+                        defaultFont.isEmbeddedBitmaps() != font.isEmbeddedBitmaps());
+        REPORTER_ASSERT(reporter, defaultFont.isForceAutoHinting() != font.isForceAutoHinting());
 
         SkTextBlobBuilder builder;
         AddRun(font, 1, SkTextBlobRunIterator::kDefault_Positioning, SkPoint::Make(0, 0), builder);
@@ -220,20 +211,10 @@
         SkTextBlobRunIterator it(blob.get());
         while (!it.done()) {
             SkPaint paint;
-            it.applyFontToPaint(&paint);
+            it.applyFontToPaint(&paint);    // need iter for fonts
+            SkFont iterFont = SkFont::LEGACY_ExtractFromPaint(paint);
 
-            REPORTER_ASSERT(reporter, paint.getTextSize() == font.getTextSize());
-            REPORTER_ASSERT(reporter, paint.getTextScaleX() == font.getTextScaleX());
-            REPORTER_ASSERT(reporter, paint.getTypeface() == font.getTypeface());
-            REPORTER_ASSERT(reporter, paint.getTextSkewX() == font.getTextSkewX());
-            REPORTER_ASSERT(reporter, paint.getHinting() == font.getHinting());
-            REPORTER_ASSERT(reporter, paint.isAntiAlias() == font.isAntiAlias());
-            REPORTER_ASSERT(reporter, paint.isFakeBoldText() == font.isFakeBoldText());
-            REPORTER_ASSERT(reporter, paint.isLinearText() == font.isLinearText());
-            REPORTER_ASSERT(reporter, paint.isSubpixelText() == font.isSubpixelText());
-            REPORTER_ASSERT(reporter, paint.isLCDRenderText() == font.isLCDRenderText());
-            REPORTER_ASSERT(reporter, paint.isEmbeddedBitmapText() == font.isEmbeddedBitmapText());
-            REPORTER_ASSERT(reporter, paint.isAutohinted() == font.isAutohinted());
+            REPORTER_ASSERT(reporter, iterFont == font);
 
             it.next();
         }
@@ -250,8 +231,7 @@
     static void RunBuilderTest(skiatest::Reporter* reporter, SkTextBlobBuilder& builder,
                                const RunDef in[], unsigned inCount,
                                const RunDef out[], unsigned outCount) {
-        SkPaint font;
-        font.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
+        SkFont font;
 
         unsigned glyphCount = 0;
         unsigned posCount = 0;
@@ -296,7 +276,7 @@
         REPORTER_ASSERT(reporter, it.done());
     }
 
-    static void AddRun(const SkPaint& font, int count, SkTextBlobRunIterator::GlyphPositioning pos,
+    static void AddRun(const SkFont& font, int count, SkTextBlobRunIterator::GlyphPositioning pos,
                        const SkPoint& offset, SkTextBlobBuilder& builder,
                        const SkRect* bounds = nullptr) {
         switch (pos) {
diff --git a/tools/sk_tool_utils.cpp b/tools/sk_tool_utils.cpp
index 00c8e63..35c059f 100644
--- a/tools/sk_tool_utils.cpp
+++ b/tools/sk_tool_utils.cpp
@@ -136,15 +136,14 @@
 }
 
 void add_to_text_blob_w_len(SkTextBlobBuilder* builder, const char* text, size_t len,
-                            const SkPaint& origPaint, SkScalar x, SkScalar y) {
-    SkPaint paint(origPaint);
+                            const SkPaint& paint, SkScalar x, SkScalar y) {
+    SkFont font = SkFont::LEGACY_ExtractFromPaint(paint);
     SkTDArray<uint16_t> glyphs;
 
-    glyphs.append(paint.textToGlyphs(text, len, nullptr));
-    paint.textToGlyphs(text, len, glyphs.begin());
+    glyphs.append(font.countText(text, len, (SkTextEncoding)paint.getTextEncoding()));
+    font.textToGlyphs(text, len, (SkTextEncoding)paint.getTextEncoding(), glyphs.begin(), glyphs.count());
 
-    paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
-    const SkTextBlobBuilder::RunBuffer& run = builder->allocRun(paint, glyphs.count(), x, y,
+    const SkTextBlobBuilder::RunBuffer& run = builder->allocRun(font, glyphs.count(), x, y,
                                                                 nullptr);
     memcpy(run.glyphs, glyphs.begin(), glyphs.count() * sizeof(uint16_t));
 }