start to hide textparams on SkPaint

Bug: skia:
Change-Id: Id73c983cc71d39fe587d355e690261627fa63aee
Reviewed-on: https://skia-review.googlesource.com/c/172643
Reviewed-by: Mike Reed <reed@google.com>
Commit-Queue: Mike Reed <reed@google.com>
diff --git a/bench/CmapBench.cpp b/bench/CmapBench.cpp
index 49e89be..a89d1aa 100644
--- a/bench/CmapBench.cpp
+++ b/bench/CmapBench.cpp
@@ -7,58 +7,49 @@
 
 #include "Benchmark.h"
 #include "SkCanvas.h"
-#include "SkPaint.h"
+#include "SkFont.h"
 #include "SkTypeface.h"
 
 enum {
     NGLYPHS = 100
 };
 
-static SkTypeface::Encoding paint2Encoding(const SkPaint& paint) {
-    SkPaint::TextEncoding enc = paint.getTextEncoding();
-    SkASSERT(SkPaint::kGlyphID_TextEncoding != enc);
-    return (SkTypeface::Encoding)enc;
-}
-
-typedef void (*TypefaceProc)(int loops, const SkPaint&, const void* text, size_t len,
+typedef void (*TypefaceProc)(int loops, const SkFont&, const void* text, size_t len,
                              int glyphCount);
 
-static void containsText_proc(int loops, const SkPaint& paint, const void* text, size_t len,
+static void containsText_proc(int loops, const SkFont& font, const void* text, size_t len,
                               int glyphCount) {
     for (int i = 0; i < loops; ++i) {
-        paint.containsText(text, len);
+        font.containsText(text, len, kUTF8_SkTextEncoding);
     }
 }
 
-static void textToGlyphs_proc(int loops, const SkPaint& paint, const void* text, size_t len,
+static void textToGlyphs_proc(int loops, const SkFont& font, const void* text, size_t len,
                               int glyphCount) {
     uint16_t glyphs[NGLYPHS];
     SkASSERT(glyphCount <= NGLYPHS);
 
     for (int i = 0; i < loops; ++i) {
-        paint.textToGlyphs(text, len, glyphs);
+        font.textToGlyphs(text, len, kUTF8_SkTextEncoding, glyphs, NGLYPHS);
     }
 }
 
-static void charsToGlyphs_proc(int loops, const SkPaint& paint, const void* text,
+static void charsToGlyphs_proc(int loops, const SkFont& font, const void* text,
                                size_t len, int glyphCount) {
-    SkTypeface::Encoding encoding = paint2Encoding(paint);
     uint16_t glyphs[NGLYPHS];
     SkASSERT(glyphCount <= NGLYPHS);
 
-    SkTypeface* face = paint.getTypeface();
+    SkTypeface* face = font.getTypeface();
     for (int i = 0; i < loops; ++i) {
-        face->charsToGlyphs(text, encoding, glyphs, glyphCount);
+        face->charsToGlyphs(text, SkTypeface::kUTF8_Encoding, glyphs, glyphCount);
     }
 }
 
-static void charsToGlyphsNull_proc(int loops, const SkPaint& paint, const void* text,
+static void charsToGlyphsNull_proc(int loops, const SkFont& font, const void* text,
                                    size_t len, int glyphCount) {
-    SkTypeface::Encoding encoding = paint2Encoding(paint);
-
-    SkTypeface* face = paint.getTypeface();
+    SkTypeface* face = font.getTypeface();
     for (int i = 0; i < loops; ++i) {
-        face->charsToGlyphs(text, encoding, nullptr, glyphCount);
+        face->charsToGlyphs(text, SkTypeface::kUTF8_Encoding, nullptr, glyphCount);
     }
 }
 
@@ -66,7 +57,7 @@
     TypefaceProc fProc;
     SkString     fName;
     char         fText[NGLYPHS];
-    SkPaint      fPaint;
+    SkFont       fFont;
 
 public:
     CMAPBench(TypefaceProc proc, const char name[]) {
@@ -77,7 +68,7 @@
             // we're jamming values into utf8, so we must keep it legal utf8
             fText[i] = 'A' + (i & 31);
         }
-        fPaint.setTypeface(SkTypeface::MakeDefault());
+        fFont.setTypeface(SkTypeface::MakeDefault());
     }
 
 protected:
@@ -86,7 +77,7 @@
     }
 
     void onDraw(int loops, SkCanvas* canvas) override {
-        fProc(loops, fPaint, fText, sizeof(fText), NGLYPHS);
+        fProc(loops, fFont, fText, sizeof(fText), NGLYPHS);
     }
 
 private:
diff --git a/bench/TextBench.cpp b/bench/TextBench.cpp
index c28f5d7..881e78a 100644
--- a/bench/TextBench.cpp
+++ b/bench/TextBench.cpp
@@ -15,6 +15,8 @@
 #include "SkTemplates.h"
 #include "SkTypeface.h"
 
+#ifdef SK_SUPPORT_LEGACY_PAINT_TEXTMEASURE
+
 enum FontQuality {
     kBW,
     kAA,
@@ -175,3 +177,5 @@
 
 DEF_BENCH( return new TextBench(STR, 16, 0xFF000000, kBW, true, true); )
 DEF_BENCH( return new TextBench(STR, 16, 0xFF000000, kAA, false, true); )
+
+#endif
diff --git a/fuzz/FuzzCanvas.cpp b/fuzz/FuzzCanvas.cpp
index aea7405..7ba1961 100644
--- a/fuzz/FuzzCanvas.cpp
+++ b/fuzz/FuzzCanvas.cpp
@@ -877,19 +877,21 @@
     }
 }
 
-static void fuzz_paint_text(Fuzz* fuzz, SkPaint* paint) {
-    paint->setTypeface(          make_fuzz_typeface(fuzz));
-    paint->setTextSize(          make_fuzz_t<SkScalar>(fuzz));
-    paint->setTextScaleX(        make_fuzz_t<SkScalar>(fuzz));
-    paint->setTextSkewX(         make_fuzz_t<SkScalar>(fuzz));
-    paint->setLinearText(        make_fuzz_t<bool>(fuzz));
-    paint->setSubpixelText(      make_fuzz_t<bool>(fuzz));
-    paint->setLCDRenderText(     make_fuzz_t<bool>(fuzz));
-    paint->setEmbeddedBitmapText(make_fuzz_t<bool>(fuzz));
-    paint->setAutohinted(        make_fuzz_t<bool>(fuzz));
-    paint->setFakeBoldText(      make_fuzz_t<bool>(fuzz));
-    paint->setHinting(           make_fuzz_t_range<SkFontHinting>(fuzz, 0,
-                                                                     kFull_SkFontHinting));
+static SkFont fuzz_font(Fuzz* fuzz) {
+    SkFont font;
+    font.setTypeface(           make_fuzz_typeface(fuzz));
+    font.setSize(               make_fuzz_t<SkScalar>(fuzz));
+    font.setScaleX(             make_fuzz_t<SkScalar>(fuzz));
+    font.setSkewX(              make_fuzz_t<SkScalar>(fuzz));
+    font.setLinearMetrics(      make_fuzz_t<bool>(fuzz));
+    font.setSubpixel(           make_fuzz_t<bool>(fuzz));
+    font.setEmbeddedBitmaps(    make_fuzz_t<bool>(fuzz));
+    font.setForceAutoHinting(   make_fuzz_t<bool>(fuzz));
+    font.setEmbolden(           make_fuzz_t<bool>(fuzz));
+    font.setHinting(            make_fuzz_t_range<SkFontHinting>(fuzz, 0, kFull_SkFontHinting));
+    font.setEdging(             make_fuzz_t_range<SkFont::Edging>(fuzz, 0,
+                                                      (int)SkFont::Edging::kSubpixelAntiAlias));
+    return font;
 }
 
 static SkTextEncoding fuzz_paint_text_encoding(Fuzz* fuzz) {
@@ -1041,6 +1043,7 @@
             return;
         }
         SkPaint paint;
+        SkFont font;
         unsigned drawCommand;
         fuzz->nextRange(&drawCommand, 0, 53);
         switch (drawCommand) {
@@ -1463,25 +1466,29 @@
             }
             case 45: {
                 fuzz_paint(fuzz, &paint, depth - 1);
-                fuzz_paint_text(fuzz, &paint);
-                paint.setTextEncoding(fuzz_paint_text_encoding(fuzz));
+                font = fuzz_font(fuzz);
+                SkTextEncoding encoding = fuzz_paint_text_encoding(fuzz);
                 SkScalar x, y;
                 fuzz->next(&x, &y);
-                SkTDArray<uint8_t> text = make_fuzz_text(fuzz, paint);
-                canvas->drawText(text.begin(), SkToSizeT(text.count()), x, y, paint);
+                SkTDArray<uint8_t> text = make_fuzz_text(fuzz, font, encoding);
+                canvas->drawSimpleText(text.begin(), SkToSizeT(text.count()), encoding, x, y,
+                                       font, paint);
                 break;
             }
+#ifdef SK_SUPPORT_LEGACY_FONTMETRICS_IN_PAINT
             case 46: {
                 fuzz_paint(fuzz, &paint, depth - 1);
-                fuzz_paint_text(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()));
+                font = fuzz_font(fuzz);
+                SkTextEncoding encoding = fuzz_paint_text_encoding(fuzz);
+                SkTDArray<uint8_t> text = make_fuzz_text(fuzz, font, encoding);
+                int glyphCount = font.countText(text.begin(), SkToSizeT(text.count()), encoding);
                 if (glyphCount < 1) {
                     break;
                 }
                 SkAutoTMalloc<SkPoint> pos(glyphCount);
                 SkAutoTMalloc<SkScalar> widths(glyphCount);
+                font.LEGACY_applyToPaint(&paint);
+                paint.setTextEncoding(encoding);
                 paint.getTextWidths(text.begin(), SkToSizeT(text.count()), widths.get());
                 pos[0] = {0, 0};
                 for (int i = 1; i < glyphCount; ++i) {
@@ -1494,14 +1501,16 @@
             }
             case 47: {
                 fuzz_paint(fuzz, &paint, depth - 1);
-                fuzz_paint_text(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()));
+                font = fuzz_font(fuzz);
+                SkTextEncoding encoding = fuzz_paint_text_encoding(fuzz);
+                SkTDArray<uint8_t> text = make_fuzz_text(fuzz, font, encoding);
+                int glyphCount = font.countText(text.begin(), SkToSizeT(text.count()), encoding);
                 SkAutoTMalloc<SkScalar> widths(glyphCount);
                 if (glyphCount < 1) {
                     break;
                 }
+                font.LEGACY_applyToPaint(&paint);
+                paint.setTextEncoding(encoding);
                 paint.getTextWidths(text.begin(), SkToSizeT(text.count()), widths.get());
                 SkScalar x = widths[0];
                 for (int i = 0; i < glyphCount; ++i) {
@@ -1518,6 +1527,7 @@
                 canvas->drawPosTextH(text.begin(), SkToSizeT(text.count()), widths.get(), y, paint);
                 break;
             }
+#endif
             case 48: {
                 // was drawtextonpath
                 break;
@@ -1526,13 +1536,14 @@
                 // was drawtextonpath
                 break;
             }
+#ifdef SK_SUPPORT_LEGACY_FONTMETRICS_IN_PAINT
             case 50: {
                 fuzz_paint(fuzz, &paint, depth - 1);
-                fuzz_paint_text(fuzz, &paint);
-                paint.setTextEncoding(fuzz_paint_text_encoding(fuzz));
+                font = fuzz_font(fuzz);
+                SkTextEncoding encoding = 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()));
+                int glyphCount = font.countText(text.begin(), SkToSizeT(text.count()), encoding);
                 SkASSERT(glyphCount <= kMaxGlyphCount);
                 fuzz->nextN(rSXform, glyphCount);
                 SkRect cullRect;
@@ -1541,10 +1552,13 @@
                 if (useCullRect) {
                     fuzz->next(&cullRect);
                 }
+                font.LEGACY_applyToPaint(&paint);
+                paint.setTextEncoding(encoding);
                 canvas->drawTextRSXform(text.begin(), SkToSizeT(text.count()), rSXform,
                                         useCullRect ? &cullRect : nullptr, paint);
                 break;
             }
+#endif
             case 51: {
                 sk_sp<SkTextBlob> blob = make_fuzz_textblob(fuzz);
                 fuzz_paint(fuzz, &paint, depth - 1);
diff --git a/include/core/SkCanvas.h b/include/core/SkCanvas.h
index 6177349..c0d005f 100644
--- a/include/core/SkCanvas.h
+++ b/include/core/SkCanvas.h
@@ -36,6 +36,7 @@
 class SkDraw;
 class SkDrawable;
 struct SkDrawShadowRec;
+class SkFont;
 class SkGlyphRunBuilder;
 class SkImage;
 class SkImageFilter;
@@ -1877,6 +1878,10 @@
     void drawText(const void* text, size_t byteLength, SkScalar x, SkScalar y,
                   const SkPaint& paint);
 
+    // Experimental
+    void drawSimpleText(const void* text, size_t byteLength, SkTextEncoding encoding,
+                        SkScalar x, SkScalar y, const SkFont& font, const SkPaint& paint);
+
     /** Draws null terminated string, with origin at (x, y), using clip, SkMatrix, and
         SkPaint paint.
 
diff --git a/include/core/SkFont.h b/include/core/SkFont.h
index ade29f3..edf1699 100644
--- a/include/core/SkFont.h
+++ b/include/core/SkFont.h
@@ -291,6 +291,23 @@
         return this->textToGlyphs(text, byteLength, encoding, nullptr, 0);
     }
 
+    /** Returns true if all text corresponds to a non-zero glyph index.
+        Returns false if any characters in text are not supported in
+        SkTypeface.
+
+        If SkTextEncoding is kGlyphID_SkTextEncoding,
+        returns true if all glyph indices in text are non-zero;
+        does not check to see if text contains valid glyph indices for SkTypeface.
+
+        Returns true if byteLength is zero.
+
+        @param text        array of characters or glyphs
+        @param byteLength  number of bytes in text array
+        @param encoding    text encoding
+        @return            true if all text corresponds to a non-zero glyph index
+     */
+    bool containsText(const void* text, size_t byteLength, SkTextEncoding encoding) const;
+
     /** Returns the advance width of text.
         The advance is the normal distance to move before drawing additional text.
         Returns the bounding box of text if bounds is not nullptr.
diff --git a/include/core/SkPaint.h b/include/core/SkPaint.h
index 71492d3..f9faee8 100644
--- a/include/core/SkPaint.h
+++ b/include/core/SkPaint.h
@@ -54,6 +54,10 @@
 class SkTextBlobRunIterator;
 class SkTypeface;
 
+#ifndef SK_SUPPORT_LEGACY_PAINT_TEXTMEASURE
+#define SK_SUPPORT_LEGACY_PAINT_TEXTMEASURE
+#endif
+
 /** \class SkPaint
     SkPaint controls options applied when drawing and measuring. SkPaint collects all
     options outside of the SkCanvas clip and SkCanvas matrix.
@@ -953,6 +957,8 @@
         this->setTextEncoding((TextEncoding)encoding);
     }
 
+#ifdef SK_SUPPORT_LEGACY_PAINT_TEXTMEASURE
+
 #ifdef SK_SUPPORT_LEGACY_FONTMETRICS_IN_PAINT
     /**
         SkFontMetrics is filled out by getFontMetrics(). SkFontMetrics contents reflect the values
@@ -1083,6 +1089,7 @@
     SkScalar measureText(const void* text, size_t length) const {
         return this->measureText(text, length, nullptr);
     }
+#endif
 
     /** Returns the bytes of text that fit within maxWidth.
         The text fragment fits if its advance width is less than or equal to maxWidth.
@@ -1101,6 +1108,7 @@
     size_t  breakText(const void* text, size_t length, SkScalar maxWidth,
                       SkScalar* measuredWidth = nullptr) const;
 
+#ifdef SK_SUPPORT_LEGACY_PAINT_TEXTMEASURE
     /** Retrieves the advance and bounds for each glyph in text, and returns
         the glyph count in text.
         Both widths and bounds may be nullptr.
@@ -1257,6 +1265,7 @@
         @return  union of bounds of all glyphs
     */
     SkRect getFontBounds() const;
+#endif
 
     /** Returns true if SkPaint prevents all drawing;
         otherwise, the SkPaint may or may not allow drawing.
diff --git a/src/core/SkCanvas.cpp b/src/core/SkCanvas.cpp
index 0ff997c..f976d71 100644
--- a/src/core/SkCanvas.cpp
+++ b/src/core/SkCanvas.cpp
@@ -2555,7 +2555,17 @@
     this->drawText(string.c_str(), string.size(), x, y, paint);
 }
 
-// These will become non-virtual, so they always call the (virtual) onDraw... method
+// These call the (virtual) onDraw... method
+void SkCanvas::drawSimpleText(const void* text, size_t byteLength, SkTextEncoding,
+                              SkScalar x, SkScalar y, const SkFont& font, const SkPaint& paint) {
+    TRACE_EVENT0("skia", TRACE_FUNC);
+    if (byteLength) {
+        sk_msan_assert_initialized(text, SkTAddOffset<const void>(text, byteLength));
+        SkPaint tmp(paint);
+        font.LEGACY_applyToPaint(&tmp);
+        this->onDrawText(text, byteLength, x, y, tmp);
+    }
+}
 void SkCanvas::drawText(const void* text, size_t byteLength, SkScalar x, SkScalar y,
                         const SkPaint& paint) {
     TRACE_EVENT0("skia", TRACE_FUNC);
diff --git a/src/core/SkFont.cpp b/src/core/SkFont.cpp
index 93de69d..4a29fea 100644
--- a/src/core/SkFont.cpp
+++ b/src/core/SkFont.cpp
@@ -16,6 +16,7 @@
 #include "SkTLazy.h"
 #include "SkTypeface.h"
 #include "SkUTF.h"
+#include "SkUtils.h"
 
 #define kDefault_Size       12
 #define kDefault_Flags      0
@@ -193,6 +194,43 @@
     return count;
 }
 
+static SkTypeface::Encoding to_encoding(SkTextEncoding e) {
+    static_assert((int)SkTypeface::kUTF8_Encoding  == (int)kUTF8_SkTextEncoding,  "");
+    static_assert((int)SkTypeface::kUTF16_Encoding == (int)kUTF16_SkTextEncoding, "");
+    static_assert((int)SkTypeface::kUTF32_Encoding == (int)kUTF32_SkTextEncoding, "");
+    return (SkTypeface::Encoding)e;
+}
+
+bool SkFont::containsText(const void* textData, size_t byteLength, SkTextEncoding textEnc) const {
+    if (0 == byteLength) {
+        return true;
+    }
+
+    SkASSERT(textData != nullptr);
+
+    // handle this encoding before the setup for the glyphcache
+    if (textEnc == kGlyphID_SkTextEncoding) {
+        const uint16_t* glyphID = static_cast<const uint16_t*>(textData);
+        size_t count = byteLength >> 1;
+        for (size_t i = 0; i < count; i++) {
+            if (0 == glyphID[i]) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    auto cache = SkStrikeCache::FindOrCreateStrikeWithNoDeviceExclusive(*this);
+    const void* stop = (const char*)textData + byteLength;
+    const SkTypeface::Encoding encoding = to_encoding(textEnc);
+    while (textData < stop) {
+        if (0 == cache->unicharToGlyph(SkUTFN_Next(encoding, &textData, stop))) {
+            return false;
+        }
+    }
+    return true;
+}
+
 static void set_bounds(const SkGlyph& g, SkRect* bounds) {
     bounds->set(SkIntToScalar(g.fLeft),
                 SkIntToScalar(g.fTop),