diff --git a/ReactAndroid/src/main/java/com/facebook/yoga/YogaNode.java b/ReactAndroid/src/main/java/com/facebook/yoga/YogaNode.java index 432c204017..cc325c923b 100644 --- a/ReactAndroid/src/main/java/com/facebook/yoga/YogaNode.java +++ b/ReactAndroid/src/main/java/com/facebook/yoga/YogaNode.java @@ -70,6 +70,14 @@ public class YogaNode implements YogaNodeAPI { @DoNotStrip private float mLeft = YogaConstants.UNDEFINED; @DoNotStrip + private float mMarginLeft = 0; + @DoNotStrip + private float mMarginTop = 0; + @DoNotStrip + private float mMarginRight = 0; + @DoNotStrip + private float mMarginBottom = 0; + @DoNotStrip private float mPaddingLeft = 0; @DoNotStrip private float mPaddingTop = 0; @@ -573,6 +581,26 @@ public class YogaNode implements YogaNodeAPI { return mHeight; } + @Override + public float getLayoutMargin(YogaEdge edge) { + switch (edge) { + case LEFT: + return mMarginLeft; + case TOP: + return mMarginTop; + case RIGHT: + return mMarginRight; + case BOTTOM: + return mMarginBottom; + case START: + return getLayoutDirection() == YogaDirection.RTL ? mMarginRight : mMarginLeft; + case END: + return getLayoutDirection() == YogaDirection.RTL ? mMarginLeft : mMarginRight; + default: + throw new IllegalArgumentException("Cannot get layout margins of multi-edge shorthands"); + } + } + @Override public float getLayoutPadding(YogaEdge edge) { switch (edge) { diff --git a/ReactAndroid/src/main/java/com/facebook/yoga/YogaNodeAPI.java b/ReactAndroid/src/main/java/com/facebook/yoga/YogaNodeAPI.java index 6d782c4525..b4a43b70d6 100644 --- a/ReactAndroid/src/main/java/com/facebook/yoga/YogaNodeAPI.java +++ b/ReactAndroid/src/main/java/com/facebook/yoga/YogaNodeAPI.java @@ -82,6 +82,7 @@ public interface YogaNodeAPI { float getLayoutY(); float getLayoutWidth(); float getLayoutHeight(); + float getLayoutMargin(YogaEdge edge); float getLayoutPadding(YogaEdge edge); YogaDirection getLayoutDirection(); YogaOverflow getOverflow(); 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 54610dbada..05d1c20e06 100644 --- a/ReactAndroid/src/main/jni/first-party/yogajni/jni/YGJNI.cpp +++ b/ReactAndroid/src/main/jni/first-party/yogajni/jni/YGJNI.cpp @@ -30,6 +30,11 @@ static void YGTransferLayoutOutputsRecursive(YGNodeRef root) { static auto leftField = obj->getClass()->getField("mLeft"); static auto topField = obj->getClass()->getField("mTop"); + static auto marginLeftField = obj->getClass()->getField("mMarginLeft"); + static auto marginTopField = obj->getClass()->getField("mMarginTop"); + static auto marginRightField = obj->getClass()->getField("mMarginRight"); + static auto marginBottomField = obj->getClass()->getField("mMarginBottom"); + static auto paddingLeftField = obj->getClass()->getField("mPaddingLeft"); static auto paddingTopField = obj->getClass()->getField("mPaddingTop"); static auto paddingRightField = obj->getClass()->getField("mPaddingRight"); @@ -40,6 +45,11 @@ static void YGTransferLayoutOutputsRecursive(YGNodeRef root) { obj->setFieldValue(leftField, YGNodeLayoutGetLeft(root)); obj->setFieldValue(topField, YGNodeLayoutGetTop(root)); + obj->setFieldValue(marginLeftField, YGNodeLayoutGetMargin(root, YGEdgeLeft)); + obj->setFieldValue(marginTopField, YGNodeLayoutGetMargin(root, YGEdgeTop)); + obj->setFieldValue(marginRightField, YGNodeLayoutGetMargin(root, YGEdgeRight)); + obj->setFieldValue(marginBottomField, YGNodeLayoutGetMargin(root, YGEdgeBottom)); + obj->setFieldValue(paddingLeftField, YGNodeLayoutGetPadding(root, YGEdgeLeft)); obj->setFieldValue(paddingTopField, YGNodeLayoutGetPadding(root, YGEdgeTop)); obj->setFieldValue(paddingRightField, YGNodeLayoutGetPadding(root, YGEdgeRight)); diff --git a/ReactCommon/yoga/yoga/Yoga.c b/ReactCommon/yoga/yoga/Yoga.c index 598f273cf6..18df466b6f 100644 --- a/ReactCommon/yoga/yoga/Yoga.c +++ b/ReactCommon/yoga/yoga/Yoga.c @@ -47,6 +47,7 @@ typedef struct YGCachedMeasurement { typedef struct YGLayout { float position[4]; float dimensions[2]; + float margin[6]; float padding[6]; YGDirection direction; @@ -530,6 +531,29 @@ void YGNodeStyleSetFlex(const YGNodeRef node, const float flex) { return node->layout.instanceName; \ } +#define YG_NODE_LAYOUT_RESOLVED_PROPERTY_IMPL(type, name, instanceName) \ + type YGNodeLayoutGet##name(const YGNodeRef node, const YGEdge edge) { \ + YG_ASSERT(edge <= YGEdgeEnd, "Cannot get layout properties of multi-edge shorthands"); \ + \ + if (edge == YGEdgeLeft) { \ + if (node->layout.direction == YGDirectionRTL) { \ + return node->layout.instanceName[YGEdgeEnd]; \ + } else { \ + return node->layout.instanceName[YGEdgeStart]; \ + } \ + } \ + \ + if (edge == YGEdgeRight) { \ + if (node->layout.direction == YGDirectionRTL) { \ + return node->layout.instanceName[YGEdgeStart]; \ + } else { \ + return node->layout.instanceName[YGEdgeEnd]; \ + } \ + } \ + \ + return node->layout.instanceName[edge]; \ + } + YG_NODE_PROPERTY_IMPL(void *, Context, context, context); YG_NODE_PROPERTY_IMPL(YGPrintFunc, PrintFunc, printFunc, print); YG_NODE_PROPERTY_IMPL(bool, HasNewLayout, hasNewLayout, hasNewLayout); @@ -571,27 +595,8 @@ YG_NODE_LAYOUT_PROPERTY_IMPL(float, Width, dimensions[YGDimensionWidth]); YG_NODE_LAYOUT_PROPERTY_IMPL(float, Height, dimensions[YGDimensionHeight]); YG_NODE_LAYOUT_PROPERTY_IMPL(YGDirection, Direction, direction); -float YGNodeLayoutGetPadding(const YGNodeRef node, const YGEdge edge) { - YG_ASSERT(edge <= YGEdgeEnd, "Cannot get layout paddings of multi-edge shorthands"); - - if (edge == YGEdgeLeft) { - if (node->layout.direction == YGDirectionRTL) { - return node->layout.padding[YGEdgeEnd]; - } else { - return node->layout.padding[YGEdgeStart]; - } - } - - if (edge == YGEdgeRight) { - if (node->layout.direction == YGDirectionRTL) { - return node->layout.padding[YGEdgeStart]; - } else { - return node->layout.padding[YGEdgeEnd]; - } - } - - return node->layout.padding[edge]; -} +YG_NODE_LAYOUT_RESOLVED_PROPERTY_IMPL(float, Margin, margin); +YG_NODE_LAYOUT_RESOLVED_PROPERTY_IMPL(float, Padding, padding); uint32_t gCurrentGenerationCount = 0; @@ -1742,6 +1747,23 @@ static void YGNodelayoutImpl(const YGNodeRef node, const YGDirection direction = YGNodeResolveDirection(node, parentDirection); node->layout.direction = direction; + node->layout.margin[YGEdgeStart] = + YGNodeLeadingMargin(node, + YGFlexDirectionResolve(YGFlexDirectionRow, direction), + parentWidth); + node->layout.margin[YGEdgeEnd] = + YGNodeTrailingMargin(node, + YGFlexDirectionResolve(YGFlexDirectionRow, direction), + parentWidth); + node->layout.margin[YGEdgeTop] = + YGNodeLeadingMargin(node, + YGFlexDirectionResolve(YGFlexDirectionColumn, direction), + parentWidth); + node->layout.margin[YGEdgeBottom] = + YGNodeTrailingMargin(node, + YGFlexDirectionResolve(YGFlexDirectionColumn, direction), + parentWidth); + node->layout.padding[YGEdgeStart] = YGNodeLeadingPadding(node, YGFlexDirectionResolve(YGFlexDirectionRow, direction), diff --git a/ReactCommon/yoga/yoga/Yoga.h b/ReactCommon/yoga/yoga/Yoga.h index cb21910dc4..141c9ddcdb 100644 --- a/ReactCommon/yoga/yoga/Yoga.h +++ b/ReactCommon/yoga/yoga/Yoga.h @@ -199,6 +199,7 @@ YG_NODE_LAYOUT_PROPERTY(YGDirection, Direction); // pixel values then the returned value will be the same as YGNodeStyleGetPadding. However if // padding was set using a percentage value then the returned value is the computed value used // during layout. +WIN_EXPORT float YGNodeLayoutGetMargin(const YGNodeRef node, const YGEdge edge); WIN_EXPORT float YGNodeLayoutGetPadding(const YGNodeRef node, const YGEdge edge); WIN_EXPORT void YGSetLogger(YGLogger logger);