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