1 | /* |
2 | * Copyright (C) 2007 Eric Seidel <eric@webkit.org> |
3 | * Copyright (C) 2018 Apple Inc. All rights reserved. |
4 | * |
5 | * This library is free software; you can redistribute it and/or |
6 | * modify it under the terms of the GNU Library General Public |
7 | * License as published by the Free Software Foundation; either |
8 | * version 2 of the License, or (at your option) any later version. |
9 | * |
10 | * This library is distributed in the hope that it will be useful, |
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
13 | * Library General Public License for more details. |
14 | * |
15 | * You should have received a copy of the GNU Library General Public License |
16 | * along with this library; see the file COPYING.LIB. If not, write to |
17 | * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, |
18 | * Boston, MA 02110-1301, USA. |
19 | */ |
20 | |
21 | #include "config.h" |
22 | #include "SVGMPathElement.h" |
23 | |
24 | #include "Document.h" |
25 | #include "SVGAnimateMotionElement.h" |
26 | #include "SVGDocumentExtensions.h" |
27 | #include "SVGNames.h" |
28 | #include "SVGPathElement.h" |
29 | #include <wtf/IsoMallocInlines.h> |
30 | |
31 | namespace WebCore { |
32 | |
33 | WTF_MAKE_ISO_ALLOCATED_IMPL(SVGMPathElement); |
34 | |
35 | inline SVGMPathElement::SVGMPathElement(const QualifiedName& tagName, Document& document) |
36 | : SVGElement(tagName, document) |
37 | , SVGExternalResourcesRequired(this) |
38 | , SVGURIReference(this) |
39 | { |
40 | ASSERT(hasTagName(SVGNames::mpathTag)); |
41 | } |
42 | |
43 | Ref<SVGMPathElement> SVGMPathElement::create(const QualifiedName& tagName, Document& document) |
44 | { |
45 | return adoptRef(*new SVGMPathElement(tagName, document)); |
46 | } |
47 | |
48 | SVGMPathElement::~SVGMPathElement() |
49 | { |
50 | clearResourceReferences(); |
51 | } |
52 | |
53 | void SVGMPathElement::buildPendingResource() |
54 | { |
55 | clearResourceReferences(); |
56 | if (!isConnected()) |
57 | return; |
58 | |
59 | auto target = SVGURIReference::targetElementFromIRIString(href(), treeScope()); |
60 | if (!target.element) { |
61 | // Do not register as pending if we are already pending this resource. |
62 | if (document().accessSVGExtensions().isPendingResource(*this, target.identifier)) |
63 | return; |
64 | |
65 | if (!target.identifier.isEmpty()) { |
66 | document().accessSVGExtensions().addPendingResource(target.identifier, *this); |
67 | ASSERT(hasPendingResources()); |
68 | } |
69 | } else if (is<SVGElement>(*target.element)) { |
70 | // Register us with the target in the dependencies map. Any change of hrefElement |
71 | // that leads to relayout/repainting now informs us, so we can react to it. |
72 | document().accessSVGExtensions().addElementReferencingTarget(*this, downcast<SVGElement>(*target.element)); |
73 | } |
74 | |
75 | targetPathChanged(); |
76 | } |
77 | |
78 | void SVGMPathElement::clearResourceReferences() |
79 | { |
80 | document().accessSVGExtensions().removeAllTargetReferencesForElement(*this); |
81 | } |
82 | |
83 | Node::InsertedIntoAncestorResult SVGMPathElement::insertedIntoAncestor(InsertionType insertionType, ContainerNode& parentOfInsertedTree) |
84 | { |
85 | SVGElement::insertedIntoAncestor(insertionType, parentOfInsertedTree); |
86 | if (insertionType.connectedToDocument) |
87 | return InsertedIntoAncestorResult::NeedsPostInsertionCallback; |
88 | return InsertedIntoAncestorResult::Done; |
89 | } |
90 | |
91 | void SVGMPathElement::didFinishInsertingNode() |
92 | { |
93 | buildPendingResource(); |
94 | } |
95 | |
96 | void SVGMPathElement::removedFromAncestor(RemovalType removalType, ContainerNode& oldParentOfRemovedTree) |
97 | { |
98 | SVGElement::removedFromAncestor(removalType, oldParentOfRemovedTree); |
99 | notifyParentOfPathChange(&oldParentOfRemovedTree); |
100 | if (removalType.disconnectedFromDocument) |
101 | clearResourceReferences(); |
102 | } |
103 | |
104 | void SVGMPathElement::parseAttribute(const QualifiedName& name, const AtomicString& value) |
105 | { |
106 | SVGElement::parseAttribute(name, value); |
107 | SVGURIReference::parseAttribute(name, value); |
108 | SVGExternalResourcesRequired::parseAttribute(name, value); |
109 | } |
110 | |
111 | void SVGMPathElement::svgAttributeChanged(const QualifiedName& attrName) |
112 | { |
113 | if (SVGURIReference::isKnownAttribute(attrName)) { |
114 | InstanceInvalidationGuard guard(*this); |
115 | buildPendingResource(); |
116 | return; |
117 | } |
118 | |
119 | SVGElement::svgAttributeChanged(attrName); |
120 | SVGExternalResourcesRequired::svgAttributeChanged(attrName); |
121 | } |
122 | |
123 | RefPtr<SVGPathElement> SVGMPathElement::pathElement() |
124 | { |
125 | auto target = targetElementFromIRIString(href(), treeScope()); |
126 | if (is<SVGPathElement>(target.element)) |
127 | return downcast<SVGPathElement>(target.element.get()); |
128 | return nullptr; |
129 | } |
130 | |
131 | void SVGMPathElement::targetPathChanged() |
132 | { |
133 | notifyParentOfPathChange(parentNode()); |
134 | } |
135 | |
136 | void SVGMPathElement::notifyParentOfPathChange(ContainerNode* parent) |
137 | { |
138 | if (is<SVGAnimateMotionElement>(parent)) |
139 | downcast<SVGAnimateMotionElement>(*parent).updateAnimationPath(); |
140 | } |
141 | |
142 | } // namespace WebCore |
143 | |