| 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 |
| (...skipping 25 matching lines...) Expand all Loading... |
| 36 { | 36 { |
| 37 } | 37 } |
| 38 | 38 |
| 39 void SVGResourcesCache::addResourcesFromLayoutObject(LayoutObject* object, const
ComputedStyle& style) | 39 void SVGResourcesCache::addResourcesFromLayoutObject(LayoutObject* object, const
ComputedStyle& style) |
| 40 { | 40 { |
| 41 ASSERT(object); | 41 ASSERT(object); |
| 42 ASSERT(!m_cache.contains(object)); | 42 ASSERT(!m_cache.contains(object)); |
| 43 | 43 |
| 44 const SVGComputedStyle& svgStyle = style.svgStyle(); | 44 const SVGComputedStyle& svgStyle = style.svgStyle(); |
| 45 | 45 |
| 46 // Build a list of all resources associated with the passed LayoutObject | 46 // Build a list of all resources associated with the passed LayoutObject. |
| 47 OwnPtr<SVGResources> newResources = SVGResources::buildResources(object, svg
Style); | 47 OwnPtr<SVGResources> newResources = SVGResources::buildResources(object, svg
Style); |
| 48 if (!newResources) | 48 if (!newResources) |
| 49 return; | 49 return; |
| 50 | 50 |
| 51 // Put object in cache. | 51 // Put object in cache. |
| 52 SVGResources* resources = m_cache.set(object, newResources.release()).stored
Value->value.get(); | 52 SVGResources* resources = m_cache.set(object, newResources.release()).stored
Value->value.get(); |
| 53 | 53 |
| 54 // Run cycle-detection _afterwards_, so self-references can be caught as wel
l. | 54 // Run cycle-detection _afterwards_, so self-references can be caught as wel
l. |
| 55 SVGResourcesCycleSolver solver(object, resources); | 55 SVGResourcesCycleSolver solver(object, resources); |
| 56 solver.resolveCycles(); | 56 solver.resolveCycles(); |
| 57 | 57 |
| 58 // Walk resources and register the layout object at each resources. | 58 // Walk resources and register the layout object as a client of each resourc
e. |
| 59 HashSet<LayoutSVGResourceContainer*> resourceSet; | 59 HashSet<LayoutSVGResourceContainer*> resourceSet; |
| 60 resources->buildSetOfResources(resourceSet); | 60 resources->buildSetOfResources(resourceSet); |
| 61 | 61 |
| 62 for (auto* resourceContainer : resourceSet) | 62 for (auto* resourceContainer : resourceSet) |
| 63 resourceContainer->addClient(object); | 63 resourceContainer->addClient(object); |
| 64 } | 64 } |
| 65 | 65 |
| 66 void SVGResourcesCache::removeResourcesFromLayoutObject(LayoutObject* object) | 66 void SVGResourcesCache::removeResourcesFromLayoutObject(LayoutObject* object) |
| 67 { | 67 { |
| 68 OwnPtr<SVGResources> resources = m_cache.take(object); | 68 OwnPtr<SVGResources> resources = m_cache.take(object); |
| 69 if (!resources) | 69 if (!resources) |
| 70 return; | 70 return; |
| 71 | 71 |
| 72 // Walk resources and register the layout object at each resources. | 72 // Walk resources and unregister the layout object as a client of each resou
rce. |
| 73 HashSet<LayoutSVGResourceContainer*> resourceSet; | 73 HashSet<LayoutSVGResourceContainer*> resourceSet; |
| 74 resources->buildSetOfResources(resourceSet); | 74 resources->buildSetOfResources(resourceSet); |
| 75 | 75 |
| 76 for (auto* resourceContainer : resourceSet) | 76 for (auto* resourceContainer : resourceSet) |
| 77 resourceContainer->removeClient(object); | 77 resourceContainer->removeClient(object); |
| 78 } | 78 } |
| 79 | 79 |
| 80 static inline SVGResourcesCache* resourcesCacheFromLayoutObject(const LayoutObje
ct* layoutObject) | 80 static inline SVGResourcesCache& resourcesCache(Document& document) |
| 81 { | 81 { |
| 82 Document& document = layoutObject->document(); | 82 return document.accessSVGExtensions().resourcesCache(); |
| 83 | |
| 84 SVGDocumentExtensions& extensions = document.accessSVGExtensions(); | |
| 85 SVGResourcesCache* cache = extensions.resourcesCache(); | |
| 86 ASSERT(cache); | |
| 87 | |
| 88 return cache; | |
| 89 } | 83 } |
| 90 | 84 |
| 91 SVGResources* SVGResourcesCache::cachedResourcesForLayoutObject(const LayoutObje
ct* layoutObject) | 85 SVGResources* SVGResourcesCache::cachedResourcesForLayoutObject(const LayoutObje
ct* layoutObject) |
| 92 { | 86 { |
| 93 ASSERT(layoutObject); | 87 ASSERT(layoutObject); |
| 94 return resourcesCacheFromLayoutObject(layoutObject)->m_cache.get(layoutObjec
t); | 88 return resourcesCache(layoutObject->document()).m_cache.get(layoutObject); |
| 95 } | 89 } |
| 96 | 90 |
| 97 void SVGResourcesCache::clientLayoutChanged(LayoutObject* object) | 91 void SVGResourcesCache::clientLayoutChanged(LayoutObject* object) |
| 98 { | 92 { |
| 99 SVGResources* resources = SVGResourcesCache::cachedResourcesForLayoutObject(
object); | 93 SVGResources* resources = cachedResourcesForLayoutObject(object); |
| 100 if (!resources) | 94 if (!resources) |
| 101 return; | 95 return; |
| 102 | 96 |
| 103 // Invalidate the resources if either the LayoutObject itself changed, | 97 // Invalidate the resources if either the LayoutObject itself changed, |
| 104 // or we have filter resources, which could depend on the layout of children
. | 98 // or we have filter resources, which could depend on the layout of children
. |
| 105 if (object->selfNeedsLayout() || resources->filter()) | 99 if (object->selfNeedsLayout() || resources->filter()) |
| 106 resources->removeClientFromCache(object); | 100 resources->removeClientFromCache(object); |
| 107 } | 101 } |
| 108 | 102 |
| 109 static inline bool layoutObjectCanHaveResources(LayoutObject* layoutObject) | 103 static inline bool layoutObjectCanHaveResources(LayoutObject* layoutObject) |
| 110 { | 104 { |
| 111 ASSERT(layoutObject); | 105 ASSERT(layoutObject); |
| 112 return layoutObject->node() && layoutObject->node()->isSVGElement() && !layo
utObject->isSVGInlineText(); | 106 return layoutObject->node() && layoutObject->node()->isSVGElement() && !layo
utObject->isSVGInlineText(); |
| 113 } | 107 } |
| 114 | 108 |
| 115 void SVGResourcesCache::clientStyleChanged(LayoutObject* layoutObject, StyleDiff
erence diff, const ComputedStyle& newStyle) | 109 void SVGResourcesCache::clientStyleChanged(LayoutObject* layoutObject, StyleDiff
erence diff, const ComputedStyle& newStyle) |
| 116 { | 110 { |
| 117 ASSERT(layoutObject); | 111 ASSERT(layoutObject); |
| 118 ASSERT(layoutObject->node()); | 112 ASSERT(layoutObject->node()); |
| 119 ASSERT(layoutObject->node()->isSVGElement()); | 113 ASSERT(layoutObject->node()->isSVGElement()); |
| 120 | 114 |
| 121 if (!diff.hasDifference() || !layoutObject->parent()) | 115 if (!diff.hasDifference() || !layoutObject->parent()) |
| 122 return; | 116 return; |
| 123 | 117 |
| 124 // In this case the proper SVGFE*Element will decide whether the modified CS
S properties require a relayout or paintInvalidation. | 118 // In this case the proper SVGFE*Element will decide whether the modified CS
S properties require |
| 119 // a relayout or paintInvalidation. |
| 125 if (layoutObject->isSVGResourceFilterPrimitive() && !diff.needsLayout()) | 120 if (layoutObject->isSVGResourceFilterPrimitive() && !diff.needsLayout()) |
| 126 return; | 121 return; |
| 127 | 122 |
| 128 // Dynamic changes of CSS properties like 'clip-path' may require us to reco
mpute the associated resources for a layoutObject. | 123 // Dynamic changes of CSS properties like 'clip-path' may require us to reco
mpute the associated |
| 129 // FIXME: Avoid passing in a useless StyleDifference, but instead compare ol
dStyle/newStyle to see which resources changed | 124 // resources for a LayoutObject. |
| 130 // to be able to selectively rebuild individual resources, instead of all of
them. | 125 // TODO(fs): Avoid passing in a useless StyleDifference, but instead compare
oldStyle/newStyle |
| 126 // to see which resources changed to be able to selectively rebuild individu
al resources, |
| 127 // instead of all of them. |
| 131 if (layoutObjectCanHaveResources(layoutObject)) { | 128 if (layoutObjectCanHaveResources(layoutObject)) { |
| 132 SVGResourcesCache* cache = resourcesCacheFromLayoutObject(layoutObject); | 129 SVGResourcesCache& cache = resourcesCache(layoutObject->document()); |
| 133 cache->removeResourcesFromLayoutObject(layoutObject); | 130 cache.removeResourcesFromLayoutObject(layoutObject); |
| 134 cache->addResourcesFromLayoutObject(layoutObject, newStyle); | 131 cache.addResourcesFromLayoutObject(layoutObject, newStyle); |
| 135 } | 132 } |
| 136 | 133 |
| 137 LayoutSVGResourceContainer::markForLayoutAndParentResourceInvalidation(layou
tObject, false); | 134 LayoutSVGResourceContainer::markForLayoutAndParentResourceInvalidation(layou
tObject, false); |
| 138 } | 135 } |
| 139 | 136 |
| 140 void SVGResourcesCache::clientWasAddedToTree(LayoutObject* layoutObject, const C
omputedStyle& newStyle) | 137 void SVGResourcesCache::clientWasAddedToTree(LayoutObject* layoutObject, const C
omputedStyle& newStyle) |
| 141 { | 138 { |
| 142 if (!layoutObject->node()) | 139 if (!layoutObject->node()) |
| 143 return; | 140 return; |
| 144 LayoutSVGResourceContainer::markForLayoutAndParentResourceInvalidation(layou
tObject, false); | 141 LayoutSVGResourceContainer::markForLayoutAndParentResourceInvalidation(layou
tObject, false); |
| 145 | 142 |
| 146 if (!layoutObjectCanHaveResources(layoutObject)) | 143 if (!layoutObjectCanHaveResources(layoutObject)) |
| 147 return; | 144 return; |
| 148 SVGResourcesCache* cache = resourcesCacheFromLayoutObject(layoutObject); | 145 SVGResourcesCache& cache = resourcesCache(layoutObject->document()); |
| 149 cache->addResourcesFromLayoutObject(layoutObject, newStyle); | 146 cache.addResourcesFromLayoutObject(layoutObject, newStyle); |
| 150 } | 147 } |
| 151 | 148 |
| 152 void SVGResourcesCache::clientWillBeRemovedFromTree(LayoutObject* layoutObject) | 149 void SVGResourcesCache::clientWillBeRemovedFromTree(LayoutObject* layoutObject) |
| 153 { | 150 { |
| 154 if (!layoutObject->node()) | 151 if (!layoutObject->node()) |
| 155 return; | 152 return; |
| 156 LayoutSVGResourceContainer::markForLayoutAndParentResourceInvalidation(layou
tObject, false); | 153 LayoutSVGResourceContainer::markForLayoutAndParentResourceInvalidation(layou
tObject, false); |
| 157 | 154 |
| 158 if (!layoutObjectCanHaveResources(layoutObject)) | 155 if (!layoutObjectCanHaveResources(layoutObject)) |
| 159 return; | 156 return; |
| 160 SVGResourcesCache* cache = resourcesCacheFromLayoutObject(layoutObject); | 157 SVGResourcesCache& cache = resourcesCache(layoutObject->document()); |
| 161 cache->removeResourcesFromLayoutObject(layoutObject); | 158 cache.removeResourcesFromLayoutObject(layoutObject); |
| 162 } | 159 } |
| 163 | 160 |
| 164 void SVGResourcesCache::clientDestroyed(LayoutObject* layoutObject) | 161 void SVGResourcesCache::clientDestroyed(LayoutObject* layoutObject) |
| 165 { | 162 { |
| 166 ASSERT(layoutObject); | 163 ASSERT(layoutObject); |
| 167 | 164 |
| 168 SVGResources* resources = SVGResourcesCache::cachedResourcesForLayoutObject(
layoutObject); | 165 SVGResources* resources = cachedResourcesForLayoutObject(layoutObject); |
| 169 if (resources) | 166 if (resources) |
| 170 resources->removeClientFromCache(layoutObject); | 167 resources->removeClientFromCache(layoutObject); |
| 171 | 168 SVGResourcesCache& cache = resourcesCache(layoutObject->document()); |
| 172 SVGResourcesCache* cache = resourcesCacheFromLayoutObject(layoutObject); | 169 cache.removeResourcesFromLayoutObject(layoutObject); |
| 173 cache->removeResourcesFromLayoutObject(layoutObject); | |
| 174 } | 170 } |
| 175 | 171 |
| 176 void SVGResourcesCache::resourceDestroyed(LayoutSVGResourceContainer* resource) | 172 void SVGResourcesCache::resourceDestroyed(LayoutSVGResourceContainer* resource) |
| 177 { | 173 { |
| 178 ASSERT(resource); | 174 ASSERT(resource); |
| 179 SVGResourcesCache* cache = resourcesCacheFromLayoutObject(resource); | 175 SVGResourcesCache& cache = resourcesCache(resource->document()); |
| 180 | 176 |
| 181 // The resource itself may have clients, that need to be notified. | 177 // The resource itself may have clients, that need to be notified. |
| 182 cache->removeResourcesFromLayoutObject(resource); | 178 cache.removeResourcesFromLayoutObject(resource); |
| 183 | 179 |
| 184 for (auto& objectResources : cache->m_cache) { | 180 for (auto& objectResources : cache.m_cache) { |
| 185 objectResources.value->resourceDestroyed(resource); | 181 objectResources.value->resourceDestroyed(resource); |
| 186 | 182 |
| 187 // Mark users of destroyed resources as pending resolution based on the
id of the old resource. | 183 // Mark users of destroyed resources as pending resolution based on the
id of the old resource. |
| 188 Element* resourceElement = resource->element(); | 184 Element* resourceElement = resource->element(); |
| 189 Element* clientElement = toElement(objectResources.key->node()); | 185 Element* clientElement = toElement(objectResources.key->node()); |
| 190 SVGDocumentExtensions& extensions = clientElement->document().accessSVGE
xtensions(); | 186 SVGDocumentExtensions& extensions = clientElement->document().accessSVGE
xtensions(); |
| 191 | 187 |
| 192 extensions.addPendingResource(resourceElement->fastGetAttribute(HTMLName
s::idAttr), clientElement); | 188 extensions.addPendingResource(resourceElement->fastGetAttribute(HTMLName
s::idAttr), clientElement); |
| 193 } | 189 } |
| 194 } | 190 } |
| 195 | 191 |
| 196 } | 192 } |
| OLD | NEW |