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/UniquePtr.h"
10 #include "mozilla/UniquePtrExtensions.h"
11 #include "DOMSVGAnimatedNumberList.h"
12 #include "nsSVGUtils.h"
13 #include "nsSVGFilterInstance.h"
15 NS_IMPL_NS_NEW_NAMESPACED_SVG_ELEMENT(FEConvolveMatrix
)
17 using namespace mozilla::gfx
;
23 SVGFEConvolveMatrixElement::WrapNode(JSContext
* aCx
, JS::Handle
<JSObject
*> aGivenProto
)
25 return SVGFEConvolveMatrixElementBinding::Wrap(aCx
, this, aGivenProto
);
28 nsSVGElement::NumberInfo
SVGFEConvolveMatrixElement::sNumberInfo
[2] =
30 { &nsGkAtoms::divisor
, 1, false },
31 { &nsGkAtoms::bias
, 0, false }
34 nsSVGElement::NumberPairInfo
SVGFEConvolveMatrixElement::sNumberPairInfo
[1] =
36 { &nsGkAtoms::kernelUnitLength
, 0, 0 }
39 nsSVGElement::IntegerInfo
SVGFEConvolveMatrixElement::sIntegerInfo
[2] =
41 { &nsGkAtoms::targetX
, 0 },
42 { &nsGkAtoms::targetY
, 0 }
45 nsSVGElement::IntegerPairInfo
SVGFEConvolveMatrixElement::sIntegerPairInfo
[1] =
47 { &nsGkAtoms::order
, 3, 3 }
50 nsSVGElement::BooleanInfo
SVGFEConvolveMatrixElement::sBooleanInfo
[1] =
52 { &nsGkAtoms::preserveAlpha
, false }
55 nsSVGEnumMapping
SVGFEConvolveMatrixElement::sEdgeModeMap
[] = {
56 {&nsGkAtoms::duplicate
, SVG_EDGEMODE_DUPLICATE
},
57 {&nsGkAtoms::wrap
, SVG_EDGEMODE_WRAP
},
58 {&nsGkAtoms::none
, SVG_EDGEMODE_NONE
},
62 nsSVGElement::EnumInfo
SVGFEConvolveMatrixElement::sEnumInfo
[1] =
64 { &nsGkAtoms::edgeMode
,
66 SVG_EDGEMODE_DUPLICATE
70 nsSVGElement::StringInfo
SVGFEConvolveMatrixElement::sStringInfo
[2] =
72 { &nsGkAtoms::result
, kNameSpaceID_None
, true },
73 { &nsGkAtoms::in
, kNameSpaceID_None
, true }
76 nsSVGElement::NumberListInfo
SVGFEConvolveMatrixElement::sNumberListInfo
[1] =
78 { &nsGkAtoms::kernelMatrix
}
81 //----------------------------------------------------------------------
84 NS_IMPL_ELEMENT_CLONE_WITH_INIT(SVGFEConvolveMatrixElement
)
86 //----------------------------------------------------------------------
88 already_AddRefed
<SVGAnimatedString
>
89 SVGFEConvolveMatrixElement::In1()
91 return mStringAttributes
[IN1
].ToDOMAnimatedString(this);
94 already_AddRefed
<SVGAnimatedInteger
>
95 SVGFEConvolveMatrixElement::OrderX()
97 return mIntegerPairAttributes
[ORDER
].ToDOMAnimatedInteger(nsSVGIntegerPair::eFirst
, this);
100 already_AddRefed
<SVGAnimatedInteger
>
101 SVGFEConvolveMatrixElement::OrderY()
103 return mIntegerPairAttributes
[ORDER
].ToDOMAnimatedInteger(nsSVGIntegerPair::eSecond
, this);
106 already_AddRefed
<DOMSVGAnimatedNumberList
>
107 SVGFEConvolveMatrixElement::KernelMatrix()
109 return DOMSVGAnimatedNumberList::GetDOMWrapper(&mNumberListAttributes
[KERNELMATRIX
],
113 already_AddRefed
<SVGAnimatedInteger
>
114 SVGFEConvolveMatrixElement::TargetX()
116 return mIntegerAttributes
[TARGET_X
].ToDOMAnimatedInteger(this);
119 already_AddRefed
<SVGAnimatedInteger
>
120 SVGFEConvolveMatrixElement::TargetY()
122 return mIntegerAttributes
[TARGET_Y
].ToDOMAnimatedInteger(this);
125 already_AddRefed
<SVGAnimatedEnumeration
>
126 SVGFEConvolveMatrixElement::EdgeMode()
128 return mEnumAttributes
[EDGEMODE
].ToDOMAnimatedEnum(this);
131 already_AddRefed
<SVGAnimatedBoolean
>
132 SVGFEConvolveMatrixElement::PreserveAlpha()
134 return mBooleanAttributes
[PRESERVEALPHA
].ToDOMAnimatedBoolean(this);
137 already_AddRefed
<SVGAnimatedNumber
>
138 SVGFEConvolveMatrixElement::Divisor()
140 return mNumberAttributes
[DIVISOR
].ToDOMAnimatedNumber(this);
143 already_AddRefed
<SVGAnimatedNumber
>
144 SVGFEConvolveMatrixElement::Bias()
146 return mNumberAttributes
[BIAS
].ToDOMAnimatedNumber(this);
149 already_AddRefed
<SVGAnimatedNumber
>
150 SVGFEConvolveMatrixElement::KernelUnitLengthX()
152 return mNumberPairAttributes
[KERNEL_UNIT_LENGTH
].ToDOMAnimatedNumber(nsSVGNumberPair::eFirst
,
156 already_AddRefed
<SVGAnimatedNumber
>
157 SVGFEConvolveMatrixElement::KernelUnitLengthY()
159 return mNumberPairAttributes
[KERNEL_UNIT_LENGTH
].ToDOMAnimatedNumber(nsSVGNumberPair::eSecond
,
164 SVGFEConvolveMatrixElement::GetSourceImageNames(nsTArray
<nsSVGStringInfo
>& aSources
)
166 aSources
.AppendElement(nsSVGStringInfo(&mStringAttributes
[IN1
], this));
169 FilterPrimitiveDescription
170 SVGFEConvolveMatrixElement::GetPrimitiveDescription(nsSVGFilterInstance
* aInstance
,
171 const IntRect
& aFilterSubregion
,
172 const nsTArray
<bool>& aInputsAreTainted
,
173 nsTArray
<RefPtr
<SourceSurface
>>& aInputImages
)
175 const FilterPrimitiveDescription
failureDescription(PrimitiveType::Empty
);
177 const SVGNumberList
&kernelMatrix
=
178 mNumberListAttributes
[KERNELMATRIX
].GetAnimValue();
179 uint32_t kmLength
= kernelMatrix
.Length();
181 int32_t orderX
= mIntegerPairAttributes
[ORDER
].GetAnimValue(nsSVGIntegerPair::eFirst
);
182 int32_t orderY
= mIntegerPairAttributes
[ORDER
].GetAnimValue(nsSVGIntegerPair::eSecond
);
184 if (orderX
<= 0 || orderY
<= 0 ||
185 static_cast<uint32_t>(orderX
* orderY
) != kmLength
) {
186 return failureDescription
;
189 int32_t targetX
, targetY
;
190 GetAnimatedIntegerValues(&targetX
, &targetY
, nullptr);
192 if (mIntegerAttributes
[TARGET_X
].IsExplicitlySet()) {
193 if (targetX
< 0 || targetX
>= orderX
)
194 return failureDescription
;
196 targetX
= orderX
/ 2;
198 if (mIntegerAttributes
[TARGET_Y
].IsExplicitlySet()) {
199 if (targetY
< 0 || targetY
>= orderY
)
200 return failureDescription
;
202 targetY
= orderY
/ 2;
205 if (orderX
> NS_SVG_OFFSCREEN_MAX_DIMENSION
||
206 orderY
> NS_SVG_OFFSCREEN_MAX_DIMENSION
)
207 return failureDescription
;
208 UniquePtr
<float[]> kernel
= MakeUniqueFallible
<float[]>(orderX
* orderY
);
210 return failureDescription
;
211 for (uint32_t i
= 0; i
< kmLength
; i
++) {
212 kernel
[kmLength
- 1 - i
] = kernelMatrix
[i
];
216 if (mNumberAttributes
[DIVISOR
].IsExplicitlySet()) {
217 divisor
= mNumberAttributes
[DIVISOR
].GetAnimValue();
219 return failureDescription
;
222 for (uint32_t i
= 1; i
< kmLength
; i
++)
223 divisor
+= kernel
[i
];
228 uint32_t edgeMode
= mEnumAttributes
[EDGEMODE
].GetAnimValue();
229 bool preserveAlpha
= mBooleanAttributes
[PRESERVEALPHA
].GetAnimValue();
230 float bias
= mNumberAttributes
[BIAS
].GetAnimValue();
232 Size kernelUnitLength
=
233 GetKernelUnitLength(aInstance
, &mNumberPairAttributes
[KERNEL_UNIT_LENGTH
]);
235 if (kernelUnitLength
.width
<= 0 || kernelUnitLength
.height
<= 0) {
236 // According to spec, A negative or zero value is an error. See link below for details.
237 // https://www.w3.org/TR/SVG/filters.html#feConvolveMatrixElementKernelUnitLengthAttribute
238 return failureDescription
;
241 FilterPrimitiveDescription
descr(PrimitiveType::ConvolveMatrix
);
242 AttributeMap
& atts
= descr
.Attributes();
243 atts
.Set(eConvolveMatrixKernelSize
, IntSize(orderX
, orderY
));
244 atts
.Set(eConvolveMatrixKernelMatrix
, &kernelMatrix
[0], kmLength
);
245 atts
.Set(eConvolveMatrixDivisor
, divisor
);
246 atts
.Set(eConvolveMatrixBias
, bias
);
247 atts
.Set(eConvolveMatrixTarget
, IntPoint(targetX
, targetY
));
248 atts
.Set(eConvolveMatrixEdgeMode
, edgeMode
);
249 atts
.Set(eConvolveMatrixKernelUnitLength
, kernelUnitLength
);
250 atts
.Set(eConvolveMatrixPreserveAlpha
, preserveAlpha
);
256 SVGFEConvolveMatrixElement::AttributeAffectsRendering(int32_t aNameSpaceID
,
257 nsAtom
* aAttribute
) const
259 return SVGFEConvolveMatrixElementBase::AttributeAffectsRendering(aNameSpaceID
, aAttribute
) ||
260 (aNameSpaceID
== kNameSpaceID_None
&&
261 (aAttribute
== nsGkAtoms::in
||
262 aAttribute
== nsGkAtoms::divisor
||
263 aAttribute
== nsGkAtoms::bias
||
264 aAttribute
== nsGkAtoms::kernelUnitLength
||
265 aAttribute
== nsGkAtoms::targetX
||
266 aAttribute
== nsGkAtoms::targetY
||
267 aAttribute
== nsGkAtoms::order
||
268 aAttribute
== nsGkAtoms::preserveAlpha
||
269 aAttribute
== nsGkAtoms::edgeMode
||
270 aAttribute
== nsGkAtoms::kernelMatrix
));
273 //----------------------------------------------------------------------
274 // nsSVGElement methods
276 nsSVGElement::NumberAttributesInfo
277 SVGFEConvolveMatrixElement::GetNumberInfo()
279 return NumberAttributesInfo(mNumberAttributes
, sNumberInfo
,
280 ArrayLength(sNumberInfo
));
283 nsSVGElement::NumberPairAttributesInfo
284 SVGFEConvolveMatrixElement::GetNumberPairInfo()
286 return NumberPairAttributesInfo(mNumberPairAttributes
, sNumberPairInfo
,
287 ArrayLength(sNumberPairInfo
));
290 nsSVGElement::IntegerAttributesInfo
291 SVGFEConvolveMatrixElement::GetIntegerInfo()
293 return IntegerAttributesInfo(mIntegerAttributes
, sIntegerInfo
,
294 ArrayLength(sIntegerInfo
));
297 nsSVGElement::IntegerPairAttributesInfo
298 SVGFEConvolveMatrixElement::GetIntegerPairInfo()
300 return IntegerPairAttributesInfo(mIntegerPairAttributes
, sIntegerPairInfo
,
301 ArrayLength(sIntegerPairInfo
));
304 nsSVGElement::BooleanAttributesInfo
305 SVGFEConvolveMatrixElement::GetBooleanInfo()
307 return BooleanAttributesInfo(mBooleanAttributes
, sBooleanInfo
,
308 ArrayLength(sBooleanInfo
));
311 nsSVGElement::EnumAttributesInfo
312 SVGFEConvolveMatrixElement::GetEnumInfo()
314 return EnumAttributesInfo(mEnumAttributes
, sEnumInfo
,
315 ArrayLength(sEnumInfo
));
318 nsSVGElement::StringAttributesInfo
319 SVGFEConvolveMatrixElement::GetStringInfo()
321 return StringAttributesInfo(mStringAttributes
, sStringInfo
,
322 ArrayLength(sStringInfo
));
325 nsSVGElement::NumberListAttributesInfo
326 SVGFEConvolveMatrixElement::GetNumberListInfo()
328 return NumberListAttributesInfo(mNumberListAttributes
, sNumberListInfo
,
329 ArrayLength(sNumberListInfo
));
333 } // namespace mozilla