start to use font for measure, not paint

-- lots more where this came from

Bug: skia:2664
Change-Id: I8bb47f02c156b0b88fbb92fec73af0eb6641b1bf
Reviewed-on: https://skia-review.googlesource.com/c/173769
Commit-Queue: Mike Reed <reed@google.com>
Reviewed-by: Mike Reed <reed@google.com>
diff --git a/bench/FontCacheBench.cpp b/bench/FontCacheBench.cpp
index beae47a..2eb2b71 100644
--- a/bench/FontCacheBench.cpp
+++ b/bench/FontCacheBench.cpp
@@ -36,15 +36,14 @@
     }
 
     void onDraw(int loops, SkCanvas* canvas) override {
-        SkPaint paint;
-        this->setupPaint(&paint);
-        paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
+        SkFont font;
+        font.setEdging(SkFont::Edging::kAntiAlias);
 
         const uint16_t* array = gUniqueGlyphIDs;
         while (*array != gUniqueGlyphIDs_Sentinel) {
             int count = count_glyphs(array);
             for (int i = 0; i < loops; ++i) {
-                paint.measureText(array, count * sizeof(uint16_t));
+                (void)font.measureText(array, count * sizeof(uint16_t), kGlyphID_SkTextEncoding);
             }
             array += count + 1;    // skip the sentinel
         }
diff --git a/bench/PicturePlaybackBench.cpp b/bench/PicturePlaybackBench.cpp
index 54ecd3c..40dde4b 100644
--- a/bench/PicturePlaybackBench.cpp
+++ b/bench/PicturePlaybackBench.cpp
@@ -17,130 +17,8 @@
 
 // This is designed to emulate about 4 screens of textual content
 
-
-class PicturePlaybackBench : public Benchmark {
-public:
-    PicturePlaybackBench(const char name[])  {
-        fName.printf("picture_playback_%s", name);
-        fPictureWidth = SkIntToScalar(PICTURE_WIDTH);
-        fPictureHeight = SkIntToScalar(PICTURE_HEIGHT);
-        fTextSize = SkIntToScalar(TEXT_SIZE);
-    }
-
-    enum {
-        PICTURE_WIDTH = 1000,
-        PICTURE_HEIGHT = 4000,
-        TEXT_SIZE = 10
-    };
-protected:
-    virtual const char* onGetName() {
-        return fName.c_str();
-    }
-
-    virtual void onDraw(int loops, SkCanvas* canvas) {
-
-        SkPictureRecorder recorder;
-        SkCanvas* pCanvas = recorder.beginRecording(PICTURE_WIDTH, PICTURE_HEIGHT, nullptr, 0);
-        this->recordCanvas(pCanvas);
-        sk_sp<SkPicture> picture(recorder.finishRecordingAsPicture());
-
-        const SkPoint translateDelta = getTranslateDelta(loops);
-
-        for (int i = 0; i < loops; i++) {
-            picture->playback(canvas);
-            canvas->translate(translateDelta.fX, translateDelta.fY);
-        }
-    }
-
-    virtual void recordCanvas(SkCanvas* canvas) = 0;
-    virtual SkPoint getTranslateDelta(int N) {
-        SkIPoint canvasSize = onGetSize();
-        return SkPoint::Make(SkIntToScalar((PICTURE_WIDTH - canvasSize.fX)/N),
-                             SkIntToScalar((PICTURE_HEIGHT- canvasSize.fY)/N));
-    }
-
-    SkString fName;
-    SkScalar fPictureWidth;
-    SkScalar fPictureHeight;
-    SkScalar fTextSize;
-private:
-    typedef Benchmark INHERITED;
-};
-
-
-class TextPlaybackBench : public PicturePlaybackBench {
-public:
-    TextPlaybackBench() : INHERITED("drawText") { }
-protected:
-    void recordCanvas(SkCanvas* canvas) override {
-        SkPaint paint;
-        paint.setTextSize(fTextSize);
-        paint.setColor(SK_ColorBLACK);
-
-        const char* text = "Hamburgefons";
-        size_t len = strlen(text);
-        const SkScalar textWidth = paint.measureText(text, len);
-
-        for (SkScalar x = 0; x < fPictureWidth; x += textWidth) {
-            for (SkScalar y = 0; y < fPictureHeight; y += fTextSize) {
-                canvas->drawText(text, len, x, y, paint);
-            }
-        }
-    }
-private:
-    typedef PicturePlaybackBench INHERITED;
-};
-
-class PosTextPlaybackBench : public PicturePlaybackBench {
-public:
-    PosTextPlaybackBench(bool drawPosH)
-        : INHERITED(drawPosH ? "drawPosTextH" : "drawPosText")
-        , fDrawPosH(drawPosH) { }
-protected:
-    void recordCanvas(SkCanvas* canvas) override {
-        SkPaint paint;
-        paint.setTextSize(fTextSize);
-        paint.setColor(SK_ColorBLACK);
-
-        const char* text = "Hamburgefons";
-        size_t len = strlen(text);
-        const SkScalar textWidth = paint.measureText(text, len);
-
-        SkScalar* adv = new SkScalar[len];
-        paint.getTextWidths(text, len, adv);
-
-        for (SkScalar x = 0; x < fPictureWidth; x += textWidth) {
-            for (SkScalar y = 0; y < fPictureHeight; y += fTextSize) {
-
-                SkPoint* pos = new SkPoint[len];
-                SkScalar advX = 0;
-
-                for (size_t i = 0; i < len; i++) {
-                    if (fDrawPosH)
-                        pos[i].set(x + advX, y);
-                    else
-                        pos[i].set(x + advX, y + i);
-                    advX += adv[i];
-                }
-
-                canvas->drawPosText(text, len, pos, paint);
-                delete[] pos;
-            }
-        }
-        delete[] adv;
-    }
-private:
-    bool fDrawPosH;
-    typedef PicturePlaybackBench INHERITED;
-};
-
-
 ///////////////////////////////////////////////////////////////////////////////
 
-DEF_BENCH( return new TextPlaybackBench(); )
-DEF_BENCH( return new PosTextPlaybackBench(true); )
-DEF_BENCH( return new PosTextPlaybackBench(false); )
-
 // Chrome draws into small tiles with impl-side painting.
 // This benchmark measures the relative performance of our bounding-box hierarchies,
 // both when querying tiles perfectly and when not.
diff --git a/gm/all_bitmap_configs.cpp b/gm/all_bitmap_configs.cpp
index d403fba..33d39cb 100644
--- a/gm/all_bitmap_configs.cpp
+++ b/gm/all_bitmap_configs.cpp
@@ -10,8 +10,9 @@
 #include "gm.h"
 #include "sk_tool_utils.h"
 
-#include "SkMath.h"
 #include "SkColorPriv.h"
+#include "SkFont.h"
+#include "SkMath.h"
 
 static SkBitmap copy_bitmap(const SkBitmap& src, SkColorType colorType) {
     const SkBitmap* srcPtr = &src;
@@ -56,23 +57,21 @@
     return bm;
 }
 
-static void draw_center_letter(char c,
-                               SkPaint* p,
-                               SkColor color,
-                               SkScalar x,
-                               SkScalar y,
-                               SkCanvas* canvas) {
+static void draw_center_letter(char c, const SkFont& font, SkColor color,
+                               SkScalar x, SkScalar y, SkCanvas* canvas) {
+    SkPaint paint;
+    paint.setColor(color);
     SkRect bounds;
-    p->setColor(color);
-    p->measureText(&c, 1, &bounds);
-    canvas->drawText(&c, 1, x - bounds.centerX(), y - bounds.centerY(), *p);
+    font.measureText(&c, 1, kUTF8_SkTextEncoding, &bounds);
+    canvas->drawSimpleText(&c, 1, kUTF8_SkTextEncoding,
+                           x - bounds.centerX(), y - bounds.centerY(),
+                           font, paint);
 }
 
 static void color_wheel_native(SkCanvas* canvas) {
     SkAutoCanvasRestore autoCanvasRestore(canvas, true);
     canvas->translate(0.5f * SCALE, 0.5f * SCALE);
     SkPaint p;
-    p.setAntiAlias(false);
     p.setColor(SK_ColorWHITE);
     canvas->drawCircle(0.0f, 0.0f, SCALE * 0.5f, p);
 
@@ -81,15 +80,18 @@
     const SkScalar D = 0.3f * SkIntToScalar(SCALE);
     const SkScalar X = SkDoubleToScalar(D * sqrt_3_over_2);
     const SkScalar Y = D * SK_ScalarHalf;
-    sk_tool_utils::set_portable_typeface(&p, nullptr, SkFontStyle::Bold());
-    p.setTextSize(0.28125f * SCALE);
-    draw_center_letter('K', &p, SK_ColorBLACK, Z, Z, canvas);
-    draw_center_letter('R', &p, SK_ColorRED, Z, D, canvas);
-    draw_center_letter('G', &p, SK_ColorGREEN, -X, -Y, canvas);
-    draw_center_letter('B', &p, SK_ColorBLUE, X, -Y, canvas);
-    draw_center_letter('C', &p, SK_ColorCYAN, Z, -D, canvas);
-    draw_center_letter('M', &p, SK_ColorMAGENTA, X, Y, canvas);
-    draw_center_letter('Y', &p, SK_ColorYELLOW, -X, Y, canvas);
+
+    SkFont font;
+    font.setEdging(SkFont::Edging::kAlias);
+    font.setTypeface(sk_tool_utils::create_portable_typeface(nullptr, SkFontStyle::Bold()));
+    font.setSize(0.28125f * SCALE);
+    draw_center_letter('K', font, SK_ColorBLACK, Z, Z, canvas);
+    draw_center_letter('R', font, SK_ColorRED, Z, D, canvas);
+    draw_center_letter('G', font, SK_ColorGREEN, -X, -Y, canvas);
+    draw_center_letter('B', font, SK_ColorBLUE, X, -Y, canvas);
+    draw_center_letter('C', font, SK_ColorCYAN, Z, -D, canvas);
+    draw_center_letter('M', font, SK_ColorMAGENTA, X, Y, canvas);
+    draw_center_letter('Y', font, SK_ColorYELLOW, -X, Y, canvas);
 }
 
 template <typename T>
diff --git a/gm/atlastext.cpp b/gm/atlastext.cpp
index cdcd694..9fc7d6c 100644
--- a/gm/atlastext.cpp
+++ b/gm/atlastext.cpp
@@ -15,6 +15,7 @@
 #include "SkAtlasTextTarget.h"
 #include "SkBitmap.h"
 #include "SkCanvas.h"
+#include "SkFont.h"
 #include "SkTypeface.h"
 #include "SkUTF.h"
 #include "gpu/TestContext.h"
@@ -29,18 +30,17 @@
     if (!text.size()) {
         return x;
     }
-    auto font = SkAtlasTextFont::Make(typeface, size);
+    auto atlas_font = SkAtlasTextFont::Make(typeface, size);
     int cnt = SkUTF::CountUTF8(text.c_str(), text.size());
     std::unique_ptr<SkGlyphID[]> glyphs(new SkGlyphID[cnt]);
     typeface->charsToGlyphs(text.c_str(), SkTypeface::Encoding::kUTF8_Encoding, glyphs.get(), cnt);
 
     // Using a paint to get the positions for each glyph.
-    SkPaint paint;
-    paint.setTextSize(size);
-    paint.setTypeface(std::move(typeface));
-    paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
+    SkFont font;
+    font.setSize(size);
+    font.setTypeface(std::move(typeface));
     std::unique_ptr<SkScalar[]> widths(new SkScalar[cnt]);
-    paint.getTextWidths(glyphs.get(), cnt * sizeof(SkGlyphID), widths.get(), nullptr);
+    font.getWidths(glyphs.get(), cnt, widths.get());
 
     std::unique_ptr<SkPoint[]> positions(new SkPoint[cnt]);
     positions[0] = {x, y};
@@ -48,7 +48,7 @@
         positions[i] = {positions[i - 1].fX + widths[i - 1], y};
     }
 
-    target->drawText(glyphs.get(), positions.get(), cnt, color, *font);
+    target->drawText(glyphs.get(), positions.get(), cnt, color, *atlas_font);
 
     // Return the width of the of draw.
     return positions[cnt - 1].fX + widths[cnt - 1] - positions[0].fX;
diff --git a/gm/constcolorprocessor.cpp b/gm/constcolorprocessor.cpp
index 4dd40cf..1079eeb 100644
--- a/gm/constcolorprocessor.cpp
+++ b/gm/constcolorprocessor.cpp
@@ -113,10 +113,12 @@
 
                     // Draw labels for the input to the processor and the processor to the right of
                     // the test rect. The input label appears above the processor label.
+                    SkFont labelFont;
+                    labelFont.setTypeface(sk_tool_utils::create_portable_typeface());
+                    labelFont.setEdging(SkFont::Edging::kAntiAlias);
+                    labelFont.setSize(10.f);
                     SkPaint labelPaint;
-                    sk_tool_utils::set_portable_typeface(&labelPaint);
                     labelPaint.setAntiAlias(true);
-                    labelPaint.setTextSize(10.f);
                     SkString inputLabel;
                     inputLabel.set("Input: ");
                     if (paintType >= SK_ARRAY_COUNT(kPaintColors)) {
@@ -129,21 +131,21 @@
 
                     SkRect inputLabelBounds;
                     // get the bounds of the text in order to position it
-                    labelPaint.measureText(inputLabel.c_str(), inputLabel.size(),
-                                           &inputLabelBounds);
-                    canvas->drawString(inputLabel,
+                    labelFont.measureText(inputLabel.c_str(), inputLabel.size(),
+                                          kUTF8_SkTextEncoding, &inputLabelBounds);
+                    canvas->drawSimpleText(inputLabel.c_str(), inputLabel.size(), kUTF8_SkTextEncoding,
                                      renderRect.fRight + kPad,
-                                     -inputLabelBounds.fTop, labelPaint);
+                                     -inputLabelBounds.fTop, labelFont, labelPaint);
                     // update the bounds to reflect the offset we used to draw it.
                     inputLabelBounds.offset(renderRect.fRight + kPad, -inputLabelBounds.fTop);
 
                     SkRect procLabelBounds;
-                    labelPaint.measureText(procLabel.c_str(), procLabel.size(),
-                                           &procLabelBounds);
-                    canvas->drawString(procLabel,
+                    labelFont.measureText(procLabel.c_str(), procLabel.size(),
+                                          kUTF8_SkTextEncoding, &procLabelBounds);
+                    canvas->drawSimpleText(procLabel.c_str(), procLabel.size(), kUTF8_SkTextEncoding,
                                      renderRect.fRight + kPad,
                                      inputLabelBounds.fBottom + 2.f - procLabelBounds.fTop,
-                                     labelPaint);
+                                     labelFont, labelPaint);
                     procLabelBounds.offset(renderRect.fRight + kPad,
                                            inputLabelBounds.fBottom + 2.f - procLabelBounds.fTop);
 
diff --git a/gm/flippity.cpp b/gm/flippity.cpp
index 1cdc500..a040ba1 100644
--- a/gm/flippity.cpp
+++ b/gm/flippity.cpp
@@ -59,13 +59,16 @@
 // Create a fixed size text label like "LL" or "LR".
 static sk_sp<SkImage> make_text_image(GrContext* context, const char* text, SkColor color) {
     SkPaint paint;
-    sk_tool_utils::set_portable_typeface(&paint);
     paint.setAntiAlias(true);
-    paint.setTextSize(32);
     paint.setColor(color);
 
+    SkFont font;
+    font.setEdging(SkFont::Edging::kAntiAlias);
+    font.setTypeface(sk_tool_utils::create_portable_typeface());
+    font.setSize(32);
+
     SkRect bounds;
-    paint.measureText(text, strlen(text), &bounds);
+    font.measureText(text, strlen(text), kUTF8_SkTextEncoding, &bounds);
     const SkMatrix mat = SkMatrix::MakeRectToRect(bounds, SkRect::MakeWH(kLabelSize, kLabelSize),
                                                   SkMatrix::kFill_ScaleToFit);
 
@@ -76,7 +79,7 @@
 
     canvas->clear(SK_ColorWHITE);
     canvas->concat(mat);
-    canvas->drawText(text, strlen(text), 0, 0, paint);
+    canvas->drawSimpleText(text, strlen(text), kUTF8_SkTextEncoding, 0, 0, font, paint);
 
     sk_sp<SkImage> image = surf->makeImageSnapshot();
 
diff --git a/gm/fontcache.cpp b/gm/fontcache.cpp
index c9c8cf7..44732ab 100644
--- a/gm/fontcache.cpp
+++ b/gm/fontcache.cpp
@@ -21,9 +21,10 @@
 #include "sk_tool_utils.h"
 
 static SkScalar draw_string(SkCanvas* canvas, const SkString& text, SkScalar x,
-                           SkScalar y, const SkPaint& paint) {
-    canvas->drawString(text, x, y, paint);
-    return x + paint.measureText(text.c_str(), text.size());
+                           SkScalar y, const SkFont& font) {
+    SkPaint paint;
+    canvas->drawSimpleText(text.c_str(), text.size(), kUTF8_SkTextEncoding, x, y, font, paint);
+    return x + font.measureText(text.c_str(), text.size(), kUTF8_SkTextEncoding);
 }
 
 class FontCacheGM : public skiagm::GM {
@@ -87,10 +88,9 @@
                                           SkString("abcdefghijklmnopqrstuvwxyz"),
                                           SkString("0123456789"),
                                           SkString("!@#$%^&*()<>[]{}")};
-        SkPaint paint;
-        paint.setAntiAlias(true);
-        paint.setLCDRenderText(false);
-        paint.setSubpixelText(true);
+        SkFont font;
+        font.setEdging(SkFont::Edging::kAntiAlias);
+        font.setSubpixel(true);
 
         static const SkScalar kSubPixelInc = 1 / 2.f;
         SkScalar x = 0;
@@ -106,11 +106,11 @@
         do {
             for (auto s : kSizes) {
                 auto size = 2 * s;
-                paint.setTextSize(size);
+                font.setSize(size);
                 for (const auto& typeface : fTypefaces) {
-                    paint.setTypeface(typeface);
+                    font.setTypeface(typeface);
                     for (const auto& text : kTexts) {
-                        x = size + draw_string(canvas, text, x + subpixelX, y + subpixelY, paint);
+                        x = size + draw_string(canvas, text, x + subpixelX, y + subpixelY, font);
                         x = SkScalarCeilToScalar(x);
                         if (x + 100 > kSize) {
                             x = 0;
diff --git a/include/core/SkPaint.h b/include/core/SkPaint.h
index 20adb1d..74e706a 100644
--- a/include/core/SkPaint.h
+++ b/include/core/SkPaint.h
@@ -968,6 +968,18 @@
     */
     SkScalar getFontSpacing() const { return this->getFontMetrics(nullptr); }
 
+    /** Returns the union of bounds of all glyphs.
+     Returned dimensions are computed by font manager from font data,
+     ignoring SkPaint::Hinting. Includes font metrics, but not fake bold or SkPathEffect.
+
+     If text size is large, text scale is one, and text skew is zero,
+     returns the bounds as:
+     { SkFontMetrics::fXMin, SkFontMetrics::fTop, SkFontMetrics::fXMax, SkFontMetrics::fBottom }.
+
+     @return  union of bounds of all glyphs
+     */
+    SkRect getFontBounds() const;
+
     /** Converts text into glyph indices.
         Returns the number of glyph indices represented by text.
         SkPaint::TextEncoding specifies how text represents characters or glyphs.
@@ -1004,6 +1016,7 @@
         @return            true if all text corresponds to a non-zero glyph index
     */
     bool containsText(const void* text, size_t byteLength) const;
+#endif
 
     /** Converts glyphs into text if possible.
         Glyph values without direct Unicode equivalents are mapped to zero.
@@ -1018,6 +1031,7 @@
     */
     void glyphsToUnichars(const SkGlyphID glyphs[], int count, SkUnichar text[]) const;
 
+#ifdef SK_SUPPORT_LEGACY_PAINT_TEXTMEASURE
     /** Returns the number of glyphs in text.
         Uses SkPaint::TextEncoding to count the glyphs.
         Returns the same result as textToGlyphs().
@@ -1124,6 +1138,7 @@
     */
     void getPosTextPath(const void* text, size_t length,
                         const SkPoint pos[], SkPath* path) const;
+#endif
 
 #ifdef SK_SUPPORT_LEGACY_TEXTINTERCEPTS
 public:
@@ -1221,19 +1236,6 @@
     int getTextBlobIntercepts(const SkTextBlob* blob, const SkScalar bounds[2],
                               SkScalar* intervals) const;
 
-    /** Returns the union of bounds of all glyphs.
-        Returned dimensions are computed by font manager from font data,
-        ignoring SkPaint::Hinting. Includes font metrics, but not fake bold or SkPathEffect.
-
-        If text size is large, text scale is one, and text skew is zero,
-        returns the bounds as:
-        { SkFontMetrics::fXMin, SkFontMetrics::fTop, SkFontMetrics::fXMax, SkFontMetrics::fBottom }.
-
-        @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/tools/fonts/create_test_font.cpp b/tools/fonts/create_test_font.cpp
index f782dc8..51a2881 100644
--- a/tools/fonts/create_test_font.cpp
+++ b/tools/fonts/create_test_font.cpp
@@ -9,10 +9,11 @@
 // and ./tools/fonts/test_font_<generic name>.inc which are read by
 // ./tools/fonts/SkTestFontMgr.cpp
 
+#include "SkFont.h"
+#include "SkFontMetrics.h"
 #include "SkFontStyle.h"
 #include "SkOSFile.h"
 #include "SkOSPath.h"
-#include "SkPaint.h"
 #include "SkPath.h"
 #include "SkSpan.h"
 #include "SkStream.h"
@@ -120,15 +121,13 @@
     return count;
 }
 
-static void output_path_data(const SkPaint& paint,
+static void output_path_data(const SkFont& font,
         int emSize, SkString* ptsOut, SkTDArray<SkPath::Verb>* verbs,
         SkTDArray<unsigned>* charCodes, SkTDArray<SkScalar>* widths) {
     for (SkUnichar index = 0x00; index < 0x7f; ++index) {
-        uint16_t utf16[2];
-        size_t utf16Bytes = sizeof(uint16_t) * SkUTF::ToUTF16(index, utf16);
+        uint16_t glyphID = font.unicharToGlyph(index);
         SkPath path;
-        SkASSERT(paint.getTextEncoding() == SkPaint::kUTF16_TextEncoding);
-        paint.getTextPath(utf16, utf16Bytes, 0, 0, &path);
+        font.getPath(glyphID, &path);
         SkPath::RawIter iter(path);
         SkPath::Verb verb;
         SkPoint pts[4];
@@ -157,8 +156,7 @@
         *verbs->append() = SkPath::kDone_Verb;
         *charCodes->append() = index;
         SkScalar width;
-        SkDEBUGCODE(int charCount =) paint.getTextWidths(utf16, utf16Bytes, &width);
-        SkASSERT(charCount == 1);
+        font.getWidths(&glyphID, 1, &width);
      // SkASSERT(floor(width) == width);  // not true for Hiragino Maru Gothic Pro
         *widths->append() = width;
         if (0 == index) {
@@ -195,17 +193,17 @@
 }
 
 static void output_font(sk_sp<SkTypeface> face, const char* identifier, FILE* out) {
-    int emSize = face->getUnitsPerEm() * 2;
-    SkPaint paint;
-    paint.setAntiAlias(true);
-    paint.setTextEncoding(SkPaint::kUTF16_TextEncoding);
-    paint.setTextSize(emSize);
-    paint.setTypeface(std::move(face));
+    const int emSize = face->getUnitsPerEm() * 2;
+    SkFont font;
+    font.setEdging(SkFont::Edging::kAntiAlias);
+    font.setSize(emSize);
+    font.setTypeface(std::move(face));
+
     SkTDArray<SkPath::Verb> verbs;
     SkTDArray<unsigned> charCodes;
     SkTDArray<SkScalar> widths;
     SkString ptsOut;
-    output_path_data(paint, emSize, &ptsOut, &verbs, &charCodes, &widths);
+    output_path_data(font, emSize, &ptsOut, &verbs, &charCodes, &widths);
     fprintf(out, "const SkScalar %sPoints[] = {\n", identifier);
     ptsOut = strip_final(ptsOut);
     fprintf(out, "%s", ptsOut.c_str());
@@ -263,7 +261,7 @@
             identifier, identifier);
 
     SkFontMetrics metrics;
-    paint.getFontMetrics(&metrics);
+    font.getMetrics(&metrics);
     fprintf(out, "const SkFontMetrics %sMetrics = {\n", identifier);
     SkString metricsStr;
     metricsStr.printf("0x%08x, ", metrics.fFlags);