[skottie] Add support for external font loading

Web fonts are quite common in Lottie text assets.  Expand the
ResourceProvider interface to allow loading of external (web) font data.

Fonts are passed back to Skottie as opaque SkData, and instantiated
using SkFontMgr::makeFromData().

Change-Id: Ia4c994bd60e6a3bd47c90172c267ed5f897a38e4
Reviewed-on: https://skia-review.googlesource.com/155601
Commit-Queue: Florin Malita <fmalita@chromium.org>
Reviewed-by: Ben Wagner <bungeman@google.com>
diff --git a/modules/skottie/include/Skottie.h b/modules/skottie/include/Skottie.h
index e82ba70..ebe7408 100644
--- a/modules/skottie/include/Skottie.h
+++ b/modules/skottie/include/Skottie.h
@@ -26,6 +26,10 @@
 
 namespace skottie {
 
+/**
+ * ResourceProvider allows Skottie embedders to control loading of external
+ * Skottie resources -- e.g. images, fonts, nested animations.
+ */
 class SK_API ResourceProvider : public SkRefCnt {
 public:
     ResourceProvider() = default;
@@ -33,7 +37,24 @@
     ResourceProvider(const ResourceProvider&) = delete;
     ResourceProvider& operator=(const ResourceProvider&) = delete;
 
-    virtual sk_sp<SkData> load(const char resource_path[], const char resource_name[]) const = 0;
+    /**
+     * Load a resource (image, nested animation) specified by |path| + |name|, and
+     * return as an SkData.
+     */
+    virtual sk_sp<SkData> load(const char resource_path[],
+                               const char resource_name[]) const;
+
+    /**
+     * Load a web font from |url| and return as an SkData.
+     *
+     * -- Note --
+     *
+     *   This mechanism assumes monolithic fonts (single data blob).  Some web font providers may
+     *   serve multiple font blobs, segmented for various unicode ranges, depending on user agent
+     *   capabilities (woff, woff2).  In that case, the embedder would need to advertise no user
+     *   agent capabilities when fetching the URL, in order to receive full font data.
+     */
+    virtual sk_sp<SkData> loadWebFont(const char url[]) const;
 };
 
 class SK_API Animation : public SkRefCnt {
diff --git a/modules/skottie/src/Skottie.cpp b/modules/skottie/src/Skottie.cpp
index 5d471df..5f5516c 100644
--- a/modules/skottie/src/Skottie.cpp
+++ b/modules/skottie/src/Skottie.cpp
@@ -167,6 +167,14 @@
 
 } // namespace internal
 
+sk_sp<SkData> ResourceProvider::load(const char[], const char[]) const {
+    return nullptr;
+}
+
+sk_sp<SkData> ResourceProvider::loadWebFont(const char[]) const {
+    return nullptr;
+}
+
 Animation::Builder& Animation::Builder::setResourceProvider(sk_sp<ResourceProvider> rp) {
     fResourceProvider = std::move(rp);
     return *this;
diff --git a/modules/skottie/src/SkottieTextLayer.cpp b/modules/skottie/src/SkottieTextLayer.cpp
index 49f834c..20b2eac 100644
--- a/modules/skottie/src/SkottieTextLayer.cpp
+++ b/modules/skottie/src/SkottieTextLayer.cpp
@@ -7,6 +7,7 @@
 
 #include "SkottiePriv.h"
 
+#include "SkData.h"
 #include "SkFontMgr.h"
 #include "SkMakeUnique.h"
 #include "SkottieAdapter.h"
@@ -92,6 +93,7 @@
     //                "fClass": "",
     //                "fFamily": "Roboto",
     //                "fName": "Roboto-Regular",
+    //                "fPath": "https://fonts.googleapis.com/css?family=Roboto",
     //                "fPath": "",
     //                "fStyle": "Regular",
     //                "fWeight": "",
@@ -109,6 +111,7 @@
                 const skjson::StringValue* jname   = (*jfont)["fName"];
                 const skjson::StringValue* jfamily = (*jfont)["fFamily"];
                 const skjson::StringValue* jstyle  = (*jfont)["fStyle"];
+                const skjson::StringValue* jpath   = (*jfont)["fPath"];
 
                 if (!jname   || !jname->size() ||
                     !jfamily || !jfamily->size() ||
@@ -118,8 +121,22 @@
                 }
 
                 const auto& fmgr = fLazyFontMgr.get();
-                sk_sp<SkTypeface> tf(fmgr->matchFamilyStyle(jfamily->begin(),
-                                                            FontStyle(jstyle->begin())));
+
+                // Typeface fallback order:
+                //   1) external web font, if a path/url is provided
+                //   2) system font (family/style)
+                //   3) system default
+
+                sk_sp<SkTypeface> tf;
+
+                if (jpath) {
+                    tf = fmgr->makeFromData(fResourceProvider->loadWebFont(jpath->begin()));
+                }
+
+                if (!tf) {
+                    tf.reset(fmgr->matchFamilyStyle(jfamily->begin(), FontStyle(jstyle->begin())));
+                }
+
                 if (!tf) {
                     LOG("!! Could not create typeface for %s|%s\n",
                         jfamily->begin(), jstyle->begin());