Skip to content

Commit

Permalink
Add errata "PercentAbsoluteOmitsPadding" (microsoft#1290)
Browse files Browse the repository at this point in the history
Summary:
X-link: facebook/yoga#1290

This change default-enables a bugfix to Yoga's handling of absolute-positioned children sized using percentages. Yoga previously measured percentage of the box without padding, where the W3C spec, and browser behavior verified by test, use the padding box instead. See facebook/yoga#850 for more details of the backing issue.

I have so far left this behind a `YGExperimentalFeature`, because it will change the dimensions of existing views which use absolute percentages with parent padding.

This change moves it from a `YGExperimentalFeature` to `YGErrata`. This means the conformant path is enabled by default, but users of `YGErrataClassic` and `YGErrataAll` will stay on the previous behavior.

Right now the name is `PercentAbsoluteOmitsPadding` as something that tries to explain the issue in lay-terms and be a little less long than the old one, but I am open to other ideas.

Differential Revision: https://internalfb.com/D45763574

fbshipit-source-id: 1ec48dbc521c259f45cee03635e02efaae5b40bd
  • Loading branch information
NickGerleman authored and facebook-github-bot committed May 11, 2023
1 parent 6dfa1d7 commit 960d08d
Show file tree
Hide file tree
Showing 5 changed files with 49 additions and 47 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
public enum YogaErrata {
NONE(0),
STRETCH_FLEX_BASIS(1),
PERCENT_ABSOLUTE_OMITS_PADDING(2),
ALL(2147483647),
CLASSIC(2147483646);

Expand All @@ -29,6 +30,7 @@ public static YogaErrata fromInt(int value) {
switch (value) {
case 0: return NONE;
case 1: return STRETCH_FLEX_BASIS;
case 2: return PERCENT_ABSOLUTE_OMITS_PADDING;
case 2147483647: return ALL;
case 2147483646: return CLASSIC;
default: throw new IllegalArgumentException("Unknown enum value: " + value);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,7 @@

public enum YogaExperimentalFeature {
WEB_FLEX_BASIS(0),
ABSOLUTE_PERCENTAGE_AGAINST_PADDING_EDGE(1),
FIX_ABSOLUTE_TRAILING_COLUMN_MARGIN(2);
FIX_ABSOLUTE_TRAILING_COLUMN_MARGIN(1);

private final int mIntValue;

Expand All @@ -27,8 +26,7 @@ public int intValue() {
public static YogaExperimentalFeature fromInt(int value) {
switch (value) {
case 0: return WEB_FLEX_BASIS;
case 1: return ABSOLUTE_PERCENTAGE_AGAINST_PADDING_EDGE;
case 2: return FIX_ABSOLUTE_TRAILING_COLUMN_MARGIN;
case 1: return FIX_ABSOLUTE_TRAILING_COLUMN_MARGIN;
default: throw new IllegalArgumentException("Unknown enum value: " + value);
}
}
Expand Down
4 changes: 2 additions & 2 deletions packages/react-native/ReactCommon/yoga/yoga/YGEnums.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,8 @@ const char* YGErrataToString(const YGErrata value) {
return "none";
case YGErrataStretchFlexBasis:
return "stretch-flex-basis";
case YGErrataPercentAbsoluteOmitsPadding:
return "percent-absolute-omits-padding";
case YGErrataAll:
return "all";
case YGErrataClassic:
Expand All @@ -105,8 +107,6 @@ const char* YGExperimentalFeatureToString(const YGExperimentalFeature value) {
switch (value) {
case YGExperimentalFeatureWebFlexBasis:
return "web-flex-basis";
case YGExperimentalFeatureAbsolutePercentageAgainstPaddingEdge:
return "absolute-percentage-against-padding-edge";
case YGExperimentalFeatureFixAbsoluteTrailingColumnMargin:
return "fix-absolute-trailing-column-margin";
}
Expand Down
2 changes: 1 addition & 1 deletion packages/react-native/ReactCommon/yoga/yoga/YGEnums.h
Original file line number Diff line number Diff line change
Expand Up @@ -58,14 +58,14 @@ YG_ENUM_DECL(
YGErrata,
YGErrataNone = 0,
YGErrataStretchFlexBasis = 1,
YGErrataPercentAbsoluteOmitsPadding = 2,
YGErrataAll = 2147483647,
YGErrataClassic = 2147483646)
YG_DEFINE_ENUM_FLAG_OPERATORS(YGErrata)

YG_ENUM_SEQ_DECL(
YGExperimentalFeature,
YGExperimentalFeatureWebFlexBasis,
YGExperimentalFeatureAbsolutePercentageAgainstPaddingEdge,
YGExperimentalFeatureFixAbsoluteTrailingColumnMargin)

YG_ENUM_SEQ_DECL(
Expand Down
82 changes: 42 additions & 40 deletions packages/react-native/ReactCommon/yoga/yoga/Yoga.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1575,21 +1575,21 @@ static void YGNodeAbsoluteLayoutChild(
(node->getLayout().measuredDimensions[dim[mainAxis]] -
child->getLayout().measuredDimensions[dim[mainAxis]]),
leading[mainAxis]);
} else if (
node->getConfig()->isExperimentalFeatureEnabled(
YGExperimentalFeatureAbsolutePercentageAgainstPaddingEdge) &&
child->isLeadingPositionDefined(mainAxis)) {
child->setLayoutPosition(
child->getLeadingPosition(
mainAxis, node->getLayout().measuredDimensions[dim[mainAxis]])
.unwrap() +
node->getLeadingBorder(mainAxis) +
child
->getLeadingMargin(
mainAxis,
node->getLayout().measuredDimensions[dim[mainAxis]])
.unwrap(),
leading[mainAxis]);
} else if (child->isLeadingPositionDefined(mainAxis)) {
if (!child->hasErrata(YGErrataPercentAbsoluteOmitsPadding)) {
child->setLayoutPosition(
child->getLeadingPosition(
mainAxis,
node->getLayout().measuredDimensions[dim[mainAxis]])
.unwrap() +
node->getLeadingBorder(mainAxis) +
child
->getLeadingMargin(
mainAxis,
node->getLayout().measuredDimensions[dim[mainAxis]])
.unwrap(),
leading[mainAxis]);
}
}

if (child->isTrailingPosDefined(crossAxis) &&
Expand Down Expand Up @@ -1621,22 +1621,21 @@ static void YGNodeAbsoluteLayoutChild(
(node->getLayout().measuredDimensions[dim[crossAxis]] -
child->getLayout().measuredDimensions[dim[crossAxis]]),
leading[crossAxis]);
} else if (
node->getConfig()->isExperimentalFeatureEnabled(
YGExperimentalFeatureAbsolutePercentageAgainstPaddingEdge) &&
child->isLeadingPositionDefined(crossAxis)) {
child->setLayoutPosition(
child->getLeadingPosition(
crossAxis,
node->getLayout().measuredDimensions[dim[crossAxis]])
.unwrap() +
node->getLeadingBorder(crossAxis) +
child
->getLeadingMargin(
crossAxis,
node->getLayout().measuredDimensions[dim[crossAxis]])
.unwrap(),
leading[crossAxis]);
} else if (child->isLeadingPositionDefined(crossAxis)) {
if (!child->hasErrata(YGErrataPercentAbsoluteOmitsPadding)) {
child->setLayoutPosition(
child->getLeadingPosition(
crossAxis,
node->getLayout().measuredDimensions[dim[crossAxis]])
.unwrap() +
node->getLeadingBorder(crossAxis) +
child
->getLeadingMargin(
crossAxis,
node->getLayout().measuredDimensions[dim[crossAxis]])
.unwrap(),
leading[crossAxis]);
}
}
}

Expand Down Expand Up @@ -3553,20 +3552,23 @@ static void YGNodelayoutImpl(
child->getStyle().positionType() != YGPositionTypeAbsolute) {
continue;
}
const bool absolutePercentageAgainstPaddingEdge =
node->getConfig()->isExperimentalFeatureEnabled(
YGExperimentalFeatureAbsolutePercentageAgainstPaddingEdge);
const bool percentAbsoluteOmitsPadding =
child->hasErrata(YGErrataPercentAbsoluteOmitsPadding);

const float width = percentAbsoluteOmitsPadding
? availableInnerWidth
: node->getLayout().measuredDimensions[YGDimensionWidth];

const float height = percentAbsoluteOmitsPadding
? availableInnerHeight
: node->getLayout().measuredDimensions[YGDimensionHeight];

YGNodeAbsoluteLayoutChild(
node,
child,
absolutePercentageAgainstPaddingEdge
? node->getLayout().measuredDimensions[YGDimensionWidth]
: availableInnerWidth,
width,
isMainAxisRow ? measureModeMainDim : measureModeCrossDim,
absolutePercentageAgainstPaddingEdge
? node->getLayout().measuredDimensions[YGDimensionHeight]
: availableInnerHeight,
height,
direction,
config,
layoutMarkerData,
Expand Down

0 comments on commit 960d08d

Please sign in to comment.