[SVG] Update of element referenced by multiple 'use' nodes is absurdly slow
[WebKit-https.git] / Source / WebCore / svg / SVGUseElement.cpp
index 0b72cf6ff02a8ab8df507ea607634b133797dfcb..0f296b9ef18b086e935e8ef4311f7f12070b3b78 100644 (file)
@@ -409,10 +409,10 @@ void SVGUseElement::clearResourceReferences()
 
 void SVGUseElement::buildPendingResource()
 {
 
 void SVGUseElement::buildPendingResource()
 {
-    if (!referencedDocument())
+    if (!referencedDocument() || isInShadowTree())
         return;
     clearResourceReferences();
         return;
     clearResourceReferences();
-    if (!inDocument() || isInShadowTree())
+    if (!inDocument())
         return;
 
     String id;
         return;
 
     String id;
@@ -430,8 +430,11 @@ void SVGUseElement::buildPendingResource()
         return;
     }
 
         return;
     }
 
-    if (target->isSVGElement())
+    if (target->isSVGElement()) {
         buildShadowAndInstanceTree(static_cast<SVGElement*>(target));
         buildShadowAndInstanceTree(static_cast<SVGElement*>(target));
+        invalidateDependentShadowTrees();
+    }
+
     ASSERT(!m_needsShadowTreeRecreation);
 }
 
     ASSERT(!m_needsShadowTreeRecreation);
 }
 
@@ -517,10 +520,6 @@ void SVGUseElement::buildShadowAndInstanceTree(SVGElement* target)
     // Update relative length information.
     updateRelativeLengthsInformation();
 
     // Update relative length information.
     updateRelativeLengthsInformation();
 
-    // Rebuild all dependent use elements.
-    ASSERT(document());
-    document()->accessSVGExtensions()->rebuildAllElementReferencesForTarget(this);
-
     // Eventually dump instance tree
 #ifdef DUMP_INSTANCE_TREE
     String text;
     // Eventually dump instance tree
 #ifdef DUMP_INSTANCE_TREE
     String text;
@@ -906,6 +905,20 @@ void SVGUseElement::invalidateShadowTree()
         return;
     m_needsShadowTreeRecreation = true;
     setNeedsStyleRecalc();
         return;
     m_needsShadowTreeRecreation = true;
     setNeedsStyleRecalc();
+    invalidateDependentShadowTrees();
+}
+
+void SVGUseElement::invalidateDependentShadowTrees()
+{
+    // Recursively invalidate dependent <use> shadow trees
+    const HashSet<SVGElementInstance*>& instances = instancesForElement();
+    const HashSet<SVGElementInstance*>::const_iterator end = instances.end();
+    for (HashSet<SVGElementInstance*>::const_iterator it = instances.begin(); it != end; ++it) {
+        if (SVGUseElement* element = (*it)->correspondingUseElement()) {
+            ASSERT(element->inDocument());
+            element->invalidateShadowTree();
+        }
+    }
 }
 
 void SVGUseElement::transferUseAttributesToReplacedElement(SVGElement* from, SVGElement* to) const
 }
 
 void SVGUseElement::transferUseAttributesToReplacedElement(SVGElement* from, SVGElement* to) const