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/SVGFETurbulenceElement.h"
8 #include "mozilla/dom/SVGFETurbulenceElementBinding.h"
9 #include "mozilla/SVGFilterInstance.h"
10 
11 NS_IMPL_NS_NEW_SVG_ELEMENT(FETurbulence)
12 
13 using namespace mozilla::gfx;
14 
15 namespace mozilla {
16 namespace dom {
17 
18 // Stitch Options
19 static const unsigned short SVG_STITCHTYPE_STITCH = 1;
20 static const unsigned short SVG_STITCHTYPE_NOSTITCH = 2;
21 
22 static const int32_t MAX_OCTAVES = 10;
23 
WrapNode(JSContext * aCx,JS::Handle<JSObject * > aGivenProto)24 JSObject* SVGFETurbulenceElement::WrapNode(JSContext* aCx,
25                                            JS::Handle<JSObject*> aGivenProto) {
26   return SVGFETurbulenceElement_Binding::Wrap(aCx, this, aGivenProto);
27 }
28 
29 SVGElement::NumberInfo SVGFETurbulenceElement::sNumberInfo[1] = {
30     {nsGkAtoms::seed, 0, false}};
31 
32 SVGElement::NumberPairInfo SVGFETurbulenceElement::sNumberPairInfo[1] = {
33     {nsGkAtoms::baseFrequency, 0, 0}};
34 
35 SVGElement::IntegerInfo SVGFETurbulenceElement::sIntegerInfo[1] = {
36     {nsGkAtoms::numOctaves, 1}};
37 
38 SVGEnumMapping SVGFETurbulenceElement::sTypeMap[] = {
39     {nsGkAtoms::fractalNoise, SVG_TURBULENCE_TYPE_FRACTALNOISE},
40     {nsGkAtoms::turbulence, SVG_TURBULENCE_TYPE_TURBULENCE},
41     {nullptr, 0}};
42 
43 SVGEnumMapping SVGFETurbulenceElement::sStitchTilesMap[] = {
44     {nsGkAtoms::stitch, SVG_STITCHTYPE_STITCH},
45     {nsGkAtoms::noStitch, SVG_STITCHTYPE_NOSTITCH},
46     {nullptr, 0}};
47 
48 SVGElement::EnumInfo SVGFETurbulenceElement::sEnumInfo[2] = {
49     {nsGkAtoms::type, sTypeMap, SVG_TURBULENCE_TYPE_TURBULENCE},
50     {nsGkAtoms::stitchTiles, sStitchTilesMap, SVG_STITCHTYPE_NOSTITCH}};
51 
52 SVGElement::StringInfo SVGFETurbulenceElement::sStringInfo[1] = {
53     {nsGkAtoms::result, kNameSpaceID_None, true}};
54 
55 //----------------------------------------------------------------------
56 // nsINode methods
57 
NS_IMPL_ELEMENT_CLONE_WITH_INIT(SVGFETurbulenceElement)58 NS_IMPL_ELEMENT_CLONE_WITH_INIT(SVGFETurbulenceElement)
59 
60 //----------------------------------------------------------------------
61 
62 already_AddRefed<DOMSVGAnimatedNumber>
63 SVGFETurbulenceElement::BaseFrequencyX() {
64   return mNumberPairAttributes[BASE_FREQ].ToDOMAnimatedNumber(
65       SVGAnimatedNumberPair::eFirst, this);
66 }
67 
68 already_AddRefed<DOMSVGAnimatedNumber>
BaseFrequencyY()69 SVGFETurbulenceElement::BaseFrequencyY() {
70   return mNumberPairAttributes[BASE_FREQ].ToDOMAnimatedNumber(
71       SVGAnimatedNumberPair::eSecond, this);
72 }
73 
NumOctaves()74 already_AddRefed<DOMSVGAnimatedInteger> SVGFETurbulenceElement::NumOctaves() {
75   return mIntegerAttributes[OCTAVES].ToDOMAnimatedInteger(this);
76 }
77 
Seed()78 already_AddRefed<DOMSVGAnimatedNumber> SVGFETurbulenceElement::Seed() {
79   return mNumberAttributes[SEED].ToDOMAnimatedNumber(this);
80 }
81 
82 already_AddRefed<DOMSVGAnimatedEnumeration>
StitchTiles()83 SVGFETurbulenceElement::StitchTiles() {
84   return mEnumAttributes[STITCHTILES].ToDOMAnimatedEnum(this);
85 }
86 
Type()87 already_AddRefed<DOMSVGAnimatedEnumeration> SVGFETurbulenceElement::Type() {
88   return mEnumAttributes[TYPE].ToDOMAnimatedEnum(this);
89 }
90 
GetPrimitiveDescription(SVGFilterInstance * aInstance,const IntRect & aFilterSubregion,const nsTArray<bool> & aInputsAreTainted,nsTArray<RefPtr<SourceSurface>> & aInputImages)91 FilterPrimitiveDescription SVGFETurbulenceElement::GetPrimitiveDescription(
92     SVGFilterInstance* aInstance, const IntRect& aFilterSubregion,
93     const nsTArray<bool>& aInputsAreTainted,
94     nsTArray<RefPtr<SourceSurface>>& aInputImages) {
95   float fX = mNumberPairAttributes[BASE_FREQ].GetAnimValue(
96       SVGAnimatedNumberPair::eFirst);
97   float fY = mNumberPairAttributes[BASE_FREQ].GetAnimValue(
98       SVGAnimatedNumberPair::eSecond);
99   float seed = mNumberAttributes[OCTAVES].GetAnimValue();
100   uint32_t octaves =
101       clamped(mIntegerAttributes[OCTAVES].GetAnimValue(), 0, MAX_OCTAVES);
102   uint32_t type = mEnumAttributes[TYPE].GetAnimValue();
103   uint16_t stitch = mEnumAttributes[STITCHTILES].GetAnimValue();
104 
105   if (fX == 0 && fY == 0) {
106     // A base frequency of zero results in transparent black for
107     // type="turbulence" and in 50% alpha 50% gray for type="fractalNoise".
108     if (type == SVG_TURBULENCE_TYPE_TURBULENCE) {
109       return FilterPrimitiveDescription();
110     }
111     FloodAttributes atts;
112     atts.mColor = sRGBColor(0.5, 0.5, 0.5, 0.5);
113     return FilterPrimitiveDescription(AsVariant(std::move(atts)));
114   }
115 
116   // We interpret the base frequency as relative to user space units. In other
117   // words, we consider one turbulence base period to be 1 / fX user space
118   // units wide and 1 / fY user space units high. We do not scale the frequency
119   // depending on the filter primitive region.
120   // We now convert the frequency from user space to filter space.
121   // If a frequency in user space units is zero, then it will also be zero in
122   // filter space. During the conversion we use a dummy period length of 1
123   // for those frequencies but then ignore the converted length and use 0
124   // for the converted frequency. This avoids division by zero.
125   gfxRect firstPeriodInUserSpace(0, 0, fX == 0 ? 1 : (1 / fX),
126                                  fY == 0 ? 1 : (1 / fY));
127   gfxRect firstPeriodInFilterSpace =
128       aInstance->UserSpaceToFilterSpace(firstPeriodInUserSpace);
129   Size frequencyInFilterSpace(
130       fX == 0 ? 0 : (1 / firstPeriodInFilterSpace.width),
131       fY == 0 ? 0 : (1 / firstPeriodInFilterSpace.height));
132   gfxPoint offset = firstPeriodInFilterSpace.TopLeft();
133 
134   TurbulenceAttributes atts;
135   atts.mOffset = IntPoint::Truncate(offset.x, offset.y);
136   atts.mBaseFrequency = frequencyInFilterSpace;
137   atts.mSeed = seed;
138   atts.mOctaves = octaves;
139   atts.mStitchable = stitch == SVG_STITCHTYPE_STITCH;
140   atts.mType = type;
141   return FilterPrimitiveDescription(AsVariant(std::move(atts)));
142 }
143 
AttributeAffectsRendering(int32_t aNameSpaceID,nsAtom * aAttribute) const144 bool SVGFETurbulenceElement::AttributeAffectsRendering(
145     int32_t aNameSpaceID, nsAtom* aAttribute) const {
146   return SVGFETurbulenceElementBase::AttributeAffectsRendering(aNameSpaceID,
147                                                                aAttribute) ||
148          (aNameSpaceID == kNameSpaceID_None &&
149           (aAttribute == nsGkAtoms::seed ||
150            aAttribute == nsGkAtoms::baseFrequency ||
151            aAttribute == nsGkAtoms::numOctaves ||
152            aAttribute == nsGkAtoms::type ||
153            aAttribute == nsGkAtoms::stitchTiles));
154 }
155 
156 //----------------------------------------------------------------------
157 // SVGElement methods
158 
GetNumberInfo()159 SVGElement::NumberAttributesInfo SVGFETurbulenceElement::GetNumberInfo() {
160   return NumberAttributesInfo(mNumberAttributes, sNumberInfo,
161                               ArrayLength(sNumberInfo));
162 }
163 
164 SVGElement::NumberPairAttributesInfo
GetNumberPairInfo()165 SVGFETurbulenceElement::GetNumberPairInfo() {
166   return NumberPairAttributesInfo(mNumberPairAttributes, sNumberPairInfo,
167                                   ArrayLength(sNumberPairInfo));
168 }
169 
GetIntegerInfo()170 SVGElement::IntegerAttributesInfo SVGFETurbulenceElement::GetIntegerInfo() {
171   return IntegerAttributesInfo(mIntegerAttributes, sIntegerInfo,
172                                ArrayLength(sIntegerInfo));
173 }
174 
GetEnumInfo()175 SVGElement::EnumAttributesInfo SVGFETurbulenceElement::GetEnumInfo() {
176   return EnumAttributesInfo(mEnumAttributes, sEnumInfo, ArrayLength(sEnumInfo));
177 }
178 
GetStringInfo()179 SVGElement::StringAttributesInfo SVGFETurbulenceElement::GetStringInfo() {
180   return StringAttributesInfo(mStringAttributes, sStringInfo,
181                               ArrayLength(sStringInfo));
182 }
183 
184 }  // namespace dom
185 }  // namespace mozilla
186