Do not mark node as dirty if, new and old values are undefined

Summary:
If we have a values already set to undefined and set it to undefined again, we invalidate the layout. This change takes this case into account and keeps the layout valid.
Fixes #630
Closes https://github.com/facebook/yoga/pull/648

Differential Revision: D6408013

Pulled By: emilsjolander

fbshipit-source-id: dc2a848d84d3de9f4650fac9e41d7c8169446406
This commit is contained in:
Lukas Wöhrl
2017-11-27 03:06:15 -08:00
committed by Facebook Github Bot
parent 55c767ba7f
commit 5aa0f44a9b
2 changed files with 128 additions and 80 deletions

View File

@@ -142,3 +142,20 @@ TEST(YogaTest, dirty_node_only_if_children_are_actually_removed) {
YGNodeFreeRecursive(root); YGNodeFreeRecursive(root);
} }
TEST(YogaTest, dirty_node_only_if_undefined_values_gets_set_to_undefined) {
const YGNodeRef root = YGNodeNew();
YGNodeStyleSetWidth(root, 50);
YGNodeStyleSetHeight(root, 50);
YGNodeStyleSetMinWidth(root, YGUndefined);
YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
EXPECT_FALSE(YGNodeIsDirty(root));
YGNodeStyleSetMinWidth(root, YGUndefined);
EXPECT_FALSE(YGNodeIsDirty(root));
YGNodeFreeRecursive(root);
}

View File

@@ -534,50 +534,68 @@ static inline const YGValue *YGNodeResolveFlexBasisPtr(const YGNodeRef node) {
} \ } \
} }
#define YG_NODE_STYLE_PROPERTY_SETTER_UNIT_IMPL(type, name, paramName, instanceName) \ #define YG_NODE_STYLE_PROPERTY_SETTER_UNIT_IMPL( \
void YGNodeStyleSet##name(const YGNodeRef node, const type paramName) { \ type, name, paramName, instanceName) \
if (node->style.instanceName.value != paramName || \ void YGNodeStyleSet##name(const YGNodeRef node, const type paramName) { \
node->style.instanceName.unit != YGUnitPoint) { \ YGValue value = { \
node->style.instanceName.value = paramName; \ .value = paramName, \
node->style.instanceName.unit = YGFloatIsUndefined(paramName) ? YGUnitAuto : YGUnitPoint; \ .unit = YGFloatIsUndefined(paramName) ? YGUnitUndefined : YGUnitPoint, \
YGNodeMarkDirtyInternal(node); \ }; \
} \ if ((node->style.instanceName.value != value.value && \
} \ value.unit != YGUnitUndefined) || \
\ node->style.instanceName.unit != value.unit) { \
void YGNodeStyleSet##name##Percent(const YGNodeRef node, const type paramName) { \ node->style.instanceName = value; \
if (node->style.instanceName.value != paramName || \ YGNodeMarkDirtyInternal(node); \
node->style.instanceName.unit != YGUnitPercent) { \ } \
node->style.instanceName.value = paramName; \ } \
node->style.instanceName.unit = YGFloatIsUndefined(paramName) ? YGUnitAuto : YGUnitPercent; \ \
YGNodeMarkDirtyInternal(node); \ void YGNodeStyleSet##name##Percent( \
} \ const YGNodeRef node, const type paramName) { \
YGValue value = { \
.value = paramName, \
.unit = \
YGFloatIsUndefined(paramName) ? YGUnitUndefined : YGUnitPercent, \
}; \
if ((node->style.instanceName.value != value.value && \
value.unit != YGUnitUndefined) || \
node->style.instanceName.unit != value.unit) { \
node->style.instanceName = value; \
YGNodeMarkDirtyInternal(node); \
} \
} }
#define YG_NODE_STYLE_PROPERTY_SETTER_UNIT_AUTO_IMPL(type, name, paramName, instanceName) \ #define YG_NODE_STYLE_PROPERTY_SETTER_UNIT_AUTO_IMPL( \
void YGNodeStyleSet##name(const YGNodeRef node, const type paramName) { \ type, name, paramName, instanceName) \
if (node->style.instanceName.value != paramName || \ void YGNodeStyleSet##name(const YGNodeRef node, const type paramName) { \
node->style.instanceName.unit != YGUnitPoint) { \ YGValue value = { \
node->style.instanceName.value = paramName; \ .value = paramName, \
node->style.instanceName.unit = YGFloatIsUndefined(paramName) ? YGUnitAuto : YGUnitPoint; \ .unit = YGFloatIsUndefined(paramName) ? YGUnitUndefined : YGUnitPoint, \
YGNodeMarkDirtyInternal(node); \ }; \
} \ if ((node->style.instanceName.value != value.value && \
} \ value.unit != YGUnitUndefined) || \
\ node->style.instanceName.unit != value.unit) { \
void YGNodeStyleSet##name##Percent(const YGNodeRef node, const type paramName) { \ node->style.instanceName = value; \
if (node->style.instanceName.value != paramName || \ YGNodeMarkDirtyInternal(node); \
node->style.instanceName.unit != YGUnitPercent) { \ } \
node->style.instanceName.value = paramName; \ } \
node->style.instanceName.unit = YGFloatIsUndefined(paramName) ? YGUnitAuto : YGUnitPercent; \ \
YGNodeMarkDirtyInternal(node); \ void YGNodeStyleSet##name##Percent( \
} \ const YGNodeRef node, const type paramName) { \
} \ if (node->style.instanceName.value != paramName || \
\ node->style.instanceName.unit != YGUnitPercent) { \
void YGNodeStyleSet##name##Auto(const YGNodeRef node) { \ node->style.instanceName.value = paramName; \
if (node->style.instanceName.unit != YGUnitAuto) { \ node->style.instanceName.unit = \
node->style.instanceName.value = YGUndefined; \ YGFloatIsUndefined(paramName) ? YGUnitAuto : YGUnitPercent; \
node->style.instanceName.unit = YGUnitAuto; \ YGNodeMarkDirtyInternal(node); \
YGNodeMarkDirtyInternal(node); \ } \
} \ } \
\
void YGNodeStyleSet##name##Auto(const YGNodeRef node) { \
if (node->style.instanceName.unit != YGUnitAuto) { \
node->style.instanceName.value = YGUndefined; \
node->style.instanceName.unit = YGUnitAuto; \
YGNodeMarkDirtyInternal(node); \
} \
} }
#define YG_NODE_STYLE_PROPERTY_IMPL(type, name, paramName, instanceName) \ #define YG_NODE_STYLE_PROPERTY_IMPL(type, name, paramName, instanceName) \
@@ -610,46 +628,59 @@ static inline const YGValue *YGNodeResolveFlexBasisPtr(const YGNodeRef node) {
} \ } \
} }
#define YG_NODE_STYLE_EDGE_PROPERTY_UNIT_IMPL(type, name, paramName, instanceName) \ #define YG_NODE_STYLE_EDGE_PROPERTY_UNIT_IMPL( \
void YGNodeStyleSet##name(const YGNodeRef node, const YGEdge edge, const float paramName) { \ type, name, paramName, instanceName) \
if (node->style.instanceName[edge].value != paramName || \ void YGNodeStyleSet##name( \
node->style.instanceName[edge].unit != YGUnitPoint) { \ const YGNodeRef node, const YGEdge edge, const float paramName) { \
node->style.instanceName[edge].value = paramName; \ YGValue value = { \
node->style.instanceName[edge].unit = \ .value = paramName, \
YGFloatIsUndefined(paramName) ? YGUnitUndefined : YGUnitPoint; \ .unit = YGFloatIsUndefined(paramName) ? YGUnitUndefined : YGUnitPoint, \
YGNodeMarkDirtyInternal(node); \ }; \
} \ if ((node->style.instanceName[edge].value != value.value && \
} \ value.unit != YGUnitUndefined) || \
\ node->style.instanceName[edge].unit != value.unit) { \
void YGNodeStyleSet##name##Percent(const YGNodeRef node, \ node->style.instanceName[edge] = value; \
const YGEdge edge, \ YGNodeMarkDirtyInternal(node); \
const float paramName) { \ } \
if (node->style.instanceName[edge].value != paramName || \ } \
node->style.instanceName[edge].unit != YGUnitPercent) { \ \
node->style.instanceName[edge].value = paramName; \ void YGNodeStyleSet##name##Percent( \
node->style.instanceName[edge].unit = \ const YGNodeRef node, const YGEdge edge, const float paramName) { \
YGFloatIsUndefined(paramName) ? YGUnitUndefined : YGUnitPercent; \ YGValue value = { \
YGNodeMarkDirtyInternal(node); \ .value = paramName, \
} \ .unit = \
} \ YGFloatIsUndefined(paramName) ? YGUnitUndefined : YGUnitPercent, \
\ }; \
WIN_STRUCT(type) YGNodeStyleGet##name(const YGNodeRef node, const YGEdge edge) { \ if ((node->style.instanceName[edge].value != value.value && \
return WIN_STRUCT_REF(node->style.instanceName[edge]); \ value.unit != YGUnitUndefined) || \
node->style.instanceName[edge].unit != value.unit) { \
node->style.instanceName[edge] = value; \
YGNodeMarkDirtyInternal(node); \
} \
} \
\
WIN_STRUCT(type) \
YGNodeStyleGet##name(const YGNodeRef node, const YGEdge edge) { \
return WIN_STRUCT_REF(node->style.instanceName[edge]); \
} }
#define YG_NODE_STYLE_EDGE_PROPERTY_IMPL(type, name, paramName, instanceName) \ #define YG_NODE_STYLE_EDGE_PROPERTY_IMPL(type, name, paramName, instanceName) \
void YGNodeStyleSet##name(const YGNodeRef node, const YGEdge edge, const float paramName) { \ void YGNodeStyleSet##name( \
if (node->style.instanceName[edge].value != paramName || \ const YGNodeRef node, const YGEdge edge, const float paramName) { \
node->style.instanceName[edge].unit != YGUnitPoint) { \ YGValue value = { \
node->style.instanceName[edge].value = paramName; \ .value = paramName, \
node->style.instanceName[edge].unit = \ .unit = YGFloatIsUndefined(paramName) ? YGUnitUndefined : YGUnitPoint, \
YGFloatIsUndefined(paramName) ? YGUnitUndefined : YGUnitPoint; \ }; \
YGNodeMarkDirtyInternal(node); \ if ((node->style.instanceName[edge].value != value.value && \
} \ value.unit != YGUnitUndefined) || \
} \ node->style.instanceName[edge].unit != value.unit) { \
\ node->style.instanceName[edge] = value; \
float YGNodeStyleGet##name(const YGNodeRef node, const YGEdge edge) { \ YGNodeMarkDirtyInternal(node); \
return node->style.instanceName[edge].value; \ } \
} \
\
float YGNodeStyleGet##name(const YGNodeRef node, const YGEdge edge) { \
return node->style.instanceName[edge].value; \
} }
#define YG_NODE_LAYOUT_PROPERTY_IMPL(type, name, instanceName) \ #define YG_NODE_LAYOUT_PROPERTY_IMPL(type, name, instanceName) \