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 blink { 31 32 inline SVGMPathElement::SVGMPathElement(Document& document) 33 : SVGElement(SVGNames::mpathTag, document) 34 , SVGURIReference(this) 35 { 36 } 37 38 DEFINE_NODE_FACTORY(SVGMPathElement) 39 40 SVGMPathElement::~SVGMPathElement() 41 { 42 #if !ENABLE(OILPAN) 43 clearResourceReferences(); 44 #endif 45 } 46 47 void 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 73 void SVGMPathElement::clearResourceReferences() 74 { 75 removeAllOutgoingReferences(); 76 } 77 78 Node::InsertionNotificationRequest SVGMPathElement::insertedInto(ContainerNode* rootParent) 79 { 80 SVGElement::insertedInto(rootParent); 81 if (rootParent->inDocument()) 82 buildPendingResource(); 83 return InsertionDone; 84 } 85 86 void SVGMPathElement::removedFrom(ContainerNode* rootParent) 87 { 88 SVGElement::removedFrom(rootParent); 89 notifyParentOfPathChange(rootParent); 90 if (rootParent->inDocument()) 91 clearResourceReferences(); 92 } 93 94 bool 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 103 void 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 117 void 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 134 SVGPathElement* SVGMPathElement::pathElement() 135 { 136 Element* target = targetElementFromIRIString(hrefString(), treeScope()); 137 return isSVGPathElement(target) ? toSVGPathElement(target) : 0; 138 } 139 140 void SVGMPathElement::targetPathChanged() 141 { 142 notifyParentOfPathChange(parentNode()); 143 } 144 145 void SVGMPathElement::notifyParentOfPathChange(ContainerNode* parent) 146 { 147 if (isSVGAnimateMotionElement(parent)) 148 toSVGAnimateMotionElement(parent)->updateAnimationPath(); 149 } 150 151 } // namespace blink 152