Add aspectRatio style property

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 ec467fbd34
commit e1df3c8782
6 changed files with 131 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);

View File

@ -149,6 +149,15 @@ CSS_NODE_STYLE_PROPERTY(float, MinHeight, minHeight);
CSS_NODE_STYLE_PROPERTY(float, MaxWidth, maxWidth);
CSS_NODE_STYLE_PROPERTY(float, MaxHeight, maxHeight);
// Yoga specific properties, not compatible with flexbox specification
// Aspect ratio control the size of the undefined dimension of a node.
// - On a node with a set width/height aspect ratio control the size of the unset dimension
// - On a node with a set flex basis aspect ratio controls the size of the node in the cross axis if unset
// - On a node with a measure function aspect ratio works as though the measure function measures the flex basis
// - On a node with flex grow/shrink aspect ratio controls the size of the node in the cross axis if unset
// - Aspect ratio takes min/max dimensions into account
CSS_NODE_STYLE_PROPERTY(float, AspectRatio, aspectRatio);
CSS_NODE_LAYOUT_PROPERTY(float, Left);
CSS_NODE_LAYOUT_PROPERTY(float, Top);
CSS_NODE_LAYOUT_PROPERTY(float, Right);

View File

@ -476,6 +476,16 @@ public class CSSNode implements CSSNodeAPI<CSSNode> {
jni_CSSNodeStyleSetMaxHeight(mNativePointer, maxheight);
}
private native float jni_CSSNodeStyleGetAspectRatio(long nativePointer);
public float getStyleAspectRatio() {
return jni_CSSNodeStyleGetAspectRatio(mNativePointer);
}
private native void jni_CSSNodeStyleSetAspectRatio(long nativePointer, float aspectRatio);
public void setStyleAspectRatio(float aspectRatio) {
jni_CSSNodeStyleSetAspectRatio(mNativePointer, aspectRatio);
}
@Override
public float getLayoutX() {
return mLeft;

View File

@ -249,6 +249,9 @@ CSS_NODE_JNI_STYLE_PROP(jfloat, float, Height);
CSS_NODE_JNI_STYLE_PROP(jfloat, float, MinHeight);
CSS_NODE_JNI_STYLE_PROP(jfloat, float, MaxHeight);
// Yoga specific properties, not compatible with flexbox specification
CSS_NODE_JNI_STYLE_PROP(jfloat, float, AspectRatio);
#define CSSMakeNativeMethod(name) makeNativeMethod(#name, name)
jint JNI_OnLoad(JavaVM *vm, void *) {
@ -312,6 +315,8 @@ jint JNI_OnLoad(JavaVM *vm, void *) {
CSSMakeNativeMethod(jni_CSSNodeStyleSetMaxWidth),
CSSMakeNativeMethod(jni_CSSNodeStyleGetMaxHeight),
CSSMakeNativeMethod(jni_CSSNodeStyleSetMaxHeight),
CSSMakeNativeMethod(jni_CSSNodeStyleGetAspectRatio),
CSSMakeNativeMethod(jni_CSSNodeStyleSetAspectRatio),
CSSMakeNativeMethod(jni_CSSNodeGetInstanceCount),
CSSMakeNativeMethod(jni_CSSLayoutSetLogger),

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);

View File

@ -149,6 +149,15 @@ CSS_NODE_STYLE_PROPERTY(float, MinHeight, minHeight);
CSS_NODE_STYLE_PROPERTY(float, MaxWidth, maxWidth);
CSS_NODE_STYLE_PROPERTY(float, MaxHeight, maxHeight);
// Yoga specific properties, not compatible with flexbox specification
// Aspect ratio control the size of the undefined dimension of a node.
// - On a node with a set width/height aspect ratio control the size of the unset dimension
// - On a node with a set flex basis aspect ratio controls the size of the node in the cross axis if unset
// - On a node with a measure function aspect ratio works as though the measure function measures the flex basis
// - On a node with flex grow/shrink aspect ratio controls the size of the node in the cross axis if unset
// - Aspect ratio takes min/max dimensions into account
CSS_NODE_STYLE_PROPERTY(float, AspectRatio, aspectRatio);
CSS_NODE_LAYOUT_PROPERTY(float, Left);
CSS_NODE_LAYOUT_PROPERTY(float, Top);
CSS_NODE_LAYOUT_PROPERTY(float, Right);