OLD | NEW |
1 /* | 1 /* |
2 * Copyright (C) Research In Motion Limited 2010. All rights reserved. | 2 * Copyright (C) Research In Motion Limited 2010. All rights reserved. |
3 * | 3 * |
4 * This library is free software; you can redistribute it and/or | 4 * This library is free software; you can redistribute it and/or |
5 * modify it under the terms of the GNU Library General Public | 5 * modify it under the terms of the GNU Library General Public |
6 * License as published by the Free Software Foundation; either | 6 * License as published by the Free Software Foundation; either |
7 * version 2 of the License, or (at your option) any later version. | 7 * version 2 of the License, or (at your option) any later version. |
8 * | 8 * |
9 * This library is distributed in the hope that it will be useful, | 9 * This library is distributed in the hope that it will be useful, |
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of | 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of |
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
12 * Library General Public License for more details. | 12 * Library General Public License for more details. |
13 * | 13 * |
14 * You should have received a copy of the GNU Library General Public License | 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 | 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, | 16 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, |
17 * Boston, MA 02110-1301, USA. | 17 * Boston, MA 02110-1301, USA. |
18 */ | 18 */ |
19 | 19 |
20 #include "core/layout/svg/LayoutSVGResourceContainer.h" | 20 #include "core/layout/svg/LayoutSVGResourceContainer.h" |
21 | 21 |
22 #include "core/layout/svg/SVGResources.h" | 22 #include "core/layout/svg/SVGResources.h" |
23 #include "core/layout/svg/SVGResourcesCache.h" | 23 #include "core/layout/svg/SVGResourcesCache.h" |
24 #include "core/svg/SVGElementProxy.h" | 24 #include "core/svg/SVGElementProxy.h" |
25 #include "core/svg/SVGTreeScopeResources.h" | 25 #include "core/svg/SVGTreeScopeResources.h" |
26 #include "platform/wtf/AutoReset.h" | 26 #include "platform/wtf/AutoReset.h" |
27 | 27 |
28 namespace blink { | 28 namespace blink { |
29 | 29 |
30 static inline SVGTreeScopeResources& SvgTreeScopeResourcesFromElement( | 30 namespace { |
31 Element* element) { | 31 |
32 DCHECK(element); | 32 SVGTreeScopeResources::Resource* ResourceForContainer( |
33 return element->GetTreeScope().EnsureSVGTreeScopedResources(); | 33 const LayoutSVGResourceContainer& resource_container) { |
| 34 const SVGElement& element = *resource_container.GetElement(); |
| 35 return element.GetTreeScope() |
| 36 .EnsureSVGTreeScopedResources() |
| 37 .ExistingResourceForId(element.GetIdAttribute()); |
34 } | 38 } |
35 | 39 |
| 40 } // namespace |
| 41 |
36 LayoutSVGResourceContainer::LayoutSVGResourceContainer(SVGElement* node) | 42 LayoutSVGResourceContainer::LayoutSVGResourceContainer(SVGElement* node) |
37 : LayoutSVGHiddenContainer(node), | 43 : LayoutSVGHiddenContainer(node), |
38 is_in_layout_(false), | 44 is_in_layout_(false), |
39 invalidation_mask_(0), | 45 invalidation_mask_(0), |
40 registered_(false), | |
41 is_invalidating_(false) {} | 46 is_invalidating_(false) {} |
42 | 47 |
43 LayoutSVGResourceContainer::~LayoutSVGResourceContainer() {} | 48 LayoutSVGResourceContainer::~LayoutSVGResourceContainer() {} |
44 | 49 |
45 void LayoutSVGResourceContainer::UpdateLayout() { | 50 void LayoutSVGResourceContainer::UpdateLayout() { |
46 // FIXME: Investigate a way to detect and break resource layout dependency | 51 // FIXME: Investigate a way to detect and break resource layout dependency |
47 // cycles early. Then we can remove this method altogether, and fall back onto | 52 // cycles early. Then we can remove this method altogether, and fall back onto |
48 // LayoutSVGHiddenContainer::layout(). | 53 // LayoutSVGHiddenContainer::layout(). |
49 DCHECK(NeedsLayout()); | 54 DCHECK(NeedsLayout()); |
50 if (is_in_layout_) | 55 if (is_in_layout_) |
(...skipping 10 matching lines...) Expand all Loading... |
61 return GetElement()->ElementProxySet(); | 66 return GetElement()->ElementProxySet(); |
62 } | 67 } |
63 | 68 |
64 void LayoutSVGResourceContainer::NotifyContentChanged() { | 69 void LayoutSVGResourceContainer::NotifyContentChanged() { |
65 if (SVGElementProxySet* proxy_set = ElementProxySet()) | 70 if (SVGElementProxySet* proxy_set = ElementProxySet()) |
66 proxy_set->NotifyContentChanged(GetElement()->GetTreeScope()); | 71 proxy_set->NotifyContentChanged(GetElement()->GetTreeScope()); |
67 } | 72 } |
68 | 73 |
69 void LayoutSVGResourceContainer::WillBeDestroyed() { | 74 void LayoutSVGResourceContainer::WillBeDestroyed() { |
70 LayoutSVGHiddenContainer::WillBeDestroyed(); | 75 LayoutSVGHiddenContainer::WillBeDestroyed(); |
71 SvgTreeScopeResourcesFromElement(GetElement()) | 76 // The resource is being torn down. If we have any clients, move those to be |
72 .RemoveResource(GetElement()->GetIdAttribute(), this); | 77 // pending on the resource (if one exists.) |
73 DCHECK(clients_.IsEmpty()); | 78 if (SVGTreeScopeResources::Resource* resource = ResourceForContainer(*this)) |
| 79 MakeClientsPending(*resource); |
74 } | 80 } |
75 | 81 |
76 void LayoutSVGResourceContainer::StyleDidChange( | 82 void LayoutSVGResourceContainer::StyleDidChange( |
77 StyleDifference diff, | 83 StyleDifference diff, |
78 const ComputedStyle* old_style) { | 84 const ComputedStyle* old_style) { |
79 LayoutSVGHiddenContainer::StyleDidChange(diff, old_style); | 85 LayoutSVGHiddenContainer::StyleDidChange(diff, old_style); |
80 SvgTreeScopeResourcesFromElement(GetElement()) | 86 // The resource has (read: may have) been attached. Notify any pending |
81 .UpdateResource(GetElement()->GetIdAttribute(), this); | 87 // clients that they can now try to add themselves as clients to the |
| 88 // resource. |
| 89 if (SVGTreeScopeResources::Resource* resource = ResourceForContainer(*this)) { |
| 90 if (resource->Target() == GetElement()) |
| 91 resource->NotifyResourceClients(); |
| 92 } |
82 } | 93 } |
83 | 94 |
84 void LayoutSVGResourceContainer::DetachAllClients(const AtomicString& to_id) { | 95 void LayoutSVGResourceContainer::MakeClientsPending( |
| 96 SVGTreeScopeResources::Resource& resource) { |
85 RemoveAllClientsFromCache(); | 97 RemoveAllClientsFromCache(); |
86 | 98 |
87 for (auto* client : clients_) { | 99 for (auto* client : clients_) { |
88 // Unlink the resource from the client's SVGResources. (The actual | 100 // Unlink the resource from the client's SVGResources. |
89 // removal will be signaled after processing all the clients.) | |
90 SVGResources* resources = | 101 SVGResources* resources = |
91 SVGResourcesCache::CachedResourcesForLayoutObject(client); | 102 SVGResourcesCache::CachedResourcesForLayoutObject(client); |
92 // Or else the client wouldn't be in the list in the first place. | 103 // Or else the client wouldn't be in the list in the first place. |
93 DCHECK(resources); | 104 DCHECK(resources); |
94 resources->ResourceDestroyed(this); | 105 resources->ResourceDestroyed(this); |
95 | 106 |
96 // Add a pending resolution based on the id of the old resource. | 107 resource.AddWatch(ToSVGElement(*client->GetNode())); |
97 Element* client_element = ToElement(client->GetNode()); | |
98 SvgTreeScopeResourcesFromElement(client_element) | |
99 .AddPendingResource(to_id, *client_element); | |
100 } | 108 } |
101 clients_.clear(); | 109 clients_.clear(); |
102 } | 110 } |
103 | 111 |
104 void LayoutSVGResourceContainer::IdChanged(const AtomicString& old_id, | |
105 const AtomicString& new_id) { | |
106 SvgTreeScopeResourcesFromElement(GetElement()) | |
107 .UpdateResource(old_id, new_id, this); | |
108 } | |
109 | |
110 void LayoutSVGResourceContainer::MarkAllClientsForInvalidation( | 112 void LayoutSVGResourceContainer::MarkAllClientsForInvalidation( |
111 InvalidationMode mode) { | 113 InvalidationMode mode) { |
112 if (is_invalidating_) | 114 if (is_invalidating_) |
113 return; | 115 return; |
114 SVGElementProxySet* proxy_set = ElementProxySet(); | 116 SVGElementProxySet* proxy_set = ElementProxySet(); |
115 if (clients_.IsEmpty() && (!proxy_set || proxy_set->IsEmpty())) | 117 if (clients_.IsEmpty() && (!proxy_set || proxy_set->IsEmpty())) |
116 return; | 118 return; |
117 if (invalidation_mask_ & mode) | 119 if (invalidation_mask_ & mode) |
118 return; | 120 return; |
119 | 121 |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
170 break; | 172 break; |
171 } | 173 } |
172 } | 174 } |
173 | 175 |
174 void LayoutSVGResourceContainer::AddClient(LayoutObject* client) { | 176 void LayoutSVGResourceContainer::AddClient(LayoutObject* client) { |
175 DCHECK(client); | 177 DCHECK(client); |
176 clients_.insert(client); | 178 clients_.insert(client); |
177 ClearInvalidationMask(); | 179 ClearInvalidationMask(); |
178 } | 180 } |
179 | 181 |
180 void LayoutSVGResourceContainer::RemoveClient(LayoutObject* client) { | 182 bool LayoutSVGResourceContainer::RemoveClient(LayoutObject* client) { |
181 DCHECK(client); | 183 DCHECK(client); |
182 RemoveClientFromCache(client, false); | 184 RemoveClientFromCache(client, false); |
183 clients_.erase(client); | 185 clients_.erase(client); |
| 186 return clients_.IsEmpty(); |
184 } | 187 } |
185 | 188 |
186 void LayoutSVGResourceContainer::InvalidateCacheAndMarkForLayout( | 189 void LayoutSVGResourceContainer::InvalidateCacheAndMarkForLayout( |
187 SubtreeLayoutScope* layout_scope) { | 190 SubtreeLayoutScope* layout_scope) { |
188 if (SelfNeedsLayout()) | 191 if (SelfNeedsLayout()) |
189 return; | 192 return; |
190 | 193 |
191 SetNeedsLayoutAndFullPaintInvalidation( | 194 SetNeedsLayoutAndFullPaintInvalidation( |
192 LayoutInvalidationReason::kSvgResourceInvalidated, kMarkContainerChain, | 195 LayoutInvalidationReason::kSvgResourceInvalidated, kMarkContainerChain, |
193 layout_scope); | 196 layout_scope); |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
256 // This will process the rest of the ancestors. | 259 // This will process the rest of the ancestors. |
257 ToLayoutSVGResourceContainer(current)->RemoveAllClientsFromCache(); | 260 ToLayoutSVGResourceContainer(current)->RemoveAllClientsFromCache(); |
258 break; | 261 break; |
259 } | 262 } |
260 | 263 |
261 current = current->Parent(); | 264 current = current->Parent(); |
262 } | 265 } |
263 } | 266 } |
264 | 267 |
265 } // namespace blink | 268 } // namespace blink |
OLD | NEW |