ViewProps.cpp 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201
  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. #include "ViewProps.h"
  8. #include <algorithm>
  9. #include <react/components/view/conversions.h>
  10. #include <react/components/view/propsConversions.h>
  11. #include <react/core/propsConversions.h>
  12. #include <react/debug/debugStringConvertibleUtils.h>
  13. #include <react/graphics/conversions.h>
  14. namespace facebook {
  15. namespace react {
  16. ViewProps::ViewProps(ViewProps const &sourceProps, RawProps const &rawProps)
  17. : YogaStylableProps(sourceProps, rawProps),
  18. AccessibilityProps(sourceProps, rawProps),
  19. opacity(
  20. convertRawProp(rawProps, "opacity", sourceProps.opacity, (Float)1.0)),
  21. foregroundColor(convertRawProp(
  22. rawProps,
  23. "foregroundColor",
  24. sourceProps.foregroundColor,
  25. {})),
  26. backgroundColor(convertRawProp(
  27. rawProps,
  28. "backgroundColor",
  29. sourceProps.backgroundColor,
  30. {})),
  31. borderRadii(convertRawProp(
  32. rawProps,
  33. "border",
  34. "Radius",
  35. sourceProps.borderRadii,
  36. {})),
  37. borderColors(convertRawProp(
  38. rawProps,
  39. "border",
  40. "Color",
  41. sourceProps.borderColors,
  42. {})),
  43. borderStyles(convertRawProp(
  44. rawProps,
  45. "border",
  46. "Style",
  47. sourceProps.borderStyles,
  48. {})),
  49. shadowColor(
  50. convertRawProp(rawProps, "shadowColor", sourceProps.shadowColor, {})),
  51. shadowOffset(convertRawProp(
  52. rawProps,
  53. "shadowOffset",
  54. sourceProps.shadowOffset,
  55. {})),
  56. shadowOpacity(convertRawProp(
  57. rawProps,
  58. "shadowOpacity",
  59. sourceProps.shadowOpacity,
  60. {})),
  61. shadowRadius(convertRawProp(
  62. rawProps,
  63. "shadowRadius",
  64. sourceProps.shadowRadius,
  65. {})),
  66. transform(
  67. convertRawProp(rawProps, "transform", sourceProps.transform, {})),
  68. backfaceVisibility(convertRawProp(
  69. rawProps,
  70. "backfaceVisibility",
  71. sourceProps.backfaceVisibility,
  72. {})),
  73. shouldRasterize(convertRawProp(
  74. rawProps,
  75. "shouldRasterize",
  76. sourceProps.shouldRasterize,
  77. {})),
  78. zIndex(convertRawProp(rawProps, "zIndex", sourceProps.zIndex, {})),
  79. pointerEvents(convertRawProp(
  80. rawProps,
  81. "pointerEvents",
  82. sourceProps.pointerEvents,
  83. {})),
  84. hitSlop(convertRawProp(rawProps, "hitSlop", sourceProps.hitSlop, {})),
  85. onLayout(convertRawProp(rawProps, "onLayout", sourceProps.onLayout, {})),
  86. collapsable(convertRawProp(
  87. rawProps,
  88. "collapsable",
  89. sourceProps.collapsable,
  90. true)){};
  91. #pragma mark - Convenience Methods
  92. static BorderRadii ensureNoOverlap(BorderRadii const &radii, Size const &size) {
  93. // "Corner curves must not overlap: When the sum of any two adjacent border
  94. // radii exceeds the size of the border box, UAs must proportionally reduce
  95. // the used values of all border radii until none of them overlap."
  96. // Source: https://www.w3.org/TR/css-backgrounds-3/#corner-overlap
  97. auto insets = EdgeInsets{
  98. /* .left = */ radii.topLeft + radii.bottomLeft,
  99. /* .top = */ radii.topLeft + radii.topRight,
  100. /* .right = */ radii.topRight + radii.bottomRight,
  101. /* .bottom = */ radii.bottomLeft + radii.bottomRight,
  102. };
  103. auto insetsScale = EdgeInsets{
  104. /* .left = */
  105. insets.left > 0 ? std::min((Float)1.0, size.height / insets.left) : 0,
  106. /* .top = */
  107. insets.top > 0 ? std::min((Float)1.0, size.width / insets.top) : 0,
  108. /* .right = */
  109. insets.right > 0 ? std::min((Float)1.0, size.height / insets.right) : 0,
  110. /* .bottom = */
  111. insets.bottom > 0 ? std::min((Float)1.0, size.width / insets.bottom) : 0,
  112. };
  113. return BorderRadii{
  114. /* topLeft = */
  115. radii.topLeft * std::min(insetsScale.top, insetsScale.left),
  116. /* topRight = */
  117. radii.topRight * std::min(insetsScale.top, insetsScale.right),
  118. /* bottomLeft = */
  119. radii.bottomLeft * std::min(insetsScale.bottom, insetsScale.left),
  120. /* bottomRight = */
  121. radii.bottomRight * std::min(insetsScale.bottom, insetsScale.right),
  122. };
  123. }
  124. BorderMetrics ViewProps::resolveBorderMetrics(
  125. LayoutMetrics const &layoutMetrics) const {
  126. auto isRTL =
  127. bool{layoutMetrics.layoutDirection == LayoutDirection::RightToLeft};
  128. auto borderWidths = CascadedBorderWidths{
  129. /* .left = */ optionalFloatFromYogaValue(yogaStyle.border()[YGEdgeLeft]),
  130. /* .top = */ optionalFloatFromYogaValue(yogaStyle.border()[YGEdgeTop]),
  131. /* .right = */
  132. optionalFloatFromYogaValue(yogaStyle.border()[YGEdgeRight]),
  133. /* .bottom = */
  134. optionalFloatFromYogaValue(yogaStyle.border()[YGEdgeBottom]),
  135. /* .start = */
  136. optionalFloatFromYogaValue(yogaStyle.border()[YGEdgeStart]),
  137. /* .end = */ optionalFloatFromYogaValue(yogaStyle.border()[YGEdgeEnd]),
  138. /* .horizontal = */
  139. optionalFloatFromYogaValue(yogaStyle.border()[YGEdgeHorizontal]),
  140. /* .vertical = */
  141. optionalFloatFromYogaValue(yogaStyle.border()[YGEdgeVertical]),
  142. /* .all = */ optionalFloatFromYogaValue(yogaStyle.border()[YGEdgeAll]),
  143. };
  144. return {
  145. /* .borderColors = */ borderColors.resolve(isRTL, {}),
  146. /* .borderWidths = */ borderWidths.resolve(isRTL, 0),
  147. /* .borderRadii = */
  148. ensureNoOverlap(borderRadii.resolve(isRTL, 0), layoutMetrics.frame.size),
  149. /* .borderStyles = */ borderStyles.resolve(isRTL, BorderStyle::Solid),
  150. };
  151. }
  152. bool ViewProps::getClipsContentToBounds() const {
  153. return yogaStyle.overflow() != YGOverflowVisible;
  154. }
  155. #ifdef ANDROID
  156. bool ViewProps::getProbablyMoreHorizontalThanVertical_DEPRECATED() const {
  157. return yogaStyle.flexDirection() == YGFlexDirectionRow;
  158. }
  159. #endif
  160. #pragma mark - DebugStringConvertible
  161. #if RN_DEBUG_STRING_CONVERTIBLE
  162. SharedDebugStringConvertibleList ViewProps::getDebugProps() const {
  163. const auto &defaultViewProps = ViewProps();
  164. return AccessibilityProps::getDebugProps() +
  165. YogaStylableProps::getDebugProps() +
  166. SharedDebugStringConvertibleList{
  167. debugStringConvertibleItem("zIndex", zIndex, defaultViewProps.zIndex),
  168. debugStringConvertibleItem(
  169. "opacity", opacity, defaultViewProps.opacity),
  170. debugStringConvertibleItem(
  171. "foregroundColor",
  172. foregroundColor,
  173. defaultViewProps.foregroundColor),
  174. debugStringConvertibleItem(
  175. "backgroundColor",
  176. backgroundColor,
  177. defaultViewProps.backgroundColor),
  178. };
  179. }
  180. #endif
  181. } // namespace react
  182. } // namespace facebook