1 /*
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 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Library General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Library General Public License for more details.
14 *
15 * You should have received a copy of the GNU Library General Public License
16 * along with this library; see the file COPYING.LIB. If not, write to
17 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 * Boston, MA 02110-1301, USA.
19 */
20
21 #include "config.h"
22
23 #if ENABLE(SVG)
24 #include "SVGRectElement.h"
25
26 #include "Attribute.h"
27 #include "RenderSVGPath.h"
28 #include "RenderSVGResource.h"
29 #include "SVGLength.h"
30 #include "SVGNames.h"
31
32 namespace WebCore {
33
34 // Animated property definitions
DEFINE_ANIMATED_LENGTH(SVGRectElement,SVGNames::xAttr,X,x)35 DEFINE_ANIMATED_LENGTH(SVGRectElement, SVGNames::xAttr, X, x)
36 DEFINE_ANIMATED_LENGTH(SVGRectElement, SVGNames::yAttr, Y, y)
37 DEFINE_ANIMATED_LENGTH(SVGRectElement, SVGNames::widthAttr, Width, width)
38 DEFINE_ANIMATED_LENGTH(SVGRectElement, SVGNames::heightAttr, Height, height)
39 DEFINE_ANIMATED_LENGTH(SVGRectElement, SVGNames::rxAttr, Rx, rx)
40 DEFINE_ANIMATED_LENGTH(SVGRectElement, SVGNames::ryAttr, Ry, ry)
41 DEFINE_ANIMATED_BOOLEAN(SVGRectElement, SVGNames::externalResourcesRequiredAttr, ExternalResourcesRequired, externalResourcesRequired)
42
43 inline SVGRectElement::SVGRectElement(const QualifiedName& tagName, Document* document)
44 : SVGStyledTransformableElement(tagName, document)
45 , m_x(LengthModeWidth)
46 , m_y(LengthModeHeight)
47 , m_width(LengthModeWidth)
48 , m_height(LengthModeHeight)
49 , m_rx(LengthModeWidth)
50 , m_ry(LengthModeHeight)
51 {
52 }
53
create(const QualifiedName & tagName,Document * document)54 PassRefPtr<SVGRectElement> SVGRectElement::create(const QualifiedName& tagName, Document* document)
55 {
56 return adoptRef(new SVGRectElement(tagName, document));
57 }
58
parseMappedAttribute(Attribute * attr)59 void SVGRectElement::parseMappedAttribute(Attribute* attr)
60 {
61 if (attr->name() == SVGNames::xAttr)
62 setXBaseValue(SVGLength(LengthModeWidth, attr->value()));
63 else if (attr->name() == SVGNames::yAttr)
64 setYBaseValue(SVGLength(LengthModeHeight, attr->value()));
65 else if (attr->name() == SVGNames::rxAttr) {
66 setRxBaseValue(SVGLength(LengthModeWidth, attr->value()));
67 if (rxBaseValue().value(this) < 0.0)
68 document()->accessSVGExtensions()->reportError("A negative value for rect <rx> is not allowed");
69 } else if (attr->name() == SVGNames::ryAttr) {
70 setRyBaseValue(SVGLength(LengthModeHeight, attr->value()));
71 if (ryBaseValue().value(this) < 0.0)
72 document()->accessSVGExtensions()->reportError("A negative value for rect <ry> is not allowed");
73 } else if (attr->name() == SVGNames::widthAttr) {
74 setWidthBaseValue(SVGLength(LengthModeWidth, attr->value()));
75 if (widthBaseValue().value(this) < 0.0)
76 document()->accessSVGExtensions()->reportError("A negative value for rect <width> is not allowed");
77 } else if (attr->name() == SVGNames::heightAttr) {
78 setHeightBaseValue(SVGLength(LengthModeHeight, attr->value()));
79 if (heightBaseValue().value(this) < 0.0)
80 document()->accessSVGExtensions()->reportError("A negative value for rect <height> is not allowed");
81 } else {
82 if (SVGTests::parseMappedAttribute(attr))
83 return;
84 if (SVGLangSpace::parseMappedAttribute(attr))
85 return;
86 if (SVGExternalResourcesRequired::parseMappedAttribute(attr))
87 return;
88 SVGStyledTransformableElement::parseMappedAttribute(attr);
89 }
90 }
91
svgAttributeChanged(const QualifiedName & attrName)92 void SVGRectElement::svgAttributeChanged(const QualifiedName& attrName)
93 {
94 SVGStyledTransformableElement::svgAttributeChanged(attrName);
95
96 bool isLengthAttribute = attrName == SVGNames::xAttr
97 || attrName == SVGNames::yAttr
98 || attrName == SVGNames::widthAttr
99 || attrName == SVGNames::heightAttr
100 || attrName == SVGNames::rxAttr
101 || attrName == SVGNames::ryAttr;
102
103 if (isLengthAttribute)
104 updateRelativeLengthsInformation();
105
106 if (SVGTests::handleAttributeChange(this, attrName))
107 return;
108
109 RenderSVGPath* renderer = static_cast<RenderSVGPath*>(this->renderer());
110 if (!renderer)
111 return;
112
113 if (isLengthAttribute) {
114 renderer->setNeedsPathUpdate();
115 RenderSVGResource::markForLayoutAndParentResourceInvalidation(renderer);
116 return;
117 }
118
119 if (SVGLangSpace::isKnownAttribute(attrName)
120 || SVGExternalResourcesRequired::isKnownAttribute(attrName))
121 RenderSVGResource::markForLayoutAndParentResourceInvalidation(renderer);
122 }
123
synchronizeProperty(const QualifiedName & attrName)124 void SVGRectElement::synchronizeProperty(const QualifiedName& attrName)
125 {
126 SVGStyledTransformableElement::synchronizeProperty(attrName);
127
128 if (attrName == anyQName()) {
129 synchronizeX();
130 synchronizeY();
131 synchronizeWidth();
132 synchronizeHeight();
133 synchronizeRx();
134 synchronizeRy();
135 synchronizeExternalResourcesRequired();
136 SVGTests::synchronizeProperties(this, attrName);
137 return;
138 }
139
140 if (attrName == SVGNames::xAttr)
141 synchronizeX();
142 else if (attrName == SVGNames::yAttr)
143 synchronizeY();
144 else if (attrName == SVGNames::widthAttr)
145 synchronizeWidth();
146 else if (attrName == SVGNames::heightAttr)
147 synchronizeHeight();
148 else if (attrName == SVGNames::rxAttr)
149 synchronizeRx();
150 else if (attrName == SVGNames::ryAttr)
151 synchronizeRy();
152 else if (SVGExternalResourcesRequired::isKnownAttribute(attrName))
153 synchronizeExternalResourcesRequired();
154 else if (SVGTests::isKnownAttribute(attrName))
155 SVGTests::synchronizeProperties(this, attrName);
156 }
157
attributeToPropertyTypeMap()158 AttributeToPropertyTypeMap& SVGRectElement::attributeToPropertyTypeMap()
159 {
160 DEFINE_STATIC_LOCAL(AttributeToPropertyTypeMap, s_attributeToPropertyTypeMap, ());
161 return s_attributeToPropertyTypeMap;
162 }
163
fillAttributeToPropertyTypeMap()164 void SVGRectElement::fillAttributeToPropertyTypeMap()
165 {
166 AttributeToPropertyTypeMap& attributeToPropertyTypeMap = this->attributeToPropertyTypeMap();
167
168 SVGStyledTransformableElement::fillPassedAttributeToPropertyTypeMap(attributeToPropertyTypeMap);
169 attributeToPropertyTypeMap.set(SVGNames::xAttr, AnimatedLength);
170 attributeToPropertyTypeMap.set(SVGNames::yAttr, AnimatedLength);
171 attributeToPropertyTypeMap.set(SVGNames::widthAttr, AnimatedLength);
172 attributeToPropertyTypeMap.set(SVGNames::heightAttr, AnimatedLength);
173 attributeToPropertyTypeMap.set(SVGNames::rxAttr, AnimatedLength);
174 attributeToPropertyTypeMap.set(SVGNames::ryAttr, AnimatedLength);
175 }
176
toPathData(Path & path) const177 void SVGRectElement::toPathData(Path& path) const
178 {
179 ASSERT(path.isEmpty());
180
181 float widthValue = width().value(this);
182 if (widthValue <= 0)
183 return;
184
185 float heightValue = height().value(this);
186 if (heightValue <= 0)
187 return;
188
189 float xValue = x().value(this);
190 float yValue = y().value(this);
191
192 FloatRect rect(xValue, yValue, widthValue, heightValue);
193
194 bool hasRx = hasAttribute(SVGNames::rxAttr);
195 bool hasRy = hasAttribute(SVGNames::ryAttr);
196 if (hasRx || hasRy) {
197 float rxValue = rx().value(this);
198 float ryValue = ry().value(this);
199 if (!hasRx)
200 rxValue = ryValue;
201 else if (!hasRy)
202 ryValue = rxValue;
203 path.addRoundedRect(rect, FloatSize(rxValue, ryValue));
204 return;
205 }
206
207 path.addRect(rect);
208 }
209
selfHasRelativeLengths() const210 bool SVGRectElement::selfHasRelativeLengths() const
211 {
212 return x().isRelative()
213 || y().isRelative()
214 || width().isRelative()
215 || height().isRelative()
216 || rx().isRelative()
217 || ry().isRelative();
218 }
219
220 }
221
222 #endif // ENABLE(SVG)
223