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/SVGLinearGradientElement.h"
28 #include "core/rendering/svg/RenderSVGResourceLinearGradient.h"
29 #include "core/svg/LinearGradientAttributes.h"
30 #include "core/svg/SVGElementInstance.h"
31 #include "core/svg/SVGLength.h"
32 #include "core/svg/SVGTransformList.h"
36 // Animated property definitions
37 BEGIN_REGISTER_ANIMATED_PROPERTIES(SVGLinearGradientElement)
38 REGISTER_PARENT_ANIMATED_PROPERTIES(SVGGradientElement)
39 END_REGISTER_ANIMATED_PROPERTIES
41 inline SVGLinearGradientElement::SVGLinearGradientElement(Document& document)
42 : SVGGradientElement(SVGNames::linearGradientTag, document)
43 , m_x1(SVGAnimatedLength::create(this, SVGNames::x1Attr, SVGLength::create(LengthModeWidth)))
44 , m_y1(SVGAnimatedLength::create(this, SVGNames::y1Attr, SVGLength::create(LengthModeHeight)))
45 , m_x2(SVGAnimatedLength::create(this, SVGNames::x2Attr, SVGLength::create(LengthModeWidth)))
46 , m_y2(SVGAnimatedLength::create(this, SVGNames::y2Attr, SVGLength::create(LengthModeHeight)))
48 ScriptWrappable::init(this);
50 // Spec: If the x2 attribute is not specified, the effect is as if a value of "100%" were specified.
51 m_x2->setDefaultValueAsString("100%");
53 addToPropertyMap(m_x1);
54 addToPropertyMap(m_y1);
55 addToPropertyMap(m_x2);
56 addToPropertyMap(m_y2);
57 registerAnimatedPropertiesForSVGLinearGradientElement();
60 PassRefPtr<SVGLinearGradientElement> SVGLinearGradientElement::create(Document& document)
62 return adoptRef(new SVGLinearGradientElement(document));
65 bool SVGLinearGradientElement::isSupportedAttribute(const QualifiedName& attrName)
67 DEFINE_STATIC_LOCAL(HashSet<QualifiedName>, supportedAttributes, ());
68 if (supportedAttributes.isEmpty()) {
69 supportedAttributes.add(SVGNames::x1Attr);
70 supportedAttributes.add(SVGNames::x2Attr);
71 supportedAttributes.add(SVGNames::y1Attr);
72 supportedAttributes.add(SVGNames::y2Attr);
74 return supportedAttributes.contains<SVGAttributeHashTranslator>(attrName);
77 void SVGLinearGradientElement::parseAttribute(const QualifiedName& name, const AtomicString& value)
79 SVGParsingError parseError = NoError;
81 if (!isSupportedAttribute(name))
82 SVGGradientElement::parseAttribute(name, value);
83 else if (name == SVGNames::x1Attr)
84 m_x1->setBaseValueAsString(value, AllowNegativeLengths, parseError);
85 else if (name == SVGNames::y1Attr)
86 m_y1->setBaseValueAsString(value, AllowNegativeLengths, parseError);
87 else if (name == SVGNames::x2Attr)
88 m_x2->setBaseValueAsString(value, AllowNegativeLengths, parseError);
89 else if (name == SVGNames::y2Attr)
90 m_y2->setBaseValueAsString(value, AllowNegativeLengths, parseError);
94 reportAttributeParsingError(parseError, name, value);
97 void SVGLinearGradientElement::svgAttributeChanged(const QualifiedName& attrName)
99 if (!isSupportedAttribute(attrName)) {
100 SVGGradientElement::svgAttributeChanged(attrName);
104 SVGElementInstance::InvalidationGuard invalidationGuard(this);
106 updateRelativeLengthsInformation();
108 RenderSVGResourceContainer* renderer = toRenderSVGResourceContainer(this->renderer());
110 renderer->invalidateCacheAndMarkForLayout();
113 RenderObject* SVGLinearGradientElement::createRenderer(RenderStyle*)
115 return new RenderSVGResourceLinearGradient(this);
118 static void setGradientAttributes(SVGGradientElement* element, LinearGradientAttributes& attributes, bool isLinear = true)
120 if (!attributes.hasSpreadMethod() && element->spreadMethodSpecified())
121 attributes.setSpreadMethod(element->spreadMethodCurrentValue());
123 if (!attributes.hasGradientUnits() && element->gradientUnitsSpecified())
124 attributes.setGradientUnits(element->gradientUnitsCurrentValue());
126 if (!attributes.hasGradientTransform() && element->gradientTransformSpecified()) {
127 AffineTransform transform;
128 element->gradientTransformCurrentValue().concatenate(transform);
129 attributes.setGradientTransform(transform);
132 if (!attributes.hasStops()) {
133 const Vector<Gradient::ColorStop>& stops(element->buildStops());
134 if (!stops.isEmpty())
135 attributes.setStops(stops);
139 SVGLinearGradientElement* linear = toSVGLinearGradientElement(element);
141 if (!attributes.hasX1() && linear->x1()->isSpecified())
142 attributes.setX1(linear->x1()->currentValue());
144 if (!attributes.hasY1() && linear->y1()->isSpecified())
145 attributes.setY1(linear->y1()->currentValue());
147 if (!attributes.hasX2() && linear->x2()->isSpecified())
148 attributes.setX2(linear->x2()->currentValue());
150 if (!attributes.hasY2() && linear->y2()->isSpecified())
151 attributes.setY2(linear->y2()->currentValue());
155 bool SVGLinearGradientElement::collectGradientAttributes(LinearGradientAttributes& attributes)
160 HashSet<SVGGradientElement*> processedGradients;
161 SVGGradientElement* current = this;
163 setGradientAttributes(current, attributes);
164 processedGradients.add(current);
167 // Respect xlink:href, take attributes from referenced element
168 Node* refNode = SVGURIReference::targetElementFromIRIString(current->hrefCurrentValue(), document());
169 if (refNode && isSVGGradientElement(*refNode)) {
170 current = toSVGGradientElement(refNode);
173 if (processedGradients.contains(current))
176 if (!current->renderer())
179 setGradientAttributes(current, attributes, current->hasTagName(SVGNames::linearGradientTag));
180 processedGradients.add(current);
186 ASSERT_NOT_REACHED();
190 bool SVGLinearGradientElement::selfHasRelativeLengths() const
192 return m_x1->currentValue()->isRelative()
193 || m_y1->currentValue()->isRelative()
194 || m_x2->currentValue()->isRelative()
195 || m_y2->currentValue()->isRelative();