Home | History | Annotate | Download | only in svg
      1 /*
      2  * Copyright (C) Research In Motion Limited 2010. All rights reserved.
      3  *
      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.
      8  *
      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.
     13  *
     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.
     18  */
     19 
     20 #include "config.h"
     21 #include "SVGResourcesCache.h"
     22 
     23 #if ENABLE(SVG)
     24 #include "RenderSVGResourceContainer.h"
     25 #include "SVGDocumentExtensions.h"
     26 #include "SVGResources.h"
     27 #include "SVGResourcesCycleSolver.h"
     28 
     29 namespace WebCore {
     30 
     31 SVGResourcesCache::SVGResourcesCache()
     32 {
     33 }
     34 
     35 SVGResourcesCache::~SVGResourcesCache()
     36 {
     37     deleteAllValues(m_cache);
     38 }
     39 
     40 void SVGResourcesCache::addResourcesFromRenderObject(RenderObject* object, const RenderStyle* style)
     41 {
     42     ASSERT(object);
     43     ASSERT(style);
     44     ASSERT(!m_cache.contains(object));
     45 
     46     const SVGRenderStyle* svgStyle = style->svgStyle();
     47     ASSERT(svgStyle);
     48 
     49     // Build a list of all resources associated with the passed RenderObject
     50     SVGResources* resources = new SVGResources;
     51     if (!resources->buildCachedResources(object, svgStyle)) {
     52         delete resources;
     53         return;
     54     }
     55 
     56     // Put object in cache.
     57     m_cache.set(object, resources);
     58 
     59     // Run cycle-detection _afterwards_, so self-references can be caught as well.
     60     SVGResourcesCycleSolver solver(object, resources);
     61     solver.resolveCycles();
     62 
     63     // Walk resources and register the render object at each resources.
     64     HashSet<RenderSVGResourceContainer*> resourceSet;
     65     resources->buildSetOfResources(resourceSet);
     66 
     67     HashSet<RenderSVGResourceContainer*>::iterator end = resourceSet.end();
     68     for (HashSet<RenderSVGResourceContainer*>::iterator it = resourceSet.begin(); it != end; ++it)
     69         (*it)->addClient(object);
     70 }
     71 
     72 void SVGResourcesCache::removeResourcesFromRenderObject(RenderObject* object)
     73 {
     74     if (!m_cache.contains(object))
     75         return;
     76 
     77     SVGResources* resources = m_cache.get(object);
     78 
     79     // Walk resources and register the render object at each resources.
     80     HashSet<RenderSVGResourceContainer*> resourceSet;
     81     resources->buildSetOfResources(resourceSet);
     82 
     83     HashSet<RenderSVGResourceContainer*>::iterator end = resourceSet.end();
     84     for (HashSet<RenderSVGResourceContainer*>::iterator it = resourceSet.begin(); it != end; ++it)
     85         (*it)->removeClient(object);
     86 
     87     delete m_cache.take(object);
     88 }
     89 
     90 static inline SVGResourcesCache* resourcesCacheFromRenderObject(RenderObject* renderer)
     91 {
     92     Document* document = renderer->document();
     93     ASSERT(document);
     94 
     95     SVGDocumentExtensions* extensions = document->accessSVGExtensions();
     96     ASSERT(extensions);
     97 
     98     SVGResourcesCache* cache = extensions->resourcesCache();
     99     ASSERT(cache);
    100 
    101     return cache;
    102 }
    103 
    104 SVGResources* SVGResourcesCache::cachedResourcesForRenderObject(RenderObject* renderer)
    105 {
    106     ASSERT(renderer);
    107     SVGResourcesCache* cache = resourcesCacheFromRenderObject(renderer);
    108     if (!cache->m_cache.contains(renderer))
    109         return 0;
    110 
    111     return cache->m_cache.get(renderer);
    112 }
    113 
    114 void SVGResourcesCache::clientLayoutChanged(RenderObject* object)
    115 {
    116     SVGResources* resources = SVGResourcesCache::cachedResourcesForRenderObject(object);
    117     if (!resources)
    118         return;
    119 
    120     resources->removeClientFromCache(object);
    121 }
    122 
    123 void SVGResourcesCache::clientStyleChanged(RenderObject* renderer, StyleDifference diff, const RenderStyle* newStyle)
    124 {
    125     ASSERT(renderer);
    126     if (diff == StyleDifferenceEqual)
    127         return;
    128 
    129     // In this case the proper SVGFE*Element will imply whether the modifided CSS properties implies a relayout or repaint.
    130     if (renderer->isSVGResourceFilterPrimitive() && diff == StyleDifferenceRepaint)
    131         return;
    132 
    133     clientUpdatedFromElement(renderer, newStyle);
    134     RenderSVGResource::markForLayoutAndParentResourceInvalidation(renderer, false);
    135 }
    136 
    137 void SVGResourcesCache::clientUpdatedFromElement(RenderObject* renderer, const RenderStyle* newStyle)
    138 {
    139     ASSERT(renderer);
    140     ASSERT(renderer->parent());
    141 
    142     SVGResourcesCache* cache = resourcesCacheFromRenderObject(renderer);
    143     cache->removeResourcesFromRenderObject(renderer);
    144     cache->addResourcesFromRenderObject(renderer, newStyle);
    145 }
    146 
    147 void SVGResourcesCache::clientDestroyed(RenderObject* renderer)
    148 {
    149     ASSERT(renderer);
    150     SVGResourcesCache* cache = resourcesCacheFromRenderObject(renderer);
    151     cache->removeResourcesFromRenderObject(renderer);
    152 }
    153 
    154 void SVGResourcesCache::resourceDestroyed(RenderSVGResourceContainer* resource)
    155 {
    156     ASSERT(resource);
    157     SVGResourcesCache* cache = resourcesCacheFromRenderObject(resource);
    158 
    159     // The resource itself may have clients, that need to be notified.
    160     cache->removeResourcesFromRenderObject(resource);
    161 
    162     HashMap<RenderObject*, SVGResources*>::iterator end = cache->m_cache.end();
    163     for (HashMap<RenderObject*, SVGResources*>::iterator it = cache->m_cache.begin(); it != end; ++it)
    164         it->second->resourceDestroyed(resource);
    165 }
    166 
    167 }
    168 
    169 #endif
    170