From b90f6e21bdc64845dc75cfb6662a810547f005e7 Mon Sep 17 00:00:00 2001 From: Lukas Woehrl Date: Tue, 22 Nov 2016 05:33:36 -0800 Subject: [PATCH] Added feature to use rounded values Summary: Added an experimental feature to allow to use only rounded values. See #184. It's not a perfect solution and definitely can be further improved. I'm looking forward to your ideas. Closes https://github.com/facebook/css-layout/pull/256 Reviewed By: splhack Differential Revision: D4214168 Pulled By: emilsjolander fbshipit-source-id: 6293352d479b7b4dad258eb3f9e0afaa11cf7236 --- CSSLayout/CSSEnums.h | 1 + CSSLayout/CSSLayout.c | 25 +- CSSLayout/CSSLayout.h | 9 +- .../CSSExperimentalFeature.cs | 1 + enums.py | 4 +- .../csslayout/CSSExperimentalFeature.java | 4 +- tests/CSSLayoutPixelRoundingTest.cpp | 852 ++++++++++++++++++ 7 files changed, 890 insertions(+), 6 deletions(-) create mode 100644 tests/CSSLayoutPixelRoundingTest.cpp diff --git a/CSSLayout/CSSEnums.h b/CSSLayout/CSSEnums.h index 8f9979f5b9..dbcb58e27b 100644 --- a/CSSLayout/CSSEnums.h +++ b/CSSLayout/CSSEnums.h @@ -67,6 +67,7 @@ typedef enum CSSDirection { } CSSDirection; typedef enum CSSExperimentalFeature { + CSSExperimentalFeatureRounding, CSSExperimentalFeatureCount, } CSSExperimentalFeature; diff --git a/CSSLayout/CSSLayout.c b/CSSLayout/CSSLayout.c index 8c07333701..eeb99195f7 100644 --- a/CSSLayout/CSSLayout.c +++ b/CSSLayout/CSSLayout.c @@ -2534,6 +2534,25 @@ bool layoutNodeInternal(const CSSNodeRef node, return (needToVisitNode || cachedResults == NULL); } +static void roundToPixelGrid(const CSSNodeRef node) { + const float fractialLeft = + node->layout.position[CSSEdgeLeft] - floorf(node->layout.position[CSSEdgeLeft]); + const float fractialTop = + node->layout.position[CSSEdgeTop] - floorf(node->layout.position[CSSEdgeTop]); + node->layout.dimensions[CSSDimensionWidth] = + roundf(fractialLeft + node->layout.dimensions[CSSDimensionWidth]) - roundf(fractialLeft); + node->layout.dimensions[CSSDimensionHeight] = + roundf(fractialTop + node->layout.dimensions[CSSDimensionHeight]) - roundf(fractialTop); + + node->layout.position[CSSEdgeLeft] = roundf(node->layout.position[CSSEdgeLeft]); + node->layout.position[CSSEdgeTop] = roundf(node->layout.position[CSSEdgeTop]); + + const uint32_t childCount = CSSNodeListCount(node->children); + for (uint32_t i = 0; i < childCount; i++) { + roundToPixelGrid(CSSNodeGetChild(node, i)); + } +} + void CSSNodeCalculateLayout(const CSSNodeRef node, const float availableWidth, const float availableHeight, @@ -2583,6 +2602,10 @@ void CSSNodeCalculateLayout(const CSSNodeRef node, "l")) { setPosition(node, node->layout.direction); + if (CSSLayoutIsExperimentalFeatureEnabled(CSSExperimentalFeatureRounding)) { + roundToPixelGrid(node); + } + if (gPrintTree) { CSSNodePrint(node, CSSPrintOptionsLayout | CSSPrintOptionsChildren | CSSPrintOptionsStyle); } @@ -2606,7 +2629,7 @@ void CSSLayoutSetExperimentalFeatureEnabled(CSSExperimentalFeature feature, bool experimentalFeatures[feature] = enabled; } -bool CSSLayoutIsExperimentalFeatureEnabled(CSSExperimentalFeature feature) { +inline bool CSSLayoutIsExperimentalFeatureEnabled(CSSExperimentalFeature feature) { return experimentalFeatures[feature]; } diff --git a/CSSLayout/CSSLayout.h b/CSSLayout/CSSLayout.h index 7bcc244e9a..e2dca0a727 100644 --- a/CSSLayout/CSSLayout.h +++ b/CSSLayout/CSSLayout.h @@ -152,9 +152,12 @@ CSS_NODE_STYLE_PROPERTY(float, MaxHeight, maxHeight); // Yoga specific properties, not compatible with flexbox specification // Aspect ratio control the size of the undefined dimension of a node. // - On a node with a set width/height aspect ratio control the size of the unset dimension -// - On a node with a set flex basis aspect ratio controls the size of the node in the cross axis if unset -// - On a node with a measure function aspect ratio works as though the measure function measures the flex basis -// - On a node with flex grow/shrink aspect ratio controls the size of the node in the cross axis if unset +// - On a node with a set flex basis aspect ratio controls the size of the node in the cross axis if +// unset +// - On a node with a measure function aspect ratio works as though the measure function measures +// the flex basis +// - On a node with flex grow/shrink aspect ratio controls the size of the node in the cross axis if +// unset // - Aspect ratio takes min/max dimensions into account CSS_NODE_STYLE_PROPERTY(float, AspectRatio, aspectRatio); diff --git a/csharp/Facebook.CSSLayout/CSSExperimentalFeature.cs b/csharp/Facebook.CSSLayout/CSSExperimentalFeature.cs index bd0809320c..9eb743091d 100644 --- a/csharp/Facebook.CSSLayout/CSSExperimentalFeature.cs +++ b/csharp/Facebook.CSSLayout/CSSExperimentalFeature.cs @@ -11,5 +11,6 @@ namespace Facebook.CSSLayout { public enum CSSExperimentalFeature { + Rounding, } } diff --git a/enums.py b/enums.py index 40f36d5a81..76261b7fa3 100644 --- a/enums.py +++ b/enums.py @@ -77,7 +77,9 @@ 'Debug', 'Verbose', ], - 'CSSExperimentalFeature': [], + 'CSSExperimentalFeature': [ + 'Rounding', + ], 'CSSPrintOptions': [ ('Layout', 1), ('Style', 2), diff --git a/java/com/facebook/csslayout/CSSExperimentalFeature.java b/java/com/facebook/csslayout/CSSExperimentalFeature.java index e0b269f9af..c2b8b7af22 100644 --- a/java/com/facebook/csslayout/CSSExperimentalFeature.java +++ b/java/com/facebook/csslayout/CSSExperimentalFeature.java @@ -10,7 +10,8 @@ package com.facebook.csslayout; public enum CSSExperimentalFeature { -__EMPTY(-1); + ROUNDING(0); + private int mIntValue; CSSExperimentalFeature(int intValue) { @@ -23,6 +24,7 @@ public int intValue() { public static CSSExperimentalFeature fromInt(int value) { switch (value) { + case 0: return ROUNDING; default: throw new IllegalArgumentException("Unkown enum value: " + value); } } diff --git a/tests/CSSLayoutPixelRoundingTest.cpp b/tests/CSSLayoutPixelRoundingTest.cpp new file mode 100644 index 0000000000..8fb3c73a58 --- /dev/null +++ b/tests/CSSLayoutPixelRoundingTest.cpp @@ -0,0 +1,852 @@ +/** + * Copyright (c) 2014-present, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + */ + +/* +* +
+
+
+
+
+ +
+
+
+
+
+
+
+ +
+
+
+
+
+ +
+
+
+
+
+ +
+
+
+
+
+ +
+
+
+
+
+
+
+
+ * + */ + +#include +#include + +class CSSLayoutFeatureRoundingTest : public ::testing::Test { + +protected: + virtual void SetUp() { + CSSLayoutSetExperimentalFeatureEnabled(CSSExperimentalFeatureRounding, true); + } + + virtual void TearDown() { + CSSLayoutSetExperimentalFeatureEnabled(CSSExperimentalFeatureRounding, false); + } +}; + +TEST_F(CSSLayoutFeatureRoundingTest, pixel_rounding_flex_basis_flex_grow_row_width_of_100) { + const CSSNodeRef root = CSSNodeNew(); + CSSNodeStyleSetFlexDirection(root, CSSFlexDirectionRow); + CSSNodeStyleSetWidth(root, 100); + CSSNodeStyleSetHeight(root, 100); + + const CSSNodeRef root_child0 = CSSNodeNew(); + CSSNodeStyleSetFlexGrow(root_child0, 1); + CSSNodeInsertChild(root, root_child0, 0); + + const CSSNodeRef root_child1 = CSSNodeNew(); + CSSNodeStyleSetFlexGrow(root_child1, 1); + CSSNodeInsertChild(root, root_child1, 1); + + const CSSNodeRef root_child2 = CSSNodeNew(); + CSSNodeStyleSetFlexGrow(root_child2, 1); + CSSNodeInsertChild(root, root_child2, 2); + CSSNodeCalculateLayout(root, CSSUndefined, CSSUndefined, CSSDirectionLTR); + + ASSERT_FLOAT_EQ(0, CSSNodeLayoutGetLeft(root)); + ASSERT_FLOAT_EQ(0, CSSNodeLayoutGetTop(root)); + ASSERT_FLOAT_EQ(100, CSSNodeLayoutGetWidth(root)); + ASSERT_FLOAT_EQ(100, CSSNodeLayoutGetHeight(root)); + + ASSERT_FLOAT_EQ(0, CSSNodeLayoutGetLeft(root_child0)); + ASSERT_FLOAT_EQ(0, CSSNodeLayoutGetTop(root_child0)); + ASSERT_FLOAT_EQ(33, CSSNodeLayoutGetWidth(root_child0)); + ASSERT_FLOAT_EQ(100, CSSNodeLayoutGetHeight(root_child0)); + + ASSERT_FLOAT_EQ(33, CSSNodeLayoutGetLeft(root_child1)); + ASSERT_FLOAT_EQ(0, CSSNodeLayoutGetTop(root_child1)); + ASSERT_FLOAT_EQ(34, CSSNodeLayoutGetWidth(root_child1)); + ASSERT_FLOAT_EQ(100, CSSNodeLayoutGetHeight(root_child1)); + + ASSERT_FLOAT_EQ(67, CSSNodeLayoutGetLeft(root_child2)); + ASSERT_FLOAT_EQ(0, CSSNodeLayoutGetTop(root_child2)); + ASSERT_FLOAT_EQ(33, CSSNodeLayoutGetWidth(root_child2)); + ASSERT_FLOAT_EQ(100, CSSNodeLayoutGetHeight(root_child2)); + + CSSNodeCalculateLayout(root, CSSUndefined, CSSUndefined, CSSDirectionRTL); + + ASSERT_FLOAT_EQ(0, CSSNodeLayoutGetLeft(root)); + ASSERT_FLOAT_EQ(0, CSSNodeLayoutGetTop(root)); + ASSERT_FLOAT_EQ(100, CSSNodeLayoutGetWidth(root)); + ASSERT_FLOAT_EQ(100, CSSNodeLayoutGetHeight(root)); + + ASSERT_FLOAT_EQ(67, CSSNodeLayoutGetLeft(root_child0)); + ASSERT_FLOAT_EQ(0, CSSNodeLayoutGetTop(root_child0)); + ASSERT_FLOAT_EQ(33, CSSNodeLayoutGetWidth(root_child0)); + ASSERT_FLOAT_EQ(100, CSSNodeLayoutGetHeight(root_child0)); + + ASSERT_FLOAT_EQ(33, CSSNodeLayoutGetLeft(root_child1)); + ASSERT_FLOAT_EQ(0, CSSNodeLayoutGetTop(root_child1)); + ASSERT_FLOAT_EQ(34, CSSNodeLayoutGetWidth(root_child1)); + ASSERT_FLOAT_EQ(100, CSSNodeLayoutGetHeight(root_child1)); + + ASSERT_FLOAT_EQ(0, CSSNodeLayoutGetLeft(root_child2)); + ASSERT_FLOAT_EQ(0, CSSNodeLayoutGetTop(root_child2)); + ASSERT_FLOAT_EQ(33, CSSNodeLayoutGetWidth(root_child2)); + ASSERT_FLOAT_EQ(100, CSSNodeLayoutGetHeight(root_child2)); + + CSSNodeFreeRecursive(root); +} + +TEST_F(CSSLayoutFeatureRoundingTest, pixel_rounding_flex_basis_flex_grow_row_prime_number_width) { + const CSSNodeRef root = CSSNodeNew(); + CSSNodeStyleSetFlexDirection(root, CSSFlexDirectionRow); + CSSNodeStyleSetWidth(root, 113); + CSSNodeStyleSetHeight(root, 100); + + const CSSNodeRef root_child0 = CSSNodeNew(); + CSSNodeStyleSetFlexGrow(root_child0, 1); + CSSNodeInsertChild(root, root_child0, 0); + + const CSSNodeRef root_child1 = CSSNodeNew(); + CSSNodeStyleSetFlexGrow(root_child1, 1); + CSSNodeInsertChild(root, root_child1, 1); + + const CSSNodeRef root_child2 = CSSNodeNew(); + CSSNodeStyleSetFlexGrow(root_child2, 1); + CSSNodeInsertChild(root, root_child2, 2); + + const CSSNodeRef root_child3 = CSSNodeNew(); + CSSNodeStyleSetFlexGrow(root_child3, 1); + CSSNodeInsertChild(root, root_child3, 3); + + const CSSNodeRef root_child4 = CSSNodeNew(); + CSSNodeStyleSetFlexGrow(root_child4, 1); + CSSNodeInsertChild(root, root_child4, 4); + CSSNodeCalculateLayout(root, CSSUndefined, CSSUndefined, CSSDirectionLTR); + + ASSERT_FLOAT_EQ(0, CSSNodeLayoutGetLeft(root)); + ASSERT_FLOAT_EQ(0, CSSNodeLayoutGetTop(root)); + ASSERT_FLOAT_EQ(113, CSSNodeLayoutGetWidth(root)); + ASSERT_FLOAT_EQ(100, CSSNodeLayoutGetHeight(root)); + + ASSERT_FLOAT_EQ(0, CSSNodeLayoutGetLeft(root_child0)); + ASSERT_FLOAT_EQ(0, CSSNodeLayoutGetTop(root_child0)); + ASSERT_FLOAT_EQ(23, CSSNodeLayoutGetWidth(root_child0)); + ASSERT_FLOAT_EQ(100, CSSNodeLayoutGetHeight(root_child0)); + + ASSERT_FLOAT_EQ(23, CSSNodeLayoutGetLeft(root_child1)); + ASSERT_FLOAT_EQ(0, CSSNodeLayoutGetTop(root_child1)); + ASSERT_FLOAT_EQ(22, CSSNodeLayoutGetWidth(root_child1)); + ASSERT_FLOAT_EQ(100, CSSNodeLayoutGetHeight(root_child1)); + + ASSERT_FLOAT_EQ(45, CSSNodeLayoutGetLeft(root_child2)); + ASSERT_FLOAT_EQ(0, CSSNodeLayoutGetTop(root_child2)); + ASSERT_FLOAT_EQ(23, CSSNodeLayoutGetWidth(root_child2)); + ASSERT_FLOAT_EQ(100, CSSNodeLayoutGetHeight(root_child2)); + + ASSERT_FLOAT_EQ(68, CSSNodeLayoutGetLeft(root_child3)); + ASSERT_FLOAT_EQ(0, CSSNodeLayoutGetTop(root_child3)); + ASSERT_FLOAT_EQ(22, CSSNodeLayoutGetWidth(root_child3)); + ASSERT_FLOAT_EQ(100, CSSNodeLayoutGetHeight(root_child3)); + + ASSERT_FLOAT_EQ(90, CSSNodeLayoutGetLeft(root_child4)); + ASSERT_FLOAT_EQ(0, CSSNodeLayoutGetTop(root_child4)); + ASSERT_FLOAT_EQ(23, CSSNodeLayoutGetWidth(root_child4)); + ASSERT_FLOAT_EQ(100, CSSNodeLayoutGetHeight(root_child4)); + + CSSNodeCalculateLayout(root, CSSUndefined, CSSUndefined, CSSDirectionRTL); + + ASSERT_FLOAT_EQ(0, CSSNodeLayoutGetLeft(root)); + ASSERT_FLOAT_EQ(0, CSSNodeLayoutGetTop(root)); + ASSERT_FLOAT_EQ(113, CSSNodeLayoutGetWidth(root)); + ASSERT_FLOAT_EQ(100, CSSNodeLayoutGetHeight(root)); + + ASSERT_FLOAT_EQ(90, CSSNodeLayoutGetLeft(root_child0)); + ASSERT_FLOAT_EQ(0, CSSNodeLayoutGetTop(root_child0)); + ASSERT_FLOAT_EQ(23, CSSNodeLayoutGetWidth(root_child0)); + ASSERT_FLOAT_EQ(100, CSSNodeLayoutGetHeight(root_child0)); + + ASSERT_FLOAT_EQ(68, CSSNodeLayoutGetLeft(root_child1)); + ASSERT_FLOAT_EQ(0, CSSNodeLayoutGetTop(root_child1)); + ASSERT_FLOAT_EQ(22, CSSNodeLayoutGetWidth(root_child1)); + ASSERT_FLOAT_EQ(100, CSSNodeLayoutGetHeight(root_child1)); + + ASSERT_FLOAT_EQ(45, CSSNodeLayoutGetLeft(root_child2)); + ASSERT_FLOAT_EQ(0, CSSNodeLayoutGetTop(root_child2)); + ASSERT_FLOAT_EQ(23, CSSNodeLayoutGetWidth(root_child2)); + ASSERT_FLOAT_EQ(100, CSSNodeLayoutGetHeight(root_child2)); + + ASSERT_FLOAT_EQ(23, CSSNodeLayoutGetLeft(root_child3)); + ASSERT_FLOAT_EQ(0, CSSNodeLayoutGetTop(root_child3)); + ASSERT_FLOAT_EQ(22, CSSNodeLayoutGetWidth(root_child3)); + ASSERT_FLOAT_EQ(100, CSSNodeLayoutGetHeight(root_child3)); + + ASSERT_FLOAT_EQ(0, CSSNodeLayoutGetLeft(root_child4)); + ASSERT_FLOAT_EQ(0, CSSNodeLayoutGetTop(root_child4)); + ASSERT_FLOAT_EQ(23, CSSNodeLayoutGetWidth(root_child4)); + ASSERT_FLOAT_EQ(100, CSSNodeLayoutGetHeight(root_child4)); + + CSSNodeFreeRecursive(root); +} + +TEST_F(CSSLayoutFeatureRoundingTest, pixel_rounding_flex_basis_flex_shrink_row) { + const CSSNodeRef root = CSSNodeNew(); + CSSNodeStyleSetFlexDirection(root, CSSFlexDirectionRow); + CSSNodeStyleSetWidth(root, 101); + CSSNodeStyleSetHeight(root, 100); + + const CSSNodeRef root_child0 = CSSNodeNew(); + CSSNodeStyleSetFlexShrink(root_child0, 1); + CSSNodeStyleSetFlexBasis(root_child0, 100); + CSSNodeInsertChild(root, root_child0, 0); + + const CSSNodeRef root_child1 = CSSNodeNew(); + CSSNodeStyleSetFlexBasis(root_child1, 25); + CSSNodeInsertChild(root, root_child1, 1); + + const CSSNodeRef root_child2 = CSSNodeNew(); + CSSNodeStyleSetFlexBasis(root_child2, 25); + CSSNodeInsertChild(root, root_child2, 2); + CSSNodeCalculateLayout(root, CSSUndefined, CSSUndefined, CSSDirectionLTR); + + ASSERT_FLOAT_EQ(0, CSSNodeLayoutGetLeft(root)); + ASSERT_FLOAT_EQ(0, CSSNodeLayoutGetTop(root)); + ASSERT_FLOAT_EQ(101, CSSNodeLayoutGetWidth(root)); + ASSERT_FLOAT_EQ(100, CSSNodeLayoutGetHeight(root)); + + ASSERT_FLOAT_EQ(0, CSSNodeLayoutGetLeft(root_child0)); + ASSERT_FLOAT_EQ(0, CSSNodeLayoutGetTop(root_child0)); + ASSERT_FLOAT_EQ(51, CSSNodeLayoutGetWidth(root_child0)); + ASSERT_FLOAT_EQ(100, CSSNodeLayoutGetHeight(root_child0)); + + ASSERT_FLOAT_EQ(51, CSSNodeLayoutGetLeft(root_child1)); + ASSERT_FLOAT_EQ(0, CSSNodeLayoutGetTop(root_child1)); + ASSERT_FLOAT_EQ(25, CSSNodeLayoutGetWidth(root_child1)); + ASSERT_FLOAT_EQ(100, CSSNodeLayoutGetHeight(root_child1)); + + ASSERT_FLOAT_EQ(76, CSSNodeLayoutGetLeft(root_child2)); + ASSERT_FLOAT_EQ(0, CSSNodeLayoutGetTop(root_child2)); + ASSERT_FLOAT_EQ(25, CSSNodeLayoutGetWidth(root_child2)); + ASSERT_FLOAT_EQ(100, CSSNodeLayoutGetHeight(root_child2)); + + CSSNodeCalculateLayout(root, CSSUndefined, CSSUndefined, CSSDirectionRTL); + + ASSERT_FLOAT_EQ(0, CSSNodeLayoutGetLeft(root)); + ASSERT_FLOAT_EQ(0, CSSNodeLayoutGetTop(root)); + ASSERT_FLOAT_EQ(101, CSSNodeLayoutGetWidth(root)); + ASSERT_FLOAT_EQ(100, CSSNodeLayoutGetHeight(root)); + + ASSERT_FLOAT_EQ(50, CSSNodeLayoutGetLeft(root_child0)); + ASSERT_FLOAT_EQ(0, CSSNodeLayoutGetTop(root_child0)); + ASSERT_FLOAT_EQ(51, CSSNodeLayoutGetWidth(root_child0)); + ASSERT_FLOAT_EQ(100, CSSNodeLayoutGetHeight(root_child0)); + + ASSERT_FLOAT_EQ(25, CSSNodeLayoutGetLeft(root_child1)); + ASSERT_FLOAT_EQ(0, CSSNodeLayoutGetTop(root_child1)); + ASSERT_FLOAT_EQ(25, CSSNodeLayoutGetWidth(root_child1)); + ASSERT_FLOAT_EQ(100, CSSNodeLayoutGetHeight(root_child1)); + + ASSERT_FLOAT_EQ(0, CSSNodeLayoutGetLeft(root_child2)); + ASSERT_FLOAT_EQ(0, CSSNodeLayoutGetTop(root_child2)); + ASSERT_FLOAT_EQ(25, CSSNodeLayoutGetWidth(root_child2)); + ASSERT_FLOAT_EQ(100, CSSNodeLayoutGetHeight(root_child2)); + + CSSNodeFreeRecursive(root); +} + + +TEST_F(CSSLayoutFeatureRoundingTest, pixel_roundingflex_basis_overrides_main_size) { + const CSSNodeRef root = CSSNodeNew(); + CSSNodeStyleSetWidth(root, 100); + CSSNodeStyleSetHeight(root, 113); + + const CSSNodeRef root_child0 = CSSNodeNew(); + CSSNodeStyleSetFlexGrow(root_child0, 1); + CSSNodeStyleSetFlexBasis(root_child0, 50); + CSSNodeStyleSetHeight(root_child0, 20); + CSSNodeInsertChild(root, root_child0, 0); + + const CSSNodeRef root_child1 = CSSNodeNew(); + CSSNodeStyleSetFlexGrow(root_child1, 1); + CSSNodeStyleSetHeight(root_child1, 10); + CSSNodeInsertChild(root, root_child1, 1); + + const CSSNodeRef root_child2 = CSSNodeNew(); + CSSNodeStyleSetFlexGrow(root_child2, 1); + CSSNodeStyleSetHeight(root_child2, 10); + CSSNodeInsertChild(root, root_child2, 2); + CSSNodeCalculateLayout(root, CSSUndefined, CSSUndefined, CSSDirectionLTR); + + ASSERT_EQ(0, CSSNodeLayoutGetLeft(root)); + ASSERT_EQ(0, CSSNodeLayoutGetTop(root)); + ASSERT_EQ(100, CSSNodeLayoutGetWidth(root)); + ASSERT_EQ(113, CSSNodeLayoutGetHeight(root)); + + ASSERT_EQ(0, CSSNodeLayoutGetLeft(root_child0)); + ASSERT_EQ(0, CSSNodeLayoutGetTop(root_child0)); + ASSERT_EQ(100, CSSNodeLayoutGetWidth(root_child0)); + ASSERT_EQ(64, CSSNodeLayoutGetHeight(root_child0)); + + ASSERT_EQ(0, CSSNodeLayoutGetLeft(root_child1)); + ASSERT_EQ(64, CSSNodeLayoutGetTop(root_child1)); + ASSERT_EQ(100, CSSNodeLayoutGetWidth(root_child1)); + ASSERT_EQ(25, CSSNodeLayoutGetHeight(root_child1)); + + ASSERT_EQ(0, CSSNodeLayoutGetLeft(root_child2)); + ASSERT_EQ(89, CSSNodeLayoutGetTop(root_child2)); + ASSERT_EQ(100, CSSNodeLayoutGetWidth(root_child2)); + ASSERT_EQ(24, CSSNodeLayoutGetHeight(root_child2)); + + CSSNodeCalculateLayout(root, CSSUndefined, CSSUndefined, CSSDirectionRTL); + + ASSERT_EQ(0, CSSNodeLayoutGetLeft(root)); + ASSERT_EQ(0, CSSNodeLayoutGetTop(root)); + ASSERT_EQ(100, CSSNodeLayoutGetWidth(root)); + ASSERT_EQ(113, CSSNodeLayoutGetHeight(root)); + + ASSERT_EQ(0, CSSNodeLayoutGetLeft(root_child0)); + ASSERT_EQ(0, CSSNodeLayoutGetTop(root_child0)); + ASSERT_EQ(100, CSSNodeLayoutGetWidth(root_child0)); + ASSERT_EQ(64, CSSNodeLayoutGetHeight(root_child0)); + + ASSERT_EQ(0, CSSNodeLayoutGetLeft(root_child1)); + ASSERT_EQ(64, CSSNodeLayoutGetTop(root_child1)); + ASSERT_EQ(100, CSSNodeLayoutGetWidth(root_child1)); + ASSERT_EQ(25, CSSNodeLayoutGetHeight(root_child1)); + + ASSERT_EQ(0, CSSNodeLayoutGetLeft(root_child2)); + ASSERT_EQ(89, CSSNodeLayoutGetTop(root_child2)); + ASSERT_EQ(100, CSSNodeLayoutGetWidth(root_child2)); + ASSERT_EQ(24, CSSNodeLayoutGetHeight(root_child2)); + + CSSNodeFreeRecursive(root); +} + +TEST_F(CSSLayoutFeatureRoundingTest, flex_basis_overrides_main_size_1) { + const CSSNodeRef root = CSSNodeNew(); + CSSNodeStyleSetWidth(root, 100); + CSSNodeStyleSetHeight(root, 113.4f); + + const CSSNodeRef root_child0 = CSSNodeNew(); + CSSNodeStyleSetFlexGrow(root_child0, 1); + CSSNodeStyleSetFlexBasis(root_child0, 50); + CSSNodeStyleSetHeight(root_child0, 20); + CSSNodeInsertChild(root, root_child0, 0); + + const CSSNodeRef root_child1 = CSSNodeNew(); + CSSNodeStyleSetFlexGrow(root_child1, 1); + CSSNodeStyleSetHeight(root_child1, 10); + CSSNodeInsertChild(root, root_child1, 1); + + const CSSNodeRef root_child2 = CSSNodeNew(); + CSSNodeStyleSetFlexGrow(root_child2, 1); + CSSNodeStyleSetHeight(root_child2, 10); + CSSNodeInsertChild(root, root_child2, 2); + CSSNodeCalculateLayout(root, CSSUndefined, CSSUndefined, CSSDirectionLTR); + + ASSERT_FLOAT_EQ(0, CSSNodeLayoutGetLeft(root)); + ASSERT_FLOAT_EQ(0, CSSNodeLayoutGetTop(root)); + ASSERT_FLOAT_EQ(100, CSSNodeLayoutGetWidth(root)); + ASSERT_FLOAT_EQ(113, CSSNodeLayoutGetHeight(root)); + + ASSERT_FLOAT_EQ(0, CSSNodeLayoutGetLeft(root_child0)); + ASSERT_FLOAT_EQ(0, CSSNodeLayoutGetTop(root_child0)); + ASSERT_FLOAT_EQ(100, CSSNodeLayoutGetWidth(root_child0)); + ASSERT_FLOAT_EQ(64, CSSNodeLayoutGetHeight(root_child0)); + + ASSERT_FLOAT_EQ(0, CSSNodeLayoutGetLeft(root_child1)); + ASSERT_FLOAT_EQ(64, CSSNodeLayoutGetTop(root_child1)); + ASSERT_FLOAT_EQ(100, CSSNodeLayoutGetWidth(root_child1)); + ASSERT_FLOAT_EQ(25, CSSNodeLayoutGetHeight(root_child1)); + + ASSERT_FLOAT_EQ(0, CSSNodeLayoutGetLeft(root_child2)); + ASSERT_FLOAT_EQ(89, CSSNodeLayoutGetTop(root_child2)); + ASSERT_FLOAT_EQ(100, CSSNodeLayoutGetWidth(root_child2)); + ASSERT_FLOAT_EQ(24, CSSNodeLayoutGetHeight(root_child2)); + + CSSNodeCalculateLayout(root, CSSUndefined, CSSUndefined, CSSDirectionRTL); + + ASSERT_FLOAT_EQ(0, CSSNodeLayoutGetLeft(root)); + ASSERT_FLOAT_EQ(0, CSSNodeLayoutGetTop(root)); + ASSERT_FLOAT_EQ(100, CSSNodeLayoutGetWidth(root)); + ASSERT_FLOAT_EQ(113, CSSNodeLayoutGetHeight(root)); + + ASSERT_FLOAT_EQ(0, CSSNodeLayoutGetLeft(root_child0)); + ASSERT_FLOAT_EQ(0, CSSNodeLayoutGetTop(root_child0)); + ASSERT_FLOAT_EQ(100, CSSNodeLayoutGetWidth(root_child0)); + ASSERT_FLOAT_EQ(64, CSSNodeLayoutGetHeight(root_child0)); + + ASSERT_FLOAT_EQ(0, CSSNodeLayoutGetLeft(root_child1)); + ASSERT_FLOAT_EQ(64, CSSNodeLayoutGetTop(root_child1)); + ASSERT_FLOAT_EQ(100, CSSNodeLayoutGetWidth(root_child1)); + ASSERT_FLOAT_EQ(25, CSSNodeLayoutGetHeight(root_child1)); + + ASSERT_FLOAT_EQ(0, CSSNodeLayoutGetLeft(root_child2)); + ASSERT_FLOAT_EQ(89, CSSNodeLayoutGetTop(root_child2)); + ASSERT_FLOAT_EQ(100, CSSNodeLayoutGetWidth(root_child2)); + ASSERT_FLOAT_EQ(24, CSSNodeLayoutGetHeight(root_child2)); + + CSSNodeFreeRecursive(root); +} + +TEST_F(CSSLayoutFeatureRoundingTest, flex_basis_overrides_main_size_2) { + const CSSNodeRef root = CSSNodeNew(); + CSSNodeStyleSetWidth(root, 100); + CSSNodeStyleSetHeight(root, 113.6f); + + const CSSNodeRef root_child0 = CSSNodeNew(); + CSSNodeStyleSetFlexGrow(root_child0, 1); + CSSNodeStyleSetFlexBasis(root_child0, 50); + CSSNodeStyleSetHeight(root_child0, 20); + CSSNodeInsertChild(root, root_child0, 0); + + const CSSNodeRef root_child1 = CSSNodeNew(); + CSSNodeStyleSetFlexGrow(root_child1, 1); + CSSNodeStyleSetHeight(root_child1, 10); + CSSNodeInsertChild(root, root_child1, 1); + + const CSSNodeRef root_child2 = CSSNodeNew(); + CSSNodeStyleSetFlexGrow(root_child2, 1); + CSSNodeStyleSetHeight(root_child2, 10); + CSSNodeInsertChild(root, root_child2, 2); + CSSNodeCalculateLayout(root, CSSUndefined, CSSUndefined, CSSDirectionLTR); + + ASSERT_FLOAT_EQ(0, CSSNodeLayoutGetLeft(root)); + ASSERT_FLOAT_EQ(0, CSSNodeLayoutGetTop(root)); + ASSERT_FLOAT_EQ(100, CSSNodeLayoutGetWidth(root)); + ASSERT_FLOAT_EQ(114, CSSNodeLayoutGetHeight(root)); + + ASSERT_FLOAT_EQ(0, CSSNodeLayoutGetLeft(root_child0)); + ASSERT_FLOAT_EQ(0, CSSNodeLayoutGetTop(root_child0)); + ASSERT_FLOAT_EQ(100, CSSNodeLayoutGetWidth(root_child0)); + ASSERT_FLOAT_EQ(65, CSSNodeLayoutGetHeight(root_child0)); + + ASSERT_FLOAT_EQ(0, CSSNodeLayoutGetLeft(root_child1)); + ASSERT_FLOAT_EQ(65, CSSNodeLayoutGetTop(root_child1)); + ASSERT_FLOAT_EQ(100, CSSNodeLayoutGetWidth(root_child1)); + ASSERT_FLOAT_EQ(24, CSSNodeLayoutGetHeight(root_child1)); + + ASSERT_FLOAT_EQ(0, CSSNodeLayoutGetLeft(root_child2)); + ASSERT_FLOAT_EQ(89, CSSNodeLayoutGetTop(root_child2)); + ASSERT_FLOAT_EQ(100, CSSNodeLayoutGetWidth(root_child2)); + ASSERT_FLOAT_EQ(25, CSSNodeLayoutGetHeight(root_child2)); + + CSSNodeCalculateLayout(root, CSSUndefined, CSSUndefined, CSSDirectionRTL); + + ASSERT_FLOAT_EQ(0, CSSNodeLayoutGetLeft(root)); + ASSERT_FLOAT_EQ(0, CSSNodeLayoutGetTop(root)); + ASSERT_FLOAT_EQ(100, CSSNodeLayoutGetWidth(root)); + ASSERT_FLOAT_EQ(114, CSSNodeLayoutGetHeight(root)); + + ASSERT_FLOAT_EQ(0, CSSNodeLayoutGetLeft(root_child0)); + ASSERT_FLOAT_EQ(0, CSSNodeLayoutGetTop(root_child0)); + ASSERT_FLOAT_EQ(100, CSSNodeLayoutGetWidth(root_child0)); + ASSERT_FLOAT_EQ(65, CSSNodeLayoutGetHeight(root_child0)); + + ASSERT_FLOAT_EQ(0, CSSNodeLayoutGetLeft(root_child1)); + ASSERT_FLOAT_EQ(65, CSSNodeLayoutGetTop(root_child1)); + ASSERT_FLOAT_EQ(100, CSSNodeLayoutGetWidth(root_child1)); + ASSERT_FLOAT_EQ(24, CSSNodeLayoutGetHeight(root_child1)); + + ASSERT_FLOAT_EQ(0, CSSNodeLayoutGetLeft(root_child2)); + ASSERT_FLOAT_EQ(89, CSSNodeLayoutGetTop(root_child2)); + ASSERT_FLOAT_EQ(100, CSSNodeLayoutGetWidth(root_child2)); + ASSERT_FLOAT_EQ(25, CSSNodeLayoutGetHeight(root_child2)); + + CSSNodeFreeRecursive(root); +} + +TEST_F(CSSLayoutFeatureRoundingTest, flex_basis_overrides_main_size_3) { + const CSSNodeRef root = CSSNodeNew(); + CSSNodeStyleSetPosition(root, CSSEdgeTop, 0.3f); + CSSNodeStyleSetWidth(root, 100); + CSSNodeStyleSetHeight(root, 113.4f); + + const CSSNodeRef root_child0 = CSSNodeNew(); + CSSNodeStyleSetFlexGrow(root_child0, 1); + CSSNodeStyleSetFlexBasis(root_child0, 50); + CSSNodeStyleSetHeight(root_child0, 20); + CSSNodeInsertChild(root, root_child0, 0); + + const CSSNodeRef root_child1 = CSSNodeNew(); + CSSNodeStyleSetFlexGrow(root_child1, 1); + CSSNodeStyleSetHeight(root_child1, 10); + CSSNodeInsertChild(root, root_child1, 1); + + const CSSNodeRef root_child2 = CSSNodeNew(); + CSSNodeStyleSetFlexGrow(root_child2, 1); + CSSNodeStyleSetHeight(root_child2, 10); + CSSNodeInsertChild(root, root_child2, 2); + CSSNodeCalculateLayout(root, CSSUndefined, CSSUndefined, CSSDirectionLTR); + + ASSERT_FLOAT_EQ(0, CSSNodeLayoutGetLeft(root)); + ASSERT_FLOAT_EQ(0, CSSNodeLayoutGetTop(root)); + ASSERT_FLOAT_EQ(100, CSSNodeLayoutGetWidth(root)); + ASSERT_FLOAT_EQ(114, CSSNodeLayoutGetHeight(root)); + + ASSERT_FLOAT_EQ(0, CSSNodeLayoutGetLeft(root_child0)); + ASSERT_FLOAT_EQ(0, CSSNodeLayoutGetTop(root_child0)); + ASSERT_FLOAT_EQ(100, CSSNodeLayoutGetWidth(root_child0)); + ASSERT_FLOAT_EQ(64, CSSNodeLayoutGetHeight(root_child0)); + + ASSERT_FLOAT_EQ(0, CSSNodeLayoutGetLeft(root_child1)); + ASSERT_FLOAT_EQ(64, CSSNodeLayoutGetTop(root_child1)); + ASSERT_FLOAT_EQ(100, CSSNodeLayoutGetWidth(root_child1)); + ASSERT_FLOAT_EQ(25, CSSNodeLayoutGetHeight(root_child1)); + + ASSERT_FLOAT_EQ(0, CSSNodeLayoutGetLeft(root_child2)); + ASSERT_FLOAT_EQ(89, CSSNodeLayoutGetTop(root_child2)); + ASSERT_FLOAT_EQ(100, CSSNodeLayoutGetWidth(root_child2)); + ASSERT_FLOAT_EQ(24, CSSNodeLayoutGetHeight(root_child2)); + + CSSNodeCalculateLayout(root, CSSUndefined, CSSUndefined, CSSDirectionRTL); + + ASSERT_FLOAT_EQ(0, CSSNodeLayoutGetLeft(root)); + ASSERT_FLOAT_EQ(0, CSSNodeLayoutGetTop(root)); + ASSERT_FLOAT_EQ(100, CSSNodeLayoutGetWidth(root)); + ASSERT_FLOAT_EQ(114, CSSNodeLayoutGetHeight(root)); + + ASSERT_FLOAT_EQ(0, CSSNodeLayoutGetLeft(root_child0)); + ASSERT_FLOAT_EQ(0, CSSNodeLayoutGetTop(root_child0)); + ASSERT_FLOAT_EQ(100, CSSNodeLayoutGetWidth(root_child0)); + ASSERT_FLOAT_EQ(64, CSSNodeLayoutGetHeight(root_child0)); + + ASSERT_FLOAT_EQ(0, CSSNodeLayoutGetLeft(root_child1)); + ASSERT_FLOAT_EQ(64, CSSNodeLayoutGetTop(root_child1)); + ASSERT_FLOAT_EQ(100, CSSNodeLayoutGetWidth(root_child1)); + ASSERT_FLOAT_EQ(25, CSSNodeLayoutGetHeight(root_child1)); + + ASSERT_FLOAT_EQ(0, CSSNodeLayoutGetLeft(root_child2)); + ASSERT_FLOAT_EQ(89, CSSNodeLayoutGetTop(root_child2)); + ASSERT_FLOAT_EQ(100, CSSNodeLayoutGetWidth(root_child2)); + ASSERT_FLOAT_EQ(24, CSSNodeLayoutGetHeight(root_child2)); + + CSSNodeFreeRecursive(root); +} + +TEST_F(CSSLayoutFeatureRoundingTest, flex_basis_overrides_main_size_4) { + const CSSNodeRef root = CSSNodeNew(); + CSSNodeStyleSetPosition(root, CSSEdgeTop, 0.7f); + CSSNodeStyleSetWidth(root, 100); + CSSNodeStyleSetHeight(root, 113.4f); + + const CSSNodeRef root_child0 = CSSNodeNew(); + CSSNodeStyleSetFlexGrow(root_child0, 1); + CSSNodeStyleSetFlexBasis(root_child0, 50); + CSSNodeStyleSetHeight(root_child0, 20); + CSSNodeInsertChild(root, root_child0, 0); + + const CSSNodeRef root_child1 = CSSNodeNew(); + CSSNodeStyleSetFlexGrow(root_child1, 1); + CSSNodeStyleSetHeight(root_child1, 10); + CSSNodeInsertChild(root, root_child1, 1); + + const CSSNodeRef root_child2 = CSSNodeNew(); + CSSNodeStyleSetFlexGrow(root_child2, 1); + CSSNodeStyleSetHeight(root_child2, 10); + CSSNodeInsertChild(root, root_child2, 2); + CSSNodeCalculateLayout(root, CSSUndefined, CSSUndefined, CSSDirectionLTR); + + ASSERT_FLOAT_EQ(0, CSSNodeLayoutGetLeft(root)); + ASSERT_FLOAT_EQ(1, CSSNodeLayoutGetTop(root)); + ASSERT_FLOAT_EQ(100, CSSNodeLayoutGetWidth(root)); + ASSERT_FLOAT_EQ(113, CSSNodeLayoutGetHeight(root)); + + ASSERT_FLOAT_EQ(0, CSSNodeLayoutGetLeft(root_child0)); + ASSERT_FLOAT_EQ(0, CSSNodeLayoutGetTop(root_child0)); + ASSERT_FLOAT_EQ(100, CSSNodeLayoutGetWidth(root_child0)); + ASSERT_FLOAT_EQ(64, CSSNodeLayoutGetHeight(root_child0)); + + ASSERT_FLOAT_EQ(0, CSSNodeLayoutGetLeft(root_child1)); + ASSERT_FLOAT_EQ(64, CSSNodeLayoutGetTop(root_child1)); + ASSERT_FLOAT_EQ(100, CSSNodeLayoutGetWidth(root_child1)); + ASSERT_FLOAT_EQ(25, CSSNodeLayoutGetHeight(root_child1)); + + ASSERT_FLOAT_EQ(0, CSSNodeLayoutGetLeft(root_child2)); + ASSERT_FLOAT_EQ(89, CSSNodeLayoutGetTop(root_child2)); + ASSERT_FLOAT_EQ(100, CSSNodeLayoutGetWidth(root_child2)); + ASSERT_FLOAT_EQ(24, CSSNodeLayoutGetHeight(root_child2)); + + CSSNodeCalculateLayout(root, CSSUndefined, CSSUndefined, CSSDirectionRTL); + + ASSERT_FLOAT_EQ(0, CSSNodeLayoutGetLeft(root)); + ASSERT_FLOAT_EQ(1, CSSNodeLayoutGetTop(root)); + ASSERT_FLOAT_EQ(100, CSSNodeLayoutGetWidth(root)); + ASSERT_FLOAT_EQ(113, CSSNodeLayoutGetHeight(root)); + + ASSERT_FLOAT_EQ(0, CSSNodeLayoutGetLeft(root_child0)); + ASSERT_FLOAT_EQ(0, CSSNodeLayoutGetTop(root_child0)); + ASSERT_FLOAT_EQ(100, CSSNodeLayoutGetWidth(root_child0)); + ASSERT_FLOAT_EQ(64, CSSNodeLayoutGetHeight(root_child0)); + + ASSERT_FLOAT_EQ(0, CSSNodeLayoutGetLeft(root_child1)); + ASSERT_FLOAT_EQ(64, CSSNodeLayoutGetTop(root_child1)); + ASSERT_FLOAT_EQ(100, CSSNodeLayoutGetWidth(root_child1)); + ASSERT_FLOAT_EQ(25, CSSNodeLayoutGetHeight(root_child1)); + + ASSERT_FLOAT_EQ(0, CSSNodeLayoutGetLeft(root_child2)); + ASSERT_FLOAT_EQ(89, CSSNodeLayoutGetTop(root_child2)); + ASSERT_FLOAT_EQ(100, CSSNodeLayoutGetWidth(root_child2)); + ASSERT_FLOAT_EQ(24, CSSNodeLayoutGetHeight(root_child2)); + + CSSNodeFreeRecursive(root); +} + +TEST_F(CSSLayoutFeatureRoundingTest, rounding_feature_total_fractial) { + const CSSNodeRef root = CSSNodeNew(); + CSSNodeStyleSetWidth(root, 87.4f); + CSSNodeStyleSetHeight(root, 113.4f); + + const CSSNodeRef root_child0 = CSSNodeNew(); + CSSNodeStyleSetFlexGrow(root_child0, 0.7f); + CSSNodeStyleSetFlexBasis(root_child0, 50.3f); + CSSNodeStyleSetHeight(root_child0, 20.3f); + CSSNodeInsertChild(root, root_child0, 0); + + const CSSNodeRef root_child1 = CSSNodeNew(); + CSSNodeStyleSetFlexGrow(root_child1, 1.6f); + CSSNodeStyleSetHeight(root_child1, 10); + CSSNodeInsertChild(root, root_child1, 1); + + const CSSNodeRef root_child2 = CSSNodeNew(); + CSSNodeStyleSetFlexGrow(root_child2, 1.1f); + CSSNodeStyleSetHeight(root_child2, 10.7f); + CSSNodeInsertChild(root, root_child2, 2); + CSSNodeCalculateLayout(root, CSSUndefined, CSSUndefined, CSSDirectionLTR); + + ASSERT_FLOAT_EQ(0, CSSNodeLayoutGetLeft(root)); + ASSERT_FLOAT_EQ(0, CSSNodeLayoutGetTop(root)); + ASSERT_FLOAT_EQ(87, CSSNodeLayoutGetWidth(root)); + ASSERT_FLOAT_EQ(113, CSSNodeLayoutGetHeight(root)); + + ASSERT_FLOAT_EQ(0, CSSNodeLayoutGetLeft(root_child0)); + ASSERT_FLOAT_EQ(0, CSSNodeLayoutGetTop(root_child0)); + ASSERT_FLOAT_EQ(87, CSSNodeLayoutGetWidth(root_child0)); + ASSERT_FLOAT_EQ(59, CSSNodeLayoutGetHeight(root_child0)); + + ASSERT_FLOAT_EQ(0, CSSNodeLayoutGetLeft(root_child1)); + ASSERT_FLOAT_EQ(59, CSSNodeLayoutGetTop(root_child1)); + ASSERT_FLOAT_EQ(87, CSSNodeLayoutGetWidth(root_child1)); + ASSERT_FLOAT_EQ(30, CSSNodeLayoutGetHeight(root_child1)); + + ASSERT_FLOAT_EQ(0, CSSNodeLayoutGetLeft(root_child2)); + ASSERT_FLOAT_EQ(89, CSSNodeLayoutGetTop(root_child2)); + ASSERT_FLOAT_EQ(87, CSSNodeLayoutGetWidth(root_child2)); + ASSERT_FLOAT_EQ(24, CSSNodeLayoutGetHeight(root_child2)); + + CSSNodeCalculateLayout(root, CSSUndefined, CSSUndefined, CSSDirectionRTL); + + ASSERT_FLOAT_EQ(0, CSSNodeLayoutGetLeft(root)); + ASSERT_FLOAT_EQ(0, CSSNodeLayoutGetTop(root)); + ASSERT_FLOAT_EQ(87, CSSNodeLayoutGetWidth(root)); + ASSERT_FLOAT_EQ(113, CSSNodeLayoutGetHeight(root)); + + ASSERT_FLOAT_EQ(0, CSSNodeLayoutGetLeft(root_child0)); + ASSERT_FLOAT_EQ(0, CSSNodeLayoutGetTop(root_child0)); + ASSERT_FLOAT_EQ(87, CSSNodeLayoutGetWidth(root_child0)); + ASSERT_FLOAT_EQ(59, CSSNodeLayoutGetHeight(root_child0)); + + ASSERT_FLOAT_EQ(0, CSSNodeLayoutGetLeft(root_child1)); + ASSERT_FLOAT_EQ(59, CSSNodeLayoutGetTop(root_child1)); + ASSERT_FLOAT_EQ(87, CSSNodeLayoutGetWidth(root_child1)); + ASSERT_FLOAT_EQ(30, CSSNodeLayoutGetHeight(root_child1)); + + ASSERT_FLOAT_EQ(0, CSSNodeLayoutGetLeft(root_child2)); + ASSERT_FLOAT_EQ(89, CSSNodeLayoutGetTop(root_child2)); + ASSERT_FLOAT_EQ(87, CSSNodeLayoutGetWidth(root_child2)); + ASSERT_FLOAT_EQ(24, CSSNodeLayoutGetHeight(root_child2)); + + CSSNodeFreeRecursive(root); +} + + +TEST_F(CSSLayoutFeatureRoundingTest, rounding_feature_total_fractial_nested) { + const CSSNodeRef root = CSSNodeNew(); + CSSNodeStyleSetWidth(root, 87.4f); + CSSNodeStyleSetHeight(root, 113.4f); + + const CSSNodeRef root_child0 = CSSNodeNew(); + CSSNodeStyleSetFlexGrow(root_child0, 0.7f); + CSSNodeStyleSetFlexBasis(root_child0, 50.3f); + CSSNodeStyleSetHeight(root_child0, 20.3f); + CSSNodeInsertChild(root, root_child0, 0); + + const CSSNodeRef root_child0_child0 = CSSNodeNew(); + CSSNodeStyleSetFlexGrow(root_child0_child0, 1.2f); + CSSNodeStyleSetFlexBasis(root_child0_child0, 0.3f); + CSSNodeStyleSetPosition(root_child0_child0, CSSEdgeBottom, 13.3f); + CSSNodeStyleSetHeight(root_child0_child0, 9.9f); + CSSNodeInsertChild(root_child0, root_child0_child0, 0); + + const CSSNodeRef root_child0_child1 = CSSNodeNew(); + CSSNodeStyleSetFlexGrow(root_child0_child1, 4.2f); + CSSNodeStyleSetFlexBasis(root_child0_child1, 0.3f); + CSSNodeStyleSetPosition(root_child0_child1, CSSEdgeTop, 13.3f); + CSSNodeStyleSetHeight(root_child0_child1, 1.1f); + CSSNodeInsertChild(root_child0, root_child0_child1, 1); + + const CSSNodeRef root_child1 = CSSNodeNew(); + CSSNodeStyleSetFlexGrow(root_child1, 1.6f); + CSSNodeStyleSetHeight(root_child1, 10); + CSSNodeInsertChild(root, root_child1, 1); + + const CSSNodeRef root_child2 = CSSNodeNew(); + CSSNodeStyleSetFlexGrow(root_child2, 1.1f); + CSSNodeStyleSetHeight(root_child2, 10.7f); + CSSNodeInsertChild(root, root_child2, 2); + CSSNodeCalculateLayout(root, CSSUndefined, CSSUndefined, CSSDirectionLTR); + + ASSERT_FLOAT_EQ(0, CSSNodeLayoutGetLeft(root)); + ASSERT_FLOAT_EQ(0, CSSNodeLayoutGetTop(root)); + ASSERT_FLOAT_EQ(87, CSSNodeLayoutGetWidth(root)); + ASSERT_FLOAT_EQ(113, CSSNodeLayoutGetHeight(root)); + + ASSERT_FLOAT_EQ(0, CSSNodeLayoutGetLeft(root_child0)); + ASSERT_FLOAT_EQ(0, CSSNodeLayoutGetTop(root_child0)); + ASSERT_FLOAT_EQ(87, CSSNodeLayoutGetWidth(root_child0)); + ASSERT_FLOAT_EQ(59, CSSNodeLayoutGetHeight(root_child0)); + + ASSERT_FLOAT_EQ(0, CSSNodeLayoutGetLeft(root_child0_child0)); + ASSERT_FLOAT_EQ(-13, CSSNodeLayoutGetTop(root_child0_child0)); + ASSERT_FLOAT_EQ(87, CSSNodeLayoutGetWidth(root_child0_child0)); + ASSERT_FLOAT_EQ(13, CSSNodeLayoutGetHeight(root_child0_child0)); + + ASSERT_FLOAT_EQ(0, CSSNodeLayoutGetLeft(root_child0_child1)); + ASSERT_FLOAT_EQ(27, CSSNodeLayoutGetTop(root_child0_child1)); + ASSERT_FLOAT_EQ(87, CSSNodeLayoutGetWidth(root_child0_child1)); + ASSERT_FLOAT_EQ(45, CSSNodeLayoutGetHeight(root_child0_child1)); + + ASSERT_FLOAT_EQ(0, CSSNodeLayoutGetLeft(root_child1)); + ASSERT_FLOAT_EQ(59, CSSNodeLayoutGetTop(root_child1)); + ASSERT_FLOAT_EQ(87, CSSNodeLayoutGetWidth(root_child1)); + ASSERT_FLOAT_EQ(30, CSSNodeLayoutGetHeight(root_child1)); + + ASSERT_FLOAT_EQ(0, CSSNodeLayoutGetLeft(root_child2)); + ASSERT_FLOAT_EQ(89, CSSNodeLayoutGetTop(root_child2)); + ASSERT_FLOAT_EQ(87, CSSNodeLayoutGetWidth(root_child2)); + ASSERT_FLOAT_EQ(24, CSSNodeLayoutGetHeight(root_child2)); + + CSSNodeCalculateLayout(root, CSSUndefined, CSSUndefined, CSSDirectionRTL); + + ASSERT_FLOAT_EQ(0, CSSNodeLayoutGetLeft(root)); + ASSERT_FLOAT_EQ(0, CSSNodeLayoutGetTop(root)); + ASSERT_FLOAT_EQ(87, CSSNodeLayoutGetWidth(root)); + ASSERT_FLOAT_EQ(113, CSSNodeLayoutGetHeight(root)); + + ASSERT_FLOAT_EQ(0, CSSNodeLayoutGetLeft(root_child0)); + ASSERT_FLOAT_EQ(0, CSSNodeLayoutGetTop(root_child0)); + ASSERT_FLOAT_EQ(87, CSSNodeLayoutGetWidth(root_child0)); + ASSERT_FLOAT_EQ(59, CSSNodeLayoutGetHeight(root_child0)); + + ASSERT_FLOAT_EQ(0, CSSNodeLayoutGetLeft(root_child0_child0)); + ASSERT_FLOAT_EQ(-13, CSSNodeLayoutGetTop(root_child0_child0)); + ASSERT_FLOAT_EQ(87, CSSNodeLayoutGetWidth(root_child0_child0)); + ASSERT_FLOAT_EQ(13, CSSNodeLayoutGetHeight(root_child0_child0)); + + ASSERT_FLOAT_EQ(0, CSSNodeLayoutGetLeft(root_child0_child1)); + ASSERT_FLOAT_EQ(27, CSSNodeLayoutGetTop(root_child0_child1)); + ASSERT_FLOAT_EQ(87, CSSNodeLayoutGetWidth(root_child0_child1)); + ASSERT_FLOAT_EQ(45, CSSNodeLayoutGetHeight(root_child0_child1)); + + ASSERT_FLOAT_EQ(0, CSSNodeLayoutGetLeft(root_child1)); + ASSERT_FLOAT_EQ(59, CSSNodeLayoutGetTop(root_child1)); + ASSERT_FLOAT_EQ(87, CSSNodeLayoutGetWidth(root_child1)); + ASSERT_FLOAT_EQ(30, CSSNodeLayoutGetHeight(root_child1)); + + ASSERT_FLOAT_EQ(0, CSSNodeLayoutGetLeft(root_child2)); + ASSERT_FLOAT_EQ(89, CSSNodeLayoutGetTop(root_child2)); + ASSERT_FLOAT_EQ(87, CSSNodeLayoutGetWidth(root_child2)); + ASSERT_FLOAT_EQ(24, CSSNodeLayoutGetHeight(root_child2)); + + CSSNodeFreeRecursive(root); +} + + +static CSSSize _measureFloor(CSSNodeRef node, + float width, + CSSMeasureMode widthMode, + float height, + CSSMeasureMode heightMode) { + + return CSSSize{ + width = 10.2, + height = 10.2, + }; +} + +static CSSSize _measureCeil(CSSNodeRef node, + float width, + CSSMeasureMode widthMode, + float height, + CSSMeasureMode heightMode) { + + return CSSSize{ + width = 10.5, + height = 10.5, + }; +} + + +TEST_F(CSSLayoutFeatureRoundingTest, rounding_feature_with_custom_measure_func_floor) { + const CSSNodeRef root = CSSNodeNew(); + + const CSSNodeRef root_child0 = CSSNodeNew(); + CSSNodeSetMeasureFunc(root_child0, _measureFloor); + CSSNodeInsertChild(root, root_child0, 0); + + CSSNodeCalculateLayout(root, CSSUndefined, CSSUndefined, CSSDirectionLTR); + + ASSERT_FLOAT_EQ(10, CSSNodeLayoutGetWidth(root_child0)); + ASSERT_FLOAT_EQ(10, CSSNodeLayoutGetHeight(root_child0)); + + CSSNodeFreeRecursive(root); +} + +TEST_F(CSSLayoutFeatureRoundingTest, rounding_feature_with_custom_measure_func_ceil) { + const CSSNodeRef root = CSSNodeNew(); + + const CSSNodeRef root_child0 = CSSNodeNew(); + CSSNodeSetMeasureFunc(root_child0, _measureCeil); + CSSNodeInsertChild(root, root_child0, 0); + + CSSNodeCalculateLayout(root, CSSUndefined, CSSUndefined, CSSDirectionLTR); + + ASSERT_FLOAT_EQ(11, CSSNodeLayoutGetWidth(root_child0)); + ASSERT_FLOAT_EQ(11, CSSNodeLayoutGetHeight(root_child0)); + + CSSNodeFreeRecursive(root); +}