From d9e5b313bb63a1ec0d402a96539c6df29bc72c42 Mon Sep 17 00:00:00 2001 From: Valentin Shergin Date: Sun, 7 Jan 2018 18:21:39 -0800 Subject: [PATCH] Helpers for proper conversion float values between CG and YG representations Summary: Yoga and CoreGraphics have different opinions about how "infinity" value should be represented. Yoga uses `NAN` which requires additional effort to compare all those values, whereas GoreGraphics uses `GFLOAT_MAX` which can be easyly compared with standard `==` operator. Messing with this can cause super weired bugs like 100% CPU load for couple of seconds somewhere in CoreGraphics. Reviewed By: mmmulani Differential Revision: D6665633 fbshipit-source-id: b6236c6fa50d1f8fb0c9576203922f7b24b7301e --- React/Views/RCTShadowView+Layout.h | 7 +++++ React/Views/RCTShadowView+Layout.m | 42 ++++++++++++++++++++++++------ 2 files changed, 41 insertions(+), 8 deletions(-) diff --git a/React/Views/RCTShadowView+Layout.h b/React/Views/RCTShadowView+Layout.h index 917b5f4a5..fe40dca40 100644 --- a/React/Views/RCTShadowView+Layout.h +++ b/React/Views/RCTShadowView+Layout.h @@ -11,6 +11,13 @@ #import +/** + * Converts float values between Yoga and CoreGraphics representations, + * especially in terms of edge cases. + */ +RCT_EXTERN float RCTYogaFloatFromCoreGraphicsFloat(CGFloat value); +RCT_EXTERN CGFloat RCTCoreGraphicsFloatFromYogaFloat(float value); + @interface RCTShadowView (Layout) #pragma mark - Computed Layout-Inferred Metrics diff --git a/React/Views/RCTShadowView+Layout.m b/React/Views/RCTShadowView+Layout.m index b5e11e8d6..614a53889 100644 --- a/React/Views/RCTShadowView+Layout.m +++ b/React/Views/RCTShadowView+Layout.m @@ -11,6 +11,32 @@ #import +/** + * Yoga and CoreGraphics have different opinions about how "infinity" value + * should be represented. + * Yoga uses `NAN` which requires additional effort to compare all those values, + * whereas GoreGraphics uses `GFLOAT_MAX` which can be easyly compared with + * standard `==` operator. + */ + +float RCTYogaFloatFromCoreGraphicsFloat(CGFloat value) +{ + if (value == CGFLOAT_MAX || isnan(value) || isinf(value)) { + return YGUndefined; + } + + return value; +} + +CGFloat RCTCoreGraphicsFloatFromYogaFloat(float value) +{ + if (value == YGUndefined || isnan(value) || isinf(value)) { + return CGFLOAT_MAX; + } + + return value; +} + @implementation RCTShadowView (Layout) #pragma mark - Computed Layout-Inferred Metrics @@ -19,10 +45,10 @@ { YGNodeRef yogaNode = self.yogaNode; return (UIEdgeInsets){ - YGNodeLayoutGetPadding(yogaNode, YGEdgeTop), - YGNodeLayoutGetPadding(yogaNode, YGEdgeLeft), - YGNodeLayoutGetPadding(yogaNode, YGEdgeBottom), - YGNodeLayoutGetPadding(yogaNode, YGEdgeRight) + RCTCoreGraphicsFloatFromYogaFloat(YGNodeLayoutGetPadding(yogaNode, YGEdgeTop)), + RCTCoreGraphicsFloatFromYogaFloat(YGNodeLayoutGetPadding(yogaNode, YGEdgeLeft)), + RCTCoreGraphicsFloatFromYogaFloat(YGNodeLayoutGetPadding(yogaNode, YGEdgeBottom)), + RCTCoreGraphicsFloatFromYogaFloat(YGNodeLayoutGetPadding(yogaNode, YGEdgeRight)) }; } @@ -30,10 +56,10 @@ { YGNodeRef yogaNode = self.yogaNode; return (UIEdgeInsets){ - YGNodeLayoutGetBorder(yogaNode, YGEdgeTop), - YGNodeLayoutGetBorder(yogaNode, YGEdgeLeft), - YGNodeLayoutGetBorder(yogaNode, YGEdgeBottom), - YGNodeLayoutGetBorder(yogaNode, YGEdgeRight) + RCTCoreGraphicsFloatFromYogaFloat(YGNodeLayoutGetBorder(yogaNode, YGEdgeTop)), + RCTCoreGraphicsFloatFromYogaFloat(YGNodeLayoutGetBorder(yogaNode, YGEdgeLeft)), + RCTCoreGraphicsFloatFromYogaFloat(YGNodeLayoutGetBorder(yogaNode, YGEdgeBottom)), + RCTCoreGraphicsFloatFromYogaFloat(YGNodeLayoutGetBorder(yogaNode, YGEdgeRight)) }; }