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

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

Issue 2722543002: Improve handling of duplicate id's for SVG resources (Closed)
Patch Set: Rebase Created 3 years, 9 months 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
« no previous file with comments | « third_party/WebKit/Source/core/svg/SVGTreeScopeResources.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2017 The Chromium Authors. All rights reserved. 1 // Copyright 2017 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "core/svg/SVGTreeScopeResources.h" 5 #include "core/svg/SVGTreeScopeResources.h"
6 6
7 #include "core/dom/Element.h" 7 #include "core/dom/Element.h"
8 #include "core/dom/TreeScope.h" 8 #include "core/dom/TreeScope.h"
9 #include "core/layout/svg/LayoutSVGResourceContainer.h" 9 #include "core/layout/svg/LayoutSVGResourceContainer.h"
10 #include "core/layout/svg/SVGResourcesCache.h" 10 #include "core/layout/svg/SVGResourcesCache.h"
11 #include "core/svg/SVGUseElement.h" 11 #include "core/svg/SVGUseElement.h"
12 #include "wtf/text/AtomicString.h" 12 #include "wtf/text/AtomicString.h"
13 13
14 namespace blink { 14 namespace blink {
15 15
16 SVGTreeScopeResources::SVGTreeScopeResources(TreeScope* treeScope) { 16 SVGTreeScopeResources::SVGTreeScopeResources(TreeScope* treeScope)
17 : m_treeScope(treeScope) {
17 // Whenever an object of SVGTreeScopeResources is created, to keep the code 18 // Whenever an object of SVGTreeScopeResources is created, to keep the code
18 // behave as before, 19 // behave as before,
19 // the document should also have an instance of SVGDocumentExtensions created. 20 // the document should also have an instance of SVGDocumentExtensions created.
20 // Thus below line is added. 21 // Thus below line is added.
21 treeScope->document().accessSVGExtensions(); 22 treeScope->document().accessSVGExtensions();
22 } 23 }
23 24
24 SVGTreeScopeResources::~SVGTreeScopeResources() = default; 25 SVGTreeScopeResources::~SVGTreeScopeResources() = default;
25 26
27 static LayoutSVGResourceContainer* lookupResource(TreeScope& treeScope,
28 const AtomicString& id) {
29 Element* element = treeScope.getElementById(id);
30 if (!element)
31 return nullptr;
32 LayoutObject* layoutObject = element->layoutObject();
33 if (!layoutObject || !layoutObject->isSVGResourceContainer())
34 return nullptr;
35 return toLayoutSVGResourceContainer(layoutObject);
36 }
37
26 void SVGTreeScopeResources::updateResource( 38 void SVGTreeScopeResources::updateResource(
27 const AtomicString& id, 39 const AtomicString& id,
28 LayoutSVGResourceContainer* resource) { 40 LayoutSVGResourceContainer* resource) {
29 DCHECK(resource); 41 DCHECK(resource);
30 if (id.isEmpty()) 42 if (resource->isRegistered() || id.isEmpty())
31 return; 43 return;
32 // Replaces resource if already present, to handle potential id changes. 44 // Lookup the current resource. (Could differ from what's in the map if an
33 m_resources.set(id, resource); 45 // element was just added/removed.)
34 46 LayoutSVGResourceContainer* currentResource =
35 SVGPendingElements* pendingElements = m_pendingResources.take(id); 47 lookupResource(*m_treeScope, id);
36 if (!pendingElements) 48 // Lookup the currently registered resource.
37 return; 49 auto it = m_resources.find(id);
38 // Update cached resources of pending clients. 50 if (it != m_resources.end()) {
39 for (Element* clientElement : *pendingElements) { 51 // Is the local map up-to-date already?
40 DCHECK(clientElement->hasPendingResources()); 52 if (it->value == currentResource)
41 clearHasPendingResourcesIfPossible(*clientElement); 53 return;
42 54 unregisterResource(it);
43 LayoutObject* layoutObject = clientElement->layoutObject();
44 if (!layoutObject)
45 continue;
46 DCHECK(layoutObject->isSVG());
47
48 StyleDifference diff;
49 diff.setNeedsFullLayout();
50 SVGResourcesCache::clientStyleChanged(layoutObject, diff,
51 layoutObject->styleRef());
52 layoutObject->setNeedsLayoutAndFullPaintInvalidation(
53 LayoutInvalidationReason::SvgResourceInvalidated);
54 } 55 }
56 if (currentResource)
57 registerResource(id, currentResource);
55 } 58 }
56 59
57 void SVGTreeScopeResources::removeResource(const AtomicString& id) { 60 void SVGTreeScopeResources::updateResource(
58 if (id.isEmpty()) 61 const AtomicString& oldId,
62 const AtomicString& newId,
63 LayoutSVGResourceContainer* resource) {
64 removeResource(oldId, resource);
65 updateResource(newId, resource);
66 }
67
68 void SVGTreeScopeResources::removeResource(
69 const AtomicString& id,
70 LayoutSVGResourceContainer* resource) {
71 DCHECK(resource);
72 if (!resource->isRegistered() || id.isEmpty())
59 return; 73 return;
60 m_resources.erase(id); 74 auto it = m_resources.find(id);
75 // If this is not the currently registered resource for this id, then do
76 // nothing.
77 if (it == m_resources.end() || it->value != resource)
78 return;
79 unregisterResource(it);
80 // If the layout tree is being torn down, then don't attempt to update the
81 // map, since that layout object is likely to be stale already.
82 if (resource->documentBeingDestroyed())
83 return;
84 // Another resource could now be current. Perform a lookup and potentially
85 // update the map.
86 LayoutSVGResourceContainer* currentResource =
87 lookupResource(*m_treeScope, id);
88 if (!currentResource)
89 return;
90 // Since this is a removal, don't allow re-adding the resource.
91 if (currentResource == resource)
92 return;
93 registerResource(id, currentResource);
94 }
95
96 void SVGTreeScopeResources::registerResource(
97 const AtomicString& id,
98 LayoutSVGResourceContainer* resource) {
99 DCHECK(!id.isEmpty());
100 DCHECK(resource);
101 DCHECK(!resource->isRegistered());
102
103 m_resources.set(id, resource);
104 resource->setRegistered(true);
105
106 notifyPendingClients(id);
107 }
108
109 void SVGTreeScopeResources::unregisterResource(ResourceMap::iterator it) {
110 LayoutSVGResourceContainer* resource = it->value;
111 DCHECK(resource);
112 DCHECK(resource->isRegistered());
113
114 resource->detachAllClients(it->key);
115
116 resource->setRegistered(false);
117 m_resources.remove(it);
61 } 118 }
62 119
63 LayoutSVGResourceContainer* SVGTreeScopeResources::resourceById( 120 LayoutSVGResourceContainer* SVGTreeScopeResources::resourceById(
64 const AtomicString& id) const { 121 const AtomicString& id) const {
65 if (id.isEmpty()) 122 if (id.isEmpty())
66 return nullptr; 123 return nullptr;
67 return m_resources.at(id); 124 return m_resources.at(id);
68 } 125 }
69 126
70 void SVGTreeScopeResources::addPendingResource(const AtomicString& id, 127 void SVGTreeScopeResources::addPendingResource(const AtomicString& id,
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
118 175
119 elements->erase(&element); 176 elements->erase(&element);
120 if (elements->isEmpty()) 177 if (elements->isEmpty())
121 toBeRemoved.push_back(entry.key); 178 toBeRemoved.push_back(entry.key);
122 } 179 }
123 m_pendingResources.removeAll(toBeRemoved); 180 m_pendingResources.removeAll(toBeRemoved);
124 181
125 clearHasPendingResourcesIfPossible(element); 182 clearHasPendingResourcesIfPossible(element);
126 } 183 }
127 184
185 void SVGTreeScopeResources::notifyPendingClients(const AtomicString& id) {
186 DCHECK(!id.isEmpty());
187 SVGPendingElements* pendingElements = m_pendingResources.take(id);
188 if (!pendingElements)
189 return;
190 // Update cached resources of pending clients.
191 for (Element* clientElement : *pendingElements) {
192 DCHECK(clientElement->hasPendingResources());
193 clearHasPendingResourcesIfPossible(*clientElement);
194
195 LayoutObject* layoutObject = clientElement->layoutObject();
196 if (!layoutObject)
197 continue;
198 DCHECK(layoutObject->isSVG());
199
200 StyleDifference diff;
201 diff.setNeedsFullLayout();
202 SVGResourcesCache::clientStyleChanged(layoutObject, diff,
203 layoutObject->styleRef());
204 layoutObject->setNeedsLayoutAndFullPaintInvalidation(
205 LayoutInvalidationReason::SvgResourceInvalidated);
206 }
207 }
208
128 void SVGTreeScopeResources::notifyResourceAvailable(const AtomicString& id) { 209 void SVGTreeScopeResources::notifyResourceAvailable(const AtomicString& id) {
129 if (id.isEmpty()) 210 if (id.isEmpty())
130 return; 211 return;
131 // Get pending elements for this id. 212 // Get pending elements for this id.
132 SVGPendingElements* pendingElements = m_pendingResources.take(id); 213 SVGPendingElements* pendingElements = m_pendingResources.take(id);
133 if (!pendingElements) 214 if (!pendingElements)
134 return; 215 return;
135 // Rebuild pending resources for each client of a pending resource that is 216 // Rebuild pending resources for each client of a pending resource that is
136 // being removed. 217 // being removed.
137 for (Element* clientElement : *pendingElements) { 218 for (Element* clientElement : *pendingElements) {
138 DCHECK(clientElement->hasPendingResources()); 219 DCHECK(clientElement->hasPendingResources());
139 if (!clientElement->hasPendingResources()) 220 if (!clientElement->hasPendingResources())
140 continue; 221 continue;
141 // TODO(fs): Ideally we'd always resolve pending resources async instead of 222 // TODO(fs): Ideally we'd always resolve pending resources async instead of
142 // inside insertedInto and svgAttributeChanged. For now we only do it for 223 // inside insertedInto and svgAttributeChanged. For now we only do it for
143 // <use> since that would stamp out DOM. 224 // <use> since that would stamp out DOM.
144 if (isSVGUseElement(clientElement)) 225 if (isSVGUseElement(clientElement))
145 toSVGUseElement(clientElement)->invalidateShadowTree(); 226 toSVGUseElement(clientElement)->invalidateShadowTree();
146 else 227 else
147 clientElement->buildPendingResource(); 228 clientElement->buildPendingResource();
148 229
149 clearHasPendingResourcesIfPossible(*clientElement); 230 clearHasPendingResourcesIfPossible(*clientElement);
150 } 231 }
151 } 232 }
152 233
153 DEFINE_TRACE(SVGTreeScopeResources) { 234 DEFINE_TRACE(SVGTreeScopeResources) {
154 visitor->trace(m_pendingResources); 235 visitor->trace(m_pendingResources);
236 visitor->trace(m_treeScope);
155 } 237 }
156 } 238 }
OLDNEW
« no previous file with comments | « third_party/WebKit/Source/core/svg/SVGTreeScopeResources.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698