/src/mozilla-central/dom/svg/SVGFEConvolveMatrixElement.cpp
Line | Count | Source (jump to first uncovered line) |
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/. */ |
6 | | |
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" |
14 | | |
15 | | NS_IMPL_NS_NEW_NAMESPACED_SVG_ELEMENT(FEConvolveMatrix) |
16 | | |
17 | | using namespace mozilla::gfx; |
18 | | |
19 | | namespace mozilla { |
20 | | namespace dom { |
21 | | |
22 | | JSObject* |
23 | | SVGFEConvolveMatrixElement::WrapNode(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) |
24 | 0 | { |
25 | 0 | return SVGFEConvolveMatrixElement_Binding::Wrap(aCx, this, aGivenProto); |
26 | 0 | } |
27 | | |
28 | | nsSVGElement::NumberInfo SVGFEConvolveMatrixElement::sNumberInfo[2] = |
29 | | { |
30 | | { &nsGkAtoms::divisor, 1, false }, |
31 | | { &nsGkAtoms::bias, 0, false } |
32 | | }; |
33 | | |
34 | | nsSVGElement::NumberPairInfo SVGFEConvolveMatrixElement::sNumberPairInfo[1] = |
35 | | { |
36 | | { &nsGkAtoms::kernelUnitLength, 0, 0 } |
37 | | }; |
38 | | |
39 | | nsSVGElement::IntegerInfo SVGFEConvolveMatrixElement::sIntegerInfo[2] = |
40 | | { |
41 | | { &nsGkAtoms::targetX, 0 }, |
42 | | { &nsGkAtoms::targetY, 0 } |
43 | | }; |
44 | | |
45 | | nsSVGElement::IntegerPairInfo SVGFEConvolveMatrixElement::sIntegerPairInfo[1] = |
46 | | { |
47 | | { &nsGkAtoms::order, 3, 3 } |
48 | | }; |
49 | | |
50 | | nsSVGElement::BooleanInfo SVGFEConvolveMatrixElement::sBooleanInfo[1] = |
51 | | { |
52 | | { &nsGkAtoms::preserveAlpha, false } |
53 | | }; |
54 | | |
55 | | nsSVGEnumMapping SVGFEConvolveMatrixElement::sEdgeModeMap[] = { |
56 | | {&nsGkAtoms::duplicate, SVG_EDGEMODE_DUPLICATE}, |
57 | | {&nsGkAtoms::wrap, SVG_EDGEMODE_WRAP}, |
58 | | {&nsGkAtoms::none, SVG_EDGEMODE_NONE}, |
59 | | {nullptr, 0} |
60 | | }; |
61 | | |
62 | | nsSVGElement::EnumInfo SVGFEConvolveMatrixElement::sEnumInfo[1] = |
63 | | { |
64 | | { &nsGkAtoms::edgeMode, |
65 | | sEdgeModeMap, |
66 | | SVG_EDGEMODE_DUPLICATE |
67 | | } |
68 | | }; |
69 | | |
70 | | nsSVGElement::StringInfo SVGFEConvolveMatrixElement::sStringInfo[2] = |
71 | | { |
72 | | { &nsGkAtoms::result, kNameSpaceID_None, true }, |
73 | | { &nsGkAtoms::in, kNameSpaceID_None, true } |
74 | | }; |
75 | | |
76 | | nsSVGElement::NumberListInfo SVGFEConvolveMatrixElement::sNumberListInfo[1] = |
77 | | { |
78 | | { &nsGkAtoms::kernelMatrix } |
79 | | }; |
80 | | |
81 | | //---------------------------------------------------------------------- |
82 | | // nsINode methods |
83 | | |
84 | | NS_IMPL_ELEMENT_CLONE_WITH_INIT(SVGFEConvolveMatrixElement) |
85 | | |
86 | | //---------------------------------------------------------------------- |
87 | | |
88 | | already_AddRefed<SVGAnimatedString> |
89 | | SVGFEConvolveMatrixElement::In1() |
90 | 0 | { |
91 | 0 | return mStringAttributes[IN1].ToDOMAnimatedString(this); |
92 | 0 | } |
93 | | |
94 | | already_AddRefed<SVGAnimatedInteger> |
95 | | SVGFEConvolveMatrixElement::OrderX() |
96 | 0 | { |
97 | 0 | return mIntegerPairAttributes[ORDER].ToDOMAnimatedInteger(nsSVGIntegerPair::eFirst, this); |
98 | 0 | } |
99 | | |
100 | | already_AddRefed<SVGAnimatedInteger> |
101 | | SVGFEConvolveMatrixElement::OrderY() |
102 | 0 | { |
103 | 0 | return mIntegerPairAttributes[ORDER].ToDOMAnimatedInteger(nsSVGIntegerPair::eSecond, this); |
104 | 0 | } |
105 | | |
106 | | already_AddRefed<DOMSVGAnimatedNumberList> |
107 | | SVGFEConvolveMatrixElement::KernelMatrix() |
108 | 0 | { |
109 | 0 | return DOMSVGAnimatedNumberList::GetDOMWrapper(&mNumberListAttributes[KERNELMATRIX], |
110 | 0 | this, KERNELMATRIX); |
111 | 0 | } |
112 | | |
113 | | already_AddRefed<SVGAnimatedInteger> |
114 | | SVGFEConvolveMatrixElement::TargetX() |
115 | 0 | { |
116 | 0 | return mIntegerAttributes[TARGET_X].ToDOMAnimatedInteger(this); |
117 | 0 | } |
118 | | |
119 | | already_AddRefed<SVGAnimatedInteger> |
120 | | SVGFEConvolveMatrixElement::TargetY() |
121 | 0 | { |
122 | 0 | return mIntegerAttributes[TARGET_Y].ToDOMAnimatedInteger(this); |
123 | 0 | } |
124 | | |
125 | | already_AddRefed<SVGAnimatedEnumeration> |
126 | | SVGFEConvolveMatrixElement::EdgeMode() |
127 | 0 | { |
128 | 0 | return mEnumAttributes[EDGEMODE].ToDOMAnimatedEnum(this); |
129 | 0 | } |
130 | | |
131 | | already_AddRefed<SVGAnimatedBoolean> |
132 | | SVGFEConvolveMatrixElement::PreserveAlpha() |
133 | 0 | { |
134 | 0 | return mBooleanAttributes[PRESERVEALPHA].ToDOMAnimatedBoolean(this); |
135 | 0 | } |
136 | | |
137 | | already_AddRefed<SVGAnimatedNumber> |
138 | | SVGFEConvolveMatrixElement::Divisor() |
139 | 0 | { |
140 | 0 | return mNumberAttributes[DIVISOR].ToDOMAnimatedNumber(this); |
141 | 0 | } |
142 | | |
143 | | already_AddRefed<SVGAnimatedNumber> |
144 | | SVGFEConvolveMatrixElement::Bias() |
145 | 0 | { |
146 | 0 | return mNumberAttributes[BIAS].ToDOMAnimatedNumber(this); |
147 | 0 | } |
148 | | |
149 | | already_AddRefed<SVGAnimatedNumber> |
150 | | SVGFEConvolveMatrixElement::KernelUnitLengthX() |
151 | 0 | { |
152 | 0 | return mNumberPairAttributes[KERNEL_UNIT_LENGTH].ToDOMAnimatedNumber(nsSVGNumberPair::eFirst, |
153 | 0 | this); |
154 | 0 | } |
155 | | |
156 | | already_AddRefed<SVGAnimatedNumber> |
157 | | SVGFEConvolveMatrixElement::KernelUnitLengthY() |
158 | 0 | { |
159 | 0 | return mNumberPairAttributes[KERNEL_UNIT_LENGTH].ToDOMAnimatedNumber(nsSVGNumberPair::eSecond, |
160 | 0 | this); |
161 | 0 | } |
162 | | |
163 | | void |
164 | | SVGFEConvolveMatrixElement::GetSourceImageNames(nsTArray<nsSVGStringInfo>& aSources) |
165 | 0 | { |
166 | 0 | aSources.AppendElement(nsSVGStringInfo(&mStringAttributes[IN1], this)); |
167 | 0 | } |
168 | | |
169 | | FilterPrimitiveDescription |
170 | | SVGFEConvolveMatrixElement::GetPrimitiveDescription(nsSVGFilterInstance* aInstance, |
171 | | const IntRect& aFilterSubregion, |
172 | | const nsTArray<bool>& aInputsAreTainted, |
173 | | nsTArray<RefPtr<SourceSurface>>& aInputImages) |
174 | 0 | { |
175 | 0 | FilterPrimitiveDescription failureDescription; |
176 | 0 |
|
177 | 0 | const SVGNumberList &kernelMatrix = |
178 | 0 | mNumberListAttributes[KERNELMATRIX].GetAnimValue(); |
179 | 0 | uint32_t kmLength = kernelMatrix.Length(); |
180 | 0 |
|
181 | 0 | int32_t orderX = mIntegerPairAttributes[ORDER].GetAnimValue(nsSVGIntegerPair::eFirst); |
182 | 0 | int32_t orderY = mIntegerPairAttributes[ORDER].GetAnimValue(nsSVGIntegerPair::eSecond); |
183 | 0 |
|
184 | 0 | if (orderX <= 0 || orderY <= 0 || |
185 | 0 | static_cast<uint32_t>(orderX * orderY) != kmLength) { |
186 | 0 | return failureDescription; |
187 | 0 | } |
188 | 0 | |
189 | 0 | int32_t targetX, targetY; |
190 | 0 | GetAnimatedIntegerValues(&targetX, &targetY, nullptr); |
191 | 0 |
|
192 | 0 | if (mIntegerAttributes[TARGET_X].IsExplicitlySet()) { |
193 | 0 | if (targetX < 0 || targetX >= orderX) |
194 | 0 | return failureDescription; |
195 | 0 | } else { |
196 | 0 | targetX = orderX / 2; |
197 | 0 | } |
198 | 0 | if (mIntegerAttributes[TARGET_Y].IsExplicitlySet()) { |
199 | 0 | if (targetY < 0 || targetY >= orderY) |
200 | 0 | return failureDescription; |
201 | 0 | } else { |
202 | 0 | targetY = orderY / 2; |
203 | 0 | } |
204 | 0 |
|
205 | 0 | if (orderX > NS_SVG_OFFSCREEN_MAX_DIMENSION || |
206 | 0 | orderY > NS_SVG_OFFSCREEN_MAX_DIMENSION) |
207 | 0 | return failureDescription; |
208 | 0 | UniquePtr<float[]> kernel = MakeUniqueFallible<float[]>(orderX * orderY); |
209 | 0 | if (!kernel) |
210 | 0 | return failureDescription; |
211 | 0 | for (uint32_t i = 0; i < kmLength; i++) { |
212 | 0 | kernel[kmLength - 1 - i] = kernelMatrix[i]; |
213 | 0 | } |
214 | 0 |
|
215 | 0 | float divisor; |
216 | 0 | if (mNumberAttributes[DIVISOR].IsExplicitlySet()) { |
217 | 0 | divisor = mNumberAttributes[DIVISOR].GetAnimValue(); |
218 | 0 | if (divisor == 0) |
219 | 0 | return failureDescription; |
220 | 0 | } else { |
221 | 0 | divisor = kernel[0]; |
222 | 0 | for (uint32_t i = 1; i < kmLength; i++) |
223 | 0 | divisor += kernel[i]; |
224 | 0 | if (divisor == 0) |
225 | 0 | divisor = 1; |
226 | 0 | } |
227 | 0 |
|
228 | 0 | uint32_t edgeMode = mEnumAttributes[EDGEMODE].GetAnimValue(); |
229 | 0 | bool preserveAlpha = mBooleanAttributes[PRESERVEALPHA].GetAnimValue(); |
230 | 0 | float bias = mNumberAttributes[BIAS].GetAnimValue(); |
231 | 0 |
|
232 | 0 | Size kernelUnitLength = |
233 | 0 | GetKernelUnitLength(aInstance, &mNumberPairAttributes[KERNEL_UNIT_LENGTH]); |
234 | 0 |
|
235 | 0 | if (kernelUnitLength.width <= 0 || kernelUnitLength.height <= 0) { |
236 | 0 | // According to spec, A negative or zero value is an error. See link below for details. |
237 | 0 | // https://www.w3.org/TR/SVG/filters.html#feConvolveMatrixElementKernelUnitLengthAttribute |
238 | 0 | return failureDescription; |
239 | 0 | } |
240 | 0 | |
241 | 0 | ConvolveMatrixAttributes atts; |
242 | 0 | atts.mKernelSize = IntSize(orderX, orderY); |
243 | 0 | atts.mKernelMatrix.AppendElements(&kernelMatrix[0], kmLength); |
244 | 0 | atts.mDivisor = divisor; |
245 | 0 | atts.mBias = bias; |
246 | 0 | atts.mTarget = IntPoint(targetX, targetY); |
247 | 0 | atts.mEdgeMode = edgeMode; |
248 | 0 | atts.mKernelUnitLength = kernelUnitLength; |
249 | 0 | atts.mPreserveAlpha = preserveAlpha; |
250 | 0 |
|
251 | 0 | return FilterPrimitiveDescription(AsVariant(std::move(atts))); |
252 | 0 | } |
253 | | |
254 | | bool |
255 | | SVGFEConvolveMatrixElement::AttributeAffectsRendering(int32_t aNameSpaceID, |
256 | | nsAtom* aAttribute) const |
257 | 0 | { |
258 | 0 | return SVGFEConvolveMatrixElementBase::AttributeAffectsRendering(aNameSpaceID, aAttribute) || |
259 | 0 | (aNameSpaceID == kNameSpaceID_None && |
260 | 0 | (aAttribute == nsGkAtoms::in || |
261 | 0 | aAttribute == nsGkAtoms::divisor || |
262 | 0 | aAttribute == nsGkAtoms::bias || |
263 | 0 | aAttribute == nsGkAtoms::kernelUnitLength || |
264 | 0 | aAttribute == nsGkAtoms::targetX || |
265 | 0 | aAttribute == nsGkAtoms::targetY || |
266 | 0 | aAttribute == nsGkAtoms::order || |
267 | 0 | aAttribute == nsGkAtoms::preserveAlpha|| |
268 | 0 | aAttribute == nsGkAtoms::edgeMode || |
269 | 0 | aAttribute == nsGkAtoms::kernelMatrix)); |
270 | 0 | } |
271 | | |
272 | | //---------------------------------------------------------------------- |
273 | | // nsSVGElement methods |
274 | | |
275 | | nsSVGElement::NumberAttributesInfo |
276 | | SVGFEConvolveMatrixElement::GetNumberInfo() |
277 | 0 | { |
278 | 0 | return NumberAttributesInfo(mNumberAttributes, sNumberInfo, |
279 | 0 | ArrayLength(sNumberInfo)); |
280 | 0 | } |
281 | | |
282 | | nsSVGElement::NumberPairAttributesInfo |
283 | | SVGFEConvolveMatrixElement::GetNumberPairInfo() |
284 | 0 | { |
285 | 0 | return NumberPairAttributesInfo(mNumberPairAttributes, sNumberPairInfo, |
286 | 0 | ArrayLength(sNumberPairInfo)); |
287 | 0 | } |
288 | | |
289 | | nsSVGElement::IntegerAttributesInfo |
290 | | SVGFEConvolveMatrixElement::GetIntegerInfo() |
291 | 0 | { |
292 | 0 | return IntegerAttributesInfo(mIntegerAttributes, sIntegerInfo, |
293 | 0 | ArrayLength(sIntegerInfo)); |
294 | 0 | } |
295 | | |
296 | | nsSVGElement::IntegerPairAttributesInfo |
297 | | SVGFEConvolveMatrixElement::GetIntegerPairInfo() |
298 | 0 | { |
299 | 0 | return IntegerPairAttributesInfo(mIntegerPairAttributes, sIntegerPairInfo, |
300 | 0 | ArrayLength(sIntegerPairInfo)); |
301 | 0 | } |
302 | | |
303 | | nsSVGElement::BooleanAttributesInfo |
304 | | SVGFEConvolveMatrixElement::GetBooleanInfo() |
305 | 0 | { |
306 | 0 | return BooleanAttributesInfo(mBooleanAttributes, sBooleanInfo, |
307 | 0 | ArrayLength(sBooleanInfo)); |
308 | 0 | } |
309 | | |
310 | | nsSVGElement::EnumAttributesInfo |
311 | | SVGFEConvolveMatrixElement::GetEnumInfo() |
312 | 0 | { |
313 | 0 | return EnumAttributesInfo(mEnumAttributes, sEnumInfo, |
314 | 0 | ArrayLength(sEnumInfo)); |
315 | 0 | } |
316 | | |
317 | | nsSVGElement::StringAttributesInfo |
318 | | SVGFEConvolveMatrixElement::GetStringInfo() |
319 | 0 | { |
320 | 0 | return StringAttributesInfo(mStringAttributes, sStringInfo, |
321 | 0 | ArrayLength(sStringInfo)); |
322 | 0 | } |
323 | | |
324 | | nsSVGElement::NumberListAttributesInfo |
325 | | SVGFEConvolveMatrixElement::GetNumberListInfo() |
326 | 0 | { |
327 | 0 | return NumberListAttributesInfo(mNumberListAttributes, sNumberListInfo, |
328 | 0 | ArrayLength(sNumberListInfo)); |
329 | 0 | } |
330 | | |
331 | | } // namespace dom |
332 | | } // namespace mozilla |