Line data Source code
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 0 : 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 0 : SVGFEConvolveMatrixElement::WrapNode(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
24 : {
25 0 : return SVGFEConvolveMatrixElementBinding::Wrap(aCx, this, aGivenProto);
26 : }
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 : // nsIDOMNode methods
83 :
84 0 : NS_IMPL_ELEMENT_CLONE_WITH_INIT(SVGFEConvolveMatrixElement)
85 :
86 : //----------------------------------------------------------------------
87 :
88 : already_AddRefed<SVGAnimatedString>
89 0 : SVGFEConvolveMatrixElement::In1()
90 : {
91 0 : return mStringAttributes[IN1].ToDOMAnimatedString(this);
92 : }
93 :
94 : already_AddRefed<SVGAnimatedInteger>
95 0 : SVGFEConvolveMatrixElement::OrderX()
96 : {
97 0 : return mIntegerPairAttributes[ORDER].ToDOMAnimatedInteger(nsSVGIntegerPair::eFirst, this);
98 : }
99 :
100 : already_AddRefed<SVGAnimatedInteger>
101 0 : SVGFEConvolveMatrixElement::OrderY()
102 : {
103 0 : return mIntegerPairAttributes[ORDER].ToDOMAnimatedInteger(nsSVGIntegerPair::eSecond, this);
104 : }
105 :
106 : already_AddRefed<DOMSVGAnimatedNumberList>
107 0 : SVGFEConvolveMatrixElement::KernelMatrix()
108 : {
109 : return DOMSVGAnimatedNumberList::GetDOMWrapper(&mNumberListAttributes[KERNELMATRIX],
110 0 : this, KERNELMATRIX);
111 : }
112 :
113 : already_AddRefed<SVGAnimatedInteger>
114 0 : SVGFEConvolveMatrixElement::TargetX()
115 : {
116 0 : return mIntegerAttributes[TARGET_X].ToDOMAnimatedInteger(this);
117 : }
118 :
119 : already_AddRefed<SVGAnimatedInteger>
120 0 : SVGFEConvolveMatrixElement::TargetY()
121 : {
122 0 : return mIntegerAttributes[TARGET_Y].ToDOMAnimatedInteger(this);
123 : }
124 :
125 : already_AddRefed<SVGAnimatedEnumeration>
126 0 : SVGFEConvolveMatrixElement::EdgeMode()
127 : {
128 0 : return mEnumAttributes[EDGEMODE].ToDOMAnimatedEnum(this);
129 : }
130 :
131 : already_AddRefed<SVGAnimatedBoolean>
132 0 : SVGFEConvolveMatrixElement::PreserveAlpha()
133 : {
134 0 : return mBooleanAttributes[PRESERVEALPHA].ToDOMAnimatedBoolean(this);
135 : }
136 :
137 : already_AddRefed<SVGAnimatedNumber>
138 0 : SVGFEConvolveMatrixElement::Divisor()
139 : {
140 0 : return mNumberAttributes[DIVISOR].ToDOMAnimatedNumber(this);
141 : }
142 :
143 : already_AddRefed<SVGAnimatedNumber>
144 0 : SVGFEConvolveMatrixElement::Bias()
145 : {
146 0 : return mNumberAttributes[BIAS].ToDOMAnimatedNumber(this);
147 : }
148 :
149 : already_AddRefed<SVGAnimatedNumber>
150 0 : SVGFEConvolveMatrixElement::KernelUnitLengthX()
151 : {
152 : return mNumberPairAttributes[KERNEL_UNIT_LENGTH].ToDOMAnimatedNumber(nsSVGNumberPair::eFirst,
153 0 : this);
154 : }
155 :
156 : already_AddRefed<SVGAnimatedNumber>
157 0 : SVGFEConvolveMatrixElement::KernelUnitLengthY()
158 : {
159 : return mNumberPairAttributes[KERNEL_UNIT_LENGTH].ToDOMAnimatedNumber(nsSVGNumberPair::eSecond,
160 0 : this);
161 : }
162 :
163 : void
164 0 : SVGFEConvolveMatrixElement::GetSourceImageNames(nsTArray<nsSVGStringInfo>& aSources)
165 : {
166 0 : aSources.AppendElement(nsSVGStringInfo(&mStringAttributes[IN1], this));
167 0 : }
168 :
169 : FilterPrimitiveDescription
170 0 : SVGFEConvolveMatrixElement::GetPrimitiveDescription(nsSVGFilterInstance* aInstance,
171 : const IntRect& aFilterSubregion,
172 : const nsTArray<bool>& aInputsAreTainted,
173 : nsTArray<RefPtr<SourceSurface>>& aInputImages)
174 : {
175 0 : const FilterPrimitiveDescription failureDescription(PrimitiveType::Empty);
176 :
177 : const SVGNumberList &kernelMatrix =
178 0 : mNumberListAttributes[KERNELMATRIX].GetAnimValue();
179 0 : uint32_t kmLength = kernelMatrix.Length();
180 :
181 0 : int32_t orderX = mIntegerPairAttributes[ORDER].GetAnimValue(nsSVGIntegerPair::eFirst);
182 0 : int32_t orderY = mIntegerPairAttributes[ORDER].GetAnimValue(nsSVGIntegerPair::eSecond);
183 :
184 0 : if (orderX <= 0 || orderY <= 0 ||
185 0 : static_cast<uint32_t>(orderX * orderY) != kmLength) {
186 0 : return failureDescription;
187 : }
188 :
189 : int32_t targetX, targetY;
190 0 : GetAnimatedIntegerValues(&targetX, &targetY, nullptr);
191 :
192 0 : if (mIntegerAttributes[TARGET_X].IsExplicitlySet()) {
193 0 : if (targetX < 0 || targetX >= orderX)
194 0 : return failureDescription;
195 : } else {
196 0 : targetX = orderX / 2;
197 : }
198 0 : if (mIntegerAttributes[TARGET_Y].IsExplicitlySet()) {
199 0 : if (targetY < 0 || targetY >= orderY)
200 0 : return failureDescription;
201 : } else {
202 0 : targetY = orderY / 2;
203 : }
204 :
205 0 : if (orderX > NS_SVG_OFFSCREEN_MAX_DIMENSION ||
206 : 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 : }
214 :
215 : float divisor;
216 0 : if (mNumberAttributes[DIVISOR].IsExplicitlySet()) {
217 0 : divisor = mNumberAttributes[DIVISOR].GetAnimValue();
218 0 : if (divisor == 0)
219 0 : return failureDescription;
220 : } 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 : }
227 :
228 0 : uint32_t edgeMode = mEnumAttributes[EDGEMODE].GetAnimValue();
229 0 : bool preserveAlpha = mBooleanAttributes[PRESERVEALPHA].GetAnimValue();
230 0 : float bias = mNumberAttributes[BIAS].GetAnimValue();
231 :
232 : Size kernelUnitLength =
233 0 : GetKernelUnitLength(aInstance, &mNumberPairAttributes[KERNEL_UNIT_LENGTH]);
234 :
235 0 : 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 0 : return failureDescription;
239 : }
240 :
241 0 : FilterPrimitiveDescription descr(PrimitiveType::ConvolveMatrix);
242 0 : AttributeMap& atts = descr.Attributes();
243 0 : atts.Set(eConvolveMatrixKernelSize, IntSize(orderX, orderY));
244 0 : atts.Set(eConvolveMatrixKernelMatrix, &kernelMatrix[0], kmLength);
245 0 : atts.Set(eConvolveMatrixDivisor, divisor);
246 0 : atts.Set(eConvolveMatrixBias, bias);
247 0 : atts.Set(eConvolveMatrixTarget, IntPoint(targetX, targetY));
248 0 : atts.Set(eConvolveMatrixEdgeMode, edgeMode);
249 0 : atts.Set(eConvolveMatrixKernelUnitLength, kernelUnitLength);
250 0 : atts.Set(eConvolveMatrixPreserveAlpha, preserveAlpha);
251 :
252 0 : return descr;
253 : }
254 :
255 : bool
256 0 : SVGFEConvolveMatrixElement::AttributeAffectsRendering(int32_t aNameSpaceID,
257 : nsIAtom* aAttribute) const
258 : {
259 0 : return SVGFEConvolveMatrixElementBase::AttributeAffectsRendering(aNameSpaceID, aAttribute) ||
260 0 : (aNameSpaceID == kNameSpaceID_None &&
261 0 : (aAttribute == nsGkAtoms::in ||
262 0 : aAttribute == nsGkAtoms::divisor ||
263 0 : aAttribute == nsGkAtoms::bias ||
264 0 : aAttribute == nsGkAtoms::kernelUnitLength ||
265 0 : aAttribute == nsGkAtoms::targetX ||
266 0 : aAttribute == nsGkAtoms::targetY ||
267 0 : aAttribute == nsGkAtoms::order ||
268 0 : aAttribute == nsGkAtoms::preserveAlpha||
269 0 : aAttribute == nsGkAtoms::edgeMode ||
270 0 : aAttribute == nsGkAtoms::kernelMatrix));
271 : }
272 :
273 : //----------------------------------------------------------------------
274 : // nsSVGElement methods
275 :
276 : nsSVGElement::NumberAttributesInfo
277 0 : SVGFEConvolveMatrixElement::GetNumberInfo()
278 : {
279 : return NumberAttributesInfo(mNumberAttributes, sNumberInfo,
280 0 : ArrayLength(sNumberInfo));
281 : }
282 :
283 : nsSVGElement::NumberPairAttributesInfo
284 0 : SVGFEConvolveMatrixElement::GetNumberPairInfo()
285 : {
286 : return NumberPairAttributesInfo(mNumberPairAttributes, sNumberPairInfo,
287 0 : ArrayLength(sNumberPairInfo));
288 : }
289 :
290 : nsSVGElement::IntegerAttributesInfo
291 0 : SVGFEConvolveMatrixElement::GetIntegerInfo()
292 : {
293 : return IntegerAttributesInfo(mIntegerAttributes, sIntegerInfo,
294 0 : ArrayLength(sIntegerInfo));
295 : }
296 :
297 : nsSVGElement::IntegerPairAttributesInfo
298 0 : SVGFEConvolveMatrixElement::GetIntegerPairInfo()
299 : {
300 : return IntegerPairAttributesInfo(mIntegerPairAttributes, sIntegerPairInfo,
301 0 : ArrayLength(sIntegerPairInfo));
302 : }
303 :
304 : nsSVGElement::BooleanAttributesInfo
305 0 : SVGFEConvolveMatrixElement::GetBooleanInfo()
306 : {
307 : return BooleanAttributesInfo(mBooleanAttributes, sBooleanInfo,
308 0 : ArrayLength(sBooleanInfo));
309 : }
310 :
311 : nsSVGElement::EnumAttributesInfo
312 0 : SVGFEConvolveMatrixElement::GetEnumInfo()
313 : {
314 : return EnumAttributesInfo(mEnumAttributes, sEnumInfo,
315 0 : ArrayLength(sEnumInfo));
316 : }
317 :
318 : nsSVGElement::StringAttributesInfo
319 0 : SVGFEConvolveMatrixElement::GetStringInfo()
320 : {
321 : return StringAttributesInfo(mStringAttributes, sStringInfo,
322 0 : ArrayLength(sStringInfo));
323 : }
324 :
325 : nsSVGElement::NumberListAttributesInfo
326 0 : SVGFEConvolveMatrixElement::GetNumberListInfo()
327 : {
328 : return NumberListAttributesInfo(mNumberListAttributes, sNumberListInfo,
329 0 : ArrayLength(sNumberListInfo));
330 : }
331 :
332 : } // namespace dom
333 : } // namespace mozilla
|