From a09ae0d6474ad111ae5a759b0a8423428a8089c0 Mon Sep 17 00:00:00 2001 From: Robert Löhning Date: Wed, 27 May 2026 12:05:45 +0200 Subject: [PATCH] Speed up QSvgStructureNode::releaseDescendants() The previous implementation traversed the tree of objects until it found something it may delete. Then it deleted that and started from the root of the tree again to find the next object. Instead, this code traverses the tree only once and deletes what it finds on the way. Amends 22d503993d156d89086f1a68c76670cbc7130be0 Task-number: QTBUG-145916 Change-Id: If693f62ea469d85536eed0fcf7a87103c335c68c Reviewed-by: Hatem ElKharashy (cherry picked from commit 32680b86192ea67d9e273061108439166e7db3d6) Reviewed-by: Qt Cherry-pick Bot (cherry picked from commit 23183692f615ef6dcf790ece69518cc661aca576) --- diff --git a/src/svg/qsvgstructure.cpp b/src/svg/qsvgstructure.cpp index fcdf00b..17dfa9b 100644 --- a/src/svg/qsvgstructure.cpp +++ b/src/svg/qsvgstructure.cpp @@ -733,35 +733,41 @@ // happen in deeply nested trees. // This function does not allocate any memory at the cost of sacrificing some performance to // make it safe to be called from a destructor. - while (!m_renderers.empty()) { - auto nodes = &m_renderers; - bool isSubtree = true; - while (isSubtree) { - switch (nodes->front()->type()) { - case QSvgNode::Doc: - case QSvgNode::Defs: - case QSvgNode::Group: - case QSvgNode::Mask: - case QSvgNode::Pattern: - case QSvgNode::Symbol: - case QSvgNode::Switch: - case QSvgNode::Filter: - { - QSvgStructureNode *subtree = static_cast(nodes->first()); - isSubtree = !subtree->m_renderers.empty(); - if (isSubtree) - nodes = &subtree->m_renderers; - } - break; - default: - isSubtree = false; - break; + QSvgNode *currentParent = this; + while (currentParent) { + switch (currentParent->type()) { + case QSvgNode::Doc: + case QSvgNode::Defs: + case QSvgNode::Group: + case QSvgNode::Mask: + case QSvgNode::Pattern: + case QSvgNode::Symbol: + case QSvgNode::Switch: + case QSvgNode::Filter: + { + QSvgStructureNode *currentParentSN = static_cast(currentParent); + if (currentParentSN->m_renderers.empty()) { + currentParent = currentParent->parent(); + if (currentParent) { + delete static_cast(currentParent)->m_renderers.first(); + static_cast(currentParent)->m_renderers.pop_front(); + } + } else { + Q_ASSERT(currentParentSN->m_renderers.first()->parent() == currentParent); + currentParent = currentParentSN->m_renderers.first(); } } - QSvgNode *node = nodes->first(); - delete node; - nodes->pop_front(); + break; + default: + currentParent = currentParent->parent(); + if (currentParent) { + delete static_cast(currentParent)->m_renderers.first(); + static_cast(currentParent)->m_renderers.pop_front(); + } + break; + } } + Q_ASSERT(this->m_renderers.empty()); } QSvgMask::QSvgMask(QSvgNode *parent, QSvgRectF bounds,