diff --git a/.gitignore b/.gitignore index 894beb17..88667ae7 100644 --- a/.gitignore +++ b/.gitignore @@ -9,6 +9,12 @@ # Visual studio code .vscode +*.pdb +*.tlog +*.obj +*.pch +*.log +*.orig # Xcode ## Build generated diff --git a/.hgignore b/.hgignore index 894beb17..88667ae7 100644 --- a/.hgignore +++ b/.hgignore @@ -9,6 +9,12 @@ # Visual studio code .vscode +*.pdb +*.tlog +*.obj +*.pch +*.log +*.orig # Xcode ## Build generated diff --git a/csharp/Facebook.Yoga/Border.cs b/csharp/Facebook.Yoga/Border.cs new file mode 100644 index 00000000..27c15cf4 --- /dev/null +++ b/csharp/Facebook.Yoga/Border.cs @@ -0,0 +1,31 @@ +/** + * 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. + */ + +namespace Facebook.Yoga +{ + public class Border + { + public float? Top; + public float? Bottom; + public float? Left; + public float? Right; + + public Border( + float? top = null, + float? bottom = null, + float? left = null, + float? right = null) + { + Top = top; + Bottom = bottom; + Left = left; + Right = right; + } + } +} \ No newline at end of file diff --git a/csharp/Facebook.Yoga/Native.cs b/csharp/Facebook.Yoga/Native.cs index a07ab94e..36a54733 100644 --- a/csharp/Facebook.Yoga/Native.cs +++ b/csharp/Facebook.Yoga/Native.cs @@ -191,43 +191,64 @@ namespace Facebook.Yoga public static extern void YGNodeStyleSetFlexBasis(YGNodeHandle node, float flexBasis); [DllImport(DllName)] - public static extern float YGNodeStyleGetFlexBasis(YGNodeHandle node); + public static extern void YGNodeStyleSetFlexBasisPercent(YGNodeHandle node, float flexBasis); + + [DllImport(DllName)] + public static extern YogaValue YGNodeStyleGetFlexBasis(YGNodeHandle node); [DllImport(DllName)] public static extern void YGNodeStyleSetWidth(YGNodeHandle node, float width); [DllImport(DllName)] - public static extern float YGNodeStyleGetWidth(YGNodeHandle node); + public static extern void YGNodeStyleSetWidthPercent(YGNodeHandle node, float width); + + [DllImport(DllName)] + public static extern YogaValue YGNodeStyleGetWidth(YGNodeHandle node); [DllImport(DllName)] public static extern void YGNodeStyleSetHeight(YGNodeHandle node, float height); [DllImport(DllName)] - public static extern float YGNodeStyleGetHeight(YGNodeHandle node); + public static extern void YGNodeStyleSetHeightPercent(YGNodeHandle node, float height); + + [DllImport(DllName)] + public static extern YogaValue YGNodeStyleGetHeight(YGNodeHandle node); [DllImport(DllName)] public static extern void YGNodeStyleSetMinWidth(YGNodeHandle node, float minWidth); [DllImport(DllName)] - public static extern float YGNodeStyleGetMinWidth(YGNodeHandle node); + public static extern void YGNodeStyleSetMinWidthPercent(YGNodeHandle node, float minWidth); + + [DllImport(DllName)] + public static extern YogaValue YGNodeStyleGetMinWidth(YGNodeHandle node); [DllImport(DllName)] public static extern void YGNodeStyleSetMinHeight(YGNodeHandle node, float minHeight); [DllImport(DllName)] - public static extern float YGNodeStyleGetMinHeight(YGNodeHandle node); + public static extern void YGNodeStyleSetMinHeightPercent(YGNodeHandle node, float minHeight); + + [DllImport(DllName)] + public static extern YogaValue YGNodeStyleGetMinHeight(YGNodeHandle node); [DllImport(DllName)] public static extern void YGNodeStyleSetMaxWidth(YGNodeHandle node, float maxWidth); [DllImport(DllName)] - public static extern float YGNodeStyleGetMaxWidth(YGNodeHandle node); + public static extern void YGNodeStyleSetMaxWidthPercent(YGNodeHandle node, float maxWidth); + + [DllImport(DllName)] + public static extern YogaValue YGNodeStyleGetMaxWidth(YGNodeHandle node); [DllImport(DllName)] public static extern void YGNodeStyleSetMaxHeight(YGNodeHandle node, float maxHeight); [DllImport(DllName)] - public static extern float YGNodeStyleGetMaxHeight(YGNodeHandle node); + public static extern void YGNodeStyleSetMaxHeightPercent(YGNodeHandle node, float maxHeight); + + [DllImport(DllName)] + public static extern YogaValue YGNodeStyleGetMaxHeight(YGNodeHandle node); [DllImport(DllName)] public static extern void YGNodeStyleSetAspectRatio(YGNodeHandle node, float aspectRatio); @@ -243,19 +264,28 @@ namespace Facebook.Yoga public static extern void YGNodeStyleSetPosition(YGNodeHandle node, YogaEdge edge, float position); [DllImport(DllName)] - public static extern float YGNodeStyleGetPosition(YGNodeHandle node, YogaEdge edge); + public static extern void YGNodeStyleSetPositionPercent(YGNodeHandle node, YogaEdge edge, float position); + + [DllImport(DllName)] + public static extern YogaValue YGNodeStyleGetPosition(YGNodeHandle node, YogaEdge edge); [DllImport(DllName)] public static extern void YGNodeStyleSetMargin(YGNodeHandle node, YogaEdge edge, float margin); [DllImport(DllName)] - public static extern float YGNodeStyleGetMargin(YGNodeHandle node, YogaEdge edge); + public static extern void YGNodeStyleSetMarginPercent(YGNodeHandle node, YogaEdge edge, float margin); + + [DllImport(DllName)] + public static extern YogaValue YGNodeStyleGetMargin(YGNodeHandle node, YogaEdge edge); [DllImport(DllName)] public static extern void YGNodeStyleSetPadding(YGNodeHandle node, YogaEdge edge, float padding); [DllImport(DllName)] - public static extern float YGNodeStyleGetPadding(YGNodeHandle node, YogaEdge edge); + public static extern void YGNodeStyleSetPaddingPercent(YGNodeHandle node, YogaEdge edge, float padding); + + [DllImport(DllName)] + public static extern YogaValue YGNodeStyleGetPadding(YGNodeHandle node, YogaEdge edge); [DllImport(DllName)] public static extern void YGNodeStyleSetBorder(YGNodeHandle node, YogaEdge edge, float border); diff --git a/csharp/Facebook.Yoga/Spacing.cs b/csharp/Facebook.Yoga/Spacing.cs index c1c53c96..7f5dffbd 100644 --- a/csharp/Facebook.Yoga/Spacing.cs +++ b/csharp/Facebook.Yoga/Spacing.cs @@ -11,16 +11,16 @@ namespace Facebook.Yoga { public class Spacing { - public float? Top; - public float? Bottom; - public float? Left; - public float? Right; + public YogaValue? Top; + public YogaValue? Bottom; + public YogaValue? Left; + public YogaValue? Right; public Spacing( - float? top = null, - float? bottom = null, - float? left = null, - float? right = null) + YogaValue? top = null, + YogaValue? bottom = null, + YogaValue? left = null, + YogaValue? right = null) { Top = top; Bottom = bottom; diff --git a/csharp/Facebook.Yoga/YogaConstants.cs b/csharp/Facebook.Yoga/YogaConstants.cs index 3e12aa14..ca8ecfbb 100644 --- a/csharp/Facebook.Yoga/YogaConstants.cs +++ b/csharp/Facebook.Yoga/YogaConstants.cs @@ -17,5 +17,10 @@ namespace Facebook.Yoga { return float.IsNaN(value); } + + public static bool IsUndefined(YogaValue value) + { + return value.Unit == YogaUnit.Undefined; + } } } diff --git a/csharp/Facebook.Yoga/YogaNode.Create.cs b/csharp/Facebook.Yoga/YogaNode.Create.cs index d04d0ffa..ee0726b5 100644 --- a/csharp/Facebook.Yoga/YogaNode.Create.cs +++ b/csharp/Facebook.Yoga/YogaNode.Create.cs @@ -26,17 +26,17 @@ namespace Facebook.Yoga float? flex = null, float? flexGrow = null, float? flexShrink = null, - float? flexBasis = null, + YogaValue? flexBasis = null, Spacing position = null, Spacing margin = null, Spacing padding = null, - Spacing border = null, - float? width = null, - float? height = null, - float? maxWidth = null, - float? maxHeight = null, - float? minWidth = null, - float? minHeight = null) + Border border = null, + YogaValue? width = null, + YogaValue? height = null, + YogaValue? maxWidth = null, + YogaValue? maxHeight = null, + YogaValue? minWidth = null, + YogaValue? minHeight = null) { YogaNode node = new YogaNode(); diff --git a/csharp/Facebook.Yoga/YogaNode.cs b/csharp/Facebook.Yoga/YogaNode.cs index 96a4d629..94cafa50 100644 --- a/csharp/Facebook.Yoga/YogaNode.cs +++ b/csharp/Facebook.Yoga/YogaNode.cs @@ -10,7 +10,6 @@ using System; using System.Collections; using System.Collections.Generic; -using System.Runtime.InteropServices; using System.Text; namespace Facebook.Yoga @@ -228,7 +227,7 @@ namespace Facebook.Yoga } } - public float FlexBasis + public YogaValue FlexBasis { get { @@ -237,28 +236,49 @@ namespace Facebook.Yoga set { - Native.YGNodeStyleSetFlexBasis(_ygNode, value); + if (value.Unit == YogaUnit.Percent) + { + Native.YGNodeStyleSetFlexBasisPercent(_ygNode, value.Value); + } + else + { + Native.YGNodeStyleSetFlexBasis(_ygNode, value.Value); + } } } - public float GetMargin(YogaEdge edge) + public YogaValue GetMargin(YogaEdge edge) { return Native.YGNodeStyleGetMargin(_ygNode, edge); } - public void SetMargin(YogaEdge edge, float value) + public void SetMargin(YogaEdge edge, YogaValue value) { - Native.YGNodeStyleSetMargin(_ygNode, edge, value); + if (value.Unit == YogaUnit.Percent) + { + Native.YGNodeStyleSetMarginPercent(_ygNode, edge, value.Value); + } + else + { + Native.YGNodeStyleSetMargin(_ygNode, edge, value.Value); + } } - public float GetPadding(YogaEdge edge) + public YogaValue GetPadding(YogaEdge edge) { return Native.YGNodeStyleGetPadding(_ygNode, edge); } - public void SetPadding(YogaEdge edge, float padding) + public void SetPadding(YogaEdge edge, YogaValue value) { - Native.YGNodeStyleSetPadding(_ygNode, edge, padding); + if (value.Unit == YogaUnit.Percent) + { + Native.YGNodeStyleSetPaddingPercent(_ygNode, edge, value.Value); + } + else + { + Native.YGNodeStyleSetPadding(_ygNode, edge, value.Value); + } } public float GetBorder(YogaEdge edge) @@ -271,17 +291,24 @@ namespace Facebook.Yoga Native.YGNodeStyleSetBorder(_ygNode, edge, border); } - public float GetPosition(YogaEdge edge) + public YogaValue GetPosition(YogaEdge edge) { return Native.YGNodeStyleGetPosition(_ygNode, edge); } - public void SetPosition(YogaEdge edge, float position) + public void SetPosition(YogaEdge edge, YogaValue value) { - Native.YGNodeStyleSetPosition(_ygNode, edge, position); + if (value.Unit == YogaUnit.Percent) + { + Native.YGNodeStyleSetPositionPercent(_ygNode, edge, value.Value); + } + else + { + Native.YGNodeStyleSetPosition(_ygNode, edge, value.Value); + } } - public float Width + public YogaValue Width { get { @@ -290,11 +317,18 @@ namespace Facebook.Yoga set { - Native.YGNodeStyleSetWidth(_ygNode, value); + if (value.Unit == YogaUnit.Percent) + { + Native.YGNodeStyleSetWidthPercent(_ygNode, value.Value); + } + else + { + Native.YGNodeStyleSetWidth(_ygNode, value.Value); + } } } - public float Height + public YogaValue Height { get { @@ -303,11 +337,18 @@ namespace Facebook.Yoga set { - Native.YGNodeStyleSetHeight(_ygNode, value); + if (value.Unit == YogaUnit.Percent) + { + Native.YGNodeStyleSetHeightPercent(_ygNode, value.Value); + } + else + { + Native.YGNodeStyleSetHeight(_ygNode, value.Value); + } } } - public float MaxWidth + public YogaValue MaxWidth { get { @@ -316,11 +357,18 @@ namespace Facebook.Yoga set { - Native.YGNodeStyleSetMaxWidth(_ygNode, value); + if (value.Unit == YogaUnit.Percent) + { + Native.YGNodeStyleSetMaxWidthPercent(_ygNode, value.Value); + } + else + { + Native.YGNodeStyleSetMaxWidth(_ygNode, value.Value); + } } } - public float MaxHeight + public YogaValue MaxHeight { get { @@ -329,11 +377,18 @@ namespace Facebook.Yoga set { - Native.YGNodeStyleSetMaxHeight(_ygNode, value); + if (value.Unit == YogaUnit.Percent) + { + Native.YGNodeStyleSetMaxHeightPercent(_ygNode, value.Value); + } + else + { + Native.YGNodeStyleSetMaxHeight(_ygNode, value.Value); + } } } - public float MinWidth + public YogaValue MinWidth { get { @@ -342,11 +397,18 @@ namespace Facebook.Yoga set { - Native.YGNodeStyleSetMinWidth(_ygNode, value); + if (value.Unit == YogaUnit.Percent) + { + Native.YGNodeStyleSetMinWidthPercent(_ygNode, value.Value); + } + else + { + Native.YGNodeStyleSetMinWidth(_ygNode, value.Value); + } } } - public float MinHeight + public YogaValue MinHeight { get { @@ -355,7 +417,14 @@ namespace Facebook.Yoga set { - Native.YGNodeStyleSetMinHeight(_ygNode, value); + if (value.Unit == YogaUnit.Percent) + { + Native.YGNodeStyleSetMinHeightPercent(_ygNode, value.Value); + } + else + { + Native.YGNodeStyleSetMinHeight(_ygNode, value.Value); + } } } diff --git a/csharp/Facebook.Yoga/YogaUnit.cs b/csharp/Facebook.Yoga/YogaUnit.cs new file mode 100644 index 00000000..396c45da --- /dev/null +++ b/csharp/Facebook.Yoga/YogaUnit.cs @@ -0,0 +1,18 @@ +/** + * 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. + */ + +namespace Facebook.Yoga +{ + public enum YogaUnit + { + Undefined, + Pixel, + Percent, + } +} diff --git a/csharp/Facebook.Yoga/YogaValue.cs b/csharp/Facebook.Yoga/YogaValue.cs new file mode 100644 index 00000000..055f7d68 --- /dev/null +++ b/csharp/Facebook.Yoga/YogaValue.cs @@ -0,0 +1,74 @@ +/** + * 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. + */ + +using System.Runtime.InteropServices; + +namespace Facebook.Yoga +{ + [StructLayout(LayoutKind.Sequential)] + public struct YogaValue + { + private float value; + private YogaUnit unit; + + public YogaUnit Unit => unit; + public float Value => value; + + public static YogaValue Pixel(float value) + { + return new YogaValue + { + value = value, + unit = YogaConstants.IsUndefined(value) ? YogaUnit.Undefined : YogaUnit.Pixel + }; + } + + public bool Equals(YogaValue other) + { + return Unit == other.Unit && (Value.Equals(other.Value) || Unit == YogaUnit.Undefined); + } + + public override bool Equals(object obj) + { + if (ReferenceEquals(null, obj)) return false; + return obj is YogaValue && Equals((YogaValue) obj); + } + + public override int GetHashCode() + { + unchecked + { + return (Value.GetHashCode() * 397) ^ (int) Unit; + } + } + + public static YogaValue Undefined() + { + return new YogaValue + { + value = YogaConstants.Undefined, + unit = YogaUnit.Undefined + }; + } + + public static YogaValue Percent(float value) + { + return new YogaValue + { + value = value, + unit = YogaConstants.IsUndefined(value) ? YogaUnit.Undefined : YogaUnit.Percent + }; + } + + public static implicit operator YogaValue(float pixelValue) + { + return Pixel(pixelValue); + } + } +} diff --git a/csharp/Facebook.Yoga/YogaValueExtensions.cs b/csharp/Facebook.Yoga/YogaValueExtensions.cs new file mode 100644 index 00000000..9ccee62a --- /dev/null +++ b/csharp/Facebook.Yoga/YogaValueExtensions.cs @@ -0,0 +1,34 @@ +/** + * 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. + */ + +namespace Facebook.Yoga +{ + public static class YogaValueExtensions + { + public static YogaValue Percent(this float value) + { + return YogaValue.Percent(value); + } + + public static YogaValue Px(this float value) + { + return YogaValue.Pixel(value); + } + + public static YogaValue Percent(this int value) + { + return YogaValue.Percent(value); + } + + public static YogaValue Px(this int value) + { + return YogaValue.Pixel(value); + } + } +} \ No newline at end of file diff --git a/csharp/tests/Facebook.Yoga/YGAbsolutePositionTest.cs b/csharp/tests/Facebook.Yoga/YGAbsolutePositionTest.cs index c9d49cc0..49f6605e 100644 --- a/csharp/tests/Facebook.Yoga/YGAbsolutePositionTest.cs +++ b/csharp/tests/Facebook.Yoga/YGAbsolutePositionTest.cs @@ -21,15 +21,15 @@ namespace Facebook.Yoga public void Test_absolute_layout_width_height_start_top() { YogaNode root = new YogaNode(); - root.Width = 100f; - root.Height = 100f; + root.Width = 100; + root.Height = 100; YogaNode root_child0 = new YogaNode(); root_child0.PositionType = YogaPositionType.Absolute; - root_child0.SetPosition(YogaEdge.Start, 10f); - root_child0.SetPosition(YogaEdge.Top, 10f); - root_child0.Width = 10f; - root_child0.Height = 10f; + root_child0.SetPosition(YogaEdge.Start, 10); + root_child0.SetPosition(YogaEdge.Top, 10); + root_child0.Width = 10; + root_child0.Height = 10; root.Insert(0, root_child0); root.StyleDirection = YogaDirection.LTR; root.CalculateLayout(); @@ -62,15 +62,15 @@ namespace Facebook.Yoga public void Test_absolute_layout_width_height_end_bottom() { YogaNode root = new YogaNode(); - root.Width = 100f; - root.Height = 100f; + root.Width = 100; + root.Height = 100; YogaNode root_child0 = new YogaNode(); root_child0.PositionType = YogaPositionType.Absolute; - root_child0.SetPosition(YogaEdge.End, 10f); - root_child0.SetPosition(YogaEdge.Bottom, 10f); - root_child0.Width = 10f; - root_child0.Height = 10f; + root_child0.SetPosition(YogaEdge.End, 10); + root_child0.SetPosition(YogaEdge.Bottom, 10); + root_child0.Width = 10; + root_child0.Height = 10; root.Insert(0, root_child0); root.StyleDirection = YogaDirection.LTR; root.CalculateLayout(); @@ -103,15 +103,15 @@ namespace Facebook.Yoga public void Test_absolute_layout_start_top_end_bottom() { YogaNode root = new YogaNode(); - root.Width = 100f; - root.Height = 100f; + root.Width = 100; + root.Height = 100; YogaNode root_child0 = new YogaNode(); root_child0.PositionType = YogaPositionType.Absolute; - root_child0.SetPosition(YogaEdge.Start, 10f); - root_child0.SetPosition(YogaEdge.Top, 10f); - root_child0.SetPosition(YogaEdge.End, 10f); - root_child0.SetPosition(YogaEdge.Bottom, 10f); + root_child0.SetPosition(YogaEdge.Start, 10); + root_child0.SetPosition(YogaEdge.Top, 10); + root_child0.SetPosition(YogaEdge.End, 10); + root_child0.SetPosition(YogaEdge.Bottom, 10); root.Insert(0, root_child0); root.StyleDirection = YogaDirection.LTR; root.CalculateLayout(); @@ -144,17 +144,17 @@ namespace Facebook.Yoga public void Test_absolute_layout_width_height_start_top_end_bottom() { YogaNode root = new YogaNode(); - root.Width = 100f; - root.Height = 100f; + root.Width = 100; + root.Height = 100; YogaNode root_child0 = new YogaNode(); root_child0.PositionType = YogaPositionType.Absolute; - root_child0.SetPosition(YogaEdge.Start, 10f); - root_child0.SetPosition(YogaEdge.Top, 10f); - root_child0.SetPosition(YogaEdge.End, 10f); - root_child0.SetPosition(YogaEdge.Bottom, 10f); - root_child0.Width = 10f; - root_child0.Height = 10f; + root_child0.SetPosition(YogaEdge.Start, 10); + root_child0.SetPosition(YogaEdge.Top, 10); + root_child0.SetPosition(YogaEdge.End, 10); + root_child0.SetPosition(YogaEdge.Bottom, 10); + root_child0.Width = 10; + root_child0.Height = 10; root.Insert(0, root_child0); root.StyleDirection = YogaDirection.LTR; root.CalculateLayout(); @@ -189,18 +189,18 @@ namespace Facebook.Yoga YogaNode root = new YogaNode(); root.FlexDirection = YogaFlexDirection.Row; root.Overflow = YogaOverflow.Hidden; - root.Width = 50f; - root.Height = 50f; + root.Width = 50; + root.Height = 50; YogaNode root_child0 = new YogaNode(); root_child0.PositionType = YogaPositionType.Absolute; - root_child0.SetPosition(YogaEdge.Start, 0f); - root_child0.SetPosition(YogaEdge.Top, 0f); + root_child0.SetPosition(YogaEdge.Start, 0); + root_child0.SetPosition(YogaEdge.Top, 0); root.Insert(0, root_child0); YogaNode root_child0_child0 = new YogaNode(); - root_child0_child0.Width = 100f; - root_child0_child0.Height = 100f; + root_child0_child0.Width = 100; + root_child0_child0.Height = 100; root_child0.Insert(0, root_child0_child0); root.StyleDirection = YogaDirection.LTR; root.CalculateLayout(); @@ -243,35 +243,35 @@ namespace Facebook.Yoga public void Test_absolute_layout_within_border() { YogaNode root = new YogaNode(); - root.SetMargin(YogaEdge.Left, 10f); - root.SetMargin(YogaEdge.Top, 10f); - root.SetMargin(YogaEdge.Right, 10f); - root.SetMargin(YogaEdge.Bottom, 10f); - root.SetPadding(YogaEdge.Left, 10f); - root.SetPadding(YogaEdge.Top, 10f); - root.SetPadding(YogaEdge.Right, 10f); - root.SetPadding(YogaEdge.Bottom, 10f); - root.SetBorder(YogaEdge.Left, 10f); - root.SetBorder(YogaEdge.Top, 10f); - root.SetBorder(YogaEdge.Right, 10f); - root.SetBorder(YogaEdge.Bottom, 10f); - root.Width = 100f; - root.Height = 100f; + root.SetMargin(YogaEdge.Left, 10); + root.SetMargin(YogaEdge.Top, 10); + root.SetMargin(YogaEdge.Right, 10); + root.SetMargin(YogaEdge.Bottom, 10); + root.SetPadding(YogaEdge.Left, 10); + root.SetPadding(YogaEdge.Top, 10); + root.SetPadding(YogaEdge.Right, 10); + root.SetPadding(YogaEdge.Bottom, 10); + root.SetBorder(YogaEdge.Left, 10); + root.SetBorder(YogaEdge.Top, 10); + root.SetBorder(YogaEdge.Right, 10); + root.SetBorder(YogaEdge.Bottom, 10); + root.Width = 100; + root.Height = 100; YogaNode root_child0 = new YogaNode(); root_child0.PositionType = YogaPositionType.Absolute; - root_child0.SetPosition(YogaEdge.Left, 0f); - root_child0.SetPosition(YogaEdge.Top, 0f); - root_child0.Width = 50f; - root_child0.Height = 50f; + root_child0.SetPosition(YogaEdge.Left, 0); + root_child0.SetPosition(YogaEdge.Top, 0); + root_child0.Width = 50; + root_child0.Height = 50; root.Insert(0, root_child0); YogaNode root_child1 = new YogaNode(); root_child1.PositionType = YogaPositionType.Absolute; - root_child1.SetPosition(YogaEdge.Right, 0f); - root_child1.SetPosition(YogaEdge.Bottom, 0f); - root_child1.Width = 50f; - root_child1.Height = 50f; + root_child1.SetPosition(YogaEdge.Right, 0); + root_child1.SetPosition(YogaEdge.Bottom, 0); + root_child1.Width = 50; + root_child1.Height = 50; root.Insert(1, root_child1); root.StyleDirection = YogaDirection.LTR; root.CalculateLayout(); diff --git a/csharp/tests/Facebook.Yoga/YGAlignContentTest.cs b/csharp/tests/Facebook.Yoga/YGAlignContentTest.cs index 598b1dd7..288e30f8 100644 --- a/csharp/tests/Facebook.Yoga/YGAlignContentTest.cs +++ b/csharp/tests/Facebook.Yoga/YGAlignContentTest.cs @@ -22,32 +22,32 @@ namespace Facebook.Yoga { YogaNode root = new YogaNode(); root.Wrap = YogaWrap.Wrap; - root.Width = 100f; - root.Height = 100f; + root.Width = 100; + root.Height = 100; YogaNode root_child0 = new YogaNode(); - root_child0.Width = 50f; - root_child0.Height = 10f; + root_child0.Width = 50; + root_child0.Height = 10; root.Insert(0, root_child0); YogaNode root_child1 = new YogaNode(); - root_child1.Width = 50f; - root_child1.Height = 10f; + root_child1.Width = 50; + root_child1.Height = 10; root.Insert(1, root_child1); YogaNode root_child2 = new YogaNode(); - root_child2.Width = 50f; - root_child2.Height = 10f; + root_child2.Width = 50; + root_child2.Height = 10; root.Insert(2, root_child2); YogaNode root_child3 = new YogaNode(); - root_child3.Width = 50f; - root_child3.Height = 10f; + root_child3.Width = 50; + root_child3.Height = 10; root.Insert(3, root_child3); YogaNode root_child4 = new YogaNode(); - root_child4.Width = 50f; - root_child4.Height = 10f; + root_child4.Width = 50; + root_child4.Height = 10; root.Insert(4, root_child4); root.StyleDirection = YogaDirection.LTR; root.CalculateLayout(); @@ -122,32 +122,32 @@ namespace Facebook.Yoga YogaNode root = new YogaNode(); root.AlignContent = YogaAlign.FlexEnd; root.Wrap = YogaWrap.Wrap; - root.Width = 100f; - root.Height = 100f; + root.Width = 100; + root.Height = 100; YogaNode root_child0 = new YogaNode(); - root_child0.Width = 50f; - root_child0.Height = 10f; + root_child0.Width = 50; + root_child0.Height = 10; root.Insert(0, root_child0); YogaNode root_child1 = new YogaNode(); - root_child1.Width = 50f; - root_child1.Height = 10f; + root_child1.Width = 50; + root_child1.Height = 10; root.Insert(1, root_child1); YogaNode root_child2 = new YogaNode(); - root_child2.Width = 50f; - root_child2.Height = 10f; + root_child2.Width = 50; + root_child2.Height = 10; root.Insert(2, root_child2); YogaNode root_child3 = new YogaNode(); - root_child3.Width = 50f; - root_child3.Height = 10f; + root_child3.Width = 50; + root_child3.Height = 10; root.Insert(3, root_child3); YogaNode root_child4 = new YogaNode(); - root_child4.Width = 50f; - root_child4.Height = 10f; + root_child4.Width = 50; + root_child4.Height = 10; root.Insert(4, root_child4); root.StyleDirection = YogaDirection.LTR; root.CalculateLayout(); @@ -222,32 +222,32 @@ namespace Facebook.Yoga YogaNode root = new YogaNode(); root.AlignContent = YogaAlign.Center; root.Wrap = YogaWrap.Wrap; - root.Width = 100f; - root.Height = 100f; + root.Width = 100; + root.Height = 100; YogaNode root_child0 = new YogaNode(); - root_child0.Width = 50f; - root_child0.Height = 10f; + root_child0.Width = 50; + root_child0.Height = 10; root.Insert(0, root_child0); YogaNode root_child1 = new YogaNode(); - root_child1.Width = 50f; - root_child1.Height = 10f; + root_child1.Width = 50; + root_child1.Height = 10; root.Insert(1, root_child1); YogaNode root_child2 = new YogaNode(); - root_child2.Width = 50f; - root_child2.Height = 10f; + root_child2.Width = 50; + root_child2.Height = 10; root.Insert(2, root_child2); YogaNode root_child3 = new YogaNode(); - root_child3.Width = 50f; - root_child3.Height = 10f; + root_child3.Width = 50; + root_child3.Height = 10; root.Insert(3, root_child3); YogaNode root_child4 = new YogaNode(); - root_child4.Width = 50f; - root_child4.Height = 10f; + root_child4.Width = 50; + root_child4.Height = 10; root.Insert(4, root_child4); root.StyleDirection = YogaDirection.LTR; root.CalculateLayout(); @@ -322,27 +322,27 @@ namespace Facebook.Yoga YogaNode root = new YogaNode(); root.AlignContent = YogaAlign.Stretch; root.Wrap = YogaWrap.Wrap; - root.Width = 100f; - root.Height = 100f; + root.Width = 100; + root.Height = 100; YogaNode root_child0 = new YogaNode(); - root_child0.Width = 50f; + root_child0.Width = 50; root.Insert(0, root_child0); YogaNode root_child1 = new YogaNode(); - root_child1.Width = 50f; + root_child1.Width = 50; root.Insert(1, root_child1); YogaNode root_child2 = new YogaNode(); - root_child2.Width = 50f; + root_child2.Width = 50; root.Insert(2, root_child2); YogaNode root_child3 = new YogaNode(); - root_child3.Width = 50f; + root_child3.Width = 50; root.Insert(3, root_child3); YogaNode root_child4 = new YogaNode(); - root_child4.Width = 50f; + root_child4.Width = 50; root.Insert(4, root_child4); root.StyleDirection = YogaDirection.LTR; root.CalculateLayout(); diff --git a/csharp/tests/Facebook.Yoga/YGAlignItemsTest.cs b/csharp/tests/Facebook.Yoga/YGAlignItemsTest.cs index 33b4c0d2..bcafe460 100644 --- a/csharp/tests/Facebook.Yoga/YGAlignItemsTest.cs +++ b/csharp/tests/Facebook.Yoga/YGAlignItemsTest.cs @@ -21,11 +21,11 @@ namespace Facebook.Yoga public void Test_align_items_stretch() { YogaNode root = new YogaNode(); - root.Width = 100f; - root.Height = 100f; + root.Width = 100; + root.Height = 100; YogaNode root_child0 = new YogaNode(); - root_child0.Height = 10f; + root_child0.Height = 10; root.Insert(0, root_child0); root.StyleDirection = YogaDirection.LTR; root.CalculateLayout(); @@ -59,12 +59,12 @@ namespace Facebook.Yoga { YogaNode root = new YogaNode(); root.AlignItems = YogaAlign.Center; - root.Width = 100f; - root.Height = 100f; + root.Width = 100; + root.Height = 100; YogaNode root_child0 = new YogaNode(); - root_child0.Width = 10f; - root_child0.Height = 10f; + root_child0.Width = 10; + root_child0.Height = 10; root.Insert(0, root_child0); root.StyleDirection = YogaDirection.LTR; root.CalculateLayout(); @@ -98,12 +98,12 @@ namespace Facebook.Yoga { YogaNode root = new YogaNode(); root.AlignItems = YogaAlign.FlexStart; - root.Width = 100f; - root.Height = 100f; + root.Width = 100; + root.Height = 100; YogaNode root_child0 = new YogaNode(); - root_child0.Width = 10f; - root_child0.Height = 10f; + root_child0.Width = 10; + root_child0.Height = 10; root.Insert(0, root_child0); root.StyleDirection = YogaDirection.LTR; root.CalculateLayout(); @@ -137,12 +137,12 @@ namespace Facebook.Yoga { YogaNode root = new YogaNode(); root.AlignItems = YogaAlign.FlexEnd; - root.Width = 100f; - root.Height = 100f; + root.Width = 100; + root.Height = 100; YogaNode root_child0 = new YogaNode(); - root_child0.Width = 10f; - root_child0.Height = 10f; + root_child0.Width = 10; + root_child0.Height = 10; root.Insert(0, root_child0); root.StyleDirection = YogaDirection.LTR; root.CalculateLayout(); diff --git a/csharp/tests/Facebook.Yoga/YGAlignSelfTest.cs b/csharp/tests/Facebook.Yoga/YGAlignSelfTest.cs index c564cf93..b4ca0e13 100644 --- a/csharp/tests/Facebook.Yoga/YGAlignSelfTest.cs +++ b/csharp/tests/Facebook.Yoga/YGAlignSelfTest.cs @@ -21,13 +21,13 @@ namespace Facebook.Yoga public void Test_align_self_center() { YogaNode root = new YogaNode(); - root.Width = 100f; - root.Height = 100f; + root.Width = 100; + root.Height = 100; YogaNode root_child0 = new YogaNode(); root_child0.AlignSelf = YogaAlign.Center; - root_child0.Width = 10f; - root_child0.Height = 10f; + root_child0.Width = 10; + root_child0.Height = 10; root.Insert(0, root_child0); root.StyleDirection = YogaDirection.LTR; root.CalculateLayout(); @@ -60,13 +60,13 @@ namespace Facebook.Yoga public void Test_align_self_flex_end() { YogaNode root = new YogaNode(); - root.Width = 100f; - root.Height = 100f; + root.Width = 100; + root.Height = 100; YogaNode root_child0 = new YogaNode(); root_child0.AlignSelf = YogaAlign.FlexEnd; - root_child0.Width = 10f; - root_child0.Height = 10f; + root_child0.Width = 10; + root_child0.Height = 10; root.Insert(0, root_child0); root.StyleDirection = YogaDirection.LTR; root.CalculateLayout(); @@ -99,13 +99,13 @@ namespace Facebook.Yoga public void Test_align_self_flex_start() { YogaNode root = new YogaNode(); - root.Width = 100f; - root.Height = 100f; + root.Width = 100; + root.Height = 100; YogaNode root_child0 = new YogaNode(); root_child0.AlignSelf = YogaAlign.FlexStart; - root_child0.Width = 10f; - root_child0.Height = 10f; + root_child0.Width = 10; + root_child0.Height = 10; root.Insert(0, root_child0); root.StyleDirection = YogaDirection.LTR; root.CalculateLayout(); @@ -139,13 +139,13 @@ namespace Facebook.Yoga { YogaNode root = new YogaNode(); root.AlignItems = YogaAlign.FlexStart; - root.Width = 100f; - root.Height = 100f; + root.Width = 100; + root.Height = 100; YogaNode root_child0 = new YogaNode(); root_child0.AlignSelf = YogaAlign.FlexEnd; - root_child0.Width = 10f; - root_child0.Height = 10f; + root_child0.Width = 10; + root_child0.Height = 10; root.Insert(0, root_child0); root.StyleDirection = YogaDirection.LTR; root.CalculateLayout(); diff --git a/csharp/tests/Facebook.Yoga/YGBorderTest.cs b/csharp/tests/Facebook.Yoga/YGBorderTest.cs index 613fe115..86029fca 100644 --- a/csharp/tests/Facebook.Yoga/YGBorderTest.cs +++ b/csharp/tests/Facebook.Yoga/YGBorderTest.cs @@ -21,10 +21,10 @@ namespace Facebook.Yoga public void Test_border_no_size() { YogaNode root = new YogaNode(); - root.SetBorder(YogaEdge.Left, 10f); - root.SetBorder(YogaEdge.Top, 10f); - root.SetBorder(YogaEdge.Right, 10f); - root.SetBorder(YogaEdge.Bottom, 10f); + root.SetBorder(YogaEdge.Left, 10); + root.SetBorder(YogaEdge.Top, 10); + root.SetBorder(YogaEdge.Right, 10); + root.SetBorder(YogaEdge.Bottom, 10); root.StyleDirection = YogaDirection.LTR; root.CalculateLayout(); @@ -46,14 +46,14 @@ namespace Facebook.Yoga public void Test_border_container_match_child() { YogaNode root = new YogaNode(); - root.SetBorder(YogaEdge.Left, 10f); - root.SetBorder(YogaEdge.Top, 10f); - root.SetBorder(YogaEdge.Right, 10f); - root.SetBorder(YogaEdge.Bottom, 10f); + root.SetBorder(YogaEdge.Left, 10); + root.SetBorder(YogaEdge.Top, 10); + root.SetBorder(YogaEdge.Right, 10); + root.SetBorder(YogaEdge.Bottom, 10); YogaNode root_child0 = new YogaNode(); - root_child0.Width = 10f; - root_child0.Height = 10f; + root_child0.Width = 10; + root_child0.Height = 10; root.Insert(0, root_child0); root.StyleDirection = YogaDirection.LTR; root.CalculateLayout(); @@ -86,16 +86,16 @@ namespace Facebook.Yoga public void Test_border_flex_child() { YogaNode root = new YogaNode(); - root.SetBorder(YogaEdge.Left, 10f); - root.SetBorder(YogaEdge.Top, 10f); - root.SetBorder(YogaEdge.Right, 10f); - root.SetBorder(YogaEdge.Bottom, 10f); - root.Width = 100f; - root.Height = 100f; + root.SetBorder(YogaEdge.Left, 10); + root.SetBorder(YogaEdge.Top, 10); + root.SetBorder(YogaEdge.Right, 10); + root.SetBorder(YogaEdge.Bottom, 10); + root.Width = 100; + root.Height = 100; YogaNode root_child0 = new YogaNode(); - root_child0.FlexGrow = 1f; - root_child0.Width = 10f; + root_child0.FlexGrow = 1; + root_child0.Width = 10; root.Insert(0, root_child0); root.StyleDirection = YogaDirection.LTR; root.CalculateLayout(); @@ -128,15 +128,15 @@ namespace Facebook.Yoga public void Test_border_stretch_child() { YogaNode root = new YogaNode(); - root.SetBorder(YogaEdge.Left, 10f); - root.SetBorder(YogaEdge.Top, 10f); - root.SetBorder(YogaEdge.Right, 10f); - root.SetBorder(YogaEdge.Bottom, 10f); - root.Width = 100f; - root.Height = 100f; + root.SetBorder(YogaEdge.Left, 10); + root.SetBorder(YogaEdge.Top, 10); + root.SetBorder(YogaEdge.Right, 10); + root.SetBorder(YogaEdge.Bottom, 10); + root.Width = 100; + root.Height = 100; YogaNode root_child0 = new YogaNode(); - root_child0.Height = 10f; + root_child0.Height = 10; root.Insert(0, root_child0); root.StyleDirection = YogaDirection.LTR; root.CalculateLayout(); @@ -171,15 +171,15 @@ namespace Facebook.Yoga YogaNode root = new YogaNode(); root.JustifyContent = YogaJustify.Center; root.AlignItems = YogaAlign.Center; - root.SetBorder(YogaEdge.Start, 10f); - root.SetBorder(YogaEdge.End, 20f); - root.SetBorder(YogaEdge.Bottom, 20f); - root.Width = 100f; - root.Height = 100f; + root.SetBorder(YogaEdge.Start, 10); + root.SetBorder(YogaEdge.End, 20); + root.SetBorder(YogaEdge.Bottom, 20); + root.Width = 100; + root.Height = 100; YogaNode root_child0 = new YogaNode(); - root_child0.Width = 10f; - root_child0.Height = 10f; + root_child0.Width = 10; + root_child0.Height = 10; root.Insert(0, root_child0); root.StyleDirection = YogaDirection.LTR; root.CalculateLayout(); diff --git a/csharp/tests/Facebook.Yoga/YGFlexDirectionTest.cs b/csharp/tests/Facebook.Yoga/YGFlexDirectionTest.cs index 10a1257a..8063b48a 100644 --- a/csharp/tests/Facebook.Yoga/YGFlexDirectionTest.cs +++ b/csharp/tests/Facebook.Yoga/YGFlexDirectionTest.cs @@ -21,18 +21,18 @@ namespace Facebook.Yoga public void Test_flex_direction_column_no_height() { YogaNode root = new YogaNode(); - root.Width = 100f; + root.Width = 100; YogaNode root_child0 = new YogaNode(); - root_child0.Height = 10f; + root_child0.Height = 10; root.Insert(0, root_child0); YogaNode root_child1 = new YogaNode(); - root_child1.Height = 10f; + root_child1.Height = 10; root.Insert(1, root_child1); YogaNode root_child2 = new YogaNode(); - root_child2.Height = 10f; + root_child2.Height = 10; root.Insert(2, root_child2); root.StyleDirection = YogaDirection.LTR; root.CalculateLayout(); @@ -86,18 +86,18 @@ namespace Facebook.Yoga { YogaNode root = new YogaNode(); root.FlexDirection = YogaFlexDirection.Row; - root.Height = 100f; + root.Height = 100; YogaNode root_child0 = new YogaNode(); - root_child0.Width = 10f; + root_child0.Width = 10; root.Insert(0, root_child0); YogaNode root_child1 = new YogaNode(); - root_child1.Width = 10f; + root_child1.Width = 10; root.Insert(1, root_child1); YogaNode root_child2 = new YogaNode(); - root_child2.Width = 10f; + root_child2.Width = 10; root.Insert(2, root_child2); root.StyleDirection = YogaDirection.LTR; root.CalculateLayout(); @@ -150,19 +150,19 @@ namespace Facebook.Yoga public void Test_flex_direction_column() { YogaNode root = new YogaNode(); - root.Width = 100f; - root.Height = 100f; + root.Width = 100; + root.Height = 100; YogaNode root_child0 = new YogaNode(); - root_child0.Height = 10f; + root_child0.Height = 10; root.Insert(0, root_child0); YogaNode root_child1 = new YogaNode(); - root_child1.Height = 10f; + root_child1.Height = 10; root.Insert(1, root_child1); YogaNode root_child2 = new YogaNode(); - root_child2.Height = 10f; + root_child2.Height = 10; root.Insert(2, root_child2); root.StyleDirection = YogaDirection.LTR; root.CalculateLayout(); @@ -216,19 +216,19 @@ namespace Facebook.Yoga { YogaNode root = new YogaNode(); root.FlexDirection = YogaFlexDirection.Row; - root.Width = 100f; - root.Height = 100f; + root.Width = 100; + root.Height = 100; YogaNode root_child0 = new YogaNode(); - root_child0.Width = 10f; + root_child0.Width = 10; root.Insert(0, root_child0); YogaNode root_child1 = new YogaNode(); - root_child1.Width = 10f; + root_child1.Width = 10; root.Insert(1, root_child1); YogaNode root_child2 = new YogaNode(); - root_child2.Width = 10f; + root_child2.Width = 10; root.Insert(2, root_child2); root.StyleDirection = YogaDirection.LTR; root.CalculateLayout(); @@ -282,19 +282,19 @@ namespace Facebook.Yoga { YogaNode root = new YogaNode(); root.FlexDirection = YogaFlexDirection.ColumnReverse; - root.Width = 100f; - root.Height = 100f; + root.Width = 100; + root.Height = 100; YogaNode root_child0 = new YogaNode(); - root_child0.Height = 10f; + root_child0.Height = 10; root.Insert(0, root_child0); YogaNode root_child1 = new YogaNode(); - root_child1.Height = 10f; + root_child1.Height = 10; root.Insert(1, root_child1); YogaNode root_child2 = new YogaNode(); - root_child2.Height = 10f; + root_child2.Height = 10; root.Insert(2, root_child2); root.StyleDirection = YogaDirection.LTR; root.CalculateLayout(); @@ -348,19 +348,19 @@ namespace Facebook.Yoga { YogaNode root = new YogaNode(); root.FlexDirection = YogaFlexDirection.RowReverse; - root.Width = 100f; - root.Height = 100f; + root.Width = 100; + root.Height = 100; YogaNode root_child0 = new YogaNode(); - root_child0.Width = 10f; + root_child0.Width = 10; root.Insert(0, root_child0); YogaNode root_child1 = new YogaNode(); - root_child1.Width = 10f; + root_child1.Width = 10; root.Insert(1, root_child1); YogaNode root_child2 = new YogaNode(); - root_child2.Width = 10f; + root_child2.Width = 10; root.Insert(2, root_child2); root.StyleDirection = YogaDirection.LTR; root.CalculateLayout(); diff --git a/csharp/tests/Facebook.Yoga/YGFlexTest.cs b/csharp/tests/Facebook.Yoga/YGFlexTest.cs index 05036680..3826fa9a 100644 --- a/csharp/tests/Facebook.Yoga/YGFlexTest.cs +++ b/csharp/tests/Facebook.Yoga/YGFlexTest.cs @@ -21,16 +21,16 @@ namespace Facebook.Yoga public void Test_flex_basis_flex_grow_column() { YogaNode root = new YogaNode(); - root.Width = 100f; - root.Height = 100f; + root.Width = 100; + root.Height = 100; YogaNode root_child0 = new YogaNode(); - root_child0.FlexGrow = 1f; - root_child0.FlexBasis = 50f; + root_child0.FlexGrow = 1; + root_child0.FlexBasis = 50; root.Insert(0, root_child0); YogaNode root_child1 = new YogaNode(); - root_child1.FlexGrow = 1f; + root_child1.FlexGrow = 1; root.Insert(1, root_child1); root.StyleDirection = YogaDirection.LTR; root.CalculateLayout(); @@ -74,16 +74,16 @@ namespace Facebook.Yoga { YogaNode root = new YogaNode(); root.FlexDirection = YogaFlexDirection.Row; - root.Width = 100f; - root.Height = 100f; + root.Width = 100; + root.Height = 100; YogaNode root_child0 = new YogaNode(); - root_child0.FlexGrow = 1f; - root_child0.FlexBasis = 50f; + root_child0.FlexGrow = 1; + root_child0.FlexBasis = 50; root.Insert(0, root_child0); YogaNode root_child1 = new YogaNode(); - root_child1.FlexGrow = 1f; + root_child1.FlexGrow = 1; root.Insert(1, root_child1); root.StyleDirection = YogaDirection.LTR; root.CalculateLayout(); @@ -126,16 +126,16 @@ namespace Facebook.Yoga public void Test_flex_basis_flex_shrink_column() { YogaNode root = new YogaNode(); - root.Width = 100f; - root.Height = 100f; + root.Width = 100; + root.Height = 100; YogaNode root_child0 = new YogaNode(); - root_child0.FlexShrink = 1f; - root_child0.FlexBasis = 100f; + root_child0.FlexShrink = 1; + root_child0.FlexBasis = 100; root.Insert(0, root_child0); YogaNode root_child1 = new YogaNode(); - root_child1.FlexBasis = 50f; + root_child1.FlexBasis = 50; root.Insert(1, root_child1); root.StyleDirection = YogaDirection.LTR; root.CalculateLayout(); @@ -179,16 +179,16 @@ namespace Facebook.Yoga { YogaNode root = new YogaNode(); root.FlexDirection = YogaFlexDirection.Row; - root.Width = 100f; - root.Height = 100f; + root.Width = 100; + root.Height = 100; YogaNode root_child0 = new YogaNode(); - root_child0.FlexShrink = 1f; - root_child0.FlexBasis = 100f; + root_child0.FlexShrink = 1; + root_child0.FlexBasis = 100; root.Insert(0, root_child0); YogaNode root_child1 = new YogaNode(); - root_child1.FlexBasis = 50f; + root_child1.FlexBasis = 50; root.Insert(1, root_child1); root.StyleDirection = YogaDirection.LTR; root.CalculateLayout(); @@ -231,22 +231,22 @@ namespace Facebook.Yoga public void Test_flex_shrink_to_zero() { YogaNode root = new YogaNode(); - root.Height = 75f; + root.Height = 75; YogaNode root_child0 = new YogaNode(); - root_child0.Width = 50f; - root_child0.Height = 50f; + root_child0.Width = 50; + root_child0.Height = 50; root.Insert(0, root_child0); YogaNode root_child1 = new YogaNode(); - root_child1.FlexShrink = 1f; - root_child1.Width = 50f; - root_child1.Height = 50f; + root_child1.FlexShrink = 1; + root_child1.Width = 50; + root_child1.Height = 50; root.Insert(1, root_child1); YogaNode root_child2 = new YogaNode(); - root_child2.Width = 50f; - root_child2.Height = 50f; + root_child2.Width = 50; + root_child2.Height = 50; root.Insert(2, root_child2); root.StyleDirection = YogaDirection.LTR; root.CalculateLayout(); @@ -299,23 +299,23 @@ namespace Facebook.Yoga public void Test_flex_basis_overrides_main_size() { YogaNode root = new YogaNode(); - root.Width = 100f; - root.Height = 100f; + root.Width = 100; + root.Height = 100; YogaNode root_child0 = new YogaNode(); - root_child0.FlexGrow = 1f; - root_child0.FlexBasis = 50f; - root_child0.Height = 20f; + root_child0.FlexGrow = 1; + root_child0.FlexBasis = 50; + root_child0.Height = 20; root.Insert(0, root_child0); YogaNode root_child1 = new YogaNode(); - root_child1.FlexGrow = 1f; - root_child1.Height = 10f; + root_child1.FlexGrow = 1; + root_child1.Height = 10; root.Insert(1, root_child1); YogaNode root_child2 = new YogaNode(); - root_child2.FlexGrow = 1f; - root_child2.Height = 10f; + root_child2.FlexGrow = 1; + root_child2.Height = 10; root.Insert(2, root_child2); root.StyleDirection = YogaDirection.LTR; root.CalculateLayout(); @@ -368,15 +368,15 @@ namespace Facebook.Yoga public void Test_flex_grow_shrink_at_most() { YogaNode root = new YogaNode(); - root.Width = 100f; - root.Height = 100f; + root.Width = 100; + root.Height = 100; YogaNode root_child0 = new YogaNode(); root.Insert(0, root_child0); YogaNode root_child0_child0 = new YogaNode(); - root_child0_child0.FlexGrow = 1f; - root_child0_child0.FlexShrink = 1f; + root_child0_child0.FlexGrow = 1; + root_child0_child0.FlexShrink = 1; root_child0.Insert(0, root_child0_child0); root.StyleDirection = YogaDirection.LTR; root.CalculateLayout(); diff --git a/csharp/tests/Facebook.Yoga/YGFlexWrapTest.cs b/csharp/tests/Facebook.Yoga/YGFlexWrapTest.cs index d5c88f7f..c4a0c352 100644 --- a/csharp/tests/Facebook.Yoga/YGFlexWrapTest.cs +++ b/csharp/tests/Facebook.Yoga/YGFlexWrapTest.cs @@ -22,26 +22,26 @@ namespace Facebook.Yoga { YogaNode root = new YogaNode(); root.Wrap = YogaWrap.Wrap; - root.Height = 100f; + root.Height = 100; YogaNode root_child0 = new YogaNode(); - root_child0.Width = 30f; - root_child0.Height = 30f; + root_child0.Width = 30; + root_child0.Height = 30; root.Insert(0, root_child0); YogaNode root_child1 = new YogaNode(); - root_child1.Width = 30f; - root_child1.Height = 30f; + root_child1.Width = 30; + root_child1.Height = 30; root.Insert(1, root_child1); YogaNode root_child2 = new YogaNode(); - root_child2.Width = 30f; - root_child2.Height = 30f; + root_child2.Width = 30; + root_child2.Height = 30; root.Insert(2, root_child2); YogaNode root_child3 = new YogaNode(); - root_child3.Width = 30f; - root_child3.Height = 30f; + root_child3.Width = 30; + root_child3.Height = 30; root.Insert(3, root_child3); root.StyleDirection = YogaDirection.LTR; root.CalculateLayout(); @@ -106,26 +106,26 @@ namespace Facebook.Yoga YogaNode root = new YogaNode(); root.FlexDirection = YogaFlexDirection.Row; root.Wrap = YogaWrap.Wrap; - root.Width = 100f; + root.Width = 100; YogaNode root_child0 = new YogaNode(); - root_child0.Width = 30f; - root_child0.Height = 30f; + root_child0.Width = 30; + root_child0.Height = 30; root.Insert(0, root_child0); YogaNode root_child1 = new YogaNode(); - root_child1.Width = 30f; - root_child1.Height = 30f; + root_child1.Width = 30; + root_child1.Height = 30; root.Insert(1, root_child1); YogaNode root_child2 = new YogaNode(); - root_child2.Width = 30f; - root_child2.Height = 30f; + root_child2.Width = 30; + root_child2.Height = 30; root.Insert(2, root_child2); YogaNode root_child3 = new YogaNode(); - root_child3.Width = 30f; - root_child3.Height = 30f; + root_child3.Width = 30; + root_child3.Height = 30; root.Insert(3, root_child3); root.StyleDirection = YogaDirection.LTR; root.CalculateLayout(); @@ -191,26 +191,26 @@ namespace Facebook.Yoga root.FlexDirection = YogaFlexDirection.Row; root.AlignItems = YogaAlign.FlexEnd; root.Wrap = YogaWrap.Wrap; - root.Width = 100f; + root.Width = 100; YogaNode root_child0 = new YogaNode(); - root_child0.Width = 30f; - root_child0.Height = 10f; + root_child0.Width = 30; + root_child0.Height = 10; root.Insert(0, root_child0); YogaNode root_child1 = new YogaNode(); - root_child1.Width = 30f; - root_child1.Height = 20f; + root_child1.Width = 30; + root_child1.Height = 20; root.Insert(1, root_child1); YogaNode root_child2 = new YogaNode(); - root_child2.Width = 30f; - root_child2.Height = 30f; + root_child2.Width = 30; + root_child2.Height = 30; root.Insert(2, root_child2); YogaNode root_child3 = new YogaNode(); - root_child3.Width = 30f; - root_child3.Height = 30f; + root_child3.Width = 30; + root_child3.Height = 30; root.Insert(3, root_child3); root.StyleDirection = YogaDirection.LTR; root.CalculateLayout(); @@ -276,26 +276,26 @@ namespace Facebook.Yoga root.FlexDirection = YogaFlexDirection.Row; root.AlignItems = YogaAlign.Center; root.Wrap = YogaWrap.Wrap; - root.Width = 100f; + root.Width = 100; YogaNode root_child0 = new YogaNode(); - root_child0.Width = 30f; - root_child0.Height = 10f; + root_child0.Width = 30; + root_child0.Height = 10; root.Insert(0, root_child0); YogaNode root_child1 = new YogaNode(); - root_child1.Width = 30f; - root_child1.Height = 20f; + root_child1.Width = 30; + root_child1.Height = 20; root.Insert(1, root_child1); YogaNode root_child2 = new YogaNode(); - root_child2.Width = 30f; - root_child2.Height = 30f; + root_child2.Width = 30; + root_child2.Height = 30; root.Insert(2, root_child2); YogaNode root_child3 = new YogaNode(); - root_child3.Width = 30f; - root_child3.Height = 30f; + root_child3.Width = 30; + root_child3.Height = 30; root.Insert(3, root_child3); root.StyleDirection = YogaDirection.LTR; root.CalculateLayout(); diff --git a/csharp/tests/Facebook.Yoga/YGJustifyContentTest.cs b/csharp/tests/Facebook.Yoga/YGJustifyContentTest.cs index 7c8bb4d1..b36f9551 100644 --- a/csharp/tests/Facebook.Yoga/YGJustifyContentTest.cs +++ b/csharp/tests/Facebook.Yoga/YGJustifyContentTest.cs @@ -22,19 +22,19 @@ namespace Facebook.Yoga { YogaNode root = new YogaNode(); root.FlexDirection = YogaFlexDirection.Row; - root.Width = 102f; - root.Height = 102f; + root.Width = 102; + root.Height = 102; YogaNode root_child0 = new YogaNode(); - root_child0.Width = 10f; + root_child0.Width = 10; root.Insert(0, root_child0); YogaNode root_child1 = new YogaNode(); - root_child1.Width = 10f; + root_child1.Width = 10; root.Insert(1, root_child1); YogaNode root_child2 = new YogaNode(); - root_child2.Width = 10f; + root_child2.Width = 10; root.Insert(2, root_child2); root.StyleDirection = YogaDirection.LTR; root.CalculateLayout(); @@ -89,19 +89,19 @@ namespace Facebook.Yoga YogaNode root = new YogaNode(); root.FlexDirection = YogaFlexDirection.Row; root.JustifyContent = YogaJustify.FlexEnd; - root.Width = 102f; - root.Height = 102f; + root.Width = 102; + root.Height = 102; YogaNode root_child0 = new YogaNode(); - root_child0.Width = 10f; + root_child0.Width = 10; root.Insert(0, root_child0); YogaNode root_child1 = new YogaNode(); - root_child1.Width = 10f; + root_child1.Width = 10; root.Insert(1, root_child1); YogaNode root_child2 = new YogaNode(); - root_child2.Width = 10f; + root_child2.Width = 10; root.Insert(2, root_child2); root.StyleDirection = YogaDirection.LTR; root.CalculateLayout(); @@ -156,19 +156,19 @@ namespace Facebook.Yoga YogaNode root = new YogaNode(); root.FlexDirection = YogaFlexDirection.Row; root.JustifyContent = YogaJustify.Center; - root.Width = 102f; - root.Height = 102f; + root.Width = 102; + root.Height = 102; YogaNode root_child0 = new YogaNode(); - root_child0.Width = 10f; + root_child0.Width = 10; root.Insert(0, root_child0); YogaNode root_child1 = new YogaNode(); - root_child1.Width = 10f; + root_child1.Width = 10; root.Insert(1, root_child1); YogaNode root_child2 = new YogaNode(); - root_child2.Width = 10f; + root_child2.Width = 10; root.Insert(2, root_child2); root.StyleDirection = YogaDirection.LTR; root.CalculateLayout(); @@ -223,19 +223,19 @@ namespace Facebook.Yoga YogaNode root = new YogaNode(); root.FlexDirection = YogaFlexDirection.Row; root.JustifyContent = YogaJustify.SpaceBetween; - root.Width = 102f; - root.Height = 102f; + root.Width = 102; + root.Height = 102; YogaNode root_child0 = new YogaNode(); - root_child0.Width = 10f; + root_child0.Width = 10; root.Insert(0, root_child0); YogaNode root_child1 = new YogaNode(); - root_child1.Width = 10f; + root_child1.Width = 10; root.Insert(1, root_child1); YogaNode root_child2 = new YogaNode(); - root_child2.Width = 10f; + root_child2.Width = 10; root.Insert(2, root_child2); root.StyleDirection = YogaDirection.LTR; root.CalculateLayout(); @@ -290,19 +290,19 @@ namespace Facebook.Yoga YogaNode root = new YogaNode(); root.FlexDirection = YogaFlexDirection.Row; root.JustifyContent = YogaJustify.SpaceAround; - root.Width = 102f; - root.Height = 102f; + root.Width = 102; + root.Height = 102; YogaNode root_child0 = new YogaNode(); - root_child0.Width = 10f; + root_child0.Width = 10; root.Insert(0, root_child0); YogaNode root_child1 = new YogaNode(); - root_child1.Width = 10f; + root_child1.Width = 10; root.Insert(1, root_child1); YogaNode root_child2 = new YogaNode(); - root_child2.Width = 10f; + root_child2.Width = 10; root.Insert(2, root_child2); root.StyleDirection = YogaDirection.LTR; root.CalculateLayout(); @@ -355,18 +355,18 @@ namespace Facebook.Yoga public void Test_justify_content_column_flex_start() { YogaNode root = new YogaNode(); - root.Width = 102f; - root.Height = 102f; + root.Width = 102; + root.Height = 102; YogaNode root_child0 = new YogaNode(); - root_child0.Height = 10f; + root_child0.Height = 10; root.Insert(0, root_child0); YogaNode root_child1 = new YogaNode(); root.Insert(1, root_child1); YogaNode root_child2 = new YogaNode(); - root_child2.Height = 10f; + root_child2.Height = 10; root.Insert(2, root_child2); root.StyleDirection = YogaDirection.LTR; root.CalculateLayout(); @@ -420,19 +420,19 @@ namespace Facebook.Yoga { YogaNode root = new YogaNode(); root.JustifyContent = YogaJustify.FlexEnd; - root.Width = 102f; - root.Height = 102f; + root.Width = 102; + root.Height = 102; YogaNode root_child0 = new YogaNode(); - root_child0.Height = 10f; + root_child0.Height = 10; root.Insert(0, root_child0); YogaNode root_child1 = new YogaNode(); - root_child1.Height = 10f; + root_child1.Height = 10; root.Insert(1, root_child1); YogaNode root_child2 = new YogaNode(); - root_child2.Height = 10f; + root_child2.Height = 10; root.Insert(2, root_child2); root.StyleDirection = YogaDirection.LTR; root.CalculateLayout(); @@ -486,19 +486,19 @@ namespace Facebook.Yoga { YogaNode root = new YogaNode(); root.JustifyContent = YogaJustify.Center; - root.Width = 102f; - root.Height = 102f; + root.Width = 102; + root.Height = 102; YogaNode root_child0 = new YogaNode(); - root_child0.Height = 10f; + root_child0.Height = 10; root.Insert(0, root_child0); YogaNode root_child1 = new YogaNode(); - root_child1.Height = 10f; + root_child1.Height = 10; root.Insert(1, root_child1); YogaNode root_child2 = new YogaNode(); - root_child2.Height = 10f; + root_child2.Height = 10; root.Insert(2, root_child2); root.StyleDirection = YogaDirection.LTR; root.CalculateLayout(); @@ -552,19 +552,19 @@ namespace Facebook.Yoga { YogaNode root = new YogaNode(); root.JustifyContent = YogaJustify.SpaceBetween; - root.Width = 102f; - root.Height = 102f; + root.Width = 102; + root.Height = 102; YogaNode root_child0 = new YogaNode(); - root_child0.Height = 10f; + root_child0.Height = 10; root.Insert(0, root_child0); YogaNode root_child1 = new YogaNode(); - root_child1.Height = 10f; + root_child1.Height = 10; root.Insert(1, root_child1); YogaNode root_child2 = new YogaNode(); - root_child2.Height = 10f; + root_child2.Height = 10; root.Insert(2, root_child2); root.StyleDirection = YogaDirection.LTR; root.CalculateLayout(); @@ -618,19 +618,19 @@ namespace Facebook.Yoga { YogaNode root = new YogaNode(); root.JustifyContent = YogaJustify.SpaceAround; - root.Width = 102f; - root.Height = 102f; + root.Width = 102; + root.Height = 102; YogaNode root_child0 = new YogaNode(); - root_child0.Height = 10f; + root_child0.Height = 10; root.Insert(0, root_child0); YogaNode root_child1 = new YogaNode(); - root_child1.Height = 10f; + root_child1.Height = 10; root.Insert(1, root_child1); YogaNode root_child2 = new YogaNode(); - root_child2.Height = 10f; + root_child2.Height = 10; root.Insert(2, root_child2); root.StyleDirection = YogaDirection.LTR; root.CalculateLayout(); diff --git a/csharp/tests/Facebook.Yoga/YGMarginTest.cs b/csharp/tests/Facebook.Yoga/YGMarginTest.cs index fa9ddee2..cc017ac4 100644 --- a/csharp/tests/Facebook.Yoga/YGMarginTest.cs +++ b/csharp/tests/Facebook.Yoga/YGMarginTest.cs @@ -22,12 +22,12 @@ namespace Facebook.Yoga { YogaNode root = new YogaNode(); root.FlexDirection = YogaFlexDirection.Row; - root.Width = 100f; - root.Height = 100f; + root.Width = 100; + root.Height = 100; YogaNode root_child0 = new YogaNode(); - root_child0.SetMargin(YogaEdge.Start, 10f); - root_child0.Width = 10f; + root_child0.SetMargin(YogaEdge.Start, 10); + root_child0.Width = 10; root.Insert(0, root_child0); root.StyleDirection = YogaDirection.LTR; root.CalculateLayout(); @@ -60,12 +60,12 @@ namespace Facebook.Yoga public void Test_margin_top() { YogaNode root = new YogaNode(); - root.Width = 100f; - root.Height = 100f; + root.Width = 100; + root.Height = 100; YogaNode root_child0 = new YogaNode(); - root_child0.SetMargin(YogaEdge.Top, 10f); - root_child0.Height = 10f; + root_child0.SetMargin(YogaEdge.Top, 10); + root_child0.Height = 10; root.Insert(0, root_child0); root.StyleDirection = YogaDirection.LTR; root.CalculateLayout(); @@ -100,12 +100,12 @@ namespace Facebook.Yoga YogaNode root = new YogaNode(); root.FlexDirection = YogaFlexDirection.Row; root.JustifyContent = YogaJustify.FlexEnd; - root.Width = 100f; - root.Height = 100f; + root.Width = 100; + root.Height = 100; YogaNode root_child0 = new YogaNode(); - root_child0.SetMargin(YogaEdge.End, 10f); - root_child0.Width = 10f; + root_child0.SetMargin(YogaEdge.End, 10); + root_child0.Width = 10; root.Insert(0, root_child0); root.StyleDirection = YogaDirection.LTR; root.CalculateLayout(); @@ -139,12 +139,12 @@ namespace Facebook.Yoga { YogaNode root = new YogaNode(); root.JustifyContent = YogaJustify.FlexEnd; - root.Width = 100f; - root.Height = 100f; + root.Width = 100; + root.Height = 100; YogaNode root_child0 = new YogaNode(); - root_child0.SetMargin(YogaEdge.Bottom, 10f); - root_child0.Height = 10f; + root_child0.SetMargin(YogaEdge.Bottom, 10); + root_child0.Height = 10; root.Insert(0, root_child0); root.StyleDirection = YogaDirection.LTR; root.CalculateLayout(); @@ -178,12 +178,12 @@ namespace Facebook.Yoga { YogaNode root = new YogaNode(); root.FlexDirection = YogaFlexDirection.Row; - root.Width = 100f; - root.Height = 100f; + root.Width = 100; + root.Height = 100; YogaNode root_child0 = new YogaNode(); - root_child0.FlexGrow = 1f; - root_child0.SetMargin(YogaEdge.Start, 10f); + root_child0.FlexGrow = 1; + root_child0.SetMargin(YogaEdge.Start, 10); root.Insert(0, root_child0); root.StyleDirection = YogaDirection.LTR; root.CalculateLayout(); @@ -216,12 +216,12 @@ namespace Facebook.Yoga public void Test_margin_and_flex_column() { YogaNode root = new YogaNode(); - root.Width = 100f; - root.Height = 100f; + root.Width = 100; + root.Height = 100; YogaNode root_child0 = new YogaNode(); - root_child0.FlexGrow = 1f; - root_child0.SetMargin(YogaEdge.Top, 10f); + root_child0.FlexGrow = 1; + root_child0.SetMargin(YogaEdge.Top, 10); root.Insert(0, root_child0); root.StyleDirection = YogaDirection.LTR; root.CalculateLayout(); @@ -255,12 +255,12 @@ namespace Facebook.Yoga { YogaNode root = new YogaNode(); root.FlexDirection = YogaFlexDirection.Row; - root.Width = 100f; - root.Height = 100f; + root.Width = 100; + root.Height = 100; YogaNode root_child0 = new YogaNode(); - root_child0.FlexGrow = 1f; - root_child0.SetMargin(YogaEdge.Top, 10f); + root_child0.FlexGrow = 1; + root_child0.SetMargin(YogaEdge.Top, 10); root.Insert(0, root_child0); root.StyleDirection = YogaDirection.LTR; root.CalculateLayout(); @@ -293,12 +293,12 @@ namespace Facebook.Yoga public void Test_margin_and_stretch_column() { YogaNode root = new YogaNode(); - root.Width = 100f; - root.Height = 100f; + root.Width = 100; + root.Height = 100; YogaNode root_child0 = new YogaNode(); - root_child0.FlexGrow = 1f; - root_child0.SetMargin(YogaEdge.Start, 10f); + root_child0.FlexGrow = 1; + root_child0.SetMargin(YogaEdge.Start, 10); root.Insert(0, root_child0); root.StyleDirection = YogaDirection.LTR; root.CalculateLayout(); @@ -332,15 +332,15 @@ namespace Facebook.Yoga { YogaNode root = new YogaNode(); root.FlexDirection = YogaFlexDirection.Row; - root.Width = 100f; - root.Height = 100f; + root.Width = 100; + root.Height = 100; YogaNode root_child0 = new YogaNode(); - root_child0.FlexGrow = 1f; + root_child0.FlexGrow = 1; root.Insert(0, root_child0); YogaNode root_child1 = new YogaNode(); - root_child1.FlexGrow = 1f; + root_child1.FlexGrow = 1; root.Insert(1, root_child1); root.StyleDirection = YogaDirection.LTR; root.CalculateLayout(); @@ -383,15 +383,15 @@ namespace Facebook.Yoga public void Test_margin_with_sibling_column() { YogaNode root = new YogaNode(); - root.Width = 100f; - root.Height = 100f; + root.Width = 100; + root.Height = 100; YogaNode root_child0 = new YogaNode(); - root_child0.FlexGrow = 1f; + root_child0.FlexGrow = 1; root.Insert(0, root_child0); YogaNode root_child1 = new YogaNode(); - root_child1.FlexGrow = 1f; + root_child1.FlexGrow = 1; root.Insert(1, root_child1); root.StyleDirection = YogaDirection.LTR; root.CalculateLayout(); diff --git a/csharp/tests/Facebook.Yoga/YGMinMaxDimensionTest.cs b/csharp/tests/Facebook.Yoga/YGMinMaxDimensionTest.cs index 39eca9ca..47568b6e 100644 --- a/csharp/tests/Facebook.Yoga/YGMinMaxDimensionTest.cs +++ b/csharp/tests/Facebook.Yoga/YGMinMaxDimensionTest.cs @@ -21,12 +21,12 @@ namespace Facebook.Yoga public void Test_max_width() { YogaNode root = new YogaNode(); - root.Width = 100f; - root.Height = 100f; + root.Width = 100; + root.Height = 100; YogaNode root_child0 = new YogaNode(); - root_child0.MaxWidth = 50f; - root_child0.Height = 10f; + root_child0.MaxWidth = 50; + root_child0.Height = 10; root.Insert(0, root_child0); root.StyleDirection = YogaDirection.LTR; root.CalculateLayout(); @@ -60,12 +60,12 @@ namespace Facebook.Yoga { YogaNode root = new YogaNode(); root.FlexDirection = YogaFlexDirection.Row; - root.Width = 100f; - root.Height = 100f; + root.Width = 100; + root.Height = 100; YogaNode root_child0 = new YogaNode(); - root_child0.Width = 10f; - root_child0.MaxHeight = 50f; + root_child0.Width = 10; + root_child0.MaxHeight = 50; root.Insert(0, root_child0); root.StyleDirection = YogaDirection.LTR; root.CalculateLayout(); @@ -98,16 +98,16 @@ namespace Facebook.Yoga public void Test_min_height() { YogaNode root = new YogaNode(); - root.Width = 100f; - root.Height = 100f; + root.Width = 100; + root.Height = 100; YogaNode root_child0 = new YogaNode(); - root_child0.FlexGrow = 1f; - root_child0.MinHeight = 60f; + root_child0.FlexGrow = 1; + root_child0.MinHeight = 60; root.Insert(0, root_child0); YogaNode root_child1 = new YogaNode(); - root_child1.FlexGrow = 1f; + root_child1.FlexGrow = 1; root.Insert(1, root_child1); root.StyleDirection = YogaDirection.LTR; root.CalculateLayout(); @@ -151,16 +151,16 @@ namespace Facebook.Yoga { YogaNode root = new YogaNode(); root.FlexDirection = YogaFlexDirection.Row; - root.Width = 100f; - root.Height = 100f; + root.Width = 100; + root.Height = 100; YogaNode root_child0 = new YogaNode(); - root_child0.FlexGrow = 1f; - root_child0.MinWidth = 60f; + root_child0.FlexGrow = 1; + root_child0.MinWidth = 60; root.Insert(0, root_child0); YogaNode root_child1 = new YogaNode(); - root_child1.FlexGrow = 1f; + root_child1.FlexGrow = 1; root.Insert(1, root_child1); root.StyleDirection = YogaDirection.LTR; root.CalculateLayout(); @@ -204,13 +204,13 @@ namespace Facebook.Yoga { YogaNode root = new YogaNode(); root.JustifyContent = YogaJustify.Center; - root.Width = 100f; - root.MinHeight = 100f; - root.MaxHeight = 200f; + root.Width = 100; + root.MinHeight = 100; + root.MaxHeight = 200; YogaNode root_child0 = new YogaNode(); - root_child0.Width = 60f; - root_child0.Height = 60f; + root_child0.Width = 60; + root_child0.Height = 60; root.Insert(0, root_child0); root.StyleDirection = YogaDirection.LTR; root.CalculateLayout(); @@ -244,13 +244,13 @@ namespace Facebook.Yoga { YogaNode root = new YogaNode(); root.AlignItems = YogaAlign.Center; - root.MinWidth = 100f; - root.MaxWidth = 200f; - root.Height = 100f; + root.MinWidth = 100; + root.MaxWidth = 200; + root.Height = 100; YogaNode root_child0 = new YogaNode(); - root_child0.Width = 60f; - root_child0.Height = 60f; + root_child0.Width = 60; + root_child0.Height = 60; root.Insert(0, root_child0); root.StyleDirection = YogaDirection.LTR; root.CalculateLayout(); @@ -284,22 +284,22 @@ namespace Facebook.Yoga { YogaNode root = new YogaNode(); root.JustifyContent = YogaJustify.Center; - root.MinHeight = 100f; - root.MaxHeight = 110f; + root.MinHeight = 100; + root.MaxHeight = 110; YogaNode root_child0 = new YogaNode(); - root_child0.Width = 50f; - root_child0.Height = 50f; + root_child0.Width = 50; + root_child0.Height = 50; root.Insert(0, root_child0); YogaNode root_child1 = new YogaNode(); - root_child1.Width = 50f; - root_child1.Height = 50f; + root_child1.Width = 50; + root_child1.Height = 50; root.Insert(1, root_child1); YogaNode root_child2 = new YogaNode(); - root_child2.Width = 50f; - root_child2.Height = 50f; + root_child2.Width = 50; + root_child2.Height = 50; root.Insert(2, root_child2); root.StyleDirection = YogaDirection.LTR; root.CalculateLayout(); @@ -352,17 +352,17 @@ namespace Facebook.Yoga public void Test_flex_grow_within_max_width() { YogaNode root = new YogaNode(); - root.Width = 200f; - root.Height = 100f; + root.Width = 200; + root.Height = 100; YogaNode root_child0 = new YogaNode(); root_child0.FlexDirection = YogaFlexDirection.Row; - root_child0.MaxWidth = 100f; + root_child0.MaxWidth = 100; root.Insert(0, root_child0); YogaNode root_child0_child0 = new YogaNode(); - root_child0_child0.FlexGrow = 1f; - root_child0_child0.Height = 20f; + root_child0_child0.FlexGrow = 1; + root_child0_child0.Height = 20; root_child0.Insert(0, root_child0_child0); root.StyleDirection = YogaDirection.LTR; root.CalculateLayout(); @@ -405,17 +405,17 @@ namespace Facebook.Yoga public void Test_flex_grow_within_constrained_max_width() { YogaNode root = new YogaNode(); - root.Width = 200f; - root.Height = 100f; + root.Width = 200; + root.Height = 100; YogaNode root_child0 = new YogaNode(); root_child0.FlexDirection = YogaFlexDirection.Row; - root_child0.MaxWidth = 300f; + root_child0.MaxWidth = 300; root.Insert(0, root_child0); YogaNode root_child0_child0 = new YogaNode(); - root_child0_child0.FlexGrow = 1f; - root_child0_child0.Height = 20f; + root_child0_child0.FlexGrow = 1; + root_child0_child0.Height = 20; root_child0.Insert(0, root_child0_child0); root.StyleDirection = YogaDirection.LTR; root.CalculateLayout(); @@ -459,15 +459,15 @@ namespace Facebook.Yoga { YogaNode root = new YogaNode(); root.FlexDirection = YogaFlexDirection.Row; - root.MinWidth = 100f; - root.Height = 100f; + root.MinWidth = 100; + root.Height = 100; YogaNode root_child0 = new YogaNode(); - root_child0.FlexGrow = 1f; + root_child0.FlexGrow = 1; root.Insert(0, root_child0); YogaNode root_child1 = new YogaNode(); - root_child1.Width = 50f; + root_child1.Width = 50; root.Insert(1, root_child1); root.StyleDirection = YogaDirection.LTR; root.CalculateLayout(); @@ -510,14 +510,14 @@ namespace Facebook.Yoga public void Test_flex_grow_within_constrained_min_column() { YogaNode root = new YogaNode(); - root.MinHeight = 100f; + root.MinHeight = 100; YogaNode root_child0 = new YogaNode(); - root_child0.FlexGrow = 1f; + root_child0.FlexGrow = 1; root.Insert(0, root_child0); YogaNode root_child1 = new YogaNode(); - root_child1.Height = 50f; + root_child1.Height = 50; root.Insert(1, root_child1); root.StyleDirection = YogaDirection.LTR; root.CalculateLayout(); @@ -560,21 +560,21 @@ namespace Facebook.Yoga public void Test_flex_grow_within_constrained_max_row() { YogaNode root = new YogaNode(); - root.Width = 200f; + root.Width = 200; YogaNode root_child0 = new YogaNode(); root_child0.FlexDirection = YogaFlexDirection.Row; - root_child0.MaxWidth = 100f; - root_child0.Height = 100f; + root_child0.MaxWidth = 100; + root_child0.Height = 100; root.Insert(0, root_child0); YogaNode root_child0_child0 = new YogaNode(); - root_child0_child0.FlexShrink = 1f; - root_child0_child0.FlexBasis = 100f; + root_child0_child0.FlexShrink = 1; + root_child0_child0.FlexBasis = 100; root_child0.Insert(0, root_child0_child0); YogaNode root_child0_child1 = new YogaNode(); - root_child0_child1.Width = 50f; + root_child0_child1.Width = 50; root_child0.Insert(1, root_child0_child1); root.StyleDirection = YogaDirection.LTR; root.CalculateLayout(); @@ -627,16 +627,16 @@ namespace Facebook.Yoga public void Test_flex_grow_within_constrained_max_column() { YogaNode root = new YogaNode(); - root.Width = 100f; - root.MaxHeight = 100f; + root.Width = 100; + root.MaxHeight = 100; YogaNode root_child0 = new YogaNode(); - root_child0.FlexShrink = 1f; - root_child0.FlexBasis = 100f; + root_child0.FlexShrink = 1; + root_child0.FlexBasis = 100; root.Insert(0, root_child0); YogaNode root_child1 = new YogaNode(); - root_child1.Height = 50f; + root_child1.Height = 50; root.Insert(1, root_child1); root.StyleDirection = YogaDirection.LTR; root.CalculateLayout(); diff --git a/csharp/tests/Facebook.Yoga/YGPaddingTest.cs b/csharp/tests/Facebook.Yoga/YGPaddingTest.cs index 7fde4e5e..b3f17014 100644 --- a/csharp/tests/Facebook.Yoga/YGPaddingTest.cs +++ b/csharp/tests/Facebook.Yoga/YGPaddingTest.cs @@ -21,10 +21,10 @@ namespace Facebook.Yoga public void Test_padding_no_size() { YogaNode root = new YogaNode(); - root.SetPadding(YogaEdge.Left, 10f); - root.SetPadding(YogaEdge.Top, 10f); - root.SetPadding(YogaEdge.Right, 10f); - root.SetPadding(YogaEdge.Bottom, 10f); + root.SetPadding(YogaEdge.Left, 10); + root.SetPadding(YogaEdge.Top, 10); + root.SetPadding(YogaEdge.Right, 10); + root.SetPadding(YogaEdge.Bottom, 10); root.StyleDirection = YogaDirection.LTR; root.CalculateLayout(); @@ -46,14 +46,14 @@ namespace Facebook.Yoga public void Test_padding_container_match_child() { YogaNode root = new YogaNode(); - root.SetPadding(YogaEdge.Left, 10f); - root.SetPadding(YogaEdge.Top, 10f); - root.SetPadding(YogaEdge.Right, 10f); - root.SetPadding(YogaEdge.Bottom, 10f); + root.SetPadding(YogaEdge.Left, 10); + root.SetPadding(YogaEdge.Top, 10); + root.SetPadding(YogaEdge.Right, 10); + root.SetPadding(YogaEdge.Bottom, 10); YogaNode root_child0 = new YogaNode(); - root_child0.Width = 10f; - root_child0.Height = 10f; + root_child0.Width = 10; + root_child0.Height = 10; root.Insert(0, root_child0); root.StyleDirection = YogaDirection.LTR; root.CalculateLayout(); @@ -86,16 +86,16 @@ namespace Facebook.Yoga public void Test_padding_flex_child() { YogaNode root = new YogaNode(); - root.SetPadding(YogaEdge.Left, 10f); - root.SetPadding(YogaEdge.Top, 10f); - root.SetPadding(YogaEdge.Right, 10f); - root.SetPadding(YogaEdge.Bottom, 10f); - root.Width = 100f; - root.Height = 100f; + root.SetPadding(YogaEdge.Left, 10); + root.SetPadding(YogaEdge.Top, 10); + root.SetPadding(YogaEdge.Right, 10); + root.SetPadding(YogaEdge.Bottom, 10); + root.Width = 100; + root.Height = 100; YogaNode root_child0 = new YogaNode(); - root_child0.FlexGrow = 1f; - root_child0.Width = 10f; + root_child0.FlexGrow = 1; + root_child0.Width = 10; root.Insert(0, root_child0); root.StyleDirection = YogaDirection.LTR; root.CalculateLayout(); @@ -128,15 +128,15 @@ namespace Facebook.Yoga public void Test_padding_stretch_child() { YogaNode root = new YogaNode(); - root.SetPadding(YogaEdge.Left, 10f); - root.SetPadding(YogaEdge.Top, 10f); - root.SetPadding(YogaEdge.Right, 10f); - root.SetPadding(YogaEdge.Bottom, 10f); - root.Width = 100f; - root.Height = 100f; + root.SetPadding(YogaEdge.Left, 10); + root.SetPadding(YogaEdge.Top, 10); + root.SetPadding(YogaEdge.Right, 10); + root.SetPadding(YogaEdge.Bottom, 10); + root.Width = 100; + root.Height = 100; YogaNode root_child0 = new YogaNode(); - root_child0.Height = 10f; + root_child0.Height = 10; root.Insert(0, root_child0); root.StyleDirection = YogaDirection.LTR; root.CalculateLayout(); @@ -171,15 +171,15 @@ namespace Facebook.Yoga YogaNode root = new YogaNode(); root.JustifyContent = YogaJustify.Center; root.AlignItems = YogaAlign.Center; - root.SetPadding(YogaEdge.Start, 10f); - root.SetPadding(YogaEdge.End, 20f); - root.SetPadding(YogaEdge.Bottom, 20f); - root.Width = 100f; - root.Height = 100f; + root.SetPadding(YogaEdge.Start, 10); + root.SetPadding(YogaEdge.End, 20); + root.SetPadding(YogaEdge.Bottom, 20); + root.Width = 100; + root.Height = 100; YogaNode root_child0 = new YogaNode(); - root_child0.Width = 10f; - root_child0.Height = 10f; + root_child0.Width = 10; + root_child0.Height = 10; root.Insert(0, root_child0); root.StyleDirection = YogaDirection.LTR; root.CalculateLayout(); @@ -214,16 +214,16 @@ namespace Facebook.Yoga YogaNode root = new YogaNode(); root.JustifyContent = YogaJustify.FlexEnd; root.AlignItems = YogaAlign.FlexEnd; - root.Width = 200f; - root.Height = 200f; + root.Width = 200; + root.Height = 200; YogaNode root_child0 = new YogaNode(); - root_child0.SetPadding(YogaEdge.Left, 20f); - root_child0.SetPadding(YogaEdge.Top, 20f); - root_child0.SetPadding(YogaEdge.Right, 20f); - root_child0.SetPadding(YogaEdge.Bottom, 20f); - root_child0.Width = 100f; - root_child0.Height = 100f; + root_child0.SetPadding(YogaEdge.Left, 20); + root_child0.SetPadding(YogaEdge.Top, 20); + root_child0.SetPadding(YogaEdge.Right, 20); + root_child0.SetPadding(YogaEdge.Bottom, 20); + root_child0.Width = 100; + root_child0.Height = 100; root.Insert(0, root_child0); root.StyleDirection = YogaDirection.LTR; root.CalculateLayout(); diff --git a/csharp/tests/Facebook.Yoga/YGPercentageTest.cs b/csharp/tests/Facebook.Yoga/YGPercentageTest.cs new file mode 100644 index 00000000..7c9bc423 --- /dev/null +++ b/csharp/tests/Facebook.Yoga/YGPercentageTest.cs @@ -0,0 +1,959 @@ +/** + * 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. + */ + + // @Generated by gentest/gentest.rb from gentest/fixtures/YGPercentageTest.html + +using System; +using NUnit.Framework; + +namespace Facebook.Yoga +{ + [TestFixture] + public class YGPercentageTest + { + [Test] + public void Test_percentage_width_height() + { + YogaNode.SetExperimentalFeatureEnabled(YogaExperimentalFeature.Rounding, true); + + YogaNode root = new YogaNode(); + root.FlexDirection = YogaFlexDirection.Row; + root.Width = 200; + root.Height = 200; + + YogaNode root_child0 = new YogaNode(); + root_child0.Width = 30.Percent(); + root_child0.Height = 30.Percent(); + root.Insert(0, root_child0); + root.StyleDirection = YogaDirection.LTR; + root.CalculateLayout(); + + Assert.AreEqual(0f, root.LayoutX); + Assert.AreEqual(0f, root.LayoutY); + Assert.AreEqual(200f, root.LayoutWidth); + Assert.AreEqual(200f, root.LayoutHeight); + + Assert.AreEqual(0f, root_child0.LayoutX); + Assert.AreEqual(0f, root_child0.LayoutY); + Assert.AreEqual(60f, root_child0.LayoutWidth); + Assert.AreEqual(60f, root_child0.LayoutHeight); + + root.StyleDirection = YogaDirection.RTL; + root.CalculateLayout(); + + Assert.AreEqual(0f, root.LayoutX); + Assert.AreEqual(0f, root.LayoutY); + Assert.AreEqual(200f, root.LayoutWidth); + Assert.AreEqual(200f, root.LayoutHeight); + + Assert.AreEqual(140f, root_child0.LayoutX); + Assert.AreEqual(0f, root_child0.LayoutY); + Assert.AreEqual(60f, root_child0.LayoutWidth); + Assert.AreEqual(60f, root_child0.LayoutHeight); + + YogaNode.SetExperimentalFeatureEnabled(YogaExperimentalFeature.Rounding, false); + } + + [Test] + public void Test_percentage_position_left_top() + { + YogaNode.SetExperimentalFeatureEnabled(YogaExperimentalFeature.Rounding, true); + + YogaNode root = new YogaNode(); + root.FlexDirection = YogaFlexDirection.Row; + root.Width = 400; + root.Height = 400; + + YogaNode root_child0 = new YogaNode(); + root_child0.SetPosition(YogaEdge.Left, 10.Percent()); + root_child0.SetPosition(YogaEdge.Top, 20.Percent()); + root_child0.Width = 45.Percent(); + root_child0.Height = 55.Percent(); + root.Insert(0, root_child0); + root.StyleDirection = YogaDirection.LTR; + root.CalculateLayout(); + + Assert.AreEqual(0f, root.LayoutX); + Assert.AreEqual(0f, root.LayoutY); + Assert.AreEqual(400f, root.LayoutWidth); + Assert.AreEqual(400f, root.LayoutHeight); + + Assert.AreEqual(40f, root_child0.LayoutX); + Assert.AreEqual(80f, root_child0.LayoutY); + Assert.AreEqual(180f, root_child0.LayoutWidth); + Assert.AreEqual(220f, root_child0.LayoutHeight); + + root.StyleDirection = YogaDirection.RTL; + root.CalculateLayout(); + + Assert.AreEqual(0f, root.LayoutX); + Assert.AreEqual(0f, root.LayoutY); + Assert.AreEqual(400f, root.LayoutWidth); + Assert.AreEqual(400f, root.LayoutHeight); + + Assert.AreEqual(260f, root_child0.LayoutX); + Assert.AreEqual(80f, root_child0.LayoutY); + Assert.AreEqual(180f, root_child0.LayoutWidth); + Assert.AreEqual(220f, root_child0.LayoutHeight); + + YogaNode.SetExperimentalFeatureEnabled(YogaExperimentalFeature.Rounding, false); + } + + [Test] + public void Test_percentage_position_bottom_right() + { + YogaNode.SetExperimentalFeatureEnabled(YogaExperimentalFeature.Rounding, true); + + YogaNode root = new YogaNode(); + root.FlexDirection = YogaFlexDirection.Row; + root.Width = 500; + root.Height = 500; + + YogaNode root_child0 = new YogaNode(); + root_child0.SetPosition(YogaEdge.Right, 20.Percent()); + root_child0.SetPosition(YogaEdge.Bottom, 10.Percent()); + root_child0.Width = 55.Percent(); + root_child0.Height = 15.Percent(); + root.Insert(0, root_child0); + root.StyleDirection = YogaDirection.LTR; + root.CalculateLayout(); + + Assert.AreEqual(0f, root.LayoutX); + Assert.AreEqual(0f, root.LayoutY); + Assert.AreEqual(500f, root.LayoutWidth); + Assert.AreEqual(500f, root.LayoutHeight); + + Assert.AreEqual(-100f, root_child0.LayoutX); + Assert.AreEqual(-50f, root_child0.LayoutY); + Assert.AreEqual(275f, root_child0.LayoutWidth); + Assert.AreEqual(75f, root_child0.LayoutHeight); + + root.StyleDirection = YogaDirection.RTL; + root.CalculateLayout(); + + Assert.AreEqual(0f, root.LayoutX); + Assert.AreEqual(0f, root.LayoutY); + Assert.AreEqual(500f, root.LayoutWidth); + Assert.AreEqual(500f, root.LayoutHeight); + + Assert.AreEqual(125f, root_child0.LayoutX); + Assert.AreEqual(-50f, root_child0.LayoutY); + Assert.AreEqual(275f, root_child0.LayoutWidth); + Assert.AreEqual(75f, root_child0.LayoutHeight); + + YogaNode.SetExperimentalFeatureEnabled(YogaExperimentalFeature.Rounding, false); + } + + [Test] + public void Test_percentage_flex_basis() + { + YogaNode.SetExperimentalFeatureEnabled(YogaExperimentalFeature.Rounding, true); + + YogaNode root = new YogaNode(); + root.FlexDirection = YogaFlexDirection.Row; + root.Width = 200; + root.Height = 200; + + YogaNode root_child0 = new YogaNode(); + root_child0.FlexGrow = 1; + root_child0.FlexBasis = 50.Percent(); + root.Insert(0, root_child0); + + YogaNode root_child1 = new YogaNode(); + root_child1.FlexGrow = 1; + root_child1.FlexBasis = 25.Percent(); + root.Insert(1, root_child1); + root.StyleDirection = YogaDirection.LTR; + root.CalculateLayout(); + + Assert.AreEqual(0f, root.LayoutX); + Assert.AreEqual(0f, root.LayoutY); + Assert.AreEqual(200f, root.LayoutWidth); + Assert.AreEqual(200f, root.LayoutHeight); + + Assert.AreEqual(0f, root_child0.LayoutX); + Assert.AreEqual(0f, root_child0.LayoutY); + Assert.AreEqual(125f, root_child0.LayoutWidth); + Assert.AreEqual(200f, root_child0.LayoutHeight); + + Assert.AreEqual(125f, root_child1.LayoutX); + Assert.AreEqual(0f, root_child1.LayoutY); + Assert.AreEqual(75f, root_child1.LayoutWidth); + Assert.AreEqual(200f, root_child1.LayoutHeight); + + root.StyleDirection = YogaDirection.RTL; + root.CalculateLayout(); + + Assert.AreEqual(0f, root.LayoutX); + Assert.AreEqual(0f, root.LayoutY); + Assert.AreEqual(200f, root.LayoutWidth); + Assert.AreEqual(200f, root.LayoutHeight); + + Assert.AreEqual(75f, root_child0.LayoutX); + Assert.AreEqual(0f, root_child0.LayoutY); + Assert.AreEqual(125f, root_child0.LayoutWidth); + Assert.AreEqual(200f, root_child0.LayoutHeight); + + Assert.AreEqual(0f, root_child1.LayoutX); + Assert.AreEqual(0f, root_child1.LayoutY); + Assert.AreEqual(75f, root_child1.LayoutWidth); + Assert.AreEqual(200f, root_child1.LayoutHeight); + + YogaNode.SetExperimentalFeatureEnabled(YogaExperimentalFeature.Rounding, false); + } + + [Test] + public void Test_percentage_flex_basis_cross() + { + YogaNode.SetExperimentalFeatureEnabled(YogaExperimentalFeature.Rounding, true); + + YogaNode root = new YogaNode(); + root.Width = 200; + root.Height = 200; + + YogaNode root_child0 = new YogaNode(); + root_child0.FlexGrow = 1; + root_child0.FlexBasis = 50.Percent(); + root.Insert(0, root_child0); + + YogaNode root_child1 = new YogaNode(); + root_child1.FlexGrow = 1; + root_child1.FlexBasis = 25.Percent(); + root.Insert(1, root_child1); + root.StyleDirection = YogaDirection.LTR; + root.CalculateLayout(); + + Assert.AreEqual(0f, root.LayoutX); + Assert.AreEqual(0f, root.LayoutY); + Assert.AreEqual(200f, root.LayoutWidth); + Assert.AreEqual(200f, root.LayoutHeight); + + Assert.AreEqual(0f, root_child0.LayoutX); + Assert.AreEqual(0f, root_child0.LayoutY); + Assert.AreEqual(200f, root_child0.LayoutWidth); + Assert.AreEqual(125f, root_child0.LayoutHeight); + + Assert.AreEqual(0f, root_child1.LayoutX); + Assert.AreEqual(125f, root_child1.LayoutY); + Assert.AreEqual(200f, root_child1.LayoutWidth); + Assert.AreEqual(75f, root_child1.LayoutHeight); + + root.StyleDirection = YogaDirection.RTL; + root.CalculateLayout(); + + Assert.AreEqual(0f, root.LayoutX); + Assert.AreEqual(0f, root.LayoutY); + Assert.AreEqual(200f, root.LayoutWidth); + Assert.AreEqual(200f, root.LayoutHeight); + + Assert.AreEqual(0f, root_child0.LayoutX); + Assert.AreEqual(0f, root_child0.LayoutY); + Assert.AreEqual(200f, root_child0.LayoutWidth); + Assert.AreEqual(125f, root_child0.LayoutHeight); + + Assert.AreEqual(0f, root_child1.LayoutX); + Assert.AreEqual(125f, root_child1.LayoutY); + Assert.AreEqual(200f, root_child1.LayoutWidth); + Assert.AreEqual(75f, root_child1.LayoutHeight); + + YogaNode.SetExperimentalFeatureEnabled(YogaExperimentalFeature.Rounding, false); + } + + [Test] + public void Test_percentage_flex_basis_cross_min_height() + { + YogaNode.SetExperimentalFeatureEnabled(YogaExperimentalFeature.Rounding, true); + + YogaNode root = new YogaNode(); + root.Width = 200; + root.Height = 200; + + YogaNode root_child0 = new YogaNode(); + root_child0.FlexGrow = 1; + root_child0.MinHeight = 60.Percent(); + root.Insert(0, root_child0); + + YogaNode root_child1 = new YogaNode(); + root_child1.FlexGrow = 2; + root_child1.MinHeight = 10.Percent(); + root.Insert(1, root_child1); + root.StyleDirection = YogaDirection.LTR; + root.CalculateLayout(); + + Assert.AreEqual(0f, root.LayoutX); + Assert.AreEqual(0f, root.LayoutY); + Assert.AreEqual(200f, root.LayoutWidth); + Assert.AreEqual(200f, root.LayoutHeight); + + Assert.AreEqual(0f, root_child0.LayoutX); + Assert.AreEqual(0f, root_child0.LayoutY); + Assert.AreEqual(200f, root_child0.LayoutWidth); + Assert.AreEqual(140f, root_child0.LayoutHeight); + + Assert.AreEqual(0f, root_child1.LayoutX); + Assert.AreEqual(140f, root_child1.LayoutY); + Assert.AreEqual(200f, root_child1.LayoutWidth); + Assert.AreEqual(60f, root_child1.LayoutHeight); + + root.StyleDirection = YogaDirection.RTL; + root.CalculateLayout(); + + Assert.AreEqual(0f, root.LayoutX); + Assert.AreEqual(0f, root.LayoutY); + Assert.AreEqual(200f, root.LayoutWidth); + Assert.AreEqual(200f, root.LayoutHeight); + + Assert.AreEqual(0f, root_child0.LayoutX); + Assert.AreEqual(0f, root_child0.LayoutY); + Assert.AreEqual(200f, root_child0.LayoutWidth); + Assert.AreEqual(140f, root_child0.LayoutHeight); + + Assert.AreEqual(0f, root_child1.LayoutX); + Assert.AreEqual(140f, root_child1.LayoutY); + Assert.AreEqual(200f, root_child1.LayoutWidth); + Assert.AreEqual(60f, root_child1.LayoutHeight); + + YogaNode.SetExperimentalFeatureEnabled(YogaExperimentalFeature.Rounding, false); + } + + [Test] + public void Test_percentage_flex_basis_main_max_height() + { + YogaNode.SetExperimentalFeatureEnabled(YogaExperimentalFeature.Rounding, true); + + YogaNode root = new YogaNode(); + root.FlexDirection = YogaFlexDirection.Row; + root.Width = 200; + root.Height = 200; + + YogaNode root_child0 = new YogaNode(); + root_child0.FlexGrow = 1; + root_child0.FlexBasis = 10.Percent(); + root_child0.MaxHeight = 60.Percent(); + root.Insert(0, root_child0); + + YogaNode root_child1 = new YogaNode(); + root_child1.FlexGrow = 4; + root_child1.FlexBasis = 10.Percent(); + root_child1.MaxHeight = 20.Percent(); + root.Insert(1, root_child1); + root.StyleDirection = YogaDirection.LTR; + root.CalculateLayout(); + + Assert.AreEqual(0f, root.LayoutX); + Assert.AreEqual(0f, root.LayoutY); + Assert.AreEqual(200f, root.LayoutWidth); + Assert.AreEqual(200f, root.LayoutHeight); + + Assert.AreEqual(0f, root_child0.LayoutX); + Assert.AreEqual(0f, root_child0.LayoutY); + Assert.AreEqual(52f, root_child0.LayoutWidth); + Assert.AreEqual(120f, root_child0.LayoutHeight); + + Assert.AreEqual(52f, root_child1.LayoutX); + Assert.AreEqual(0f, root_child1.LayoutY); + Assert.AreEqual(148f, root_child1.LayoutWidth); + Assert.AreEqual(40f, root_child1.LayoutHeight); + + root.StyleDirection = YogaDirection.RTL; + root.CalculateLayout(); + + Assert.AreEqual(0f, root.LayoutX); + Assert.AreEqual(0f, root.LayoutY); + Assert.AreEqual(200f, root.LayoutWidth); + Assert.AreEqual(200f, root.LayoutHeight); + + Assert.AreEqual(148f, root_child0.LayoutX); + Assert.AreEqual(0f, root_child0.LayoutY); + Assert.AreEqual(52f, root_child0.LayoutWidth); + Assert.AreEqual(120f, root_child0.LayoutHeight); + + Assert.AreEqual(0f, root_child1.LayoutX); + Assert.AreEqual(0f, root_child1.LayoutY); + Assert.AreEqual(148f, root_child1.LayoutWidth); + Assert.AreEqual(40f, root_child1.LayoutHeight); + + YogaNode.SetExperimentalFeatureEnabled(YogaExperimentalFeature.Rounding, false); + } + + [Test] + public void Test_percentage_flex_basis_cross_max_height() + { + YogaNode.SetExperimentalFeatureEnabled(YogaExperimentalFeature.Rounding, true); + + YogaNode root = new YogaNode(); + root.Width = 200; + root.Height = 200; + + YogaNode root_child0 = new YogaNode(); + root_child0.FlexGrow = 1; + root_child0.FlexBasis = 10.Percent(); + root_child0.MaxHeight = 60.Percent(); + root.Insert(0, root_child0); + + YogaNode root_child1 = new YogaNode(); + root_child1.FlexGrow = 4; + root_child1.FlexBasis = 10.Percent(); + root_child1.MaxHeight = 20.Percent(); + root.Insert(1, root_child1); + root.StyleDirection = YogaDirection.LTR; + root.CalculateLayout(); + + Assert.AreEqual(0f, root.LayoutX); + Assert.AreEqual(0f, root.LayoutY); + Assert.AreEqual(200f, root.LayoutWidth); + Assert.AreEqual(200f, root.LayoutHeight); + + Assert.AreEqual(0f, root_child0.LayoutX); + Assert.AreEqual(0f, root_child0.LayoutY); + Assert.AreEqual(200f, root_child0.LayoutWidth); + Assert.AreEqual(120f, root_child0.LayoutHeight); + + Assert.AreEqual(0f, root_child1.LayoutX); + Assert.AreEqual(120f, root_child1.LayoutY); + Assert.AreEqual(200f, root_child1.LayoutWidth); + Assert.AreEqual(40f, root_child1.LayoutHeight); + + root.StyleDirection = YogaDirection.RTL; + root.CalculateLayout(); + + Assert.AreEqual(0f, root.LayoutX); + Assert.AreEqual(0f, root.LayoutY); + Assert.AreEqual(200f, root.LayoutWidth); + Assert.AreEqual(200f, root.LayoutHeight); + + Assert.AreEqual(0f, root_child0.LayoutX); + Assert.AreEqual(0f, root_child0.LayoutY); + Assert.AreEqual(200f, root_child0.LayoutWidth); + Assert.AreEqual(120f, root_child0.LayoutHeight); + + Assert.AreEqual(0f, root_child1.LayoutX); + Assert.AreEqual(120f, root_child1.LayoutY); + Assert.AreEqual(200f, root_child1.LayoutWidth); + Assert.AreEqual(40f, root_child1.LayoutHeight); + + YogaNode.SetExperimentalFeatureEnabled(YogaExperimentalFeature.Rounding, false); + } + + [Test] + public void Test_percentage_flex_basis_main_max_width() + { + YogaNode.SetExperimentalFeatureEnabled(YogaExperimentalFeature.Rounding, true); + + YogaNode root = new YogaNode(); + root.FlexDirection = YogaFlexDirection.Row; + root.Width = 200; + root.Height = 200; + + YogaNode root_child0 = new YogaNode(); + root_child0.FlexGrow = 1; + root_child0.FlexBasis = 15.Percent(); + root_child0.MaxWidth = 60.Percent(); + root.Insert(0, root_child0); + + YogaNode root_child1 = new YogaNode(); + root_child1.FlexGrow = 4; + root_child1.FlexBasis = 10.Percent(); + root_child1.MaxWidth = 20.Percent(); + root.Insert(1, root_child1); + root.StyleDirection = YogaDirection.LTR; + root.CalculateLayout(); + + Assert.AreEqual(0f, root.LayoutX); + Assert.AreEqual(0f, root.LayoutY); + Assert.AreEqual(200f, root.LayoutWidth); + Assert.AreEqual(200f, root.LayoutHeight); + + Assert.AreEqual(0f, root_child0.LayoutX); + Assert.AreEqual(0f, root_child0.LayoutY); + Assert.AreEqual(120f, root_child0.LayoutWidth); + Assert.AreEqual(200f, root_child0.LayoutHeight); + + Assert.AreEqual(120f, root_child1.LayoutX); + Assert.AreEqual(0f, root_child1.LayoutY); + Assert.AreEqual(40f, root_child1.LayoutWidth); + Assert.AreEqual(200f, root_child1.LayoutHeight); + + root.StyleDirection = YogaDirection.RTL; + root.CalculateLayout(); + + Assert.AreEqual(0f, root.LayoutX); + Assert.AreEqual(0f, root.LayoutY); + Assert.AreEqual(200f, root.LayoutWidth); + Assert.AreEqual(200f, root.LayoutHeight); + + Assert.AreEqual(80f, root_child0.LayoutX); + Assert.AreEqual(0f, root_child0.LayoutY); + Assert.AreEqual(120f, root_child0.LayoutWidth); + Assert.AreEqual(200f, root_child0.LayoutHeight); + + Assert.AreEqual(40f, root_child1.LayoutX); + Assert.AreEqual(0f, root_child1.LayoutY); + Assert.AreEqual(40f, root_child1.LayoutWidth); + Assert.AreEqual(200f, root_child1.LayoutHeight); + + YogaNode.SetExperimentalFeatureEnabled(YogaExperimentalFeature.Rounding, false); + } + + [Test] + public void Test_percentage_flex_basis_cross_max_width() + { + YogaNode.SetExperimentalFeatureEnabled(YogaExperimentalFeature.Rounding, true); + + YogaNode root = new YogaNode(); + root.Width = 200; + root.Height = 200; + + YogaNode root_child0 = new YogaNode(); + root_child0.FlexGrow = 1; + root_child0.FlexBasis = 10.Percent(); + root_child0.MaxWidth = 60.Percent(); + root.Insert(0, root_child0); + + YogaNode root_child1 = new YogaNode(); + root_child1.FlexGrow = 4; + root_child1.FlexBasis = 15.Percent(); + root_child1.MaxWidth = 20.Percent(); + root.Insert(1, root_child1); + root.StyleDirection = YogaDirection.LTR; + root.CalculateLayout(); + + Assert.AreEqual(0f, root.LayoutX); + Assert.AreEqual(0f, root.LayoutY); + Assert.AreEqual(200f, root.LayoutWidth); + Assert.AreEqual(200f, root.LayoutHeight); + + Assert.AreEqual(0f, root_child0.LayoutX); + Assert.AreEqual(0f, root_child0.LayoutY); + Assert.AreEqual(120f, root_child0.LayoutWidth); + Assert.AreEqual(50f, root_child0.LayoutHeight); + + Assert.AreEqual(0f, root_child1.LayoutX); + Assert.AreEqual(50f, root_child1.LayoutY); + Assert.AreEqual(40f, root_child1.LayoutWidth); + Assert.AreEqual(150f, root_child1.LayoutHeight); + + root.StyleDirection = YogaDirection.RTL; + root.CalculateLayout(); + + Assert.AreEqual(0f, root.LayoutX); + Assert.AreEqual(0f, root.LayoutY); + Assert.AreEqual(200f, root.LayoutWidth); + Assert.AreEqual(200f, root.LayoutHeight); + + Assert.AreEqual(80f, root_child0.LayoutX); + Assert.AreEqual(0f, root_child0.LayoutY); + Assert.AreEqual(120f, root_child0.LayoutWidth); + Assert.AreEqual(50f, root_child0.LayoutHeight); + + Assert.AreEqual(160f, root_child1.LayoutX); + Assert.AreEqual(50f, root_child1.LayoutY); + Assert.AreEqual(40f, root_child1.LayoutWidth); + Assert.AreEqual(150f, root_child1.LayoutHeight); + + YogaNode.SetExperimentalFeatureEnabled(YogaExperimentalFeature.Rounding, false); + } + + [Test] + public void Test_percentage_flex_basis_main_min_width() + { + YogaNode.SetExperimentalFeatureEnabled(YogaExperimentalFeature.Rounding, true); + + YogaNode root = new YogaNode(); + root.FlexDirection = YogaFlexDirection.Row; + root.Width = 200; + root.Height = 200; + + YogaNode root_child0 = new YogaNode(); + root_child0.FlexGrow = 1; + root_child0.FlexBasis = 15.Percent(); + root_child0.MinWidth = 60.Percent(); + root.Insert(0, root_child0); + + YogaNode root_child1 = new YogaNode(); + root_child1.FlexGrow = 4; + root_child1.FlexBasis = 10.Percent(); + root_child1.MinWidth = 20.Percent(); + root.Insert(1, root_child1); + root.StyleDirection = YogaDirection.LTR; + root.CalculateLayout(); + + Assert.AreEqual(0f, root.LayoutX); + Assert.AreEqual(0f, root.LayoutY); + Assert.AreEqual(200f, root.LayoutWidth); + Assert.AreEqual(200f, root.LayoutHeight); + + Assert.AreEqual(0f, root_child0.LayoutX); + Assert.AreEqual(0f, root_child0.LayoutY); + Assert.AreEqual(120f, root_child0.LayoutWidth); + Assert.AreEqual(200f, root_child0.LayoutHeight); + + Assert.AreEqual(120f, root_child1.LayoutX); + Assert.AreEqual(0f, root_child1.LayoutY); + Assert.AreEqual(80f, root_child1.LayoutWidth); + Assert.AreEqual(200f, root_child1.LayoutHeight); + + root.StyleDirection = YogaDirection.RTL; + root.CalculateLayout(); + + Assert.AreEqual(0f, root.LayoutX); + Assert.AreEqual(0f, root.LayoutY); + Assert.AreEqual(200f, root.LayoutWidth); + Assert.AreEqual(200f, root.LayoutHeight); + + Assert.AreEqual(80f, root_child0.LayoutX); + Assert.AreEqual(0f, root_child0.LayoutY); + Assert.AreEqual(120f, root_child0.LayoutWidth); + Assert.AreEqual(200f, root_child0.LayoutHeight); + + Assert.AreEqual(0f, root_child1.LayoutX); + Assert.AreEqual(0f, root_child1.LayoutY); + Assert.AreEqual(80f, root_child1.LayoutWidth); + Assert.AreEqual(200f, root_child1.LayoutHeight); + + YogaNode.SetExperimentalFeatureEnabled(YogaExperimentalFeature.Rounding, false); + } + + [Test] + public void Test_percentage_flex_basis_cross_min_width() + { + YogaNode.SetExperimentalFeatureEnabled(YogaExperimentalFeature.Rounding, true); + + YogaNode root = new YogaNode(); + root.Width = 200; + root.Height = 200; + + YogaNode root_child0 = new YogaNode(); + root_child0.FlexGrow = 1; + root_child0.FlexBasis = 10.Percent(); + root_child0.MinWidth = 60.Percent(); + root.Insert(0, root_child0); + + YogaNode root_child1 = new YogaNode(); + root_child1.FlexGrow = 4; + root_child1.FlexBasis = 15.Percent(); + root_child1.MinWidth = 20.Percent(); + root.Insert(1, root_child1); + root.StyleDirection = YogaDirection.LTR; + root.CalculateLayout(); + + Assert.AreEqual(0f, root.LayoutX); + Assert.AreEqual(0f, root.LayoutY); + Assert.AreEqual(200f, root.LayoutWidth); + Assert.AreEqual(200f, root.LayoutHeight); + + Assert.AreEqual(0f, root_child0.LayoutX); + Assert.AreEqual(0f, root_child0.LayoutY); + Assert.AreEqual(200f, root_child0.LayoutWidth); + Assert.AreEqual(50f, root_child0.LayoutHeight); + + Assert.AreEqual(0f, root_child1.LayoutX); + Assert.AreEqual(50f, root_child1.LayoutY); + Assert.AreEqual(200f, root_child1.LayoutWidth); + Assert.AreEqual(150f, root_child1.LayoutHeight); + + root.StyleDirection = YogaDirection.RTL; + root.CalculateLayout(); + + Assert.AreEqual(0f, root.LayoutX); + Assert.AreEqual(0f, root.LayoutY); + Assert.AreEqual(200f, root.LayoutWidth); + Assert.AreEqual(200f, root.LayoutHeight); + + Assert.AreEqual(0f, root_child0.LayoutX); + Assert.AreEqual(0f, root_child0.LayoutY); + Assert.AreEqual(200f, root_child0.LayoutWidth); + Assert.AreEqual(50f, root_child0.LayoutHeight); + + Assert.AreEqual(0f, root_child1.LayoutX); + Assert.AreEqual(50f, root_child1.LayoutY); + Assert.AreEqual(200f, root_child1.LayoutWidth); + Assert.AreEqual(150f, root_child1.LayoutHeight); + + YogaNode.SetExperimentalFeatureEnabled(YogaExperimentalFeature.Rounding, false); + } + + [Test] + public void Test_percentage_multiple_nested_with_padding_margin_and_percentage_values() + { + YogaNode.SetExperimentalFeatureEnabled(YogaExperimentalFeature.Rounding, true); + + YogaNode root = new YogaNode(); + root.Width = 200; + root.Height = 200; + + YogaNode root_child0 = new YogaNode(); + root_child0.FlexGrow = 1; + root_child0.FlexBasis = 10.Percent(); + root_child0.SetMargin(YogaEdge.Left, 5); + root_child0.SetMargin(YogaEdge.Top, 5); + root_child0.SetMargin(YogaEdge.Right, 5); + root_child0.SetMargin(YogaEdge.Bottom, 5); + root_child0.SetPadding(YogaEdge.Left, 3); + root_child0.SetPadding(YogaEdge.Top, 3); + root_child0.SetPadding(YogaEdge.Right, 3); + root_child0.SetPadding(YogaEdge.Bottom, 3); + root_child0.MinWidth = 60.Percent(); + root.Insert(0, root_child0); + + YogaNode root_child0_child0 = new YogaNode(); + root_child0_child0.SetMargin(YogaEdge.Left, 5); + root_child0_child0.SetMargin(YogaEdge.Top, 5); + root_child0_child0.SetMargin(YogaEdge.Right, 5); + root_child0_child0.SetMargin(YogaEdge.Bottom, 5); + root_child0_child0.SetPadding(YogaEdge.Left, 3.Percent()); + root_child0_child0.SetPadding(YogaEdge.Top, 3.Percent()); + root_child0_child0.SetPadding(YogaEdge.Right, 3.Percent()); + root_child0_child0.SetPadding(YogaEdge.Bottom, 3.Percent()); + root_child0_child0.Width = 50.Percent(); + root_child0.Insert(0, root_child0_child0); + + YogaNode root_child0_child0_child0 = new YogaNode(); + root_child0_child0_child0.SetMargin(YogaEdge.Left, 5.Percent()); + root_child0_child0_child0.SetMargin(YogaEdge.Top, 5.Percent()); + root_child0_child0_child0.SetMargin(YogaEdge.Right, 5.Percent()); + root_child0_child0_child0.SetMargin(YogaEdge.Bottom, 5.Percent()); + root_child0_child0_child0.SetPadding(YogaEdge.Left, 3); + root_child0_child0_child0.SetPadding(YogaEdge.Top, 3); + root_child0_child0_child0.SetPadding(YogaEdge.Right, 3); + root_child0_child0_child0.SetPadding(YogaEdge.Bottom, 3); + root_child0_child0_child0.Width = 45.Percent(); + root_child0_child0.Insert(0, root_child0_child0_child0); + + YogaNode root_child1 = new YogaNode(); + root_child1.FlexGrow = 4; + root_child1.FlexBasis = 15.Percent(); + root_child1.MinWidth = 20.Percent(); + root.Insert(1, root_child1); + root.StyleDirection = YogaDirection.LTR; + root.CalculateLayout(); + + Assert.AreEqual(0f, root.LayoutX); + Assert.AreEqual(0f, root.LayoutY); + Assert.AreEqual(200f, root.LayoutWidth); + Assert.AreEqual(200f, root.LayoutHeight); + + Assert.AreEqual(5f, root_child0.LayoutX); + Assert.AreEqual(5f, root_child0.LayoutY); + Assert.AreEqual(190f, root_child0.LayoutWidth); + Assert.AreEqual(48f, root_child0.LayoutHeight); + + Assert.AreEqual(8f, root_child0_child0.LayoutX); + Assert.AreEqual(8f, root_child0_child0.LayoutY); + Assert.AreEqual(92f, root_child0_child0.LayoutWidth); + Assert.AreEqual(25f, root_child0_child0.LayoutHeight); + + Assert.AreEqual(10f, root_child0_child0_child0.LayoutX); + Assert.AreEqual(10f, root_child0_child0_child0.LayoutY); + Assert.AreEqual(36f, root_child0_child0_child0.LayoutWidth); + Assert.AreEqual(6f, root_child0_child0_child0.LayoutHeight); + + Assert.AreEqual(0f, root_child1.LayoutX); + Assert.AreEqual(58f, root_child1.LayoutY); + Assert.AreEqual(200f, root_child1.LayoutWidth); + Assert.AreEqual(142f, root_child1.LayoutHeight); + + root.StyleDirection = YogaDirection.RTL; + root.CalculateLayout(); + + Assert.AreEqual(0f, root.LayoutX); + Assert.AreEqual(0f, root.LayoutY); + Assert.AreEqual(200f, root.LayoutWidth); + Assert.AreEqual(200f, root.LayoutHeight); + + Assert.AreEqual(5f, root_child0.LayoutX); + Assert.AreEqual(5f, root_child0.LayoutY); + Assert.AreEqual(190f, root_child0.LayoutWidth); + Assert.AreEqual(48f, root_child0.LayoutHeight); + + Assert.AreEqual(90f, root_child0_child0.LayoutX); + Assert.AreEqual(8f, root_child0_child0.LayoutY); + Assert.AreEqual(92f, root_child0_child0.LayoutWidth); + Assert.AreEqual(25f, root_child0_child0.LayoutHeight); + + Assert.AreEqual(46f, root_child0_child0_child0.LayoutX); + Assert.AreEqual(10f, root_child0_child0_child0.LayoutY); + Assert.AreEqual(36f, root_child0_child0_child0.LayoutWidth); + Assert.AreEqual(6f, root_child0_child0_child0.LayoutHeight); + + Assert.AreEqual(0f, root_child1.LayoutX); + Assert.AreEqual(58f, root_child1.LayoutY); + Assert.AreEqual(200f, root_child1.LayoutWidth); + Assert.AreEqual(142f, root_child1.LayoutHeight); + + YogaNode.SetExperimentalFeatureEnabled(YogaExperimentalFeature.Rounding, false); + } + + [Test] + public void Test_percentage_margin_should_calculate_based_only_on_width() + { + YogaNode.SetExperimentalFeatureEnabled(YogaExperimentalFeature.Rounding, true); + + YogaNode root = new YogaNode(); + root.Width = 200; + root.Height = 100; + + YogaNode root_child0 = new YogaNode(); + root_child0.FlexGrow = 1; + root_child0.SetMargin(YogaEdge.Left, 10.Percent()); + root_child0.SetMargin(YogaEdge.Top, 10.Percent()); + root_child0.SetMargin(YogaEdge.Right, 10.Percent()); + root_child0.SetMargin(YogaEdge.Bottom, 10.Percent()); + root.Insert(0, root_child0); + + YogaNode root_child0_child0 = new YogaNode(); + root_child0_child0.Width = 10; + root_child0_child0.Height = 10; + root_child0.Insert(0, root_child0_child0); + root.StyleDirection = YogaDirection.LTR; + root.CalculateLayout(); + + Assert.AreEqual(0f, root.LayoutX); + Assert.AreEqual(0f, root.LayoutY); + Assert.AreEqual(200f, root.LayoutWidth); + Assert.AreEqual(100f, root.LayoutHeight); + + Assert.AreEqual(20f, root_child0.LayoutX); + Assert.AreEqual(20f, root_child0.LayoutY); + Assert.AreEqual(160f, root_child0.LayoutWidth); + Assert.AreEqual(60f, root_child0.LayoutHeight); + + Assert.AreEqual(0f, root_child0_child0.LayoutX); + Assert.AreEqual(0f, root_child0_child0.LayoutY); + Assert.AreEqual(10f, root_child0_child0.LayoutWidth); + Assert.AreEqual(10f, root_child0_child0.LayoutHeight); + + root.StyleDirection = YogaDirection.RTL; + root.CalculateLayout(); + + Assert.AreEqual(0f, root.LayoutX); + Assert.AreEqual(0f, root.LayoutY); + Assert.AreEqual(200f, root.LayoutWidth); + Assert.AreEqual(100f, root.LayoutHeight); + + Assert.AreEqual(20f, root_child0.LayoutX); + Assert.AreEqual(20f, root_child0.LayoutY); + Assert.AreEqual(160f, root_child0.LayoutWidth); + Assert.AreEqual(60f, root_child0.LayoutHeight); + + Assert.AreEqual(150f, root_child0_child0.LayoutX); + Assert.AreEqual(0f, root_child0_child0.LayoutY); + Assert.AreEqual(10f, root_child0_child0.LayoutWidth); + Assert.AreEqual(10f, root_child0_child0.LayoutHeight); + + YogaNode.SetExperimentalFeatureEnabled(YogaExperimentalFeature.Rounding, false); + } + + [Test] + public void Test_percentage_padding_should_calculate_based_only_on_width() + { + YogaNode.SetExperimentalFeatureEnabled(YogaExperimentalFeature.Rounding, true); + + YogaNode root = new YogaNode(); + root.Width = 200; + root.Height = 100; + + YogaNode root_child0 = new YogaNode(); + root_child0.FlexGrow = 1; + root_child0.SetPadding(YogaEdge.Left, 10.Percent()); + root_child0.SetPadding(YogaEdge.Top, 10.Percent()); + root_child0.SetPadding(YogaEdge.Right, 10.Percent()); + root_child0.SetPadding(YogaEdge.Bottom, 10.Percent()); + root.Insert(0, root_child0); + + YogaNode root_child0_child0 = new YogaNode(); + root_child0_child0.Width = 10; + root_child0_child0.Height = 10; + root_child0.Insert(0, root_child0_child0); + root.StyleDirection = YogaDirection.LTR; + root.CalculateLayout(); + + Assert.AreEqual(0f, root.LayoutX); + Assert.AreEqual(0f, root.LayoutY); + Assert.AreEqual(200f, root.LayoutWidth); + Assert.AreEqual(100f, root.LayoutHeight); + + Assert.AreEqual(0f, root_child0.LayoutX); + Assert.AreEqual(0f, root_child0.LayoutY); + Assert.AreEqual(200f, root_child0.LayoutWidth); + Assert.AreEqual(100f, root_child0.LayoutHeight); + + Assert.AreEqual(20f, root_child0_child0.LayoutX); + Assert.AreEqual(20f, root_child0_child0.LayoutY); + Assert.AreEqual(10f, root_child0_child0.LayoutWidth); + Assert.AreEqual(10f, root_child0_child0.LayoutHeight); + + root.StyleDirection = YogaDirection.RTL; + root.CalculateLayout(); + + Assert.AreEqual(0f, root.LayoutX); + Assert.AreEqual(0f, root.LayoutY); + Assert.AreEqual(200f, root.LayoutWidth); + Assert.AreEqual(100f, root.LayoutHeight); + + Assert.AreEqual(0f, root_child0.LayoutX); + Assert.AreEqual(0f, root_child0.LayoutY); + Assert.AreEqual(200f, root_child0.LayoutWidth); + Assert.AreEqual(100f, root_child0.LayoutHeight); + + Assert.AreEqual(170f, root_child0_child0.LayoutX); + Assert.AreEqual(20f, root_child0_child0.LayoutY); + Assert.AreEqual(10f, root_child0_child0.LayoutWidth); + Assert.AreEqual(10f, root_child0_child0.LayoutHeight); + + YogaNode.SetExperimentalFeatureEnabled(YogaExperimentalFeature.Rounding, false); + } + + [Test] + public void Test_percentage_absolute_position() + { + YogaNode.SetExperimentalFeatureEnabled(YogaExperimentalFeature.Rounding, true); + + YogaNode root = new YogaNode(); + root.Width = 200; + root.Height = 100; + + YogaNode root_child0 = new YogaNode(); + root_child0.PositionType = YogaPositionType.Absolute; + root_child0.SetPosition(YogaEdge.Left, 30.Percent()); + root_child0.SetPosition(YogaEdge.Top, 10.Percent()); + root_child0.Width = 10; + root_child0.Height = 10; + root.Insert(0, root_child0); + root.StyleDirection = YogaDirection.LTR; + root.CalculateLayout(); + + Assert.AreEqual(0f, root.LayoutX); + Assert.AreEqual(0f, root.LayoutY); + Assert.AreEqual(200f, root.LayoutWidth); + Assert.AreEqual(100f, root.LayoutHeight); + + Assert.AreEqual(60f, root_child0.LayoutX); + Assert.AreEqual(10f, root_child0.LayoutY); + Assert.AreEqual(10f, root_child0.LayoutWidth); + Assert.AreEqual(10f, root_child0.LayoutHeight); + + root.StyleDirection = YogaDirection.RTL; + root.CalculateLayout(); + + Assert.AreEqual(0f, root.LayoutX); + Assert.AreEqual(0f, root.LayoutY); + Assert.AreEqual(200f, root.LayoutWidth); + Assert.AreEqual(100f, root.LayoutHeight); + + Assert.AreEqual(60f, root_child0.LayoutX); + Assert.AreEqual(10f, root_child0.LayoutY); + Assert.AreEqual(10f, root_child0.LayoutWidth); + Assert.AreEqual(10f, root_child0.LayoutHeight); + + YogaNode.SetExperimentalFeatureEnabled(YogaExperimentalFeature.Rounding, false); + } + + } +} diff --git a/csharp/tests/Facebook.Yoga/YGRoundingTest.cs b/csharp/tests/Facebook.Yoga/YGRoundingTest.cs index 62da0f0c..2ed2c39d 100644 --- a/csharp/tests/Facebook.Yoga/YGRoundingTest.cs +++ b/csharp/tests/Facebook.Yoga/YGRoundingTest.cs @@ -24,19 +24,19 @@ namespace Facebook.Yoga YogaNode root = new YogaNode(); root.FlexDirection = YogaFlexDirection.Row; - root.Width = 100f; - root.Height = 100f; + root.Width = 100; + root.Height = 100; YogaNode root_child0 = new YogaNode(); - root_child0.FlexGrow = 1f; + root_child0.FlexGrow = 1; root.Insert(0, root_child0); YogaNode root_child1 = new YogaNode(); - root_child1.FlexGrow = 1f; + root_child1.FlexGrow = 1; root.Insert(1, root_child1); YogaNode root_child2 = new YogaNode(); - root_child2.FlexGrow = 1f; + root_child2.FlexGrow = 1; root.Insert(2, root_child2); root.StyleDirection = YogaDirection.LTR; root.CalculateLayout(); @@ -94,27 +94,27 @@ namespace Facebook.Yoga YogaNode root = new YogaNode(); root.FlexDirection = YogaFlexDirection.Row; - root.Width = 113f; - root.Height = 100f; + root.Width = 113; + root.Height = 100; YogaNode root_child0 = new YogaNode(); - root_child0.FlexGrow = 1f; + root_child0.FlexGrow = 1; root.Insert(0, root_child0); YogaNode root_child1 = new YogaNode(); - root_child1.FlexGrow = 1f; + root_child1.FlexGrow = 1; root.Insert(1, root_child1); YogaNode root_child2 = new YogaNode(); - root_child2.FlexGrow = 1f; + root_child2.FlexGrow = 1; root.Insert(2, root_child2); YogaNode root_child3 = new YogaNode(); - root_child3.FlexGrow = 1f; + root_child3.FlexGrow = 1; root.Insert(3, root_child3); YogaNode root_child4 = new YogaNode(); - root_child4.FlexGrow = 1f; + root_child4.FlexGrow = 1; root.Insert(4, root_child4); root.StyleDirection = YogaDirection.LTR; root.CalculateLayout(); @@ -192,20 +192,20 @@ namespace Facebook.Yoga YogaNode root = new YogaNode(); root.FlexDirection = YogaFlexDirection.Row; - root.Width = 101f; - root.Height = 100f; + root.Width = 101; + root.Height = 100; YogaNode root_child0 = new YogaNode(); - root_child0.FlexShrink = 1f; - root_child0.FlexBasis = 100f; + root_child0.FlexShrink = 1; + root_child0.FlexBasis = 100; root.Insert(0, root_child0); YogaNode root_child1 = new YogaNode(); - root_child1.FlexBasis = 25f; + root_child1.FlexBasis = 25; root.Insert(1, root_child1); YogaNode root_child2 = new YogaNode(); - root_child2.FlexBasis = 25f; + root_child2.FlexBasis = 25; root.Insert(2, root_child2); root.StyleDirection = YogaDirection.LTR; root.CalculateLayout(); @@ -262,23 +262,23 @@ namespace Facebook.Yoga YogaNode.SetExperimentalFeatureEnabled(YogaExperimentalFeature.Rounding, true); YogaNode root = new YogaNode(); - root.Width = 100f; - root.Height = 113f; + root.Width = 100; + root.Height = 113; YogaNode root_child0 = new YogaNode(); - root_child0.FlexGrow = 1f; - root_child0.FlexBasis = 50f; - root_child0.Height = 20f; + root_child0.FlexGrow = 1; + root_child0.FlexBasis = 50; + root_child0.Height = 20; root.Insert(0, root_child0); YogaNode root_child1 = new YogaNode(); - root_child1.FlexGrow = 1f; - root_child1.Height = 10f; + root_child1.FlexGrow = 1; + root_child1.Height = 10; root.Insert(1, root_child1); YogaNode root_child2 = new YogaNode(); - root_child2.FlexGrow = 1f; - root_child2.Height = 10f; + root_child2.FlexGrow = 1; + root_child2.Height = 10; root.Insert(2, root_child2); root.StyleDirection = YogaDirection.LTR; root.CalculateLayout(); @@ -346,7 +346,7 @@ namespace Facebook.Yoga YogaNode root_child1 = new YogaNode(); root_child1.FlexGrow = 1.6f; - root_child1.Height = 10f; + root_child1.Height = 10; root.Insert(1, root_child1); YogaNode root_child2 = new YogaNode(); @@ -418,14 +418,14 @@ namespace Facebook.Yoga root.Insert(0, root_child0); YogaNode root_child0_child0 = new YogaNode(); - root_child0_child0.FlexGrow = 1f; + root_child0_child0.FlexGrow = 1; root_child0_child0.FlexBasis = 0.3f; root_child0_child0.SetPosition(YogaEdge.Bottom, 13.3f); root_child0_child0.Height = 9.9f; root_child0.Insert(0, root_child0_child0); YogaNode root_child0_child1 = new YogaNode(); - root_child0_child1.FlexGrow = 4f; + root_child0_child1.FlexGrow = 4; root_child0_child1.FlexBasis = 0.3f; root_child0_child1.SetPosition(YogaEdge.Top, 13.3f); root_child0_child1.Height = 1.1f; @@ -433,7 +433,7 @@ namespace Facebook.Yoga YogaNode root_child1 = new YogaNode(); root_child1.FlexGrow = 1.6f; - root_child1.Height = 10f; + root_child1.Height = 10; root.Insert(1, root_child1); YogaNode root_child2 = new YogaNode(); @@ -515,23 +515,23 @@ namespace Facebook.Yoga YogaNode.SetExperimentalFeatureEnabled(YogaExperimentalFeature.Rounding, true); YogaNode root = new YogaNode(); - root.Width = 100f; + root.Width = 100; root.Height = 113.4f; YogaNode root_child0 = new YogaNode(); - root_child0.FlexGrow = 1f; - root_child0.FlexBasis = 50f; - root_child0.Height = 20f; + root_child0.FlexGrow = 1; + root_child0.FlexBasis = 50; + root_child0.Height = 20; root.Insert(0, root_child0); YogaNode root_child1 = new YogaNode(); - root_child1.FlexGrow = 1f; - root_child1.Height = 10f; + root_child1.FlexGrow = 1; + root_child1.Height = 10; root.Insert(1, root_child1); YogaNode root_child2 = new YogaNode(); - root_child2.FlexGrow = 1f; - root_child2.Height = 10f; + root_child2.FlexGrow = 1; + root_child2.Height = 10; root.Insert(2, root_child2); root.StyleDirection = YogaDirection.LTR; root.CalculateLayout(); @@ -588,23 +588,23 @@ namespace Facebook.Yoga YogaNode.SetExperimentalFeatureEnabled(YogaExperimentalFeature.Rounding, true); YogaNode root = new YogaNode(); - root.Width = 100f; + root.Width = 100; root.Height = 113.6f; YogaNode root_child0 = new YogaNode(); - root_child0.FlexGrow = 1f; - root_child0.FlexBasis = 50f; - root_child0.Height = 20f; + root_child0.FlexGrow = 1; + root_child0.FlexBasis = 50; + root_child0.Height = 20; root.Insert(0, root_child0); YogaNode root_child1 = new YogaNode(); - root_child1.FlexGrow = 1f; - root_child1.Height = 10f; + root_child1.FlexGrow = 1; + root_child1.Height = 10; root.Insert(1, root_child1); YogaNode root_child2 = new YogaNode(); - root_child2.FlexGrow = 1f; - root_child2.Height = 10f; + root_child2.FlexGrow = 1; + root_child2.Height = 10; root.Insert(2, root_child2); root.StyleDirection = YogaDirection.LTR; root.CalculateLayout(); @@ -662,23 +662,23 @@ namespace Facebook.Yoga YogaNode root = new YogaNode(); root.SetPosition(YogaEdge.Top, 0.3f); - root.Width = 100f; + root.Width = 100; root.Height = 113.4f; YogaNode root_child0 = new YogaNode(); - root_child0.FlexGrow = 1f; - root_child0.FlexBasis = 50f; - root_child0.Height = 20f; + root_child0.FlexGrow = 1; + root_child0.FlexBasis = 50; + root_child0.Height = 20; root.Insert(0, root_child0); YogaNode root_child1 = new YogaNode(); - root_child1.FlexGrow = 1f; - root_child1.Height = 10f; + root_child1.FlexGrow = 1; + root_child1.Height = 10; root.Insert(1, root_child1); YogaNode root_child2 = new YogaNode(); - root_child2.FlexGrow = 1f; - root_child2.Height = 10f; + root_child2.FlexGrow = 1; + root_child2.Height = 10; root.Insert(2, root_child2); root.StyleDirection = YogaDirection.LTR; root.CalculateLayout(); @@ -736,23 +736,23 @@ namespace Facebook.Yoga YogaNode root = new YogaNode(); root.SetPosition(YogaEdge.Top, 0.7f); - root.Width = 100f; + root.Width = 100; root.Height = 113.4f; YogaNode root_child0 = new YogaNode(); - root_child0.FlexGrow = 1f; - root_child0.FlexBasis = 50f; - root_child0.Height = 20f; + root_child0.FlexGrow = 1; + root_child0.FlexBasis = 50; + root_child0.Height = 20; root.Insert(0, root_child0); YogaNode root_child1 = new YogaNode(); - root_child1.FlexGrow = 1f; - root_child1.Height = 10f; + root_child1.FlexGrow = 1; + root_child1.Height = 10; root.Insert(1, root_child1); YogaNode root_child2 = new YogaNode(); - root_child2.FlexGrow = 1f; - root_child2.Height = 10f; + root_child2.FlexGrow = 1; + root_child2.Height = 10; root.Insert(2, root_child2); root.StyleDirection = YogaDirection.LTR; root.CalculateLayout(); diff --git a/csharp/tests/Facebook.Yoga/YogaNodeCreateTest.cs b/csharp/tests/Facebook.Yoga/YogaNodeCreateTest.cs index 0d43cdbc..74573a36 100644 --- a/csharp/tests/Facebook.Yoga/YogaNodeCreateTest.cs +++ b/csharp/tests/Facebook.Yoga/YogaNodeCreateTest.cs @@ -51,14 +51,14 @@ namespace Facebook.Yoga Assert.AreEqual(YogaFlexDirection.Column, node.FlexDirection); Assert.AreEqual(YogaPositionType.Absolute, node.PositionType); Assert.AreEqual(YogaWrap.Wrap, node.Wrap); - Assert.AreEqual(6, node.GetPosition(YogaEdge.Top)); + Assert.AreEqual(6.Px(), node.GetPosition(YogaEdge.Top)); Assert.IsTrue(YogaConstants.IsUndefined(node.GetPosition(YogaEdge.Bottom))); - Assert.AreEqual(4, node.GetPosition(YogaEdge.Right)); + Assert.AreEqual(4.Px(), node.GetPosition(YogaEdge.Right)); Assert.IsTrue(YogaConstants.IsUndefined(node.GetPosition(YogaEdge.Left))); - Assert.AreEqual(0, node.GetMargin(YogaEdge.Top)); - Assert.AreEqual(5, node.GetMargin(YogaEdge.Bottom)); - Assert.AreEqual(3, node.GetMargin(YogaEdge.Left)); - Assert.AreEqual(0, node.GetMargin(YogaEdge.Right)); + Assert.AreEqual(0.Px(), node.GetMargin(YogaEdge.Top)); + Assert.AreEqual(5.Px(), node.GetMargin(YogaEdge.Bottom)); + Assert.AreEqual(3.Px(), node.GetMargin(YogaEdge.Left)); + Assert.AreEqual(0.Px(), node.GetMargin(YogaEdge.Right)); } [Test] @@ -85,7 +85,7 @@ namespace Facebook.Yoga position: new Spacing(top: 5, bottom: 6, left: 7, right: 8), margin: new Spacing(top: 9, bottom: 10, left: 11, right: 12), padding: new Spacing(top: 13, bottom: 14, left: 15, right: 16), - border: new Spacing(top: 17, bottom: 18, left: 19, right: 20), + border: new Border(top: 17, bottom: 18, left: 19, right: 20), width: 21, height: 22, @@ -108,36 +108,36 @@ namespace Facebook.Yoga Assert.AreEqual(2, node.FlexGrow); Assert.AreEqual(3, node.FlexShrink); - Assert.AreEqual(4, node.FlexBasis); + Assert.AreEqual(4.Px(), node.FlexBasis); node.FlexGrow = YogaConstants.Undefined; Assert.AreEqual(1, node.FlexGrow); - Assert.AreEqual(5, node.GetPosition(YogaEdge.Top)); - Assert.AreEqual(6, node.GetPosition(YogaEdge.Bottom)); - Assert.AreEqual(7, node.GetPosition(YogaEdge.Left)); - Assert.AreEqual(8, node.GetPosition(YogaEdge.Right)); + Assert.AreEqual(5.Px(), node.GetPosition(YogaEdge.Top)); + Assert.AreEqual(6.Px(), node.GetPosition(YogaEdge.Bottom)); + Assert.AreEqual(7.Px(), node.GetPosition(YogaEdge.Left)); + Assert.AreEqual(8.Px(), node.GetPosition(YogaEdge.Right)); - Assert.AreEqual(9, node.GetMargin(YogaEdge.Top)); - Assert.AreEqual(10, node.GetMargin(YogaEdge.Bottom)); - Assert.AreEqual(11, node.GetMargin(YogaEdge.Left)); - Assert.AreEqual(12, node.GetMargin(YogaEdge.Right)); + Assert.AreEqual(9.Px(), node.GetMargin(YogaEdge.Top)); + Assert.AreEqual(10.Px(), node.GetMargin(YogaEdge.Bottom)); + Assert.AreEqual(11.Px(), node.GetMargin(YogaEdge.Left)); + Assert.AreEqual(12.Px(), node.GetMargin(YogaEdge.Right)); - Assert.AreEqual(13, node.GetPadding(YogaEdge.Top)); - Assert.AreEqual(14, node.GetPadding(YogaEdge.Bottom)); - Assert.AreEqual(15, node.GetPadding(YogaEdge.Left)); - Assert.AreEqual(16, node.GetPadding(YogaEdge.Right)); + Assert.AreEqual(13.Px(), node.GetPadding(YogaEdge.Top)); + Assert.AreEqual(14.Px(), node.GetPadding(YogaEdge.Bottom)); + Assert.AreEqual(15.Px(), node.GetPadding(YogaEdge.Left)); + Assert.AreEqual(16.Px(), node.GetPadding(YogaEdge.Right)); Assert.AreEqual(17, node.GetBorder(YogaEdge.Top)); Assert.AreEqual(18, node.GetBorder(YogaEdge.Bottom)); Assert.AreEqual(19, node.GetBorder(YogaEdge.Left)); Assert.AreEqual(20, node.GetBorder(YogaEdge.Right)); - Assert.AreEqual(21, node.Width); - Assert.AreEqual(22, node.Height); - Assert.AreEqual(23, node.MinWidth); - Assert.AreEqual(24, node.MinHeight); - Assert.AreEqual(25, node.MaxWidth); - Assert.AreEqual(26, node.MaxHeight); + Assert.AreEqual(21.Px(), node.Width); + Assert.AreEqual(22.Px(), node.Height); + Assert.AreEqual(23.Px(), node.MinWidth); + Assert.AreEqual(24.Px(), node.MinHeight); + Assert.AreEqual(25.Px(), node.MaxWidth); + Assert.AreEqual(26.Px(), node.MaxHeight); } } } diff --git a/csharp/tests/Facebook.Yoga/YogaNodeTest.cs b/csharp/tests/Facebook.Yoga/YogaNodeTest.cs index b9e20982..ebb09083 100644 --- a/csharp/tests/Facebook.Yoga/YogaNodeTest.cs +++ b/csharp/tests/Facebook.Yoga/YogaNodeTest.cs @@ -212,7 +212,7 @@ namespace Facebook.Yoga parent.Insert(0, child0); parent.Insert(0, child1); parent.CalculateLayout(); - Assert.AreEqual(parent.Print(), "{layout: {width: 100, height: 120, top: 0, left: 0}, flexDirection: 'column', alignItems: 'stretch', flexGrow: 0, flexShrink: 0, overflow: 'visible', width: 100, height: 120, children: [\n {layout: {width: 35, height: 45, top: 0, left: 0}, flexDirection: 'column', alignItems: 'stretch', flexGrow: 0, flexShrink: 0, overflow: 'visible', width: 35, height: 45, },\n {layout: {width: 30, height: 40, top: 45, left: 0}, flexDirection: 'column', alignItems: 'stretch', flexGrow: 0, flexShrink: 0, overflow: 'visible', width: 30, height: 40, },\n]},\n"); + Assert.AreEqual("{layout: {width: 100, height: 120, top: 0, left: 0}, flexDirection: 'column', alignItems: 'stretch', flexGrow: 0, flexShrink: 0, overflow: 'visible', width: 100px, height: 120px, children: [\n {layout: {width: 35, height: 45, top: 0, left: 0}, flexDirection: 'column', alignItems: 'stretch', flexGrow: 0, flexShrink: 0, overflow: 'visible', width: 35px, height: 45px, },\n {layout: {width: 30, height: 40, top: 45, left: 0}, flexDirection: 'column', alignItems: 'stretch', flexGrow: 0, flexShrink: 0, overflow: 'visible', width: 30px, height: 40px, },\n]},\n", parent.Print()); } [Test] @@ -225,7 +225,7 @@ namespace Facebook.Yoga node1.MaxHeight = 100; node0.CopyStyle(node1); - Assert.AreEqual(100, node0.MaxHeight); + Assert.AreEqual(100.Px(), node0.MaxHeight); } private void ForceGC() diff --git a/enums.py b/enums.py index 756c7c43..f23fa164 100644 --- a/enums.py +++ b/enums.py @@ -17,6 +17,11 @@ ENUMS = { 'LTR', 'RTL', ], + 'Unit': [ + 'Undefined', + 'Pixel', + 'Percent', + ], 'FlexDirection': [ 'Column', 'ColumnReverse', diff --git a/gentest/fixtures/YGPercentageTest.html b/gentest/fixtures/YGPercentageTest.html new file mode 100644 index 00000000..87c4753c --- /dev/null +++ b/gentest/fixtures/YGPercentageTest.html @@ -0,0 +1,82 @@ +
+
+
+ +
+
+
+ +
+
+
+ +
+
+
+
+ +
+
+
+
+ +
+
+
+
+ +
+
+
+
+ +
+
+
+
+ +
+
+
+
+ +
+
+
+
+ + +
+
+
+
+ +
+
+
+
+ +
+
+
+
+
+
+
+
+ +
+
+
+
+
+ +
+
+
+
+
+ +
+
+
\ No newline at end of file diff --git a/gentest/gentest-cpp.js b/gentest/gentest-cpp.js index 0333dd7c..f8ecf8be 100644 --- a/gentest/gentest-cpp.js +++ b/gentest/gentest-cpp.js @@ -7,10 +7,18 @@ * of patent rights can be found in the PATENTS file in the same directory. */ -function toFloatString(n) { +function toValueCpp(value) { + var n = value.toString().replace('px','').replace('%',''); return n + (Number(n) == n && n % 1 !== 0 ? 'f' : ''); } +function toFunctionName(value) { + if (value.indexOf('%') >= 0){ + return 'Percent'; + } + return ''; +} + var CPPEmitter = function() { Emitter.call(this, 'cpp', ' '); }; @@ -66,7 +74,7 @@ CPPEmitter.prototype = Object.create(Emitter.prototype, { }}, AssertEQ:{value:function(v0, v1) { - this.push('ASSERT_FLOAT_EQ(' + toFloatString(v0) + ', ' + v1 + ');'); + this.push('ASSERT_FLOAT_EQ(' + toValueCpp(v0) + ', ' + v1 + ');'); }}, YGAlignAuto:{value:'YGAlignAuto'}, @@ -133,90 +141,90 @@ CPPEmitter.prototype = Object.create(Emitter.prototype, { }}, YGNodeStyleSetAlignContent:{value:function(nodeName, value) { - this.push('YGNodeStyleSetAlignContent(' + nodeName + ', ' + value + ');'); + this.push('YGNodeStyleSetAlignContent(' + nodeName + ', ' + toValueCpp(value) + ');'); }}, YGNodeStyleSetAlignItems:{value:function(nodeName, value) { - this.push('YGNodeStyleSetAlignItems(' + nodeName + ', ' + value + ');'); + this.push('YGNodeStyleSetAlignItems(' + nodeName + ', ' + toValueCpp(value) + ');'); }}, YGNodeStyleSetAlignSelf:{value:function(nodeName, value) { - this.push('YGNodeStyleSetAlignSelf(' + nodeName + ', ' + value + ');'); + this.push('YGNodeStyleSetAlignSelf(' + nodeName + ', ' + toValueCpp(value) + ');'); }}, YGNodeStyleSetBorder:{value:function(nodeName, edge, value) { - this.push('YGNodeStyleSetBorder(' + nodeName + ', ' + edge + ', ' + toFloatString(value) + ');'); + this.push('YGNodeStyleSetBorder(' + nodeName + ', ' + edge + ', ' + toValueCpp(value) + ');'); }}, YGNodeStyleSetDirection:{value:function(nodeName, value) { - this.push('YGNodeStyleSetDirection(' + nodeName + ', ' + value + ');'); + this.push('YGNodeStyleSetDirection(' + nodeName + ', ' + toValueCpp(value) + ');'); }}, YGNodeStyleSetFlexBasis:{value:function(nodeName, value) { - this.push('YGNodeStyleSetFlexBasis(' + nodeName + ', ' + toFloatString(value) + ');'); + this.push('YGNodeStyleSetFlexBasis' + toFunctionName(value) + '(' + nodeName + ', ' + toValueCpp(value) + ');'); }}, YGNodeStyleSetFlexDirection:{value:function(nodeName, value) { - this.push('YGNodeStyleSetFlexDirection(' + nodeName + ', ' + value + ');'); + this.push('YGNodeStyleSetFlexDirection(' + nodeName + ', ' + toValueCpp(value) + ');'); }}, YGNodeStyleSetFlexGrow:{value:function(nodeName, value) { - this.push('YGNodeStyleSetFlexGrow(' + nodeName + ', ' + toFloatString(value) + ');'); + this.push('YGNodeStyleSetFlexGrow(' + nodeName + ', ' + toValueCpp(value) + ');'); }}, YGNodeStyleSetFlexShrink:{value:function(nodeName, value) { - this.push('YGNodeStyleSetFlexShrink(' + nodeName + ', ' + toFloatString(value) + ');'); + this.push('YGNodeStyleSetFlexShrink(' + nodeName + ', ' + toValueCpp(value) + ');'); }}, YGNodeStyleSetFlexWrap:{value:function(nodeName, value) { - this.push('YGNodeStyleSetFlexWrap(' + nodeName + ', ' + value + ');'); + this.push('YGNodeStyleSetFlexWrap(' + nodeName + ', ' + toValueCpp(value) + ');'); }}, YGNodeStyleSetHeight:{value:function(nodeName, value) { - this.push('YGNodeStyleSetHeight(' + nodeName + ', ' + toFloatString(value) + ');'); + this.push('YGNodeStyleSetHeight' + toFunctionName(value) + '(' + nodeName + ', ' + toValueCpp(value) + ');'); }}, YGNodeStyleSetJustifyContent:{value:function(nodeName, value) { - this.push('YGNodeStyleSetJustifyContent(' + nodeName + ', ' + value + ');'); + this.push('YGNodeStyleSetJustifyContent(' + nodeName + ', ' + toValueCpp(value) + ');'); }}, YGNodeStyleSetMargin:{value:function(nodeName, edge, value) { - this.push('YGNodeStyleSetMargin(' + nodeName + ', ' + edge + ', ' + toFloatString(value) + ');'); + this.push('YGNodeStyleSetMargin' + toFunctionName(value) + '(' + nodeName + ', ' + edge + ', ' + toValueCpp(value) + ');'); }}, YGNodeStyleSetMaxHeight:{value:function(nodeName, value) { - this.push('YGNodeStyleSetMaxHeight(' + nodeName + ', ' + toFloatString(value) + ');'); + this.push('YGNodeStyleSetMaxHeight' + toFunctionName(value) + '(' + nodeName + ', ' + toValueCpp(value) + ');'); }}, YGNodeStyleSetMaxWidth:{value:function(nodeName, value) { - this.push('YGNodeStyleSetMaxWidth(' + nodeName + ', ' + toFloatString(value) + ');'); + this.push('YGNodeStyleSetMaxWidth' + toFunctionName(value) + '(' + nodeName + ', ' + toValueCpp(value) + ');'); }}, YGNodeStyleSetMinHeight:{value:function(nodeName, value) { - this.push('YGNodeStyleSetMinHeight(' + nodeName + ', ' + toFloatString(value) + ');'); + this.push('YGNodeStyleSetMinHeight' + toFunctionName(value) + '(' + nodeName + ', ' + toValueCpp(value) + ');'); }}, YGNodeStyleSetMinWidth:{value:function(nodeName, value) { - this.push('YGNodeStyleSetMinWidth(' + nodeName + ', ' + toFloatString(value) + ');'); + this.push('YGNodeStyleSetMinWidth' + toFunctionName(value) + '(' + nodeName + ', ' + toValueCpp(value) + ');'); }}, YGNodeStyleSetOverflow:{value:function(nodeName, value) { - this.push('YGNodeStyleSetOverflow(' + nodeName + ', ' + value + ');'); + this.push('YGNodeStyleSetOverflow(' + nodeName + ', ' + toValueCpp(value) + ');'); }}, YGNodeStyleSetPadding:{value:function(nodeName, edge, value) { - this.push('YGNodeStyleSetPadding(' + nodeName + ', ' + edge + ', ' + toFloatString(value) + ');'); + this.push('YGNodeStyleSetPadding' + toFunctionName(value) + '(' + nodeName + ', ' + edge + ', ' + toValueCpp(value) + ');'); }}, YGNodeStyleSetPosition:{value:function(nodeName, edge, value) { - this.push('YGNodeStyleSetPosition(' + nodeName + ', ' + edge + ', ' + toFloatString(value) + ');'); + this.push('YGNodeStyleSetPosition' + toFunctionName(value) + '(' + nodeName + ', ' + edge + ', ' + toValueCpp(value) + ');'); }}, YGNodeStyleSetPositionType:{value:function(nodeName, value) { - this.push('YGNodeStyleSetPositionType(' + nodeName + ', ' + value + ');'); + this.push('YGNodeStyleSetPositionType(' + nodeName + ', ' + toValueCpp(value) + ');'); }}, YGNodeStyleSetWidth:{value:function(nodeName, value) { - this.push('YGNodeStyleSetWidth(' + nodeName + ', ' + toFloatString(value) + ');'); + this.push('YGNodeStyleSetWidth' + toFunctionName(value) + '(' + nodeName + ', ' + toValueCpp(value) + ');'); }}, }); diff --git a/gentest/gentest-cs.js b/gentest/gentest-cs.js index 0dbbb498..3c78198d 100644 --- a/gentest/gentest-cs.js +++ b/gentest/gentest-cs.js @@ -7,6 +7,19 @@ * of patent rights can be found in the PATENTS file in the same directory. */ +function toValueCs(value) { + var n = value.toString().replace('px','').replace('%',''); + return n + (Number(n) == n && n % 1 !== 0 ? 'f' : ''); +} + +function toCsUnitValue(value) { + var methodName = ''; + if (value.indexOf('%') >= 0){ + methodName = '.Percent()'; + } + return toValueCs(value) + methodName; +} + var CSEmitter = function() { Emitter.call(this, 'cs', ' '); }; @@ -143,90 +156,90 @@ CSEmitter.prototype = Object.create(Emitter.prototype, { }}, YGNodeStyleSetAlignContent:{value:function(nodeName, value) { - this.push(nodeName + '.AlignContent = ' + value + ';'); + this.push(nodeName + '.AlignContent = ' + toValueCs(value) + ';'); }}, YGNodeStyleSetAlignItems:{value:function(nodeName, value) { - this.push(nodeName + '.AlignItems = ' + value + ';'); + this.push(nodeName + '.AlignItems = ' + toValueCs(value) + ';'); }}, YGNodeStyleSetAlignSelf:{value:function(nodeName, value) { - this.push(nodeName + '.AlignSelf = ' + value + ';'); + this.push(nodeName + '.AlignSelf = ' + toValueCs(value) + ';'); }}, YGNodeStyleSetBorder:{value:function(nodeName, edge, value) { - this.push(nodeName + '.SetBorder(' + edge + ', ' + value + 'f);'); + this.push(nodeName + '.SetBorder(' + edge + ', ' + toValueCs(value) + ');'); }}, YGNodeStyleSetDirection:{value:function(nodeName, value) { - this.push(nodeName + '.StyleDirection = ' + value + ';'); + this.push(nodeName + '.StyleDirection = ' + toValueCs(value) + ';'); }}, YGNodeStyleSetFlexBasis:{value:function(nodeName, value) { - this.push(nodeName + '.FlexBasis = ' + value + 'f;'); + this.push(nodeName + '.FlexBasis = ' + toCsUnitValue(value) + ';'); }}, YGNodeStyleSetFlexDirection:{value:function(nodeName, value) { - this.push(nodeName + '.FlexDirection = ' + value + ';'); + this.push(nodeName + '.FlexDirection = ' + toValueCs(value) + ';'); }}, YGNodeStyleSetFlexGrow:{value:function(nodeName, value) { - this.push(nodeName + '.FlexGrow = ' + value + 'f;'); + this.push(nodeName + '.FlexGrow = ' + toValueCs(value) + ';'); }}, YGNodeStyleSetFlexShrink:{value:function(nodeName, value) { - this.push(nodeName + '.FlexShrink = ' + value + 'f;'); + this.push(nodeName + '.FlexShrink = ' + toValueCs(value) + ';'); }}, YGNodeStyleSetFlexWrap:{value:function(nodeName, value) { - this.push(nodeName + '.Wrap = ' + value + ';'); + this.push(nodeName + '.Wrap = ' + toValueCs(value) + ';'); }}, YGNodeStyleSetHeight:{value:function(nodeName, value) { - this.push(nodeName + '.Height = ' + value + 'f;'); + this.push(nodeName + '.Height = ' + toCsUnitValue(value) + ';'); }}, YGNodeStyleSetJustifyContent:{value:function(nodeName, value) { - this.push(nodeName + '.JustifyContent = ' + value + ';'); + this.push(nodeName + '.JustifyContent = ' + toValueCs(value) + ';'); }}, YGNodeStyleSetMargin:{value:function(nodeName, edge, value) { - this.push(nodeName + '.SetMargin(' + edge + ', ' + value + 'f);'); + this.push(nodeName + '.SetMargin(' + edge + ', ' + toCsUnitValue(value) + ');'); }}, YGNodeStyleSetMaxHeight:{value:function(nodeName, value) { - this.push(nodeName + '.MaxHeight = ' + value + 'f;'); + this.push(nodeName + '.MaxHeight = ' + toCsUnitValue(value) + ';'); }}, YGNodeStyleSetMaxWidth:{value:function(nodeName, value) { - this.push(nodeName + '.MaxWidth = ' + value + 'f;'); + this.push(nodeName + '.MaxWidth = ' + toCsUnitValue(value) + ';'); }}, YGNodeStyleSetMinHeight:{value:function(nodeName, value) { - this.push(nodeName + '.MinHeight = ' + value + 'f;'); + this.push(nodeName + '.MinHeight = ' + toCsUnitValue(value) + ';'); }}, YGNodeStyleSetMinWidth:{value:function(nodeName, value) { - this.push(nodeName + '.MinWidth = ' + value + 'f;'); + this.push(nodeName + '.MinWidth = ' + toCsUnitValue(value) + ';'); }}, YGNodeStyleSetOverflow:{value:function(nodeName, value) { - this.push(nodeName + '.Overflow = ' + value + ';'); + this.push(nodeName + '.Overflow = ' + toValueCs(value) + ';'); }}, YGNodeStyleSetPadding:{value:function(nodeName, edge, value) { - this.push(nodeName + '.SetPadding(' + edge + ', ' + value + 'f);'); + this.push(nodeName + '.SetPadding(' + edge + ', ' + toCsUnitValue(value) + ');'); }}, YGNodeStyleSetPosition:{value:function(nodeName, edge, value) { - this.push(nodeName + '.SetPosition(' + edge + ', ' + value + 'f);'); + this.push(nodeName + '.SetPosition(' + edge + ', ' + toCsUnitValue(value) + ');'); }}, YGNodeStyleSetPositionType:{value:function(nodeName, value) { - this.push(nodeName + '.PositionType = ' + value + ';'); + this.push(nodeName + '.PositionType = ' + toValueCs(value) + ';'); }}, YGNodeStyleSetWidth:{value:function(nodeName, value) { - this.push(nodeName + '.Width = ' + value + 'f;'); + this.push(nodeName + '.Width = ' + toCsUnitValue(value) + ';'); }}, }); diff --git a/gentest/gentest-java.js b/gentest/gentest-java.js index 7034c617..36fd578a 100644 --- a/gentest/gentest-java.js +++ b/gentest/gentest-java.js @@ -7,6 +7,18 @@ * of patent rights can be found in the PATENTS file in the same directory. */ +function toValueJava(value) { + var n = value.toString().replace('px','').replace('%',''); + return n + (Number(n) == n && n % 1 !== 0 ? '' : ''); +} + +function toMethodName(value) { + if (value.indexOf('%') >= 0){ + return 'Percent'; + } + return ''; +} + var JavaEmitter = function() { Emitter.call(this, 'java', ' '); }; @@ -148,90 +160,90 @@ JavaEmitter.prototype = Object.create(Emitter.prototype, { }}, YGNodeStyleSetAlignContent:{value:function(nodeName, value) { - this.push(nodeName + '.setAlignContent(' + value + ');'); + this.push(nodeName + '.setAlignContent(' + toValueJava(value) + ');'); }}, YGNodeStyleSetAlignItems:{value:function(nodeName, value) { - this.push(nodeName + '.setAlignItems(' + value + ');'); + this.push(nodeName + '.setAlignItems(' + toValueJava(value) + ');'); }}, YGNodeStyleSetAlignSelf:{value:function(nodeName, value) { - this.push(nodeName + '.setAlignSelf(' + value + ');'); + this.push(nodeName + '.setAlignSelf(' + toValueJava(value) + ');'); }}, YGNodeStyleSetBorder:{value:function(nodeName, edge, value) { - this.push(nodeName + '.setBorder(' + edge + ', ' + value + 'f);'); + this.push(nodeName + '.setBorder(' + edge + ', ' + toValueJava(value) + 'f);'); }}, YGNodeStyleSetDirection:{value:function(nodeName, value) { - this.push(nodeName + '.setDirection(' + value + ');'); + this.push(nodeName + '.setDirection(' + toValueJava(value) + ');'); }}, YGNodeStyleSetFlexBasis:{value:function(nodeName, value) { - this.push(nodeName + '.setFlexBasis(' + value + 'f);'); + this.push(nodeName + '.setFlexBasis' + toMethodName(value) + '(' + toValueJava(value) + 'f);'); }}, YGNodeStyleSetFlexDirection:{value:function(nodeName, value) { - this.push(nodeName + '.setFlexDirection(' + value + ');'); + this.push(nodeName + '.setFlexDirection(' + toValueJava(value) + ');'); }}, YGNodeStyleSetFlexGrow:{value:function(nodeName, value) { - this.push(nodeName + '.setFlexGrow(' + value + 'f);'); + this.push(nodeName + '.setFlexGrow(' + toValueJava(value) + 'f);'); }}, YGNodeStyleSetFlexShrink:{value:function(nodeName, value) { - this.push(nodeName + '.setFlexShrink(' + value + 'f);'); + this.push(nodeName + '.setFlexShrink(' + toValueJava(value) + 'f);'); }}, YGNodeStyleSetFlexWrap:{value:function(nodeName, value) { - this.push(nodeName + '.setWrap(' + value + ');'); + this.push(nodeName + '.setWrap(' + toValueJava(value) + ');'); }}, YGNodeStyleSetHeight:{value:function(nodeName, value) { - this.push(nodeName + '.setHeight(' + value + 'f);'); + this.push(nodeName + '.setHeight' + toMethodName(value) + '(' + toValueJava(value) + 'f);'); }}, YGNodeStyleSetJustifyContent:{value:function(nodeName, value) { - this.push(nodeName + '.setJustifyContent(' + value + ');'); + this.push(nodeName + '.setJustifyContent(' + toValueJava(value) + ');'); }}, YGNodeStyleSetMargin:{value:function(nodeName, edge, value) { - this.push(nodeName + '.setMargin(' + edge + ', ' + value + 'f);'); + this.push(nodeName + '.setMargin' + toMethodName(value) + '(' + edge + ', ' + toValueJava(value) + 'f);'); }}, YGNodeStyleSetMaxHeight:{value:function(nodeName, value) { - this.push(nodeName + '.setMaxHeight(' + value + 'f);'); + this.push(nodeName + '.setMaxHeight' + toMethodName(value) + '(' + toValueJava(value) + 'f);'); }}, YGNodeStyleSetMaxWidth:{value:function(nodeName, value) { - this.push(nodeName + '.setMaxWidth(' + value + 'f);'); + this.push(nodeName + '.setMaxWidth' + toMethodName(value) + '(' + toValueJava(value) + 'f);'); }}, YGNodeStyleSetMinHeight:{value:function(nodeName, value) { - this.push(nodeName + '.setMinHeight(' + value + 'f);'); + this.push(nodeName + '.setMinHeight' + toMethodName(value) + '(' + toValueJava(value) + 'f);'); }}, YGNodeStyleSetMinWidth:{value:function(nodeName, value) { - this.push(nodeName + '.setMinWidth(' + value + 'f);'); + this.push(nodeName + '.setMinWidth' + toMethodName(value) + '(' + toValueJava(value) + 'f);'); }}, YGNodeStyleSetOverflow:{value:function(nodeName, value) { - this.push(nodeName + '.setOverflow(' + value + ');'); + this.push(nodeName + '.setOverflow(' + toValueJava(value) + ');'); }}, YGNodeStyleSetPadding:{value:function(nodeName, edge, value) { - this.push(nodeName + '.setPadding(' + edge + ', ' + value + ');'); + this.push(nodeName + '.setPadding' + toMethodName(value) + '(' + edge + ', ' + toValueJava(value) + ');'); }}, YGNodeStyleSetPosition:{value:function(nodeName, edge, value) { - this.push(nodeName + '.setPosition(' + edge + ', ' + value + 'f);'); + this.push(nodeName + '.setPosition' + toMethodName(value) + '(' + edge + ', ' + toValueJava(value) + 'f);'); }}, YGNodeStyleSetPositionType:{value:function(nodeName, value) { - this.push(nodeName + '.setPositionType(' + value + ');'); + this.push(nodeName + '.setPositionType(' + toValueJava(value) + ');'); }}, YGNodeStyleSetWidth:{value:function(nodeName, value) { - this.push(nodeName + '.setWidth(' + value + 'f);'); + this.push(nodeName + '.setWidth' + toMethodName(value) + '(' + toValueJava(value) + 'f);'); }}, }); diff --git a/gentest/gentest.js b/gentest/gentest.js index 5851b45e..59341c88 100755 --- a/gentest/gentest.js +++ b/gentest/gentest.js @@ -384,7 +384,7 @@ function pixelValue(e, value) { switch (value) { case 'auto': return e.YGUndefined; case 'undefined': return e.YGUndefined; - default: return value.replace('px', ''); + default: return value; } } diff --git a/java/com/facebook/yoga/YogaConstants.java b/java/com/facebook/yoga/YogaConstants.java index 93dc9f81..ff50f2ab 100644 --- a/java/com/facebook/yoga/YogaConstants.java +++ b/java/com/facebook/yoga/YogaConstants.java @@ -16,4 +16,8 @@ public class YogaConstants { public static boolean isUndefined(float value) { return Float.compare(value, UNDEFINED) == 0; } + + public static boolean isUndefined(YogaValue value) { + return value.unit == YogaUnit.UNDEFINED; + } } diff --git a/java/com/facebook/yoga/YogaNode.java b/java/com/facebook/yoga/YogaNode.java index 2aa11faa..0a4e0bac 100644 --- a/java/com/facebook/yoga/YogaNode.java +++ b/java/com/facebook/yoga/YogaNode.java @@ -323,10 +323,10 @@ public class YogaNode implements YogaNodeAPI { jni_YGNodeStyleSetFlexShrink(mNativePointer, flexShrink); } - private native float jni_YGNodeStyleGetFlexBasis(long nativePointer); + private native Object jni_YGNodeStyleGetFlexBasis(long nativePointer); @Override - public float getFlexBasis() { - return jni_YGNodeStyleGetFlexBasis(mNativePointer); + public YogaValue getFlexBasis() { + return (YogaValue) jni_YGNodeStyleGetFlexBasis(mNativePointer); } private native void jni_YGNodeStyleSetFlexBasis(long nativePointer, float flexBasis); @@ -335,13 +335,19 @@ public class YogaNode implements YogaNodeAPI { jni_YGNodeStyleSetFlexBasis(mNativePointer, flexBasis); } - private native float jni_YGNodeStyleGetMargin(long nativePointer, int edge); + private native void jni_YGNodeStyleSetFlexBasisPercent(long nativePointer, float percent); @Override - public float getMargin(YogaEdge edge) { + public void setFlexBasisPercent(float percent) { + jni_YGNodeStyleSetFlexBasisPercent(mNativePointer, percent); + } + + private native Object jni_YGNodeStyleGetMargin(long nativePointer, int edge); + @Override + public YogaValue getMargin(YogaEdge edge) { if (!mHasSetMargin) { - return edge.intValue() < YogaEdge.START.intValue() ? 0 : YogaConstants.UNDEFINED; + return edge.intValue() < YogaEdge.START.intValue() ? YogaValue.ZERO : YogaValue.UNDEFINED; } - return jni_YGNodeStyleGetMargin(mNativePointer, edge.intValue()); + return (YogaValue) jni_YGNodeStyleGetMargin(mNativePointer, edge.intValue()); } private native void jni_YGNodeStyleSetMargin(long nativePointer, int edge, float margin); @@ -351,13 +357,20 @@ public class YogaNode implements YogaNodeAPI { jni_YGNodeStyleSetMargin(mNativePointer, edge.intValue(), margin); } - private native float jni_YGNodeStyleGetPadding(long nativePointer, int edge); + private native void jni_YGNodeStyleSetMarginPercent(long nativePointer, int edge, float percent); @Override - public float getPadding(YogaEdge edge) { + public void setMarginPercent(YogaEdge edge, float percent) { + mHasSetMargin = true; + jni_YGNodeStyleSetMarginPercent(mNativePointer, edge.intValue(), percent); + } + + private native Object jni_YGNodeStyleGetPadding(long nativePointer, int edge); + @Override + public YogaValue getPadding(YogaEdge edge) { if (!mHasSetPadding) { - return edge.intValue() < YogaEdge.START.intValue() ? 0 : YogaConstants.UNDEFINED; + return edge.intValue() < YogaEdge.START.intValue() ? YogaValue.ZERO : YogaValue.UNDEFINED; } - return jni_YGNodeStyleGetPadding(mNativePointer, edge.intValue()); + return (YogaValue) jni_YGNodeStyleGetPadding(mNativePointer, edge.intValue()); } private native void jni_YGNodeStyleSetPadding(long nativePointer, int edge, float padding); @@ -367,6 +380,13 @@ public class YogaNode implements YogaNodeAPI { jni_YGNodeStyleSetPadding(mNativePointer, edge.intValue(), padding); } + private native void jni_YGNodeStyleSetPaddingPercent(long nativePointer, int edge, float percent); + @Override + public void setPaddingPercent(YogaEdge edge, float percent) { + mHasSetPadding = true; + jni_YGNodeStyleSetPaddingPercent(mNativePointer, edge.intValue(), percent); + } + private native float jni_YGNodeStyleGetBorder(long nativePointer, int edge); @Override public float getBorder(YogaEdge edge) { @@ -383,13 +403,13 @@ public class YogaNode implements YogaNodeAPI { jni_YGNodeStyleSetBorder(mNativePointer, edge.intValue(), border); } - private native float jni_YGNodeStyleGetPosition(long nativePointer, int edge); + private native Object jni_YGNodeStyleGetPosition(long nativePointer, int edge); @Override - public float getPosition(YogaEdge edge) { + public YogaValue getPosition(YogaEdge edge) { if (!mHasSetPosition) { - return YogaConstants.UNDEFINED; + return YogaValue.UNDEFINED; } - return jni_YGNodeStyleGetPosition(mNativePointer, edge.intValue()); + return (YogaValue) jni_YGNodeStyleGetPosition(mNativePointer, edge.intValue()); } private native void jni_YGNodeStyleSetPosition(long nativePointer, int edge, float position); @@ -399,10 +419,17 @@ public class YogaNode implements YogaNodeAPI { jni_YGNodeStyleSetPosition(mNativePointer, edge.intValue(), position); } - private native float jni_YGNodeStyleGetWidth(long nativePointer); + private native void jni_YGNodeStyleSetPositionPercent(long nativePointer, int edge, float percent); @Override - public float getWidth() { - return jni_YGNodeStyleGetWidth(mNativePointer); + public void setPositionPercent(YogaEdge edge, float percent) { + mHasSetPosition = true; + jni_YGNodeStyleSetPositionPercent(mNativePointer, edge.intValue(), percent); + } + + private native Object jni_YGNodeStyleGetWidth(long nativePointer); + @Override + public YogaValue getWidth() { + return (YogaValue) jni_YGNodeStyleGetWidth(mNativePointer); } private native void jni_YGNodeStyleSetWidth(long nativePointer, float width); @@ -411,10 +438,16 @@ public class YogaNode implements YogaNodeAPI { jni_YGNodeStyleSetWidth(mNativePointer, width); } - private native float jni_YGNodeStyleGetHeight(long nativePointer); + private native void jni_YGNodeStyleSetWidthPercent(long nativePointer, float percent); @Override - public float getHeight() { - return jni_YGNodeStyleGetHeight(mNativePointer); + public void setWidthPercent(float percent) { + jni_YGNodeStyleSetWidthPercent(mNativePointer, percent); + } + + private native Object jni_YGNodeStyleGetHeight(long nativePointer); + @Override + public YogaValue getHeight() { + return (YogaValue) jni_YGNodeStyleGetHeight(mNativePointer); } private native void jni_YGNodeStyleSetHeight(long nativePointer, float height); @@ -423,10 +456,16 @@ public class YogaNode implements YogaNodeAPI { jni_YGNodeStyleSetHeight(mNativePointer, height); } - private native float jni_YGNodeStyleGetMinWidth(long nativePointer); + private native void jni_YGNodeStyleSetHeightPercent(long nativePointer, float percent); @Override - public float getMinWidth() { - return jni_YGNodeStyleGetMinWidth(mNativePointer); + public void setHeightPercent(float percent) { + jni_YGNodeStyleSetHeightPercent(mNativePointer, percent); + } + + private native Object jni_YGNodeStyleGetMinWidth(long nativePointer); + @Override + public YogaValue getMinWidth() { + return (YogaValue) jni_YGNodeStyleGetMinWidth(mNativePointer); } private native void jni_YGNodeStyleSetMinWidth(long nativePointer, float minWidth); @@ -435,10 +474,16 @@ public class YogaNode implements YogaNodeAPI { jni_YGNodeStyleSetMinWidth(mNativePointer, minWidth); } - private native float jni_YGNodeStyleGetMinHeight(long nativePointer); + private native void jni_YGNodeStyleSetMinWidthPercent(long nativePointer, float percent); @Override - public float getMinHeight() { - return jni_YGNodeStyleGetMinHeight(mNativePointer); + public void setMinWidthPercent(float percent) { + jni_YGNodeStyleSetMinWidthPercent(mNativePointer, percent); + } + + private native Object jni_YGNodeStyleGetMinHeight(long nativePointer); + @Override + public YogaValue getMinHeight() { + return (YogaValue) jni_YGNodeStyleGetMinHeight(mNativePointer); } private native void jni_YGNodeStyleSetMinHeight(long nativePointer, float minHeight); @@ -447,10 +492,16 @@ public class YogaNode implements YogaNodeAPI { jni_YGNodeStyleSetMinHeight(mNativePointer, minHeight); } - private native float jni_YGNodeStyleGetMaxWidth(long nativePointer); + private native void jni_YGNodeStyleSetMinHeightPercent(long nativePointer, float percent); @Override - public float getMaxWidth() { - return jni_YGNodeStyleGetMaxWidth(mNativePointer); + public void setMinHeightPercent(float percent) { + jni_YGNodeStyleSetMinHeightPercent(mNativePointer, percent); + } + + private native Object jni_YGNodeStyleGetMaxWidth(long nativePointer); + @Override + public YogaValue getMaxWidth() { + return (YogaValue) jni_YGNodeStyleGetMaxWidth(mNativePointer); } private native void jni_YGNodeStyleSetMaxWidth(long nativePointer, float maxWidth); @@ -459,10 +510,16 @@ public class YogaNode implements YogaNodeAPI { jni_YGNodeStyleSetMaxWidth(mNativePointer, maxWidth); } - private native float jni_YGNodeStyleGetMaxHeight(long nativePointer); + private native void jni_YGNodeStyleSetMaxWidthPercent(long nativePointer, float percent); @Override - public float getMaxHeight() { - return jni_YGNodeStyleGetMaxHeight(mNativePointer); + public void setMaxWidthPercent(float percent) { + jni_YGNodeStyleSetMaxWidthPercent(mNativePointer, percent); + } + + private native Object jni_YGNodeStyleGetMaxHeight(long nativePointer); + @Override + public YogaValue getMaxHeight() { + return (YogaValue) jni_YGNodeStyleGetMaxHeight(mNativePointer); } private native void jni_YGNodeStyleSetMaxHeight(long nativePointer, float maxheight); @@ -471,6 +528,12 @@ public class YogaNode implements YogaNodeAPI { jni_YGNodeStyleSetMaxHeight(mNativePointer, maxheight); } + private native void jni_YGNodeStyleSetMaxHeightPercent(long nativePointer, float percent); + @Override + public void setMaxHeightPercent(float percent) { + jni_YGNodeStyleSetMaxHeightPercent(mNativePointer, percent); + } + private native float jni_YGNodeStyleGetAspectRatio(long nativePointer); public float getAspectRatio() { return jni_YGNodeStyleGetAspectRatio(mNativePointer); diff --git a/java/com/facebook/yoga/YogaNodeAPI.java b/java/com/facebook/yoga/YogaNodeAPI.java index cb3b5be8..b3cf0ac3 100644 --- a/java/com/facebook/yoga/YogaNodeAPI.java +++ b/java/com/facebook/yoga/YogaNodeAPI.java @@ -45,28 +45,38 @@ public interface YogaNodeAPI { void setFlexGrow(float flexGrow); float getFlexShrink(); void setFlexShrink(float flexShrink); - float getFlexBasis(); + YogaValue getFlexBasis(); void setFlexBasis(float flexBasis); - float getMargin(YogaEdge edge); + void setFlexBasisPercent(float percent); + YogaValue getMargin(YogaEdge edge); void setMargin(YogaEdge edge, float margin); - float getPadding(YogaEdge edge); + void setMarginPercent(YogaEdge edge, float percent); + YogaValue getPadding(YogaEdge edge); void setPadding(YogaEdge edge, float padding); + void setPaddingPercent(YogaEdge edge, float percent); float getBorder(YogaEdge edge); void setBorder(YogaEdge edge, float border); - float getPosition(YogaEdge edge); + YogaValue getPosition(YogaEdge edge); void setPosition(YogaEdge edge, float position); - float getWidth(); + void setPositionPercent(YogaEdge edge, float percent); + YogaValue getWidth(); void setWidth(float width); - float getHeight(); + void setWidthPercent(float percent); + YogaValue getHeight(); void setHeight(float height); - float getMaxWidth(); + void setHeightPercent(float percent); + YogaValue getMaxWidth(); void setMaxWidth(float maxWidth); - float getMinWidth(); + void setMaxWidthPercent(float percent); + YogaValue getMinWidth(); void setMinWidth(float minWidth); - float getMaxHeight(); + void setMinWidthPercent(float percent); + YogaValue getMaxHeight(); void setMaxHeight(float maxHeight); - float getMinHeight(); + void setMaxHeightPercent(float percent); + YogaValue getMinHeight(); void setMinHeight(float minHeight); + void setMinHeightPercent(float percent); float getLayoutX(); float getLayoutY(); float getLayoutWidth(); diff --git a/java/com/facebook/yoga/YogaUnit.java b/java/com/facebook/yoga/YogaUnit.java new file mode 100644 index 00000000..43e4b787 --- /dev/null +++ b/java/com/facebook/yoga/YogaUnit.java @@ -0,0 +1,38 @@ +/** + * 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. + */ + +package com.facebook.yoga; + +import com.facebook.proguard.annotations.DoNotStrip; + +@DoNotStrip +public enum YogaUnit { + UNDEFINED(0), + PIXEL(1), + PERCENT(2); + + private int mIntValue; + + YogaUnit(int intValue) { + mIntValue = intValue; + } + + public int intValue() { + return mIntValue; + } + + public static YogaUnit fromInt(int value) { + switch (value) { + case 0: return UNDEFINED; + case 1: return PIXEL; + case 2: return PERCENT; + default: throw new IllegalArgumentException("Unkown enum value: " + value); + } + } +} diff --git a/java/com/facebook/yoga/YogaValue.java b/java/com/facebook/yoga/YogaValue.java new file mode 100644 index 00000000..c2d257fc --- /dev/null +++ b/java/com/facebook/yoga/YogaValue.java @@ -0,0 +1,45 @@ +/** + * 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. + */ + +package com.facebook.yoga; + +import com.facebook.proguard.annotations.DoNotStrip; + +@DoNotStrip +public class YogaValue { + static final YogaValue UNDEFINED = new YogaValue(YogaConstants.UNDEFINED, YogaUnit.UNDEFINED); + static final YogaValue ZERO = new YogaValue(0, YogaUnit.PIXEL); + + public final float value; + public final YogaUnit unit; + + YogaValue(float value, YogaUnit unit) { + this.value = value; + this.unit = unit; + } + + @DoNotStrip + YogaValue(float value, int unit) { + this(value, YogaUnit.fromInt(unit)); + } + + @Override + public boolean equals(Object other) { + if (other instanceof YogaValue) { + final YogaValue otherValue = (YogaValue) other; + return value == otherValue.value && unit == otherValue.unit; + } + return false; + } + + @Override + public int hashCode() { + return Float.floatToIntBits(value) + unit.intValue(); + } +} diff --git a/java/jni/YGJNI.cpp b/java/jni/YGJNI.cpp index d0c2a804..de648a4b 100644 --- a/java/jni/YGJNI.cpp +++ b/java/jni/YGJNI.cpp @@ -7,9 +7,9 @@ * of patent rights can be found in the PATENTS file in the same directory. */ -#include #include #include +#include using namespace facebook::jni; using namespace std; @@ -70,8 +70,8 @@ static YGSize YGJNIMeasureFunc(YGNodeRef node, int32_t wBits = 0xFFFFFFFF & (measureResult >> 32); int32_t hBits = 0xFFFFFFFF & measureResult; - const float *measuredWidth = reinterpret_cast(&wBits); - const float *measuredHeight = reinterpret_cast(&hBits); + const float *measuredWidth = reinterpret_cast(&wBits); + const float *measuredHeight = reinterpret_cast(&hBits); return YGSize{*measuredWidth, *measuredHeight}; } else { @@ -204,6 +204,14 @@ void jni_YGNodeCopyStyle(alias_ref, jlong dstNativePointer, jlong srcNa YGNodeCopyStyle(_jlong2YGNodeRef(dstNativePointer), _jlong2YGNodeRef(srcNativePointer)); } +struct JYogaValue : public JavaClass { + constexpr static auto kJavaDescriptor = "Lcom/facebook/yoga/YogaValue;"; + + static local_ref create(YGValue value) { + return newInstance(value.value, static_cast(value.unit)); + } +}; + #define YG_NODE_JNI_STYLE_PROP(javatype, type, name) \ javatype jni_YGNodeStyleGet##name(alias_ref, jlong nativePointer) { \ return (javatype) YGNodeStyleGet##name(_jlong2YGNodeRef(nativePointer)); \ @@ -213,6 +221,19 @@ void jni_YGNodeCopyStyle(alias_ref, jlong dstNativePointer, jlong srcNa YGNodeStyleSet##name(_jlong2YGNodeRef(nativePointer), static_cast(value)); \ } +#define YG_NODE_JNI_STYLE_UNIT_PROP(name) \ + local_ref jni_YGNodeStyleGet##name(alias_ref, jlong nativePointer) { \ + return JYogaValue::create(YGNodeStyleGet##name(_jlong2YGNodeRef(nativePointer))); \ + } \ + \ + void jni_YGNodeStyleSet##name(alias_ref, jlong nativePointer, jfloat value) { \ + YGNodeStyleSet##name(_jlong2YGNodeRef(nativePointer), static_cast(value)); \ + } \ + \ + void jni_YGNodeStyleSet##name##Percent(alias_ref, jlong nativePointer, jfloat value) { \ + YGNodeStyleSet##name##Percent(_jlong2YGNodeRef(nativePointer), static_cast(value)); \ + } + #define YG_NODE_JNI_STYLE_EDGE_PROP(javatype, type, name) \ javatype jni_YGNodeStyleGet##name(alias_ref, jlong nativePointer, jint edge) { \ return (javatype) YGNodeStyleGet##name(_jlong2YGNodeRef(nativePointer), \ @@ -228,6 +249,29 @@ void jni_YGNodeCopyStyle(alias_ref, jlong dstNativePointer, jlong srcNa static_cast(value)); \ } +#define YG_NODE_JNI_STYLE_EDGE_UNIT_PROP(name) \ + local_ref jni_YGNodeStyleGet##name(alias_ref, \ + jlong nativePointer, \ + jint edge) { \ + return JYogaValue::create( \ + YGNodeStyleGet##name(_jlong2YGNodeRef(nativePointer), static_cast(edge))); \ + } \ + \ + void jni_YGNodeStyleSet##name(alias_ref, jlong nativePointer, jint edge, jfloat value) { \ + YGNodeStyleSet##name(_jlong2YGNodeRef(nativePointer), \ + static_cast(edge), \ + static_cast(value)); \ + } \ + \ + void jni_YGNodeStyleSet##name##Percent(alias_ref, \ + jlong nativePointer, \ + jint edge, \ + jfloat value) { \ + YGNodeStyleSet##name##Percent(_jlong2YGNodeRef(nativePointer), \ + static_cast(edge), \ + static_cast(value)); \ + } + YG_NODE_JNI_STYLE_PROP(jint, YGDirection, Direction); YG_NODE_JNI_STYLE_PROP(jint, YGFlexDirection, FlexDirection); YG_NODE_JNI_STYLE_PROP(jint, YGJustify, JustifyContent); @@ -243,19 +287,19 @@ void jni_YGNodeStyleSetFlex(alias_ref, jlong nativePointer, jfloat valu } YG_NODE_JNI_STYLE_PROP(jfloat, float, FlexGrow); YG_NODE_JNI_STYLE_PROP(jfloat, float, FlexShrink); -YG_NODE_JNI_STYLE_PROP(jfloat, float, FlexBasis); +YG_NODE_JNI_STYLE_UNIT_PROP(FlexBasis); -YG_NODE_JNI_STYLE_EDGE_PROP(jfloat, float, Position); -YG_NODE_JNI_STYLE_EDGE_PROP(jfloat, float, Margin); -YG_NODE_JNI_STYLE_EDGE_PROP(jfloat, float, Padding); +YG_NODE_JNI_STYLE_EDGE_UNIT_PROP(Position); +YG_NODE_JNI_STYLE_EDGE_UNIT_PROP(Margin); +YG_NODE_JNI_STYLE_EDGE_UNIT_PROP(Padding); YG_NODE_JNI_STYLE_EDGE_PROP(jfloat, float, Border); -YG_NODE_JNI_STYLE_PROP(jfloat, float, Width); -YG_NODE_JNI_STYLE_PROP(jfloat, float, MinWidth); -YG_NODE_JNI_STYLE_PROP(jfloat, float, MaxWidth); -YG_NODE_JNI_STYLE_PROP(jfloat, float, Height); -YG_NODE_JNI_STYLE_PROP(jfloat, float, MinHeight); -YG_NODE_JNI_STYLE_PROP(jfloat, float, MaxHeight); +YG_NODE_JNI_STYLE_UNIT_PROP(Width); +YG_NODE_JNI_STYLE_UNIT_PROP(MinWidth); +YG_NODE_JNI_STYLE_UNIT_PROP(MaxWidth); +YG_NODE_JNI_STYLE_UNIT_PROP(Height); +YG_NODE_JNI_STYLE_UNIT_PROP(MinHeight); +YG_NODE_JNI_STYLE_UNIT_PROP(MaxHeight); // Yoga specific properties, not compatible with flexbox specification YG_NODE_JNI_STYLE_PROP(jfloat, float, AspectRatio); @@ -278,7 +322,6 @@ jint JNI_OnLoad(JavaVM *vm, void *) { YGMakeNativeMethod(jni_YGNodeMarkLayoutSeen), YGMakeNativeMethod(jni_YGNodeSetHasMeasureFunc), YGMakeNativeMethod(jni_YGNodeCopyStyle), - YGMakeNativeMethod(jni_YGNodeStyleGetDirection), YGMakeNativeMethod(jni_YGNodeStyleSetDirection), YGMakeNativeMethod(jni_YGNodeStyleGetFlexDirection), @@ -303,29 +346,38 @@ jint JNI_OnLoad(JavaVM *vm, void *) { YGMakeNativeMethod(jni_YGNodeStyleSetFlexShrink), YGMakeNativeMethod(jni_YGNodeStyleGetFlexBasis), YGMakeNativeMethod(jni_YGNodeStyleSetFlexBasis), + YGMakeNativeMethod(jni_YGNodeStyleSetFlexBasisPercent), YGMakeNativeMethod(jni_YGNodeStyleGetMargin), YGMakeNativeMethod(jni_YGNodeStyleSetMargin), + YGMakeNativeMethod(jni_YGNodeStyleSetMarginPercent), YGMakeNativeMethod(jni_YGNodeStyleGetPadding), YGMakeNativeMethod(jni_YGNodeStyleSetPadding), + YGMakeNativeMethod(jni_YGNodeStyleSetPaddingPercent), YGMakeNativeMethod(jni_YGNodeStyleGetBorder), YGMakeNativeMethod(jni_YGNodeStyleSetBorder), YGMakeNativeMethod(jni_YGNodeStyleGetPosition), YGMakeNativeMethod(jni_YGNodeStyleSetPosition), + YGMakeNativeMethod(jni_YGNodeStyleSetPositionPercent), YGMakeNativeMethod(jni_YGNodeStyleGetWidth), YGMakeNativeMethod(jni_YGNodeStyleSetWidth), + YGMakeNativeMethod(jni_YGNodeStyleSetWidthPercent), YGMakeNativeMethod(jni_YGNodeStyleGetHeight), YGMakeNativeMethod(jni_YGNodeStyleSetHeight), + YGMakeNativeMethod(jni_YGNodeStyleSetHeightPercent), YGMakeNativeMethod(jni_YGNodeStyleGetMinWidth), YGMakeNativeMethod(jni_YGNodeStyleSetMinWidth), + YGMakeNativeMethod(jni_YGNodeStyleSetMinWidthPercent), YGMakeNativeMethod(jni_YGNodeStyleGetMinHeight), YGMakeNativeMethod(jni_YGNodeStyleSetMinHeight), + YGMakeNativeMethod(jni_YGNodeStyleSetMinHeightPercent), YGMakeNativeMethod(jni_YGNodeStyleGetMaxWidth), YGMakeNativeMethod(jni_YGNodeStyleSetMaxWidth), + YGMakeNativeMethod(jni_YGNodeStyleSetMaxWidthPercent), YGMakeNativeMethod(jni_YGNodeStyleGetMaxHeight), YGMakeNativeMethod(jni_YGNodeStyleSetMaxHeight), + YGMakeNativeMethod(jni_YGNodeStyleSetMaxHeightPercent), YGMakeNativeMethod(jni_YGNodeStyleGetAspectRatio), YGMakeNativeMethod(jni_YGNodeStyleSetAspectRatio), - YGMakeNativeMethod(jni_YGNodeGetInstanceCount), YGMakeNativeMethod(jni_YGSetLogger), YGMakeNativeMethod(jni_YGLog), diff --git a/java/tests/com/facebook/yoga/YGPercentageTest.java b/java/tests/com/facebook/yoga/YGPercentageTest.java new file mode 100644 index 00000000..c746008a --- /dev/null +++ b/java/tests/com/facebook/yoga/YGPercentageTest.java @@ -0,0 +1,941 @@ +/** + * 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. + */ + + // @Generated by gentest/gentest.rb from gentest/fixtures/YGPercentageTest.html + +package com.facebook.yoga; + +import org.junit.Test; + +import static org.junit.Assert.assertEquals; + +public class YGPercentageTest { + @Test + public void test_percentage_width_height() { + YogaNode.setExperimentalFeatureEnabled(YogaExperimentalFeature.ROUNDING, true); + + final YogaNode root = new YogaNode(); + root.setFlexDirection(YogaFlexDirection.ROW); + root.setWidth(200f); + root.setHeight(200f); + + final YogaNode root_child0 = new YogaNode(); + root_child0.setWidthPercent(30f); + root_child0.setHeightPercent(30f); + root.addChildAt(root_child0, 0); + root.setDirection(YogaDirection.LTR); + root.calculateLayout(); + + assertEquals(0f, root.getLayoutX(), 0.0f); + assertEquals(0f, root.getLayoutY(), 0.0f); + assertEquals(200f, root.getLayoutWidth(), 0.0f); + assertEquals(200f, root.getLayoutHeight(), 0.0f); + + assertEquals(0f, root_child0.getLayoutX(), 0.0f); + assertEquals(0f, root_child0.getLayoutY(), 0.0f); + assertEquals(60f, root_child0.getLayoutWidth(), 0.0f); + assertEquals(60f, root_child0.getLayoutHeight(), 0.0f); + + root.setDirection(YogaDirection.RTL); + root.calculateLayout(); + + assertEquals(0f, root.getLayoutX(), 0.0f); + assertEquals(0f, root.getLayoutY(), 0.0f); + assertEquals(200f, root.getLayoutWidth(), 0.0f); + assertEquals(200f, root.getLayoutHeight(), 0.0f); + + assertEquals(140f, root_child0.getLayoutX(), 0.0f); + assertEquals(0f, root_child0.getLayoutY(), 0.0f); + assertEquals(60f, root_child0.getLayoutWidth(), 0.0f); + assertEquals(60f, root_child0.getLayoutHeight(), 0.0f); + + YogaNode.setExperimentalFeatureEnabled(YogaExperimentalFeature.ROUNDING, false); + } + + @Test + public void test_percentage_position_left_top() { + YogaNode.setExperimentalFeatureEnabled(YogaExperimentalFeature.ROUNDING, true); + + final YogaNode root = new YogaNode(); + root.setFlexDirection(YogaFlexDirection.ROW); + root.setWidth(400f); + root.setHeight(400f); + + final YogaNode root_child0 = new YogaNode(); + root_child0.setPositionPercent(YogaEdge.LEFT, 10f); + root_child0.setPositionPercent(YogaEdge.TOP, 20f); + root_child0.setWidthPercent(45f); + root_child0.setHeightPercent(55f); + root.addChildAt(root_child0, 0); + root.setDirection(YogaDirection.LTR); + root.calculateLayout(); + + assertEquals(0f, root.getLayoutX(), 0.0f); + assertEquals(0f, root.getLayoutY(), 0.0f); + assertEquals(400f, root.getLayoutWidth(), 0.0f); + assertEquals(400f, root.getLayoutHeight(), 0.0f); + + assertEquals(40f, root_child0.getLayoutX(), 0.0f); + assertEquals(80f, root_child0.getLayoutY(), 0.0f); + assertEquals(180f, root_child0.getLayoutWidth(), 0.0f); + assertEquals(220f, root_child0.getLayoutHeight(), 0.0f); + + root.setDirection(YogaDirection.RTL); + root.calculateLayout(); + + assertEquals(0f, root.getLayoutX(), 0.0f); + assertEquals(0f, root.getLayoutY(), 0.0f); + assertEquals(400f, root.getLayoutWidth(), 0.0f); + assertEquals(400f, root.getLayoutHeight(), 0.0f); + + assertEquals(260f, root_child0.getLayoutX(), 0.0f); + assertEquals(80f, root_child0.getLayoutY(), 0.0f); + assertEquals(180f, root_child0.getLayoutWidth(), 0.0f); + assertEquals(220f, root_child0.getLayoutHeight(), 0.0f); + + YogaNode.setExperimentalFeatureEnabled(YogaExperimentalFeature.ROUNDING, false); + } + + @Test + public void test_percentage_position_bottom_right() { + YogaNode.setExperimentalFeatureEnabled(YogaExperimentalFeature.ROUNDING, true); + + final YogaNode root = new YogaNode(); + root.setFlexDirection(YogaFlexDirection.ROW); + root.setWidth(500f); + root.setHeight(500f); + + final YogaNode root_child0 = new YogaNode(); + root_child0.setPositionPercent(YogaEdge.RIGHT, 20f); + root_child0.setPositionPercent(YogaEdge.BOTTOM, 10f); + root_child0.setWidthPercent(55f); + root_child0.setHeightPercent(15f); + root.addChildAt(root_child0, 0); + root.setDirection(YogaDirection.LTR); + root.calculateLayout(); + + assertEquals(0f, root.getLayoutX(), 0.0f); + assertEquals(0f, root.getLayoutY(), 0.0f); + assertEquals(500f, root.getLayoutWidth(), 0.0f); + assertEquals(500f, root.getLayoutHeight(), 0.0f); + + assertEquals(-100f, root_child0.getLayoutX(), 0.0f); + assertEquals(-50f, root_child0.getLayoutY(), 0.0f); + assertEquals(275f, root_child0.getLayoutWidth(), 0.0f); + assertEquals(75f, root_child0.getLayoutHeight(), 0.0f); + + root.setDirection(YogaDirection.RTL); + root.calculateLayout(); + + assertEquals(0f, root.getLayoutX(), 0.0f); + assertEquals(0f, root.getLayoutY(), 0.0f); + assertEquals(500f, root.getLayoutWidth(), 0.0f); + assertEquals(500f, root.getLayoutHeight(), 0.0f); + + assertEquals(125f, root_child0.getLayoutX(), 0.0f); + assertEquals(-50f, root_child0.getLayoutY(), 0.0f); + assertEquals(275f, root_child0.getLayoutWidth(), 0.0f); + assertEquals(75f, root_child0.getLayoutHeight(), 0.0f); + + YogaNode.setExperimentalFeatureEnabled(YogaExperimentalFeature.ROUNDING, false); + } + + @Test + public void test_percentage_flex_basis() { + YogaNode.setExperimentalFeatureEnabled(YogaExperimentalFeature.ROUNDING, true); + + final YogaNode root = new YogaNode(); + root.setFlexDirection(YogaFlexDirection.ROW); + root.setWidth(200f); + root.setHeight(200f); + + final YogaNode root_child0 = new YogaNode(); + root_child0.setFlexGrow(1f); + root_child0.setFlexBasisPercent(50f); + root.addChildAt(root_child0, 0); + + final YogaNode root_child1 = new YogaNode(); + root_child1.setFlexGrow(1f); + root_child1.setFlexBasisPercent(25f); + root.addChildAt(root_child1, 1); + root.setDirection(YogaDirection.LTR); + root.calculateLayout(); + + assertEquals(0f, root.getLayoutX(), 0.0f); + assertEquals(0f, root.getLayoutY(), 0.0f); + assertEquals(200f, root.getLayoutWidth(), 0.0f); + assertEquals(200f, root.getLayoutHeight(), 0.0f); + + assertEquals(0f, root_child0.getLayoutX(), 0.0f); + assertEquals(0f, root_child0.getLayoutY(), 0.0f); + assertEquals(125f, root_child0.getLayoutWidth(), 0.0f); + assertEquals(200f, root_child0.getLayoutHeight(), 0.0f); + + assertEquals(125f, root_child1.getLayoutX(), 0.0f); + assertEquals(0f, root_child1.getLayoutY(), 0.0f); + assertEquals(75f, root_child1.getLayoutWidth(), 0.0f); + assertEquals(200f, root_child1.getLayoutHeight(), 0.0f); + + root.setDirection(YogaDirection.RTL); + root.calculateLayout(); + + assertEquals(0f, root.getLayoutX(), 0.0f); + assertEquals(0f, root.getLayoutY(), 0.0f); + assertEquals(200f, root.getLayoutWidth(), 0.0f); + assertEquals(200f, root.getLayoutHeight(), 0.0f); + + assertEquals(75f, root_child0.getLayoutX(), 0.0f); + assertEquals(0f, root_child0.getLayoutY(), 0.0f); + assertEquals(125f, root_child0.getLayoutWidth(), 0.0f); + assertEquals(200f, root_child0.getLayoutHeight(), 0.0f); + + assertEquals(0f, root_child1.getLayoutX(), 0.0f); + assertEquals(0f, root_child1.getLayoutY(), 0.0f); + assertEquals(75f, root_child1.getLayoutWidth(), 0.0f); + assertEquals(200f, root_child1.getLayoutHeight(), 0.0f); + + YogaNode.setExperimentalFeatureEnabled(YogaExperimentalFeature.ROUNDING, false); + } + + @Test + public void test_percentage_flex_basis_cross() { + YogaNode.setExperimentalFeatureEnabled(YogaExperimentalFeature.ROUNDING, true); + + final YogaNode root = new YogaNode(); + root.setWidth(200f); + root.setHeight(200f); + + final YogaNode root_child0 = new YogaNode(); + root_child0.setFlexGrow(1f); + root_child0.setFlexBasisPercent(50f); + root.addChildAt(root_child0, 0); + + final YogaNode root_child1 = new YogaNode(); + root_child1.setFlexGrow(1f); + root_child1.setFlexBasisPercent(25f); + root.addChildAt(root_child1, 1); + root.setDirection(YogaDirection.LTR); + root.calculateLayout(); + + assertEquals(0f, root.getLayoutX(), 0.0f); + assertEquals(0f, root.getLayoutY(), 0.0f); + assertEquals(200f, root.getLayoutWidth(), 0.0f); + assertEquals(200f, root.getLayoutHeight(), 0.0f); + + assertEquals(0f, root_child0.getLayoutX(), 0.0f); + assertEquals(0f, root_child0.getLayoutY(), 0.0f); + assertEquals(200f, root_child0.getLayoutWidth(), 0.0f); + assertEquals(125f, root_child0.getLayoutHeight(), 0.0f); + + assertEquals(0f, root_child1.getLayoutX(), 0.0f); + assertEquals(125f, root_child1.getLayoutY(), 0.0f); + assertEquals(200f, root_child1.getLayoutWidth(), 0.0f); + assertEquals(75f, root_child1.getLayoutHeight(), 0.0f); + + root.setDirection(YogaDirection.RTL); + root.calculateLayout(); + + assertEquals(0f, root.getLayoutX(), 0.0f); + assertEquals(0f, root.getLayoutY(), 0.0f); + assertEquals(200f, root.getLayoutWidth(), 0.0f); + assertEquals(200f, root.getLayoutHeight(), 0.0f); + + assertEquals(0f, root_child0.getLayoutX(), 0.0f); + assertEquals(0f, root_child0.getLayoutY(), 0.0f); + assertEquals(200f, root_child0.getLayoutWidth(), 0.0f); + assertEquals(125f, root_child0.getLayoutHeight(), 0.0f); + + assertEquals(0f, root_child1.getLayoutX(), 0.0f); + assertEquals(125f, root_child1.getLayoutY(), 0.0f); + assertEquals(200f, root_child1.getLayoutWidth(), 0.0f); + assertEquals(75f, root_child1.getLayoutHeight(), 0.0f); + + YogaNode.setExperimentalFeatureEnabled(YogaExperimentalFeature.ROUNDING, false); + } + + @Test + public void test_percentage_flex_basis_cross_min_height() { + YogaNode.setExperimentalFeatureEnabled(YogaExperimentalFeature.ROUNDING, true); + + final YogaNode root = new YogaNode(); + root.setWidth(200f); + root.setHeight(200f); + + final YogaNode root_child0 = new YogaNode(); + root_child0.setFlexGrow(1f); + root_child0.setMinHeightPercent(60f); + root.addChildAt(root_child0, 0); + + final YogaNode root_child1 = new YogaNode(); + root_child1.setFlexGrow(2f); + root_child1.setMinHeightPercent(10f); + root.addChildAt(root_child1, 1); + root.setDirection(YogaDirection.LTR); + root.calculateLayout(); + + assertEquals(0f, root.getLayoutX(), 0.0f); + assertEquals(0f, root.getLayoutY(), 0.0f); + assertEquals(200f, root.getLayoutWidth(), 0.0f); + assertEquals(200f, root.getLayoutHeight(), 0.0f); + + assertEquals(0f, root_child0.getLayoutX(), 0.0f); + assertEquals(0f, root_child0.getLayoutY(), 0.0f); + assertEquals(200f, root_child0.getLayoutWidth(), 0.0f); + assertEquals(140f, root_child0.getLayoutHeight(), 0.0f); + + assertEquals(0f, root_child1.getLayoutX(), 0.0f); + assertEquals(140f, root_child1.getLayoutY(), 0.0f); + assertEquals(200f, root_child1.getLayoutWidth(), 0.0f); + assertEquals(60f, root_child1.getLayoutHeight(), 0.0f); + + root.setDirection(YogaDirection.RTL); + root.calculateLayout(); + + assertEquals(0f, root.getLayoutX(), 0.0f); + assertEquals(0f, root.getLayoutY(), 0.0f); + assertEquals(200f, root.getLayoutWidth(), 0.0f); + assertEquals(200f, root.getLayoutHeight(), 0.0f); + + assertEquals(0f, root_child0.getLayoutX(), 0.0f); + assertEquals(0f, root_child0.getLayoutY(), 0.0f); + assertEquals(200f, root_child0.getLayoutWidth(), 0.0f); + assertEquals(140f, root_child0.getLayoutHeight(), 0.0f); + + assertEquals(0f, root_child1.getLayoutX(), 0.0f); + assertEquals(140f, root_child1.getLayoutY(), 0.0f); + assertEquals(200f, root_child1.getLayoutWidth(), 0.0f); + assertEquals(60f, root_child1.getLayoutHeight(), 0.0f); + + YogaNode.setExperimentalFeatureEnabled(YogaExperimentalFeature.ROUNDING, false); + } + + @Test + public void test_percentage_flex_basis_main_max_height() { + YogaNode.setExperimentalFeatureEnabled(YogaExperimentalFeature.ROUNDING, true); + + final YogaNode root = new YogaNode(); + root.setFlexDirection(YogaFlexDirection.ROW); + root.setWidth(200f); + root.setHeight(200f); + + final YogaNode root_child0 = new YogaNode(); + root_child0.setFlexGrow(1f); + root_child0.setFlexBasisPercent(10f); + root_child0.setMaxHeightPercent(60f); + root.addChildAt(root_child0, 0); + + final YogaNode root_child1 = new YogaNode(); + root_child1.setFlexGrow(4f); + root_child1.setFlexBasisPercent(10f); + root_child1.setMaxHeightPercent(20f); + root.addChildAt(root_child1, 1); + root.setDirection(YogaDirection.LTR); + root.calculateLayout(); + + assertEquals(0f, root.getLayoutX(), 0.0f); + assertEquals(0f, root.getLayoutY(), 0.0f); + assertEquals(200f, root.getLayoutWidth(), 0.0f); + assertEquals(200f, root.getLayoutHeight(), 0.0f); + + assertEquals(0f, root_child0.getLayoutX(), 0.0f); + assertEquals(0f, root_child0.getLayoutY(), 0.0f); + assertEquals(52f, root_child0.getLayoutWidth(), 0.0f); + assertEquals(120f, root_child0.getLayoutHeight(), 0.0f); + + assertEquals(52f, root_child1.getLayoutX(), 0.0f); + assertEquals(0f, root_child1.getLayoutY(), 0.0f); + assertEquals(148f, root_child1.getLayoutWidth(), 0.0f); + assertEquals(40f, root_child1.getLayoutHeight(), 0.0f); + + root.setDirection(YogaDirection.RTL); + root.calculateLayout(); + + assertEquals(0f, root.getLayoutX(), 0.0f); + assertEquals(0f, root.getLayoutY(), 0.0f); + assertEquals(200f, root.getLayoutWidth(), 0.0f); + assertEquals(200f, root.getLayoutHeight(), 0.0f); + + assertEquals(148f, root_child0.getLayoutX(), 0.0f); + assertEquals(0f, root_child0.getLayoutY(), 0.0f); + assertEquals(52f, root_child0.getLayoutWidth(), 0.0f); + assertEquals(120f, root_child0.getLayoutHeight(), 0.0f); + + assertEquals(0f, root_child1.getLayoutX(), 0.0f); + assertEquals(0f, root_child1.getLayoutY(), 0.0f); + assertEquals(148f, root_child1.getLayoutWidth(), 0.0f); + assertEquals(40f, root_child1.getLayoutHeight(), 0.0f); + + YogaNode.setExperimentalFeatureEnabled(YogaExperimentalFeature.ROUNDING, false); + } + + @Test + public void test_percentage_flex_basis_cross_max_height() { + YogaNode.setExperimentalFeatureEnabled(YogaExperimentalFeature.ROUNDING, true); + + final YogaNode root = new YogaNode(); + root.setWidth(200f); + root.setHeight(200f); + + final YogaNode root_child0 = new YogaNode(); + root_child0.setFlexGrow(1f); + root_child0.setFlexBasisPercent(10f); + root_child0.setMaxHeightPercent(60f); + root.addChildAt(root_child0, 0); + + final YogaNode root_child1 = new YogaNode(); + root_child1.setFlexGrow(4f); + root_child1.setFlexBasisPercent(10f); + root_child1.setMaxHeightPercent(20f); + root.addChildAt(root_child1, 1); + root.setDirection(YogaDirection.LTR); + root.calculateLayout(); + + assertEquals(0f, root.getLayoutX(), 0.0f); + assertEquals(0f, root.getLayoutY(), 0.0f); + assertEquals(200f, root.getLayoutWidth(), 0.0f); + assertEquals(200f, root.getLayoutHeight(), 0.0f); + + assertEquals(0f, root_child0.getLayoutX(), 0.0f); + assertEquals(0f, root_child0.getLayoutY(), 0.0f); + assertEquals(200f, root_child0.getLayoutWidth(), 0.0f); + assertEquals(120f, root_child0.getLayoutHeight(), 0.0f); + + assertEquals(0f, root_child1.getLayoutX(), 0.0f); + assertEquals(120f, root_child1.getLayoutY(), 0.0f); + assertEquals(200f, root_child1.getLayoutWidth(), 0.0f); + assertEquals(40f, root_child1.getLayoutHeight(), 0.0f); + + root.setDirection(YogaDirection.RTL); + root.calculateLayout(); + + assertEquals(0f, root.getLayoutX(), 0.0f); + assertEquals(0f, root.getLayoutY(), 0.0f); + assertEquals(200f, root.getLayoutWidth(), 0.0f); + assertEquals(200f, root.getLayoutHeight(), 0.0f); + + assertEquals(0f, root_child0.getLayoutX(), 0.0f); + assertEquals(0f, root_child0.getLayoutY(), 0.0f); + assertEquals(200f, root_child0.getLayoutWidth(), 0.0f); + assertEquals(120f, root_child0.getLayoutHeight(), 0.0f); + + assertEquals(0f, root_child1.getLayoutX(), 0.0f); + assertEquals(120f, root_child1.getLayoutY(), 0.0f); + assertEquals(200f, root_child1.getLayoutWidth(), 0.0f); + assertEquals(40f, root_child1.getLayoutHeight(), 0.0f); + + YogaNode.setExperimentalFeatureEnabled(YogaExperimentalFeature.ROUNDING, false); + } + + @Test + public void test_percentage_flex_basis_main_max_width() { + YogaNode.setExperimentalFeatureEnabled(YogaExperimentalFeature.ROUNDING, true); + + final YogaNode root = new YogaNode(); + root.setFlexDirection(YogaFlexDirection.ROW); + root.setWidth(200f); + root.setHeight(200f); + + final YogaNode root_child0 = new YogaNode(); + root_child0.setFlexGrow(1f); + root_child0.setFlexBasisPercent(15f); + root_child0.setMaxWidthPercent(60f); + root.addChildAt(root_child0, 0); + + final YogaNode root_child1 = new YogaNode(); + root_child1.setFlexGrow(4f); + root_child1.setFlexBasisPercent(10f); + root_child1.setMaxWidthPercent(20f); + root.addChildAt(root_child1, 1); + root.setDirection(YogaDirection.LTR); + root.calculateLayout(); + + assertEquals(0f, root.getLayoutX(), 0.0f); + assertEquals(0f, root.getLayoutY(), 0.0f); + assertEquals(200f, root.getLayoutWidth(), 0.0f); + assertEquals(200f, root.getLayoutHeight(), 0.0f); + + assertEquals(0f, root_child0.getLayoutX(), 0.0f); + assertEquals(0f, root_child0.getLayoutY(), 0.0f); + assertEquals(120f, root_child0.getLayoutWidth(), 0.0f); + assertEquals(200f, root_child0.getLayoutHeight(), 0.0f); + + assertEquals(120f, root_child1.getLayoutX(), 0.0f); + assertEquals(0f, root_child1.getLayoutY(), 0.0f); + assertEquals(40f, root_child1.getLayoutWidth(), 0.0f); + assertEquals(200f, root_child1.getLayoutHeight(), 0.0f); + + root.setDirection(YogaDirection.RTL); + root.calculateLayout(); + + assertEquals(0f, root.getLayoutX(), 0.0f); + assertEquals(0f, root.getLayoutY(), 0.0f); + assertEquals(200f, root.getLayoutWidth(), 0.0f); + assertEquals(200f, root.getLayoutHeight(), 0.0f); + + assertEquals(80f, root_child0.getLayoutX(), 0.0f); + assertEquals(0f, root_child0.getLayoutY(), 0.0f); + assertEquals(120f, root_child0.getLayoutWidth(), 0.0f); + assertEquals(200f, root_child0.getLayoutHeight(), 0.0f); + + assertEquals(40f, root_child1.getLayoutX(), 0.0f); + assertEquals(0f, root_child1.getLayoutY(), 0.0f); + assertEquals(40f, root_child1.getLayoutWidth(), 0.0f); + assertEquals(200f, root_child1.getLayoutHeight(), 0.0f); + + YogaNode.setExperimentalFeatureEnabled(YogaExperimentalFeature.ROUNDING, false); + } + + @Test + public void test_percentage_flex_basis_cross_max_width() { + YogaNode.setExperimentalFeatureEnabled(YogaExperimentalFeature.ROUNDING, true); + + final YogaNode root = new YogaNode(); + root.setWidth(200f); + root.setHeight(200f); + + final YogaNode root_child0 = new YogaNode(); + root_child0.setFlexGrow(1f); + root_child0.setFlexBasisPercent(10f); + root_child0.setMaxWidthPercent(60f); + root.addChildAt(root_child0, 0); + + final YogaNode root_child1 = new YogaNode(); + root_child1.setFlexGrow(4f); + root_child1.setFlexBasisPercent(15f); + root_child1.setMaxWidthPercent(20f); + root.addChildAt(root_child1, 1); + root.setDirection(YogaDirection.LTR); + root.calculateLayout(); + + assertEquals(0f, root.getLayoutX(), 0.0f); + assertEquals(0f, root.getLayoutY(), 0.0f); + assertEquals(200f, root.getLayoutWidth(), 0.0f); + assertEquals(200f, root.getLayoutHeight(), 0.0f); + + assertEquals(0f, root_child0.getLayoutX(), 0.0f); + assertEquals(0f, root_child0.getLayoutY(), 0.0f); + assertEquals(120f, root_child0.getLayoutWidth(), 0.0f); + assertEquals(50f, root_child0.getLayoutHeight(), 0.0f); + + assertEquals(0f, root_child1.getLayoutX(), 0.0f); + assertEquals(50f, root_child1.getLayoutY(), 0.0f); + assertEquals(40f, root_child1.getLayoutWidth(), 0.0f); + assertEquals(150f, root_child1.getLayoutHeight(), 0.0f); + + root.setDirection(YogaDirection.RTL); + root.calculateLayout(); + + assertEquals(0f, root.getLayoutX(), 0.0f); + assertEquals(0f, root.getLayoutY(), 0.0f); + assertEquals(200f, root.getLayoutWidth(), 0.0f); + assertEquals(200f, root.getLayoutHeight(), 0.0f); + + assertEquals(80f, root_child0.getLayoutX(), 0.0f); + assertEquals(0f, root_child0.getLayoutY(), 0.0f); + assertEquals(120f, root_child0.getLayoutWidth(), 0.0f); + assertEquals(50f, root_child0.getLayoutHeight(), 0.0f); + + assertEquals(160f, root_child1.getLayoutX(), 0.0f); + assertEquals(50f, root_child1.getLayoutY(), 0.0f); + assertEquals(40f, root_child1.getLayoutWidth(), 0.0f); + assertEquals(150f, root_child1.getLayoutHeight(), 0.0f); + + YogaNode.setExperimentalFeatureEnabled(YogaExperimentalFeature.ROUNDING, false); + } + + @Test + public void test_percentage_flex_basis_main_min_width() { + YogaNode.setExperimentalFeatureEnabled(YogaExperimentalFeature.ROUNDING, true); + + final YogaNode root = new YogaNode(); + root.setFlexDirection(YogaFlexDirection.ROW); + root.setWidth(200f); + root.setHeight(200f); + + final YogaNode root_child0 = new YogaNode(); + root_child0.setFlexGrow(1f); + root_child0.setFlexBasisPercent(15f); + root_child0.setMinWidthPercent(60f); + root.addChildAt(root_child0, 0); + + final YogaNode root_child1 = new YogaNode(); + root_child1.setFlexGrow(4f); + root_child1.setFlexBasisPercent(10f); + root_child1.setMinWidthPercent(20f); + root.addChildAt(root_child1, 1); + root.setDirection(YogaDirection.LTR); + root.calculateLayout(); + + assertEquals(0f, root.getLayoutX(), 0.0f); + assertEquals(0f, root.getLayoutY(), 0.0f); + assertEquals(200f, root.getLayoutWidth(), 0.0f); + assertEquals(200f, root.getLayoutHeight(), 0.0f); + + assertEquals(0f, root_child0.getLayoutX(), 0.0f); + assertEquals(0f, root_child0.getLayoutY(), 0.0f); + assertEquals(120f, root_child0.getLayoutWidth(), 0.0f); + assertEquals(200f, root_child0.getLayoutHeight(), 0.0f); + + assertEquals(120f, root_child1.getLayoutX(), 0.0f); + assertEquals(0f, root_child1.getLayoutY(), 0.0f); + assertEquals(80f, root_child1.getLayoutWidth(), 0.0f); + assertEquals(200f, root_child1.getLayoutHeight(), 0.0f); + + root.setDirection(YogaDirection.RTL); + root.calculateLayout(); + + assertEquals(0f, root.getLayoutX(), 0.0f); + assertEquals(0f, root.getLayoutY(), 0.0f); + assertEquals(200f, root.getLayoutWidth(), 0.0f); + assertEquals(200f, root.getLayoutHeight(), 0.0f); + + assertEquals(80f, root_child0.getLayoutX(), 0.0f); + assertEquals(0f, root_child0.getLayoutY(), 0.0f); + assertEquals(120f, root_child0.getLayoutWidth(), 0.0f); + assertEquals(200f, root_child0.getLayoutHeight(), 0.0f); + + assertEquals(0f, root_child1.getLayoutX(), 0.0f); + assertEquals(0f, root_child1.getLayoutY(), 0.0f); + assertEquals(80f, root_child1.getLayoutWidth(), 0.0f); + assertEquals(200f, root_child1.getLayoutHeight(), 0.0f); + + YogaNode.setExperimentalFeatureEnabled(YogaExperimentalFeature.ROUNDING, false); + } + + @Test + public void test_percentage_flex_basis_cross_min_width() { + YogaNode.setExperimentalFeatureEnabled(YogaExperimentalFeature.ROUNDING, true); + + final YogaNode root = new YogaNode(); + root.setWidth(200f); + root.setHeight(200f); + + final YogaNode root_child0 = new YogaNode(); + root_child0.setFlexGrow(1f); + root_child0.setFlexBasisPercent(10f); + root_child0.setMinWidthPercent(60f); + root.addChildAt(root_child0, 0); + + final YogaNode root_child1 = new YogaNode(); + root_child1.setFlexGrow(4f); + root_child1.setFlexBasisPercent(15f); + root_child1.setMinWidthPercent(20f); + root.addChildAt(root_child1, 1); + root.setDirection(YogaDirection.LTR); + root.calculateLayout(); + + assertEquals(0f, root.getLayoutX(), 0.0f); + assertEquals(0f, root.getLayoutY(), 0.0f); + assertEquals(200f, root.getLayoutWidth(), 0.0f); + assertEquals(200f, root.getLayoutHeight(), 0.0f); + + assertEquals(0f, root_child0.getLayoutX(), 0.0f); + assertEquals(0f, root_child0.getLayoutY(), 0.0f); + assertEquals(200f, root_child0.getLayoutWidth(), 0.0f); + assertEquals(50f, root_child0.getLayoutHeight(), 0.0f); + + assertEquals(0f, root_child1.getLayoutX(), 0.0f); + assertEquals(50f, root_child1.getLayoutY(), 0.0f); + assertEquals(200f, root_child1.getLayoutWidth(), 0.0f); + assertEquals(150f, root_child1.getLayoutHeight(), 0.0f); + + root.setDirection(YogaDirection.RTL); + root.calculateLayout(); + + assertEquals(0f, root.getLayoutX(), 0.0f); + assertEquals(0f, root.getLayoutY(), 0.0f); + assertEquals(200f, root.getLayoutWidth(), 0.0f); + assertEquals(200f, root.getLayoutHeight(), 0.0f); + + assertEquals(0f, root_child0.getLayoutX(), 0.0f); + assertEquals(0f, root_child0.getLayoutY(), 0.0f); + assertEquals(200f, root_child0.getLayoutWidth(), 0.0f); + assertEquals(50f, root_child0.getLayoutHeight(), 0.0f); + + assertEquals(0f, root_child1.getLayoutX(), 0.0f); + assertEquals(50f, root_child1.getLayoutY(), 0.0f); + assertEquals(200f, root_child1.getLayoutWidth(), 0.0f); + assertEquals(150f, root_child1.getLayoutHeight(), 0.0f); + + YogaNode.setExperimentalFeatureEnabled(YogaExperimentalFeature.ROUNDING, false); + } + + @Test + public void test_percentage_multiple_nested_with_padding_margin_and_percentage_values() { + YogaNode.setExperimentalFeatureEnabled(YogaExperimentalFeature.ROUNDING, true); + + final YogaNode root = new YogaNode(); + root.setWidth(200f); + root.setHeight(200f); + + final YogaNode root_child0 = new YogaNode(); + root_child0.setFlexGrow(1f); + root_child0.setFlexBasisPercent(10f); + root_child0.setMargin(YogaEdge.LEFT, 5f); + root_child0.setMargin(YogaEdge.TOP, 5f); + root_child0.setMargin(YogaEdge.RIGHT, 5f); + root_child0.setMargin(YogaEdge.BOTTOM, 5f); + root_child0.setPadding(YogaEdge.LEFT, 3); + root_child0.setPadding(YogaEdge.TOP, 3); + root_child0.setPadding(YogaEdge.RIGHT, 3); + root_child0.setPadding(YogaEdge.BOTTOM, 3); + root_child0.setMinWidthPercent(60f); + root.addChildAt(root_child0, 0); + + final YogaNode root_child0_child0 = new YogaNode(); + root_child0_child0.setMargin(YogaEdge.LEFT, 5f); + root_child0_child0.setMargin(YogaEdge.TOP, 5f); + root_child0_child0.setMargin(YogaEdge.RIGHT, 5f); + root_child0_child0.setMargin(YogaEdge.BOTTOM, 5f); + root_child0_child0.setPaddingPercent(YogaEdge.LEFT, 3); + root_child0_child0.setPaddingPercent(YogaEdge.TOP, 3); + root_child0_child0.setPaddingPercent(YogaEdge.RIGHT, 3); + root_child0_child0.setPaddingPercent(YogaEdge.BOTTOM, 3); + root_child0_child0.setWidthPercent(50f); + root_child0.addChildAt(root_child0_child0, 0); + + final YogaNode root_child0_child0_child0 = new YogaNode(); + root_child0_child0_child0.setMarginPercent(YogaEdge.LEFT, 5f); + root_child0_child0_child0.setMarginPercent(YogaEdge.TOP, 5f); + root_child0_child0_child0.setMarginPercent(YogaEdge.RIGHT, 5f); + root_child0_child0_child0.setMarginPercent(YogaEdge.BOTTOM, 5f); + root_child0_child0_child0.setPadding(YogaEdge.LEFT, 3); + root_child0_child0_child0.setPadding(YogaEdge.TOP, 3); + root_child0_child0_child0.setPadding(YogaEdge.RIGHT, 3); + root_child0_child0_child0.setPadding(YogaEdge.BOTTOM, 3); + root_child0_child0_child0.setWidthPercent(45f); + root_child0_child0.addChildAt(root_child0_child0_child0, 0); + + final YogaNode root_child1 = new YogaNode(); + root_child1.setFlexGrow(4f); + root_child1.setFlexBasisPercent(15f); + root_child1.setMinWidthPercent(20f); + root.addChildAt(root_child1, 1); + root.setDirection(YogaDirection.LTR); + root.calculateLayout(); + + assertEquals(0f, root.getLayoutX(), 0.0f); + assertEquals(0f, root.getLayoutY(), 0.0f); + assertEquals(200f, root.getLayoutWidth(), 0.0f); + assertEquals(200f, root.getLayoutHeight(), 0.0f); + + assertEquals(5f, root_child0.getLayoutX(), 0.0f); + assertEquals(5f, root_child0.getLayoutY(), 0.0f); + assertEquals(190f, root_child0.getLayoutWidth(), 0.0f); + assertEquals(48f, root_child0.getLayoutHeight(), 0.0f); + + assertEquals(8f, root_child0_child0.getLayoutX(), 0.0f); + assertEquals(8f, root_child0_child0.getLayoutY(), 0.0f); + assertEquals(92f, root_child0_child0.getLayoutWidth(), 0.0f); + assertEquals(25f, root_child0_child0.getLayoutHeight(), 0.0f); + + assertEquals(10f, root_child0_child0_child0.getLayoutX(), 0.0f); + assertEquals(10f, root_child0_child0_child0.getLayoutY(), 0.0f); + assertEquals(36f, root_child0_child0_child0.getLayoutWidth(), 0.0f); + assertEquals(6f, root_child0_child0_child0.getLayoutHeight(), 0.0f); + + assertEquals(0f, root_child1.getLayoutX(), 0.0f); + assertEquals(58f, root_child1.getLayoutY(), 0.0f); + assertEquals(200f, root_child1.getLayoutWidth(), 0.0f); + assertEquals(142f, root_child1.getLayoutHeight(), 0.0f); + + root.setDirection(YogaDirection.RTL); + root.calculateLayout(); + + assertEquals(0f, root.getLayoutX(), 0.0f); + assertEquals(0f, root.getLayoutY(), 0.0f); + assertEquals(200f, root.getLayoutWidth(), 0.0f); + assertEquals(200f, root.getLayoutHeight(), 0.0f); + + assertEquals(5f, root_child0.getLayoutX(), 0.0f); + assertEquals(5f, root_child0.getLayoutY(), 0.0f); + assertEquals(190f, root_child0.getLayoutWidth(), 0.0f); + assertEquals(48f, root_child0.getLayoutHeight(), 0.0f); + + assertEquals(90f, root_child0_child0.getLayoutX(), 0.0f); + assertEquals(8f, root_child0_child0.getLayoutY(), 0.0f); + assertEquals(92f, root_child0_child0.getLayoutWidth(), 0.0f); + assertEquals(25f, root_child0_child0.getLayoutHeight(), 0.0f); + + assertEquals(46f, root_child0_child0_child0.getLayoutX(), 0.0f); + assertEquals(10f, root_child0_child0_child0.getLayoutY(), 0.0f); + assertEquals(36f, root_child0_child0_child0.getLayoutWidth(), 0.0f); + assertEquals(6f, root_child0_child0_child0.getLayoutHeight(), 0.0f); + + assertEquals(0f, root_child1.getLayoutX(), 0.0f); + assertEquals(58f, root_child1.getLayoutY(), 0.0f); + assertEquals(200f, root_child1.getLayoutWidth(), 0.0f); + assertEquals(142f, root_child1.getLayoutHeight(), 0.0f); + + YogaNode.setExperimentalFeatureEnabled(YogaExperimentalFeature.ROUNDING, false); + } + + @Test + public void test_percentage_margin_should_calculate_based_only_on_width() { + YogaNode.setExperimentalFeatureEnabled(YogaExperimentalFeature.ROUNDING, true); + + final YogaNode root = new YogaNode(); + root.setWidth(200f); + root.setHeight(100f); + + final YogaNode root_child0 = new YogaNode(); + root_child0.setFlexGrow(1f); + root_child0.setMarginPercent(YogaEdge.LEFT, 10f); + root_child0.setMarginPercent(YogaEdge.TOP, 10f); + root_child0.setMarginPercent(YogaEdge.RIGHT, 10f); + root_child0.setMarginPercent(YogaEdge.BOTTOM, 10f); + root.addChildAt(root_child0, 0); + + final YogaNode root_child0_child0 = new YogaNode(); + root_child0_child0.setWidth(10f); + root_child0_child0.setHeight(10f); + root_child0.addChildAt(root_child0_child0, 0); + root.setDirection(YogaDirection.LTR); + root.calculateLayout(); + + assertEquals(0f, root.getLayoutX(), 0.0f); + assertEquals(0f, root.getLayoutY(), 0.0f); + assertEquals(200f, root.getLayoutWidth(), 0.0f); + assertEquals(100f, root.getLayoutHeight(), 0.0f); + + assertEquals(20f, root_child0.getLayoutX(), 0.0f); + assertEquals(20f, root_child0.getLayoutY(), 0.0f); + assertEquals(160f, root_child0.getLayoutWidth(), 0.0f); + assertEquals(60f, root_child0.getLayoutHeight(), 0.0f); + + assertEquals(0f, root_child0_child0.getLayoutX(), 0.0f); + assertEquals(0f, root_child0_child0.getLayoutY(), 0.0f); + assertEquals(10f, root_child0_child0.getLayoutWidth(), 0.0f); + assertEquals(10f, root_child0_child0.getLayoutHeight(), 0.0f); + + root.setDirection(YogaDirection.RTL); + root.calculateLayout(); + + assertEquals(0f, root.getLayoutX(), 0.0f); + assertEquals(0f, root.getLayoutY(), 0.0f); + assertEquals(200f, root.getLayoutWidth(), 0.0f); + assertEquals(100f, root.getLayoutHeight(), 0.0f); + + assertEquals(20f, root_child0.getLayoutX(), 0.0f); + assertEquals(20f, root_child0.getLayoutY(), 0.0f); + assertEquals(160f, root_child0.getLayoutWidth(), 0.0f); + assertEquals(60f, root_child0.getLayoutHeight(), 0.0f); + + assertEquals(150f, root_child0_child0.getLayoutX(), 0.0f); + assertEquals(0f, root_child0_child0.getLayoutY(), 0.0f); + assertEquals(10f, root_child0_child0.getLayoutWidth(), 0.0f); + assertEquals(10f, root_child0_child0.getLayoutHeight(), 0.0f); + + YogaNode.setExperimentalFeatureEnabled(YogaExperimentalFeature.ROUNDING, false); + } + + @Test + public void test_percentage_padding_should_calculate_based_only_on_width() { + YogaNode.setExperimentalFeatureEnabled(YogaExperimentalFeature.ROUNDING, true); + + final YogaNode root = new YogaNode(); + root.setWidth(200f); + root.setHeight(100f); + + final YogaNode root_child0 = new YogaNode(); + root_child0.setFlexGrow(1f); + root_child0.setPaddingPercent(YogaEdge.LEFT, 10); + root_child0.setPaddingPercent(YogaEdge.TOP, 10); + root_child0.setPaddingPercent(YogaEdge.RIGHT, 10); + root_child0.setPaddingPercent(YogaEdge.BOTTOM, 10); + root.addChildAt(root_child0, 0); + + final YogaNode root_child0_child0 = new YogaNode(); + root_child0_child0.setWidth(10f); + root_child0_child0.setHeight(10f); + root_child0.addChildAt(root_child0_child0, 0); + root.setDirection(YogaDirection.LTR); + root.calculateLayout(); + + assertEquals(0f, root.getLayoutX(), 0.0f); + assertEquals(0f, root.getLayoutY(), 0.0f); + assertEquals(200f, root.getLayoutWidth(), 0.0f); + assertEquals(100f, root.getLayoutHeight(), 0.0f); + + assertEquals(0f, root_child0.getLayoutX(), 0.0f); + assertEquals(0f, root_child0.getLayoutY(), 0.0f); + assertEquals(200f, root_child0.getLayoutWidth(), 0.0f); + assertEquals(100f, root_child0.getLayoutHeight(), 0.0f); + + assertEquals(20f, root_child0_child0.getLayoutX(), 0.0f); + assertEquals(20f, root_child0_child0.getLayoutY(), 0.0f); + assertEquals(10f, root_child0_child0.getLayoutWidth(), 0.0f); + assertEquals(10f, root_child0_child0.getLayoutHeight(), 0.0f); + + root.setDirection(YogaDirection.RTL); + root.calculateLayout(); + + assertEquals(0f, root.getLayoutX(), 0.0f); + assertEquals(0f, root.getLayoutY(), 0.0f); + assertEquals(200f, root.getLayoutWidth(), 0.0f); + assertEquals(100f, root.getLayoutHeight(), 0.0f); + + assertEquals(0f, root_child0.getLayoutX(), 0.0f); + assertEquals(0f, root_child0.getLayoutY(), 0.0f); + assertEquals(200f, root_child0.getLayoutWidth(), 0.0f); + assertEquals(100f, root_child0.getLayoutHeight(), 0.0f); + + assertEquals(170f, root_child0_child0.getLayoutX(), 0.0f); + assertEquals(20f, root_child0_child0.getLayoutY(), 0.0f); + assertEquals(10f, root_child0_child0.getLayoutWidth(), 0.0f); + assertEquals(10f, root_child0_child0.getLayoutHeight(), 0.0f); + + YogaNode.setExperimentalFeatureEnabled(YogaExperimentalFeature.ROUNDING, false); + } + + @Test + public void test_percentage_absolute_position() { + YogaNode.setExperimentalFeatureEnabled(YogaExperimentalFeature.ROUNDING, true); + + final YogaNode root = new YogaNode(); + root.setWidth(200f); + root.setHeight(100f); + + final YogaNode root_child0 = new YogaNode(); + root_child0.setPositionType(YogaPositionType.ABSOLUTE); + root_child0.setPositionPercent(YogaEdge.LEFT, 30f); + root_child0.setPositionPercent(YogaEdge.TOP, 10f); + root_child0.setWidth(10f); + root_child0.setHeight(10f); + root.addChildAt(root_child0, 0); + root.setDirection(YogaDirection.LTR); + root.calculateLayout(); + + assertEquals(0f, root.getLayoutX(), 0.0f); + assertEquals(0f, root.getLayoutY(), 0.0f); + assertEquals(200f, root.getLayoutWidth(), 0.0f); + assertEquals(100f, root.getLayoutHeight(), 0.0f); + + assertEquals(60f, root_child0.getLayoutX(), 0.0f); + assertEquals(10f, root_child0.getLayoutY(), 0.0f); + assertEquals(10f, root_child0.getLayoutWidth(), 0.0f); + assertEquals(10f, root_child0.getLayoutHeight(), 0.0f); + + root.setDirection(YogaDirection.RTL); + root.calculateLayout(); + + assertEquals(0f, root.getLayoutX(), 0.0f); + assertEquals(0f, root.getLayoutY(), 0.0f); + assertEquals(200f, root.getLayoutWidth(), 0.0f); + assertEquals(100f, root.getLayoutHeight(), 0.0f); + + assertEquals(60f, root_child0.getLayoutX(), 0.0f); + assertEquals(10f, root_child0.getLayoutY(), 0.0f); + assertEquals(10f, root_child0.getLayoutWidth(), 0.0f); + assertEquals(10f, root_child0.getLayoutHeight(), 0.0f); + + YogaNode.setExperimentalFeatureEnabled(YogaExperimentalFeature.ROUNDING, false); + } + +} diff --git a/java/tests/com/facebook/yoga/YogaNodeTest.java b/java/tests/com/facebook/yoga/YogaNodeTest.java index cfa0dcd5..2e7a9e7a 100644 --- a/java/tests/com/facebook/yoga/YogaNodeTest.java +++ b/java/tests/com/facebook/yoga/YogaNodeTest.java @@ -136,6 +136,6 @@ public class YogaNodeTest { node1.setMaxHeight(100); node0.copyStyle(node1); - assertEquals(100, (int) node0.getMaxHeight()); + assertEquals(100, (int) node0.getMaxHeight().value); } } diff --git a/tests/YGDefaultValuesTest.cpp b/tests/YGDefaultValuesTest.cpp index 044059b5..b553a011 100644 --- a/tests/YGDefaultValuesTest.cpp +++ b/tests/YGDefaultValuesTest.cpp @@ -27,49 +27,49 @@ TEST(YogaTest, assert_default_values) { ASSERT_EQ(YGOverflowVisible, YGNodeStyleGetOverflow(root)); ASSERT_FLOAT_EQ(0, YGNodeStyleGetFlexGrow(root)); ASSERT_FLOAT_EQ(0, YGNodeStyleGetFlexShrink(root)); - ASSERT_TRUE(YGValueIsUndefined(YGNodeStyleGetFlexBasis(root))); + ASSERT_FALSE(YGNodeStyleGetFlexBasis(root).unit != YGUnitUndefined); - ASSERT_TRUE(YGValueIsUndefined(YGNodeStyleGetPosition(root, YGEdgeLeft))); - ASSERT_TRUE(YGValueIsUndefined(YGNodeStyleGetPosition(root, YGEdgeTop))); - ASSERT_TRUE(YGValueIsUndefined(YGNodeStyleGetPosition(root, YGEdgeRight))); - ASSERT_TRUE(YGValueIsUndefined(YGNodeStyleGetPosition(root, YGEdgeBottom))); - ASSERT_TRUE(YGValueIsUndefined(YGNodeStyleGetPosition(root, YGEdgeStart))); - ASSERT_TRUE(YGValueIsUndefined(YGNodeStyleGetPosition(root, YGEdgeEnd))); + ASSERT_FALSE(YGNodeStyleGetPosition(root, YGEdgeLeft).unit != YGUnitUndefined); + ASSERT_FALSE(YGNodeStyleGetPosition(root, YGEdgeTop).unit != YGUnitUndefined); + ASSERT_FALSE(YGNodeStyleGetPosition(root, YGEdgeRight).unit != YGUnitUndefined); + ASSERT_FALSE(YGNodeStyleGetPosition(root, YGEdgeBottom).unit != YGUnitUndefined); + ASSERT_FALSE(YGNodeStyleGetPosition(root, YGEdgeStart).unit != YGUnitUndefined); + ASSERT_FALSE(YGNodeStyleGetPosition(root, YGEdgeEnd).unit != YGUnitUndefined); - ASSERT_FLOAT_EQ(0, YGNodeStyleGetMargin(root, YGEdgeLeft)); - ASSERT_FLOAT_EQ(0, YGNodeStyleGetMargin(root, YGEdgeTop)); - ASSERT_FLOAT_EQ(0, YGNodeStyleGetMargin(root, YGEdgeRight)); - ASSERT_FLOAT_EQ(0, YGNodeStyleGetMargin(root, YGEdgeBottom)); - ASSERT_TRUE(YGValueIsUndefined(YGNodeStyleGetMargin(root, YGEdgeStart))); - ASSERT_TRUE(YGValueIsUndefined(YGNodeStyleGetMargin(root, YGEdgeEnd))); + ASSERT_FLOAT_EQ(0, YGNodeStyleGetMargin(root, YGEdgeLeft).value); + ASSERT_FLOAT_EQ(0, YGNodeStyleGetMargin(root, YGEdgeTop).value); + ASSERT_FLOAT_EQ(0, YGNodeStyleGetMargin(root, YGEdgeRight).value); + ASSERT_FLOAT_EQ(0, YGNodeStyleGetMargin(root, YGEdgeBottom).value); + ASSERT_FALSE(YGNodeStyleGetMargin(root, YGEdgeStart).unit != YGUnitUndefined); + ASSERT_FALSE(YGNodeStyleGetMargin(root, YGEdgeEnd).unit != YGUnitUndefined); - ASSERT_FLOAT_EQ(0, YGNodeStyleGetPadding(root, YGEdgeLeft)); - ASSERT_FLOAT_EQ(0, YGNodeStyleGetPadding(root, YGEdgeTop)); - ASSERT_FLOAT_EQ(0, YGNodeStyleGetPadding(root, YGEdgeRight)); - ASSERT_FLOAT_EQ(0, YGNodeStyleGetPadding(root, YGEdgeBottom)); - ASSERT_TRUE(YGValueIsUndefined(YGNodeStyleGetPadding(root, YGEdgeStart))); - ASSERT_TRUE(YGValueIsUndefined(YGNodeStyleGetPadding(root, YGEdgeEnd))); + ASSERT_FLOAT_EQ(0, YGNodeStyleGetPadding(root, YGEdgeLeft).value); + ASSERT_FLOAT_EQ(0, YGNodeStyleGetPadding(root, YGEdgeTop).value); + ASSERT_FLOAT_EQ(0, YGNodeStyleGetPadding(root, YGEdgeRight).value); + ASSERT_FLOAT_EQ(0, YGNodeStyleGetPadding(root, YGEdgeBottom).value); + ASSERT_FALSE(YGNodeStyleGetPadding(root, YGEdgeStart).unit != YGUnitUndefined); + ASSERT_FALSE(YGNodeStyleGetPadding(root, YGEdgeEnd).unit != YGUnitUndefined); ASSERT_FLOAT_EQ(0, YGNodeStyleGetBorder(root, YGEdgeLeft)); ASSERT_FLOAT_EQ(0, YGNodeStyleGetBorder(root, YGEdgeTop)); ASSERT_FLOAT_EQ(0, YGNodeStyleGetBorder(root, YGEdgeRight)); ASSERT_FLOAT_EQ(0, YGNodeStyleGetBorder(root, YGEdgeBottom)); - ASSERT_TRUE(YGValueIsUndefined(YGNodeStyleGetBorder(root, YGEdgeStart))); - ASSERT_TRUE(YGValueIsUndefined(YGNodeStyleGetBorder(root, YGEdgeEnd))); + ASSERT_TRUE(YGFloatIsUndefined(YGNodeStyleGetBorder(root, YGEdgeStart))); + ASSERT_TRUE(YGFloatIsUndefined(YGNodeStyleGetBorder(root, YGEdgeEnd))); - ASSERT_TRUE(YGValueIsUndefined(YGNodeStyleGetWidth(root))); - ASSERT_TRUE(YGValueIsUndefined(YGNodeStyleGetHeight(root))); - ASSERT_TRUE(YGValueIsUndefined(YGNodeStyleGetMinWidth(root))); - ASSERT_TRUE(YGValueIsUndefined(YGNodeStyleGetMinHeight(root))); - ASSERT_TRUE(YGValueIsUndefined(YGNodeStyleGetMaxWidth(root))); - ASSERT_TRUE(YGValueIsUndefined(YGNodeStyleGetMaxHeight(root))); + ASSERT_FALSE(YGNodeStyleGetWidth(root).unit != YGUnitUndefined); + ASSERT_FALSE(YGNodeStyleGetHeight(root).unit != YGUnitUndefined); + ASSERT_FALSE(YGNodeStyleGetMinWidth(root).unit != YGUnitUndefined); + ASSERT_FALSE(YGNodeStyleGetMinHeight(root).unit != YGUnitUndefined); + ASSERT_FALSE(YGNodeStyleGetMaxWidth(root).unit != YGUnitUndefined); + ASSERT_FALSE(YGNodeStyleGetMaxHeight(root).unit != YGUnitUndefined); ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root)); ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root)); ASSERT_FLOAT_EQ(0, YGNodeLayoutGetRight(root)); ASSERT_FLOAT_EQ(0, YGNodeLayoutGetBottom(root)); - ASSERT_TRUE(YGValueIsUndefined(YGNodeLayoutGetWidth(root))); - ASSERT_TRUE(YGValueIsUndefined(YGNodeLayoutGetHeight(root))); + ASSERT_TRUE(YGFloatIsUndefined(YGNodeLayoutGetWidth(root))); + ASSERT_TRUE(YGFloatIsUndefined(YGNodeLayoutGetHeight(root))); ASSERT_EQ(YGDirectionInherit, YGNodeLayoutGetDirection(root)); YGNodeFreeRecursive(root); diff --git a/tests/YGMeasureModeTest.cpp b/tests/YGMeasureModeTest.cpp index 730247fa..cd5aedba 100644 --- a/tests/YGMeasureModeTest.cpp +++ b/tests/YGMeasureModeTest.cpp @@ -283,7 +283,7 @@ TEST(YogaTest, overflow_scroll_column) { ASSERT_FLOAT_EQ(100, constraintList.constraints[0].width); ASSERT_EQ(YGMeasureModeAtMost, constraintList.constraints[0].widthMode); - ASSERT_TRUE(YGValueIsUndefined(constraintList.constraints[0].height)); + ASSERT_TRUE(YGFloatIsUndefined(constraintList.constraints[0].height)); ASSERT_EQ(YGMeasureModeUndefined, constraintList.constraints[0].heightMode); free(constraintList.constraints); @@ -312,7 +312,7 @@ TEST(YogaTest, overflow_scroll_row) { ASSERT_EQ(1, constraintList.length); - ASSERT_TRUE(YGValueIsUndefined(constraintList.constraints[0].width)); + ASSERT_TRUE(YGFloatIsUndefined(constraintList.constraints[0].width)); ASSERT_EQ(YGMeasureModeUndefined, constraintList.constraints[0].widthMode); ASSERT_FLOAT_EQ(100, constraintList.constraints[0].height); diff --git a/tests/YGPercentageTest.cpp b/tests/YGPercentageTest.cpp new file mode 100644 index 00000000..80d2f4f7 --- /dev/null +++ b/tests/YGPercentageTest.cpp @@ -0,0 +1,919 @@ +/** + * 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. + */ + + // @Generated by gentest/gentest.rb from gentest/fixtures/YGPercentageTest.html + +#include +#include + +TEST(YogaTest, percentage_width_height) { + YGSetExperimentalFeatureEnabled(YGExperimentalFeatureRounding, true); + + const YGNodeRef root = YGNodeNew(); + YGNodeStyleSetFlexDirection(root, YGFlexDirectionRow); + YGNodeStyleSetWidth(root, 200); + YGNodeStyleSetHeight(root, 200); + + const YGNodeRef root_child0 = YGNodeNew(); + YGNodeStyleSetWidthPercent(root_child0, 30); + YGNodeStyleSetHeightPercent(root_child0, 30); + YGNodeInsertChild(root, root_child0, 0); + YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR); + + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root)); + ASSERT_FLOAT_EQ(200, YGNodeLayoutGetWidth(root)); + ASSERT_FLOAT_EQ(200, YGNodeLayoutGetHeight(root)); + + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0)); + ASSERT_FLOAT_EQ(60, YGNodeLayoutGetWidth(root_child0)); + ASSERT_FLOAT_EQ(60, YGNodeLayoutGetHeight(root_child0)); + + YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL); + + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root)); + ASSERT_FLOAT_EQ(200, YGNodeLayoutGetWidth(root)); + ASSERT_FLOAT_EQ(200, YGNodeLayoutGetHeight(root)); + + ASSERT_FLOAT_EQ(140, YGNodeLayoutGetLeft(root_child0)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0)); + ASSERT_FLOAT_EQ(60, YGNodeLayoutGetWidth(root_child0)); + ASSERT_FLOAT_EQ(60, YGNodeLayoutGetHeight(root_child0)); + + YGNodeFreeRecursive(root); + + YGSetExperimentalFeatureEnabled(YGExperimentalFeatureRounding, false); +} + +TEST(YogaTest, percentage_position_left_top) { + YGSetExperimentalFeatureEnabled(YGExperimentalFeatureRounding, true); + + const YGNodeRef root = YGNodeNew(); + YGNodeStyleSetFlexDirection(root, YGFlexDirectionRow); + YGNodeStyleSetWidth(root, 400); + YGNodeStyleSetHeight(root, 400); + + const YGNodeRef root_child0 = YGNodeNew(); + YGNodeStyleSetPositionPercent(root_child0, YGEdgeLeft, 10); + YGNodeStyleSetPositionPercent(root_child0, YGEdgeTop, 20); + YGNodeStyleSetWidthPercent(root_child0, 45); + YGNodeStyleSetHeightPercent(root_child0, 55); + YGNodeInsertChild(root, root_child0, 0); + YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR); + + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root)); + ASSERT_FLOAT_EQ(400, YGNodeLayoutGetWidth(root)); + ASSERT_FLOAT_EQ(400, YGNodeLayoutGetHeight(root)); + + ASSERT_FLOAT_EQ(40, YGNodeLayoutGetLeft(root_child0)); + ASSERT_FLOAT_EQ(80, YGNodeLayoutGetTop(root_child0)); + ASSERT_FLOAT_EQ(180, YGNodeLayoutGetWidth(root_child0)); + ASSERT_FLOAT_EQ(220, YGNodeLayoutGetHeight(root_child0)); + + YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL); + + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root)); + ASSERT_FLOAT_EQ(400, YGNodeLayoutGetWidth(root)); + ASSERT_FLOAT_EQ(400, YGNodeLayoutGetHeight(root)); + + ASSERT_FLOAT_EQ(260, YGNodeLayoutGetLeft(root_child0)); + ASSERT_FLOAT_EQ(80, YGNodeLayoutGetTop(root_child0)); + ASSERT_FLOAT_EQ(180, YGNodeLayoutGetWidth(root_child0)); + ASSERT_FLOAT_EQ(220, YGNodeLayoutGetHeight(root_child0)); + + YGNodeFreeRecursive(root); + + YGSetExperimentalFeatureEnabled(YGExperimentalFeatureRounding, false); +} + +TEST(YogaTest, percentage_position_bottom_right) { + YGSetExperimentalFeatureEnabled(YGExperimentalFeatureRounding, true); + + const YGNodeRef root = YGNodeNew(); + YGNodeStyleSetFlexDirection(root, YGFlexDirectionRow); + YGNodeStyleSetWidth(root, 500); + YGNodeStyleSetHeight(root, 500); + + const YGNodeRef root_child0 = YGNodeNew(); + YGNodeStyleSetPositionPercent(root_child0, YGEdgeRight, 20); + YGNodeStyleSetPositionPercent(root_child0, YGEdgeBottom, 10); + YGNodeStyleSetWidthPercent(root_child0, 55); + YGNodeStyleSetHeightPercent(root_child0, 15); + YGNodeInsertChild(root, root_child0, 0); + YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR); + + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root)); + ASSERT_FLOAT_EQ(500, YGNodeLayoutGetWidth(root)); + ASSERT_FLOAT_EQ(500, YGNodeLayoutGetHeight(root)); + + ASSERT_FLOAT_EQ(-100, YGNodeLayoutGetLeft(root_child0)); + ASSERT_FLOAT_EQ(-50, YGNodeLayoutGetTop(root_child0)); + ASSERT_FLOAT_EQ(275, YGNodeLayoutGetWidth(root_child0)); + ASSERT_FLOAT_EQ(75, YGNodeLayoutGetHeight(root_child0)); + + YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL); + + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root)); + ASSERT_FLOAT_EQ(500, YGNodeLayoutGetWidth(root)); + ASSERT_FLOAT_EQ(500, YGNodeLayoutGetHeight(root)); + + ASSERT_FLOAT_EQ(125, YGNodeLayoutGetLeft(root_child0)); + ASSERT_FLOAT_EQ(-50, YGNodeLayoutGetTop(root_child0)); + ASSERT_FLOAT_EQ(275, YGNodeLayoutGetWidth(root_child0)); + ASSERT_FLOAT_EQ(75, YGNodeLayoutGetHeight(root_child0)); + + YGNodeFreeRecursive(root); + + YGSetExperimentalFeatureEnabled(YGExperimentalFeatureRounding, false); +} + +TEST(YogaTest, percentage_flex_basis) { + YGSetExperimentalFeatureEnabled(YGExperimentalFeatureRounding, true); + + const YGNodeRef root = YGNodeNew(); + YGNodeStyleSetFlexDirection(root, YGFlexDirectionRow); + YGNodeStyleSetWidth(root, 200); + YGNodeStyleSetHeight(root, 200); + + const YGNodeRef root_child0 = YGNodeNew(); + YGNodeStyleSetFlexGrow(root_child0, 1); + YGNodeStyleSetFlexBasisPercent(root_child0, 50); + YGNodeInsertChild(root, root_child0, 0); + + const YGNodeRef root_child1 = YGNodeNew(); + YGNodeStyleSetFlexGrow(root_child1, 1); + YGNodeStyleSetFlexBasisPercent(root_child1, 25); + YGNodeInsertChild(root, root_child1, 1); + YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR); + + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root)); + ASSERT_FLOAT_EQ(200, YGNodeLayoutGetWidth(root)); + ASSERT_FLOAT_EQ(200, YGNodeLayoutGetHeight(root)); + + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0)); + ASSERT_FLOAT_EQ(125, YGNodeLayoutGetWidth(root_child0)); + ASSERT_FLOAT_EQ(200, YGNodeLayoutGetHeight(root_child0)); + + ASSERT_FLOAT_EQ(125, YGNodeLayoutGetLeft(root_child1)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child1)); + ASSERT_FLOAT_EQ(75, YGNodeLayoutGetWidth(root_child1)); + ASSERT_FLOAT_EQ(200, YGNodeLayoutGetHeight(root_child1)); + + YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL); + + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root)); + ASSERT_FLOAT_EQ(200, YGNodeLayoutGetWidth(root)); + ASSERT_FLOAT_EQ(200, YGNodeLayoutGetHeight(root)); + + ASSERT_FLOAT_EQ(75, YGNodeLayoutGetLeft(root_child0)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0)); + ASSERT_FLOAT_EQ(125, YGNodeLayoutGetWidth(root_child0)); + ASSERT_FLOAT_EQ(200, YGNodeLayoutGetHeight(root_child0)); + + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child1)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child1)); + ASSERT_FLOAT_EQ(75, YGNodeLayoutGetWidth(root_child1)); + ASSERT_FLOAT_EQ(200, YGNodeLayoutGetHeight(root_child1)); + + YGNodeFreeRecursive(root); + + YGSetExperimentalFeatureEnabled(YGExperimentalFeatureRounding, false); +} + +TEST(YogaTest, percentage_flex_basis_cross) { + YGSetExperimentalFeatureEnabled(YGExperimentalFeatureRounding, true); + + const YGNodeRef root = YGNodeNew(); + YGNodeStyleSetWidth(root, 200); + YGNodeStyleSetHeight(root, 200); + + const YGNodeRef root_child0 = YGNodeNew(); + YGNodeStyleSetFlexGrow(root_child0, 1); + YGNodeStyleSetFlexBasisPercent(root_child0, 50); + YGNodeInsertChild(root, root_child0, 0); + + const YGNodeRef root_child1 = YGNodeNew(); + YGNodeStyleSetFlexGrow(root_child1, 1); + YGNodeStyleSetFlexBasisPercent(root_child1, 25); + YGNodeInsertChild(root, root_child1, 1); + YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR); + + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root)); + ASSERT_FLOAT_EQ(200, YGNodeLayoutGetWidth(root)); + ASSERT_FLOAT_EQ(200, YGNodeLayoutGetHeight(root)); + + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0)); + ASSERT_FLOAT_EQ(200, YGNodeLayoutGetWidth(root_child0)); + ASSERT_FLOAT_EQ(125, YGNodeLayoutGetHeight(root_child0)); + + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child1)); + ASSERT_FLOAT_EQ(125, YGNodeLayoutGetTop(root_child1)); + ASSERT_FLOAT_EQ(200, YGNodeLayoutGetWidth(root_child1)); + ASSERT_FLOAT_EQ(75, YGNodeLayoutGetHeight(root_child1)); + + YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL); + + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root)); + ASSERT_FLOAT_EQ(200, YGNodeLayoutGetWidth(root)); + ASSERT_FLOAT_EQ(200, YGNodeLayoutGetHeight(root)); + + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0)); + ASSERT_FLOAT_EQ(200, YGNodeLayoutGetWidth(root_child0)); + ASSERT_FLOAT_EQ(125, YGNodeLayoutGetHeight(root_child0)); + + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child1)); + ASSERT_FLOAT_EQ(125, YGNodeLayoutGetTop(root_child1)); + ASSERT_FLOAT_EQ(200, YGNodeLayoutGetWidth(root_child1)); + ASSERT_FLOAT_EQ(75, YGNodeLayoutGetHeight(root_child1)); + + YGNodeFreeRecursive(root); + + YGSetExperimentalFeatureEnabled(YGExperimentalFeatureRounding, false); +} + +TEST(YogaTest, percentage_flex_basis_cross_min_height) { + YGSetExperimentalFeatureEnabled(YGExperimentalFeatureRounding, true); + + const YGNodeRef root = YGNodeNew(); + YGNodeStyleSetWidth(root, 200); + YGNodeStyleSetHeight(root, 200); + + const YGNodeRef root_child0 = YGNodeNew(); + YGNodeStyleSetFlexGrow(root_child0, 1); + YGNodeStyleSetMinHeightPercent(root_child0, 60); + YGNodeInsertChild(root, root_child0, 0); + + const YGNodeRef root_child1 = YGNodeNew(); + YGNodeStyleSetFlexGrow(root_child1, 2); + YGNodeStyleSetMinHeightPercent(root_child1, 10); + YGNodeInsertChild(root, root_child1, 1); + YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR); + + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root)); + ASSERT_FLOAT_EQ(200, YGNodeLayoutGetWidth(root)); + ASSERT_FLOAT_EQ(200, YGNodeLayoutGetHeight(root)); + + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0)); + ASSERT_FLOAT_EQ(200, YGNodeLayoutGetWidth(root_child0)); + ASSERT_FLOAT_EQ(140, YGNodeLayoutGetHeight(root_child0)); + + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child1)); + ASSERT_FLOAT_EQ(140, YGNodeLayoutGetTop(root_child1)); + ASSERT_FLOAT_EQ(200, YGNodeLayoutGetWidth(root_child1)); + ASSERT_FLOAT_EQ(60, YGNodeLayoutGetHeight(root_child1)); + + YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL); + + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root)); + ASSERT_FLOAT_EQ(200, YGNodeLayoutGetWidth(root)); + ASSERT_FLOAT_EQ(200, YGNodeLayoutGetHeight(root)); + + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0)); + ASSERT_FLOAT_EQ(200, YGNodeLayoutGetWidth(root_child0)); + ASSERT_FLOAT_EQ(140, YGNodeLayoutGetHeight(root_child0)); + + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child1)); + ASSERT_FLOAT_EQ(140, YGNodeLayoutGetTop(root_child1)); + ASSERT_FLOAT_EQ(200, YGNodeLayoutGetWidth(root_child1)); + ASSERT_FLOAT_EQ(60, YGNodeLayoutGetHeight(root_child1)); + + YGNodeFreeRecursive(root); + + YGSetExperimentalFeatureEnabled(YGExperimentalFeatureRounding, false); +} + +TEST(YogaTest, percentage_flex_basis_main_max_height) { + YGSetExperimentalFeatureEnabled(YGExperimentalFeatureRounding, true); + + const YGNodeRef root = YGNodeNew(); + YGNodeStyleSetFlexDirection(root, YGFlexDirectionRow); + YGNodeStyleSetWidth(root, 200); + YGNodeStyleSetHeight(root, 200); + + const YGNodeRef root_child0 = YGNodeNew(); + YGNodeStyleSetFlexGrow(root_child0, 1); + YGNodeStyleSetFlexBasisPercent(root_child0, 10); + YGNodeStyleSetMaxHeightPercent(root_child0, 60); + YGNodeInsertChild(root, root_child0, 0); + + const YGNodeRef root_child1 = YGNodeNew(); + YGNodeStyleSetFlexGrow(root_child1, 4); + YGNodeStyleSetFlexBasisPercent(root_child1, 10); + YGNodeStyleSetMaxHeightPercent(root_child1, 20); + YGNodeInsertChild(root, root_child1, 1); + YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR); + + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root)); + ASSERT_FLOAT_EQ(200, YGNodeLayoutGetWidth(root)); + ASSERT_FLOAT_EQ(200, YGNodeLayoutGetHeight(root)); + + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0)); + ASSERT_FLOAT_EQ(52, YGNodeLayoutGetWidth(root_child0)); + ASSERT_FLOAT_EQ(120, YGNodeLayoutGetHeight(root_child0)); + + ASSERT_FLOAT_EQ(52, YGNodeLayoutGetLeft(root_child1)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child1)); + ASSERT_FLOAT_EQ(148, YGNodeLayoutGetWidth(root_child1)); + ASSERT_FLOAT_EQ(40, YGNodeLayoutGetHeight(root_child1)); + + YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL); + + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root)); + ASSERT_FLOAT_EQ(200, YGNodeLayoutGetWidth(root)); + ASSERT_FLOAT_EQ(200, YGNodeLayoutGetHeight(root)); + + ASSERT_FLOAT_EQ(148, YGNodeLayoutGetLeft(root_child0)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0)); + ASSERT_FLOAT_EQ(52, YGNodeLayoutGetWidth(root_child0)); + ASSERT_FLOAT_EQ(120, YGNodeLayoutGetHeight(root_child0)); + + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child1)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child1)); + ASSERT_FLOAT_EQ(148, YGNodeLayoutGetWidth(root_child1)); + ASSERT_FLOAT_EQ(40, YGNodeLayoutGetHeight(root_child1)); + + YGNodeFreeRecursive(root); + + YGSetExperimentalFeatureEnabled(YGExperimentalFeatureRounding, false); +} + +TEST(YogaTest, percentage_flex_basis_cross_max_height) { + YGSetExperimentalFeatureEnabled(YGExperimentalFeatureRounding, true); + + const YGNodeRef root = YGNodeNew(); + YGNodeStyleSetWidth(root, 200); + YGNodeStyleSetHeight(root, 200); + + const YGNodeRef root_child0 = YGNodeNew(); + YGNodeStyleSetFlexGrow(root_child0, 1); + YGNodeStyleSetFlexBasisPercent(root_child0, 10); + YGNodeStyleSetMaxHeightPercent(root_child0, 60); + YGNodeInsertChild(root, root_child0, 0); + + const YGNodeRef root_child1 = YGNodeNew(); + YGNodeStyleSetFlexGrow(root_child1, 4); + YGNodeStyleSetFlexBasisPercent(root_child1, 10); + YGNodeStyleSetMaxHeightPercent(root_child1, 20); + YGNodeInsertChild(root, root_child1, 1); + YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR); + + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root)); + ASSERT_FLOAT_EQ(200, YGNodeLayoutGetWidth(root)); + ASSERT_FLOAT_EQ(200, YGNodeLayoutGetHeight(root)); + + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0)); + ASSERT_FLOAT_EQ(200, YGNodeLayoutGetWidth(root_child0)); + ASSERT_FLOAT_EQ(120, YGNodeLayoutGetHeight(root_child0)); + + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child1)); + ASSERT_FLOAT_EQ(120, YGNodeLayoutGetTop(root_child1)); + ASSERT_FLOAT_EQ(200, YGNodeLayoutGetWidth(root_child1)); + ASSERT_FLOAT_EQ(40, YGNodeLayoutGetHeight(root_child1)); + + YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL); + + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root)); + ASSERT_FLOAT_EQ(200, YGNodeLayoutGetWidth(root)); + ASSERT_FLOAT_EQ(200, YGNodeLayoutGetHeight(root)); + + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0)); + ASSERT_FLOAT_EQ(200, YGNodeLayoutGetWidth(root_child0)); + ASSERT_FLOAT_EQ(120, YGNodeLayoutGetHeight(root_child0)); + + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child1)); + ASSERT_FLOAT_EQ(120, YGNodeLayoutGetTop(root_child1)); + ASSERT_FLOAT_EQ(200, YGNodeLayoutGetWidth(root_child1)); + ASSERT_FLOAT_EQ(40, YGNodeLayoutGetHeight(root_child1)); + + YGNodeFreeRecursive(root); + + YGSetExperimentalFeatureEnabled(YGExperimentalFeatureRounding, false); +} + +TEST(YogaTest, percentage_flex_basis_main_max_width) { + YGSetExperimentalFeatureEnabled(YGExperimentalFeatureRounding, true); + + const YGNodeRef root = YGNodeNew(); + YGNodeStyleSetFlexDirection(root, YGFlexDirectionRow); + YGNodeStyleSetWidth(root, 200); + YGNodeStyleSetHeight(root, 200); + + const YGNodeRef root_child0 = YGNodeNew(); + YGNodeStyleSetFlexGrow(root_child0, 1); + YGNodeStyleSetFlexBasisPercent(root_child0, 15); + YGNodeStyleSetMaxWidthPercent(root_child0, 60); + YGNodeInsertChild(root, root_child0, 0); + + const YGNodeRef root_child1 = YGNodeNew(); + YGNodeStyleSetFlexGrow(root_child1, 4); + YGNodeStyleSetFlexBasisPercent(root_child1, 10); + YGNodeStyleSetMaxWidthPercent(root_child1, 20); + YGNodeInsertChild(root, root_child1, 1); + YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR); + + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root)); + ASSERT_FLOAT_EQ(200, YGNodeLayoutGetWidth(root)); + ASSERT_FLOAT_EQ(200, YGNodeLayoutGetHeight(root)); + + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0)); + ASSERT_FLOAT_EQ(120, YGNodeLayoutGetWidth(root_child0)); + ASSERT_FLOAT_EQ(200, YGNodeLayoutGetHeight(root_child0)); + + ASSERT_FLOAT_EQ(120, YGNodeLayoutGetLeft(root_child1)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child1)); + ASSERT_FLOAT_EQ(40, YGNodeLayoutGetWidth(root_child1)); + ASSERT_FLOAT_EQ(200, YGNodeLayoutGetHeight(root_child1)); + + YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL); + + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root)); + ASSERT_FLOAT_EQ(200, YGNodeLayoutGetWidth(root)); + ASSERT_FLOAT_EQ(200, YGNodeLayoutGetHeight(root)); + + ASSERT_FLOAT_EQ(80, YGNodeLayoutGetLeft(root_child0)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0)); + ASSERT_FLOAT_EQ(120, YGNodeLayoutGetWidth(root_child0)); + ASSERT_FLOAT_EQ(200, YGNodeLayoutGetHeight(root_child0)); + + ASSERT_FLOAT_EQ(40, YGNodeLayoutGetLeft(root_child1)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child1)); + ASSERT_FLOAT_EQ(40, YGNodeLayoutGetWidth(root_child1)); + ASSERT_FLOAT_EQ(200, YGNodeLayoutGetHeight(root_child1)); + + YGNodeFreeRecursive(root); + + YGSetExperimentalFeatureEnabled(YGExperimentalFeatureRounding, false); +} + +TEST(YogaTest, percentage_flex_basis_cross_max_width) { + YGSetExperimentalFeatureEnabled(YGExperimentalFeatureRounding, true); + + const YGNodeRef root = YGNodeNew(); + YGNodeStyleSetWidth(root, 200); + YGNodeStyleSetHeight(root, 200); + + const YGNodeRef root_child0 = YGNodeNew(); + YGNodeStyleSetFlexGrow(root_child0, 1); + YGNodeStyleSetFlexBasisPercent(root_child0, 10); + YGNodeStyleSetMaxWidthPercent(root_child0, 60); + YGNodeInsertChild(root, root_child0, 0); + + const YGNodeRef root_child1 = YGNodeNew(); + YGNodeStyleSetFlexGrow(root_child1, 4); + YGNodeStyleSetFlexBasisPercent(root_child1, 15); + YGNodeStyleSetMaxWidthPercent(root_child1, 20); + YGNodeInsertChild(root, root_child1, 1); + YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR); + + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root)); + ASSERT_FLOAT_EQ(200, YGNodeLayoutGetWidth(root)); + ASSERT_FLOAT_EQ(200, YGNodeLayoutGetHeight(root)); + + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0)); + ASSERT_FLOAT_EQ(120, YGNodeLayoutGetWidth(root_child0)); + ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child0)); + + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child1)); + ASSERT_FLOAT_EQ(50, YGNodeLayoutGetTop(root_child1)); + ASSERT_FLOAT_EQ(40, YGNodeLayoutGetWidth(root_child1)); + ASSERT_FLOAT_EQ(150, YGNodeLayoutGetHeight(root_child1)); + + YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL); + + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root)); + ASSERT_FLOAT_EQ(200, YGNodeLayoutGetWidth(root)); + ASSERT_FLOAT_EQ(200, YGNodeLayoutGetHeight(root)); + + ASSERT_FLOAT_EQ(80, YGNodeLayoutGetLeft(root_child0)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0)); + ASSERT_FLOAT_EQ(120, YGNodeLayoutGetWidth(root_child0)); + ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child0)); + + ASSERT_FLOAT_EQ(160, YGNodeLayoutGetLeft(root_child1)); + ASSERT_FLOAT_EQ(50, YGNodeLayoutGetTop(root_child1)); + ASSERT_FLOAT_EQ(40, YGNodeLayoutGetWidth(root_child1)); + ASSERT_FLOAT_EQ(150, YGNodeLayoutGetHeight(root_child1)); + + YGNodeFreeRecursive(root); + + YGSetExperimentalFeatureEnabled(YGExperimentalFeatureRounding, false); +} + +TEST(YogaTest, percentage_flex_basis_main_min_width) { + YGSetExperimentalFeatureEnabled(YGExperimentalFeatureRounding, true); + + const YGNodeRef root = YGNodeNew(); + YGNodeStyleSetFlexDirection(root, YGFlexDirectionRow); + YGNodeStyleSetWidth(root, 200); + YGNodeStyleSetHeight(root, 200); + + const YGNodeRef root_child0 = YGNodeNew(); + YGNodeStyleSetFlexGrow(root_child0, 1); + YGNodeStyleSetFlexBasisPercent(root_child0, 15); + YGNodeStyleSetMinWidthPercent(root_child0, 60); + YGNodeInsertChild(root, root_child0, 0); + + const YGNodeRef root_child1 = YGNodeNew(); + YGNodeStyleSetFlexGrow(root_child1, 4); + YGNodeStyleSetFlexBasisPercent(root_child1, 10); + YGNodeStyleSetMinWidthPercent(root_child1, 20); + YGNodeInsertChild(root, root_child1, 1); + YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR); + + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root)); + ASSERT_FLOAT_EQ(200, YGNodeLayoutGetWidth(root)); + ASSERT_FLOAT_EQ(200, YGNodeLayoutGetHeight(root)); + + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0)); + ASSERT_FLOAT_EQ(120, YGNodeLayoutGetWidth(root_child0)); + ASSERT_FLOAT_EQ(200, YGNodeLayoutGetHeight(root_child0)); + + ASSERT_FLOAT_EQ(120, YGNodeLayoutGetLeft(root_child1)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child1)); + ASSERT_FLOAT_EQ(80, YGNodeLayoutGetWidth(root_child1)); + ASSERT_FLOAT_EQ(200, YGNodeLayoutGetHeight(root_child1)); + + YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL); + + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root)); + ASSERT_FLOAT_EQ(200, YGNodeLayoutGetWidth(root)); + ASSERT_FLOAT_EQ(200, YGNodeLayoutGetHeight(root)); + + ASSERT_FLOAT_EQ(80, YGNodeLayoutGetLeft(root_child0)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0)); + ASSERT_FLOAT_EQ(120, YGNodeLayoutGetWidth(root_child0)); + ASSERT_FLOAT_EQ(200, YGNodeLayoutGetHeight(root_child0)); + + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child1)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child1)); + ASSERT_FLOAT_EQ(80, YGNodeLayoutGetWidth(root_child1)); + ASSERT_FLOAT_EQ(200, YGNodeLayoutGetHeight(root_child1)); + + YGNodeFreeRecursive(root); + + YGSetExperimentalFeatureEnabled(YGExperimentalFeatureRounding, false); +} + +TEST(YogaTest, percentage_flex_basis_cross_min_width) { + YGSetExperimentalFeatureEnabled(YGExperimentalFeatureRounding, true); + + const YGNodeRef root = YGNodeNew(); + YGNodeStyleSetWidth(root, 200); + YGNodeStyleSetHeight(root, 200); + + const YGNodeRef root_child0 = YGNodeNew(); + YGNodeStyleSetFlexGrow(root_child0, 1); + YGNodeStyleSetFlexBasisPercent(root_child0, 10); + YGNodeStyleSetMinWidthPercent(root_child0, 60); + YGNodeInsertChild(root, root_child0, 0); + + const YGNodeRef root_child1 = YGNodeNew(); + YGNodeStyleSetFlexGrow(root_child1, 4); + YGNodeStyleSetFlexBasisPercent(root_child1, 15); + YGNodeStyleSetMinWidthPercent(root_child1, 20); + YGNodeInsertChild(root, root_child1, 1); + YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR); + + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root)); + ASSERT_FLOAT_EQ(200, YGNodeLayoutGetWidth(root)); + ASSERT_FLOAT_EQ(200, YGNodeLayoutGetHeight(root)); + + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0)); + ASSERT_FLOAT_EQ(200, YGNodeLayoutGetWidth(root_child0)); + ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child0)); + + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child1)); + ASSERT_FLOAT_EQ(50, YGNodeLayoutGetTop(root_child1)); + ASSERT_FLOAT_EQ(200, YGNodeLayoutGetWidth(root_child1)); + ASSERT_FLOAT_EQ(150, YGNodeLayoutGetHeight(root_child1)); + + YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL); + + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root)); + ASSERT_FLOAT_EQ(200, YGNodeLayoutGetWidth(root)); + ASSERT_FLOAT_EQ(200, YGNodeLayoutGetHeight(root)); + + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0)); + ASSERT_FLOAT_EQ(200, YGNodeLayoutGetWidth(root_child0)); + ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child0)); + + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child1)); + ASSERT_FLOAT_EQ(50, YGNodeLayoutGetTop(root_child1)); + ASSERT_FLOAT_EQ(200, YGNodeLayoutGetWidth(root_child1)); + ASSERT_FLOAT_EQ(150, YGNodeLayoutGetHeight(root_child1)); + + YGNodeFreeRecursive(root); + + YGSetExperimentalFeatureEnabled(YGExperimentalFeatureRounding, false); +} + +TEST(YogaTest, percentage_multiple_nested_with_padding_margin_and_percentage_values) { + YGSetExperimentalFeatureEnabled(YGExperimentalFeatureRounding, true); + + const YGNodeRef root = YGNodeNew(); + YGNodeStyleSetWidth(root, 200); + YGNodeStyleSetHeight(root, 200); + + const YGNodeRef root_child0 = YGNodeNew(); + YGNodeStyleSetFlexGrow(root_child0, 1); + YGNodeStyleSetFlexBasisPercent(root_child0, 10); + YGNodeStyleSetMargin(root_child0, YGEdgeLeft, 5); + YGNodeStyleSetMargin(root_child0, YGEdgeTop, 5); + YGNodeStyleSetMargin(root_child0, YGEdgeRight, 5); + YGNodeStyleSetMargin(root_child0, YGEdgeBottom, 5); + YGNodeStyleSetPadding(root_child0, YGEdgeLeft, 3); + YGNodeStyleSetPadding(root_child0, YGEdgeTop, 3); + YGNodeStyleSetPadding(root_child0, YGEdgeRight, 3); + YGNodeStyleSetPadding(root_child0, YGEdgeBottom, 3); + YGNodeStyleSetMinWidthPercent(root_child0, 60); + YGNodeInsertChild(root, root_child0, 0); + + const YGNodeRef root_child0_child0 = YGNodeNew(); + YGNodeStyleSetMargin(root_child0_child0, YGEdgeLeft, 5); + YGNodeStyleSetMargin(root_child0_child0, YGEdgeTop, 5); + YGNodeStyleSetMargin(root_child0_child0, YGEdgeRight, 5); + YGNodeStyleSetMargin(root_child0_child0, YGEdgeBottom, 5); + YGNodeStyleSetPaddingPercent(root_child0_child0, YGEdgeLeft, 3); + YGNodeStyleSetPaddingPercent(root_child0_child0, YGEdgeTop, 3); + YGNodeStyleSetPaddingPercent(root_child0_child0, YGEdgeRight, 3); + YGNodeStyleSetPaddingPercent(root_child0_child0, YGEdgeBottom, 3); + YGNodeStyleSetWidthPercent(root_child0_child0, 50); + YGNodeInsertChild(root_child0, root_child0_child0, 0); + + const YGNodeRef root_child0_child0_child0 = YGNodeNew(); + YGNodeStyleSetMarginPercent(root_child0_child0_child0, YGEdgeLeft, 5); + YGNodeStyleSetMarginPercent(root_child0_child0_child0, YGEdgeTop, 5); + YGNodeStyleSetMarginPercent(root_child0_child0_child0, YGEdgeRight, 5); + YGNodeStyleSetMarginPercent(root_child0_child0_child0, YGEdgeBottom, 5); + YGNodeStyleSetPadding(root_child0_child0_child0, YGEdgeLeft, 3); + YGNodeStyleSetPadding(root_child0_child0_child0, YGEdgeTop, 3); + YGNodeStyleSetPadding(root_child0_child0_child0, YGEdgeRight, 3); + YGNodeStyleSetPadding(root_child0_child0_child0, YGEdgeBottom, 3); + YGNodeStyleSetWidthPercent(root_child0_child0_child0, 45); + YGNodeInsertChild(root_child0_child0, root_child0_child0_child0, 0); + + const YGNodeRef root_child1 = YGNodeNew(); + YGNodeStyleSetFlexGrow(root_child1, 4); + YGNodeStyleSetFlexBasisPercent(root_child1, 15); + YGNodeStyleSetMinWidthPercent(root_child1, 20); + YGNodeInsertChild(root, root_child1, 1); + YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR); + + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root)); + ASSERT_FLOAT_EQ(200, YGNodeLayoutGetWidth(root)); + ASSERT_FLOAT_EQ(200, YGNodeLayoutGetHeight(root)); + + ASSERT_FLOAT_EQ(5, YGNodeLayoutGetLeft(root_child0)); + ASSERT_FLOAT_EQ(5, YGNodeLayoutGetTop(root_child0)); + ASSERT_FLOAT_EQ(190, YGNodeLayoutGetWidth(root_child0)); + ASSERT_FLOAT_EQ(48, YGNodeLayoutGetHeight(root_child0)); + + ASSERT_FLOAT_EQ(8, YGNodeLayoutGetLeft(root_child0_child0)); + ASSERT_FLOAT_EQ(8, YGNodeLayoutGetTop(root_child0_child0)); + ASSERT_FLOAT_EQ(92, YGNodeLayoutGetWidth(root_child0_child0)); + ASSERT_FLOAT_EQ(25, YGNodeLayoutGetHeight(root_child0_child0)); + + ASSERT_FLOAT_EQ(10, YGNodeLayoutGetLeft(root_child0_child0_child0)); + ASSERT_FLOAT_EQ(10, YGNodeLayoutGetTop(root_child0_child0_child0)); + ASSERT_FLOAT_EQ(36, YGNodeLayoutGetWidth(root_child0_child0_child0)); + ASSERT_FLOAT_EQ(6, YGNodeLayoutGetHeight(root_child0_child0_child0)); + + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child1)); + ASSERT_FLOAT_EQ(58, YGNodeLayoutGetTop(root_child1)); + ASSERT_FLOAT_EQ(200, YGNodeLayoutGetWidth(root_child1)); + ASSERT_FLOAT_EQ(142, YGNodeLayoutGetHeight(root_child1)); + + YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL); + + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root)); + ASSERT_FLOAT_EQ(200, YGNodeLayoutGetWidth(root)); + ASSERT_FLOAT_EQ(200, YGNodeLayoutGetHeight(root)); + + ASSERT_FLOAT_EQ(5, YGNodeLayoutGetLeft(root_child0)); + ASSERT_FLOAT_EQ(5, YGNodeLayoutGetTop(root_child0)); + ASSERT_FLOAT_EQ(190, YGNodeLayoutGetWidth(root_child0)); + ASSERT_FLOAT_EQ(48, YGNodeLayoutGetHeight(root_child0)); + + ASSERT_FLOAT_EQ(90, YGNodeLayoutGetLeft(root_child0_child0)); + ASSERT_FLOAT_EQ(8, YGNodeLayoutGetTop(root_child0_child0)); + ASSERT_FLOAT_EQ(92, YGNodeLayoutGetWidth(root_child0_child0)); + ASSERT_FLOAT_EQ(25, YGNodeLayoutGetHeight(root_child0_child0)); + + ASSERT_FLOAT_EQ(46, YGNodeLayoutGetLeft(root_child0_child0_child0)); + ASSERT_FLOAT_EQ(10, YGNodeLayoutGetTop(root_child0_child0_child0)); + ASSERT_FLOAT_EQ(36, YGNodeLayoutGetWidth(root_child0_child0_child0)); + ASSERT_FLOAT_EQ(6, YGNodeLayoutGetHeight(root_child0_child0_child0)); + + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child1)); + ASSERT_FLOAT_EQ(58, YGNodeLayoutGetTop(root_child1)); + ASSERT_FLOAT_EQ(200, YGNodeLayoutGetWidth(root_child1)); + ASSERT_FLOAT_EQ(142, YGNodeLayoutGetHeight(root_child1)); + + YGNodeFreeRecursive(root); + + YGSetExperimentalFeatureEnabled(YGExperimentalFeatureRounding, false); +} + +TEST(YogaTest, percentage_margin_should_calculate_based_only_on_width) { + YGSetExperimentalFeatureEnabled(YGExperimentalFeatureRounding, true); + + const YGNodeRef root = YGNodeNew(); + YGNodeStyleSetWidth(root, 200); + YGNodeStyleSetHeight(root, 100); + + const YGNodeRef root_child0 = YGNodeNew(); + YGNodeStyleSetFlexGrow(root_child0, 1); + YGNodeStyleSetMarginPercent(root_child0, YGEdgeLeft, 10); + YGNodeStyleSetMarginPercent(root_child0, YGEdgeTop, 10); + YGNodeStyleSetMarginPercent(root_child0, YGEdgeRight, 10); + YGNodeStyleSetMarginPercent(root_child0, YGEdgeBottom, 10); + YGNodeInsertChild(root, root_child0, 0); + + const YGNodeRef root_child0_child0 = YGNodeNew(); + YGNodeStyleSetWidth(root_child0_child0, 10); + YGNodeStyleSetHeight(root_child0_child0, 10); + YGNodeInsertChild(root_child0, root_child0_child0, 0); + YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR); + + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root)); + ASSERT_FLOAT_EQ(200, YGNodeLayoutGetWidth(root)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root)); + + ASSERT_FLOAT_EQ(20, YGNodeLayoutGetLeft(root_child0)); + ASSERT_FLOAT_EQ(20, YGNodeLayoutGetTop(root_child0)); + ASSERT_FLOAT_EQ(160, YGNodeLayoutGetWidth(root_child0)); + ASSERT_FLOAT_EQ(60, YGNodeLayoutGetHeight(root_child0)); + + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0_child0)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0_child0)); + ASSERT_FLOAT_EQ(10, YGNodeLayoutGetWidth(root_child0_child0)); + ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child0_child0)); + + YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL); + + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root)); + ASSERT_FLOAT_EQ(200, YGNodeLayoutGetWidth(root)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root)); + + ASSERT_FLOAT_EQ(20, YGNodeLayoutGetLeft(root_child0)); + ASSERT_FLOAT_EQ(20, YGNodeLayoutGetTop(root_child0)); + ASSERT_FLOAT_EQ(160, YGNodeLayoutGetWidth(root_child0)); + ASSERT_FLOAT_EQ(60, YGNodeLayoutGetHeight(root_child0)); + + ASSERT_FLOAT_EQ(150, YGNodeLayoutGetLeft(root_child0_child0)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0_child0)); + ASSERT_FLOAT_EQ(10, YGNodeLayoutGetWidth(root_child0_child0)); + ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child0_child0)); + + YGNodeFreeRecursive(root); + + YGSetExperimentalFeatureEnabled(YGExperimentalFeatureRounding, false); +} + +TEST(YogaTest, percentage_padding_should_calculate_based_only_on_width) { + YGSetExperimentalFeatureEnabled(YGExperimentalFeatureRounding, true); + + const YGNodeRef root = YGNodeNew(); + YGNodeStyleSetWidth(root, 200); + YGNodeStyleSetHeight(root, 100); + + const YGNodeRef root_child0 = YGNodeNew(); + YGNodeStyleSetFlexGrow(root_child0, 1); + YGNodeStyleSetPaddingPercent(root_child0, YGEdgeLeft, 10); + YGNodeStyleSetPaddingPercent(root_child0, YGEdgeTop, 10); + YGNodeStyleSetPaddingPercent(root_child0, YGEdgeRight, 10); + YGNodeStyleSetPaddingPercent(root_child0, YGEdgeBottom, 10); + YGNodeInsertChild(root, root_child0, 0); + + const YGNodeRef root_child0_child0 = YGNodeNew(); + YGNodeStyleSetWidth(root_child0_child0, 10); + YGNodeStyleSetHeight(root_child0_child0, 10); + YGNodeInsertChild(root_child0, root_child0_child0, 0); + YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR); + + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root)); + ASSERT_FLOAT_EQ(200, YGNodeLayoutGetWidth(root)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root)); + + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0)); + ASSERT_FLOAT_EQ(200, YGNodeLayoutGetWidth(root_child0)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child0)); + + ASSERT_FLOAT_EQ(20, YGNodeLayoutGetLeft(root_child0_child0)); + ASSERT_FLOAT_EQ(20, YGNodeLayoutGetTop(root_child0_child0)); + ASSERT_FLOAT_EQ(10, YGNodeLayoutGetWidth(root_child0_child0)); + ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child0_child0)); + + YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL); + + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root)); + ASSERT_FLOAT_EQ(200, YGNodeLayoutGetWidth(root)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root)); + + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0)); + ASSERT_FLOAT_EQ(200, YGNodeLayoutGetWidth(root_child0)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child0)); + + ASSERT_FLOAT_EQ(170, YGNodeLayoutGetLeft(root_child0_child0)); + ASSERT_FLOAT_EQ(20, YGNodeLayoutGetTop(root_child0_child0)); + ASSERT_FLOAT_EQ(10, YGNodeLayoutGetWidth(root_child0_child0)); + ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child0_child0)); + + YGNodeFreeRecursive(root); + + YGSetExperimentalFeatureEnabled(YGExperimentalFeatureRounding, false); +} + +TEST(YogaTest, percentage_absolute_position) { + YGSetExperimentalFeatureEnabled(YGExperimentalFeatureRounding, true); + + const YGNodeRef root = YGNodeNew(); + YGNodeStyleSetWidth(root, 200); + YGNodeStyleSetHeight(root, 100); + + const YGNodeRef root_child0 = YGNodeNew(); + YGNodeStyleSetPositionType(root_child0, YGPositionTypeAbsolute); + YGNodeStyleSetPositionPercent(root_child0, YGEdgeLeft, 30); + YGNodeStyleSetPositionPercent(root_child0, YGEdgeTop, 10); + YGNodeStyleSetWidth(root_child0, 10); + YGNodeStyleSetHeight(root_child0, 10); + YGNodeInsertChild(root, root_child0, 0); + YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR); + + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root)); + ASSERT_FLOAT_EQ(200, YGNodeLayoutGetWidth(root)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root)); + + ASSERT_FLOAT_EQ(60, YGNodeLayoutGetLeft(root_child0)); + ASSERT_FLOAT_EQ(10, YGNodeLayoutGetTop(root_child0)); + ASSERT_FLOAT_EQ(10, YGNodeLayoutGetWidth(root_child0)); + ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child0)); + + YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL); + + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root)); + ASSERT_FLOAT_EQ(200, YGNodeLayoutGetWidth(root)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root)); + + ASSERT_FLOAT_EQ(60, YGNodeLayoutGetLeft(root_child0)); + ASSERT_FLOAT_EQ(10, YGNodeLayoutGetTop(root_child0)); + ASSERT_FLOAT_EQ(10, YGNodeLayoutGetWidth(root_child0)); + ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child0)); + + YGNodeFreeRecursive(root); + + YGSetExperimentalFeatureEnabled(YGExperimentalFeatureRounding, false); +} diff --git a/tests/YGStyleTest.cpp b/tests/YGStyleTest.cpp index 4eb7fd60..83555edd 100644 --- a/tests/YGStyleTest.cpp +++ b/tests/YGStyleTest.cpp @@ -26,7 +26,7 @@ TEST(YogaTest, copy_style_modified) { const YGNodeRef node0 = YGNodeNew(); ASSERT_FALSE(YGNodeIsDirty(node0)); ASSERT_EQ(YGFlexDirectionColumn, YGNodeStyleGetFlexDirection(node0)); - ASSERT_TRUE(YGValueIsUndefined(YGNodeStyleGetMaxHeight(node0))); + ASSERT_FALSE(YGNodeStyleGetMaxHeight(node0).unit != YGUnitUndefined); const YGNodeRef node1 = YGNodeNew(); YGNodeStyleSetFlexDirection(node1, YGFlexDirectionRow); @@ -35,7 +35,7 @@ TEST(YogaTest, copy_style_modified) { YGNodeCopyStyle(node0, node1); ASSERT_TRUE(YGNodeIsDirty(node0)); ASSERT_EQ(YGFlexDirectionRow, YGNodeStyleGetFlexDirection(node0)); - ASSERT_FLOAT_EQ(10, YGNodeStyleGetMaxHeight(node0)); + ASSERT_FLOAT_EQ(10, YGNodeStyleGetMaxHeight(node0).value); YGNodeFree(node0); YGNodeFree(node1); diff --git a/yoga/YGEnums.h b/yoga/YGEnums.h index a64c1673..be60e02c 100644 --- a/yoga/YGEnums.h +++ b/yoga/YGEnums.h @@ -113,4 +113,11 @@ typedef enum YGAlign { YGAlignStretch, } YGAlign; +#define YGUnitCount 3 +typedef enum YGUnit { + YGUnitUndefined, + YGUnitPixel, + YGUnitPercent, +} YGUnit; + YG_EXTERN_C_END diff --git a/yoga/Yoga.c b/yoga/Yoga.c index 32bc01e4..d4285444 100644 --- a/yoga/Yoga.c +++ b/yoga/Yoga.c @@ -77,14 +77,14 @@ typedef struct YGStyle { float flex; float flexGrow; float flexShrink; - float flexBasis; - float margin[YGEdgeCount]; - float position[YGEdgeCount]; - float padding[YGEdgeCount]; - float border[YGEdgeCount]; - float dimensions[2]; - float minDimensions[2]; - float maxDimensions[2]; + YGValue flexBasis; + YGValue margin[YGEdgeCount]; + YGValue position[YGEdgeCount]; + YGValue padding[YGEdgeCount]; + YGValue border[YGEdgeCount]; + YGValue dimensions[2]; + YGValue minDimensions[2]; + YGValue maxDimensions[2]; // Yoga specific properties, not compatible with flexbox specification float aspectRatio; @@ -106,64 +106,68 @@ typedef struct YGNode { void *context; } YGNode; -#define YG_DEFAULT_EDGE_VALUES { \ - [YGEdgeLeft] = YGUndefined, \ - [YGEdgeTop] = YGUndefined, \ - [YGEdgeRight] = YGUndefined, \ - [YGEdgeBottom] = YGUndefined, \ - [YGEdgeStart] = YGUndefined, \ - [YGEdgeEnd] = YGUndefined, \ - [YGEdgeHorizontal] = YGUndefined, \ - [YGEdgeVertical] = YGUndefined, \ - [YGEdgeAll] = YGUndefined, \ -} +#define YG_UNDEFINED_VALUES \ + { .value = YGUndefined, .unit = YGUnitUndefined } -#define YG_DEFAULT_DIMENSION_VALUES { \ - [YGDimensionWidth] = YGUndefined, \ - [YGDimensionHeight] = YGUndefined, \ -} +#define YG_DEFAULT_EDGE_VALUES_UNIT \ + { \ + [YGEdgeLeft] = YG_UNDEFINED_VALUES, [YGEdgeTop] = YG_UNDEFINED_VALUES, \ + [YGEdgeRight] = YG_UNDEFINED_VALUES, [YGEdgeBottom] = YG_UNDEFINED_VALUES, \ + [YGEdgeStart] = YG_UNDEFINED_VALUES, [YGEdgeEnd] = YG_UNDEFINED_VALUES, \ + [YGEdgeHorizontal] = YG_UNDEFINED_VALUES, [YGEdgeVertical] = YG_UNDEFINED_VALUES, \ + [YGEdgeAll] = YG_UNDEFINED_VALUES, \ + } -YGNode gYGNodeDefaults = { - .parent = NULL, - .children = NULL, - .hasNewLayout = true, - .isDirty = false, +#define YG_DEFAULT_DIMENSION_VALUES \ + { [YGDimensionWidth] = YGUndefined, [YGDimensionHeight] = YGUndefined, } - .style = { - .flex = YGUndefined, - .flexGrow = YGUndefined, - .flexShrink = YGUndefined, - .flexBasis = YGUndefined, - .justifyContent = YGJustifyFlexStart, - .alignItems = YGAlignStretch, - .alignContent = YGAlignFlexStart, - .direction = YGDirectionInherit, - .flexDirection = YGFlexDirectionColumn, - .overflow = YGOverflowVisible, - .dimensions = YG_DEFAULT_DIMENSION_VALUES, - .minDimensions = YG_DEFAULT_DIMENSION_VALUES, - .maxDimensions = YG_DEFAULT_DIMENSION_VALUES, - .position = YG_DEFAULT_EDGE_VALUES, - .margin = YG_DEFAULT_EDGE_VALUES, - .padding = YG_DEFAULT_EDGE_VALUES, - .border = YG_DEFAULT_EDGE_VALUES, - .aspectRatio = YGUndefined, - }, +#define YG_DEFAULT_DIMENSION_VALUES_UNIT \ + { [YGDimensionWidth] = YG_UNDEFINED_VALUES, [YGDimensionHeight] = YG_UNDEFINED_VALUES, } - .layout = { - .dimensions = YG_DEFAULT_DIMENSION_VALUES, - .lastParentDirection = (YGDirection) -1, - .nextCachedMeasurementsIndex = 0, - .computedFlexBasis = YGUndefined, - .measuredDimensions = YG_DEFAULT_DIMENSION_VALUES, +static YGNode gYGNodeDefaults = { + .parent = NULL, + .children = NULL, + .hasNewLayout = true, + .isDirty = false, - .cachedLayout = { - .widthMeasureMode = (YGMeasureMode) -1, - .heightMeasureMode = (YGMeasureMode) -1, - .computedWidth = -1, - .computedHeight = -1, - }, - }, + .style = + { + .flex = YGUndefined, + .flexGrow = YGUndefined, + .flexShrink = YGUndefined, + .flexBasis = YG_UNDEFINED_VALUES, + .justifyContent = YGJustifyFlexStart, + .alignItems = YGAlignStretch, + .alignContent = YGAlignFlexStart, + .direction = YGDirectionInherit, + .flexDirection = YGFlexDirectionColumn, + .overflow = YGOverflowVisible, + .dimensions = YG_DEFAULT_DIMENSION_VALUES_UNIT, + .minDimensions = YG_DEFAULT_DIMENSION_VALUES_UNIT, + .maxDimensions = YG_DEFAULT_DIMENSION_VALUES_UNIT, + .position = YG_DEFAULT_EDGE_VALUES_UNIT, + .margin = YG_DEFAULT_EDGE_VALUES_UNIT, + .padding = YG_DEFAULT_EDGE_VALUES_UNIT, + .border = YG_DEFAULT_EDGE_VALUES_UNIT, + .aspectRatio = YGUndefined, + }, + + .layout = + { + .dimensions = YG_DEFAULT_DIMENSION_VALUES, + .lastParentDirection = (YGDirection) -1, + .nextCachedMeasurementsIndex = 0, + .computedFlexBasis = YGUndefined, + .measuredDimensions = YG_DEFAULT_DIMENSION_VALUES, + + .cachedLayout = + { + .widthMeasureMode = (YGMeasureMode) -1, + .heightMeasureMode = (YGMeasureMode) -1, + .computedWidth = -1, + .computedHeight = -1, + }, + }, }; static void YGNodeMarkDirtyInternal(const YGNodeRef node); @@ -173,6 +177,10 @@ YGCalloc gYGCalloc = &calloc; YGRealloc gYGRealloc = &realloc; YGFree gYGFree = &free; +static YGValue YGValueUndefined = YG_UNDEFINED_VALUES; + +static YGValue YGValueZero = {.value = 0, .unit = YGUnitPixel}; + #ifdef ANDROID #include static int YGAndroidLog(YGLogLevel level, const char *format, va_list args) { @@ -214,35 +222,44 @@ static int YGDefaultLog(YGLogLevel level, const char *format, va_list args) { static YGLogger gLogger = &YGDefaultLog; #endif -static inline float YGComputedEdgeValue(const float edges[YGEdgeCount], - const YGEdge edge, - const float defaultValue) { +static inline const YGValue *YGComputedEdgeValue(const YGValue edges[YGEdgeCount], + const YGEdge edge, + const YGValue *const defaultValue) { YG_ASSERT(edge <= YGEdgeEnd, "Cannot get computed value of multi-edge shorthands"); - if (!YGValueIsUndefined(edges[edge])) { - return edges[edge]; + if (edges[edge].unit != YGUnitUndefined) { + return &edges[edge]; } - if ((edge == YGEdgeTop || edge == YGEdgeBottom) && !YGValueIsUndefined(edges[YGEdgeVertical])) { - return edges[YGEdgeVertical]; + if ((edge == YGEdgeTop || edge == YGEdgeBottom) && + edges[YGEdgeVertical].unit != YGUnitUndefined) { + return &edges[YGEdgeVertical]; } if ((edge == YGEdgeLeft || edge == YGEdgeRight || edge == YGEdgeStart || edge == YGEdgeEnd) && - !YGValueIsUndefined(edges[YGEdgeHorizontal])) { - return edges[YGEdgeHorizontal]; + edges[YGEdgeHorizontal].unit != YGUnitUndefined) { + return &edges[YGEdgeHorizontal]; } - if (!YGValueIsUndefined(edges[YGEdgeAll])) { - return edges[YGEdgeAll]; + if (edges[YGEdgeAll].unit != YGUnitUndefined) { + return &edges[YGEdgeAll]; } if (edge == YGEdgeStart || edge == YGEdgeEnd) { - return YGUndefined; + return &YGValueUndefined; } return defaultValue; } +static inline float YGValueResolve(const YGValue *const unit, const float parentSize) { + if (unit->unit == YGUnitPixel) { + return unit->value; + } else { + return unit->value * parentSize / 100.0f; + } +} + int32_t gNodeInstanceCount = 0; YGNodeRef YGNodeNew(void) { @@ -281,7 +298,8 @@ void YGNodeFreeRecursive(const YGNodeRef root) { } void YGNodeReset(const YGNodeRef node) { - YG_ASSERT(YGNodeGetChildCount(node) == 0, "Cannot reset a node which still has children attached"); + YG_ASSERT(YGNodeGetChildCount(node) == 0, + "Cannot reset a node which still has children attached"); YG_ASSERT(node->parent == NULL, "Cannot reset a node still attached to a parent"); YGNodeListFree(node->children); @@ -363,33 +381,37 @@ void YGNodeCopyStyle(const YGNodeRef dstNode, const YGNodeRef srcNode) { } inline float YGNodeStyleGetFlexGrow(const YGNodeRef node) { - if (!YGValueIsUndefined(node->style.flexGrow)) { + if (!YGFloatIsUndefined(node->style.flexGrow)) { return node->style.flexGrow; } - if (!YGValueIsUndefined(node->style.flex) && node->style.flex > 0) { + if (!YGFloatIsUndefined(node->style.flex) && node->style.flex > 0.0f) { return node->style.flex; } - return 0; + return 0.0f; } inline float YGNodeStyleGetFlexShrink(const YGNodeRef node) { - if (!YGValueIsUndefined(node->style.flexShrink)) { + if (!YGFloatIsUndefined(node->style.flexShrink)) { return node->style.flexShrink; } - if (!YGValueIsUndefined(node->style.flex) && node->style.flex < 0) { + if (!YGFloatIsUndefined(node->style.flex) && node->style.flex < 0.0f) { return -node->style.flex; } - return 0; + return 0.0f; } -inline float YGNodeStyleGetFlexBasis(const YGNodeRef node) { - if (!YGValueIsUndefined(node->style.flexBasis)) { - return node->style.flexBasis; +static inline const YGValue *YGNodeStyleGetFlexBasisPtr(const YGNodeRef node) { + if (node->style.flexBasis.unit != YGUnitUndefined) { + return &node->style.flexBasis; } - if (!YGValueIsUndefined(node->style.flex)) { - return node->style.flex > 0 ? 0 : YGUndefined; + if (!YGFloatIsUndefined(node->style.flex) && node->style.flex > 0.0f) { + return &YGValueZero; } - return YGUndefined; + return &YGValueUndefined; +} + +inline YGValue YGNodeStyleGetFlexBasis(const YGNodeRef node) { + return *YGNodeStyleGetFlexBasisPtr(node); } void YGNodeStyleSetFlex(const YGNodeRef node, const float flex) { @@ -416,6 +438,27 @@ void YGNodeStyleSetFlex(const YGNodeRef node, const float flex) { } \ } +#define YG_NODE_STYLE_PROPERTY_SETTER_UNIT_IMPL(type, name, paramName, instanceName) \ + void YGNodeStyleSet##name(const YGNodeRef node, const type paramName) { \ + if (node->style.instanceName.value != paramName || \ + node->style.instanceName.unit != YGUnitPixel) { \ + node->style.instanceName.value = paramName; \ + node->style.instanceName.unit = \ + YGFloatIsUndefined(paramName) ? YGUnitUndefined : YGUnitPixel; \ + YGNodeMarkDirtyInternal(node); \ + } \ + } \ + \ + void YGNodeStyleSet##name##Percent(const YGNodeRef node, const type paramName) { \ + if (node->style.instanceName.value != paramName || \ + node->style.instanceName.unit != YGUnitPercent) { \ + node->style.instanceName.value = paramName; \ + node->style.instanceName.unit = \ + YGFloatIsUndefined(paramName) ? YGUnitUndefined : YGUnitPercent; \ + YGNodeMarkDirtyInternal(node); \ + } \ + } + #define YG_NODE_STYLE_PROPERTY_IMPL(type, name, paramName, instanceName) \ YG_NODE_STYLE_PROPERTY_SETTER_IMPL(type, name, paramName, instanceName) \ \ @@ -423,16 +466,53 @@ void YGNodeStyleSetFlex(const YGNodeRef node, const float flex) { return node->style.instanceName; \ } -#define YG_NODE_STYLE_EDGE_PROPERTY_IMPL(type, name, paramName, instanceName, defaultValue) \ - void YGNodeStyleSet##name(const YGNodeRef node, const YGEdge edge, const type paramName) { \ - if (node->style.instanceName[edge] != paramName) { \ - node->style.instanceName[edge] = paramName; \ - YGNodeMarkDirtyInternal(node); \ - } \ - } \ - \ - type YGNodeStyleGet##name(const YGNodeRef node, const YGEdge edge) { \ - return YGComputedEdgeValue(node->style.instanceName, edge, defaultValue); \ +#define YG_NODE_STYLE_PROPERTY_UNIT_IMPL(type, name, paramName, instanceName) \ + YG_NODE_STYLE_PROPERTY_SETTER_UNIT_IMPL(float, name, paramName, instanceName) \ + \ + type YGNodeStyleGet##name(const YGNodeRef node) { \ + return node->style.instanceName; \ + } + +#define YG_NODE_STYLE_EDGE_PROPERTY_UNIT_IMPL(type, name, paramName, instanceName, defaultValue) \ + void YGNodeStyleSet##name(const YGNodeRef node, const YGEdge edge, const float paramName) { \ + if (node->style.instanceName[edge].value != paramName || \ + node->style.instanceName[edge].unit != YGUnitPixel) { \ + node->style.instanceName[edge].value = paramName; \ + node->style.instanceName[edge].unit = \ + YGFloatIsUndefined(paramName) ? YGUnitUndefined : YGUnitPixel; \ + YGNodeMarkDirtyInternal(node); \ + } \ + } \ + \ + void YGNodeStyleSet##name##Percent(const YGNodeRef node, \ + const YGEdge edge, \ + const float paramName) { \ + if (node->style.instanceName[edge].value != paramName || \ + node->style.instanceName[edge].unit != YGUnitPercent) { \ + node->style.instanceName[edge].value = paramName; \ + node->style.instanceName[edge].unit = \ + YGFloatIsUndefined(paramName) ? YGUnitUndefined : YGUnitPercent; \ + YGNodeMarkDirtyInternal(node); \ + } \ + } \ + \ + type YGNodeStyleGet##name(const YGNodeRef node, const YGEdge edge) { \ + return *YGComputedEdgeValue(node->style.instanceName, edge, &defaultValue); \ + } + +#define YG_NODE_STYLE_EDGE_PROPERTY_IMPL(type, name, paramName, instanceName, defaultValue) \ + void YGNodeStyleSet##name(const YGNodeRef node, const YGEdge edge, const float paramName) { \ + if (node->style.instanceName[edge].value != paramName || \ + node->style.instanceName[edge].unit != YGUnitPixel) { \ + node->style.instanceName[edge].value = paramName; \ + node->style.instanceName[edge].unit = \ + YGFloatIsUndefined(paramName) ? YGUnitUndefined : YGUnitPixel; \ + YGNodeMarkDirtyInternal(node); \ + } \ + } \ + \ + float YGNodeStyleGet##name(const YGNodeRef node, const YGEdge edge) { \ + return YGComputedEdgeValue(node->style.instanceName, edge, &defaultValue)->value; \ } #define YG_NODE_LAYOUT_PROPERTY_IMPL(type, name, instanceName) \ @@ -456,19 +536,19 @@ YG_NODE_STYLE_PROPERTY_IMPL(YGOverflow, Overflow, overflow, overflow); YG_NODE_STYLE_PROPERTY_SETTER_IMPL(float, FlexGrow, flexGrow, flexGrow); YG_NODE_STYLE_PROPERTY_SETTER_IMPL(float, FlexShrink, flexShrink, flexShrink); -YG_NODE_STYLE_PROPERTY_SETTER_IMPL(float, FlexBasis, flexBasis, flexBasis); +YG_NODE_STYLE_PROPERTY_SETTER_UNIT_IMPL(float, FlexBasis, flexBasis, flexBasis); -YG_NODE_STYLE_EDGE_PROPERTY_IMPL(float, Position, position, position, YGUndefined); -YG_NODE_STYLE_EDGE_PROPERTY_IMPL(float, Margin, margin, margin, 0); -YG_NODE_STYLE_EDGE_PROPERTY_IMPL(float, Padding, padding, padding, 0); -YG_NODE_STYLE_EDGE_PROPERTY_IMPL(float, Border, border, border, 0); +YG_NODE_STYLE_EDGE_PROPERTY_UNIT_IMPL(YGValue, Position, position, position, YGValueUndefined); +YG_NODE_STYLE_EDGE_PROPERTY_UNIT_IMPL(YGValue, Margin, margin, margin, YGValueZero); +YG_NODE_STYLE_EDGE_PROPERTY_UNIT_IMPL(YGValue, Padding, padding, padding, YGValueZero); +YG_NODE_STYLE_EDGE_PROPERTY_IMPL(float, Border, border, border, YGValueZero); -YG_NODE_STYLE_PROPERTY_IMPL(float, Width, width, dimensions[YGDimensionWidth]); -YG_NODE_STYLE_PROPERTY_IMPL(float, Height, height, dimensions[YGDimensionHeight]); -YG_NODE_STYLE_PROPERTY_IMPL(float, MinWidth, minWidth, minDimensions[YGDimensionWidth]); -YG_NODE_STYLE_PROPERTY_IMPL(float, MinHeight, minHeight, minDimensions[YGDimensionHeight]); -YG_NODE_STYLE_PROPERTY_IMPL(float, MaxWidth, maxWidth, maxDimensions[YGDimensionWidth]); -YG_NODE_STYLE_PROPERTY_IMPL(float, MaxHeight, maxHeight, maxDimensions[YGDimensionHeight]); +YG_NODE_STYLE_PROPERTY_UNIT_IMPL(YGValue, Width, width, dimensions[YGDimensionWidth]); +YG_NODE_STYLE_PROPERTY_UNIT_IMPL(YGValue, Height, height, dimensions[YGDimensionHeight]); +YG_NODE_STYLE_PROPERTY_UNIT_IMPL(YGValue, MinWidth, minWidth, minDimensions[YGDimensionWidth]); +YG_NODE_STYLE_PROPERTY_UNIT_IMPL(YGValue, MinHeight, minHeight, minDimensions[YGDimensionHeight]); +YG_NODE_STYLE_PROPERTY_UNIT_IMPL(YGValue, MaxWidth, maxWidth, maxDimensions[YGDimensionWidth]); +YG_NODE_STYLE_PROPERTY_UNIT_IMPL(YGValue, MaxHeight, maxHeight, maxDimensions[YGDimensionHeight]); // Yoga specific properties, not compatible with flexbox specification YG_NODE_STYLE_PROPERTY_IMPL(float, AspectRatio, aspectRatio, aspectRatio); @@ -489,18 +569,32 @@ bool YGLayoutNodeInternal(const YGNodeRef node, const YGDirection parentDirection, const YGMeasureMode widthMeasureMode, const YGMeasureMode heightMeasureMode, + const float parentWidth, + const float parentHeight, const bool performLayout, const char *reason); -inline bool YGValueIsUndefined(const float value) { +inline bool YGFloatIsUndefined(const float value) { return isnan(value); } -static inline bool YGFloatsEqual(const float a, const float b) { - if (YGValueIsUndefined(a)) { - return YGValueIsUndefined(b); +static inline bool YGValueEqual(const YGValue a, const YGValue b) { + if (a.unit != b.unit) { + return false; } - return fabs(a - b) < 0.0001; + + if (a.unit == YGUnitUndefined) { + return true; + } + + return fabs(a.value - b.value) < 0.0001f; +} + +static inline bool YGFloatsEqual(const float a, const float b) { + if (YGFloatIsUndefined(a)) { + return YGFloatIsUndefined(b); + } + return fabs(a - b) < 0.0001f; } static void YGIndent(const uint32_t n) { @@ -509,21 +603,35 @@ static void YGIndent(const uint32_t n) { } } -static void YGPrintNumberIfNotZero(const char *str, const float number) { - if (!YGFloatsEqual(number, 0)) { +static void YGPrintNumberIfNotZero(const char *str, const YGValue *const number) { + if (!YGFloatsEqual(number->value, 0)) { + YGLog(YGLogLevelDebug, + "%s: %g%s, ", + str, + number->value, + number->unit == YGUnitPixel ? "px" : "%"); + } +} + +static void YGPrintNumberIfNotUndefinedf(const char *str, const float number) { + if (!YGFloatIsUndefined(number)) { YGLog(YGLogLevelDebug, "%s: %g, ", str, number); } } -static void YGPrintNumberIfNotUndefined(const char *str, const float number) { - if (!YGValueIsUndefined(number)) { - YGLog(YGLogLevelDebug, "%s: %g, ", str, number); +static void YGPrintNumberIfNotUndefined(const char *str, const YGValue *const number) { + if (number->unit != YGUnitUndefined) { + YGLog(YGLogLevelDebug, + "%s: %g%s, ", + str, + number->value, + number->unit == YGUnitPixel ? "px" : "%"); } } -static bool YGFourFloatsEqual(const float four[4]) { - return YGFloatsEqual(four[0], four[1]) && YGFloatsEqual(four[0], four[2]) && - YGFloatsEqual(four[0], four[3]); +static bool YGFourValuesEqual(const YGValue four[4]) { + return YGValueEqual(four[0], four[1]) && YGValueEqual(four[0], four[2]) && + YGValueEqual(four[0], four[3]); } static void YGNodePrintInternal(const YGNodeRef node, @@ -592,9 +700,9 @@ static void YGNodePrintInternal(const YGNodeRef node, YGLog(YGLogLevelDebug, "alignSelf: 'stretch', "); } - YGPrintNumberIfNotUndefined("flexGrow", YGNodeStyleGetFlexGrow(node)); - YGPrintNumberIfNotUndefined("flexShrink", YGNodeStyleGetFlexShrink(node)); - YGPrintNumberIfNotUndefined("flexBasis", YGNodeStyleGetFlexBasis(node)); + YGPrintNumberIfNotUndefinedf("flexGrow", YGNodeStyleGetFlexGrow(node)); + YGPrintNumberIfNotUndefinedf("flexShrink", YGNodeStyleGetFlexShrink(node)); + YGPrintNumberIfNotUndefined("flexBasis", YGNodeStyleGetFlexBasisPtr(node)); if (node->style.overflow == YGOverflowHidden) { YGLog(YGLogLevelDebug, "overflow: 'hidden', "); @@ -604,71 +712,79 @@ static void YGNodePrintInternal(const YGNodeRef node, YGLog(YGLogLevelDebug, "overflow: 'scroll', "); } - if (YGFourFloatsEqual(node->style.margin)) { - YGPrintNumberIfNotZero("margin", YGComputedEdgeValue(node->style.margin, YGEdgeLeft, 0)); + if (YGFourValuesEqual(node->style.margin)) { + YGPrintNumberIfNotZero("margin", + YGComputedEdgeValue(node->style.margin, YGEdgeLeft, &YGValueZero)); } else { - YGPrintNumberIfNotZero("marginLeft", YGComputedEdgeValue(node->style.margin, YGEdgeLeft, 0)); + YGPrintNumberIfNotZero("marginLeft", + YGComputedEdgeValue(node->style.margin, YGEdgeLeft, &YGValueZero)); YGPrintNumberIfNotZero("marginRight", - YGComputedEdgeValue(node->style.margin, YGEdgeRight, 0)); - YGPrintNumberIfNotZero("marginTop", YGComputedEdgeValue(node->style.margin, YGEdgeTop, 0)); + YGComputedEdgeValue(node->style.margin, YGEdgeRight, &YGValueZero)); + YGPrintNumberIfNotZero("marginTop", + YGComputedEdgeValue(node->style.margin, YGEdgeTop, &YGValueZero)); YGPrintNumberIfNotZero("marginBottom", - YGComputedEdgeValue(node->style.margin, YGEdgeBottom, 0)); + YGComputedEdgeValue(node->style.margin, YGEdgeBottom, &YGValueZero)); YGPrintNumberIfNotZero("marginStart", - YGComputedEdgeValue(node->style.margin, YGEdgeStart, 0)); - YGPrintNumberIfNotZero("marginEnd", YGComputedEdgeValue(node->style.margin, YGEdgeEnd, 0)); + YGComputedEdgeValue(node->style.margin, YGEdgeStart, &YGValueZero)); + YGPrintNumberIfNotZero("marginEnd", + YGComputedEdgeValue(node->style.margin, YGEdgeEnd, &YGValueZero)); } - if (YGFourFloatsEqual(node->style.padding)) { - YGPrintNumberIfNotZero("padding", YGComputedEdgeValue(node->style.padding, YGEdgeLeft, 0)); + if (YGFourValuesEqual(node->style.padding)) { + YGPrintNumberIfNotZero("padding", + YGComputedEdgeValue(node->style.padding, YGEdgeLeft, &YGValueZero)); } else { YGPrintNumberIfNotZero("paddingLeft", - YGComputedEdgeValue(node->style.padding, YGEdgeLeft, 0)); + YGComputedEdgeValue(node->style.padding, YGEdgeLeft, &YGValueZero)); YGPrintNumberIfNotZero("paddingRight", - YGComputedEdgeValue(node->style.padding, YGEdgeRight, 0)); - YGPrintNumberIfNotZero("paddingTop", YGComputedEdgeValue(node->style.padding, YGEdgeTop, 0)); + YGComputedEdgeValue(node->style.padding, YGEdgeRight, &YGValueZero)); + YGPrintNumberIfNotZero("paddingTop", + YGComputedEdgeValue(node->style.padding, YGEdgeTop, &YGValueZero)); YGPrintNumberIfNotZero("paddingBottom", - YGComputedEdgeValue(node->style.padding, YGEdgeBottom, 0)); + YGComputedEdgeValue(node->style.padding, YGEdgeBottom, &YGValueZero)); YGPrintNumberIfNotZero("paddingStart", - YGComputedEdgeValue(node->style.padding, YGEdgeStart, 0)); - YGPrintNumberIfNotZero("paddingEnd", YGComputedEdgeValue(node->style.padding, YGEdgeEnd, 0)); + YGComputedEdgeValue(node->style.padding, YGEdgeStart, &YGValueZero)); + YGPrintNumberIfNotZero("paddingEnd", + YGComputedEdgeValue(node->style.padding, YGEdgeEnd, &YGValueZero)); } - if (YGFourFloatsEqual(node->style.border)) { - YGPrintNumberIfNotZero("borderWidth", YGComputedEdgeValue(node->style.border, YGEdgeLeft, 0)); + if (YGFourValuesEqual(node->style.border)) { + YGPrintNumberIfNotZero("borderWidth", + YGComputedEdgeValue(node->style.border, YGEdgeLeft, &YGValueZero)); } else { YGPrintNumberIfNotZero("borderLeftWidth", - YGComputedEdgeValue(node->style.border, YGEdgeLeft, 0)); + YGComputedEdgeValue(node->style.border, YGEdgeLeft, &YGValueZero)); YGPrintNumberIfNotZero("borderRightWidth", - YGComputedEdgeValue(node->style.border, YGEdgeRight, 0)); + YGComputedEdgeValue(node->style.border, YGEdgeRight, &YGValueZero)); YGPrintNumberIfNotZero("borderTopWidth", - YGComputedEdgeValue(node->style.border, YGEdgeTop, 0)); + YGComputedEdgeValue(node->style.border, YGEdgeTop, &YGValueZero)); YGPrintNumberIfNotZero("borderBottomWidth", - YGComputedEdgeValue(node->style.border, YGEdgeBottom, 0)); + YGComputedEdgeValue(node->style.border, YGEdgeBottom, &YGValueZero)); YGPrintNumberIfNotZero("borderStartWidth", - YGComputedEdgeValue(node->style.border, YGEdgeStart, 0)); + YGComputedEdgeValue(node->style.border, YGEdgeStart, &YGValueZero)); YGPrintNumberIfNotZero("borderEndWidth", - YGComputedEdgeValue(node->style.border, YGEdgeEnd, 0)); + YGComputedEdgeValue(node->style.border, YGEdgeEnd, &YGValueZero)); } - YGPrintNumberIfNotUndefined("width", node->style.dimensions[YGDimensionWidth]); - YGPrintNumberIfNotUndefined("height", node->style.dimensions[YGDimensionHeight]); - YGPrintNumberIfNotUndefined("maxWidth", node->style.maxDimensions[YGDimensionWidth]); - YGPrintNumberIfNotUndefined("maxHeight", node->style.maxDimensions[YGDimensionHeight]); - YGPrintNumberIfNotUndefined("minWidth", node->style.minDimensions[YGDimensionWidth]); - YGPrintNumberIfNotUndefined("minHeight", node->style.minDimensions[YGDimensionHeight]); + YGPrintNumberIfNotUndefined("width", &node->style.dimensions[YGDimensionWidth]); + YGPrintNumberIfNotUndefined("height", &node->style.dimensions[YGDimensionHeight]); + YGPrintNumberIfNotUndefined("maxWidth", &node->style.maxDimensions[YGDimensionWidth]); + YGPrintNumberIfNotUndefined("maxHeight", &node->style.maxDimensions[YGDimensionHeight]); + YGPrintNumberIfNotUndefined("minWidth", &node->style.minDimensions[YGDimensionWidth]); + YGPrintNumberIfNotUndefined("minHeight", &node->style.minDimensions[YGDimensionHeight]); if (node->style.positionType == YGPositionTypeAbsolute) { YGLog(YGLogLevelDebug, "position: 'absolute', "); } - YGPrintNumberIfNotUndefined("left", - YGComputedEdgeValue(node->style.position, YGEdgeLeft, YGUndefined)); YGPrintNumberIfNotUndefined( - "right", YGComputedEdgeValue(node->style.position, YGEdgeRight, YGUndefined)); - YGPrintNumberIfNotUndefined("top", - YGComputedEdgeValue(node->style.position, YGEdgeTop, YGUndefined)); + "left", YGComputedEdgeValue(node->style.position, YGEdgeLeft, &YGValueUndefined)); YGPrintNumberIfNotUndefined( - "bottom", YGComputedEdgeValue(node->style.position, YGEdgeBottom, YGUndefined)); + "right", YGComputedEdgeValue(node->style.position, YGEdgeRight, &YGValueUndefined)); + YGPrintNumberIfNotUndefined( + "top", YGComputedEdgeValue(node->style.position, YGEdgeTop, &YGValueUndefined)); + YGPrintNumberIfNotUndefined( + "bottom", YGComputedEdgeValue(node->style.position, YGEdgeBottom, &YGValueUndefined)); } const uint32_t childCount = YGNodeListCount(node->children); @@ -721,75 +837,95 @@ static inline bool YGFlexDirectionIsColumn(const YGFlexDirection flexDirection) return flexDirection == YGFlexDirectionColumn || flexDirection == YGFlexDirectionColumnReverse; } -static inline float YGNodeLeadingMargin(const YGNodeRef node, const YGFlexDirection axis) { - if (YGFlexDirectionIsRow(axis) && !YGValueIsUndefined(node->style.margin[YGEdgeStart])) { - return node->style.margin[YGEdgeStart]; +static inline float YGNodeLeadingMargin(const YGNodeRef node, + const YGFlexDirection axis, + const float widthSize) { + if (YGFlexDirectionIsRow(axis) && node->style.margin[YGEdgeStart].unit != YGUnitUndefined) { + return YGValueResolve(&node->style.margin[YGEdgeStart], widthSize); } - return YGComputedEdgeValue(node->style.margin, leading[axis], 0); + return YGValueResolve(YGComputedEdgeValue(node->style.margin, leading[axis], &YGValueZero), + widthSize); } -static float YGNodeTrailingMargin(const YGNodeRef node, const YGFlexDirection axis) { - if (YGFlexDirectionIsRow(axis) && !YGValueIsUndefined(node->style.margin[YGEdgeEnd])) { - return node->style.margin[YGEdgeEnd]; +static float YGNodeTrailingMargin(const YGNodeRef node, + const YGFlexDirection axis, + const float widthSize) { + if (YGFlexDirectionIsRow(axis) && node->style.margin[YGEdgeEnd].unit != YGUnitUndefined) { + return YGValueResolve(&node->style.margin[YGEdgeEnd], widthSize); } - return YGComputedEdgeValue(node->style.margin, trailing[axis], 0); + return YGValueResolve(YGComputedEdgeValue(node->style.margin, trailing[axis], &YGValueZero), + widthSize); } -static float YGNodeLeadingPadding(const YGNodeRef node, const YGFlexDirection axis) { - if (YGFlexDirectionIsRow(axis) && !YGValueIsUndefined(node->style.padding[YGEdgeStart]) && - node->style.padding[YGEdgeStart] >= 0) { - return node->style.padding[YGEdgeStart]; +static float YGNodeLeadingPadding(const YGNodeRef node, + const YGFlexDirection axis, + const float widthSize) { + if (YGFlexDirectionIsRow(axis) && node->style.padding[YGEdgeStart].unit != YGUnitUndefined && + YGValueResolve(&node->style.padding[YGEdgeStart], widthSize) >= 0.0f) { + return YGValueResolve(&node->style.padding[YGEdgeStart], widthSize); } - return fmaxf(YGComputedEdgeValue(node->style.padding, leading[axis], 0), 0); + return fmaxf(YGValueResolve(YGComputedEdgeValue(node->style.padding, leading[axis], &YGValueZero), + widthSize), + 0.0f); } -static float YGNodeTrailingPadding(const YGNodeRef node, const YGFlexDirection axis) { - if (YGFlexDirectionIsRow(axis) && !YGValueIsUndefined(node->style.padding[YGEdgeEnd]) && - node->style.padding[YGEdgeEnd] >= 0) { - return node->style.padding[YGEdgeEnd]; +static float YGNodeTrailingPadding(const YGNodeRef node, + const YGFlexDirection axis, + const float widthSize) { + if (YGFlexDirectionIsRow(axis) && node->style.padding[YGEdgeEnd].unit != YGUnitUndefined && + YGValueResolve(&node->style.padding[YGEdgeEnd], widthSize) >= 0.0f) { + return YGValueResolve(&node->style.padding[YGEdgeEnd], widthSize); } - return fmaxf(YGComputedEdgeValue(node->style.padding, trailing[axis], 0), 0); + return fmaxf(YGValueResolve(YGComputedEdgeValue(node->style.padding, trailing[axis], &YGValueZero), + widthSize), + 0.0f); } static float YGNodeLeadingBorder(const YGNodeRef node, const YGFlexDirection axis) { - if (YGFlexDirectionIsRow(axis) && !YGValueIsUndefined(node->style.border[YGEdgeStart]) && - node->style.border[YGEdgeStart] >= 0) { - return node->style.border[YGEdgeStart]; + if (YGFlexDirectionIsRow(axis) && node->style.border[YGEdgeStart].unit != YGUnitUndefined && + node->style.border[YGEdgeStart].value >= 0.0f) { + return node->style.border[YGEdgeStart].value; } - return fmaxf(YGComputedEdgeValue(node->style.border, leading[axis], 0), 0); + return fmaxf(YGComputedEdgeValue(node->style.border, leading[axis], &YGValueZero)->value, 0.0f); } static float YGNodeTrailingBorder(const YGNodeRef node, const YGFlexDirection axis) { - if (YGFlexDirectionIsRow(axis) && !YGValueIsUndefined(node->style.border[YGEdgeEnd]) && - node->style.border[YGEdgeEnd] >= 0) { - return node->style.border[YGEdgeEnd]; + if (YGFlexDirectionIsRow(axis) && node->style.border[YGEdgeEnd].unit != YGUnitUndefined && + node->style.border[YGEdgeEnd].value >= 0.0f) { + return node->style.border[YGEdgeEnd].value; } - return fmaxf(YGComputedEdgeValue(node->style.border, trailing[axis], 0), 0); + return fmaxf(YGComputedEdgeValue(node->style.border, trailing[axis], &YGValueZero)->value, 0.0f); } static inline float YGNodeLeadingPaddingAndBorder(const YGNodeRef node, - const YGFlexDirection axis) { - return YGNodeLeadingPadding(node, axis) + YGNodeLeadingBorder(node, axis); + const YGFlexDirection axis, + const float widthSize) { + return YGNodeLeadingPadding(node, axis, widthSize) + YGNodeLeadingBorder(node, axis); } static inline float YGNodeTrailingPaddingAndBorder(const YGNodeRef node, - const YGFlexDirection axis) { - return YGNodeTrailingPadding(node, axis) + YGNodeTrailingBorder(node, axis); + const YGFlexDirection axis, + const float widthSize) { + return YGNodeTrailingPadding(node, axis, widthSize) + YGNodeTrailingBorder(node, axis); } -static inline float YGNodeMarginForAxis(const YGNodeRef node, const YGFlexDirection axis) { - return YGNodeLeadingMargin(node, axis) + YGNodeTrailingMargin(node, axis); +static inline float YGNodeMarginForAxis(const YGNodeRef node, + const YGFlexDirection axis, + const float widthSize) { + return YGNodeLeadingMargin(node, axis, widthSize) + YGNodeTrailingMargin(node, axis, widthSize); } static inline float YGNodePaddingAndBorderForAxis(const YGNodeRef node, - const YGFlexDirection axis) { - return YGNodeLeadingPaddingAndBorder(node, axis) + YGNodeTrailingPaddingAndBorder(node, axis); + const YGFlexDirection axis, + const float widthSize) { + return YGNodeLeadingPaddingAndBorder(node, axis, widthSize) + + YGNodeTrailingPaddingAndBorder(node, axis, widthSize); } static inline YGAlign YGNodeAlignItem(const YGNodeRef node, const YGNodeRef child) { @@ -830,86 +966,97 @@ static inline bool YGNodeIsFlex(const YGNodeRef node) { (YGNodeStyleGetFlexGrow(node) != 0 || YGNodeStyleGetFlexShrink(node) != 0)); } -static inline float YGNodeDimWithMargin(const YGNodeRef node, const YGFlexDirection axis) { - return node->layout.measuredDimensions[dim[axis]] + YGNodeLeadingMargin(node, axis) + - YGNodeTrailingMargin(node, axis); +static inline float YGNodeDimWithMargin(const YGNodeRef node, + const YGFlexDirection axis, + const float widthSize) { + return node->layout.measuredDimensions[dim[axis]] + YGNodeLeadingMargin(node, axis, widthSize) + + YGNodeTrailingMargin(node, axis, widthSize); } static inline bool YGNodeIsStyleDimDefined(const YGNodeRef node, const YGFlexDirection axis) { - const float value = node->style.dimensions[dim[axis]]; - return !YGValueIsUndefined(value) && value >= 0.0; + return node->style.dimensions[dim[axis]].unit != YGUnitUndefined && + node->style.dimensions[dim[axis]].value >= 0.0f; } static inline bool YGNodeIsLayoutDimDefined(const YGNodeRef node, const YGFlexDirection axis) { const float value = node->layout.measuredDimensions[dim[axis]]; - return !YGValueIsUndefined(value) && value >= 0.0; + return !YGFloatIsUndefined(value) && value >= 0.0f; } static inline bool YGNodeIsLeadingPosDefined(const YGNodeRef node, const YGFlexDirection axis) { return (YGFlexDirectionIsRow(axis) && - !YGValueIsUndefined( - YGComputedEdgeValue(node->style.position, YGEdgeStart, YGUndefined))) || - !YGValueIsUndefined(YGComputedEdgeValue(node->style.position, leading[axis], YGUndefined)); + YGComputedEdgeValue(node->style.position, YGEdgeStart, &YGValueUndefined)->unit != + YGUnitUndefined) || + YGComputedEdgeValue(node->style.position, leading[axis], &YGValueUndefined)->unit != + YGUnitUndefined; } static inline bool YGNodeIsTrailingPosDefined(const YGNodeRef node, const YGFlexDirection axis) { return (YGFlexDirectionIsRow(axis) && - !YGValueIsUndefined(YGComputedEdgeValue(node->style.position, YGEdgeEnd, YGUndefined))) || - !YGValueIsUndefined( - YGComputedEdgeValue(node->style.position, trailing[axis], YGUndefined)); + YGComputedEdgeValue(node->style.position, YGEdgeEnd, &YGValueUndefined)->unit != + YGUnitUndefined) || + YGComputedEdgeValue(node->style.position, trailing[axis], &YGValueUndefined)->unit != + YGUnitUndefined; } -static float YGNodeLeadingPosition(const YGNodeRef node, const YGFlexDirection axis) { +static float YGNodeLeadingPosition(const YGNodeRef node, + const YGFlexDirection axis, + const float axisSize) { if (YGFlexDirectionIsRow(axis)) { - const float leadingPosition = - YGComputedEdgeValue(node->style.position, YGEdgeStart, YGUndefined); - if (!YGValueIsUndefined(leadingPosition)) { - return leadingPosition; + const YGValue *leadingPosition = + YGComputedEdgeValue(node->style.position, YGEdgeStart, &YGValueUndefined); + if (leadingPosition->unit != YGUnitUndefined) { + return YGValueResolve(leadingPosition, axisSize); } } - const float leadingPosition = - YGComputedEdgeValue(node->style.position, leading[axis], YGUndefined); + const YGValue *leadingPosition = + YGComputedEdgeValue(node->style.position, leading[axis], &YGValueUndefined); - return YGValueIsUndefined(leadingPosition) ? 0 : leadingPosition; + return leadingPosition->unit == YGUnitUndefined ? 0.0f + : YGValueResolve(leadingPosition, axisSize); } -static float YGNodeTrailingPosition(const YGNodeRef node, const YGFlexDirection axis) { +static float YGNodeTrailingPosition(const YGNodeRef node, + const YGFlexDirection axis, + const float axisSize) { if (YGFlexDirectionIsRow(axis)) { - const float trailingPosition = - YGComputedEdgeValue(node->style.position, YGEdgeEnd, YGUndefined); - if (!YGValueIsUndefined(trailingPosition)) { - return trailingPosition; + const YGValue *trailingPosition = + YGComputedEdgeValue(node->style.position, YGEdgeEnd, &YGValueUndefined); + if (trailingPosition->unit != YGUnitUndefined) { + return YGValueResolve(trailingPosition, axisSize); } } - const float trailingPosition = - YGComputedEdgeValue(node->style.position, trailing[axis], YGUndefined); + const YGValue *trailingPosition = + YGComputedEdgeValue(node->style.position, trailing[axis], &YGValueUndefined); - return YGValueIsUndefined(trailingPosition) ? 0 : trailingPosition; + return trailingPosition->unit == YGUnitUndefined ? 0.0f + : YGValueResolve(trailingPosition, axisSize); } static float YGNodeBoundAxisWithinMinAndMax(const YGNodeRef node, const YGFlexDirection axis, - const float value) { + const float value, + const float axisSize) { float min = YGUndefined; float max = YGUndefined; if (YGFlexDirectionIsColumn(axis)) { - min = node->style.minDimensions[YGDimensionHeight]; - max = node->style.maxDimensions[YGDimensionHeight]; + min = YGValueResolve(&node->style.minDimensions[YGDimensionHeight], axisSize); + max = YGValueResolve(&node->style.maxDimensions[YGDimensionHeight], axisSize); } else if (YGFlexDirectionIsRow(axis)) { - min = node->style.minDimensions[YGDimensionWidth]; - max = node->style.maxDimensions[YGDimensionWidth]; + min = YGValueResolve(&node->style.minDimensions[YGDimensionWidth], axisSize); + max = YGValueResolve(&node->style.maxDimensions[YGDimensionWidth], axisSize); } float boundValue = value; - if (!YGValueIsUndefined(max) && max >= 0.0 && boundValue > max) { + if (!YGFloatIsUndefined(max) && max >= 0.0f && boundValue > max) { boundValue = max; } - if (!YGValueIsUndefined(min) && min >= 0.0 && boundValue < min) { + if (!YGFloatIsUndefined(min) && min >= 0.0f && boundValue < min) { boundValue = min; } @@ -921,9 +1068,11 @@ static float YGNodeBoundAxisWithinMinAndMax(const YGNodeRef node, // padding and border amount. static inline float YGNodeBoundAxis(const YGNodeRef node, const YGFlexDirection axis, - const float value) { - return fmaxf(YGNodeBoundAxisWithinMinAndMax(node, axis, value), - YGNodePaddingAndBorderForAxis(node, axis)); + const float value, + const float axisSize, + const float widthSize) { + return fmaxf(YGNodeBoundAxisWithinMinAndMax(node, axis, value, axisSize), + YGNodePaddingAndBorderForAxis(node, axis, widthSize)); } static void YGNodeSetChildTrailingPosition(const YGNodeRef node, @@ -936,19 +1085,21 @@ static void YGNodeSetChildTrailingPosition(const YGNodeRef node, // If both left and right are defined, then use left. Otherwise return // +left or -right depending on which is defined. -static float YGNodeRelativePosition(const YGNodeRef node, const YGFlexDirection axis) { - return YGNodeIsLeadingPosDefined(node, axis) ? YGNodeLeadingPosition(node, axis) - : -YGNodeTrailingPosition(node, axis); +static float YGNodeRelativePosition(const YGNodeRef node, + const YGFlexDirection axis, + const float axisSize) { + return YGNodeIsLeadingPosDefined(node, axis) ? YGNodeLeadingPosition(node, axis, axisSize) + : -YGNodeTrailingPosition(node, axis, axisSize); } static void YGConstrainMaxSizeForMode(const float maxSize, YGMeasureMode *mode, float *size) { switch (*mode) { case YGMeasureModeExactly: case YGMeasureModeAtMost: - *size = (YGValueIsUndefined(maxSize) || *size < maxSize) ? *size : maxSize; + *size = (YGFloatIsUndefined(maxSize) || *size < maxSize) ? *size : maxSize; break; case YGMeasureModeUndefined: - if (!YGValueIsUndefined(maxSize)) { + if (!YGFloatIsUndefined(maxSize)) { *mode = YGMeasureModeAtMost; *size = maxSize; } @@ -956,20 +1107,24 @@ static void YGConstrainMaxSizeForMode(const float maxSize, YGMeasureMode *mode, } } -static void YGNodeSetPosition(const YGNodeRef node, const YGDirection direction) { +static void YGNodeSetPosition(const YGNodeRef node, + const YGDirection direction, + const float mainSize, + const float crossSize, + const float parentWidth) { const YGFlexDirection mainAxis = YGFlexDirectionResolve(node->style.flexDirection, direction); const YGFlexDirection crossAxis = YGFlexDirectionCross(mainAxis, direction); - const float relativePositionMain = YGNodeRelativePosition(node, mainAxis); - const float relativePositionCross = YGNodeRelativePosition(node, crossAxis); + const float relativePositionMain = YGNodeRelativePosition(node, mainAxis, mainSize); + const float relativePositionCross = YGNodeRelativePosition(node, crossAxis, crossSize); node->layout.position[leading[mainAxis]] = - YGNodeLeadingMargin(node, mainAxis) + relativePositionMain; + YGNodeLeadingMargin(node, mainAxis, parentWidth) + relativePositionMain; node->layout.position[trailing[mainAxis]] = - YGNodeTrailingMargin(node, mainAxis) + relativePositionMain; + YGNodeTrailingMargin(node, mainAxis, parentWidth) + relativePositionMain; node->layout.position[leading[crossAxis]] = - YGNodeLeadingMargin(node, crossAxis) + relativePositionCross; + YGNodeLeadingMargin(node, crossAxis, parentWidth) + relativePositionCross; node->layout.position[trailing[crossAxis]] = - YGNodeTrailingMargin(node, crossAxis) + relativePositionCross; + YGNodeTrailingMargin(node, crossAxis, parentWidth) + relativePositionCross; } static void YGNodeComputeFlexBasisForChild(const YGNodeRef node, @@ -977,10 +1132,14 @@ static void YGNodeComputeFlexBasisForChild(const YGNodeRef node, const float width, const YGMeasureMode widthMode, const float height, + const float parentWidth, + const float parentHeight, const YGMeasureMode heightMode, const YGDirection direction) { const YGFlexDirection mainAxis = YGFlexDirectionResolve(node->style.flexDirection, direction); const bool isMainAxisRow = YGFlexDirectionIsRow(mainAxis); + const float mainAxisSize = isMainAxisRow ? width : height; + const float mainAxisParentSize = isMainAxisRow ? parentWidth : parentHeight; float childWidth; float childHeight; @@ -990,24 +1149,25 @@ static void YGNodeComputeFlexBasisForChild(const YGNodeRef node, const bool isRowStyleDimDefined = YGNodeIsStyleDimDefined(child, YGFlexDirectionRow); const bool isColumnStyleDimDefined = YGNodeIsStyleDimDefined(child, YGFlexDirectionColumn); - if (!YGValueIsUndefined(YGNodeStyleGetFlexBasis(child)) && - !YGValueIsUndefined(isMainAxisRow ? width : height)) { - if (YGValueIsUndefined(child->layout.computedFlexBasis) || + if (YGNodeStyleGetFlexBasisPtr(child)->unit != YGUnitUndefined && + !YGFloatIsUndefined(mainAxisSize)) { + if (YGFloatIsUndefined(child->layout.computedFlexBasis) || (YGIsExperimentalFeatureEnabled(YGExperimentalFeatureWebFlexBasis) && child->layout.computedFlexBasisGeneration != gCurrentGenerationCount)) { child->layout.computedFlexBasis = - fmaxf(YGNodeStyleGetFlexBasis(child), YGNodePaddingAndBorderForAxis(child, mainAxis)); + fmaxf(YGValueResolve(YGNodeStyleGetFlexBasisPtr(child), mainAxisParentSize), + YGNodePaddingAndBorderForAxis(child, mainAxis, parentWidth)); } } else if (isMainAxisRow && isRowStyleDimDefined) { // The width is definite, so use that as the flex basis. child->layout.computedFlexBasis = - fmaxf(child->style.dimensions[YGDimensionWidth], - YGNodePaddingAndBorderForAxis(child, YGFlexDirectionRow)); + fmaxf(YGValueResolve(&child->style.dimensions[YGDimensionWidth], parentWidth), + YGNodePaddingAndBorderForAxis(child, YGFlexDirectionRow, parentWidth)); } else if (!isMainAxisRow && isColumnStyleDimDefined) { // The height is definite, so use that as the flex basis. child->layout.computedFlexBasis = - fmaxf(child->style.dimensions[YGDimensionHeight], - YGNodePaddingAndBorderForAxis(child, YGFlexDirectionColumn)); + fmaxf(YGValueResolve(&child->style.dimensions[YGDimensionHeight], parentHeight), + YGNodePaddingAndBorderForAxis(child, YGFlexDirectionColumn, parentWidth)); } else { // Compute the flex basis and hypothetical main size (i.e. the clamped // flex basis). @@ -1017,13 +1177,13 @@ static void YGNodeComputeFlexBasisForChild(const YGNodeRef node, childHeightMeasureMode = YGMeasureModeUndefined; if (isRowStyleDimDefined) { - childWidth = child->style.dimensions[YGDimensionWidth] + - YGNodeMarginForAxis(child, YGFlexDirectionRow); + childWidth = YGValueResolve(&child->style.dimensions[YGDimensionWidth], parentWidth) + + YGNodeMarginForAxis(child, YGFlexDirectionRow, parentWidth); childWidthMeasureMode = YGMeasureModeExactly; } if (isColumnStyleDimDefined) { - childHeight = child->style.dimensions[YGDimensionHeight] + - YGNodeMarginForAxis(child, YGFlexDirectionColumn); + childHeight = YGValueResolve(&child->style.dimensions[YGDimensionHeight], parentHeight) + + YGNodeMarginForAxis(child, YGFlexDirectionColumn, parentWidth); childHeightMeasureMode = YGMeasureModeExactly; } @@ -1031,7 +1191,7 @@ static void YGNodeComputeFlexBasisForChild(const YGNodeRef node, // but all major browsers appear to implement the following logic. if ((!isMainAxisRow && node->style.overflow == YGOverflowScroll) || node->style.overflow != YGOverflowScroll) { - if (YGValueIsUndefined(childWidth) && !YGValueIsUndefined(width)) { + if (YGFloatIsUndefined(childWidth) && !YGFloatIsUndefined(width)) { childWidth = width; childWidthMeasureMode = YGMeasureModeAtMost; } @@ -1039,7 +1199,7 @@ static void YGNodeComputeFlexBasisForChild(const YGNodeRef node, if ((isMainAxisRow && node->style.overflow == YGOverflowScroll) || node->style.overflow != YGOverflowScroll) { - if (YGValueIsUndefined(childHeight) && !YGValueIsUndefined(height)) { + if (YGFloatIsUndefined(childHeight) && !YGFloatIsUndefined(height)) { childHeight = height; childHeightMeasureMode = YGMeasureModeAtMost; } @@ -1048,35 +1208,37 @@ static void YGNodeComputeFlexBasisForChild(const YGNodeRef node, // If child has no defined size in the cross axis and is set to stretch, // set the cross // axis to be measured exactly with the available inner width - if (!isMainAxisRow && !YGValueIsUndefined(width) && !isRowStyleDimDefined && + if (!isMainAxisRow && !YGFloatIsUndefined(width) && !isRowStyleDimDefined && widthMode == YGMeasureModeExactly && YGNodeAlignItem(node, child) == YGAlignStretch) { childWidth = width; childWidthMeasureMode = YGMeasureModeExactly; } - if (isMainAxisRow && !YGValueIsUndefined(height) && !isColumnStyleDimDefined && + if (isMainAxisRow && !YGFloatIsUndefined(height) && !isColumnStyleDimDefined && heightMode == YGMeasureModeExactly && YGNodeAlignItem(node, child) == YGAlignStretch) { childHeight = height; childHeightMeasureMode = YGMeasureModeExactly; } - if (!YGValueIsUndefined(child->style.aspectRatio)) { + if (!YGFloatIsUndefined(child->style.aspectRatio)) { if (!isMainAxisRow && childWidthMeasureMode == YGMeasureModeExactly) { child->layout.computedFlexBasis = fmaxf(childWidth / child->style.aspectRatio, - YGNodePaddingAndBorderForAxis(child, YGFlexDirectionColumn)); + YGNodePaddingAndBorderForAxis(child, YGFlexDirectionColumn, parentWidth)); return; } else if (isMainAxisRow && childHeightMeasureMode == YGMeasureModeExactly) { child->layout.computedFlexBasis = fmaxf(childHeight * child->style.aspectRatio, - YGNodePaddingAndBorderForAxis(child, YGFlexDirectionRow)); + YGNodePaddingAndBorderForAxis(child, YGFlexDirectionRow, parentWidth)); return; } } - YGConstrainMaxSizeForMode(child->style.maxDimensions[YGDimensionWidth], + YGConstrainMaxSizeForMode(YGValueResolve(&child->style.maxDimensions[YGDimensionWidth], + parentWidth), &childWidthMeasureMode, &childWidth); - YGConstrainMaxSizeForMode(child->style.maxDimensions[YGDimensionHeight], + YGConstrainMaxSizeForMode(YGValueResolve(&child->style.maxDimensions[YGDimensionHeight], + parentHeight), &childHeightMeasureMode, &childHeight); @@ -1087,13 +1249,15 @@ static void YGNodeComputeFlexBasisForChild(const YGNodeRef node, direction, childWidthMeasureMode, childHeightMeasureMode, + parentWidth, + parentHeight, false, "measure"); child->layout.computedFlexBasis = fmaxf(isMainAxisRow ? child->layout.measuredDimensions[YGDimensionWidth] : child->layout.measuredDimensions[YGDimensionHeight], - YGNodePaddingAndBorderForAxis(child, mainAxis)); + YGNodePaddingAndBorderForAxis(child, mainAxis, parentWidth)); } child->layout.computedFlexBasisGeneration = gCurrentGenerationCount; @@ -1103,6 +1267,7 @@ static void YGNodeAbsoluteLayoutChild(const YGNodeRef node, const YGNodeRef child, const float width, const YGMeasureMode widthMode, + const float height, const YGDirection direction) { const YGFlexDirection mainAxis = YGFlexDirectionResolve(node->style.flexDirection, direction); const YGFlexDirection crossAxis = YGFlexDirectionCross(mainAxis, direction); @@ -1114,8 +1279,8 @@ static void YGNodeAbsoluteLayoutChild(const YGNodeRef node, YGMeasureMode childHeightMeasureMode = YGMeasureModeUndefined; if (YGNodeIsStyleDimDefined(child, YGFlexDirectionRow)) { - childWidth = - child->style.dimensions[YGDimensionWidth] + YGNodeMarginForAxis(child, YGFlexDirectionRow); + childWidth = YGValueResolve(&child->style.dimensions[YGDimensionWidth], width) + + YGNodeMarginForAxis(child, YGFlexDirectionRow, width); } else { // If the child doesn't have a specified width, compute the width based // on the left/right @@ -1125,15 +1290,15 @@ static void YGNodeAbsoluteLayoutChild(const YGNodeRef node, childWidth = node->layout.measuredDimensions[YGDimensionWidth] - (YGNodeLeadingBorder(node, YGFlexDirectionRow) + YGNodeTrailingBorder(node, YGFlexDirectionRow)) - - (YGNodeLeadingPosition(child, YGFlexDirectionRow) + - YGNodeTrailingPosition(child, YGFlexDirectionRow)); - childWidth = YGNodeBoundAxis(child, YGFlexDirectionRow, childWidth); + (YGNodeLeadingPosition(child, YGFlexDirectionRow, width) + + YGNodeTrailingPosition(child, YGFlexDirectionRow, width)); + childWidth = YGNodeBoundAxis(child, YGFlexDirectionRow, childWidth, width, width); } } if (YGNodeIsStyleDimDefined(child, YGFlexDirectionColumn)) { - childHeight = child->style.dimensions[YGDimensionHeight] + - YGNodeMarginForAxis(child, YGFlexDirectionColumn); + childHeight = YGValueResolve(&child->style.dimensions[YGDimensionHeight], height) + + YGNodeMarginForAxis(child, YGFlexDirectionColumn, width); } else { // If the child doesn't have a specified height, compute the height // based on the top/bottom @@ -1143,38 +1308,38 @@ static void YGNodeAbsoluteLayoutChild(const YGNodeRef node, childHeight = node->layout.measuredDimensions[YGDimensionHeight] - (YGNodeLeadingBorder(node, YGFlexDirectionColumn) + YGNodeTrailingBorder(node, YGFlexDirectionColumn)) - - (YGNodeLeadingPosition(child, YGFlexDirectionColumn) + - YGNodeTrailingPosition(child, YGFlexDirectionColumn)); - childHeight = YGNodeBoundAxis(child, YGFlexDirectionColumn, childHeight); + (YGNodeLeadingPosition(child, YGFlexDirectionColumn, height) + + YGNodeTrailingPosition(child, YGFlexDirectionColumn, height)); + childHeight = YGNodeBoundAxis(child, YGFlexDirectionColumn, childHeight, height, width); } } // Exactly one dimension needs to be defined for us to be able to do aspect ratio // calculation. One dimension being the anchor and the other being flexible. - if (YGValueIsUndefined(childWidth) ^ YGValueIsUndefined(childHeight)) { - if (!YGValueIsUndefined(child->style.aspectRatio)) { - if (YGValueIsUndefined(childWidth)) { + if (YGFloatIsUndefined(childWidth) ^ YGFloatIsUndefined(childHeight)) { + if (!YGFloatIsUndefined(child->style.aspectRatio)) { + if (YGFloatIsUndefined(childWidth)) { childWidth = fmaxf(childHeight * child->style.aspectRatio, - YGNodePaddingAndBorderForAxis(child, YGFlexDirectionColumn)); - } else if (YGValueIsUndefined(childHeight)) { + YGNodePaddingAndBorderForAxis(child, YGFlexDirectionColumn, width)); + } else if (YGFloatIsUndefined(childHeight)) { childHeight = fmaxf(childWidth / child->style.aspectRatio, - YGNodePaddingAndBorderForAxis(child, YGFlexDirectionRow)); + YGNodePaddingAndBorderForAxis(child, YGFlexDirectionRow, width)); } } } // If we're still missing one or the other dimension, measure the content. - if (YGValueIsUndefined(childWidth) || YGValueIsUndefined(childHeight)) { + if (YGFloatIsUndefined(childWidth) || YGFloatIsUndefined(childHeight)) { childWidthMeasureMode = - YGValueIsUndefined(childWidth) ? YGMeasureModeUndefined : YGMeasureModeExactly; + YGFloatIsUndefined(childWidth) ? YGMeasureModeUndefined : YGMeasureModeExactly; childHeightMeasureMode = - YGValueIsUndefined(childHeight) ? YGMeasureModeUndefined : YGMeasureModeExactly; + YGFloatIsUndefined(childHeight) ? YGMeasureModeUndefined : YGMeasureModeExactly; // According to the spec, if the main size is not definite and the // child's inline axis is parallel to the main axis (i.e. it's // horizontal), the child should be sized using "UNDEFINED" in // the main size. Otherwise use "AT_MOST" in the cross axis. - if (!isMainAxisRow && YGValueIsUndefined(childWidth) && widthMode != YGMeasureModeUndefined) { + if (!isMainAxisRow && YGFloatIsUndefined(childWidth) && widthMode != YGMeasureModeUndefined) { childWidth = width; childWidthMeasureMode = YGMeasureModeAtMost; } @@ -1185,12 +1350,14 @@ static void YGNodeAbsoluteLayoutChild(const YGNodeRef node, direction, childWidthMeasureMode, childHeightMeasureMode, + childWidth, + childHeight, false, "abs-measure"); childWidth = child->layout.measuredDimensions[YGDimensionWidth] + - YGNodeMarginForAxis(child, YGFlexDirectionRow); + YGNodeMarginForAxis(child, YGFlexDirectionRow, width); childHeight = child->layout.measuredDimensions[YGDimensionHeight] + - YGNodeMarginForAxis(child, YGFlexDirectionColumn); + YGNodeMarginForAxis(child, YGFlexDirectionColumn, width); } YGLayoutNodeInternal(child, @@ -1199,6 +1366,8 @@ static void YGNodeAbsoluteLayoutChild(const YGNodeRef node, direction, YGMeasureModeExactly, YGMeasureModeExactly, + childWidth, + childHeight, true, "abs-layout"); @@ -1206,7 +1375,7 @@ static void YGNodeAbsoluteLayoutChild(const YGNodeRef node, child->layout.position[leading[mainAxis]] = node->layout.measuredDimensions[dim[mainAxis]] - child->layout.measuredDimensions[dim[mainAxis]] - YGNodeTrailingBorder(node, mainAxis) - - YGNodeTrailingPosition(child, mainAxis); + YGNodeTrailingPosition(child, mainAxis, width); } if (YGNodeIsTrailingPosDefined(child, crossAxis) && @@ -1214,7 +1383,7 @@ static void YGNodeAbsoluteLayoutChild(const YGNodeRef node, child->layout.position[leading[crossAxis]] = node->layout.measuredDimensions[dim[crossAxis]] - child->layout.measuredDimensions[dim[crossAxis]] - YGNodeTrailingBorder(node, crossAxis) - - YGNodeTrailingPosition(child, crossAxis); + YGNodeTrailingPosition(child, crossAxis, width); } } @@ -1225,28 +1394,33 @@ static void YGNodeWithMeasureFuncSetMeasuredDimensions(const YGNodeRef node, const YGMeasureMode heightMeasureMode) { YG_ASSERT(node->measure, "Expected node to have custom measure function"); - const float paddingAndBorderAxisRow = YGNodePaddingAndBorderForAxis(node, YGFlexDirectionRow); + const float paddingAndBorderAxisRow = + YGNodePaddingAndBorderForAxis(node, YGFlexDirectionRow, availableWidth); const float paddingAndBorderAxisColumn = - YGNodePaddingAndBorderForAxis(node, YGFlexDirectionColumn); - const float marginAxisRow = YGNodeMarginForAxis(node, YGFlexDirectionRow); - const float marginAxisColumn = YGNodeMarginForAxis(node, YGFlexDirectionColumn); + YGNodePaddingAndBorderForAxis(node, YGFlexDirectionColumn, availableWidth); + const float marginAxisRow = YGNodeMarginForAxis(node, YGFlexDirectionRow, availableWidth); + const float marginAxisColumn = YGNodeMarginForAxis(node, YGFlexDirectionColumn, availableWidth); const float innerWidth = availableWidth - marginAxisRow - paddingAndBorderAxisRow; const float innerHeight = availableHeight - marginAxisColumn - paddingAndBorderAxisColumn; if (widthMeasureMode == YGMeasureModeExactly && heightMeasureMode == YGMeasureModeExactly) { // Don't bother sizing the text if both dimensions are already defined. - node->layout.measuredDimensions[YGDimensionWidth] = - YGNodeBoundAxis(node, YGFlexDirectionRow, availableWidth - marginAxisRow); + node->layout.measuredDimensions[YGDimensionWidth] = YGNodeBoundAxis( + node, YGFlexDirectionRow, availableWidth - marginAxisRow, availableWidth, availableWidth); node->layout.measuredDimensions[YGDimensionHeight] = - YGNodeBoundAxis(node, YGFlexDirectionColumn, availableHeight - marginAxisColumn); - } else if (innerWidth <= 0 || innerHeight <= 0) { + YGNodeBoundAxis(node, + YGFlexDirectionColumn, + availableHeight - marginAxisColumn, + availableHeight, + availableWidth); + } else if (innerWidth <= 0.0f || innerHeight <= 0.0f) { // Don't bother sizing the text if there's no horizontal or vertical // space. node->layout.measuredDimensions[YGDimensionWidth] = - YGNodeBoundAxis(node, YGFlexDirectionRow, 0); + YGNodeBoundAxis(node, YGFlexDirectionRow, 0.0f, availableWidth, availableWidth); node->layout.measuredDimensions[YGDimensionHeight] = - YGNodeBoundAxis(node, YGFlexDirectionColumn, 0); + YGNodeBoundAxis(node, YGFlexDirectionColumn, 0.0f, availableHeight, availableWidth); } else { // Measure the text under the current constraints. const YGSize measuredSize = @@ -1258,14 +1432,18 @@ static void YGNodeWithMeasureFuncSetMeasuredDimensions(const YGNodeRef node, (widthMeasureMode == YGMeasureModeUndefined || widthMeasureMode == YGMeasureModeAtMost) ? measuredSize.width + paddingAndBorderAxisRow - : availableWidth - marginAxisRow); + : availableWidth - marginAxisRow, + availableWidth, + availableWidth); node->layout.measuredDimensions[YGDimensionHeight] = YGNodeBoundAxis(node, YGFlexDirectionColumn, (heightMeasureMode == YGMeasureModeUndefined || heightMeasureMode == YGMeasureModeAtMost) ? measuredSize.height + paddingAndBorderAxisColumn - : availableHeight - marginAxisColumn); + : availableHeight - marginAxisColumn, + availableHeight, + availableWidth); } } @@ -1275,12 +1453,15 @@ static void YGNodeEmptyContainerSetMeasuredDimensions(const YGNodeRef node, const float availableWidth, const float availableHeight, const YGMeasureMode widthMeasureMode, - const YGMeasureMode heightMeasureMode) { - const float paddingAndBorderAxisRow = YGNodePaddingAndBorderForAxis(node, YGFlexDirectionRow); + const YGMeasureMode heightMeasureMode, + const float parentWidth, + const float parentHeight) { + const float paddingAndBorderAxisRow = + YGNodePaddingAndBorderForAxis(node, YGFlexDirectionRow, parentWidth); const float paddingAndBorderAxisColumn = - YGNodePaddingAndBorderForAxis(node, YGFlexDirectionColumn); - const float marginAxisRow = YGNodeMarginForAxis(node, YGFlexDirectionRow); - const float marginAxisColumn = YGNodeMarginForAxis(node, YGFlexDirectionColumn); + YGNodePaddingAndBorderForAxis(node, YGFlexDirectionColumn, parentWidth); + const float marginAxisRow = YGNodeMarginForAxis(node, YGFlexDirectionRow, parentWidth); + const float marginAxisColumn = YGNodeMarginForAxis(node, YGFlexDirectionColumn, parentWidth); node->layout.measuredDimensions[YGDimensionWidth] = YGNodeBoundAxis(node, @@ -1288,40 +1469,52 @@ static void YGNodeEmptyContainerSetMeasuredDimensions(const YGNodeRef node, (widthMeasureMode == YGMeasureModeUndefined || widthMeasureMode == YGMeasureModeAtMost) ? paddingAndBorderAxisRow - : availableWidth - marginAxisRow); + : availableWidth - marginAxisRow, + parentWidth, + parentWidth); node->layout.measuredDimensions[YGDimensionHeight] = YGNodeBoundAxis(node, YGFlexDirectionColumn, (heightMeasureMode == YGMeasureModeUndefined || heightMeasureMode == YGMeasureModeAtMost) ? paddingAndBorderAxisColumn - : availableHeight - marginAxisColumn); + : availableHeight - marginAxisColumn, + parentHeight, + parentWidth); } static bool YGNodeFixedSizeSetMeasuredDimensions(const YGNodeRef node, const float availableWidth, const float availableHeight, const YGMeasureMode widthMeasureMode, - const YGMeasureMode heightMeasureMode) { - if ((widthMeasureMode == YGMeasureModeAtMost && availableWidth <= 0) || - (heightMeasureMode == YGMeasureModeAtMost && availableHeight <= 0) || + const YGMeasureMode heightMeasureMode, + const float parentWidth, + const float parentHeight) { + if ((widthMeasureMode == YGMeasureModeAtMost && availableWidth <= 0.0f) || + (heightMeasureMode == YGMeasureModeAtMost && availableHeight <= 0.0f) || (widthMeasureMode == YGMeasureModeExactly && heightMeasureMode == YGMeasureModeExactly)) { - const float marginAxisColumn = YGNodeMarginForAxis(node, YGFlexDirectionColumn); - const float marginAxisRow = YGNodeMarginForAxis(node, YGFlexDirectionRow); + const float marginAxisColumn = YGNodeMarginForAxis(node, YGFlexDirectionColumn, parentWidth); + const float marginAxisRow = YGNodeMarginForAxis(node, YGFlexDirectionRow, parentWidth); node->layout.measuredDimensions[YGDimensionWidth] = YGNodeBoundAxis(node, YGFlexDirectionRow, - YGValueIsUndefined(availableWidth) || (widthMeasureMode == YGMeasureModeAtMost && availableWidth < 0) - ? 0 - : availableWidth - marginAxisRow); + YGFloatIsUndefined(availableWidth) || + (widthMeasureMode == YGMeasureModeAtMost && availableWidth < 0.0f) + ? 0.0f + : availableWidth - marginAxisRow, + parentWidth, + parentWidth); node->layout.measuredDimensions[YGDimensionHeight] = YGNodeBoundAxis(node, YGFlexDirectionColumn, - YGValueIsUndefined(availableHeight) || (heightMeasureMode == YGMeasureModeAtMost && availableHeight < 0) - ? 0 - : availableHeight - marginAxisColumn); + YGFloatIsUndefined(availableHeight) || + (heightMeasureMode == YGMeasureModeAtMost && availableHeight < 0.0f) + ? 0.0f + : availableHeight - marginAxisColumn, + parentHeight, + parentWidth); return true; } @@ -1447,11 +1640,13 @@ static void YGNodelayoutImpl(const YGNodeRef node, const YGDirection parentDirection, const YGMeasureMode widthMeasureMode, const YGMeasureMode heightMeasureMode, + const float parentWidth, + const float parentHeight, const bool performLayout) { - YG_ASSERT(YGValueIsUndefined(availableWidth) ? widthMeasureMode == YGMeasureModeUndefined : true, + YG_ASSERT(YGFloatIsUndefined(availableWidth) ? widthMeasureMode == YGMeasureModeUndefined : true, "availableWidth is indefinite so widthMeasureMode must be " "YGMeasureModeUndefined"); - YG_ASSERT(YGValueIsUndefined(availableHeight) ? heightMeasureMode == YGMeasureModeUndefined + YG_ASSERT(YGFloatIsUndefined(availableHeight) ? heightMeasureMode == YGMeasureModeUndefined : true, "availableHeight is indefinite so heightMeasureMode must be " "YGMeasureModeUndefined"); @@ -1468,16 +1663,25 @@ static void YGNodelayoutImpl(const YGNodeRef node, const uint32_t childCount = YGNodeListCount(node->children); if (childCount == 0) { - YGNodeEmptyContainerSetMeasuredDimensions( - node, availableWidth, availableHeight, widthMeasureMode, heightMeasureMode); + YGNodeEmptyContainerSetMeasuredDimensions(node, + availableWidth, + availableHeight, + widthMeasureMode, + heightMeasureMode, + parentWidth, + parentHeight); return; } // If we're not being asked to perform a full layout we can skip the algorithm if we already know // the size - if (!performLayout && - YGNodeFixedSizeSetMeasuredDimensions( - node, availableWidth, availableHeight, widthMeasureMode, heightMeasureMode)) { + if (!performLayout && YGNodeFixedSizeSetMeasuredDimensions(node, + availableWidth, + availableHeight, + widthMeasureMode, + heightMeasureMode, + parentWidth, + parentHeight)) { return; } @@ -1488,40 +1692,58 @@ static void YGNodelayoutImpl(const YGNodeRef node, const YGJustify justifyContent = node->style.justifyContent; const bool isNodeFlexWrap = node->style.flexWrap == YGWrapWrap; + const float mainAxisParentSize = isMainAxisRow ? parentWidth : parentHeight; + const float crossAxisParentSize = isMainAxisRow ? parentHeight : parentWidth; + YGNodeRef firstAbsoluteChild = NULL; YGNodeRef currentAbsoluteChild = NULL; - const float leadingPaddingAndBorderMain = YGNodeLeadingPaddingAndBorder(node, mainAxis); - const float trailingPaddingAndBorderMain = YGNodeTrailingPaddingAndBorder(node, mainAxis); - const float leadingPaddingAndBorderCross = YGNodeLeadingPaddingAndBorder(node, crossAxis); - const float paddingAndBorderAxisMain = YGNodePaddingAndBorderForAxis(node, mainAxis); - const float paddingAndBorderAxisCross = YGNodePaddingAndBorderForAxis(node, crossAxis); + const float leadingPaddingAndBorderMain = + YGNodeLeadingPaddingAndBorder(node, mainAxis, parentWidth); + const float trailingPaddingAndBorderMain = + YGNodeTrailingPaddingAndBorder(node, mainAxis, parentWidth); + const float leadingPaddingAndBorderCross = + YGNodeLeadingPaddingAndBorder(node, crossAxis, parentWidth); + const float paddingAndBorderAxisMain = YGNodePaddingAndBorderForAxis(node, mainAxis, parentWidth); + const float paddingAndBorderAxisCross = + YGNodePaddingAndBorderForAxis(node, crossAxis, parentWidth); const YGMeasureMode measureModeMainDim = isMainAxisRow ? widthMeasureMode : heightMeasureMode; const YGMeasureMode measureModeCrossDim = isMainAxisRow ? heightMeasureMode : widthMeasureMode; - const float paddingAndBorderAxisRow = isMainAxisRow ? paddingAndBorderAxisMain : paddingAndBorderAxisCross; - const float paddingAndBorderAxisColumn = isMainAxisRow ? paddingAndBorderAxisCross : paddingAndBorderAxisMain; + const float paddingAndBorderAxisRow = + isMainAxisRow ? paddingAndBorderAxisMain : paddingAndBorderAxisCross; + const float paddingAndBorderAxisColumn = + isMainAxisRow ? paddingAndBorderAxisCross : paddingAndBorderAxisMain; - const float marginAxisRow = YGNodeMarginForAxis(node, YGFlexDirectionRow); - const float marginAxisColumn = YGNodeMarginForAxis(node, YGFlexDirectionColumn); + const float marginAxisRow = YGNodeMarginForAxis(node, YGFlexDirectionRow, parentWidth); + const float marginAxisColumn = YGNodeMarginForAxis(node, YGFlexDirectionColumn, parentWidth); // STEP 2: DETERMINE AVAILABLE SIZE IN MAIN AND CROSS DIRECTIONS - float availableInnerWidth = availableWidth - marginAxisRow - paddingAndBorderAxisRow; - const float minInnerWidth = node->style.minDimensions[YGDimensionWidth] - marginAxisRow - paddingAndBorderAxisRow; - const float maxInnerWidth = node->style.maxDimensions[YGDimensionWidth] - marginAxisRow - paddingAndBorderAxisRow; - float availableInnerHeight = - availableHeight - marginAxisColumn - paddingAndBorderAxisColumn; - const float minInnerHeight = node->style.minDimensions[YGDimensionHeight] - marginAxisColumn - paddingAndBorderAxisColumn; - const float maxInnerHeight = node->style.maxDimensions[YGDimensionHeight] - marginAxisColumn - paddingAndBorderAxisColumn; + const float minInnerWidth = + YGValueResolve(&node->style.minDimensions[YGDimensionWidth], parentWidth) - marginAxisRow - + paddingAndBorderAxisRow; + const float maxInnerWidth = + YGValueResolve(&node->style.maxDimensions[YGDimensionWidth], parentWidth) - marginAxisRow - + paddingAndBorderAxisRow; + const float minInnerHeight = + YGValueResolve(&node->style.minDimensions[YGDimensionHeight], parentHeight) - + marginAxisColumn - paddingAndBorderAxisColumn; + const float maxInnerHeight = + YGValueResolve(&node->style.maxDimensions[YGDimensionHeight], parentHeight) - + marginAxisColumn - paddingAndBorderAxisColumn; const float minInnerMainDim = isMainAxisRow ? minInnerWidth : minInnerHeight; const float maxInnerMainDim = isMainAxisRow ? maxInnerWidth : maxInnerHeight; - // Max dimension overrides predefined dimension value; Min dimension in turn overrides both of the above - if (!YGValueIsUndefined(availableInnerWidth)) { + // Max dimension overrides predefined dimension value; Min dimension in turn overrides both of the + // above + float availableInnerWidth = availableWidth - marginAxisRow - paddingAndBorderAxisRow; + if (!YGFloatIsUndefined(availableInnerWidth)) { availableInnerWidth = fmaxf(fminf(availableInnerWidth, maxInnerWidth), minInnerWidth); } - if (!YGValueIsUndefined(availableInnerHeight)) { + + float availableInnerHeight = availableHeight - marginAxisColumn - paddingAndBorderAxisColumn; + if (!YGFloatIsUndefined(availableInnerHeight)) { availableInnerHeight = fmaxf(fminf(availableInnerHeight, maxInnerHeight), minInnerHeight); } @@ -1542,7 +1764,7 @@ static void YGNodelayoutImpl(const YGNodeRef node, singleFlexChild = NULL; break; } - } else if (YGNodeStyleGetFlexGrow(child) > 0 && YGNodeStyleGetFlexShrink(child) > 0) { + } else if (YGNodeStyleGetFlexGrow(child) > 0.0f && YGNodeStyleGetFlexShrink(child) > 0.0f) { singleFlexChild = child; } } @@ -1555,7 +1777,11 @@ static void YGNodelayoutImpl(const YGNodeRef node, if (performLayout) { // Set the initial position (relative to the parent). const YGDirection childDirection = YGNodeResolveDirection(child, direction); - YGNodeSetPosition(child, childDirection); + YGNodeSetPosition(child, + childDirection, + availableInnerMainDim, + availableInnerCrossDim, + availableInnerWidth); } // Absolute-positioned children don't participate in flex layout. Add them @@ -1581,6 +1807,8 @@ static void YGNodelayoutImpl(const YGNodeRef node, availableInnerWidth, widthMeasureMode, availableInnerHeight, + availableInnerWidth, + availableInnerHeight, heightMeasureMode, direction); } @@ -1628,8 +1856,8 @@ static void YGNodelayoutImpl(const YGNodeRef node, child->lineIndex = lineCount; if (child->style.positionType != YGPositionTypeAbsolute) { - const float outerFlexBasis = - child->layout.computedFlexBasis + YGNodeMarginForAxis(child, mainAxis); + const float outerFlexBasis = child->layout.computedFlexBasis + + YGNodeMarginForAxis(child, mainAxis, availableInnerWidth); // If this is a multi-line flow and this item pushes us over the // available size, we've @@ -1681,18 +1909,17 @@ static void YGNodelayoutImpl(const YGNodeRef node, // the line length, so there's no more space left to distribute. // We resolve main dimension to fit minimum and maximum values - if (YGValueIsUndefined(availableInnerMainDim)) { - if (!YGValueIsUndefined(minInnerMainDim) && - sizeConsumedOnCurrentLine < minInnerMainDim) { + if (YGFloatIsUndefined(availableInnerMainDim)) { + if (!YGFloatIsUndefined(minInnerMainDim) && sizeConsumedOnCurrentLine < minInnerMainDim) { availableInnerMainDim = minInnerMainDim; - } else if (!YGValueIsUndefined(maxInnerMainDim) && + } else if (!YGFloatIsUndefined(maxInnerMainDim) && sizeConsumedOnCurrentLine > maxInnerMainDim) { availableInnerMainDim = maxInnerMainDim; } } float remainingFreeSpace = 0; - if (!YGValueIsUndefined(availableInnerMainDim)) { + if (!YGFloatIsUndefined(availableInnerMainDim)) { remainingFreeSpace = availableInnerMainDim - sizeConsumedOnCurrentLine; } else if (sizeConsumedOnCurrentLine < 0) { // availableInnerMainDim is indefinite which means the node is being sized @@ -1752,7 +1979,11 @@ static void YGNodelayoutImpl(const YGNodeRef node, baseMainSize = childFlexBasis + remainingFreeSpace / totalFlexShrinkScaledFactors * flexShrinkScaledFactor; - boundMainSize = YGNodeBoundAxis(currentRelativeChild, mainAxis, baseMainSize); + boundMainSize = YGNodeBoundAxis(currentRelativeChild, + mainAxis, + baseMainSize, + availableInnerMainDim, + availableInnerWidth); if (baseMainSize != boundMainSize) { // By excluding this item's size and flex factor from remaining, // this item's @@ -1771,7 +2002,11 @@ static void YGNodelayoutImpl(const YGNodeRef node, if (flexGrowFactor != 0) { baseMainSize = childFlexBasis + remainingFreeSpace / totalFlexGrowFactors * flexGrowFactor; - boundMainSize = YGNodeBoundAxis(currentRelativeChild, mainAxis, baseMainSize); + boundMainSize = YGNodeBoundAxis(currentRelativeChild, + mainAxis, + baseMainSize, + availableInnerMainDim, + availableInnerWidth); if (baseMainSize != boundMainSize) { // By excluding this item's size and flex factor from remaining, // this item's @@ -1813,7 +2048,11 @@ static void YGNodelayoutImpl(const YGNodeRef node, (remainingFreeSpace / totalFlexShrinkScaledFactors) * flexShrinkScaledFactor; } - updatedMainSize = YGNodeBoundAxis(currentRelativeChild, mainAxis, childSize); + updatedMainSize = YGNodeBoundAxis(currentRelativeChild, + mainAxis, + childSize, + availableInnerMainDim, + availableInnerWidth); } } else if (remainingFreeSpace > 0) { flexGrowFactor = YGNodeStyleGetFlexGrow(currentRelativeChild); @@ -1824,7 +2063,9 @@ static void YGNodelayoutImpl(const YGNodeRef node, YGNodeBoundAxis(currentRelativeChild, mainAxis, childFlexBasis + - remainingFreeSpace / totalFlexGrowFactors * flexGrowFactor); + remainingFreeSpace / totalFlexGrowFactors * flexGrowFactor, + availableInnerMainDim, + availableInnerWidth); } } @@ -1837,10 +2078,11 @@ static void YGNodelayoutImpl(const YGNodeRef node, if (isMainAxisRow) { childWidth = - updatedMainSize + YGNodeMarginForAxis(currentRelativeChild, YGFlexDirectionRow); + updatedMainSize + + YGNodeMarginForAxis(currentRelativeChild, YGFlexDirectionRow, availableInnerWidth); childWidthMeasureMode = YGMeasureModeExactly; - if (!YGValueIsUndefined(availableInnerCrossDim) && + if (!YGFloatIsUndefined(availableInnerCrossDim) && !YGNodeIsStyleDimDefined(currentRelativeChild, YGFlexDirectionColumn) && heightMeasureMode == YGMeasureModeExactly && YGNodeAlignItem(node, currentRelativeChild) == YGAlignStretch) { @@ -1849,18 +2091,22 @@ static void YGNodelayoutImpl(const YGNodeRef node, } else if (!YGNodeIsStyleDimDefined(currentRelativeChild, YGFlexDirectionColumn)) { childHeight = availableInnerCrossDim; childHeightMeasureMode = - YGValueIsUndefined(childHeight) ? YGMeasureModeUndefined : YGMeasureModeAtMost; + YGFloatIsUndefined(childHeight) ? YGMeasureModeUndefined : YGMeasureModeAtMost; } else { - childHeight = currentRelativeChild->style.dimensions[YGDimensionHeight] + - YGNodeMarginForAxis(currentRelativeChild, YGFlexDirectionColumn); + childHeight = YGValueResolve(¤tRelativeChild->style.dimensions[YGDimensionHeight], + availableInnerHeight) + + YGNodeMarginForAxis(currentRelativeChild, + YGFlexDirectionColumn, + availableInnerWidth); childHeightMeasureMode = YGMeasureModeExactly; } } else { childHeight = - updatedMainSize + YGNodeMarginForAxis(currentRelativeChild, YGFlexDirectionColumn); + updatedMainSize + + YGNodeMarginForAxis(currentRelativeChild, YGFlexDirectionColumn, availableInnerWidth); childHeightMeasureMode = YGMeasureModeExactly; - if (!YGValueIsUndefined(availableInnerCrossDim) && + if (!YGFloatIsUndefined(availableInnerCrossDim) && !YGNodeIsStyleDimDefined(currentRelativeChild, YGFlexDirectionRow) && widthMeasureMode == YGMeasureModeExactly && YGNodeAlignItem(node, currentRelativeChild) == YGAlignStretch) { @@ -1869,27 +2115,31 @@ static void YGNodelayoutImpl(const YGNodeRef node, } else if (!YGNodeIsStyleDimDefined(currentRelativeChild, YGFlexDirectionRow)) { childWidth = availableInnerCrossDim; childWidthMeasureMode = - YGValueIsUndefined(childWidth) ? YGMeasureModeUndefined : YGMeasureModeAtMost; + YGFloatIsUndefined(childWidth) ? YGMeasureModeUndefined : YGMeasureModeAtMost; } else { - childWidth = currentRelativeChild->style.dimensions[YGDimensionWidth] + - YGNodeMarginForAxis(currentRelativeChild, YGFlexDirectionRow); + childWidth = + YGValueResolve(¤tRelativeChild->style.dimensions[YGDimensionWidth], + availableInnerWidth) + + YGNodeMarginForAxis(currentRelativeChild, YGFlexDirectionRow, availableInnerWidth); childWidthMeasureMode = YGMeasureModeExactly; } } - if (!YGValueIsUndefined(currentRelativeChild->style.aspectRatio)) { + if (!YGFloatIsUndefined(currentRelativeChild->style.aspectRatio)) { if (isMainAxisRow) { - childHeight = - fmaxf(childWidth / currentRelativeChild->style.aspectRatio, - YGNodePaddingAndBorderForAxis(currentRelativeChild, YGFlexDirectionColumn)); + childHeight = fmaxf(childWidth / currentRelativeChild->style.aspectRatio, + YGNodePaddingAndBorderForAxis(currentRelativeChild, + YGFlexDirectionColumn, + availableInnerWidth)); childHeightMeasureMode = YGMeasureModeExactly; childHeight = fminf(childHeight, availableInnerHeight); childWidth = childHeight * currentRelativeChild->style.aspectRatio; } else { - childWidth = - fmaxf(childHeight * currentRelativeChild->style.aspectRatio, - YGNodePaddingAndBorderForAxis(currentRelativeChild, YGFlexDirectionRow)); + childWidth = fmaxf(childHeight * currentRelativeChild->style.aspectRatio, + YGNodePaddingAndBorderForAxis(currentRelativeChild, + YGFlexDirectionRow, + availableInnerWidth)); childWidthMeasureMode = YGMeasureModeExactly; childWidth = fminf(childWidth, availableInnerWidth); @@ -1897,12 +2147,16 @@ static void YGNodelayoutImpl(const YGNodeRef node, } } - YGConstrainMaxSizeForMode(currentRelativeChild->style.maxDimensions[YGDimensionWidth], - &childWidthMeasureMode, - &childWidth); - YGConstrainMaxSizeForMode(currentRelativeChild->style.maxDimensions[YGDimensionHeight], - &childHeightMeasureMode, - &childHeight); + YGConstrainMaxSizeForMode( + YGValueResolve(¤tRelativeChild->style.maxDimensions[YGDimensionWidth], + availableInnerWidth), + &childWidthMeasureMode, + &childWidth); + YGConstrainMaxSizeForMode( + YGValueResolve(¤tRelativeChild->style.maxDimensions[YGDimensionHeight], + availableInnerHeight), + &childHeightMeasureMode, + &childHeight); const bool requiresStretchLayout = !YGNodeIsStyleDimDefined(currentRelativeChild, crossAxis) && @@ -1916,6 +2170,8 @@ static void YGNodelayoutImpl(const YGNodeRef node, direction, childWidthMeasureMode, childHeightMeasureMode, + availableInnerWidth, + availableInnerHeight, performLayout && !requiresStretchLayout, "flex"); @@ -1938,11 +2194,12 @@ static void YGNodelayoutImpl(const YGNodeRef node, // constraint by the min size defined for the main axis. if (measureModeMainDim == YGMeasureModeAtMost && remainingFreeSpace > 0) { - if (!YGValueIsUndefined(node->style.minDimensions[dim[mainAxis]]) && - node->style.minDimensions[dim[mainAxis]] >= 0) { - remainingFreeSpace = fmaxf(0, - node->style.minDimensions[dim[mainAxis]] - - (availableInnerMainDim - remainingFreeSpace)); + if (node->style.minDimensions[dim[mainAxis]].unit != YGUnitUndefined && + YGValueResolve(&node->style.minDimensions[dim[mainAxis]], mainAxisParentSize) >= 0) { + remainingFreeSpace = + fmaxf(0, + YGValueResolve(&node->style.minDimensions[dim[mainAxis]], mainAxisParentSize) - + (availableInnerMainDim - remainingFreeSpace)); } else { remainingFreeSpace = 0; } @@ -1983,9 +2240,10 @@ static void YGNodelayoutImpl(const YGNodeRef node, // In case the child is position absolute and has left/top being // defined, we override the position to whatever the user said // (and margin/border). - child->layout.position[pos[mainAxis]] = YGNodeLeadingPosition(child, mainAxis) + - YGNodeLeadingBorder(node, mainAxis) + - YGNodeLeadingMargin(child, mainAxis); + child->layout.position[pos[mainAxis]] = + YGNodeLeadingPosition(child, mainAxis, availableInnerMainDim) + + YGNodeLeadingBorder(node, mainAxis) + + YGNodeLeadingMargin(child, mainAxis, availableInnerWidth); } } else { // Now that we placed the element, we need to update the variables. @@ -2000,18 +2258,18 @@ static void YGNodelayoutImpl(const YGNodeRef node, // If we skipped the flex step, then we can't rely on the // measuredDims because // they weren't computed. This means we can't call YGNodeDimWithMargin. - mainDim += betweenMainDim + YGNodeMarginForAxis(child, mainAxis) + + mainDim += betweenMainDim + YGNodeMarginForAxis(child, mainAxis, availableInnerWidth) + child->layout.computedFlexBasis; crossDim = availableInnerCrossDim; } else { // The main dimension is the sum of all the elements dimension plus // the spacing. - mainDim += betweenMainDim + YGNodeDimWithMargin(child, mainAxis); + mainDim += betweenMainDim + YGNodeDimWithMargin(child, mainAxis, availableInnerWidth); // The cross dimension is the max of the elements dimension since // there // can only be one element in that cross dimension. - crossDim = fmaxf(crossDim, YGNodeDimWithMargin(child, crossAxis)); + crossDim = fmaxf(crossDim, YGNodeDimWithMargin(child, crossAxis, availableInnerWidth)); } } else if (performLayout) { child->layout.position[pos[mainAxis]] += @@ -2026,7 +2284,11 @@ static void YGNodelayoutImpl(const YGNodeRef node, if (measureModeCrossDim == YGMeasureModeUndefined || measureModeCrossDim == YGMeasureModeAtMost) { // Compute the cross axis from the max cross dimension of the children. - containerCrossAxis = YGNodeBoundAxis(node, crossAxis, crossDim + paddingAndBorderAxisCross) - + containerCrossAxis = YGNodeBoundAxis(node, + crossAxis, + crossDim + paddingAndBorderAxisCross, + crossAxisParentSize, + parentWidth) - paddingAndBorderAxisCross; if (measureModeCrossDim == YGMeasureModeAtMost) { @@ -2040,7 +2302,11 @@ static void YGNodelayoutImpl(const YGNodeRef node, } // Clamp to the min/max size specified on the container. - crossDim = YGNodeBoundAxis(node, crossAxis, crossDim + paddingAndBorderAxisCross) - + crossDim = YGNodeBoundAxis(node, + crossAxis, + crossDim + paddingAndBorderAxisCross, + crossAxisParentSize, + parentWidth) - paddingAndBorderAxisCross; // STEP 7: CROSS-AXIS ALIGNMENT @@ -2055,12 +2321,14 @@ static void YGNodelayoutImpl(const YGNodeRef node, // set, override all the previously computed positions to set it // correctly. if (YGNodeIsLeadingPosDefined(child, crossAxis)) { - child->layout.position[pos[crossAxis]] = YGNodeLeadingPosition(child, crossAxis) + - YGNodeLeadingBorder(node, crossAxis) + - YGNodeLeadingMargin(child, crossAxis); + child->layout.position[pos[crossAxis]] = + YGNodeLeadingPosition(child, crossAxis, availableInnerCrossDim) + + YGNodeLeadingBorder(node, crossAxis) + + YGNodeLeadingMargin(child, crossAxis, availableInnerWidth); } else { child->layout.position[pos[crossAxis]] = - YGNodeLeadingBorder(node, crossAxis) + YGNodeLeadingMargin(child, crossAxis); + YGNodeLeadingBorder(node, crossAxis) + + YGNodeLeadingMargin(child, crossAxis, availableInnerWidth); } } else { float leadingCrossDim = leadingPaddingAndBorderCross; @@ -2086,28 +2354,30 @@ static void YGNodelayoutImpl(const YGNodeRef node, if (isMainAxisRow) { childWidth = child->layout.measuredDimensions[YGDimensionWidth] + - YGNodeMarginForAxis(child, YGFlexDirectionRow); + YGNodeMarginForAxis(child, YGFlexDirectionRow, availableInnerWidth); - if (!YGValueIsUndefined(child->style.aspectRatio)) { + if (!YGFloatIsUndefined(child->style.aspectRatio)) { childHeight = childWidth / child->style.aspectRatio; } else { childHeight = crossDim; } } else { childHeight = child->layout.measuredDimensions[YGDimensionHeight] + - YGNodeMarginForAxis(child, YGFlexDirectionColumn); + YGNodeMarginForAxis(child, YGFlexDirectionColumn, availableInnerWidth); - if (!YGValueIsUndefined(child->style.aspectRatio)) { + if (!YGFloatIsUndefined(child->style.aspectRatio)) { childWidth = childHeight * child->style.aspectRatio; } else { childWidth = crossDim; } } - YGConstrainMaxSizeForMode(child->style.maxDimensions[YGDimensionWidth], + YGConstrainMaxSizeForMode(YGValueResolve(&child->style.maxDimensions[YGDimensionWidth], + availableInnerWidth), &childWidthMeasureMode, &childWidth); - YGConstrainMaxSizeForMode(child->style.maxDimensions[YGDimensionHeight], + YGConstrainMaxSizeForMode(YGValueResolve(&child->style.maxDimensions[YGDimensionHeight], + availableInnerHeight), &childHeightMeasureMode, &childHeight); @@ -2115,9 +2385,9 @@ static void YGNodelayoutImpl(const YGNodeRef node, // no need to stretch. if (!isCrossSizeDefinite) { childWidthMeasureMode = - YGValueIsUndefined(childWidth) ? YGMeasureModeUndefined : YGMeasureModeExactly; + YGFloatIsUndefined(childWidth) ? YGMeasureModeUndefined : YGMeasureModeExactly; childHeightMeasureMode = - YGValueIsUndefined(childHeight) ? YGMeasureModeUndefined : YGMeasureModeExactly; + YGFloatIsUndefined(childHeight) ? YGMeasureModeUndefined : YGMeasureModeExactly; YGLayoutNodeInternal(child, childWidth, @@ -2125,12 +2395,14 @@ static void YGNodelayoutImpl(const YGNodeRef node, direction, childWidthMeasureMode, childHeightMeasureMode, + availableInnerWidth, + availableInnerHeight, true, "stretch"); } } else if (alignItem != YGAlignFlexStart) { const float remainingCrossDim = - containerCrossAxis - YGNodeDimWithMargin(child, crossAxis); + containerCrossAxis - YGNodeDimWithMargin(child, crossAxis, availableInnerWidth); if (alignItem == YGAlignCenter) { leadingCrossDim += remainingCrossDim / 2; @@ -2150,7 +2422,7 @@ static void YGNodelayoutImpl(const YGNodeRef node, } // STEP 8: MULTI-LINE CONTENT ALIGNMENT - if (lineCount > 1 && performLayout && !YGValueIsUndefined(availableInnerCrossDim)) { + if (lineCount > 1 && performLayout && !YGFloatIsUndefined(availableInnerCrossDim)) { const float remainingAlignContentDim = availableInnerCrossDim - totalLineCrossDim; float crossDimLead = 0; @@ -2191,7 +2463,7 @@ static void YGNodelayoutImpl(const YGNodeRef node, if (YGNodeIsLayoutDimDefined(child, crossAxis)) { lineHeight = fmaxf(lineHeight, child->layout.measuredDimensions[dim[crossAxis]] + - YGNodeMarginForAxis(child, crossAxis)); + YGNodeMarginForAxis(child, crossAxis, availableInnerWidth)); } } } @@ -2206,12 +2478,13 @@ static void YGNodelayoutImpl(const YGNodeRef node, switch (YGNodeAlignItem(node, child)) { case YGAlignFlexStart: { child->layout.position[pos[crossAxis]] = - currentLead + YGNodeLeadingMargin(child, crossAxis); + currentLead + YGNodeLeadingMargin(child, crossAxis, availableInnerWidth); break; } case YGAlignFlexEnd: { child->layout.position[pos[crossAxis]] = - currentLead + lineHeight - YGNodeTrailingMargin(child, crossAxis) - + currentLead + lineHeight - + YGNodeTrailingMargin(child, crossAxis, availableInnerWidth) - child->layout.measuredDimensions[dim[crossAxis]]; break; } @@ -2223,7 +2496,7 @@ static void YGNodelayoutImpl(const YGNodeRef node, } case YGAlignStretch: { child->layout.position[pos[crossAxis]] = - currentLead + YGNodeLeadingMargin(child, crossAxis); + currentLead + YGNodeLeadingMargin(child, crossAxis, availableInnerWidth); // TODO(prenaux): Correctly set the height of items with indefinite // (auto) crossAxis dimension. break; @@ -2240,10 +2513,10 @@ static void YGNodelayoutImpl(const YGNodeRef node, } // STEP 9: COMPUTING FINAL DIMENSIONS - node->layout.measuredDimensions[YGDimensionWidth] = - YGNodeBoundAxis(node, YGFlexDirectionRow, availableWidth - marginAxisRow); - node->layout.measuredDimensions[YGDimensionHeight] = - YGNodeBoundAxis(node, YGFlexDirectionColumn, availableHeight - marginAxisColumn); + node->layout.measuredDimensions[YGDimensionWidth] = YGNodeBoundAxis( + node, YGFlexDirectionRow, availableWidth - marginAxisRow, parentWidth, parentWidth); + node->layout.measuredDimensions[YGDimensionHeight] = YGNodeBoundAxis( + node, YGFlexDirectionColumn, availableHeight - marginAxisColumn, parentHeight, parentWidth); // If the user didn't specify a width or height for the node, set the // dimensions based on the children. @@ -2251,25 +2524,30 @@ static void YGNodelayoutImpl(const YGNodeRef node, // Clamp the size to the min/max size, if specified, and make sure it // doesn't go below the padding and border amount. node->layout.measuredDimensions[dim[mainAxis]] = - YGNodeBoundAxis(node, mainAxis, maxLineMainDim); + YGNodeBoundAxis(node, mainAxis, maxLineMainDim, mainAxisParentSize, parentWidth); } else if (measureModeMainDim == YGMeasureModeAtMost) { - node->layout.measuredDimensions[dim[mainAxis]] = - fmaxf(fminf(availableInnerMainDim + paddingAndBorderAxisMain, - YGNodeBoundAxisWithinMinAndMax(node, mainAxis, maxLineMainDim)), - paddingAndBorderAxisMain); + node->layout.measuredDimensions[dim[mainAxis]] = fmaxf( + fminf(availableInnerMainDim + paddingAndBorderAxisMain, + YGNodeBoundAxisWithinMinAndMax(node, mainAxis, maxLineMainDim, mainAxisParentSize)), + paddingAndBorderAxisMain); } if (measureModeCrossDim == YGMeasureModeUndefined) { // Clamp the size to the min/max size, if specified, and make sure it // doesn't go below the padding and border amount. node->layout.measuredDimensions[dim[crossAxis]] = - YGNodeBoundAxis(node, crossAxis, totalLineCrossDim + paddingAndBorderAxisCross); + YGNodeBoundAxis(node, + crossAxis, + totalLineCrossDim + paddingAndBorderAxisCross, + crossAxisParentSize, + parentWidth); } else if (measureModeCrossDim == YGMeasureModeAtMost) { node->layout.measuredDimensions[dim[crossAxis]] = fmaxf(fminf(availableInnerCrossDim + paddingAndBorderAxisCross, YGNodeBoundAxisWithinMinAndMax(node, crossAxis, - totalLineCrossDim + paddingAndBorderAxisCross)), + totalLineCrossDim + paddingAndBorderAxisCross, + crossAxisParentSize)), paddingAndBorderAxisCross); } @@ -2277,8 +2555,12 @@ static void YGNodelayoutImpl(const YGNodeRef node, // STEP 10: SIZING AND POSITIONING ABSOLUTE CHILDREN for (currentAbsoluteChild = firstAbsoluteChild; currentAbsoluteChild != NULL; currentAbsoluteChild = currentAbsoluteChild->nextChild) { - YGNodeAbsoluteLayoutChild( - node, currentAbsoluteChild, availableInnerWidth, widthMeasureMode, direction); + YGNodeAbsoluteLayoutChild(node, + currentAbsoluteChild, + availableInnerWidth, + widthMeasureMode, + availableInnerHeight, + direction); } // STEP 11: SETTING TRAILING POSITIONS FOR CHILDREN @@ -2415,6 +2697,8 @@ bool YGLayoutNodeInternal(const YGNodeRef node, const YGDirection parentDirection, const YGMeasureMode widthMeasureMode, const YGMeasureMode heightMeasureMode, + const float parentWidth, + const float parentHeight, const bool performLayout, const char *reason) { YGLayout *layout = &node->layout; @@ -2449,8 +2733,8 @@ bool YGLayoutNodeInternal(const YGNodeRef node, // expensive to measure, so it's worth avoiding redundant measurements if at // all possible. if (node->measure) { - const float marginAxisRow = YGNodeMarginForAxis(node, YGFlexDirectionRow); - const float marginAxisColumn = YGNodeMarginForAxis(node, YGFlexDirectionColumn); + const float marginAxisRow = YGNodeMarginForAxis(node, YGFlexDirectionRow, parentWidth); + const float marginAxisColumn = YGNodeMarginForAxis(node, YGFlexDirectionColumn, parentWidth); // First, try to use the layout cache. if (YGNodeCanUseCachedMeasurement(widthMeasureMode, @@ -2543,6 +2827,8 @@ bool YGLayoutNodeInternal(const YGNodeRef node, parentDirection, widthMeasureMode, heightMeasureMode, + parentWidth, + parentHeight, performLayout); if (gPrintChanges) { @@ -2634,25 +2920,26 @@ void YGNodeCalculateLayout(const YGNodeRef node, YGMeasureMode widthMeasureMode = YGMeasureModeUndefined; YGMeasureMode heightMeasureMode = YGMeasureModeUndefined; - if (!YGValueIsUndefined(width)) { + if (!YGFloatIsUndefined(width)) { widthMeasureMode = YGMeasureModeExactly; } else if (YGNodeIsStyleDimDefined(node, YGFlexDirectionRow)) { - width = node->style.dimensions[dim[YGFlexDirectionRow]] + - YGNodeMarginForAxis(node, YGFlexDirectionRow); + width = YGValueResolve(&node->style.dimensions[dim[YGFlexDirectionRow]], availableWidth) + + YGNodeMarginForAxis(node, YGFlexDirectionRow, availableWidth); widthMeasureMode = YGMeasureModeExactly; - } else if (node->style.maxDimensions[YGDimensionWidth] >= 0.0) { - width = node->style.maxDimensions[YGDimensionWidth]; + } else if (YGValueResolve(&node->style.maxDimensions[YGDimensionWidth], availableWidth) >= 0.0f) { + width = YGValueResolve(&node->style.maxDimensions[YGDimensionWidth], availableWidth); widthMeasureMode = YGMeasureModeAtMost; } - if (!YGValueIsUndefined(height)) { + if (!YGFloatIsUndefined(height)) { heightMeasureMode = YGMeasureModeExactly; } else if (YGNodeIsStyleDimDefined(node, YGFlexDirectionColumn)) { - height = node->style.dimensions[dim[YGFlexDirectionColumn]] + - YGNodeMarginForAxis(node, YGFlexDirectionColumn); + height = YGValueResolve(&node->style.dimensions[dim[YGFlexDirectionColumn]], availableHeight) + + YGNodeMarginForAxis(node, YGFlexDirectionColumn, availableWidth); heightMeasureMode = YGMeasureModeExactly; - } else if (node->style.maxDimensions[YGDimensionHeight] >= 0.0) { - height = node->style.maxDimensions[YGDimensionHeight]; + } else if (YGValueResolve(&node->style.maxDimensions[YGDimensionHeight], availableHeight) >= + 0.0f) { + height = YGValueResolve(&node->style.maxDimensions[YGDimensionHeight], availableHeight); heightMeasureMode = YGMeasureModeAtMost; } @@ -2662,10 +2949,12 @@ void YGNodeCalculateLayout(const YGNodeRef node, parentDirection, widthMeasureMode, heightMeasureMode, + availableWidth, + availableHeight, true, "initia" "l")) { - YGNodeSetPosition(node, node->layout.direction); + YGNodeSetPosition(node, node->layout.direction, availableWidth, availableHeight, availableWidth); if (YGIsExperimentalFeatureEnabled(YGExperimentalFeatureRounding)) { roundToPixelGrid(node); diff --git a/yoga/Yoga.h b/yoga/Yoga.h index 5e10b503..083d3073 100644 --- a/yoga/Yoga.h +++ b/yoga/Yoga.h @@ -38,6 +38,11 @@ typedef struct YGSize { float height; } YGSize; +typedef struct YGValue { + float value; + YGUnit unit; +} YGValue; + typedef struct YGNode *YGNodeRef; typedef YGSize (*YGMeasureFunc)(YGNodeRef node, float width, @@ -83,7 +88,7 @@ WIN_EXPORT bool YGNodeIsDirty(const YGNodeRef node); WIN_EXPORT void YGNodePrint(const YGNodeRef node, const YGPrintOptions options); -WIN_EXPORT bool YGValueIsUndefined(const float value); +WIN_EXPORT bool YGFloatIsUndefined(const float value); WIN_EXPORT bool YGNodeCanUseCachedMeasurement(const YGMeasureMode widthMode, const float width, @@ -108,12 +113,26 @@ WIN_EXPORT void YGNodeCopyStyle(const YGNodeRef dstNode, const YGNodeRef srcNode WIN_EXPORT void YGNodeStyleSet##name(const YGNodeRef node, const type paramName); \ WIN_EXPORT type YGNodeStyleGet##name(const YGNodeRef node); +#define YG_NODE_STYLE_PROPERTY_UNIT(type, name, paramName) \ + WIN_EXPORT void YGNodeStyleSet##name(const YGNodeRef node, const float paramName); \ + WIN_EXPORT void YGNodeStyleSet##name##Percent(const YGNodeRef node, const float paramName); \ + WIN_EXPORT type YGNodeStyleGet##name(const YGNodeRef node); + #define YG_NODE_STYLE_EDGE_PROPERTY(type, name, paramName) \ WIN_EXPORT void YGNodeStyleSet##name(const YGNodeRef node, \ const YGEdge edge, \ const type paramName); \ WIN_EXPORT type YGNodeStyleGet##name(const YGNodeRef node, const YGEdge edge); +#define YG_NODE_STYLE_EDGE_PROPERTY_UNIT(type, name, paramName) \ + WIN_EXPORT void YGNodeStyleSet##name(const YGNodeRef node, \ + const YGEdge edge, \ + const float paramName); \ + WIN_EXPORT void YGNodeStyleSet##name##Percent(const YGNodeRef node, \ + const YGEdge edge, \ + const float paramName); \ + WIN_EXPORT type YGNodeStyleGet##name(const YGNodeRef node, const YGEdge edge); + #define YG_NODE_LAYOUT_PROPERTY(type, name) \ WIN_EXPORT type YGNodeLayoutGet##name(const YGNodeRef node); @@ -135,19 +154,19 @@ YG_NODE_STYLE_PROPERTY(YGOverflow, Overflow, overflow); WIN_EXPORT void YGNodeStyleSetFlex(const YGNodeRef node, const float flex); YG_NODE_STYLE_PROPERTY(float, FlexGrow, flexGrow); YG_NODE_STYLE_PROPERTY(float, FlexShrink, flexShrink); -YG_NODE_STYLE_PROPERTY(float, FlexBasis, flexBasis); +YG_NODE_STYLE_PROPERTY_UNIT(YGValue, FlexBasis, flexBasis); -YG_NODE_STYLE_EDGE_PROPERTY(float, Position, position); -YG_NODE_STYLE_EDGE_PROPERTY(float, Margin, margin); -YG_NODE_STYLE_EDGE_PROPERTY(float, Padding, padding); +YG_NODE_STYLE_EDGE_PROPERTY_UNIT(YGValue, Position, position); +YG_NODE_STYLE_EDGE_PROPERTY_UNIT(YGValue, Margin, margin); +YG_NODE_STYLE_EDGE_PROPERTY_UNIT(YGValue, Padding, padding); YG_NODE_STYLE_EDGE_PROPERTY(float, Border, border); -YG_NODE_STYLE_PROPERTY(float, Width, width); -YG_NODE_STYLE_PROPERTY(float, Height, height); -YG_NODE_STYLE_PROPERTY(float, MinWidth, minWidth); -YG_NODE_STYLE_PROPERTY(float, MinHeight, minHeight); -YG_NODE_STYLE_PROPERTY(float, MaxWidth, maxWidth); -YG_NODE_STYLE_PROPERTY(float, MaxHeight, maxHeight); +YG_NODE_STYLE_PROPERTY_UNIT(YGValue, Width, width); +YG_NODE_STYLE_PROPERTY_UNIT(YGValue, Height, height); +YG_NODE_STYLE_PROPERTY_UNIT(YGValue, MinWidth, minWidth); +YG_NODE_STYLE_PROPERTY_UNIT(YGValue, MinHeight, minHeight); +YG_NODE_STYLE_PROPERTY_UNIT(YGValue, MaxWidth, maxWidth); +YG_NODE_STYLE_PROPERTY_UNIT(YGValue, MaxHeight, maxHeight); // Yoga specific properties, not compatible with flexbox specification // Aspect ratio control the size of the undefined dimension of a node.