Skip to content
Permalink
Browse files

Remove the use of legacy flag and log the diff if its used

Reviewed By: emilsjolander

Differential Revision: D6856812

fbshipit-source-id: e4724d80702cc75c1894e348e137b24e663573d2
  • Loading branch information...
priteshrnandgaonkar authored and facebook-github-bot committed Feb 2, 2018
1 parent 752427b commit 9f7cedbe14321d24b7aee1ba969b3d23d5c9d204
@@ -572,6 +572,13 @@ void YGNode::markDirtyAndPropogate() {
}
}

void YGNode::markDirtyAndPropogateDownwards() {
isDirty_ = true;
for_each(children_.begin(), children_.end(), [](YGNodeRef childNode) {
childNode->markDirtyAndPropogateDownwards();
});
}

float YGNode::resolveFlexGrow() {
// Root nodes flexGrow should always be 0
if (parent_ == nullptr) {
@@ -666,3 +673,57 @@ float YGNode::getLeadingPaddingAndBorder(
const float widthSize) {
return getLeadingPadding(axis, widthSize) + getLeadingBorder(axis);
}

bool YGNode::didUseLegacyFlag() {
bool didUseLegacyFlag = layout_.didUseLegacyFlag;
if (didUseLegacyFlag) {
return true;
}
for (const auto& child : children_) {
if (child->layout_.didUseLegacyFlag) {
didUseLegacyFlag = true;
break;
}
}
return didUseLegacyFlag;
}

void YGNode::setAndPropogateUseLegacyFlag(bool useLegacyFlag) {
config_->useLegacyStretchBehaviour = useLegacyFlag;
for_each(children_.begin(), children_.end(), [=](YGNodeRef childNode) {
childNode->getConfig()->useLegacyStretchBehaviour = useLegacyFlag;
});
}

void YGNode::setLayoutDoesLegacyFlagAffectsLayout(
bool doesLegacyFlagAffectsLayout) {
layout_.doesLegacyStretchFlagAffectsLayout = doesLegacyFlagAffectsLayout;
}

void YGNode::setLayoutDidUseLegacyFlag(bool didUseLegacyFlag) {
layout_.didUseLegacyFlag = didUseLegacyFlag;
}

bool YGNode::isLayoutTreeEqualToNode(const YGNode& node) const {
if (children_.size() != node.children_.size()) {
return false;
}
if (layout_ != node.layout_) {
return false;
}
if (children_.size() == 0) {
return true;
}

bool isLayoutTreeEqual = true;
YGNodeRef otherNodeChildren = nullptr;
for (std::vector<YGNodeRef>::size_type i = 0; i < children_.size(); ++i) {
otherNodeChildren = node.children_[i];
isLayoutTreeEqual =
children_[i]->isLayoutTreeEqualToNode(*otherNodeChildren);
if (!isLayoutTreeEqual) {
return false;
}
}
return isLayoutTreeEqual;
}
@@ -129,6 +129,10 @@ struct YGNode {
const float mainSize,
const float crossSize,
const float parentWidth);
void setAndPropogateUseLegacyFlag(bool useLegacyFlag);
void setLayoutDoesLegacyFlagAffectsLayout(bool doesLegacyFlagAffectsLayout);
void setLayoutDidUseLegacyFlag(bool didUseLegacyFlag);
void markDirtyAndPropogateDownwards();

// Other methods
YGValue marginLeadingValue(const YGFlexDirection axis) const;
@@ -150,4 +154,6 @@ struct YGNode {
float resolveFlexGrow();
float resolveFlexShrink();
bool isNodeFlexible();
bool didUseLegacyFlag();
bool isLayoutTreeEqualToNode(const YGNode& node) const;
};
@@ -44,15 +44,43 @@ bool YGValueArrayEqual(
return areEqual;
}

typedef struct YGCachedMeasurement {
struct YGCachedMeasurement {
float availableWidth;
float availableHeight;
YGMeasureMode widthMeasureMode;
YGMeasureMode heightMeasureMode;

float computedWidth;
float computedHeight;
} YGCachedMeasurement;

bool operator==(YGCachedMeasurement measurement) const {
bool isEqual = widthMeasureMode == measurement.widthMeasureMode &&
heightMeasureMode == measurement.heightMeasureMode;

if (!std::isnan(availableWidth) ||
!std::isnan(measurement.availableWidth)) {
isEqual = isEqual && availableWidth == measurement.availableWidth;
}
if (!std::isnan(availableHeight) ||
!std::isnan(measurement.availableHeight)) {
isEqual = isEqual && availableHeight == measurement.availableHeight;
}
if (!std::isnan(computedWidth) || !std::isnan(measurement.computedWidth)) {
isEqual = isEqual && computedWidth == measurement.computedWidth;
}
if (!std::isnan(
computedHeight || !std::isnan(measurement.computedHeight))) {
isEqual = isEqual && computedHeight == measurement.computedHeight;
}

return availableWidth == measurement.availableWidth &&
availableHeight == measurement.availableHeight &&
widthMeasureMode == measurement.widthMeasureMode &&
heightMeasureMode == measurement.heightMeasureMode &&
computedWidth == measurement.computedWidth &&
computedHeight == measurement.computedHeight;
}
};

// This value was chosen based on empiracle data. Even the most complicated
// layouts should not require more than 16 entries to fit within the cache.
@@ -80,6 +108,44 @@ struct YGLayout {
std::array<float, 2> measuredDimensions;

YGCachedMeasurement cachedLayout;
bool didUseLegacyFlag;
bool doesLegacyStretchFlagAffectsLayout;

bool operator==(YGLayout layout) const {
bool isEqual = position == layout.position &&
dimensions == layout.dimensions && margin == layout.margin &&
border == layout.border && padding == layout.padding &&
direction == layout.direction && hadOverflow == layout.hadOverflow &&
lastParentDirection == layout.lastParentDirection &&
nextCachedMeasurementsIndex == layout.nextCachedMeasurementsIndex &&
cachedLayout == layout.cachedLayout;

for (uint32_t i = 0; i < YG_MAX_CACHED_RESULT_COUNT && isEqual; ++i) {
isEqual =
isEqual && cachedMeasurements[i] == layout.cachedMeasurements[i];
}

if (!YGFloatIsUndefined(computedFlexBasis) ||
!YGFloatIsUndefined(layout.computedFlexBasis)) {
isEqual = isEqual && (computedFlexBasis == layout.computedFlexBasis);
}
if (!YGFloatIsUndefined(measuredDimensions[0]) ||
!YGFloatIsUndefined(layout.measuredDimensions[0])) {
isEqual =
isEqual && (measuredDimensions[0] == layout.measuredDimensions[0]);
}
if (!YGFloatIsUndefined(measuredDimensions[1]) ||
!YGFloatIsUndefined(layout.measuredDimensions[1])) {
isEqual =
isEqual && (measuredDimensions[1] == layout.measuredDimensions[1]);
}

return isEqual;
}

bool operator!=(YGLayout layout) const {
return !(*this == layout);
}
};

struct YGStyle {
@@ -150,15 +216,15 @@ struct YGStyle {
}
};

typedef struct YGConfig {
struct YGConfig {
bool experimentalFeatures[YGExperimentalFeatureCount + 1];
bool useWebDefaults;
bool useLegacyStretchBehaviour;
float pointScaleFactor;
YGLogger logger;
YGNodeClonedFunc cloneNodeCallback;
void* context;
} YGConfig;
};

#define YG_UNDEFINED_VALUES \
{ .value = YGUndefined, .unit = YGUnitUndefined }
@@ -272,6 +338,8 @@ static const YGLayout gYGNodeLayoutDefaults = {
.computedWidth = -1,
.computedHeight = -1,
},
.didUseLegacyFlag = false,
.doesLegacyStretchFlagAffectsLayout = false,
};

extern bool YGFloatsEqual(const float a, const float b);
@@ -211,6 +211,10 @@ bool YGNodeIsDirty(YGNodeRef node) {
return node->isDirty();
}

bool YGNodeLayoutGetDidUseLegacyFlag(const YGNodeRef node) {
return node->didUseLegacyFlag();
}

int32_t gNodeInstanceCount = 0;
int32_t gConfigInstanceCount = 0;

@@ -243,6 +247,29 @@ YGNodeRef YGNodeClone(YGNodeRef oldNode) {
return node;
}

static YGNodeRef YGNodeDeepClone(YGNodeRef oldNode) {
YGNodeRef node = YGNodeClone(oldNode);
YGVector vec = YGVector();
vec.reserve(oldNode->getChildren().size());
YGNodeRef childNode = nullptr;
for (auto& item : oldNode->getChildren()) {
childNode = YGNodeDeepClone(item);
childNode->setParent(node);
vec.push_back(childNode);
}
node->setChildren(vec);

if (oldNode->getNextChild() != nullptr) {
node->setNextChild(YGNodeDeepClone(oldNode->getNextChild()));
}

if (node->getConfig() != nullptr) {
node->setConfig(new YGConfig(*node->getConfig()));
}

return node;
}

void YGNodeFree(const YGNodeRef node) {
if (node->getParent()) {
node->getParent()->removeChild(node);
@@ -1975,10 +2002,15 @@ static void YGNodelayoutImpl(const YGNodeRef node,
} else {
if (!node->getConfig()->useLegacyStretchBehaviour &&
(totalFlexGrowFactors == 0 || node->resolveFlexGrow() == 0)) {
// If we don't have any children to flex or we can't flex the node itself,
// space we've used is all space we need. Root node also should be shrunk to minimum
// If we don't have any children to flex or we can't flex the node
// itself, space we've used is all space we need. Root node also
// should be shrunk to minimum
availableInnerMainDim = sizeConsumedOnCurrentLine;
}

if (node->getConfig()->useLegacyStretchBehaviour) {
node->setLayoutDidUseLegacyFlag(true);
}
sizeBasedOnContent = !node->getConfig()->useLegacyStretchBehaviour;
}
}
@@ -3330,7 +3362,6 @@ void YGNodeCalculateLayout(const YGNodeRef node,
// input
// parameters don't change.
gCurrentGenerationCount++;

node->resolveDimension();
float width = YGUndefined;
YGMeasureMode widthMeasureMode = YGMeasureModeUndefined;
@@ -3396,6 +3427,59 @@ void YGNodeCalculateLayout(const YGNodeRef node,
YGPrintOptionsStyle));
}
}

bool didUseLegacyFlag = node->didUseLegacyFlag();

// We want to get rid off `useLegacyStretchBehaviour` from YGConfig. But we
// aren't sure whether client's of yoga have gotten rid off this flag or not.
// So logging this in YGLayout would help to find out the call sites depending
// on this flag. This check would be removed once we are sure no one is
// dependent on this flag anymore.
if (didUseLegacyFlag) {
const YGNodeRef originalNode = YGNodeDeepClone(node);
originalNode->resolveDimension();
// Recursively mark nodes as dirty
originalNode->markDirtyAndPropogateDownwards();
gCurrentGenerationCount++;
// Rerun the layout, and calculate the diff
originalNode->setAndPropogateUseLegacyFlag(false);
if (YGLayoutNodeInternal(
originalNode,
width,
height,
parentDirection,
widthMeasureMode,
heightMeasureMode,
parentWidth,
parentHeight,
true,
"initial",
originalNode->getConfig())) {
originalNode->setPosition(
originalNode->getLayout().direction,
parentWidth,
parentHeight,
parentWidth);
YGRoundToPixelGrid(
originalNode,
originalNode->getConfig()->pointScaleFactor,
0.0f,
0.0f);

// Set whether the two layouts are different or not.
node->setLayoutDoesLegacyFlagAffectsLayout(
!originalNode->isLayoutTreeEqualToNode(*node));

if (gPrintTree) {
YGNodePrint(
originalNode,
(YGPrintOptions)(
YGPrintOptionsLayout | YGPrintOptionsChildren |
YGPrintOptionsStyle));
}
}
YGNodeFreeRecursive(originalNode);
}
}

void YGConfigSetLogger(const YGConfigRef config, YGLogger logger) {
@@ -175,6 +175,7 @@ void YGNodeSetHasNewLayout(YGNodeRef node, bool hasNewLayout);
YGNodeType YGNodeGetNodeType(YGNodeRef node);
void YGNodeSetNodeType(YGNodeRef node, YGNodeType nodeType);
bool YGNodeIsDirty(YGNodeRef node);
bool YGNodeLayoutGetDidUseLegacyFlag(const YGNodeRef node);

YG_NODE_STYLE_PROPERTY(YGDirection, Direction, direction);
YG_NODE_STYLE_PROPERTY(YGFlexDirection, FlexDirection, flexDirection);

0 comments on commit 9f7cedb

Please sign in to comment.
You can’t perform that action at this time.