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