Addresses thread safety, GitHub issue #769. #855

Closed
jpap wants to merge 1 commits from issue-769-thread-safety into master
4 changed files with 130 additions and 60 deletions
Showing only changes of commit 13ebc70449 - Show all commits

View File

@@ -22,12 +22,8 @@ struct YGLayout {
bool doesLegacyStretchFlagAffectsLayout : 1; bool doesLegacyStretchFlagAffectsLayout : 1;
bool hadOverflow : 1; bool hadOverflow : 1;
uint32_t computedFlexBasisGeneration = 0;
YGFloatOptional computedFlexBasis = {}; YGFloatOptional computedFlexBasis = {};
// Instead of recomputing the entire layout every single time, we cache some
// information to break early when nothing changed
uint32_t generationCount = 0;
YGDirection lastOwnerDirection = (YGDirection) -1; YGDirection lastOwnerDirection = (YGDirection) -1;
uint32_t nextCachedMeasurementsIndex = 0; uint32_t nextCachedMeasurementsIndex = 0;

View File

@@ -189,11 +189,6 @@ void YGNode::setLayoutPosition(float position, int index) {
layout_.position[index] = position; layout_.position[index] = position;
} }
void YGNode::setLayoutComputedFlexBasisGeneration(
uint32_t computedFlexBasisGeneration) {
layout_.computedFlexBasisGeneration = computedFlexBasisGeneration;
}
void YGNode::setLayoutMeasuredDimension(float measuredDimension, int index) { void YGNode::setLayoutMeasuredDimension(float measuredDimension, int index) {
layout_.measuredDimensions[index] = measuredDimension; layout_.measuredDimensions[index] = measuredDimension;
} }

View File

@@ -239,8 +239,6 @@ public:
void setDirty(bool isDirty); void setDirty(bool isDirty);
void setLayoutLastOwnerDirection(YGDirection direction); void setLayoutLastOwnerDirection(YGDirection direction);
void setLayoutComputedFlexBasis(const YGFloatOptional computedFlexBasis); void setLayoutComputedFlexBasis(const YGFloatOptional computedFlexBasis);
void setLayoutComputedFlexBasisGeneration(
uint32_t computedFlexBasisGeneration);
void setLayoutMeasuredDimension(float measuredDimension, int index); void setLayoutMeasuredDimension(float measuredDimension, int index);
void setLayoutHadOverflow(bool hadOverflow); void setLayoutHadOverflow(bool hadOverflow);
void setLayoutDimension(float dimension, int index); void setLayoutDimension(float dimension, int index);

View File

@@ -8,6 +8,8 @@
#include <float.h> #include <float.h>
#include <string.h> #include <string.h>
#include <algorithm> #include <algorithm>
#include <map>
#include <atomic>
#include "Utils.h" #include "Utils.h"
#include "YGNode.h" #include "YGNode.h"
#include "YGNodePrint.h" #include "YGNodePrint.h"
@@ -25,6 +27,44 @@ __forceinline const float fmaxf(const float a, const float b) {
using namespace facebook::yoga; using namespace facebook::yoga;
// NodeActions tracks actions on a node.
typedef std::map<const YGNodeRef, uint8_t> NodeActions;
// Standard node actions.
typedef YG_ENUM_BEGIN(NodeAction){
NodeActionNone,
NodeActionDidVisit = 1 << 0,
NodeActionDidComputeFlexBasis = 1 << 1,
} YG_ENUM_END(NodeAction);
// NodeActionsMark marks an action against a node.
static void NodeActionsMark(NodeActions& nam, const YGNodeRef n, uint8_t mask) {
auto iter = nam.find(n);
if (iter != nam.end()) {
iter->second |= mask; // Update
}
else {
nam.insert(std::pair<const YGNodeRef, uint8_t>(n, mask)); // Create
}
}
// NodeActionsGet retrieves a mark against a node, or returns 0.
static uint8_t NodeActionsGet(NodeActions& nam, const YGNodeRef n) {
auto iter = nam.find(n);
return iter == nam.end() ? 0 : iter->second;
}
// Convenience macros for marking/getting actions against nodes.
#define NodeActionsDidVisit(nam, n) \
((NodeActionsGet(nam, n) & NodeActionDidVisit) != 0)
#define NodeActionsDidComputeFlexBasis(nam, n) \
((NodeActionsGet(nam, n) & NodeActionDidComputeFlexBasis) != 0)
#define NodeActionsMarkDidVisit(nam, n) \
NodeActionsMark(nam, n, NodeActionDidVisit)
#define NodeActionsMarkDidComputeFlexBasis(nam, n) \
NodeActionsMark(nam, n, NodeActionDidComputeFlexBasis)
#ifdef ANDROID #ifdef ANDROID
static int YGAndroidLog( static int YGAndroidLog(
const YGConfigRef config, const YGConfigRef config,
@@ -206,8 +246,8 @@ void YGNodeMarkDirtyAndPropogateToDescendants(const YGNodeRef node) {
return node->markDirtyAndPropogateDownwards(); return node->markDirtyAndPropogateDownwards();
} }
int32_t gNodeInstanceCount = 0; std::atomic<int32_t> gNodeInstanceCount(0);
int32_t gConfigInstanceCount = 0; std::atomic<int32_t> gConfigInstanceCount(0);
WIN_EXPORT YGNodeRef YGNodeNewWithConfig(const YGConfigRef config) { WIN_EXPORT YGNodeRef YGNodeNewWithConfig(const YGConfigRef config) {
const YGNodeRef node = new YGNode(); const YGNodeRef node = new YGNode();
@@ -1021,10 +1061,9 @@ bool YGNodeLayoutGetDidLegacyStretchFlagAffectLayout(const YGNodeRef node) {
return node->getLayout().doesLegacyStretchFlagAffectsLayout; return node->getLayout().doesLegacyStretchFlagAffectsLayout;
} }
uint32_t gCurrentGenerationCount = 0;
bool YGLayoutNodeInternal( bool YGLayoutNodeInternal(
const YGNodeRef node, const YGNodeRef node,
int depth,
const float availableWidth, const float availableWidth,
const float availableHeight, const float availableHeight,
const YGDirection ownerDirection, const YGDirection ownerDirection,
@@ -1034,7 +1073,8 @@ bool YGLayoutNodeInternal(
const float ownerHeight, const float ownerHeight,
const bool performLayout, const bool performLayout,
const char* reason, const char* reason,
const YGConfigRef config); const YGConfigRef config,
NodeActions& nodeActions);
static void YGNodePrintInternal( static void YGNodePrintInternal(
const YGNodeRef node, const YGNodeRef node,
@@ -1265,6 +1305,7 @@ static void YGConstrainMaxSizeForMode(
static void YGNodeComputeFlexBasisForChild( static void YGNodeComputeFlexBasisForChild(
const YGNodeRef node, const YGNodeRef node,
int depth,
const YGNodeRef child, const YGNodeRef child,
const float width, const float width,
const YGMeasureMode widthMode, const YGMeasureMode widthMode,
@@ -1273,7 +1314,8 @@ static void YGNodeComputeFlexBasisForChild(
const float ownerHeight, const float ownerHeight,
const YGMeasureMode heightMode, const YGMeasureMode heightMode,
const YGDirection direction, const YGDirection direction,
const YGConfigRef config) { const YGConfigRef config,
NodeActions& nodeActions) {
const YGFlexDirection mainAxis = const YGFlexDirection mainAxis =
YGResolveFlexDirection(node->getStyle().flexDirection, direction); YGResolveFlexDirection(node->getStyle().flexDirection, direction);
const bool isMainAxisRow = YGFlexDirectionIsRow(mainAxis); const bool isMainAxisRow = YGFlexDirectionIsRow(mainAxis);
@@ -1296,8 +1338,7 @@ static void YGNodeComputeFlexBasisForChild(
if (child->getLayout().computedFlexBasis.isUndefined() || if (child->getLayout().computedFlexBasis.isUndefined() ||
(YGConfigIsExperimentalFeatureEnabled( (YGConfigIsExperimentalFeatureEnabled(
child->getConfig(), YGExperimentalFeatureWebFlexBasis) && child->getConfig(), YGExperimentalFeatureWebFlexBasis) &&
child->getLayout().computedFlexBasisGeneration != !NodeActionsDidComputeFlexBasis(nodeActions, child))) {
gCurrentGenerationCount)) {
const YGFloatOptional paddingAndBorder = YGFloatOptional( const YGFloatOptional paddingAndBorder = YGFloatOptional(
YGNodePaddingAndBorderForAxis(child, mainAxis, ownerWidth)); YGNodePaddingAndBorderForAxis(child, mainAxis, ownerWidth));
child->setLayoutComputedFlexBasis( child->setLayoutComputedFlexBasis(
@@ -1437,6 +1478,7 @@ static void YGNodeComputeFlexBasisForChild(
// Measure the child // Measure the child
YGLayoutNodeInternal( YGLayoutNodeInternal(
child, child,
depth,
childWidth, childWidth,
childHeight, childHeight,
direction, direction,
@@ -1446,23 +1488,26 @@ static void YGNodeComputeFlexBasisForChild(
ownerHeight, ownerHeight,
false, false,
"measure", "measure",
config); config,
nodeActions);
child->setLayoutComputedFlexBasis(YGFloatOptional(YGFloatMax( child->setLayoutComputedFlexBasis(YGFloatOptional(YGFloatMax(
child->getLayout().measuredDimensions[dim[mainAxis]], child->getLayout().measuredDimensions[dim[mainAxis]],
YGNodePaddingAndBorderForAxis(child, mainAxis, ownerWidth)))); YGNodePaddingAndBorderForAxis(child, mainAxis, ownerWidth))));
} }
child->setLayoutComputedFlexBasisGeneration(gCurrentGenerationCount); NodeActionsMarkDidComputeFlexBasis(nodeActions, child);
} }
static void YGNodeAbsoluteLayoutChild( static void YGNodeAbsoluteLayoutChild(
const YGNodeRef node, const YGNodeRef node,
int depth,
const YGNodeRef child, const YGNodeRef child,
const float width, const float width,
const YGMeasureMode widthMode, const YGMeasureMode widthMode,
const float height, const float height,
const YGDirection direction, const YGDirection direction,
const YGConfigRef config) { const YGConfigRef config,
NodeActions& nodeActions) {
const YGFlexDirection mainAxis = const YGFlexDirection mainAxis =
YGResolveFlexDirection(node->getStyle().flexDirection, direction); YGResolveFlexDirection(node->getStyle().flexDirection, direction);
const YGFlexDirection crossAxis = YGFlexDirectionCross(mainAxis, direction); const YGFlexDirection crossAxis = YGFlexDirectionCross(mainAxis, direction);
@@ -1557,6 +1602,7 @@ static void YGNodeAbsoluteLayoutChild(
YGLayoutNodeInternal( YGLayoutNodeInternal(
child, child,
depth,
childWidth, childWidth,
childHeight, childHeight,
direction, direction,
@@ -1566,7 +1612,8 @@ static void YGNodeAbsoluteLayoutChild(
childHeight, childHeight,
false, false,
"abs-measure", "abs-measure",
config); config,
nodeActions);
childWidth = child->getLayout().measuredDimensions[YGDimensionWidth] + childWidth = child->getLayout().measuredDimensions[YGDimensionWidth] +
child->getMarginForAxis(YGFlexDirectionRow, width).unwrap(); child->getMarginForAxis(YGFlexDirectionRow, width).unwrap();
childHeight = child->getLayout().measuredDimensions[YGDimensionHeight] + childHeight = child->getLayout().measuredDimensions[YGDimensionHeight] +
@@ -1575,6 +1622,7 @@ static void YGNodeAbsoluteLayoutChild(
YGLayoutNodeInternal( YGLayoutNodeInternal(
child, child,
depth,
childWidth, childWidth,
childHeight, childHeight,
direction, direction,
@@ -1584,7 +1632,8 @@ static void YGNodeAbsoluteLayoutChild(
childHeight, childHeight,
true, true,
"abs-layout", "abs-layout",
config); config,
nodeActions);
if (child->isTrailingPosDefined(mainAxis) && if (child->isTrailingPosDefined(mainAxis) &&
!child->isLeadingPositionDefined(mainAxis)) { !child->isLeadingPositionDefined(mainAxis)) {
@@ -1873,6 +1922,7 @@ static float YGNodeCalculateAvailableInnerDim(
static float YGNodeComputeFlexBasisForChildren( static float YGNodeComputeFlexBasisForChildren(
const YGNodeRef node, const YGNodeRef node,
int depth,
const float availableInnerWidth, const float availableInnerWidth,
const float availableInnerHeight, const float availableInnerHeight,
YGMeasureMode widthMeasureMode, YGMeasureMode widthMeasureMode,
@@ -1880,7 +1930,8 @@ static float YGNodeComputeFlexBasisForChildren(
YGDirection direction, YGDirection direction,
YGFlexDirection mainAxis, YGFlexDirection mainAxis,
const YGConfigRef config, const YGConfigRef config,
bool performLayout) { bool performLayout,
NodeActions& nodeActions) {
float totalOuterFlexBasis = 0.0f; float totalOuterFlexBasis = 0.0f;
YGNodeRef singleFlexChild = nullptr; YGNodeRef singleFlexChild = nullptr;
YGVector children = node->getChildren(); YGVector children = node->getChildren();
@@ -1931,11 +1982,12 @@ static float YGNodeComputeFlexBasisForChildren(
continue; continue;
} }
if (child == singleFlexChild) { if (child == singleFlexChild) {
child->setLayoutComputedFlexBasisGeneration(gCurrentGenerationCount); NodeActionsMarkDidComputeFlexBasis(nodeActions, child);
child->setLayoutComputedFlexBasis(YGFloatOptional(0)); child->setLayoutComputedFlexBasis(YGFloatOptional(0));
} else { } else {
YGNodeComputeFlexBasisForChild( YGNodeComputeFlexBasisForChild(
node, node,
depth,
child, child,
availableInnerWidth, availableInnerWidth,
widthMeasureMode, widthMeasureMode,
@@ -1944,7 +1996,8 @@ static float YGNodeComputeFlexBasisForChildren(
availableInnerHeight, availableInnerHeight,
heightMeasureMode, heightMeasureMode,
direction, direction,
config); config,
nodeActions);
} }
totalOuterFlexBasis += totalOuterFlexBasis +=
@@ -2046,6 +2099,7 @@ static YGCollectFlexItemsRowValues YGCalculateCollectFlexItemsRowValues(
static float YGDistributeFreeSpaceSecondPass( static float YGDistributeFreeSpaceSecondPass(
YGCollectFlexItemsRowValues& collectedFlexItemsValues, YGCollectFlexItemsRowValues& collectedFlexItemsValues,
const YGNodeRef node, const YGNodeRef node,
int depth,
const YGFlexDirection mainAxis, const YGFlexDirection mainAxis,
const YGFlexDirection crossAxis, const YGFlexDirection crossAxis,
const float mainAxisownerSize, const float mainAxisownerSize,
@@ -2056,7 +2110,8 @@ static float YGDistributeFreeSpaceSecondPass(
const bool flexBasisOverflows, const bool flexBasisOverflows,
const YGMeasureMode measureModeCrossDim, const YGMeasureMode measureModeCrossDim,
const bool performLayout, const bool performLayout,
const YGConfigRef config) { const YGConfigRef config,
NodeActions& nodeActions) {
float childFlexBasis = 0; float childFlexBasis = 0;
float flexShrinkScaledFactor = 0; float flexShrinkScaledFactor = 0;
float flexGrowFactor = 0; float flexGrowFactor = 0;
@@ -2211,6 +2266,7 @@ static float YGDistributeFreeSpaceSecondPass(
// main size. // main size.
YGLayoutNodeInternal( YGLayoutNodeInternal(
currentRelativeChild, currentRelativeChild,
depth,
childWidth, childWidth,
childHeight, childHeight,
node->getLayout().direction, node->getLayout().direction,
@@ -2220,7 +2276,8 @@ static float YGDistributeFreeSpaceSecondPass(
availableInnerHeight, availableInnerHeight,
performLayout && !requiresStretchLayout, performLayout && !requiresStretchLayout,
"flex", "flex",
config); config,
nodeActions);
node->setLayoutHadOverflow( node->setLayoutHadOverflow(
node->getLayout().hadOverflow | node->getLayout().hadOverflow |
currentRelativeChild->getLayout().hadOverflow); currentRelativeChild->getLayout().hadOverflow);
@@ -2338,6 +2395,7 @@ static void YGDistributeFreeSpaceFirstPass(
// //
static void YGResolveFlexibleLength( static void YGResolveFlexibleLength(
const YGNodeRef node, const YGNodeRef node,
int depth,
YGCollectFlexItemsRowValues& collectedFlexItemsValues, YGCollectFlexItemsRowValues& collectedFlexItemsValues,
const YGFlexDirection mainAxis, const YGFlexDirection mainAxis,
const YGFlexDirection crossAxis, const YGFlexDirection crossAxis,
@@ -2349,7 +2407,8 @@ static void YGResolveFlexibleLength(
const bool flexBasisOverflows, const bool flexBasisOverflows,
const YGMeasureMode measureModeCrossDim, const YGMeasureMode measureModeCrossDim,
const bool performLayout, const bool performLayout,
const YGConfigRef config) { const YGConfigRef config,
NodeActions& nodeActions) {
const float originalFreeSpace = collectedFlexItemsValues.remainingFreeSpace; const float originalFreeSpace = collectedFlexItemsValues.remainingFreeSpace;
// First pass: detect the flex items whose min/max constraints trigger // First pass: detect the flex items whose min/max constraints trigger
YGDistributeFreeSpaceFirstPass( YGDistributeFreeSpaceFirstPass(
@@ -2363,6 +2422,7 @@ static void YGResolveFlexibleLength(
const float distributedFreeSpace = YGDistributeFreeSpaceSecondPass( const float distributedFreeSpace = YGDistributeFreeSpaceSecondPass(
collectedFlexItemsValues, collectedFlexItemsValues,
node, node,
depth,
mainAxis, mainAxis,
crossAxis, crossAxis,
mainAxisownerSize, mainAxisownerSize,
@@ -2373,7 +2433,8 @@ static void YGResolveFlexibleLength(
flexBasisOverflows, flexBasisOverflows,
measureModeCrossDim, measureModeCrossDim,
performLayout, performLayout,
config); config,
nodeActions);
collectedFlexItemsValues.remainingFreeSpace = collectedFlexItemsValues.remainingFreeSpace =
originalFreeSpace - distributedFreeSpace; originalFreeSpace - distributedFreeSpace;
@@ -2661,6 +2722,7 @@ static void YGJustifyMainAxis(
// //
static void YGNodelayoutImpl( static void YGNodelayoutImpl(
const YGNodeRef node, const YGNodeRef node,
int depth,
const float availableWidth, const float availableWidth,
const float availableHeight, const float availableHeight,
const YGDirection ownerDirection, const YGDirection ownerDirection,
@@ -2669,7 +2731,8 @@ static void YGNodelayoutImpl(
const float ownerWidth, const float ownerWidth,
const float ownerHeight, const float ownerHeight,
const bool performLayout, const bool performLayout,
const YGConfigRef config) { const YGConfigRef config,
NodeActions& nodeActions) {
YGAssertWithNode( YGAssertWithNode(
node, node,
YGFloatIsUndefined(availableWidth) YGFloatIsUndefined(availableWidth)
@@ -2843,6 +2906,7 @@ static void YGNodelayoutImpl(
float totalOuterFlexBasis = YGNodeComputeFlexBasisForChildren( float totalOuterFlexBasis = YGNodeComputeFlexBasisForChildren(
node, node,
depth,
availableInnerWidth, availableInnerWidth,
availableInnerHeight, availableInnerHeight,
widthMeasureMode, widthMeasureMode,
@@ -2850,7 +2914,8 @@ static void YGNodelayoutImpl(
direction, direction,
mainAxis, mainAxis,
config, config,
performLayout); performLayout,
nodeActions);
const bool flexBasisOverflows = measureModeMainDim == YGMeasureModeUndefined const bool flexBasisOverflows = measureModeMainDim == YGMeasureModeUndefined
? false ? false
@@ -2945,6 +3010,7 @@ static void YGNodelayoutImpl(
if (!canSkipFlex) { if (!canSkipFlex) {
YGResolveFlexibleLength( YGResolveFlexibleLength(
node, node,
depth,
collectedFlexItemsValues, collectedFlexItemsValues,
mainAxis, mainAxis,
crossAxis, crossAxis,
@@ -2956,7 +3022,8 @@ static void YGNodelayoutImpl(
flexBasisOverflows, flexBasisOverflows,
measureModeCrossDim, measureModeCrossDim,
performLayout, performLayout,
config); config,
nodeActions);
} }
node->setLayoutHadOverflow( node->setLayoutHadOverflow(
@@ -3112,6 +3179,7 @@ static void YGNodelayoutImpl(
YGLayoutNodeInternal( YGLayoutNodeInternal(
child, child,
depth,
childWidth, childWidth,
childHeight, childHeight,
direction, direction,
@@ -3121,7 +3189,8 @@ static void YGNodelayoutImpl(
availableInnerHeight, availableInnerHeight,
true, true,
"stretch", "stretch",
config); config,
nodeActions);
} }
} else { } else {
const float remainingCrossDim = containerCrossAxis - const float remainingCrossDim = containerCrossAxis -
@@ -3318,6 +3387,7 @@ static void YGNodelayoutImpl(
.measuredDimensions[YGDimensionHeight]))) { .measuredDimensions[YGDimensionHeight]))) {
YGLayoutNodeInternal( YGLayoutNodeInternal(
child, child,
depth,
childWidth, childWidth,
childHeight, childHeight,
direction, direction,
@@ -3327,7 +3397,8 @@ static void YGNodelayoutImpl(
availableInnerHeight, availableInnerHeight,
true, true,
"multiline-stretch", "multiline-stretch",
config); config,
nodeActions);
} }
} }
break; break;
@@ -3459,12 +3530,14 @@ static void YGNodelayoutImpl(
} }
YGNodeAbsoluteLayoutChild( YGNodeAbsoluteLayoutChild(
node, node,
depth,
child, child,
availableInnerWidth, availableInnerWidth,
isMainAxisRow ? measureModeMainDim : measureModeCrossDim, isMainAxisRow ? measureModeMainDim : measureModeCrossDim,
availableInnerHeight, availableInnerHeight,
direction, direction,
config); config,
nodeActions);
} }
// STEP 11: SETTING TRAILING POSITIONS FOR CHILDREN // STEP 11: SETTING TRAILING POSITIONS FOR CHILDREN
@@ -3492,9 +3565,8 @@ static void YGNodelayoutImpl(
} }
} }
uint32_t gDepth = 0; const bool gPrintChanges = false;
bool gPrintChanges = false; const bool gPrintSkips = false;
bool gPrintSkips = false;
static const char* spacer = static const char* spacer =
" "; " ";
@@ -3687,6 +3759,7 @@ bool YGNodeCanUseCachedMeasurement(
// //
bool YGLayoutNodeInternal( bool YGLayoutNodeInternal(
const YGNodeRef node, const YGNodeRef node,
int depth,
const float availableWidth, const float availableWidth,
const float availableHeight, const float availableHeight,
const YGDirection ownerDirection, const YGDirection ownerDirection,
@@ -3696,13 +3769,16 @@ bool YGLayoutNodeInternal(
const float ownerHeight, const float ownerHeight,
const bool performLayout, const bool performLayout,
const char* reason, const char* reason,
const YGConfigRef config) { const YGConfigRef config,
NodeActions& nodeActions) {
YGLayout* layout = &node->getLayout(); YGLayout* layout = &node->getLayout();
gDepth++; if (gPrintChanges) {
depth++;
}
const bool needToVisitNode = const bool needToVisitNode =
(node->isDirty() && layout->generationCount != gCurrentGenerationCount) || (node->isDirty() && !NodeActionsDidVisit(nodeActions, node)) ||
layout->lastOwnerDirection != ownerDirection; layout->lastOwnerDirection != ownerDirection;
if (needToVisitNode) { if (needToVisitNode) {
@@ -3800,8 +3876,8 @@ bool YGLayoutNodeInternal(
node, node,
YGLogLevelVerbose, YGLogLevelVerbose,
"%s%d.{[skipped] ", "%s%d.{[skipped] ",
YGSpacer(gDepth), YGSpacer(depth),
gDepth); depth);
if (node->getPrintFunc() != nullptr) { if (node->getPrintFunc() != nullptr) {
node->getPrintFunc()(node); node->getPrintFunc()(node);
} }
@@ -3823,8 +3899,8 @@ bool YGLayoutNodeInternal(
node, node,
YGLogLevelVerbose, YGLogLevelVerbose,
"%s%d.{%s", "%s%d.{%s",
YGSpacer(gDepth), YGSpacer(depth),
gDepth, depth,
needToVisitNode ? "*" : ""); needToVisitNode ? "*" : "");
if (node->getPrintFunc() != nullptr) { if (node->getPrintFunc() != nullptr) {
node->getPrintFunc()(node); node->getPrintFunc()(node);
@@ -3842,6 +3918,7 @@ bool YGLayoutNodeInternal(
YGNodelayoutImpl( YGNodelayoutImpl(
node, node,
depth,
availableWidth, availableWidth,
availableHeight, availableHeight,
ownerDirection, ownerDirection,
@@ -3850,15 +3927,16 @@ bool YGLayoutNodeInternal(
ownerWidth, ownerWidth,
ownerHeight, ownerHeight,
performLayout, performLayout,
config); config,
nodeActions);
if (gPrintChanges) { if (gPrintChanges) {
YGLog( YGLog(
node, node,
YGLogLevelVerbose, YGLogLevelVerbose,
"%s%d.}%s", "%s%d.}%s",
YGSpacer(gDepth), YGSpacer(depth),
gDepth, depth,
needToVisitNode ? "*" : ""); needToVisitNode ? "*" : "");
if (node->getPrintFunc() != nullptr) { if (node->getPrintFunc() != nullptr) {
node->getPrintFunc()(node); node->getPrintFunc()(node);
@@ -3918,8 +3996,10 @@ bool YGLayoutNodeInternal(
node->setDirty(false); node->setDirty(false);
} }
gDepth--; if (gPrintChanges) {
layout->generationCount = gCurrentGenerationCount; depth--;
}
NodeActionsMarkDidVisit(nodeActions, node);
return (needToVisitNode || cachedResults == nullptr); return (needToVisitNode || cachedResults == nullptr);
} }
@@ -4018,10 +4098,7 @@ void YGNodeCalculateLayout(
const float ownerWidth, const float ownerWidth,
const float ownerHeight, const float ownerHeight,
const YGDirection ownerDirection) { const YGDirection ownerDirection) {
// Increment the generation count. This will force the recursive routine to NodeActions nodeActions;
// visit all dirty nodes at least once. Subsequent visits will be skipped if
// the input parameters don't change.
gCurrentGenerationCount++;
node->resolveDimension(); node->resolveDimension();
float width = YGUndefined; float width = YGUndefined;
YGMeasureMode widthMeasureMode = YGMeasureModeUndefined; YGMeasureMode widthMeasureMode = YGMeasureModeUndefined;
@@ -4069,6 +4146,7 @@ void YGNodeCalculateLayout(
} }
if (YGLayoutNodeInternal( if (YGLayoutNodeInternal(
node, node,
0, // tree root depth
width, width,
height, height,
ownerDirection, ownerDirection,
@@ -4078,7 +4156,8 @@ void YGNodeCalculateLayout(
ownerHeight, ownerHeight,
true, true,
"initial", "initial",
node->getConfig())) { node->getConfig(),
nodeActions)) {
node->setPosition( node->setPosition(
node->getLayout().direction, ownerWidth, ownerHeight, ownerWidth); node->getLayout().direction, ownerWidth, ownerHeight, ownerWidth);
YGRoundToPixelGrid(node, node->getConfig()->pointScaleFactor, 0.0f, 0.0f); YGRoundToPixelGrid(node, node->getConfig()->pointScaleFactor, 0.0f, 0.0f);
@@ -4103,13 +4182,14 @@ void YGNodeCalculateLayout(
node->didUseLegacyFlag()) { node->didUseLegacyFlag()) {
const YGNodeRef originalNode = YGNodeDeepClone(node); const YGNodeRef originalNode = YGNodeDeepClone(node);
originalNode->resolveDimension(); originalNode->resolveDimension();
// Recursively mark nodes as dirty // Start over: recursively mark nodes as dirty and clear node actions.
originalNode->markDirtyAndPropogateDownwards(); originalNode->markDirtyAndPropogateDownwards();
gCurrentGenerationCount++; nodeActions.clear();
// Rerun the layout, and calculate the diff // Rerun the layout, and calculate the diff
originalNode->setAndPropogateUseLegacyFlag(false); originalNode->setAndPropogateUseLegacyFlag(false);
if (YGLayoutNodeInternal( if (YGLayoutNodeInternal(
originalNode, originalNode,
0, // tree root depth
width, width,
height, height,
ownerDirection, ownerDirection,
@@ -4119,7 +4199,8 @@ void YGNodeCalculateLayout(
ownerHeight, ownerHeight,
true, true,
"initial", "initial",
originalNode->getConfig())) { originalNode->getConfig(),
nodeActions)) {
originalNode->setPosition( originalNode->setPosition(
originalNode->getLayout().direction, originalNode->getLayout().direction,
ownerWidth, ownerWidth,