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 "RenderSVGRect.h"
29#include "RenderSVGResource.h"
30#include "SVGElementInstance.h"
31#include "SVGLength.h"
32#include "SVGNames.h"
33
34namespace WebCore {
35
36// Animated property definitions
37DEFINE_ANIMATED_LENGTH(SVGRectElement, SVGNames::xAttr, X, x)
38DEFINE_ANIMATED_LENGTH(SVGRectElement, SVGNames::yAttr, Y, y)
39DEFINE_ANIMATED_LENGTH(SVGRectElement, SVGNames::widthAttr, Width, width)
40DEFINE_ANIMATED_LENGTH(SVGRectElement, SVGNames::heightAttr, Height, height)
41DEFINE_ANIMATED_LENGTH(SVGRectElement, SVGNames::rxAttr, Rx, rx)
42DEFINE_ANIMATED_LENGTH(SVGRectElement, SVGNames::ryAttr, Ry, ry)
43DEFINE_ANIMATED_BOOLEAN(SVGRectElement, SVGNames::externalResourcesRequiredAttr, ExternalResourcesRequired, externalResourcesRequired)
44
45BEGIN_REGISTER_ANIMATED_PROPERTIES(SVGRectElement)
46    REGISTER_LOCAL_ANIMATED_PROPERTY(x)
47    REGISTER_LOCAL_ANIMATED_PROPERTY(y)
48    REGISTER_LOCAL_ANIMATED_PROPERTY(width)
49    REGISTER_LOCAL_ANIMATED_PROPERTY(height)
50    REGISTER_LOCAL_ANIMATED_PROPERTY(rx)
51    REGISTER_LOCAL_ANIMATED_PROPERTY(ry)
52    REGISTER_LOCAL_ANIMATED_PROPERTY(externalResourcesRequired)
53    REGISTER_PARENT_ANIMATED_PROPERTIES(SVGStyledTransformableElement)
54    REGISTER_PARENT_ANIMATED_PROPERTIES(SVGTests)
55END_REGISTER_ANIMATED_PROPERTIES
56
57inline SVGRectElement::SVGRectElement(const QualifiedName& tagName, Document* document)
58    : SVGStyledTransformableElement(tagName, document)
59    , m_x(LengthModeWidth)
60    , m_y(LengthModeHeight)
61    , m_width(LengthModeWidth)
62    , m_height(LengthModeHeight)
63    , m_rx(LengthModeWidth)
64    , m_ry(LengthModeHeight)
65{
66    ASSERT(hasTagName(SVGNames::rectTag));
67    registerAnimatedPropertiesForSVGRectElement();
68}
69
70PassRefPtr<SVGRectElement> SVGRectElement::create(const QualifiedName& tagName, Document* document)
71{
72    return adoptRef(new SVGRectElement(tagName, document));
73}
74
75bool SVGRectElement::isSupportedAttribute(const QualifiedName& attrName)
76{
77    DEFINE_STATIC_LOCAL(HashSet<QualifiedName>, supportedAttributes, ());
78    if (supportedAttributes.isEmpty()) {
79        SVGTests::addSupportedAttributes(supportedAttributes);
80        SVGLangSpace::addSupportedAttributes(supportedAttributes);
81        SVGExternalResourcesRequired::addSupportedAttributes(supportedAttributes);
82        supportedAttributes.add(SVGNames::xAttr);
83        supportedAttributes.add(SVGNames::yAttr);
84        supportedAttributes.add(SVGNames::widthAttr);
85        supportedAttributes.add(SVGNames::heightAttr);
86        supportedAttributes.add(SVGNames::rxAttr);
87        supportedAttributes.add(SVGNames::ryAttr);
88    }
89    return supportedAttributes.contains<QualifiedName, SVGAttributeHashTranslator>(attrName);
90}
91
92void SVGRectElement::parseAttribute(const QualifiedName& name, const AtomicString& value)
93{
94    SVGParsingError parseError = NoError;
95
96    if (!isSupportedAttribute(name))
97        SVGStyledTransformableElement::parseAttribute(name, value);
98    else if (name == SVGNames::xAttr)
99        setXBaseValue(SVGLength::construct(LengthModeWidth, value, parseError));
100    else if (name == SVGNames::yAttr)
101        setYBaseValue(SVGLength::construct(LengthModeHeight, value, parseError));
102    else if (name == SVGNames::rxAttr)
103        setRxBaseValue(SVGLength::construct(LengthModeWidth, value, parseError, ForbidNegativeLengths));
104    else if (name == SVGNames::ryAttr)
105        setRyBaseValue(SVGLength::construct(LengthModeHeight, value, parseError, ForbidNegativeLengths));
106    else if (name == SVGNames::widthAttr)
107        setWidthBaseValue(SVGLength::construct(LengthModeWidth, value, parseError, ForbidNegativeLengths));
108    else if (name == SVGNames::heightAttr)
109        setHeightBaseValue(SVGLength::construct(LengthModeHeight, value, parseError, ForbidNegativeLengths));
110    else if (SVGTests::parseAttribute(name, value)
111             || SVGLangSpace::parseAttribute(name, value)
112             || SVGExternalResourcesRequired::parseAttribute(name, value)) {
113    } else
114        ASSERT_NOT_REACHED();
115
116    reportAttributeParsingError(parseError, name, value);
117}
118
119void SVGRectElement::svgAttributeChanged(const QualifiedName& attrName)
120{
121    if (!isSupportedAttribute(attrName)) {
122        SVGStyledTransformableElement::svgAttributeChanged(attrName);
123        return;
124    }
125
126    SVGElementInstance::InvalidationGuard invalidationGuard(this);
127
128    bool isLengthAttribute = attrName == SVGNames::xAttr
129                          || attrName == SVGNames::yAttr
130                          || attrName == SVGNames::widthAttr
131                          || attrName == SVGNames::heightAttr
132                          || attrName == SVGNames::rxAttr
133                          || attrName == SVGNames::ryAttr;
134
135    if (isLengthAttribute)
136        updateRelativeLengthsInformation();
137
138    if (SVGTests::handleAttributeChange(this, attrName))
139        return;
140
141    RenderSVGShape* renderer = toRenderSVGShape(this->renderer());
142    if (!renderer)
143        return;
144
145    if (isLengthAttribute) {
146        renderer->setNeedsShapeUpdate();
147        RenderSVGResource::markForLayoutAndParentResourceInvalidation(renderer);
148        return;
149    }
150
151    if (SVGLangSpace::isKnownAttribute(attrName) || SVGExternalResourcesRequired::isKnownAttribute(attrName)) {
152        RenderSVGResource::markForLayoutAndParentResourceInvalidation(renderer);
153        return;
154    }
155
156    ASSERT_NOT_REACHED();
157}
158
159bool SVGRectElement::selfHasRelativeLengths() const
160{
161    return x().isRelative()
162        || y().isRelative()
163        || width().isRelative()
164        || height().isRelative()
165        || rx().isRelative()
166        || ry().isRelative();
167}
168
169RenderObject* SVGRectElement::createRenderer(RenderArena* arena, RenderStyle*)
170{
171    return new (arena) RenderSVGRect(this);
172}
173
174}
175
176#endif // ENABLE(SVG)
177