diff --git a/React/CSSLayout/CSSEnums.h b/React/CSSLayout/CSSEnums.h index 8f9979f5b9ae24..dbcb58e27b8fa2 100644 --- a/React/CSSLayout/CSSEnums.h +++ b/React/CSSLayout/CSSEnums.h @@ -67,6 +67,7 @@ typedef enum CSSDirection { } CSSDirection; typedef enum CSSExperimentalFeature { + CSSExperimentalFeatureRounding, CSSExperimentalFeatureCount, } CSSExperimentalFeature; diff --git a/React/CSSLayout/CSSLayout.c b/React/CSSLayout/CSSLayout.c index 8c0733370146d0..eeb99195f7e960 100644 --- a/React/CSSLayout/CSSLayout.c +++ b/React/CSSLayout/CSSLayout.c @@ -2534,6 +2534,25 @@ bool layoutNodeInternal(const CSSNodeRef node, return (needToVisitNode || cachedResults == NULL); } +static void roundToPixelGrid(const CSSNodeRef node) { + const float fractialLeft = + node->layout.position[CSSEdgeLeft] - floorf(node->layout.position[CSSEdgeLeft]); + const float fractialTop = + node->layout.position[CSSEdgeTop] - floorf(node->layout.position[CSSEdgeTop]); + node->layout.dimensions[CSSDimensionWidth] = + roundf(fractialLeft + node->layout.dimensions[CSSDimensionWidth]) - roundf(fractialLeft); + node->layout.dimensions[CSSDimensionHeight] = + roundf(fractialTop + node->layout.dimensions[CSSDimensionHeight]) - roundf(fractialTop); + + node->layout.position[CSSEdgeLeft] = roundf(node->layout.position[CSSEdgeLeft]); + node->layout.position[CSSEdgeTop] = roundf(node->layout.position[CSSEdgeTop]); + + const uint32_t childCount = CSSNodeListCount(node->children); + for (uint32_t i = 0; i < childCount; i++) { + roundToPixelGrid(CSSNodeGetChild(node, i)); + } +} + void CSSNodeCalculateLayout(const CSSNodeRef node, const float availableWidth, const float availableHeight, @@ -2583,6 +2602,10 @@ void CSSNodeCalculateLayout(const CSSNodeRef node, "l")) { setPosition(node, node->layout.direction); + if (CSSLayoutIsExperimentalFeatureEnabled(CSSExperimentalFeatureRounding)) { + roundToPixelGrid(node); + } + if (gPrintTree) { CSSNodePrint(node, CSSPrintOptionsLayout | CSSPrintOptionsChildren | CSSPrintOptionsStyle); } @@ -2606,7 +2629,7 @@ void CSSLayoutSetExperimentalFeatureEnabled(CSSExperimentalFeature feature, bool experimentalFeatures[feature] = enabled; } -bool CSSLayoutIsExperimentalFeatureEnabled(CSSExperimentalFeature feature) { +inline bool CSSLayoutIsExperimentalFeatureEnabled(CSSExperimentalFeature feature) { return experimentalFeatures[feature]; } diff --git a/React/CSSLayout/CSSLayout.h b/React/CSSLayout/CSSLayout.h index 7bcc244e9a4e06..e2dca0a7271869 100644 --- a/React/CSSLayout/CSSLayout.h +++ b/React/CSSLayout/CSSLayout.h @@ -152,9 +152,12 @@ 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 +// - 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); diff --git a/ReactAndroid/src/main/java/com/facebook/csslayout/CSSExperimentalFeature.java b/ReactAndroid/src/main/java/com/facebook/csslayout/CSSExperimentalFeature.java index e0b269f9af71ea..c2b8b7af226114 100644 --- a/ReactAndroid/src/main/java/com/facebook/csslayout/CSSExperimentalFeature.java +++ b/ReactAndroid/src/main/java/com/facebook/csslayout/CSSExperimentalFeature.java @@ -10,7 +10,8 @@ package com.facebook.csslayout; public enum CSSExperimentalFeature { -__EMPTY(-1); + ROUNDING(0); + private int mIntValue; CSSExperimentalFeature(int intValue) { @@ -23,6 +24,7 @@ public int intValue() { public static CSSExperimentalFeature fromInt(int value) { switch (value) { + case 0: return ROUNDING; default: throw new IllegalArgumentException("Unkown enum value: " + value); } } diff --git a/ReactCommon/CSSLayout/CSSLayout/CSSEnums.h b/ReactCommon/CSSLayout/CSSLayout/CSSEnums.h index 8f9979f5b9ae24..dbcb58e27b8fa2 100644 --- a/ReactCommon/CSSLayout/CSSLayout/CSSEnums.h +++ b/ReactCommon/CSSLayout/CSSLayout/CSSEnums.h @@ -67,6 +67,7 @@ typedef enum CSSDirection { } CSSDirection; typedef enum CSSExperimentalFeature { + CSSExperimentalFeatureRounding, CSSExperimentalFeatureCount, } CSSExperimentalFeature; diff --git a/ReactCommon/CSSLayout/CSSLayout/CSSLayout.c b/ReactCommon/CSSLayout/CSSLayout/CSSLayout.c index 8c0733370146d0..eeb99195f7e960 100644 --- a/ReactCommon/CSSLayout/CSSLayout/CSSLayout.c +++ b/ReactCommon/CSSLayout/CSSLayout/CSSLayout.c @@ -2534,6 +2534,25 @@ bool layoutNodeInternal(const CSSNodeRef node, return (needToVisitNode || cachedResults == NULL); } +static void roundToPixelGrid(const CSSNodeRef node) { + const float fractialLeft = + node->layout.position[CSSEdgeLeft] - floorf(node->layout.position[CSSEdgeLeft]); + const float fractialTop = + node->layout.position[CSSEdgeTop] - floorf(node->layout.position[CSSEdgeTop]); + node->layout.dimensions[CSSDimensionWidth] = + roundf(fractialLeft + node->layout.dimensions[CSSDimensionWidth]) - roundf(fractialLeft); + node->layout.dimensions[CSSDimensionHeight] = + roundf(fractialTop + node->layout.dimensions[CSSDimensionHeight]) - roundf(fractialTop); + + node->layout.position[CSSEdgeLeft] = roundf(node->layout.position[CSSEdgeLeft]); + node->layout.position[CSSEdgeTop] = roundf(node->layout.position[CSSEdgeTop]); + + const uint32_t childCount = CSSNodeListCount(node->children); + for (uint32_t i = 0; i < childCount; i++) { + roundToPixelGrid(CSSNodeGetChild(node, i)); + } +} + void CSSNodeCalculateLayout(const CSSNodeRef node, const float availableWidth, const float availableHeight, @@ -2583,6 +2602,10 @@ void CSSNodeCalculateLayout(const CSSNodeRef node, "l")) { setPosition(node, node->layout.direction); + if (CSSLayoutIsExperimentalFeatureEnabled(CSSExperimentalFeatureRounding)) { + roundToPixelGrid(node); + } + if (gPrintTree) { CSSNodePrint(node, CSSPrintOptionsLayout | CSSPrintOptionsChildren | CSSPrintOptionsStyle); } @@ -2606,7 +2629,7 @@ void CSSLayoutSetExperimentalFeatureEnabled(CSSExperimentalFeature feature, bool experimentalFeatures[feature] = enabled; } -bool CSSLayoutIsExperimentalFeatureEnabled(CSSExperimentalFeature feature) { +inline bool CSSLayoutIsExperimentalFeatureEnabled(CSSExperimentalFeature feature) { return experimentalFeatures[feature]; } diff --git a/ReactCommon/CSSLayout/CSSLayout/CSSLayout.h b/ReactCommon/CSSLayout/CSSLayout/CSSLayout.h index 7bcc244e9a4e06..e2dca0a7271869 100644 --- a/ReactCommon/CSSLayout/CSSLayout/CSSLayout.h +++ b/ReactCommon/CSSLayout/CSSLayout/CSSLayout.h @@ -152,9 +152,12 @@ 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 +// - 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);