void SVGResourcesCache::addResourcesFromRenderObject(RenderObject* object, const RenderStyle* style) { ASSERT(object); ASSERT(style); ASSERT(!m_cache.contains(object)); const SVGRenderStyle* svgStyle = style->svgStyle(); ASSERT(svgStyle); // Build a list of all resources associated with the passed RenderObject SVGResources* resources = new SVGResources; if (!resources->buildCachedResources(object, svgStyle)) { delete resources; return; } // Put object in cache. m_cache.set(object, resources); // Run cycle-detection _afterwards_, so self-references can be caught as well. SVGResourcesCycleSolver solver(object, resources); solver.resolveCycles(); // Walk resources and register the render object at each resources. 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); }
bool SVGResourcesCycleSolver::resourceContainsCycles(RenderObject* renderer) const { ASSERT(renderer); // First (first loop iteration) operate on the resources of the given // renderer. // <marker id="a"> <path marker-start="url(#b)"/> ... // <marker id="b" marker-start="url(#a)"/> // Then operate on the child resources of the given renderer. // <marker id="a"> <path marker-start="url(#b)"/> ... // <marker id="b"> <path marker-start="url(#a)"/> ... for (RenderObject* child = renderer; child; child = child->nextInPreOrder(renderer)) { SVGResources* childResources = SVGResourcesCache::cachedResourcesForRenderObject(child); if (!childResources) continue; // A child of the given 'resource' contains resources. HashSet<RenderSVGResourceContainer*> childSet; childResources->buildSetOfResources(childSet); // Walk all child resources and check whether they reference any resource contained in the resources set. HashSet<RenderSVGResourceContainer*>::iterator end = childSet.end(); for (HashSet<RenderSVGResourceContainer*>::iterator it = childSet.begin(); it != end; ++it) { if (m_allResources.contains(*it)) return true; } } return false; }
void SVGResourcesCache::addResourcesFromLayoutObject(LayoutObject* object, const ComputedStyle& style) { ASSERT(object); ASSERT(!m_cache.contains(object)); const SVGComputedStyle& svgStyle = style.svgStyle(); // Build a list of all resources associated with the passed LayoutObject OwnPtr<SVGResources> newResources = SVGResources::buildResources(object, svgStyle); if (!newResources) return; // Put object in cache. SVGResources* resources = m_cache.set(object, newResources.release()).storedValue->value.get(); // Run cycle-detection _afterwards_, so self-references can be caught as well. SVGResourcesCycleSolver solver(object, resources); solver.resolveCycles(); // Walk resources and register the layout object at each resources. HashSet<LayoutSVGResourceContainer*> resourceSet; resources->buildSetOfResources(resourceSet); for (auto* resourceContainer : resourceSet) resourceContainer->addClient(object); }
void SVGResourcesCache::removeResourcesFromRenderObject(RenderObject* object) { if (!m_cache.contains(object)) return; SVGResources* resources = m_cache.get(object); // Walk resources and register the render object at each resources. 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); delete m_cache.take(object); }
bool SVGResourcesCycleSolver::resourceContainsCycles(RenderElement& renderer) const { // First operate on the resources of the given renderer. // <marker id="a"> <path marker-start="url(#b)"/> ... // <marker id="b" marker-start="url(#a)"/> if (SVGResources* resources = SVGResourcesCache::cachedResourcesForRenderObject(renderer)) { HashSet<RenderSVGResourceContainer*> resourceSet; resources->buildSetOfResources(resourceSet); // Walk all resources and check wheter they reference any resource contained in the resources set. for (auto* resource : resourceSet) { if (m_allResources.contains(resource)) return true; } } // Then operate on the child resources of the given renderer. // <marker id="a"> <path marker-start="url(#b)"/> ... // <marker id="b"> <path marker-start="url(#a)"/> ... for (auto& child : childrenOfType<RenderElement>(renderer)) { SVGResources* childResources = SVGResourcesCache::cachedResourcesForRenderObject(child); if (!childResources) continue; // A child of the given 'resource' contains resources. HashSet<RenderSVGResourceContainer*> childResourceSet; childResources->buildSetOfResources(childResourceSet); // Walk all child resources and check wheter they reference any resource contained in the resources set. for (auto* resource : childResourceSet) { if (m_allResources.contains(resource)) return true; } // Walk children recursively, stop immediately if we found a cycle if (resourceContainsCycles(child)) return true; } return false; }