Add aspectRatio style property

Summary: Implement aspect ratio as part of Yoga. Aspect ratio allows users of the library to specify the size of the undefined dimension in terms of an aspect ratio. See test cases for examples.

Reviewed By: gkassabli

Differential Revision: D4211458

fbshipit-source-id: f8d0d318369c7b529ee29e61a52b17d0cf3b396d
This commit is contained in:
Emil Sjolander
2016-11-21 10:12:26 -08:00
committed by Facebook Github Bot
parent b16c22a8f3
commit 55fc795686
9 changed files with 507 additions and 0 deletions

View File

@@ -85,6 +85,9 @@ typedef struct CSSStyle {
float dimensions[2];
float minDimensions[2];
float maxDimensions[2];
// Yoga specific properties, not compatible with flexbox specification
float aspectRatio;
} CSSStyle;
typedef struct CSSNode {
@@ -269,6 +272,8 @@ void CSSNodeInit(const CSSNodeRef node) {
node->style.border[edge] = CSSUndefined;
}
node->style.aspectRatio = CSSUndefined;
node->layout.dimensions[CSSDimensionWidth] = CSSUndefined;
node->layout.dimensions[CSSDimensionHeight] = CSSUndefined;
@@ -459,6 +464,9 @@ CSS_NODE_STYLE_PROPERTY_IMPL(float, MinHeight, minHeight, minDimensions[CSSDimen
CSS_NODE_STYLE_PROPERTY_IMPL(float, MaxWidth, maxWidth, maxDimensions[CSSDimensionWidth]);
CSS_NODE_STYLE_PROPERTY_IMPL(float, MaxHeight, maxHeight, maxDimensions[CSSDimensionHeight]);
// Yoga specific properties, not compatible with flexbox specification
CSS_NODE_STYLE_PROPERTY_IMPL(float, AspectRatio, aspectRatio, aspectRatio);
CSS_NODE_LAYOUT_PROPERTY_IMPL(float, Left, position[CSSEdgeLeft]);
CSS_NODE_LAYOUT_PROPERTY_IMPL(float, Top, position[CSSEdgeTop]);
CSS_NODE_LAYOUT_PROPERTY_IMPL(float, Right, position[CSSEdgeRight]);
@@ -1032,6 +1040,20 @@ static void computeChildFlexBasis(const CSSNodeRef node,
childHeightMeasureMode = CSSMeasureModeExactly;
}
if (!CSSValueIsUndefined(child->style.aspectRatio)) {
if (!isMainAxisRow && childWidthMeasureMode == CSSMeasureModeExactly) {
child->layout.computedFlexBasis =
fmaxf(childWidth * child->style.aspectRatio,
getPaddingAndBorderAxis(child, CSSFlexDirectionColumn));
return;
} else if (isMainAxisRow && childHeightMeasureMode == CSSMeasureModeExactly) {
child->layout.computedFlexBasis =
fmaxf(childHeight * child->style.aspectRatio,
getPaddingAndBorderAxis(child, CSSFlexDirectionRow));
return;
}
}
constrainMaxSizeForMode(child->style.maxDimensions[CSSDimensionWidth],
&childWidthMeasureMode,
&childWidth);
@@ -1108,6 +1130,20 @@ static void absoluteLayoutChild(const CSSNodeRef node,
}
}
// Exactly one dimension needs to be defined for us to be able to do aspect ratio
// calculation. One dimension being the anchor and the other being flexible.
if (CSSValueIsUndefined(childWidth) ^ CSSValueIsUndefined(childHeight)) {
if (!CSSValueIsUndefined(child->style.aspectRatio)) {
if (CSSValueIsUndefined(childWidth)) {
childWidth = fmaxf(childHeight * child->style.aspectRatio,
getPaddingAndBorderAxis(child, CSSFlexDirectionColumn));
} else if (CSSValueIsUndefined(childHeight)) {
childHeight = fmaxf(childWidth * child->style.aspectRatio,
getPaddingAndBorderAxis(child, CSSFlexDirectionRow));
}
}
}
// If we're still missing one or the other dimension, measure the content.
if (CSSValueIsUndefined(childWidth) || CSSValueIsUndefined(childHeight)) {
childWidthMeasureMode =
@@ -1774,6 +1810,19 @@ static void layoutNodeImpl(const CSSNodeRef node,
}
}
if (!CSSValueIsUndefined(currentRelativeChild->style.aspectRatio)) {
if (isMainAxisRow && childHeightMeasureMode != CSSMeasureModeExactly) {
childHeight =
fmaxf(childWidth * currentRelativeChild->style.aspectRatio,
getPaddingAndBorderAxis(currentRelativeChild, CSSFlexDirectionColumn));
childHeightMeasureMode = CSSMeasureModeExactly;
} else if (!isMainAxisRow && childWidthMeasureMode != CSSMeasureModeExactly) {
childWidth = fmaxf(childHeight * currentRelativeChild->style.aspectRatio,
getPaddingAndBorderAxis(currentRelativeChild, CSSFlexDirectionRow));
childWidthMeasureMode = CSSMeasureModeExactly;
}
}
constrainMaxSizeForMode(currentRelativeChild->style.maxDimensions[CSSDimensionWidth],
&childWidthMeasureMode,
&childWidth);