SVGResourcesCache.cpp [plain text]
#include "config.h"
#include "SVGResourcesCache.h"
#if ENABLE(SVG)
#include "HTMLNames.h"
#include "RenderSVGResourceContainer.h"
#include "SVGDocumentExtensions.h"
#include "SVGResources.h"
#include "SVGResourcesCycleSolver.h"
#include "SVGStyledElement.h"
namespace WebCore {
SVGResourcesCache::SVGResourcesCache()
{
}
SVGResourcesCache::~SVGResourcesCache()
{
}
void SVGResourcesCache::addResourcesFromRenderObject(RenderObject* object, const RenderStyle* style)
{
ASSERT(object);
ASSERT(style);
ASSERT(!m_cache.contains(object));
const SVGRenderStyle* svgStyle = style->svgStyle();
ASSERT(svgStyle);
OwnPtr<SVGResources> newResources = adoptPtr(new SVGResources);
if (!newResources->buildCachedResources(object, svgStyle))
return;
SVGResources* resources = m_cache.set(object, newResources.release()).iterator->value.get();
SVGResourcesCycleSolver solver(object, resources);
solver.resolveCycles();
HashSet<RenderSVGResourceContainer*> resourceSet;
resources->buildSetOfResources(resourceSet);
HashSet<RenderSVGResourceContainer*>::iterator end = resourceSet.end();
for (HashSet<RenderSVGResourceContainer*>::iterator it = resourceSet.begin(); it != end; ++it)
(*it)->addClient(object);
}
void SVGResourcesCache::removeResourcesFromRenderObject(RenderObject* object)
{
if (!m_cache.contains(object))
return;
OwnPtr<SVGResources> resources = m_cache.take(object);
HashSet<RenderSVGResourceContainer*> resourceSet;
resources->buildSetOfResources(resourceSet);
HashSet<RenderSVGResourceContainer*>::iterator end = resourceSet.end();
for (HashSet<RenderSVGResourceContainer*>::iterator it = resourceSet.begin(); it != end; ++it)
(*it)->removeClient(object);
}
static inline SVGResourcesCache* resourcesCacheFromRenderObject(const RenderObject* renderer)
{
Document* document = renderer->document();
ASSERT(document);
SVGDocumentExtensions* extensions = document->accessSVGExtensions();
ASSERT(extensions);
SVGResourcesCache* cache = extensions->resourcesCache();
ASSERT(cache);
return cache;
}
SVGResources* SVGResourcesCache::cachedResourcesForRenderObject(const RenderObject* renderer)
{
ASSERT(renderer);
return resourcesCacheFromRenderObject(renderer)->m_cache.get(renderer);
}
void SVGResourcesCache::clientLayoutChanged(RenderObject* object)
{
SVGResources* resources = SVGResourcesCache::cachedResourcesForRenderObject(object);
if (!resources)
return;
if (object->selfNeedsLayout())
resources->removeClientFromCache(object);
}
static inline bool rendererCanHaveResources(RenderObject* renderer)
{
ASSERT(renderer);
return renderer->node() && renderer->node()->isSVGElement() && !renderer->isSVGInlineText();
}
void SVGResourcesCache::clientStyleChanged(RenderObject* renderer, StyleDifference diff, const RenderStyle* newStyle)
{
ASSERT(renderer);
if (diff == StyleDifferenceEqual || !renderer->parent())
return;
if (renderer->isSVGResourceFilterPrimitive() && (diff == StyleDifferenceRepaint || diff == StyleDifferenceRepaintIfText))
return;
if (rendererCanHaveResources(renderer)) {
SVGResourcesCache* cache = resourcesCacheFromRenderObject(renderer);
cache->removeResourcesFromRenderObject(renderer);
cache->addResourcesFromRenderObject(renderer, newStyle);
}
RenderSVGResource::markForLayoutAndParentResourceInvalidation(renderer, false);
if (renderer->node() && !renderer->node()->isSVGElement())
renderer->node()->setNeedsStyleRecalc(SyntheticStyleChange);
}
void SVGResourcesCache::clientWasAddedToTree(RenderObject* renderer, const RenderStyle* newStyle)
{
if (!renderer->node())
return;
RenderSVGResource::markForLayoutAndParentResourceInvalidation(renderer, false);
if (!rendererCanHaveResources(renderer))
return;
SVGResourcesCache* cache = resourcesCacheFromRenderObject(renderer);
cache->addResourcesFromRenderObject(renderer, newStyle);
}
void SVGResourcesCache::clientWillBeRemovedFromTree(RenderObject* renderer)
{
if (!renderer->node())
return;
RenderSVGResource::markForLayoutAndParentResourceInvalidation(renderer, false);
if (!rendererCanHaveResources(renderer))
return;
SVGResourcesCache* cache = resourcesCacheFromRenderObject(renderer);
cache->removeResourcesFromRenderObject(renderer);
}
void SVGResourcesCache::clientDestroyed(RenderObject* renderer)
{
ASSERT(renderer);
SVGResources* resources = SVGResourcesCache::cachedResourcesForRenderObject(renderer);
if (resources)
resources->removeClientFromCache(renderer);
SVGResourcesCache* cache = resourcesCacheFromRenderObject(renderer);
cache->removeResourcesFromRenderObject(renderer);
}
void SVGResourcesCache::resourceDestroyed(RenderSVGResourceContainer* resource)
{
ASSERT(resource);
SVGResourcesCache* cache = resourcesCacheFromRenderObject(resource);
cache->removeResourcesFromRenderObject(resource);
CacheMap::iterator end = cache->m_cache.end();
for (CacheMap::iterator it = cache->m_cache.begin(); it != end; ++it) {
it->value->resourceDestroyed(resource);
Element* resourceElement = toElement(resource->node());
Element* clientElement = toElement(it->key->node());
SVGDocumentExtensions* extensions = clientElement->document()->accessSVGExtensions();
extensions->addPendingResource(resourceElement->fastGetAttribute(HTMLNames::idAttr), clientElement);
}
}
}
#endif