DM FontMgr updates

  - return nullptr for the various makeFromFoo() that we can't support,
    and tweak a few unit tests to bail out early when they do

  - create FontStyleSet and SkTypefaces once

  - abort early from FontHostStream if we can't openStream()

  - implement SkTestTypeface::onCreateFamilyNameIterator()
    with SkOTUtils::LocalizedStrings_SingleName() so FontNames passes

  - pin out-of-range glyph IDs to zero in SkTestTypeface

Change-Id: Iac53265e331fc1c5c507513af3ab299063e6610a
Reviewed-on: https://skia-review.googlesource.com/69501
Reviewed-by: Ben Wagner <bungeman@google.com>
Commit-Queue: Mike Klein <mtklein@chromium.org>
diff --git a/dm/DMFontMgr.cpp b/dm/DMFontMgr.cpp
index 51ee612..d275c41 100644
--- a/dm/DMFontMgr.cpp
+++ b/dm/DMFontMgr.cpp
@@ -17,10 +17,18 @@
         "Toy Liberation Mono",
     };
 
-    FontStyleSet::FontStyleSet(int familyIndex) : fFamilyName(kFamilyNames[familyIndex]) {}
+    FontStyleSet::FontStyleSet(int familyIndex) {
+        using sk_tool_utils::create_portable_typeface;
+        const char* familyName = kFamilyNames[familyIndex];
 
-    // Each font family has 4 styles: Normal, Bold, Italic, BoldItalic.
+        fTypefaces[0] = create_portable_typeface(familyName, SkFontStyle::Normal());
+        fTypefaces[1] = create_portable_typeface(familyName, SkFontStyle::Bold());
+        fTypefaces[2] = create_portable_typeface(familyName, SkFontStyle::Italic());
+        fTypefaces[3] = create_portable_typeface(familyName, SkFontStyle::BoldItalic());
+    }
+
     int FontStyleSet::count() { return 4; }
+
     void FontStyleSet::getStyle(int index, SkFontStyle* style, SkString* name) {
         switch (index) {
             default:
@@ -39,27 +47,30 @@
         }
     }
 
-    SkTypeface* FontStyleSet::matchStyle(const SkFontStyle& style) {
-        return this->matchStyleCSS3(style);
+    SkTypeface* FontStyleSet::createTypeface(int index) {
+        return SkRef(fTypefaces[index].get());
     }
 
-    SkTypeface* FontStyleSet::createTypeface(int index) {
-        SkFontStyle style;
-        this->getStyle(index, &style, nullptr);
-
-        return sk_tool_utils::create_portable_typeface(fFamilyName, style).release();
+    SkTypeface* FontStyleSet::matchStyle(const SkFontStyle& pattern) {
+        return this->matchStyleCSS3(pattern);
     }
 
     // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //
 
-    int FontMgr::onCountFamilies() const { return SK_ARRAY_COUNT(kFamilyNames); }
+    FontMgr::FontMgr() {
+        fFamilies[0] = sk_make_sp<FontStyleSet>(0);
+        fFamilies[1] = sk_make_sp<FontStyleSet>(1);
+        fFamilies[2] = sk_make_sp<FontStyleSet>(2);
+    }
+
+    int FontMgr::onCountFamilies() const { return SK_ARRAY_COUNT(fFamilies); }
 
     void FontMgr::onGetFamilyName(int index, SkString* familyName) const {
         *familyName = kFamilyNames[index];
     }
 
     SkFontStyleSet* FontMgr::onCreateStyleSet(int index) const {
-        return new FontStyleSet(index);
+        return SkRef(fFamilies[index].get());
     }
 
     SkFontStyleSet* FontMgr::onMatchFamily(const char familyName[]) const {
@@ -96,25 +107,25 @@
     }
 
     sk_sp<SkTypeface> FontMgr::onMakeFromData(sk_sp<SkData>, int ttcIndex) const {
-        return sk_sp<SkTypeface>(this->matchFamilyStyle("Sans", SkFontStyle::Normal()));
+        return nullptr;
     }
 
     sk_sp<SkTypeface> FontMgr::onMakeFromStreamIndex(std::unique_ptr<SkStreamAsset>,
                                                      int ttcIndex) const {
-        return sk_sp<SkTypeface>(this->matchFamilyStyle("Sans", SkFontStyle::Normal()));
+        return nullptr;
     }
 
     sk_sp<SkTypeface> FontMgr::onMakeFromStreamArgs(std::unique_ptr<SkStreamAsset>,
                                                     const SkFontArguments&) const {
-        return sk_sp<SkTypeface>(this->matchFamilyStyle("Sans", SkFontStyle::Normal()));
+        return nullptr;
     }
 
     sk_sp<SkTypeface> FontMgr::onMakeFromFontData(std::unique_ptr<SkFontData>) const {
-        return sk_sp<SkTypeface>(this->matchFamilyStyle("Sans", SkFontStyle::Normal()));
+        return nullptr;
     }
 
     sk_sp<SkTypeface> FontMgr::onMakeFromFile(const char path[], int ttcIndex) const {
-        return sk_sp<SkTypeface>(this->matchFamilyStyle("Sans", SkFontStyle::Normal()));
+        return nullptr;
     }
 
     sk_sp<SkTypeface> FontMgr::onLegacyMakeTypeface(const char familyName[],
diff --git a/dm/DMFontMgr.h b/dm/DMFontMgr.h
index b2eb0ac..c484644 100644
--- a/dm/DMFontMgr.h
+++ b/dm/DMFontMgr.h
@@ -14,7 +14,6 @@
 
 namespace DM {
 
-    // Returned by DM::FontMgr below.
     class FontStyleSet final : public SkFontStyleSet {
     public:
         explicit FontStyleSet(int familyIndex);
@@ -25,10 +24,12 @@
         SkTypeface* matchStyle(const SkFontStyle& pattern) override;
 
     private:
-        const char* fFamilyName;
+        sk_sp<SkTypeface> fTypefaces[4];
     };
 
-    struct FontMgr final : public SkFontMgr {
+    class FontMgr final : public SkFontMgr {
+    public:
+        FontMgr();
 
         int onCountFamilies() const override;
         void onGetFamilyName(int index, SkString* familyName) const override;
@@ -54,6 +55,9 @@
         sk_sp<SkTypeface> onMakeFromFile(const char path[], int ttcIndex) const override;
 
         sk_sp<SkTypeface> onLegacyMakeTypeface(const char familyName[], SkFontStyle) const override;
+
+    private:
+        sk_sp<FontStyleSet> fFamilies[3];
     };
 
 }  // namespace DM
diff --git a/src/fonts/SkTestScalerContext.cpp b/src/fonts/SkTestScalerContext.cpp
index ec53c54..34ec6af 100644
--- a/src/fonts/SkTestScalerContext.cpp
+++ b/src/fonts/SkTestScalerContext.cpp
@@ -13,6 +13,7 @@
 #include "SkGlyph.h"
 #include "SkMakeUnique.h"
 #include "SkMask.h"
+#include "SkOTUtils.h"
 #include "SkPaintPriv.h"
 #include "SkScalerContext.h"
 #include "SkTestScalerContext.h"
@@ -133,13 +134,17 @@
 }
 
 void SkTestTypeface::getMetrics(SkGlyph* glyph) {
+    SkGlyphID glyphID = glyph->getGlyphID();
+    glyphID = glyphID < fTestFont->fCharCodesCount ? glyphID : 0;
+
     // TODO(benjaminwagner): Update users to use floats.
-    glyph->fAdvanceX = SkFixedToFloat(fTestFont->fWidths[glyph->getGlyphID()]);
+    glyph->fAdvanceX = SkFixedToFloat(fTestFont->fWidths[glyphID]);
     glyph->fAdvanceY = 0;
 }
 
-void SkTestTypeface::getPath(SkGlyphID glyph, SkPath* path) {
-    *path = *fTestFont->fPaths[glyph];
+void SkTestTypeface::getPath(SkGlyphID glyphID, SkPath* path) {
+    glyphID = glyphID < fTestFont->fCharCodesCount ? glyphID : 0;
+    *path = *fTestFont->fPaths[glyphID];
 }
 
 void SkTestTypeface::onFilterRec(SkScalerContextRec* rec) const {
@@ -183,9 +188,7 @@
 SkTypeface::LocalizedStrings* SkTestTypeface::onCreateFamilyNameIterator() const {
     SkString familyName(fTestFont->fName);
     SkString language("und"); //undetermined
-//SkASSERT(0);  // incomplete
-    return nullptr;
-//     return new SkOTUtils::LocalizedStrings_SingleName(familyName, language);
+    return new SkOTUtils::LocalizedStrings_SingleName(familyName, language);
 }
 
 class SkTestScalerContext : public SkScalerContext {
diff --git a/tests/FontHostStreamTest.cpp b/tests/FontHostStreamTest.cpp
index c3bc878..e97ea0d 100644
--- a/tests/FontHostStreamTest.cpp
+++ b/tests/FontHostStreamTest.cpp
@@ -88,6 +88,12 @@
                                                        : SkTypeface::MakeDefault());
         int ttcIndex;
         std::unique_ptr<SkStreamAsset> fontData(typeface->openStream(&ttcIndex));
+        if (!fontData) {
+            // We're using a SkTypeface that can't give us a stream.
+            // This happens with portable or system fonts.  End the test now.
+            return;
+        }
+
         sk_sp<SkTypeface> streamTypeface(SkTypeface::MakeFromStream(fontData.release()));
 
         SkFontDescriptor desc;
diff --git a/tests/TypefaceTest.cpp b/tests/TypefaceTest.cpp
index 6175d36..c8e96c5 100644
--- a/tests/TypefaceTest.cpp
+++ b/tests/TypefaceTest.cpp
@@ -50,7 +50,10 @@
     os2Table->usWidthClass.value = static_cast<WidthType>(SkEndian_SwapBE16(width));
 
     sk_sp<SkTypeface> newTypeface(SkTypeface::MakeFromStream(new SkMemoryStream(sk_ref_sp(data))));
-    SkASSERT_RELEASE(newTypeface);
+    if (!newTypeface) {
+        // Not all SkFontMgr can MakeFromStream().
+        return;
+    }
 
     SkFontStyle newStyle = newTypeface->fontStyle();
 
@@ -111,6 +114,11 @@
     // TODO: if axes are set and the back-end doesn't support them, should we create the typeface?
     sk_sp<SkTypeface> typeface = fm->makeFromStream(std::move(distortable), params);
 
+    if (!typeface) {
+        // Not all SkFontMgr can makeFromStream().
+        return;
+    }
+
     int count = typeface->getVariationDesignPosition(nullptr, 0);
     if (count == -1) {
         return;