2 * Copyright (C) Research In Motion Limited 2010. All rights reserved.
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
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
16 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17 * Boston, MA 02110-1301, USA.
21 #include "SVGResourcesCache.h"
24 #include "HTMLNames.h"
25 #include "RenderSVGResourceContainer.h"
26 #include "SVGDocumentExtensions.h"
27 #include "SVGResources.h"
28 #include "SVGResourcesCycleSolver.h"
29 #include "SVGStyledElement.h"
33 SVGResourcesCache::SVGResourcesCache()
37 SVGResourcesCache::~SVGResourcesCache()
39 deleteAllValues(m_cache);
42 void SVGResourcesCache::addResourcesFromRenderObject(RenderObject* object, const RenderStyle* style)
46 ASSERT(!m_cache.contains(object));
48 const SVGRenderStyle* svgStyle = style->svgStyle();
51 // Build a list of all resources associated with the passed RenderObject
52 SVGResources* resources = new SVGResources;
53 if (!resources->buildCachedResources(object, svgStyle)) {
58 // Put object in cache.
59 m_cache.set(object, resources);
61 // Run cycle-detection _afterwards_, so self-references can be caught as well.
62 SVGResourcesCycleSolver solver(object, resources);
63 solver.resolveCycles();
65 // Walk resources and register the render object at each resources.
66 HashSet<RenderSVGResourceContainer*> resourceSet;
67 resources->buildSetOfResources(resourceSet);
69 HashSet<RenderSVGResourceContainer*>::iterator end = resourceSet.end();
70 for (HashSet<RenderSVGResourceContainer*>::iterator it = resourceSet.begin(); it != end; ++it)
71 (*it)->addClient(object);
74 void SVGResourcesCache::removeResourcesFromRenderObject(RenderObject* object)
76 if (!m_cache.contains(object))
79 SVGResources* resources = m_cache.get(object);
81 // Walk resources and register the render object at each resources.
82 HashSet<RenderSVGResourceContainer*> resourceSet;
83 resources->buildSetOfResources(resourceSet);
85 HashSet<RenderSVGResourceContainer*>::iterator end = resourceSet.end();
86 for (HashSet<RenderSVGResourceContainer*>::iterator it = resourceSet.begin(); it != end; ++it)
87 (*it)->removeClient(object);
89 delete m_cache.take(object);
92 static inline SVGResourcesCache* resourcesCacheFromRenderObject(RenderObject* renderer)
94 Document* document = renderer->document();
97 SVGDocumentExtensions* extensions = document->accessSVGExtensions();
100 SVGResourcesCache* cache = extensions->resourcesCache();
106 SVGResources* SVGResourcesCache::cachedResourcesForRenderObject(RenderObject* renderer)
109 SVGResourcesCache* cache = resourcesCacheFromRenderObject(renderer);
110 if (!cache->m_cache.contains(renderer))
113 return cache->m_cache.get(renderer);
116 void SVGResourcesCache::clientLayoutChanged(RenderObject* object)
118 SVGResources* resources = SVGResourcesCache::cachedResourcesForRenderObject(object);
122 resources->removeClientFromCache(object);
125 void SVGResourcesCache::clientStyleChanged(RenderObject* renderer, StyleDifference diff, const RenderStyle* newStyle)
128 if (diff == StyleDifferenceEqual)
131 // In this case the proper SVGFE*Element will decide whether the modified CSS properties require a relayout or repaint.
132 if (renderer->isSVGResourceFilterPrimitive() && diff == StyleDifferenceRepaint)
135 clientUpdatedFromElement(renderer, newStyle);
136 RenderSVGResource::markForLayoutAndParentResourceInvalidation(renderer, false);
139 void SVGResourcesCache::clientUpdatedFromElement(RenderObject* renderer, const RenderStyle* newStyle)
142 ASSERT(renderer->parent());
144 SVGResourcesCache* cache = resourcesCacheFromRenderObject(renderer);
145 cache->removeResourcesFromRenderObject(renderer);
146 cache->addResourcesFromRenderObject(renderer, newStyle);
148 SVGResources* resources = SVGResourcesCache::cachedResourcesForRenderObject(renderer);
152 resources->removeClientFromCache(renderer);
155 void SVGResourcesCache::clientDestroyed(RenderObject* renderer)
158 SVGResourcesCache* cache = resourcesCacheFromRenderObject(renderer);
159 cache->removeResourcesFromRenderObject(renderer);
162 void SVGResourcesCache::resourceDestroyed(RenderSVGResourceContainer* resource)
165 SVGResourcesCache* cache = resourcesCacheFromRenderObject(resource);
167 // The resource itself may have clients, that need to be notified.
168 cache->removeResourcesFromRenderObject(resource);
170 HashMap<RenderObject*, SVGResources*>::iterator end = cache->m_cache.end();
171 for (HashMap<RenderObject*, SVGResources*>::iterator it = cache->m_cache.begin(); it != end; ++it) {
172 it->second->resourceDestroyed(resource);
174 // Mark users of destroyed resources as pending resolution based on the id of the old resource.
175 Element* resourceElement = toElement(resource->node());
176 SVGStyledElement* clientElement = toSVGStyledElement(it->first->node());
177 SVGDocumentExtensions* extensions = clientElement->document()->accessSVGExtensions();
179 extensions->addPendingResource(resourceElement->fastGetAttribute(HTMLNames::idAttr), clientElement);