Compute edge values similar to how Spacing.java does it

Reviewed By: lexs

Differential Revision: D3728742

fbshipit-source-id: aa19400880afa49664f7bde72b1df45314e699bb
This commit is contained in:
Emil Sjolander 2016-08-17 10:36:40 -07:00 committed by Facebook Github Bot 7
parent fa9cf22074
commit 0da5fd21c7
2 changed files with 129 additions and 113 deletions

View File

@ -60,10 +60,10 @@ typedef struct CSSStyle {
float flexGrow; float flexGrow;
float flexShrink; float flexShrink;
float flexBasis; float flexBasis;
float margin[6]; float margin[CSSEdgeCount];
float position[6]; float position[CSSEdgeCount];
float padding[6]; float padding[CSSEdgeCount];
float border[6]; float border[CSSEdgeCount];
float dimensions[2]; float dimensions[2];
float minDimensions[2]; float minDimensions[2];
float maxDimensions[2]; float maxDimensions[2];

View File

@ -23,6 +23,34 @@ __forceinline const float fmaxf(const float a, const float b) {
#endif #endif
#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 CSSNodeNew() {
CSSNodeRef node = calloc(1, sizeof(CSSNode)); CSSNodeRef node = calloc(1, sizeof(CSSNode));
CSS_ASSERT(node, "Could not allocate memory for node"); 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[CSSDimensionWidth] = CSSUndefined;
node->style.maxDimensions[CSSDimensionHeight] = CSSUndefined; node->style.maxDimensions[CSSDimensionHeight] = CSSUndefined;
node->style.position[CSSEdgeLeft] = CSSUndefined; for (CSSEdge edge = CSSEdgeLeft; edge < CSSEdgeCount; edge++) {
node->style.position[CSSEdgeTop] = CSSUndefined; node->style.position[edge] = CSSUndefined;
node->style.position[CSSEdgeRight] = CSSUndefined; node->style.margin[edge] = CSSUndefined;
node->style.position[CSSEdgeBottom] = CSSUndefined; node->style.padding[edge] = CSSUndefined;
node->style.position[CSSEdgeStart] = CSSUndefined; node->style.border[edge] = 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;
node->layout.dimensions[CSSDimensionWidth] = CSSUndefined; node->layout.dimensions[CSSDimensionWidth] = CSSUndefined;
node->layout.dimensions[CSSDimensionHeight] = CSSUndefined; node->layout.dimensions[CSSDimensionHeight] = CSSUndefined;
@ -179,35 +200,16 @@ float CSSNodeStyleGetFlex(CSSNodeRef node) {
return node->style.instanceName; \ return node->style.instanceName; \
} }
#define CSS_NODE_STYLE_EDGE_PROPERTY_IMPL(type, name, paramName, instanceName) \ #define CSS_NODE_STYLE_EDGE_PROPERTY_IMPL(type, name, paramName, instanceName, defaultValue) \
void CSSNodeStyleSet##name(CSSNodeRef node, CSSEdge edge, type paramName) { \ void CSSNodeStyleSet##name(CSSNodeRef node, CSSEdge edge, type paramName) { \
switch (edge) { \ if (node->style.instanceName[edge] != paramName) { \
case CSSEdgeHorizontal: \ node->style.instanceName[edge] = paramName; \
CSSNodeStyleSet##name(node, CSSEdgeLeft, paramName); \ _CSSNodeMarkDirty(node); \
CSSNodeStyleSet##name(node, CSSEdgeRight, paramName); \ } \
CSSNodeStyleSet##name(node, CSSEdgeStart, paramName); \ } \
CSSNodeStyleSet##name(node, CSSEdgeEnd, paramName); \ \
break; \ type CSSNodeStyleGet##name(CSSNodeRef node, CSSEdge edge) { \
case CSSEdgeVertical: \ return computedEdgeValue(node->style.instanceName, edge, defaultValue); \
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_LAYOUT_PROPERTY_IMPL(type, name, instanceName) \ #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, FlexShrink, flexShrink, flexShrink);
CSS_NODE_STYLE_PROPERTY_IMPL(float, FlexBasis, flexBasis, flexBasis); 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, Position, position, position, CSSUndefined);
CSS_NODE_STYLE_EDGE_PROPERTY_IMPL(float, Margin, margin, margin); CSS_NODE_STYLE_EDGE_PROPERTY_IMPL(float, Margin, margin, margin, 0);
CSS_NODE_STYLE_EDGE_PROPERTY_IMPL(float, Padding, padding, padding); CSS_NODE_STYLE_EDGE_PROPERTY_IMPL(float, Padding, padding, padding, 0);
CSS_NODE_STYLE_EDGE_PROPERTY_IMPL(float, Border, border, border); 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, Width, width, dimensions[CSSDimensionWidth]);
CSS_NODE_STYLE_PROPERTY_IMPL(float, Height, height, dimensions[CSSDimensionHeight]); 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)) { 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 { } else {
print_number_0("marginLeft", node->style.margin[CSSEdgeLeft]); print_number_0("marginLeft", computedEdgeValue(node->style.margin, CSSEdgeLeft, 0));
print_number_0("marginRight", node->style.margin[CSSEdgeRight]); print_number_0("marginRight", computedEdgeValue(node->style.margin, CSSEdgeRight, 0));
print_number_0("marginTop", node->style.margin[CSSEdgeTop]); print_number_0("marginTop", computedEdgeValue(node->style.margin, CSSEdgeTop, 0));
print_number_0("marginBottom", node->style.margin[CSSEdgeBottom]); print_number_0("marginBottom", computedEdgeValue(node->style.margin, CSSEdgeBottom, 0));
print_number_0("marginStart", node->style.margin[CSSEdgeStart]); print_number_0("marginStart", computedEdgeValue(node->style.margin, CSSEdgeStart, 0));
print_number_0("marginEnd", node->style.margin[CSSEdgeEnd]); print_number_0("marginEnd", computedEdgeValue(node->style.margin, CSSEdgeEnd, 0));
} }
if (four_equal(node->style.padding)) { 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 { } else {
print_number_0("paddingLeft", node->style.padding[CSSEdgeLeft]); print_number_0("paddingLeft", computedEdgeValue(node->style.padding, CSSEdgeLeft, 0));
print_number_0("paddingRight", node->style.padding[CSSEdgeRight]); print_number_0("paddingRight", computedEdgeValue(node->style.padding, CSSEdgeRight, 0));
print_number_0("paddingTop", node->style.padding[CSSEdgeTop]); print_number_0("paddingTop", computedEdgeValue(node->style.padding, CSSEdgeTop, 0));
print_number_0("paddingBottom", node->style.padding[CSSEdgeBottom]); print_number_0("paddingBottom", computedEdgeValue(node->style.padding, CSSEdgeBottom, 0));
print_number_0("paddingStart", node->style.padding[CSSEdgeStart]); print_number_0("paddingStart", computedEdgeValue(node->style.padding, CSSEdgeStart, 0));
print_number_0("paddingEnd", node->style.padding[CSSEdgeEnd]); print_number_0("paddingEnd", computedEdgeValue(node->style.padding, CSSEdgeEnd, 0));
} }
if (four_equal(node->style.border)) { 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 { } else {
print_number_0("borderLeftWidth", node->style.border[CSSEdgeLeft]); print_number_0("borderLeftWidth", computedEdgeValue(node->style.border, CSSEdgeLeft, 0));
print_number_0("borderRightWidth", node->style.border[CSSEdgeRight]); print_number_0("borderRightWidth", computedEdgeValue(node->style.border, CSSEdgeRight, 0));
print_number_0("borderTopWidth", node->style.border[CSSEdgeTop]); print_number_0("borderTopWidth", computedEdgeValue(node->style.border, CSSEdgeTop, 0));
print_number_0("borderBottomWidth", node->style.border[CSSEdgeBottom]); print_number_0("borderBottomWidth", computedEdgeValue(node->style.border, CSSEdgeBottom, 0));
print_number_0("borderStartWidth", node->style.border[CSSEdgeStart]); print_number_0("borderStartWidth", computedEdgeValue(node->style.border, CSSEdgeStart, 0));
print_number_0("borderEndWidth", node->style.border[CSSEdgeEnd]); print_number_0("borderEndWidth", computedEdgeValue(node->style.border, CSSEdgeEnd, 0));
} }
print_number_nan("width", node->style.dimensions[CSSDimensionWidth]); 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', "); printf("position: 'absolute', ");
} }
print_number_nan("left", node->style.position[CSSEdgeLeft]); print_number_nan("left", computedEdgeValue(node->style.position, CSSEdgeLeft, CSSUndefined));
print_number_nan("right", node->style.position[CSSEdgeRight]); print_number_nan("right", computedEdgeValue(node->style.position, CSSEdgeRight, CSSUndefined));
print_number_nan("top", node->style.position[CSSEdgeTop]); print_number_nan("top", computedEdgeValue(node->style.position, CSSEdgeTop, CSSUndefined));
print_number_nan("bottom", node->style.position[CSSEdgeBottom]); print_number_nan("bottom",
computedEdgeValue(node->style.position, CSSEdgeBottom, CSSUndefined));
} }
uint32_t childCount = CSSNodeListCount(node->children); uint32_t childCount = CSSNodeListCount(node->children);
@ -473,68 +476,74 @@ static bool isColumnDirection(CSSFlexDirection flexDirection) {
} }
static float getLeadingMargin(CSSNode *node, CSSFlexDirection axis) { static float getLeadingMargin(CSSNode *node, CSSFlexDirection axis) {
if (isRowDirection(axis) && !CSSValueIsUndefined(node->style.margin[CSSEdgeStart])) { if (isRowDirection(axis) &&
return node->style.margin[CSSEdgeStart]; !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) { static float getTrailingMargin(CSSNode *node, CSSFlexDirection axis) {
if (isRowDirection(axis) && !CSSValueIsUndefined(node->style.margin[CSSEdgeEnd])) { if (isRowDirection(axis) &&
return node->style.margin[CSSEdgeEnd]; !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) { static float getLeadingPadding(CSSNode *node, CSSFlexDirection axis) {
if (isRowDirection(axis) && !CSSValueIsUndefined(node->style.padding[CSSEdgeStart]) && if (isRowDirection(axis) &&
node->style.padding[CSSEdgeStart] >= 0) { !CSSValueIsUndefined(computedEdgeValue(node->style.padding, CSSEdgeStart, 0)) &&
return node->style.padding[CSSEdgeStart]; computedEdgeValue(node->style.padding, CSSEdgeStart, 0) >= 0) {
return computedEdgeValue(node->style.padding, CSSEdgeStart, 0);
} }
if (node->style.padding[leading[axis]] >= 0) { if (computedEdgeValue(node->style.padding, leading[axis], 0) >= 0) {
return node->style.padding[leading[axis]]; return computedEdgeValue(node->style.padding, leading[axis], 0);
} }
return 0; return 0;
} }
static float getTrailingPadding(CSSNode *node, CSSFlexDirection axis) { static float getTrailingPadding(CSSNode *node, CSSFlexDirection axis) {
if (isRowDirection(axis) && !CSSValueIsUndefined(node->style.padding[CSSEdgeEnd]) && if (isRowDirection(axis) &&
node->style.padding[CSSEdgeEnd] >= 0) { !CSSValueIsUndefined(computedEdgeValue(node->style.padding, CSSEdgeEnd, 0)) &&
return node->style.padding[CSSEdgeEnd]; computedEdgeValue(node->style.padding, CSSEdgeEnd, 0) >= 0) {
return computedEdgeValue(node->style.padding, CSSEdgeEnd, 0);
} }
if (node->style.padding[trailing[axis]] >= 0) { if (computedEdgeValue(node->style.padding, trailing[axis], 0) >= 0) {
return node->style.padding[trailing[axis]]; return computedEdgeValue(node->style.padding, trailing[axis], 0);
} }
return 0; return 0;
} }
static float getLeadingBorder(CSSNode *node, CSSFlexDirection axis) { static float getLeadingBorder(CSSNode *node, CSSFlexDirection axis) {
if (isRowDirection(axis) && !CSSValueIsUndefined(node->style.border[CSSEdgeStart]) && if (isRowDirection(axis) &&
node->style.border[CSSEdgeStart] >= 0) { !CSSValueIsUndefined(computedEdgeValue(node->style.border, CSSEdgeStart, 0)) &&
return node->style.border[CSSEdgeStart]; computedEdgeValue(node->style.border, CSSEdgeStart, 0) >= 0) {
return computedEdgeValue(node->style.border, CSSEdgeStart, 0);
} }
if (node->style.border[leading[axis]] >= 0) { if (computedEdgeValue(node->style.border, leading[axis], 0) >= 0) {
return node->style.border[leading[axis]]; return computedEdgeValue(node->style.border, leading[axis], 0);
} }
return 0; return 0;
} }
static float getTrailingBorder(CSSNode *node, CSSFlexDirection axis) { static float getTrailingBorder(CSSNode *node, CSSFlexDirection axis) {
if (isRowDirection(axis) && !CSSValueIsUndefined(node->style.border[CSSEdgeEnd]) && if (isRowDirection(axis) &&
node->style.border[CSSEdgeEnd] >= 0) { !CSSValueIsUndefined(computedEdgeValue(node->style.border, CSSEdgeEnd, 0)) &&
return node->style.border[CSSEdgeEnd]; computedEdgeValue(node->style.border, CSSEdgeEnd, 0) >= 0) {
return computedEdgeValue(node->style.border, CSSEdgeEnd, 0);
} }
if (node->style.border[trailing[axis]] >= 0) { if (computedEdgeValue(node->style.border, trailing[axis], 0) >= 0) {
return node->style.border[trailing[axis]]; return computedEdgeValue(node->style.border, trailing[axis], 0);
} }
return 0; return 0;
@ -623,13 +632,18 @@ static bool isLayoutDimDefined(CSSNode *node, CSSFlexDirection axis) {
} }
static bool isLeadingPosDefined(CSSNode *node, CSSFlexDirection axis) { static bool isLeadingPosDefined(CSSNode *node, CSSFlexDirection axis) {
return (isRowDirection(axis) && !CSSValueIsUndefined(node->style.position[CSSEdgeStart])) || return (isRowDirection(axis) &&
!CSSValueIsUndefined(node->style.position[leading[axis]]); !CSSValueIsUndefined(
computedEdgeValue(node->style.position, CSSEdgeStart, CSSUndefined))) ||
!CSSValueIsUndefined(computedEdgeValue(node->style.position, leading[axis], CSSUndefined));
} }
static bool isTrailingPosDefined(CSSNode *node, CSSFlexDirection axis) { static bool isTrailingPosDefined(CSSNode *node, CSSFlexDirection axis) {
return (isRowDirection(axis) && !CSSValueIsUndefined(node->style.position[CSSEdgeEnd])) || return (isRowDirection(axis) &&
!CSSValueIsUndefined(node->style.position[trailing[axis]]); !CSSValueIsUndefined(
computedEdgeValue(node->style.position, CSSEdgeEnd, CSSUndefined))) ||
!CSSValueIsUndefined(
computedEdgeValue(node->style.position, trailing[axis], CSSUndefined));
} }
static bool isMeasureDefined(CSSNode *node) { static bool isMeasureDefined(CSSNode *node) {
@ -637,21 +651,23 @@ static bool isMeasureDefined(CSSNode *node) {
} }
static float getLeadingPosition(CSSNode *node, CSSFlexDirection axis) { static float getLeadingPosition(CSSNode *node, CSSFlexDirection axis) {
if (isRowDirection(axis) && !CSSValueIsUndefined(node->style.position[CSSEdgeStart])) { if (isRowDirection(axis) &&
return node->style.position[CSSEdgeStart]; !CSSValueIsUndefined(computedEdgeValue(node->style.position, CSSEdgeStart, CSSUndefined))) {
return computedEdgeValue(node->style.position, CSSEdgeStart, CSSUndefined);
} }
if (!CSSValueIsUndefined(node->style.position[leading[axis]])) { if (!CSSValueIsUndefined(computedEdgeValue(node->style.position, leading[axis], CSSUndefined))) {
return node->style.position[leading[axis]]; return computedEdgeValue(node->style.position, leading[axis], CSSUndefined);
} }
return 0; return 0;
} }
static float getTrailingPosition(CSSNode *node, CSSFlexDirection axis) { static float getTrailingPosition(CSSNode *node, CSSFlexDirection axis) {
if (isRowDirection(axis) && !CSSValueIsUndefined(node->style.position[CSSEdgeEnd])) { if (isRowDirection(axis) &&
return node->style.position[CSSEdgeEnd]; !CSSValueIsUndefined(computedEdgeValue(node->style.position, CSSEdgeEnd, CSSUndefined))) {
return computedEdgeValue(node->style.position, CSSEdgeEnd, CSSUndefined);
} }
if (!CSSValueIsUndefined(node->style.position[trailing[axis]])) { if (!CSSValueIsUndefined(computedEdgeValue(node->style.position, trailing[axis], CSSUndefined))) {
return node->style.position[trailing[axis]]; return computedEdgeValue(node->style.position, trailing[axis], CSSUndefined);
} }
return 0; return 0;
} }