[svg] Add several skeleton classes for filters

Added:

- SkSVGFilter: This corresponds to a <filter> element. Also added some
  of the attributes of this element.
- SkSVGFe: This will be the base class of all <fe*> elements.
- SkSVGFilterContext: This will hold the contextual mapping of string id
  -> image filter result, for constructing pipelines.

Bug: skia:10841
Change-Id: I15a29d39411a6255ab4e11f022baa10554b2bce6
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/330618
Commit-Queue: Tyler Denniston <tdenniston@google.com>
Reviewed-by: Florin Malita <fmalita@chromium.org>
diff --git a/modules/svg/include/SkSVGAttribute.h b/modules/svg/include/SkSVGAttribute.h
index dd806a3..1886d85 100644
--- a/modules/svg/include/SkSVGAttribute.h
+++ b/modules/svg/include/SkSVGAttribute.h
@@ -24,6 +24,7 @@
     kFillOpacity,
     kFillRule,
     kFilter,
+    kFilterUnits,
     kFontFamily,
     kFontSize,
     kFontStyle,
diff --git a/modules/svg/include/SkSVGFe.h b/modules/svg/include/SkSVGFe.h
new file mode 100644
index 0000000..4f8fbc4
--- /dev/null
+++ b/modules/svg/include/SkSVGFe.h
@@ -0,0 +1,35 @@
+/*
+ * 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 SkSVGFe_DEFINED
+#define SkSVGFe_DEFINED
+
+#include "modules/svg/include/SkSVGHiddenContainer.h"
+
+class SkImageFilter;
+class SkSVGFilterContext;
+
+class SkSVGFe : public SkSVGHiddenContainer {
+public:
+    ~SkSVGFe() override = default;
+
+    static bool IsFilterElement(const sk_sp<SkSVGNode>& node) { return false; }
+
+    sk_sp<SkImageFilter> makeImageFilter(const SkSVGRenderContext& ctx,
+                                         SkSVGFilterContext* fctx) const;
+
+protected:
+    explicit SkSVGFe(SkSVGTag t) : INHERITED(t) {}
+
+    virtual sk_sp<SkImageFilter> onMakeImageFilter(const SkSVGRenderContext&,
+                                                   const SkSVGFilterContext&) const = 0;
+
+private:
+    using INHERITED = SkSVGHiddenContainer;
+};
+
+#endif  // SkSVGFe_DEFINED
diff --git a/modules/svg/include/SkSVGFilter.h b/modules/svg/include/SkSVGFilter.h
new file mode 100644
index 0000000..2b1bf5f
--- /dev/null
+++ b/modules/svg/include/SkSVGFilter.h
@@ -0,0 +1,36 @@
+/*
+ * 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 SkSVGFilter_DEFINED
+#define SkSVGFilter_DEFINED
+
+#include "modules/svg/include/SkSVGHiddenContainer.h"
+#include "modules/svg/include/SkSVGTypes.h"
+
+class SkSVGFilter final : public SkSVGHiddenContainer {
+public:
+    ~SkSVGFilter() override = default;
+
+    static sk_sp<SkSVGFilter> Make() { return sk_sp<SkSVGFilter>(new SkSVGFilter()); }
+
+    SVG_ATTR(X, SkSVGLength, SkSVGLength(-10, SkSVGLength::Unit::kPercentage))
+    SVG_ATTR(Y, SkSVGLength, SkSVGLength(-10, SkSVGLength::Unit::kPercentage))
+    SVG_ATTR(Width, SkSVGLength, SkSVGLength(120, SkSVGLength::Unit::kPercentage))
+    SVG_ATTR(Height, SkSVGLength, SkSVGLength(120, SkSVGLength::Unit::kPercentage))
+    SVG_ATTR(FilterUnits,
+             SkSVGObjectBoundingBoxUnits,
+             SkSVGObjectBoundingBoxUnits(SkSVGObjectBoundingBoxUnits::Type::kObjectBoundingBox))
+
+private:
+    SkSVGFilter() : INHERITED(SkSVGTag::kFilter) {}
+
+    void onSetAttribute(SkSVGAttribute, const SkSVGValue&) override;
+
+    using INHERITED = SkSVGHiddenContainer;
+};
+
+#endif  // SkSVGFilter_DEFINED
diff --git a/modules/svg/include/SkSVGFilterContext.h b/modules/svg/include/SkSVGFilterContext.h
new file mode 100644
index 0000000..9077c63
--- /dev/null
+++ b/modules/svg/include/SkSVGFilterContext.h
@@ -0,0 +1,32 @@
+/*
+ * 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 SkSVGFilterContext_DEFINED
+#define SkSVGFilterContext_DEFINED
+
+#include "include/core/SkRect.h"
+#include "include/core/SkRefCnt.h"
+#include "include/private/SkTHash.h"
+
+class SkImageFilter;
+class SkPicture;
+class SkString;
+
+class SkSVGFilterContext {
+public:
+    SkSVGFilterContext(const SkRect& filterEffectsRegion)
+            : fFilterEffectsRegion(filterEffectsRegion) {}
+
+    sk_sp<SkImageFilter> findResultById(const SkString& id) const;
+
+    const SkRect& filterEffectsRegion() const { return fFilterEffectsRegion; }
+
+private:
+    SkRect fFilterEffectsRegion;
+};
+
+#endif  // SkSVGFilterContext_DEFINED
diff --git a/modules/svg/include/SkSVGNode.h b/modules/svg/include/SkSVGNode.h
index c532de9..e0aa24d 100644
--- a/modules/svg/include/SkSVGNode.h
+++ b/modules/svg/include/SkSVGNode.h
@@ -24,6 +24,7 @@
     kClipPath,
     kDefs,
     kEllipse,
+    kFilter,
     kG,
     kLine,
     kLinearGradient,
diff --git a/modules/svg/src/SkSVGDOM.cpp b/modules/svg/src/SkSVGDOM.cpp
index 9886563..2c3d1da 100644
--- a/modules/svg/src/SkSVGDOM.cpp
+++ b/modules/svg/src/SkSVGDOM.cpp
@@ -15,6 +15,7 @@
 #include "modules/svg/include/SkSVGDOM.h"
 #include "modules/svg/include/SkSVGDefs.h"
 #include "modules/svg/include/SkSVGEllipse.h"
+#include "modules/svg/include/SkSVGFilter.h"
 #include "modules/svg/include/SkSVGG.h"
 #include "modules/svg/include/SkSVGLine.h"
 #include "modules/svg/include/SkSVGLinearGradient.h"
@@ -434,6 +435,8 @@
     { "fill-opacity"       , { SkSVGAttribute::kFillOpacity      , SetNumberAttribute       }},
     { "fill-rule"          , { SkSVGAttribute::kFillRule         , SetFillRuleAttribute     }},
     { "filter"             , { SkSVGAttribute::kFilter           , SetFilterAttribute       }},
+    { "filterUnits"        , { SkSVGAttribute::kFilterUnits      ,
+                               SetObjectBoundingBoxUnitsAttribute }},
     { "font-family"        , { SkSVGAttribute::kFontFamily       , SetFontFamilyAttribute   }},
     { "font-size"          , { SkSVGAttribute::kFontSize         , SetFontSizeAttribute     }},
     { "font-style"         , { SkSVGAttribute::kFontStyle        , SetFontStyleAttribute    }},
@@ -487,6 +490,7 @@
     { "clipPath"      , []() -> sk_sp<SkSVGNode> { return SkSVGClipPath::Make();       }},
     { "defs"          , []() -> sk_sp<SkSVGNode> { return SkSVGDefs::Make();           }},
     { "ellipse"       , []() -> sk_sp<SkSVGNode> { return SkSVGEllipse::Make();        }},
+    { "filter"        , []() -> sk_sp<SkSVGNode> { return SkSVGFilter::Make();         }},
     { "g"             , []() -> sk_sp<SkSVGNode> { return SkSVGG::Make();              }},
     { "line"          , []() -> sk_sp<SkSVGNode> { return SkSVGLine::Make();           }},
     { "linearGradient", []() -> sk_sp<SkSVGNode> { return SkSVGLinearGradient::Make(); }},
diff --git a/modules/svg/src/SkSVGFe.cpp b/modules/svg/src/SkSVGFe.cpp
new file mode 100644
index 0000000..058c05c
--- /dev/null
+++ b/modules/svg/src/SkSVGFe.cpp
@@ -0,0 +1,15 @@
+/*
+ * Copyright 2020 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "include/effects/SkImageFilters.h"
+#include "modules/svg/include/SkSVGFe.h"
+#include "modules/svg/include/SkSVGFilterContext.h"
+
+sk_sp<SkImageFilter> SkSVGFe::makeImageFilter(const SkSVGRenderContext& ctx,
+                                              SkSVGFilterContext* fctx) const {
+    return this->onMakeImageFilter(ctx, *fctx);
+}
diff --git a/modules/svg/src/SkSVGFilter.cpp b/modules/svg/src/SkSVGFilter.cpp
new file mode 100644
index 0000000..4e3ae57
--- /dev/null
+++ b/modules/svg/src/SkSVGFilter.cpp
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2020 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "include/effects/SkImageFilters.h"
+#include "modules/svg/include/SkSVGFe.h"
+#include "modules/svg/include/SkSVGFilter.h"
+#include "modules/svg/include/SkSVGFilterContext.h"
+#include "modules/svg/include/SkSVGRenderContext.h"
+#include "modules/svg/include/SkSVGValue.h"
+
+void SkSVGFilter::onSetAttribute(SkSVGAttribute attr, const SkSVGValue& v) {
+    switch (attr) {
+        case SkSVGAttribute::kX:
+            if (const auto* x = v.as<SkSVGLengthValue>()) {
+                this->setX(*x);
+            }
+            break;
+        case SkSVGAttribute::kY:
+            if (const auto* y = v.as<SkSVGLengthValue>()) {
+                this->setY(*y);
+            }
+            break;
+        case SkSVGAttribute::kWidth:
+            if (const auto* w = v.as<SkSVGLengthValue>()) {
+                this->setWidth(*w);
+            }
+            break;
+        case SkSVGAttribute::kHeight:
+            if (const auto* h = v.as<SkSVGLengthValue>()) {
+                this->setHeight(*h);
+            }
+            break;
+        case SkSVGAttribute::kFilterUnits:
+            if (const auto* filterUnits = v.as<SkSVGObjectBoundingBoxUnitsValue>()) {
+                this->setFilterUnits(*filterUnits);
+            }
+            break;
+        default:
+            this->INHERITED::onSetAttribute(attr, v);
+    }
+}
diff --git a/modules/svg/src/SkSVGFilterContext.cpp b/modules/svg/src/SkSVGFilterContext.cpp
new file mode 100644
index 0000000..743272a
--- /dev/null
+++ b/modules/svg/src/SkSVGFilterContext.cpp
@@ -0,0 +1,13 @@
+/*
+ * Copyright 2020 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "include/effects/SkImageFilters.h"
+#include "modules/svg/include/SkSVGFilterContext.h"
+
+sk_sp<SkImageFilter> SkSVGFilterContext::findResultById(const SkString& id) const {
+    return nullptr;
+}
diff --git a/modules/svg/svg.gni b/modules/svg/svg.gni
index df70da8..85e8142 100644
--- a/modules/svg/svg.gni
+++ b/modules/svg/svg.gni
@@ -16,6 +16,9 @@
   "$_include/SkSVGDefs.h",
   "$_include/SkSVGDOM.h",
   "$_include/SkSVGEllipse.h",
+  "$_include/SkSVGFe.h",
+  "$_include/SkSVGFilter.h",
+  "$_include/SkSVGFilterContext.h",
   "$_include/SkSVGG.h",
   "$_include/SkSVGGradient.h",
   "$_include/SkSVGHiddenContainer.h",
@@ -47,6 +50,9 @@
   "$_src/SkSVGContainer.cpp",
   "$_src/SkSVGDOM.cpp",
   "$_src/SkSVGEllipse.cpp",
+  "$_src/SkSVGFe.cpp",
+  "$_src/SkSVGFilter.cpp",
+  "$_src/SkSVGFilterContext.cpp",
   "$_src/SkSVGGradient.cpp",
   "$_src/SkSVGLine.cpp",
   "$_src/SkSVGLinearGradient.cpp",