1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #include "mozilla/dom/SVGFEConvolveMatrixElement.h"
8 #include "mozilla/dom/SVGFEConvolveMatrixElementBinding.h"
9 #include "mozilla/SVGFilterInstance.h"
10 #include "mozilla/SVGUtils.h"
11 #include "mozilla/UniquePtr.h"
12 #include "mozilla/UniquePtrExtensions.h"
13 #include "DOMSVGAnimatedNumberList.h"
14 #include "mozilla/dom/Document.h"
15 #include "mozilla/dom/BindContext.h"
18 NS_IMPL_NS_NEW_SVG_ELEMENT(FEConvolveMatrix
)
20 using namespace mozilla::gfx
;
22 namespace mozilla::dom
{
24 JSObject
* SVGFEConvolveMatrixElement::WrapNode(
25 JSContext
* aCx
, JS::Handle
<JSObject
*> aGivenProto
) {
26 return SVGFEConvolveMatrixElement_Binding::Wrap(aCx
, this, aGivenProto
);
29 SVGElement::NumberInfo
SVGFEConvolveMatrixElement::sNumberInfo
[2] = {
30 {nsGkAtoms::divisor
, 1}, {nsGkAtoms::bias
, 0}};
32 SVGElement::NumberPairInfo
SVGFEConvolveMatrixElement::sNumberPairInfo
[1] = {
33 {nsGkAtoms::kernelUnitLength
, 0, 0}};
35 SVGElement::IntegerInfo
SVGFEConvolveMatrixElement::sIntegerInfo
[2] = {
36 {nsGkAtoms::targetX
, 0}, {nsGkAtoms::targetY
, 0}};
38 SVGElement::IntegerPairInfo
SVGFEConvolveMatrixElement::sIntegerPairInfo
[1] = {
39 {nsGkAtoms::order
, 3, 3}};
41 SVGElement::BooleanInfo
SVGFEConvolveMatrixElement::sBooleanInfo
[1] = {
42 {nsGkAtoms::preserveAlpha
, false}};
44 SVGEnumMapping
SVGFEConvolveMatrixElement::sEdgeModeMap
[] = {
45 {nsGkAtoms::duplicate
, SVG_EDGEMODE_DUPLICATE
},
46 {nsGkAtoms::wrap
, SVG_EDGEMODE_WRAP
},
47 {nsGkAtoms::none
, SVG_EDGEMODE_NONE
},
50 SVGElement::EnumInfo
SVGFEConvolveMatrixElement::sEnumInfo
[1] = {
51 {nsGkAtoms::edgeMode
, sEdgeModeMap
, SVG_EDGEMODE_DUPLICATE
}};
53 SVGElement::StringInfo
SVGFEConvolveMatrixElement::sStringInfo
[2] = {
54 {nsGkAtoms::result
, kNameSpaceID_None
, true},
55 {nsGkAtoms::in
, kNameSpaceID_None
, true}};
57 SVGElement::NumberListInfo
SVGFEConvolveMatrixElement::sNumberListInfo
[1] = {
58 {nsGkAtoms::kernelMatrix
}};
60 //----------------------------------------------------------------------
63 NS_IMPL_ELEMENT_CLONE_WITH_INIT(SVGFEConvolveMatrixElement
)
65 //----------------------------------------------------------------------
67 already_AddRefed
<DOMSVGAnimatedString
> SVGFEConvolveMatrixElement::In1() {
68 return mStringAttributes
[IN1
].ToDOMAnimatedString(this);
71 already_AddRefed
<DOMSVGAnimatedInteger
> SVGFEConvolveMatrixElement::OrderX() {
72 return mIntegerPairAttributes
[ORDER
].ToDOMAnimatedInteger(
73 SVGAnimatedIntegerPair::eFirst
, this);
76 already_AddRefed
<DOMSVGAnimatedInteger
> SVGFEConvolveMatrixElement::OrderY() {
77 return mIntegerPairAttributes
[ORDER
].ToDOMAnimatedInteger(
78 SVGAnimatedIntegerPair::eSecond
, this);
81 already_AddRefed
<DOMSVGAnimatedNumberList
>
82 SVGFEConvolveMatrixElement::KernelMatrix() {
83 return DOMSVGAnimatedNumberList::GetDOMWrapper(
84 &mNumberListAttributes
[KERNELMATRIX
], this, KERNELMATRIX
);
87 already_AddRefed
<DOMSVGAnimatedInteger
> SVGFEConvolveMatrixElement::TargetX() {
88 return mIntegerAttributes
[TARGET_X
].ToDOMAnimatedInteger(this);
91 already_AddRefed
<DOMSVGAnimatedInteger
> SVGFEConvolveMatrixElement::TargetY() {
92 return mIntegerAttributes
[TARGET_Y
].ToDOMAnimatedInteger(this);
95 already_AddRefed
<DOMSVGAnimatedEnumeration
>
96 SVGFEConvolveMatrixElement::EdgeMode() {
97 return mEnumAttributes
[EDGEMODE
].ToDOMAnimatedEnum(this);
100 already_AddRefed
<DOMSVGAnimatedBoolean
>
101 SVGFEConvolveMatrixElement::PreserveAlpha() {
102 return mBooleanAttributes
[PRESERVEALPHA
].ToDOMAnimatedBoolean(this);
105 already_AddRefed
<DOMSVGAnimatedNumber
> SVGFEConvolveMatrixElement::Divisor() {
106 return mNumberAttributes
[DIVISOR
].ToDOMAnimatedNumber(this);
109 already_AddRefed
<DOMSVGAnimatedNumber
> SVGFEConvolveMatrixElement::Bias() {
110 return mNumberAttributes
[BIAS
].ToDOMAnimatedNumber(this);
113 already_AddRefed
<DOMSVGAnimatedNumber
>
114 SVGFEConvolveMatrixElement::KernelUnitLengthX() {
115 return mNumberPairAttributes
[KERNEL_UNIT_LENGTH
].ToDOMAnimatedNumber(
116 SVGAnimatedNumberPair::eFirst
, this);
119 already_AddRefed
<DOMSVGAnimatedNumber
>
120 SVGFEConvolveMatrixElement::KernelUnitLengthY() {
121 return mNumberPairAttributes
[KERNEL_UNIT_LENGTH
].ToDOMAnimatedNumber(
122 SVGAnimatedNumberPair::eSecond
, this);
125 void SVGFEConvolveMatrixElement::GetSourceImageNames(
126 nsTArray
<SVGStringInfo
>& aSources
) {
127 aSources
.AppendElement(SVGStringInfo(&mStringAttributes
[IN1
], this));
130 FilterPrimitiveDescription
SVGFEConvolveMatrixElement::GetPrimitiveDescription(
131 SVGFilterInstance
* aInstance
, const IntRect
& aFilterSubregion
,
132 const nsTArray
<bool>& aInputsAreTainted
,
133 nsTArray
<RefPtr
<SourceSurface
>>& aInputImages
) {
134 FilterPrimitiveDescription failureDescription
;
136 const SVGNumberList
& kernelMatrix
=
137 mNumberListAttributes
[KERNELMATRIX
].GetAnimValue();
138 uint32_t kmLength
= kernelMatrix
.Length();
140 int32_t orderX
= mIntegerPairAttributes
[ORDER
].GetAnimValue(
141 SVGAnimatedIntegerPair::eFirst
);
142 int32_t orderY
= mIntegerPairAttributes
[ORDER
].GetAnimValue(
143 SVGAnimatedIntegerPair::eSecond
);
145 if (orderX
<= 0 || orderY
<= 0 ||
146 static_cast<uint32_t>(orderX
* orderY
) != kmLength
) {
147 return failureDescription
;
150 int32_t targetX
, targetY
;
151 GetAnimatedIntegerValues(&targetX
, &targetY
, nullptr);
153 if (mIntegerAttributes
[TARGET_X
].IsExplicitlySet()) {
154 if (targetX
< 0 || targetX
>= orderX
) return failureDescription
;
156 targetX
= orderX
/ 2;
158 if (mIntegerAttributes
[TARGET_Y
].IsExplicitlySet()) {
159 if (targetY
< 0 || targetY
>= orderY
) return failureDescription
;
161 targetY
= orderY
/ 2;
164 if (orderX
> NS_SVG_OFFSCREEN_MAX_DIMENSION
||
165 orderY
> NS_SVG_OFFSCREEN_MAX_DIMENSION
)
166 return failureDescription
;
169 if (mNumberAttributes
[DIVISOR
].IsExplicitlySet()) {
170 divisor
= mNumberAttributes
[DIVISOR
].GetAnimValue();
171 if (divisor
== 0) return failureDescription
;
173 divisor
= std::accumulate(kernelMatrix
.begin(), kernelMatrix
.end(), 0.0f
);
174 if (divisor
== 0) divisor
= 1;
177 uint32_t edgeMode
= mEnumAttributes
[EDGEMODE
].GetAnimValue();
178 bool preserveAlpha
= mBooleanAttributes
[PRESERVEALPHA
].GetAnimValue();
179 float bias
= mNumberAttributes
[BIAS
].GetAnimValue();
181 Size kernelUnitLength
= GetKernelUnitLength(
182 aInstance
, &mNumberPairAttributes
[KERNEL_UNIT_LENGTH
]);
184 if (kernelUnitLength
.width
<= 0 || kernelUnitLength
.height
<= 0) {
185 // According to spec, A negative or zero value is an error. See link below
187 // https://www.w3.org/TR/SVG/filters.html#feConvolveMatrixElementKernelUnitLengthAttribute
188 return failureDescription
;
191 ConvolveMatrixAttributes atts
;
192 atts
.mKernelSize
= IntSize(orderX
, orderY
);
193 atts
.mKernelMatrix
.AppendElements(&kernelMatrix
[0], kmLength
);
194 atts
.mDivisor
= divisor
;
196 atts
.mTarget
= IntPoint(targetX
, targetY
);
197 atts
.mEdgeMode
= edgeMode
;
198 atts
.mKernelUnitLength
= kernelUnitLength
;
199 atts
.mPreserveAlpha
= preserveAlpha
;
201 return FilterPrimitiveDescription(AsVariant(std::move(atts
)));
204 bool SVGFEConvolveMatrixElement::AttributeAffectsRendering(
205 int32_t aNameSpaceID
, nsAtom
* aAttribute
) const {
206 return SVGFEConvolveMatrixElementBase::AttributeAffectsRendering(
207 aNameSpaceID
, aAttribute
) ||
208 (aNameSpaceID
== kNameSpaceID_None
&&
209 (aAttribute
== nsGkAtoms::in
|| aAttribute
== nsGkAtoms::divisor
||
210 aAttribute
== nsGkAtoms::bias
||
211 aAttribute
== nsGkAtoms::kernelUnitLength
||
212 aAttribute
== nsGkAtoms::targetX
||
213 aAttribute
== nsGkAtoms::targetY
|| aAttribute
== nsGkAtoms::order
||
214 aAttribute
== nsGkAtoms::preserveAlpha
||
215 aAttribute
== nsGkAtoms::edgeMode
||
216 aAttribute
== nsGkAtoms::kernelMatrix
));
219 nsresult
SVGFEConvolveMatrixElement::BindToTree(BindContext
& aCtx
,
221 if (aCtx
.InComposedDoc()) {
222 aCtx
.OwnerDoc().SetUseCounter(eUseCounter_custom_feConvolveMatrix
);
225 return SVGFEConvolveMatrixElementBase::BindToTree(aCtx
, aParent
);
228 //----------------------------------------------------------------------
229 // SVGElement methods
231 SVGElement::NumberAttributesInfo
SVGFEConvolveMatrixElement::GetNumberInfo() {
232 return NumberAttributesInfo(mNumberAttributes
, sNumberInfo
,
233 std::size(sNumberInfo
));
236 SVGElement::NumberPairAttributesInfo
237 SVGFEConvolveMatrixElement::GetNumberPairInfo() {
238 return NumberPairAttributesInfo(mNumberPairAttributes
, sNumberPairInfo
,
239 std::size(sNumberPairInfo
));
242 SVGElement::IntegerAttributesInfo
SVGFEConvolveMatrixElement::GetIntegerInfo() {
243 return IntegerAttributesInfo(mIntegerAttributes
, sIntegerInfo
,
244 std::size(sIntegerInfo
));
247 SVGElement::IntegerPairAttributesInfo
248 SVGFEConvolveMatrixElement::GetIntegerPairInfo() {
249 return IntegerPairAttributesInfo(mIntegerPairAttributes
, sIntegerPairInfo
,
250 std::size(sIntegerPairInfo
));
253 SVGElement::BooleanAttributesInfo
SVGFEConvolveMatrixElement::GetBooleanInfo() {
254 return BooleanAttributesInfo(mBooleanAttributes
, sBooleanInfo
,
255 std::size(sBooleanInfo
));
258 SVGElement::EnumAttributesInfo
SVGFEConvolveMatrixElement::GetEnumInfo() {
259 return EnumAttributesInfo(mEnumAttributes
, sEnumInfo
, std::size(sEnumInfo
));
262 SVGElement::StringAttributesInfo
SVGFEConvolveMatrixElement::GetStringInfo() {
263 return StringAttributesInfo(mStringAttributes
, sStringInfo
,
264 std::size(sStringInfo
));
267 SVGElement::NumberListAttributesInfo
268 SVGFEConvolveMatrixElement::GetNumberListInfo() {
269 return NumberListAttributesInfo(mNumberListAttributes
, sNumberListInfo
,
270 std::size(sNumberListInfo
));
273 } // namespace mozilla::dom