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/SVGPolyElement.h" 24 25 #include "core/dom/Document.h" 26 #include "core/rendering/svg/RenderSVGResource.h" 27 #include "core/svg/SVGAnimatedPointList.h" 28 #include "core/svg/SVGElementInstance.h" 29 #include "core/svg/SVGParserUtilities.h" 30 31 namespace WebCore { 32 33 // Define custom animated property 'points'. 34 const SVGPropertyInfo* SVGPolyElement::pointsPropertyInfo() 35 { 36 static const SVGPropertyInfo* s_propertyInfo = 0; 37 if (!s_propertyInfo) { 38 s_propertyInfo = new SVGPropertyInfo(AnimatedPoints, 39 PropertyIsReadWrite, 40 SVGNames::pointsAttr, 41 SVGNames::pointsAttr.localName(), 42 &SVGPolyElement::synchronizePoints, 43 &SVGPolyElement::lookupOrCreatePointsWrapper); 44 } 45 return s_propertyInfo; 46 } 47 48 SVGPointList& SVGPolyElement::pointsCurrentValue() 49 { 50 SVGAnimatedProperty* wrapper = SVGAnimatedProperty::lookupWrapper<SVGPolyElement, SVGAnimatedPointList>(this, pointsPropertyInfo()); 51 if (wrapper && wrapper->isAnimating()) { 52 if (SVGListPropertyTearOff<SVGPointList>* ap = animatedPoints()) 53 return ap->values(); 54 } 55 56 return m_points.value; 57 } 58 59 // Animated property definitions 60 DEFINE_ANIMATED_BOOLEAN(SVGPolyElement, SVGNames::externalResourcesRequiredAttr, ExternalResourcesRequired, externalResourcesRequired) 61 62 BEGIN_REGISTER_ANIMATED_PROPERTIES(SVGPolyElement) 63 REGISTER_LOCAL_ANIMATED_PROPERTY(points) 64 REGISTER_LOCAL_ANIMATED_PROPERTY(externalResourcesRequired) 65 REGISTER_PARENT_ANIMATED_PROPERTIES(SVGGraphicsElement) 66 END_REGISTER_ANIMATED_PROPERTIES 67 68 SVGPolyElement::SVGPolyElement(const QualifiedName& tagName, Document& document) 69 : SVGGeometryElement(tagName, document) 70 { 71 registerAnimatedPropertiesForSVGPolyElement(); 72 } 73 74 bool SVGPolyElement::isSupportedAttribute(const QualifiedName& attrName) 75 { 76 DEFINE_STATIC_LOCAL(HashSet<QualifiedName>, supportedAttributes, ()); 77 if (supportedAttributes.isEmpty()) { 78 SVGExternalResourcesRequired::addSupportedAttributes(supportedAttributes); 79 supportedAttributes.add(SVGNames::pointsAttr); 80 } 81 return supportedAttributes.contains<SVGAttributeHashTranslator>(attrName); 82 } 83 84 void SVGPolyElement::parseAttribute(const QualifiedName& name, const AtomicString& value) 85 { 86 if (!isSupportedAttribute(name)) { 87 SVGGeometryElement::parseAttribute(name, value); 88 return; 89 } 90 91 if (name == SVGNames::pointsAttr) { 92 SVGPointList newList; 93 if (!pointsListFromSVGData(newList, value)) 94 document().accessSVGExtensions()->reportError("Problem parsing points=\"" + value + "\""); 95 96 if (SVGAnimatedProperty* wrapper = SVGAnimatedProperty::lookupWrapper<SVGPolyElement, SVGAnimatedPointList>(this, pointsPropertyInfo())) 97 static_cast<SVGAnimatedPointList*>(wrapper)->detachListWrappers(newList.size()); 98 99 m_points.value = newList; 100 return; 101 } 102 103 if (SVGExternalResourcesRequired::parseAttribute(name, value)) 104 return; 105 106 ASSERT_NOT_REACHED(); 107 } 108 109 void SVGPolyElement::svgAttributeChanged(const QualifiedName& attrName) 110 { 111 if (!isSupportedAttribute(attrName)) { 112 SVGGeometryElement::svgAttributeChanged(attrName); 113 return; 114 } 115 116 SVGElementInstance::InvalidationGuard invalidationGuard(this); 117 118 RenderSVGShape* renderer = toRenderSVGShape(this->renderer()); 119 if (!renderer) 120 return; 121 122 if (attrName == SVGNames::pointsAttr) { 123 renderer->setNeedsShapeUpdate(); 124 RenderSVGResource::markForLayoutAndParentResourceInvalidation(renderer); 125 return; 126 } 127 128 if (SVGExternalResourcesRequired::isKnownAttribute(attrName)) { 129 RenderSVGResource::markForLayoutAndParentResourceInvalidation(renderer); 130 return; 131 } 132 133 ASSERT_NOT_REACHED(); 134 } 135 136 void SVGPolyElement::synchronizePoints(SVGElement* contextElement) 137 { 138 ASSERT(contextElement); 139 SVGPolyElement* ownerType = toSVGPolyElement(contextElement); 140 if (!ownerType->m_points.shouldSynchronize) 141 return; 142 ownerType->m_points.synchronize(ownerType, pointsPropertyInfo()->attributeName, ownerType->m_points.value.valueAsString()); 143 } 144 145 PassRefPtr<SVGAnimatedProperty> SVGPolyElement::lookupOrCreatePointsWrapper(SVGElement* contextElement) 146 { 147 ASSERT(contextElement); 148 SVGPolyElement* ownerType = toSVGPolyElement(contextElement); 149 return SVGAnimatedProperty::lookupOrCreateWrapper<SVGPolyElement, SVGAnimatedPointList, SVGPointList> 150 (ownerType, pointsPropertyInfo(), ownerType->m_points.value); 151 } 152 153 SVGListPropertyTearOff<SVGPointList>* SVGPolyElement::points() 154 { 155 m_points.shouldSynchronize = true; 156 return static_cast<SVGListPropertyTearOff<SVGPointList>*>(static_pointer_cast<SVGAnimatedPointList>(lookupOrCreatePointsWrapper(this))->baseVal()); 157 } 158 159 SVGListPropertyTearOff<SVGPointList>* SVGPolyElement::animatedPoints() 160 { 161 m_points.shouldSynchronize = true; 162 return static_cast<SVGListPropertyTearOff<SVGPointList>*>(static_pointer_cast<SVGAnimatedPointList>(lookupOrCreatePointsWrapper(this))->animVal()); 163 } 164 165 } 166