added functionality using which child node can tell parent node to use it as a reference baseline

Summary:
@public
Currently only parent can tell the layout to align its children based on baseline. But if one of the children is a column or row then basealign does not work as expected.

We have added an api setReferenceBaseline which when set to true would mean that it's baseline would be considered as the reference baseline for parent amongst its siblings. If there are more than one siblings with referenceBaseline set, the first one would be considered.

Reviewed By: davidaurelio

Differential Revision: D12883323

fbshipit-source-id: 19beccfc47d98bb38f81f5b66ba764e83680f821
This commit is contained in:
Sidharth Guglani
2018-11-14 02:49:27 -08:00
committed by Facebook Github Bot
parent 7a60399b2b
commit 4e2011c381
11 changed files with 774 additions and 4 deletions

View File

@@ -88,6 +88,14 @@ namespace Facebook.Yoga
[DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
public static extern void YGNodeRemoveChild(YGNodeHandle node, YGNodeHandle child);
[DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
public static extern void YGNodeSetIsReferenceBaseline(
YGNodeHandle node,
bool isReferenceBaseline);
[DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
public static extern bool YGNodeIsReferenceBaseline(YGNodeHandle node);
[DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
public static extern void YGNodeCalculateLayout(
YGNodeHandle node,

View File

@@ -519,6 +519,19 @@ namespace Facebook.Yoga
Native.YGNodeSetHasNewLayout(_ygNode, false);
}
public bool IsReferenceBaseline
{
get
{
return Native.YGNodeIsReferenceBaseline(_ygNode);
}
set
{
Native.YGNodeSetIsReferenceBaseline(_ygNode, value);
}
}
public bool ValuesEqual(float f1, float f2)
{
if (float.IsNaN(f1) || float.IsNaN(f2))
@@ -594,7 +607,7 @@ namespace Facebook.Yoga
}
public void CalculateLayout(
float width = YogaConstants.Undefined,
float width = YogaConstants.Undefined,
float height = YogaConstants.Undefined)
{
Native.YGNodeCalculateLayout(

View File

@@ -159,6 +159,7 @@ public class YogaNode implements Cloneable {
}
private static native void jni_YGNodeInsertChild(long nativePointer, long childPointer, int index);
public void addChildAt(YogaNode child, int i) {
if (child.mOwner != null) {
throw new IllegalStateException("Child already has a parent, it must be removed first.");
@@ -183,6 +184,18 @@ public class YogaNode implements Cloneable {
jni_YGNodeInsertSharedChild(mNativePointer, child.mNativePointer, i);
}
private static native void jni_YGNodeSetIsReferenceBaseline(long nativePointer, boolean isReferenceBaseline);
public void setIsReferenceBaseline(boolean isReferenceBaseline) {
jni_YGNodeSetIsReferenceBaseline(mNativePointer, isReferenceBaseline);
}
private static native boolean jni_YGNodeIsReferenceBaseline(long nativePointer);
public boolean isReferenceBaseline() {
return jni_YGNodeIsReferenceBaseline(mNativePointer);
}
private static native void jni_YGNodeSetOwner(long nativePointer, long newOwnerNativePointer);
private native long jni_YGNodeClone(long nativePointer, Object newNode);

View File

@@ -371,6 +371,17 @@ void jni_YGNodeRemoveChild(jlong nativePointer, jlong childPointer) {
_jlong2YGNodeRef(nativePointer), _jlong2YGNodeRef(childPointer));
}
void jni_YGNodeSetIsReferenceBaseline(
jlong nativePointer,
jboolean isReferenceBaseline) {
YGNodeSetIsReferenceBaseline(
_jlong2YGNodeRef(nativePointer), isReferenceBaseline);
}
jboolean jni_YGNodeIsReferenceBaseline(jlong nativePointer) {
return YGNodeIsReferenceBaseline(_jlong2YGNodeRef(nativePointer));
}
void jni_YGNodeCalculateLayout(
alias_ref<jclass>,
jlong nativePointer,
@@ -666,6 +677,8 @@ jint jni_YGNodeGetInstanceCount() {
YGMakeCriticalNativeMethod(jni_YGNodeInsertChild), \
YGMakeCriticalNativeMethod(jni_YGNodeInsertSharedChild), \
YGMakeCriticalNativeMethod(jni_YGNodeRemoveChild), \
YGMakeCriticalNativeMethod(jni_YGNodeSetIsReferenceBaseline), \
YGMakeCriticalNativeMethod(jni_YGNodeIsReferenceBaseline), \
YGMakeNativeMethod(jni_YGNodeCalculateLayout), \
YGMakeCriticalNativeMethod(jni_YGNodeMarkDirty), \
YGMakeCriticalNativeMethod( \

View File

@@ -253,6 +253,10 @@ void Node::setPaddingPercent(int edge, double padding)
YGNodeStyleSetPaddingPercent(m_node, static_cast<YGEdge>(edge), padding);
}
void Node::setIsReferenceBaseline(bool isReferenceBaseline) {
YGNodeSetIsReferenceBaseline(m_node, isReferenceBaseline);
}
int Node::getPositionType(void) const
{
return YGNodeStyleGetPositionType(m_node);
@@ -368,6 +372,10 @@ Value Node::getPadding(int edge) const
return Value::fromYGValue(YGNodeStyleGetPadding(m_node, static_cast<YGEdge>(edge)));
}
bool Node::isReferenceBaseline() {
return YGNodeIsReferenceBaseline(m_node);
}
void Node::insertChild(Node * child, unsigned index)
{
YGNodeInsertChild(m_node, child->m_node, index);

View File

@@ -187,7 +187,9 @@ class Node {
double getComputedBorder(int edge) const;
double getComputedPadding(int edge) const;
private:
public:
void setIsReferenceBaseline(bool isReferenceBaseline);
bool isReferenceBaseline();
YGNodeRef m_node;

View File

@@ -150,6 +150,9 @@ NBIND_CLASS(Node)
method(getParent);
method(getChild);
method(isReferenceBaseline);
method(setIsReferenceBaseline);
method(setMeasureFunc);
method(unsetMeasureFunc);

View File

@@ -5,8 +5,8 @@
* file in the root directory of this source tree.
*
*/
#include <gtest/gtest.h>
#include <yoga/YGNode.h>
#include <yoga/Yoga.h>
static float
@@ -38,6 +38,22 @@ static YGSize _measure2(
};
}
static YGNodeRef createYGNode(
YGConfigRef config,
YGFlexDirection direction,
int width,
int height,
bool alignBaseline) {
const YGNodeRef node = YGNodeNewWithConfig(config);
YGNodeStyleSetFlexDirection(node, direction);
if (alignBaseline) {
YGNodeStyleSetAlignItems(node, YGAlignBaseline);
}
YGNodeStyleSetWidth(node, width);
YGNodeStyleSetHeight(node, height);
return node;
}
// Test case for bug in T32999822
TEST(YogaTest, align_baseline_parent_ht_not_specified) {
YGConfigRef config = YGConfigNew();
@@ -164,3 +180,673 @@ TEST(YogaTest, align_baseline_with_no_baseline_func_and_no_parent_ht) {
YGConfigFree(config);
}
TEST(YogaTest, align_baseline_parent_using_child_in_column_as_reference) {
YGConfigRef config = YGConfigNew();
const YGNodeRef root =
createYGNode(config, YGFlexDirectionRow, 1000, 1000, true);
const YGNodeRef root_child0 =
createYGNode(config, YGFlexDirectionColumn, 500, 600, false);
YGNodeInsertChild(root, root_child0, 0);
const YGNodeRef root_child1 =
createYGNode(config, YGFlexDirectionColumn, 500, 800, false);
YGNodeInsertChild(root, root_child1, 1);
const YGNodeRef root_child1_child0 =
createYGNode(config, YGFlexDirectionColumn, 500, 300, false);
YGNodeInsertChild(root_child1, root_child1_child0, 0);
const YGNodeRef root_child1_child1 =
createYGNode(config, YGFlexDirectionColumn, 500, 400, false);
root_child1_child1->setBaseLineFunc(_baselineFunc);
YGNodeSetIsReferenceBaseline(root_child1_child1, true);
YGNodeInsertChild(root_child1, root_child1_child1, 1);
YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
ASSERT_FLOAT_EQ(500, YGNodeLayoutGetLeft(root_child1));
ASSERT_FLOAT_EQ(100, YGNodeLayoutGetTop(root_child1));
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child1_child0));
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child1_child0));
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child1_child1));
ASSERT_FLOAT_EQ(300, YGNodeLayoutGetTop(root_child1_child1));
YGNodeFreeRecursive(root);
YGConfigFree(config);
}
TEST(
YogaTest,
align_baseline_parent_using_child_with_padding_in_column_as_reference) {
YGConfigRef config = YGConfigNew();
const YGNodeRef root =
createYGNode(config, YGFlexDirectionRow, 1000, 1000, true);
const YGNodeRef root_child0 =
createYGNode(config, YGFlexDirectionColumn, 500, 600, false);
YGNodeInsertChild(root, root_child0, 0);
const YGNodeRef root_child1 =
createYGNode(config, YGFlexDirectionColumn, 500, 800, false);
YGNodeInsertChild(root, root_child1, 1);
const YGNodeRef root_child1_child0 =
createYGNode(config, YGFlexDirectionColumn, 500, 300, false);
YGNodeInsertChild(root_child1, root_child1_child0, 0);
const YGNodeRef root_child1_child1 =
createYGNode(config, YGFlexDirectionColumn, 500, 400, false);
root_child1_child1->setBaseLineFunc(_baselineFunc);
YGNodeSetIsReferenceBaseline(root_child1_child1, true);
YGNodeStyleSetPadding(root_child1_child1, YGEdgeLeft, 100);
YGNodeStyleSetPadding(root_child1_child1, YGEdgeRight, 100);
YGNodeStyleSetPadding(root_child1_child1, YGEdgeTop, 100);
YGNodeStyleSetPadding(root_child1_child1, YGEdgeBottom, 100);
YGNodeInsertChild(root_child1, root_child1_child1, 1);
YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
ASSERT_FLOAT_EQ(500, YGNodeLayoutGetLeft(root_child1));
ASSERT_FLOAT_EQ(100, YGNodeLayoutGetTop(root_child1));
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child1_child0));
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child1_child0));
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child1_child1));
ASSERT_FLOAT_EQ(300, YGNodeLayoutGetTop(root_child1_child1));
YGNodeFreeRecursive(root);
YGConfigFree(config);
}
TEST(
YogaTest,
align_baseline_parent_with_padding_using_child_in_column_as_reference) {
YGConfigRef config = YGConfigNew();
const YGNodeRef root =
createYGNode(config, YGFlexDirectionRow, 1000, 1000, true);
const YGNodeRef root_child0 =
createYGNode(config, YGFlexDirectionColumn, 500, 600, false);
YGNodeInsertChild(root, root_child0, 0);
const YGNodeRef root_child1 =
createYGNode(config, YGFlexDirectionColumn, 500, 800, false);
YGNodeStyleSetPadding(root_child1, YGEdgeLeft, 100);
YGNodeStyleSetPadding(root_child1, YGEdgeRight, 100);
YGNodeStyleSetPadding(root_child1, YGEdgeTop, 100);
YGNodeStyleSetPadding(root_child1, YGEdgeBottom, 100);
YGNodeInsertChild(root, root_child1, 1);
const YGNodeRef root_child1_child0 =
createYGNode(config, YGFlexDirectionColumn, 500, 300, false);
YGNodeInsertChild(root_child1, root_child1_child0, 0);
const YGNodeRef root_child1_child1 =
createYGNode(config, YGFlexDirectionColumn, 500, 400, false);
root_child1_child1->setBaseLineFunc(_baselineFunc);
YGNodeSetIsReferenceBaseline(root_child1_child1, true);
YGNodeInsertChild(root_child1, root_child1_child1, 1);
YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
ASSERT_FLOAT_EQ(500, YGNodeLayoutGetLeft(root_child1));
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child1));
ASSERT_FLOAT_EQ(100, YGNodeLayoutGetLeft(root_child1_child0));
ASSERT_FLOAT_EQ(100, YGNodeLayoutGetTop(root_child1_child0));
ASSERT_FLOAT_EQ(100, YGNodeLayoutGetLeft(root_child1_child1));
ASSERT_FLOAT_EQ(400, YGNodeLayoutGetTop(root_child1_child1));
YGNodeFreeRecursive(root);
YGConfigFree(config);
}
TEST(
YogaTest,
align_baseline_parent_with_margin_using_child_in_column_as_reference) {
YGConfigRef config = YGConfigNew();
const YGNodeRef root =
createYGNode(config, YGFlexDirectionRow, 1000, 1000, true);
const YGNodeRef root_child0 =
createYGNode(config, YGFlexDirectionColumn, 500, 600, false);
YGNodeInsertChild(root, root_child0, 0);
const YGNodeRef root_child1 =
createYGNode(config, YGFlexDirectionColumn, 500, 800, false);
YGNodeStyleSetMargin(root_child1, YGEdgeLeft, 100);
YGNodeStyleSetMargin(root_child1, YGEdgeRight, 100);
YGNodeStyleSetMargin(root_child1, YGEdgeTop, 100);
YGNodeStyleSetMargin(root_child1, YGEdgeBottom, 100);
YGNodeInsertChild(root, root_child1, 1);
const YGNodeRef root_child1_child0 =
createYGNode(config, YGFlexDirectionColumn, 500, 300, false);
YGNodeInsertChild(root_child1, root_child1_child0, 0);
const YGNodeRef root_child1_child1 =
createYGNode(config, YGFlexDirectionColumn, 500, 400, false);
root_child1_child1->setBaseLineFunc(_baselineFunc);
YGNodeSetIsReferenceBaseline(root_child1_child1, true);
YGNodeInsertChild(root_child1, root_child1_child1, 1);
YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
ASSERT_FLOAT_EQ(600, YGNodeLayoutGetLeft(root_child1));
ASSERT_FLOAT_EQ(100, YGNodeLayoutGetTop(root_child1));
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child1_child0));
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child1_child0));
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child1_child1));
ASSERT_FLOAT_EQ(300, YGNodeLayoutGetTop(root_child1_child1));
YGNodeFreeRecursive(root);
YGConfigFree(config);
}
TEST(
YogaTest,
align_baseline_parent_using_child_with_margin_in_column_as_reference) {
YGConfigRef config = YGConfigNew();
const YGNodeRef root =
createYGNode(config, YGFlexDirectionRow, 1000, 1000, true);
const YGNodeRef root_child0 =
createYGNode(config, YGFlexDirectionColumn, 500, 600, false);
YGNodeInsertChild(root, root_child0, 0);
const YGNodeRef root_child1 =
createYGNode(config, YGFlexDirectionColumn, 500, 800, false);
YGNodeInsertChild(root, root_child1, 1);
const YGNodeRef root_child1_child0 =
createYGNode(config, YGFlexDirectionColumn, 500, 300, false);
YGNodeInsertChild(root_child1, root_child1_child0, 0);
const YGNodeRef root_child1_child1 =
createYGNode(config, YGFlexDirectionColumn, 500, 400, false);
root_child1_child1->setBaseLineFunc(_baselineFunc);
YGNodeSetIsReferenceBaseline(root_child1_child1, true);
YGNodeStyleSetMargin(root_child1_child1, YGEdgeLeft, 100);
YGNodeStyleSetMargin(root_child1_child1, YGEdgeRight, 100);
YGNodeStyleSetMargin(root_child1_child1, YGEdgeTop, 100);
YGNodeStyleSetMargin(root_child1_child1, YGEdgeBottom, 100);
YGNodeInsertChild(root_child1, root_child1_child1, 1);
YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
ASSERT_FLOAT_EQ(500, YGNodeLayoutGetLeft(root_child1));
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child1));
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child1_child0));
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child1_child0));
ASSERT_FLOAT_EQ(100, YGNodeLayoutGetLeft(root_child1_child1));
ASSERT_FLOAT_EQ(400, YGNodeLayoutGetTop(root_child1_child1));
YGNodeFreeRecursive(root);
YGConfigFree(config);
}
TEST(YogaTest, align_baseline_parent_using_child_in_row_as_reference) {
YGConfigRef config = YGConfigNew();
const YGNodeRef root =
createYGNode(config, YGFlexDirectionRow, 1000, 1000, true);
const YGNodeRef root_child0 =
createYGNode(config, YGFlexDirectionColumn, 500, 600, false);
YGNodeInsertChild(root, root_child0, 0);
const YGNodeRef root_child1 =
createYGNode(config, YGFlexDirectionRow, 500, 800, true);
YGNodeInsertChild(root, root_child1, 1);
const YGNodeRef root_child1_child0 =
createYGNode(config, YGFlexDirectionColumn, 500, 500, false);
YGNodeInsertChild(root_child1, root_child1_child0, 0);
const YGNodeRef root_child1_child1 =
createYGNode(config, YGFlexDirectionColumn, 500, 400, false);
root_child1_child1->setBaseLineFunc(_baselineFunc);
YGNodeSetIsReferenceBaseline(root_child1_child1, true);
YGNodeInsertChild(root_child1, root_child1_child1, 1);
YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
ASSERT_FLOAT_EQ(500, YGNodeLayoutGetLeft(root_child1));
ASSERT_FLOAT_EQ(100, YGNodeLayoutGetTop(root_child1));
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child1_child0));
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child1_child0));
ASSERT_FLOAT_EQ(500, YGNodeLayoutGetLeft(root_child1_child1));
ASSERT_FLOAT_EQ(300, YGNodeLayoutGetTop(root_child1_child1));
YGNodeFreeRecursive(root);
YGConfigFree(config);
}
TEST(
YogaTest,
align_baseline_parent_using_child_with_padding_in_row_as_reference) {
YGConfigRef config = YGConfigNew();
const YGNodeRef root =
createYGNode(config, YGFlexDirectionRow, 1000, 1000, true);
const YGNodeRef root_child0 =
createYGNode(config, YGFlexDirectionColumn, 500, 600, false);
YGNodeInsertChild(root, root_child0, 0);
const YGNodeRef root_child1 =
createYGNode(config, YGFlexDirectionRow, 500, 800, true);
YGNodeInsertChild(root, root_child1, 1);
const YGNodeRef root_child1_child0 =
createYGNode(config, YGFlexDirectionColumn, 500, 500, false);
YGNodeInsertChild(root_child1, root_child1_child0, 0);
const YGNodeRef root_child1_child1 =
createYGNode(config, YGFlexDirectionColumn, 500, 400, false);
root_child1_child1->setBaseLineFunc(_baselineFunc);
YGNodeSetIsReferenceBaseline(root_child1_child1, true);
YGNodeStyleSetPadding(root_child1_child1, YGEdgeLeft, 100);
YGNodeStyleSetPadding(root_child1_child1, YGEdgeRight, 100);
YGNodeStyleSetPadding(root_child1_child1, YGEdgeTop, 100);
YGNodeStyleSetPadding(root_child1_child1, YGEdgeBottom, 100);
YGNodeInsertChild(root_child1, root_child1_child1, 1);
YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
ASSERT_FLOAT_EQ(500, YGNodeLayoutGetLeft(root_child1));
ASSERT_FLOAT_EQ(100, YGNodeLayoutGetTop(root_child1));
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child1_child0));
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child1_child0));
ASSERT_FLOAT_EQ(500, YGNodeLayoutGetLeft(root_child1_child1));
ASSERT_FLOAT_EQ(300, YGNodeLayoutGetTop(root_child1_child1));
YGNodeFreeRecursive(root);
YGConfigFree(config);
}
TEST(
YogaTest,
align_baseline_parent_using_child_with_margin_in_row_as_reference) {
YGConfigRef config = YGConfigNew();
const YGNodeRef root =
createYGNode(config, YGFlexDirectionRow, 1000, 1000, true);
const YGNodeRef root_child0 =
createYGNode(config, YGFlexDirectionColumn, 500, 600, false);
YGNodeInsertChild(root, root_child0, 0);
const YGNodeRef root_child1 =
createYGNode(config, YGFlexDirectionRow, 500, 800, true);
YGNodeInsertChild(root, root_child1, 1);
const YGNodeRef root_child1_child0 =
createYGNode(config, YGFlexDirectionColumn, 500, 500, false);
YGNodeInsertChild(root_child1, root_child1_child0, 0);
const YGNodeRef root_child1_child1 =
createYGNode(config, YGFlexDirectionColumn, 500, 400, false);
root_child1_child1->setBaseLineFunc(_baselineFunc);
YGNodeSetIsReferenceBaseline(root_child1_child1, true);
YGNodeStyleSetMargin(root_child1_child1, YGEdgeLeft, 100);
YGNodeStyleSetMargin(root_child1_child1, YGEdgeRight, 100);
YGNodeStyleSetMargin(root_child1_child1, YGEdgeTop, 100);
YGNodeStyleSetMargin(root_child1_child1, YGEdgeBottom, 100);
YGNodeInsertChild(root_child1, root_child1_child1, 1);
YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
ASSERT_FLOAT_EQ(500, YGNodeLayoutGetLeft(root_child1));
ASSERT_FLOAT_EQ(100, YGNodeLayoutGetTop(root_child1));
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child1_child0));
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child1_child0));
ASSERT_FLOAT_EQ(600, YGNodeLayoutGetLeft(root_child1_child1));
ASSERT_FLOAT_EQ(300, YGNodeLayoutGetTop(root_child1_child1));
YGNodeFreeRecursive(root);
YGConfigFree(config);
}
TEST(
YogaTest,
align_baseline_parent_using_child_in_column_as_reference_with_no_baseline_func) {
YGConfigRef config = YGConfigNew();
const YGNodeRef root =
createYGNode(config, YGFlexDirectionRow, 1000, 1000, true);
const YGNodeRef root_child0 =
createYGNode(config, YGFlexDirectionColumn, 500, 600, false);
YGNodeInsertChild(root, root_child0, 0);
const YGNodeRef root_child1 =
createYGNode(config, YGFlexDirectionColumn, 500, 800, false);
YGNodeInsertChild(root, root_child1, 1);
const YGNodeRef root_child1_child0 =
createYGNode(config, YGFlexDirectionColumn, 500, 300, false);
YGNodeInsertChild(root_child1, root_child1_child0, 0);
const YGNodeRef root_child1_child1 =
createYGNode(config, YGFlexDirectionColumn, 500, 400, false);
YGNodeSetIsReferenceBaseline(root_child1_child1, true);
YGNodeInsertChild(root_child1, root_child1_child1, 1);
YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
ASSERT_FLOAT_EQ(100, YGNodeLayoutGetTop(root_child0));
ASSERT_FLOAT_EQ(500, YGNodeLayoutGetLeft(root_child1));
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child1));
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child1_child0));
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child1_child0));
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child1_child1));
ASSERT_FLOAT_EQ(300, YGNodeLayoutGetTop(root_child1_child1));
YGNodeFreeRecursive(root);
YGConfigFree(config);
}
TEST(
YogaTest,
align_baseline_parent_using_child_in_row_as_reference_with_no_baseline_func) {
YGConfigRef config = YGConfigNew();
const YGNodeRef root =
createYGNode(config, YGFlexDirectionRow, 1000, 1000, true);
const YGNodeRef root_child0 =
createYGNode(config, YGFlexDirectionColumn, 500, 600, false);
YGNodeInsertChild(root, root_child0, 0);
const YGNodeRef root_child1 =
createYGNode(config, YGFlexDirectionRow, 500, 800, true);
YGNodeInsertChild(root, root_child1, 1);
const YGNodeRef root_child1_child0 =
createYGNode(config, YGFlexDirectionColumn, 500, 500, false);
YGNodeInsertChild(root_child1, root_child1_child0, 0);
const YGNodeRef root_child1_child1 =
createYGNode(config, YGFlexDirectionColumn, 500, 400, false);
YGNodeSetIsReferenceBaseline(root_child1_child1, true);
YGNodeInsertChild(root_child1, root_child1_child1, 1);
YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
ASSERT_FLOAT_EQ(500, YGNodeLayoutGetLeft(root_child1));
ASSERT_FLOAT_EQ(100, YGNodeLayoutGetTop(root_child1));
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child1_child0));
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child1_child0));
ASSERT_FLOAT_EQ(500, YGNodeLayoutGetLeft(root_child1_child1));
ASSERT_FLOAT_EQ(100, YGNodeLayoutGetTop(root_child1_child1));
YGNodeFreeRecursive(root);
YGConfigFree(config);
}
TEST(
YogaTest,
align_baseline_parent_using_child_in_column_as_reference_with_height_not_specified) {
YGConfigRef config = YGConfigNew();
const YGNodeRef root = YGNodeNewWithConfig(config);
YGNodeStyleSetFlexDirection(root, YGFlexDirectionRow);
YGNodeStyleSetAlignItems(root, YGAlignBaseline);
YGNodeStyleSetWidth(root, 1000);
const YGNodeRef root_child0 =
createYGNode(config, YGFlexDirectionColumn, 500, 600, false);
YGNodeInsertChild(root, root_child0, 0);
const YGNodeRef root_child1 = YGNodeNewWithConfig(config);
YGNodeStyleSetFlexDirection(root_child1, YGFlexDirectionColumn);
YGNodeStyleSetWidth(root_child1, 500);
YGNodeInsertChild(root, root_child1, 1);
const YGNodeRef root_child1_child0 =
createYGNode(config, YGFlexDirectionColumn, 500, 300, false);
YGNodeInsertChild(root_child1, root_child1_child0, 0);
const YGNodeRef root_child1_child1 =
createYGNode(config, YGFlexDirectionColumn, 500, 400, false);
root_child1_child1->setBaseLineFunc(_baselineFunc);
YGNodeSetIsReferenceBaseline(root_child1_child1, true);
YGNodeInsertChild(root_child1, root_child1_child1, 1);
YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
ASSERT_FLOAT_EQ(800, YGNodeLayoutGetHeight(root));
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
ASSERT_FLOAT_EQ(500, YGNodeLayoutGetLeft(root_child1));
ASSERT_FLOAT_EQ(100, YGNodeLayoutGetTop(root_child1));
ASSERT_FLOAT_EQ(700, YGNodeLayoutGetHeight(root_child1));
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child1_child0));
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child1_child0));
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child1_child1));
ASSERT_FLOAT_EQ(300, YGNodeLayoutGetTop(root_child1_child1));
YGNodeFreeRecursive(root);
YGConfigFree(config);
}
TEST(
YogaTest,
align_baseline_parent_using_child_in_row_as_reference_with_height_not_specified) {
YGConfigRef config = YGConfigNew();
const YGNodeRef root = YGNodeNewWithConfig(config);
YGNodeStyleSetFlexDirection(root, YGFlexDirectionRow);
YGNodeStyleSetAlignItems(root, YGAlignBaseline);
YGNodeStyleSetWidth(root, 1000);
const YGNodeRef root_child0 =
createYGNode(config, YGFlexDirectionColumn, 500, 600, false);
YGNodeInsertChild(root, root_child0, 0);
const YGNodeRef root_child1 = YGNodeNewWithConfig(config);
YGNodeStyleSetFlexDirection(root_child1, YGFlexDirectionRow);
YGNodeStyleSetWidth(root_child1, 500);
YGNodeInsertChild(root, root_child1, 1);
const YGNodeRef root_child1_child0 =
createYGNode(config, YGFlexDirectionColumn, 500, 500, false);
YGNodeInsertChild(root_child1, root_child1_child0, 0);
const YGNodeRef root_child1_child1 =
createYGNode(config, YGFlexDirectionColumn, 500, 400, false);
root_child1_child1->setBaseLineFunc(_baselineFunc);
YGNodeSetIsReferenceBaseline(root_child1_child1, true);
YGNodeInsertChild(root_child1, root_child1_child1, 1);
YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
ASSERT_FLOAT_EQ(900, YGNodeLayoutGetHeight(root));
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
ASSERT_FLOAT_EQ(500, YGNodeLayoutGetLeft(root_child1));
ASSERT_FLOAT_EQ(400, YGNodeLayoutGetTop(root_child1));
ASSERT_FLOAT_EQ(500, YGNodeLayoutGetHeight(root_child1));
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child1_child0));
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child1_child0));
ASSERT_FLOAT_EQ(500, YGNodeLayoutGetLeft(root_child1_child1));
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child1_child1));
YGNodeFreeRecursive(root);
YGConfigFree(config);
}
TEST(
YogaTest,
align_baseline_parent_using_child_in_column_as_reference_with_no_baseline_func_and_height_not_specified) {
YGConfigRef config = YGConfigNew();
const YGNodeRef root = YGNodeNewWithConfig(config);
YGNodeStyleSetFlexDirection(root, YGFlexDirectionRow);
YGNodeStyleSetAlignItems(root, YGAlignBaseline);
YGNodeStyleSetWidth(root, 1000);
const YGNodeRef root_child0 =
createYGNode(config, YGFlexDirectionColumn, 500, 600, false);
YGNodeInsertChild(root, root_child0, 0);
const YGNodeRef root_child1 = YGNodeNewWithConfig(config);
YGNodeStyleSetFlexDirection(root_child1, YGFlexDirectionColumn);
YGNodeStyleSetWidth(root_child1, 500);
YGNodeInsertChild(root, root_child1, 1);
const YGNodeRef root_child1_child0 =
createYGNode(config, YGFlexDirectionColumn, 500, 300, false);
YGNodeInsertChild(root_child1, root_child1_child0, 0);
const YGNodeRef root_child1_child1 =
createYGNode(config, YGFlexDirectionColumn, 500, 400, false);
YGNodeSetIsReferenceBaseline(root_child1_child1, true);
YGNodeInsertChild(root_child1, root_child1_child1, 1);
YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
ASSERT_FLOAT_EQ(700, YGNodeLayoutGetHeight(root));
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
ASSERT_FLOAT_EQ(100, YGNodeLayoutGetTop(root_child0));
ASSERT_FLOAT_EQ(500, YGNodeLayoutGetLeft(root_child1));
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child1));
ASSERT_FLOAT_EQ(700, YGNodeLayoutGetHeight(root_child1));
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child1_child0));
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child1_child0));
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child1_child1));
ASSERT_FLOAT_EQ(300, YGNodeLayoutGetTop(root_child1_child1));
YGNodeFreeRecursive(root);
YGConfigFree(config);
}
TEST(
YogaTest,
align_baseline_parent_using_child_in_row_as_reference_with_no_baseline_func_and_height_not_specified) {
YGConfigRef config = YGConfigNew();
const YGNodeRef root = YGNodeNewWithConfig(config);
YGNodeStyleSetFlexDirection(root, YGFlexDirectionRow);
YGNodeStyleSetAlignItems(root, YGAlignBaseline);
YGNodeStyleSetWidth(root, 1000);
const YGNodeRef root_child0 =
createYGNode(config, YGFlexDirectionColumn, 500, 600, false);
YGNodeInsertChild(root, root_child0, 0);
const YGNodeRef root_child1 = YGNodeNewWithConfig(config);
YGNodeStyleSetFlexDirection(root_child1, YGFlexDirectionRow);
YGNodeStyleSetWidth(root_child1, 500);
YGNodeInsertChild(root, root_child1, 1);
const YGNodeRef root_child1_child0 =
createYGNode(config, YGFlexDirectionColumn, 500, 500, false);
YGNodeInsertChild(root_child1, root_child1_child0, 0);
const YGNodeRef root_child1_child1 =
createYGNode(config, YGFlexDirectionColumn, 500, 400, false);
YGNodeSetIsReferenceBaseline(root_child1_child1, true);
YGNodeInsertChild(root_child1, root_child1_child1, 1);
YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
ASSERT_FLOAT_EQ(700, YGNodeLayoutGetHeight(root));
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
ASSERT_FLOAT_EQ(500, YGNodeLayoutGetLeft(root_child1));
ASSERT_FLOAT_EQ(200, YGNodeLayoutGetTop(root_child1));
ASSERT_FLOAT_EQ(500, YGNodeLayoutGetHeight(root_child1));
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child1_child0));
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child1_child0));
ASSERT_FLOAT_EQ(500, YGNodeLayoutGetLeft(root_child1_child1));
ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child1_child1));
YGNodeFreeRecursive(root);
YGConfigFree(config);
}

View File

@@ -17,6 +17,7 @@ struct YGNode {
void* context_ = nullptr;
YGPrintFunc print_ = nullptr;
bool hasNewLayout_ = true;
bool isReferenceBaseline_ = false;
YGNodeType nodeType_ = YGNodeTypeDefault;
YGMeasureFunc measure_ = nullptr;
YGBaselineFunc baseline_ = nullptr;
@@ -93,6 +94,10 @@ struct YGNode {
return lineIndex_;
}
bool isReferenceBaseline() {
return isReferenceBaseline_;
}
// returns the YGNodeRef that owns this YGNode. An owner is used to identify
// the YogaTree that a YGNode belongs to.
// This method will return the parent of the YGNode when a YGNode only belongs
@@ -211,6 +216,10 @@ struct YGNode {
lineIndex_ = lineIndex;
}
void setIsReferenceBaseline(bool isReferenceBaseline) {
isReferenceBaseline_ = isReferenceBaseline;
}
void setOwner(YGNodeRef owner) {
owner_ = owner;
}

View File

@@ -380,6 +380,14 @@ void YGConfigCopy(const YGConfigRef dest, const YGConfigRef src) {
memcpy(dest, src, sizeof(YGConfig));
}
void YGNodeSetIsReferenceBaseline(YGNodeRef node, bool isReferenceBaseline) {
node->setIsReferenceBaseline(isReferenceBaseline);
}
bool YGNodeIsReferenceBaseline(YGNodeRef node) {
return node->isReferenceBaseline();
}
void YGNodeInsertChild(
const YGNodeRef node,
const YGNodeRef child,
@@ -1138,7 +1146,8 @@ static float YGBaseline(const YGNodeRef node) {
if (child->getStyle().positionType == YGPositionTypeAbsolute) {
continue;
}
if (YGNodeAlignItem(node, child) == YGAlignBaseline) {
if (YGNodeAlignItem(node, child) == YGAlignBaseline ||
child->isReferenceBaseline()) {
baselineChild = child;
break;
}

View File

@@ -114,6 +114,12 @@ WIN_EXPORT void YGNodeSetChildren(
const YGNodeRef children[],
const uint32_t count);
WIN_EXPORT void YGNodeSetIsReferenceBaseline(
YGNodeRef node,
bool isReferenceBaseline);
WIN_EXPORT bool YGNodeIsReferenceBaseline(YGNodeRef node);
WIN_EXPORT void YGNodeCalculateLayout(
const YGNodeRef node,
const float availableWidth,