[svg] Implement feComposite, basic filter result storage

- Plumbing to store filter results by id and resolve them as inputs
  when referenced
- Added implementation of feComposite filter
- Added call to resolve input in feColorMatrix
- Bugfix to SkSVGFilterType operator==

The tests filters-color-01-b and filters-composite-03-b should now be
passing.

Bug: skia:10841
Change-Id: I2cd099c60ac21710f25184806c5cc537656b42af
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/332723
Commit-Queue: Tyler Denniston <tdenniston@google.com>
Reviewed-by: Florin Malita <fmalita@chromium.org>
diff --git a/modules/svg/include/SkSVGFe.h b/modules/svg/include/SkSVGFe.h
index 7965a39..1031b15 100644
--- a/modules/svg/include/SkSVGFe.h
+++ b/modules/svg/include/SkSVGFe.h
@@ -18,11 +18,15 @@
     ~SkSVGFe() override = default;
 
     static bool IsFilterEffect(const sk_sp<SkSVGNode>& node) {
-        return node->tag() == SkSVGTag::kFeTurbulence || node->tag() == SkSVGTag::kFeColorMatrix;
+        return node->tag() == SkSVGTag::kFeTurbulence || node->tag() == SkSVGTag::kFeColorMatrix ||
+               node->tag() == SkSVGTag::kFeComposite;
     }
 
     sk_sp<SkImageFilter> makeImageFilter(const SkSVGRenderContext& ctx,
-                                         SkSVGFilterContext* fctx) const;
+                                         const SkSVGFilterContext& fctx) const;
+
+    SVG_ATTR(In, SkSVGFeInputType, SkSVGFeInputType(SkSVGFeInputType::Type::kSourceGraphic))
+    SVG_ATTR(Result, SkSVGStringType, SkSVGStringType())
 
 protected:
     explicit SkSVGFe(SkSVGTag t) : INHERITED(t) {}
@@ -30,6 +34,8 @@
     virtual sk_sp<SkImageFilter> onMakeImageFilter(const SkSVGRenderContext&,
                                                    const SkSVGFilterContext&) const = 0;
 
+    bool parseAndSetAttribute(const char*, const char*) override;
+
 private:
     using INHERITED = SkSVGHiddenContainer;
 };
diff --git a/modules/svg/include/SkSVGFeComposite.h b/modules/svg/include/SkSVGFeComposite.h
new file mode 100644
index 0000000..9a6570a
--- /dev/null
+++ b/modules/svg/include/SkSVGFeComposite.h
@@ -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.
+ */
+
+#ifndef SkSVGFeComposite_DEFINED
+#define SkSVGFeComposite_DEFINED
+
+#include "include/core/SkBlendMode.h"
+#include "modules/svg/include/SkSVGFe.h"
+#include "modules/svg/include/SkSVGTypes.h"
+
+class SkSVGFeComposite final : public SkSVGFe {
+public:
+    ~SkSVGFeComposite() override = default;
+    static sk_sp<SkSVGFeComposite> Make() {
+        return sk_sp<SkSVGFeComposite>(new SkSVGFeComposite());
+    }
+
+    SVG_ATTR(In2, SkSVGFeInputType, SkSVGFeInputType())
+    SVG_ATTR(K1, SkSVGNumberType, SkSVGNumberType(0))
+    SVG_ATTR(K2, SkSVGNumberType, SkSVGNumberType(0))
+    SVG_ATTR(K3, SkSVGNumberType, SkSVGNumberType(0))
+    SVG_ATTR(K4, SkSVGNumberType, SkSVGNumberType(0))
+    SVG_ATTR(Operator, SkSVGFeCompositeOperator, SkSVGFeCompositeOperator::kOver)
+
+protected:
+    sk_sp<SkImageFilter> onMakeImageFilter(const SkSVGRenderContext&,
+                                           const SkSVGFilterContext&) const override;
+
+    bool parseAndSetAttribute(const char*, const char*) override;
+
+private:
+    SkSVGFeComposite() : INHERITED(SkSVGTag::kFeComposite) {}
+
+    static SkBlendMode BlendModeForOperator(SkSVGFeCompositeOperator);
+
+    using INHERITED = SkSVGFe;
+};
+
+#endif  // SkSVGFeComposite_DEFINED
diff --git a/modules/svg/include/SkSVGFilterContext.h b/modules/svg/include/SkSVGFilterContext.h
index 9077c63..01a138b 100644
--- a/modules/svg/include/SkSVGFilterContext.h
+++ b/modules/svg/include/SkSVGFilterContext.h
@@ -10,23 +10,31 @@
 
 #include "include/core/SkRect.h"
 #include "include/core/SkRefCnt.h"
+#include "include/core/SkString.h"
 #include "include/private/SkTHash.h"
+#include "modules/svg/include/SkSVGTypes.h"
 
 class SkImageFilter;
-class SkPicture;
-class SkString;
+class SkSVGFeInputType;
+class SkSVGRenderContext;
 
 class SkSVGFilterContext {
 public:
     SkSVGFilterContext(const SkRect& filterEffectsRegion)
             : fFilterEffectsRegion(filterEffectsRegion) {}
 
-    sk_sp<SkImageFilter> findResultById(const SkString& id) const;
-
     const SkRect& filterEffectsRegion() const { return fFilterEffectsRegion; }
 
+    void registerResult(const SkSVGStringType&, const sk_sp<SkImageFilter>&);
+
+    sk_sp<SkImageFilter> resolveInput(const SkSVGRenderContext&, const SkSVGFeInputType&) const;
+
 private:
+    sk_sp<SkImageFilter> findResultById(const SkSVGStringType&) const;
+
     SkRect fFilterEffectsRegion;
+
+    SkTHashMap<SkSVGStringType, sk_sp<SkImageFilter>> fResults;
 };
 
 #endif  // SkSVGFilterContext_DEFINED
diff --git a/modules/svg/include/SkSVGNode.h b/modules/svg/include/SkSVGNode.h
index 26a9dd8..8b731a5 100644
--- a/modules/svg/include/SkSVGNode.h
+++ b/modules/svg/include/SkSVGNode.h
@@ -26,6 +26,7 @@
     kDefs,
     kEllipse,
     kFeColorMatrix,
+    kFeComposite,
     kFeTurbulence,
     kFilter,
     kG,
diff --git a/modules/svg/include/SkSVGTypes.h b/modules/svg/include/SkSVGTypes.h
index 3985aa1..e4f0fb7 100644
--- a/modules/svg/include/SkSVGTypes.h
+++ b/modules/svg/include/SkSVGTypes.h
@@ -501,7 +501,9 @@
     explicit SkSVGFilterType(Type t) : fType(t) {}
     explicit SkSVGFilterType(const SkString& iri) : fType(Type::kIRI), fIRI(iri) {}
 
-    bool operator==(const SkSVGFilterType& other) const { return fType == other.fType; }
+    bool operator==(const SkSVGFilterType& other) const {
+        return fType == other.fType && fIRI == other.fIRI;
+    }
     bool operator!=(const SkSVGFilterType& other) const { return !(*this == other); }
 
     const SkString& iri() const {
@@ -516,6 +518,40 @@
     SkString fIRI;
 };
 
+class SkSVGFeInputType {
+public:
+    enum class Type {
+        kSourceGraphic,
+        kSourceAlpha,
+        kBackgroundImage,
+        kBackgroundAlpha,
+        kFillPaint,
+        kStrokePaint,
+        kFilterPrimitiveReference,
+    };
+
+    SkSVGFeInputType() : fType(Type::kSourceGraphic) {}
+    explicit SkSVGFeInputType(Type t) : fType(t) {}
+    explicit SkSVGFeInputType(const SkSVGStringType& id)
+            : fType(Type::kFilterPrimitiveReference), fId(id) {}
+
+    bool operator==(const SkSVGFeInputType& other) const {
+        return fType == other.fType && fId == other.fId;
+    }
+    bool operator!=(const SkSVGFeInputType& other) const { return !(*this == other); }
+
+    const SkString& id() const {
+        SkASSERT(fType == Type::kFilterPrimitiveReference);
+        return fId;
+    }
+
+    Type type() const { return fType; }
+
+private:
+    Type fType;
+    SkString fId;
+};
+
 enum class SkSVGFeColorMatrixType {
     kMatrix,
     kSaturate,
@@ -525,6 +561,15 @@
 
 using SkSVGFeColorMatrixValues = SkTDArray<SkSVGNumberType>;
 
+enum class SkSVGFeCompositeOperator {
+    kOver,
+    kIn,
+    kOut,
+    kAtop,
+    kXor,
+    kArithmetic,
+};
+
 class SkSVGFeTurbulenceBaseFrequency {
 public:
     SkSVGFeTurbulenceBaseFrequency() : fFreqX(0), fFreqY(0) {}