Baseline support
Summary: Added baseline support (see #132) You have the ability for a custom baseline function (```float(*YGBaselineFunc)(YGNodeRef node);```) to return whatever baseline you want. Closes https://github.com/facebook/yoga/pull/317 Reviewed By: splhack Differential Revision: D4385061 Pulled By: emilsjolander fbshipit-source-id: cb8a59a09237c840fa3e21753ab68239997dab0c
This commit is contained in:
committed by
Facebook Github Bot
parent
6d48307c8d
commit
c169a98be6
@@ -16,5 +16,6 @@ namespace Facebook.Yoga
|
||||
Center,
|
||||
FlexEnd,
|
||||
Stretch,
|
||||
Baseline,
|
||||
}
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -174,5 +174,76 @@ namespace Facebook.Yoga
|
||||
Assert.AreEqual(10f, root_child0.LayoutHeight);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Test_align_self_baseline()
|
||||
{
|
||||
YogaNode root = new YogaNode();
|
||||
root.FlexDirection = YogaFlexDirection.Row;
|
||||
root.Width = 100;
|
||||
root.Height = 100;
|
||||
|
||||
YogaNode root_child0 = new YogaNode();
|
||||
root_child0.AlignSelf = YogaAlign.Baseline;
|
||||
root_child0.Width = 50;
|
||||
root_child0.Height = 50;
|
||||
root.Insert(0, root_child0);
|
||||
|
||||
YogaNode root_child1 = new YogaNode();
|
||||
root_child1.AlignSelf = YogaAlign.Baseline;
|
||||
root_child1.Width = 50;
|
||||
root_child1.Height = 20;
|
||||
root.Insert(1, root_child1);
|
||||
|
||||
YogaNode root_child1_child0 = new YogaNode();
|
||||
root_child1_child0.Width = 50;
|
||||
root_child1_child0.Height = 10;
|
||||
root_child1.Insert(0, root_child1_child0);
|
||||
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(50f, root_child0.LayoutHeight);
|
||||
|
||||
Assert.AreEqual(50f, root_child1.LayoutX);
|
||||
Assert.AreEqual(40f, root_child1.LayoutY);
|
||||
Assert.AreEqual(50f, root_child1.LayoutWidth);
|
||||
Assert.AreEqual(20f, root_child1.LayoutHeight);
|
||||
|
||||
Assert.AreEqual(0f, root_child1_child0.LayoutX);
|
||||
Assert.AreEqual(0f, root_child1_child0.LayoutY);
|
||||
Assert.AreEqual(50f, root_child1_child0.LayoutWidth);
|
||||
Assert.AreEqual(10f, root_child1_child0.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(50f, root_child0.LayoutHeight);
|
||||
|
||||
Assert.AreEqual(0f, root_child1.LayoutX);
|
||||
Assert.AreEqual(40f, root_child1.LayoutY);
|
||||
Assert.AreEqual(50f, root_child1.LayoutWidth);
|
||||
Assert.AreEqual(20f, root_child1.LayoutHeight);
|
||||
|
||||
Assert.AreEqual(0f, root_child1_child0.LayoutX);
|
||||
Assert.AreEqual(0f, root_child1_child0.LayoutY);
|
||||
Assert.AreEqual(50f, root_child1_child0.LayoutWidth);
|
||||
Assert.AreEqual(10f, root_child1_child0.LayoutHeight);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
1
enums.py
1
enums.py
@@ -46,6 +46,7 @@ ENUMS = {
|
||||
'Center',
|
||||
'FlexEnd',
|
||||
'Stretch',
|
||||
'Baseline',
|
||||
],
|
||||
'PositionType': [
|
||||
'Relative',
|
||||
|
@@ -13,3 +13,135 @@
|
||||
<div id="align_items_flex_end" style="width: 100px; height: 100px; align-items: flex-end;">
|
||||
<div style="height: 10px; width: 10px;"></div>
|
||||
</div>
|
||||
|
||||
<div id="align_baseline" style="width: 100px; height: 100px; flex-direction:row; align-items: baseline;">
|
||||
<div style="width: 50px; height: 50px;"></div>
|
||||
<div style="width: 50px; height: 20px;"></div>
|
||||
</div>
|
||||
|
||||
<div id="align_baseline_child" style="width: 100px; height: 100px; flex-direction:row; align-items: baseline;">
|
||||
<div style="width: 50px; height: 50px;"></div>
|
||||
<div style="width: 50px; height: 20px;">
|
||||
<div style="width: 50px; height: 10px;"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="align_baseline_child_multiline" style="width: 100px; height: 100px; flex-direction:row; align-items: baseline;">
|
||||
<div style="width: 50px; height: 60px;"></div>
|
||||
<div style="width: 50px; height: 25px;flex-wrap:wrap;flex-direction:row;">
|
||||
<div style="width: 25px; height: 20px;"></div>
|
||||
<div style="width: 25px; height: 10px;"></div>
|
||||
<div style="width: 25px; height: 20px;"></div>
|
||||
<div style="width: 25px; height: 10px;"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="align_baseline_child_multiline_override" style="width: 100px; height: 100px; flex-direction:row; align-items: baseline;">
|
||||
<div style="width: 50px; height: 60px;"></div>
|
||||
<div style="width: 50px; height: 25px;flex-wrap:wrap;flex-direction:row;">
|
||||
<div style="width: 25px; height: 20px;"></div>
|
||||
<div style="width: 25px; height: 10px;align-self:baseline;"></div>
|
||||
<div style="width: 25px; height: 20px;"></div>
|
||||
<div style="width: 25px; height: 10px;align-self:baseline;"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="align_baseline_child_multiline_no_override_on_secondline" style="width: 100px; height: 100px; flex-direction:row; align-items: baseline;">
|
||||
<div style="width: 50px; height: 60px;"></div>
|
||||
<div style="width: 50px; height: 25px;flex-wrap:wrap;flex-direction:row;">
|
||||
<div style="width: 25px; height: 20px;"></div>
|
||||
<div style="width: 25px; height: 10px;"></div>
|
||||
<div style="width: 25px; height: 20px;"></div>
|
||||
<div style="width: 25px; height: 10px;align-self:baseline;"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div id="align_baseline_child_top" style="width: 100px; height: 100px; flex-direction:row; align-items: baseline;">
|
||||
<div style="width: 50px; height: 50px;top:10px;"></div>
|
||||
<div style="width: 50px; height: 20px;">
|
||||
<div style="width: 50px; height: 10px;"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="align_baseline_child_top2" style="width: 100px; height: 100px; flex-direction:row; align-items: baseline;">
|
||||
<div style="width: 50px; height: 50px;"></div>
|
||||
<div style="width: 50px; height: 20px;top:5px">
|
||||
<div style="width: 50px; height: 10px;"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="align_baseline_double_nested_child" style="width: 100px; height: 100px; flex-direction:row; align-items: baseline;">
|
||||
<div style="width: 50px; height: 50px;">
|
||||
<div style="width: 50px; height: 20px;"></div>
|
||||
</div>
|
||||
<div style="width: 50px; height: 20px;">
|
||||
<div style="width: 50px; height: 15px;"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div id="align_baseline_column" style="width: 100px; height: 100px; flex-direction:column; align-items: baseline;">
|
||||
<div style="width: 50px; height: 50px;"></div>
|
||||
<div style="width: 50px; height: 20px;"></div>
|
||||
</div>
|
||||
|
||||
<div id="align_baseline_child_margin" style="width: 100px; height: 100px; flex-direction:row; align-items: baseline;">
|
||||
<div style="width: 50px; height: 50px;margin: 5px;"></div>
|
||||
<div style="width: 50px; height: 20px;">
|
||||
<div style="width: 50px; height: 10px;margin: 1px;"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="align_baseline_child_padding" style="width: 100px; height: 100px; padding:5px; flex-direction:row; align-items: baseline;">
|
||||
<div style="width: 50px; height: 50px;"></div>
|
||||
<div style="width: 50px; height: 20px;padding:5px;">
|
||||
<div style="width: 50px; height: 10px;"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="align_baseline_multiline" style="width: 100px; height: 100px; flex-direction:row; align-items: baseline;flex-wrap:wrap;">
|
||||
<div style="width: 50px; height: 50px;"></div>
|
||||
<div style="width: 50px; height: 20px;">
|
||||
<div style="width: 50px; height: 10px;"></div>
|
||||
</div>
|
||||
<div style="width: 50px; height: 20px;">
|
||||
<div style="width: 50px; height: 10px;"></div>
|
||||
</div>
|
||||
<div style="width: 50px; height: 50px;"></div>
|
||||
</div>
|
||||
|
||||
<div id="align_baseline_multiline_column" style="width: 100px; height: 100px; flex-direction:column; align-items: baseline;flex-wrap:wrap;">
|
||||
<div style="width: 50px; height: 50px;"></div>
|
||||
<div style="width: 30px; height: 50px;">
|
||||
<div style="width: 20px; height: 20px;"></div>
|
||||
</div>
|
||||
<div style="width: 40px; height: 70px;">
|
||||
<div style="width: 10px; height: 10px;"></div>
|
||||
</div>
|
||||
<div style="width: 50px; height: 20px;"></div>
|
||||
</div>
|
||||
|
||||
<div id="align_baseline_multiline_column2" style="width: 100px; height: 100px; flex-direction:column; align-items: baseline;flex-wrap:wrap;">
|
||||
<div style="width: 50px; height: 50px;flex-direction:column;"></div>
|
||||
<div style="width: 30px; height: 50px;flex-direction:column;">
|
||||
<div style="width: 20px; height: 20px;flex-direction:column;"></div>
|
||||
</div>
|
||||
<div style="width: 40px; height: 70px;flex-direction:column;">
|
||||
<div style="width: 10px; height: 10px;flex-direction:column;"></div>
|
||||
</div>
|
||||
<div style="width: 50px; height: 20px;flex-direction:column;"></div>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
<div id="align_baseline_multiline_row_and_column" style="width: 100px; height: 100px; flex-direction:row; align-items: baseline;flex-wrap:wrap;">
|
||||
<div style="width: 50px; height: 50px;"></div>
|
||||
<div style="width: 50px; height: 50px;flex-direction:column;">
|
||||
<div style="width: 50px; height: 10px;"></div>
|
||||
</div>
|
||||
<div style="width: 50px; height: 20px;flex-direction:column;">
|
||||
<div style="width: 50px; height: 10px;"></div>
|
||||
</div>
|
||||
<div style="width: 50px; height: 20px;"></div>
|
||||
</div>
|
@@ -13,3 +13,11 @@
|
||||
<div id="align_self_flex_end_override_flex_start" style="width:100px; height: 100px; align-items: flex-start;">
|
||||
<div style="height: 10px; width: 10px; align-self: flex-end;"></div>
|
||||
</div>
|
||||
|
||||
|
||||
<div id="align_self_baseline" style="width: 100px; height: 100px; flex-direction:row;">
|
||||
<div style="width: 50px; height: 50px;align-self: baseline;"></div>
|
||||
<div style="width: 50px; height: 20px;align-self: baseline;">
|
||||
<div style="width: 50px; height: 10px;"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
@@ -83,6 +83,8 @@ CPPEmitter.prototype = Object.create(Emitter.prototype, {
|
||||
YGAlignFlexStart:{value:'YGAlignFlexStart'},
|
||||
YGAlignStretch:{value:'YGAlignStretch'},
|
||||
|
||||
YGAlignBaseline:{value:'YGAlignBaseline'},
|
||||
|
||||
YGDirectionInherit:{value:'YGDirectionInherit'},
|
||||
YGDirectionLTR:{value:'YGDirectionLTR'},
|
||||
YGDirectionRTL:{value:'YGDirectionRTL'},
|
||||
|
@@ -96,6 +96,7 @@ CSEmitter.prototype = Object.create(Emitter.prototype, {
|
||||
YGAlignFlexEnd:{value:'YogaAlign.FlexEnd'},
|
||||
YGAlignFlexStart:{value:'YogaAlign.FlexStart'},
|
||||
YGAlignStretch:{value:'YogaAlign.Stretch'},
|
||||
YGAlignBaseline:{value:'YogaAlign.Baseline'},
|
||||
|
||||
YGDirectionInherit:{value:'YogaDirection.Inherit'},
|
||||
YGDirectionLTR:{value:'YogaDirection.LTR'},
|
||||
|
@@ -100,6 +100,7 @@ JavaEmitter.prototype = Object.create(Emitter.prototype, {
|
||||
YGAlignFlexEnd:{value:'YogaAlign.FLEX_END'},
|
||||
YGAlignFlexStart:{value:'YogaAlign.FLEX_START'},
|
||||
YGAlignStretch:{value:'YogaAlign.STRETCH'},
|
||||
YGAlignBaseline:{value:'YogaAlign.BASELINE'},
|
||||
|
||||
YGDirectionInherit:{value:'YogaDirection.INHERIT'},
|
||||
YGDirectionLTR:{value:'YogaDirection.LTR'},
|
||||
|
@@ -90,6 +90,7 @@ JavascriptEmitter.prototype = Object.create(Emitter.prototype, {
|
||||
YGAlignFlexEnd:{value:'Yoga.ALIGN_FLEX_END'},
|
||||
YGAlignFlexStart:{value:'Yoga.ALIGN_FLEX_START'},
|
||||
YGAlignStretch:{value:'Yoga.ALIGN_STRETCH'},
|
||||
YGAlignBaseline:{value:'Yoga.ALIGN_BASELINE'},
|
||||
|
||||
YGDirectionInherit:{value:'Yoga.DIRECTION_INHERIT'},
|
||||
YGDirectionLTR:{value:'Yoga.DIRECTION_LTR'},
|
||||
|
@@ -377,6 +377,7 @@ function alignValue(e, value) {
|
||||
case 'stretch': return e.YGAlignStretch;
|
||||
case 'flex-start': return e.YGAlignFlexStart;
|
||||
case 'flex-end': return e.YGAlignFlexEnd;
|
||||
case 'baseline': return e.YGAlignBaseline;
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -17,7 +17,8 @@ public enum YogaAlign {
|
||||
FLEX_START(1),
|
||||
CENTER(2),
|
||||
FLEX_END(3),
|
||||
STRETCH(4);
|
||||
STRETCH(4),
|
||||
BASELINE(5);
|
||||
|
||||
private int mIntValue;
|
||||
|
||||
@@ -36,6 +37,7 @@ public enum YogaAlign {
|
||||
case 2: return CENTER;
|
||||
case 3: return FLEX_END;
|
||||
case 4: return STRETCH;
|
||||
case 5: return BASELINE;
|
||||
default: throw new IllegalArgumentException("Unkown enum value: " + value);
|
||||
}
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -169,4 +169,74 @@ public class YGAlignSelfTest {
|
||||
assertEquals(10f, root_child0.getLayoutHeight(), 0.0f);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test_align_self_baseline() {
|
||||
final YogaNode root = new YogaNode();
|
||||
root.setFlexDirection(YogaFlexDirection.ROW);
|
||||
root.setWidth(100f);
|
||||
root.setHeight(100f);
|
||||
|
||||
final YogaNode root_child0 = new YogaNode();
|
||||
root_child0.setAlignSelf(YogaAlign.BASELINE);
|
||||
root_child0.setWidth(50f);
|
||||
root_child0.setHeight(50f);
|
||||
root.addChildAt(root_child0, 0);
|
||||
|
||||
final YogaNode root_child1 = new YogaNode();
|
||||
root_child1.setAlignSelf(YogaAlign.BASELINE);
|
||||
root_child1.setWidth(50f);
|
||||
root_child1.setHeight(20f);
|
||||
root.addChildAt(root_child1, 1);
|
||||
|
||||
final YogaNode root_child1_child0 = new YogaNode();
|
||||
root_child1_child0.setWidth(50f);
|
||||
root_child1_child0.setHeight(10f);
|
||||
root_child1.addChildAt(root_child1_child0, 0);
|
||||
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(50f, root_child0.getLayoutHeight(), 0.0f);
|
||||
|
||||
assertEquals(50f, root_child1.getLayoutX(), 0.0f);
|
||||
assertEquals(40f, root_child1.getLayoutY(), 0.0f);
|
||||
assertEquals(50f, root_child1.getLayoutWidth(), 0.0f);
|
||||
assertEquals(20f, root_child1.getLayoutHeight(), 0.0f);
|
||||
|
||||
assertEquals(0f, root_child1_child0.getLayoutX(), 0.0f);
|
||||
assertEquals(0f, root_child1_child0.getLayoutY(), 0.0f);
|
||||
assertEquals(50f, root_child1_child0.getLayoutWidth(), 0.0f);
|
||||
assertEquals(10f, root_child1_child0.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(50f, root_child0.getLayoutHeight(), 0.0f);
|
||||
|
||||
assertEquals(0f, root_child1.getLayoutX(), 0.0f);
|
||||
assertEquals(40f, root_child1.getLayoutY(), 0.0f);
|
||||
assertEquals(50f, root_child1.getLayoutWidth(), 0.0f);
|
||||
assertEquals(20f, root_child1.getLayoutHeight(), 0.0f);
|
||||
|
||||
assertEquals(0f, root_child1_child0.getLayoutX(), 0.0f);
|
||||
assertEquals(0f, root_child1_child0.getLayoutY(), 0.0f);
|
||||
assertEquals(50f, root_child1_child0.getLayoutWidth(), 0.0f);
|
||||
assertEquals(10f, root_child1_child0.getLayoutHeight(), 0.0f);
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -76,12 +76,13 @@ module.exports = {
|
||||
EXPERIMENTAL_FEATURE_ROUNDING: 0,
|
||||
EXPERIMENTAL_FEATURE_WEB_FLEX_BASIS: 1,
|
||||
|
||||
ALIGN_COUNT: 5,
|
||||
ALIGN_COUNT: 6,
|
||||
ALIGN_AUTO: 0,
|
||||
ALIGN_FLEX_START: 1,
|
||||
ALIGN_CENTER: 2,
|
||||
ALIGN_FLEX_END: 3,
|
||||
ALIGN_STRETCH: 4,
|
||||
ALIGN_BASELINE: 5,
|
||||
|
||||
UNIT_COUNT: 3,
|
||||
UNIT_UNDEFINED: 0,
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -160,3 +160,72 @@ TEST(YogaTest, align_self_flex_end_override_flex_start) {
|
||||
|
||||
YGNodeFreeRecursive(root);
|
||||
}
|
||||
|
||||
TEST(YogaTest, align_self_baseline) {
|
||||
const YGNodeRef root = YGNodeNew();
|
||||
YGNodeStyleSetFlexDirection(root, YGFlexDirectionRow);
|
||||
YGNodeStyleSetWidth(root, 100);
|
||||
YGNodeStyleSetHeight(root, 100);
|
||||
|
||||
const YGNodeRef root_child0 = YGNodeNew();
|
||||
YGNodeStyleSetAlignSelf(root_child0, YGAlignBaseline);
|
||||
YGNodeStyleSetWidth(root_child0, 50);
|
||||
YGNodeStyleSetHeight(root_child0, 50);
|
||||
YGNodeInsertChild(root, root_child0, 0);
|
||||
|
||||
const YGNodeRef root_child1 = YGNodeNew();
|
||||
YGNodeStyleSetAlignSelf(root_child1, YGAlignBaseline);
|
||||
YGNodeStyleSetWidth(root_child1, 50);
|
||||
YGNodeStyleSetHeight(root_child1, 20);
|
||||
YGNodeInsertChild(root, root_child1, 1);
|
||||
|
||||
const YGNodeRef root_child1_child0 = YGNodeNew();
|
||||
YGNodeStyleSetWidth(root_child1_child0, 50);
|
||||
YGNodeStyleSetHeight(root_child1_child0, 10);
|
||||
YGNodeInsertChild(root_child1, root_child1_child0, 0);
|
||||
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(50, YGNodeLayoutGetHeight(root_child0));
|
||||
|
||||
ASSERT_FLOAT_EQ(50, YGNodeLayoutGetLeft(root_child1));
|
||||
ASSERT_FLOAT_EQ(40, YGNodeLayoutGetTop(root_child1));
|
||||
ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child1));
|
||||
ASSERT_FLOAT_EQ(20, YGNodeLayoutGetHeight(root_child1));
|
||||
|
||||
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child1_child0));
|
||||
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child1_child0));
|
||||
ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child1_child0));
|
||||
ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child1_child0));
|
||||
|
||||
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(50, YGNodeLayoutGetHeight(root_child0));
|
||||
|
||||
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child1));
|
||||
ASSERT_FLOAT_EQ(40, YGNodeLayoutGetTop(root_child1));
|
||||
ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child1));
|
||||
ASSERT_FLOAT_EQ(20, YGNodeLayoutGetHeight(root_child1));
|
||||
|
||||
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child1_child0));
|
||||
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child1_child0));
|
||||
ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child1_child0));
|
||||
ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child1_child0));
|
||||
|
||||
YGNodeFreeRecursive(root);
|
||||
}
|
||||
|
63
tests/YGBaselineFuncTest.cpp
Normal file
63
tests/YGBaselineFuncTest.cpp
Normal file
@@ -0,0 +1,63 @@
|
||||
/**
|
||||
* Copyright (c) 2014-present, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD-style license found in the
|
||||
* LICENSE file in the root directory of this source tree. An additional grant
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
*/
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
#include <yoga/Yoga.h>
|
||||
|
||||
static float _baseline(YGNodeRef node, const float width, const float height) {
|
||||
float *baseline = (float *) YGNodeGetContext(node);
|
||||
return *baseline;
|
||||
}
|
||||
|
||||
TEST(YogaTest, align_baseline_customer_func) {
|
||||
const YGNodeRef root = YGNodeNew();
|
||||
YGNodeStyleSetFlexDirection(root, YGFlexDirectionRow);
|
||||
YGNodeStyleSetAlignItems(root, YGAlignBaseline);
|
||||
YGNodeStyleSetWidth(root, 100);
|
||||
YGNodeStyleSetHeight(root, 100);
|
||||
|
||||
const YGNodeRef root_child0 = YGNodeNew();
|
||||
YGNodeStyleSetWidth(root_child0, 50);
|
||||
YGNodeStyleSetHeight(root_child0, 50);
|
||||
YGNodeInsertChild(root, root_child0, 0);
|
||||
|
||||
const YGNodeRef root_child1 = YGNodeNew();
|
||||
YGNodeStyleSetWidth(root_child1, 50);
|
||||
YGNodeStyleSetHeight(root_child1, 20);
|
||||
YGNodeInsertChild(root, root_child1, 1);
|
||||
|
||||
float baselineValue = 10;
|
||||
const YGNodeRef root_child1_child0 = YGNodeNew();
|
||||
YGNodeSetContext(root_child1_child0, &baselineValue);
|
||||
YGNodeStyleSetWidth(root_child1_child0, 50);
|
||||
YGNodeSetBaselineFunc(root_child1_child0, _baseline);
|
||||
YGNodeStyleSetHeight(root_child1_child0, 20);
|
||||
YGNodeInsertChild(root_child1, root_child1_child0, 0);
|
||||
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(50, YGNodeLayoutGetHeight(root_child0));
|
||||
|
||||
ASSERT_FLOAT_EQ(50, YGNodeLayoutGetLeft(root_child1));
|
||||
ASSERT_FLOAT_EQ(40, YGNodeLayoutGetTop(root_child1));
|
||||
ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child1));
|
||||
ASSERT_FLOAT_EQ(20, YGNodeLayoutGetHeight(root_child1));
|
||||
|
||||
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child1_child0));
|
||||
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child1_child0));
|
||||
ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child1_child0));
|
||||
ASSERT_FLOAT_EQ(20, YGNodeLayoutGetHeight(root_child1_child0));
|
||||
}
|
@@ -104,13 +104,14 @@ typedef enum YGExperimentalFeature {
|
||||
YGExperimentalFeatureWebFlexBasis,
|
||||
} YGExperimentalFeature;
|
||||
|
||||
#define YGAlignCount 5
|
||||
#define YGAlignCount 6
|
||||
typedef enum YGAlign {
|
||||
YGAlignAuto,
|
||||
YGAlignFlexStart,
|
||||
YGAlignCenter,
|
||||
YGAlignFlexEnd,
|
||||
YGAlignStretch,
|
||||
YGAlignBaseline,
|
||||
} YGAlign;
|
||||
|
||||
#define YGUnitCount 3
|
||||
|
122
yoga/Yoga.c
122
yoga/Yoga.c
@@ -102,6 +102,7 @@ typedef struct YGNode {
|
||||
struct YGNode *nextChild;
|
||||
|
||||
YGMeasureFunc measure;
|
||||
YGBaselineFunc baseline;
|
||||
YGPrintFunc print;
|
||||
void *context;
|
||||
|
||||
@@ -337,6 +338,14 @@ YGMeasureFunc YGNodeGetMeasureFunc(const YGNodeRef node) {
|
||||
return node->measure;
|
||||
}
|
||||
|
||||
void YGNodeSetBaselineFunc(const YGNodeRef node, YGBaselineFunc baselineFunc) {
|
||||
node->baseline = baselineFunc;
|
||||
}
|
||||
|
||||
YGBaselineFunc YGNodeGetBaselineFunc(const YGNodeRef node) {
|
||||
return node->baseline;
|
||||
}
|
||||
|
||||
void YGNodeInsertChild(const YGNodeRef node, const YGNodeRef child, const uint32_t index) {
|
||||
YG_ASSERT(child->parent == NULL, "Child already has a parent, it must be removed first.");
|
||||
YG_ASSERT(node->measure == NULL,
|
||||
@@ -893,8 +902,8 @@ static float YGNodeLeadingPadding(const YGNodeRef node,
|
||||
}
|
||||
|
||||
return fmaxf(YGValueResolve(YGComputedEdgeValue(node->style.padding, leading[axis], &YGValueZero),
|
||||
widthSize),
|
||||
0.0f);
|
||||
widthSize),
|
||||
0.0f);
|
||||
}
|
||||
|
||||
static float YGNodeTrailingPadding(const YGNodeRef node,
|
||||
@@ -906,8 +915,8 @@ static float YGNodeTrailingPadding(const YGNodeRef node,
|
||||
}
|
||||
|
||||
return fmaxf(YGValueResolve(YGComputedEdgeValue(node->style.padding, trailing[axis], &YGValueZero),
|
||||
widthSize),
|
||||
0.0f);
|
||||
widthSize),
|
||||
0.0f);
|
||||
}
|
||||
|
||||
static float YGNodeLeadingBorder(const YGNodeRef node, const YGFlexDirection axis) {
|
||||
@@ -954,7 +963,12 @@ static inline float YGNodePaddingAndBorderForAxis(const YGNodeRef node,
|
||||
}
|
||||
|
||||
static inline YGAlign YGNodeAlignItem(const YGNodeRef node, const YGNodeRef child) {
|
||||
return child->style.alignSelf == YGAlignAuto ? node->style.alignItems : child->style.alignSelf;
|
||||
const YGAlign align =
|
||||
child->style.alignSelf == YGAlignAuto ? node->style.alignItems : child->style.alignSelf;
|
||||
if (align == YGAlignBaseline && YGFlexDirectionIsColumn(node->style.flexDirection)) {
|
||||
return YGAlignFlexStart;
|
||||
}
|
||||
return align;
|
||||
}
|
||||
|
||||
static inline YGDirection YGNodeResolveDirection(const YGNodeRef node,
|
||||
@@ -966,6 +980,40 @@ static inline YGDirection YGNodeResolveDirection(const YGNodeRef node,
|
||||
}
|
||||
}
|
||||
|
||||
static float YGBaseline(const YGNodeRef node) {
|
||||
if (node->baseline != NULL) {
|
||||
const float baseline = node->baseline(node, node->layout.measuredDimensions[YGDimensionWidth], node->layout.measuredDimensions[YGDimensionHeight]);
|
||||
YG_ASSERT(!YGFloatIsUndefined(baseline), "Expect custom baseline function to not return NaN")
|
||||
return baseline;
|
||||
}
|
||||
|
||||
YGNodeRef baselineChild = NULL;
|
||||
for (uint32_t i = 0; i < YGNodeGetChildCount(node); i++) {
|
||||
const YGNodeRef child = YGNodeGetChild(node, i);
|
||||
if (child->lineIndex > 0) {
|
||||
break;
|
||||
}
|
||||
if (child->style.positionType == YGPositionTypeAbsolute) {
|
||||
continue;
|
||||
}
|
||||
if (YGNodeAlignItem(node, child) == YGAlignBaseline) {
|
||||
baselineChild = child;
|
||||
break;
|
||||
}
|
||||
|
||||
if (baselineChild == NULL) {
|
||||
baselineChild = child;
|
||||
}
|
||||
}
|
||||
|
||||
if (baselineChild == NULL) {
|
||||
return node->layout.measuredDimensions[YGDimensionHeight];
|
||||
}
|
||||
|
||||
const float baseline = YGBaseline(baselineChild);
|
||||
return baseline + baselineChild->layout.position[YGEdgeTop];
|
||||
}
|
||||
|
||||
static inline YGFlexDirection YGFlexDirectionResolve(const YGFlexDirection flexDirection,
|
||||
const YGDirection direction) {
|
||||
if (direction == YGDirectionRTL) {
|
||||
@@ -991,6 +1039,24 @@ static inline bool YGNodeIsFlex(const YGNodeRef node) {
|
||||
(YGNodeStyleGetFlexGrow(node) != 0 || YGNodeStyleGetFlexShrink(node) != 0));
|
||||
}
|
||||
|
||||
static bool YGIsBaselineLayout(const YGNodeRef node) {
|
||||
if (YGFlexDirectionIsColumn(node->style.flexDirection)) {
|
||||
return false;
|
||||
}
|
||||
if (node->style.alignItems == YGAlignBaseline) {
|
||||
return true;
|
||||
}
|
||||
for (uint32_t i = 0; i < YGNodeGetChildCount(node); i++) {
|
||||
const YGNodeRef child = YGNodeGetChild(node, i);
|
||||
if (child->style.positionType == YGPositionTypeRelative &&
|
||||
child->style.alignSelf == YGAlignBaseline) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static inline float YGNodeDimWithMargin(const YGNodeRef node,
|
||||
const YGFlexDirection axis,
|
||||
const float widthSize) {
|
||||
@@ -1583,8 +1649,6 @@ static bool YGNodeFixedSizeSetMeasuredDimensions(const YGNodeRef node,
|
||||
// * Margins cannot be specified as 'auto'. They must be specified in terms of
|
||||
// pixel
|
||||
// values, and the default value is 0.
|
||||
// * The 'baseline' value is not supported for alignItems and alignSelf
|
||||
// properties.
|
||||
// * Values of width, maxWidth, minWidth, height, maxHeight and minHeight must
|
||||
// be
|
||||
// specified as pixel values, not as percentages.
|
||||
@@ -1680,10 +1744,22 @@ static void YGNodelayoutImpl(const YGNodeRef node,
|
||||
const YGDirection direction = YGNodeResolveDirection(node, parentDirection);
|
||||
node->layout.direction = direction;
|
||||
|
||||
node->layout.padding[YGEdgeStart] = YGNodeLeadingPadding(node, YGFlexDirectionResolve(YGFlexDirectionRow, direction), parentWidth);
|
||||
node->layout.padding[YGEdgeEnd] = YGNodeTrailingPadding(node, YGFlexDirectionResolve(YGFlexDirectionRow, direction), parentWidth);
|
||||
node->layout.padding[YGEdgeTop] = YGNodeLeadingPadding(node, YGFlexDirectionResolve(YGFlexDirectionColumn, direction), parentWidth);
|
||||
node->layout.padding[YGEdgeBottom] = YGNodeTrailingPadding(node, YGFlexDirectionResolve(YGFlexDirectionColumn, direction), parentWidth);
|
||||
node->layout.padding[YGEdgeStart] =
|
||||
YGNodeLeadingPadding(node,
|
||||
YGFlexDirectionResolve(YGFlexDirectionRow, direction),
|
||||
parentWidth);
|
||||
node->layout.padding[YGEdgeEnd] =
|
||||
YGNodeTrailingPadding(node,
|
||||
YGFlexDirectionResolve(YGFlexDirectionRow, direction),
|
||||
parentWidth);
|
||||
node->layout.padding[YGEdgeTop] =
|
||||
YGNodeLeadingPadding(node,
|
||||
YGFlexDirectionResolve(YGFlexDirectionColumn, direction),
|
||||
parentWidth);
|
||||
node->layout.padding[YGEdgeBottom] =
|
||||
YGNodeTrailingPadding(node,
|
||||
YGFlexDirectionResolve(YGFlexDirectionColumn, direction),
|
||||
parentWidth);
|
||||
|
||||
if (node->measure) {
|
||||
YGNodeWithMeasureFuncSetMeasuredDimensions(
|
||||
@@ -2452,7 +2528,8 @@ static void YGNodelayoutImpl(const YGNodeRef node,
|
||||
}
|
||||
|
||||
// STEP 8: MULTI-LINE CONTENT ALIGNMENT
|
||||
if (lineCount > 1 && performLayout && !YGFloatIsUndefined(availableInnerCrossDim)) {
|
||||
if (performLayout && (lineCount > 1 || YGIsBaselineLayout(node)) &&
|
||||
!YGFloatIsUndefined(availableInnerCrossDim)) {
|
||||
const float remainingAlignContentDim = availableInnerCrossDim - totalLineCrossDim;
|
||||
|
||||
float crossDimLead = 0;
|
||||
@@ -2472,6 +2549,7 @@ static void YGNodelayoutImpl(const YGNodeRef node,
|
||||
break;
|
||||
case YGAlignAuto:
|
||||
case YGAlignFlexStart:
|
||||
case YGAlignBaseline:
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -2482,6 +2560,8 @@ static void YGNodelayoutImpl(const YGNodeRef node,
|
||||
|
||||
// compute the line's height and find the endIndex
|
||||
float lineHeight = 0;
|
||||
float maxAscentForCurrentLine = 0;
|
||||
float maxDescentForCurrentLine = 0;
|
||||
for (ii = startIndex; ii < childCount; ii++) {
|
||||
const YGNodeRef child = YGNodeListGet(node->children, ii);
|
||||
|
||||
@@ -2489,12 +2569,22 @@ static void YGNodelayoutImpl(const YGNodeRef node,
|
||||
if (child->lineIndex != i) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (YGNodeIsLayoutDimDefined(child, crossAxis)) {
|
||||
lineHeight = fmaxf(lineHeight,
|
||||
child->layout.measuredDimensions[dim[crossAxis]] +
|
||||
YGNodeMarginForAxis(child, crossAxis, availableInnerWidth));
|
||||
}
|
||||
if (YGNodeAlignItem(node, child) == YGAlignBaseline) {
|
||||
const float ascent =
|
||||
YGBaseline(child) +
|
||||
YGNodeLeadingMargin(child, YGFlexDirectionColumn, availableInnerWidth);
|
||||
const float descent =
|
||||
child->layout.measuredDimensions[YGDimensionHeight] +
|
||||
YGNodeMarginForAxis(child, YGFlexDirectionColumn, availableInnerWidth) - ascent;
|
||||
maxAscentForCurrentLine = fmaxf(maxAscentForCurrentLine, ascent);
|
||||
maxDescentForCurrentLine = fmaxf(maxDescentForCurrentLine, descent);
|
||||
lineHeight = fmaxf(lineHeight, maxAscentForCurrentLine + maxDescentForCurrentLine);
|
||||
}
|
||||
}
|
||||
}
|
||||
endIndex = ii;
|
||||
@@ -2531,6 +2621,12 @@ static void YGNodelayoutImpl(const YGNodeRef node,
|
||||
// (auto) crossAxis dimension.
|
||||
break;
|
||||
}
|
||||
case YGAlignBaseline: {
|
||||
child->layout.position[YGEdgeTop] =
|
||||
currentLead + maxAscentForCurrentLine - YGBaseline(child) +
|
||||
YGNodeLeadingPosition(child, YGFlexDirectionColumn, availableInnerCrossDim);
|
||||
break;
|
||||
}
|
||||
case YGAlignAuto:
|
||||
break;
|
||||
}
|
||||
|
@@ -49,6 +49,7 @@ typedef YGSize (*YGMeasureFunc)(YGNodeRef node,
|
||||
YGMeasureMode widthMode,
|
||||
float height,
|
||||
YGMeasureMode heightMode);
|
||||
typedef float (*YGBaselineFunc)(YGNodeRef node, const float width, const float height);
|
||||
typedef void (*YGPrintFunc)(YGNodeRef node);
|
||||
typedef int (*YGLogger)(YGLogLevel level, const char *format, va_list args);
|
||||
|
||||
@@ -138,6 +139,7 @@ WIN_EXPORT void YGNodeCopyStyle(const YGNodeRef dstNode, const YGNodeRef srcNode
|
||||
|
||||
YG_NODE_PROPERTY(void *, Context, context);
|
||||
YG_NODE_PROPERTY(YGMeasureFunc, MeasureFunc, measureFunc);
|
||||
YG_NODE_PROPERTY(YGBaselineFunc, BaselineFunc, baselineFunc)
|
||||
YG_NODE_PROPERTY(YGPrintFunc, PrintFunc, printFunc);
|
||||
YG_NODE_PROPERTY(bool, HasNewLayout, hasNewLayout);
|
||||
|
||||
|
Reference in New Issue
Block a user