Add svg parsing to CanvasKit viewer.html

Also enables ccpr and makes flags parsing more robust.

Change-Id: Ia98467403de87423a63167681b2ee635b0fa593a
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/292690
Commit-Queue: Chris Dalton <csmartdalton@google.com>
Reviewed-by: Kevin Lubick <kjlubick@google.com>
diff --git a/modules/canvaskit/BUILD.gn b/modules/canvaskit/BUILD.gn
index be152b2..861db54 100644
--- a/modules/canvaskit/BUILD.gn
+++ b/modules/canvaskit/BUILD.gn
@@ -9,6 +9,7 @@
   sources = [
     "../../tools/viewer/SKPSlide.cpp",
     "../../tools/viewer/SampleSlide.cpp",
+    "../../tools/viewer/SvgSlide.cpp",
   ]
   deps = [ "../..:samples" ]
 }
diff --git a/modules/canvaskit/canvaskit/viewer.html b/modules/canvaskit/canvaskit/viewer.html
index e890554..c5c46d1 100644
--- a/modules/canvaskit/canvaskit/viewer.html
+++ b/modules/canvaskit/canvaskit/viewer.html
@@ -17,8 +17,9 @@
 <script type="text/javascript" charset="utf-8">
   const flags = {};
   for (pair of location.hash.substring(1).split(',')) {
-    const [key, value] = pair.split(':', 2);
-    flags[key] = value;
+    // Parse "values" as an array in case the value has a colon (e.g., "slide:http://...").
+    const [key, ...values] = pair.split(':');
+    flags[key] = values.join(':');
   }
   window.onhashchange = function() {
     location.reload();
@@ -35,22 +36,22 @@
   });
 
   function LoadSlide(CanvasKit) {
-    if (!CanvasKit.MakeSlide || !CanvasKit.MakeSkpSlide) {
+    if (!CanvasKit.MakeSlide || !CanvasKit.MakeSkpSlide || !CanvasKit.MakeSvgSlide) {
       throw 'Not compiled with Viewer.';
     }
     const slideName = flags.slide || 'WavyPathText';
-    if (slideName.endsWith('.skp')) {
+    if (slideName.endsWith('.skp') || slideName.endsWith('.svg')) {
       fetch(slideName).then(function(response) {
         if (response.status != 200) {
             throw 'Error fetching ' + slideName;
         }
-        response.arrayBuffer().then(function(data) {
-          let slide = CanvasKit.MakeSkpSlide(slideName, data);
-          if (!slide) {
-            throw 'Could not parse skp data for slide ' + slideName;
-          }
-          ViewerMain(CanvasKit, slide);
-        });
+        if (slideName.endsWith('.skp')) {
+          response.arrayBuffer().then((data) => ViewerMain(
+              CanvasKit, CanvasKit.MakeSkpSlide(slideName, data)));
+        } else {
+          response.text().then((text) => ViewerMain(
+              CanvasKit, CanvasKit.MakeSvgSlide(slideName, text)));
+        }
       });
     } else {
       let slide = CanvasKit.MakeSlide(slideName);
diff --git a/modules/canvaskit/compile.sh b/modules/canvaskit/compile.sh
index e2eb513..6fcf1b0 100755
--- a/modules/canvaskit/compile.sh
+++ b/modules/canvaskit/compile.sh
@@ -90,11 +90,13 @@
   SKOTTIE_BINDINGS=""
 fi
 
+GN_VIEWER="skia_use_expat=false skia_enable_ccpr=false"
 VIEWER_BINDINGS=""
 VIEWER_LIB=""
 
 if [[ $@ == *viewer* ]]; then
   echo "Including viewer"
+  GN_VIEWER="skia_use_expat=true skia_enable_ccpr=true"
   VIEWER_BINDINGS="$BASE_DIR/viewer_bindings.cpp"
   VIEWER_LIB="$BUILD_DIR/libviewer_wasm.a"
   IS_OFFICIAL_BUILD="false"
@@ -268,7 +270,6 @@
   skia_use_angle=false \
   skia_use_dng_sdk=false \
   skia_use_egl=true \
-  skia_use_expat=false \
   skia_use_fontconfig=false \
   skia_use_freetype=true \
   skia_use_libheif=false \
@@ -293,9 +294,9 @@
   ${GN_GPU} \
   ${GN_FONT} \
   ${GN_PARTICLES} \
+  ${GN_VIEWER} \
   \
   skia_enable_skshaper=true \
-  skia_enable_ccpr=false \
   skia_enable_nvpr=false \
   skia_enable_skparagraph=true \
   skia_enable_pdf=false"
diff --git a/modules/canvaskit/viewer_bindings.cpp b/modules/canvaskit/viewer_bindings.cpp
index 9f34ee5..6a6e4bc 100644
--- a/modules/canvaskit/viewer_bindings.cpp
+++ b/modules/canvaskit/viewer_bindings.cpp
@@ -12,6 +12,7 @@
 #include "include/gpu/GrContext.h"
 #include "tools/viewer/SKPSlide.h"
 #include "tools/viewer/SampleSlide.h"
+#include "tools/viewer/SvgSlide.h"
 #include <GLES3/gl3.h>
 #include <string>
 
@@ -31,6 +32,12 @@
     return sk_make_sp<SKPSlide>(SkString(name.c_str()), std::move(stream));
 }
 
+sk_sp<Slide> MakeSvgSlide(std::string name, std::string svgText) {
+    auto stream = std::make_unique<SkMemoryStream>(svgText.data(), svgText.size(),
+                                                   /*copyData=*/true);
+    return sk_make_sp<SvgSlide>(SkString(name.c_str()), std::move(stream));
+}
+
 static void delete_wrapped_framebuffer(SkSurface::ReleaseContext context) {
     GLuint framebuffer = (GLuint)context;
     glDeleteFramebuffers(1, &framebuffer);
@@ -96,6 +103,7 @@
 EMSCRIPTEN_BINDINGS(Viewer) {
     function("MakeSlide", &MakeSlide);
     function("MakeSkpSlide", &MakeSkpSlide);
+    function("MakeSvgSlide", &MakeSvgSlide);
     function("MakeOffscreenFramebuffer", &MakeOffscreenFramebuffer);
     function("BlitOffscreenFramebuffer", &BlitOffscreenFramebuffer);
     class_<Slide>("Slide")
diff --git a/tools/viewer/SvgSlide.cpp b/tools/viewer/SvgSlide.cpp
index 3779ffd..c420843 100644
--- a/tools/viewer/SvgSlide.cpp
+++ b/tools/viewer/SvgSlide.cpp
@@ -14,18 +14,26 @@
 #include "include/core/SkStream.h"
 
 SvgSlide::SvgSlide(const SkString& name, const SkString& path)
-    : fPath(path) {
+        : SvgSlide(name, SkStream::MakeFromFile(path.c_str())) {
+}
+
+SvgSlide::SvgSlide(const SkString& name, std::unique_ptr<SkStream> stream)
+        : fStream(std::move(stream)) {
     fName = name;
 }
 
 void SvgSlide::load(SkScalar w, SkScalar h) {
-    fWinSize   = SkSize::Make(w, h);
+    if (!fStream) {
+        SkDebugf("No svg stream for slide %s.\n", fName.c_str());
+        return;
+    }
 
-    if (const auto svgStream =  SkStream::MakeFromFile(fPath.c_str())) {
-        fDom = SkSVGDOM::MakeFromStream(*svgStream);
-        if (fDom) {
-            fDom->setContainerSize(fWinSize);
-        }
+    fWinSize = SkSize::Make(w, h);
+
+    fStream->rewind();
+    fDom = SkSVGDOM::MakeFromStream(*fStream);
+    if (fDom) {
+        fDom->setContainerSize(fWinSize);
     }
 }
 
diff --git a/tools/viewer/SvgSlide.h b/tools/viewer/SvgSlide.h
index ccc840e..6a15a30 100644
--- a/tools/viewer/SvgSlide.h
+++ b/tools/viewer/SvgSlide.h
@@ -15,6 +15,7 @@
 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;
@@ -24,9 +25,8 @@
 
     void draw(SkCanvas*) override;
 private:
-    const SkString  fPath;
-
-    SkSize          fWinSize = SkSize::MakeEmpty();
+    std::unique_ptr<SkStream> fStream;
+    SkSize fWinSize = SkSize::MakeEmpty();
     sk_sp<SkSVGDOM> fDom;
 
     typedef Slide INHERITED;