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"
15 NS_IMPL_NS_NEW_SVG_ELEMENT(FEConvolveMatrix
)
17 using namespace mozilla::gfx
;
22 JSObject
* SVGFEConvolveMatrixElement::WrapNode(
23 JSContext
* aCx
, JS::Handle
<JSObject
*> aGivenProto
) {
24 return SVGFEConvolveMatrixElement_Binding::Wrap(aCx
, this, aGivenProto
);
27 SVGElement::NumberInfo
SVGFEConvolveMatrixElement::sNumberInfo
[2] = {
28 {nsGkAtoms::divisor
, 1, false}, {nsGkAtoms::bias
, 0, false}};
30 SVGElement::NumberPairInfo
SVGFEConvolveMatrixElement::sNumberPairInfo
[1] = {
31 {nsGkAtoms::kernelUnitLength
, 0, 0}};
33 SVGElement::IntegerInfo
SVGFEConvolveMatrixElement::sIntegerInfo
[2] = {
34 {nsGkAtoms::targetX
, 0}, {nsGkAtoms::targetY
, 0}};
36 SVGElement::IntegerPairInfo
SVGFEConvolveMatrixElement::sIntegerPairInfo
[1] = {
37 {nsGkAtoms::order
, 3, 3}};
39 SVGElement::BooleanInfo
SVGFEConvolveMatrixElement::sBooleanInfo
[1] = {
40 {nsGkAtoms::preserveAlpha
, false}};
42 SVGEnumMapping
SVGFEConvolveMatrixElement::sEdgeModeMap
[] = {
43 {nsGkAtoms::duplicate
, SVG_EDGEMODE_DUPLICATE
},
44 {nsGkAtoms::wrap
, SVG_EDGEMODE_WRAP
},
45 {nsGkAtoms::none
, SVG_EDGEMODE_NONE
},
48 SVGElement::EnumInfo
SVGFEConvolveMatrixElement::sEnumInfo
[1] = {
49 {nsGkAtoms::edgeMode
, sEdgeModeMap
, SVG_EDGEMODE_DUPLICATE
}};
51 SVGElement::StringInfo
SVGFEConvolveMatrixElement::sStringInfo
[2] = {
52 {nsGkAtoms::result
, kNameSpaceID_None
, true},
53 {nsGkAtoms::in
, kNameSpaceID_None
, true}};
55 SVGElement::NumberListInfo
SVGFEConvolveMatrixElement::sNumberListInfo
[1] = {
56 {nsGkAtoms::kernelMatrix
}};
58 //----------------------------------------------------------------------
61 NS_IMPL_ELEMENT_CLONE_WITH_INIT(SVGFEConvolveMatrixElement
)
63 //----------------------------------------------------------------------
65 already_AddRefed
<DOMSVGAnimatedString
> SVGFEConvolveMatrixElement::In1() {
66 return mStringAttributes
[IN1
].ToDOMAnimatedString(this);
69 already_AddRefed
<DOMSVGAnimatedInteger
> SVGFEConvolveMatrixElement::OrderX() {
70 return mIntegerPairAttributes
[ORDER
].ToDOMAnimatedInteger(
71 SVGAnimatedIntegerPair::eFirst
, this);
74 already_AddRefed
<DOMSVGAnimatedInteger
> SVGFEConvolveMatrixElement::OrderY() {
75 return mIntegerPairAttributes
[ORDER
].ToDOMAnimatedInteger(
76 SVGAnimatedIntegerPair::eSecond
, this);
79 already_AddRefed
<DOMSVGAnimatedNumberList
>
80 SVGFEConvolveMatrixElement::KernelMatrix() {
81 return DOMSVGAnimatedNumberList::GetDOMWrapper(
82 &mNumberListAttributes
[KERNELMATRIX
], this, KERNELMATRIX
);
85 already_AddRefed
<DOMSVGAnimatedInteger
> SVGFEConvolveMatrixElement::TargetX() {
86 return mIntegerAttributes
[TARGET_X
].ToDOMAnimatedInteger(this);
89 already_AddRefed
<DOMSVGAnimatedInteger
> SVGFEConvolveMatrixElement::TargetY() {
90 return mIntegerAttributes
[TARGET_Y
].ToDOMAnimatedInteger(this);
93 already_AddRefed
<DOMSVGAnimatedEnumeration
>
94 SVGFEConvolveMatrixElement::EdgeMode() {
95 return mEnumAttributes
[EDGEMODE
].ToDOMAnimatedEnum(this);
98 already_AddRefed
<DOMSVGAnimatedBoolean
>
99 SVGFEConvolveMatrixElement::PreserveAlpha() {
100 return mBooleanAttributes
[PRESERVEALPHA
].ToDOMAnimatedBoolean(this);
103 already_AddRefed
<DOMSVGAnimatedNumber
> SVGFEConvolveMatrixElement::Divisor() {
104 return mNumberAttributes
[DIVISOR
].ToDOMAnimatedNumber(this);
107 already_AddRefed
<DOMSVGAnimatedNumber
> SVGFEConvolveMatrixElement::Bias() {
108 return mNumberAttributes
[BIAS
].ToDOMAnimatedNumber(this);
111 already_AddRefed
<DOMSVGAnimatedNumber
>
112 SVGFEConvolveMatrixElement::KernelUnitLengthX() {
113 return mNumberPairAttributes
[KERNEL_UNIT_LENGTH
].ToDOMAnimatedNumber(
114 SVGAnimatedNumberPair::eFirst
, this);
117 already_AddRefed
<DOMSVGAnimatedNumber
>
118 SVGFEConvolveMatrixElement::KernelUnitLengthY() {
119 return mNumberPairAttributes
[KERNEL_UNIT_LENGTH
].ToDOMAnimatedNumber(
120 SVGAnimatedNumberPair::eSecond
, this);
123 void SVGFEConvolveMatrixElement::GetSourceImageNames(
124 nsTArray
<SVGStringInfo
>& aSources
) {
125 aSources
.AppendElement(SVGStringInfo(&mStringAttributes
[IN1
], this));
128 FilterPrimitiveDescription
SVGFEConvolveMatrixElement::GetPrimitiveDescription(
129 SVGFilterInstance
* aInstance
, const IntRect
& aFilterSubregion
,
130 const nsTArray
<bool>& aInputsAreTainted
,
131 nsTArray
<RefPtr
<SourceSurface
>>& aInputImages
) {
132 FilterPrimitiveDescription failureDescription
;
134 const SVGNumberList
& kernelMatrix
=
135 mNumberListAttributes
[KERNELMATRIX
].GetAnimValue();
136 uint32_t kmLength
= kernelMatrix
.Length();
138 int32_t orderX
= mIntegerPairAttributes
[ORDER
].GetAnimValue(
139 SVGAnimatedIntegerPair::eFirst
);
140 int32_t orderY
= mIntegerPairAttributes
[ORDER
].GetAnimValue(
141 SVGAnimatedIntegerPair::eSecond
);
143 if (orderX
<= 0 || orderY
<= 0 ||
144 static_cast<uint32_t>(orderX
* orderY
) != kmLength
) {
145 return failureDescription
;
148 int32_t targetX
, targetY
;
149 GetAnimatedIntegerValues(&targetX
, &targetY
, nullptr);
151 if (mIntegerAttributes
[TARGET_X
].IsExplicitlySet()) {
152 if (targetX
< 0 || targetX
>= orderX
) return failureDescription
;
154 targetX
= orderX
/ 2;
156 if (mIntegerAttributes
[TARGET_Y
].IsExplicitlySet()) {
157 if (targetY
< 0 || targetY
>= orderY
) return failureDescription
;
159 targetY
= orderY
/ 2;
162 if (orderX
> NS_SVG_OFFSCREEN_MAX_DIMENSION
||
163 orderY
> NS_SVG_OFFSCREEN_MAX_DIMENSION
)
164 return failureDescription
;
165 UniquePtr
<float[]> kernel
= MakeUniqueFallible
<float[]>(orderX
* orderY
);
166 if (!kernel
) return failureDescription
;
167 for (uint32_t i
= 0; i
< kmLength
; i
++) {
168 kernel
[kmLength
- 1 - i
] = kernelMatrix
[i
];
172 if (mNumberAttributes
[DIVISOR
].IsExplicitlySet()) {
173 divisor
= mNumberAttributes
[DIVISOR
].GetAnimValue();
174 if (divisor
== 0) return failureDescription
;
177 for (uint32_t i
= 1; i
< kmLength
; i
++) divisor
+= kernel
[i
];
178 if (divisor
== 0) divisor
= 1;
181 uint32_t edgeMode
= mEnumAttributes
[EDGEMODE
].GetAnimValue();
182 bool preserveAlpha
= mBooleanAttributes
[PRESERVEALPHA
].GetAnimValue();
183 float bias
= mNumberAttributes
[BIAS
].GetAnimValue();
185 Size kernelUnitLength
= GetKernelUnitLength(
186 aInstance
, &mNumberPairAttributes
[KERNEL_UNIT_LENGTH
]);
188 if (kernelUnitLength
.width
<= 0 || kernelUnitLength
.height
<= 0) {
189 // According to spec, A negative or zero value is an error. See link below
191 // https://www.w3.org/TR/SVG/filters.html#feConvolveMatrixElementKernelUnitLengthAttribute
192 return failureDescription
;
195 ConvolveMatrixAttributes atts
;
196 atts
.mKernelSize
= IntSize(orderX
, orderY
);
197 atts
.mKernelMatrix
.AppendElements(&kernelMatrix
[0], kmLength
);
198 atts
.mDivisor
= divisor
;
200 atts
.mTarget
= IntPoint(targetX
, targetY
);
201 atts
.mEdgeMode
= edgeMode
;
202 atts
.mKernelUnitLength
= kernelUnitLength
;
203 atts
.mPreserveAlpha
= preserveAlpha
;
205 return FilterPrimitiveDescription(AsVariant(std::move(atts
)));
208 bool SVGFEConvolveMatrixElement::AttributeAffectsRendering(
209 int32_t aNameSpaceID
, nsAtom
* aAttribute
) const {
210 return SVGFEConvolveMatrixElementBase::AttributeAffectsRendering(
211 aNameSpaceID
, aAttribute
) ||
212 (aNameSpaceID
== kNameSpaceID_None
&&
213 (aAttribute
== nsGkAtoms::in
|| aAttribute
== nsGkAtoms::divisor
||
214 aAttribute
== nsGkAtoms::bias
||
215 aAttribute
== nsGkAtoms::kernelUnitLength
||
216 aAttribute
== nsGkAtoms::targetX
||
217 aAttribute
== nsGkAtoms::targetY
|| aAttribute
== nsGkAtoms::order
||
218 aAttribute
== nsGkAtoms::preserveAlpha
||
219 aAttribute
== nsGkAtoms::edgeMode
||
220 aAttribute
== nsGkAtoms::kernelMatrix
));
223 //----------------------------------------------------------------------
224 // SVGElement methods
226 SVGElement::NumberAttributesInfo
SVGFEConvolveMatrixElement::GetNumberInfo() {
227 return NumberAttributesInfo(mNumberAttributes
, sNumberInfo
,
228 ArrayLength(sNumberInfo
));
231 SVGElement::NumberPairAttributesInfo
232 SVGFEConvolveMatrixElement::GetNumberPairInfo() {
233 return NumberPairAttributesInfo(mNumberPairAttributes
, sNumberPairInfo
,
234 ArrayLength(sNumberPairInfo
));
237 SVGElement::IntegerAttributesInfo
SVGFEConvolveMatrixElement::GetIntegerInfo() {
238 return IntegerAttributesInfo(mIntegerAttributes
, sIntegerInfo
,
239 ArrayLength(sIntegerInfo
));
242 SVGElement::IntegerPairAttributesInfo
243 SVGFEConvolveMatrixElement::GetIntegerPairInfo() {
244 return IntegerPairAttributesInfo(mIntegerPairAttributes
, sIntegerPairInfo
,
245 ArrayLength(sIntegerPairInfo
));
248 SVGElement::BooleanAttributesInfo
SVGFEConvolveMatrixElement::GetBooleanInfo() {
249 return BooleanAttributesInfo(mBooleanAttributes
, sBooleanInfo
,
250 ArrayLength(sBooleanInfo
));
253 SVGElement::EnumAttributesInfo
SVGFEConvolveMatrixElement::GetEnumInfo() {
254 return EnumAttributesInfo(mEnumAttributes
, sEnumInfo
, ArrayLength(sEnumInfo
));
257 SVGElement::StringAttributesInfo
SVGFEConvolveMatrixElement::GetStringInfo() {
258 return StringAttributesInfo(mStringAttributes
, sStringInfo
,
259 ArrayLength(sStringInfo
));
262 SVGElement::NumberListAttributesInfo
263 SVGFEConvolveMatrixElement::GetNumberListInfo() {
264 return NumberListAttributesInfo(mNumberListAttributes
, sNumberListInfo
,
265 ArrayLength(sNumberListInfo
));
269 } // namespace mozilla