Coverage Report

Created: 2018-09-25 14:53

/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