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/SVGTransformList.h"
34 inline SVGRadialGradientElement::SVGRadialGradientElement(Document& document)
35 : SVGGradientElement(SVGNames::radialGradientTag, document)
36 , m_cx(SVGAnimatedLength::create(this, SVGNames::cxAttr, SVGLength::create(LengthModeWidth), AllowNegativeLengths))
37 , m_cy(SVGAnimatedLength::create(this, SVGNames::cyAttr, SVGLength::create(LengthModeHeight), AllowNegativeLengths))
38 , m_r(SVGAnimatedLength::create(this, SVGNames::rAttr, SVGLength::create(LengthModeOther), ForbidNegativeLengths))
39 , m_fx(SVGAnimatedLength::create(this, SVGNames::fxAttr, SVGLength::create(LengthModeWidth), AllowNegativeLengths))
40 , m_fy(SVGAnimatedLength::create(this, SVGNames::fyAttr, SVGLength::create(LengthModeHeight), AllowNegativeLengths))
41 , m_fr(SVGAnimatedLength::create(this, SVGNames::frAttr, SVGLength::create(LengthModeOther), ForbidNegativeLengths))
43 // Spec: If the cx/cy/r attribute is not specified, the effect is as if a value of "50%" were specified.
44 m_cx->setDefaultValueAsString("50%");
45 m_cy->setDefaultValueAsString("50%");
46 m_r->setDefaultValueAsString("50%");
48 // SVG2-Draft Spec: If the fr attributed is not specified, the effect is as if a value of "0%" were specified.
49 m_fr->setDefaultValueAsString("0%");
51 addToPropertyMap(m_cx);
52 addToPropertyMap(m_cy);
53 addToPropertyMap(m_r);
54 addToPropertyMap(m_fx);
55 addToPropertyMap(m_fy);
56 addToPropertyMap(m_fr);
59 DEFINE_NODE_FACTORY(SVGRadialGradientElement)
61 bool SVGRadialGradientElement::isSupportedAttribute(const QualifiedName& attrName)
63 DEFINE_STATIC_LOCAL(HashSet<QualifiedName>, supportedAttributes, ());
64 if (supportedAttributes.isEmpty()) {
65 supportedAttributes.add(SVGNames::cxAttr);
66 supportedAttributes.add(SVGNames::cyAttr);
67 supportedAttributes.add(SVGNames::fxAttr);
68 supportedAttributes.add(SVGNames::fyAttr);
69 supportedAttributes.add(SVGNames::rAttr);
70 supportedAttributes.add(SVGNames::frAttr);
72 return supportedAttributes.contains<SVGAttributeHashTranslator>(attrName);
75 void SVGRadialGradientElement::parseAttribute(const QualifiedName& name, const AtomicString& value)
77 parseAttributeNew(name, value);
80 void SVGRadialGradientElement::svgAttributeChanged(const QualifiedName& attrName)
82 if (!isSupportedAttribute(attrName)) {
83 SVGGradientElement::svgAttributeChanged(attrName);
87 SVGElement::InvalidationGuard invalidationGuard(this);
89 updateRelativeLengthsInformation();
91 RenderSVGResourceContainer* renderer = toRenderSVGResourceContainer(this->renderer());
93 renderer->invalidateCacheAndMarkForLayout();
96 RenderObject* SVGRadialGradientElement::createRenderer(RenderStyle*)
98 return new RenderSVGResourceRadialGradient(this);
101 static void setGradientAttributes(SVGGradientElement* element, RadialGradientAttributes& attributes, bool isRadial = true)
103 if (!attributes.hasSpreadMethod() && element->spreadMethod()->isSpecified())
104 attributes.setSpreadMethod(element->spreadMethod()->currentValue()->enumValue());
106 if (!attributes.hasGradientUnits() && element->gradientUnits()->isSpecified())
107 attributes.setGradientUnits(element->gradientUnits()->currentValue()->enumValue());
109 if (!attributes.hasGradientTransform() && element->gradientTransform()->isSpecified()) {
110 AffineTransform transform;
111 element->gradientTransform()->currentValue()->concatenate(transform);
112 attributes.setGradientTransform(transform);
115 if (!attributes.hasStops()) {
116 const Vector<Gradient::ColorStop>& stops(element->buildStops());
117 if (!stops.isEmpty())
118 attributes.setStops(stops);
122 SVGRadialGradientElement* radial = toSVGRadialGradientElement(element);
124 if (!attributes.hasCx() && radial->cx()->isSpecified())
125 attributes.setCx(radial->cx()->currentValue());
127 if (!attributes.hasCy() && radial->cy()->isSpecified())
128 attributes.setCy(radial->cy()->currentValue());
130 if (!attributes.hasR() && radial->r()->isSpecified())
131 attributes.setR(radial->r()->currentValue());
133 if (!attributes.hasFx() && radial->fx()->isSpecified())
134 attributes.setFx(radial->fx()->currentValue());
136 if (!attributes.hasFy() && radial->fy()->isSpecified())
137 attributes.setFy(radial->fy()->currentValue());
139 if (!attributes.hasFr() && radial->fr()->isSpecified())
140 attributes.setFr(radial->fr()->currentValue());
144 bool SVGRadialGradientElement::collectGradientAttributes(RadialGradientAttributes& attributes)
149 WillBeHeapHashSet<RawPtrWillBeMember<SVGGradientElement> > processedGradients;
150 SVGGradientElement* current = this;
152 setGradientAttributes(current, attributes);
153 processedGradients.add(current);
156 // Respect xlink:href, take attributes from referenced element
157 Node* refNode = SVGURIReference::targetElementFromIRIString(current->href()->currentValue()->value(), treeScope());
158 if (refNode && isSVGGradientElement(*refNode)) {
159 current = toSVGGradientElement(refNode);
162 if (processedGradients.contains(current))
165 if (!current->renderer())
168 setGradientAttributes(current, attributes, isSVGRadialGradientElement(*current));
169 processedGradients.add(current);
175 // Handle default values for fx/fy
176 if (!attributes.hasFx())
177 attributes.setFx(attributes.cx());
179 if (!attributes.hasFy())
180 attributes.setFy(attributes.cy());
185 bool SVGRadialGradientElement::selfHasRelativeLengths() const
187 return m_cx->currentValue()->isRelative()
188 || m_cy->currentValue()->isRelative()
189 || m_r->currentValue()->isRelative()
190 || m_fx->currentValue()->isRelative()
191 || m_fy->currentValue()->isRelative()
192 || m_fr->currentValue()->isRelative();