2 * Copyright (C) 2004, 2005, 2006, 2008 Nikolas Zimmermann <zimmermann@kde.org>
3 * Copyright (C) 2004, 2005, 2006, 2007 Rob Buis <buis@kde.org>
4 * Copyright (C) 2008 Eric Seidel <eric@webkit.org>
5 * Copyright (C) 2008 Dirk Schulze <krit@webkit.org>
6 * Copyright (C) Research In Motion Limited 2010. All rights reserved.
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Library General Public
10 * License as published by the Free Software Foundation; either
11 * version 2 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Library General Public License for more details.
18 * You should have received a copy of the GNU Library General Public License
19 * along with this library; see the file COPYING.LIB. If not, write to
20 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
21 * Boston, MA 02110-1301, USA.
26 #include "core/svg/SVGRadialGradientElement.h"
28 #include "core/rendering/svg/RenderSVGResourceRadialGradient.h"
29 #include "core/svg/RadialGradientAttributes.h"
30 #include "core/svg/SVGElementInstance.h"
31 #include "core/svg/SVGTransformList.h"
35 // Animated property definitions
37 BEGIN_REGISTER_ANIMATED_PROPERTIES(SVGRadialGradientElement)
38 REGISTER_PARENT_ANIMATED_PROPERTIES(SVGGradientElement)
39 END_REGISTER_ANIMATED_PROPERTIES
41 inline SVGRadialGradientElement::SVGRadialGradientElement(Document& document)
42 : SVGGradientElement(SVGNames::radialGradientTag, document)
43 , m_cx(SVGAnimatedLength::create(this, SVGNames::cxAttr, SVGLength::create(LengthModeWidth)))
44 , m_cy(SVGAnimatedLength::create(this, SVGNames::cyAttr, SVGLength::create(LengthModeHeight)))
45 , m_r(SVGAnimatedLength::create(this, SVGNames::rAttr, SVGLength::create(LengthModeOther)))
46 , m_fx(SVGAnimatedLength::create(this, SVGNames::fxAttr, SVGLength::create(LengthModeWidth)))
47 , m_fy(SVGAnimatedLength::create(this, SVGNames::fyAttr, SVGLength::create(LengthModeHeight)))
48 , m_fr(SVGAnimatedLength::create(this, SVGNames::frAttr, SVGLength::create(LengthModeOther)))
50 ScriptWrappable::init(this);
52 // Spec: If the cx/cy/r attribute is not specified, the effect is as if a value of "50%" were specified.
53 m_cx->setDefaultValueAsString("50%");
54 m_cy->setDefaultValueAsString("50%");
55 m_r->setDefaultValueAsString("50%");
57 // SVG2-Draft Spec: If the fr attributed is not specified, the effect is as if a value of "0%" were specified.
58 m_fr->setDefaultValueAsString("0%");
60 addToPropertyMap(m_cx);
61 addToPropertyMap(m_cy);
62 addToPropertyMap(m_r);
63 addToPropertyMap(m_fx);
64 addToPropertyMap(m_fy);
65 addToPropertyMap(m_fr);
66 registerAnimatedPropertiesForSVGRadialGradientElement();
69 PassRefPtr<SVGRadialGradientElement> SVGRadialGradientElement::create(Document& document)
71 return adoptRef(new SVGRadialGradientElement(document));
74 bool SVGRadialGradientElement::isSupportedAttribute(const QualifiedName& attrName)
76 DEFINE_STATIC_LOCAL(HashSet<QualifiedName>, supportedAttributes, ());
77 if (supportedAttributes.isEmpty()) {
78 supportedAttributes.add(SVGNames::cxAttr);
79 supportedAttributes.add(SVGNames::cyAttr);
80 supportedAttributes.add(SVGNames::fxAttr);
81 supportedAttributes.add(SVGNames::fyAttr);
82 supportedAttributes.add(SVGNames::rAttr);
83 supportedAttributes.add(SVGNames::frAttr);
85 return supportedAttributes.contains<SVGAttributeHashTranslator>(attrName);
88 void SVGRadialGradientElement::parseAttribute(const QualifiedName& name, const AtomicString& value)
90 SVGParsingError parseError = NoError;
92 if (!isSupportedAttribute(name))
93 SVGGradientElement::parseAttribute(name, value);
94 else if (name == SVGNames::cxAttr)
95 m_cx->setBaseValueAsString(value, AllowNegativeLengths, parseError);
96 else if (name == SVGNames::cyAttr)
97 m_cy->setBaseValueAsString(value, AllowNegativeLengths, parseError);
98 else if (name == SVGNames::rAttr)
99 m_r->setBaseValueAsString(value, ForbidNegativeLengths, parseError);
100 else if (name == SVGNames::fxAttr)
101 m_fx->setBaseValueAsString(value, AllowNegativeLengths, parseError);
102 else if (name == SVGNames::fyAttr)
103 m_fy->setBaseValueAsString(value, AllowNegativeLengths, parseError);
104 else if (name == SVGNames::frAttr)
105 m_fr->setBaseValueAsString(value, ForbidNegativeLengths, parseError);
107 ASSERT_NOT_REACHED();
109 reportAttributeParsingError(parseError, name, value);
112 void SVGRadialGradientElement::svgAttributeChanged(const QualifiedName& attrName)
114 if (!isSupportedAttribute(attrName)) {
115 SVGGradientElement::svgAttributeChanged(attrName);
119 SVGElementInstance::InvalidationGuard invalidationGuard(this);
121 updateRelativeLengthsInformation();
123 RenderSVGResourceContainer* renderer = toRenderSVGResourceContainer(this->renderer());
125 renderer->invalidateCacheAndMarkForLayout();
128 RenderObject* SVGRadialGradientElement::createRenderer(RenderStyle*)
130 return new RenderSVGResourceRadialGradient(this);
133 static void setGradientAttributes(SVGGradientElement* element, RadialGradientAttributes& attributes, bool isRadial = true)
135 if (!attributes.hasSpreadMethod() && element->spreadMethodSpecified())
136 attributes.setSpreadMethod(element->spreadMethodCurrentValue());
138 if (!attributes.hasGradientUnits() && element->gradientUnitsSpecified())
139 attributes.setGradientUnits(element->gradientUnitsCurrentValue());
141 if (!attributes.hasGradientTransform() && element->gradientTransformSpecified()) {
142 AffineTransform transform;
143 element->gradientTransformCurrentValue().concatenate(transform);
144 attributes.setGradientTransform(transform);
147 if (!attributes.hasStops()) {
148 const Vector<Gradient::ColorStop>& stops(element->buildStops());
149 if (!stops.isEmpty())
150 attributes.setStops(stops);
154 SVGRadialGradientElement* radial = toSVGRadialGradientElement(element);
156 if (!attributes.hasCx() && radial->cx()->isSpecified())
157 attributes.setCx(radial->cx()->currentValue());
159 if (!attributes.hasCy() && radial->cy()->isSpecified())
160 attributes.setCy(radial->cy()->currentValue());
162 if (!attributes.hasR() && radial->r()->isSpecified())
163 attributes.setR(radial->r()->currentValue());
165 if (!attributes.hasFx() && radial->fx()->isSpecified())
166 attributes.setFx(radial->fx()->currentValue());
168 if (!attributes.hasFy() && radial->fy()->isSpecified())
169 attributes.setFy(radial->fy()->currentValue());
171 if (!attributes.hasFr() && radial->fr()->isSpecified())
172 attributes.setFr(radial->fr()->currentValue());
176 bool SVGRadialGradientElement::collectGradientAttributes(RadialGradientAttributes& attributes)
181 HashSet<SVGGradientElement*> processedGradients;
182 SVGGradientElement* current = this;
184 setGradientAttributes(current, attributes);
185 processedGradients.add(current);
188 // Respect xlink:href, take attributes from referenced element
189 Node* refNode = SVGURIReference::targetElementFromIRIString(current->href()->currentValue()->value(), document());
190 if (refNode && isSVGGradientElement(*refNode)) {
191 current = toSVGGradientElement(refNode);
194 if (processedGradients.contains(current))
197 if (!current->renderer())
200 setGradientAttributes(current, attributes, current->hasTagName(SVGNames::radialGradientTag));
201 processedGradients.add(current);
207 // Handle default values for fx/fy
208 if (!attributes.hasFx())
209 attributes.setFx(attributes.cx());
211 if (!attributes.hasFy())
212 attributes.setFy(attributes.cy());
217 bool SVGRadialGradientElement::selfHasRelativeLengths() const
219 return m_cx->currentValue()->isRelative()
220 || m_cy->currentValue()->isRelative()
221 || m_r->currentValue()->isRelative()
222 || m_fx->currentValue()->isRelative()
223 || m_fy->currentValue()->isRelative()
224 || m_fr->currentValue()->isRelative();