diff --git a/yoga/YGNode.cpp b/yoga/YGNode.cpp index a80484f168..22316fde92 100644 --- a/yoga/YGNode.cpp +++ b/yoga/YGNode.cpp @@ -121,14 +121,17 @@ void YGNode::setMeasureFunc(YGMeasureFunc measureFunc) { void YGNode::replaceChild(YGNodeRef child, uint32_t index) { children_[index] = child; + setChildRoot(child); } void YGNode::replaceChild(YGNodeRef oldChild, YGNodeRef newChild) { std::replace(children_.begin(), children_.end(), oldChild, newChild); + setChildRoot(newChild); } void YGNode::insertChild(YGNodeRef child, uint32_t index) { children_.insert(children_.begin() + index, child); + setChildRoot(child); } void YGNode::setDirty(bool isDirty) { @@ -552,3 +555,15 @@ bool YGNode::isLayoutTreeEqualToNode(const YGNode& node) const { } return isLayoutTreeEqual; } + +YGNodeRef YGNode::getRoot() { + if (pRoot == nullptr) pRoot = this; + return pRoot; +} + +void YGNode::setChildRoot(YGNodeRef node) { + node->pRoot = getRoot(); + for (auto child: node->children_) { + setChildRoot(child); + } +} \ No newline at end of file diff --git a/yoga/YGNode.h b/yoga/YGNode.h index 7120846ef7..6a184963c0 100644 --- a/yoga/YGNode.h +++ b/yoga/YGNode.h @@ -270,4 +270,13 @@ struct YGNode { bool isNodeFlexible(); bool didUseLegacyFlag(); bool isLayoutTreeEqualToNode(const YGNode& node) const; + +private: + YGNodeRef pRoot = nullptr; + +public: + uint32_t gCurrentGenerationCount = 0; + uint32_t gDepth = 0; + YGNodeRef getRoot(); + void setChildRoot(YGNodeRef node); }; diff --git a/yoga/Yoga.cpp b/yoga/Yoga.cpp index b9a5f781eb..a59d640db9 100644 --- a/yoga/Yoga.cpp +++ b/yoga/Yoga.cpp @@ -14,6 +14,7 @@ #include "YGNode.h" #include "YGNodePrint.h" #include "Yoga-internal.h" +#include #ifdef _MSC_VER #include @@ -222,8 +223,8 @@ void YGNodeMarkDirtyAndPropogateToDescendants(const YGNodeRef node) { return node->markDirtyAndPropogateDownwards(); } -int32_t gNodeInstanceCount = 0; -int32_t gConfigInstanceCount = 0; +std::atomic gNodeInstanceCount(0); +std::atomic gConfigInstanceCount(0); WIN_EXPORT YGNodeRef YGNodeNewWithConfig(const YGConfigRef config) { const YGNodeRef node = new YGNode(); @@ -254,6 +255,7 @@ YGNodeRef YGNodeClone(YGNodeRef oldNode) { oldNode->getConfig(), node != nullptr, "Could not allocate memory for node"); + oldNode->setChildRoot(node); gNodeInstanceCount++; node->setOwner(nullptr); return node; @@ -307,8 +309,8 @@ void YGNodeFree(const YGNodeRef node) { static void YGConfigFreeRecursive(const YGNodeRef root) { if (root->getConfig() != nullptr) { - gConfigInstanceCount--; delete root->getConfig(); + gConfigInstanceCount--; } // Delete configs recursively for childrens for (auto* child : root->getChildren()) { @@ -1068,8 +1070,6 @@ bool YGNodeLayoutGetDidLegacyStretchFlagAffectLayout(const YGNodeRef node) { return node->getLayout().doesLegacyStretchFlagAffectsLayout; } -uint32_t gCurrentGenerationCount = 0; - bool YGLayoutNodeInternal( const YGNodeRef node, const float availableWidth, @@ -1341,8 +1341,7 @@ static void YGNodeComputeFlexBasisForChild( if (child->getLayout().computedFlexBasis.isUndefined() || (YGConfigIsExperimentalFeatureEnabled( child->getConfig(), YGExperimentalFeatureWebFlexBasis) && - child->getLayout().computedFlexBasisGeneration != - gCurrentGenerationCount)) { + child->getLayout().computedFlexBasisGeneration != node->getRoot()->gCurrentGenerationCount)) { const YGFloatOptional& paddingAndBorder = YGFloatOptional( YGNodePaddingAndBorderForAxis(child, mainAxis, ownerWidth)); child->setLayoutComputedFlexBasis( @@ -1496,7 +1495,7 @@ static void YGNodeComputeFlexBasisForChild( child->getLayout().measuredDimensions[dim[mainAxis]], YGNodePaddingAndBorderForAxis(child, mainAxis, ownerWidth)))); } - child->setLayoutComputedFlexBasisGeneration(gCurrentGenerationCount); + child->setLayoutComputedFlexBasisGeneration(node->getRoot()->gCurrentGenerationCount); } static void YGNodeAbsoluteLayoutChild( @@ -1977,7 +1976,7 @@ static void YGNodeComputeFlexBasisForChildren( continue; } if (child == singleFlexChild) { - child->setLayoutComputedFlexBasisGeneration(gCurrentGenerationCount); + child->setLayoutComputedFlexBasisGeneration(node->getRoot()->gCurrentGenerationCount); child->setLayoutComputedFlexBasis(YGFloatOptional(0)); } else { YGNodeComputeFlexBasisForChild( @@ -3521,7 +3520,6 @@ static void YGNodelayoutImpl( } } -uint32_t gDepth = 0; bool gPrintTree = false; bool gPrintChanges = false; bool gPrintSkips = false; @@ -3711,10 +3709,10 @@ bool YGLayoutNodeInternal( const YGConfigRef config) { YGLayout* layout = &node->getLayout(); - gDepth++; + node->getRoot()->gDepth++; const bool needToVisitNode = - (node->isDirty() && layout->generationCount != gCurrentGenerationCount) || + (node->isDirty() && layout->generationCount != node->getRoot()->gCurrentGenerationCount) || layout->lastOwnerDirection != ownerDirection; if (needToVisitNode) { @@ -3816,8 +3814,8 @@ bool YGLayoutNodeInternal( node, YGLogLevelVerbose, "%s%d.{[skipped] ", - YGSpacer(gDepth), - gDepth); + YGSpacer(node->getRoot()->gDepth), + node->getRoot()->gDepth); if (node->getPrintFunc() != nullptr) { node->getPrintFunc()(node); } @@ -3839,8 +3837,8 @@ bool YGLayoutNodeInternal( node, YGLogLevelVerbose, "%s%d.{%s", - YGSpacer(gDepth), - gDepth, + YGSpacer(node->getRoot()->gDepth), + node->getRoot()->gDepth, needToVisitNode ? "*" : ""); if (node->getPrintFunc() != nullptr) { node->getPrintFunc()(node); @@ -3873,8 +3871,8 @@ bool YGLayoutNodeInternal( node, YGLogLevelVerbose, "%s%d.}%s", - YGSpacer(gDepth), - gDepth, + YGSpacer(node->getRoot()->gDepth), + node->getRoot()->gDepth, needToVisitNode ? "*" : ""); if (node->getPrintFunc() != nullptr) { node->getPrintFunc()(node); @@ -3934,8 +3932,8 @@ bool YGLayoutNodeInternal( node->setDirty(false); } - gDepth--; - layout->generationCount = gCurrentGenerationCount; + node->getRoot()->gDepth--; + layout->generationCount = node->getRoot()->gCurrentGenerationCount; return (needToVisitNode || cachedResults == nullptr); } @@ -4039,7 +4037,7 @@ void YGNodeCalculateLayout( // all dirty nodes at least once. Subsequent visits will be skipped if the // input // parameters don't change. - gCurrentGenerationCount++; + node->getRoot()->gCurrentGenerationCount++; node->resolveDimension(); float width = YGUndefined; YGMeasureMode widthMeasureMode = YGMeasureModeUndefined; @@ -4120,7 +4118,7 @@ void YGNodeCalculateLayout( originalNode->resolveDimension(); // Recursively mark nodes as dirty originalNode->markDirtyAndPropogateDownwards(); - gCurrentGenerationCount++; + node->getRoot()->gCurrentGenerationCount++; // Rerun the layout, and calculate the diff originalNode->setAndPropogateUseLegacyFlag(false); if (YGLayoutNodeInternal(