[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) {}