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 33namespace WebCore { 34 35// Animated property definitions 36DEFINE_ANIMATED_LENGTH(SVGCircleElement, SVGNames::cxAttr, Cx, cx) 37DEFINE_ANIMATED_LENGTH(SVGCircleElement, SVGNames::cyAttr, Cy, cy) 38DEFINE_ANIMATED_LENGTH(SVGCircleElement, SVGNames::rAttr, R, r) 39DEFINE_ANIMATED_BOOLEAN(SVGCircleElement, SVGNames::externalResourcesRequiredAttr, ExternalResourcesRequired, externalResourcesRequired) 40 41inline 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 49PassRefPtr<SVGCircleElement> SVGCircleElement::create(const QualifiedName& tagName, Document* document) 50{ 51 return adoptRef(new SVGCircleElement(tagName, document)); 52} 53 54void 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 75void 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 104void 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 129AttributeToPropertyTypeMap& SVGCircleElement::attributeToPropertyTypeMap() 130{ 131 DEFINE_STATIC_LOCAL(AttributeToPropertyTypeMap, s_attributeToPropertyTypeMap, ()); 132 return s_attributeToPropertyTypeMap; 133} 134 135void 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 145void 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 157bool SVGCircleElement::selfHasRelativeLengths() const 158{ 159 return cx().isRelative() 160 || cy().isRelative() 161 || r().isRelative(); 162} 163 164} 165 166#endif // ENABLE(SVG) 167