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/SVGGradientElement.h"
8 
9 #include "mozilla/AlreadyAddRefed.h"
10 #include "mozilla/ArrayUtils.h"
11 #include "mozilla/dom/SVGElement.h"
12 #include "mozilla/dom/SVGGradientElementBinding.h"
13 #include "mozilla/dom/SVGLengthBinding.h"
14 #include "mozilla/dom/SVGLinearGradientElementBinding.h"
15 #include "mozilla/dom/SVGRadialGradientElementBinding.h"
16 #include "mozilla/dom/SVGUnitTypesBinding.h"
17 #include "DOMSVGAnimatedTransformList.h"
18 #include "nsGkAtoms.h"
19 
20 NS_IMPL_NS_NEW_SVG_ELEMENT(LinearGradient)
21 NS_IMPL_NS_NEW_SVG_ELEMENT(RadialGradient)
22 
23 namespace mozilla {
24 namespace dom {
25 
26 using namespace SVGGradientElement_Binding;
27 using namespace SVGUnitTypes_Binding;
28 
29 //--------------------- Gradients------------------------
30 
31 SVGEnumMapping SVGGradientElement::sSpreadMethodMap[] = {
32     {nsGkAtoms::pad, SVG_SPREADMETHOD_PAD},
33     {nsGkAtoms::reflect, SVG_SPREADMETHOD_REFLECT},
34     {nsGkAtoms::repeat, SVG_SPREADMETHOD_REPEAT},
35     {nullptr, 0}};
36 
37 SVGElement::EnumInfo SVGGradientElement::sEnumInfo[2] = {
38     {nsGkAtoms::gradientUnits, sSVGUnitTypesMap,
39      SVG_UNIT_TYPE_OBJECTBOUNDINGBOX},
40     {nsGkAtoms::spreadMethod, sSpreadMethodMap, SVG_SPREADMETHOD_PAD}};
41 
42 SVGElement::StringInfo SVGGradientElement::sStringInfo[2] = {
43     {nsGkAtoms::href, kNameSpaceID_None, true},
44     {nsGkAtoms::href, kNameSpaceID_XLink, true}};
45 
46 //----------------------------------------------------------------------
47 // Implementation
48 
SVGGradientElement(already_AddRefed<mozilla::dom::NodeInfo> && aNodeInfo)49 SVGGradientElement::SVGGradientElement(
50     already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo)
51     : SVGGradientElementBase(std::move(aNodeInfo)) {}
52 
53 //----------------------------------------------------------------------
54 // SVGElement methods
55 
GetEnumInfo()56 SVGElement::EnumAttributesInfo SVGGradientElement::GetEnumInfo() {
57   return EnumAttributesInfo(mEnumAttributes, sEnumInfo, ArrayLength(sEnumInfo));
58 }
59 
GetStringInfo()60 SVGElement::StringAttributesInfo SVGGradientElement::GetStringInfo() {
61   return StringAttributesInfo(mStringAttributes, sStringInfo,
62                               ArrayLength(sStringInfo));
63 }
64 
65 already_AddRefed<DOMSVGAnimatedEnumeration>
GradientUnits()66 SVGGradientElement::GradientUnits() {
67   return mEnumAttributes[GRADIENTUNITS].ToDOMAnimatedEnum(this);
68 }
69 
70 already_AddRefed<DOMSVGAnimatedTransformList>
GradientTransform()71 SVGGradientElement::GradientTransform() {
72   // We're creating a DOM wrapper, so we must tell GetAnimatedTransformList
73   // to allocate the DOMSVGAnimatedTransformList if it hasn't already done so:
74   return DOMSVGAnimatedTransformList::GetDOMWrapper(
75       GetAnimatedTransformList(DO_ALLOCATE), this);
76 }
77 
SpreadMethod()78 already_AddRefed<DOMSVGAnimatedEnumeration> SVGGradientElement::SpreadMethod() {
79   return mEnumAttributes[SPREADMETHOD].ToDOMAnimatedEnum(this);
80 }
81 
Href()82 already_AddRefed<DOMSVGAnimatedString> SVGGradientElement::Href() {
83   return mStringAttributes[HREF].IsExplicitlySet()
84              ? mStringAttributes[HREF].ToDOMAnimatedString(this)
85              : mStringAttributes[XLINK_HREF].ToDOMAnimatedString(this);
86 }
87 
88 //----------------------------------------------------------------------
89 // nsIContent methods
90 
NS_IMETHODIMP_(bool)91 NS_IMETHODIMP_(bool)
92 SVGGradientElement::IsAttributeMapped(const nsAtom* name) const {
93   static const MappedAttributeEntry* const map[] = {sColorMap,
94                                                     sGradientStopMap};
95 
96   return FindAttributeDependence(name, map) ||
97          SVGGradientElementBase::IsAttributeMapped(name);
98 }
99 
100 //---------------------Linear Gradients------------------------
101 
WrapNode(JSContext * aCx,JS::Handle<JSObject * > aGivenProto)102 JSObject* SVGLinearGradientElement::WrapNode(
103     JSContext* aCx, JS::Handle<JSObject*> aGivenProto) {
104   return SVGLinearGradientElement_Binding::Wrap(aCx, this, aGivenProto);
105 }
106 
107 SVGElement::LengthInfo SVGLinearGradientElement::sLengthInfo[4] = {
108     {nsGkAtoms::x1, 0, SVGLength_Binding::SVG_LENGTHTYPE_PERCENTAGE,
109      SVGContentUtils::X},
110     {nsGkAtoms::y1, 0, SVGLength_Binding::SVG_LENGTHTYPE_PERCENTAGE,
111      SVGContentUtils::Y},
112     {nsGkAtoms::x2, 100, SVGLength_Binding::SVG_LENGTHTYPE_PERCENTAGE,
113      SVGContentUtils::X},
114     {nsGkAtoms::y2, 0, SVGLength_Binding::SVG_LENGTHTYPE_PERCENTAGE,
115      SVGContentUtils::Y},
116 };
117 
118 //----------------------------------------------------------------------
119 // Implementation
120 
SVGLinearGradientElement(already_AddRefed<mozilla::dom::NodeInfo> && aNodeInfo)121 SVGLinearGradientElement::SVGLinearGradientElement(
122     already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo)
123     : SVGLinearGradientElementBase(std::move(aNodeInfo)) {}
124 
125 //----------------------------------------------------------------------
126 // nsINode methods
127 
NS_IMPL_ELEMENT_CLONE_WITH_INIT(SVGLinearGradientElement)128 NS_IMPL_ELEMENT_CLONE_WITH_INIT(SVGLinearGradientElement)
129 
130 //----------------------------------------------------------------------
131 
132 already_AddRefed<DOMSVGAnimatedLength> SVGLinearGradientElement::X1() {
133   return mLengthAttributes[ATTR_X1].ToDOMAnimatedLength(this);
134 }
135 
Y1()136 already_AddRefed<DOMSVGAnimatedLength> SVGLinearGradientElement::Y1() {
137   return mLengthAttributes[ATTR_Y1].ToDOMAnimatedLength(this);
138 }
139 
X2()140 already_AddRefed<DOMSVGAnimatedLength> SVGLinearGradientElement::X2() {
141   return mLengthAttributes[ATTR_X2].ToDOMAnimatedLength(this);
142 }
143 
Y2()144 already_AddRefed<DOMSVGAnimatedLength> SVGLinearGradientElement::Y2() {
145   return mLengthAttributes[ATTR_Y2].ToDOMAnimatedLength(this);
146 }
147 
148 //----------------------------------------------------------------------
149 // SVGElement methods
150 
GetAnimatedTransformList(uint32_t aFlags)151 SVGAnimatedTransformList* SVGGradientElement::GetAnimatedTransformList(
152     uint32_t aFlags) {
153   if (!mGradientTransform && (aFlags & DO_ALLOCATE)) {
154     mGradientTransform = MakeUnique<SVGAnimatedTransformList>();
155   }
156   return mGradientTransform.get();
157 }
158 
GetLengthInfo()159 SVGElement::LengthAttributesInfo SVGLinearGradientElement::GetLengthInfo() {
160   return LengthAttributesInfo(mLengthAttributes, sLengthInfo,
161                               ArrayLength(sLengthInfo));
162 }
163 
164 //-------------------------- Radial Gradients ----------------------------
165 
WrapNode(JSContext * aCx,JS::Handle<JSObject * > aGivenProto)166 JSObject* SVGRadialGradientElement::WrapNode(
167     JSContext* aCx, JS::Handle<JSObject*> aGivenProto) {
168   return SVGRadialGradientElement_Binding::Wrap(aCx, this, aGivenProto);
169 }
170 
171 SVGElement::LengthInfo SVGRadialGradientElement::sLengthInfo[6] = {
172     {nsGkAtoms::cx, 50, SVGLength_Binding::SVG_LENGTHTYPE_PERCENTAGE,
173      SVGContentUtils::X},
174     {nsGkAtoms::cy, 50, SVGLength_Binding::SVG_LENGTHTYPE_PERCENTAGE,
175      SVGContentUtils::Y},
176     {nsGkAtoms::r, 50, SVGLength_Binding::SVG_LENGTHTYPE_PERCENTAGE,
177      SVGContentUtils::XY},
178     {nsGkAtoms::fx, 50, SVGLength_Binding::SVG_LENGTHTYPE_PERCENTAGE,
179      SVGContentUtils::X},
180     {nsGkAtoms::fy, 50, SVGLength_Binding::SVG_LENGTHTYPE_PERCENTAGE,
181      SVGContentUtils::Y},
182     {nsGkAtoms::fr, 0, SVGLength_Binding::SVG_LENGTHTYPE_PERCENTAGE,
183      SVGContentUtils::XY},
184 };
185 
186 //----------------------------------------------------------------------
187 // Implementation
188 
SVGRadialGradientElement(already_AddRefed<mozilla::dom::NodeInfo> && aNodeInfo)189 SVGRadialGradientElement::SVGRadialGradientElement(
190     already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo)
191     : SVGRadialGradientElementBase(std::move(aNodeInfo)) {}
192 
193 //----------------------------------------------------------------------
194 // nsINode methods
195 
NS_IMPL_ELEMENT_CLONE_WITH_INIT(SVGRadialGradientElement)196 NS_IMPL_ELEMENT_CLONE_WITH_INIT(SVGRadialGradientElement)
197 
198 //----------------------------------------------------------------------
199 
200 already_AddRefed<DOMSVGAnimatedLength> SVGRadialGradientElement::Cx() {
201   return mLengthAttributes[ATTR_CX].ToDOMAnimatedLength(this);
202 }
203 
Cy()204 already_AddRefed<DOMSVGAnimatedLength> SVGRadialGradientElement::Cy() {
205   return mLengthAttributes[ATTR_CY].ToDOMAnimatedLength(this);
206 }
207 
R()208 already_AddRefed<DOMSVGAnimatedLength> SVGRadialGradientElement::R() {
209   return mLengthAttributes[ATTR_R].ToDOMAnimatedLength(this);
210 }
211 
Fx()212 already_AddRefed<DOMSVGAnimatedLength> SVGRadialGradientElement::Fx() {
213   return mLengthAttributes[ATTR_FX].ToDOMAnimatedLength(this);
214 }
215 
Fy()216 already_AddRefed<DOMSVGAnimatedLength> SVGRadialGradientElement::Fy() {
217   return mLengthAttributes[ATTR_FY].ToDOMAnimatedLength(this);
218 }
219 
Fr()220 already_AddRefed<DOMSVGAnimatedLength> SVGRadialGradientElement::Fr() {
221   return mLengthAttributes[ATTR_FR].ToDOMAnimatedLength(this);
222 }
223 
224 //----------------------------------------------------------------------
225 // SVGElement methods
226 
GetLengthInfo()227 SVGElement::LengthAttributesInfo SVGRadialGradientElement::GetLengthInfo() {
228   return LengthAttributesInfo(mLengthAttributes, sLengthInfo,
229                               ArrayLength(sLengthInfo));
230 }
231 
232 }  // namespace dom
233 }  // namespace mozilla
234