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/. */
7 #include "mozilla/dom/SVGFETurbulenceElement.h"
8 #include "mozilla/dom/SVGFETurbulenceElementBinding.h"
9 #include "mozilla/SVGFilterInstance.h"
11 NS_IMPL_NS_NEW_SVG_ELEMENT(FETurbulence
)
13 using namespace mozilla::gfx
;
19 static const unsigned short SVG_STITCHTYPE_STITCH
= 1;
20 static const unsigned short SVG_STITCHTYPE_NOSTITCH
= 2;
22 static const int32_t MAX_OCTAVES
= 10;
24 JSObject
* SVGFETurbulenceElement::WrapNode(JSContext
* aCx
,
25 JS::Handle
<JSObject
*> aGivenProto
) {
26 return SVGFETurbulenceElement_Binding::Wrap(aCx
, this, aGivenProto
);
29 SVGElement::NumberInfo
SVGFETurbulenceElement::sNumberInfo
[1] = {
30 {nsGkAtoms::seed
, 0, false}};
32 SVGElement::NumberPairInfo
SVGFETurbulenceElement::sNumberPairInfo
[1] = {
33 {nsGkAtoms::baseFrequency
, 0, 0}};
35 SVGElement::IntegerInfo
SVGFETurbulenceElement::sIntegerInfo
[1] = {
36 {nsGkAtoms::numOctaves
, 1}};
38 SVGEnumMapping
SVGFETurbulenceElement::sTypeMap
[] = {
39 {nsGkAtoms::fractalNoise
, SVG_TURBULENCE_TYPE_FRACTALNOISE
},
40 {nsGkAtoms::turbulence
, SVG_TURBULENCE_TYPE_TURBULENCE
},
43 SVGEnumMapping
SVGFETurbulenceElement::sStitchTilesMap
[] = {
44 {nsGkAtoms::stitch
, SVG_STITCHTYPE_STITCH
},
45 {nsGkAtoms::noStitch
, SVG_STITCHTYPE_NOSTITCH
},
48 SVGElement::EnumInfo
SVGFETurbulenceElement::sEnumInfo
[2] = {
49 {nsGkAtoms::type
, sTypeMap
, SVG_TURBULENCE_TYPE_TURBULENCE
},
50 {nsGkAtoms::stitchTiles
, sStitchTilesMap
, SVG_STITCHTYPE_NOSTITCH
}};
52 SVGElement::StringInfo
SVGFETurbulenceElement::sStringInfo
[1] = {
53 {nsGkAtoms::result
, kNameSpaceID_None
, true}};
55 //----------------------------------------------------------------------
58 NS_IMPL_ELEMENT_CLONE_WITH_INIT(SVGFETurbulenceElement
)
60 //----------------------------------------------------------------------
62 already_AddRefed
<DOMSVGAnimatedNumber
>
63 SVGFETurbulenceElement::BaseFrequencyX() {
64 return mNumberPairAttributes
[BASE_FREQ
].ToDOMAnimatedNumber(
65 SVGAnimatedNumberPair::eFirst
, this);
68 already_AddRefed
<DOMSVGAnimatedNumber
>
69 SVGFETurbulenceElement::BaseFrequencyY() {
70 return mNumberPairAttributes
[BASE_FREQ
].ToDOMAnimatedNumber(
71 SVGAnimatedNumberPair::eSecond
, this);
74 already_AddRefed
<DOMSVGAnimatedInteger
> SVGFETurbulenceElement::NumOctaves() {
75 return mIntegerAttributes
[OCTAVES
].ToDOMAnimatedInteger(this);
78 already_AddRefed
<DOMSVGAnimatedNumber
> SVGFETurbulenceElement::Seed() {
79 return mNumberAttributes
[SEED
].ToDOMAnimatedNumber(this);
82 already_AddRefed
<DOMSVGAnimatedEnumeration
>
83 SVGFETurbulenceElement::StitchTiles() {
84 return mEnumAttributes
[STITCHTILES
].ToDOMAnimatedEnum(this);
87 already_AddRefed
<DOMSVGAnimatedEnumeration
> SVGFETurbulenceElement::Type() {
88 return mEnumAttributes
[TYPE
].ToDOMAnimatedEnum(this);
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();
101 clamped(mIntegerAttributes
[OCTAVES
].GetAnimValue(), 0, MAX_OCTAVES
);
102 uint32_t type
= mEnumAttributes
[TYPE
].GetAnimValue();
103 uint16_t stitch
= mEnumAttributes
[STITCHTILES
].GetAnimValue();
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();
111 FloodAttributes atts
;
112 atts
.mColor
= sRGBColor(0.5, 0.5, 0.5, 0.5);
113 return FilterPrimitiveDescription(AsVariant(std::move(atts
)));
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();
134 TurbulenceAttributes atts
;
135 atts
.mOffset
= IntPoint::Truncate(offset
.x
, offset
.y
);
136 atts
.mBaseFrequency
= frequencyInFilterSpace
;
138 atts
.mOctaves
= octaves
;
139 atts
.mStitchable
= stitch
== SVG_STITCHTYPE_STITCH
;
141 return FilterPrimitiveDescription(AsVariant(std::move(atts
)));
144 bool SVGFETurbulenceElement::AttributeAffectsRendering(
145 int32_t aNameSpaceID
, nsAtom
* aAttribute
) const {
146 return SVGFETurbulenceElementBase::AttributeAffectsRendering(aNameSpaceID
,
148 (aNameSpaceID
== kNameSpaceID_None
&&
149 (aAttribute
== nsGkAtoms::seed
||
150 aAttribute
== nsGkAtoms::baseFrequency
||
151 aAttribute
== nsGkAtoms::numOctaves
||
152 aAttribute
== nsGkAtoms::type
||
153 aAttribute
== nsGkAtoms::stitchTiles
));
156 //----------------------------------------------------------------------
157 // SVGElement methods
159 SVGElement::NumberAttributesInfo
SVGFETurbulenceElement::GetNumberInfo() {
160 return NumberAttributesInfo(mNumberAttributes
, sNumberInfo
,
161 ArrayLength(sNumberInfo
));
164 SVGElement::NumberPairAttributesInfo
165 SVGFETurbulenceElement::GetNumberPairInfo() {
166 return NumberPairAttributesInfo(mNumberPairAttributes
, sNumberPairInfo
,
167 ArrayLength(sNumberPairInfo
));
170 SVGElement::IntegerAttributesInfo
SVGFETurbulenceElement::GetIntegerInfo() {
171 return IntegerAttributesInfo(mIntegerAttributes
, sIntegerInfo
,
172 ArrayLength(sIntegerInfo
));
175 SVGElement::EnumAttributesInfo
SVGFETurbulenceElement::GetEnumInfo() {
176 return EnumAttributesInfo(mEnumAttributes
, sEnumInfo
, ArrayLength(sEnumInfo
));
179 SVGElement::StringAttributesInfo
SVGFETurbulenceElement::GetStringInfo() {
180 return StringAttributesInfo(mStringAttributes
, sStringInfo
,
181 ArrayLength(sStringInfo
));
185 } // namespace mozilla