diff --git a/YogaKit/Tests/YogaKitTests.m b/YogaKit/Tests/YogaKitTests.m index 99927ade..68d97dd5 100644 --- a/YogaKit/Tests/YogaKitTests.m +++ b/YogaKit/Tests/YogaKitTests.m @@ -268,4 +268,79 @@ } } +- (void)testyg_isLeafFlag +{ + UIView *view = [[UIView alloc] initWithFrame:CGRectZero]; + XCTAssertTrue(view.yg_isLeaf); + + for (int i=0; i<10; i++) { + UIView *subview = [[UIView alloc] initWithFrame:CGRectZero]; + [view addSubview:subview]; + } + XCTAssertTrue(view.yg_isLeaf); + + [view yg_setUsesYoga:YES]; + [view yg_setWidth:50.0]; + XCTAssertTrue(view.yg_isLeaf); + + UIView *const subview = view.subviews[0]; + [subview yg_setUsesYoga:YES]; + [subview yg_setWidth:50.0]; + XCTAssertFalse(view.yg_isLeaf); +} + +- (void)testThatWeCorrectlyAttachNestedViews +{ + UIView *container = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 300, 50)]; + [container yg_setUsesYoga:YES]; + [container yg_setFlexDirection:YGFlexDirectionColumn]; + + UIView *subview1 = [[UIView alloc] initWithFrame:CGRectZero]; + [subview1 yg_setUsesYoga:YES]; + [subview1 yg_setWidth:100]; + [subview1 yg_setFlexGrow:1]; + [subview1 yg_setFlexDirection:YGFlexDirectionColumn]; + [container addSubview:subview1]; + + UIView *subview2 = [[UIView alloc] initWithFrame:CGRectZero]; + [subview2 yg_setUsesYoga:YES]; + [subview2 yg_setWidth:150]; + [subview2 yg_setFlexGrow:1]; + [subview2 yg_setFlexDirection:YGFlexDirectionColumn]; + [container addSubview:subview2]; + + for (UIView *view in @[subview1, subview2]) { + UIView *someView = [[UIView alloc] initWithFrame:CGRectZero]; + [someView yg_setUsesYoga:YES]; + [someView yg_setFlexGrow:1]; + [view addSubview:someView]; + } + [container yg_applyLayout]; + + // Add the same amount of new views, reapply layout. + for (UIView *view in @[subview1, subview2]) { + UIView *someView = [[UIView alloc] initWithFrame:CGRectZero]; + [someView yg_setUsesYoga:YES]; + [someView yg_setFlexGrow:1]; + [view addSubview:someView]; + } + [container yg_applyLayout]; + + XCTAssertTrue(CGSizeEqualToSize(CGSizeMake(100, 25), subview1.bounds.size), @"Actual size is %@", NSStringFromCGSize(subview1.bounds.size)); + for (UIView *subview in subview1.subviews) { + const CGSize subviewSize = subview.bounds.size; + XCTAssertFalse(CGSizeEqualToSize(CGSizeZero, subviewSize)); + XCTAssertFalse(isnan(subviewSize.height)); + XCTAssertFalse(isnan(subviewSize.width)); + } + + XCTAssertTrue(CGSizeEqualToSize(CGSizeMake(150, 25), subview2.bounds.size), @"Actual size is %@", NSStringFromCGSize(subview2.bounds.size)); + for (UIView *subview in subview2.subviews) { + const CGSize subviewSize = subview.bounds.size; + XCTAssertFalse(CGSizeEqualToSize(CGSizeZero, subview.bounds.size)); + XCTAssertFalse(isnan(subviewSize.height)); + XCTAssertFalse(isnan(subviewSize.width)); + } +} + @end diff --git a/csharp/Unity/.gitignore b/csharp/Unity/.gitignore new file mode 100644 index 00000000..a26b100a --- /dev/null +++ b/csharp/Unity/.gitignore @@ -0,0 +1,3 @@ +Yoga +yoga.dll +yoga.unitypackage diff --git a/csharp/Unity/pack.sh b/csharp/Unity/pack.sh new file mode 100755 index 00000000..402a9632 --- /dev/null +++ b/csharp/Unity/pack.sh @@ -0,0 +1,53 @@ +#!/bin/sh +# 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. + +cd "$( dirname "$0" )" + +if [ \! -f yoga.dll ]; then + echo "Launch win.bat on Windows and copy yoga.dll to here" + exit 1 +fi + +function build { + buck build $1 + echo "$root/`buck targets --show-output $1|tail -1|awk '{print $2}'`" +} + +function copy { + mkdir -p $3 + cp $1 $3/$2 +} + +rm -rf Yoga yoga.unitypackage + +root=`buck root|tail -f` +mac=$(build '//csharp:yoganet#default,shared') +armv7=$(build '//csharp:yoganet#android-armv7,shared') +ios=$(build '//csharp:yoganet-ios') +win=yoga.dll + +Unity -quit -batchMode -createProject Yoga + +copy $win ${win##*/} Yoga/Assets/Facebook.Yoga/Plugins/x86_64 +copy $mac yoga Yoga/Assets/Facebook.Yoga/Plugins/x86_64/yoga.bundle/Contents/MacOS +armv7path=Assets/Plugins/Android/libs/armeabi-v7a +copy $armv7 ${armv7##*/} Yoga/$armv7path +iospath=Assets/Plugins/iOS +copy $ios ${ios##*/} Yoga/$iospath +libs="$armv7path/${armv7##*/} $iospath/${ios##*/}" + +scripts=Yoga/Assets/Facebook.Yoga/Scripts/Facebook.Yoga +mkdir -p $scripts +(cd ../Facebook.Yoga; tar cf - *.cs)|tar -C $scripts -xf - + +tests=Yoga/Assets/Facebook.Yoga/Editor/Facebook.Yoga.Tests +mkdir -p $tests +(cd ../tests/Facebook.Yoga; tar cf - *.cs)|tar -C $tests -xf - + +Unity -quit -batchMode -projectPath `pwd`/Yoga -exportPackage Assets/Facebook.Yoga $libs `pwd`/yoga.unitypackage + diff --git a/csharp/Unity/win.bat b/csharp/Unity/win.bat new file mode 100755 index 00000000..3f838cd4 --- /dev/null +++ b/csharp/Unity/win.bat @@ -0,0 +1,2 @@ +"C:\Program Files (x86)\MSBuild\14.0\Bin\MSBuild.exe" ..\Yoga\Yoga.vcxproj /p:configuration=Release /property:Platform=x64 +xcopy "..\Yoga\x64\Release\yoga.dll" %~dp0 /s /d /y diff --git a/csharp/tests/Facebook.Yoga/YGMinMaxDimensionTest.cs b/csharp/tests/Facebook.Yoga/YGMinMaxDimensionTest.cs index 04413d41..39eca9ca 100644 --- a/csharp/tests/Facebook.Yoga/YGMinMaxDimensionTest.cs +++ b/csharp/tests/Facebook.Yoga/YGMinMaxDimensionTest.cs @@ -454,5 +454,226 @@ namespace Facebook.Yoga Assert.AreEqual(20f, root_child0_child0.LayoutHeight); } + [Test] + public void Test_flex_grow_within_constrained_min_row() + { + YogaNode root = new YogaNode(); + root.FlexDirection = YogaFlexDirection.Row; + root.MinWidth = 100f; + root.Height = 100f; + + YogaNode root_child0 = new YogaNode(); + root_child0.FlexGrow = 1f; + root.Insert(0, root_child0); + + YogaNode root_child1 = new YogaNode(); + root_child1.Width = 50f; + root.Insert(1, root_child1); + root.StyleDirection = YogaDirection.LTR; + root.CalculateLayout(); + + Assert.AreEqual(0f, root.LayoutX); + Assert.AreEqual(0f, root.LayoutY); + Assert.AreEqual(100f, root.LayoutWidth); + Assert.AreEqual(100f, root.LayoutHeight); + + Assert.AreEqual(0f, root_child0.LayoutX); + Assert.AreEqual(0f, root_child0.LayoutY); + Assert.AreEqual(50f, root_child0.LayoutWidth); + Assert.AreEqual(100f, root_child0.LayoutHeight); + + Assert.AreEqual(50f, root_child1.LayoutX); + Assert.AreEqual(0f, root_child1.LayoutY); + Assert.AreEqual(50f, root_child1.LayoutWidth); + Assert.AreEqual(100f, root_child1.LayoutHeight); + + root.StyleDirection = YogaDirection.RTL; + root.CalculateLayout(); + + Assert.AreEqual(0f, root.LayoutX); + Assert.AreEqual(0f, root.LayoutY); + Assert.AreEqual(100f, root.LayoutWidth); + Assert.AreEqual(100f, root.LayoutHeight); + + Assert.AreEqual(50f, root_child0.LayoutX); + Assert.AreEqual(0f, root_child0.LayoutY); + Assert.AreEqual(50f, root_child0.LayoutWidth); + Assert.AreEqual(100f, root_child0.LayoutHeight); + + Assert.AreEqual(0f, root_child1.LayoutX); + Assert.AreEqual(0f, root_child1.LayoutY); + Assert.AreEqual(50f, root_child1.LayoutWidth); + Assert.AreEqual(100f, root_child1.LayoutHeight); + } + + [Test] + public void Test_flex_grow_within_constrained_min_column() + { + YogaNode root = new YogaNode(); + root.MinHeight = 100f; + + YogaNode root_child0 = new YogaNode(); + root_child0.FlexGrow = 1f; + root.Insert(0, root_child0); + + YogaNode root_child1 = new YogaNode(); + root_child1.Height = 50f; + root.Insert(1, root_child1); + root.StyleDirection = YogaDirection.LTR; + root.CalculateLayout(); + + Assert.AreEqual(0f, root.LayoutX); + Assert.AreEqual(0f, root.LayoutY); + Assert.AreEqual(0f, root.LayoutWidth); + Assert.AreEqual(100f, root.LayoutHeight); + + Assert.AreEqual(0f, root_child0.LayoutX); + Assert.AreEqual(0f, root_child0.LayoutY); + Assert.AreEqual(0f, root_child0.LayoutWidth); + Assert.AreEqual(50f, root_child0.LayoutHeight); + + Assert.AreEqual(0f, root_child1.LayoutX); + Assert.AreEqual(50f, root_child1.LayoutY); + Assert.AreEqual(0f, root_child1.LayoutWidth); + Assert.AreEqual(50f, root_child1.LayoutHeight); + + root.StyleDirection = YogaDirection.RTL; + root.CalculateLayout(); + + Assert.AreEqual(0f, root.LayoutX); + Assert.AreEqual(0f, root.LayoutY); + Assert.AreEqual(0f, root.LayoutWidth); + Assert.AreEqual(100f, root.LayoutHeight); + + Assert.AreEqual(0f, root_child0.LayoutX); + Assert.AreEqual(0f, root_child0.LayoutY); + Assert.AreEqual(0f, root_child0.LayoutWidth); + Assert.AreEqual(50f, root_child0.LayoutHeight); + + Assert.AreEqual(0f, root_child1.LayoutX); + Assert.AreEqual(50f, root_child1.LayoutY); + Assert.AreEqual(0f, root_child1.LayoutWidth); + Assert.AreEqual(50f, root_child1.LayoutHeight); + } + + [Test] + public void Test_flex_grow_within_constrained_max_row() + { + YogaNode root = new YogaNode(); + root.Width = 200f; + + YogaNode root_child0 = new YogaNode(); + root_child0.FlexDirection = YogaFlexDirection.Row; + root_child0.MaxWidth = 100f; + root_child0.Height = 100f; + root.Insert(0, root_child0); + + YogaNode root_child0_child0 = new YogaNode(); + root_child0_child0.FlexShrink = 1f; + root_child0_child0.FlexBasis = 100f; + root_child0.Insert(0, root_child0_child0); + + YogaNode root_child0_child1 = new YogaNode(); + root_child0_child1.Width = 50f; + root_child0.Insert(1, root_child0_child1); + 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(100f, root_child0.LayoutWidth); + Assert.AreEqual(100f, root_child0.LayoutHeight); + + Assert.AreEqual(0f, root_child0_child0.LayoutX); + Assert.AreEqual(0f, root_child0_child0.LayoutY); + Assert.AreEqual(50f, root_child0_child0.LayoutWidth); + Assert.AreEqual(100f, root_child0_child0.LayoutHeight); + + Assert.AreEqual(50f, root_child0_child1.LayoutX); + Assert.AreEqual(0f, root_child0_child1.LayoutY); + Assert.AreEqual(50f, root_child0_child1.LayoutWidth); + Assert.AreEqual(100f, root_child0_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(100f, root.LayoutHeight); + + Assert.AreEqual(100f, root_child0.LayoutX); + Assert.AreEqual(0f, root_child0.LayoutY); + Assert.AreEqual(100f, root_child0.LayoutWidth); + Assert.AreEqual(100f, root_child0.LayoutHeight); + + Assert.AreEqual(50f, root_child0_child0.LayoutX); + Assert.AreEqual(0f, root_child0_child0.LayoutY); + Assert.AreEqual(50f, root_child0_child0.LayoutWidth); + Assert.AreEqual(100f, root_child0_child0.LayoutHeight); + + Assert.AreEqual(0f, root_child0_child1.LayoutX); + Assert.AreEqual(0f, root_child0_child1.LayoutY); + Assert.AreEqual(50f, root_child0_child1.LayoutWidth); + Assert.AreEqual(100f, root_child0_child1.LayoutHeight); + } + + [Test] + public void Test_flex_grow_within_constrained_max_column() + { + YogaNode root = new YogaNode(); + root.Width = 100f; + root.MaxHeight = 100f; + + YogaNode root_child0 = new YogaNode(); + root_child0.FlexShrink = 1f; + root_child0.FlexBasis = 100f; + root.Insert(0, root_child0); + + YogaNode root_child1 = new YogaNode(); + root_child1.Height = 50f; + root.Insert(1, root_child1); + root.StyleDirection = YogaDirection.LTR; + root.CalculateLayout(); + + Assert.AreEqual(0f, root.LayoutX); + Assert.AreEqual(0f, root.LayoutY); + Assert.AreEqual(100f, root.LayoutWidth); + Assert.AreEqual(100f, root.LayoutHeight); + + Assert.AreEqual(0f, root_child0.LayoutX); + Assert.AreEqual(0f, root_child0.LayoutY); + Assert.AreEqual(100f, root_child0.LayoutWidth); + Assert.AreEqual(50f, root_child0.LayoutHeight); + + Assert.AreEqual(0f, root_child1.LayoutX); + Assert.AreEqual(50f, root_child1.LayoutY); + Assert.AreEqual(100f, root_child1.LayoutWidth); + Assert.AreEqual(50f, root_child1.LayoutHeight); + + root.StyleDirection = YogaDirection.RTL; + root.CalculateLayout(); + + Assert.AreEqual(0f, root.LayoutX); + Assert.AreEqual(0f, root.LayoutY); + Assert.AreEqual(100f, root.LayoutWidth); + Assert.AreEqual(100f, root.LayoutHeight); + + Assert.AreEqual(0f, root_child0.LayoutX); + Assert.AreEqual(0f, root_child0.LayoutY); + Assert.AreEqual(100f, root_child0.LayoutWidth); + Assert.AreEqual(50f, root_child0.LayoutHeight); + + Assert.AreEqual(0f, root_child1.LayoutX); + Assert.AreEqual(50f, root_child1.LayoutY); + Assert.AreEqual(100f, root_child1.LayoutWidth); + Assert.AreEqual(50f, root_child1.LayoutHeight); + } + } } diff --git a/enums.py b/enums.py index 8584f81c..2ae25f2a 100644 --- a/enums.py +++ b/enums.py @@ -128,20 +128,20 @@ def to_java_upper(symbol): root = os.path.dirname(os.path.abspath(__file__)) -# write out C header +# write out C headers with open(root + '/yoga/YGEnums.h', 'w') as f: f.write(LICENSE) f.write('#pragma once\n\n') f.write('#include "YGMacros.h"\n\n') f.write('YG_EXTERN_C_BEGIN\n\n') for name, values in ENUMS.items(): + f.write('#define YG%sCount %s\n' % (name, len(values))) f.write('typedef enum YG%s {\n' % name) for value in values: if isinstance(value, tuple): f.write(' YG%s%s = %d,\n' % (name, value[0], value[1])) else: f.write(' YG%s%s,\n' % (name, value)) - f.write(' YG%sCount,\n' % name) f.write('} YG%s;\n' % name) f.write('\n') f.write('YG_EXTERN_C_END\n') diff --git a/gentest/fixtures/YGMinMaxDimensionTest.html b/gentest/fixtures/YGMinMaxDimensionTest.html index 6e469707..6adf67e5 100644 --- a/gentest/fixtures/YGMinMaxDimensionTest.html +++ b/gentest/fixtures/YGMinMaxDimensionTest.html @@ -41,3 +41,25 @@
+ +
+
+
+
+ +
+
+
+
+ +
+
+
+
+
+
+ +
+
+
+
diff --git a/java/tests/com/facebook/yoga/YGMinMaxDimensionTest.java b/java/tests/com/facebook/yoga/YGMinMaxDimensionTest.java index f37a5c54..f5f96357 100644 --- a/java/tests/com/facebook/yoga/YGMinMaxDimensionTest.java +++ b/java/tests/com/facebook/yoga/YGMinMaxDimensionTest.java @@ -444,4 +444,221 @@ public class YGMinMaxDimensionTest { assertEquals(20f, root_child0_child0.getLayoutHeight(), 0.0f); } + @Test + public void test_flex_grow_within_constrained_min_row() { + final YogaNode root = new YogaNode(); + root.setFlexDirection(YogaFlexDirection.ROW); + root.setMinWidth(100f); + root.setHeight(100f); + + final YogaNode root_child0 = new YogaNode(); + root_child0.setFlexGrow(1f); + root.addChildAt(root_child0, 0); + + final YogaNode root_child1 = new YogaNode(); + root_child1.setWidth(50f); + root.addChildAt(root_child1, 1); + root.setDirection(YogaDirection.LTR); + root.calculateLayout(); + + assertEquals(0f, root.getLayoutX(), 0.0f); + assertEquals(0f, root.getLayoutY(), 0.0f); + assertEquals(100f, 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(50f, root_child0.getLayoutWidth(), 0.0f); + assertEquals(100f, root_child0.getLayoutHeight(), 0.0f); + + assertEquals(50f, root_child1.getLayoutX(), 0.0f); + assertEquals(0f, root_child1.getLayoutY(), 0.0f); + assertEquals(50f, root_child1.getLayoutWidth(), 0.0f); + assertEquals(100f, root_child1.getLayoutHeight(), 0.0f); + + root.setDirection(YogaDirection.RTL); + root.calculateLayout(); + + assertEquals(0f, root.getLayoutX(), 0.0f); + assertEquals(0f, root.getLayoutY(), 0.0f); + assertEquals(100f, root.getLayoutWidth(), 0.0f); + assertEquals(100f, root.getLayoutHeight(), 0.0f); + + assertEquals(50f, root_child0.getLayoutX(), 0.0f); + assertEquals(0f, root_child0.getLayoutY(), 0.0f); + assertEquals(50f, root_child0.getLayoutWidth(), 0.0f); + assertEquals(100f, root_child0.getLayoutHeight(), 0.0f); + + assertEquals(0f, root_child1.getLayoutX(), 0.0f); + assertEquals(0f, root_child1.getLayoutY(), 0.0f); + assertEquals(50f, root_child1.getLayoutWidth(), 0.0f); + assertEquals(100f, root_child1.getLayoutHeight(), 0.0f); + } + + @Test + public void test_flex_grow_within_constrained_min_column() { + final YogaNode root = new YogaNode(); + root.setMinHeight(100f); + + final YogaNode root_child0 = new YogaNode(); + root_child0.setFlexGrow(1f); + root.addChildAt(root_child0, 0); + + final YogaNode root_child1 = new YogaNode(); + root_child1.setHeight(50f); + root.addChildAt(root_child1, 1); + root.setDirection(YogaDirection.LTR); + root.calculateLayout(); + + assertEquals(0f, root.getLayoutX(), 0.0f); + assertEquals(0f, root.getLayoutY(), 0.0f); + assertEquals(0f, 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(0f, 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(0f, root_child1.getLayoutWidth(), 0.0f); + assertEquals(50f, root_child1.getLayoutHeight(), 0.0f); + + root.setDirection(YogaDirection.RTL); + root.calculateLayout(); + + assertEquals(0f, root.getLayoutX(), 0.0f); + assertEquals(0f, root.getLayoutY(), 0.0f); + assertEquals(0f, 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(0f, 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(0f, root_child1.getLayoutWidth(), 0.0f); + assertEquals(50f, root_child1.getLayoutHeight(), 0.0f); + } + + @Test + public void test_flex_grow_within_constrained_max_row() { + final YogaNode root = new YogaNode(); + root.setWidth(200f); + + final YogaNode root_child0 = new YogaNode(); + root_child0.setFlexDirection(YogaFlexDirection.ROW); + root_child0.setMaxWidth(100f); + root_child0.setHeight(100f); + root.addChildAt(root_child0, 0); + + final YogaNode root_child0_child0 = new YogaNode(); + root_child0_child0.setFlexShrink(1f); + root_child0_child0.setFlexBasis(100f); + root_child0.addChildAt(root_child0_child0, 0); + + final YogaNode root_child0_child1 = new YogaNode(); + root_child0_child1.setWidth(50f); + root_child0.addChildAt(root_child0_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(100f, root.getLayoutHeight(), 0.0f); + + assertEquals(0f, root_child0.getLayoutX(), 0.0f); + assertEquals(0f, root_child0.getLayoutY(), 0.0f); + assertEquals(100f, root_child0.getLayoutWidth(), 0.0f); + assertEquals(100f, root_child0.getLayoutHeight(), 0.0f); + + assertEquals(0f, root_child0_child0.getLayoutX(), 0.0f); + assertEquals(0f, root_child0_child0.getLayoutY(), 0.0f); + assertEquals(50f, root_child0_child0.getLayoutWidth(), 0.0f); + assertEquals(100f, root_child0_child0.getLayoutHeight(), 0.0f); + + assertEquals(50f, root_child0_child1.getLayoutX(), 0.0f); + assertEquals(0f, root_child0_child1.getLayoutY(), 0.0f); + assertEquals(50f, root_child0_child1.getLayoutWidth(), 0.0f); + assertEquals(100f, root_child0_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(100f, root.getLayoutHeight(), 0.0f); + + assertEquals(100f, root_child0.getLayoutX(), 0.0f); + assertEquals(0f, root_child0.getLayoutY(), 0.0f); + assertEquals(100f, root_child0.getLayoutWidth(), 0.0f); + assertEquals(100f, root_child0.getLayoutHeight(), 0.0f); + + assertEquals(50f, root_child0_child0.getLayoutX(), 0.0f); + assertEquals(0f, root_child0_child0.getLayoutY(), 0.0f); + assertEquals(50f, root_child0_child0.getLayoutWidth(), 0.0f); + assertEquals(100f, root_child0_child0.getLayoutHeight(), 0.0f); + + assertEquals(0f, root_child0_child1.getLayoutX(), 0.0f); + assertEquals(0f, root_child0_child1.getLayoutY(), 0.0f); + assertEquals(50f, root_child0_child1.getLayoutWidth(), 0.0f); + assertEquals(100f, root_child0_child1.getLayoutHeight(), 0.0f); + } + + @Test + public void test_flex_grow_within_constrained_max_column() { + final YogaNode root = new YogaNode(); + root.setWidth(100f); + root.setMaxHeight(100f); + + final YogaNode root_child0 = new YogaNode(); + root_child0.setFlexShrink(1f); + root_child0.setFlexBasis(100f); + root.addChildAt(root_child0, 0); + + final YogaNode root_child1 = new YogaNode(); + root_child1.setHeight(50f); + root.addChildAt(root_child1, 1); + root.setDirection(YogaDirection.LTR); + root.calculateLayout(); + + assertEquals(0f, root.getLayoutX(), 0.0f); + assertEquals(0f, root.getLayoutY(), 0.0f); + assertEquals(100f, 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(100f, 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(100f, root_child1.getLayoutWidth(), 0.0f); + assertEquals(50f, root_child1.getLayoutHeight(), 0.0f); + + root.setDirection(YogaDirection.RTL); + root.calculateLayout(); + + assertEquals(0f, root.getLayoutX(), 0.0f); + assertEquals(0f, root.getLayoutY(), 0.0f); + assertEquals(100f, 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(100f, 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(100f, root_child1.getLayoutWidth(), 0.0f); + assertEquals(50f, root_child1.getLayoutHeight(), 0.0f); + } + } diff --git a/tests/YGAspectRatioTest.cpp b/tests/YGAspectRatioTest.cpp index 22846c9b..b6e32de2 100644 --- a/tests/YGAspectRatioTest.cpp +++ b/tests/YGAspectRatioTest.cpp @@ -63,12 +63,15 @@ TEST(YogaTest, aspect_ratio_main_defined) { YGNodeFreeRecursive(root); } -TEST(YogaTest, aspect_ratio_both_dimensions_defined) { +TEST(YogaTest, aspect_ratio_both_dimensions_defined_row) { const YGNodeRef root = YGNodeNew(); + YGNodeStyleSetFlexDirection(root, YGFlexDirectionRow); + YGNodeStyleSetAlignItems(root, YGAlignFlexStart); YGNodeStyleSetWidth(root, 100); YGNodeStyleSetHeight(root, 100); const YGNodeRef root_child0 = YGNodeNew(); + YGNodeStyleSetWidth(root_child0, 100); YGNodeStyleSetHeight(root_child0, 50); YGNodeStyleSetAspectRatio(root_child0, 1); YGNodeInsertChild(root, root_child0, 0); @@ -78,6 +81,28 @@ TEST(YogaTest, aspect_ratio_both_dimensions_defined) { ASSERT_EQ(0, YGNodeLayoutGetLeft(root_child0)); ASSERT_EQ(0, YGNodeLayoutGetTop(root_child0)); ASSERT_EQ(100, YGNodeLayoutGetWidth(root_child0)); + ASSERT_EQ(100, YGNodeLayoutGetHeight(root_child0)); + + YGNodeFreeRecursive(root); +} + +TEST(YogaTest, aspect_ratio_both_dimensions_defined_column) { + const YGNodeRef root = YGNodeNew(); + YGNodeStyleSetAlignItems(root, YGAlignFlexStart); + YGNodeStyleSetWidth(root, 100); + YGNodeStyleSetHeight(root, 100); + + const YGNodeRef root_child0 = YGNodeNew(); + YGNodeStyleSetWidth(root_child0, 100); + YGNodeStyleSetHeight(root_child0, 50); + YGNodeStyleSetAspectRatio(root_child0, 1); + YGNodeInsertChild(root, root_child0, 0); + + YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR); + + ASSERT_EQ(0, YGNodeLayoutGetLeft(root_child0)); + ASSERT_EQ(0, YGNodeLayoutGetTop(root_child0)); + ASSERT_EQ(50, YGNodeLayoutGetWidth(root_child0)); ASSERT_EQ(50, YGNodeLayoutGetHeight(root_child0)); YGNodeFreeRecursive(root); @@ -351,7 +376,7 @@ TEST(YogaTest, aspect_ratio_double_main) { const YGNodeRef root_child0 = YGNodeNew(); YGNodeStyleSetWidth(root_child0, 50); - YGNodeStyleSetAspectRatio(root_child0, 2); + YGNodeStyleSetAspectRatio(root_child0, 0.5); YGNodeInsertChild(root, root_child0, 0); YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR); @@ -372,7 +397,7 @@ TEST(YogaTest, aspect_ratio_half_main) { const YGNodeRef root_child0 = YGNodeNew(); YGNodeStyleSetWidth(root_child0, 100); - YGNodeStyleSetAspectRatio(root_child0, 0.5); + YGNodeStyleSetAspectRatio(root_child0, 2); YGNodeInsertChild(root, root_child0, 0); YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR); @@ -405,3 +430,249 @@ TEST(YogaTest, aspect_ratio_with_measure_func) { YGNodeFreeRecursive(root); } + +TEST(YogaTest, aspect_ratio_width_height_flex_grow_row) { + const YGNodeRef root = YGNodeNew(); + YGNodeStyleSetFlexDirection(root, YGFlexDirectionRow); + YGNodeStyleSetAlignItems(root, YGAlignFlexStart); + YGNodeStyleSetWidth(root, 100); + YGNodeStyleSetHeight(root, 200); + + const YGNodeRef root_child0 = YGNodeNew(); + YGNodeStyleSetWidth(root_child0, 50); + YGNodeStyleSetHeight(root_child0, 50); + YGNodeStyleSetFlexGrow(root_child0, 1); + YGNodeStyleSetAspectRatio(root_child0, 1); + YGNodeInsertChild(root, root_child0, 0); + + YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR); + + ASSERT_EQ(0, YGNodeLayoutGetLeft(root_child0)); + ASSERT_EQ(0, YGNodeLayoutGetTop(root_child0)); + ASSERT_EQ(100, YGNodeLayoutGetWidth(root_child0)); + ASSERT_EQ(100, YGNodeLayoutGetHeight(root_child0)); + + YGNodeFreeRecursive(root); +} + +TEST(YogaTest, aspect_ratio_width_height_flex_grow_column) { + const YGNodeRef root = YGNodeNew(); + YGNodeStyleSetAlignItems(root, YGAlignFlexStart); + YGNodeStyleSetWidth(root, 200); + YGNodeStyleSetHeight(root, 100); + + const YGNodeRef root_child0 = YGNodeNew(); + YGNodeStyleSetWidth(root_child0, 50); + YGNodeStyleSetHeight(root_child0, 50); + YGNodeStyleSetFlexGrow(root_child0, 1); + YGNodeStyleSetAspectRatio(root_child0, 1); + YGNodeInsertChild(root, root_child0, 0); + + YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR); + + ASSERT_EQ(0, YGNodeLayoutGetLeft(root_child0)); + ASSERT_EQ(0, YGNodeLayoutGetTop(root_child0)); + ASSERT_EQ(100, YGNodeLayoutGetWidth(root_child0)); + ASSERT_EQ(100, YGNodeLayoutGetHeight(root_child0)); + + YGNodeFreeRecursive(root); +} + +TEST(YogaTest, aspect_ratio_height_as_flex_basis) { + const YGNodeRef root = YGNodeNew(); + YGNodeStyleSetAlignItems(root, YGAlignFlexStart); + YGNodeStyleSetFlexDirection(root, YGFlexDirectionRow); + YGNodeStyleSetWidth(root, 200); + YGNodeStyleSetHeight(root, 200); + + const YGNodeRef root_child0 = YGNodeNew(); + YGNodeStyleSetHeight(root_child0, 50); + YGNodeStyleSetFlexGrow(root_child0, 1); + YGNodeStyleSetAspectRatio(root_child0, 1); + YGNodeInsertChild(root, root_child0, 0); + + const YGNodeRef root_child1 = YGNodeNew(); + YGNodeStyleSetHeight(root_child1, 100); + YGNodeStyleSetFlexGrow(root_child1, 1); + YGNodeStyleSetAspectRatio(root_child1, 1); + YGNodeInsertChild(root, root_child1, 1); + + YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR); + + ASSERT_EQ(0, YGNodeLayoutGetLeft(root_child0)); + ASSERT_EQ(0, YGNodeLayoutGetTop(root_child0)); + ASSERT_EQ(75, YGNodeLayoutGetWidth(root_child0)); + ASSERT_EQ(75, YGNodeLayoutGetHeight(root_child0)); + + ASSERT_EQ(75, YGNodeLayoutGetLeft(root_child1)); + ASSERT_EQ(0, YGNodeLayoutGetTop(root_child1)); + ASSERT_EQ(125, YGNodeLayoutGetWidth(root_child1)); + ASSERT_EQ(125, YGNodeLayoutGetHeight(root_child1)); + + YGNodeFreeRecursive(root); +} + +TEST(YogaTest, aspect_ratio_width_as_flex_basis) { + const YGNodeRef root = YGNodeNew(); + YGNodeStyleSetAlignItems(root, YGAlignFlexStart); + YGNodeStyleSetWidth(root, 200); + YGNodeStyleSetHeight(root, 200); + + const YGNodeRef root_child0 = YGNodeNew(); + YGNodeStyleSetWidth(root_child0, 50); + YGNodeStyleSetFlexGrow(root_child0, 1); + YGNodeStyleSetAspectRatio(root_child0, 1); + YGNodeInsertChild(root, root_child0, 0); + + const YGNodeRef root_child1 = YGNodeNew(); + YGNodeStyleSetWidth(root_child1, 100); + YGNodeStyleSetFlexGrow(root_child1, 1); + YGNodeStyleSetAspectRatio(root_child1, 1); + YGNodeInsertChild(root, root_child1, 1); + + YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR); + + ASSERT_EQ(0, YGNodeLayoutGetLeft(root_child0)); + ASSERT_EQ(0, YGNodeLayoutGetTop(root_child0)); + ASSERT_EQ(75, YGNodeLayoutGetWidth(root_child0)); + ASSERT_EQ(75, YGNodeLayoutGetHeight(root_child0)); + + ASSERT_EQ(0, YGNodeLayoutGetLeft(root_child1)); + ASSERT_EQ(75, YGNodeLayoutGetTop(root_child1)); + ASSERT_EQ(125, YGNodeLayoutGetWidth(root_child1)); + ASSERT_EQ(125, YGNodeLayoutGetHeight(root_child1)); + + YGNodeFreeRecursive(root); +} + +TEST(YogaTest, aspect_ratio_overrides_flex_grow_row) { + const YGNodeRef root = YGNodeNew(); + YGNodeStyleSetAlignItems(root, YGAlignFlexStart); + YGNodeStyleSetFlexDirection(root, YGFlexDirectionRow); + YGNodeStyleSetWidth(root, 100); + YGNodeStyleSetHeight(root, 100); + + const YGNodeRef root_child0 = YGNodeNew(); + YGNodeStyleSetWidth(root_child0, 50); + YGNodeStyleSetFlexGrow(root_child0, 1); + YGNodeStyleSetAspectRatio(root_child0, 0.5); + YGNodeInsertChild(root, root_child0, 0); + + YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR); + + ASSERT_EQ(0, YGNodeLayoutGetLeft(root_child0)); + ASSERT_EQ(0, YGNodeLayoutGetTop(root_child0)); + ASSERT_EQ(50, YGNodeLayoutGetWidth(root_child0)); + ASSERT_EQ(100, YGNodeLayoutGetHeight(root_child0)); + + YGNodeFreeRecursive(root); +} + +TEST(YogaTest, aspect_ratio_overrides_flex_grow_column) { + const YGNodeRef root = YGNodeNew(); + YGNodeStyleSetAlignItems(root, YGAlignFlexStart); + YGNodeStyleSetWidth(root, 100); + YGNodeStyleSetHeight(root, 100); + + const YGNodeRef root_child0 = YGNodeNew(); + YGNodeStyleSetHeight(root_child0, 50); + YGNodeStyleSetFlexGrow(root_child0, 1); + YGNodeStyleSetAspectRatio(root_child0, 2); + YGNodeInsertChild(root, root_child0, 0); + + YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR); + + ASSERT_EQ(0, YGNodeLayoutGetLeft(root_child0)); + ASSERT_EQ(0, YGNodeLayoutGetTop(root_child0)); + ASSERT_EQ(100, YGNodeLayoutGetWidth(root_child0)); + ASSERT_EQ(50, YGNodeLayoutGetHeight(root_child0)); + + YGNodeFreeRecursive(root); +} + +TEST(YogaTest, aspect_ratio_left_right_absolute) { + const YGNodeRef root = YGNodeNew(); + YGNodeStyleSetWidth(root, 100); + YGNodeStyleSetHeight(root, 100); + + const YGNodeRef root_child0 = YGNodeNew(); + YGNodeStyleSetPositionType(root_child0, YGPositionTypeAbsolute); + YGNodeStyleSetPosition(root_child0, YGEdgeLeft, 10); + YGNodeStyleSetPosition(root_child0, YGEdgeTop, 10); + YGNodeStyleSetPosition(root_child0, YGEdgeRight, 10); + YGNodeStyleSetAspectRatio(root_child0, 1); + YGNodeInsertChild(root, root_child0, 0); + + YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR); + + ASSERT_EQ(10, YGNodeLayoutGetLeft(root_child0)); + ASSERT_EQ(10, YGNodeLayoutGetTop(root_child0)); + ASSERT_EQ(80, YGNodeLayoutGetWidth(root_child0)); + ASSERT_EQ(80, YGNodeLayoutGetHeight(root_child0)); + + YGNodeFreeRecursive(root); +} + +TEST(YogaTest, aspect_ratio_top_bottom_absolute) { + const YGNodeRef root = YGNodeNew(); + YGNodeStyleSetWidth(root, 100); + YGNodeStyleSetHeight(root, 100); + + const YGNodeRef root_child0 = YGNodeNew(); + YGNodeStyleSetPositionType(root_child0, YGPositionTypeAbsolute); + YGNodeStyleSetPosition(root_child0, YGEdgeLeft, 10); + YGNodeStyleSetPosition(root_child0, YGEdgeTop, 10); + YGNodeStyleSetPosition(root_child0, YGEdgeBottom, 10); + YGNodeStyleSetAspectRatio(root_child0, 1); + YGNodeInsertChild(root, root_child0, 0); + + YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR); + + ASSERT_EQ(10, YGNodeLayoutGetLeft(root_child0)); + ASSERT_EQ(10, YGNodeLayoutGetTop(root_child0)); + ASSERT_EQ(80, YGNodeLayoutGetWidth(root_child0)); + ASSERT_EQ(80, YGNodeLayoutGetHeight(root_child0)); + + YGNodeFreeRecursive(root); +} + +TEST(YogaTest, aspect_ratio_width_overrides_align_stretch_row) { + const YGNodeRef root = YGNodeNew(); + YGNodeStyleSetFlexDirection(root, YGFlexDirectionRow); + YGNodeStyleSetWidth(root, 100); + YGNodeStyleSetHeight(root, 100); + + const YGNodeRef root_child0 = YGNodeNew(); + YGNodeStyleSetWidth(root_child0, 50); + YGNodeStyleSetAspectRatio(root_child0, 1); + YGNodeInsertChild(root, root_child0, 0); + + YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR); + + ASSERT_EQ(0, YGNodeLayoutGetLeft(root_child0)); + ASSERT_EQ(0, YGNodeLayoutGetTop(root_child0)); + ASSERT_EQ(50, YGNodeLayoutGetWidth(root_child0)); + ASSERT_EQ(50, YGNodeLayoutGetHeight(root_child0)); + + YGNodeFreeRecursive(root); +} + +TEST(YogaTest, aspect_ratio_height_overrides_align_stretch_column) { + const YGNodeRef root = YGNodeNew(); + YGNodeStyleSetWidth(root, 100); + YGNodeStyleSetHeight(root, 100); + + const YGNodeRef root_child0 = YGNodeNew(); + YGNodeStyleSetHeight(root_child0, 50); + YGNodeStyleSetAspectRatio(root_child0, 1); + YGNodeInsertChild(root, root_child0, 0); + + YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR); + + ASSERT_EQ(0, YGNodeLayoutGetLeft(root_child0)); + ASSERT_EQ(0, YGNodeLayoutGetTop(root_child0)); + ASSERT_EQ(50, YGNodeLayoutGetWidth(root_child0)); + ASSERT_EQ(50, YGNodeLayoutGetHeight(root_child0)); + + YGNodeFreeRecursive(root); +} diff --git a/tests/YGMemoryFuncTest.cpp b/tests/YGMemoryFuncTest.cpp index bef2985c..b6481373 100644 --- a/tests/YGMemoryFuncTest.cpp +++ b/tests/YGMemoryFuncTest.cpp @@ -56,7 +56,7 @@ TEST(YogaTest, memory_func_test_funcs) { } YGNodeFreeRecursive(root); ASSERT_NE(testMallocCount, 0); - ASSERT_NE(testCallocCount, 0); + ASSERT_EQ(testCallocCount, 0); ASSERT_NE(testReallocCount, 0); ASSERT_NE(testFreeCount, 0); YGSetMemoryFuncs(NULL, NULL, NULL, NULL); diff --git a/tests/YGMinMaxDimensionTest.cpp b/tests/YGMinMaxDimensionTest.cpp index 2c6d3120..b1463e52 100644 --- a/tests/YGMinMaxDimensionTest.cpp +++ b/tests/YGMinMaxDimensionTest.cpp @@ -430,3 +430,216 @@ TEST(YogaTest, flex_grow_within_constrained_max_width) { YGNodeFreeRecursive(root); } + +TEST(YogaTest, flex_grow_within_constrained_min_row) { + const YGNodeRef root = YGNodeNew(); + YGNodeStyleSetFlexDirection(root, YGFlexDirectionRow); + YGNodeStyleSetMinWidth(root, 100); + YGNodeStyleSetHeight(root, 100); + + const YGNodeRef root_child0 = YGNodeNew(); + YGNodeStyleSetFlexGrow(root_child0, 1); + YGNodeInsertChild(root, root_child0, 0); + + const YGNodeRef root_child1 = YGNodeNew(); + YGNodeStyleSetWidth(root_child1, 50); + 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(100, 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(50, YGNodeLayoutGetWidth(root_child0)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child0)); + + ASSERT_FLOAT_EQ(50, YGNodeLayoutGetLeft(root_child1)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child1)); + ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child1)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child1)); + + YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL); + + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root)); + + ASSERT_FLOAT_EQ(50, YGNodeLayoutGetLeft(root_child0)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0)); + ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child0)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child0)); + + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child1)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child1)); + ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child1)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child1)); + + YGNodeFreeRecursive(root); +} + +TEST(YogaTest, flex_grow_within_constrained_min_column) { + const YGNodeRef root = YGNodeNew(); + YGNodeStyleSetMinHeight(root, 100); + + const YGNodeRef root_child0 = YGNodeNew(); + YGNodeStyleSetFlexGrow(root_child0, 1); + YGNodeInsertChild(root, root_child0, 0); + + const YGNodeRef root_child1 = YGNodeNew(); + YGNodeStyleSetHeight(root_child1, 50); + 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(0, 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(0, 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(0, YGNodeLayoutGetWidth(root_child1)); + ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child1)); + + YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL); + + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root)); + ASSERT_FLOAT_EQ(0, 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(0, 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(0, YGNodeLayoutGetWidth(root_child1)); + ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child1)); + + YGNodeFreeRecursive(root); +} + +TEST(YogaTest, flex_grow_within_constrained_max_row) { + const YGNodeRef root = YGNodeNew(); + YGNodeStyleSetWidth(root, 200); + + const YGNodeRef root_child0 = YGNodeNew(); + YGNodeStyleSetFlexDirection(root_child0, YGFlexDirectionRow); + YGNodeStyleSetMaxWidth(root_child0, 100); + YGNodeStyleSetHeight(root_child0, 100); + YGNodeInsertChild(root, root_child0, 0); + + const YGNodeRef root_child0_child0 = YGNodeNew(); + YGNodeStyleSetFlexShrink(root_child0_child0, 1); + YGNodeStyleSetFlexBasis(root_child0_child0, 100); + YGNodeInsertChild(root_child0, root_child0_child0, 0); + + const YGNodeRef root_child0_child1 = YGNodeNew(); + YGNodeStyleSetWidth(root_child0_child1, 50); + YGNodeInsertChild(root_child0, root_child0_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(100, YGNodeLayoutGetHeight(root)); + + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child0)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child0)); + + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0_child0)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0_child0)); + ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child0_child0)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child0_child0)); + + ASSERT_FLOAT_EQ(50, YGNodeLayoutGetLeft(root_child0_child1)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0_child1)); + ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child0_child1)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child0_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(100, YGNodeLayoutGetHeight(root)); + + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetLeft(root_child0)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child0)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child0)); + + ASSERT_FLOAT_EQ(50, YGNodeLayoutGetLeft(root_child0_child0)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0_child0)); + ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child0_child0)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child0_child0)); + + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0_child1)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0_child1)); + ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child0_child1)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child0_child1)); + + YGNodeFreeRecursive(root); +} + +TEST(YogaTest, flex_grow_within_constrained_max_column) { + const YGNodeRef root = YGNodeNew(); + YGNodeStyleSetWidth(root, 100); + YGNodeStyleSetMaxHeight(root, 100); + + const YGNodeRef root_child0 = YGNodeNew(); + YGNodeStyleSetFlexShrink(root_child0, 1); + YGNodeStyleSetFlexBasis(root_child0, 100); + YGNodeInsertChild(root, root_child0, 0); + + const YGNodeRef root_child1 = YGNodeNew(); + YGNodeStyleSetHeight(root_child1, 50); + 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(100, 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(100, 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(100, YGNodeLayoutGetWidth(root_child1)); + ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child1)); + + YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL); + + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root)); + ASSERT_FLOAT_EQ(100, 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(100, 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(100, YGNodeLayoutGetWidth(root_child1)); + ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child1)); + + YGNodeFreeRecursive(root); +} diff --git a/yoga/YGEnums.h b/yoga/YGEnums.h index 85d9d2f9..a64c1673 100644 --- a/yoga/YGEnums.h +++ b/yoga/YGEnums.h @@ -13,28 +13,29 @@ YG_EXTERN_C_BEGIN +#define YGFlexDirectionCount 4 typedef enum YGFlexDirection { YGFlexDirectionColumn, YGFlexDirectionColumnReverse, YGFlexDirectionRow, YGFlexDirectionRowReverse, - YGFlexDirectionCount, } YGFlexDirection; +#define YGMeasureModeCount 3 typedef enum YGMeasureMode { YGMeasureModeUndefined, YGMeasureModeExactly, YGMeasureModeAtMost, - YGMeasureModeCount, } YGMeasureMode; +#define YGPrintOptionsCount 3 typedef enum YGPrintOptions { YGPrintOptionsLayout = 1, YGPrintOptionsStyle = 2, YGPrintOptionsChildren = 4, - YGPrintOptionsCount, } YGPrintOptions; +#define YGEdgeCount 9 typedef enum YGEdge { YGEdgeLeft, YGEdgeTop, @@ -45,72 +46,71 @@ typedef enum YGEdge { YGEdgeHorizontal, YGEdgeVertical, YGEdgeAll, - YGEdgeCount, } YGEdge; +#define YGPositionTypeCount 2 typedef enum YGPositionType { YGPositionTypeRelative, YGPositionTypeAbsolute, - YGPositionTypeCount, } YGPositionType; +#define YGDimensionCount 2 typedef enum YGDimension { YGDimensionWidth, YGDimensionHeight, - YGDimensionCount, } YGDimension; +#define YGJustifyCount 5 typedef enum YGJustify { YGJustifyFlexStart, YGJustifyCenter, YGJustifyFlexEnd, YGJustifySpaceBetween, YGJustifySpaceAround, - YGJustifyCount, } YGJustify; +#define YGDirectionCount 3 typedef enum YGDirection { YGDirectionInherit, YGDirectionLTR, YGDirectionRTL, - YGDirectionCount, } YGDirection; +#define YGLogLevelCount 5 typedef enum YGLogLevel { YGLogLevelError, YGLogLevelWarn, YGLogLevelInfo, YGLogLevelDebug, YGLogLevelVerbose, - YGLogLevelCount, } YGLogLevel; +#define YGWrapCount 2 typedef enum YGWrap { YGWrapNoWrap, YGWrapWrap, - YGWrapCount, } YGWrap; +#define YGOverflowCount 3 typedef enum YGOverflow { YGOverflowVisible, YGOverflowHidden, YGOverflowScroll, - YGOverflowCount, } YGOverflow; +#define YGExperimentalFeatureCount 2 typedef enum YGExperimentalFeature { YGExperimentalFeatureRounding, YGExperimentalFeatureWebFlexBasis, - YGExperimentalFeatureCount, } YGExperimentalFeature; +#define YGAlignCount 5 typedef enum YGAlign { YGAlignAuto, YGAlignFlexStart, YGAlignCenter, YGAlignFlexEnd, YGAlignStretch, - YGAlignCount, } YGAlign; YG_EXTERN_C_END diff --git a/yoga/Yoga.c b/yoga/Yoga.c index dad81116..9723d894 100644 --- a/yoga/Yoga.c +++ b/yoga/Yoga.c @@ -42,7 +42,7 @@ typedef struct YGCachedMeasurement { // This value was chosen based on empiracle data. Even the most complicated // layouts should not require more than 16 entries to fit within the cache. -enum { YG_MAX_CACHED_RESULT_COUNT = 16 }; +#define YG_MAX_CACHED_RESULT_COUNT 16 typedef struct YGLayout { float position[4]; @@ -106,6 +106,66 @@ 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_DEFAULT_DIMENSION_VALUES { \ + [YGDimensionWidth] = YGUndefined, \ + [YGDimensionHeight] = YGUndefined, \ +} + +YGNode gYGNodeDefaults = { + .parent = NULL, + .children = NULL, + .hasNewLayout = true, + .isDirty = false, + + .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, + }, + + .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); YGMalloc gYGMalloc = &malloc; @@ -133,8 +193,6 @@ static int YGAndroidLog(YGLogLevel level, const char *format, va_list args) { case YGLogLevelVerbose: androidLevel = ANDROID_LOG_VERBOSE; break; - case YGLogLevelCount: - break; } const int result = __android_log_vprint(androidLevel, "YG-layout", format, args); return result; @@ -185,68 +243,14 @@ static inline float YGComputedEdgeValue(const float edges[YGEdgeCount], return defaultValue; } -static void YGNodeInit(const YGNodeRef node) { - node->parent = NULL; - node->children = NULL; - node->hasNewLayout = true; - node->isDirty = false; - - node->style.flex = YGUndefined; - node->style.flexGrow = YGUndefined; - node->style.flexShrink = YGUndefined; - node->style.flexBasis = YGUndefined; - - node->style.alignItems = YGAlignStretch; - node->style.alignContent = YGAlignFlexStart; - - node->style.direction = YGDirectionInherit; - node->style.flexDirection = YGFlexDirectionColumn; - - node->style.overflow = YGOverflowVisible; - - // Some of the fields default to undefined and not 0 - node->style.dimensions[YGDimensionWidth] = YGUndefined; - node->style.dimensions[YGDimensionHeight] = YGUndefined; - - node->style.minDimensions[YGDimensionWidth] = YGUndefined; - node->style.minDimensions[YGDimensionHeight] = YGUndefined; - - node->style.maxDimensions[YGDimensionWidth] = YGUndefined; - node->style.maxDimensions[YGDimensionHeight] = YGUndefined; - - for (YGEdge edge = YGEdgeLeft; edge < YGEdgeCount; edge++) { - node->style.position[edge] = YGUndefined; - node->style.margin[edge] = YGUndefined; - node->style.padding[edge] = YGUndefined; - node->style.border[edge] = YGUndefined; - } - - node->style.aspectRatio = YGUndefined; - - node->layout.dimensions[YGDimensionWidth] = YGUndefined; - node->layout.dimensions[YGDimensionHeight] = YGUndefined; - - // Such that the comparison is always going to be false - node->layout.lastParentDirection = (YGDirection) -1; - node->layout.nextCachedMeasurementsIndex = 0; - node->layout.computedFlexBasis = YGUndefined; - - node->layout.measuredDimensions[YGDimensionWidth] = YGUndefined; - node->layout.measuredDimensions[YGDimensionHeight] = YGUndefined; - node->layout.cachedLayout.widthMeasureMode = (YGMeasureMode) -1; - node->layout.cachedLayout.heightMeasureMode = (YGMeasureMode) -1; - node->layout.cachedLayout.computedWidth = -1; - node->layout.cachedLayout.computedHeight = -1; -} - int32_t gNodeInstanceCount = 0; YGNodeRef YGNodeNew(void) { - const YGNodeRef node = gYGCalloc(1, sizeof(YGNode)); + const YGNodeRef node = gYGMalloc(sizeof(YGNode)); YG_ASSERT(node, "Could not allocate memory for node"); gNodeInstanceCount++; - YGNodeInit(node); + memcpy(node, &gYGNodeDefaults, sizeof(YGNode)); return node; } @@ -281,8 +285,7 @@ void YGNodeReset(const YGNodeRef node) { YG_ASSERT(node->parent == NULL, "Cannot reset a node still attached to a parent"); YGNodeListFree(node->children); - memset(node, 0, sizeof(YGNode)); - YGNodeInit(node); + memcpy(node, &gYGNodeDefaults, sizeof(YGNode)); } int32_t YGNodeGetInstanceCount(void) { @@ -824,7 +827,7 @@ static YGFlexDirection YGFlexDirectionCross(const YGFlexDirection flexDirection, static inline bool YGNodeIsFlex(const YGNodeRef node) { return (node->style.positionType == YGPositionTypeRelative && - (node->style.flexGrow != 0 || node->style.flexShrink != 0 || node->style.flex != 0)); + (YGNodeStyleGetFlexGrow(node) != 0 || YGNodeStyleGetFlexShrink(node) != 0)); } static inline float YGNodeDimWithMargin(const YGNodeRef node, const YGFlexDirection axis) { @@ -950,8 +953,6 @@ static void YGConstrainMaxSizeForMode(const float maxSize, YGMeasureMode *mode, *size = maxSize; } break; - case YGMeasureModeCount: - break; } } @@ -1061,7 +1062,7 @@ static void YGNodeComputeFlexBasisForChild(const YGNodeRef node, if (!YGValueIsUndefined(child->style.aspectRatio)) { if (!isMainAxisRow && childWidthMeasureMode == YGMeasureModeExactly) { child->layout.computedFlexBasis = - fmaxf(childWidth * child->style.aspectRatio, + fmaxf(childWidth / child->style.aspectRatio, YGNodePaddingAndBorderForAxis(child, YGFlexDirectionColumn)); return; } else if (isMainAxisRow && childHeightMeasureMode == YGMeasureModeExactly) { @@ -1156,7 +1157,7 @@ static void YGNodeAbsoluteLayoutChild(const YGNodeRef node, childWidth = fmaxf(childHeight * child->style.aspectRatio, YGNodePaddingAndBorderForAxis(child, YGFlexDirectionColumn)); } else if (YGValueIsUndefined(childHeight)) { - childHeight = fmaxf(childWidth * child->style.aspectRatio, + childHeight = fmaxf(childWidth / child->style.aspectRatio, YGNodePaddingAndBorderForAxis(child, YGFlexDirectionRow)); } } @@ -1506,10 +1507,25 @@ static void YGNodelayoutImpl(const YGNodeRef node, const float marginAxisColumn = YGNodeMarginForAxis(node, YGFlexDirectionColumn); // STEP 2: DETERMINE AVAILABLE SIZE IN MAIN AND CROSS DIRECTIONS - const float availableInnerWidth = availableWidth - marginAxisRow - paddingAndBorderAxisRow; - const float availableInnerHeight = + 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 availableInnerMainDim = isMainAxisRow ? availableInnerWidth : availableInnerHeight; + const float minInnerHeight = node->style.minDimensions[YGDimensionHeight] - marginAxisColumn - paddingAndBorderAxisColumn; + const float maxInnerHeight = node->style.maxDimensions[YGDimensionHeight] - 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)) { + availableInnerWidth = fmaxf(fminf(availableInnerWidth, maxInnerWidth), minInnerWidth); + } + if (!YGValueIsUndefined(availableInnerHeight)) { + availableInnerHeight = fmaxf(fminf(availableInnerHeight, maxInnerHeight), minInnerHeight); + } + + float availableInnerMainDim = isMainAxisRow ? availableInnerWidth : availableInnerHeight; const float availableInnerCrossDim = isMainAxisRow ? availableInnerHeight : availableInnerWidth; // If there is only one child with flexGrow + flexShrink it means we can set the @@ -1663,6 +1679,18 @@ static void YGNodelayoutImpl(const YGNodeRef node, // Calculate the remaining available space that needs to be allocated. // If the main dimension size isn't known, it is computed based on // 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) { + availableInnerMainDim = minInnerMainDim; + } else if (!YGValueIsUndefined(maxInnerMainDim) && + sizeConsumedOnCurrentLine > maxInnerMainDim) { + availableInnerMainDim = maxInnerMainDim; + } + } + float remainingFreeSpace = 0; if (!YGValueIsUndefined(availableInnerMainDim)) { remainingFreeSpace = availableInnerMainDim - sizeConsumedOnCurrentLine; @@ -1850,16 +1878,22 @@ static void YGNodelayoutImpl(const YGNodeRef node, } if (!YGValueIsUndefined(currentRelativeChild->style.aspectRatio)) { - if (isMainAxisRow && childHeightMeasureMode != YGMeasureModeExactly) { + if (isMainAxisRow) { childHeight = - fmaxf(childWidth * currentRelativeChild->style.aspectRatio, + fmaxf(childWidth / currentRelativeChild->style.aspectRatio, YGNodePaddingAndBorderForAxis(currentRelativeChild, YGFlexDirectionColumn)); childHeightMeasureMode = YGMeasureModeExactly; - } else if (!isMainAxisRow && childWidthMeasureMode != YGMeasureModeExactly) { + + childHeight = fminf(childHeight, availableInnerHeight); + childWidth = childHeight * currentRelativeChild->style.aspectRatio; + } else { childWidth = fmaxf(childHeight * currentRelativeChild->style.aspectRatio, YGNodePaddingAndBorderForAxis(currentRelativeChild, YGFlexDirectionRow)); childWidthMeasureMode = YGMeasureModeExactly; + + childWidth = fminf(childWidth, availableInnerWidth); + childHeight = childWidth / currentRelativeChild->style.aspectRatio; } } @@ -1934,7 +1968,6 @@ static void YGNodelayoutImpl(const YGNodeRef node, leadingMainDim = betweenMainDim / 2; break; case YGJustifyFlexStart: - case YGJustifyCount: break; } @@ -2052,13 +2085,23 @@ static void YGNodelayoutImpl(const YGNodeRef node, YGMeasureMode childHeightMeasureMode = YGMeasureModeExactly; if (isMainAxisRow) { - childHeight = crossDim; childWidth = child->layout.measuredDimensions[YGDimensionWidth] + YGNodeMarginForAxis(child, YGFlexDirectionRow); + + if (!YGValueIsUndefined(child->style.aspectRatio)) { + childHeight = childWidth / child->style.aspectRatio; + } else { + childHeight = crossDim; + } } else { - childWidth = crossDim; childHeight = child->layout.measuredDimensions[YGDimensionHeight] + YGNodeMarginForAxis(child, YGFlexDirectionColumn); + + if (!YGValueIsUndefined(child->style.aspectRatio)) { + childWidth = childHeight * child->style.aspectRatio; + } else { + childWidth = crossDim; + } } YGConstrainMaxSizeForMode(child->style.maxDimensions[YGDimensionWidth], @@ -2127,7 +2170,6 @@ static void YGNodelayoutImpl(const YGNodeRef node, break; case YGAlignAuto: case YGAlignFlexStart: - case YGAlignCount: break; } @@ -2187,7 +2229,6 @@ static void YGNodelayoutImpl(const YGNodeRef node, break; } case YGAlignAuto: - case YGAlignCount: break; } } diff --git a/yoga/Yoga.h b/yoga/Yoga.h index 3bb96727..5e10b503 100644 --- a/yoga/Yoga.h +++ b/yoga/Yoga.h @@ -151,6 +151,9 @@ YG_NODE_STYLE_PROPERTY(float, MaxHeight, maxHeight); // Yoga specific properties, not compatible with flexbox specification // Aspect ratio control the size of the undefined dimension of a node. +// Aspect ratio is encoded as a floating point value width/height. e.g. A value of 2 leads to a node +// with a width twice the size of its height while a value of 0.5 gives the opposite effect. +// // - On a node with a set width/height aspect ratio control the size of the unset dimension // - On a node with a set flex basis aspect ratio controls the size of the node in the cross axis if // unset