Permalink
Browse files

Add aspectRatio style property

Reviewed By: gkassabli

Differential Revision: D4211458

fbshipit-source-id: f8d0d318369c7b529ee29e61a52b17d0cf3b396d
  • Loading branch information...
1 parent ec467fb commit e1df3c878203fbed6cdf541849ab3ad490b8c93f @emilsjolander emilsjolander committed with Facebook Github Bot Nov 21, 2016
@@ -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);
@@ -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);
@@ -476,6 +476,16 @@ public void setStyleMaxHeight(float maxheight) {
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;
@@ -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),
@@ -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);
@@ -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);

0 comments on commit e1df3c8

Please sign in to comment.