Impl of content box (#1711)

Summary:
X-link: https://github.com/facebook/react-native/pull/46741

Pull Request resolved: https://github.com/facebook/yoga/pull/1711

box sizing is really just a reinterpretation of what length properties (like `width`, `height`, `max-width`, etc) mean. So to implement this I just add the border and padding if we are in content box when we ask for any of these properties. All the math that gets done by the algorithm is still in border box land, and the layout we return is to be interpreted as the border box (this is actually the expected behavior per https://drafts.csswg.org/css-sizing/#box-sizing). This makes this implementation pretty simple actually.

Changelog: [Internal]

Reviewed By: NickGerleman

Differential Revision: D63416833

fbshipit-source-id: fd76132cf51e8a5092129802c3a12ab24023018b
This commit is contained in:
Joe Vilches
2024-10-01 15:19:22 -07:00
committed by Facebook GitHub Bot
parent bc5098fc80
commit 671ae61a39
10 changed files with 181 additions and 121 deletions

View File

@@ -1,4 +1,4 @@
<div data-disabled="true" id="box_sizing_content_box"
<div id="box_sizing_content_box_simple"
style="width: 100px; height: 100px; padding: 5px; border-width: 10px; box-sizing: content-box">
</div>
@@ -6,7 +6,7 @@
style="width: 100px; height: 100px; padding: 5px; border-width: 10px; box-sizing: border-box">
</div>
<div data-disabled="true" id="box_sizing_content_box_padding_only"
<div id="box_sizing_content_box_padding_only"
style="width: 100px; height: 100px; padding: 5px; box-sizing: content-box">
</div>
@@ -14,7 +14,7 @@
style="width: 100px; height: 100px; padding: 5px; box-sizing: border-box">
</div>
<div data-disabled="true" id="box_sizing_content_box_border_only"
<div id="box_sizing_content_box_border_only"
style="width: 100px; height: 100px; border-width: 10px; box-sizing: content-box">
</div>
@@ -22,7 +22,7 @@
style="width: 100px; height: 100px; border-width: 10px; box-sizing: border-box">
</div>
<div data-disabled="true" id="box_sizing_content_box_no_padding_no_border"
<div id="box_sizing_content_box_no_padding_no_border"
style="width: 100px; height: 100px; box-sizing: content-box">
</div>
@@ -30,7 +30,7 @@
style="width: 100px; height: 100px; box-sizing: border-box">
</div>
<div data-disabled="true" id="box_sizing_content_box_children"
<div id="box_sizing_content_box_children"
style="width: 100px; height: 100px; padding: 5px; border-width: 10px; box-sizing: content-box">
<div style="width: 25px; height: 25px"></div>
<div style="width: 25px; height: 25px"></div>
@@ -46,7 +46,7 @@
<div style="width: 25px; height: 25px"></div>
</div>
<div data-disabled="true" id="box_sizing_content_box_siblings" style="width: 100px; height: 100px;">
<div id="box_sizing_content_box_siblings" style="width: 100px; height: 100px;">
<div style="width: 25px; height: 25px"></div>
<div style="width: 25px; height: 25px; box-sizing: content-box; padding: 10px; border-width: 10px"></div>
<div style="width: 25px; height: 25px"></div>
@@ -60,7 +60,7 @@
<div style="width: 25px; height: 25px"></div>
</div>
<div data-disabled="true" id="box_sizing_content_box_max_width" style="width: 100px; height: 100px;">
<div id="box_sizing_content_box_max_width" style="width: 100px; height: 100px;">
<div style="max-width: 50px; height: 25px; box-sizing: content-box; padding: 5px; border-width: 15px"></div>
<div style="width: 25px; height: 25px"></div>
</div>
@@ -70,7 +70,7 @@
<div style="width: 25px; height: 25px"></div>
</div>
<div data-disabled="true" id="box_sizing_content_box_max_height" style="width: 100px; height: 100px;">
<div id="box_sizing_content_box_max_height" style="width: 100px; height: 100px;">
<div style="width: 50px; max-height: 50px; box-sizing: content-box; padding: 5px; border-width: 15px"></div>
<div style="width: 25px; height: 25px"></div>
</div>
@@ -80,7 +80,7 @@
<div style="width: 25px; height: 25px"></div>
</div>
<div data-disabled="true" id="box_sizing_content_box_min_width" style="width: 100px; height: 100px;">
<div id="box_sizing_content_box_min_width" style="width: 100px; height: 100px;">
<div style="min-width: 50px; height: 25px; box-sizing: content-box; padding: 5px; border-width: 15px"></div>
<div style="width: 25px; height: 25px"></div>
</div>
@@ -90,7 +90,7 @@
<div style="width: 25px; height: 25px"></div>
</div>
<div data-disabled="true" id="box_sizing_content_box_min_height" style="width: 100px; height: 100px;">
<div id="box_sizing_content_box_min_height" style="width: 100px; height: 100px;">
<div style="width: 50px; min-height: 50px; box-sizing: content-box; padding: 5px; border-width: 15px"></div>
<div style="width: 25px; height: 25px"></div>
</div>
@@ -100,7 +100,7 @@
<div style="width: 25px; height: 25px"></div>
</div>
<div data-disabled="true" id="box_sizing_content_box_no_height_no_width" style="width: 100px; height: 100px;">
<div id="box_sizing_content_box_no_height_no_width" style="width: 100px; height: 100px;">
<div style="box-sizing: content-box; padding: 2px; border-width: 7px">
</div>
</div>
@@ -110,7 +110,7 @@
</div>
</div>
<div data-disabled="true" id="box_sizing_content_box_nested"
<div id="box_sizing_content_box_nested"
style="width: 100px; height: 100px; box-sizing: content-box; padding: 15px; border-width: 3px;">
<div style="width: 20px; height: 20px; box-sizing: content-box; padding: 2px; border-width: 7px">
<div style="width: 10px; height: 5px; box-sizing: content-box; padding: 1px; border-width: 2px"></div>
@@ -124,7 +124,7 @@
</div>
</div>
<div data-disabled="true" id="box_sizing_content_box_nested_alternating"
<div id="box_sizing_content_box_nested_alternating"
style="width: 100px; height: 100px; box-sizing: content-box; padding: 3px; border-width: 2px;">
<div style="width: 40px; height: 40px; box-sizing: border-box; padding: 8px; border-width: 2px">
<div style="width: 20px; height: 25px; box-sizing: content-box; padding: 3px; border-width: 6px">
@@ -134,7 +134,7 @@
</div>
</div>
<div data-disabled="true" id="box_sizing_border_box_nested_alternating"
<div id="box_sizing_border_box_nested_alternating"
style="width: 100px; height: 100px; box-sizing: border-box; padding: 3px; border-width: 2px;">
<div style="width: 40px; height: 40px; box-sizing: content-box; padding: 8px; border-width: 2px">
<div style="width: 20px; height: 25px; box-sizing: border-box; padding: 3px; border-width: 6px">

View File

@@ -4,7 +4,7 @@
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @generated SignedSource<<84bb16d1a7ae39fb8f159ee58baef4c2>>
* @generated SignedSource<<c57cfea6c33a34e2a67a855138e9833b>>
* generated by gentest/gentest-driver.ts from gentest/fixtures/YGBoxSizingTest.html
*/
@@ -28,8 +28,7 @@ public class YGBoxSizingTest {
@Parameterized.Parameter public TestParametrization.NodeFactory mNodeFactory;
@Test
@Ignore
public void test_box_sizing_content_box() {
public void test_box_sizing_content_box_simple() {
YogaConfig config = YogaConfigFactory.create();
final YogaNode root = createNode(config);
@@ -96,7 +95,6 @@ public class YGBoxSizingTest {
}
@Test
@Ignore
public void test_box_sizing_content_box_padding_only() {
YogaConfig config = YogaConfigFactory.create();
@@ -156,7 +154,6 @@ public class YGBoxSizingTest {
}
@Test
@Ignore
public void test_box_sizing_content_box_border_only() {
YogaConfig config = YogaConfigFactory.create();
@@ -216,7 +213,6 @@ public class YGBoxSizingTest {
}
@Test
@Ignore
public void test_box_sizing_content_box_no_padding_no_border() {
YogaConfig config = YogaConfigFactory.create();
@@ -268,7 +264,6 @@ public class YGBoxSizingTest {
}
@Test
@Ignore
public void test_box_sizing_content_box_children() {
YogaConfig config = YogaConfigFactory.create();
@@ -456,7 +451,6 @@ public class YGBoxSizingTest {
}
@Test
@Ignore
public void test_box_sizing_content_box_siblings() {
YogaConfig config = YogaConfigFactory.create();
@@ -644,7 +638,6 @@ public class YGBoxSizingTest {
}
@Test
@Ignore
public void test_box_sizing_content_box_max_width() {
YogaConfig config = YogaConfigFactory.create();
@@ -772,7 +765,6 @@ public class YGBoxSizingTest {
}
@Test
@Ignore
public void test_box_sizing_content_box_max_height() {
YogaConfig config = YogaConfigFactory.create();
@@ -900,7 +892,6 @@ public class YGBoxSizingTest {
}
@Test
@Ignore
public void test_box_sizing_content_box_min_width() {
YogaConfig config = YogaConfigFactory.create();
@@ -1028,7 +1019,6 @@ public class YGBoxSizingTest {
}
@Test
@Ignore
public void test_box_sizing_content_box_min_height() {
YogaConfig config = YogaConfigFactory.create();
@@ -1156,7 +1146,6 @@ public class YGBoxSizingTest {
}
@Test
@Ignore
public void test_box_sizing_content_box_no_height_no_width() {
YogaConfig config = YogaConfigFactory.create();
@@ -1250,7 +1239,6 @@ public class YGBoxSizingTest {
}
@Test
@Ignore
public void test_box_sizing_content_box_nested() {
YogaConfig config = YogaConfigFactory.create();
@@ -1412,7 +1400,6 @@ public class YGBoxSizingTest {
}
@Test
@Ignore
public void test_box_sizing_content_box_nested_alternating() {
YogaConfig config = YogaConfigFactory.create();
@@ -1517,7 +1504,6 @@ public class YGBoxSizingTest {
}
@Test
@Ignore
public void test_box_sizing_border_box_nested_alternating() {
YogaConfig config = YogaConfigFactory.create();

View File

@@ -4,7 +4,7 @@
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @generated SignedSource<<40a2a45449f152b9c1f91adfc46ac6df>>
* @generated SignedSource<<5ce4b1bc764d2bf325b844053b98134e>>
* generated by gentest/gentest-driver.ts from gentest/fixtures/YGBoxSizingTest.html
*/
@@ -28,7 +28,7 @@ import {
Wrap,
} from 'yoga-layout';
test.skip('box_sizing_content_box', () => {
test('box_sizing_content_box_simple', () => {
const config = Yoga.Config.create();
let root;
@@ -105,7 +105,7 @@ test('box_sizing_border_box', () => {
config.free();
}
});
test.skip('box_sizing_content_box_padding_only', () => {
test('box_sizing_content_box_padding_only', () => {
const config = Yoga.Config.create();
let root;
@@ -174,7 +174,7 @@ test('box_sizing_border_box_padding_only', () => {
config.free();
}
});
test.skip('box_sizing_content_box_border_only', () => {
test('box_sizing_content_box_border_only', () => {
const config = Yoga.Config.create();
let root;
@@ -243,7 +243,7 @@ test('box_sizing_border_box_border_only', () => {
config.free();
}
});
test.skip('box_sizing_content_box_no_padding_no_border', () => {
test('box_sizing_content_box_no_padding_no_border', () => {
const config = Yoga.Config.create();
let root;
@@ -304,7 +304,7 @@ test('box_sizing_border_box_no_padding_no_border', () => {
config.free();
}
});
test.skip('box_sizing_content_box_children', () => {
test('box_sizing_content_box_children', () => {
const config = Yoga.Config.create();
let root;
@@ -501,7 +501,7 @@ test('box_sizing_border_box_children', () => {
config.free();
}
});
test.skip('box_sizing_content_box_siblings', () => {
test('box_sizing_content_box_siblings', () => {
const config = Yoga.Config.create();
let root;
@@ -698,7 +698,7 @@ test('box_sizing_border_box_siblings', () => {
config.free();
}
});
test.skip('box_sizing_content_box_max_width', () => {
test('box_sizing_content_box_max_width', () => {
const config = Yoga.Config.create();
let root;
@@ -835,7 +835,7 @@ test('box_sizing_border_box_max_width', () => {
config.free();
}
});
test.skip('box_sizing_content_box_max_height', () => {
test('box_sizing_content_box_max_height', () => {
const config = Yoga.Config.create();
let root;
@@ -972,7 +972,7 @@ test('box_sizing_border_box_max_height', () => {
config.free();
}
});
test.skip('box_sizing_content_box_min_width', () => {
test('box_sizing_content_box_min_width', () => {
const config = Yoga.Config.create();
let root;
@@ -1109,7 +1109,7 @@ test('box_sizing_border_box_min_width', () => {
config.free();
}
});
test.skip('box_sizing_content_box_min_height', () => {
test('box_sizing_content_box_min_height', () => {
const config = Yoga.Config.create();
let root;
@@ -1246,7 +1246,7 @@ test('box_sizing_border_box_min_height', () => {
config.free();
}
});
test.skip('box_sizing_content_box_no_height_no_width', () => {
test('box_sizing_content_box_no_height_no_width', () => {
const config = Yoga.Config.create();
let root;
@@ -1349,7 +1349,7 @@ test('box_sizing_border_box_no_height_no_width', () => {
config.free();
}
});
test.skip('box_sizing_content_box_nested', () => {
test('box_sizing_content_box_nested', () => {
const config = Yoga.Config.create();
let root;
@@ -1520,7 +1520,7 @@ test('box_sizing_border_box_nested', () => {
config.free();
}
});
test.skip('box_sizing_content_box_nested_alternating', () => {
test('box_sizing_content_box_nested_alternating', () => {
const config = Yoga.Config.create();
let root;
@@ -1629,7 +1629,7 @@ test.skip('box_sizing_content_box_nested_alternating', () => {
config.free();
}
});
test.skip('box_sizing_border_box_nested_alternating', () => {
test('box_sizing_border_box_nested_alternating', () => {
const config = Yoga.Config.create();
let root;

View File

@@ -5,7 +5,7 @@
* LICENSE file in the root directory of this source tree.
*
* clang-format off
* @generated SignedSource<<38c0ba6ef126d3453c7e0b56da131566>>
* @generated SignedSource<<56d0eec106ade0bbd034067594249c76>>
* generated by gentest/gentest-driver.ts from gentest/fixtures/YGBoxSizingTest.html
*/
@@ -13,9 +13,7 @@
#include <yoga/Yoga.h>
#include "../util/TestUtil.h"
TEST(YogaTest, box_sizing_content_box) {
GTEST_SKIP();
TEST(YogaTest, box_sizing_content_box_simple) {
YGConfigRef config = YGConfigNew();
YGNodeRef root = YGNodeNewWithConfig(config);
@@ -85,8 +83,6 @@ TEST(YogaTest, box_sizing_border_box) {
}
TEST(YogaTest, box_sizing_content_box_padding_only) {
GTEST_SKIP();
YGConfigRef config = YGConfigNew();
YGNodeRef root = YGNodeNewWithConfig(config);
@@ -148,8 +144,6 @@ TEST(YogaTest, box_sizing_border_box_padding_only) {
}
TEST(YogaTest, box_sizing_content_box_border_only) {
GTEST_SKIP();
YGConfigRef config = YGConfigNew();
YGNodeRef root = YGNodeNewWithConfig(config);
@@ -211,8 +205,6 @@ TEST(YogaTest, box_sizing_border_box_border_only) {
}
TEST(YogaTest, box_sizing_content_box_no_padding_no_border) {
GTEST_SKIP();
YGConfigRef config = YGConfigNew();
YGNodeRef root = YGNodeNewWithConfig(config);
@@ -266,8 +258,6 @@ TEST(YogaTest, box_sizing_border_box_no_padding_no_border) {
}
TEST(YogaTest, box_sizing_content_box_children) {
GTEST_SKIP();
YGConfigRef config = YGConfigNew();
YGNodeRef root = YGNodeNewWithConfig(config);
@@ -457,8 +447,6 @@ TEST(YogaTest, box_sizing_border_box_children) {
}
TEST(YogaTest, box_sizing_content_box_siblings) {
GTEST_SKIP();
YGConfigRef config = YGConfigNew();
YGNodeRef root = YGNodeNewWithConfig(config);
@@ -648,8 +636,6 @@ TEST(YogaTest, box_sizing_border_box_siblings) {
}
TEST(YogaTest, box_sizing_content_box_max_width) {
GTEST_SKIP();
YGConfigRef config = YGConfigNew();
YGNodeRef root = YGNodeNewWithConfig(config);
@@ -779,8 +765,6 @@ TEST(YogaTest, box_sizing_border_box_max_width) {
}
TEST(YogaTest, box_sizing_content_box_max_height) {
GTEST_SKIP();
YGConfigRef config = YGConfigNew();
YGNodeRef root = YGNodeNewWithConfig(config);
@@ -910,8 +894,6 @@ TEST(YogaTest, box_sizing_border_box_max_height) {
}
TEST(YogaTest, box_sizing_content_box_min_width) {
GTEST_SKIP();
YGConfigRef config = YGConfigNew();
YGNodeRef root = YGNodeNewWithConfig(config);
@@ -1041,8 +1023,6 @@ TEST(YogaTest, box_sizing_border_box_min_width) {
}
TEST(YogaTest, box_sizing_content_box_min_height) {
GTEST_SKIP();
YGConfigRef config = YGConfigNew();
YGNodeRef root = YGNodeNewWithConfig(config);
@@ -1172,8 +1152,6 @@ TEST(YogaTest, box_sizing_border_box_min_height) {
}
TEST(YogaTest, box_sizing_content_box_no_height_no_width) {
GTEST_SKIP();
YGConfigRef config = YGConfigNew();
YGNodeRef root = YGNodeNewWithConfig(config);
@@ -1269,8 +1247,6 @@ TEST(YogaTest, box_sizing_border_box_no_height_no_width) {
}
TEST(YogaTest, box_sizing_content_box_nested) {
GTEST_SKIP();
YGConfigRef config = YGConfigNew();
YGNodeRef root = YGNodeNewWithConfig(config);
@@ -1434,8 +1410,6 @@ TEST(YogaTest, box_sizing_border_box_nested) {
}
TEST(YogaTest, box_sizing_content_box_nested_alternating) {
GTEST_SKIP();
YGConfigRef config = YGConfigNew();
YGNodeRef root = YGNodeNewWithConfig(config);
@@ -1541,8 +1515,6 @@ TEST(YogaTest, box_sizing_content_box_nested_alternating) {
}
TEST(YogaTest, box_sizing_border_box_nested_alternating) {
GTEST_SKIP();
YGConfigRef config = YGConfigNew();
YGNodeRef root = YGNodeNewWithConfig(config);

View File

@@ -324,8 +324,9 @@ void layoutAbsoluteChild(
FlexDirection::Column, containingBlockWidth);
if (child->hasDefiniteLength(Dimension::Width, containingBlockWidth)) {
childWidth = child->getProcessedDimension(Dimension::Width)
.resolve(containingBlockWidth)
childWidth = child
->getResolvedDimension(
direction, Dimension::Width, containingBlockWidth)
.unwrap() +
marginRow;
} else {
@@ -359,8 +360,9 @@ void layoutAbsoluteChild(
}
if (child->hasDefiniteLength(Dimension::Height, containingBlockHeight)) {
childHeight = child->getProcessedDimension(Dimension::Height)
.resolve(containingBlockHeight)
childHeight = child
->getResolvedDimension(
direction, Dimension::Height, containingBlockHeight)
.unwrap() +
marginColumn;
} else {

View File

@@ -29,6 +29,7 @@ inline float paddingAndBorderForAxis(
inline FloatOptional boundAxisWithinMinAndMax(
const yoga::Node* const node,
const Direction direction,
const FlexDirection axis,
const FloatOptional value,
const float axisSize) {
@@ -36,11 +37,15 @@ inline FloatOptional boundAxisWithinMinAndMax(
FloatOptional max;
if (isColumn(axis)) {
min = node->style().minDimension(Dimension::Height).resolve(axisSize);
max = node->style().maxDimension(Dimension::Height).resolve(axisSize);
min = node->style().resolvedMinDimension(
direction, Dimension::Height, axisSize);
max = node->style().resolvedMaxDimension(
direction, Dimension::Height, axisSize);
} else if (isRow(axis)) {
min = node->style().minDimension(Dimension::Width).resolve(axisSize);
max = node->style().maxDimension(Dimension::Width).resolve(axisSize);
min = node->style().resolvedMinDimension(
direction, Dimension::Width, axisSize);
max = node->style().resolvedMaxDimension(
direction, Dimension::Width, axisSize);
}
if (max >= FloatOptional{0} && value > max) {
@@ -64,7 +69,8 @@ inline float boundAxis(
const float axisSize,
const float widthSize) {
return yoga::maxOrDefined(
boundAxisWithinMinAndMax(node, axis, FloatOptional{value}, axisSize)
boundAxisWithinMinAndMax(
node, direction, axis, FloatOptional{value}, axisSize)
.unwrap(),
paddingAndBorderForAxis(node, axis, direction, widthSize));
}

View File

@@ -38,13 +38,14 @@ std::atomic<uint32_t> gCurrentGenerationCount(0);
static void constrainMaxSizeForMode(
const yoga::Node* node,
Direction direction,
FlexDirection axis,
float ownerAxisSize,
float ownerWidth,
/*in_out*/ SizingMode* mode,
/*in_out*/ float* size) {
const FloatOptional maxSize =
node->style().maxDimension(dimension(axis)).resolve(ownerAxisSize) +
const FloatOptional maxSize = node->style().resolvedMaxDimension(
direction, dimension(axis), ownerAxisSize) +
FloatOptional(node->style().computeMarginForAxis(axis, ownerWidth));
switch (*mode) {
case SizingMode::StretchFit:
@@ -110,7 +111,7 @@ static void computeFlexBasisForChild(
child, FlexDirection::Row, direction, ownerWidth));
child->setLayoutComputedFlexBasis(yoga::maxOrDefined(
child->getProcessedDimension(Dimension::Width).resolve(ownerWidth),
child->getResolvedDimension(direction, Dimension::Width, ownerWidth),
paddingAndBorder));
} else if (!isMainAxisRow && isColumnStyleDimDefined) {
// The height is definite, so use that as the flex basis.
@@ -118,7 +119,7 @@ static void computeFlexBasisForChild(
FloatOptional(paddingAndBorderForAxis(
child, FlexDirection::Column, direction, ownerWidth));
child->setLayoutComputedFlexBasis(yoga::maxOrDefined(
child->getProcessedDimension(Dimension::Height).resolve(ownerHeight),
child->getResolvedDimension(direction, Dimension::Height, ownerHeight),
paddingAndBorder));
} else {
// Compute the flex basis and hypothetical main size (i.e. the clamped flex
@@ -132,16 +133,16 @@ static void computeFlexBasisForChild(
child->style().computeMarginForAxis(FlexDirection::Column, ownerWidth);
if (isRowStyleDimDefined) {
childWidth = child->getProcessedDimension(Dimension::Width)
.resolve(ownerWidth)
.unwrap() +
childWidth =
child->getResolvedDimension(direction, Dimension::Width, ownerWidth)
.unwrap() +
marginRow;
childWidthSizingMode = SizingMode::StretchFit;
}
if (isColumnStyleDimDefined) {
childHeight = child->getProcessedDimension(Dimension::Height)
.resolve(ownerHeight)
.unwrap() +
childHeight =
child->getResolvedDimension(direction, Dimension::Height, ownerHeight)
.unwrap() +
marginColumn;
childHeightSizingMode = SizingMode::StretchFit;
}
@@ -216,6 +217,7 @@ static void computeFlexBasisForChild(
constrainMaxSizeForMode(
child,
direction,
FlexDirection::Row,
ownerWidth,
ownerWidth,
@@ -223,6 +225,7 @@ static void computeFlexBasisForChild(
&childWidth);
constrainMaxSizeForMode(
child,
direction,
FlexDirection::Column,
ownerHeight,
ownerWidth,
@@ -469,6 +472,7 @@ static void zeroOutLayoutRecursively(yoga::Node* const node) {
static float calculateAvailableInnerDimension(
const yoga::Node* const node,
const Direction direction,
const Dimension dimension,
const float availableDim,
const float paddingAndBorder,
@@ -480,13 +484,13 @@ static float calculateAvailableInnerDimension(
// We want to make sure our available height does not violate min and max
// constraints
const FloatOptional minDimensionOptional =
node->style().minDimension(dimension).resolve(ownerDim);
node->style().resolvedMinDimension(direction, dimension, ownerDim);
const float minInnerDim = minDimensionOptional.isUndefined()
? 0.0f
: minDimensionOptional.unwrap() - paddingAndBorder;
const FloatOptional maxDimensionOptional =
node->style().maxDimension(dimension).resolve(ownerDim);
node->style().resolvedMaxDimension(direction, dimension, ownerDim);
const float maxInnerDim = maxDimensionOptional.isUndefined()
? FLT_MAX
@@ -611,6 +615,7 @@ static float distributeFreeSpaceSecondPass(
for (auto currentLineChild : flexLine.itemsInFlow) {
childFlexBasis = boundAxisWithinMinAndMax(
currentLineChild,
direction,
mainAxis,
currentLineChild->getLayout().computedFlexBasis,
mainAxisownerSize)
@@ -709,8 +714,9 @@ static float distributeFreeSpaceSecondPass(
: SizingMode::FitContent;
} else {
childCrossSize =
currentLineChild->getProcessedDimension(dimension(crossAxis))
.resolve(availableInnerCrossDim)
currentLineChild
->getResolvedDimension(
direction, dimension(crossAxis), availableInnerCrossDim)
.unwrap() +
marginCross;
const bool isLoosePercentageMeasurement =
@@ -725,6 +731,7 @@ static float distributeFreeSpaceSecondPass(
constrainMaxSizeForMode(
currentLineChild,
direction,
mainAxis,
availableInnerMainDim,
availableInnerWidth,
@@ -732,6 +739,7 @@ static float distributeFreeSpaceSecondPass(
&childMainSize);
constrainMaxSizeForMode(
currentLineChild,
direction,
crossAxis,
availableInnerCrossDim,
availableInnerWidth,
@@ -812,6 +820,7 @@ static void distributeFreeSpaceFirstPass(
for (auto currentLineChild : flexLine.itemsInFlow) {
float childFlexBasis = boundAxisWithinMinAndMax(
currentLineChild,
direction,
mainAxis,
currentLineChild->getLayout().computedFlexBasis,
mainAxisownerSize)
@@ -982,8 +991,9 @@ static void justifyMainAxis(
if (sizingModeMainDim == SizingMode::FitContent &&
flexLine.layout.remainingFreeSpace > 0) {
if (style.minDimension(dimension(mainAxis)).isDefined() &&
style.minDimension(dimension(mainAxis))
.resolve(mainAxisownerSize)
style
.resolvedMinDimension(
direction, dimension(mainAxis), mainAxisownerSize)
.isDefined()) {
// This condition makes sure that if the size of main dimension(after
// considering child nodes main dim, leading and trailing padding etc)
@@ -992,9 +1002,11 @@ static void justifyMainAxis(
// `minAvailableMainDim` denotes minimum available space in which child
// can be laid out, it will exclude space consumed by padding and border.
const float minAvailableMainDim = style.minDimension(dimension(mainAxis))
.resolve(mainAxisownerSize)
.unwrap() -
const float minAvailableMainDim =
style
.resolvedMinDimension(
direction, dimension(mainAxis), mainAxisownerSize)
.unwrap() -
leadingPaddingAndBorderMain - trailingPaddingAndBorderMain;
const float occupiedSpaceByChildNodes =
availableInnerMainDim - flexLine.layout.remainingFreeSpace;
@@ -1387,12 +1399,14 @@ static void calculateLayoutImpl(
float availableInnerWidth = calculateAvailableInnerDimension(
node,
direction,
Dimension::Width,
availableWidth - marginAxisRow,
paddingAndBorderAxisRow,
ownerWidth);
float availableInnerHeight = calculateAvailableInnerDimension(
node,
direction,
Dimension::Height,
availableHeight - marginAxisColumn,
paddingAndBorderAxisColumn,
@@ -1480,16 +1494,20 @@ static void calculateLayoutImpl(
if (sizingModeMainDim != SizingMode::StretchFit) {
const auto& style = node->style();
const float minInnerWidth =
style.minDimension(Dimension::Width).resolve(ownerWidth).unwrap() -
style.resolvedMinDimension(direction, Dimension::Width, ownerWidth)
.unwrap() -
paddingAndBorderAxisRow;
const float maxInnerWidth =
style.maxDimension(Dimension::Width).resolve(ownerWidth).unwrap() -
style.resolvedMaxDimension(direction, Dimension::Width, ownerWidth)
.unwrap() -
paddingAndBorderAxisRow;
const float minInnerHeight =
style.minDimension(Dimension::Height).resolve(ownerHeight).unwrap() -
style.resolvedMinDimension(direction, Dimension::Height, ownerHeight)
.unwrap() -
paddingAndBorderAxisColumn;
const float maxInnerHeight =
style.maxDimension(Dimension::Height).resolve(ownerHeight).unwrap() -
style.resolvedMaxDimension(direction, Dimension::Height, ownerHeight)
.unwrap() -
paddingAndBorderAxisColumn;
const float minInnerMainDim =
@@ -1688,6 +1706,7 @@ static void calculateLayoutImpl(
SizingMode childCrossSizingMode = SizingMode::StretchFit;
constrainMaxSizeForMode(
child,
direction,
mainAxis,
availableInnerMainDim,
availableInnerWidth,
@@ -1695,6 +1714,7 @@ static void calculateLayoutImpl(
&childMainSize);
constrainMaxSizeForMode(
child,
direction,
crossAxis,
availableInnerCrossDim,
availableInnerWidth,
@@ -1781,8 +1801,8 @@ static void calculateLayoutImpl(
const float unclampedCrossDim = sizingModeCrossDim == SizingMode::StretchFit
? availableInnerCrossDim + paddingAndBorderAxisCross
: node->hasDefiniteLength(dimension(crossAxis), crossAxisownerSize)
? node->getProcessedDimension(dimension(crossAxis))
.resolve(crossAxisownerSize)
? node->getResolvedDimension(
direction, dimension(crossAxis), crossAxisownerSize)
.unwrap()
: totalLineCrossDim + paddingAndBorderAxisCross;
@@ -2035,6 +2055,7 @@ static void calculateLayoutImpl(
availableInnerMainDim + paddingAndBorderAxisMain,
boundAxisWithinMinAndMax(
node,
direction,
mainAxis,
FloatOptional{maxLineMainDim},
mainAxisownerSize)
@@ -2067,6 +2088,7 @@ static void calculateLayoutImpl(
availableInnerCrossDim + paddingAndBorderAxisCross,
boundAxisWithinMinAndMax(
node,
direction,
crossAxis,
FloatOptional{
totalLineCrossDim + paddingAndBorderAxisCross},
@@ -2355,20 +2377,21 @@ void calculateLayout(
// the input parameters don't change.
gCurrentGenerationCount.fetch_add(1, std::memory_order_relaxed);
node->processDimensions();
const Direction direction = node->resolveDirection(ownerDirection);
float width = YGUndefined;
SizingMode widthSizingMode = SizingMode::MaxContent;
const auto& style = node->style();
if (node->hasDefiniteLength(Dimension::Width, ownerWidth)) {
width =
(node->getProcessedDimension(Dimension::Width)
.resolve(ownerWidth)
(node->getResolvedDimension(
direction, dimension(FlexDirection::Row), ownerWidth)
.unwrap() +
node->style().computeMarginForAxis(FlexDirection::Row, ownerWidth));
widthSizingMode = SizingMode::StretchFit;
} else if (style.maxDimension(Dimension::Width)
.resolve(ownerWidth)
} else if (style.resolvedMaxDimension(direction, Dimension::Width, ownerWidth)
.isDefined()) {
width = style.maxDimension(Dimension::Width).resolve(ownerWidth).unwrap();
width = style.resolvedMaxDimension(direction, Dimension::Width, ownerWidth)
.unwrap();
widthSizingMode = SizingMode::FitContent;
} else {
width = ownerWidth;
@@ -2380,16 +2403,18 @@ void calculateLayout(
SizingMode heightSizingMode = SizingMode::MaxContent;
if (node->hasDefiniteLength(Dimension::Height, ownerHeight)) {
height =
(node->getProcessedDimension(Dimension::Height)
.resolve(ownerHeight)
(node->getResolvedDimension(
direction, dimension(FlexDirection::Column), ownerHeight)
.unwrap() +
node->style().computeMarginForAxis(FlexDirection::Column, ownerWidth));
heightSizingMode = SizingMode::StretchFit;
} else if (style.maxDimension(Dimension::Height)
.resolve(ownerHeight)
} else if (style
.resolvedMaxDimension(
direction, Dimension::Height, ownerHeight)
.isDefined()) {
height =
style.maxDimension(Dimension::Height).resolve(ownerHeight).unwrap();
style.resolvedMaxDimension(direction, Dimension::Height, ownerHeight)
.unwrap();
heightSizingMode = SizingMode::FitContent;
} else {
height = ownerHeight;

View File

@@ -32,8 +32,9 @@ FlexLine calculateFlexLine(
size_t firstElementInLineIndex = startOfLineIndex;
float sizeConsumedIncludingMinConstraint = 0;
const FlexDirection mainAxis = resolveDirection(
node->style().flexDirection(), node->resolveDirection(ownerDirection));
const Direction direction = node->resolveDirection(ownerDirection);
const FlexDirection mainAxis =
resolveDirection(node->style().flexDirection(), direction);
const bool isNodeFlexWrap = node->style().flexWrap() != Wrap::NoWrap;
const float gap =
node->style().computeGapForAxis(mainAxis, availableInnerMainDim);
@@ -67,6 +68,7 @@ FlexLine calculateFlexLine(
const float flexBasisWithMinAndMaxConstraints =
boundAxisWithinMinAndMax(
child,
direction,
mainAxis,
child->getLayout().computedFlexBasis,
mainAxisownerSize)

View File

@@ -156,6 +156,25 @@ class YG_EXPORT Node : public ::YGNode {
return processedDimensions_[static_cast<size_t>(dimension)];
}
FloatOptional getResolvedDimension(
Direction direction,
Dimension dimension,
float referenceLength) const {
FloatOptional value =
getProcessedDimension(dimension).resolve(referenceLength);
if (style_.boxSizing() == BoxSizing::BorderBox) {
return value;
}
FloatOptional dimensionPaddingAndBorder =
FloatOptional{style_.computePaddingAndBorderForDimension(
direction, dimension, referenceLength)};
return value +
(dimensionPaddingAndBorder.isDefined() ? dimensionPaddingAndBorder
: FloatOptional{0.0});
}
// Setters
void setContext(void* context) {

View File

@@ -189,6 +189,23 @@ class YG_EXPORT Style {
pool_.store(minDimensions_[yoga::to_underlying(axis)], value);
}
FloatOptional resolvedMinDimension(
Direction direction,
Dimension axis,
float referenceLength) const {
FloatOptional value = minDimension(axis).resolve(referenceLength);
if (boxSizing() == BoxSizing::BorderBox) {
return value;
}
FloatOptional dimensionPaddingAndBorder = FloatOptional{
computePaddingAndBorderForDimension(direction, axis, referenceLength)};
return value +
(dimensionPaddingAndBorder.isDefined() ? dimensionPaddingAndBorder
: FloatOptional{0.0});
}
Style::Length maxDimension(Dimension axis) const {
return pool_.getLength(maxDimensions_[yoga::to_underlying(axis)]);
}
@@ -196,6 +213,23 @@ class YG_EXPORT Style {
pool_.store(maxDimensions_[yoga::to_underlying(axis)], value);
}
FloatOptional resolvedMaxDimension(
Direction direction,
Dimension axis,
float referenceLength) const {
FloatOptional value = maxDimension(axis).resolve(referenceLength);
if (boxSizing() == BoxSizing::BorderBox) {
return value;
}
FloatOptional dimensionPaddingAndBorder = FloatOptional{
computePaddingAndBorderForDimension(direction, axis, referenceLength)};
return value +
(dimensionPaddingAndBorder.isDefined() ? dimensionPaddingAndBorder
: FloatOptional{0.0});
}
FloatOptional aspectRatio() const {
return pool_.getNumber(aspectRatio_);
}
@@ -446,6 +480,20 @@ class YG_EXPORT Style {
computeFlexEndBorder(axis, direction);
}
float computePaddingAndBorderForDimension(
Direction direction,
Dimension dimension,
float widthSize) const {
FlexDirection flexDirectionForDimension = dimension == Dimension::Width
? FlexDirection::Row
: FlexDirection::Column;
return computeFlexStartPaddingAndBorder(
flexDirectionForDimension, direction, widthSize) +
computeFlexEndPaddingAndBorder(
flexDirectionForDimension, direction, widthSize);
}
float computeBorderForAxis(FlexDirection axis) const {
return computeInlineStartBorder(axis, Direction::LTR) +
computeInlineEndBorder(axis, Direction::LTR);