SVGFEConvolveMatrixElement.cpp (9899B)
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 9 #include <numeric> 10 11 #include "DOMSVGAnimatedNumberList.h" 12 #include "mozilla/SVGFilterInstance.h" 13 #include "mozilla/SVGUtils.h" 14 #include "mozilla/dom/BindContext.h" 15 #include "mozilla/dom/Document.h" 16 #include "mozilla/dom/SVGFEConvolveMatrixElementBinding.h" 17 18 NS_IMPL_NS_NEW_SVG_ELEMENT(FEConvolveMatrix) 19 20 using namespace mozilla::gfx; 21 22 namespace mozilla::dom { 23 24 JSObject* SVGFEConvolveMatrixElement::WrapNode( 25 JSContext* aCx, JS::Handle<JSObject*> aGivenProto) { 26 return SVGFEConvolveMatrixElement_Binding::Wrap(aCx, this, aGivenProto); 27 } 28 29 SVGElement::NumberInfo SVGFEConvolveMatrixElement::sNumberInfo[2] = { 30 {nsGkAtoms::divisor, 1}, {nsGkAtoms::bias, 0}}; 31 32 SVGElement::NumberPairInfo SVGFEConvolveMatrixElement::sNumberPairInfo[1] = { 33 {nsGkAtoms::kernelUnitLength, 0, 0}}; 34 35 SVGElement::IntegerInfo SVGFEConvolveMatrixElement::sIntegerInfo[2] = { 36 {nsGkAtoms::targetX, 0}, {nsGkAtoms::targetY, 0}}; 37 38 SVGElement::IntegerPairInfo SVGFEConvolveMatrixElement::sIntegerPairInfo[1] = { 39 {nsGkAtoms::order, 3, 3}}; 40 41 SVGElement::BooleanInfo SVGFEConvolveMatrixElement::sBooleanInfo[1] = { 42 {nsGkAtoms::preserveAlpha, false}}; 43 44 SVGEnumMapping SVGFEConvolveMatrixElement::sEdgeModeMap[] = { 45 {nsGkAtoms::duplicate, SVG_EDGEMODE_DUPLICATE}, 46 {nsGkAtoms::wrap, SVG_EDGEMODE_WRAP}, 47 {nsGkAtoms::none, SVG_EDGEMODE_NONE}, 48 {nullptr, 0}}; 49 50 SVGElement::EnumInfo SVGFEConvolveMatrixElement::sEnumInfo[1] = { 51 {nsGkAtoms::edgeMode, sEdgeModeMap, SVG_EDGEMODE_DUPLICATE}}; 52 53 SVGElement::StringInfo SVGFEConvolveMatrixElement::sStringInfo[2] = { 54 {nsGkAtoms::result, kNameSpaceID_None, true}, 55 {nsGkAtoms::in, kNameSpaceID_None, true}}; 56 57 SVGElement::NumberListInfo SVGFEConvolveMatrixElement::sNumberListInfo[1] = { 58 {nsGkAtoms::kernelMatrix}}; 59 60 //---------------------------------------------------------------------- 61 // nsINode methods 62 63 NS_IMPL_ELEMENT_CLONE_WITH_INIT(SVGFEConvolveMatrixElement) 64 65 //---------------------------------------------------------------------- 66 67 already_AddRefed<DOMSVGAnimatedString> SVGFEConvolveMatrixElement::In1() { 68 return mStringAttributes[IN1].ToDOMAnimatedString(this); 69 } 70 71 already_AddRefed<DOMSVGAnimatedInteger> SVGFEConvolveMatrixElement::OrderX() { 72 return mIntegerPairAttributes[ORDER].ToDOMAnimatedInteger( 73 SVGAnimatedIntegerPair::eFirst, this); 74 } 75 76 already_AddRefed<DOMSVGAnimatedInteger> SVGFEConvolveMatrixElement::OrderY() { 77 return mIntegerPairAttributes[ORDER].ToDOMAnimatedInteger( 78 SVGAnimatedIntegerPair::eSecond, this); 79 } 80 81 already_AddRefed<DOMSVGAnimatedNumberList> 82 SVGFEConvolveMatrixElement::KernelMatrix() { 83 return DOMSVGAnimatedNumberList::GetDOMWrapper( 84 &mNumberListAttributes[KERNELMATRIX], this, KERNELMATRIX); 85 } 86 87 already_AddRefed<DOMSVGAnimatedInteger> SVGFEConvolveMatrixElement::TargetX() { 88 return mIntegerAttributes[TARGET_X].ToDOMAnimatedInteger(this); 89 } 90 91 already_AddRefed<DOMSVGAnimatedInteger> SVGFEConvolveMatrixElement::TargetY() { 92 return mIntegerAttributes[TARGET_Y].ToDOMAnimatedInteger(this); 93 } 94 95 already_AddRefed<DOMSVGAnimatedEnumeration> 96 SVGFEConvolveMatrixElement::EdgeMode() { 97 return mEnumAttributes[EDGEMODE].ToDOMAnimatedEnum(this); 98 } 99 100 already_AddRefed<DOMSVGAnimatedBoolean> 101 SVGFEConvolveMatrixElement::PreserveAlpha() { 102 return mBooleanAttributes[PRESERVEALPHA].ToDOMAnimatedBoolean(this); 103 } 104 105 already_AddRefed<DOMSVGAnimatedNumber> SVGFEConvolveMatrixElement::Divisor() { 106 return mNumberAttributes[DIVISOR].ToDOMAnimatedNumber(this); 107 } 108 109 already_AddRefed<DOMSVGAnimatedNumber> SVGFEConvolveMatrixElement::Bias() { 110 return mNumberAttributes[BIAS].ToDOMAnimatedNumber(this); 111 } 112 113 already_AddRefed<DOMSVGAnimatedNumber> 114 SVGFEConvolveMatrixElement::KernelUnitLengthX() { 115 return mNumberPairAttributes[KERNEL_UNIT_LENGTH].ToDOMAnimatedNumber( 116 SVGAnimatedNumberPair::eFirst, this); 117 } 118 119 already_AddRefed<DOMSVGAnimatedNumber> 120 SVGFEConvolveMatrixElement::KernelUnitLengthY() { 121 return mNumberPairAttributes[KERNEL_UNIT_LENGTH].ToDOMAnimatedNumber( 122 SVGAnimatedNumberPair::eSecond, this); 123 } 124 125 void SVGFEConvolveMatrixElement::GetSourceImageNames( 126 nsTArray<SVGStringInfo>& aSources) { 127 aSources.AppendElement(SVGStringInfo(&mStringAttributes[IN1], this)); 128 } 129 130 FilterPrimitiveDescription SVGFEConvolveMatrixElement::GetPrimitiveDescription( 131 SVGFilterInstance* aInstance, const IntRect& aFilterSubregion, 132 const nsTArray<bool>& aInputsAreTainted, 133 nsTArray<RefPtr<SourceSurface>>& aInputImages) { 134 FilterPrimitiveDescription failureDescription; 135 136 const SVGNumberList& kernelMatrix = 137 mNumberListAttributes[KERNELMATRIX].GetAnimValue(); 138 uint32_t kmLength = kernelMatrix.Length(); 139 140 int32_t orderX = mIntegerPairAttributes[ORDER].GetAnimValue( 141 SVGAnimatedIntegerPair::eFirst); 142 int32_t orderY = mIntegerPairAttributes[ORDER].GetAnimValue( 143 SVGAnimatedIntegerPair::eSecond); 144 145 if (orderX <= 0 || orderY <= 0 || 146 static_cast<uint32_t>(orderX * orderY) != kmLength) { 147 return failureDescription; 148 } 149 150 int32_t targetX, targetY; 151 GetAnimatedIntegerValues(&targetX, &targetY, nullptr); 152 153 if (mIntegerAttributes[TARGET_X].IsExplicitlySet()) { 154 if (targetX < 0 || targetX >= orderX) return failureDescription; 155 } else { 156 targetX = orderX / 2; 157 } 158 if (mIntegerAttributes[TARGET_Y].IsExplicitlySet()) { 159 if (targetY < 0 || targetY >= orderY) return failureDescription; 160 } else { 161 targetY = orderY / 2; 162 } 163 164 if (orderX > kReasonableSurfaceSize || orderY > kReasonableSurfaceSize) 165 return failureDescription; 166 167 float divisor; 168 if (mNumberAttributes[DIVISOR].IsExplicitlySet()) { 169 divisor = mNumberAttributes[DIVISOR].GetAnimValue(); 170 } 171 if (!mNumberAttributes[DIVISOR].IsExplicitlySet() || divisor == 0) { 172 divisor = std::accumulate(kernelMatrix.begin(), kernelMatrix.end(), 0.0f); 173 if (divisor == 0) { 174 divisor = 1; 175 } 176 } 177 178 uint32_t edgeMode = mEnumAttributes[EDGEMODE].GetAnimValue(); 179 bool preserveAlpha = mBooleanAttributes[PRESERVEALPHA].GetAnimValue(); 180 float bias = mNumberAttributes[BIAS].GetAnimValue(); 181 182 Size kernelUnitLength = GetKernelUnitLength( 183 aInstance, &mNumberPairAttributes[KERNEL_UNIT_LENGTH]); 184 185 MOZ_ASSERT(kernelUnitLength.width > 0.0f && kernelUnitLength.height > 0.0f, 186 "Expecting positive kernelUnitLength values"); 187 188 ConvolveMatrixAttributes atts; 189 atts.mKernelSize = IntSize(orderX, orderY); 190 atts.mKernelMatrix.AppendElements(&kernelMatrix[0], kmLength); 191 atts.mDivisor = divisor; 192 atts.mBias = bias; 193 atts.mTarget = IntPoint(targetX, targetY); 194 atts.mEdgeMode = edgeMode; 195 atts.mKernelUnitLength = kernelUnitLength; 196 atts.mPreserveAlpha = preserveAlpha; 197 198 return FilterPrimitiveDescription(AsVariant(std::move(atts))); 199 } 200 201 bool SVGFEConvolveMatrixElement::AttributeAffectsRendering( 202 int32_t aNameSpaceID, nsAtom* aAttribute) const { 203 return SVGFEConvolveMatrixElementBase::AttributeAffectsRendering( 204 aNameSpaceID, aAttribute) || 205 (aNameSpaceID == kNameSpaceID_None && 206 (aAttribute == nsGkAtoms::in || aAttribute == nsGkAtoms::divisor || 207 aAttribute == nsGkAtoms::bias || 208 aAttribute == nsGkAtoms::kernelUnitLength || 209 aAttribute == nsGkAtoms::targetX || 210 aAttribute == nsGkAtoms::targetY || aAttribute == nsGkAtoms::order || 211 aAttribute == nsGkAtoms::preserveAlpha || 212 aAttribute == nsGkAtoms::edgeMode || 213 aAttribute == nsGkAtoms::kernelMatrix)); 214 } 215 216 nsresult SVGFEConvolveMatrixElement::BindToTree(BindContext& aCtx, 217 nsINode& aParent) { 218 if (aCtx.InComposedDoc()) { 219 aCtx.OwnerDoc().SetUseCounter(eUseCounter_custom_feConvolveMatrix); 220 } 221 222 return SVGFEConvolveMatrixElementBase::BindToTree(aCtx, aParent); 223 } 224 225 //---------------------------------------------------------------------- 226 // SVGElement methods 227 228 SVGElement::NumberAttributesInfo SVGFEConvolveMatrixElement::GetNumberInfo() { 229 return NumberAttributesInfo(mNumberAttributes, sNumberInfo, 230 std::size(sNumberInfo)); 231 } 232 233 SVGElement::NumberPairAttributesInfo 234 SVGFEConvolveMatrixElement::GetNumberPairInfo() { 235 return NumberPairAttributesInfo(mNumberPairAttributes, sNumberPairInfo, 236 std::size(sNumberPairInfo)); 237 } 238 239 SVGElement::IntegerAttributesInfo SVGFEConvolveMatrixElement::GetIntegerInfo() { 240 return IntegerAttributesInfo(mIntegerAttributes, sIntegerInfo, 241 std::size(sIntegerInfo)); 242 } 243 244 SVGElement::IntegerPairAttributesInfo 245 SVGFEConvolveMatrixElement::GetIntegerPairInfo() { 246 return IntegerPairAttributesInfo(mIntegerPairAttributes, sIntegerPairInfo, 247 std::size(sIntegerPairInfo)); 248 } 249 250 SVGElement::BooleanAttributesInfo SVGFEConvolveMatrixElement::GetBooleanInfo() { 251 return BooleanAttributesInfo(mBooleanAttributes, sBooleanInfo, 252 std::size(sBooleanInfo)); 253 } 254 255 SVGElement::EnumAttributesInfo SVGFEConvolveMatrixElement::GetEnumInfo() { 256 return EnumAttributesInfo(mEnumAttributes, sEnumInfo, std::size(sEnumInfo)); 257 } 258 259 SVGElement::StringAttributesInfo SVGFEConvolveMatrixElement::GetStringInfo() { 260 return StringAttributesInfo(mStringAttributes, sStringInfo, 261 std::size(sStringInfo)); 262 } 263 264 SVGElement::NumberListAttributesInfo 265 SVGFEConvolveMatrixElement::GetNumberListInfo() { 266 return NumberListAttributesInfo(mNumberListAttributes, sNumberListInfo, 267 std::size(sNumberListInfo)); 268 } 269 270 } // namespace mozilla::dom