[svg] Plumb a ResourceProvider

... for image loading.

Update the SVG tools to pass local/FS resource providers.

Change-Id: I2c0e446047da87f177fde0f23b7ea1f0a856e808
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/359996
Commit-Queue: Florin Malita <fmalita@google.com>
Reviewed-by: Tyler Denniston <tdenniston@google.com>
diff --git a/dm/DMSrcSink.cpp b/dm/DMSrcSink.cpp
index 30645a0..8a8b354 100644
--- a/dm/DMSrcSink.cpp
+++ b/dm/DMSrcSink.cpp
@@ -1313,13 +1313,17 @@
     : fName(SkOSPath::Basename(path.c_str()))
     , fScale(1) {
 
-    sk_sp<SkData> data(SkData::MakeFromFileName(path.c_str()));
-    if (!data) {
+    auto stream = SkStream::MakeFromFile(path.c_str());
+    if (!stream) {
         return;
     }
 
-    SkMemoryStream stream(std::move(data));
-    fDom = SkSVGDOM::MakeFromStream(stream);
+    auto rp = skresources::DataURIResourceProviderProxy::Make(
+                  skresources::FileResourceProvider::Make(SkOSPath::Dirname(path.c_str()),
+                                                          /*predecode=*/true),
+                  /*predecode=*/true);
+    fDom = SkSVGDOM::Builder().setResourceProvider(std::move(rp))
+                              .make(*stream);
     if (!fDom) {
         return;
     }
diff --git a/modules/svg/BUILD.gn b/modules/svg/BUILD.gn
index 6f5a4d3..e1a6056 100644
--- a/modules/svg/BUILD.gn
+++ b/modules/svg/BUILD.gn
@@ -20,6 +20,7 @@
     configs += [ "../../:skia_private" ]
     deps = [
       "../..:skia",
+      "../skresources",
       "../skshaper",
     ]
   }
diff --git a/modules/svg/include/SkSVGDOM.h b/modules/svg/include/SkSVGDOM.h
index 2c0bc27..c9e0b31 100644
--- a/modules/svg/include/SkSVGDOM.h
+++ b/modules/svg/include/SkSVGDOM.h
@@ -12,6 +12,7 @@
 #include "include/core/SkRefCnt.h"
 #include "include/core/SkSize.h"
 #include "include/private/SkTemplates.h"
+#include "modules/skresources/include/SkResources.h"
 #include "modules/svg/include/SkSVGIDMapper.h"
 
 class SkCanvas;
@@ -29,10 +30,16 @@
          */
         Builder& setFontManager(sk_sp<SkFontMgr>);
 
+        /**
+         * Specify a resource provider for loading images etc.
+         */
+        Builder& setResourceProvider(sk_sp<skresources::ResourceProvider>);
+
         sk_sp<SkSVGDOM> make(SkStream&) const;
 
     private:
-        sk_sp<SkFontMgr> fFontMgr;
+        sk_sp<SkFontMgr>                     fFontMgr;
+        sk_sp<skresources::ResourceProvider> fResourceProvider;
     };
 
     static sk_sp<SkSVGDOM> MakeFromStream(SkStream& str) {
@@ -48,11 +55,13 @@
     void render(SkCanvas*) const;
 
 private:
-    SkSVGDOM(sk_sp<SkSVGSVG>, sk_sp<SkFontMgr>, SkSVGIDMapper&&);
+    SkSVGDOM(sk_sp<SkSVGSVG>, sk_sp<SkFontMgr>, sk_sp<skresources::ResourceProvider>,
+             SkSVGIDMapper&&);
 
-    const sk_sp<SkSVGSVG>  fRoot;
-    const sk_sp<SkFontMgr> fFontMgr;
-    const SkSVGIDMapper    fIDMapper;
+    const sk_sp<SkSVGSVG>                      fRoot;
+    const sk_sp<SkFontMgr>                     fFontMgr;
+    const sk_sp<skresources::ResourceProvider> fResourceProvider;
+    const SkSVGIDMapper                        fIDMapper;
 
     SkSize                 fContainerSize;
 };
diff --git a/modules/svg/include/SkSVGRenderContext.h b/modules/svg/include/SkSVGRenderContext.h
index 5be4e37..981756a 100644
--- a/modules/svg/include/SkSVGRenderContext.h
+++ b/modules/svg/include/SkSVGRenderContext.h
@@ -14,6 +14,7 @@
 #include "include/core/SkRect.h"
 #include "include/core/SkSize.h"
 #include "include/core/SkTypes.h"
+#include "modules/skresources/include/SkResources.h"
 #include "modules/svg/include/SkSVGAttribute.h"
 #include "modules/svg/include/SkSVGIDMapper.h"
 #include "src/core/SkTLazy.h"
@@ -55,7 +56,8 @@
 
 class SkSVGRenderContext {
 public:
-    SkSVGRenderContext(SkCanvas*, const sk_sp<SkFontMgr>&, const SkSVGIDMapper&,
+    SkSVGRenderContext(SkCanvas*, const sk_sp<SkFontMgr>&,
+                       const sk_sp<skresources::ResourceProvider>&, const SkSVGIDMapper&,
                        const SkSVGLengthContext&, const SkSVGPresentationContext&,
                        const SkSVGNode*);
     SkSVGRenderContext(const SkSVGRenderContext&);
@@ -145,6 +147,7 @@
     SkTLazy<SkPaint> commonPaint(const SkSVGPaint&, float opacity) const;
 
     const sk_sp<SkFontMgr>&                       fFontMgr;
+    const sk_sp<skresources::ResourceProvider>&   fResourceProvider;
     const SkSVGIDMapper&                          fIDMapper;
     SkTCopyOnFirstWrite<SkSVGLengthContext>       fLengthContext;
     SkTCopyOnFirstWrite<SkSVGPresentationContext> fPresentationContext;
diff --git a/modules/svg/src/SkSVGDOM.cpp b/modules/svg/src/SkSVGDOM.cpp
index e562b53..08b8c65 100644
--- a/modules/svg/src/SkSVGDOM.cpp
+++ b/modules/svg/src/SkSVGDOM.cpp
@@ -410,6 +410,11 @@
     return *this;
 }
 
+SkSVGDOM::Builder& SkSVGDOM::Builder::setResourceProvider(sk_sp<skresources::ResourceProvider> rp) {
+    fResourceProvider = std::move(rp);
+    return *this;
+}
+
 sk_sp<SkSVGDOM> SkSVGDOM::Builder::make(SkStream& str) const {
     SkDOM xmlDom;
     if (!xmlDom.build(str)) {
@@ -424,22 +429,35 @@
         return nullptr;
     }
 
+    class NullResourceProvider final : public skresources::ResourceProvider {
+        sk_sp<SkData> load(const char[], const char[]) const override { return nullptr; }
+    };
+
+    auto resource_provider = fResourceProvider ? fResourceProvider
+                                               : sk_make_sp<NullResourceProvider>();
+
     return sk_sp<SkSVGDOM>(new SkSVGDOM(sk_sp<SkSVGSVG>(static_cast<SkSVGSVG*>(root.release())),
-                                        std::move(fFontMgr), std::move(mapper)));
+                                        std::move(fFontMgr), std::move(resource_provider),
+                                        std::move(mapper)));
 }
 
-SkSVGDOM::SkSVGDOM(sk_sp<SkSVGSVG> root, sk_sp<SkFontMgr> fmgr, SkSVGIDMapper&& mapper)
+SkSVGDOM::SkSVGDOM(sk_sp<SkSVGSVG> root, sk_sp<SkFontMgr> fmgr,
+                   sk_sp<skresources::ResourceProvider> rp, SkSVGIDMapper&& mapper)
     : fRoot(std::move(root))
     , fFontMgr(std::move(fmgr))
+    , fResourceProvider(std::move(rp))
     , fIDMapper(std::move(mapper))
     , fContainerSize(fRoot->intrinsicSize(SkSVGLengthContext(SkSize::Make(0, 0))))
-{}
+{
+    SkASSERT(fResourceProvider);
+}
 
 void SkSVGDOM::render(SkCanvas* canvas) const {
     if (fRoot) {
         SkSVGLengthContext       lctx(fContainerSize);
         SkSVGPresentationContext pctx;
-        fRoot->render(SkSVGRenderContext(canvas, fFontMgr, fIDMapper, lctx, pctx, nullptr));
+        fRoot->render(SkSVGRenderContext(canvas, fFontMgr, fResourceProvider, fIDMapper, lctx, pctx,
+                                         nullptr));
     }
 }
 
diff --git a/modules/svg/src/SkSVGRenderContext.cpp b/modules/svg/src/SkSVGRenderContext.cpp
index 563f8db..db5191a 100644
--- a/modules/svg/src/SkSVGRenderContext.cpp
+++ b/modules/svg/src/SkSVGRenderContext.cpp
@@ -145,11 +145,13 @@
 
 SkSVGRenderContext::SkSVGRenderContext(SkCanvas* canvas,
                                        const sk_sp<SkFontMgr>& fmgr,
+                                       const sk_sp<skresources::ResourceProvider>& rp,
                                        const SkSVGIDMapper& mapper,
                                        const SkSVGLengthContext& lctx,
                                        const SkSVGPresentationContext& pctx,
                                        const SkSVGNode* node)
     : fFontMgr(fmgr)
+    , fResourceProvider(rp)
     , fIDMapper(mapper)
     , fLengthContext(lctx)
     , fPresentationContext(pctx)
@@ -160,6 +162,7 @@
 SkSVGRenderContext::SkSVGRenderContext(const SkSVGRenderContext& other)
     : SkSVGRenderContext(other.fCanvas,
                          other.fFontMgr,
+                         other.fResourceProvider,
                          other.fIDMapper,
                          *other.fLengthContext,
                          *other.fPresentationContext,
@@ -168,6 +171,7 @@
 SkSVGRenderContext::SkSVGRenderContext(const SkSVGRenderContext& other, SkCanvas* canvas)
     : SkSVGRenderContext(canvas,
                          other.fFontMgr,
+                         other.fResourceProvider,
                          other.fIDMapper,
                          *other.fLengthContext,
                          *other.fPresentationContext,
@@ -176,6 +180,7 @@
 SkSVGRenderContext::SkSVGRenderContext(const SkSVGRenderContext& other, const SkSVGNode* node)
     : SkSVGRenderContext(other.fCanvas,
                          other.fFontMgr,
+                         other.fResourceProvider,
                          other.fIDMapper,
                          *other.fLengthContext,
                          *other.fPresentationContext,
@@ -390,6 +395,7 @@
         SkSVGPresentationContext pctx;
         SkSVGRenderContext local_ctx(fCanvas,
                                      fFontMgr,
+                                     fResourceProvider,
                                      fIDMapper,
                                      *fLengthContext,
                                      pctx,
diff --git a/modules/svg/tests/Text.cpp b/modules/svg/tests/Text.cpp
index 107395b..7308ac8 100644
--- a/modules/svg/tests/Text.cpp
+++ b/modules/svg/tests/Text.cpp
@@ -162,7 +162,8 @@
         const SkSVGPresentationContext pctx;
         SkNoDrawCanvas canvas(0, 0);
         sk_sp<SkFontMgr> fmgr;
-        const SkSVGRenderContext ctx(&canvas, fmgr, mapper, lctx, pctx, nullptr);
+        sk_sp<skresources::ResourceProvider> rp;
+        const SkSVGRenderContext ctx(&canvas, fmgr, rp, mapper, lctx, pctx, nullptr);
 
         SkSVGTextContext tctx(ctx, mock_cb);
         SkSVGTextContext::ScopedPosResolver pa(*a, lctx, &tctx, tst.offseta);
diff --git a/modules/svg/utils/SvgTool.cpp b/modules/svg/utils/SvgTool.cpp
index 71ab3c3..7ee49a2 100644
--- a/modules/svg/utils/SvgTool.cpp
+++ b/modules/svg/utils/SvgTool.cpp
@@ -11,7 +11,9 @@
 #include "include/core/SkStream.h"
 #include "include/core/SkSurface.h"
 #include "include/encode/SkPngEncoder.h"
+#include "modules/skresources/include/SkResources.h"
 #include "modules/svg/include/SkSVGDOM.h"
+#include "src/utils/SkOSPath.h"
 #include "tools/flags/CommandLineFlags.h"
 
 static DEFINE_string2(input , i, nullptr, "Input SVG file.");
@@ -39,9 +41,14 @@
         return 1;
     }
 
+    auto rp = skresources::DataURIResourceProviderProxy::Make(
+                  skresources::FileResourceProvider::Make(SkOSPath::Dirname(FLAGS_input[0]),
+                                                          /*predecode=*/true),
+                  /*predecode=*/true);
 
     auto svg_dom = SkSVGDOM::Builder()
                         .setFontManager(SkFontMgr::RefDefault())
+                        .setResourceProvider(std::move(rp))
                         .make(in);
     if (!svg_dom) {
         std::cerr << "Could not parse " << FLAGS_input[0] << "\n";
diff --git a/tools/viewer/SvgSlide.cpp b/tools/viewer/SvgSlide.cpp
index 28bdb21..2bab0ae 100644
--- a/tools/viewer/SvgSlide.cpp
+++ b/tools/viewer/SvgSlide.cpp
@@ -11,27 +11,31 @@
 
 #include "include/core/SkCanvas.h"
 #include "include/core/SkStream.h"
+#include "modules/skresources/include/SkResources.h"
 #include "modules/svg/include/SkSVGDOM.h"
+#include "src/utils/SkOSPath.h"
 
 SvgSlide::SvgSlide(const SkString& name, const SkString& path)
-        : SvgSlide(name, SkStream::MakeFromFile(path.c_str())) {
-}
-
-SvgSlide::SvgSlide(const SkString& name, std::unique_ptr<SkStream> stream)
-        : fStream(std::move(stream)) {
+    : fPath(path)
+{
     fName = name;
 }
 
 void SvgSlide::load(SkScalar w, SkScalar h) {
-    if (!fStream) {
-        SkDebugf("No svg stream for slide %s.\n", fName.c_str());
+    auto stream = SkStream::MakeFromFile(fPath.c_str());
+
+    if (!stream) {
+        SkDebugf("Could not open %s.\n", fPath.c_str());
         return;
     }
 
     fWinSize = SkSize::Make(w, h);
 
-    fStream->rewind();
-    fDom = SkSVGDOM::MakeFromStream(*fStream);
+    auto rp = skresources::DataURIResourceProviderProxy::Make(
+                  skresources::FileResourceProvider::Make(SkOSPath::Dirname(fPath.c_str()),
+                                                          /*predecode=*/true),
+                  /*predecode=*/true);
+    fDom = SkSVGDOM::Builder().setResourceProvider(std::move(rp)).make(*stream);
     if (fDom) {
         fDom->setContainerSize(fWinSize);
     }
diff --git a/tools/viewer/SvgSlide.h b/tools/viewer/SvgSlide.h
index fa10ffe..895e3fc 100644
--- a/tools/viewer/SvgSlide.h
+++ b/tools/viewer/SvgSlide.h
@@ -15,7 +15,6 @@
 class SvgSlide final : public Slide {
 public:
     SvgSlide(const SkString& name, const SkString& path);
-    SvgSlide(const SkString& name, std::unique_ptr<SkStream>);
 
     void load(SkScalar winWidth, SkScalar winHeight) override;
     void unload() override;
@@ -25,8 +24,9 @@
 
     void draw(SkCanvas*) override;
 private:
-    std::unique_ptr<SkStream> fStream;
-    SkSize fWinSize = SkSize::MakeEmpty();
+    const SkString  fPath;
+
+    SkSize          fWinSize = SkSize::MakeEmpty();
     sk_sp<SkSVGDOM> fDom;
 
     using INHERITED = Slide;