Skip to content

Commit

Permalink
Helpers for proper conversion float values between CG and YG represen…
Browse files Browse the repository at this point in the history
…tations

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
  • Loading branch information
shergin authored and facebook-github-bot committed Jan 8, 2018
1 parent af226ef commit d9e5b31
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 8 deletions.
7 changes: 7 additions & 0 deletions React/Views/RCTShadowView+Layout.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,13 @@

#import <React/RCTShadowView.h>

/**
* 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
Expand Down
42 changes: 34 additions & 8 deletions React/Views/RCTShadowView+Layout.m
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,32 @@

#import <yoga/Yoga.h>

/**
* 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
Expand All @@ -19,21 +45,21 @@ - (UIEdgeInsets)paddingAsInsets
{
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))
};
}

- (UIEdgeInsets)borderAsInsets
{
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))
};
}

Expand Down

0 comments on commit d9e5b31

Please sign in to comment.