From 1c69b61c26aaf24176573dfb40bcad805acd7f3c Mon Sep 17 00:00:00 2001 From: Lukas Woehrl Date: Tue, 22 Nov 2016 05:33:36 -0800 Subject: [PATCH] Added feature to use rounded values Summary: Added an experimental feature to allow to use only rounded values. See #184. It's not a perfect solution and definitely can be further improved. I'm looking forward to your ideas. Closes https://github.com/facebook/css-layout/pull/256 Reviewed By: splhack Differential Revision: D4214168 Pulled By: emilsjolander fbshipit-source-id: 6293352d479b7b4dad258eb3f9e0afaa11cf7236 --- React/CSSLayout/CSSEnums.h | 1 + React/CSSLayout/CSSLayout.c | 25 ++++++++++++++++++- React/CSSLayout/CSSLayout.h | 9 ++++--- .../csslayout/CSSExperimentalFeature.java | 4 ++- ReactCommon/CSSLayout/CSSLayout/CSSEnums.h | 1 + ReactCommon/CSSLayout/CSSLayout/CSSLayout.c | 25 ++++++++++++++++++- ReactCommon/CSSLayout/CSSLayout/CSSLayout.h | 9 ++++--- 7 files changed, 65 insertions(+), 9 deletions(-) diff --git a/React/CSSLayout/CSSEnums.h b/React/CSSLayout/CSSEnums.h index 8f9979f5b..dbcb58e27 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 8c0733370..eeb99195f 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 7bcc244e9..e2dca0a72 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 e0b269f9a..c2b8b7af2 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 @@ __EMPTY(-1); 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 8f9979f5b..dbcb58e27 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 8c0733370..eeb99195f 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 7bcc244e9..e2dca0a72 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);