[svg] Relocate out of experimental

Move the SVG rendering code to modules/svg, and componentize.
Also split into include/src/utils.

As external clients still reference the old header locations,
introduce temporary forwarding headers to facilitate the migration.

Change-Id: Ib289dbdcd80c16a01c47805e7242f2e08bebc165
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/326948
Reviewed-by: Tyler Denniston <tdenniston@google.com>
Commit-Queue: Florin Malita <fmalita@google.com>
diff --git a/BUILD.gn b/BUILD.gn
index 1021b43..3b103ef 100644
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -1801,8 +1801,8 @@
       defines += [ "SK_TOOLS_REQUIRE_RESOURCES" ]
     }
     deps = [
-      ":experimental_svg_model",
       ":flags",
+      "modules/svg",
     ]
     public_deps = [ ":gpu_tool_utils" ]
   }
@@ -1866,7 +1866,6 @@
       sources -= [ "//tests/FontMgrFontConfigTest.cpp" ]
     }
     deps = [
-      ":experimental_svg_model",
       ":flags",
       ":skia",
       ":skvm_builders",
@@ -1901,52 +1900,6 @@
     ]
   }
 
-  # TODO(fmalita): componentize & relocate
-  test_lib("experimental_svg_model") {
-    if (skia_use_expat) {
-      sources = [
-        "experimental/svg/model/SkSVGAttribute.cpp",
-        "experimental/svg/model/SkSVGAttributeParser.cpp",
-        "experimental/svg/model/SkSVGCircle.cpp",
-        "experimental/svg/model/SkSVGClipPath.cpp",
-        "experimental/svg/model/SkSVGContainer.cpp",
-        "experimental/svg/model/SkSVGDOM.cpp",
-        "experimental/svg/model/SkSVGEllipse.cpp",
-        "experimental/svg/model/SkSVGGradient.cpp",
-        "experimental/svg/model/SkSVGLine.cpp",
-        "experimental/svg/model/SkSVGLinearGradient.cpp",
-        "experimental/svg/model/SkSVGNode.cpp",
-        "experimental/svg/model/SkSVGPath.cpp",
-        "experimental/svg/model/SkSVGPattern.cpp",
-        "experimental/svg/model/SkSVGPoly.cpp",
-        "experimental/svg/model/SkSVGRadialGradient.cpp",
-        "experimental/svg/model/SkSVGRect.cpp",
-        "experimental/svg/model/SkSVGRenderContext.cpp",
-        "experimental/svg/model/SkSVGSVG.cpp",
-        "experimental/svg/model/SkSVGShape.cpp",
-        "experimental/svg/model/SkSVGStop.cpp",
-        "experimental/svg/model/SkSVGText.cpp",
-        "experimental/svg/model/SkSVGTransformableNode.cpp",
-        "experimental/svg/model/SkSVGUse.cpp",
-        "experimental/svg/model/SkSVGValue.cpp",
-      ]
-      deps = [
-        ":skia",
-        ":xml",
-      ]
-    }
-  }
-
-  if (skia_use_expat && !skia_use_wuffs) {
-    test_app("svg_tool") {
-      sources = [ "experimental/svg/utils/SvgTool.cpp" ]
-      deps = [
-        ":experimental_svg_model",
-        ":flags",
-      ]
-    }
-  }
-
   test_lib("experimental_xform") {
     sources = [
       "experimental/xform/SkShape.cpp",
@@ -1960,6 +1913,9 @@
     test_app("skottie_tool") {
       deps = [ "modules/skottie:tool" ]
     }
+    test_app("svg_tool") {
+      deps = [ "modules/svg:tool" ]
+    }
   }
 
   test_app("make_skqp_model") {
@@ -1975,7 +1931,6 @@
     }
     public_deps = [ ":tool_utils" ]
     deps = [
-      ":experimental_svg_model",
       ":flags",
       ":gpu_tool_utils",
       ":xml",
@@ -2015,7 +1970,6 @@
       deps = [
         ":common_flags_aa",
         ":common_flags_gpu",
-        ":experimental_svg_model",
         ":flags",
         ":gm",
         ":gpu_tool_utils",
@@ -2026,6 +1980,7 @@
         ":trace",
         "modules/skottie",
         "modules/skottie:utils",
+        "modules/svg",
       ]
     }
     test_app("dm") {
@@ -2040,7 +1995,6 @@
         ":common_flags_config",
         ":common_flags_gpu",
         ":common_flags_images",
-        ":experimental_svg_model",
         ":flags",
         ":gm",
         ":gpu_tool_utils",
@@ -2052,6 +2006,7 @@
         "experimental/skrive",
         "modules/skottie",
         "modules/skottie:utils",
+        "modules/svg",
       ]
     }
   }
@@ -2078,7 +2033,6 @@
       ":common_flags_config",
       ":common_flags_gpu",
       ":common_flags_images",
-      ":experimental_svg_model",
       ":flags",
       ":gm",
       ":gpu_tool_utils",
@@ -2578,7 +2532,6 @@
 
       deps = [
         ":common_flags_gpu",
-        ":experimental_svg_model",
         ":flags",
         ":gm",
         ":gpu_tool_utils",
@@ -2593,6 +2546,7 @@
         "modules/skottie",
         "modules/skottie:utils",
         "modules/sksg:samples",
+        "modules/svg",
         "//third_party/imgui",
       ]
       if (skia_use_experimental_xform) {
@@ -2783,7 +2737,7 @@
         "tools/fonts/TestSVGTypeface.cpp",
         "tools/fonts/TestTypeface.cpp",
       ]
-      deps = [ ":experimental_svg_model" ]
+      deps = [ "modules/svg" ]
     }
 
     libfuzzer_app("region_set_path") {
@@ -2803,7 +2757,7 @@
         "tools/fonts/TestSVGTypeface.cpp",
         "tools/fonts/TestTypeface.cpp",
       ]
-      deps = [ ":experimental_svg_model" ]
+      deps = [ "modules/svg" ]
     }
 
     libfuzzer_app("path_deserialize") {
@@ -2840,7 +2794,7 @@
         "tools/fonts/TestTypeface.cpp",
       ]
       deps = [
-        ":experimental_svg_model",
+        "modules/svg",
         "//third_party/libpng",
       ]
     }
@@ -2914,7 +2868,7 @@
         "tools/fonts/TestTypeface.cpp",
       ]
       deps = [
-        ":experimental_svg_model",
+        "modules/svg",
         "//third_party/libpng",
       ]
     }
@@ -2941,7 +2895,7 @@
           "tools/fonts/TestTypeface.cpp",
         ]
         deps = [
-          ":experimental_svg_model",
+          "modules/svg",
           "//third_party/libpng",
         ]
       }
@@ -2967,7 +2921,7 @@
         "tools/fonts/TestTypeface.cpp",
       ]
       deps = [
-        ":experimental_svg_model",
+        "modules/svg",
         "//third_party/libpng",
       ]
     }
@@ -2991,7 +2945,7 @@
         "tools/fonts/TestTypeface.cpp",
       ]
       deps = [
-        ":experimental_svg_model",
+        "modules/svg",
         "//third_party/libpng",
       ]
     }
@@ -3029,8 +2983,8 @@
         "tools/fonts/TestTypeface.cpp",
       ]
       deps = [
-        ":experimental_svg_model",
         "modules/skottie:skottie",
+        "modules/svg",
       ]
     }
 
@@ -3084,7 +3038,7 @@
 
     libfuzzer_app("svg_dom") {
       sources = [ "fuzz/oss_fuzz/FuzzSVG.cpp" ]
-      deps = [ ":experimental_svg_model" ]
+      deps = [ "modules/svg" ]
     }
 
     libfuzzer_app("skruntimeeffect") {
diff --git a/bench/nanobench.cpp b/bench/nanobench.cpp
index ffb42cf..04dbd011 100644
--- a/bench/nanobench.cpp
+++ b/bench/nanobench.cpp
@@ -48,7 +48,7 @@
 #include "tools/trace/SkDebugfTracer.h"
 
 #ifdef SK_XML
-#include "experimental/svg/model/SkSVGDOM.h"
+#include "modules/svg/include/SkSVGDOM.h"
 #endif  // SK_XML
 
 #ifdef SK_ENABLE_ANDROID_UTILS
diff --git a/dm/DMSrcSink.cpp b/dm/DMSrcSink.cpp
index c7f3601..eb2ff11 100644
--- a/dm/DMSrcSink.cpp
+++ b/dm/DMSrcSink.cpp
@@ -71,8 +71,8 @@
 #endif
 
 #if defined(SK_XML)
-    #include "experimental/svg/model/SkSVGDOM.h"
     #include "include/svg/SkSVGCanvas.h"
+    #include "modules/svg/include/SkSVGDOM.h"
     #include "src/xml/SkXMLWriter.h"
 #endif
 
@@ -2339,8 +2339,8 @@
 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
 
 #ifdef TEST_VIA_SVG
-#include "experimental/svg/model/SkSVGDOM.h"
 #include "include/svg/SkSVGCanvas.h"
+#include "modules/svg/include/SkSVGDOM.h"
 #include "src/xml/SkXMLWriter.h"
 
 Result ViaSVG::draw(const Src& src, SkBitmap* bitmap, SkWStream* stream, SkString* log) const {
diff --git a/experimental/svg/model/SkSVGAttribute.h b/experimental/svg/model/SkSVGAttribute.h
index 3a2f5a8..48a3de8 100644
--- a/experimental/svg/model/SkSVGAttribute.h
+++ b/experimental/svg/model/SkSVGAttribute.h
@@ -1,99 +1,10 @@
 /*
- * Copyright 2016 Google Inc.
+ * Copyright 2020 Google Inc.
  *
  * Use of this source code is governed by a BSD-style license that can be
  * found in the LICENSE file.
  */
 
-#ifndef SkSVGAttribute_DEFINED
-#define SkSVGAttribute_DEFINED
+// Transitional forwarding header.  To be removed.
+#include "modules/svg/include/SkSVGAttribute.h"
 
-#include "experimental/svg/model/SkSVGTypes.h"
-#include "src/core/SkTLazy.h"
-
-class SkSVGRenderContext;
-
-enum class SkSVGAttribute {
-    kClipPath,
-    kClipRule,
-    kColor,
-    kCx, // <circle>, <ellipse>, <radialGradient>: center x position
-    kCy, // <circle>, <ellipse>, <radialGradient>: center y position
-    kD,
-    kFill,
-    kFillOpacity,
-    kFillRule,
-    kFontFamily,
-    kFontSize,
-    kFontStyle,
-    kFontWeight,
-    kFx, // <radialGradient>: focal point x position
-    kFy, // <radialGradient>: focal point y position
-    kGradientTransform,
-    kHeight,
-    kHref,
-    kOffset,
-    kOpacity,
-    kPatternTransform,
-    kPoints,
-    kR,  // <circle>, <radialGradient>: radius
-    kRx, // <ellipse>,<rect>: horizontal (corner) radius
-    kRy, // <ellipse>,<rect>: vertical (corner) radius
-    kSpreadMethod,
-    kStopColor,
-    kStopOpacity,
-    kStroke,
-    kStrokeDashArray,
-    kStrokeDashOffset,
-    kStrokeOpacity,
-    kStrokeLineCap,
-    kStrokeLineJoin,
-    kStrokeMiterLimit,
-    kStrokeWidth,
-    kTransform,
-    kText,
-    kTextAnchor,
-    kViewBox,
-    kVisibility,
-    kWidth,
-    kX,
-    kX1, // <line>: first endpoint x
-    kX2, // <line>: second endpoint x
-    kY,
-    kY1, // <line>: first endpoint y
-    kY2, // <line>: second endpoint y
-
-    kUnknown,
-};
-
-struct SkSVGPresentationAttributes {
-    static SkSVGPresentationAttributes MakeInitial();
-
-    // TODO: SkTLazy adds an extra ptr per attribute; refactor to reduce overhead.
-
-    SkTLazy<SkSVGPaint>      fFill;
-    SkTLazy<SkSVGNumberType> fFillOpacity;
-    SkTLazy<SkSVGFillRule>   fFillRule;
-    SkTLazy<SkSVGFillRule>   fClipRule;
-
-    SkTLazy<SkSVGPaint>      fStroke;
-    SkTLazy<SkSVGDashArray>  fStrokeDashArray;
-    SkTLazy<SkSVGLength>     fStrokeDashOffset;
-    SkTLazy<SkSVGLineCap>    fStrokeLineCap;
-    SkTLazy<SkSVGLineJoin>   fStrokeLineJoin;
-    SkTLazy<SkSVGNumberType> fStrokeMiterLimit;
-    SkTLazy<SkSVGNumberType> fStrokeOpacity;
-    SkTLazy<SkSVGLength>     fStrokeWidth;
-
-    SkTLazy<SkSVGVisibility> fVisibility;
-
-    SkTLazy<SkSVGColorType>  fColor;
-
-    // TODO(tdenniston): add SkSVGStopColor
-
-    // uninherited
-    SkTLazy<SkSVGNumberType> fOpacity;
-    SkTLazy<SkSVGClip>       fClipPath;
-};
-
-#endif // SkSVGAttribute_DEFINED
diff --git a/experimental/svg/model/SkSVGAttributeParser.h b/experimental/svg/model/SkSVGAttributeParser.h
index 054de3f..6e15d26 100644
--- a/experimental/svg/model/SkSVGAttributeParser.h
+++ b/experimental/svg/model/SkSVGAttributeParser.h
@@ -1,76 +1,10 @@
 /*
- * Copyright 2016 Google Inc.
+ * Copyright 2020 Google Inc.
  *
  * Use of this source code is governed by a BSD-style license that can be
  * found in the LICENSE file.
  */
 
-#ifndef SkSVGAttributeParser_DEFINED
-#define SkSVGAttributeParser_DEFINED
+// Transitional forwarding header.  To be removed.
+#include "modules/svg/include/SkSVGAttributeParser.h"
 
-#include "experimental/svg/model/SkSVGTypes.h"
-#include "include/private/SkNoncopyable.h"
-
-class SkSVGAttributeParser : public SkNoncopyable {
-public:
-    SkSVGAttributeParser(const char[]);
-
-    bool parseColor(SkSVGColorType*);
-    bool parseClipPath(SkSVGClip*);
-    bool parseFillRule(SkSVGFillRule*);
-    bool parseNumber(SkSVGNumberType*);
-    bool parseLength(SkSVGLength*);
-    bool parseViewBox(SkSVGViewBoxType*);
-    bool parseTransform(SkSVGTransformType*);
-    bool parsePaint(SkSVGPaint*);
-    bool parseLineCap(SkSVGLineCap*);
-    bool parseLineJoin(SkSVGLineJoin*);
-    bool parsePoints(SkSVGPointsType*);
-    bool parseIRI(SkSVGStringType*);
-    bool parseSpreadMethod(SkSVGSpreadMethod*);
-    bool parseStopColor(SkSVGStopColor*);
-    bool parseVisibility(SkSVGVisibility*);
-    bool parseDashArray(SkSVGDashArray*);
-
-private:
-    // Stack-only
-    void* operator new(size_t) = delete;
-    void* operator new(size_t, void*) = delete;
-
-    template <typename F>
-    bool advanceWhile(F func);
-
-    bool parseWSToken();
-    bool parseEOSToken();
-    bool parseSepToken();
-    bool parseCommaWspToken();
-    bool parseExpectedStringToken(const char*);
-    bool parseScalarToken(SkScalar*);
-    bool parseHexToken(uint32_t*);
-    bool parseLengthUnitToken(SkSVGLength::Unit*);
-    bool parseNamedColorToken(SkColor*);
-    bool parseHexColorToken(SkColor*);
-    bool parseColorComponentToken(int32_t*);
-    bool parseRGBColorToken(SkColor*);
-    bool parseFuncIRI(SkSVGStringType*);
-
-    // Transform helpers
-    bool parseMatrixToken(SkMatrix*);
-    bool parseTranslateToken(SkMatrix*);
-    bool parseScaleToken(SkMatrix*);
-    bool parseRotateToken(SkMatrix*);
-    bool parseSkewXToken(SkMatrix*);
-    bool parseSkewYToken(SkMatrix*);
-
-    // Parses a sequence of 'WS* <prefix> WS* (<nested>)', where the nested sequence
-    // is handled by the passed functor.
-    template <typename Func, typename T>
-    bool parseParenthesized(const char* prefix, Func, T* result);
-
-    // The current position in the input string.
-    const char* fCurPos;
-
-    using INHERITED = SkNoncopyable;
-};
-
-#endif // SkSVGAttributeParser_DEFINED
diff --git a/experimental/svg/model/SkSVGCircle.h b/experimental/svg/model/SkSVGCircle.h
index 85ed5c7..6ec529d 100644
--- a/experimental/svg/model/SkSVGCircle.h
+++ b/experimental/svg/model/SkSVGCircle.h
@@ -1,46 +1,10 @@
 /*
- * Copyright 2016 Google Inc.
+ * Copyright 2020 Google Inc.
  *
  * Use of this source code is governed by a BSD-style license that can be
  * found in the LICENSE file.
  */
 
-#ifndef SkSVGCircle_DEFINED
-#define SkSVGCircle_DEFINED
+// Transitional forwarding header.  To be removed.
+#include "modules/svg/include/SkSVGCircle.h"
 
-#include "experimental/svg/model/SkSVGShape.h"
-#include "experimental/svg/model/SkSVGTypes.h"
-
-struct SkPoint;
-
-class SkSVGCircle final : public SkSVGShape {
-public:
-    ~SkSVGCircle() override = default;
-    static sk_sp<SkSVGCircle> Make() { return sk_sp<SkSVGCircle>(new SkSVGCircle()); }
-
-    void setCx(const SkSVGLength&);
-    void setCy(const SkSVGLength&);
-    void setR(const SkSVGLength&);
-
-protected:
-    void onSetAttribute(SkSVGAttribute, const SkSVGValue&) override;
-
-    void onDraw(SkCanvas*, const SkSVGLengthContext&, const SkPaint&,
-                SkPathFillType) const override;
-
-    SkPath onAsPath(const SkSVGRenderContext&) const override;
-
-private:
-    SkSVGCircle();
-
-    // resolve and return the center and radius values
-    std::tuple<SkPoint, SkScalar> resolve(const SkSVGLengthContext&) const;
-
-    SkSVGLength fCx = SkSVGLength(0);
-    SkSVGLength fCy = SkSVGLength(0);
-    SkSVGLength fR  = SkSVGLength(0);
-
-    using INHERITED = SkSVGShape;
-};
-
-#endif // SkSVGCircle_DEFINED
diff --git a/experimental/svg/model/SkSVGClipPath.h b/experimental/svg/model/SkSVGClipPath.h
index 445e79f..c5b00d3 100644
--- a/experimental/svg/model/SkSVGClipPath.h
+++ b/experimental/svg/model/SkSVGClipPath.h
@@ -1,26 +1,10 @@
 /*
- * Copyright 2016 Google Inc.
+ * Copyright 2020 Google Inc.
  *
  * Use of this source code is governed by a BSD-style license that can be
  * found in the LICENSE file.
  */
 
-#ifndef SkSVGClipPath_DEFINED
-#define SkSVGClipPath_DEFINED
+// Transitional forwarding header.  To be removed.
+#include "modules/svg/include/SkSVGClipPath.h"
 
-#include "experimental/svg/model/SkSVGHiddenContainer.h"
-#include "experimental/svg/model/SkSVGTypes.h"
-
-class SkSVGClipPath final : public SkSVGHiddenContainer {
-public:
-    static sk_sp<SkSVGClipPath> Make() {
-        return sk_sp<SkSVGClipPath>(new SkSVGClipPath());
-    }
-
-private:
-    SkSVGClipPath();
-
-    using INHERITED = SkSVGHiddenContainer;
-};
-
-#endif // SkSVGClipPath_DEFINED
diff --git a/experimental/svg/model/SkSVGContainer.h b/experimental/svg/model/SkSVGContainer.h
index 8756e6f..7efb7e1 100644
--- a/experimental/svg/model/SkSVGContainer.h
+++ b/experimental/svg/model/SkSVGContainer.h
@@ -1,36 +1,10 @@
 /*
- * Copyright 2016 Google Inc.
+ * Copyright 2020 Google Inc.
  *
  * Use of this source code is governed by a BSD-style license that can be
  * found in the LICENSE file.
  */
 
-#ifndef SkSVGContainer_DEFINED
-#define SkSVGContainer_DEFINED
+// Transitional forwarding header.  To be removed.
+#include "modules/svg/include/SkSVGContainer.h"
 
-#include "experimental/svg/model/SkSVGTransformableNode.h"
-#include "include/private/SkTArray.h"
-
-class SkSVGContainer : public SkSVGTransformableNode {
-public:
-    ~SkSVGContainer() override = default;
-
-    void appendChild(sk_sp<SkSVGNode>) override;
-
-protected:
-    explicit SkSVGContainer(SkSVGTag);
-
-    void onRender(const SkSVGRenderContext&) const override;
-
-    SkPath onAsPath(const SkSVGRenderContext&) const override;
-
-    bool hasChildren() const final;
-
-    // TODO: add some sort of child iterator, and hide the container.
-    SkSTArray<1, sk_sp<SkSVGNode>, true> fChildren;
-
-private:
-    using INHERITED = SkSVGTransformableNode;
-};
-
-#endif // SkSVGContainer_DEFINED
diff --git a/experimental/svg/model/SkSVGDOM.h b/experimental/svg/model/SkSVGDOM.h
index c2de5ff..f63d85d 100644
--- a/experimental/svg/model/SkSVGDOM.h
+++ b/experimental/svg/model/SkSVGDOM.h
@@ -1,48 +1,10 @@
 /*
- * Copyright 2016 Google Inc.
+ * Copyright 2020 Google Inc.
  *
  * Use of this source code is governed by a BSD-style license that can be
  * found in the LICENSE file.
  */
 
-#ifndef SkSVGDOM_DEFINED
-#define SkSVGDOM_DEFINED
+// Transitional forwarding header.  To be removed.
+#include "modules/svg/include/SkSVGDOM.h"
 
-#include "experimental/svg/model/SkSVGIDMapper.h"
-#include "include/core/SkRefCnt.h"
-#include "include/core/SkSize.h"
-#include "include/private/SkTemplates.h"
-
-class SkCanvas;
-class SkDOM;
-class SkStream;
-class SkSVGNode;
-
-class SkSVGDOM : public SkRefCnt {
-public:
-    SkSVGDOM();
-
-    static sk_sp<SkSVGDOM> MakeFromDOM(const SkDOM&);
-    static sk_sp<SkSVGDOM> MakeFromStream(SkStream&);
-
-    const SkSize& containerSize() const;
-    void setContainerSize(const SkSize&);
-
-    void setRoot(sk_sp<SkSVGNode>);
-
-    // Returns the node with the given id, or nullptr if not found.
-    sk_sp<SkSVGNode>* findNodeById(const char* id);
-
-    void render(SkCanvas*) const;
-
-private:
-    SkSize intrinsicSize() const;
-
-    SkSize           fContainerSize;
-    sk_sp<SkSVGNode> fRoot;
-    SkSVGIDMapper    fIDMapper;
-
-    using INHERITED = SkRefCnt;
-};
-
-#endif // SkSVGDOM_DEFINED
diff --git a/experimental/svg/model/SkSVGDefs.h b/experimental/svg/model/SkSVGDefs.h
index 0b9c6f0..70f4c3b 100644
--- a/experimental/svg/model/SkSVGDefs.h
+++ b/experimental/svg/model/SkSVGDefs.h
@@ -1,23 +1,10 @@
 /*
- * Copyright 2016 Google Inc.
+ * Copyright 2020 Google Inc.
  *
  * Use of this source code is governed by a BSD-style license that can be
  * found in the LICENSE file.
  */
 
-#ifndef SkSVGDefs_DEFINED
-#define SkSVGDefs_DEFINED
+// Transitional forwarding header.  To be removed.
+#include "modules/svg/include/SkSVGDefs.h"
 
-#include "experimental/svg/model/SkSVGHiddenContainer.h"
-
-class SkSVGDefs : public SkSVGHiddenContainer {
-public:
-    static sk_sp<SkSVGDefs> Make() { return sk_sp<SkSVGDefs>(new SkSVGDefs()); }
-
-private:
-    SkSVGDefs() : INHERITED(SkSVGTag::kDefs) {}
-
-    using INHERITED = SkSVGHiddenContainer;
-};
-
-#endif // SkSVGDefs_DEFINED
diff --git a/experimental/svg/model/SkSVGEllipse.h b/experimental/svg/model/SkSVGEllipse.h
index 63c4c34..8531ba7 100644
--- a/experimental/svg/model/SkSVGEllipse.h
+++ b/experimental/svg/model/SkSVGEllipse.h
@@ -1,47 +1,10 @@
 /*
- * Copyright 2016 Google Inc.
+ * Copyright 2020 Google Inc.
  *
  * Use of this source code is governed by a BSD-style license that can be
  * found in the LICENSE file.
  */
 
-#ifndef SkSVGEllipse_DEFINED
-#define SkSVGEllipse_DEFINED
+// Transitional forwarding header.  To be removed.
+#include "modules/svg/include/SkSVGEllipse.h"
 
-#include "experimental/svg/model/SkSVGShape.h"
-#include "experimental/svg/model/SkSVGTypes.h"
-
-struct SkRect;
-
-class SkSVGEllipse final : public SkSVGShape {
-public:
-    ~SkSVGEllipse() override = default;
-    static sk_sp<SkSVGEllipse> Make() { return sk_sp<SkSVGEllipse>(new SkSVGEllipse()); }
-
-    void setCx(const SkSVGLength&);
-    void setCy(const SkSVGLength&);
-    void setRx(const SkSVGLength&);
-    void setRy(const SkSVGLength&);
-
-protected:
-    void onSetAttribute(SkSVGAttribute, const SkSVGValue&) override;
-
-    void onDraw(SkCanvas*, const SkSVGLengthContext&, const SkPaint&,
-                SkPathFillType) const override;
-
-    SkPath onAsPath(const SkSVGRenderContext&) const override;
-
-private:
-    SkSVGEllipse();
-
-    SkRect resolve(const SkSVGLengthContext&) const;
-
-    SkSVGLength fCx = SkSVGLength(0);
-    SkSVGLength fCy = SkSVGLength(0);
-    SkSVGLength fRx = SkSVGLength(0);
-    SkSVGLength fRy = SkSVGLength(0);
-
-    using INHERITED = SkSVGShape;
-};
-
-#endif // SkSVGEllipse_DEFINED
diff --git a/experimental/svg/model/SkSVGG.h b/experimental/svg/model/SkSVGG.h
index f8970cf..ee91471 100644
--- a/experimental/svg/model/SkSVGG.h
+++ b/experimental/svg/model/SkSVGG.h
@@ -1,23 +1,10 @@
 /*
- * Copyright 2016 Google Inc.
+ * Copyright 2020 Google Inc.
  *
  * Use of this source code is governed by a BSD-style license that can be
  * found in the LICENSE file.
  */
 
-#ifndef SkSVGG_DEFINED
-#define SkSVGG_DEFINED
+// Transitional forwarding header.  To be removed.
+#include "modules/svg/include/SkSVGG.h"
 
-#include "experimental/svg/model/SkSVGContainer.h"
-
-class SkSVGG : public SkSVGContainer {
-public:
-    static sk_sp<SkSVGG> Make() { return sk_sp<SkSVGG>(new SkSVGG()); }
-
-private:
-    SkSVGG() : INHERITED(SkSVGTag::kG) { }
-
-    using INHERITED = SkSVGContainer;
-};
-
-#endif // SkSVGG_DEFINED
diff --git a/experimental/svg/model/SkSVGGradient.h b/experimental/svg/model/SkSVGGradient.h
index 2fc5efe..b7708bf 100644
--- a/experimental/svg/model/SkSVGGradient.h
+++ b/experimental/svg/model/SkSVGGradient.h
@@ -1,51 +1,10 @@
 /*
- * Copyright 2017 Google Inc.
+ * Copyright 2020 Google Inc.
  *
  * Use of this source code is governed by a BSD-style license that can be
  * found in the LICENSE file.
  */
 
-#ifndef SkSVGGradient_DEFINED
-#define SkSVGGradient_DEFINED
+// Transitional forwarding header.  To be removed.
+#include "modules/svg/include/SkSVGGradient.h"
 
-#include "experimental/svg/model/SkSVGHiddenContainer.h"
-#include "experimental/svg/model/SkSVGTypes.h"
-#include "include/core/SkShader.h"
-
-class SkMatrix;
-class SkSVGRenderContext;
-class SkSVGStop;
-
-class SkSVGGradient : public SkSVGHiddenContainer {
-public:
-    ~SkSVGGradient() override = default;
-
-    void setHref(const SkSVGStringType&);
-    void setGradientTransform(const SkSVGTransformType&);
-    void setSpreadMethod(const SkSVGSpreadMethod&);
-
-protected:
-    explicit SkSVGGradient(SkSVGTag t) : INHERITED(t) {}
-
-    void onSetAttribute(SkSVGAttribute, const SkSVGValue&) override;
-
-    bool onAsPaint(const SkSVGRenderContext&, SkPaint*) const final;
-
-    virtual sk_sp<SkShader> onMakeShader(const SkSVGRenderContext&,
-                                         const SkColor*, const SkScalar*, int count,
-                                         SkTileMode, const SkMatrix& localMatrix) const = 0;
-
-private:
-    using StopPositionArray = SkSTArray<2, SkScalar, true>;
-    using    StopColorArray = SkSTArray<2,  SkColor, true>;
-    void collectColorStops(const SkSVGRenderContext&, StopPositionArray*, StopColorArray*) const;
-    SkColor resolveStopColor(const SkSVGRenderContext&, const SkSVGStop&) const;
-
-    SkSVGStringType    fHref;
-    SkSVGTransformType fGradientTransform = SkSVGTransformType(SkMatrix::I());
-    SkSVGSpreadMethod  fSpreadMethod = SkSVGSpreadMethod(SkSVGSpreadMethod::Type::kPad);
-
-    using INHERITED = SkSVGHiddenContainer;
-};
-
-#endif // SkSVGGradient_DEFINED
diff --git a/experimental/svg/model/SkSVGHiddenContainer.h b/experimental/svg/model/SkSVGHiddenContainer.h
index f323470..ad7c464 100644
--- a/experimental/svg/model/SkSVGHiddenContainer.h
+++ b/experimental/svg/model/SkSVGHiddenContainer.h
@@ -1,23 +1,10 @@
 /*
- * Copyright 2016 Google Inc.
+ * Copyright 2020 Google Inc.
  *
  * Use of this source code is governed by a BSD-style license that can be
  * found in the LICENSE file.
  */
 
-#ifndef SkSVGHiddenContainer_DEFINED
-#define SkSVGHiddenContainer_DEFINED
+// Transitional forwarding header.  To be removed.
+#include "modules/svg/include/SkSVGHiddenContainer.h"
 
-#include "experimental/svg/model/SkSVGContainer.h"
-
-class SkSVGHiddenContainer : public SkSVGContainer {
-protected:
-    explicit SkSVGHiddenContainer(SkSVGTag t) : INHERITED(t) {}
-
-    void onRender(const SkSVGRenderContext&) const final {}
-
-private:
-    using INHERITED = SkSVGContainer;
-};
-
-#endif // SkSVGHiddenContainer_DEFINED
diff --git a/experimental/svg/model/SkSVGIDMapper.h b/experimental/svg/model/SkSVGIDMapper.h
index ea0d916..244c350 100644
--- a/experimental/svg/model/SkSVGIDMapper.h
+++ b/experimental/svg/model/SkSVGIDMapper.h
@@ -1,19 +1,10 @@
 /*
- * Copyright 2016 Google Inc.
+ * Copyright 2020 Google Inc.
  *
  * Use of this source code is governed by a BSD-style license that can be
  * found in the LICENSE file.
  */
 
-#ifndef SkSVGIDMapper_DEFINED
-#define SkSVGIDMapper_DEFINED
+// Transitional forwarding header.  To be removed.
+#include "modules/svg/include/SkSVGIDMapper.h"
 
-#include "include/core/SkRefCnt.h"
-#include "include/private/SkTHash.h"
-
-class SkString;
-class SkSVGNode;
-
-using SkSVGIDMapper = SkTHashMap<SkString, sk_sp<SkSVGNode>>;
-
-#endif // SkSVGIDMapper_DEFINED
diff --git a/experimental/svg/model/SkSVGLine.h b/experimental/svg/model/SkSVGLine.h
index 5df0220..1008a68 100644
--- a/experimental/svg/model/SkSVGLine.h
+++ b/experimental/svg/model/SkSVGLine.h
@@ -1,48 +1,10 @@
 /*
- * Copyright 2016 Google Inc.
+ * Copyright 2020 Google Inc.
  *
  * Use of this source code is governed by a BSD-style license that can be
  * found in the LICENSE file.
  */
 
-#ifndef SkSVGLine_DEFINED
-#define SkSVGLine_DEFINED
+// Transitional forwarding header.  To be removed.
+#include "modules/svg/include/SkSVGLine.h"
 
-#include "experimental/svg/model/SkSVGShape.h"
-#include "experimental/svg/model/SkSVGTypes.h"
-
-struct SkPoint;
-
-class SkSVGLine final : public SkSVGShape {
-public:
-    ~SkSVGLine() override = default;
-    static sk_sp<SkSVGLine> Make() { return sk_sp<SkSVGLine>(new SkSVGLine()); }
-
-    void setX1(const SkSVGLength&);
-    void setY1(const SkSVGLength&);
-    void setX2(const SkSVGLength&);
-    void setY2(const SkSVGLength&);
-
-protected:
-    void onSetAttribute(SkSVGAttribute, const SkSVGValue&) override;
-
-    void onDraw(SkCanvas*, const SkSVGLengthContext&, const SkPaint&,
-                SkPathFillType) const override;
-
-    SkPath onAsPath(const SkSVGRenderContext&) const override;
-
-private:
-    SkSVGLine();
-
-    // resolve and return the two endpoints
-    std::tuple<SkPoint, SkPoint> resolve(const SkSVGLengthContext&) const;
-
-    SkSVGLength fX1 = SkSVGLength(0);
-    SkSVGLength fY1 = SkSVGLength(0);
-    SkSVGLength fX2 = SkSVGLength(0);
-    SkSVGLength fY2 = SkSVGLength(0);
-
-    using INHERITED = SkSVGShape;
-};
-
-#endif // SkSVGLine_DEFINED
diff --git a/experimental/svg/model/SkSVGLinearGradient.h b/experimental/svg/model/SkSVGLinearGradient.h
index 9f3b1a6..ce6e844 100644
--- a/experimental/svg/model/SkSVGLinearGradient.h
+++ b/experimental/svg/model/SkSVGLinearGradient.h
@@ -1,43 +1,10 @@
 /*
- * Copyright 2016 Google Inc.
+ * Copyright 2020 Google Inc.
  *
  * Use of this source code is governed by a BSD-style license that can be
  * found in the LICENSE file.
  */
 
-#ifndef SkSVGLinearGradient_DEFINED
-#define SkSVGLinearGradient_DEFINED
+// Transitional forwarding header.  To be removed.
+#include "modules/svg/include/SkSVGLinearGradient.h"
 
-#include "experimental/svg/model/SkSVGGradient.h"
-#include "experimental/svg/model/SkSVGTypes.h"
-
-class SkSVGLinearGradient final : public SkSVGGradient {
-public:
-    ~SkSVGLinearGradient() override = default;
-    static sk_sp<SkSVGLinearGradient> Make() {
-        return sk_sp<SkSVGLinearGradient>(new SkSVGLinearGradient());
-    }
-
-    void setX1(const SkSVGLength&);
-    void setY1(const SkSVGLength&);
-    void setX2(const SkSVGLength&);
-    void setY2(const SkSVGLength&);
-
-protected:
-    void onSetAttribute(SkSVGAttribute, const SkSVGValue&) override;
-
-    sk_sp<SkShader> onMakeShader(const SkSVGRenderContext&,
-                                 const SkColor*, const SkScalar*, int count,
-                                 SkTileMode, const SkMatrix&) const override;
-private:
-    SkSVGLinearGradient();
-
-    SkSVGLength fX1 = SkSVGLength(0  , SkSVGLength::Unit::kPercentage);
-    SkSVGLength fY1 = SkSVGLength(0  , SkSVGLength::Unit::kPercentage);
-    SkSVGLength fX2 = SkSVGLength(100, SkSVGLength::Unit::kPercentage);
-    SkSVGLength fY2 = SkSVGLength(0  , SkSVGLength::Unit::kPercentage);
-
-    using INHERITED = SkSVGGradient;
-};
-
-#endif // SkSVGLinearGradient_DEFINED
diff --git a/experimental/svg/model/SkSVGNode.h b/experimental/svg/model/SkSVGNode.h
index 99d07b2..d3c01e6 100644
--- a/experimental/svg/model/SkSVGNode.h
+++ b/experimental/svg/model/SkSVGNode.h
@@ -1,103 +1,10 @@
 /*
- * Copyright 2016 Google Inc.
+ * Copyright 2020 Google Inc.
  *
  * Use of this source code is governed by a BSD-style license that can be
  * found in the LICENSE file.
  */
 
-#ifndef SkSVGNode_DEFINED
-#define SkSVGNode_DEFINED
+// Transitional forwarding header.  To be removed.
+#include "modules/svg/include/SkSVGNode.h"
 
-#include "experimental/svg/model/SkSVGAttribute.h"
-#include "include/core/SkRefCnt.h"
-
-class SkCanvas;
-class SkMatrix;
-class SkPaint;
-class SkPath;
-class SkSVGRenderContext;
-class SkSVGValue;
-
-enum class SkSVGTag {
-    kCircle,
-    kClipPath,
-    kDefs,
-    kEllipse,
-    kG,
-    kLine,
-    kLinearGradient,
-    kPath,
-    kPattern,
-    kPolygon,
-    kPolyline,
-    kRadialGradient,
-    kRect,
-    kStop,
-    kSvg,
-    kText,
-    kUse
-};
-
-class SkSVGNode : public SkRefCnt {
-public:
-    ~SkSVGNode() override;
-
-    SkSVGTag tag() const { return fTag; }
-
-    virtual void appendChild(sk_sp<SkSVGNode>) = 0;
-
-    void render(const SkSVGRenderContext&) const;
-    bool asPaint(const SkSVGRenderContext&, SkPaint*) const;
-    SkPath asPath(const SkSVGRenderContext&) const;
-
-    void setAttribute(SkSVGAttribute, const SkSVGValue&);
-    bool setAttribute(const char* attributeName, const char* attributeValue);
-
-    void setClipPath(const SkSVGClip&);
-    void setClipRule(const SkSVGFillRule&);
-    void setColor(const SkSVGColorType&);
-    void setFill(const SkSVGPaint&);
-    void setFillOpacity(const SkSVGNumberType&);
-    void setFillRule(const SkSVGFillRule&);
-    void setOpacity(const SkSVGNumberType&);
-    void setStroke(const SkSVGPaint&);
-    void setStrokeDashArray(const SkSVGDashArray&);
-    void setStrokeDashOffset(const SkSVGLength&);
-    void setStrokeOpacity(const SkSVGNumberType&);
-    void setStrokeLineCap(const SkSVGLineCap&);
-    void setStrokeLineJoin(const SkSVGLineJoin&);
-    void setStrokeMiterLimit(const SkSVGNumberType&);
-    void setStrokeWidth(const SkSVGLength&);
-    void setVisibility(const SkSVGVisibility&);
-
-protected:
-    SkSVGNode(SkSVGTag);
-
-    // Called before onRender(), to apply local attributes to the context.  Unlike onRender(),
-    // onPrepareToRender() bubbles up the inheritance chain: overriders should always call
-    // INHERITED::onPrepareToRender(), unless they intend to short-circuit rendering
-    // (return false).
-    // Implementations are expected to return true if rendering is to continue, or false if
-    // the node/subtree rendering is disabled.
-    virtual bool onPrepareToRender(SkSVGRenderContext*) const;
-
-    virtual void onRender(const SkSVGRenderContext&) const = 0;
-
-    virtual bool onAsPaint(const SkSVGRenderContext&, SkPaint*) const { return false; }
-
-    virtual SkPath onAsPath(const SkSVGRenderContext&) const = 0;
-
-    virtual void onSetAttribute(SkSVGAttribute, const SkSVGValue&);
-
-    virtual bool hasChildren() const { return false; }
-
-private:
-    SkSVGTag                    fTag;
-
-    // FIXME: this should be sparse
-    SkSVGPresentationAttributes fPresentationAttributes;
-
-    using INHERITED = SkRefCnt;
-};
-
-#endif // SkSVGNode_DEFINED
diff --git a/experimental/svg/model/SkSVGPath.h b/experimental/svg/model/SkSVGPath.h
index 166741c..38f9a5e 100644
--- a/experimental/svg/model/SkSVGPath.h
+++ b/experimental/svg/model/SkSVGPath.h
@@ -1,37 +1,10 @@
 /*
- * Copyright 2016 Google Inc.
+ * Copyright 2020 Google Inc.
  *
  * Use of this source code is governed by a BSD-style license that can be
  * found in the LICENSE file.
  */
 
-#ifndef SkSVGPath_DEFINED
-#define SkSVGPath_DEFINED
+// Transitional forwarding header.  To be removed.
+#include "modules/svg/include/SkSVGPath.h"
 
-#include "experimental/svg/model/SkSVGShape.h"
-#include "include/core/SkPath.h"
-
-class SkSVGPath final : public SkSVGShape {
-public:
-    ~SkSVGPath() override = default;
-    static sk_sp<SkSVGPath> Make() { return sk_sp<SkSVGPath>(new SkSVGPath()); }
-
-    void setPath(const SkPath& path) { fPath = path; }
-
-protected:
-    void onSetAttribute(SkSVGAttribute, const SkSVGValue&) override;
-
-    void onDraw(SkCanvas*, const SkSVGLengthContext&, const SkPaint&,
-                SkPathFillType) const override;
-
-    SkPath onAsPath(const SkSVGRenderContext&) const override;
-
-private:
-    SkSVGPath();
-
-    mutable SkPath fPath; // mutated in onDraw(), to apply inherited fill types.
-
-    using INHERITED = SkSVGShape;
-};
-
-#endif // SkSVGPath_DEFINED
diff --git a/experimental/svg/model/SkSVGPattern.h b/experimental/svg/model/SkSVGPattern.h
index 541f1fa..75a677b 100644
--- a/experimental/svg/model/SkSVGPattern.h
+++ b/experimental/svg/model/SkSVGPattern.h
@@ -1,59 +1,10 @@
 /*
- * Copyright 2017 Google Inc.
+ * Copyright 2020 Google Inc.
  *
  * Use of this source code is governed by a BSD-style license that can be
  * found in the LICENSE file.
  */
 
-#ifndef SkSVGPattern_DEFINED
-#define SkSVGPattern_DEFINED
+// Transitional forwarding header.  To be removed.
+#include "modules/svg/include/SkSVGPattern.h"
 
-#include "experimental/svg/model/SkSVGHiddenContainer.h"
-#include "experimental/svg/model/SkSVGTypes.h"
-
-class SkSVGRenderContext;
-
-class SkSVGPattern final : public SkSVGHiddenContainer {
-public:
-    ~SkSVGPattern() override = default;
-
-    static sk_sp<SkSVGPattern> Make() {
-        return sk_sp<SkSVGPattern>(new SkSVGPattern());
-    }
-
-    void setX(const SkSVGLength&);
-    void setY(const SkSVGLength&);
-    void setWidth(const SkSVGLength&);
-    void setHeight(const SkSVGLength&);
-    void setHref(const SkSVGStringType&);
-    void setPatternTransform(const SkSVGTransformType&);
-
-protected:
-    SkSVGPattern();
-
-    void onSetAttribute(SkSVGAttribute, const SkSVGValue&) override;
-
-    bool onAsPaint(const SkSVGRenderContext&, SkPaint*) const override;
-
-private:
-    struct PatternAttributes {
-        SkTLazy<SkSVGLength>        fX,
-                                    fY,
-                                    fWidth,
-                                    fHeight;
-        SkTLazy<SkSVGTransformType> fPatternTransform;
-    } fAttributes;
-
-    SkSVGStringType    fHref;
-
-    const SkSVGPattern* resolveHref(const SkSVGRenderContext&, PatternAttributes*) const;
-    const SkSVGPattern* hrefTarget(const SkSVGRenderContext&) const;
-
-    // TODO:
-    //   - patternUnits
-    //   - patternContentUnits
-
-    using INHERITED = SkSVGHiddenContainer;
-};
-
-#endif // SkSVGPattern_DEFINED
diff --git a/experimental/svg/model/SkSVGPoly.h b/experimental/svg/model/SkSVGPoly.h
index e847ca8..b65f9fd 100644
--- a/experimental/svg/model/SkSVGPoly.h
+++ b/experimental/svg/model/SkSVGPoly.h
@@ -1,45 +1,10 @@
 /*
- * Copyright 2016 Google Inc.
+ * Copyright 2020 Google Inc.
  *
  * Use of this source code is governed by a BSD-style license that can be
  * found in the LICENSE file.
  */
 
-#ifndef SkSVGPoly_DEFINED
-#define SkSVGPoly_DEFINED
+// Transitional forwarding header.  To be removed.
+#include "modules/svg/include/SkSVGPoly.h"
 
-#include "experimental/svg/model/SkSVGShape.h"
-#include "include/core/SkPath.h"
-
-// Handles <polygon> and <polyline> elements.
-class SkSVGPoly final : public SkSVGShape {
-public:
-    ~SkSVGPoly() override = default;
-
-    static sk_sp<SkSVGPoly> MakePolygon() {
-        return sk_sp<SkSVGPoly>(new SkSVGPoly(SkSVGTag::kPolygon));
-    }
-
-    static sk_sp<SkSVGPoly> MakePolyline() {
-        return sk_sp<SkSVGPoly>(new SkSVGPoly(SkSVGTag::kPolyline));
-    }
-
-    void setPoints(const SkSVGPointsType&);
-
-protected:
-    void onSetAttribute(SkSVGAttribute, const SkSVGValue&) override;
-
-    void onDraw(SkCanvas*, const SkSVGLengthContext&, const SkPaint&,
-                SkPathFillType) const override;
-
-    SkPath onAsPath(const SkSVGRenderContext&) const override;
-
-private:
-    SkSVGPoly(SkSVGTag);
-
-    mutable SkPath fPath;  // mutated in onDraw(), to apply inherited fill types.
-
-    using INHERITED = SkSVGShape;
-};
-
-#endif // SkSVGPoly_DEFINED
diff --git a/experimental/svg/model/SkSVGRadialGradient.h b/experimental/svg/model/SkSVGRadialGradient.h
index d2643fa..49648b3 100644
--- a/experimental/svg/model/SkSVGRadialGradient.h
+++ b/experimental/svg/model/SkSVGRadialGradient.h
@@ -1,46 +1,10 @@
 /*
- * Copyright 2017 Google Inc.
+ * Copyright 2020 Google Inc.
  *
  * Use of this source code is governed by a BSD-style license that can be
  * found in the LICENSE file.
  */
 
-#ifndef SkSVGRadialGradient_DEFINED
-#define SkSVGRadialGradient_DEFINED
+// Transitional forwarding header.  To be removed.
+#include "modules/svg/include/SkSVGRadialGradient.h"
 
-#include "experimental/svg/model/SkSVGGradient.h"
-#include "experimental/svg/model/SkSVGTypes.h"
-
-class SkSVGRadialGradient final : public SkSVGGradient {
-public:
-    ~SkSVGRadialGradient() override = default;
-    static sk_sp<SkSVGRadialGradient> Make() {
-        return sk_sp<SkSVGRadialGradient>(new SkSVGRadialGradient());
-    }
-
-    void setCx(const SkSVGLength&);
-    void setCy(const SkSVGLength&);
-    void setR(const SkSVGLength&);
-    void setFx(const SkSVGLength&);
-    void setFy(const SkSVGLength&);
-
-protected:
-    void onSetAttribute(SkSVGAttribute, const SkSVGValue&) override;
-
-    sk_sp<SkShader> onMakeShader(const SkSVGRenderContext&,
-                                 const SkColor*, const SkScalar*, int count,
-                                 SkTileMode, const SkMatrix&) const override;
-private:
-    SkSVGRadialGradient();
-
-    SkSVGLength fCx = SkSVGLength(50, SkSVGLength::Unit::kPercentage);
-    SkSVGLength fCy = SkSVGLength(50, SkSVGLength::Unit::kPercentage);
-    SkSVGLength fR  = SkSVGLength(50, SkSVGLength::Unit::kPercentage);
-    SkTLazy<SkSVGLength> fFx;
-    SkTLazy<SkSVGLength> fFy;
-
-
-   using INHERITED = SkSVGGradient;
-};
-
-#endif // SkSVGRadialGradient_DEFINED
diff --git a/experimental/svg/model/SkSVGRect.h b/experimental/svg/model/SkSVGRect.h
index 20b4dbc..89cf038 100644
--- a/experimental/svg/model/SkSVGRect.h
+++ b/experimental/svg/model/SkSVGRect.h
@@ -1,54 +1,10 @@
 /*
- * Copyright 2016 Google Inc.
+ * Copyright 2020 Google Inc.
  *
  * Use of this source code is governed by a BSD-style license that can be
  * found in the LICENSE file.
  */
 
-#ifndef SkSVGRect_DEFINED
-#define SkSVGRect_DEFINED
+// Transitional forwarding header.  To be removed.
+#include "modules/svg/include/SkSVGRect.h"
 
-#include "experimental/svg/model/SkSVGShape.h"
-#include "experimental/svg/model/SkSVGTypes.h"
-
-class SkRRect;
-
-class SkSVGRect final : public SkSVGShape {
-public:
-    ~SkSVGRect() override = default;
-    static sk_sp<SkSVGRect> Make() { return sk_sp<SkSVGRect>(new SkSVGRect()); }
-
-    void setX(const SkSVGLength&);
-    void setY(const SkSVGLength&);
-    void setWidth(const SkSVGLength&);
-    void setHeight(const SkSVGLength&);
-    void setRx(const SkSVGLength&);
-    void setRy(const SkSVGLength&);
-
-protected:
-    void onSetAttribute(SkSVGAttribute, const SkSVGValue&) override;
-
-    void onDraw(SkCanvas*, const SkSVGLengthContext&, const SkPaint&,
-                SkPathFillType) const override;
-
-    SkPath onAsPath(const SkSVGRenderContext&) const override;
-
-private:
-    SkSVGRect();
-
-    SkRRect resolve(const SkSVGLengthContext&) const;
-
-    SkSVGLength fX      = SkSVGLength(0);
-    SkSVGLength fY      = SkSVGLength(0);
-    SkSVGLength fWidth  = SkSVGLength(0);
-    SkSVGLength fHeight = SkSVGLength(0);
-
-    // The x radius for rounded rects.
-    SkSVGLength fRx     = SkSVGLength(0);
-    // The y radius for rounded rects.
-    SkSVGLength fRy     = SkSVGLength(0);
-
-    using INHERITED = SkSVGShape;
-};
-
-#endif // SkSVGRect_DEFINED
diff --git a/experimental/svg/model/SkSVGRenderContext.h b/experimental/svg/model/SkSVGRenderContext.h
index 8c8c85a..35c6788 100644
--- a/experimental/svg/model/SkSVGRenderContext.h
+++ b/experimental/svg/model/SkSVGRenderContext.h
@@ -1,144 +1,10 @@
 /*
- * Copyright 2016 Google Inc.
+ * Copyright 2020 Google Inc.
  *
  * Use of this source code is governed by a BSD-style license that can be
  * found in the LICENSE file.
  */
 
-#ifndef SkSVGRenderContext_DEFINED
-#define SkSVGRenderContext_DEFINED
+// Transitional forwarding header.  To be removed.
+#include "modules/svg/include/SkSVGRenderContext.h"
 
-#include "experimental/svg/model/SkSVGAttribute.h"
-#include "experimental/svg/model/SkSVGIDMapper.h"
-#include "include/core/SkPaint.h"
-#include "include/core/SkPath.h"
-#include "include/core/SkRect.h"
-#include "include/core/SkSize.h"
-#include "include/core/SkTypes.h"
-#include "src/core/SkTLazy.h"
-
-class SkCanvas;
-class SkSVGLength;
-
-class SkSVGLengthContext {
-public:
-    SkSVGLengthContext(const SkSize& viewport, SkScalar dpi = 90)
-        : fViewport(viewport), fDPI(dpi) {}
-
-    enum class LengthType {
-        kHorizontal,
-        kVertical,
-        kOther,
-    };
-
-    const SkSize& viewPort() const { return fViewport; }
-    void setViewPort(const SkSize& viewport) { fViewport = viewport; }
-
-    SkScalar resolve(const SkSVGLength&, LengthType) const;
-    SkRect   resolveRect(const SkSVGLength& x, const SkSVGLength& y,
-                         const SkSVGLength& w, const SkSVGLength& h) const;
-
-private:
-    SkSize   fViewport;
-    SkScalar fDPI;
-};
-
-struct SkSVGPresentationContext {
-    SkSVGPresentationContext();
-    SkSVGPresentationContext(const SkSVGPresentationContext&)            = default;
-    SkSVGPresentationContext& operator=(const SkSVGPresentationContext&) = default;
-
-    // Inherited presentation attributes, computed for the current node.
-    SkSVGPresentationAttributes fInherited;
-
-    // Cached paints, reflecting the current presentation attributes.
-    SkPaint fFillPaint;
-    SkPaint fStrokePaint;
-};
-
-class SkSVGRenderContext {
-public:
-    SkSVGRenderContext(SkCanvas*, const SkSVGIDMapper&, const SkSVGLengthContext&,
-                       const SkSVGPresentationContext&);
-    SkSVGRenderContext(const SkSVGRenderContext&);
-    SkSVGRenderContext(const SkSVGRenderContext&, SkCanvas*);
-    ~SkSVGRenderContext();
-
-    const SkSVGLengthContext& lengthContext() const { return *fLengthContext; }
-    SkSVGLengthContext* writableLengthContext() { return fLengthContext.writable(); }
-
-    const SkSVGPresentationContext& presentationContext() const { return *fPresentationContext; }
-
-    SkCanvas* canvas() const { return fCanvas; }
-    void saveOnce();
-
-    enum ApplyFlags {
-        kLeaf = 1 << 0, // the target node doesn't have descendants
-    };
-    void applyPresentationAttributes(const SkSVGPresentationAttributes&, uint32_t flags);
-
-    // Scoped wrapper that temporarily clears the original node reference.
-    class BorrowedNode {
-    public:
-        explicit BorrowedNode(sk_sp<SkSVGNode>* node)
-            : fOwner(node) {
-            if (fOwner) {
-                fBorrowed = std::move(*fOwner);
-                *fOwner = nullptr;
-            }
-        }
-
-        ~BorrowedNode() {
-            if (fOwner) {
-                *fOwner = std::move(fBorrowed);
-            }
-        }
-
-        const SkSVGNode* get() const { return fBorrowed.get(); }
-        const SkSVGNode* operator->() const { return fBorrowed.get(); }
-        const SkSVGNode& operator*() const { return *fBorrowed; }
-
-        operator bool() const { return !!fBorrowed; }
-
-    private:
-        // noncopyable
-        BorrowedNode(const BorrowedNode&)      = delete;
-        BorrowedNode& operator=(BorrowedNode&) = delete;
-
-        sk_sp<SkSVGNode>* fOwner;
-        sk_sp<SkSVGNode>  fBorrowed;
-    };
-
-    // Note: the id->node association is cleared for the lifetime of the returned value
-    // (effectively breaks reference cycles, assuming appropriate return value scoping).
-    BorrowedNode findNodeById(const SkString&) const;
-
-    const SkPaint* fillPaint() const;
-    const SkPaint* strokePaint() const;
-
-    // The local computed clip path (not inherited).
-    const SkPath* clipPath() const { return fClipPath.getMaybeNull(); }
-
-private:
-    // Stack-only
-    void* operator new(size_t)                               = delete;
-    void* operator new(size_t, void*)                        = delete;
-    SkSVGRenderContext& operator=(const SkSVGRenderContext&) = delete;
-
-    void applyOpacity(SkScalar opacity, uint32_t flags);
-    void applyClip(const SkSVGClip&);
-    void updatePaintsWithCurrentColor(const SkSVGPresentationAttributes&);
-
-    const SkSVGIDMapper&                          fIDMapper;
-    SkTCopyOnFirstWrite<SkSVGLengthContext>       fLengthContext;
-    SkTCopyOnFirstWrite<SkSVGPresentationContext> fPresentationContext;
-    SkCanvas*                                     fCanvas;
-    // The save count on 'fCanvas' at construction time.
-    // A restoreToCount() will be issued on destruction.
-    int                                           fCanvasSaveCount;
-
-    // clipPath, if present for the current context (not inherited).
-    SkTLazy<SkPath>                               fClipPath;
-};
-
-#endif // SkSVGRenderContext_DEFINED
diff --git a/experimental/svg/model/SkSVGSVG.h b/experimental/svg/model/SkSVGSVG.h
index e44c8f3..e5d20f0 100644
--- a/experimental/svg/model/SkSVGSVG.h
+++ b/experimental/svg/model/SkSVGSVG.h
@@ -1,49 +1,10 @@
 /*
- * Copyright 2016 Google Inc.
+ * Copyright 2020 Google Inc.
  *
  * Use of this source code is governed by a BSD-style license that can be
  * found in the LICENSE file.
  */
 
-#ifndef SkSVGSVG_DEFINED
-#define SkSVGSVG_DEFINED
+// Transitional forwarding header.  To be removed.
+#include "modules/svg/include/SkSVGSVG.h"
 
-#include "experimental/svg/model/SkSVGContainer.h"
-#include "experimental/svg/model/SkSVGTypes.h"
-#include "src/core/SkTLazy.h"
-
-class SkSVGLengthContext;
-
-class SkSVGSVG : public SkSVGContainer {
-public:
-    ~SkSVGSVG() override = default;
-
-    static sk_sp<SkSVGSVG> Make() { return sk_sp<SkSVGSVG>(new SkSVGSVG()); }
-
-    void setX(const SkSVGLength&);
-    void setY(const SkSVGLength&);
-    void setWidth(const SkSVGLength&);
-    void setHeight(const SkSVGLength&);
-    void setViewBox(const SkSVGViewBoxType&);
-
-    SkSize intrinsicSize(const SkSVGLengthContext&) const;
-
-protected:
-    bool onPrepareToRender(SkSVGRenderContext*) const override;
-
-    void onSetAttribute(SkSVGAttribute, const SkSVGValue&) override;
-
-private:
-    SkSVGSVG();
-
-    SkSVGLength fX      = SkSVGLength(0);
-    SkSVGLength fY      = SkSVGLength(0);
-    SkSVGLength fWidth  = SkSVGLength(100, SkSVGLength::Unit::kPercentage);
-    SkSVGLength fHeight = SkSVGLength(100, SkSVGLength::Unit::kPercentage);
-
-    SkTLazy<SkSVGViewBoxType> fViewBox;
-
-    using INHERITED = SkSVGContainer;
-};
-
-#endif // SkSVGSVG_DEFINED
diff --git a/experimental/svg/model/SkSVGShape.h b/experimental/svg/model/SkSVGShape.h
index 56fc782..537e9cd 100644
--- a/experimental/svg/model/SkSVGShape.h
+++ b/experimental/svg/model/SkSVGShape.h
@@ -1,35 +1,10 @@
 /*
- * Copyright 2016 Google Inc.
+ * Copyright 2020 Google Inc.
  *
  * Use of this source code is governed by a BSD-style license that can be
  * found in the LICENSE file.
  */
 
-#ifndef SkSVGShape_DEFINED
-#define SkSVGShape_DEFINED
+// Transitional forwarding header.  To be removed.
+#include "modules/svg/include/SkSVGShape.h"
 
-#include "experimental/svg/model/SkSVGTransformableNode.h"
-#include "include/core/SkPath.h"
-
-class SkSVGLengthContext;
-class SkPaint;
-
-class SkSVGShape : public SkSVGTransformableNode {
-public:
-    ~SkSVGShape() override = default;
-
-    void appendChild(sk_sp<SkSVGNode>) override;
-
-protected:
-    SkSVGShape(SkSVGTag);
-
-    void onRender(const SkSVGRenderContext&) const final;
-
-    virtual void onDraw(SkCanvas*, const SkSVGLengthContext&, const SkPaint&,
-                        SkPathFillType) const = 0;
-
-private:
-    using INHERITED = SkSVGTransformableNode;
-};
-
-#endif // SkSVGShape_DEFINED
diff --git a/experimental/svg/model/SkSVGStop.h b/experimental/svg/model/SkSVGStop.h
index 816e23d..e114609 100644
--- a/experimental/svg/model/SkSVGStop.h
+++ b/experimental/svg/model/SkSVGStop.h
@@ -1,44 +1,10 @@
 /*
- * Copyright 2016 Google Inc.
+ * Copyright 2020 Google Inc.
  *
  * Use of this source code is governed by a BSD-style license that can be
  * found in the LICENSE file.
  */
 
-#ifndef SkSVGStop_DEFINED
-#define SkSVGStop_DEFINED
+// Transitional forwarding header.  To be removed.
+#include "modules/svg/include/SkSVGStop.h"
 
-#include "experimental/svg/model/SkSVGHiddenContainer.h"
-#include "experimental/svg/model/SkSVGTypes.h"
-
-class SkSVGLengthContext;
-
-class SkSVGStop : public SkSVGHiddenContainer {
-public:
-    ~SkSVGStop() override = default;
-    static sk_sp<SkSVGStop> Make() {
-        return sk_sp<SkSVGStop>(new SkSVGStop());
-    }
-
-    const SkSVGLength& offset() const { return fOffset; }
-    const SkSVGStopColor& stopColor() const { return fStopColor; }
-    const SkSVGNumberType& stopOpacity() const { return fStopOpacity; }
-
-    void setOffset(const SkSVGLength&);
-    void setStopColor(const SkSVGStopColor&);
-    void setStopOpacity(const SkSVGNumberType&);
-
-protected:
-    void onSetAttribute(SkSVGAttribute, const SkSVGValue&) override;
-
-private:
-    SkSVGStop();
-
-    SkSVGLength          fOffset = SkSVGLength(0  , SkSVGLength::Unit::kPercentage);
-    SkSVGStopColor    fStopColor = SkSVGStopColor(SK_ColorBLACK);
-    SkSVGNumberType fStopOpacity = SkSVGNumberType(1);
-
-    using INHERITED = SkSVGHiddenContainer;
-};
-
-#endif // SkSVGStop_DEFINED
diff --git a/experimental/svg/model/SkSVGText.h b/experimental/svg/model/SkSVGText.h
index 61e69d8..ca866ff 100644
--- a/experimental/svg/model/SkSVGText.h
+++ b/experimental/svg/model/SkSVGText.h
@@ -1,57 +1,10 @@
 /*
- * Copyright 2019 Google Inc.
+ * Copyright 2020 Google Inc.
  *
  * Use of this source code is governed by a BSD-style license that can be
  * found in the LICENSE file.
  */
 
-#ifndef SkSVGText_DEFINED
-#define SkSVGText_DEFINED
+// Transitional forwarding header.  To be removed.
+#include "modules/svg/include/SkSVGText.h"
 
-#include "experimental/svg/model/SkSVGShape.h"
-#include "experimental/svg/model/SkSVGTypes.h"
-#include "include/core/SkFont.h"
-#include "include/utils/SkTextUtils.h"
-
-class SkRRect;
-
-class SkSVGText final : public SkSVGShape {
- public:
-  ~SkSVGText() override = default;
-  static sk_sp<SkSVGText> Make() {
-    return sk_sp<SkSVGText>(new SkSVGText()); }
-
-  void setX(const SkSVGLength&);
-  void setY(const SkSVGLength&);
-  void setFontFamily(const SkSVGStringType&);
-  void setFontSize(const SkSVGLength&);
-  void setFontStyle(const SkSVGStringType&);
-  void setFontWeight(const SkSVGStringType&);
-  void setText(const SkSVGStringType&);
-  void setTextAnchor(const SkSVGStringType&);
-
- protected:
-  void onSetAttribute(SkSVGAttribute, const SkSVGValue&) override;
-
-  void onDraw(SkCanvas*, const SkSVGLengthContext&, const SkPaint&,
-              SkPathFillType) const override;
-
-  SkPath onAsPath(const SkSVGRenderContext&) const override;
-
-  void loadFont();
-
- private:
-  SkSVGText();
-  SkSVGLength fX = SkSVGLength(0);
-  SkSVGLength fY = SkSVGLength(0);
-  SkSVGStringType fText;
-  sk_sp<SkTypeface> fTypeface;
-  SkSVGLength fFontSize;
-  SkSVGStringType fFontFamily;
-  SkSVGStringType fFontStyle;
-  SkSVGStringType fFontWeight;
-  SkTextUtils::Align fTextAlign = SkTextUtils::Align::kLeft_Align;
-  using INHERITED = SkSVGShape;
-};
-
-#endif  // SkSVGText_DEFINED
diff --git a/experimental/svg/model/SkSVGTransformableNode.h b/experimental/svg/model/SkSVGTransformableNode.h
index c86df6c..7c8a790 100644
--- a/experimental/svg/model/SkSVGTransformableNode.h
+++ b/experimental/svg/model/SkSVGTransformableNode.h
@@ -1,36 +1,10 @@
 /*
- * Copyright 2016 Google Inc.
+ * Copyright 2020 Google Inc.
  *
  * Use of this source code is governed by a BSD-style license that can be
  * found in the LICENSE file.
  */
 
-#ifndef SkSVGTransformableNode_DEFINED
-#define SkSVGTransformableNode_DEFINED
+// Transitional forwarding header.  To be removed.
+#include "modules/svg/include/SkSVGTransformableNode.h"
 
-#include "experimental/svg/model/SkSVGNode.h"
-#include "include/core/SkMatrix.h"
-
-class SkSVGTransformableNode : public SkSVGNode {
-public:
-    ~SkSVGTransformableNode() override = default;
-
-    void setTransform(const SkSVGTransformType& t) { fTransform = t; }
-
-protected:
-    SkSVGTransformableNode(SkSVGTag);
-
-    bool onPrepareToRender(SkSVGRenderContext*) const override;
-
-    void onSetAttribute(SkSVGAttribute, const SkSVGValue&) override;
-
-    void mapToParent(SkPath*) const;
-
-private:
-    // FIXME: should be sparse
-    SkSVGTransformType fTransform;
-
-    using INHERITED = SkSVGNode;
-};
-
-#endif // SkSVGTransformableNode_DEFINED
diff --git a/experimental/svg/model/SkSVGTypes.h b/experimental/svg/model/SkSVGTypes.h
index d4563d1..888de9b 100644
--- a/experimental/svg/model/SkSVGTypes.h
+++ b/experimental/svg/model/SkSVGTypes.h
@@ -1,311 +1,10 @@
 /*
- * Copyright 2016 Google Inc.
+ * Copyright 2020 Google Inc.
  *
  * Use of this source code is governed by a BSD-style license that can be
  * found in the LICENSE file.
  */
 
-#ifndef SkSVGTypes_DEFINED
-#define SkSVGTypes_DEFINED
-
-#include "include/core/SkColor.h"
-#include "include/core/SkMatrix.h"
-#include "include/core/SkPath.h"
-#include "include/core/SkPoint.h"
-#include "include/core/SkRect.h"
-#include "include/core/SkScalar.h"
-#include "include/core/SkString.h"
-#include "include/core/SkTypes.h"
-#include "include/private/SkTDArray.h"
-
-using SkSVGColorType     = SkColor;
-using SkSVGNumberType    = SkScalar;
-using SkSVGStringType    = SkString;
-using SkSVGViewBoxType   = SkRect;
-using SkSVGTransformType = SkMatrix;
-using SkSVGPointsType    = SkTDArray<SkPoint>;
-
-class SkSVGLength {
-public:
-    enum class Unit {
-        kUnknown,
-        kNumber,
-        kPercentage,
-        kEMS,
-        kEXS,
-        kPX,
-        kCM,
-        kMM,
-        kIN,
-        kPT,
-        kPC,
-    };
-
-    constexpr SkSVGLength()                    : fValue(0), fUnit(Unit::kUnknown) {}
-    explicit constexpr SkSVGLength(SkScalar v, Unit u = Unit::kNumber)
-        : fValue(v), fUnit(u) {}
-    SkSVGLength(const SkSVGLength&)            = default;
-    SkSVGLength& operator=(const SkSVGLength&) = default;
-
-    bool operator==(const SkSVGLength& other) const {
-        return fUnit == other.fUnit && fValue == other.fValue;
-    }
-    bool operator!=(const SkSVGLength& other) const { return !(*this == other); }
-
-    const SkScalar& value() const { return fValue; }
-    const Unit&     unit()  const { return fUnit;  }
-
-private:
-    SkScalar fValue;
-    Unit     fUnit;
-};
-
-class SkSVGPaint {
-public:
-    enum class Type {
-        kNone,
-        kCurrentColor,
-        kColor,
-        kInherit,
-        kIRI,
-    };
-
-    SkSVGPaint() : fType(Type::kInherit), fColor(SK_ColorBLACK) {}
-    explicit SkSVGPaint(Type t) : fType(t), fColor(SK_ColorBLACK) {}
-    explicit SkSVGPaint(const SkSVGColorType& c) : fType(Type::kColor), fColor(c) {}
-    explicit SkSVGPaint(const SkString& iri)
-        : fType(Type::kIRI), fColor(SK_ColorBLACK), fIRI(iri) {}
-
-    SkSVGPaint(const SkSVGPaint&)            = default;
-    SkSVGPaint& operator=(const SkSVGPaint&) = default;
-
-    bool operator==(const SkSVGPaint& other) const {
-        return fType == other.fType && fColor == other.fColor && fIRI == other.fIRI;
-    }
-    bool operator!=(const SkSVGPaint& other) const { return !(*this == other); }
-
-    Type type() const { return fType; }
-    const SkSVGColorType& color() const { SkASSERT(fType == Type::kColor); return fColor; }
-    const SkString& iri() const { SkASSERT(fType == Type::kIRI); return fIRI; }
-
-private:
-    Type fType;
-
-    // Logical union.
-    SkSVGColorType fColor;
-    SkString       fIRI;
-};
-
-class SkSVGClip {
-public:
-    enum class Type {
-        kNone,
-        kInherit,
-        kIRI,
-    };
-
-    SkSVGClip() : fType(Type::kNone) {}
-    explicit SkSVGClip(Type t) : fType(t)           {}
-    explicit SkSVGClip(const SkString& iri) : fType(Type::kIRI), fIRI(iri) {}
-
-    SkSVGClip(const SkSVGClip&)            = default;
-    SkSVGClip& operator=(const SkSVGClip&) = default;
-
-    bool operator==(const SkSVGClip& other) const {
-        return fType == other.fType && fIRI == other.fIRI;
-    }
-    bool operator!=(const SkSVGClip& other) const { return !(*this == other); }
-
-    Type type() const { return fType; }
-    const SkString& iri() const { SkASSERT(fType == Type::kIRI); return fIRI; }
-
-private:
-    Type           fType;
-    SkString       fIRI;
-};
-
-class SkSVGLineCap {
-public:
-    enum class Type {
-        kButt,
-        kRound,
-        kSquare,
-        kInherit,
-    };
-
-    constexpr SkSVGLineCap() : fType(Type::kInherit) {}
-    constexpr explicit SkSVGLineCap(Type t) : fType(t) {}
-
-    SkSVGLineCap(const SkSVGLineCap&)            = default;
-    SkSVGLineCap& operator=(const SkSVGLineCap&) = default;
-
-    bool operator==(const SkSVGLineCap& other) const { return fType == other.fType; }
-    bool operator!=(const SkSVGLineCap& other) const { return !(*this == other); }
-
-    Type type() const { return fType; }
-
-private:
-    Type fType;
-};
-
-class SkSVGLineJoin {
-public:
-    enum class Type {
-        kMiter,
-        kRound,
-        kBevel,
-        kInherit,
-    };
-
-    constexpr SkSVGLineJoin() : fType(Type::kInherit) {}
-    constexpr explicit SkSVGLineJoin(Type t) : fType(t) {}
-
-    SkSVGLineJoin(const SkSVGLineJoin&)            = default;
-    SkSVGLineJoin& operator=(const SkSVGLineJoin&) = default;
-
-    bool operator==(const SkSVGLineJoin& other) const { return fType == other.fType; }
-    bool operator!=(const SkSVGLineJoin& other) const { return !(*this == other); }
-
-    Type type() const { return fType; }
-
-private:
-    Type fType;
-};
-
-class SkSVGSpreadMethod {
-public:
-    // These values must match Skia's SkShader::TileMode enum.
-    enum class Type {
-        kPad,       // kClamp_TileMode
-        kRepeat,    // kRepeat_TileMode
-        kReflect,   // kMirror_TileMode
-    };
-
-    constexpr SkSVGSpreadMethod() : fType(Type::kPad) {}
-    constexpr explicit SkSVGSpreadMethod(Type t) : fType(t) {}
-
-    SkSVGSpreadMethod(const SkSVGSpreadMethod&)            = default;
-    SkSVGSpreadMethod& operator=(const SkSVGSpreadMethod&) = default;
-
-    bool operator==(const SkSVGSpreadMethod& other) const { return fType == other.fType; }
-    bool operator!=(const SkSVGSpreadMethod& other) const { return !(*this == other); }
-
-    Type type() const { return fType; }
-
-private:
-    Type fType;
-};
-
-class SkSVGFillRule {
-public:
-    enum class Type {
-        kNonZero,
-        kEvenOdd,
-        kInherit,
-    };
-
-    constexpr SkSVGFillRule() : fType(Type::kInherit) {}
-    constexpr explicit SkSVGFillRule(Type t) : fType(t) {}
-
-    SkSVGFillRule(const SkSVGFillRule&)            = default;
-    SkSVGFillRule& operator=(const SkSVGFillRule&) = default;
-
-    bool operator==(const SkSVGFillRule& other) const { return fType == other.fType; }
-    bool operator!=(const SkSVGFillRule& other) const { return !(*this == other); }
-
-    Type type() const { return fType; }
-
-    SkPathFillType asFillType() const {
-        SkASSERT(fType != Type::kInherit); // should never be called for unresolved values.
-        return fType == Type::kEvenOdd ? SkPathFillType::kEvenOdd : SkPathFillType::kWinding;
-    }
-
-private:
-    Type fType;
-};
-
-class SkSVGVisibility {
-public:
-    enum class Type {
-        kVisible,
-        kHidden,
-        kCollapse,
-        kInherit,
-    };
-
-    constexpr SkSVGVisibility() : fType(Type::kVisible) {}
-    constexpr explicit SkSVGVisibility(Type t) : fType(t) {}
-
-    SkSVGVisibility(const SkSVGVisibility&)            = default;
-    SkSVGVisibility& operator=(const SkSVGVisibility&) = default;
-
-    bool operator==(const SkSVGVisibility& other) const { return fType == other.fType; }
-    bool operator!=(const SkSVGVisibility& other) const { return !(*this == other); }
-
-    Type type() const { return fType; }
-
-private:
-    Type fType;
-};
-
-class SkSVGDashArray {
-public:
-    enum class Type {
-        kNone,
-        kDashArray,
-        kInherit,
-    };
-
-    SkSVGDashArray()                : fType(Type::kNone) {}
-    explicit SkSVGDashArray(Type t) : fType(t) {}
-    explicit SkSVGDashArray(SkTDArray<SkSVGLength>&& dashArray)
-        : fType(Type::kDashArray)
-        , fDashArray(std::move(dashArray)) {}
-
-    SkSVGDashArray(const SkSVGDashArray&)            = default;
-    SkSVGDashArray& operator=(const SkSVGDashArray&) = default;
-
-    bool operator==(const SkSVGDashArray& other) const {
-        return fType == other.fType && fDashArray == other.fDashArray;
-    }
-    bool operator!=(const SkSVGDashArray& other) const { return !(*this == other); }
-
-    Type type() const { return fType; }
-
-    const SkTDArray<SkSVGLength>& dashArray() const { return fDashArray; }
-
-private:
-    Type fType;
-    SkTDArray<SkSVGLength> fDashArray;
-};
-
-class SkSVGStopColor {
-public:
-    enum class Type {
-        kColor,
-        kCurrentColor,
-        kICCColor,
-        kInherit,
-    };
-
-    SkSVGStopColor() : fType(Type::kColor), fColor(SK_ColorBLACK) {}
-    explicit SkSVGStopColor(Type t) : fType(t), fColor(SK_ColorBLACK) {}
-    explicit SkSVGStopColor(const SkSVGColorType& c) : fType(Type::kColor), fColor(c) {}
-
-    SkSVGStopColor(const SkSVGStopColor&)            = default;
-    SkSVGStopColor& operator=(const SkSVGStopColor&) = default;
-
-    bool operator==(const SkSVGStopColor& other) const {
-        return fType == other.fType && fColor == other.fColor;
-    }
-    bool operator!=(const SkSVGStopColor& other) const { return !(*this == other); }
-
-    Type type() const { return fType; }
-    const SkSVGColorType& color() const { SkASSERT(fType == Type::kColor); return fColor; }
-
-private:
-    Type fType;
-    SkSVGColorType fColor;
-};
+// Transitional forwarding header.  To be removed.
+#include "modules/svg/include/SkSVGTypes.h"
 
-#endif // SkSVGTypes_DEFINED
diff --git a/experimental/svg/model/SkSVGUse.h b/experimental/svg/model/SkSVGUse.h
index 41fa470..f392f83 100644
--- a/experimental/svg/model/SkSVGUse.h
+++ b/experimental/svg/model/SkSVGUse.h
@@ -1,47 +1,10 @@
 /*
- * Copyright 2017 Google Inc.
+ * Copyright 2020 Google Inc.
  *
  * Use of this source code is governed by a BSD-style license that can be
  * found in the LICENSE file.
  */
 
-#ifndef SkSVGUse_DEFINED
-#define SkSVGUse_DEFINED
+// Transitional forwarding header.  To be removed.
+#include "modules/svg/include/SkSVGUse.h"
 
-#include "experimental/svg/model/SkSVGTransformableNode.h"
-#include "experimental/svg/model/SkSVGTypes.h"
-
-/**
- * Implements support for <use> (reference) elements.
- * (https://www.w3.org/TR/SVG11/struct.html#UseElement)
- */
-class SkSVGUse final : public SkSVGTransformableNode {
-public:
-    ~SkSVGUse() override = default;
-
-    static sk_sp<SkSVGUse> Make() { return sk_sp<SkSVGUse>(new SkSVGUse()); }
-
-    void appendChild(sk_sp<SkSVGNode>) override;
-
-    void setHref(const SkSVGStringType&);
-    void setX(const SkSVGLength&);
-    void setY(const SkSVGLength&);
-
-protected:
-    void onSetAttribute(SkSVGAttribute, const SkSVGValue&) override;
-
-    bool onPrepareToRender(SkSVGRenderContext*) const override;
-    void onRender(const SkSVGRenderContext&) const override;
-    SkPath onAsPath(const SkSVGRenderContext&) const override;
-
-private:
-    SkSVGUse();
-
-    SkSVGStringType    fHref;
-    SkSVGLength        fX = SkSVGLength(0);
-    SkSVGLength        fY = SkSVGLength(0);
-
-    using INHERITED = SkSVGTransformableNode;
-};
-
-#endif // SkSVGUse_DEFINED
diff --git a/experimental/svg/model/SkSVGValue.h b/experimental/svg/model/SkSVGValue.h
index 791bf32..9d52852 100644
--- a/experimental/svg/model/SkSVGValue.h
+++ b/experimental/svg/model/SkSVGValue.h
@@ -1,97 +1,10 @@
 /*
- * Copyright 2016 Google Inc.
+ * Copyright 2020 Google Inc.
  *
  * Use of this source code is governed by a BSD-style license that can be
  * found in the LICENSE file.
  */
 
-#ifndef SkSVGValue_DEFINED
-#define SkSVGValue_DEFINED
+// Transitional forwarding header.  To be removed.
+#include "modules/svg/include/SkSVGValue.h"
 
-#include "experimental/svg/model/SkSVGTypes.h"
-#include "include/core/SkColor.h"
-#include "include/core/SkMatrix.h"
-#include "include/core/SkPath.h"
-#include "include/core/SkTypes.h"
-#include "include/private/SkNoncopyable.h"
-
-class SkSVGValue : public SkNoncopyable {
-public:
-    enum class Type {
-        kClip,
-        kColor,
-        kDashArray,
-        kFillRule,
-        kLength,
-        kLineCap,
-        kLineJoin,
-        kNumber,
-        kPaint,
-        kPath,
-        kPoints,
-        kSpreadMethod,
-        kStopColor,
-        kString,
-        kTransform,
-        kViewBox,
-        kVisibility,
-    };
-
-    Type type() const { return fType; }
-
-    template <typename T>
-    const T* as() const {
-        return fType == T::TYPE ? static_cast<const T*>(this) : nullptr;
-    }
-
-protected:
-    SkSVGValue(Type t) : fType(t) { }
-
-private:
-    Type fType;
-
-    using INHERITED = SkNoncopyable;
-};
-
-template <typename T, SkSVGValue::Type ValueType>
-class SkSVGWrapperValue final : public SkSVGValue {
-public:
-    static constexpr Type TYPE = ValueType;
-
-    explicit SkSVGWrapperValue(const T& v)
-        : INHERITED(ValueType)
-        , fWrappedValue(v) { }
-
-    operator const T&() const { return fWrappedValue; }
-    const T* operator->() const { return &fWrappedValue; }
-
-private:
-    // Stack-only
-    void* operator new(size_t) = delete;
-    void* operator new(size_t, void*) = delete;
-
-    const T& fWrappedValue;
-
-    using INHERITED = SkSVGValue;
-};
-
-using SkSVGClipValue         = SkSVGWrapperValue<SkSVGClip         , SkSVGValue::Type::kClip      >;
-using SkSVGColorValue        = SkSVGWrapperValue<SkSVGColorType    , SkSVGValue::Type::kColor     >;
-using SkSVGFillRuleValue     = SkSVGWrapperValue<SkSVGFillRule     , SkSVGValue::Type::kFillRule  >;
-using SkSVGLengthValue       = SkSVGWrapperValue<SkSVGLength       , SkSVGValue::Type::kLength    >;
-using SkSVGPathValue         = SkSVGWrapperValue<SkPath            , SkSVGValue::Type::kPath      >;
-using SkSVGTransformValue    = SkSVGWrapperValue<SkSVGTransformType, SkSVGValue::Type::kTransform >;
-using SkSVGViewBoxValue      = SkSVGWrapperValue<SkSVGViewBoxType  , SkSVGValue::Type::kViewBox   >;
-using SkSVGPaintValue        = SkSVGWrapperValue<SkSVGPaint        , SkSVGValue::Type::kPaint     >;
-using SkSVGLineCapValue      = SkSVGWrapperValue<SkSVGLineCap      , SkSVGValue::Type::kLineCap   >;
-using SkSVGLineJoinValue     = SkSVGWrapperValue<SkSVGLineJoin     , SkSVGValue::Type::kLineJoin  >;
-using SkSVGNumberValue       = SkSVGWrapperValue<SkSVGNumberType   , SkSVGValue::Type::kNumber    >;
-using SkSVGPointsValue       = SkSVGWrapperValue<SkSVGPointsType   , SkSVGValue::Type::kPoints    >;
-using SkSVGStringValue       = SkSVGWrapperValue<SkSVGStringType   , SkSVGValue::Type::kString    >;
-using SkSVGSpreadMethodValue = SkSVGWrapperValue<SkSVGSpreadMethod ,
-                                                 SkSVGValue::Type::kSpreadMethod>;
-using SkSVGStopColorValue    = SkSVGWrapperValue<SkSVGStopColor    , SkSVGValue::Type::kStopColor >;
-using SkSVGVisibilityValue   = SkSVGWrapperValue<SkSVGVisibility   , SkSVGValue::Type::kVisibility>;
-using SkSVGDashArrayValue    = SkSVGWrapperValue<SkSVGDashArray    , SkSVGValue::Type::kDashArray >;
-
-#endif // SkSVGValue_DEFINED
diff --git a/fuzz/oss_fuzz/FuzzSVG.cpp b/fuzz/oss_fuzz/FuzzSVG.cpp
index 41ba244..1750630 100644
--- a/fuzz/oss_fuzz/FuzzSVG.cpp
+++ b/fuzz/oss_fuzz/FuzzSVG.cpp
@@ -5,10 +5,10 @@
  * found in the LICENSE file.
  */
 
-#include "experimental/svg/model/SkSVGDOM.h"
 #include "include/core/SkData.h"
 #include "include/core/SkStream.h"
 #include "include/core/SkSurface.h"
+#include "modules/svg/include/SkSVGDOM.h"
 
 void FuzzSVG(sk_sp<SkData> bytes) {
     uint8_t w = 100;
diff --git a/gn/skia.gni b/gn/skia.gni
index 2ae6030..a6ffb6e 100644
--- a/gn/skia.gni
+++ b/gn/skia.gni
@@ -26,6 +26,7 @@
   skia_enable_skrive = true
   skia_enable_sksl_interpreter = is_skia_dev_build
   skia_enable_skvm_jit_when_possible = is_skia_dev_build
+  skia_enable_svg = true
   skia_enable_tools = is_skia_dev_build
   skia_enable_gpu_debug_layers = is_skia_dev_build && is_debug
   skia_generate_workarounds = false
diff --git a/modules/skottie/BUILD.gn b/modules/skottie/BUILD.gn
index 030335c..be937dc 100644
--- a/modules/skottie/BUILD.gn
+++ b/modules/skottie/BUILD.gn
@@ -85,8 +85,8 @@
         ]
 
         deps = [
-          "../..:experimental_svg_model",
           "../..:skia",
+          "../svg",
         ]
 
         public_deps = [ ":skottie" ]
diff --git a/modules/svg/BUILD.gn b/modules/svg/BUILD.gn
new file mode 100644
index 0000000..dd470f5
--- /dev/null
+++ b/modules/svg/BUILD.gn
@@ -0,0 +1,43 @@
+# Copyright 2020 Google Inc.
+#
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import("../../gn/skia.gni")
+
+if (skia_enable_svg) {
+  config("public_config") {
+    defines = [ "SK_ENABLE_SVG" ]
+    include_dirs = [ "include" ]
+  }
+
+  component("svg") {
+    check_includes = false
+    import("svg.gni")
+    public_configs = [ ":public_config" ]
+    public = skia_svg_public
+    sources = skia_svg_sources
+    configs += [ "../../:skia_private" ]
+    deps = [ "../..:skia" ]
+  }
+
+  if (skia_enable_tools && defined(is_skia_standalone)) {
+    source_set("tool") {
+      check_includes = false
+      testonly = true
+
+      configs += [ "../..:skia_private" ]
+      sources = [ "utils/SvgTool.cpp" ]
+
+      deps = [
+        "../..:flags",
+        "../..:skia",
+      ]
+
+      public_deps = [ ":svg" ]
+    }
+  }
+} else {
+  group("svg") {
+  }
+}
diff --git a/modules/svg/include/SkSVGAttribute.h b/modules/svg/include/SkSVGAttribute.h
new file mode 100644
index 0000000..3c129d0
--- /dev/null
+++ b/modules/svg/include/SkSVGAttribute.h
@@ -0,0 +1,99 @@
+/*
+ * Copyright 2016 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkSVGAttribute_DEFINED
+#define SkSVGAttribute_DEFINED
+
+#include "modules/svg/include/SkSVGTypes.h"
+#include "src/core/SkTLazy.h"
+
+class SkSVGRenderContext;
+
+enum class SkSVGAttribute {
+    kClipPath,
+    kClipRule,
+    kColor,
+    kCx, // <circle>, <ellipse>, <radialGradient>: center x position
+    kCy, // <circle>, <ellipse>, <radialGradient>: center y position
+    kD,
+    kFill,
+    kFillOpacity,
+    kFillRule,
+    kFontFamily,
+    kFontSize,
+    kFontStyle,
+    kFontWeight,
+    kFx, // <radialGradient>: focal point x position
+    kFy, // <radialGradient>: focal point y position
+    kGradientTransform,
+    kHeight,
+    kHref,
+    kOffset,
+    kOpacity,
+    kPatternTransform,
+    kPoints,
+    kR,  // <circle>, <radialGradient>: radius
+    kRx, // <ellipse>,<rect>: horizontal (corner) radius
+    kRy, // <ellipse>,<rect>: vertical (corner) radius
+    kSpreadMethod,
+    kStopColor,
+    kStopOpacity,
+    kStroke,
+    kStrokeDashArray,
+    kStrokeDashOffset,
+    kStrokeOpacity,
+    kStrokeLineCap,
+    kStrokeLineJoin,
+    kStrokeMiterLimit,
+    kStrokeWidth,
+    kTransform,
+    kText,
+    kTextAnchor,
+    kViewBox,
+    kVisibility,
+    kWidth,
+    kX,
+    kX1, // <line>: first endpoint x
+    kX2, // <line>: second endpoint x
+    kY,
+    kY1, // <line>: first endpoint y
+    kY2, // <line>: second endpoint y
+
+    kUnknown,
+};
+
+struct SkSVGPresentationAttributes {
+    static SkSVGPresentationAttributes MakeInitial();
+
+    // TODO: SkTLazy adds an extra ptr per attribute; refactor to reduce overhead.
+
+    SkTLazy<SkSVGPaint>      fFill;
+    SkTLazy<SkSVGNumberType> fFillOpacity;
+    SkTLazy<SkSVGFillRule>   fFillRule;
+    SkTLazy<SkSVGFillRule>   fClipRule;
+
+    SkTLazy<SkSVGPaint>      fStroke;
+    SkTLazy<SkSVGDashArray>  fStrokeDashArray;
+    SkTLazy<SkSVGLength>     fStrokeDashOffset;
+    SkTLazy<SkSVGLineCap>    fStrokeLineCap;
+    SkTLazy<SkSVGLineJoin>   fStrokeLineJoin;
+    SkTLazy<SkSVGNumberType> fStrokeMiterLimit;
+    SkTLazy<SkSVGNumberType> fStrokeOpacity;
+    SkTLazy<SkSVGLength>     fStrokeWidth;
+
+    SkTLazy<SkSVGVisibility> fVisibility;
+
+    SkTLazy<SkSVGColorType>  fColor;
+
+    // TODO(tdenniston): add SkSVGStopColor
+
+    // uninherited
+    SkTLazy<SkSVGNumberType> fOpacity;
+    SkTLazy<SkSVGClip>       fClipPath;
+};
+
+#endif // SkSVGAttribute_DEFINED
diff --git a/modules/svg/include/SkSVGAttributeParser.h b/modules/svg/include/SkSVGAttributeParser.h
new file mode 100644
index 0000000..81ae1d3
--- /dev/null
+++ b/modules/svg/include/SkSVGAttributeParser.h
@@ -0,0 +1,76 @@
+/*
+ * Copyright 2016 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkSVGAttributeParser_DEFINED
+#define SkSVGAttributeParser_DEFINED
+
+#include "include/private/SkNoncopyable.h"
+#include "modules/svg/include/SkSVGTypes.h"
+
+class SkSVGAttributeParser : public SkNoncopyable {
+public:
+    SkSVGAttributeParser(const char[]);
+
+    bool parseColor(SkSVGColorType*);
+    bool parseClipPath(SkSVGClip*);
+    bool parseFillRule(SkSVGFillRule*);
+    bool parseNumber(SkSVGNumberType*);
+    bool parseLength(SkSVGLength*);
+    bool parseViewBox(SkSVGViewBoxType*);
+    bool parseTransform(SkSVGTransformType*);
+    bool parsePaint(SkSVGPaint*);
+    bool parseLineCap(SkSVGLineCap*);
+    bool parseLineJoin(SkSVGLineJoin*);
+    bool parsePoints(SkSVGPointsType*);
+    bool parseIRI(SkSVGStringType*);
+    bool parseSpreadMethod(SkSVGSpreadMethod*);
+    bool parseStopColor(SkSVGStopColor*);
+    bool parseVisibility(SkSVGVisibility*);
+    bool parseDashArray(SkSVGDashArray*);
+
+private:
+    // Stack-only
+    void* operator new(size_t) = delete;
+    void* operator new(size_t, void*) = delete;
+
+    template <typename F>
+    bool advanceWhile(F func);
+
+    bool parseWSToken();
+    bool parseEOSToken();
+    bool parseSepToken();
+    bool parseCommaWspToken();
+    bool parseExpectedStringToken(const char*);
+    bool parseScalarToken(SkScalar*);
+    bool parseHexToken(uint32_t*);
+    bool parseLengthUnitToken(SkSVGLength::Unit*);
+    bool parseNamedColorToken(SkColor*);
+    bool parseHexColorToken(SkColor*);
+    bool parseColorComponentToken(int32_t*);
+    bool parseRGBColorToken(SkColor*);
+    bool parseFuncIRI(SkSVGStringType*);
+
+    // Transform helpers
+    bool parseMatrixToken(SkMatrix*);
+    bool parseTranslateToken(SkMatrix*);
+    bool parseScaleToken(SkMatrix*);
+    bool parseRotateToken(SkMatrix*);
+    bool parseSkewXToken(SkMatrix*);
+    bool parseSkewYToken(SkMatrix*);
+
+    // Parses a sequence of 'WS* <prefix> WS* (<nested>)', where the nested sequence
+    // is handled by the passed functor.
+    template <typename Func, typename T>
+    bool parseParenthesized(const char* prefix, Func, T* result);
+
+    // The current position in the input string.
+    const char* fCurPos;
+
+    using INHERITED = SkNoncopyable;
+};
+
+#endif // SkSVGAttributeParser_DEFINED
diff --git a/modules/svg/include/SkSVGCircle.h b/modules/svg/include/SkSVGCircle.h
new file mode 100644
index 0000000..8bc0da9
--- /dev/null
+++ b/modules/svg/include/SkSVGCircle.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2016 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkSVGCircle_DEFINED
+#define SkSVGCircle_DEFINED
+
+#include "modules/svg/include/SkSVGShape.h"
+#include "modules/svg/include/SkSVGTypes.h"
+
+struct SkPoint;
+
+class SkSVGCircle final : public SkSVGShape {
+public:
+    ~SkSVGCircle() override = default;
+    static sk_sp<SkSVGCircle> Make() { return sk_sp<SkSVGCircle>(new SkSVGCircle()); }
+
+    void setCx(const SkSVGLength&);
+    void setCy(const SkSVGLength&);
+    void setR(const SkSVGLength&);
+
+protected:
+    void onSetAttribute(SkSVGAttribute, const SkSVGValue&) override;
+
+    void onDraw(SkCanvas*, const SkSVGLengthContext&, const SkPaint&,
+                SkPathFillType) const override;
+
+    SkPath onAsPath(const SkSVGRenderContext&) const override;
+
+private:
+    SkSVGCircle();
+
+    // resolve and return the center and radius values
+    std::tuple<SkPoint, SkScalar> resolve(const SkSVGLengthContext&) const;
+
+    SkSVGLength fCx = SkSVGLength(0);
+    SkSVGLength fCy = SkSVGLength(0);
+    SkSVGLength fR  = SkSVGLength(0);
+
+    using INHERITED = SkSVGShape;
+};
+
+#endif // SkSVGCircle_DEFINED
diff --git a/modules/svg/include/SkSVGClipPath.h b/modules/svg/include/SkSVGClipPath.h
new file mode 100644
index 0000000..d711a6b
--- /dev/null
+++ b/modules/svg/include/SkSVGClipPath.h
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2016 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkSVGClipPath_DEFINED
+#define SkSVGClipPath_DEFINED
+
+#include "modules/svg/include/SkSVGHiddenContainer.h"
+#include "modules/svg/include/SkSVGTypes.h"
+
+class SkSVGClipPath final : public SkSVGHiddenContainer {
+public:
+    static sk_sp<SkSVGClipPath> Make() {
+        return sk_sp<SkSVGClipPath>(new SkSVGClipPath());
+    }
+
+private:
+    SkSVGClipPath();
+
+    using INHERITED = SkSVGHiddenContainer;
+};
+
+#endif // SkSVGClipPath_DEFINED
diff --git a/modules/svg/include/SkSVGContainer.h b/modules/svg/include/SkSVGContainer.h
new file mode 100644
index 0000000..4b386ec
--- /dev/null
+++ b/modules/svg/include/SkSVGContainer.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2016 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkSVGContainer_DEFINED
+#define SkSVGContainer_DEFINED
+
+#include "include/private/SkTArray.h"
+#include "modules/svg/include/SkSVGTransformableNode.h"
+
+class SkSVGContainer : public SkSVGTransformableNode {
+public:
+    ~SkSVGContainer() override = default;
+
+    void appendChild(sk_sp<SkSVGNode>) override;
+
+protected:
+    explicit SkSVGContainer(SkSVGTag);
+
+    void onRender(const SkSVGRenderContext&) const override;
+
+    SkPath onAsPath(const SkSVGRenderContext&) const override;
+
+    bool hasChildren() const final;
+
+    // TODO: add some sort of child iterator, and hide the container.
+    SkSTArray<1, sk_sp<SkSVGNode>, true> fChildren;
+
+private:
+    using INHERITED = SkSVGTransformableNode;
+};
+
+#endif // SkSVGContainer_DEFINED
diff --git a/modules/svg/include/SkSVGDOM.h b/modules/svg/include/SkSVGDOM.h
new file mode 100644
index 0000000..bdb8c98
--- /dev/null
+++ b/modules/svg/include/SkSVGDOM.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2016 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkSVGDOM_DEFINED
+#define SkSVGDOM_DEFINED
+
+#include "include/core/SkRefCnt.h"
+#include "include/core/SkSize.h"
+#include "include/private/SkTemplates.h"
+#include "modules/svg/include/SkSVGIDMapper.h"
+
+class SkCanvas;
+class SkDOM;
+class SkStream;
+class SkSVGNode;
+
+class SkSVGDOM : public SkRefCnt {
+public:
+    SkSVGDOM();
+
+    static sk_sp<SkSVGDOM> MakeFromDOM(const SkDOM&);
+    static sk_sp<SkSVGDOM> MakeFromStream(SkStream&);
+
+    const SkSize& containerSize() const;
+    void setContainerSize(const SkSize&);
+
+    void setRoot(sk_sp<SkSVGNode>);
+
+    // Returns the node with the given id, or nullptr if not found.
+    sk_sp<SkSVGNode>* findNodeById(const char* id);
+
+    void render(SkCanvas*) const;
+
+private:
+    SkSize intrinsicSize() const;
+
+    SkSize           fContainerSize;
+    sk_sp<SkSVGNode> fRoot;
+    SkSVGIDMapper    fIDMapper;
+
+    using INHERITED = SkRefCnt;
+};
+
+#endif // SkSVGDOM_DEFINED
diff --git a/modules/svg/include/SkSVGDefs.h b/modules/svg/include/SkSVGDefs.h
new file mode 100644
index 0000000..46fbf43
--- /dev/null
+++ b/modules/svg/include/SkSVGDefs.h
@@ -0,0 +1,23 @@
+/*
+ * Copyright 2016 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkSVGDefs_DEFINED
+#define SkSVGDefs_DEFINED
+
+#include "modules/svg/include/SkSVGHiddenContainer.h"
+
+class SkSVGDefs : public SkSVGHiddenContainer {
+public:
+    static sk_sp<SkSVGDefs> Make() { return sk_sp<SkSVGDefs>(new SkSVGDefs()); }
+
+private:
+    SkSVGDefs() : INHERITED(SkSVGTag::kDefs) {}
+
+    using INHERITED = SkSVGHiddenContainer;
+};
+
+#endif // SkSVGDefs_DEFINED
diff --git a/modules/svg/include/SkSVGEllipse.h b/modules/svg/include/SkSVGEllipse.h
new file mode 100644
index 0000000..96b06da
--- /dev/null
+++ b/modules/svg/include/SkSVGEllipse.h
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2016 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkSVGEllipse_DEFINED
+#define SkSVGEllipse_DEFINED
+
+#include "modules/svg/include/SkSVGShape.h"
+#include "modules/svg/include/SkSVGTypes.h"
+
+struct SkRect;
+
+class SkSVGEllipse final : public SkSVGShape {
+public:
+    ~SkSVGEllipse() override = default;
+    static sk_sp<SkSVGEllipse> Make() { return sk_sp<SkSVGEllipse>(new SkSVGEllipse()); }
+
+    void setCx(const SkSVGLength&);
+    void setCy(const SkSVGLength&);
+    void setRx(const SkSVGLength&);
+    void setRy(const SkSVGLength&);
+
+protected:
+    void onSetAttribute(SkSVGAttribute, const SkSVGValue&) override;
+
+    void onDraw(SkCanvas*, const SkSVGLengthContext&, const SkPaint&,
+                SkPathFillType) const override;
+
+    SkPath onAsPath(const SkSVGRenderContext&) const override;
+
+private:
+    SkSVGEllipse();
+
+    SkRect resolve(const SkSVGLengthContext&) const;
+
+    SkSVGLength fCx = SkSVGLength(0);
+    SkSVGLength fCy = SkSVGLength(0);
+    SkSVGLength fRx = SkSVGLength(0);
+    SkSVGLength fRy = SkSVGLength(0);
+
+    using INHERITED = SkSVGShape;
+};
+
+#endif // SkSVGEllipse_DEFINED
diff --git a/modules/svg/include/SkSVGG.h b/modules/svg/include/SkSVGG.h
new file mode 100644
index 0000000..4d7368f
--- /dev/null
+++ b/modules/svg/include/SkSVGG.h
@@ -0,0 +1,23 @@
+/*
+ * Copyright 2016 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkSVGG_DEFINED
+#define SkSVGG_DEFINED
+
+#include "modules/svg/include/SkSVGContainer.h"
+
+class SkSVGG : public SkSVGContainer {
+public:
+    static sk_sp<SkSVGG> Make() { return sk_sp<SkSVGG>(new SkSVGG()); }
+
+private:
+    SkSVGG() : INHERITED(SkSVGTag::kG) { }
+
+    using INHERITED = SkSVGContainer;
+};
+
+#endif // SkSVGG_DEFINED
diff --git a/modules/svg/include/SkSVGGradient.h b/modules/svg/include/SkSVGGradient.h
new file mode 100644
index 0000000..469bfe6
--- /dev/null
+++ b/modules/svg/include/SkSVGGradient.h
@@ -0,0 +1,51 @@
+/*
+ * Copyright 2017 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkSVGGradient_DEFINED
+#define SkSVGGradient_DEFINED
+
+#include "include/core/SkShader.h"
+#include "modules/svg/include/SkSVGHiddenContainer.h"
+#include "modules/svg/include/SkSVGTypes.h"
+
+class SkMatrix;
+class SkSVGRenderContext;
+class SkSVGStop;
+
+class SkSVGGradient : public SkSVGHiddenContainer {
+public:
+    ~SkSVGGradient() override = default;
+
+    void setHref(const SkSVGStringType&);
+    void setGradientTransform(const SkSVGTransformType&);
+    void setSpreadMethod(const SkSVGSpreadMethod&);
+
+protected:
+    explicit SkSVGGradient(SkSVGTag t) : INHERITED(t) {}
+
+    void onSetAttribute(SkSVGAttribute, const SkSVGValue&) override;
+
+    bool onAsPaint(const SkSVGRenderContext&, SkPaint*) const final;
+
+    virtual sk_sp<SkShader> onMakeShader(const SkSVGRenderContext&,
+                                         const SkColor*, const SkScalar*, int count,
+                                         SkTileMode, const SkMatrix& localMatrix) const = 0;
+
+private:
+    using StopPositionArray = SkSTArray<2, SkScalar, true>;
+    using    StopColorArray = SkSTArray<2,  SkColor, true>;
+    void collectColorStops(const SkSVGRenderContext&, StopPositionArray*, StopColorArray*) const;
+    SkColor resolveStopColor(const SkSVGRenderContext&, const SkSVGStop&) const;
+
+    SkSVGStringType    fHref;
+    SkSVGTransformType fGradientTransform = SkSVGTransformType(SkMatrix::I());
+    SkSVGSpreadMethod  fSpreadMethod = SkSVGSpreadMethod(SkSVGSpreadMethod::Type::kPad);
+
+    using INHERITED = SkSVGHiddenContainer;
+};
+
+#endif // SkSVGGradient_DEFINED
diff --git a/modules/svg/include/SkSVGHiddenContainer.h b/modules/svg/include/SkSVGHiddenContainer.h
new file mode 100644
index 0000000..319118e
--- /dev/null
+++ b/modules/svg/include/SkSVGHiddenContainer.h
@@ -0,0 +1,23 @@
+/*
+ * Copyright 2016 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkSVGHiddenContainer_DEFINED
+#define SkSVGHiddenContainer_DEFINED
+
+#include "modules/svg/include/SkSVGContainer.h"
+
+class SkSVGHiddenContainer : public SkSVGContainer {
+protected:
+    explicit SkSVGHiddenContainer(SkSVGTag t) : INHERITED(t) {}
+
+    void onRender(const SkSVGRenderContext&) const final {}
+
+private:
+    using INHERITED = SkSVGContainer;
+};
+
+#endif // SkSVGHiddenContainer_DEFINED
diff --git a/modules/svg/include/SkSVGIDMapper.h b/modules/svg/include/SkSVGIDMapper.h
new file mode 100644
index 0000000..ea0d916
--- /dev/null
+++ b/modules/svg/include/SkSVGIDMapper.h
@@ -0,0 +1,19 @@
+/*
+ * Copyright 2016 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkSVGIDMapper_DEFINED
+#define SkSVGIDMapper_DEFINED
+
+#include "include/core/SkRefCnt.h"
+#include "include/private/SkTHash.h"
+
+class SkString;
+class SkSVGNode;
+
+using SkSVGIDMapper = SkTHashMap<SkString, sk_sp<SkSVGNode>>;
+
+#endif // SkSVGIDMapper_DEFINED
diff --git a/modules/svg/include/SkSVGLine.h b/modules/svg/include/SkSVGLine.h
new file mode 100644
index 0000000..8f4ed4d
--- /dev/null
+++ b/modules/svg/include/SkSVGLine.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2016 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkSVGLine_DEFINED
+#define SkSVGLine_DEFINED
+
+#include "modules/svg/include/SkSVGShape.h"
+#include "modules/svg/include/SkSVGTypes.h"
+
+struct SkPoint;
+
+class SkSVGLine final : public SkSVGShape {
+public:
+    ~SkSVGLine() override = default;
+    static sk_sp<SkSVGLine> Make() { return sk_sp<SkSVGLine>(new SkSVGLine()); }
+
+    void setX1(const SkSVGLength&);
+    void setY1(const SkSVGLength&);
+    void setX2(const SkSVGLength&);
+    void setY2(const SkSVGLength&);
+
+protected:
+    void onSetAttribute(SkSVGAttribute, const SkSVGValue&) override;
+
+    void onDraw(SkCanvas*, const SkSVGLengthContext&, const SkPaint&,
+                SkPathFillType) const override;
+
+    SkPath onAsPath(const SkSVGRenderContext&) const override;
+
+private:
+    SkSVGLine();
+
+    // resolve and return the two endpoints
+    std::tuple<SkPoint, SkPoint> resolve(const SkSVGLengthContext&) const;
+
+    SkSVGLength fX1 = SkSVGLength(0);
+    SkSVGLength fY1 = SkSVGLength(0);
+    SkSVGLength fX2 = SkSVGLength(0);
+    SkSVGLength fY2 = SkSVGLength(0);
+
+    using INHERITED = SkSVGShape;
+};
+
+#endif // SkSVGLine_DEFINED
diff --git a/modules/svg/include/SkSVGLinearGradient.h b/modules/svg/include/SkSVGLinearGradient.h
new file mode 100644
index 0000000..d1170fa
--- /dev/null
+++ b/modules/svg/include/SkSVGLinearGradient.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2016 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkSVGLinearGradient_DEFINED
+#define SkSVGLinearGradient_DEFINED
+
+#include "modules/svg/include/SkSVGGradient.h"
+#include "modules/svg/include/SkSVGTypes.h"
+
+class SkSVGLinearGradient final : public SkSVGGradient {
+public:
+    ~SkSVGLinearGradient() override = default;
+    static sk_sp<SkSVGLinearGradient> Make() {
+        return sk_sp<SkSVGLinearGradient>(new SkSVGLinearGradient());
+    }
+
+    void setX1(const SkSVGLength&);
+    void setY1(const SkSVGLength&);
+    void setX2(const SkSVGLength&);
+    void setY2(const SkSVGLength&);
+
+protected:
+    void onSetAttribute(SkSVGAttribute, const SkSVGValue&) override;
+
+    sk_sp<SkShader> onMakeShader(const SkSVGRenderContext&,
+                                 const SkColor*, const SkScalar*, int count,
+                                 SkTileMode, const SkMatrix&) const override;
+private:
+    SkSVGLinearGradient();
+
+    SkSVGLength fX1 = SkSVGLength(0  , SkSVGLength::Unit::kPercentage);
+    SkSVGLength fY1 = SkSVGLength(0  , SkSVGLength::Unit::kPercentage);
+    SkSVGLength fX2 = SkSVGLength(100, SkSVGLength::Unit::kPercentage);
+    SkSVGLength fY2 = SkSVGLength(0  , SkSVGLength::Unit::kPercentage);
+
+    using INHERITED = SkSVGGradient;
+};
+
+#endif // SkSVGLinearGradient_DEFINED
diff --git a/modules/svg/include/SkSVGNode.h b/modules/svg/include/SkSVGNode.h
new file mode 100644
index 0000000..2e92c6b
--- /dev/null
+++ b/modules/svg/include/SkSVGNode.h
@@ -0,0 +1,103 @@
+/*
+ * Copyright 2016 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkSVGNode_DEFINED
+#define SkSVGNode_DEFINED
+
+#include "include/core/SkRefCnt.h"
+#include "modules/svg/include/SkSVGAttribute.h"
+
+class SkCanvas;
+class SkMatrix;
+class SkPaint;
+class SkPath;
+class SkSVGRenderContext;
+class SkSVGValue;
+
+enum class SkSVGTag {
+    kCircle,
+    kClipPath,
+    kDefs,
+    kEllipse,
+    kG,
+    kLine,
+    kLinearGradient,
+    kPath,
+    kPattern,
+    kPolygon,
+    kPolyline,
+    kRadialGradient,
+    kRect,
+    kStop,
+    kSvg,
+    kText,
+    kUse
+};
+
+class SkSVGNode : public SkRefCnt {
+public:
+    ~SkSVGNode() override;
+
+    SkSVGTag tag() const { return fTag; }
+
+    virtual void appendChild(sk_sp<SkSVGNode>) = 0;
+
+    void render(const SkSVGRenderContext&) const;
+    bool asPaint(const SkSVGRenderContext&, SkPaint*) const;
+    SkPath asPath(const SkSVGRenderContext&) const;
+
+    void setAttribute(SkSVGAttribute, const SkSVGValue&);
+    bool setAttribute(const char* attributeName, const char* attributeValue);
+
+    void setClipPath(const SkSVGClip&);
+    void setClipRule(const SkSVGFillRule&);
+    void setColor(const SkSVGColorType&);
+    void setFill(const SkSVGPaint&);
+    void setFillOpacity(const SkSVGNumberType&);
+    void setFillRule(const SkSVGFillRule&);
+    void setOpacity(const SkSVGNumberType&);
+    void setStroke(const SkSVGPaint&);
+    void setStrokeDashArray(const SkSVGDashArray&);
+    void setStrokeDashOffset(const SkSVGLength&);
+    void setStrokeOpacity(const SkSVGNumberType&);
+    void setStrokeLineCap(const SkSVGLineCap&);
+    void setStrokeLineJoin(const SkSVGLineJoin&);
+    void setStrokeMiterLimit(const SkSVGNumberType&);
+    void setStrokeWidth(const SkSVGLength&);
+    void setVisibility(const SkSVGVisibility&);
+
+protected:
+    SkSVGNode(SkSVGTag);
+
+    // Called before onRender(), to apply local attributes to the context.  Unlike onRender(),
+    // onPrepareToRender() bubbles up the inheritance chain: overriders should always call
+    // INHERITED::onPrepareToRender(), unless they intend to short-circuit rendering
+    // (return false).
+    // Implementations are expected to return true if rendering is to continue, or false if
+    // the node/subtree rendering is disabled.
+    virtual bool onPrepareToRender(SkSVGRenderContext*) const;
+
+    virtual void onRender(const SkSVGRenderContext&) const = 0;
+
+    virtual bool onAsPaint(const SkSVGRenderContext&, SkPaint*) const { return false; }
+
+    virtual SkPath onAsPath(const SkSVGRenderContext&) const = 0;
+
+    virtual void onSetAttribute(SkSVGAttribute, const SkSVGValue&);
+
+    virtual bool hasChildren() const { return false; }
+
+private:
+    SkSVGTag                    fTag;
+
+    // FIXME: this should be sparse
+    SkSVGPresentationAttributes fPresentationAttributes;
+
+    using INHERITED = SkRefCnt;
+};
+
+#endif // SkSVGNode_DEFINED
diff --git a/modules/svg/include/SkSVGPath.h b/modules/svg/include/SkSVGPath.h
new file mode 100644
index 0000000..169837e
--- /dev/null
+++ b/modules/svg/include/SkSVGPath.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2016 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkSVGPath_DEFINED
+#define SkSVGPath_DEFINED
+
+#include "include/core/SkPath.h"
+#include "modules/svg/include/SkSVGShape.h"
+
+class SkSVGPath final : public SkSVGShape {
+public:
+    ~SkSVGPath() override = default;
+    static sk_sp<SkSVGPath> Make() { return sk_sp<SkSVGPath>(new SkSVGPath()); }
+
+    void setPath(const SkPath& path) { fPath = path; }
+
+protected:
+    void onSetAttribute(SkSVGAttribute, const SkSVGValue&) override;
+
+    void onDraw(SkCanvas*, const SkSVGLengthContext&, const SkPaint&,
+                SkPathFillType) const override;
+
+    SkPath onAsPath(const SkSVGRenderContext&) const override;
+
+private:
+    SkSVGPath();
+
+    mutable SkPath fPath; // mutated in onDraw(), to apply inherited fill types.
+
+    using INHERITED = SkSVGShape;
+};
+
+#endif // SkSVGPath_DEFINED
diff --git a/modules/svg/include/SkSVGPattern.h b/modules/svg/include/SkSVGPattern.h
new file mode 100644
index 0000000..64cebf4
--- /dev/null
+++ b/modules/svg/include/SkSVGPattern.h
@@ -0,0 +1,59 @@
+/*
+ * Copyright 2017 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkSVGPattern_DEFINED
+#define SkSVGPattern_DEFINED
+
+#include "modules/svg/include/SkSVGHiddenContainer.h"
+#include "modules/svg/include/SkSVGTypes.h"
+
+class SkSVGRenderContext;
+
+class SkSVGPattern final : public SkSVGHiddenContainer {
+public:
+    ~SkSVGPattern() override = default;
+
+    static sk_sp<SkSVGPattern> Make() {
+        return sk_sp<SkSVGPattern>(new SkSVGPattern());
+    }
+
+    void setX(const SkSVGLength&);
+    void setY(const SkSVGLength&);
+    void setWidth(const SkSVGLength&);
+    void setHeight(const SkSVGLength&);
+    void setHref(const SkSVGStringType&);
+    void setPatternTransform(const SkSVGTransformType&);
+
+protected:
+    SkSVGPattern();
+
+    void onSetAttribute(SkSVGAttribute, const SkSVGValue&) override;
+
+    bool onAsPaint(const SkSVGRenderContext&, SkPaint*) const override;
+
+private:
+    struct PatternAttributes {
+        SkTLazy<SkSVGLength>        fX,
+                                    fY,
+                                    fWidth,
+                                    fHeight;
+        SkTLazy<SkSVGTransformType> fPatternTransform;
+    } fAttributes;
+
+    SkSVGStringType    fHref;
+
+    const SkSVGPattern* resolveHref(const SkSVGRenderContext&, PatternAttributes*) const;
+    const SkSVGPattern* hrefTarget(const SkSVGRenderContext&) const;
+
+    // TODO:
+    //   - patternUnits
+    //   - patternContentUnits
+
+    using INHERITED = SkSVGHiddenContainer;
+};
+
+#endif // SkSVGPattern_DEFINED
diff --git a/modules/svg/include/SkSVGPoly.h b/modules/svg/include/SkSVGPoly.h
new file mode 100644
index 0000000..ad890aa
--- /dev/null
+++ b/modules/svg/include/SkSVGPoly.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2016 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkSVGPoly_DEFINED
+#define SkSVGPoly_DEFINED
+
+#include "include/core/SkPath.h"
+#include "modules/svg/include/SkSVGShape.h"
+
+// Handles <polygon> and <polyline> elements.
+class SkSVGPoly final : public SkSVGShape {
+public:
+    ~SkSVGPoly() override = default;
+
+    static sk_sp<SkSVGPoly> MakePolygon() {
+        return sk_sp<SkSVGPoly>(new SkSVGPoly(SkSVGTag::kPolygon));
+    }
+
+    static sk_sp<SkSVGPoly> MakePolyline() {
+        return sk_sp<SkSVGPoly>(new SkSVGPoly(SkSVGTag::kPolyline));
+    }
+
+    void setPoints(const SkSVGPointsType&);
+
+protected:
+    void onSetAttribute(SkSVGAttribute, const SkSVGValue&) override;
+
+    void onDraw(SkCanvas*, const SkSVGLengthContext&, const SkPaint&,
+                SkPathFillType) const override;
+
+    SkPath onAsPath(const SkSVGRenderContext&) const override;
+
+private:
+    SkSVGPoly(SkSVGTag);
+
+    mutable SkPath fPath;  // mutated in onDraw(), to apply inherited fill types.
+
+    using INHERITED = SkSVGShape;
+};
+
+#endif // SkSVGPoly_DEFINED
diff --git a/modules/svg/include/SkSVGRadialGradient.h b/modules/svg/include/SkSVGRadialGradient.h
new file mode 100644
index 0000000..e9fd0d8
--- /dev/null
+++ b/modules/svg/include/SkSVGRadialGradient.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2017 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkSVGRadialGradient_DEFINED
+#define SkSVGRadialGradient_DEFINED
+
+#include "modules/svg/include/SkSVGGradient.h"
+#include "modules/svg/include/SkSVGTypes.h"
+
+class SkSVGRadialGradient final : public SkSVGGradient {
+public:
+    ~SkSVGRadialGradient() override = default;
+    static sk_sp<SkSVGRadialGradient> Make() {
+        return sk_sp<SkSVGRadialGradient>(new SkSVGRadialGradient());
+    }
+
+    void setCx(const SkSVGLength&);
+    void setCy(const SkSVGLength&);
+    void setR(const SkSVGLength&);
+    void setFx(const SkSVGLength&);
+    void setFy(const SkSVGLength&);
+
+protected:
+    void onSetAttribute(SkSVGAttribute, const SkSVGValue&) override;
+
+    sk_sp<SkShader> onMakeShader(const SkSVGRenderContext&,
+                                 const SkColor*, const SkScalar*, int count,
+                                 SkTileMode, const SkMatrix&) const override;
+private:
+    SkSVGRadialGradient();
+
+    SkSVGLength fCx = SkSVGLength(50, SkSVGLength::Unit::kPercentage);
+    SkSVGLength fCy = SkSVGLength(50, SkSVGLength::Unit::kPercentage);
+    SkSVGLength fR  = SkSVGLength(50, SkSVGLength::Unit::kPercentage);
+    SkTLazy<SkSVGLength> fFx;
+    SkTLazy<SkSVGLength> fFy;
+
+
+   using INHERITED = SkSVGGradient;
+};
+
+#endif // SkSVGRadialGradient_DEFINED
diff --git a/modules/svg/include/SkSVGRect.h b/modules/svg/include/SkSVGRect.h
new file mode 100644
index 0000000..507d9d9
--- /dev/null
+++ b/modules/svg/include/SkSVGRect.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2016 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkSVGRect_DEFINED
+#define SkSVGRect_DEFINED
+
+#include "modules/svg/include/SkSVGShape.h"
+#include "modules/svg/include/SkSVGTypes.h"
+
+class SkRRect;
+
+class SkSVGRect final : public SkSVGShape {
+public:
+    ~SkSVGRect() override = default;
+    static sk_sp<SkSVGRect> Make() { return sk_sp<SkSVGRect>(new SkSVGRect()); }
+
+    void setX(const SkSVGLength&);
+    void setY(const SkSVGLength&);
+    void setWidth(const SkSVGLength&);
+    void setHeight(const SkSVGLength&);
+    void setRx(const SkSVGLength&);
+    void setRy(const SkSVGLength&);
+
+protected:
+    void onSetAttribute(SkSVGAttribute, const SkSVGValue&) override;
+
+    void onDraw(SkCanvas*, const SkSVGLengthContext&, const SkPaint&,
+                SkPathFillType) const override;
+
+    SkPath onAsPath(const SkSVGRenderContext&) const override;
+
+private:
+    SkSVGRect();
+
+    SkRRect resolve(const SkSVGLengthContext&) const;
+
+    SkSVGLength fX      = SkSVGLength(0);
+    SkSVGLength fY      = SkSVGLength(0);
+    SkSVGLength fWidth  = SkSVGLength(0);
+    SkSVGLength fHeight = SkSVGLength(0);
+
+    // The x radius for rounded rects.
+    SkSVGLength fRx     = SkSVGLength(0);
+    // The y radius for rounded rects.
+    SkSVGLength fRy     = SkSVGLength(0);
+
+    using INHERITED = SkSVGShape;
+};
+
+#endif // SkSVGRect_DEFINED
diff --git a/modules/svg/include/SkSVGRenderContext.h b/modules/svg/include/SkSVGRenderContext.h
new file mode 100644
index 0000000..0659a89
--- /dev/null
+++ b/modules/svg/include/SkSVGRenderContext.h
@@ -0,0 +1,144 @@
+/*
+ * Copyright 2016 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkSVGRenderContext_DEFINED
+#define SkSVGRenderContext_DEFINED
+
+#include "include/core/SkPaint.h"
+#include "include/core/SkPath.h"
+#include "include/core/SkRect.h"
+#include "include/core/SkSize.h"
+#include "include/core/SkTypes.h"
+#include "modules/svg/include/SkSVGAttribute.h"
+#include "modules/svg/include/SkSVGIDMapper.h"
+#include "src/core/SkTLazy.h"
+
+class SkCanvas;
+class SkSVGLength;
+
+class SkSVGLengthContext {
+public:
+    SkSVGLengthContext(const SkSize& viewport, SkScalar dpi = 90)
+        : fViewport(viewport), fDPI(dpi) {}
+
+    enum class LengthType {
+        kHorizontal,
+        kVertical,
+        kOther,
+    };
+
+    const SkSize& viewPort() const { return fViewport; }
+    void setViewPort(const SkSize& viewport) { fViewport = viewport; }
+
+    SkScalar resolve(const SkSVGLength&, LengthType) const;
+    SkRect   resolveRect(const SkSVGLength& x, const SkSVGLength& y,
+                         const SkSVGLength& w, const SkSVGLength& h) const;
+
+private:
+    SkSize   fViewport;
+    SkScalar fDPI;
+};
+
+struct SkSVGPresentationContext {
+    SkSVGPresentationContext();
+    SkSVGPresentationContext(const SkSVGPresentationContext&)            = default;
+    SkSVGPresentationContext& operator=(const SkSVGPresentationContext&) = default;
+
+    // Inherited presentation attributes, computed for the current node.
+    SkSVGPresentationAttributes fInherited;
+
+    // Cached paints, reflecting the current presentation attributes.
+    SkPaint fFillPaint;
+    SkPaint fStrokePaint;
+};
+
+class SkSVGRenderContext {
+public:
+    SkSVGRenderContext(SkCanvas*, const SkSVGIDMapper&, const SkSVGLengthContext&,
+                       const SkSVGPresentationContext&);
+    SkSVGRenderContext(const SkSVGRenderContext&);
+    SkSVGRenderContext(const SkSVGRenderContext&, SkCanvas*);
+    ~SkSVGRenderContext();
+
+    const SkSVGLengthContext& lengthContext() const { return *fLengthContext; }
+    SkSVGLengthContext* writableLengthContext() { return fLengthContext.writable(); }
+
+    const SkSVGPresentationContext& presentationContext() const { return *fPresentationContext; }
+
+    SkCanvas* canvas() const { return fCanvas; }
+    void saveOnce();
+
+    enum ApplyFlags {
+        kLeaf = 1 << 0, // the target node doesn't have descendants
+    };
+    void applyPresentationAttributes(const SkSVGPresentationAttributes&, uint32_t flags);
+
+    // Scoped wrapper that temporarily clears the original node reference.
+    class BorrowedNode {
+    public:
+        explicit BorrowedNode(sk_sp<SkSVGNode>* node)
+            : fOwner(node) {
+            if (fOwner) {
+                fBorrowed = std::move(*fOwner);
+                *fOwner = nullptr;
+            }
+        }
+
+        ~BorrowedNode() {
+            if (fOwner) {
+                *fOwner = std::move(fBorrowed);
+            }
+        }
+
+        const SkSVGNode* get() const { return fBorrowed.get(); }
+        const SkSVGNode* operator->() const { return fBorrowed.get(); }
+        const SkSVGNode& operator*() const { return *fBorrowed; }
+
+        operator bool() const { return !!fBorrowed; }
+
+    private:
+        // noncopyable
+        BorrowedNode(const BorrowedNode&)      = delete;
+        BorrowedNode& operator=(BorrowedNode&) = delete;
+
+        sk_sp<SkSVGNode>* fOwner;
+        sk_sp<SkSVGNode>  fBorrowed;
+    };
+
+    // Note: the id->node association is cleared for the lifetime of the returned value
+    // (effectively breaks reference cycles, assuming appropriate return value scoping).
+    BorrowedNode findNodeById(const SkString&) const;
+
+    const SkPaint* fillPaint() const;
+    const SkPaint* strokePaint() const;
+
+    // The local computed clip path (not inherited).
+    const SkPath* clipPath() const { return fClipPath.getMaybeNull(); }
+
+private:
+    // Stack-only
+    void* operator new(size_t)                               = delete;
+    void* operator new(size_t, void*)                        = delete;
+    SkSVGRenderContext& operator=(const SkSVGRenderContext&) = delete;
+
+    void applyOpacity(SkScalar opacity, uint32_t flags);
+    void applyClip(const SkSVGClip&);
+    void updatePaintsWithCurrentColor(const SkSVGPresentationAttributes&);
+
+    const SkSVGIDMapper&                          fIDMapper;
+    SkTCopyOnFirstWrite<SkSVGLengthContext>       fLengthContext;
+    SkTCopyOnFirstWrite<SkSVGPresentationContext> fPresentationContext;
+    SkCanvas*                                     fCanvas;
+    // The save count on 'fCanvas' at construction time.
+    // A restoreToCount() will be issued on destruction.
+    int                                           fCanvasSaveCount;
+
+    // clipPath, if present for the current context (not inherited).
+    SkTLazy<SkPath>                               fClipPath;
+};
+
+#endif // SkSVGRenderContext_DEFINED
diff --git a/modules/svg/include/SkSVGSVG.h b/modules/svg/include/SkSVGSVG.h
new file mode 100644
index 0000000..7494d78
--- /dev/null
+++ b/modules/svg/include/SkSVGSVG.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2016 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkSVGSVG_DEFINED
+#define SkSVGSVG_DEFINED
+
+#include "modules/svg/include/SkSVGContainer.h"
+#include "modules/svg/include/SkSVGTypes.h"
+#include "src/core/SkTLazy.h"
+
+class SkSVGLengthContext;
+
+class SkSVGSVG : public SkSVGContainer {
+public:
+    ~SkSVGSVG() override = default;
+
+    static sk_sp<SkSVGSVG> Make() { return sk_sp<SkSVGSVG>(new SkSVGSVG()); }
+
+    void setX(const SkSVGLength&);
+    void setY(const SkSVGLength&);
+    void setWidth(const SkSVGLength&);
+    void setHeight(const SkSVGLength&);
+    void setViewBox(const SkSVGViewBoxType&);
+
+    SkSize intrinsicSize(const SkSVGLengthContext&) const;
+
+protected:
+    bool onPrepareToRender(SkSVGRenderContext*) const override;
+
+    void onSetAttribute(SkSVGAttribute, const SkSVGValue&) override;
+
+private:
+    SkSVGSVG();
+
+    SkSVGLength fX      = SkSVGLength(0);
+    SkSVGLength fY      = SkSVGLength(0);
+    SkSVGLength fWidth  = SkSVGLength(100, SkSVGLength::Unit::kPercentage);
+    SkSVGLength fHeight = SkSVGLength(100, SkSVGLength::Unit::kPercentage);
+
+    SkTLazy<SkSVGViewBoxType> fViewBox;
+
+    using INHERITED = SkSVGContainer;
+};
+
+#endif // SkSVGSVG_DEFINED
diff --git a/modules/svg/include/SkSVGShape.h b/modules/svg/include/SkSVGShape.h
new file mode 100644
index 0000000..b1c7126
--- /dev/null
+++ b/modules/svg/include/SkSVGShape.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2016 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkSVGShape_DEFINED
+#define SkSVGShape_DEFINED
+
+#include "include/core/SkPath.h"
+#include "modules/svg/include/SkSVGTransformableNode.h"
+
+class SkSVGLengthContext;
+class SkPaint;
+
+class SkSVGShape : public SkSVGTransformableNode {
+public:
+    ~SkSVGShape() override = default;
+
+    void appendChild(sk_sp<SkSVGNode>) override;
+
+protected:
+    SkSVGShape(SkSVGTag);
+
+    void onRender(const SkSVGRenderContext&) const final;
+
+    virtual void onDraw(SkCanvas*, const SkSVGLengthContext&, const SkPaint&,
+                        SkPathFillType) const = 0;
+
+private:
+    using INHERITED = SkSVGTransformableNode;
+};
+
+#endif // SkSVGShape_DEFINED
diff --git a/modules/svg/include/SkSVGStop.h b/modules/svg/include/SkSVGStop.h
new file mode 100644
index 0000000..a558f57
--- /dev/null
+++ b/modules/svg/include/SkSVGStop.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2016 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkSVGStop_DEFINED
+#define SkSVGStop_DEFINED
+
+#include "modules/svg/include/SkSVGHiddenContainer.h"
+#include "modules/svg/include/SkSVGTypes.h"
+
+class SkSVGLengthContext;
+
+class SkSVGStop : public SkSVGHiddenContainer {
+public:
+    ~SkSVGStop() override = default;
+    static sk_sp<SkSVGStop> Make() {
+        return sk_sp<SkSVGStop>(new SkSVGStop());
+    }
+
+    const SkSVGLength& offset() const { return fOffset; }
+    const SkSVGStopColor& stopColor() const { return fStopColor; }
+    const SkSVGNumberType& stopOpacity() const { return fStopOpacity; }
+
+    void setOffset(const SkSVGLength&);
+    void setStopColor(const SkSVGStopColor&);
+    void setStopOpacity(const SkSVGNumberType&);
+
+protected:
+    void onSetAttribute(SkSVGAttribute, const SkSVGValue&) override;
+
+private:
+    SkSVGStop();
+
+    SkSVGLength          fOffset = SkSVGLength(0  , SkSVGLength::Unit::kPercentage);
+    SkSVGStopColor    fStopColor = SkSVGStopColor(SK_ColorBLACK);
+    SkSVGNumberType fStopOpacity = SkSVGNumberType(1);
+
+    using INHERITED = SkSVGHiddenContainer;
+};
+
+#endif // SkSVGStop_DEFINED
diff --git a/modules/svg/include/SkSVGText.h b/modules/svg/include/SkSVGText.h
new file mode 100644
index 0000000..9336f73
--- /dev/null
+++ b/modules/svg/include/SkSVGText.h
@@ -0,0 +1,57 @@
+/*
+ * Copyright 2019 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkSVGText_DEFINED
+#define SkSVGText_DEFINED
+
+#include "include/core/SkFont.h"
+#include "include/utils/SkTextUtils.h"
+#include "modules/svg/include/SkSVGShape.h"
+#include "modules/svg/include/SkSVGTypes.h"
+
+class SkRRect;
+
+class SkSVGText final : public SkSVGShape {
+ public:
+  ~SkSVGText() override = default;
+  static sk_sp<SkSVGText> Make() {
+    return sk_sp<SkSVGText>(new SkSVGText()); }
+
+  void setX(const SkSVGLength&);
+  void setY(const SkSVGLength&);
+  void setFontFamily(const SkSVGStringType&);
+  void setFontSize(const SkSVGLength&);
+  void setFontStyle(const SkSVGStringType&);
+  void setFontWeight(const SkSVGStringType&);
+  void setText(const SkSVGStringType&);
+  void setTextAnchor(const SkSVGStringType&);
+
+ protected:
+  void onSetAttribute(SkSVGAttribute, const SkSVGValue&) override;
+
+  void onDraw(SkCanvas*, const SkSVGLengthContext&, const SkPaint&,
+              SkPathFillType) const override;
+
+  SkPath onAsPath(const SkSVGRenderContext&) const override;
+
+  void loadFont();
+
+ private:
+  SkSVGText();
+  SkSVGLength fX = SkSVGLength(0);
+  SkSVGLength fY = SkSVGLength(0);
+  SkSVGStringType fText;
+  sk_sp<SkTypeface> fTypeface;
+  SkSVGLength fFontSize;
+  SkSVGStringType fFontFamily;
+  SkSVGStringType fFontStyle;
+  SkSVGStringType fFontWeight;
+  SkTextUtils::Align fTextAlign = SkTextUtils::Align::kLeft_Align;
+  using INHERITED = SkSVGShape;
+};
+
+#endif  // SkSVGText_DEFINED
diff --git a/modules/svg/include/SkSVGTransformableNode.h b/modules/svg/include/SkSVGTransformableNode.h
new file mode 100644
index 0000000..55e0c0a
--- /dev/null
+++ b/modules/svg/include/SkSVGTransformableNode.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2016 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkSVGTransformableNode_DEFINED
+#define SkSVGTransformableNode_DEFINED
+
+#include "include/core/SkMatrix.h"
+#include "modules/svg/include/SkSVGNode.h"
+
+class SkSVGTransformableNode : public SkSVGNode {
+public:
+    ~SkSVGTransformableNode() override = default;
+
+    void setTransform(const SkSVGTransformType& t) { fTransform = t; }
+
+protected:
+    SkSVGTransformableNode(SkSVGTag);
+
+    bool onPrepareToRender(SkSVGRenderContext*) const override;
+
+    void onSetAttribute(SkSVGAttribute, const SkSVGValue&) override;
+
+    void mapToParent(SkPath*) const;
+
+private:
+    // FIXME: should be sparse
+    SkSVGTransformType fTransform;
+
+    using INHERITED = SkSVGNode;
+};
+
+#endif // SkSVGTransformableNode_DEFINED
diff --git a/modules/svg/include/SkSVGTypes.h b/modules/svg/include/SkSVGTypes.h
new file mode 100644
index 0000000..d4563d1
--- /dev/null
+++ b/modules/svg/include/SkSVGTypes.h
@@ -0,0 +1,311 @@
+/*
+ * Copyright 2016 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkSVGTypes_DEFINED
+#define SkSVGTypes_DEFINED
+
+#include "include/core/SkColor.h"
+#include "include/core/SkMatrix.h"
+#include "include/core/SkPath.h"
+#include "include/core/SkPoint.h"
+#include "include/core/SkRect.h"
+#include "include/core/SkScalar.h"
+#include "include/core/SkString.h"
+#include "include/core/SkTypes.h"
+#include "include/private/SkTDArray.h"
+
+using SkSVGColorType     = SkColor;
+using SkSVGNumberType    = SkScalar;
+using SkSVGStringType    = SkString;
+using SkSVGViewBoxType   = SkRect;
+using SkSVGTransformType = SkMatrix;
+using SkSVGPointsType    = SkTDArray<SkPoint>;
+
+class SkSVGLength {
+public:
+    enum class Unit {
+        kUnknown,
+        kNumber,
+        kPercentage,
+        kEMS,
+        kEXS,
+        kPX,
+        kCM,
+        kMM,
+        kIN,
+        kPT,
+        kPC,
+    };
+
+    constexpr SkSVGLength()                    : fValue(0), fUnit(Unit::kUnknown) {}
+    explicit constexpr SkSVGLength(SkScalar v, Unit u = Unit::kNumber)
+        : fValue(v), fUnit(u) {}
+    SkSVGLength(const SkSVGLength&)            = default;
+    SkSVGLength& operator=(const SkSVGLength&) = default;
+
+    bool operator==(const SkSVGLength& other) const {
+        return fUnit == other.fUnit && fValue == other.fValue;
+    }
+    bool operator!=(const SkSVGLength& other) const { return !(*this == other); }
+
+    const SkScalar& value() const { return fValue; }
+    const Unit&     unit()  const { return fUnit;  }
+
+private:
+    SkScalar fValue;
+    Unit     fUnit;
+};
+
+class SkSVGPaint {
+public:
+    enum class Type {
+        kNone,
+        kCurrentColor,
+        kColor,
+        kInherit,
+        kIRI,
+    };
+
+    SkSVGPaint() : fType(Type::kInherit), fColor(SK_ColorBLACK) {}
+    explicit SkSVGPaint(Type t) : fType(t), fColor(SK_ColorBLACK) {}
+    explicit SkSVGPaint(const SkSVGColorType& c) : fType(Type::kColor), fColor(c) {}
+    explicit SkSVGPaint(const SkString& iri)
+        : fType(Type::kIRI), fColor(SK_ColorBLACK), fIRI(iri) {}
+
+    SkSVGPaint(const SkSVGPaint&)            = default;
+    SkSVGPaint& operator=(const SkSVGPaint&) = default;
+
+    bool operator==(const SkSVGPaint& other) const {
+        return fType == other.fType && fColor == other.fColor && fIRI == other.fIRI;
+    }
+    bool operator!=(const SkSVGPaint& other) const { return !(*this == other); }
+
+    Type type() const { return fType; }
+    const SkSVGColorType& color() const { SkASSERT(fType == Type::kColor); return fColor; }
+    const SkString& iri() const { SkASSERT(fType == Type::kIRI); return fIRI; }
+
+private:
+    Type fType;
+
+    // Logical union.
+    SkSVGColorType fColor;
+    SkString       fIRI;
+};
+
+class SkSVGClip {
+public:
+    enum class Type {
+        kNone,
+        kInherit,
+        kIRI,
+    };
+
+    SkSVGClip() : fType(Type::kNone) {}
+    explicit SkSVGClip(Type t) : fType(t)           {}
+    explicit SkSVGClip(const SkString& iri) : fType(Type::kIRI), fIRI(iri) {}
+
+    SkSVGClip(const SkSVGClip&)            = default;
+    SkSVGClip& operator=(const SkSVGClip&) = default;
+
+    bool operator==(const SkSVGClip& other) const {
+        return fType == other.fType && fIRI == other.fIRI;
+    }
+    bool operator!=(const SkSVGClip& other) const { return !(*this == other); }
+
+    Type type() const { return fType; }
+    const SkString& iri() const { SkASSERT(fType == Type::kIRI); return fIRI; }
+
+private:
+    Type           fType;
+    SkString       fIRI;
+};
+
+class SkSVGLineCap {
+public:
+    enum class Type {
+        kButt,
+        kRound,
+        kSquare,
+        kInherit,
+    };
+
+    constexpr SkSVGLineCap() : fType(Type::kInherit) {}
+    constexpr explicit SkSVGLineCap(Type t) : fType(t) {}
+
+    SkSVGLineCap(const SkSVGLineCap&)            = default;
+    SkSVGLineCap& operator=(const SkSVGLineCap&) = default;
+
+    bool operator==(const SkSVGLineCap& other) const { return fType == other.fType; }
+    bool operator!=(const SkSVGLineCap& other) const { return !(*this == other); }
+
+    Type type() const { return fType; }
+
+private:
+    Type fType;
+};
+
+class SkSVGLineJoin {
+public:
+    enum class Type {
+        kMiter,
+        kRound,
+        kBevel,
+        kInherit,
+    };
+
+    constexpr SkSVGLineJoin() : fType(Type::kInherit) {}
+    constexpr explicit SkSVGLineJoin(Type t) : fType(t) {}
+
+    SkSVGLineJoin(const SkSVGLineJoin&)            = default;
+    SkSVGLineJoin& operator=(const SkSVGLineJoin&) = default;
+
+    bool operator==(const SkSVGLineJoin& other) const { return fType == other.fType; }
+    bool operator!=(const SkSVGLineJoin& other) const { return !(*this == other); }
+
+    Type type() const { return fType; }
+
+private:
+    Type fType;
+};
+
+class SkSVGSpreadMethod {
+public:
+    // These values must match Skia's SkShader::TileMode enum.
+    enum class Type {
+        kPad,       // kClamp_TileMode
+        kRepeat,    // kRepeat_TileMode
+        kReflect,   // kMirror_TileMode
+    };
+
+    constexpr SkSVGSpreadMethod() : fType(Type::kPad) {}
+    constexpr explicit SkSVGSpreadMethod(Type t) : fType(t) {}
+
+    SkSVGSpreadMethod(const SkSVGSpreadMethod&)            = default;
+    SkSVGSpreadMethod& operator=(const SkSVGSpreadMethod&) = default;
+
+    bool operator==(const SkSVGSpreadMethod& other) const { return fType == other.fType; }
+    bool operator!=(const SkSVGSpreadMethod& other) const { return !(*this == other); }
+
+    Type type() const { return fType; }
+
+private:
+    Type fType;
+};
+
+class SkSVGFillRule {
+public:
+    enum class Type {
+        kNonZero,
+        kEvenOdd,
+        kInherit,
+    };
+
+    constexpr SkSVGFillRule() : fType(Type::kInherit) {}
+    constexpr explicit SkSVGFillRule(Type t) : fType(t) {}
+
+    SkSVGFillRule(const SkSVGFillRule&)            = default;
+    SkSVGFillRule& operator=(const SkSVGFillRule&) = default;
+
+    bool operator==(const SkSVGFillRule& other) const { return fType == other.fType; }
+    bool operator!=(const SkSVGFillRule& other) const { return !(*this == other); }
+
+    Type type() const { return fType; }
+
+    SkPathFillType asFillType() const {
+        SkASSERT(fType != Type::kInherit); // should never be called for unresolved values.
+        return fType == Type::kEvenOdd ? SkPathFillType::kEvenOdd : SkPathFillType::kWinding;
+    }
+
+private:
+    Type fType;
+};
+
+class SkSVGVisibility {
+public:
+    enum class Type {
+        kVisible,
+        kHidden,
+        kCollapse,
+        kInherit,
+    };
+
+    constexpr SkSVGVisibility() : fType(Type::kVisible) {}
+    constexpr explicit SkSVGVisibility(Type t) : fType(t) {}
+
+    SkSVGVisibility(const SkSVGVisibility&)            = default;
+    SkSVGVisibility& operator=(const SkSVGVisibility&) = default;
+
+    bool operator==(const SkSVGVisibility& other) const { return fType == other.fType; }
+    bool operator!=(const SkSVGVisibility& other) const { return !(*this == other); }
+
+    Type type() const { return fType; }
+
+private:
+    Type fType;
+};
+
+class SkSVGDashArray {
+public:
+    enum class Type {
+        kNone,
+        kDashArray,
+        kInherit,
+    };
+
+    SkSVGDashArray()                : fType(Type::kNone) {}
+    explicit SkSVGDashArray(Type t) : fType(t) {}
+    explicit SkSVGDashArray(SkTDArray<SkSVGLength>&& dashArray)
+        : fType(Type::kDashArray)
+        , fDashArray(std::move(dashArray)) {}
+
+    SkSVGDashArray(const SkSVGDashArray&)            = default;
+    SkSVGDashArray& operator=(const SkSVGDashArray&) = default;
+
+    bool operator==(const SkSVGDashArray& other) const {
+        return fType == other.fType && fDashArray == other.fDashArray;
+    }
+    bool operator!=(const SkSVGDashArray& other) const { return !(*this == other); }
+
+    Type type() const { return fType; }
+
+    const SkTDArray<SkSVGLength>& dashArray() const { return fDashArray; }
+
+private:
+    Type fType;
+    SkTDArray<SkSVGLength> fDashArray;
+};
+
+class SkSVGStopColor {
+public:
+    enum class Type {
+        kColor,
+        kCurrentColor,
+        kICCColor,
+        kInherit,
+    };
+
+    SkSVGStopColor() : fType(Type::kColor), fColor(SK_ColorBLACK) {}
+    explicit SkSVGStopColor(Type t) : fType(t), fColor(SK_ColorBLACK) {}
+    explicit SkSVGStopColor(const SkSVGColorType& c) : fType(Type::kColor), fColor(c) {}
+
+    SkSVGStopColor(const SkSVGStopColor&)            = default;
+    SkSVGStopColor& operator=(const SkSVGStopColor&) = default;
+
+    bool operator==(const SkSVGStopColor& other) const {
+        return fType == other.fType && fColor == other.fColor;
+    }
+    bool operator!=(const SkSVGStopColor& other) const { return !(*this == other); }
+
+    Type type() const { return fType; }
+    const SkSVGColorType& color() const { SkASSERT(fType == Type::kColor); return fColor; }
+
+private:
+    Type fType;
+    SkSVGColorType fColor;
+};
+
+#endif // SkSVGTypes_DEFINED
diff --git a/modules/svg/include/SkSVGUse.h b/modules/svg/include/SkSVGUse.h
new file mode 100644
index 0000000..4a87f99
--- /dev/null
+++ b/modules/svg/include/SkSVGUse.h
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2017 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkSVGUse_DEFINED
+#define SkSVGUse_DEFINED
+
+#include "modules/svg/include/SkSVGTransformableNode.h"
+#include "modules/svg/include/SkSVGTypes.h"
+
+/**
+ * Implements support for <use> (reference) elements.
+ * (https://www.w3.org/TR/SVG11/struct.html#UseElement)
+ */
+class SkSVGUse final : public SkSVGTransformableNode {
+public:
+    ~SkSVGUse() override = default;
+
+    static sk_sp<SkSVGUse> Make() { return sk_sp<SkSVGUse>(new SkSVGUse()); }
+
+    void appendChild(sk_sp<SkSVGNode>) override;
+
+    void setHref(const SkSVGStringType&);
+    void setX(const SkSVGLength&);
+    void setY(const SkSVGLength&);
+
+protected:
+    void onSetAttribute(SkSVGAttribute, const SkSVGValue&) override;
+
+    bool onPrepareToRender(SkSVGRenderContext*) const override;
+    void onRender(const SkSVGRenderContext&) const override;
+    SkPath onAsPath(const SkSVGRenderContext&) const override;
+
+private:
+    SkSVGUse();
+
+    SkSVGStringType    fHref;
+    SkSVGLength        fX = SkSVGLength(0);
+    SkSVGLength        fY = SkSVGLength(0);
+
+    using INHERITED = SkSVGTransformableNode;
+};
+
+#endif // SkSVGUse_DEFINED
diff --git a/modules/svg/include/SkSVGValue.h b/modules/svg/include/SkSVGValue.h
new file mode 100644
index 0000000..7b74cd0
--- /dev/null
+++ b/modules/svg/include/SkSVGValue.h
@@ -0,0 +1,97 @@
+/*
+ * Copyright 2016 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkSVGValue_DEFINED
+#define SkSVGValue_DEFINED
+
+#include "include/core/SkColor.h"
+#include "include/core/SkMatrix.h"
+#include "include/core/SkPath.h"
+#include "include/core/SkTypes.h"
+#include "include/private/SkNoncopyable.h"
+#include "modules/svg/include/SkSVGTypes.h"
+
+class SkSVGValue : public SkNoncopyable {
+public:
+    enum class Type {
+        kClip,
+        kColor,
+        kDashArray,
+        kFillRule,
+        kLength,
+        kLineCap,
+        kLineJoin,
+        kNumber,
+        kPaint,
+        kPath,
+        kPoints,
+        kSpreadMethod,
+        kStopColor,
+        kString,
+        kTransform,
+        kViewBox,
+        kVisibility,
+    };
+
+    Type type() const { return fType; }
+
+    template <typename T>
+    const T* as() const {
+        return fType == T::TYPE ? static_cast<const T*>(this) : nullptr;
+    }
+
+protected:
+    SkSVGValue(Type t) : fType(t) { }
+
+private:
+    Type fType;
+
+    using INHERITED = SkNoncopyable;
+};
+
+template <typename T, SkSVGValue::Type ValueType>
+class SkSVGWrapperValue final : public SkSVGValue {
+public:
+    static constexpr Type TYPE = ValueType;
+
+    explicit SkSVGWrapperValue(const T& v)
+        : INHERITED(ValueType)
+        , fWrappedValue(v) { }
+
+    operator const T&() const { return fWrappedValue; }
+    const T* operator->() const { return &fWrappedValue; }
+
+private:
+    // Stack-only
+    void* operator new(size_t) = delete;
+    void* operator new(size_t, void*) = delete;
+
+    const T& fWrappedValue;
+
+    using INHERITED = SkSVGValue;
+};
+
+using SkSVGClipValue         = SkSVGWrapperValue<SkSVGClip         , SkSVGValue::Type::kClip      >;
+using SkSVGColorValue        = SkSVGWrapperValue<SkSVGColorType    , SkSVGValue::Type::kColor     >;
+using SkSVGFillRuleValue     = SkSVGWrapperValue<SkSVGFillRule     , SkSVGValue::Type::kFillRule  >;
+using SkSVGLengthValue       = SkSVGWrapperValue<SkSVGLength       , SkSVGValue::Type::kLength    >;
+using SkSVGPathValue         = SkSVGWrapperValue<SkPath            , SkSVGValue::Type::kPath      >;
+using SkSVGTransformValue    = SkSVGWrapperValue<SkSVGTransformType, SkSVGValue::Type::kTransform >;
+using SkSVGViewBoxValue      = SkSVGWrapperValue<SkSVGViewBoxType  , SkSVGValue::Type::kViewBox   >;
+using SkSVGPaintValue        = SkSVGWrapperValue<SkSVGPaint        , SkSVGValue::Type::kPaint     >;
+using SkSVGLineCapValue      = SkSVGWrapperValue<SkSVGLineCap      , SkSVGValue::Type::kLineCap   >;
+using SkSVGLineJoinValue     = SkSVGWrapperValue<SkSVGLineJoin     , SkSVGValue::Type::kLineJoin  >;
+using SkSVGNumberValue       = SkSVGWrapperValue<SkSVGNumberType   , SkSVGValue::Type::kNumber    >;
+using SkSVGPointsValue       = SkSVGWrapperValue<SkSVGPointsType   , SkSVGValue::Type::kPoints    >;
+using SkSVGStringValue       = SkSVGWrapperValue<SkSVGStringType   , SkSVGValue::Type::kString    >;
+using SkSVGSpreadMethodValue = SkSVGWrapperValue<SkSVGSpreadMethod ,
+                                                 SkSVGValue::Type::kSpreadMethod>;
+using SkSVGStopColorValue    = SkSVGWrapperValue<SkSVGStopColor    , SkSVGValue::Type::kStopColor >;
+using SkSVGVisibilityValue   = SkSVGWrapperValue<SkSVGVisibility   , SkSVGValue::Type::kVisibility>;
+using SkSVGDashArrayValue    = SkSVGWrapperValue<SkSVGDashArray    , SkSVGValue::Type::kDashArray >;
+
+#endif // SkSVGValue_DEFINED
diff --git a/experimental/svg/model/SkSVGAttribute.cpp b/modules/svg/src/SkSVGAttribute.cpp
similarity index 95%
rename from experimental/svg/model/SkSVGAttribute.cpp
rename to modules/svg/src/SkSVGAttribute.cpp
index 00539fe..5bdb65b 100644
--- a/experimental/svg/model/SkSVGAttribute.cpp
+++ b/modules/svg/src/SkSVGAttribute.cpp
@@ -5,7 +5,7 @@
  * found in the LICENSE file.
  */
 
-#include "experimental/svg/model/SkSVGAttribute.h"
+#include "modules/svg/include/SkSVGAttribute.h"
 
 SkSVGPresentationAttributes SkSVGPresentationAttributes::MakeInitial() {
     SkSVGPresentationAttributes result;
diff --git a/experimental/svg/model/SkSVGAttributeParser.cpp b/modules/svg/src/SkSVGAttributeParser.cpp
similarity index 99%
rename from experimental/svg/model/SkSVGAttributeParser.cpp
rename to modules/svg/src/SkSVGAttributeParser.cpp
index 4661500..3ecd920 100644
--- a/experimental/svg/model/SkSVGAttributeParser.cpp
+++ b/modules/svg/src/SkSVGAttributeParser.cpp
@@ -5,9 +5,9 @@
  * found in the LICENSE file.
  */
 
-#include "experimental/svg/model/SkSVGAttributeParser.h"
-#include "experimental/svg/model/SkSVGTypes.h"
 #include "include/utils/SkParse.h"
+#include "modules/svg/include/SkSVGAttributeParser.h"
+#include "modules/svg/include/SkSVGTypes.h"
 
 namespace {
 
diff --git a/experimental/svg/model/SkSVGCircle.cpp b/modules/svg/src/SkSVGCircle.cpp
similarity index 92%
rename from experimental/svg/model/SkSVGCircle.cpp
rename to modules/svg/src/SkSVGCircle.cpp
index 196758f..6b25f09 100644
--- a/experimental/svg/model/SkSVGCircle.cpp
+++ b/modules/svg/src/SkSVGCircle.cpp
@@ -5,10 +5,10 @@
  * found in the LICENSE file.
  */
 
-#include "experimental/svg/model/SkSVGCircle.h"
-#include "experimental/svg/model/SkSVGRenderContext.h"
-#include "experimental/svg/model/SkSVGValue.h"
 #include "include/core/SkCanvas.h"
+#include "modules/svg/include/SkSVGCircle.h"
+#include "modules/svg/include/SkSVGRenderContext.h"
+#include "modules/svg/include/SkSVGValue.h"
 
 SkSVGCircle::SkSVGCircle() : INHERITED(SkSVGTag::kCircle) {}
 
diff --git a/experimental/svg/model/SkSVGClipPath.cpp b/modules/svg/src/SkSVGClipPath.cpp
similarity index 80%
rename from experimental/svg/model/SkSVGClipPath.cpp
rename to modules/svg/src/SkSVGClipPath.cpp
index face942..71d00b3 100644
--- a/experimental/svg/model/SkSVGClipPath.cpp
+++ b/modules/svg/src/SkSVGClipPath.cpp
@@ -5,6 +5,6 @@
  * found in the LICENSE file.
  */
 
-#include "experimental/svg/model/SkSVGClipPath.h"
+#include "modules/svg/include/SkSVGClipPath.h"
 
 SkSVGClipPath::SkSVGClipPath() : INHERITED(SkSVGTag::kClipPath) {}
diff --git a/experimental/svg/model/SkSVGContainer.cpp b/modules/svg/src/SkSVGContainer.cpp
similarity index 94%
rename from experimental/svg/model/SkSVGContainer.cpp
rename to modules/svg/src/SkSVGContainer.cpp
index aca4e8d..961194c 100644
--- a/experimental/svg/model/SkSVGContainer.cpp
+++ b/modules/svg/src/SkSVGContainer.cpp
@@ -5,7 +5,7 @@
  * found in the LICENSE file.
  */
 
-#include "experimental/svg/model/SkSVGContainer.h"
+#include "modules/svg/include/SkSVGContainer.h"
 
 #include "include/core/SkPath.h"
 #include "include/pathops/SkPathOps.h"
diff --git a/experimental/svg/model/SkSVGDOM.cpp b/modules/svg/src/SkSVGDOM.cpp
similarity index 94%
rename from experimental/svg/model/SkSVGDOM.cpp
rename to modules/svg/src/SkSVGDOM.cpp
index f29e655..c833a6a 100644
--- a/experimental/svg/model/SkSVGDOM.cpp
+++ b/modules/svg/src/SkSVGDOM.cpp
@@ -5,32 +5,32 @@
  * found in the LICENSE file.
  */
 
-#include "experimental/svg/model/SkSVGAttributeParser.h"
-#include "experimental/svg/model/SkSVGCircle.h"
-#include "experimental/svg/model/SkSVGClipPath.h"
-#include "experimental/svg/model/SkSVGDOM.h"
-#include "experimental/svg/model/SkSVGDefs.h"
-#include "experimental/svg/model/SkSVGEllipse.h"
-#include "experimental/svg/model/SkSVGG.h"
-#include "experimental/svg/model/SkSVGLine.h"
-#include "experimental/svg/model/SkSVGLinearGradient.h"
-#include "experimental/svg/model/SkSVGNode.h"
-#include "experimental/svg/model/SkSVGPath.h"
-#include "experimental/svg/model/SkSVGPattern.h"
-#include "experimental/svg/model/SkSVGPoly.h"
-#include "experimental/svg/model/SkSVGRadialGradient.h"
-#include "experimental/svg/model/SkSVGRect.h"
-#include "experimental/svg/model/SkSVGRenderContext.h"
-#include "experimental/svg/model/SkSVGSVG.h"
-#include "experimental/svg/model/SkSVGStop.h"
-#include "experimental/svg/model/SkSVGText.h"
-#include "experimental/svg/model/SkSVGTypes.h"
-#include "experimental/svg/model/SkSVGUse.h"
-#include "experimental/svg/model/SkSVGValue.h"
 #include "include/core/SkCanvas.h"
 #include "include/core/SkString.h"
 #include "include/private/SkTo.h"
 #include "include/utils/SkParsePath.h"
+#include "modules/svg/include/SkSVGAttributeParser.h"
+#include "modules/svg/include/SkSVGCircle.h"
+#include "modules/svg/include/SkSVGClipPath.h"
+#include "modules/svg/include/SkSVGDOM.h"
+#include "modules/svg/include/SkSVGDefs.h"
+#include "modules/svg/include/SkSVGEllipse.h"
+#include "modules/svg/include/SkSVGG.h"
+#include "modules/svg/include/SkSVGLine.h"
+#include "modules/svg/include/SkSVGLinearGradient.h"
+#include "modules/svg/include/SkSVGNode.h"
+#include "modules/svg/include/SkSVGPath.h"
+#include "modules/svg/include/SkSVGPattern.h"
+#include "modules/svg/include/SkSVGPoly.h"
+#include "modules/svg/include/SkSVGRadialGradient.h"
+#include "modules/svg/include/SkSVGRect.h"
+#include "modules/svg/include/SkSVGRenderContext.h"
+#include "modules/svg/include/SkSVGSVG.h"
+#include "modules/svg/include/SkSVGStop.h"
+#include "modules/svg/include/SkSVGText.h"
+#include "modules/svg/include/SkSVGTypes.h"
+#include "modules/svg/include/SkSVGUse.h"
+#include "modules/svg/include/SkSVGValue.h"
 #include "src/core/SkTSearch.h"
 #include "src/xml/SkDOM.h"
 
diff --git a/experimental/svg/model/SkSVGEllipse.cpp b/modules/svg/src/SkSVGEllipse.cpp
similarity index 93%
rename from experimental/svg/model/SkSVGEllipse.cpp
rename to modules/svg/src/SkSVGEllipse.cpp
index 5300bf6..2c8ef0e 100644
--- a/experimental/svg/model/SkSVGEllipse.cpp
+++ b/modules/svg/src/SkSVGEllipse.cpp
@@ -5,10 +5,10 @@
  * found in the LICENSE file.
  */
 
-#include "experimental/svg/model/SkSVGEllipse.h"
-#include "experimental/svg/model/SkSVGRenderContext.h"
-#include "experimental/svg/model/SkSVGValue.h"
 #include "include/core/SkCanvas.h"
+#include "modules/svg/include/SkSVGEllipse.h"
+#include "modules/svg/include/SkSVGRenderContext.h"
+#include "modules/svg/include/SkSVGValue.h"
 
 SkSVGEllipse::SkSVGEllipse() : INHERITED(SkSVGTag::kEllipse) {}
 
diff --git a/experimental/svg/model/SkSVGGradient.cpp b/modules/svg/src/SkSVGGradient.cpp
similarity index 95%
rename from experimental/svg/model/SkSVGGradient.cpp
rename to modules/svg/src/SkSVGGradient.cpp
index c9ac907..b868f11 100644
--- a/experimental/svg/model/SkSVGGradient.cpp
+++ b/modules/svg/src/SkSVGGradient.cpp
@@ -5,10 +5,10 @@
  * found in the LICENSE file.
  */
 
-#include "experimental/svg/model/SkSVGGradient.h"
-#include "experimental/svg/model/SkSVGRenderContext.h"
-#include "experimental/svg/model/SkSVGStop.h"
-#include "experimental/svg/model/SkSVGValue.h"
+#include "modules/svg/include/SkSVGGradient.h"
+#include "modules/svg/include/SkSVGRenderContext.h"
+#include "modules/svg/include/SkSVGStop.h"
+#include "modules/svg/include/SkSVGValue.h"
 
 void SkSVGGradient::setHref(const SkSVGStringType& href) {
     fHref = std::move(href);
diff --git a/experimental/svg/model/SkSVGLine.cpp b/modules/svg/src/SkSVGLine.cpp
similarity index 93%
rename from experimental/svg/model/SkSVGLine.cpp
rename to modules/svg/src/SkSVGLine.cpp
index 0bb2510..6f8ce10 100644
--- a/experimental/svg/model/SkSVGLine.cpp
+++ b/modules/svg/src/SkSVGLine.cpp
@@ -5,10 +5,10 @@
  * found in the LICENSE file.
  */
 
-#include "experimental/svg/model/SkSVGLine.h"
-#include "experimental/svg/model/SkSVGRenderContext.h"
-#include "experimental/svg/model/SkSVGValue.h"
 #include "include/core/SkCanvas.h"
+#include "modules/svg/include/SkSVGLine.h"
+#include "modules/svg/include/SkSVGRenderContext.h"
+#include "modules/svg/include/SkSVGValue.h"
 
 SkSVGLine::SkSVGLine() : INHERITED(SkSVGTag::kLine) {}
 
diff --git a/experimental/svg/model/SkSVGLinearGradient.cpp b/modules/svg/src/SkSVGLinearGradient.cpp
similarity index 92%
rename from experimental/svg/model/SkSVGLinearGradient.cpp
rename to modules/svg/src/SkSVGLinearGradient.cpp
index 59edc84..436428d 100644
--- a/experimental/svg/model/SkSVGLinearGradient.cpp
+++ b/modules/svg/src/SkSVGLinearGradient.cpp
@@ -5,10 +5,10 @@
  * found in the LICENSE file.
  */
 
-#include "experimental/svg/model/SkSVGLinearGradient.h"
-#include "experimental/svg/model/SkSVGRenderContext.h"
-#include "experimental/svg/model/SkSVGValue.h"
 #include "include/effects/SkGradientShader.h"
+#include "modules/svg/include/SkSVGLinearGradient.h"
+#include "modules/svg/include/SkSVGRenderContext.h"
+#include "modules/svg/include/SkSVGValue.h"
 
 SkSVGLinearGradient::SkSVGLinearGradient() : INHERITED(SkSVGTag::kLinearGradient) {}
 
diff --git a/experimental/svg/model/SkSVGNode.cpp b/modules/svg/src/SkSVGNode.cpp
similarity index 97%
rename from experimental/svg/model/SkSVGNode.cpp
rename to modules/svg/src/SkSVGNode.cpp
index eeccd2e..ea19342 100644
--- a/experimental/svg/model/SkSVGNode.cpp
+++ b/modules/svg/src/SkSVGNode.cpp
@@ -5,12 +5,12 @@
  * found in the LICENSE file.
  */
 
-#include "experimental/svg/model/SkSVGNode.h"
-#include "experimental/svg/model/SkSVGRenderContext.h"
-#include "experimental/svg/model/SkSVGValue.h"
 #include "include/core/SkCanvas.h"
 #include "include/core/SkMatrix.h"
 #include "include/pathops/SkPathOps.h"
+#include "modules/svg/include/SkSVGNode.h"
+#include "modules/svg/include/SkSVGRenderContext.h"
+#include "modules/svg/include/SkSVGValue.h"
 #include "src/core/SkTLazy.h"
 
 SkSVGNode::SkSVGNode(SkSVGTag t) : fTag(t) { }
diff --git a/experimental/svg/model/SkSVGPath.cpp b/modules/svg/src/SkSVGPath.cpp
similarity index 88%
rename from experimental/svg/model/SkSVGPath.cpp
rename to modules/svg/src/SkSVGPath.cpp
index 330bde0..f839379 100644
--- a/experimental/svg/model/SkSVGPath.cpp
+++ b/modules/svg/src/SkSVGPath.cpp
@@ -5,11 +5,11 @@
  * found in the LICENSE file.
  */
 
-#include "experimental/svg/model/SkSVGPath.h"
-#include "experimental/svg/model/SkSVGRenderContext.h"
-#include "experimental/svg/model/SkSVGValue.h"
 #include "include/core/SkCanvas.h"
 #include "include/core/SkPaint.h"
+#include "modules/svg/include/SkSVGPath.h"
+#include "modules/svg/include/SkSVGRenderContext.h"
+#include "modules/svg/include/SkSVGValue.h"
 
 SkSVGPath::SkSVGPath() : INHERITED(SkSVGTag::kPath) { }
 
diff --git a/experimental/svg/model/SkSVGPattern.cpp b/modules/svg/src/SkSVGPattern.cpp
similarity index 96%
rename from experimental/svg/model/SkSVGPattern.cpp
rename to modules/svg/src/SkSVGPattern.cpp
index 6128458..64e01c6 100644
--- a/experimental/svg/model/SkSVGPattern.cpp
+++ b/modules/svg/src/SkSVGPattern.cpp
@@ -5,12 +5,12 @@
  * found in the LICENSE file.
  */
 
-#include "experimental/svg/model/SkSVGPattern.h"
+#include "modules/svg/include/SkSVGPattern.h"
 
-#include "experimental/svg/model/SkSVGRenderContext.h"
-#include "experimental/svg/model/SkSVGValue.h"
 #include "include/core/SkPictureRecorder.h"
 #include "include/core/SkShader.h"
+#include "modules/svg/include/SkSVGRenderContext.h"
+#include "modules/svg/include/SkSVGValue.h"
 
 SkSVGPattern::SkSVGPattern() : INHERITED(SkSVGTag::kPattern) {}
 
diff --git a/experimental/svg/model/SkSVGPoly.cpp b/modules/svg/src/SkSVGPoly.cpp
similarity index 90%
rename from experimental/svg/model/SkSVGPoly.cpp
rename to modules/svg/src/SkSVGPoly.cpp
index dfca38a..0aac9e6 100644
--- a/experimental/svg/model/SkSVGPoly.cpp
+++ b/modules/svg/src/SkSVGPoly.cpp
@@ -5,10 +5,10 @@
  * found in the LICENSE file.
  */
 
-#include "experimental/svg/model/SkSVGPoly.h"
-#include "experimental/svg/model/SkSVGRenderContext.h"
-#include "experimental/svg/model/SkSVGValue.h"
 #include "include/core/SkCanvas.h"
+#include "modules/svg/include/SkSVGPoly.h"
+#include "modules/svg/include/SkSVGRenderContext.h"
+#include "modules/svg/include/SkSVGValue.h"
 #include "src/core/SkTLazy.h"
 
 SkSVGPoly::SkSVGPoly(SkSVGTag t) : INHERITED(t) {}
diff --git a/experimental/svg/model/SkSVGRadialGradient.cpp b/modules/svg/src/SkSVGRadialGradient.cpp
similarity index 93%
rename from experimental/svg/model/SkSVGRadialGradient.cpp
rename to modules/svg/src/SkSVGRadialGradient.cpp
index 8b82204..4d311a6 100644
--- a/experimental/svg/model/SkSVGRadialGradient.cpp
+++ b/modules/svg/src/SkSVGRadialGradient.cpp
@@ -5,10 +5,10 @@
  * found in the LICENSE file.
  */
 
-#include "experimental/svg/model/SkSVGRadialGradient.h"
-#include "experimental/svg/model/SkSVGRenderContext.h"
-#include "experimental/svg/model/SkSVGValue.h"
 #include "include/effects/SkGradientShader.h"
+#include "modules/svg/include/SkSVGRadialGradient.h"
+#include "modules/svg/include/SkSVGRenderContext.h"
+#include "modules/svg/include/SkSVGValue.h"
 
 SkSVGRadialGradient::SkSVGRadialGradient() : INHERITED(SkSVGTag::kRadialGradient) {}
 
diff --git a/experimental/svg/model/SkSVGRect.cpp b/modules/svg/src/SkSVGRect.cpp
similarity index 93%
rename from experimental/svg/model/SkSVGRect.cpp
rename to modules/svg/src/SkSVGRect.cpp
index 0d99946..9f5e3a9 100644
--- a/experimental/svg/model/SkSVGRect.cpp
+++ b/modules/svg/src/SkSVGRect.cpp
@@ -5,11 +5,11 @@
  * found in the LICENSE file.
  */
 
-#include "experimental/svg/model/SkSVGRect.h"
-#include "experimental/svg/model/SkSVGRenderContext.h"
-#include "experimental/svg/model/SkSVGValue.h"
 #include "include/core/SkCanvas.h"
 #include "include/core/SkRect.h"
+#include "modules/svg/include/SkSVGRect.h"
+#include "modules/svg/include/SkSVGRenderContext.h"
+#include "modules/svg/include/SkSVGValue.h"
 
 SkSVGRect::SkSVGRect() : INHERITED(SkSVGTag::kRect) {}
 
diff --git a/experimental/svg/model/SkSVGRenderContext.cpp b/modules/svg/src/SkSVGRenderContext.cpp
similarity index 98%
rename from experimental/svg/model/SkSVGRenderContext.cpp
rename to modules/svg/src/SkSVGRenderContext.cpp
index 15787bc..4607f67 100644
--- a/experimental/svg/model/SkSVGRenderContext.cpp
+++ b/modules/svg/src/SkSVGRenderContext.cpp
@@ -5,15 +5,15 @@
  * found in the LICENSE file.
  */
 
-#include "experimental/svg/model/SkSVGRenderContext.h"
+#include "modules/svg/include/SkSVGRenderContext.h"
 
-#include "experimental/svg/model/SkSVGAttribute.h"
-#include "experimental/svg/model/SkSVGNode.h"
-#include "experimental/svg/model/SkSVGTypes.h"
 #include "include/core/SkCanvas.h"
 #include "include/core/SkPath.h"
 #include "include/effects/SkDashPathEffect.h"
 #include "include/private/SkTo.h"
+#include "modules/svg/include/SkSVGAttribute.h"
+#include "modules/svg/include/SkSVGNode.h"
+#include "modules/svg/include/SkSVGTypes.h"
 
 namespace {
 
diff --git a/experimental/svg/model/SkSVGSVG.cpp b/modules/svg/src/SkSVGSVG.cpp
similarity index 94%
rename from experimental/svg/model/SkSVGSVG.cpp
rename to modules/svg/src/SkSVGSVG.cpp
index e4fecfa..2542d2b 100644
--- a/experimental/svg/model/SkSVGSVG.cpp
+++ b/modules/svg/src/SkSVGSVG.cpp
@@ -5,10 +5,10 @@
  * found in the LICENSE file.
  */
 
-#include "experimental/svg/model/SkSVGRenderContext.h"
-#include "experimental/svg/model/SkSVGSVG.h"
-#include "experimental/svg/model/SkSVGValue.h"
 #include "include/core/SkCanvas.h"
+#include "modules/svg/include/SkSVGRenderContext.h"
+#include "modules/svg/include/SkSVGSVG.h"
+#include "modules/svg/include/SkSVGValue.h"
 
 SkSVGSVG::SkSVGSVG() : INHERITED(SkSVGTag::kSvg) { }
 
diff --git a/experimental/svg/model/SkSVGShape.cpp b/modules/svg/src/SkSVGShape.cpp
similarity index 88%
rename from experimental/svg/model/SkSVGShape.cpp
rename to modules/svg/src/SkSVGShape.cpp
index 62bc789..327acfd 100644
--- a/experimental/svg/model/SkSVGShape.cpp
+++ b/modules/svg/src/SkSVGShape.cpp
@@ -5,8 +5,8 @@
  * found in the LICENSE file.
  */
 
-#include "experimental/svg/model/SkSVGRenderContext.h"
-#include "experimental/svg/model/SkSVGShape.h"
+#include "modules/svg/include/SkSVGRenderContext.h"
+#include "modules/svg/include/SkSVGShape.h"
 
 SkSVGShape::SkSVGShape(SkSVGTag t) : INHERITED(t) {}
 
diff --git a/experimental/svg/model/SkSVGStop.cpp b/modules/svg/src/SkSVGStop.cpp
similarity index 88%
rename from experimental/svg/model/SkSVGStop.cpp
rename to modules/svg/src/SkSVGStop.cpp
index 67e9794..4705581 100644
--- a/experimental/svg/model/SkSVGStop.cpp
+++ b/modules/svg/src/SkSVGStop.cpp
@@ -5,9 +5,9 @@
  * found in the LICENSE file.
  */
 
-#include "experimental/svg/model/SkSVGRenderContext.h"
-#include "experimental/svg/model/SkSVGStop.h"
-#include "experimental/svg/model/SkSVGValue.h"
+#include "modules/svg/include/SkSVGRenderContext.h"
+#include "modules/svg/include/SkSVGStop.h"
+#include "modules/svg/include/SkSVGValue.h"
 
 SkSVGStop::SkSVGStop() : INHERITED(SkSVGTag::kStop) {}
 
diff --git a/experimental/svg/model/SkSVGText.cpp b/modules/svg/src/SkSVGText.cpp
similarity index 95%
rename from experimental/svg/model/SkSVGText.cpp
rename to modules/svg/src/SkSVGText.cpp
index d54c870..b2d8704 100644
--- a/experimental/svg/model/SkSVGText.cpp
+++ b/modules/svg/src/SkSVGText.cpp
@@ -5,13 +5,13 @@
  * found in the LICENSE file.
  */
 
-#include "experimental/svg/model/SkSVGText.h"
+#include "modules/svg/include/SkSVGText.h"
 
-#include "experimental/svg/model/SkSVGRenderContext.h"
-#include "experimental/svg/model/SkSVGValue.h"
 #include "include/core/SkCanvas.h"
 #include "include/core/SkFontStyle.h"
 #include "include/core/SkString.h"
+#include "modules/svg/include/SkSVGRenderContext.h"
+#include "modules/svg/include/SkSVGValue.h"
 
 SkSVGText::SkSVGText() : INHERITED(SkSVGTag::kText) {}
 
diff --git a/experimental/svg/model/SkSVGTransformableNode.cpp b/modules/svg/src/SkSVGTransformableNode.cpp
similarity index 86%
rename from experimental/svg/model/SkSVGTransformableNode.cpp
rename to modules/svg/src/SkSVGTransformableNode.cpp
index 9eeb7ea..f76f2c4 100644
--- a/experimental/svg/model/SkSVGTransformableNode.cpp
+++ b/modules/svg/src/SkSVGTransformableNode.cpp
@@ -5,10 +5,10 @@
  * found in the LICENSE file.
  */
 
-#include "experimental/svg/model/SkSVGRenderContext.h"
-#include "experimental/svg/model/SkSVGTransformableNode.h"
-#include "experimental/svg/model/SkSVGValue.h"
 #include "include/core/SkCanvas.h"
+#include "modules/svg/include/SkSVGRenderContext.h"
+#include "modules/svg/include/SkSVGTransformableNode.h"
+#include "modules/svg/include/SkSVGValue.h"
 
 SkSVGTransformableNode::SkSVGTransformableNode(SkSVGTag tag)
     : INHERITED(tag)
diff --git a/experimental/svg/model/SkSVGUse.cpp b/modules/svg/src/SkSVGUse.cpp
similarity index 92%
rename from experimental/svg/model/SkSVGUse.cpp
rename to modules/svg/src/SkSVGUse.cpp
index 73972c7..ea510ea 100644
--- a/experimental/svg/model/SkSVGUse.cpp
+++ b/modules/svg/src/SkSVGUse.cpp
@@ -5,11 +5,11 @@
  * found in the LICENSE file.
  */
 
-#include "experimental/svg/model/SkSVGUse.h"
+#include "modules/svg/include/SkSVGUse.h"
 
-#include "experimental/svg/model/SkSVGRenderContext.h"
-#include "experimental/svg/model/SkSVGValue.h"
 #include "include/core/SkCanvas.h"
+#include "modules/svg/include/SkSVGRenderContext.h"
+#include "modules/svg/include/SkSVGValue.h"
 
 SkSVGUse::SkSVGUse() : INHERITED(SkSVGTag::kUse) {}
 
diff --git a/experimental/svg/model/SkSVGValue.cpp b/modules/svg/src/SkSVGValue.cpp
similarity index 100%
rename from experimental/svg/model/SkSVGValue.cpp
rename to modules/svg/src/SkSVGValue.cpp
diff --git a/modules/svg/svg.gni b/modules/svg/svg.gni
new file mode 100644
index 0000000..df70da8
--- /dev/null
+++ b/modules/svg/svg.gni
@@ -0,0 +1,67 @@
+# Copyright 2020 Google Inc.
+#
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+# Things are easiest for everyone if these source paths are absolute.
+_src = get_path_info("src", "abspath")
+_include = get_path_info("include", "abspath")
+
+skia_svg_public = [
+  "$_include/SkSVGAttribute.h",
+  "$_include/SkSVGAttributeParser.h",
+  "$_include/SkSVGCircle.h",
+  "$_include/SkSVGClipPath.h",
+  "$_include/SkSVGContainer.h",
+  "$_include/SkSVGDefs.h",
+  "$_include/SkSVGDOM.h",
+  "$_include/SkSVGEllipse.h",
+  "$_include/SkSVGG.h",
+  "$_include/SkSVGGradient.h",
+  "$_include/SkSVGHiddenContainer.h",
+  "$_include/SkSVGIDMapper.h",
+  "$_include/SkSVGLinearGradient.h",
+  "$_include/SkSVGLine.h",
+  "$_include/SkSVGNode.h",
+  "$_include/SkSVGPath.h",
+  "$_include/SkSVGPattern.h",
+  "$_include/SkSVGPoly.h",
+  "$_include/SkSVGRadialGradient.h",
+  "$_include/SkSVGRect.h",
+  "$_include/SkSVGRenderContext.h",
+  "$_include/SkSVGShape.h",
+  "$_include/SkSVGStop.h",
+  "$_include/SkSVGSVG.h",
+  "$_include/SkSVGText.h",
+  "$_include/SkSVGTransformableNode.h",
+  "$_include/SkSVGTypes.h",
+  "$_include/SkSVGUse.h",
+  "$_include/SkSVGValue.h",
+]
+
+skia_svg_sources = [
+  "$_src/SkSVGAttribute.cpp",
+  "$_src/SkSVGAttributeParser.cpp",
+  "$_src/SkSVGCircle.cpp",
+  "$_src/SkSVGClipPath.cpp",
+  "$_src/SkSVGContainer.cpp",
+  "$_src/SkSVGDOM.cpp",
+  "$_src/SkSVGEllipse.cpp",
+  "$_src/SkSVGGradient.cpp",
+  "$_src/SkSVGLine.cpp",
+  "$_src/SkSVGLinearGradient.cpp",
+  "$_src/SkSVGNode.cpp",
+  "$_src/SkSVGPath.cpp",
+  "$_src/SkSVGPattern.cpp",
+  "$_src/SkSVGPoly.cpp",
+  "$_src/SkSVGRadialGradient.cpp",
+  "$_src/SkSVGRect.cpp",
+  "$_src/SkSVGRenderContext.cpp",
+  "$_src/SkSVGSVG.cpp",
+  "$_src/SkSVGShape.cpp",
+  "$_src/SkSVGStop.cpp",
+  "$_src/SkSVGText.cpp",
+  "$_src/SkSVGTransformableNode.cpp",
+  "$_src/SkSVGUse.cpp",
+  "$_src/SkSVGValue.cpp",
+]
diff --git a/experimental/svg/utils/SvgTool.cpp b/modules/svg/utils/SvgTool.cpp
similarity index 97%
rename from experimental/svg/utils/SvgTool.cpp
rename to modules/svg/utils/SvgTool.cpp
index 34236f6..e78e686 100644
--- a/experimental/svg/utils/SvgTool.cpp
+++ b/modules/svg/utils/SvgTool.cpp
@@ -7,11 +7,11 @@
 
 #include <iostream>
 
-#include "experimental/svg/model/SkSVGDOM.h"
 #include "include/core/SkMatrix.h"
 #include "include/core/SkStream.h"
 #include "include/core/SkSurface.h"
 #include "include/encode/SkPngEncoder.h"
+#include "modules/svg/include/SkSVGDOM.h"
 #include "tools/flags/CommandLineFlags.h"
 
 static DEFINE_string2(input , i, nullptr, "Input SVG file.");
diff --git a/public.bzl b/public.bzl
index f6f99c1..19cf9fe 100644
--- a/public.bzl
+++ b/public.bzl
@@ -566,12 +566,13 @@
         "dm/*.h",
         "experimental/pipe/*.cpp",
         "experimental/pipe/*.h",
-        "experimental/svg/model/*.cpp",
-        "experimental/svg/model/*.h",
         "gm/*.cpp",
         "gm/*.h",
         "gm/verifiers/*.cpp",
         "gm/verifiers/*.h",
+        # TODO(fmalita): SVG sources should not be included here
+        "modules/svg/include/*.h",
+        "modules/svg/src/*.cpp",
         "src/utils/SkMultiPictureDocument.cpp",
         "src/xml/*.cpp",
         "tests/*.cpp",
@@ -987,17 +988,21 @@
 ################################################################################
 
 def svg_lib_hdrs():
-    return native.glob(["experimental/svg/model/*.h"])
+    return native.glob([
+        # transitional headers, to be removed
+        "experimental/svg/model/*.h",
+        "modules/svg/include/*.h",
+    ])
 
 def svg_lib_srcs():
-    return native.glob(["experimental/svg/model/*.cpp"])
+    return native.glob(["modules/svg/src/*.cpp"])
 
 ################################################################################
 ## svg_tool
 ################################################################################
 
 SVG_TOOL_SRCS = [
-    "experimental/svg/utils/SvgTool.cpp",
+    "modules/svg/utils/SvgTool.cpp",
     # TODO(benjaminwagner): Add "flags" target.
     "tools/flags/CommandLineFlags.cpp",
     "tools/flags/CommandLineFlags.h",
diff --git a/samplecode/SampleCowboy.cpp b/samplecode/SampleCowboy.cpp
index 4925508..3cfb82d 100644
--- a/samplecode/SampleCowboy.cpp
+++ b/samplecode/SampleCowboy.cpp
@@ -9,10 +9,10 @@
 
 #ifdef SK_XML
 
-#include "experimental/svg/model/SkSVGDOM.h"
 #include "include/core/SkCanvas.h"
 #include "include/core/SkRect.h"
 #include "include/core/SkStream.h"
+#include "modules/svg/include/SkSVGDOM.h"
 #include "samplecode/Sample.h"
 #include "src/core/SkOSFile.h"
 #include "src/utils/SkOSPath.h"
diff --git a/samplecode/SampleSVGFile.cpp b/samplecode/SampleSVGFile.cpp
index 6069fae..c295e3a 100644
--- a/samplecode/SampleSVGFile.cpp
+++ b/samplecode/SampleSVGFile.cpp
@@ -9,9 +9,9 @@
 
 #ifdef SK_XML
 
-#include "experimental/svg/model/SkSVGDOM.h"
 #include "include/core/SkCanvas.h"
 #include "include/core/SkStream.h"
+#include "modules/svg/include/SkSVGDOM.h"
 #include "samplecode/Sample.h"
 #include "src/core/SkOSFile.h"
 #include "src/utils/SkOSPath.h"
diff --git a/tools/fm/fm.cpp b/tools/fm/fm.cpp
index cf20fab..203c604 100644
--- a/tools/fm/fm.cpp
+++ b/tools/fm/fm.cpp
@@ -1,7 +1,6 @@
 // Copyright 2019 Google LLC.
 // Use of this source code is governed by a BSD-style license that can be found in the LICENSE file.
 
-#include "experimental/svg/model/SkSVGDOM.h"
 #include "gm/gm.h"
 #include "include/codec/SkCodec.h"
 #include "include/core/SkCanvas.h"
@@ -13,6 +12,7 @@
 #include "include/gpu/GrContextOptions.h"
 #include "include/gpu/GrDirectContext.h"
 #include "include/private/SkTHash.h"
+#include "modules/svg/include/SkSVGDOM.h"
 #include "src/core/SkColorSpacePriv.h"
 #include "src/core/SkMD5.h"
 #include "src/core/SkOSFile.h"
diff --git a/tools/fonts/TestSVGTypeface.cpp b/tools/fonts/TestSVGTypeface.cpp
index 5c19493..72473a8 100644
--- a/tools/fonts/TestSVGTypeface.cpp
+++ b/tools/fonts/TestSVGTypeface.cpp
@@ -9,7 +9,6 @@
 
 #ifdef SK_XML
 
-#include "experimental/svg/model/SkSVGDOM.h"
 #include "include/core/SkBitmap.h"
 #include "include/core/SkCanvas.h"
 #include "include/core/SkColor.h"
@@ -30,6 +29,7 @@
 #include "include/private/SkTDArray.h"
 #include "include/private/SkTemplates.h"
 #include "include/utils/SkNoDrawCanvas.h"
+#include "modules/svg/include/SkSVGDOM.h"
 #include "src/core/SkAdvancedTypefaceMetrics.h"
 #include "src/core/SkFontDescriptor.h"
 #include "src/core/SkFontPriv.h"
diff --git a/tools/rewrite_includes.py b/tools/rewrite_includes.py
index 6ebd460..5ae8ddb 100755
--- a/tools/rewrite_includes.py
+++ b/tools/rewrite_includes.py
@@ -39,7 +39,8 @@
 # Don't count our local Vulkan headers as Skia headers;
 # we don't want #include <vulkan/vulkan_foo.h> rewritten to point to them.
 # Nor do we care about things in node_modules, used by *Kits.
-ignorelist = ['include/third_party/vulkan', 'node_modules']
+# Also ignore transitional SVG headers.
+ignorelist = ['include/third_party/vulkan', 'node_modules', 'experimental/svg/model']
 
 assert '/' in [os.sep, os.altsep]
 def fix_path(p):
diff --git a/tools/skpbench/skpbench.cpp b/tools/skpbench/skpbench.cpp
index 8300d34..afb55fe 100644
--- a/tools/skpbench/skpbench.cpp
+++ b/tools/skpbench/skpbench.cpp
@@ -34,7 +34,7 @@
 #include "tools/gpu/GrContextFactory.h"
 
 #ifdef SK_XML
-#include "experimental/svg/model/SkSVGDOM.h"
+#include "modules/svg/include/SkSVGDOM.h"
 #include "src/xml/SkDOM.h"
 #endif
 
diff --git a/tools/viewer/BisectSlide.cpp b/tools/viewer/BisectSlide.cpp
index fa2bed9..1f6deea 100644
--- a/tools/viewer/BisectSlide.cpp
+++ b/tools/viewer/BisectSlide.cpp
@@ -14,7 +14,7 @@
 #include <utility>
 
 #ifdef SK_XML
-#include "experimental/svg/model/SkSVGDOM.h"
+#include "modules/svg/include/SkSVGDOM.h"
 #include "src/xml/SkDOM.h"
 #endif
 
diff --git a/tools/viewer/SvgSlide.cpp b/tools/viewer/SvgSlide.cpp
index c420843..28bdb21 100644
--- a/tools/viewer/SvgSlide.cpp
+++ b/tools/viewer/SvgSlide.cpp
@@ -9,9 +9,9 @@
 
 #if defined(SK_XML)
 
-#include "experimental/svg/model/SkSVGDOM.h"
 #include "include/core/SkCanvas.h"
 #include "include/core/SkStream.h"
+#include "modules/svg/include/SkSVGDOM.h"
 
 SvgSlide::SvgSlide(const SkString& name, const SkString& path)
         : SvgSlide(name, SkStream::MakeFromFile(path.c_str())) {