Bumping manifests a=b2g-bump
[gecko.git] / dom / svg / nsSVGFilters.cpp
blobaa3d2941c5ede0bebee98ab17036de924373dbcf
1 /* a*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 #include "mozilla/ArrayUtils.h"
8 #include "nsSVGElement.h"
9 #include "nsGkAtoms.h"
10 #include "nsSVGNumber2.h"
11 #include "nsSVGNumberPair.h"
12 #include "nsSVGInteger.h"
13 #include "nsSVGIntegerPair.h"
14 #include "nsSVGBoolean.h"
15 #include "nsCOMPtr.h"
16 #include "nsSVGFilterInstance.h"
17 #include "nsSVGEnum.h"
18 #include "SVGNumberList.h"
19 #include "SVGAnimatedNumberList.h"
20 #include "DOMSVGAnimatedNumberList.h"
21 #include "nsSVGFilters.h"
22 #include "nsLayoutUtils.h"
23 #include "nsSVGUtils.h"
24 #include "nsStyleContext.h"
25 #include "nsIFrame.h"
26 #include "imgIContainer.h"
27 #include "nsNetUtil.h"
28 #include "mozilla/dom/SVGFilterElement.h"
29 #include "nsSVGString.h"
30 #include "SVGContentUtils.h"
31 #include <algorithm>
32 #include "mozilla/dom/SVGAnimatedLength.h"
33 #include "mozilla/dom/SVGComponentTransferFunctionElement.h"
34 #include "mozilla/dom/SVGFEDistantLightElement.h"
35 #include "mozilla/dom/SVGFEFuncAElementBinding.h"
36 #include "mozilla/dom/SVGFEFuncBElementBinding.h"
37 #include "mozilla/dom/SVGFEFuncGElementBinding.h"
38 #include "mozilla/dom/SVGFEFuncRElementBinding.h"
39 #include "mozilla/dom/SVGFEPointLightElement.h"
40 #include "mozilla/dom/SVGFESpotLightElement.h"
42 #if defined(XP_WIN)
43 // Prevent Windows redefining LoadImage
44 #undef LoadImage
45 #endif
47 using namespace mozilla;
48 using namespace mozilla::dom;
49 using namespace mozilla::gfx;
51 //--------------------Filter Element Base Class-----------------------
53 nsSVGElement::LengthInfo nsSVGFE::sLengthInfo[4] =
55 { &nsGkAtoms::x, 0, nsIDOMSVGLength::SVG_LENGTHTYPE_PERCENTAGE, SVGContentUtils::X },
56 { &nsGkAtoms::y, 0, nsIDOMSVGLength::SVG_LENGTHTYPE_PERCENTAGE, SVGContentUtils::Y },
57 { &nsGkAtoms::width, 100, nsIDOMSVGLength::SVG_LENGTHTYPE_PERCENTAGE, SVGContentUtils::X },
58 { &nsGkAtoms::height, 100, nsIDOMSVGLength::SVG_LENGTHTYPE_PERCENTAGE, SVGContentUtils::Y }
61 //----------------------------------------------------------------------
62 // nsISupports methods
64 NS_IMPL_ADDREF_INHERITED(nsSVGFE,nsSVGFEBase)
65 NS_IMPL_RELEASE_INHERITED(nsSVGFE,nsSVGFEBase)
67 NS_INTERFACE_MAP_BEGIN(nsSVGFE)
68 // nsISupports is an ambiguous base of nsSVGFE so we have to work
69 // around that
70 if ( aIID.Equals(NS_GET_IID(nsSVGFE)) )
71 foundInterface = static_cast<nsISupports*>(static_cast<void*>(this));
72 else
73 NS_INTERFACE_MAP_END_INHERITING(nsSVGFEBase)
75 //----------------------------------------------------------------------
76 // Implementation
78 void
79 nsSVGFE::GetSourceImageNames(nsTArray<nsSVGStringInfo>& aSources)
83 bool
84 nsSVGFE::OutputIsTainted(const nsTArray<bool>& aInputsAreTainted,
85 nsIPrincipal* aReferencePrincipal)
87 // This is the default implementation for OutputIsTainted.
88 // Our output is tainted if we have at least one tainted input.
89 for (uint32_t i = 0; i < aInputsAreTainted.Length(); i++) {
90 if (aInputsAreTainted[i]) {
91 return true;
94 return false;
97 bool
98 nsSVGFE::AttributeAffectsRendering(int32_t aNameSpaceID,
99 nsIAtom* aAttribute) const
101 return aNameSpaceID == kNameSpaceID_None &&
102 (aAttribute == nsGkAtoms::x ||
103 aAttribute == nsGkAtoms::y ||
104 aAttribute == nsGkAtoms::width ||
105 aAttribute == nsGkAtoms::height ||
106 aAttribute == nsGkAtoms::result);
109 already_AddRefed<SVGAnimatedLength>
110 nsSVGFE::X()
112 return mLengthAttributes[ATTR_X].ToDOMAnimatedLength(this);
115 already_AddRefed<SVGAnimatedLength>
116 nsSVGFE::Y()
118 return mLengthAttributes[ATTR_Y].ToDOMAnimatedLength(this);
121 already_AddRefed<SVGAnimatedLength>
122 nsSVGFE::Width()
124 return mLengthAttributes[ATTR_WIDTH].ToDOMAnimatedLength(this);
127 already_AddRefed<SVGAnimatedLength>
128 nsSVGFE::Height()
130 return mLengthAttributes[ATTR_HEIGHT].ToDOMAnimatedLength(this);
133 already_AddRefed<SVGAnimatedString>
134 nsSVGFE::Result()
136 return GetResultImageName().ToDOMAnimatedString(this);
139 //----------------------------------------------------------------------
140 // nsIContent methods
142 NS_IMETHODIMP_(bool)
143 nsSVGFE::IsAttributeMapped(const nsIAtom* name) const
145 static const MappedAttributeEntry* const map[] = {
146 sFiltersMap
149 return FindAttributeDependence(name, map) ||
150 nsSVGFEBase::IsAttributeMapped(name);
153 //----------------------------------------------------------------------
154 // nsSVGElement methods
157 bool
158 nsSVGFE::StyleIsSetToSRGB()
160 nsIFrame* frame = GetPrimaryFrame();
161 if (!frame) return false;
163 nsStyleContext* style = frame->StyleContext();
164 return style->StyleSVG()->mColorInterpolationFilters ==
165 NS_STYLE_COLOR_INTERPOLATION_SRGB;
168 /* virtual */ bool
169 nsSVGFE::HasValidDimensions() const
171 return (!mLengthAttributes[ATTR_WIDTH].IsExplicitlySet() ||
172 mLengthAttributes[ATTR_WIDTH].GetAnimValInSpecifiedUnits() > 0) &&
173 (!mLengthAttributes[ATTR_HEIGHT].IsExplicitlySet() ||
174 mLengthAttributes[ATTR_HEIGHT].GetAnimValInSpecifiedUnits() > 0);
177 Size
178 nsSVGFE::GetKernelUnitLength(nsSVGFilterInstance* aInstance,
179 nsSVGNumberPair *aKernelUnitLength)
181 if (!aKernelUnitLength->IsExplicitlySet()) {
182 return Size(1, 1);
185 float kernelX = aInstance->GetPrimitiveNumber(SVGContentUtils::X,
186 aKernelUnitLength,
187 nsSVGNumberPair::eFirst);
188 float kernelY = aInstance->GetPrimitiveNumber(SVGContentUtils::Y,
189 aKernelUnitLength,
190 nsSVGNumberPair::eSecond);
191 return Size(kernelX, kernelY);
194 nsSVGElement::LengthAttributesInfo
195 nsSVGFE::GetLengthInfo()
197 return LengthAttributesInfo(mLengthAttributes, sLengthInfo,
198 ArrayLength(sLengthInfo));
201 namespace mozilla {
202 namespace dom {
204 nsSVGElement::NumberListInfo SVGComponentTransferFunctionElement::sNumberListInfo[1] =
206 { &nsGkAtoms::tableValues }
209 nsSVGElement::NumberInfo SVGComponentTransferFunctionElement::sNumberInfo[5] =
211 { &nsGkAtoms::slope, 1, false },
212 { &nsGkAtoms::intercept, 0, false },
213 { &nsGkAtoms::amplitude, 1, false },
214 { &nsGkAtoms::exponent, 1, false },
215 { &nsGkAtoms::offset, 0, false }
218 nsSVGEnumMapping SVGComponentTransferFunctionElement::sTypeMap[] = {
219 {&nsGkAtoms::identity,
220 SVG_FECOMPONENTTRANSFER_TYPE_IDENTITY},
221 {&nsGkAtoms::table,
222 SVG_FECOMPONENTTRANSFER_TYPE_TABLE},
223 {&nsGkAtoms::discrete,
224 SVG_FECOMPONENTTRANSFER_TYPE_DISCRETE},
225 {&nsGkAtoms::linear,
226 SVG_FECOMPONENTTRANSFER_TYPE_LINEAR},
227 {&nsGkAtoms::gamma,
228 SVG_FECOMPONENTTRANSFER_TYPE_GAMMA},
229 {nullptr, 0}
232 nsSVGElement::EnumInfo SVGComponentTransferFunctionElement::sEnumInfo[1] =
234 { &nsGkAtoms::type,
235 sTypeMap,
236 SVG_FECOMPONENTTRANSFER_TYPE_IDENTITY
240 //----------------------------------------------------------------------
241 // nsISupports methods
243 NS_IMPL_ADDREF_INHERITED(SVGComponentTransferFunctionElement,SVGComponentTransferFunctionElementBase)
244 NS_IMPL_RELEASE_INHERITED(SVGComponentTransferFunctionElement,SVGComponentTransferFunctionElementBase)
246 NS_INTERFACE_MAP_BEGIN(SVGComponentTransferFunctionElement)
247 // nsISupports is an ambiguous base of nsSVGFE so we have to work
248 // around that
249 if ( aIID.Equals(NS_GET_IID(SVGComponentTransferFunctionElement)) )
250 foundInterface = static_cast<nsISupports*>(static_cast<void*>(this));
251 else
252 NS_INTERFACE_MAP_END_INHERITING(SVGComponentTransferFunctionElementBase)
255 //----------------------------------------------------------------------
256 // nsFEUnstyledElement methods
258 bool
259 SVGComponentTransferFunctionElement::AttributeAffectsRendering(int32_t aNameSpaceID,
260 nsIAtom* aAttribute) const
262 return aNameSpaceID == kNameSpaceID_None &&
263 (aAttribute == nsGkAtoms::tableValues ||
264 aAttribute == nsGkAtoms::slope ||
265 aAttribute == nsGkAtoms::intercept ||
266 aAttribute == nsGkAtoms::amplitude ||
267 aAttribute == nsGkAtoms::exponent ||
268 aAttribute == nsGkAtoms::offset ||
269 aAttribute == nsGkAtoms::type);
272 //----------------------------------------------------------------------
274 already_AddRefed<SVGAnimatedEnumeration>
275 SVGComponentTransferFunctionElement::Type()
277 return mEnumAttributes[TYPE].ToDOMAnimatedEnum(this);
280 already_AddRefed<DOMSVGAnimatedNumberList>
281 SVGComponentTransferFunctionElement::TableValues()
283 return DOMSVGAnimatedNumberList::GetDOMWrapper(
284 &mNumberListAttributes[TABLEVALUES], this, TABLEVALUES);
287 already_AddRefed<SVGAnimatedNumber>
288 SVGComponentTransferFunctionElement::Slope()
290 return mNumberAttributes[SLOPE].ToDOMAnimatedNumber(this);
293 already_AddRefed<SVGAnimatedNumber>
294 SVGComponentTransferFunctionElement::Intercept()
296 return mNumberAttributes[INTERCEPT].ToDOMAnimatedNumber(this);
299 already_AddRefed<SVGAnimatedNumber>
300 SVGComponentTransferFunctionElement::Amplitude()
302 return mNumberAttributes[AMPLITUDE].ToDOMAnimatedNumber(this);
305 already_AddRefed<SVGAnimatedNumber>
306 SVGComponentTransferFunctionElement::Exponent()
308 return mNumberAttributes[EXPONENT].ToDOMAnimatedNumber(this);
311 already_AddRefed<SVGAnimatedNumber>
312 SVGComponentTransferFunctionElement::Offset()
314 return mNumberAttributes[OFFSET].ToDOMAnimatedNumber(this);
317 AttributeMap
318 SVGComponentTransferFunctionElement::ComputeAttributes()
320 uint32_t type = mEnumAttributes[TYPE].GetAnimValue();
322 float slope, intercept, amplitude, exponent, offset;
323 GetAnimatedNumberValues(&slope, &intercept, &amplitude,
324 &exponent, &offset, nullptr);
326 const SVGNumberList &tableValues =
327 mNumberListAttributes[TABLEVALUES].GetAnimValue();
329 AttributeMap map;
330 map.Set(eComponentTransferFunctionType, type);
331 map.Set(eComponentTransferFunctionSlope, slope);
332 map.Set(eComponentTransferFunctionIntercept, intercept);
333 map.Set(eComponentTransferFunctionAmplitude, amplitude);
334 map.Set(eComponentTransferFunctionExponent, exponent);
335 map.Set(eComponentTransferFunctionOffset, offset);
336 if (tableValues.Length()) {
337 map.Set(eComponentTransferFunctionTableValues, &tableValues[0], tableValues.Length());
338 } else {
339 map.Set(eComponentTransferFunctionTableValues, nullptr, 0);
341 return map;
344 //----------------------------------------------------------------------
345 // nsSVGElement methods
347 nsSVGElement::NumberListAttributesInfo
348 SVGComponentTransferFunctionElement::GetNumberListInfo()
350 return NumberListAttributesInfo(mNumberListAttributes, sNumberListInfo,
351 ArrayLength(sNumberListInfo));
354 nsSVGElement::EnumAttributesInfo
355 SVGComponentTransferFunctionElement::GetEnumInfo()
357 return EnumAttributesInfo(mEnumAttributes, sEnumInfo,
358 ArrayLength(sEnumInfo));
361 nsSVGElement::NumberAttributesInfo
362 SVGComponentTransferFunctionElement::GetNumberInfo()
364 return NumberAttributesInfo(mNumberAttributes, sNumberInfo,
365 ArrayLength(sNumberInfo));
368 /* virtual */ JSObject*
369 SVGFEFuncRElement::WrapNode(JSContext* aCx)
371 return SVGFEFuncRElementBinding::Wrap(aCx, this);
374 } // namespace dom
375 } // namespace mozilla
377 NS_IMPL_NS_NEW_NAMESPACED_SVG_ELEMENT(FEFuncR)
379 namespace mozilla {
380 namespace dom {
382 NS_IMPL_ELEMENT_CLONE_WITH_INIT(SVGFEFuncRElement)
384 /* virtual */ JSObject*
385 SVGFEFuncGElement::WrapNode(JSContext* aCx)
387 return SVGFEFuncGElementBinding::Wrap(aCx, this);
390 } // namespace dom
391 } // namespace mozilla
393 NS_IMPL_NS_NEW_NAMESPACED_SVG_ELEMENT(FEFuncG)
395 namespace mozilla {
396 namespace dom {
398 NS_IMPL_ELEMENT_CLONE_WITH_INIT(SVGFEFuncGElement)
400 /* virtual */ JSObject*
401 SVGFEFuncBElement::WrapNode(JSContext* aCx)
403 return SVGFEFuncBElementBinding::Wrap(aCx, this);
406 } // namespace dom
407 } // namespace mozilla
409 NS_IMPL_NS_NEW_NAMESPACED_SVG_ELEMENT(FEFuncB)
411 namespace mozilla {
412 namespace dom {
414 NS_IMPL_ELEMENT_CLONE_WITH_INIT(SVGFEFuncBElement)
416 /* virtual */ JSObject*
417 SVGFEFuncAElement::WrapNode(JSContext* aCx)
419 return SVGFEFuncAElementBinding::Wrap(aCx, this);
422 } // namespace dom
423 } // namespace mozilla
425 NS_IMPL_NS_NEW_NAMESPACED_SVG_ELEMENT(FEFuncA)
427 namespace mozilla {
428 namespace dom {
430 NS_IMPL_ELEMENT_CLONE_WITH_INIT(SVGFEFuncAElement)
432 } // namespace dom
433 } // namespace mozilla
435 //--------------------------------------------------------------------
437 nsSVGElement::NumberInfo nsSVGFELightingElement::sNumberInfo[4] =
439 { &nsGkAtoms::surfaceScale, 1, false },
440 { &nsGkAtoms::diffuseConstant, 1, false },
441 { &nsGkAtoms::specularConstant, 1, false },
442 { &nsGkAtoms::specularExponent, 1, false }
445 nsSVGElement::NumberPairInfo nsSVGFELightingElement::sNumberPairInfo[1] =
447 { &nsGkAtoms::kernelUnitLength, 0, 0 }
450 nsSVGElement::StringInfo nsSVGFELightingElement::sStringInfo[2] =
452 { &nsGkAtoms::result, kNameSpaceID_None, true },
453 { &nsGkAtoms::in, kNameSpaceID_None, true }
456 //----------------------------------------------------------------------
457 // nsISupports methods
459 NS_IMPL_ADDREF_INHERITED(nsSVGFELightingElement,nsSVGFELightingElementBase)
460 NS_IMPL_RELEASE_INHERITED(nsSVGFELightingElement,nsSVGFELightingElementBase)
462 NS_INTERFACE_MAP_BEGIN(nsSVGFELightingElement)
463 NS_INTERFACE_MAP_END_INHERITING(nsSVGFELightingElementBase)
465 //----------------------------------------------------------------------
466 // Implementation
468 NS_IMETHODIMP_(bool)
469 nsSVGFELightingElement::IsAttributeMapped(const nsIAtom* name) const
471 static const MappedAttributeEntry* const map[] = {
472 sLightingEffectsMap
475 return FindAttributeDependence(name, map) ||
476 nsSVGFELightingElementBase::IsAttributeMapped(name);
479 void
480 nsSVGFELightingElement::GetSourceImageNames(nsTArray<nsSVGStringInfo>& aSources)
482 aSources.AppendElement(nsSVGStringInfo(&mStringAttributes[IN1], this));
485 AttributeMap
486 nsSVGFELightingElement::ComputeLightAttributes(nsSVGFilterInstance* aInstance)
488 // find specified light
489 for (nsCOMPtr<nsIContent> child = nsINode::GetFirstChild();
490 child;
491 child = child->GetNextSibling()) {
492 if (child->IsSVG(nsGkAtoms::feDistantLight) ||
493 child->IsSVG(nsGkAtoms::fePointLight) ||
494 child->IsSVG(nsGkAtoms::feSpotLight)) {
495 return static_cast<SVGFELightElement*>(child.get())->ComputeLightAttributes(aInstance);
499 AttributeMap map;
500 map.Set(eLightType, (uint32_t)eLightTypeNone);
501 return map;
504 FilterPrimitiveDescription
505 nsSVGFELightingElement::AddLightingAttributes(FilterPrimitiveDescription aDescription,
506 nsSVGFilterInstance* aInstance)
508 nsIFrame* frame = GetPrimaryFrame();
509 if (!frame) {
510 return FilterPrimitiveDescription(PrimitiveType::Empty);
513 nsStyleContext* style = frame->StyleContext();
514 Color color(Color::FromABGR(style->StyleSVGReset()->mLightingColor));
515 color.a = 1.f;
516 float surfaceScale = mNumberAttributes[SURFACE_SCALE].GetAnimValue();
517 Size kernelUnitLength =
518 GetKernelUnitLength(aInstance, &mNumberPairAttributes[KERNEL_UNIT_LENGTH]);
520 FilterPrimitiveDescription& descr = aDescription;
521 descr.Attributes().Set(eLightingLight, ComputeLightAttributes(aInstance));
522 descr.Attributes().Set(eLightingSurfaceScale, surfaceScale);
523 descr.Attributes().Set(eLightingKernelUnitLength, kernelUnitLength);
524 descr.Attributes().Set(eLightingColor, color);
525 return descr;
528 bool
529 nsSVGFELightingElement::AttributeAffectsRendering(int32_t aNameSpaceID,
530 nsIAtom* aAttribute) const
532 return nsSVGFELightingElementBase::AttributeAffectsRendering(aNameSpaceID, aAttribute) ||
533 (aNameSpaceID == kNameSpaceID_None &&
534 (aAttribute == nsGkAtoms::in ||
535 aAttribute == nsGkAtoms::surfaceScale ||
536 aAttribute == nsGkAtoms::kernelUnitLength));
539 //----------------------------------------------------------------------
540 // nsSVGElement methods
542 nsSVGElement::NumberAttributesInfo
543 nsSVGFELightingElement::GetNumberInfo()
545 return NumberAttributesInfo(mNumberAttributes, sNumberInfo,
546 ArrayLength(sNumberInfo));
549 nsSVGElement::NumberPairAttributesInfo
550 nsSVGFELightingElement::GetNumberPairInfo()
552 return NumberPairAttributesInfo(mNumberPairAttributes, sNumberPairInfo,
553 ArrayLength(sNumberPairInfo));
556 nsSVGElement::StringAttributesInfo
557 nsSVGFELightingElement::GetStringInfo()
559 return StringAttributesInfo(mStringAttributes, sStringInfo,
560 ArrayLength(sStringInfo));