1/* 2 * Copyright (C) 2007 Eric Seidel <eric@webkit.org> 3 * 4 * This library is free software; you can redistribute it and/or 5 * modify it under the terms of the GNU Library General Public 6 * License as published by the Free Software Foundation; either 7 * version 2 of the License, or (at your option) any later version. 8 * 9 * This library is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 * Library General Public License for more details. 13 * 14 * You should have received a copy of the GNU Library General Public License 15 * along with this library; see the file COPYING.LIB. If not, write to 16 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 17 * Boston, MA 02110-1301, USA. 18 */ 19 20#include "config.h" 21 22#include "core/svg/SVGMPathElement.h" 23 24#include "XLinkNames.h" 25#include "core/dom/Document.h" 26#include "core/svg/SVGAnimateMotionElement.h" 27#include "core/svg/SVGDocumentExtensions.h" 28#include "core/svg/SVGPathElement.h" 29 30namespace WebCore { 31 32// Animated property definitions 33DEFINE_ANIMATED_STRING(SVGMPathElement, XLinkNames::hrefAttr, Href, href) 34DEFINE_ANIMATED_BOOLEAN(SVGMPathElement, SVGNames::externalResourcesRequiredAttr, ExternalResourcesRequired, externalResourcesRequired) 35 36BEGIN_REGISTER_ANIMATED_PROPERTIES(SVGMPathElement) 37 REGISTER_LOCAL_ANIMATED_PROPERTY(href) 38 REGISTER_LOCAL_ANIMATED_PROPERTY(externalResourcesRequired) 39END_REGISTER_ANIMATED_PROPERTIES 40 41inline SVGMPathElement::SVGMPathElement(Document& document) 42 : SVGElement(SVGNames::mpathTag, document) 43{ 44 ScriptWrappable::init(this); 45 registerAnimatedPropertiesForSVGMPathElement(); 46} 47 48PassRefPtr<SVGMPathElement> SVGMPathElement::create(Document& document) 49{ 50 return adoptRef(new SVGMPathElement(document)); 51} 52 53SVGMPathElement::~SVGMPathElement() 54{ 55 clearResourceReferences(); 56} 57 58void SVGMPathElement::buildPendingResource() 59{ 60 clearResourceReferences(); 61 if (!inDocument()) 62 return; 63 64 String id; 65 Element* target = SVGURIReference::targetElementFromIRIString(hrefCurrentValue(), document(), &id); 66 if (!target) { 67 // Do not register as pending if we are already pending this resource. 68 if (document().accessSVGExtensions()->isElementPendingResource(this, id)) 69 return; 70 71 if (!id.isEmpty()) { 72 document().accessSVGExtensions()->addPendingResource(id, this); 73 ASSERT(hasPendingResources()); 74 } 75 } else if (target->isSVGElement()) { 76 // Register us with the target in the dependencies map. Any change of hrefElement 77 // that leads to relayout/repainting now informs us, so we can react to it. 78 document().accessSVGExtensions()->addElementReferencingTarget(this, toSVGElement(target)); 79 } 80 81 targetPathChanged(); 82} 83 84void SVGMPathElement::clearResourceReferences() 85{ 86 document().accessSVGExtensions()->removeAllTargetReferencesForElement(this); 87} 88 89Node::InsertionNotificationRequest SVGMPathElement::insertedInto(ContainerNode* rootParent) 90{ 91 SVGElement::insertedInto(rootParent); 92 if (rootParent->inDocument()) 93 buildPendingResource(); 94 return InsertionDone; 95} 96 97void SVGMPathElement::removedFrom(ContainerNode* rootParent) 98{ 99 SVGElement::removedFrom(rootParent); 100 notifyParentOfPathChange(rootParent); 101 if (rootParent->inDocument()) 102 clearResourceReferences(); 103} 104 105bool SVGMPathElement::isSupportedAttribute(const QualifiedName& attrName) 106{ 107 DEFINE_STATIC_LOCAL(HashSet<QualifiedName>, supportedAttributes, ()); 108 if (supportedAttributes.isEmpty()) { 109 SVGURIReference::addSupportedAttributes(supportedAttributes); 110 SVGExternalResourcesRequired::addSupportedAttributes(supportedAttributes); 111 } 112 return supportedAttributes.contains<SVGAttributeHashTranslator>(attrName); 113} 114 115void SVGMPathElement::parseAttribute(const QualifiedName& name, const AtomicString& value) 116{ 117 if (!isSupportedAttribute(name)) { 118 SVGElement::parseAttribute(name, value); 119 return; 120 } 121 122 if (SVGURIReference::parseAttribute(name, value)) 123 return; 124 if (SVGExternalResourcesRequired::parseAttribute(name, value)) 125 return; 126 127 ASSERT_NOT_REACHED(); 128} 129 130void SVGMPathElement::svgAttributeChanged(const QualifiedName& attrName) 131{ 132 if (!isSupportedAttribute(attrName)) { 133 SVGElement::svgAttributeChanged(attrName); 134 return; 135 } 136 137 SVGElementInstance::InvalidationGuard invalidationGuard(this); 138 139 if (SVGURIReference::isKnownAttribute(attrName)) { 140 buildPendingResource(); 141 return; 142 } 143 144 if (SVGExternalResourcesRequired::isKnownAttribute(attrName)) 145 return; 146 147 ASSERT_NOT_REACHED(); 148} 149 150SVGPathElement* SVGMPathElement::pathElement() 151{ 152 Element* target = targetElementFromIRIString(hrefCurrentValue(), document()); 153 if (target && target->hasTagName(SVGNames::pathTag)) 154 return toSVGPathElement(target); 155 return 0; 156} 157 158void SVGMPathElement::targetPathChanged() 159{ 160 notifyParentOfPathChange(parentNode()); 161} 162 163void SVGMPathElement::notifyParentOfPathChange(ContainerNode* parent) 164{ 165 if (parent && parent->hasTagName(SVGNames::animateMotionTag)) 166 static_cast<SVGAnimateMotionElement*>(parent)->updateAnimationPath(); 167} 168 169} // namespace WebCore 170