diff --git a/React/Views/RCTShadowView.m b/React/Views/RCTShadowView.m index 9a099a51f..f38844c09 100644 --- a/React/Views/RCTShadowView.m +++ b/React/Views/RCTShadowView.m @@ -67,6 +67,8 @@ switch (ygvalue.unit) { \ case YGUnitPercent: \ setter##Percent(__VA_ARGS__, ygvalue.value); \ break; \ + case YGUnitAuto: \ + break; \ } #define DEFINE_PROCESS_META_PROPS(type) \ diff --git a/ReactAndroid/src/main/java/com/facebook/yoga/YogaNode.java b/ReactAndroid/src/main/java/com/facebook/yoga/YogaNode.java index 08edbd467..94f16a991 100644 --- a/ReactAndroid/src/main/java/com/facebook/yoga/YogaNode.java +++ b/ReactAndroid/src/main/java/com/facebook/yoga/YogaNode.java @@ -378,6 +378,12 @@ public class YogaNode implements YogaNodeAPI { jni_YGNodeStyleSetFlexBasisPercent(mNativePointer, percent); } + private native void jni_YGNodeStyleSetFlexBasisAuto(long nativePointer); + @Override + public void setFlexBasisAuto() { + jni_YGNodeStyleSetFlexBasisAuto(mNativePointer); + } + private native Object jni_YGNodeStyleGetMargin(long nativePointer, int edge); @Override public YogaValue getMargin(YogaEdge edge) { @@ -401,6 +407,13 @@ public class YogaNode implements YogaNodeAPI { jni_YGNodeStyleSetMarginPercent(mNativePointer, edge.intValue(), percent); } + private native void jni_YGNodeStyleSetMarginAuto(long nativePointer, int edge); + @Override + public void setMarginAuto(YogaEdge edge) { + mHasSetMargin = true; + jni_YGNodeStyleSetMarginAuto(mNativePointer, edge.intValue()); + } + private native Object jni_YGNodeStyleGetPadding(long nativePointer, int edge); @Override public YogaValue getPadding(YogaEdge edge) { @@ -481,6 +494,12 @@ public class YogaNode implements YogaNodeAPI { jni_YGNodeStyleSetWidthPercent(mNativePointer, percent); } + private native void jni_YGNodeStyleSetWidthAuto(long nativePointer); + @Override + public void setWidthAuto() { + jni_YGNodeStyleSetWidthAuto(mNativePointer); + } + private native Object jni_YGNodeStyleGetHeight(long nativePointer); @Override public YogaValue getHeight() { @@ -499,6 +518,12 @@ public class YogaNode implements YogaNodeAPI { jni_YGNodeStyleSetHeightPercent(mNativePointer, percent); } + private native void jni_YGNodeStyleSetHeightAuto(long nativePointer); + @Override + public void setHeightAuto() { + jni_YGNodeStyleSetHeightAuto(mNativePointer); + } + private native Object jni_YGNodeStyleGetMinWidth(long nativePointer); @Override public YogaValue getMinWidth() { diff --git a/ReactAndroid/src/main/java/com/facebook/yoga/YogaNodeAPI.java b/ReactAndroid/src/main/java/com/facebook/yoga/YogaNodeAPI.java index 406ec587e..1c4af327d 100644 --- a/ReactAndroid/src/main/java/com/facebook/yoga/YogaNodeAPI.java +++ b/ReactAndroid/src/main/java/com/facebook/yoga/YogaNodeAPI.java @@ -49,9 +49,11 @@ public interface YogaNodeAPI { YogaValue getFlexBasis(); void setFlexBasis(float flexBasis); void setFlexBasisPercent(float percent); + void setFlexBasisAuto(); YogaValue getMargin(YogaEdge edge); void setMargin(YogaEdge edge, float margin); void setMarginPercent(YogaEdge edge, float percent); + void setMarginAuto(YogaEdge edge); YogaValue getPadding(YogaEdge edge); void setPadding(YogaEdge edge, float padding); void setPaddingPercent(YogaEdge edge, float percent); @@ -63,9 +65,11 @@ public interface YogaNodeAPI { YogaValue getWidth(); void setWidth(float width); void setWidthPercent(float percent); + void setWidthAuto(); YogaValue getHeight(); void setHeight(float height); void setHeightPercent(float percent); + void setHeightAuto(); YogaValue getMaxWidth(); void setMaxWidth(float maxWidth); void setMaxWidthPercent(float percent); diff --git a/ReactAndroid/src/main/java/com/facebook/yoga/YogaUnit.java b/ReactAndroid/src/main/java/com/facebook/yoga/YogaUnit.java index f14e5216c..2fd6655b1 100644 --- a/ReactAndroid/src/main/java/com/facebook/yoga/YogaUnit.java +++ b/ReactAndroid/src/main/java/com/facebook/yoga/YogaUnit.java @@ -15,7 +15,8 @@ import com.facebook.proguard.annotations.DoNotStrip; public enum YogaUnit { UNDEFINED(0), PIXEL(1), - PERCENT(2); + PERCENT(2), + AUTO(3); private int mIntValue; @@ -32,6 +33,7 @@ public enum YogaUnit { case 0: return UNDEFINED; case 1: return PIXEL; case 2: return PERCENT; + case 3: return AUTO; default: throw new IllegalArgumentException("Unknown enum value: " + value); } } diff --git a/ReactAndroid/src/main/jni/first-party/yogajni/jni/YGJNI.cpp b/ReactAndroid/src/main/jni/first-party/yogajni/jni/YGJNI.cpp index 929235432..15f6d46f5 100644 --- a/ReactAndroid/src/main/jni/first-party/yogajni/jni/YGJNI.cpp +++ b/ReactAndroid/src/main/jni/first-party/yogajni/jni/YGJNI.cpp @@ -285,6 +285,12 @@ struct JYogaValue : public JavaClass { YGNodeStyleSet##name##Percent(_jlong2YGNodeRef(nativePointer), static_cast(value)); \ } +#define YG_NODE_JNI_STYLE_UNIT_PROP_AUTO(name) \ + YG_NODE_JNI_STYLE_UNIT_PROP(name) \ + void jni_YGNodeStyleSet##name##Auto(alias_ref, jlong nativePointer) { \ + YGNodeStyleSet##name##Auto(_jlong2YGNodeRef(nativePointer)); \ + } + #define YG_NODE_JNI_STYLE_EDGE_PROP(javatype, type, name) \ javatype jni_YGNodeStyleGet##name(alias_ref, jlong nativePointer, jint edge) { \ return (javatype) YGNodeStyleGet##name(_jlong2YGNodeRef(nativePointer), \ @@ -323,6 +329,12 @@ struct JYogaValue : public JavaClass { static_cast(value)); \ } +#define YG_NODE_JNI_STYLE_EDGE_UNIT_PROP_AUTO(name) \ + YG_NODE_JNI_STYLE_EDGE_UNIT_PROP(name) \ + void jni_YGNodeStyleSet##name##Auto(alias_ref, jlong nativePointer, jint edge) { \ + YGNodeStyleSet##name##Auto(_jlong2YGNodeRef(nativePointer), static_cast(edge)); \ + } + YG_NODE_JNI_STYLE_PROP(jint, YGDirection, Direction); YG_NODE_JNI_STYLE_PROP(jint, YGFlexDirection, FlexDirection); YG_NODE_JNI_STYLE_PROP(jint, YGJustify, JustifyContent); @@ -339,17 +351,17 @@ void jni_YGNodeStyleSetFlex(alias_ref, jlong nativePointer, jfloat valu } YG_NODE_JNI_STYLE_PROP(jfloat, float, FlexGrow); YG_NODE_JNI_STYLE_PROP(jfloat, float, FlexShrink); -YG_NODE_JNI_STYLE_UNIT_PROP(FlexBasis); +YG_NODE_JNI_STYLE_UNIT_PROP_AUTO(FlexBasis); YG_NODE_JNI_STYLE_EDGE_UNIT_PROP(Position); -YG_NODE_JNI_STYLE_EDGE_UNIT_PROP(Margin); +YG_NODE_JNI_STYLE_EDGE_UNIT_PROP_AUTO(Margin); YG_NODE_JNI_STYLE_EDGE_UNIT_PROP(Padding); YG_NODE_JNI_STYLE_EDGE_PROP(jfloat, float, Border); -YG_NODE_JNI_STYLE_UNIT_PROP(Width); +YG_NODE_JNI_STYLE_UNIT_PROP_AUTO(Width); YG_NODE_JNI_STYLE_UNIT_PROP(MinWidth); YG_NODE_JNI_STYLE_UNIT_PROP(MaxWidth); -YG_NODE_JNI_STYLE_UNIT_PROP(Height); +YG_NODE_JNI_STYLE_UNIT_PROP_AUTO(Height); YG_NODE_JNI_STYLE_UNIT_PROP(MinHeight); YG_NODE_JNI_STYLE_UNIT_PROP(MaxHeight); @@ -402,9 +414,11 @@ jint JNI_OnLoad(JavaVM *vm, void *) { YGMakeNativeMethod(jni_YGNodeStyleGetFlexBasis), YGMakeNativeMethod(jni_YGNodeStyleSetFlexBasis), YGMakeNativeMethod(jni_YGNodeStyleSetFlexBasisPercent), + YGMakeNativeMethod(jni_YGNodeStyleSetFlexBasisAuto), YGMakeNativeMethod(jni_YGNodeStyleGetMargin), YGMakeNativeMethod(jni_YGNodeStyleSetMargin), YGMakeNativeMethod(jni_YGNodeStyleSetMarginPercent), + YGMakeNativeMethod(jni_YGNodeStyleSetMarginAuto), YGMakeNativeMethod(jni_YGNodeStyleGetPadding), YGMakeNativeMethod(jni_YGNodeStyleSetPadding), YGMakeNativeMethod(jni_YGNodeStyleSetPaddingPercent), @@ -416,9 +430,11 @@ jint JNI_OnLoad(JavaVM *vm, void *) { YGMakeNativeMethod(jni_YGNodeStyleGetWidth), YGMakeNativeMethod(jni_YGNodeStyleSetWidth), YGMakeNativeMethod(jni_YGNodeStyleSetWidthPercent), + YGMakeNativeMethod(jni_YGNodeStyleSetWidthAuto), YGMakeNativeMethod(jni_YGNodeStyleGetHeight), YGMakeNativeMethod(jni_YGNodeStyleSetHeight), YGMakeNativeMethod(jni_YGNodeStyleSetHeightPercent), + YGMakeNativeMethod(jni_YGNodeStyleSetHeightAuto), YGMakeNativeMethod(jni_YGNodeStyleGetMinWidth), YGMakeNativeMethod(jni_YGNodeStyleSetMinWidth), YGMakeNativeMethod(jni_YGNodeStyleSetMinWidthPercent), diff --git a/ReactCommon/yoga/yoga/YGEnums.h b/ReactCommon/yoga/yoga/YGEnums.h index 5a97ef786..74ec96cc0 100644 --- a/ReactCommon/yoga/yoga/YGEnums.h +++ b/ReactCommon/yoga/yoga/YGEnums.h @@ -116,11 +116,12 @@ typedef YG_ENUM_BEGIN(YGPrintOptions) { YGPrintOptionsChildren = 4, } YG_ENUM_END(YGPrintOptions); -#define YGUnitCount 3 +#define YGUnitCount 4 typedef YG_ENUM_BEGIN(YGUnit) { YGUnitUndefined, YGUnitPixel, YGUnitPercent, + YGUnitAuto, } YG_ENUM_END(YGUnit); #define YGWrapCount 2 diff --git a/ReactCommon/yoga/yoga/Yoga.c b/ReactCommon/yoga/yoga/Yoga.c index cb260ae8c..7123b5b44 100644 --- a/ReactCommon/yoga/yoga/Yoga.c +++ b/ReactCommon/yoga/yoga/Yoga.c @@ -118,6 +118,9 @@ typedef struct YGNode { #define YG_UNDEFINED_VALUES \ { .value = YGUndefined, .unit = YGUnitUndefined } +#define YG_AUTO_VALUES \ + { .value = YGUndefined, .unit = YGUnitAuto } + #define YG_DEFAULT_EDGE_VALUES_UNIT \ { \ [YGEdgeLeft] = YG_UNDEFINED_VALUES, [YGEdgeTop] = YG_UNDEFINED_VALUES, \ @@ -133,6 +136,9 @@ typedef struct YGNode { #define YG_DEFAULT_DIMENSION_VALUES_UNIT \ { [YGDimensionWidth] = YG_UNDEFINED_VALUES, [YGDimensionHeight] = YG_UNDEFINED_VALUES, } +#define YG_DEFAULT_DIMENSION_VALUES_AUTO_UNIT \ + { [YGDimensionWidth] = YG_AUTO_VALUES, [YGDimensionHeight] = YG_AUTO_VALUES, } + static YGNode gYGNodeDefaults = { .parent = NULL, .children = NULL, @@ -146,7 +152,7 @@ static YGNode gYGNodeDefaults = { .flex = YGUndefined, .flexGrow = YGUndefined, .flexShrink = YGUndefined, - .flexBasis = YG_UNDEFINED_VALUES, + .flexBasis = YG_AUTO_VALUES, .justifyContent = YGJustifyFlexStart, .alignItems = YGAlignStretch, .alignContent = YGAlignFlexStart, @@ -154,7 +160,7 @@ static YGNode gYGNodeDefaults = { .flexDirection = YGFlexDirectionColumn, .overflow = YGOverflowVisible, .display = YGDisplayFlex, - .dimensions = YG_DEFAULT_DIMENSION_VALUES_UNIT, + .dimensions = YG_DEFAULT_DIMENSION_VALUES_AUTO_UNIT, .minDimensions = YG_DEFAULT_DIMENSION_VALUES_UNIT, .maxDimensions = YG_DEFAULT_DIMENSION_VALUES_UNIT, .position = YG_DEFAULT_EDGE_VALUES_UNIT, @@ -265,6 +271,7 @@ static inline const YGValue *YGComputedEdgeValue(const YGValue edges[YGEdgeCount static inline float YGValueResolve(const YGValue *const value, const float parentSize) { switch (value->unit) { case YGUnitUndefined: + case YGUnitAuto: return YGUndefined; case YGUnitPixel: return value->value; @@ -274,6 +281,10 @@ static inline float YGValueResolve(const YGValue *const value, const float paren return YGUndefined; } +static inline float YGValueResolveMargin(const YGValue *const value, const float parentSize) { + return value->unit == YGUnitAuto ? 0 : YGValueResolve(value, parentSize); +} + int32_t gNodeInstanceCount = 0; YGNodeRef YGNodeNew(void) { @@ -423,13 +434,13 @@ inline float YGNodeStyleGetFlexShrink(const YGNodeRef node) { } static inline const YGValue *YGNodeStyleGetFlexBasisPtr(const YGNodeRef node) { - if (node->style.flexBasis.unit != YGUnitUndefined) { + if (node->style.flexBasis.unit != YGUnitAuto) { return &node->style.flexBasis; } if (!YGFloatIsUndefined(node->style.flex) && node->style.flex > 0.0f) { return &YGValueZero; } - return &YGValueUndefined; + return &YGValueAuto; } inline YGValue YGNodeStyleGetFlexBasis(const YGNodeRef node) { @@ -481,6 +492,33 @@ void YGNodeStyleSetFlex(const YGNodeRef node, const float flex) { } \ } +#define YG_NODE_STYLE_PROPERTY_SETTER_UNIT_AUTO_IMPL(type, name, paramName, instanceName) \ + void YGNodeStyleSet##name(const YGNodeRef node, const type paramName) { \ + if (node->style.instanceName.value != paramName || \ + node->style.instanceName.unit != YGUnitPixel) { \ + node->style.instanceName.value = YGFloatIsUndefined(paramName) ? YGUndefined : paramName; \ + node->style.instanceName.unit = YGFloatIsUndefined(paramName) ? YGUnitAuto : YGUnitPixel; \ + YGNodeMarkDirtyInternal(node); \ + } \ + } \ + \ + void YGNodeStyleSet##name##Percent(const YGNodeRef node, const type paramName) { \ + if (node->style.instanceName.value != paramName || \ + node->style.instanceName.unit != YGUnitPercent) { \ + node->style.instanceName.value = YGFloatIsUndefined(paramName) ? YGUndefined : paramName; \ + node->style.instanceName.unit = YGFloatIsUndefined(paramName) ? YGUnitAuto : YGUnitPercent; \ + YGNodeMarkDirtyInternal(node); \ + } \ + } \ + \ + void YGNodeStyleSet##name##Auto(const YGNodeRef node) { \ + if (node->style.instanceName.unit != YGUnitAuto) { \ + node->style.instanceName.value = YGUndefined; \ + node->style.instanceName.unit = YGUnitAuto; \ + YGNodeMarkDirtyInternal(node); \ + } \ + } + #define YG_NODE_STYLE_PROPERTY_IMPL(type, name, paramName, instanceName) \ YG_NODE_STYLE_PROPERTY_SETTER_IMPL(type, name, paramName, instanceName) \ \ @@ -495,6 +533,22 @@ void YGNodeStyleSetFlex(const YGNodeRef node, const float flex) { return node->style.instanceName; \ } +#define YG_NODE_STYLE_PROPERTY_UNIT_AUTO_IMPL(type, name, paramName, instanceName) \ + YG_NODE_STYLE_PROPERTY_SETTER_UNIT_AUTO_IMPL(float, name, paramName, instanceName) \ + \ + type YGNodeStyleGet##name(const YGNodeRef node) { \ + return node->style.instanceName; \ + } + +#define YG_NODE_STYLE_EDGE_PROPERTY_UNIT_AUTO_IMPL(type, name, instanceName) \ + void YGNodeStyleSet##name##Auto(const YGNodeRef node, const YGEdge edge) { \ + if (node->style.instanceName[edge].unit != YGUnitAuto) { \ + node->style.instanceName[edge].value = YGUndefined; \ + node->style.instanceName[edge].unit = YGUnitAuto; \ + YGNodeMarkDirtyInternal(node); \ + } \ + } + #define YG_NODE_STYLE_EDGE_PROPERTY_UNIT_IMPL(type, name, paramName, instanceName) \ void YGNodeStyleSet##name(const YGNodeRef node, const YGEdge edge, const float paramName) { \ if (node->style.instanceName[edge].value != paramName || \ @@ -582,15 +636,16 @@ YG_NODE_STYLE_PROPERTY_IMPL(YGDisplay, Display, display, display); YG_NODE_STYLE_PROPERTY_SETTER_IMPL(float, FlexGrow, flexGrow, flexGrow); YG_NODE_STYLE_PROPERTY_SETTER_IMPL(float, FlexShrink, flexShrink, flexShrink); -YG_NODE_STYLE_PROPERTY_SETTER_UNIT_IMPL(float, FlexBasis, flexBasis, flexBasis); +YG_NODE_STYLE_PROPERTY_SETTER_UNIT_AUTO_IMPL(float, FlexBasis, flexBasis, flexBasis); YG_NODE_STYLE_EDGE_PROPERTY_UNIT_IMPL(YGValue, Position, position, position); YG_NODE_STYLE_EDGE_PROPERTY_UNIT_IMPL(YGValue, Margin, margin, margin); +YG_NODE_STYLE_EDGE_PROPERTY_UNIT_AUTO_IMPL(YGValue, Margin, margin); YG_NODE_STYLE_EDGE_PROPERTY_UNIT_IMPL(YGValue, Padding, padding, padding); YG_NODE_STYLE_EDGE_PROPERTY_IMPL(float, Border, border, border); -YG_NODE_STYLE_PROPERTY_UNIT_IMPL(YGValue, Width, width, dimensions[YGDimensionWidth]); -YG_NODE_STYLE_PROPERTY_UNIT_IMPL(YGValue, Height, height, dimensions[YGDimensionHeight]); +YG_NODE_STYLE_PROPERTY_UNIT_AUTO_IMPL(YGValue, Width, width, dimensions[YGDimensionWidth]); +YG_NODE_STYLE_PROPERTY_UNIT_AUTO_IMPL(YGValue, Height, height, dimensions[YGDimensionHeight]); YG_NODE_STYLE_PROPERTY_UNIT_IMPL(YGValue, MinWidth, minWidth, minDimensions[YGDimensionWidth]); YG_NODE_STYLE_PROPERTY_UNIT_IMPL(YGValue, MinHeight, minHeight, minDimensions[YGDimensionHeight]); YG_NODE_STYLE_PROPERTY_UNIT_IMPL(YGValue, MaxWidth, maxWidth, maxDimensions[YGDimensionWidth]); @@ -902,22 +957,22 @@ static inline float YGNodeLeadingMargin(const YGNodeRef node, const YGFlexDirection axis, const float widthSize) { if (YGFlexDirectionIsRow(axis) && node->style.margin[YGEdgeStart].unit != YGUnitUndefined) { - return YGValueResolve(&node->style.margin[YGEdgeStart], widthSize); + return YGValueResolveMargin(&node->style.margin[YGEdgeStart], widthSize); } - return YGValueResolve(YGComputedEdgeValue(node->style.margin, leading[axis], &YGValueZero), - widthSize); + return YGValueResolveMargin(YGComputedEdgeValue(node->style.margin, leading[axis], &YGValueZero), + widthSize); } static float YGNodeTrailingMargin(const YGNodeRef node, const YGFlexDirection axis, const float widthSize) { if (YGFlexDirectionIsRow(axis) && node->style.margin[YGEdgeEnd].unit != YGUnitUndefined) { - return YGValueResolve(&node->style.margin[YGEdgeEnd], widthSize); + return YGValueResolveMargin(&node->style.margin[YGEdgeEnd], widthSize); } - return YGValueResolve(YGComputedEdgeValue(node->style.margin, trailing[axis], &YGValueZero), - widthSize); + return YGValueResolveMargin(YGComputedEdgeValue(node->style.margin, trailing[axis], &YGValueZero), + widthSize); } static float YGNodeLeadingPadding(const YGNodeRef node, @@ -1096,7 +1151,8 @@ static inline float YGNodeDimWithMargin(const YGNodeRef node, static inline bool YGNodeIsStyleDimDefined(const YGNodeRef node, const YGFlexDirection axis, const float parentSize) { - return !(node->resolvedDimensions[dim[axis]]->unit == YGUnitUndefined || + return !(node->resolvedDimensions[dim[axis]]->unit == YGUnitAuto || + node->resolvedDimensions[dim[axis]]->unit == YGUnitUndefined || (node->resolvedDimensions[dim[axis]]->unit == YGUnitPixel && node->resolvedDimensions[dim[axis]]->value < 0.0f) || (node->resolvedDimensions[dim[axis]]->unit == YGUnitPercent && @@ -2430,27 +2486,42 @@ static void YGNodelayoutImpl(const YGNodeRef node, } } - switch (justifyContent) { - case YGJustifyCenter: - leadingMainDim = remainingFreeSpace / 2; - break; - case YGJustifyFlexEnd: - leadingMainDim = remainingFreeSpace; - break; - case YGJustifySpaceBetween: - if (itemsOnLine > 1) { - betweenMainDim = fmaxf(remainingFreeSpace, 0) / (itemsOnLine - 1); - } else { - betweenMainDim = 0; + int numberOfAutoMarginsOnCurrentLine = 0; + for (uint32_t i = startOfLineIndex; i < endOfLineIndex; i++) { + const YGNodeRef child = YGNodeListGet(node->children, i); + if (child->style.positionType == YGPositionTypeRelative) { + if (child->style.margin[leading[mainAxis]].unit == YGUnitAuto) { + numberOfAutoMarginsOnCurrentLine++; } - break; - case YGJustifySpaceAround: - // Space on the edges is half of the space between elements - betweenMainDim = remainingFreeSpace / itemsOnLine; - leadingMainDim = betweenMainDim / 2; - break; - case YGJustifyFlexStart: - break; + if (child->style.margin[trailing[mainAxis]].unit == YGUnitAuto) { + numberOfAutoMarginsOnCurrentLine++; + } + } + } + + if (numberOfAutoMarginsOnCurrentLine == 0) { + switch (justifyContent) { + case YGJustifyCenter: + leadingMainDim = remainingFreeSpace / 2; + break; + case YGJustifyFlexEnd: + leadingMainDim = remainingFreeSpace; + break; + case YGJustifySpaceBetween: + if (itemsOnLine > 1) { + betweenMainDim = fmaxf(remainingFreeSpace, 0) / (itemsOnLine - 1); + } else { + betweenMainDim = 0; + } + break; + case YGJustifySpaceAround: + // Space on the edges is half of the space between elements + betweenMainDim = remainingFreeSpace / itemsOnLine; + leadingMainDim = betweenMainDim / 2; + break; + case YGJustifyFlexStart: + break; + } } float mainDim = leadingPaddingAndBorderMain + leadingMainDim; @@ -2477,10 +2548,18 @@ static void YGNodelayoutImpl(const YGNodeRef node, // We need to do that only for relative elements. Absolute elements // do not take part in that phase. if (child->style.positionType == YGPositionTypeRelative) { + if (child->style.margin[leading[mainAxis]].unit == YGUnitAuto) { + mainDim += remainingFreeSpace / numberOfAutoMarginsOnCurrentLine; + } + if (performLayout) { child->layout.position[pos[mainAxis]] += mainDim; } + if (child->style.margin[trailing[mainAxis]].unit == YGUnitAuto) { + mainDim += remainingFreeSpace / numberOfAutoMarginsOnCurrentLine; + } + if (canSkipFlex) { // If we skipped the flex step, then we can't rely on the // measuredDims because @@ -2569,7 +2648,9 @@ static void YGNodelayoutImpl(const YGNodeRef node, // time, this time // forcing the cross-axis size to be the computed cross size for the // current line. - if (alignItem == YGAlignStretch) { + if (alignItem == YGAlignStretch && + child->style.margin[leading[crossAxis]].unit != YGUnitAuto && + child->style.margin[trailing[crossAxis]].unit != YGUnitAuto) { const bool isCrossSizeDefinite = (isMainAxisRow && YGNodeIsStyleDimDefined(child, YGFlexDirectionColumn, availableInnerHeight)) || @@ -2636,17 +2717,25 @@ static void YGNodelayoutImpl(const YGNodeRef node, true, "stretch"); } - } else if (alignItem != YGAlignFlexStart) { + } else { const float remainingCrossDim = containerCrossAxis - YGNodeDimWithMargin(child, crossAxis, availableInnerWidth); - if (alignItem == YGAlignCenter) { + if (child->style.margin[leading[crossAxis]].unit == YGUnitAuto && + child->style.margin[trailing[crossAxis]].unit == YGUnitAuto) { leadingCrossDim += remainingCrossDim / 2; - } else { // YGAlignFlexEnd + } else if (child->style.margin[trailing[crossAxis]].unit == YGUnitAuto) { + // No-Op + } else if (child->style.margin[leading[crossAxis]].unit == YGUnitAuto) { + leadingCrossDim += remainingCrossDim; + } else if (alignItem == YGAlignFlexStart) { + // No-Op + } else if (alignItem == YGAlignCenter) { + leadingCrossDim += remainingCrossDim / 2; + } else { leadingCrossDim += remainingCrossDim; } } - // And we apply the position child->layout.position[pos[crossAxis]] += totalLineCrossDim + leadingCrossDim; } diff --git a/ReactCommon/yoga/yoga/Yoga.h b/ReactCommon/yoga/yoga/Yoga.h index bf9bd3e89..858a29146 100644 --- a/ReactCommon/yoga/yoga/Yoga.h +++ b/ReactCommon/yoga/yoga/Yoga.h @@ -44,6 +44,7 @@ typedef struct YGValue { } YGValue; static const YGValue YGValueUndefined = {YGUndefined, YGUnitUndefined}; +static const YGValue YGValueAuto = {0, YGUnitAuto}; typedef struct YGNode *YGNodeRef; typedef YGSize (*YGMeasureFunc)(YGNodeRef node, @@ -121,6 +122,10 @@ WIN_EXPORT void YGNodeCopyStyle(const YGNodeRef dstNode, const YGNodeRef srcNode WIN_EXPORT void YGNodeStyleSet##name##Percent(const YGNodeRef node, const float paramName); \ WIN_EXPORT type YGNodeStyleGet##name(const YGNodeRef node); +#define YG_NODE_STYLE_PROPERTY_UNIT_AUTO(type, name, paramName) \ + YG_NODE_STYLE_PROPERTY_UNIT(type, name, paramName) \ + WIN_EXPORT void YGNodeStyleSet##name##Auto(const YGNodeRef node); + #define YG_NODE_STYLE_EDGE_PROPERTY(type, name, paramName) \ WIN_EXPORT void YGNodeStyleSet##name(const YGNodeRef node, \ const YGEdge edge, \ @@ -136,6 +141,9 @@ WIN_EXPORT void YGNodeCopyStyle(const YGNodeRef dstNode, const YGNodeRef srcNode const float paramName); \ WIN_EXPORT type YGNodeStyleGet##name(const YGNodeRef node, const YGEdge edge); +#define YG_NODE_STYLE_EDGE_PROPERTY_UNIT_AUTO(type, name) \ + WIN_EXPORT void YGNodeStyleSet##name##Auto(const YGNodeRef node, const YGEdge edge); + #define YG_NODE_LAYOUT_PROPERTY(type, name) \ WIN_EXPORT type YGNodeLayoutGet##name(const YGNodeRef node); @@ -162,15 +170,16 @@ YG_NODE_STYLE_PROPERTY(YGDisplay, Display, display); WIN_EXPORT void YGNodeStyleSetFlex(const YGNodeRef node, const float flex); YG_NODE_STYLE_PROPERTY(float, FlexGrow, flexGrow); YG_NODE_STYLE_PROPERTY(float, FlexShrink, flexShrink); -YG_NODE_STYLE_PROPERTY_UNIT(YGValue, FlexBasis, flexBasis); +YG_NODE_STYLE_PROPERTY_UNIT_AUTO(YGValue, FlexBasis, flexBasis); YG_NODE_STYLE_EDGE_PROPERTY_UNIT(YGValue, Position, position); YG_NODE_STYLE_EDGE_PROPERTY_UNIT(YGValue, Margin, margin); +YG_NODE_STYLE_EDGE_PROPERTY_UNIT_AUTO(YGValue, Margin); YG_NODE_STYLE_EDGE_PROPERTY_UNIT(YGValue, Padding, padding); YG_NODE_STYLE_EDGE_PROPERTY(float, Border, border); -YG_NODE_STYLE_PROPERTY_UNIT(YGValue, Width, width); -YG_NODE_STYLE_PROPERTY_UNIT(YGValue, Height, height); +YG_NODE_STYLE_PROPERTY_UNIT_AUTO(YGValue, Width, width); +YG_NODE_STYLE_PROPERTY_UNIT_AUTO(YGValue, Height, height); YG_NODE_STYLE_PROPERTY_UNIT(YGValue, MinWidth, minWidth); YG_NODE_STYLE_PROPERTY_UNIT(YGValue, MinHeight, minHeight); YG_NODE_STYLE_PROPERTY_UNIT(YGValue, MaxWidth, maxWidth);