Split custom font managers.
authorBen Wagner <bungeman@google.com>
Wed, 8 Feb 2017 22:29:33 +0000 (17:29 -0500)
committerSkia Commit-Bot <skia-commit-bot@chromium.org>
Thu, 9 Feb 2017 14:50:05 +0000 (14:50 +0000)
Some users would like to use the empty font manager, but the directory
gont manager brings in extra dependencies to work which would otherwise
be unneeded. Allow these users to build just the bits of code they
actually need.

Change-Id: Ib029ef2682883509bad5a2aa39f1ef55631f4d8a
Reviewed-on: https://skia-review.googlesource.com/8200
Reviewed-by: Mike Reed <reed@google.com>
Commit-Queue: Ben Wagner <bungeman@google.com>

BUILD.gn
include/ports/SkFontMgr_custom.h [deleted file]
include/ports/SkFontMgr_directory.h [new file with mode: 0644]
include/ports/SkFontMgr_empty.h [new file with mode: 0644]
public.bzl
src/ports/SkFontMgr_custom.cpp
src/ports/SkFontMgr_custom.h [new file with mode: 0644]
src/ports/SkFontMgr_custom_directory.cpp [new file with mode: 0644]
src/ports/SkFontMgr_custom_directory_factory.cpp
src/ports/SkFontMgr_custom_embedded.cpp [new file with mode: 0644]
src/ports/SkFontMgr_custom_empty.cpp [new file with mode: 0644]

index e389cd2d7daa162367de7299a8139b953bf7779a..d0f415d056936cfa6d195b432f13e346bc0911a9 100644 (file)
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -344,7 +344,11 @@ optional("fontmgr_custom") {
   ]
   sources = [
     "src/ports/SkFontMgr_custom.cpp",
+    "src/ports/SkFontMgr_custom.h",
+    "src/ports/SkFontMgr_custom_directory.cpp",
     "src/ports/SkFontMgr_custom_directory_factory.cpp",
+    "src/ports/SkFontMgr_custom_embedded.cpp",
+    "src/ports/SkFontMgr_custom_empty.cpp",
   ]
 }
 
@@ -373,6 +377,7 @@ optional("fontmgr_fuchsia") {
   ]
   sources = [
     "src/ports/SkFontMgr_custom.cpp",
+    "src/ports/SkFontMgr_custom_empty.cpp",
     "src/ports/SkFontMgr_custom_empty_factory.cpp",
   ]
 }
diff --git a/include/ports/SkFontMgr_custom.h b/include/ports/SkFontMgr_custom.h
deleted file mode 100644 (file)
index d918763..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
- * Copyright 2015 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#ifndef SkFontMgr_custom_DEFINED
-#define SkFontMgr_custom_DEFINED
-
-#include "SkTypes.h"
-
-class SkFontMgr;
-
-/** Create a custom font manager which scans a given directory for font files. */
-SK_API sk_sp<SkFontMgr> SkFontMgr_New_Custom_Directory(const char* dir);
-
-/** Create a custom font manager that contains no built-in fonts. */
-SK_API sk_sp<SkFontMgr> SkFontMgr_New_Custom_Empty();
-
-#endif // SkFontMgr_custom_DEFINED
diff --git a/include/ports/SkFontMgr_directory.h b/include/ports/SkFontMgr_directory.h
new file mode 100644 (file)
index 0000000..8f79a7f
--- /dev/null
@@ -0,0 +1,21 @@
+/*
+ * Copyright 2015 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkFontMgr_directory_DEFINED
+#define SkFontMgr_directory_DEFINED
+
+#include "SkRefCnt.h"
+#include "SkTypes.h"
+
+class SkFontMgr;
+
+/** Create a custom font manager which scans a given directory for font files.
+ *  This font manager uses FreeType for rendering.
+ */
+SK_API sk_sp<SkFontMgr> SkFontMgr_New_Custom_Directory(const char* dir);
+
+#endif // SkFontMgr_directory_DEFINED
diff --git a/include/ports/SkFontMgr_empty.h b/include/ports/SkFontMgr_empty.h
new file mode 100644 (file)
index 0000000..dbeef58
--- /dev/null
@@ -0,0 +1,21 @@
+/*
+ * Copyright 2015 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkFontMgr_empty_DEFINED
+#define SkFontMgr_empty_DEFINED
+
+#include "SkRefCnt.h"
+#include "SkTypes.h"
+
+class SkFontMgr;
+
+/** Create a custom font manager that contains no built-in fonts.
+ *  This font manager uses FreeType for rendering.
+ */
+SK_API sk_sp<SkFontMgr> SkFontMgr_New_Custom_Empty();
+
+#endif // SkFontMgr_empty_DEFINED
index a808bb13eb5b202e93c968d2958e44e4bd702688..15709bf2f2adda5246b0dca685119d2500cc5e6a 100644 (file)
@@ -280,6 +280,9 @@ BASE_SRCS_IOS = struct(
         "src/ports/*nacl*",
         "src/ports/*win*",
         "src/ports/SkFontMgr_custom.cpp",
+        "src/ports/SkFontMgr_custom_directory.cpp",
+        "src/ports/SkFontMgr_custom_embedded.cpp",
+        "src/ports/SkFontMgr_custom_empty.cpp",
         "src/ports/SkFontMgr_custom_directory_factory.cpp",
         "src/ports/SkFontMgr_custom_embedded_factory.cpp",
         "src/ports/SkFontMgr_custom_empty_factory.cpp",
index 1b6baa19a449f7e5f4d8fff75c7ff8fb9b3b04ac..4e4887d27dc15027b2212a5104d85e29153715ba 100644 (file)
 #include "SkFontMgr_custom.h"
 #include "SkFontStyle.h"
 #include "SkMakeUnique.h"
-#include "SkOSFile.h"
-#include "SkOSPath.h"
 #include "SkRefCnt.h"
 #include "SkStream.h"
 #include "SkString.h"
 #include "SkTArray.h"
 #include "SkTemplates.h"
 #include "SkTypeface.h"
-#include "SkTypefaceCache.h"
 #include "SkTypes.h"
 
 #include <limits>
 
 class SkData;
 
-/** The base SkTypeface implementation for the custom font manager. */
-class SkTypeface_Custom : public SkTypeface_FreeType {
-public:
-    SkTypeface_Custom(const SkFontStyle& style, bool isFixedPitch,
-                      bool sysFont, const SkString familyName, int index)
-        : INHERITED(style, isFixedPitch)
-        , fIsSysFont(sysFont), fFamilyName(familyName), fIndex(index)
-    { }
+SkTypeface_Custom::SkTypeface_Custom(const SkFontStyle& style, bool isFixedPitch,
+                                     bool sysFont, const SkString familyName, int index)
+    : INHERITED(style, isFixedPitch)
+    , fIsSysFont(sysFont), fFamilyName(familyName), fIndex(index)
+{ }
 
-    bool isSysFont() const { return fIsSysFont; }
+bool SkTypeface_Custom::isSysFont() const { return fIsSysFont; }
 
-protected:
-    void onGetFamilyName(SkString* familyName) const override {
-        *familyName = fFamilyName;
-    }
-
-    void onGetFontDescriptor(SkFontDescriptor* desc, bool* isLocal) const override {
-        desc->setFamilyName(fFamilyName.c_str());
-        desc->setStyle(this->fontStyle());
-        *isLocal = !this->isSysFont();
-    }
-
-    int getIndex() const { return fIndex; }
-
-private:
-    const bool fIsSysFont;
-    const SkString fFamilyName;
-    const int fIndex;
-
-    typedef SkTypeface_FreeType INHERITED;
-};
-
-/** The empty SkTypeface implementation for the custom font manager.
- *  Used as the last resort fallback typeface.
- */
-class SkTypeface_Empty : public SkTypeface_Custom {
-public:
-    SkTypeface_Empty() : INHERITED(SkFontStyle(), false, true, SkString(), 0) {}
-
-protected:
-    SkStreamAsset* onOpenStream(int*) const override { return nullptr; }
-
-private:
-    typedef SkTypeface_Custom INHERITED;
-};
-
-/** The stream SkTypeface implementation for the custom font manager. */
-class SkTypeface_Stream : public SkTypeface_Custom {
-public:
-    SkTypeface_Stream(std::unique_ptr<SkFontData> fontData,
-                      const SkFontStyle& style, bool isFixedPitch, bool sysFont,
-                      const SkString familyName)
-        : INHERITED(style, isFixedPitch, sysFont, familyName, fontData->getIndex())
-        , fData(std::move(fontData))
-    { }
-
-protected:
-    SkStreamAsset* onOpenStream(int* ttcIndex) const override {
-        *ttcIndex = fData->getIndex();
-        return fData->getStream()->duplicate();
-    }
-
-    std::unique_ptr<SkFontData> onMakeFontData() const override {
-        return skstd::make_unique<SkFontData>(*fData);
-    }
-
-private:
-    const std::unique_ptr<const SkFontData> fData;
-
-    typedef SkTypeface_Custom INHERITED;
-};
-
-/** The file SkTypeface implementation for the custom font manager. */
-class SkTypeface_File : public SkTypeface_Custom {
-public:
-    SkTypeface_File(const SkFontStyle& style, bool isFixedPitch, bool sysFont,
-                    const SkString familyName, const char path[], int index)
-        : INHERITED(style, isFixedPitch, sysFont, familyName, index)
-        , fPath(path)
-    { }
-
-protected:
-    SkStreamAsset* onOpenStream(int* ttcIndex) const override {
-        *ttcIndex = this->getIndex();
-        return SkStream::MakeFromFile(fPath.c_str()).release();
-    }
-
-private:
-    SkString fPath;
-
-    typedef SkTypeface_Custom INHERITED;
-};
-
-///////////////////////////////////////////////////////////////////////////////
-
-/**
- *  SkFontStyleSet_Custom
- *
- *  This class is used by SkFontMgr_Custom to hold SkTypeface_Custom families.
- */
-class SkFontStyleSet_Custom : public SkFontStyleSet {
-public:
-    explicit SkFontStyleSet_Custom(const SkString familyName) : fFamilyName(familyName) { }
-
-    /** Should only be called during the inital build phase. */
-    void appendTypeface(sk_sp<SkTypeface_Custom> typeface) {
-        fStyles.emplace_back(std::move(typeface));
-    }
-
-    int count() override {
-        return fStyles.count();
-    }
+void SkTypeface_Custom::onGetFamilyName(SkString* familyName) const {
+    *familyName = fFamilyName;
+}
 
-    void getStyle(int index, SkFontStyle* style, SkString* name) override {
-        SkASSERT(index < fStyles.count());
-        if (style) {
-            *style = fStyles[index]->fontStyle();
-        }
-        if (name) {
-            name->reset();
-        }
-    }
+void SkTypeface_Custom::onGetFontDescriptor(SkFontDescriptor* desc, bool* isLocal) const {
+    desc->setFamilyName(fFamilyName.c_str());
+    desc->setStyle(this->fontStyle());
+    *isLocal = !this->isSysFont();
+}
 
-    SkTypeface* createTypeface(int index) override {
-        SkASSERT(index < fStyles.count());
-        return SkRef(fStyles[index].get());
-    }
+int SkTypeface_Custom::getIndex() const { return fIndex; }
 
-    SkTypeface* matchStyle(const SkFontStyle& pattern) override {
-        return this->matchStyleCSS3(pattern);
-    }
 
-    SkString getFamilyName() { return fFamilyName; }
+SkTypeface_Empty::SkTypeface_Empty() : INHERITED(SkFontStyle(), false, true, SkString(), 0) {}
 
-private:
-    SkTArray<sk_sp<SkTypeface_Custom>> fStyles;
-    SkString fFamilyName;
+SkStreamAsset* SkTypeface_Empty::onOpenStream(int*) const { return nullptr; }
 
-    friend class SkFontMgr_Custom;
-};
 
-/**
- *  SkFontMgr_Custom
- *
- *  This class is essentially a collection of SkFontStyleSet_Custom,
- *  one SkFontStyleSet_Custom for each family. This class may be modified
- *  to load fonts from any source by changing the initialization.
- */
-class SkFontMgr_Custom : public SkFontMgr {
-public:
-    typedef SkTArray<sk_sp<SkFontStyleSet_Custom>> Families;
-    class SystemFontLoader {
-    public:
-        virtual ~SystemFontLoader() { }
-        virtual void loadSystemFonts(const SkTypeface_FreeType::Scanner&, Families*) const = 0;
-    };
-    explicit SkFontMgr_Custom(const SystemFontLoader& loader) : fDefaultFamily(nullptr) {
-        loader.loadSystemFonts(fScanner, &fFamilies);
-
-        // Try to pick a default font.
-        static const char* defaultNames[] = {
-            "Arial", "Verdana", "Times New Roman", "Droid Sans", nullptr
-        };
-        for (size_t i = 0; i < SK_ARRAY_COUNT(defaultNames); ++i) {
-            sk_sp<SkFontStyleSet_Custom> set(this->onMatchFamily(defaultNames[i]));
-            if (nullptr == set) {
-                continue;
-            }
+SkTypeface_Stream::SkTypeface_Stream(std::unique_ptr<SkFontData> fontData,
+                                     const SkFontStyle& style, bool isFixedPitch, bool sysFont,
+                                     const SkString familyName)
+    : INHERITED(style, isFixedPitch, sysFont, familyName, fontData->getIndex())
+    , fData(std::move(fontData))
+{ }
 
-            sk_sp<SkTypeface> tf(set->matchStyle(SkFontStyle(SkFontStyle::kNormal_Weight,
-                                                             SkFontStyle::kNormal_Width,
-                                                             SkFontStyle::kUpright_Slant)));
-            if (nullptr == tf) {
-                continue;
-            }
+SkStreamAsset* SkTypeface_Stream::onOpenStream(int* ttcIndex) const {
+    *ttcIndex = fData->getIndex();
+    return fData->getStream()->duplicate();
+}
 
-            fDefaultFamily = set.get();
-            break;
-        }
-        if (nullptr == fDefaultFamily) {
-            fDefaultFamily = fFamilies[0].get();
-        }
-    }
+std::unique_ptr<SkFontData> SkTypeface_Stream::onMakeFontData() const {
+    return skstd::make_unique<SkFontData>(*fData);
+}
 
-protected:
-    int onCountFamilies() const override {
-        return fFamilies.count();
-    }
 
-    void onGetFamilyName(int index, SkString* familyName) const override {
-        SkASSERT(index < fFamilies.count());
-        familyName->set(fFamilies[index]->getFamilyName());
-    }
+SkTypeface_File::SkTypeface_File(const SkFontStyle& style, bool isFixedPitch, bool sysFont,
+                                 const SkString familyName, const char path[], int index)
+    : INHERITED(style, isFixedPitch, sysFont, familyName, index)
+    , fPath(path)
+{ }
 
-    SkFontStyleSet_Custom* onCreateStyleSet(int index) const override {
-        SkASSERT(index < fFamilies.count());
-        return SkRef(fFamilies[index].get());
-    }
+SkStreamAsset* SkTypeface_File::onOpenStream(int* ttcIndex) const {
+    *ttcIndex = this->getIndex();
+    return SkStream::MakeFromFile(fPath.c_str()).release();
+}
 
-    SkFontStyleSet_Custom* onMatchFamily(const char familyName[]) const override {
-        for (int i = 0; i < fFamilies.count(); ++i) {
-            if (fFamilies[i]->getFamilyName().equals(familyName)) {
-                return SkRef(fFamilies[i].get());
-            }
-        }
-        return nullptr;
-    }
+///////////////////////////////////////////////////////////////////////////////
 
-    SkTypeface* onMatchFamilyStyle(const char familyName[],
-                                   const SkFontStyle& fontStyle) const override
-    {
-        sk_sp<SkFontStyleSet> sset(this->matchFamily(familyName));
-        return sset->matchStyle(fontStyle);
-    }
+SkFontStyleSet_Custom::SkFontStyleSet_Custom(const SkString familyName) : fFamilyName(familyName) {}
 
-    SkTypeface* onMatchFamilyStyleCharacter(const char familyName[], const SkFontStyle&,
-                                            const char* bcp47[], int bcp47Count,
-                                            SkUnichar character) const override
-    {
-        return nullptr;
-    }
+void SkFontStyleSet_Custom::appendTypeface(sk_sp<SkTypeface_Custom> typeface) {
+    fStyles.emplace_back(std::move(typeface));
+}
 
-    SkTypeface* onMatchFaceStyle(const SkTypeface* familyMember,
-                                 const SkFontStyle& fontStyle) const override
-    {
-        for (int i = 0; i < fFamilies.count(); ++i) {
-            for (int j = 0; j < fFamilies[i]->fStyles.count(); ++j) {
-                if (fFamilies[i]->fStyles[j].get() == familyMember) {
-                    return fFamilies[i]->matchStyle(fontStyle);
-                }
-            }
-        }
-        return nullptr;
-    }
+int SkFontStyleSet_Custom::count() {
+    return fStyles.count();
+}
 
-    SkTypeface* onCreateFromData(SkData* data, int ttcIndex) const override {
-        return this->createFromStream(new SkMemoryStream(sk_ref_sp(data)), ttcIndex);
+void SkFontStyleSet_Custom::getStyle(int index, SkFontStyle* style, SkString* name) {
+    SkASSERT(index < fStyles.count());
+    if (style) {
+        *style = fStyles[index]->fontStyle();
     }
-
-    SkTypeface* onCreateFromStream(SkStreamAsset* bareStream, int ttcIndex) const override {
-        return this->createFromStream(bareStream, FontParameters().setCollectionIndex(ttcIndex));
+    if (name) {
+        name->reset();
     }
+}
 
-    SkTypeface* onCreateFromStream(SkStreamAsset* s, const FontParameters& params) const override {
-        using Scanner = SkTypeface_FreeType::Scanner;
-        std::unique_ptr<SkStreamAsset> stream(s);
-        bool isFixedPitch;
-        SkFontStyle style;
-        SkString name;
-        Scanner::AxisDefinitions axisDefinitions;
-        if (!fScanner.scanFont(stream.get(), params.getCollectionIndex(),
-                               &name, &style, &isFixedPitch, &axisDefinitions))
-        {
-            return nullptr;
-        }
-
-        int paramAxisCount;
-        const FontParameters::Axis* paramAxes = params.getAxes(&paramAxisCount);
-        SkAutoSTMalloc<4, SkFixed> axisValues(axisDefinitions.count());
-        Scanner::computeAxisValues(axisDefinitions, paramAxes, paramAxisCount, axisValues, name);
+SkTypeface* SkFontStyleSet_Custom::createTypeface(int index) {
+    SkASSERT(index < fStyles.count());
+    return SkRef(fStyles[index].get());
+}
 
-        auto data = skstd::make_unique<SkFontData>(std::move(stream), params.getCollectionIndex(),
-                                                   axisValues.get(), axisDefinitions.count());
-        return new SkTypeface_Stream(std::move(data), style, isFixedPitch, false, name);
-    }
+SkTypeface* SkFontStyleSet_Custom::matchStyle(const SkFontStyle& pattern) {
+    return this->matchStyleCSS3(pattern);
+}
 
-    SkTypeface* onCreateFromFontData(std::unique_ptr<SkFontData> data) const override {
-        bool isFixedPitch;
-        SkFontStyle style;
-        SkString name;
-        if (!fScanner.scanFont(data->getStream(), data->getIndex(),
-                               &name, &style, &isFixedPitch, nullptr))
-        {
-            return nullptr;
-        }
-        return new SkTypeface_Stream(std::move(data), style, isFixedPitch, false, name);
-    }
+SkString SkFontStyleSet_Custom::getFamilyName() { return fFamilyName; }
 
-    SkTypeface* onCreateFromFile(const char path[], int ttcIndex) const override {
-        std::unique_ptr<SkStreamAsset> stream = SkStream::MakeFromFile(path);
-        return stream.get() ? this->createFromStream(stream.release(), ttcIndex) : nullptr;
-    }
 
-    SkTypeface* onLegacyCreateTypeface(const char familyName[], SkFontStyle style) const override {
-        SkTypeface* tf = nullptr;
+SkFontMgr_Custom::SkFontMgr_Custom(const SystemFontLoader& loader) : fDefaultFamily(nullptr) {
+    loader.loadSystemFonts(fScanner, &fFamilies);
 
-        if (familyName) {
-            tf = this->onMatchFamilyStyle(familyName, style);
+    // Try to pick a default font.
+    static const char* defaultNames[] = {
+        "Arial", "Verdana", "Times New Roman", "Droid Sans", nullptr
+    };
+    for (size_t i = 0; i < SK_ARRAY_COUNT(defaultNames); ++i) {
+        sk_sp<SkFontStyleSet_Custom> set(this->onMatchFamily(defaultNames[i]));
+        if (nullptr == set) {
+            continue;
         }
 
+        sk_sp<SkTypeface> tf(set->matchStyle(SkFontStyle(SkFontStyle::kNormal_Weight,
+                                                         SkFontStyle::kNormal_Width,
+                                                         SkFontStyle::kUpright_Slant)));
         if (nullptr == tf) {
-            tf = fDefaultFamily->matchStyle(style);
+            continue;
         }
 
-        return tf;
+        fDefaultFamily = set.get();
+        break;
     }
+    if (nullptr == fDefaultFamily) {
+        fDefaultFamily = fFamilies[0].get();
+    }
+}
 
-private:
-    Families fFamilies;
-    SkFontStyleSet_Custom* fDefaultFamily;
-    SkTypeface_FreeType::Scanner fScanner;
-};
-
-///////////////////////////////////////////////////////////////////////////////
+int SkFontMgr_Custom::onCountFamilies() const {
+    return fFamilies.count();
+}
 
-class DirectorySystemFontLoader : public SkFontMgr_Custom::SystemFontLoader {
-public:
-    DirectorySystemFontLoader(const char* dir) : fBaseDirectory(dir) { }
+void SkFontMgr_Custom::onGetFamilyName(int index, SkString* familyName) const {
+    SkASSERT(index < fFamilies.count());
+    familyName->set(fFamilies[index]->getFamilyName());
+}
 
-    void loadSystemFonts(const SkTypeface_FreeType::Scanner& scanner,
-                         SkFontMgr_Custom::Families* families) const override
-    {
-        load_directory_fonts(scanner, fBaseDirectory, ".ttf", families);
-        load_directory_fonts(scanner, fBaseDirectory, ".ttc", families);
-        load_directory_fonts(scanner, fBaseDirectory, ".otf", families);
-        load_directory_fonts(scanner, fBaseDirectory, ".pfb", families);
-
-        if (families->empty()) {
-            SkFontStyleSet_Custom* family = new SkFontStyleSet_Custom(SkString());
-            families->push_back().reset(family);
-            family->appendTypeface(sk_make_sp<SkTypeface_Empty>());
-        }
-    }
+SkFontStyleSet_Custom* SkFontMgr_Custom::onCreateStyleSet(int index) const {
+    SkASSERT(index < fFamilies.count());
+    return SkRef(fFamilies[index].get());
+}
 
-private:
-    static SkFontStyleSet_Custom* find_family(SkFontMgr_Custom::Families& families,
-                                              const char familyName[])
-    {
-       for (int i = 0; i < families.count(); ++i) {
-            if (families[i]->getFamilyName().equals(familyName)) {
-                return families[i].get();
-            }
+SkFontStyleSet_Custom* SkFontMgr_Custom::onMatchFamily(const char familyName[]) const {
+    for (int i = 0; i < fFamilies.count(); ++i) {
+        if (fFamilies[i]->getFamilyName().equals(familyName)) {
+            return SkRef(fFamilies[i].get());
         }
-        return nullptr;
     }
+    return nullptr;
+}
 
-    static void load_directory_fonts(const SkTypeface_FreeType::Scanner& scanner,
-                                     const SkString& directory, const char* suffix,
-                                     SkFontMgr_Custom::Families* families)
-    {
-        SkOSFile::Iter iter(directory.c_str(), suffix);
-        SkString name;
-
-        while (iter.next(&name, false)) {
-            SkString filename(SkOSPath::Join(directory.c_str(), name.c_str()));
-            std::unique_ptr<SkStreamAsset> stream = SkStream::MakeFromFile(filename.c_str());
-            if (!stream) {
-                SkDebugf("---- failed to open <%s>\n", filename.c_str());
-                continue;
-            }
-
-            int numFaces;
-            if (!scanner.recognizedFont(stream.get(), &numFaces)) {
-                SkDebugf("---- failed to open <%s> as a font\n", filename.c_str());
-                continue;
-            }
+SkTypeface* SkFontMgr_Custom::onMatchFamilyStyle(const char familyName[],
+                                const SkFontStyle& fontStyle) const
+{
+    sk_sp<SkFontStyleSet> sset(this->matchFamily(familyName));
+    return sset->matchStyle(fontStyle);
+}
 
-            for (int faceIndex = 0; faceIndex < numFaces; ++faceIndex) {
-                bool isFixedPitch;
-                SkString realname;
-                SkFontStyle style = SkFontStyle(); // avoid uninitialized warning
-                if (!scanner.scanFont(stream.get(), faceIndex,
-                                      &realname, &style, &isFixedPitch, nullptr))
-                {
-                    SkDebugf("---- failed to open <%s> <%d> as a font\n",
-                             filename.c_str(), faceIndex);
-                    continue;
-                }
-
-                SkFontStyleSet_Custom* addTo = find_family(*families, realname.c_str());
-                if (nullptr == addTo) {
-                    addTo = new SkFontStyleSet_Custom(realname);
-                    families->push_back().reset(addTo);
-                }
-                addTo->appendTypeface(sk_make_sp<SkTypeface_File>(style, isFixedPitch, true,
-                                                                  realname, filename.c_str(),
-                                                                  faceIndex));
-            }
-        }
+SkTypeface* SkFontMgr_Custom::onMatchFamilyStyleCharacter(const char familyName[],
+                                                          const SkFontStyle&,
+                                                          const char* bcp47[], int bcp47Count,
+                                                          SkUnichar character) const
+{
+    return nullptr;
+}
 
-        SkOSFile::Iter dirIter(directory.c_str());
-        while (dirIter.next(&name, true)) {
-            if (name.startsWith(".")) {
-                continue;
+SkTypeface* SkFontMgr_Custom::onMatchFaceStyle(const SkTypeface* familyMember,
+                                               const SkFontStyle& fontStyle) const
+{
+    for (int i = 0; i < fFamilies.count(); ++i) {
+        for (int j = 0; j < fFamilies[i]->fStyles.count(); ++j) {
+            if (fFamilies[i]->fStyles[j].get() == familyMember) {
+                return fFamilies[i]->matchStyle(fontStyle);
             }
-            SkString dirname(SkOSPath::Join(directory.c_str(), name.c_str()));
-            load_directory_fonts(scanner, dirname, suffix, families);
         }
     }
-
-    SkString fBaseDirectory;
-};
-
-SK_API sk_sp<SkFontMgr> SkFontMgr_New_Custom_Directory(const char* dir) {
-    return sk_make_sp<SkFontMgr_Custom>(DirectorySystemFontLoader(dir));
+    return nullptr;
 }
 
-///////////////////////////////////////////////////////////////////////////////
-
-struct SkEmbeddedResource { const uint8_t* data; size_t size; };
-struct SkEmbeddedResourceHeader { const SkEmbeddedResource* entries; int count; };
-
-class EmbeddedSystemFontLoader : public SkFontMgr_Custom::SystemFontLoader {
-public:
-    EmbeddedSystemFontLoader(const SkEmbeddedResourceHeader* header) : fHeader(header) { }
-
-    void loadSystemFonts(const SkTypeface_FreeType::Scanner& scanner,
-                         SkFontMgr_Custom::Families* families) const override
-    {
-        for (int i = 0; i < fHeader->count; ++i) {
-            const SkEmbeddedResource& fontEntry = fHeader->entries[i];
-            load_embedded_font(scanner, fontEntry.data, fontEntry.size, i, families);
-        }
+SkTypeface* SkFontMgr_Custom::onCreateFromData(SkData* data, int ttcIndex) const {
+    return this->createFromStream(new SkMemoryStream(sk_ref_sp(data)), ttcIndex);
+}
 
-        if (families->empty()) {
-            SkFontStyleSet_Custom* family = new SkFontStyleSet_Custom(SkString());
-            families->push_back().reset(family);
-            family->appendTypeface(sk_make_sp<SkTypeface_Empty>());
-        }
-    }
+SkTypeface* SkFontMgr_Custom::onCreateFromStream(SkStreamAsset* bareStream, int ttcIndex) const {
+    return this->createFromStream(bareStream, FontParameters().setCollectionIndex(ttcIndex));
+}
 
-private:
-    static SkFontStyleSet_Custom* find_family(SkFontMgr_Custom::Families& families,
-                                              const char familyName[])
+SkTypeface* SkFontMgr_Custom::onCreateFromStream(SkStreamAsset* s,
+                                                 const FontParameters& params) const
+{
+    using Scanner = SkTypeface_FreeType::Scanner;
+    std::unique_ptr<SkStreamAsset> stream(s);
+    bool isFixedPitch;
+    SkFontStyle style;
+    SkString name;
+    Scanner::AxisDefinitions axisDefinitions;
+    if (!fScanner.scanFont(stream.get(), params.getCollectionIndex(),
+                            &name, &style, &isFixedPitch, &axisDefinitions))
     {
-       for (int i = 0; i < families.count(); ++i) {
-            if (families[i]->getFamilyName().equals(familyName)) {
-                return families[i].get();
-            }
-        }
         return nullptr;
     }
 
-    static void load_embedded_font(const SkTypeface_FreeType::Scanner& scanner,
-                                   const uint8_t* data, size_t size, int index,
-                                   SkFontMgr_Custom::Families* families)
-    {
-        auto stream = skstd::make_unique<SkMemoryStream>(data, size, false);
-
-        int numFaces;
-        if (!scanner.recognizedFont(stream.get(), &numFaces)) {
-            SkDebugf("---- failed to open <%d> as a font\n", index);
-            return;
-        }
+    int paramAxisCount;
+    const FontParameters::Axis* paramAxes = params.getAxes(&paramAxisCount);
+    SkAutoSTMalloc<4, SkFixed> axisValues(axisDefinitions.count());
+    Scanner::computeAxisValues(axisDefinitions, paramAxes, paramAxisCount, axisValues, name);
 
-        for (int faceIndex = 0; faceIndex < numFaces; ++faceIndex) {
-            bool isFixedPitch;
-            SkString realname;
-            SkFontStyle style = SkFontStyle(); // avoid uninitialized warning
-            if (!scanner.scanFont(stream.get(), faceIndex,
-                                  &realname, &style, &isFixedPitch, nullptr))
-            {
-                SkDebugf("---- failed to open <%d> <%d> as a font\n", index, faceIndex);
-                return;
-            }
+    auto data = skstd::make_unique<SkFontData>(std::move(stream), params.getCollectionIndex(),
+                                                axisValues.get(), axisDefinitions.count());
+    return new SkTypeface_Stream(std::move(data), style, isFixedPitch, false, name);
+}
 
-            SkFontStyleSet_Custom* addTo = find_family(*families, realname.c_str());
-            if (nullptr == addTo) {
-                addTo = new SkFontStyleSet_Custom(realname);
-                families->push_back().reset(addTo);
-            }
-            auto data = skstd::make_unique<SkFontData>(std::move(stream), faceIndex, nullptr, 0);
-            addTo->appendTypeface(sk_make_sp<SkTypeface_Stream>(std::move(data),
-                                                                style, isFixedPitch,
-                                                                true, realname));
-        }
+SkTypeface* SkFontMgr_Custom::onCreateFromFontData(std::unique_ptr<SkFontData> data) const {
+    bool isFixedPitch;
+    SkFontStyle style;
+    SkString name;
+    if (!fScanner.scanFont(data->getStream(), data->getIndex(),
+                            &name, &style, &isFixedPitch, nullptr))
+    {
+        return nullptr;
     }
-
-    const SkEmbeddedResourceHeader* fHeader;
-};
-
-sk_sp<SkFontMgr> SkFontMgr_New_Custom_Embedded(const SkEmbeddedResourceHeader* header) {
-    return sk_make_sp<SkFontMgr_Custom>(EmbeddedSystemFontLoader(header));
+    return new SkTypeface_Stream(std::move(data), style, isFixedPitch, false, name);
 }
 
-///////////////////////////////////////////////////////////////////////////////
+SkTypeface* SkFontMgr_Custom::onCreateFromFile(const char path[], int ttcIndex) const {
+    std::unique_ptr<SkStreamAsset> stream = SkStream::MakeFromFile(path);
+    return stream.get() ? this->createFromStream(stream.release(), ttcIndex) : nullptr;
+}
 
-class EmptyFontLoader : public SkFontMgr_Custom::SystemFontLoader {
-public:
-    EmptyFontLoader() { }
+SkTypeface* SkFontMgr_Custom::onLegacyCreateTypeface(const char familyName[],
+                                                     SkFontStyle style) const
+{
+    SkTypeface* tf = nullptr;
 
-    void loadSystemFonts(const SkTypeface_FreeType::Scanner& scanner,
-                         SkFontMgr_Custom::Families* families) const override
-    {
-        SkFontStyleSet_Custom* family = new SkFontStyleSet_Custom(SkString());
-        families->push_back().reset(family);
-        family->appendTypeface(sk_make_sp<SkTypeface_Empty>());
+    if (familyName) {
+        tf = this->onMatchFamilyStyle(familyName, style);
     }
 
-};
+    if (nullptr == tf) {
+        tf = fDefaultFamily->matchStyle(style);
+    }
 
-SK_API sk_sp<SkFontMgr> SkFontMgr_New_Custom_Empty() {
-    return sk_make_sp<SkFontMgr_Custom>(EmptyFontLoader());
+    return tf;
 }
diff --git a/src/ports/SkFontMgr_custom.h b/src/ports/SkFontMgr_custom.h
new file mode 100644 (file)
index 0000000..9149378
--- /dev/null
@@ -0,0 +1,158 @@
+/*
+ * Copyright 2006 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkFontMgr_custom_DEFINED
+#define SkFontMgr_custom_DEFINED
+
+#include "SkFontHost_FreeType_common.h"
+#include "SkFontMgr.h"
+#include "SkFontStyle.h"
+#include "SkRefCnt.h"
+#include "SkString.h"
+#include "SkTArray.h"
+#include "SkTypes.h"
+
+class SkData;
+class SkFontDescriptor;
+class SkStreamAsset;
+class SkTypeface;
+
+/** The base SkTypeface implementation for the custom font manager. */
+class SkTypeface_Custom : public SkTypeface_FreeType {
+public:
+    SkTypeface_Custom(const SkFontStyle& style, bool isFixedPitch,
+                      bool sysFont, const SkString familyName, int index);
+    bool isSysFont() const;
+
+protected:
+    void onGetFamilyName(SkString* familyName) const override;
+    void onGetFontDescriptor(SkFontDescriptor* desc, bool* isLocal) const override;
+    int getIndex() const;
+
+private:
+    const bool fIsSysFont;
+    const SkString fFamilyName;
+    const int fIndex;
+
+    typedef SkTypeface_FreeType INHERITED;
+};
+
+/** The empty SkTypeface implementation for the custom font manager.
+ *  Used as the last resort fallback typeface.
+ */
+class SkTypeface_Empty : public SkTypeface_Custom {
+public:
+    SkTypeface_Empty() ;
+
+protected:
+    SkStreamAsset* onOpenStream(int*) const override;
+
+private:
+    typedef SkTypeface_Custom INHERITED;
+};
+
+/** The stream SkTypeface implementation for the custom font manager. */
+class SkTypeface_Stream : public SkTypeface_Custom {
+public:
+    SkTypeface_Stream(std::unique_ptr<SkFontData> fontData,
+                      const SkFontStyle& style, bool isFixedPitch, bool sysFont,
+                      const SkString familyName);
+
+protected:
+    SkStreamAsset* onOpenStream(int* ttcIndex) const override;
+    std::unique_ptr<SkFontData> onMakeFontData() const override;
+
+private:
+    const std::unique_ptr<const SkFontData> fData;
+
+    typedef SkTypeface_Custom INHERITED;
+};
+
+/** The file SkTypeface implementation for the custom font manager. */
+class SkTypeface_File : public SkTypeface_Custom {
+public:
+    SkTypeface_File(const SkFontStyle& style, bool isFixedPitch, bool sysFont,
+                    const SkString familyName, const char path[], int index);
+
+protected:
+    SkStreamAsset* onOpenStream(int* ttcIndex) const override;
+
+private:
+    SkString fPath;
+
+    typedef SkTypeface_Custom INHERITED;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+
+/**
+ *  SkFontStyleSet_Custom
+ *
+ *  This class is used by SkFontMgr_Custom to hold SkTypeface_Custom families.
+ */
+class SkFontStyleSet_Custom : public SkFontStyleSet {
+public:
+    explicit SkFontStyleSet_Custom(const SkString familyName);
+
+    /** Should only be called during the inital build phase. */
+    void appendTypeface(sk_sp<SkTypeface_Custom> typeface);
+    int count() override;
+    void getStyle(int index, SkFontStyle* style, SkString* name) override;
+    SkTypeface* createTypeface(int index) override;
+    SkTypeface* matchStyle(const SkFontStyle& pattern) override;
+    SkString getFamilyName();
+
+private:
+    SkTArray<sk_sp<SkTypeface_Custom>> fStyles;
+    SkString fFamilyName;
+
+    friend class SkFontMgr_Custom;
+};
+
+/**
+ *  SkFontMgr_Custom
+ *
+ *  This class is essentially a collection of SkFontStyleSet_Custom,
+ *  one SkFontStyleSet_Custom for each family. This class may be modified
+ *  to load fonts from any source by changing the initialization.
+ */
+class SkFontMgr_Custom : public SkFontMgr {
+public:
+    typedef SkTArray<sk_sp<SkFontStyleSet_Custom>> Families;
+    class SystemFontLoader {
+    public:
+        virtual ~SystemFontLoader() { }
+        virtual void loadSystemFonts(const SkTypeface_FreeType::Scanner&, Families*) const = 0;
+    };
+    explicit SkFontMgr_Custom(const SystemFontLoader& loader);
+
+protected:
+    int onCountFamilies() const override;
+    void onGetFamilyName(int index, SkString* familyName) const override;
+    SkFontStyleSet_Custom* onCreateStyleSet(int index) const override;
+    SkFontStyleSet_Custom* onMatchFamily(const char familyName[]) const override;
+    SkTypeface* onMatchFamilyStyle(const char familyName[],
+                                   const SkFontStyle& fontStyle) const override;
+    SkTypeface* onMatchFamilyStyleCharacter(const char familyName[], const SkFontStyle&,
+                                            const char* bcp47[], int bcp47Count,
+                                            SkUnichar character) const override;
+    SkTypeface* onMatchFaceStyle(const SkTypeface* familyMember,
+                                 const SkFontStyle& fontStyle) const override;
+    SkTypeface* onCreateFromData(SkData* data, int ttcIndex) const override;
+    SkTypeface* onCreateFromStream(SkStreamAsset* bareStream, int ttcIndex) const override;
+    SkTypeface* onCreateFromStream(SkStreamAsset* s, const FontParameters& params) const override;
+    SkTypeface* onCreateFromFontData(std::unique_ptr<SkFontData> data) const override;
+    SkTypeface* onCreateFromFile(const char path[], int ttcIndex) const override;
+    SkTypeface* onLegacyCreateTypeface(const char familyName[], SkFontStyle style) const override;
+
+private:
+    Families fFamilies;
+    SkFontStyleSet_Custom* fDefaultFamily;
+    SkTypeface_FreeType::Scanner fScanner;
+};
+
+#endif
diff --git a/src/ports/SkFontMgr_custom_directory.cpp b/src/ports/SkFontMgr_custom_directory.cpp
new file mode 100644 (file)
index 0000000..af32287
--- /dev/null
@@ -0,0 +1,104 @@
+/*
+ * Copyright 2017 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "SkFontMgr_custom.h"
+#include "SkFontMgr_directory.h"
+#include "SkOSFile.h"
+#include "SkOSPath.h"
+#include "SkStream.h"
+
+class DirectorySystemFontLoader : public SkFontMgr_Custom::SystemFontLoader {
+public:
+    DirectorySystemFontLoader(const char* dir) : fBaseDirectory(dir) { }
+
+    void loadSystemFonts(const SkTypeface_FreeType::Scanner& scanner,
+                         SkFontMgr_Custom::Families* families) const override
+    {
+        load_directory_fonts(scanner, fBaseDirectory, ".ttf", families);
+        load_directory_fonts(scanner, fBaseDirectory, ".ttc", families);
+        load_directory_fonts(scanner, fBaseDirectory, ".otf", families);
+        load_directory_fonts(scanner, fBaseDirectory, ".pfb", families);
+
+        if (families->empty()) {
+            SkFontStyleSet_Custom* family = new SkFontStyleSet_Custom(SkString());
+            families->push_back().reset(family);
+            family->appendTypeface(sk_make_sp<SkTypeface_Empty>());
+        }
+    }
+
+private:
+    static SkFontStyleSet_Custom* find_family(SkFontMgr_Custom::Families& families,
+                                              const char familyName[])
+    {
+       for (int i = 0; i < families.count(); ++i) {
+            if (families[i]->getFamilyName().equals(familyName)) {
+                return families[i].get();
+            }
+        }
+        return nullptr;
+    }
+
+    static void load_directory_fonts(const SkTypeface_FreeType::Scanner& scanner,
+                                     const SkString& directory, const char* suffix,
+                                     SkFontMgr_Custom::Families* families)
+    {
+        SkOSFile::Iter iter(directory.c_str(), suffix);
+        SkString name;
+
+        while (iter.next(&name, false)) {
+            SkString filename(SkOSPath::Join(directory.c_str(), name.c_str()));
+            std::unique_ptr<SkStreamAsset> stream = SkStream::MakeFromFile(filename.c_str());
+            if (!stream) {
+                SkDebugf("---- failed to open <%s>\n", filename.c_str());
+                continue;
+            }
+
+            int numFaces;
+            if (!scanner.recognizedFont(stream.get(), &numFaces)) {
+                SkDebugf("---- failed to open <%s> as a font\n", filename.c_str());
+                continue;
+            }
+
+            for (int faceIndex = 0; faceIndex < numFaces; ++faceIndex) {
+                bool isFixedPitch;
+                SkString realname;
+                SkFontStyle style = SkFontStyle(); // avoid uninitialized warning
+                if (!scanner.scanFont(stream.get(), faceIndex,
+                                      &realname, &style, &isFixedPitch, nullptr))
+                {
+                    SkDebugf("---- failed to open <%s> <%d> as a font\n",
+                             filename.c_str(), faceIndex);
+                    continue;
+                }
+
+                SkFontStyleSet_Custom* addTo = find_family(*families, realname.c_str());
+                if (nullptr == addTo) {
+                    addTo = new SkFontStyleSet_Custom(realname);
+                    families->push_back().reset(addTo);
+                }
+                addTo->appendTypeface(sk_make_sp<SkTypeface_File>(style, isFixedPitch, true,
+                                                                  realname, filename.c_str(),
+                                                                  faceIndex));
+            }
+        }
+
+        SkOSFile::Iter dirIter(directory.c_str());
+        while (dirIter.next(&name, true)) {
+            if (name.startsWith(".")) {
+                continue;
+            }
+            SkString dirname(SkOSPath::Join(directory.c_str(), name.c_str()));
+            load_directory_fonts(scanner, dirname, suffix, families);
+        }
+    }
+
+    SkString fBaseDirectory;
+};
+
+SK_API sk_sp<SkFontMgr> SkFontMgr_New_Custom_Directory(const char* dir) {
+    return sk_make_sp<SkFontMgr_Custom>(DirectorySystemFontLoader(dir));
+}
index 7ed47118e4b90cb0cff5e4e90cdc454848e4a0a5..e8d4bb3f3e5059955321931f2dd6e0af4f634630 100644 (file)
@@ -6,7 +6,7 @@
  */
 
 #include "SkFontMgr.h"
-#include "SkFontMgr_custom.h"
+#include "SkFontMgr_directory.h"
 
 #ifndef SK_FONT_FILE_PREFIX
 #    define SK_FONT_FILE_PREFIX "/usr/share/fonts/"
diff --git a/src/ports/SkFontMgr_custom_embedded.cpp b/src/ports/SkFontMgr_custom_embedded.cpp
new file mode 100644 (file)
index 0000000..bb8d9f2
--- /dev/null
@@ -0,0 +1,87 @@
+/*
+ * Copyright 2017 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "SkFontDescriptor.h"
+#include "SkFontMgr_custom.h"
+#include "SkMakeUnique.h"
+#include "SkStream.h"
+
+struct SkEmbeddedResource { const uint8_t* data; size_t size; };
+struct SkEmbeddedResourceHeader { const SkEmbeddedResource* entries; int count; };
+
+class EmbeddedSystemFontLoader : public SkFontMgr_Custom::SystemFontLoader {
+public:
+    EmbeddedSystemFontLoader(const SkEmbeddedResourceHeader* header) : fHeader(header) { }
+
+    void loadSystemFonts(const SkTypeface_FreeType::Scanner& scanner,
+                         SkFontMgr_Custom::Families* families) const override
+    {
+        for (int i = 0; i < fHeader->count; ++i) {
+            const SkEmbeddedResource& fontEntry = fHeader->entries[i];
+            load_embedded_font(scanner, fontEntry.data, fontEntry.size, i, families);
+        }
+
+        if (families->empty()) {
+            SkFontStyleSet_Custom* family = new SkFontStyleSet_Custom(SkString());
+            families->push_back().reset(family);
+            family->appendTypeface(sk_make_sp<SkTypeface_Empty>());
+        }
+    }
+
+private:
+    static SkFontStyleSet_Custom* find_family(SkFontMgr_Custom::Families& families,
+                                              const char familyName[])
+    {
+       for (int i = 0; i < families.count(); ++i) {
+            if (families[i]->getFamilyName().equals(familyName)) {
+                return families[i].get();
+            }
+        }
+        return nullptr;
+    }
+
+    static void load_embedded_font(const SkTypeface_FreeType::Scanner& scanner,
+                                   const uint8_t* data, size_t size, int index,
+                                   SkFontMgr_Custom::Families* families)
+    {
+        auto stream = skstd::make_unique<SkMemoryStream>(data, size, false);
+
+        int numFaces;
+        if (!scanner.recognizedFont(stream.get(), &numFaces)) {
+            SkDebugf("---- failed to open <%d> as a font\n", index);
+            return;
+        }
+
+        for (int faceIndex = 0; faceIndex < numFaces; ++faceIndex) {
+            bool isFixedPitch;
+            SkString realname;
+            SkFontStyle style = SkFontStyle(); // avoid uninitialized warning
+            if (!scanner.scanFont(stream.get(), faceIndex,
+                                  &realname, &style, &isFixedPitch, nullptr))
+            {
+                SkDebugf("---- failed to open <%d> <%d> as a font\n", index, faceIndex);
+                return;
+            }
+
+            SkFontStyleSet_Custom* addTo = find_family(*families, realname.c_str());
+            if (nullptr == addTo) {
+                addTo = new SkFontStyleSet_Custom(realname);
+                families->push_back().reset(addTo);
+            }
+            auto data = skstd::make_unique<SkFontData>(std::move(stream), faceIndex, nullptr, 0);
+            addTo->appendTypeface(sk_make_sp<SkTypeface_Stream>(std::move(data),
+                                                                style, isFixedPitch,
+                                                                true, realname));
+        }
+    }
+
+    const SkEmbeddedResourceHeader* fHeader;
+};
+
+sk_sp<SkFontMgr> SkFontMgr_New_Custom_Embedded(const SkEmbeddedResourceHeader* header) {
+    return sk_make_sp<SkFontMgr_Custom>(EmbeddedSystemFontLoader(header));
+}
diff --git a/src/ports/SkFontMgr_custom_empty.cpp b/src/ports/SkFontMgr_custom_empty.cpp
new file mode 100644 (file)
index 0000000..8732bc3
--- /dev/null
@@ -0,0 +1,27 @@
+/*
+ * Copyright 2017 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "SkFontMgr_custom.h"
+#include "SkFontMgr_empty.h"
+
+class EmptyFontLoader : public SkFontMgr_Custom::SystemFontLoader {
+public:
+    EmptyFontLoader() { }
+
+    void loadSystemFonts(const SkTypeface_FreeType::Scanner& scanner,
+                         SkFontMgr_Custom::Families* families) const override
+    {
+        SkFontStyleSet_Custom* family = new SkFontStyleSet_Custom(SkString());
+        families->push_back().reset(family);
+        family->appendTypeface(sk_make_sp<SkTypeface_Empty>());
+    }
+
+};
+
+SK_API sk_sp<SkFontMgr> SkFontMgr_New_Custom_Empty() {
+    return sk_make_sp<SkFontMgr_Custom>(EmptyFontLoader());
+}