1b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam/*
2b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * Copyright (C) Research In Motion Limited 2010. All rights reserved.
36e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom *
46e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom * This library is free software; you can redistribute it and/or
5b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * modify it under the terms of the GNU Library General Public
6b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * License as published by the Free Software Foundation; either
7b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * version 2 of the License, or (at your option) any later version.
8b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam *
9b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * This library is distributed in the hope that it will be useful,
10b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * but WITHOUT ANY WARRANTY; without even the implied warranty of
11b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * Library General Public License for more details.
13b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam *
14b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * You should have received a copy of the GNU Library General Public License
15b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * along with this library; see the file COPYING.LIB.  If not, write to
16b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * Boston, MA 02110-1301, USA.
18b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam */
19b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
20b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam#include "config.h"
21b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam#include "SVGResourcesCache.h"
22b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
23b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam#if ENABLE(SVG)
24b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam#include "RenderSVGResourceContainer.h"
25b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam#include "SVGDocumentExtensions.h"
26b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam#include "SVGResources.h"
27b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam#include "SVGResourcesCycleSolver.h"
28b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
29b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallamnamespace WebCore {
30b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
31b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter HallamSVGResourcesCache::SVGResourcesCache()
32b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam{
33b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam}
34b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
35b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter HallamSVGResourcesCache::~SVGResourcesCache()
36b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam{
37b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    deleteAllValues(m_cache);
38b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam}
39b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
40b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallamvoid SVGResourcesCache::addResourcesFromRenderObject(RenderObject* object, const RenderStyle* style)
41b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam{
42b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    ASSERT(object);
43b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    ASSERT(style);
44b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    ASSERT(!m_cache.contains(object));
45b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
46b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    const SVGRenderStyle* svgStyle = style->svgStyle();
47b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    ASSERT(svgStyle);
48b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
49b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    // Build a list of all resources associated with the passed RenderObject
50b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    SVGResources* resources = new SVGResources;
51b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    if (!resources->buildCachedResources(object, svgStyle)) {
52b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        delete resources;
53b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        return;
54b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    }
55b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
56b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    // Put object in cache.
57b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    m_cache.set(object, resources);
58b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
59b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    // Run cycle-detection _afterwards_, so self-references can be caught as well.
60b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    SVGResourcesCycleSolver solver(object, resources);
61b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    solver.resolveCycles();
62b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
63b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    // Walk resources and register the render object at each resources.
64b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    HashSet<RenderSVGResourceContainer*> resourceSet;
65b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    resources->buildSetOfResources(resourceSet);
66b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
676e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom    HashSet<RenderSVGResourceContainer*>::iterator end = resourceSet.end();
686e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom    for (HashSet<RenderSVGResourceContainer*>::iterator it = resourceSet.begin(); it != end; ++it)
696e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        (*it)->addClient(object);
706e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom}
716e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom
726e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstromvoid SVGResourcesCache::removeResourcesFromRenderObject(RenderObject* object)
736e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom{
746e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom    if (!m_cache.contains(object))
756e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        return;
766e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom
776e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom    SVGResources* resources = m_cache.get(object);
786e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom
796e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom    // Walk resources and register the render object at each resources.
806e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom    HashSet<RenderSVGResourceContainer*> resourceSet;
816e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom    resources->buildSetOfResources(resourceSet);
826e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom
836e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom    HashSet<RenderSVGResourceContainer*>::iterator end = resourceSet.end();
846e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom    for (HashSet<RenderSVGResourceContainer*>::iterator it = resourceSet.begin(); it != end; ++it)
856e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        (*it)->removeClient(object);
86b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
876e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom    delete m_cache.take(object);
88b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam}
89b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
90b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallamstatic inline SVGResourcesCache* resourcesCacheFromRenderObject(RenderObject* renderer)
91b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam{
92b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    Document* document = renderer->document();
93b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    ASSERT(document);
94b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
95b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    SVGDocumentExtensions* extensions = document->accessSVGExtensions();
96b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    ASSERT(extensions);
97b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
98b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    SVGResourcesCache* cache = extensions->resourcesCache();
99b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    ASSERT(cache);
100b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
101b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    return cache;
102b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam}
103b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
104b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter HallamSVGResources* SVGResourcesCache::cachedResourcesForRenderObject(RenderObject* renderer)
105b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam{
106b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    ASSERT(renderer);
107b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    SVGResourcesCache* cache = resourcesCacheFromRenderObject(renderer);
108b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    if (!cache->m_cache.contains(renderer))
109b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        return 0;
110b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
111b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    return cache->m_cache.get(renderer);
112b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam}
113b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
114b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallamvoid SVGResourcesCache::clientLayoutChanged(RenderObject* object)
115b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam{
116b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    SVGResources* resources = SVGResourcesCache::cachedResourcesForRenderObject(object);
117b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    if (!resources)
118b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        return;
119b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
120b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    resources->removeClientFromCache(object);
121b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam}
122b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
123b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallamvoid SVGResourcesCache::clientStyleChanged(RenderObject* renderer, StyleDifference diff, const RenderStyle* newStyle)
124b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam{
125b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    ASSERT(renderer);
126b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    if (diff == StyleDifferenceEqual)
127b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        return;
128b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
129b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    // In this case the proper SVGFE*Element will imply whether the modifided CSS properties implies a relayout or repaint.
130b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    if (renderer->isSVGResourceFilterPrimitive() && diff == StyleDifferenceRepaint)
131c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        return;
132c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom
133c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom    clientUpdatedFromElement(renderer, newStyle);
134c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom    RenderSVGResource::markForLayoutAndParentResourceInvalidation(renderer, false);
135c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom}
136b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
137b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallamvoid SVGResourcesCache::clientUpdatedFromElement(RenderObject* renderer, const RenderStyle* newStyle)
138b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam{
139b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    ASSERT(renderer);
140b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    ASSERT(renderer->parent());
141b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
142b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    SVGResourcesCache* cache = resourcesCacheFromRenderObject(renderer);
143b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    cache->removeResourcesFromRenderObject(renderer);
144b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    cache->addResourcesFromRenderObject(renderer, newStyle);
145b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam}
146b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
147b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallamvoid SVGResourcesCache::clientDestroyed(RenderObject* renderer)
148b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam{
149b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    ASSERT(renderer);
150b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    SVGResourcesCache* cache = resourcesCacheFromRenderObject(renderer);
151b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    cache->removeResourcesFromRenderObject(renderer);
152b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam}
153b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
154b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallamvoid SVGResourcesCache::resourceDestroyed(RenderSVGResourceContainer* resource)
155b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam{
156b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    ASSERT(resource);
157b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    SVGResourcesCache* cache = resourcesCacheFromRenderObject(resource);
158b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
159b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    // The resource itself may have clients, that need to be notified.
160b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    cache->removeResourcesFromRenderObject(resource);
161b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
162b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    HashMap<RenderObject*, SVGResources*>::iterator end = cache->m_cache.end();
163b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    for (HashMap<RenderObject*, SVGResources*>::iterator it = cache->m_cache.begin(); it != end; ++it)
164b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        it->second->resourceDestroyed(resource);
165b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam}
166b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
167b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam}
168b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
169b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam#endif
170b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam