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 "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 30 namespace WebCore { 31 32 // Animated property definitions 33 DEFINE_ANIMATED_STRING(SVGMPathElement, XLinkNames::hrefAttr, Href, href) 34 DEFINE_ANIMATED_BOOLEAN(SVGMPathElement, SVGNames::externalResourcesRequiredAttr, ExternalResourcesRequired, externalResourcesRequired) 35 36 BEGIN_REGISTER_ANIMATED_PROPERTIES(SVGMPathElement) 37 REGISTER_LOCAL_ANIMATED_PROPERTY(href) 38 REGISTER_LOCAL_ANIMATED_PROPERTY(externalResourcesRequired) 39 END_REGISTER_ANIMATED_PROPERTIES 40 41 inline SVGMPathElement::SVGMPathElement(Document& document) 42 : SVGElement(SVGNames::mpathTag, document) 43 { 44 ScriptWrappable::init(this); 45 registerAnimatedPropertiesForSVGMPathElement(); 46 } 47 48 PassRefPtr<SVGMPathElement> SVGMPathElement::create(Document& document) 49 { 50 return adoptRef(new SVGMPathElement(document)); 51 } 52 53 SVGMPathElement::~SVGMPathElement() 54 { 55 clearResourceReferences(); 56 } 57 58 void 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 84 void SVGMPathElement::clearResourceReferences() 85 { 86 document().accessSVGExtensions()->removeAllTargetReferencesForElement(this); 87 } 88 89 Node::InsertionNotificationRequest SVGMPathElement::insertedInto(ContainerNode* rootParent) 90 { 91 SVGElement::insertedInto(rootParent); 92 if (rootParent->inDocument()) 93 buildPendingResource(); 94 return InsertionDone; 95 } 96 97 void SVGMPathElement::removedFrom(ContainerNode* rootParent) 98 { 99 SVGElement::removedFrom(rootParent); 100 notifyParentOfPathChange(rootParent); 101 if (rootParent->inDocument()) 102 clearResourceReferences(); 103 } 104 105 bool 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 115 void 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 130 void 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 150 SVGPathElement* 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 158 void SVGMPathElement::targetPathChanged() 159 { 160 notifyParentOfPathChange(parentNode()); 161 } 162 163 void SVGMPathElement::notifyParentOfPathChange(ContainerNode* parent) 164 { 165 if (parent && parent->hasTagName(SVGNames::animateMotionTag)) 166 static_cast<SVGAnimateMotionElement*>(parent)->updateAnimationPath(); 167 } 168 169 } // namespace WebCore 170