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 "SVGCircleElement.h"
25
26 #include "Attribute.h"
27 #include "FloatPoint.h"
28 #include "RenderSVGPath.h"
29 #include "RenderSVGResource.h"
30 #include "SVGLength.h"
31 #include "SVGNames.h"
32
33 namespace WebCore {
34
35 // Animated property definitions
DEFINE_ANIMATED_LENGTH(SVGCircleElement,SVGNames::cxAttr,Cx,cx)36 DEFINE_ANIMATED_LENGTH(SVGCircleElement, SVGNames::cxAttr, Cx, cx)
37 DEFINE_ANIMATED_LENGTH(SVGCircleElement, SVGNames::cyAttr, Cy, cy)
38 DEFINE_ANIMATED_LENGTH(SVGCircleElement, SVGNames::rAttr, R, r)
39 DEFINE_ANIMATED_BOOLEAN(SVGCircleElement, SVGNames::externalResourcesRequiredAttr, ExternalResourcesRequired, externalResourcesRequired)
40
41 inline SVGCircleElement::SVGCircleElement(const QualifiedName& tagName, Document* document)
42 : SVGStyledTransformableElement(tagName, document)
43 , m_cx(LengthModeWidth)
44 , m_cy(LengthModeHeight)
45 , m_r(LengthModeOther)
46 {
47 }
48
create(const QualifiedName & tagName,Document * document)49 PassRefPtr<SVGCircleElement> SVGCircleElement::create(const QualifiedName& tagName, Document* document)
50 {
51 return adoptRef(new SVGCircleElement(tagName, document));
52 }
53
parseMappedAttribute(Attribute * attr)54 void SVGCircleElement::parseMappedAttribute(Attribute* attr)
55 {
56 if (attr->name() == SVGNames::cxAttr)
57 setCxBaseValue(SVGLength(LengthModeWidth, attr->value()));
58 else if (attr->name() == SVGNames::cyAttr)
59 setCyBaseValue(SVGLength(LengthModeHeight, attr->value()));
60 else if (attr->name() == SVGNames::rAttr) {
61 setRBaseValue(SVGLength(LengthModeOther, attr->value()));
62 if (rBaseValue().value(this) < 0.0)
63 document()->accessSVGExtensions()->reportError("A negative value for circle <r> is not allowed");
64 } else {
65 if (SVGTests::parseMappedAttribute(attr))
66 return;
67 if (SVGLangSpace::parseMappedAttribute(attr))
68 return;
69 if (SVGExternalResourcesRequired::parseMappedAttribute(attr))
70 return;
71 SVGStyledTransformableElement::parseMappedAttribute(attr);
72 }
73 }
74
svgAttributeChanged(const QualifiedName & attrName)75 void SVGCircleElement::svgAttributeChanged(const QualifiedName& attrName)
76 {
77 SVGStyledTransformableElement::svgAttributeChanged(attrName);
78
79 bool isLengthAttribute = attrName == SVGNames::cxAttr
80 || attrName == SVGNames::cyAttr
81 || attrName == SVGNames::rAttr;
82
83 if (isLengthAttribute)
84 updateRelativeLengthsInformation();
85
86 if (SVGTests::handleAttributeChange(this, attrName))
87 return;
88
89 RenderSVGPath* renderer = static_cast<RenderSVGPath*>(this->renderer());
90 if (!renderer)
91 return;
92
93 if (isLengthAttribute) {
94 renderer->setNeedsPathUpdate();
95 RenderSVGResource::markForLayoutAndParentResourceInvalidation(renderer);
96 return;
97 }
98
99 if (SVGLangSpace::isKnownAttribute(attrName)
100 || SVGExternalResourcesRequired::isKnownAttribute(attrName))
101 RenderSVGResource::markForLayoutAndParentResourceInvalidation(renderer);
102 }
103
synchronizeProperty(const QualifiedName & attrName)104 void SVGCircleElement::synchronizeProperty(const QualifiedName& attrName)
105 {
106 SVGStyledTransformableElement::synchronizeProperty(attrName);
107
108 if (attrName == anyQName()) {
109 synchronizeCx();
110 synchronizeCy();
111 synchronizeR();
112 synchronizeExternalResourcesRequired();
113 SVGTests::synchronizeProperties(this, attrName);
114 return;
115 }
116
117 if (attrName == SVGNames::cxAttr)
118 synchronizeCx();
119 else if (attrName == SVGNames::cyAttr)
120 synchronizeCy();
121 else if (attrName == SVGNames::rAttr)
122 synchronizeR();
123 else if (SVGExternalResourcesRequired::isKnownAttribute(attrName))
124 synchronizeExternalResourcesRequired();
125 else if (SVGTests::isKnownAttribute(attrName))
126 SVGTests::synchronizeProperties(this, attrName);
127 }
128
attributeToPropertyTypeMap()129 AttributeToPropertyTypeMap& SVGCircleElement::attributeToPropertyTypeMap()
130 {
131 DEFINE_STATIC_LOCAL(AttributeToPropertyTypeMap, s_attributeToPropertyTypeMap, ());
132 return s_attributeToPropertyTypeMap;
133 }
134
fillAttributeToPropertyTypeMap()135 void SVGCircleElement::fillAttributeToPropertyTypeMap()
136 {
137 AttributeToPropertyTypeMap& attributeToPropertyTypeMap = this->attributeToPropertyTypeMap();
138
139 SVGStyledTransformableElement::fillPassedAttributeToPropertyTypeMap(attributeToPropertyTypeMap);
140 attributeToPropertyTypeMap.set(SVGNames::cxAttr, AnimatedLength);
141 attributeToPropertyTypeMap.set(SVGNames::cyAttr, AnimatedLength);
142 attributeToPropertyTypeMap.set(SVGNames::rAttr, AnimatedLength);
143 }
144
toPathData(Path & path) const145 void SVGCircleElement::toPathData(Path& path) const
146 {
147 ASSERT(path.isEmpty());
148
149 float radius = r().value(this);
150
151 if (radius <= 0)
152 return;
153
154 path.addEllipse(FloatRect(cx().value(this) - radius, cy().value(this) - radius, radius * 2, radius * 2));
155 }
156
selfHasRelativeLengths() const157 bool SVGCircleElement::selfHasRelativeLengths() const
158 {
159 return cx().isRelative()
160 || cy().isRelative()
161 || r().isRelative();
162 }
163
164 }
165
166 #endif // ENABLE(SVG)
167