From 5f8de423f190bbb79a62f804151bc24824fa32d8 Mon Sep 17 00:00:00 2001 From: "Matt A. Tobin" Date: Fri, 2 Feb 2018 04:16:08 -0500 Subject: Add m-esr52 at 52.6.0 --- dom/svg/nsSVGFilters.cpp | 567 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 567 insertions(+) create mode 100644 dom/svg/nsSVGFilters.cpp (limited to 'dom/svg/nsSVGFilters.cpp') diff --git a/dom/svg/nsSVGFilters.cpp b/dom/svg/nsSVGFilters.cpp new file mode 100644 index 000000000..c677156c9 --- /dev/null +++ b/dom/svg/nsSVGFilters.cpp @@ -0,0 +1,567 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "mozilla/ArrayUtils.h" + +#include "nsSVGElement.h" +#include "nsGkAtoms.h" +#include "nsSVGNumber2.h" +#include "nsSVGNumberPair.h" +#include "nsSVGInteger.h" +#include "nsSVGIntegerPair.h" +#include "nsSVGBoolean.h" +#include "nsCOMPtr.h" +#include "nsSVGFilterInstance.h" +#include "nsSVGEnum.h" +#include "SVGNumberList.h" +#include "SVGAnimatedNumberList.h" +#include "DOMSVGAnimatedNumberList.h" +#include "nsSVGFilters.h" +#include "nsLayoutUtils.h" +#include "nsSVGUtils.h" +#include "nsStyleContext.h" +#include "nsIFrame.h" +#include "imgIContainer.h" +#include "mozilla/dom/SVGFilterElement.h" +#include "nsSVGString.h" +#include "SVGContentUtils.h" +#include +#include "mozilla/dom/SVGAnimatedLength.h" +#include "mozilla/dom/SVGComponentTransferFunctionElement.h" +#include "mozilla/dom/SVGFEDistantLightElement.h" +#include "mozilla/dom/SVGFEFuncAElementBinding.h" +#include "mozilla/dom/SVGFEFuncBElementBinding.h" +#include "mozilla/dom/SVGFEFuncGElementBinding.h" +#include "mozilla/dom/SVGFEFuncRElementBinding.h" +#include "mozilla/dom/SVGFEPointLightElement.h" +#include "mozilla/dom/SVGFESpotLightElement.h" + +#if defined(XP_WIN) +// Prevent Windows redefining LoadImage +#undef LoadImage +#endif + +using namespace mozilla; +using namespace mozilla::dom; +using namespace mozilla::gfx; + +//--------------------Filter Element Base Class----------------------- + +nsSVGElement::LengthInfo nsSVGFE::sLengthInfo[4] = +{ + { &nsGkAtoms::x, 0, nsIDOMSVGLength::SVG_LENGTHTYPE_PERCENTAGE, SVGContentUtils::X }, + { &nsGkAtoms::y, 0, nsIDOMSVGLength::SVG_LENGTHTYPE_PERCENTAGE, SVGContentUtils::Y }, + { &nsGkAtoms::width, 100, nsIDOMSVGLength::SVG_LENGTHTYPE_PERCENTAGE, SVGContentUtils::X }, + { &nsGkAtoms::height, 100, nsIDOMSVGLength::SVG_LENGTHTYPE_PERCENTAGE, SVGContentUtils::Y } +}; + +//---------------------------------------------------------------------- +// nsISupports methods + +NS_IMPL_ADDREF_INHERITED(nsSVGFE,nsSVGFEBase) +NS_IMPL_RELEASE_INHERITED(nsSVGFE,nsSVGFEBase) + +NS_INTERFACE_MAP_BEGIN(nsSVGFE) + // nsISupports is an ambiguous base of nsSVGFE so we have to work + // around that + if ( aIID.Equals(NS_GET_IID(nsSVGFE)) ) + foundInterface = static_cast(static_cast(this)); + else +NS_INTERFACE_MAP_END_INHERITING(nsSVGFEBase) + +//---------------------------------------------------------------------- +// Implementation + +void +nsSVGFE::GetSourceImageNames(nsTArray& aSources) +{ +} + +bool +nsSVGFE::OutputIsTainted(const nsTArray& aInputsAreTainted, + nsIPrincipal* aReferencePrincipal) +{ + // This is the default implementation for OutputIsTainted. + // Our output is tainted if we have at least one tainted input. + for (uint32_t i = 0; i < aInputsAreTainted.Length(); i++) { + if (aInputsAreTainted[i]) { + return true; + } + } + return false; +} + +bool +nsSVGFE::AttributeAffectsRendering(int32_t aNameSpaceID, + nsIAtom* aAttribute) const +{ + return aNameSpaceID == kNameSpaceID_None && + (aAttribute == nsGkAtoms::x || + aAttribute == nsGkAtoms::y || + aAttribute == nsGkAtoms::width || + aAttribute == nsGkAtoms::height || + aAttribute == nsGkAtoms::result); +} + +already_AddRefed +nsSVGFE::X() +{ + return mLengthAttributes[ATTR_X].ToDOMAnimatedLength(this); +} + +already_AddRefed +nsSVGFE::Y() +{ + return mLengthAttributes[ATTR_Y].ToDOMAnimatedLength(this); +} + +already_AddRefed +nsSVGFE::Width() +{ + return mLengthAttributes[ATTR_WIDTH].ToDOMAnimatedLength(this); +} + +already_AddRefed +nsSVGFE::Height() +{ + return mLengthAttributes[ATTR_HEIGHT].ToDOMAnimatedLength(this); +} + +already_AddRefed +nsSVGFE::Result() +{ + return GetResultImageName().ToDOMAnimatedString(this); +} + +//---------------------------------------------------------------------- +// nsIContent methods + +NS_IMETHODIMP_(bool) +nsSVGFE::IsAttributeMapped(const nsIAtom* name) const +{ + static const MappedAttributeEntry* const map[] = { + sFiltersMap + }; + + return FindAttributeDependence(name, map) || + nsSVGFEBase::IsAttributeMapped(name); +} + +//---------------------------------------------------------------------- +// nsSVGElement methods + + +bool +nsSVGFE::StyleIsSetToSRGB() +{ + nsIFrame* frame = GetPrimaryFrame(); + if (!frame) return false; + + nsStyleContext* style = frame->StyleContext(); + return style->StyleSVG()->mColorInterpolationFilters == + NS_STYLE_COLOR_INTERPOLATION_SRGB; +} + +/* virtual */ bool +nsSVGFE::HasValidDimensions() const +{ + return (!mLengthAttributes[ATTR_WIDTH].IsExplicitlySet() || + mLengthAttributes[ATTR_WIDTH].GetAnimValInSpecifiedUnits() > 0) && + (!mLengthAttributes[ATTR_HEIGHT].IsExplicitlySet() || + mLengthAttributes[ATTR_HEIGHT].GetAnimValInSpecifiedUnits() > 0); +} + +Size +nsSVGFE::GetKernelUnitLength(nsSVGFilterInstance* aInstance, + nsSVGNumberPair *aKernelUnitLength) +{ + if (!aKernelUnitLength->IsExplicitlySet()) { + return Size(1, 1); + } + + float kernelX = aInstance->GetPrimitiveNumber(SVGContentUtils::X, + aKernelUnitLength, + nsSVGNumberPair::eFirst); + float kernelY = aInstance->GetPrimitiveNumber(SVGContentUtils::Y, + aKernelUnitLength, + nsSVGNumberPair::eSecond); + return Size(kernelX, kernelY); +} + +nsSVGElement::LengthAttributesInfo +nsSVGFE::GetLengthInfo() +{ + return LengthAttributesInfo(mLengthAttributes, sLengthInfo, + ArrayLength(sLengthInfo)); +} + +namespace mozilla { +namespace dom { + +nsSVGElement::NumberListInfo SVGComponentTransferFunctionElement::sNumberListInfo[1] = +{ + { &nsGkAtoms::tableValues } +}; + +nsSVGElement::NumberInfo SVGComponentTransferFunctionElement::sNumberInfo[5] = +{ + { &nsGkAtoms::slope, 1, false }, + { &nsGkAtoms::intercept, 0, false }, + { &nsGkAtoms::amplitude, 1, false }, + { &nsGkAtoms::exponent, 1, false }, + { &nsGkAtoms::offset, 0, false } +}; + +nsSVGEnumMapping SVGComponentTransferFunctionElement::sTypeMap[] = { + {&nsGkAtoms::identity, + SVG_FECOMPONENTTRANSFER_TYPE_IDENTITY}, + {&nsGkAtoms::table, + SVG_FECOMPONENTTRANSFER_TYPE_TABLE}, + {&nsGkAtoms::discrete, + SVG_FECOMPONENTTRANSFER_TYPE_DISCRETE}, + {&nsGkAtoms::linear, + SVG_FECOMPONENTTRANSFER_TYPE_LINEAR}, + {&nsGkAtoms::gamma, + SVG_FECOMPONENTTRANSFER_TYPE_GAMMA}, + {nullptr, 0} +}; + +nsSVGElement::EnumInfo SVGComponentTransferFunctionElement::sEnumInfo[1] = +{ + { &nsGkAtoms::type, + sTypeMap, + SVG_FECOMPONENTTRANSFER_TYPE_IDENTITY + } +}; + +//---------------------------------------------------------------------- +// nsISupports methods + +NS_IMPL_ADDREF_INHERITED(SVGComponentTransferFunctionElement,SVGComponentTransferFunctionElementBase) +NS_IMPL_RELEASE_INHERITED(SVGComponentTransferFunctionElement,SVGComponentTransferFunctionElementBase) + +NS_INTERFACE_MAP_BEGIN(SVGComponentTransferFunctionElement) + // nsISupports is an ambiguous base of nsSVGFE so we have to work + // around that + if ( aIID.Equals(NS_GET_IID(SVGComponentTransferFunctionElement)) ) + foundInterface = static_cast(static_cast(this)); + else +NS_INTERFACE_MAP_END_INHERITING(SVGComponentTransferFunctionElementBase) + + +//---------------------------------------------------------------------- +// nsFEUnstyledElement methods + +bool +SVGComponentTransferFunctionElement::AttributeAffectsRendering(int32_t aNameSpaceID, + nsIAtom* aAttribute) const +{ + return aNameSpaceID == kNameSpaceID_None && + (aAttribute == nsGkAtoms::tableValues || + aAttribute == nsGkAtoms::slope || + aAttribute == nsGkAtoms::intercept || + aAttribute == nsGkAtoms::amplitude || + aAttribute == nsGkAtoms::exponent || + aAttribute == nsGkAtoms::offset || + aAttribute == nsGkAtoms::type); +} + +//---------------------------------------------------------------------- + +already_AddRefed +SVGComponentTransferFunctionElement::Type() +{ + return mEnumAttributes[TYPE].ToDOMAnimatedEnum(this); +} + +already_AddRefed +SVGComponentTransferFunctionElement::TableValues() +{ + return DOMSVGAnimatedNumberList::GetDOMWrapper( + &mNumberListAttributes[TABLEVALUES], this, TABLEVALUES); +} + +already_AddRefed +SVGComponentTransferFunctionElement::Slope() +{ + return mNumberAttributes[SLOPE].ToDOMAnimatedNumber(this); +} + +already_AddRefed +SVGComponentTransferFunctionElement::Intercept() +{ + return mNumberAttributes[INTERCEPT].ToDOMAnimatedNumber(this); +} + +already_AddRefed +SVGComponentTransferFunctionElement::Amplitude() +{ + return mNumberAttributes[AMPLITUDE].ToDOMAnimatedNumber(this); +} + +already_AddRefed +SVGComponentTransferFunctionElement::Exponent() +{ + return mNumberAttributes[EXPONENT].ToDOMAnimatedNumber(this); +} + +already_AddRefed +SVGComponentTransferFunctionElement::Offset() +{ + return mNumberAttributes[OFFSET].ToDOMAnimatedNumber(this); +} + +AttributeMap +SVGComponentTransferFunctionElement::ComputeAttributes() +{ + uint32_t type = mEnumAttributes[TYPE].GetAnimValue(); + + float slope, intercept, amplitude, exponent, offset; + GetAnimatedNumberValues(&slope, &intercept, &litude, + &exponent, &offset, nullptr); + + const SVGNumberList &tableValues = + mNumberListAttributes[TABLEVALUES].GetAnimValue(); + + AttributeMap map; + map.Set(eComponentTransferFunctionType, type); + map.Set(eComponentTransferFunctionSlope, slope); + map.Set(eComponentTransferFunctionIntercept, intercept); + map.Set(eComponentTransferFunctionAmplitude, amplitude); + map.Set(eComponentTransferFunctionExponent, exponent); + map.Set(eComponentTransferFunctionOffset, offset); + if (tableValues.Length()) { + map.Set(eComponentTransferFunctionTableValues, &tableValues[0], tableValues.Length()); + } else { + map.Set(eComponentTransferFunctionTableValues, nullptr, 0); + } + return map; +} + +//---------------------------------------------------------------------- +// nsSVGElement methods + +nsSVGElement::NumberListAttributesInfo +SVGComponentTransferFunctionElement::GetNumberListInfo() +{ + return NumberListAttributesInfo(mNumberListAttributes, sNumberListInfo, + ArrayLength(sNumberListInfo)); +} + +nsSVGElement::EnumAttributesInfo +SVGComponentTransferFunctionElement::GetEnumInfo() +{ + return EnumAttributesInfo(mEnumAttributes, sEnumInfo, + ArrayLength(sEnumInfo)); +} + +nsSVGElement::NumberAttributesInfo +SVGComponentTransferFunctionElement::GetNumberInfo() +{ + return NumberAttributesInfo(mNumberAttributes, sNumberInfo, + ArrayLength(sNumberInfo)); +} + +/* virtual */ JSObject* +SVGFEFuncRElement::WrapNode(JSContext* aCx, JS::Handle aGivenProto) +{ + return SVGFEFuncRElementBinding::Wrap(aCx, this, aGivenProto); +} + +} // namespace dom +} // namespace mozilla + +NS_IMPL_NS_NEW_NAMESPACED_SVG_ELEMENT(FEFuncR) + +namespace mozilla { +namespace dom { + +NS_IMPL_ELEMENT_CLONE_WITH_INIT(SVGFEFuncRElement) + +/* virtual */ JSObject* +SVGFEFuncGElement::WrapNode(JSContext* aCx, JS::Handle aGivenProto) +{ + return SVGFEFuncGElementBinding::Wrap(aCx, this, aGivenProto); +} + +} // namespace dom +} // namespace mozilla + +NS_IMPL_NS_NEW_NAMESPACED_SVG_ELEMENT(FEFuncG) + +namespace mozilla { +namespace dom { + +NS_IMPL_ELEMENT_CLONE_WITH_INIT(SVGFEFuncGElement) + +/* virtual */ JSObject* +SVGFEFuncBElement::WrapNode(JSContext* aCx, JS::Handle aGivenProto) +{ + return SVGFEFuncBElementBinding::Wrap(aCx, this, aGivenProto); +} + +} // namespace dom +} // namespace mozilla + +NS_IMPL_NS_NEW_NAMESPACED_SVG_ELEMENT(FEFuncB) + +namespace mozilla { +namespace dom { + +NS_IMPL_ELEMENT_CLONE_WITH_INIT(SVGFEFuncBElement) + +/* virtual */ JSObject* +SVGFEFuncAElement::WrapNode(JSContext* aCx, JS::Handle aGivenProto) +{ + return SVGFEFuncAElementBinding::Wrap(aCx, this, aGivenProto); +} + +} // namespace dom +} // namespace mozilla + +NS_IMPL_NS_NEW_NAMESPACED_SVG_ELEMENT(FEFuncA) + +namespace mozilla { +namespace dom { + +NS_IMPL_ELEMENT_CLONE_WITH_INIT(SVGFEFuncAElement) + +} // namespace dom +} // namespace mozilla + +//-------------------------------------------------------------------- +// +nsSVGElement::NumberInfo nsSVGFELightingElement::sNumberInfo[4] = +{ + { &nsGkAtoms::surfaceScale, 1, false }, + { &nsGkAtoms::diffuseConstant, 1, false }, + { &nsGkAtoms::specularConstant, 1, false }, + { &nsGkAtoms::specularExponent, 1, false } +}; + +nsSVGElement::NumberPairInfo nsSVGFELightingElement::sNumberPairInfo[1] = +{ + { &nsGkAtoms::kernelUnitLength, 0, 0 } +}; + +nsSVGElement::StringInfo nsSVGFELightingElement::sStringInfo[2] = +{ + { &nsGkAtoms::result, kNameSpaceID_None, true }, + { &nsGkAtoms::in, kNameSpaceID_None, true } +}; + +//---------------------------------------------------------------------- +// nsISupports methods + +NS_IMPL_ADDREF_INHERITED(nsSVGFELightingElement,nsSVGFELightingElementBase) +NS_IMPL_RELEASE_INHERITED(nsSVGFELightingElement,nsSVGFELightingElementBase) + +NS_INTERFACE_MAP_BEGIN(nsSVGFELightingElement) +NS_INTERFACE_MAP_END_INHERITING(nsSVGFELightingElementBase) + +//---------------------------------------------------------------------- +// Implementation + +NS_IMETHODIMP_(bool) +nsSVGFELightingElement::IsAttributeMapped(const nsIAtom* name) const +{ + static const MappedAttributeEntry* const map[] = { + sLightingEffectsMap + }; + + return FindAttributeDependence(name, map) || + nsSVGFELightingElementBase::IsAttributeMapped(name); +} + +void +nsSVGFELightingElement::GetSourceImageNames(nsTArray& aSources) +{ + aSources.AppendElement(nsSVGStringInfo(&mStringAttributes[IN1], this)); +} + +AttributeMap +nsSVGFELightingElement::ComputeLightAttributes(nsSVGFilterInstance* aInstance) +{ + // find specified light + for (nsCOMPtr child = nsINode::GetFirstChild(); + child; + child = child->GetNextSibling()) { + if (child->IsAnyOfSVGElements(nsGkAtoms::feDistantLight, + nsGkAtoms::fePointLight, + nsGkAtoms::feSpotLight)) { + return static_cast(child.get())->ComputeLightAttributes(aInstance); + } + } + + AttributeMap map; + map.Set(eLightType, (uint32_t)eLightTypeNone); + return map; +} + +FilterPrimitiveDescription +nsSVGFELightingElement::AddLightingAttributes(FilterPrimitiveDescription aDescription, + nsSVGFilterInstance* aInstance) +{ + nsIFrame* frame = GetPrimaryFrame(); + if (!frame) { + return FilterPrimitiveDescription(PrimitiveType::Empty); + } + + nsStyleContext* style = frame->StyleContext(); + Color color(Color::FromABGR(style->StyleSVGReset()->mLightingColor)); + color.a = 1.f; + float surfaceScale = mNumberAttributes[SURFACE_SCALE].GetAnimValue(); + Size kernelUnitLength = + GetKernelUnitLength(aInstance, &mNumberPairAttributes[KERNEL_UNIT_LENGTH]); + + if (kernelUnitLength.width <= 0 || kernelUnitLength.height <= 0) { + // According to spec, A negative or zero value is an error. See link below for details. + // https://www.w3.org/TR/SVG/filters.html#feSpecularLightingKernelUnitLengthAttribute + return FilterPrimitiveDescription(PrimitiveType::Empty); + } + + FilterPrimitiveDescription& descr = aDescription; + descr.Attributes().Set(eLightingLight, ComputeLightAttributes(aInstance)); + descr.Attributes().Set(eLightingSurfaceScale, surfaceScale); + descr.Attributes().Set(eLightingKernelUnitLength, kernelUnitLength); + descr.Attributes().Set(eLightingColor, color); + return descr; +} + +bool +nsSVGFELightingElement::AttributeAffectsRendering(int32_t aNameSpaceID, + nsIAtom* aAttribute) const +{ + return nsSVGFELightingElementBase::AttributeAffectsRendering(aNameSpaceID, aAttribute) || + (aNameSpaceID == kNameSpaceID_None && + (aAttribute == nsGkAtoms::in || + aAttribute == nsGkAtoms::surfaceScale || + aAttribute == nsGkAtoms::kernelUnitLength)); +} + +//---------------------------------------------------------------------- +// nsSVGElement methods + +nsSVGElement::NumberAttributesInfo +nsSVGFELightingElement::GetNumberInfo() +{ + return NumberAttributesInfo(mNumberAttributes, sNumberInfo, + ArrayLength(sNumberInfo)); +} + +nsSVGElement::NumberPairAttributesInfo +nsSVGFELightingElement::GetNumberPairInfo() +{ + return NumberPairAttributesInfo(mNumberPairAttributes, sNumberPairInfo, + ArrayLength(sNumberPairInfo)); +} + +nsSVGElement::StringAttributesInfo +nsSVGFELightingElement::GetStringInfo() +{ + return StringAttributesInfo(mStringAttributes, sStringInfo, + ArrayLength(sStringInfo)); +} -- cgit v1.2.3