diff options
Diffstat (limited to 'dom/svg/SVGFEConvolveMatrixElement.cpp')
-rw-r--r-- | dom/svg/SVGFEConvolveMatrixElement.cpp | 333 |
1 files changed, 333 insertions, 0 deletions
diff --git a/dom/svg/SVGFEConvolveMatrixElement.cpp b/dom/svg/SVGFEConvolveMatrixElement.cpp new file mode 100644 index 000000000..3d387ca6a --- /dev/null +++ b/dom/svg/SVGFEConvolveMatrixElement.cpp @@ -0,0 +1,333 @@ +/* -*- 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/dom/SVGFEConvolveMatrixElement.h" +#include "mozilla/dom/SVGFEConvolveMatrixElementBinding.h" +#include "mozilla/UniquePtr.h" +#include "mozilla/UniquePtrExtensions.h" +#include "DOMSVGAnimatedNumberList.h" +#include "nsSVGUtils.h" +#include "nsSVGFilterInstance.h" + +NS_IMPL_NS_NEW_NAMESPACED_SVG_ELEMENT(FEConvolveMatrix) + +using namespace mozilla::gfx; + +namespace mozilla { +namespace dom { + +JSObject* +SVGFEConvolveMatrixElement::WrapNode(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) +{ + return SVGFEConvolveMatrixElementBinding::Wrap(aCx, this, aGivenProto); +} + +nsSVGElement::NumberInfo SVGFEConvolveMatrixElement::sNumberInfo[2] = +{ + { &nsGkAtoms::divisor, 1, false }, + { &nsGkAtoms::bias, 0, false } +}; + +nsSVGElement::NumberPairInfo SVGFEConvolveMatrixElement::sNumberPairInfo[1] = +{ + { &nsGkAtoms::kernelUnitLength, 0, 0 } +}; + +nsSVGElement::IntegerInfo SVGFEConvolveMatrixElement::sIntegerInfo[2] = +{ + { &nsGkAtoms::targetX, 0 }, + { &nsGkAtoms::targetY, 0 } +}; + +nsSVGElement::IntegerPairInfo SVGFEConvolveMatrixElement::sIntegerPairInfo[1] = +{ + { &nsGkAtoms::order, 3, 3 } +}; + +nsSVGElement::BooleanInfo SVGFEConvolveMatrixElement::sBooleanInfo[1] = +{ + { &nsGkAtoms::preserveAlpha, false } +}; + +nsSVGEnumMapping SVGFEConvolveMatrixElement::sEdgeModeMap[] = { + {&nsGkAtoms::duplicate, SVG_EDGEMODE_DUPLICATE}, + {&nsGkAtoms::wrap, SVG_EDGEMODE_WRAP}, + {&nsGkAtoms::none, SVG_EDGEMODE_NONE}, + {nullptr, 0} +}; + +nsSVGElement::EnumInfo SVGFEConvolveMatrixElement::sEnumInfo[1] = +{ + { &nsGkAtoms::edgeMode, + sEdgeModeMap, + SVG_EDGEMODE_DUPLICATE + } +}; + +nsSVGElement::StringInfo SVGFEConvolveMatrixElement::sStringInfo[2] = +{ + { &nsGkAtoms::result, kNameSpaceID_None, true }, + { &nsGkAtoms::in, kNameSpaceID_None, true } +}; + +nsSVGElement::NumberListInfo SVGFEConvolveMatrixElement::sNumberListInfo[1] = +{ + { &nsGkAtoms::kernelMatrix } +}; + +//---------------------------------------------------------------------- +// nsIDOMNode methods + +NS_IMPL_ELEMENT_CLONE_WITH_INIT(SVGFEConvolveMatrixElement) + +//---------------------------------------------------------------------- + +already_AddRefed<SVGAnimatedString> +SVGFEConvolveMatrixElement::In1() +{ + return mStringAttributes[IN1].ToDOMAnimatedString(this); +} + +already_AddRefed<SVGAnimatedInteger> +SVGFEConvolveMatrixElement::OrderX() +{ + return mIntegerPairAttributes[ORDER].ToDOMAnimatedInteger(nsSVGIntegerPair::eFirst, this); +} + +already_AddRefed<SVGAnimatedInteger> +SVGFEConvolveMatrixElement::OrderY() +{ + return mIntegerPairAttributes[ORDER].ToDOMAnimatedInteger(nsSVGIntegerPair::eSecond, this); +} + +already_AddRefed<DOMSVGAnimatedNumberList> +SVGFEConvolveMatrixElement::KernelMatrix() +{ + return DOMSVGAnimatedNumberList::GetDOMWrapper(&mNumberListAttributes[KERNELMATRIX], + this, KERNELMATRIX); +} + +already_AddRefed<SVGAnimatedInteger> +SVGFEConvolveMatrixElement::TargetX() +{ + return mIntegerAttributes[TARGET_X].ToDOMAnimatedInteger(this); +} + +already_AddRefed<SVGAnimatedInteger> +SVGFEConvolveMatrixElement::TargetY() +{ + return mIntegerAttributes[TARGET_Y].ToDOMAnimatedInteger(this); +} + +already_AddRefed<SVGAnimatedEnumeration> +SVGFEConvolveMatrixElement::EdgeMode() +{ + return mEnumAttributes[EDGEMODE].ToDOMAnimatedEnum(this); +} + +already_AddRefed<SVGAnimatedBoolean> +SVGFEConvolveMatrixElement::PreserveAlpha() +{ + return mBooleanAttributes[PRESERVEALPHA].ToDOMAnimatedBoolean(this); +} + +already_AddRefed<SVGAnimatedNumber> +SVGFEConvolveMatrixElement::Divisor() +{ + return mNumberAttributes[DIVISOR].ToDOMAnimatedNumber(this); +} + +already_AddRefed<SVGAnimatedNumber> +SVGFEConvolveMatrixElement::Bias() +{ + return mNumberAttributes[BIAS].ToDOMAnimatedNumber(this); +} + +already_AddRefed<SVGAnimatedNumber> +SVGFEConvolveMatrixElement::KernelUnitLengthX() +{ + return mNumberPairAttributes[KERNEL_UNIT_LENGTH].ToDOMAnimatedNumber(nsSVGNumberPair::eFirst, + this); +} + +already_AddRefed<SVGAnimatedNumber> +SVGFEConvolveMatrixElement::KernelUnitLengthY() +{ + return mNumberPairAttributes[KERNEL_UNIT_LENGTH].ToDOMAnimatedNumber(nsSVGNumberPair::eSecond, + this); +} + +void +SVGFEConvolveMatrixElement::GetSourceImageNames(nsTArray<nsSVGStringInfo>& aSources) +{ + aSources.AppendElement(nsSVGStringInfo(&mStringAttributes[IN1], this)); +} + +FilterPrimitiveDescription +SVGFEConvolveMatrixElement::GetPrimitiveDescription(nsSVGFilterInstance* aInstance, + const IntRect& aFilterSubregion, + const nsTArray<bool>& aInputsAreTainted, + nsTArray<RefPtr<SourceSurface>>& aInputImages) +{ + const FilterPrimitiveDescription failureDescription(PrimitiveType::Empty); + + const SVGNumberList &kernelMatrix = + mNumberListAttributes[KERNELMATRIX].GetAnimValue(); + uint32_t kmLength = kernelMatrix.Length(); + + int32_t orderX = mIntegerPairAttributes[ORDER].GetAnimValue(nsSVGIntegerPair::eFirst); + int32_t orderY = mIntegerPairAttributes[ORDER].GetAnimValue(nsSVGIntegerPair::eSecond); + + if (orderX <= 0 || orderY <= 0 || + static_cast<uint32_t>(orderX * orderY) != kmLength) { + return failureDescription; + } + + int32_t targetX, targetY; + GetAnimatedIntegerValues(&targetX, &targetY, nullptr); + + if (mIntegerAttributes[TARGET_X].IsExplicitlySet()) { + if (targetX < 0 || targetX >= orderX) + return failureDescription; + } else { + targetX = orderX / 2; + } + if (mIntegerAttributes[TARGET_Y].IsExplicitlySet()) { + if (targetY < 0 || targetY >= orderY) + return failureDescription; + } else { + targetY = orderY / 2; + } + + if (orderX > NS_SVG_OFFSCREEN_MAX_DIMENSION || + orderY > NS_SVG_OFFSCREEN_MAX_DIMENSION) + return failureDescription; + UniquePtr<float[]> kernel = MakeUniqueFallible<float[]>(orderX * orderY); + if (!kernel) + return failureDescription; + for (uint32_t i = 0; i < kmLength; i++) { + kernel[kmLength - 1 - i] = kernelMatrix[i]; + } + + float divisor; + if (mNumberAttributes[DIVISOR].IsExplicitlySet()) { + divisor = mNumberAttributes[DIVISOR].GetAnimValue(); + if (divisor == 0) + return failureDescription; + } else { + divisor = kernel[0]; + for (uint32_t i = 1; i < kmLength; i++) + divisor += kernel[i]; + if (divisor == 0) + divisor = 1; + } + + uint32_t edgeMode = mEnumAttributes[EDGEMODE].GetAnimValue(); + bool preserveAlpha = mBooleanAttributes[PRESERVEALPHA].GetAnimValue(); + float bias = mNumberAttributes[BIAS].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#feConvolveMatrixElementKernelUnitLengthAttribute + return failureDescription; + } + + FilterPrimitiveDescription descr(PrimitiveType::ConvolveMatrix); + AttributeMap& atts = descr.Attributes(); + atts.Set(eConvolveMatrixKernelSize, IntSize(orderX, orderY)); + atts.Set(eConvolveMatrixKernelMatrix, &kernelMatrix[0], kmLength); + atts.Set(eConvolveMatrixDivisor, divisor); + atts.Set(eConvolveMatrixBias, bias); + atts.Set(eConvolveMatrixTarget, IntPoint(targetX, targetY)); + atts.Set(eConvolveMatrixEdgeMode, edgeMode); + atts.Set(eConvolveMatrixKernelUnitLength, kernelUnitLength); + atts.Set(eConvolveMatrixPreserveAlpha, preserveAlpha); + + return descr; +} + +bool +SVGFEConvolveMatrixElement::AttributeAffectsRendering(int32_t aNameSpaceID, + nsIAtom* aAttribute) const +{ + return SVGFEConvolveMatrixElementBase::AttributeAffectsRendering(aNameSpaceID, aAttribute) || + (aNameSpaceID == kNameSpaceID_None && + (aAttribute == nsGkAtoms::in || + aAttribute == nsGkAtoms::divisor || + aAttribute == nsGkAtoms::bias || + aAttribute == nsGkAtoms::kernelUnitLength || + aAttribute == nsGkAtoms::targetX || + aAttribute == nsGkAtoms::targetY || + aAttribute == nsGkAtoms::order || + aAttribute == nsGkAtoms::preserveAlpha|| + aAttribute == nsGkAtoms::edgeMode || + aAttribute == nsGkAtoms::kernelMatrix)); +} + +//---------------------------------------------------------------------- +// nsSVGElement methods + +nsSVGElement::NumberAttributesInfo +SVGFEConvolveMatrixElement::GetNumberInfo() +{ + return NumberAttributesInfo(mNumberAttributes, sNumberInfo, + ArrayLength(sNumberInfo)); +} + +nsSVGElement::NumberPairAttributesInfo +SVGFEConvolveMatrixElement::GetNumberPairInfo() +{ + return NumberPairAttributesInfo(mNumberPairAttributes, sNumberPairInfo, + ArrayLength(sNumberPairInfo)); +} + +nsSVGElement::IntegerAttributesInfo +SVGFEConvolveMatrixElement::GetIntegerInfo() +{ + return IntegerAttributesInfo(mIntegerAttributes, sIntegerInfo, + ArrayLength(sIntegerInfo)); +} + +nsSVGElement::IntegerPairAttributesInfo +SVGFEConvolveMatrixElement::GetIntegerPairInfo() +{ + return IntegerPairAttributesInfo(mIntegerPairAttributes, sIntegerPairInfo, + ArrayLength(sIntegerPairInfo)); +} + +nsSVGElement::BooleanAttributesInfo +SVGFEConvolveMatrixElement::GetBooleanInfo() +{ + return BooleanAttributesInfo(mBooleanAttributes, sBooleanInfo, + ArrayLength(sBooleanInfo)); +} + +nsSVGElement::EnumAttributesInfo +SVGFEConvolveMatrixElement::GetEnumInfo() +{ + return EnumAttributesInfo(mEnumAttributes, sEnumInfo, + ArrayLength(sEnumInfo)); +} + +nsSVGElement::StringAttributesInfo +SVGFEConvolveMatrixElement::GetStringInfo() +{ + return StringAttributesInfo(mStringAttributes, sStringInfo, + ArrayLength(sStringInfo)); +} + +nsSVGElement::NumberListAttributesInfo +SVGFEConvolveMatrixElement::GetNumberListInfo() +{ + return NumberListAttributesInfo(mNumberListAttributes, sNumberListInfo, + ArrayLength(sNumberListInfo)); +} + +} // namespace dom +} // namespace mozilla |