2018-02-12 08:04:16 +00:00
|
|
|
/**
|
2018-09-11 22:27:47 +00:00
|
|
|
* Copyright (c) Facebook, Inc. and its affiliates.
|
2018-02-12 08:04:16 +00:00
|
|
|
*
|
2018-02-17 02:24:55 +00:00
|
|
|
* This source code is licensed under the MIT license found in the
|
|
|
|
* LICENSE file in the root directory of this source tree.
|
2018-02-12 08:04:16 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
#import <yoga/Yoga.h>
|
|
|
|
|
|
|
|
#import "RCTAssert.h"
|
|
|
|
#import "RCTShadowView+Layout.h"
|
|
|
|
|
|
|
|
RCTLayoutMetrics RCTLayoutMetricsFromYogaNode(YGNodeRef yogaNode)
|
|
|
|
{
|
|
|
|
RCTLayoutMetrics layoutMetrics;
|
|
|
|
|
|
|
|
CGRect frame = (CGRect){
|
|
|
|
(CGPoint){
|
|
|
|
RCTCoreGraphicsFloatFromYogaFloat(YGNodeLayoutGetLeft(yogaNode)),
|
|
|
|
RCTCoreGraphicsFloatFromYogaFloat(YGNodeLayoutGetTop(yogaNode))
|
|
|
|
},
|
|
|
|
(CGSize){
|
|
|
|
RCTCoreGraphicsFloatFromYogaFloat(YGNodeLayoutGetWidth(yogaNode)),
|
|
|
|
RCTCoreGraphicsFloatFromYogaFloat(YGNodeLayoutGetHeight(yogaNode))
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
UIEdgeInsets padding = (UIEdgeInsets){
|
|
|
|
RCTCoreGraphicsFloatFromYogaFloat(YGNodeLayoutGetPadding(yogaNode, YGEdgeTop)),
|
|
|
|
RCTCoreGraphicsFloatFromYogaFloat(YGNodeLayoutGetPadding(yogaNode, YGEdgeLeft)),
|
|
|
|
RCTCoreGraphicsFloatFromYogaFloat(YGNodeLayoutGetPadding(yogaNode, YGEdgeBottom)),
|
|
|
|
RCTCoreGraphicsFloatFromYogaFloat(YGNodeLayoutGetPadding(yogaNode, YGEdgeRight))
|
|
|
|
};
|
|
|
|
|
|
|
|
UIEdgeInsets borderWidth = (UIEdgeInsets){
|
|
|
|
RCTCoreGraphicsFloatFromYogaFloat(YGNodeLayoutGetBorder(yogaNode, YGEdgeTop)),
|
|
|
|
RCTCoreGraphicsFloatFromYogaFloat(YGNodeLayoutGetBorder(yogaNode, YGEdgeLeft)),
|
|
|
|
RCTCoreGraphicsFloatFromYogaFloat(YGNodeLayoutGetBorder(yogaNode, YGEdgeBottom)),
|
|
|
|
RCTCoreGraphicsFloatFromYogaFloat(YGNodeLayoutGetBorder(yogaNode, YGEdgeRight))
|
|
|
|
};
|
|
|
|
|
|
|
|
UIEdgeInsets compoundInsets = (UIEdgeInsets){
|
|
|
|
borderWidth.top + padding.top,
|
|
|
|
borderWidth.left + padding.left,
|
|
|
|
borderWidth.bottom + padding.bottom,
|
|
|
|
borderWidth.right + padding.right
|
|
|
|
};
|
|
|
|
|
|
|
|
CGRect bounds = (CGRect){CGPointZero, frame.size};
|
|
|
|
CGRect contentFrame = UIEdgeInsetsInsetRect(bounds, compoundInsets);
|
|
|
|
|
|
|
|
layoutMetrics.frame = frame;
|
|
|
|
layoutMetrics.borderWidth = borderWidth;
|
|
|
|
layoutMetrics.contentFrame = contentFrame;
|
|
|
|
layoutMetrics.displayType = RCTReactDisplayTypeFromYogaDisplayType(YGNodeStyleGetDisplay(yogaNode));
|
|
|
|
layoutMetrics.layoutDirection = RCTUIKitLayoutDirectionFromYogaLayoutDirection(YGNodeLayoutGetDirection(yogaNode));
|
|
|
|
|
|
|
|
return layoutMetrics;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* 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;
|
|
|
|
}
|
|
|
|
|
|
|
|
CGFloat RCTCoreGraphicsFloatFromYogaValue(YGValue value, CGFloat baseFloatValue)
|
|
|
|
{
|
|
|
|
switch (value.unit) {
|
|
|
|
case YGUnitPoint:
|
|
|
|
return RCTCoreGraphicsFloatFromYogaFloat(value.value);
|
|
|
|
case YGUnitPercent:
|
|
|
|
return RCTCoreGraphicsFloatFromYogaFloat(value.value) * baseFloatValue;
|
|
|
|
case YGUnitAuto:
|
|
|
|
case YGUnitUndefined:
|
|
|
|
return baseFloatValue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
YGDirection RCTYogaLayoutDirectionFromUIKitLayoutDirection(UIUserInterfaceLayoutDirection direction)
|
|
|
|
{
|
|
|
|
switch (direction) {
|
|
|
|
case UIUserInterfaceLayoutDirectionRightToLeft:
|
|
|
|
return YGDirectionRTL;
|
|
|
|
case UIUserInterfaceLayoutDirectionLeftToRight:
|
|
|
|
return YGDirectionLTR;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
UIUserInterfaceLayoutDirection RCTUIKitLayoutDirectionFromYogaLayoutDirection(YGDirection direction)
|
|
|
|
{
|
|
|
|
switch (direction) {
|
|
|
|
case YGDirectionInherit:
|
|
|
|
case YGDirectionLTR:
|
|
|
|
return UIUserInterfaceLayoutDirectionLeftToRight;
|
|
|
|
case YGDirectionRTL:
|
|
|
|
return UIUserInterfaceLayoutDirectionRightToLeft;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
YGDisplay RCTYogaDisplayTypeFromReactDisplayType(RCTDisplayType displayType)
|
|
|
|
{
|
|
|
|
switch (displayType) {
|
|
|
|
case RCTDisplayTypeNone:
|
|
|
|
return YGDisplayNone;
|
|
|
|
case RCTDisplayTypeFlex:
|
|
|
|
return YGDisplayFlex;
|
|
|
|
case RCTDisplayTypeInline:
|
|
|
|
RCTAssert(NO, @"RCTDisplayTypeInline cannot be converted to YGDisplay value.");
|
|
|
|
return YGDisplayNone;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
RCTDisplayType RCTReactDisplayTypeFromYogaDisplayType(YGDisplay displayType)
|
|
|
|
{
|
|
|
|
switch (displayType) {
|
|
|
|
case YGDisplayFlex:
|
|
|
|
return RCTDisplayTypeFlex;
|
|
|
|
case YGDisplayNone:
|
|
|
|
return RCTDisplayTypeNone;
|
|
|
|
}
|
|
|
|
}
|