void SVGResourcesCycleSolver::resolveCycles() { ASSERT(m_allResources.isEmpty()); #if DEBUG_CYCLE_DETECTION > 0 fprintf(stderr, "\nBefore cycle detection:\n"); m_resources.dump(&m_renderer); #endif // Stash all resources into a HashSet for the ease of traversing. HashSet<RenderSVGResourceContainer*> localResources; m_resources.buildSetOfResources(localResources); ASSERT(!localResources.isEmpty()); // Add all parent resource containers to the HashSet. HashSet<RenderSVGResourceContainer*> ancestorResources; for (auto& resource : ancestorsOfType<RenderSVGResourceContainer>(m_renderer)) ancestorResources.add(&resource); #if DEBUG_CYCLE_DETECTION > 0 fprintf(stderr, "\nDetecting wheter any resources references any of following objects:\n"); { fprintf(stderr, "Local resources:\n"); for (auto* resource : localResources) fprintf(stderr, "|> %s: object=%p (node=%p)\n", resource->renderName(), resource, resource->node()); fprintf(stderr, "Parent resources:\n"); for (auto* resource : ancestorResources) fprintf(stderr, "|> %s: object=%p (node=%p)\n", resource->renderName(), resource, resource->node()); } #endif // Build combined set of local and parent resources. m_allResources = localResources; for (auto* resource : ancestorResources) m_allResources.add(resource); // If we're a resource, add ourselves to the HashSet. if (m_renderer.isSVGResourceContainer()) m_allResources.add(&toRenderSVGResourceContainer(m_renderer)); ASSERT(!m_allResources.isEmpty()); // The job of this function is to determine wheter any of the 'resources' associated with the given 'renderer' // references us (or wheter any of its kids references us) -> that's a cycle, we need to find and break it. for (auto* resource : localResources) { if (ancestorResources.contains(resource) || resourceContainsCycles(*resource)) breakCycle(*resource); } #if DEBUG_CYCLE_DETECTION > 0 fprintf(stderr, "\nAfter cycle detection:\n"); m_resources.dump(m_renderer); #endif m_allResources.clear(); }
void SVGResourcesCycleSolver::resolveCycles() { ASSERT(m_activeResources.isEmpty()); // If the starting LayoutObject is a resource container itself, then add it // to the active set (to break direct self-references.) if (m_layoutObject->isSVGResourceContainer()) m_activeResources.add(toLayoutSVGResourceContainer(m_layoutObject)); ResourceSet localResources; m_resources->buildSetOfResources(localResources); // This performs a depth-first search for a back-edge in all the // (potentially disjoint) graphs formed by the resources referenced by // |m_layoutObject|. for (auto* localResource : localResources) { if (m_activeResources.contains(localResource) || resourceContainsCycles(localResource)) breakCycle(localResource); } m_activeResources.clear(); }
void SVGResourcesCycleSolver::resolveCycles() { ASSERT(m_allResources.isEmpty()); #if DEBUG_CYCLE_DETECTION > 0 fprintf(stderr, "\nBefore cycle detection:\n"); m_resources->dump(m_renderer); #endif // Stash all resources into a HashSet for the ease of traversing. HashSet<RenderSVGResourceContainer*> localResources; m_resources->buildSetOfResources(localResources); ASSERT(!localResources.isEmpty()); // Add all parent resource containers to the HashSet. HashSet<RenderSVGResourceContainer*> parentResources; RenderObject* parent = m_renderer->parent(); while (parent) { if (parent->isSVGResourceContainer()) parentResources.add(toRenderSVGResourceContainer(parent)); parent = parent->parent(); } #if DEBUG_CYCLE_DETECTION > 0 fprintf(stderr, "\nDetecting wheter any resources references any of following objects:\n"); { fprintf(stderr, "Local resources:\n"); HashSet<RenderSVGResourceContainer*>::iterator end = localResources.end(); for (HashSet<RenderSVGResourceContainer*>::iterator it = localResources.begin(); it != end; ++it) fprintf(stderr, "|> %s: object=%p (node=%p)\n", (*it)->renderName(), *it, (*it)->node()); fprintf(stderr, "Parent resources:\n"); end = parentResources.end(); for (HashSet<RenderSVGResourceContainer*>::iterator it = parentResources.begin(); it != end; ++it) fprintf(stderr, "|> %s: object=%p (node=%p)\n", (*it)->renderName(), *it, (*it)->node()); } #endif // Build combined set of local and parent resources. m_allResources = localResources; HashSet<RenderSVGResourceContainer*>::iterator end = parentResources.end(); for (HashSet<RenderSVGResourceContainer*>::iterator it = parentResources.begin(); it != end; ++it) m_allResources.add(*it); // If we're a resource, add ourselves to the HashSet. if (m_renderer->isSVGResourceContainer()) m_allResources.add(toRenderSVGResourceContainer(m_renderer)); ASSERT(!m_allResources.isEmpty()); // The job of this function is to determine wheter any of the 'resources' associated with the given 'renderer' // references us (or wheter any of its kids references us) -> that's a cycle, we need to find and break it. end = localResources.end(); for (HashSet<RenderSVGResourceContainer*>::iterator it = localResources.begin(); it != end; ++it) { RenderSVGResourceContainer* resource = *it; if (parentResources.contains(resource) || resourceContainsCycles(resource)) breakCycle(resource); } #if DEBUG_CYCLE_DETECTION > 0 fprintf(stderr, "\nAfter cycle detection:\n"); m_resources->dump(m_renderer); #endif m_allResources.clear(); }