RCTLayout.m 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132
  1. /*
  2. * Copyright (c) Facebook, Inc. and its affiliates.
  3. *
  4. * This source code is licensed under the MIT license found in the
  5. * LICENSE file in the root directory of this source tree.
  6. */
  7. #import <yoga/Yoga.h>
  8. #import "RCTAssert.h"
  9. #import "RCTShadowView+Layout.h"
  10. RCTLayoutMetrics RCTLayoutMetricsFromYogaNode(YGNodeRef yogaNode)
  11. {
  12. RCTLayoutMetrics layoutMetrics;
  13. CGRect frame = (CGRect){(CGPoint){RCTCoreGraphicsFloatFromYogaFloat(YGNodeLayoutGetLeft(yogaNode)),
  14. RCTCoreGraphicsFloatFromYogaFloat(YGNodeLayoutGetTop(yogaNode))},
  15. (CGSize){RCTCoreGraphicsFloatFromYogaFloat(YGNodeLayoutGetWidth(yogaNode)),
  16. RCTCoreGraphicsFloatFromYogaFloat(YGNodeLayoutGetHeight(yogaNode))}};
  17. UIEdgeInsets padding =
  18. (UIEdgeInsets){RCTCoreGraphicsFloatFromYogaFloat(YGNodeLayoutGetPadding(yogaNode, YGEdgeTop)),
  19. RCTCoreGraphicsFloatFromYogaFloat(YGNodeLayoutGetPadding(yogaNode, YGEdgeLeft)),
  20. RCTCoreGraphicsFloatFromYogaFloat(YGNodeLayoutGetPadding(yogaNode, YGEdgeBottom)),
  21. RCTCoreGraphicsFloatFromYogaFloat(YGNodeLayoutGetPadding(yogaNode, YGEdgeRight))};
  22. UIEdgeInsets borderWidth =
  23. (UIEdgeInsets){RCTCoreGraphicsFloatFromYogaFloat(YGNodeLayoutGetBorder(yogaNode, YGEdgeTop)),
  24. RCTCoreGraphicsFloatFromYogaFloat(YGNodeLayoutGetBorder(yogaNode, YGEdgeLeft)),
  25. RCTCoreGraphicsFloatFromYogaFloat(YGNodeLayoutGetBorder(yogaNode, YGEdgeBottom)),
  26. RCTCoreGraphicsFloatFromYogaFloat(YGNodeLayoutGetBorder(yogaNode, YGEdgeRight))};
  27. UIEdgeInsets compoundInsets = (UIEdgeInsets){borderWidth.top + padding.top,
  28. borderWidth.left + padding.left,
  29. borderWidth.bottom + padding.bottom,
  30. borderWidth.right + padding.right};
  31. CGRect bounds = (CGRect){CGPointZero, frame.size};
  32. CGRect contentFrame = UIEdgeInsetsInsetRect(bounds, compoundInsets);
  33. layoutMetrics.frame = frame;
  34. layoutMetrics.borderWidth = borderWidth;
  35. layoutMetrics.contentFrame = contentFrame;
  36. layoutMetrics.displayType = RCTReactDisplayTypeFromYogaDisplayType(YGNodeStyleGetDisplay(yogaNode));
  37. layoutMetrics.layoutDirection = RCTUIKitLayoutDirectionFromYogaLayoutDirection(YGNodeLayoutGetDirection(yogaNode));
  38. return layoutMetrics;
  39. }
  40. /**
  41. * Yoga and CoreGraphics have different opinions about how "infinity" value
  42. * should be represented.
  43. * Yoga uses `NAN` which requires additional effort to compare all those values,
  44. * whereas GoreGraphics uses `GFLOAT_MAX` which can be easyly compared with
  45. * standard `==` operator.
  46. */
  47. float RCTYogaFloatFromCoreGraphicsFloat(CGFloat value)
  48. {
  49. if (value == CGFLOAT_MAX || isnan(value) || isinf(value)) {
  50. return YGUndefined;
  51. }
  52. return value;
  53. }
  54. CGFloat RCTCoreGraphicsFloatFromYogaFloat(float value)
  55. {
  56. if (value == YGUndefined || isnan(value) || isinf(value)) {
  57. return CGFLOAT_MAX;
  58. }
  59. return value;
  60. }
  61. CGFloat RCTCoreGraphicsFloatFromYogaValue(YGValue value, CGFloat baseFloatValue)
  62. {
  63. switch (value.unit) {
  64. case YGUnitPoint:
  65. return RCTCoreGraphicsFloatFromYogaFloat(value.value);
  66. case YGUnitPercent:
  67. return RCTCoreGraphicsFloatFromYogaFloat(value.value) * baseFloatValue;
  68. case YGUnitAuto:
  69. case YGUnitUndefined:
  70. return baseFloatValue;
  71. }
  72. }
  73. YGDirection RCTYogaLayoutDirectionFromUIKitLayoutDirection(UIUserInterfaceLayoutDirection direction)
  74. {
  75. switch (direction) {
  76. case UIUserInterfaceLayoutDirectionRightToLeft:
  77. return YGDirectionRTL;
  78. case UIUserInterfaceLayoutDirectionLeftToRight:
  79. return YGDirectionLTR;
  80. }
  81. }
  82. UIUserInterfaceLayoutDirection RCTUIKitLayoutDirectionFromYogaLayoutDirection(YGDirection direction)
  83. {
  84. switch (direction) {
  85. case YGDirectionInherit:
  86. case YGDirectionLTR:
  87. return UIUserInterfaceLayoutDirectionLeftToRight;
  88. case YGDirectionRTL:
  89. return UIUserInterfaceLayoutDirectionRightToLeft;
  90. }
  91. }
  92. YGDisplay RCTYogaDisplayTypeFromReactDisplayType(RCTDisplayType displayType)
  93. {
  94. switch (displayType) {
  95. case RCTDisplayTypeNone:
  96. return YGDisplayNone;
  97. case RCTDisplayTypeFlex:
  98. return YGDisplayFlex;
  99. case RCTDisplayTypeInline:
  100. RCTAssert(NO, @"RCTDisplayTypeInline cannot be converted to YGDisplay value.");
  101. return YGDisplayNone;
  102. }
  103. }
  104. RCTDisplayType RCTReactDisplayTypeFromYogaDisplayType(YGDisplay displayType)
  105. {
  106. switch (displayType) {
  107. case YGDisplayFlex:
  108. return RCTDisplayTypeFlex;
  109. case YGDisplayNone:
  110. return RCTDisplayTypeNone;
  111. }
  112. }