From 0da5fd21c7c136b0067587445181a755235c6a60 Mon Sep 17 00:00:00 2001 From: Emil Sjolander Date: Wed, 17 Aug 2016 10:36:40 -0700 Subject: [PATCH] Compute edge values similar to how Spacing.java does it Reviewed By: lexs Differential Revision: D3728742 fbshipit-source-id: aa19400880afa49664f7bde72b1df45314e699bb --- React/CSSLayout/CSSLayout-internal.h | 8 +- React/CSSLayout/CSSLayout.c | 234 ++++++++++++++------------- 2 files changed, 129 insertions(+), 113 deletions(-) diff --git a/React/CSSLayout/CSSLayout-internal.h b/React/CSSLayout/CSSLayout-internal.h index e5cf8966b..da46bfdc1 100644 --- a/React/CSSLayout/CSSLayout-internal.h +++ b/React/CSSLayout/CSSLayout-internal.h @@ -60,10 +60,10 @@ typedef struct CSSStyle { float flexGrow; float flexShrink; float flexBasis; - float margin[6]; - float position[6]; - float padding[6]; - float border[6]; + float margin[CSSEdgeCount]; + float position[CSSEdgeCount]; + float padding[CSSEdgeCount]; + float border[CSSEdgeCount]; float dimensions[2]; float minDimensions[2]; float maxDimensions[2]; diff --git a/React/CSSLayout/CSSLayout.c b/React/CSSLayout/CSSLayout.c index e2dd8fe1c..0613398e7 100644 --- a/React/CSSLayout/CSSLayout.c +++ b/React/CSSLayout/CSSLayout.c @@ -23,6 +23,34 @@ __forceinline const float fmaxf(const float a, const float b) { #endif #endif +static float computedEdgeValue(float edges[CSSEdgeCount], CSSEdge edge, float defaultValue) { + CSS_ASSERT(edge <= CSSEdgeEnd, "Cannot get computed value of multi-edge shorthands"); + + if (!CSSValueIsUndefined(edges[edge])) { + return edges[edge]; + } + + if ((edge == CSSEdgeTop || edge == CSSEdgeBottom) && + !CSSValueIsUndefined(edges[CSSEdgeVertical])) { + return edges[CSSEdgeVertical]; + } + + if ((edge == CSSEdgeLeft || edge == CSSEdgeRight || edge == CSSEdgeStart || edge == CSSEdgeEnd) && + !CSSValueIsUndefined(edges[CSSEdgeHorizontal])) { + return edges[CSSEdgeHorizontal]; + } + + if (!CSSValueIsUndefined(edges[CSSEdgeAll])) { + return edges[CSSEdgeAll]; + } + + if (edge == CSSEdgeStart || edge == CSSEdgeEnd) { + return CSSUndefined; + } + + return defaultValue; +} + CSSNodeRef CSSNodeNew() { CSSNodeRef node = calloc(1, sizeof(CSSNode)); CSS_ASSERT(node, "Could not allocate memory for node"); @@ -64,19 +92,12 @@ void CSSNodeInit(CSSNodeRef node) { node->style.maxDimensions[CSSDimensionWidth] = CSSUndefined; node->style.maxDimensions[CSSDimensionHeight] = CSSUndefined; - node->style.position[CSSEdgeLeft] = CSSUndefined; - node->style.position[CSSEdgeTop] = CSSUndefined; - node->style.position[CSSEdgeRight] = CSSUndefined; - node->style.position[CSSEdgeBottom] = CSSUndefined; - node->style.position[CSSEdgeStart] = CSSUndefined; - node->style.position[CSSEdgeEnd] = CSSUndefined; - - node->style.margin[CSSEdgeStart] = CSSUndefined; - node->style.margin[CSSEdgeEnd] = CSSUndefined; - node->style.padding[CSSEdgeStart] = CSSUndefined; - node->style.padding[CSSEdgeEnd] = CSSUndefined; - node->style.border[CSSEdgeStart] = CSSUndefined; - node->style.border[CSSEdgeEnd] = CSSUndefined; + for (CSSEdge edge = CSSEdgeLeft; edge < CSSEdgeCount; edge++) { + node->style.position[edge] = CSSUndefined; + node->style.margin[edge] = CSSUndefined; + node->style.padding[edge] = CSSUndefined; + node->style.border[edge] = CSSUndefined; + } node->layout.dimensions[CSSDimensionWidth] = CSSUndefined; node->layout.dimensions[CSSDimensionHeight] = CSSUndefined; @@ -179,35 +200,16 @@ float CSSNodeStyleGetFlex(CSSNodeRef node) { return node->style.instanceName; \ } -#define CSS_NODE_STYLE_EDGE_PROPERTY_IMPL(type, name, paramName, instanceName) \ - void CSSNodeStyleSet##name(CSSNodeRef node, CSSEdge edge, type paramName) { \ - switch (edge) { \ - case CSSEdgeHorizontal: \ - CSSNodeStyleSet##name(node, CSSEdgeLeft, paramName); \ - CSSNodeStyleSet##name(node, CSSEdgeRight, paramName); \ - CSSNodeStyleSet##name(node, CSSEdgeStart, paramName); \ - CSSNodeStyleSet##name(node, CSSEdgeEnd, paramName); \ - break; \ - case CSSEdgeVertical: \ - CSSNodeStyleSet##name(node, CSSEdgeTop, paramName); \ - CSSNodeStyleSet##name(node, CSSEdgeBottom, paramName); \ - break; \ - case CSSEdgeAll: \ - CSSNodeStyleSet##name(node, CSSEdgeHorizontal, paramName); \ - CSSNodeStyleSet##name(node, CSSEdgeVertical, paramName); \ - break; \ - default: \ - if (node->style.instanceName[edge] != paramName) { \ - node->style.instanceName[edge] = paramName; \ - _CSSNodeMarkDirty(node); \ - } \ - break; \ - } \ - } \ - \ - type CSSNodeStyleGet##name(CSSNodeRef node, CSSEdge edge) { \ - CSS_ASSERT(edge <= CSSEdgeEnd, "Cannot get value of compound edge"); \ - return node->style.instanceName[edge]; \ +#define CSS_NODE_STYLE_EDGE_PROPERTY_IMPL(type, name, paramName, instanceName, defaultValue) \ + void CSSNodeStyleSet##name(CSSNodeRef node, CSSEdge edge, type paramName) { \ + if (node->style.instanceName[edge] != paramName) { \ + node->style.instanceName[edge] = paramName; \ + _CSSNodeMarkDirty(node); \ + } \ + } \ + \ + type CSSNodeStyleGet##name(CSSNodeRef node, CSSEdge edge) { \ + return computedEdgeValue(node->style.instanceName, edge, defaultValue); \ } #define CSS_NODE_LAYOUT_PROPERTY_IMPL(type, name, instanceName) \ @@ -234,10 +236,10 @@ CSS_NODE_STYLE_PROPERTY_IMPL(float, FlexGrow, flexGrow, flexGrow); CSS_NODE_STYLE_PROPERTY_IMPL(float, FlexShrink, flexShrink, flexShrink); CSS_NODE_STYLE_PROPERTY_IMPL(float, FlexBasis, flexBasis, flexBasis); -CSS_NODE_STYLE_EDGE_PROPERTY_IMPL(float, Position, position, position); -CSS_NODE_STYLE_EDGE_PROPERTY_IMPL(float, Margin, margin, margin); -CSS_NODE_STYLE_EDGE_PROPERTY_IMPL(float, Padding, padding, padding); -CSS_NODE_STYLE_EDGE_PROPERTY_IMPL(float, Border, border, border); +CSS_NODE_STYLE_EDGE_PROPERTY_IMPL(float, Position, position, position, CSSUndefined); +CSS_NODE_STYLE_EDGE_PROPERTY_IMPL(float, Margin, margin, margin, 0); +CSS_NODE_STYLE_EDGE_PROPERTY_IMPL(float, Padding, padding, padding, 0); +CSS_NODE_STYLE_EDGE_PROPERTY_IMPL(float, Border, border, border, 0); CSS_NODE_STYLE_PROPERTY_IMPL(float, Width, width, dimensions[CSSDimensionWidth]); CSS_NODE_STYLE_PROPERTY_IMPL(float, Height, height, dimensions[CSSDimensionHeight]); @@ -373,36 +375,36 @@ static void print_css_node_rec(CSSNode *node, CSSPrintOptions options, uint32_t } if (four_equal(node->style.margin)) { - print_number_0("margin", node->style.margin[CSSEdgeLeft]); + print_number_0("margin", computedEdgeValue(node->style.margin, CSSEdgeLeft, 0)); } else { - print_number_0("marginLeft", node->style.margin[CSSEdgeLeft]); - print_number_0("marginRight", node->style.margin[CSSEdgeRight]); - print_number_0("marginTop", node->style.margin[CSSEdgeTop]); - print_number_0("marginBottom", node->style.margin[CSSEdgeBottom]); - print_number_0("marginStart", node->style.margin[CSSEdgeStart]); - print_number_0("marginEnd", node->style.margin[CSSEdgeEnd]); + print_number_0("marginLeft", computedEdgeValue(node->style.margin, CSSEdgeLeft, 0)); + print_number_0("marginRight", computedEdgeValue(node->style.margin, CSSEdgeRight, 0)); + print_number_0("marginTop", computedEdgeValue(node->style.margin, CSSEdgeTop, 0)); + print_number_0("marginBottom", computedEdgeValue(node->style.margin, CSSEdgeBottom, 0)); + print_number_0("marginStart", computedEdgeValue(node->style.margin, CSSEdgeStart, 0)); + print_number_0("marginEnd", computedEdgeValue(node->style.margin, CSSEdgeEnd, 0)); } if (four_equal(node->style.padding)) { - print_number_0("padding", node->style.padding[CSSEdgeLeft]); + print_number_0("padding", computedEdgeValue(node->style.padding, CSSEdgeLeft, 0)); } else { - print_number_0("paddingLeft", node->style.padding[CSSEdgeLeft]); - print_number_0("paddingRight", node->style.padding[CSSEdgeRight]); - print_number_0("paddingTop", node->style.padding[CSSEdgeTop]); - print_number_0("paddingBottom", node->style.padding[CSSEdgeBottom]); - print_number_0("paddingStart", node->style.padding[CSSEdgeStart]); - print_number_0("paddingEnd", node->style.padding[CSSEdgeEnd]); + print_number_0("paddingLeft", computedEdgeValue(node->style.padding, CSSEdgeLeft, 0)); + print_number_0("paddingRight", computedEdgeValue(node->style.padding, CSSEdgeRight, 0)); + print_number_0("paddingTop", computedEdgeValue(node->style.padding, CSSEdgeTop, 0)); + print_number_0("paddingBottom", computedEdgeValue(node->style.padding, CSSEdgeBottom, 0)); + print_number_0("paddingStart", computedEdgeValue(node->style.padding, CSSEdgeStart, 0)); + print_number_0("paddingEnd", computedEdgeValue(node->style.padding, CSSEdgeEnd, 0)); } if (four_equal(node->style.border)) { - print_number_0("borderWidth", node->style.border[CSSEdgeLeft]); + print_number_0("borderWidth", computedEdgeValue(node->style.border, CSSEdgeLeft, 0)); } else { - print_number_0("borderLeftWidth", node->style.border[CSSEdgeLeft]); - print_number_0("borderRightWidth", node->style.border[CSSEdgeRight]); - print_number_0("borderTopWidth", node->style.border[CSSEdgeTop]); - print_number_0("borderBottomWidth", node->style.border[CSSEdgeBottom]); - print_number_0("borderStartWidth", node->style.border[CSSEdgeStart]); - print_number_0("borderEndWidth", node->style.border[CSSEdgeEnd]); + print_number_0("borderLeftWidth", computedEdgeValue(node->style.border, CSSEdgeLeft, 0)); + print_number_0("borderRightWidth", computedEdgeValue(node->style.border, CSSEdgeRight, 0)); + print_number_0("borderTopWidth", computedEdgeValue(node->style.border, CSSEdgeTop, 0)); + print_number_0("borderBottomWidth", computedEdgeValue(node->style.border, CSSEdgeBottom, 0)); + print_number_0("borderStartWidth", computedEdgeValue(node->style.border, CSSEdgeStart, 0)); + print_number_0("borderEndWidth", computedEdgeValue(node->style.border, CSSEdgeEnd, 0)); } print_number_nan("width", node->style.dimensions[CSSDimensionWidth]); @@ -416,10 +418,11 @@ static void print_css_node_rec(CSSNode *node, CSSPrintOptions options, uint32_t printf("position: 'absolute', "); } - print_number_nan("left", node->style.position[CSSEdgeLeft]); - print_number_nan("right", node->style.position[CSSEdgeRight]); - print_number_nan("top", node->style.position[CSSEdgeTop]); - print_number_nan("bottom", node->style.position[CSSEdgeBottom]); + print_number_nan("left", computedEdgeValue(node->style.position, CSSEdgeLeft, CSSUndefined)); + print_number_nan("right", computedEdgeValue(node->style.position, CSSEdgeRight, CSSUndefined)); + print_number_nan("top", computedEdgeValue(node->style.position, CSSEdgeTop, CSSUndefined)); + print_number_nan("bottom", + computedEdgeValue(node->style.position, CSSEdgeBottom, CSSUndefined)); } uint32_t childCount = CSSNodeListCount(node->children); @@ -473,68 +476,74 @@ static bool isColumnDirection(CSSFlexDirection flexDirection) { } static float getLeadingMargin(CSSNode *node, CSSFlexDirection axis) { - if (isRowDirection(axis) && !CSSValueIsUndefined(node->style.margin[CSSEdgeStart])) { - return node->style.margin[CSSEdgeStart]; + if (isRowDirection(axis) && + !CSSValueIsUndefined(computedEdgeValue(node->style.margin, CSSEdgeStart, 0))) { + return computedEdgeValue(node->style.margin, CSSEdgeStart, 0); } - return node->style.margin[leading[axis]]; + return computedEdgeValue(node->style.margin, leading[axis], 0); } static float getTrailingMargin(CSSNode *node, CSSFlexDirection axis) { - if (isRowDirection(axis) && !CSSValueIsUndefined(node->style.margin[CSSEdgeEnd])) { - return node->style.margin[CSSEdgeEnd]; + if (isRowDirection(axis) && + !CSSValueIsUndefined(computedEdgeValue(node->style.margin, CSSEdgeEnd, 0))) { + return computedEdgeValue(node->style.margin, CSSEdgeEnd, 0); } - return node->style.margin[trailing[axis]]; + return computedEdgeValue(node->style.margin, trailing[axis], 0); } static float getLeadingPadding(CSSNode *node, CSSFlexDirection axis) { - if (isRowDirection(axis) && !CSSValueIsUndefined(node->style.padding[CSSEdgeStart]) && - node->style.padding[CSSEdgeStart] >= 0) { - return node->style.padding[CSSEdgeStart]; + if (isRowDirection(axis) && + !CSSValueIsUndefined(computedEdgeValue(node->style.padding, CSSEdgeStart, 0)) && + computedEdgeValue(node->style.padding, CSSEdgeStart, 0) >= 0) { + return computedEdgeValue(node->style.padding, CSSEdgeStart, 0); } - if (node->style.padding[leading[axis]] >= 0) { - return node->style.padding[leading[axis]]; + if (computedEdgeValue(node->style.padding, leading[axis], 0) >= 0) { + return computedEdgeValue(node->style.padding, leading[axis], 0); } return 0; } static float getTrailingPadding(CSSNode *node, CSSFlexDirection axis) { - if (isRowDirection(axis) && !CSSValueIsUndefined(node->style.padding[CSSEdgeEnd]) && - node->style.padding[CSSEdgeEnd] >= 0) { - return node->style.padding[CSSEdgeEnd]; + if (isRowDirection(axis) && + !CSSValueIsUndefined(computedEdgeValue(node->style.padding, CSSEdgeEnd, 0)) && + computedEdgeValue(node->style.padding, CSSEdgeEnd, 0) >= 0) { + return computedEdgeValue(node->style.padding, CSSEdgeEnd, 0); } - if (node->style.padding[trailing[axis]] >= 0) { - return node->style.padding[trailing[axis]]; + if (computedEdgeValue(node->style.padding, trailing[axis], 0) >= 0) { + return computedEdgeValue(node->style.padding, trailing[axis], 0); } return 0; } static float getLeadingBorder(CSSNode *node, CSSFlexDirection axis) { - if (isRowDirection(axis) && !CSSValueIsUndefined(node->style.border[CSSEdgeStart]) && - node->style.border[CSSEdgeStart] >= 0) { - return node->style.border[CSSEdgeStart]; + if (isRowDirection(axis) && + !CSSValueIsUndefined(computedEdgeValue(node->style.border, CSSEdgeStart, 0)) && + computedEdgeValue(node->style.border, CSSEdgeStart, 0) >= 0) { + return computedEdgeValue(node->style.border, CSSEdgeStart, 0); } - if (node->style.border[leading[axis]] >= 0) { - return node->style.border[leading[axis]]; + if (computedEdgeValue(node->style.border, leading[axis], 0) >= 0) { + return computedEdgeValue(node->style.border, leading[axis], 0); } return 0; } static float getTrailingBorder(CSSNode *node, CSSFlexDirection axis) { - if (isRowDirection(axis) && !CSSValueIsUndefined(node->style.border[CSSEdgeEnd]) && - node->style.border[CSSEdgeEnd] >= 0) { - return node->style.border[CSSEdgeEnd]; + if (isRowDirection(axis) && + !CSSValueIsUndefined(computedEdgeValue(node->style.border, CSSEdgeEnd, 0)) && + computedEdgeValue(node->style.border, CSSEdgeEnd, 0) >= 0) { + return computedEdgeValue(node->style.border, CSSEdgeEnd, 0); } - if (node->style.border[trailing[axis]] >= 0) { - return node->style.border[trailing[axis]]; + if (computedEdgeValue(node->style.border, trailing[axis], 0) >= 0) { + return computedEdgeValue(node->style.border, trailing[axis], 0); } return 0; @@ -623,13 +632,18 @@ static bool isLayoutDimDefined(CSSNode *node, CSSFlexDirection axis) { } static bool isLeadingPosDefined(CSSNode *node, CSSFlexDirection axis) { - return (isRowDirection(axis) && !CSSValueIsUndefined(node->style.position[CSSEdgeStart])) || - !CSSValueIsUndefined(node->style.position[leading[axis]]); + return (isRowDirection(axis) && + !CSSValueIsUndefined( + computedEdgeValue(node->style.position, CSSEdgeStart, CSSUndefined))) || + !CSSValueIsUndefined(computedEdgeValue(node->style.position, leading[axis], CSSUndefined)); } static bool isTrailingPosDefined(CSSNode *node, CSSFlexDirection axis) { - return (isRowDirection(axis) && !CSSValueIsUndefined(node->style.position[CSSEdgeEnd])) || - !CSSValueIsUndefined(node->style.position[trailing[axis]]); + return (isRowDirection(axis) && + !CSSValueIsUndefined( + computedEdgeValue(node->style.position, CSSEdgeEnd, CSSUndefined))) || + !CSSValueIsUndefined( + computedEdgeValue(node->style.position, trailing[axis], CSSUndefined)); } static bool isMeasureDefined(CSSNode *node) { @@ -637,21 +651,23 @@ static bool isMeasureDefined(CSSNode *node) { } static float getLeadingPosition(CSSNode *node, CSSFlexDirection axis) { - if (isRowDirection(axis) && !CSSValueIsUndefined(node->style.position[CSSEdgeStart])) { - return node->style.position[CSSEdgeStart]; + if (isRowDirection(axis) && + !CSSValueIsUndefined(computedEdgeValue(node->style.position, CSSEdgeStart, CSSUndefined))) { + return computedEdgeValue(node->style.position, CSSEdgeStart, CSSUndefined); } - if (!CSSValueIsUndefined(node->style.position[leading[axis]])) { - return node->style.position[leading[axis]]; + if (!CSSValueIsUndefined(computedEdgeValue(node->style.position, leading[axis], CSSUndefined))) { + return computedEdgeValue(node->style.position, leading[axis], CSSUndefined); } return 0; } static float getTrailingPosition(CSSNode *node, CSSFlexDirection axis) { - if (isRowDirection(axis) && !CSSValueIsUndefined(node->style.position[CSSEdgeEnd])) { - return node->style.position[CSSEdgeEnd]; + if (isRowDirection(axis) && + !CSSValueIsUndefined(computedEdgeValue(node->style.position, CSSEdgeEnd, CSSUndefined))) { + return computedEdgeValue(node->style.position, CSSEdgeEnd, CSSUndefined); } - if (!CSSValueIsUndefined(node->style.position[trailing[axis]])) { - return node->style.position[trailing[axis]]; + if (!CSSValueIsUndefined(computedEdgeValue(node->style.position, trailing[axis], CSSUndefined))) { + return computedEdgeValue(node->style.position, trailing[axis], CSSUndefined); } return 0; }