SVGFEConvolveMatrixElement.cpp 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333
  1. /* -*- Mode: C++; tab-width: 8; 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/. */
  5. #include "mozilla/dom/SVGFEConvolveMatrixElement.h"
  6. #include "mozilla/dom/SVGFEConvolveMatrixElementBinding.h"
  7. #include "mozilla/UniquePtr.h"
  8. #include "mozilla/UniquePtrExtensions.h"
  9. #include "DOMSVGAnimatedNumberList.h"
  10. #include "nsSVGUtils.h"
  11. #include "nsSVGFilterInstance.h"
  12. NS_IMPL_NS_NEW_NAMESPACED_SVG_ELEMENT(FEConvolveMatrix)
  13. using namespace mozilla::gfx;
  14. namespace mozilla {
  15. namespace dom {
  16. JSObject*
  17. SVGFEConvolveMatrixElement::WrapNode(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
  18. {
  19. return SVGFEConvolveMatrixElementBinding::Wrap(aCx, this, aGivenProto);
  20. }
  21. nsSVGElement::NumberInfo SVGFEConvolveMatrixElement::sNumberInfo[2] =
  22. {
  23. { &nsGkAtoms::divisor, 1, false },
  24. { &nsGkAtoms::bias, 0, false }
  25. };
  26. nsSVGElement::NumberPairInfo SVGFEConvolveMatrixElement::sNumberPairInfo[1] =
  27. {
  28. { &nsGkAtoms::kernelUnitLength, 0, 0 }
  29. };
  30. nsSVGElement::IntegerInfo SVGFEConvolveMatrixElement::sIntegerInfo[2] =
  31. {
  32. { &nsGkAtoms::targetX, 0 },
  33. { &nsGkAtoms::targetY, 0 }
  34. };
  35. nsSVGElement::IntegerPairInfo SVGFEConvolveMatrixElement::sIntegerPairInfo[1] =
  36. {
  37. { &nsGkAtoms::order, 3, 3 }
  38. };
  39. nsSVGElement::BooleanInfo SVGFEConvolveMatrixElement::sBooleanInfo[1] =
  40. {
  41. { &nsGkAtoms::preserveAlpha, false }
  42. };
  43. nsSVGEnumMapping SVGFEConvolveMatrixElement::sEdgeModeMap[] = {
  44. {&nsGkAtoms::duplicate, SVG_EDGEMODE_DUPLICATE},
  45. {&nsGkAtoms::wrap, SVG_EDGEMODE_WRAP},
  46. {&nsGkAtoms::none, SVG_EDGEMODE_NONE},
  47. {nullptr, 0}
  48. };
  49. nsSVGElement::EnumInfo SVGFEConvolveMatrixElement::sEnumInfo[1] =
  50. {
  51. { &nsGkAtoms::edgeMode,
  52. sEdgeModeMap,
  53. SVG_EDGEMODE_DUPLICATE
  54. }
  55. };
  56. nsSVGElement::StringInfo SVGFEConvolveMatrixElement::sStringInfo[2] =
  57. {
  58. { &nsGkAtoms::result, kNameSpaceID_None, true },
  59. { &nsGkAtoms::in, kNameSpaceID_None, true }
  60. };
  61. nsSVGElement::NumberListInfo SVGFEConvolveMatrixElement::sNumberListInfo[1] =
  62. {
  63. { &nsGkAtoms::kernelMatrix }
  64. };
  65. //----------------------------------------------------------------------
  66. // nsIDOMNode methods
  67. NS_IMPL_ELEMENT_CLONE_WITH_INIT(SVGFEConvolveMatrixElement)
  68. //----------------------------------------------------------------------
  69. already_AddRefed<SVGAnimatedString>
  70. SVGFEConvolveMatrixElement::In1()
  71. {
  72. return mStringAttributes[IN1].ToDOMAnimatedString(this);
  73. }
  74. already_AddRefed<SVGAnimatedInteger>
  75. SVGFEConvolveMatrixElement::OrderX()
  76. {
  77. return mIntegerPairAttributes[ORDER].ToDOMAnimatedInteger(nsSVGIntegerPair::eFirst, this);
  78. }
  79. already_AddRefed<SVGAnimatedInteger>
  80. SVGFEConvolveMatrixElement::OrderY()
  81. {
  82. return mIntegerPairAttributes[ORDER].ToDOMAnimatedInteger(nsSVGIntegerPair::eSecond, this);
  83. }
  84. already_AddRefed<DOMSVGAnimatedNumberList>
  85. SVGFEConvolveMatrixElement::KernelMatrix()
  86. {
  87. return DOMSVGAnimatedNumberList::GetDOMWrapper(&mNumberListAttributes[KERNELMATRIX],
  88. this, KERNELMATRIX);
  89. }
  90. already_AddRefed<SVGAnimatedInteger>
  91. SVGFEConvolveMatrixElement::TargetX()
  92. {
  93. return mIntegerAttributes[TARGET_X].ToDOMAnimatedInteger(this);
  94. }
  95. already_AddRefed<SVGAnimatedInteger>
  96. SVGFEConvolveMatrixElement::TargetY()
  97. {
  98. return mIntegerAttributes[TARGET_Y].ToDOMAnimatedInteger(this);
  99. }
  100. already_AddRefed<SVGAnimatedEnumeration>
  101. SVGFEConvolveMatrixElement::EdgeMode()
  102. {
  103. return mEnumAttributes[EDGEMODE].ToDOMAnimatedEnum(this);
  104. }
  105. already_AddRefed<SVGAnimatedBoolean>
  106. SVGFEConvolveMatrixElement::PreserveAlpha()
  107. {
  108. return mBooleanAttributes[PRESERVEALPHA].ToDOMAnimatedBoolean(this);
  109. }
  110. already_AddRefed<SVGAnimatedNumber>
  111. SVGFEConvolveMatrixElement::Divisor()
  112. {
  113. return mNumberAttributes[DIVISOR].ToDOMAnimatedNumber(this);
  114. }
  115. already_AddRefed<SVGAnimatedNumber>
  116. SVGFEConvolveMatrixElement::Bias()
  117. {
  118. return mNumberAttributes[BIAS].ToDOMAnimatedNumber(this);
  119. }
  120. already_AddRefed<SVGAnimatedNumber>
  121. SVGFEConvolveMatrixElement::KernelUnitLengthX()
  122. {
  123. return mNumberPairAttributes[KERNEL_UNIT_LENGTH].ToDOMAnimatedNumber(nsSVGNumberPair::eFirst,
  124. this);
  125. }
  126. already_AddRefed<SVGAnimatedNumber>
  127. SVGFEConvolveMatrixElement::KernelUnitLengthY()
  128. {
  129. return mNumberPairAttributes[KERNEL_UNIT_LENGTH].ToDOMAnimatedNumber(nsSVGNumberPair::eSecond,
  130. this);
  131. }
  132. void
  133. SVGFEConvolveMatrixElement::GetSourceImageNames(nsTArray<nsSVGStringInfo>& aSources)
  134. {
  135. aSources.AppendElement(nsSVGStringInfo(&mStringAttributes[IN1], this));
  136. }
  137. FilterPrimitiveDescription
  138. SVGFEConvolveMatrixElement::GetPrimitiveDescription(nsSVGFilterInstance* aInstance,
  139. const IntRect& aFilterSubregion,
  140. const nsTArray<bool>& aInputsAreTainted,
  141. nsTArray<RefPtr<SourceSurface>>& aInputImages)
  142. {
  143. const FilterPrimitiveDescription failureDescription(PrimitiveType::Empty);
  144. const SVGNumberList &kernelMatrix =
  145. mNumberListAttributes[KERNELMATRIX].GetAnimValue();
  146. uint32_t kmLength = kernelMatrix.Length();
  147. int32_t orderX = mIntegerPairAttributes[ORDER].GetAnimValue(nsSVGIntegerPair::eFirst);
  148. int32_t orderY = mIntegerPairAttributes[ORDER].GetAnimValue(nsSVGIntegerPair::eSecond);
  149. if (orderX <= 0 || orderY <= 0 ||
  150. static_cast<uint32_t>(orderX * orderY) != kmLength) {
  151. return failureDescription;
  152. }
  153. int32_t targetX, targetY;
  154. GetAnimatedIntegerValues(&targetX, &targetY, nullptr);
  155. if (mIntegerAttributes[TARGET_X].IsExplicitlySet()) {
  156. if (targetX < 0 || targetX >= orderX)
  157. return failureDescription;
  158. } else {
  159. targetX = orderX / 2;
  160. }
  161. if (mIntegerAttributes[TARGET_Y].IsExplicitlySet()) {
  162. if (targetY < 0 || targetY >= orderY)
  163. return failureDescription;
  164. } else {
  165. targetY = orderY / 2;
  166. }
  167. if (orderX > NS_SVG_OFFSCREEN_MAX_DIMENSION ||
  168. orderY > NS_SVG_OFFSCREEN_MAX_DIMENSION)
  169. return failureDescription;
  170. UniquePtr<float[]> kernel = MakeUniqueFallible<float[]>(orderX * orderY);
  171. if (!kernel)
  172. return failureDescription;
  173. for (uint32_t i = 0; i < kmLength; i++) {
  174. kernel[kmLength - 1 - i] = kernelMatrix[i];
  175. }
  176. float divisor;
  177. if (mNumberAttributes[DIVISOR].IsExplicitlySet()) {
  178. divisor = mNumberAttributes[DIVISOR].GetAnimValue();
  179. if (divisor == 0)
  180. return failureDescription;
  181. } else {
  182. divisor = kernel[0];
  183. for (uint32_t i = 1; i < kmLength; i++)
  184. divisor += kernel[i];
  185. if (divisor == 0)
  186. divisor = 1;
  187. }
  188. uint32_t edgeMode = mEnumAttributes[EDGEMODE].GetAnimValue();
  189. bool preserveAlpha = mBooleanAttributes[PRESERVEALPHA].GetAnimValue();
  190. float bias = mNumberAttributes[BIAS].GetAnimValue();
  191. Size kernelUnitLength =
  192. GetKernelUnitLength(aInstance, &mNumberPairAttributes[KERNEL_UNIT_LENGTH]);
  193. if (kernelUnitLength.width <= 0 || kernelUnitLength.height <= 0) {
  194. // According to spec, A negative or zero value is an error. See link below for details.
  195. // https://www.w3.org/TR/SVG/filters.html#feConvolveMatrixElementKernelUnitLengthAttribute
  196. return failureDescription;
  197. }
  198. FilterPrimitiveDescription descr(PrimitiveType::ConvolveMatrix);
  199. AttributeMap& atts = descr.Attributes();
  200. atts.Set(eConvolveMatrixKernelSize, IntSize(orderX, orderY));
  201. atts.Set(eConvolveMatrixKernelMatrix, &kernelMatrix[0], kmLength);
  202. atts.Set(eConvolveMatrixDivisor, divisor);
  203. atts.Set(eConvolveMatrixBias, bias);
  204. atts.Set(eConvolveMatrixTarget, IntPoint(targetX, targetY));
  205. atts.Set(eConvolveMatrixEdgeMode, edgeMode);
  206. atts.Set(eConvolveMatrixKernelUnitLength, kernelUnitLength);
  207. atts.Set(eConvolveMatrixPreserveAlpha, preserveAlpha);
  208. return descr;
  209. }
  210. bool
  211. SVGFEConvolveMatrixElement::AttributeAffectsRendering(int32_t aNameSpaceID,
  212. nsIAtom* aAttribute) const
  213. {
  214. return SVGFEConvolveMatrixElementBase::AttributeAffectsRendering(aNameSpaceID, aAttribute) ||
  215. (aNameSpaceID == kNameSpaceID_None &&
  216. (aAttribute == nsGkAtoms::in ||
  217. aAttribute == nsGkAtoms::divisor ||
  218. aAttribute == nsGkAtoms::bias ||
  219. aAttribute == nsGkAtoms::kernelUnitLength ||
  220. aAttribute == nsGkAtoms::targetX ||
  221. aAttribute == nsGkAtoms::targetY ||
  222. aAttribute == nsGkAtoms::order ||
  223. aAttribute == nsGkAtoms::preserveAlpha||
  224. aAttribute == nsGkAtoms::edgeMode ||
  225. aAttribute == nsGkAtoms::kernelMatrix));
  226. }
  227. //----------------------------------------------------------------------
  228. // nsSVGElement methods
  229. nsSVGElement::NumberAttributesInfo
  230. SVGFEConvolveMatrixElement::GetNumberInfo()
  231. {
  232. return NumberAttributesInfo(mNumberAttributes, sNumberInfo,
  233. ArrayLength(sNumberInfo));
  234. }
  235. nsSVGElement::NumberPairAttributesInfo
  236. SVGFEConvolveMatrixElement::GetNumberPairInfo()
  237. {
  238. return NumberPairAttributesInfo(mNumberPairAttributes, sNumberPairInfo,
  239. ArrayLength(sNumberPairInfo));
  240. }
  241. nsSVGElement::IntegerAttributesInfo
  242. SVGFEConvolveMatrixElement::GetIntegerInfo()
  243. {
  244. return IntegerAttributesInfo(mIntegerAttributes, sIntegerInfo,
  245. ArrayLength(sIntegerInfo));
  246. }
  247. nsSVGElement::IntegerPairAttributesInfo
  248. SVGFEConvolveMatrixElement::GetIntegerPairInfo()
  249. {
  250. return IntegerPairAttributesInfo(mIntegerPairAttributes, sIntegerPairInfo,
  251. ArrayLength(sIntegerPairInfo));
  252. }
  253. nsSVGElement::BooleanAttributesInfo
  254. SVGFEConvolveMatrixElement::GetBooleanInfo()
  255. {
  256. return BooleanAttributesInfo(mBooleanAttributes, sBooleanInfo,
  257. ArrayLength(sBooleanInfo));
  258. }
  259. nsSVGElement::EnumAttributesInfo
  260. SVGFEConvolveMatrixElement::GetEnumInfo()
  261. {
  262. return EnumAttributesInfo(mEnumAttributes, sEnumInfo,
  263. ArrayLength(sEnumInfo));
  264. }
  265. nsSVGElement::StringAttributesInfo
  266. SVGFEConvolveMatrixElement::GetStringInfo()
  267. {
  268. return StringAttributesInfo(mStringAttributes, sStringInfo,
  269. ArrayLength(sStringInfo));
  270. }
  271. nsSVGElement::NumberListAttributesInfo
  272. SVGFEConvolveMatrixElement::GetNumberListInfo()
  273. {
  274. return NumberListAttributesInfo(mNumberListAttributes, sNumberListInfo,
  275. ArrayLength(sNumberListInfo));
  276. }
  277. } // namespace dom
  278. } // namespace mozilla