Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(112)

Side by Side Diff: third_party/WebKit/Source/core/svg/SVGElementProxy.cpp

Issue 2401343002: Tracking filter mutation via SVGElementProxy (Closed)
Patch Set: Rebase Created 4 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2016 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "core/svg/SVGElementProxy.h"
6
7 #include "core/dom/IdTargetObserver.h"
8 #include "core/fetch/FetchInitiatorTypeNames.h"
9 #include "core/fetch/FetchRequest.h"
10 #include "core/fetch/ResourceFetcher.h"
11 #include "core/svg/SVGElement.h"
12 #include "core/svg/SVGFilterElement.h"
13 #include "core/svg/SVGResourceClient.h"
14
15 namespace blink {
16
17 class SVGElementProxy::IdObserver : public IdTargetObserver {
18 public:
19 IdObserver(TreeScope& treeScope, SVGElementProxy& proxy)
20 : IdTargetObserver(treeScope.idTargetObserverRegistry(), proxy.id()),
21 m_treeScope(&treeScope) {}
22
23 void addClient(SVGResourceClient* client) { m_clients.add(client); }
24 bool removeClient(SVGResourceClient* client) {
25 return m_clients.remove(client);
26 }
27
28 TreeScope* treeScope() const { return m_treeScope; }
29 void transferClients(IdObserver& observer) {
30 for (const auto& client : m_clients)
31 observer.m_clients.add(client.key, client.value);
32 m_clients.clear();
33 }
34
35 DEFINE_INLINE_VIRTUAL_TRACE() {
36 visitor->trace(m_clients);
37 visitor->trace(m_treeScope);
38 IdTargetObserver::trace(visitor);
39 }
40
41 void contentChanged() {
42 DCHECK(lifecycle().state() <= DocumentLifecycle::CompositingClean ||
43 lifecycle().state() >= DocumentLifecycle::PaintClean);
44 HeapVector<Member<SVGResourceClient>> clients;
45 copyToVector(m_clients, clients);
46 for (SVGResourceClient* client : clients)
47 client->resourceContentChanged();
48 }
49
50 private:
51 const DocumentLifecycle& lifecycle() const {
52 return m_treeScope->document().lifecycle();
53 }
54 void idTargetChanged() override {
55 DCHECK(lifecycle().stateAllowsTreeMutations());
56 HeapVector<Member<SVGResourceClient>> clients;
57 copyToVector(m_clients, clients);
58 for (SVGResourceClient* client : clients)
59 client->resourceElementChanged();
60 }
61 HeapHashCountedSet<Member<SVGResourceClient>> m_clients;
62 Member<TreeScope> m_treeScope;
63 };
64
65 SVGElementProxy::SVGElementProxy(const AtomicString& id)
66 : m_id(id), m_isLocal(true) {}
67
68 SVGElementProxy::SVGElementProxy(const String& url, const AtomicString& id)
69 : m_id(id), m_url(url), m_isLocal(false) {}
70
71 SVGElementProxy::~SVGElementProxy() {}
72
73 void SVGElementProxy::addClient(SVGResourceClient* client) {
74 // An empty id will never be a valid element reference.
75 if (m_id.isEmpty())
76 return;
77 if (m_document) {
78 m_document->addClient(client);
79 return;
80 }
81 TreeScope* clientScope = client->treeScope();
82 TreeScope* lookupScope =
83 clientScope ? treeScopeForLookup(*clientScope) : nullptr;
84 if (!lookupScope)
85 return;
86 // Ensure sure we have an observer registered for this tree scope.
87 auto& scopeObserver =
88 m_observers.add(lookupScope, nullptr).storedValue->value;
89 if (!scopeObserver)
90 scopeObserver = new IdObserver(*lookupScope, *this);
91
92 auto& observer = m_clients.add(client, nullptr).storedValue->value;
93 if (!observer)
94 observer = scopeObserver;
95
96 DCHECK(observer && scopeObserver);
97
98 // If the client moved to a different scope, we need to unregister the old
99 // observer and transfer any clients from it before replacing it. Thus any
100 // clients that remain to be removed will be transferred to the new observer,
101 // and hence removed from it instead.
102 if (observer != scopeObserver) {
103 observer->unregister();
104 observer->transferClients(*scopeObserver);
105 observer = scopeObserver;
106 }
107 observer->addClient(client);
108 }
109
110 void SVGElementProxy::removeClient(SVGResourceClient* client) {
111 // An empty id will never be a valid element reference.
112 if (m_id.isEmpty())
113 return;
114 if (m_document) {
115 m_document->removeClient(client);
116 return;
117 }
118 auto entry = m_clients.find(client);
119 if (entry == m_clients.end())
120 return;
121 IdObserver* observer = entry->value;
122 DCHECK(observer);
123 // If the client is not the last client in the scope, then no further action
124 // needs to be taken.
125 if (!observer->removeClient(client))
126 return;
127 // Unregister and drop the scope association, then drop the client.
128 observer->unregister();
129 m_observers.remove(observer->treeScope());
130 m_clients.remove(entry);
131 }
132
133 void SVGElementProxy::resolve(Document& document) {
134 if (m_isLocal || m_id.isEmpty() || m_url.isEmpty())
135 return;
136 FetchRequest request(ResourceRequest(m_url), FetchInitiatorTypeNames::css);
137 m_document = DocumentResource::fetchSVGDocument(request, document.fetcher());
138 m_url = String();
139 }
140
141 TreeScope* SVGElementProxy::treeScopeForLookup(TreeScope& treeScope) const {
142 if (m_isLocal)
143 return &treeScope;
144 if (!m_document)
145 return nullptr;
146 return m_document->document();
147 }
148
149 SVGElement* SVGElementProxy::findElement(TreeScope& treeScope) {
150 // An empty id will never be a valid element reference.
151 if (m_id.isEmpty())
152 return nullptr;
153 TreeScope* lookupScope = treeScopeForLookup(treeScope);
154 if (!lookupScope)
155 return nullptr;
156 if (Element* targetElement = lookupScope->getElementById(m_id)) {
157 if (isSVGFilterElement(*targetElement)) {
158 toSVGFilterElement(*targetElement).elementProxySet().add(*this);
159 return toSVGElement(targetElement);
160 }
161 }
162 return nullptr;
163 }
164
165 void SVGElementProxy::contentChanged(TreeScope& treeScope) {
166 if (auto* observer = m_observers.get(&treeScope))
167 observer->contentChanged();
168 }
169
170 DEFINE_TRACE(SVGElementProxy) {
171 visitor->trace(m_clients);
172 visitor->trace(m_observers);
173 visitor->trace(m_document);
174 }
175
176 void SVGElementProxySet::add(SVGElementProxy& elementProxy) {
177 m_elementProxies.add(&elementProxy);
178 }
179
180 bool SVGElementProxySet::isEmpty() const {
181 return m_elementProxies.isEmpty();
182 }
183
184 void SVGElementProxySet::notifyContentChanged(TreeScope& treeScope) {
185 for (SVGElementProxy* proxy : m_elementProxies)
186 proxy->contentChanged(treeScope);
187 }
188
189 DEFINE_TRACE(SVGElementProxySet) {
190 visitor->trace(m_elementProxies);
191 }
192
193 } // namespace blink
OLDNEW
« no previous file with comments | « third_party/WebKit/Source/core/svg/SVGElementProxy.h ('k') | third_party/WebKit/Source/core/svg/SVGFilterElement.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698