1 /* 2 * Copyright (C) 2007 Eric Seidel <eric (at) 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 "SVGNames.h" 25 #include "XLinkNames.h" 26 #include "core/dom/Document.h" 27 #include "core/svg/SVGAnimateMotionElement.h" 28 #include "core/svg/SVGDocumentExtensions.h" 29 #include "core/svg/SVGPathElement.h" 30 31 namespace WebCore { 32 33 // Animated property definitions 34 DEFINE_ANIMATED_STRING(SVGMPathElement, XLinkNames::hrefAttr, Href, href) 35 DEFINE_ANIMATED_BOOLEAN(SVGMPathElement, SVGNames::externalResourcesRequiredAttr, ExternalResourcesRequired, externalResourcesRequired) 36 37 BEGIN_REGISTER_ANIMATED_PROPERTIES(SVGMPathElement) 38 REGISTER_LOCAL_ANIMATED_PROPERTY(href) 39 REGISTER_LOCAL_ANIMATED_PROPERTY(externalResourcesRequired) 40 END_REGISTER_ANIMATED_PROPERTIES 41 42 inline SVGMPathElement::SVGMPathElement(const QualifiedName& tagName, Document* document) 43 : SVGElement(tagName, document) 44 { 45 ASSERT(hasTagName(SVGNames::mpathTag)); 46 ScriptWrappable::init(this); 47 registerAnimatedPropertiesForSVGMPathElement(); 48 } 49 50 PassRefPtr<SVGMPathElement> SVGMPathElement::create(const QualifiedName& tagName, Document* document) 51 { 52 return adoptRef(new SVGMPathElement(tagName, document)); 53 } 54 55 SVGMPathElement::~SVGMPathElement() 56 { 57 clearResourceReferences(); 58 } 59 60 void SVGMPathElement::buildPendingResource() 61 { 62 clearResourceReferences(); 63 if (!inDocument()) 64 return; 65 66 String id; 67 Element* target = SVGURIReference::targetElementFromIRIString(hrefCurrentValue(), document(), &id); 68 if (!target) { 69 // Do not register as pending if we are already pending this resource. 70 if (document()->accessSVGExtensions()->isElementPendingResource(this, id)) 71 return; 72 73 if (!id.isEmpty()) { 74 document()->accessSVGExtensions()->addPendingResource(id, this); 75 ASSERT(hasPendingResources()); 76 } 77 } else if (target->isSVGElement()) { 78 // Register us with the target in the dependencies map. Any change of hrefElement 79 // that leads to relayout/repainting now informs us, so we can react to it. 80 document()->accessSVGExtensions()->addElementReferencingTarget(this, toSVGElement(target)); 81 } 82 83 targetPathChanged(); 84 } 85 86 void SVGMPathElement::clearResourceReferences() 87 { 88 ASSERT(document()); 89 document()->accessSVGExtensions()->removeAllTargetReferencesForElement(this); 90 } 91 92 Node::InsertionNotificationRequest SVGMPathElement::insertedInto(ContainerNode* rootParent) 93 { 94 SVGElement::insertedInto(rootParent); 95 if (rootParent->inDocument()) 96 buildPendingResource(); 97 return InsertionDone; 98 } 99 100 void SVGMPathElement::removedFrom(ContainerNode* rootParent) 101 { 102 SVGElement::removedFrom(rootParent); 103 notifyParentOfPathChange(rootParent); 104 if (rootParent->inDocument()) 105 clearResourceReferences(); 106 } 107 108 bool SVGMPathElement::isSupportedAttribute(const QualifiedName& attrName) 109 { 110 DEFINE_STATIC_LOCAL(HashSet<QualifiedName>, supportedAttributes, ()); 111 if (supportedAttributes.isEmpty()) { 112 SVGURIReference::addSupportedAttributes(supportedAttributes); 113 SVGExternalResourcesRequired::addSupportedAttributes(supportedAttributes); 114 } 115 return supportedAttributes.contains<SVGAttributeHashTranslator>(attrName); 116 } 117 118 void SVGMPathElement::parseAttribute(const QualifiedName& name, const AtomicString& value) 119 { 120 if (!isSupportedAttribute(name)) { 121 SVGElement::parseAttribute(name, value); 122 return; 123 } 124 125 if (SVGURIReference::parseAttribute(name, value)) 126 return; 127 if (SVGExternalResourcesRequired::parseAttribute(name, value)) 128 return; 129 130 ASSERT_NOT_REACHED(); 131 } 132 133 void SVGMPathElement::svgAttributeChanged(const QualifiedName& attrName) 134 { 135 if (!isSupportedAttribute(attrName)) { 136 SVGElement::svgAttributeChanged(attrName); 137 return; 138 } 139 140 SVGElementInstance::InvalidationGuard invalidationGuard(this); 141 142 if (SVGURIReference::isKnownAttribute(attrName)) { 143 buildPendingResource(); 144 return; 145 } 146 147 if (SVGExternalResourcesRequired::isKnownAttribute(attrName)) 148 return; 149 150 ASSERT_NOT_REACHED(); 151 } 152 153 SVGPathElement* SVGMPathElement::pathElement() 154 { 155 Element* target = targetElementFromIRIString(hrefCurrentValue(), document()); 156 if (target && target->hasTagName(SVGNames::pathTag)) 157 return toSVGPathElement(target); 158 return 0; 159 } 160 161 void SVGMPathElement::targetPathChanged() 162 { 163 notifyParentOfPathChange(parentNode()); 164 } 165 166 void SVGMPathElement::notifyParentOfPathChange(ContainerNode* parent) 167 { 168 if (parent && parent->hasTagName(SVGNames::animateMotionTag)) 169 static_cast<SVGAnimateMotionElement*>(parent)->updateAnimationPath(); 170 } 171 172 } // namespace WebCore 173