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