1 /* 2 * Copyright (C) 2004, 2005, 2006, 2008 Nikolas Zimmermann <zimmermann (at) kde.org> 3 * Copyright (C) 2004, 2005, 2006, 2007 Rob Buis <buis (at) 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/SVGCircleElement.h" 24 25 #include "SVGNames.h" 26 #include "core/rendering/svg/RenderSVGEllipse.h" 27 #include "core/rendering/svg/RenderSVGResource.h" 28 #include "core/svg/SVGElementInstance.h" 29 #include "core/svg/SVGLength.h" 30 31 namespace WebCore { 32 33 // Animated property definitions 34 DEFINE_ANIMATED_LENGTH(SVGCircleElement, SVGNames::cxAttr, Cx, cx) 35 DEFINE_ANIMATED_LENGTH(SVGCircleElement, SVGNames::cyAttr, Cy, cy) 36 DEFINE_ANIMATED_LENGTH(SVGCircleElement, SVGNames::rAttr, R, r) 37 DEFINE_ANIMATED_BOOLEAN(SVGCircleElement, SVGNames::externalResourcesRequiredAttr, ExternalResourcesRequired, externalResourcesRequired) 38 39 BEGIN_REGISTER_ANIMATED_PROPERTIES(SVGCircleElement) 40 REGISTER_LOCAL_ANIMATED_PROPERTY(cx) 41 REGISTER_LOCAL_ANIMATED_PROPERTY(cy) 42 REGISTER_LOCAL_ANIMATED_PROPERTY(r) 43 REGISTER_LOCAL_ANIMATED_PROPERTY(externalResourcesRequired) 44 REGISTER_PARENT_ANIMATED_PROPERTIES(SVGGraphicsElement) 45 END_REGISTER_ANIMATED_PROPERTIES 46 47 inline SVGCircleElement::SVGCircleElement(const QualifiedName& tagName, Document* document) 48 : SVGGraphicsElement(tagName, document) 49 , m_cx(LengthModeWidth) 50 , m_cy(LengthModeHeight) 51 , m_r(LengthModeOther) 52 { 53 ASSERT(hasTagName(SVGNames::circleTag)); 54 ScriptWrappable::init(this); 55 registerAnimatedPropertiesForSVGCircleElement(); 56 } 57 58 PassRefPtr<SVGCircleElement> SVGCircleElement::create(const QualifiedName& tagName, Document* document) 59 { 60 return adoptRef(new SVGCircleElement(tagName, document)); 61 } 62 63 bool SVGCircleElement::isSupportedAttribute(const QualifiedName& attrName) 64 { 65 DEFINE_STATIC_LOCAL(HashSet<QualifiedName>, supportedAttributes, ()); 66 if (supportedAttributes.isEmpty()) { 67 SVGLangSpace::addSupportedAttributes(supportedAttributes); 68 SVGExternalResourcesRequired::addSupportedAttributes(supportedAttributes); 69 supportedAttributes.add(SVGNames::cxAttr); 70 supportedAttributes.add(SVGNames::cyAttr); 71 supportedAttributes.add(SVGNames::rAttr); 72 } 73 return supportedAttributes.contains<SVGAttributeHashTranslator>(attrName); 74 } 75 76 void SVGCircleElement::parseAttribute(const QualifiedName& name, const AtomicString& value) 77 { 78 SVGParsingError parseError = NoError; 79 80 if (!isSupportedAttribute(name)) 81 SVGGraphicsElement::parseAttribute(name, value); 82 else if (name == SVGNames::cxAttr) 83 setCxBaseValue(SVGLength::construct(LengthModeWidth, value, parseError)); 84 else if (name == SVGNames::cyAttr) 85 setCyBaseValue(SVGLength::construct(LengthModeHeight, value, parseError)); 86 else if (name == SVGNames::rAttr) 87 setRBaseValue(SVGLength::construct(LengthModeOther, value, parseError, ForbidNegativeLengths)); 88 else if (SVGLangSpace::parseAttribute(name, value) 89 || SVGExternalResourcesRequired::parseAttribute(name, value)) { 90 } else 91 ASSERT_NOT_REACHED(); 92 93 reportAttributeParsingError(parseError, name, value); 94 } 95 96 void SVGCircleElement::svgAttributeChanged(const QualifiedName& attrName) 97 { 98 if (!isSupportedAttribute(attrName)) { 99 SVGGraphicsElement::svgAttributeChanged(attrName); 100 return; 101 } 102 103 SVGElementInstance::InvalidationGuard invalidationGuard(this); 104 105 bool isLengthAttribute = attrName == SVGNames::cxAttr 106 || attrName == SVGNames::cyAttr 107 || attrName == SVGNames::rAttr; 108 109 if (isLengthAttribute) 110 updateRelativeLengthsInformation(); 111 112 RenderSVGShape* renderer = toRenderSVGShape(this->renderer()); 113 if (!renderer) 114 return; 115 116 if (isLengthAttribute) { 117 renderer->setNeedsShapeUpdate(); 118 RenderSVGResource::markForLayoutAndParentResourceInvalidation(renderer); 119 return; 120 } 121 122 if (SVGLangSpace::isKnownAttribute(attrName) || SVGExternalResourcesRequired::isKnownAttribute(attrName)) { 123 RenderSVGResource::markForLayoutAndParentResourceInvalidation(renderer); 124 return; 125 } 126 127 ASSERT_NOT_REACHED(); 128 } 129 130 bool SVGCircleElement::selfHasRelativeLengths() const 131 { 132 return cxCurrentValue().isRelative() 133 || cyCurrentValue().isRelative() 134 || rCurrentValue().isRelative(); 135 } 136 137 RenderObject* SVGCircleElement::createRenderer(RenderStyle*) 138 { 139 return new RenderSVGEllipse(this); 140 } 141 142 } 143