SVGResourcesCache.cpp [plain text]
#include "config.h"
#include "SVGResourcesCache.h"
#include "HTMLNames.h"
#include "RenderSVGResourceContainer.h"
#include "SVGResources.h"
#include "SVGResourcesCycleSolver.h"
namespace WebCore {
SVGResourcesCache::SVGResourcesCache()
{
}
SVGResourcesCache::~SVGResourcesCache()
{
}
void SVGResourcesCache::addResourcesFromRenderer(RenderElement& renderer, const RenderStyle& style)
{
ASSERT(!m_cache.contains(&renderer));
auto newResources = std::make_unique<SVGResources>();
if (!newResources->buildCachedResources(renderer, style))
return;
SVGResources& resources = *m_cache.add(&renderer, WTFMove(newResources)).iterator->value;
SVGResourcesCycleSolver solver(renderer, resources);
solver.resolveCycles();
HashSet<RenderSVGResourceContainer*> resourceSet;
resources.buildSetOfResources(resourceSet);
for (auto* resourceContainer : resourceSet)
resourceContainer->addClient(renderer);
}
void SVGResourcesCache::removeResourcesFromRenderer(RenderElement& renderer)
{
std::unique_ptr<SVGResources> resources = m_cache.take(&renderer);
if (!resources)
return;
HashSet<RenderSVGResourceContainer*> resourceSet;
resources->buildSetOfResources(resourceSet);
for (auto* resourceContainer : resourceSet)
resourceContainer->removeClient(renderer);
}
static inline SVGResourcesCache& resourcesCacheFromRenderer(const RenderElement& renderer)
{
return renderer.document().accessSVGExtensions().resourcesCache();
}
SVGResources* SVGResourcesCache::cachedResourcesForRenderer(const RenderElement& renderer)
{
return resourcesCacheFromRenderer(renderer).m_cache.get(&renderer);
}
void SVGResourcesCache::clientLayoutChanged(RenderElement& renderer)
{
auto* resources = SVGResourcesCache::cachedResourcesForRenderer(renderer);
if (!resources)
return;
if (renderer.selfNeedsLayout())
resources->removeClientFromCache(renderer);
}
static inline bool rendererCanHaveResources(RenderObject& renderer)
{
return renderer.node() && renderer.node()->isSVGElement() && !renderer.isSVGInlineText();
}
void SVGResourcesCache::clientStyleChanged(RenderElement& renderer, StyleDifference diff, const RenderStyle& newStyle)
{
if (diff == StyleDifferenceEqual || !renderer.parent())
return;
if (renderer.isSVGResourceFilterPrimitive() && (diff == StyleDifferenceRepaint || diff == StyleDifferenceRepaintIfTextOrBorderOrOutline))
return;
if (rendererCanHaveResources(renderer)) {
auto& cache = resourcesCacheFromRenderer(renderer);
cache.removeResourcesFromRenderer(renderer);
cache.addResourcesFromRenderer(renderer, newStyle);
}
RenderSVGResource::markForLayoutAndParentResourceInvalidation(renderer, false);
if (renderer.element() && !renderer.element()->isSVGElement())
renderer.element()->setNeedsStyleRecalc(SyntheticStyleChange);
}
void SVGResourcesCache::clientWasAddedToTree(RenderObject& renderer)
{
if (renderer.isAnonymous())
return;
RenderSVGResource::markForLayoutAndParentResourceInvalidation(renderer, false);
if (!rendererCanHaveResources(renderer))
return;
RenderElement& elementRenderer = downcast<RenderElement>(renderer);
resourcesCacheFromRenderer(elementRenderer).addResourcesFromRenderer(elementRenderer, elementRenderer.style());
}
void SVGResourcesCache::clientWillBeRemovedFromTree(RenderObject& renderer)
{
if (renderer.isAnonymous())
return;
RenderSVGResource::markForLayoutAndParentResourceInvalidation(renderer, false);
if (!rendererCanHaveResources(renderer))
return;
RenderElement& elementRenderer = downcast<RenderElement>(renderer);
resourcesCacheFromRenderer(elementRenderer).removeResourcesFromRenderer(elementRenderer);
}
void SVGResourcesCache::clientDestroyed(RenderElement& renderer)
{
if (auto* resources = SVGResourcesCache::cachedResourcesForRenderer(renderer))
resources->removeClientFromCache(renderer);
resourcesCacheFromRenderer(renderer).removeResourcesFromRenderer(renderer);
}
void SVGResourcesCache::resourceDestroyed(RenderSVGResourceContainer& resource)
{
auto& cache = resourcesCacheFromRenderer(resource);
cache.removeResourcesFromRenderer(resource);
for (auto& it : cache.m_cache) {
it.value->resourceDestroyed(resource);
Element& resourceElement = resource.element();
Element* clientElement = it.key->element();
clientElement->document().accessSVGExtensions().addPendingResource(resourceElement.getIdAttribute(), clientElement);
}
}
}