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 "core/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 inline SVGMPathElement::SVGMPathElement(Document& document) 33 : SVGElement(SVGNames::mpathTag, document) 34 , SVGURIReference(this) 35 { 36 ScriptWrappable::init(this); 37 } 38 39 DEFINE_NODE_FACTORY(SVGMPathElement) 40 41 SVGMPathElement::~SVGMPathElement() 42 { 43 #if !ENABLE(OILPAN) 44 clearResourceReferences(); 45 #endif 46 } 47 48 void SVGMPathElement::buildPendingResource() 49 { 50 clearResourceReferences(); 51 if (!inDocument()) 52 return; 53 54 AtomicString id; 55 Element* target = SVGURIReference::targetElementFromIRIString(hrefString(), treeScope(), &id); 56 if (!target) { 57 // Do not register as pending if we are already pending this resource. 58 if (document().accessSVGExtensions().isElementPendingResource(this, id)) 59 return; 60 61 if (!id.isEmpty()) { 62 document().accessSVGExtensions().addPendingResource(id, this); 63 ASSERT(hasPendingResources()); 64 } 65 } else if (target->isSVGElement()) { 66 // Register us with the target in the dependencies map. Any change of hrefElement 67 // that leads to relayout/repainting now informs us, so we can react to it. 68 document().accessSVGExtensions().addElementReferencingTarget(this, toSVGElement(target)); 69 } 70 71 targetPathChanged(); 72 } 73 74 void SVGMPathElement::clearResourceReferences() 75 { 76 document().accessSVGExtensions().removeAllTargetReferencesForElement(this); 77 } 78 79 Node::InsertionNotificationRequest SVGMPathElement::insertedInto(ContainerNode* rootParent) 80 { 81 SVGElement::insertedInto(rootParent); 82 if (rootParent->inDocument()) 83 buildPendingResource(); 84 return InsertionDone; 85 } 86 87 void SVGMPathElement::removedFrom(ContainerNode* rootParent) 88 { 89 SVGElement::removedFrom(rootParent); 90 notifyParentOfPathChange(rootParent); 91 if (rootParent->inDocument()) 92 clearResourceReferences(); 93 } 94 95 bool SVGMPathElement::isSupportedAttribute(const QualifiedName& attrName) 96 { 97 DEFINE_STATIC_LOCAL(HashSet<QualifiedName>, supportedAttributes, ()); 98 if (supportedAttributes.isEmpty()) { 99 SVGURIReference::addSupportedAttributes(supportedAttributes); 100 } 101 return supportedAttributes.contains<SVGAttributeHashTranslator>(attrName); 102 } 103 104 void SVGMPathElement::parseAttribute(const QualifiedName& name, const AtomicString& value) 105 { 106 SVGParsingError parseError = NoError; 107 108 if (!isSupportedAttribute(name)) { 109 SVGElement::parseAttribute(name, value); 110 } else if (SVGURIReference::parseAttribute(name, value, parseError)) { 111 } else { 112 ASSERT_NOT_REACHED(); 113 } 114 115 reportAttributeParsingError(parseError, name, value); 116 } 117 118 void SVGMPathElement::svgAttributeChanged(const QualifiedName& attrName) 119 { 120 if (!isSupportedAttribute(attrName)) { 121 SVGElement::svgAttributeChanged(attrName); 122 return; 123 } 124 125 SVGElement::InvalidationGuard invalidationGuard(this); 126 127 if (SVGURIReference::isKnownAttribute(attrName)) { 128 buildPendingResource(); 129 return; 130 } 131 132 ASSERT_NOT_REACHED(); 133 } 134 135 SVGPathElement* SVGMPathElement::pathElement() 136 { 137 Element* target = targetElementFromIRIString(hrefString(), treeScope()); 138 return isSVGPathElement(target) ? toSVGPathElement(target) : 0; 139 } 140 141 void SVGMPathElement::targetPathChanged() 142 { 143 notifyParentOfPathChange(parentNode()); 144 } 145 146 void SVGMPathElement::notifyParentOfPathChange(ContainerNode* parent) 147 { 148 if (isSVGAnimateMotionElement(parent)) 149 toSVGAnimateMotionElement(parent)->updateAnimationPath(); 150 } 151 152 } // namespace WebCore 153