Skip to content

Commit e1df3c8

Browse files
Emil SjolanderFacebook Github Bot
authored andcommitted
Add aspectRatio style property
Reviewed By: gkassabli Differential Revision: D4211458 fbshipit-source-id: f8d0d318369c7b529ee29e61a52b17d0cf3b396d
1 parent ec467fb commit e1df3c8

6 files changed

Lines changed: 131 additions & 0 deletions

File tree

React/CSSLayout/CSSLayout.c

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,9 @@ typedef struct CSSStyle {
8585
float dimensions[2];
8686
float minDimensions[2];
8787
float maxDimensions[2];
88+
89+
// Yoga specific properties, not compatible with flexbox specification
90+
float aspectRatio;
8891
} CSSStyle;
8992

9093
typedef struct CSSNode {
@@ -269,6 +272,8 @@ void CSSNodeInit(const CSSNodeRef node) {
269272
node->style.border[edge] = CSSUndefined;
270273
}
271274

275+
node->style.aspectRatio = CSSUndefined;
276+
272277
node->layout.dimensions[CSSDimensionWidth] = CSSUndefined;
273278
node->layout.dimensions[CSSDimensionHeight] = CSSUndefined;
274279

@@ -459,6 +464,9 @@ CSS_NODE_STYLE_PROPERTY_IMPL(float, MinHeight, minHeight, minDimensions[CSSDimen
459464
CSS_NODE_STYLE_PROPERTY_IMPL(float, MaxWidth, maxWidth, maxDimensions[CSSDimensionWidth]);
460465
CSS_NODE_STYLE_PROPERTY_IMPL(float, MaxHeight, maxHeight, maxDimensions[CSSDimensionHeight]);
461466

467+
// Yoga specific properties, not compatible with flexbox specification
468+
CSS_NODE_STYLE_PROPERTY_IMPL(float, AspectRatio, aspectRatio, aspectRatio);
469+
462470
CSS_NODE_LAYOUT_PROPERTY_IMPL(float, Left, position[CSSEdgeLeft]);
463471
CSS_NODE_LAYOUT_PROPERTY_IMPL(float, Top, position[CSSEdgeTop]);
464472
CSS_NODE_LAYOUT_PROPERTY_IMPL(float, Right, position[CSSEdgeRight]);
@@ -1032,6 +1040,20 @@ static void computeChildFlexBasis(const CSSNodeRef node,
10321040
childHeightMeasureMode = CSSMeasureModeExactly;
10331041
}
10341042

1043+
if (!CSSValueIsUndefined(child->style.aspectRatio)) {
1044+
if (!isMainAxisRow && childWidthMeasureMode == CSSMeasureModeExactly) {
1045+
child->layout.computedFlexBasis =
1046+
fmaxf(childWidth * child->style.aspectRatio,
1047+
getPaddingAndBorderAxis(child, CSSFlexDirectionColumn));
1048+
return;
1049+
} else if (isMainAxisRow && childHeightMeasureMode == CSSMeasureModeExactly) {
1050+
child->layout.computedFlexBasis =
1051+
fmaxf(childHeight * child->style.aspectRatio,
1052+
getPaddingAndBorderAxis(child, CSSFlexDirectionRow));
1053+
return;
1054+
}
1055+
}
1056+
10351057
constrainMaxSizeForMode(child->style.maxDimensions[CSSDimensionWidth],
10361058
&childWidthMeasureMode,
10371059
&childWidth);
@@ -1108,6 +1130,20 @@ static void absoluteLayoutChild(const CSSNodeRef node,
11081130
}
11091131
}
11101132

1133+
// Exactly one dimension needs to be defined for us to be able to do aspect ratio
1134+
// calculation. One dimension being the anchor and the other being flexible.
1135+
if (CSSValueIsUndefined(childWidth) ^ CSSValueIsUndefined(childHeight)) {
1136+
if (!CSSValueIsUndefined(child->style.aspectRatio)) {
1137+
if (CSSValueIsUndefined(childWidth)) {
1138+
childWidth = fmaxf(childHeight * child->style.aspectRatio,
1139+
getPaddingAndBorderAxis(child, CSSFlexDirectionColumn));
1140+
} else if (CSSValueIsUndefined(childHeight)) {
1141+
childHeight = fmaxf(childWidth * child->style.aspectRatio,
1142+
getPaddingAndBorderAxis(child, CSSFlexDirectionRow));
1143+
}
1144+
}
1145+
}
1146+
11111147
// If we're still missing one or the other dimension, measure the content.
11121148
if (CSSValueIsUndefined(childWidth) || CSSValueIsUndefined(childHeight)) {
11131149
childWidthMeasureMode =
@@ -1774,6 +1810,19 @@ static void layoutNodeImpl(const CSSNodeRef node,
17741810
}
17751811
}
17761812

1813+
if (!CSSValueIsUndefined(currentRelativeChild->style.aspectRatio)) {
1814+
if (isMainAxisRow && childHeightMeasureMode != CSSMeasureModeExactly) {
1815+
childHeight =
1816+
fmaxf(childWidth * currentRelativeChild->style.aspectRatio,
1817+
getPaddingAndBorderAxis(currentRelativeChild, CSSFlexDirectionColumn));
1818+
childHeightMeasureMode = CSSMeasureModeExactly;
1819+
} else if (!isMainAxisRow && childWidthMeasureMode != CSSMeasureModeExactly) {
1820+
childWidth = fmaxf(childHeight * currentRelativeChild->style.aspectRatio,
1821+
getPaddingAndBorderAxis(currentRelativeChild, CSSFlexDirectionRow));
1822+
childWidthMeasureMode = CSSMeasureModeExactly;
1823+
}
1824+
}
1825+
17771826
constrainMaxSizeForMode(currentRelativeChild->style.maxDimensions[CSSDimensionWidth],
17781827
&childWidthMeasureMode,
17791828
&childWidth);

React/CSSLayout/CSSLayout.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,15 @@ CSS_NODE_STYLE_PROPERTY(float, MinHeight, minHeight);
149149
CSS_NODE_STYLE_PROPERTY(float, MaxWidth, maxWidth);
150150
CSS_NODE_STYLE_PROPERTY(float, MaxHeight, maxHeight);
151151

152+
// Yoga specific properties, not compatible with flexbox specification
153+
// Aspect ratio control the size of the undefined dimension of a node.
154+
// - On a node with a set width/height aspect ratio control the size of the unset dimension
155+
// - On a node with a set flex basis aspect ratio controls the size of the node in the cross axis if unset
156+
// - On a node with a measure function aspect ratio works as though the measure function measures the flex basis
157+
// - On a node with flex grow/shrink aspect ratio controls the size of the node in the cross axis if unset
158+
// - Aspect ratio takes min/max dimensions into account
159+
CSS_NODE_STYLE_PROPERTY(float, AspectRatio, aspectRatio);
160+
152161
CSS_NODE_LAYOUT_PROPERTY(float, Left);
153162
CSS_NODE_LAYOUT_PROPERTY(float, Top);
154163
CSS_NODE_LAYOUT_PROPERTY(float, Right);

ReactAndroid/src/main/java/com/facebook/csslayout/CSSNode.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -476,6 +476,16 @@ public void setStyleMaxHeight(float maxheight) {
476476
jni_CSSNodeStyleSetMaxHeight(mNativePointer, maxheight);
477477
}
478478

479+
private native float jni_CSSNodeStyleGetAspectRatio(long nativePointer);
480+
public float getStyleAspectRatio() {
481+
return jni_CSSNodeStyleGetAspectRatio(mNativePointer);
482+
}
483+
484+
private native void jni_CSSNodeStyleSetAspectRatio(long nativePointer, float aspectRatio);
485+
public void setStyleAspectRatio(float aspectRatio) {
486+
jni_CSSNodeStyleSetAspectRatio(mNativePointer, aspectRatio);
487+
}
488+
479489
@Override
480490
public float getLayoutX() {
481491
return mLeft;

ReactAndroid/src/main/jni/first-party/csslayoutjni/jni/CSSJNI.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -249,6 +249,9 @@ CSS_NODE_JNI_STYLE_PROP(jfloat, float, Height);
249249
CSS_NODE_JNI_STYLE_PROP(jfloat, float, MinHeight);
250250
CSS_NODE_JNI_STYLE_PROP(jfloat, float, MaxHeight);
251251

252+
// Yoga specific properties, not compatible with flexbox specification
253+
CSS_NODE_JNI_STYLE_PROP(jfloat, float, AspectRatio);
254+
252255
#define CSSMakeNativeMethod(name) makeNativeMethod(#name, name)
253256

254257
jint JNI_OnLoad(JavaVM *vm, void *) {
@@ -312,6 +315,8 @@ jint JNI_OnLoad(JavaVM *vm, void *) {
312315
CSSMakeNativeMethod(jni_CSSNodeStyleSetMaxWidth),
313316
CSSMakeNativeMethod(jni_CSSNodeStyleGetMaxHeight),
314317
CSSMakeNativeMethod(jni_CSSNodeStyleSetMaxHeight),
318+
CSSMakeNativeMethod(jni_CSSNodeStyleGetAspectRatio),
319+
CSSMakeNativeMethod(jni_CSSNodeStyleSetAspectRatio),
315320

316321
CSSMakeNativeMethod(jni_CSSNodeGetInstanceCount),
317322
CSSMakeNativeMethod(jni_CSSLayoutSetLogger),

ReactCommon/CSSLayout/CSSLayout/CSSLayout.c

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,9 @@ typedef struct CSSStyle {
8585
float dimensions[2];
8686
float minDimensions[2];
8787
float maxDimensions[2];
88+
89+
// Yoga specific properties, not compatible with flexbox specification
90+
float aspectRatio;
8891
} CSSStyle;
8992

9093
typedef struct CSSNode {
@@ -269,6 +272,8 @@ void CSSNodeInit(const CSSNodeRef node) {
269272
node->style.border[edge] = CSSUndefined;
270273
}
271274

275+
node->style.aspectRatio = CSSUndefined;
276+
272277
node->layout.dimensions[CSSDimensionWidth] = CSSUndefined;
273278
node->layout.dimensions[CSSDimensionHeight] = CSSUndefined;
274279

@@ -459,6 +464,9 @@ CSS_NODE_STYLE_PROPERTY_IMPL(float, MinHeight, minHeight, minDimensions[CSSDimen
459464
CSS_NODE_STYLE_PROPERTY_IMPL(float, MaxWidth, maxWidth, maxDimensions[CSSDimensionWidth]);
460465
CSS_NODE_STYLE_PROPERTY_IMPL(float, MaxHeight, maxHeight, maxDimensions[CSSDimensionHeight]);
461466

467+
// Yoga specific properties, not compatible with flexbox specification
468+
CSS_NODE_STYLE_PROPERTY_IMPL(float, AspectRatio, aspectRatio, aspectRatio);
469+
462470
CSS_NODE_LAYOUT_PROPERTY_IMPL(float, Left, position[CSSEdgeLeft]);
463471
CSS_NODE_LAYOUT_PROPERTY_IMPL(float, Top, position[CSSEdgeTop]);
464472
CSS_NODE_LAYOUT_PROPERTY_IMPL(float, Right, position[CSSEdgeRight]);
@@ -1032,6 +1040,20 @@ static void computeChildFlexBasis(const CSSNodeRef node,
10321040
childHeightMeasureMode = CSSMeasureModeExactly;
10331041
}
10341042

1043+
if (!CSSValueIsUndefined(child->style.aspectRatio)) {
1044+
if (!isMainAxisRow && childWidthMeasureMode == CSSMeasureModeExactly) {
1045+
child->layout.computedFlexBasis =
1046+
fmaxf(childWidth * child->style.aspectRatio,
1047+
getPaddingAndBorderAxis(child, CSSFlexDirectionColumn));
1048+
return;
1049+
} else if (isMainAxisRow && childHeightMeasureMode == CSSMeasureModeExactly) {
1050+
child->layout.computedFlexBasis =
1051+
fmaxf(childHeight * child->style.aspectRatio,
1052+
getPaddingAndBorderAxis(child, CSSFlexDirectionRow));
1053+
return;
1054+
}
1055+
}
1056+
10351057
constrainMaxSizeForMode(child->style.maxDimensions[CSSDimensionWidth],
10361058
&childWidthMeasureMode,
10371059
&childWidth);
@@ -1108,6 +1130,20 @@ static void absoluteLayoutChild(const CSSNodeRef node,
11081130
}
11091131
}
11101132

1133+
// Exactly one dimension needs to be defined for us to be able to do aspect ratio
1134+
// calculation. One dimension being the anchor and the other being flexible.
1135+
if (CSSValueIsUndefined(childWidth) ^ CSSValueIsUndefined(childHeight)) {
1136+
if (!CSSValueIsUndefined(child->style.aspectRatio)) {
1137+
if (CSSValueIsUndefined(childWidth)) {
1138+
childWidth = fmaxf(childHeight * child->style.aspectRatio,
1139+
getPaddingAndBorderAxis(child, CSSFlexDirectionColumn));
1140+
} else if (CSSValueIsUndefined(childHeight)) {
1141+
childHeight = fmaxf(childWidth * child->style.aspectRatio,
1142+
getPaddingAndBorderAxis(child, CSSFlexDirectionRow));
1143+
}
1144+
}
1145+
}
1146+
11111147
// If we're still missing one or the other dimension, measure the content.
11121148
if (CSSValueIsUndefined(childWidth) || CSSValueIsUndefined(childHeight)) {
11131149
childWidthMeasureMode =
@@ -1774,6 +1810,19 @@ static void layoutNodeImpl(const CSSNodeRef node,
17741810
}
17751811
}
17761812

1813+
if (!CSSValueIsUndefined(currentRelativeChild->style.aspectRatio)) {
1814+
if (isMainAxisRow && childHeightMeasureMode != CSSMeasureModeExactly) {
1815+
childHeight =
1816+
fmaxf(childWidth * currentRelativeChild->style.aspectRatio,
1817+
getPaddingAndBorderAxis(currentRelativeChild, CSSFlexDirectionColumn));
1818+
childHeightMeasureMode = CSSMeasureModeExactly;
1819+
} else if (!isMainAxisRow && childWidthMeasureMode != CSSMeasureModeExactly) {
1820+
childWidth = fmaxf(childHeight * currentRelativeChild->style.aspectRatio,
1821+
getPaddingAndBorderAxis(currentRelativeChild, CSSFlexDirectionRow));
1822+
childWidthMeasureMode = CSSMeasureModeExactly;
1823+
}
1824+
}
1825+
17771826
constrainMaxSizeForMode(currentRelativeChild->style.maxDimensions[CSSDimensionWidth],
17781827
&childWidthMeasureMode,
17791828
&childWidth);

ReactCommon/CSSLayout/CSSLayout/CSSLayout.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,15 @@ CSS_NODE_STYLE_PROPERTY(float, MinHeight, minHeight);
149149
CSS_NODE_STYLE_PROPERTY(float, MaxWidth, maxWidth);
150150
CSS_NODE_STYLE_PROPERTY(float, MaxHeight, maxHeight);
151151

152+
// Yoga specific properties, not compatible with flexbox specification
153+
// Aspect ratio control the size of the undefined dimension of a node.
154+
// - On a node with a set width/height aspect ratio control the size of the unset dimension
155+
// - On a node with a set flex basis aspect ratio controls the size of the node in the cross axis if unset
156+
// - On a node with a measure function aspect ratio works as though the measure function measures the flex basis
157+
// - On a node with flex grow/shrink aspect ratio controls the size of the node in the cross axis if unset
158+
// - Aspect ratio takes min/max dimensions into account
159+
CSS_NODE_STYLE_PROPERTY(float, AspectRatio, aspectRatio);
160+
152161
CSS_NODE_LAYOUT_PROPERTY(float, Left);
153162
CSS_NODE_LAYOUT_PROPERTY(float, Top);
154163
CSS_NODE_LAYOUT_PROPERTY(float, Right);

0 commit comments

Comments
 (0)