Add SkSVGCanvas

Add a public SVG canvas factory + move the SVG files from
experimental -> src/svg/.

Update current clients to the new API.

R=reed@google.com, mtklein@google.com, halcanary@google.com

Review URL: https://codereview.chromium.org/902583006
diff --git a/dm/DMSrcSink.cpp b/dm/DMSrcSink.cpp
index 8370573..b0df70b 100644
--- a/dm/DMSrcSink.cpp
+++ b/dm/DMSrcSink.cpp
@@ -6,8 +6,9 @@
 #include "SkOSFile.h"
 #include "SkPictureRecorder.h"
 #include "SkRandom.h"
-#include "SkSVGDevice.h"
+#include "SkSVGCanvas.h"
 #include "SkStream.h"
+#include "SkXMLWriter.h"
 
 namespace DM {
 
@@ -237,9 +238,11 @@
 SVGSink::SVGSink() {}
 
 Error SVGSink::draw(const Src& src, SkBitmap*, SkWStream* dst, SkString*) const {
-    SkAutoTUnref<SkBaseDevice> device(SkSVGDevice::Create(src.size(), dst));
-    SkCanvas canvas(device);
-    return src.draw(&canvas);
+    SkAutoTDelete<SkXMLWriter> xmlWriter(SkNEW_ARGS(SkXMLStreamWriter, (dst)));
+    SkAutoTUnref<SkCanvas> canvas(SkSVGCanvas::Create(
+        SkRect::MakeWH(SkIntToScalar(src.size().width()), SkIntToScalar(src.size().height())),
+        xmlWriter));
+    return src.draw(canvas);
 }
 
 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
diff --git a/gyp/dm.gypi b/gyp/dm.gypi
index 9ace2ac..3912bec 100644
--- a/gyp/dm.gypi
+++ b/gyp/dm.gypi
@@ -2,7 +2,6 @@
 {
   'include_dirs': [
     '../dm',
-    '../experimental/svg',
     '../gm',
     '../src/core',
     '../src/effects',
@@ -19,6 +18,7 @@
     'flags.gyp:flags',
     'jsoncpp.gyp:jsoncpp',
     'skia_lib.gyp:skia_lib',
+    'svg.gyp:svg',
     'tools.gyp:crash_handler',
     'tools.gyp:proc_stats',
     'tools.gyp:sk_tool_utils',
@@ -36,7 +36,6 @@
     '../dm/DMJsonWriter.cpp',
     '../gm/gm.cpp',
 
-    '../experimental/svg/SkSVGDevice.cpp',
     '../src/pipe/utils/SamplePipeControllers.cpp',
     '../src/utils/debugger/SkDebugCanvas.cpp',
     '../src/utils/debugger/SkDrawCommand.cpp',
diff --git a/gyp/svg.gyp b/gyp/svg.gyp
index 4c0822e..d681bda 100644
--- a/gyp/svg.gyp
+++ b/gyp/svg.gyp
@@ -10,6 +10,31 @@
         'xml.gyp:*',
       ],
       'include_dirs': [
+        '../include/svg',
+      ],
+      'sources': [
+        '<(skia_include_path)/svg/SkSVGCanvas.h',
+
+        '<(skia_src_path)/svg/SkSVGCanvas.cpp',
+        '<(skia_src_path)/svg/SkSVGDevice.cpp',
+        '<(skia_src_path)/svg/SkSVGDevice.h',
+      ],
+      'direct_dependent_settings': {
+        'include_dirs': [
+          '../include/svg',
+        ],
+      },
+    },
+    {
+      'target_name': 'svg_parser',
+      'product_name': 'skia_svg_parser',
+      'type': 'static_library',
+      'standalone_static_library': 1,
+      'dependencies': [
+        'skia_lib.gyp:skia_lib',
+        'xml.gyp:*',
+      ],
+      'include_dirs': [
         '../include/svg/parser',
       ],
       'sources': [
diff --git a/gyp/tools.gyp b/gyp/tools.gyp
index c844ebe..a83522c 100644
--- a/gyp/tools.gyp
+++ b/gyp/tools.gyp
@@ -265,12 +265,11 @@
       ],
     },
     {
+      # Superseded by dm, should be removed.
       'target_name': 'skp2svg',
       'type': 'executable',
       'sources': [
-        '../experimental/svg/skp2svg.cpp',
-        '../experimental/svg/SkSVGDevice.cpp',
-        '../experimental/svg/SkSVGDevice.h',
+        '../src/svg/skp2svg.cpp',
         '../tools/LazyDecodeBitmap.cpp',
       ],
       'include_dirs': [
@@ -281,6 +280,7 @@
       'dependencies': [
         'flags.gyp:flags',
         'skia_lib.gyp:skia_lib',
+        'svg.gyp:svg',
         'xml.gyp:xml',
       ],
     },
diff --git a/include/svg/SkSVGCanvas.h b/include/svg/SkSVGCanvas.h
new file mode 100644
index 0000000..e285faa
--- /dev/null
+++ b/include/svg/SkSVGCanvas.h
@@ -0,0 +1,31 @@
+/*
+ * 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 SkSVGCanvas_DEFINED
+#define SkSVGCanvas_DEFINED
+
+#include "SkCanvas.h"
+
+class SkXMLWriter;
+
+class SK_API SkSVGCanvas {
+public:
+    /**
+     *  Returns a new canvas that will generate SVG commands from its draw calls, and send
+     *  them to the provided xmlwriter. Ownership of the xmlwriter is not transfered to the canvas,
+     *  but it must stay valid during the lifetime of the returned canvas.
+     *
+     *  The canvas may buffer some drawing calls, so the output is not guaranteed to be valid
+     *  or complete until the canvas instance is deleted.
+     *
+     *  The 'bounds' parameter defines an initial SVG viewport (viewBox attribute on the root
+     *  SVG element).
+     */
+    static SkCanvas* Create(const SkRect& bounds, SkXMLWriter*);
+};
+
+#endif
diff --git a/src/svg/SkSVGCanvas.cpp b/src/svg/SkSVGCanvas.cpp
new file mode 100644
index 0000000..22a6e0b
--- /dev/null
+++ b/src/svg/SkSVGCanvas.cpp
@@ -0,0 +1,17 @@
+/*
+ * Copyright 2015 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "SkSVGCanvas.h"
+#include "SkSVGDevice.h"
+
+SkCanvas* SkSVGCanvas::Create(const SkRect& bounds, SkXMLWriter* writer) {
+    // TODO: pass full bounds to the device
+    SkISize size = bounds.roundOut().size();
+    SkAutoTUnref<SkBaseDevice> device(SkSVGDevice::Create(size, writer));
+
+    return SkNEW_ARGS(SkCanvas, (device));
+}
diff --git a/experimental/svg/SkSVGDevice.cpp b/src/svg/SkSVGDevice.cpp
similarity index 98%
rename from experimental/svg/SkSVGDevice.cpp
rename to src/svg/SkSVGDevice.cpp
index 8d4ee4c..bf19a81 100644
--- a/experimental/svg/SkSVGDevice.cpp
+++ b/src/svg/SkSVGDevice.cpp
@@ -471,17 +471,18 @@
     }
 }
 
-SkBaseDevice* SkSVGDevice::Create(const SkISize& size, SkWStream* wstream) {
-    if (!SkToBool(wstream)) {
+SkBaseDevice* SkSVGDevice::Create(const SkISize& size, SkXMLWriter* writer) {
+    if (!writer) {
         return NULL;
     }
 
-    return SkNEW_ARGS(SkSVGDevice, (size, wstream));
+    return SkNEW_ARGS(SkSVGDevice, (size, writer));
 }
 
-SkSVGDevice::SkSVGDevice(const SkISize& size, SkWStream* wstream)
-    : fWriter(SkNEW_ARGS(SkXMLStreamWriter, (wstream)))
+SkSVGDevice::SkSVGDevice(const SkISize& size, SkXMLWriter* writer)
+    : fWriter(writer)
     , fResourceBucket(SkNEW(ResourceBucket)) {
+    SkASSERT(writer);
 
     fLegacyBitmap.setInfo(SkImageInfo::MakeUnknown(size.width(), size.height()));
 
diff --git a/experimental/svg/SkSVGDevice.h b/src/svg/SkSVGDevice.h
similarity index 93%
rename from experimental/svg/SkSVGDevice.h
rename to src/svg/SkSVGDevice.h
index 0ea9e19..fdfc8c3 100644
--- a/experimental/svg/SkSVGDevice.h
+++ b/src/svg/SkSVGDevice.h
@@ -10,12 +10,11 @@
 
 #include "SkDevice.h"
 
-class SkWStream;
 class SkXMLWriter;
 
 class SkSVGDevice : public SkBaseDevice {
 public:
-    static SkBaseDevice* Create(const SkISize& size, SkWStream* wstream);
+    static SkBaseDevice* Create(const SkISize& size, SkXMLWriter* writer);
 
     virtual SkImageInfo imageInfo() const SK_OVERRIDE;
 
@@ -59,13 +58,13 @@
     virtual const SkBitmap& onAccessBitmap() SK_OVERRIDE;
 
 private:
-    SkSVGDevice(const SkISize& size, SkWStream* wstream);
+    SkSVGDevice(const SkISize& size, SkXMLWriter* writer);
     virtual ~SkSVGDevice();
 
     class AutoElement;
     class ResourceBucket;
 
-    SkAutoTDelete<SkXMLWriter>    fWriter;
+    SkXMLWriter*                  fWriter;
     SkAutoTDelete<AutoElement>    fRootElement;
     SkAutoTDelete<ResourceBucket> fResourceBucket;
     SkBitmap                      fLegacyBitmap;
diff --git a/experimental/svg/skp2svg.cpp b/src/svg/skp2svg.cpp
similarity index 86%
rename from experimental/svg/skp2svg.cpp
rename to src/svg/skp2svg.cpp
index 95bb04a..ae6e54c 100644
--- a/experimental/svg/skp2svg.cpp
+++ b/src/svg/skp2svg.cpp
@@ -9,7 +9,8 @@
 #include "SkCommandLineFlags.h"
 #include "SkPicture.h"
 #include "SkStream.h"
-#include "SkSVGDevice.h"
+#include "SkSVGCanvas.h"
+#include "SkXMLWriter.h"
 
 DEFINE_string2(input, i, "", "input skp file");
 DEFINE_string2(output, o, "", "output svg file (optional)");
@@ -54,11 +55,10 @@
         outStream.reset(SkNEW(SkDebugWStream));
     }
 
-    SkISize size = pic->cullRect().roundOut().size();
-    SkAutoTUnref<SkBaseDevice> svgDevice(SkSVGDevice::Create(size, outStream));
-    SkCanvas svgCanvas(svgDevice.get());
+    SkAutoTDelete<SkXMLWriter> xmlWriter(SkNEW_ARGS(SkXMLStreamWriter, (outStream.get())));
+    SkAutoTUnref<SkCanvas> svgCanvas(SkSVGCanvas::Create(pic->cullRect(), xmlWriter.get()));
 
-    pic->playback(&svgCanvas);
+    pic->playback(svgCanvas);
 
     return kSuccess;
 }