YGNodePrint.cpp 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231
  1. /*
  2. * Copyright (c) 2017-present, Facebook, Inc.
  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 "YGNodePrint.h"
  8. #include <stdarg.h>
  9. #include "YGEnums.h"
  10. #include "YGNode.h"
  11. #include "Yoga-internal.h"
  12. namespace facebook {
  13. namespace yoga {
  14. typedef std::string string;
  15. static void indent(string* base, uint32_t level) {
  16. for (uint32_t i = 0; i < level; ++i) {
  17. base->append(" ");
  18. }
  19. }
  20. static bool areFourValuesEqual(const std::array<YGValue, YGEdgeCount>& four) {
  21. return YGValueEqual(four[0], four[1]) && YGValueEqual(four[0], four[2]) &&
  22. YGValueEqual(four[0], four[3]);
  23. }
  24. static void appendFormatedString(string* str, const char* fmt, ...) {
  25. va_list args;
  26. va_start(args, fmt);
  27. va_list argsCopy;
  28. va_copy(argsCopy, args);
  29. std::vector<char> buf(1 + vsnprintf(NULL, 0, fmt, args));
  30. va_end(args);
  31. vsnprintf(buf.data(), buf.size(), fmt, argsCopy);
  32. va_end(argsCopy);
  33. string result = string(buf.begin(), buf.end() - 1);
  34. str->append(result);
  35. }
  36. static void appendFloatOptionalIfDefined(
  37. string* base,
  38. const string key,
  39. const YGFloatOptional num) {
  40. if (!num.isUndefined()) {
  41. appendFormatedString(base, "%s: %g; ", key.c_str(), num.getValue());
  42. }
  43. }
  44. static void appendNumberIfNotUndefined(
  45. string* base,
  46. const string key,
  47. const YGValue number) {
  48. if (number.unit != YGUnitUndefined) {
  49. if (number.unit == YGUnitAuto) {
  50. base->append(key + ": auto; ");
  51. } else {
  52. string unit = number.unit == YGUnitPoint ? "px" : "%%";
  53. appendFormatedString(
  54. base, "%s: %g%s; ", key.c_str(), number.value, unit.c_str());
  55. }
  56. }
  57. }
  58. static void
  59. appendNumberIfNotAuto(string* base, const string& key, const YGValue number) {
  60. if (number.unit != YGUnitAuto) {
  61. appendNumberIfNotUndefined(base, key, number);
  62. }
  63. }
  64. static void
  65. appendNumberIfNotZero(string* base, const string& str, const YGValue number) {
  66. if (number.unit == YGUnitAuto) {
  67. base->append(str + ": auto; ");
  68. } else if (!YGFloatsEqual(number.value, 0)) {
  69. appendNumberIfNotUndefined(base, str, number);
  70. }
  71. }
  72. static void appendEdges(
  73. string* base,
  74. const string& key,
  75. const std::array<YGValue, YGEdgeCount>& edges) {
  76. if (areFourValuesEqual(edges)) {
  77. appendNumberIfNotZero(base, key, edges[YGEdgeLeft]);
  78. } else {
  79. for (int edge = YGEdgeLeft; edge != YGEdgeAll; ++edge) {
  80. string str = key + "-" + YGEdgeToString(static_cast<YGEdge>(edge));
  81. appendNumberIfNotZero(base, str, edges[edge]);
  82. }
  83. }
  84. }
  85. static void appendEdgeIfNotUndefined(
  86. string* base,
  87. const string& str,
  88. const std::array<YGValue, YGEdgeCount>& edges,
  89. const YGEdge edge) {
  90. appendNumberIfNotUndefined(
  91. base, str, *YGComputedEdgeValue(edges, edge, &YGValueUndefined));
  92. }
  93. void YGNodeToString(
  94. std::string* str,
  95. YGNodeRef node,
  96. YGPrintOptions options,
  97. uint32_t level) {
  98. indent(str, level);
  99. appendFormatedString(str, "<div ");
  100. if (node->getPrintFunc() != nullptr) {
  101. node->getPrintFunc()(node);
  102. }
  103. if (options & YGPrintOptionsLayout) {
  104. appendFormatedString(str, "layout=\"");
  105. appendFormatedString(
  106. str, "width: %g; ", node->getLayout().dimensions[YGDimensionWidth]);
  107. appendFormatedString(
  108. str, "height: %g; ", node->getLayout().dimensions[YGDimensionHeight]);
  109. appendFormatedString(
  110. str, "top: %g; ", node->getLayout().position[YGEdgeTop]);
  111. appendFormatedString(
  112. str, "left: %g;", node->getLayout().position[YGEdgeLeft]);
  113. appendFormatedString(str, "\" ");
  114. }
  115. if (options & YGPrintOptionsStyle) {
  116. appendFormatedString(str, "style=\"");
  117. if (node->getStyle().flexDirection != YGNode().getStyle().flexDirection) {
  118. appendFormatedString(
  119. str,
  120. "flex-direction: %s; ",
  121. YGFlexDirectionToString(node->getStyle().flexDirection));
  122. }
  123. if (node->getStyle().justifyContent != YGNode().getStyle().justifyContent) {
  124. appendFormatedString(
  125. str,
  126. "justify-content: %s; ",
  127. YGJustifyToString(node->getStyle().justifyContent));
  128. }
  129. if (node->getStyle().alignItems != YGNode().getStyle().alignItems) {
  130. appendFormatedString(
  131. str,
  132. "align-items: %s; ",
  133. YGAlignToString(node->getStyle().alignItems));
  134. }
  135. if (node->getStyle().alignContent != YGNode().getStyle().alignContent) {
  136. appendFormatedString(
  137. str,
  138. "align-content: %s; ",
  139. YGAlignToString(node->getStyle().alignContent));
  140. }
  141. if (node->getStyle().alignSelf != YGNode().getStyle().alignSelf) {
  142. appendFormatedString(
  143. str, "align-self: %s; ", YGAlignToString(node->getStyle().alignSelf));
  144. }
  145. appendFloatOptionalIfDefined(str, "flex-grow", node->getStyle().flexGrow);
  146. appendFloatOptionalIfDefined(
  147. str, "flex-shrink", node->getStyle().flexShrink);
  148. appendNumberIfNotAuto(str, "flex-basis", node->getStyle().flexBasis);
  149. appendFloatOptionalIfDefined(str, "flex", node->getStyle().flex);
  150. if (node->getStyle().flexWrap != YGNode().getStyle().flexWrap) {
  151. appendFormatedString(
  152. str, "flexWrap: %s; ", YGWrapToString(node->getStyle().flexWrap));
  153. }
  154. if (node->getStyle().overflow != YGNode().getStyle().overflow) {
  155. appendFormatedString(
  156. str, "overflow: %s; ", YGOverflowToString(node->getStyle().overflow));
  157. }
  158. if (node->getStyle().display != YGNode().getStyle().display) {
  159. appendFormatedString(
  160. str, "display: %s; ", YGDisplayToString(node->getStyle().display));
  161. }
  162. appendEdges(str, "margin", node->getStyle().margin);
  163. appendEdges(str, "padding", node->getStyle().padding);
  164. appendEdges(str, "border", node->getStyle().border);
  165. appendNumberIfNotAuto(
  166. str, "width", node->getStyle().dimensions[YGDimensionWidth]);
  167. appendNumberIfNotAuto(
  168. str, "height", node->getStyle().dimensions[YGDimensionHeight]);
  169. appendNumberIfNotAuto(
  170. str, "max-width", node->getStyle().maxDimensions[YGDimensionWidth]);
  171. appendNumberIfNotAuto(
  172. str, "max-height", node->getStyle().maxDimensions[YGDimensionHeight]);
  173. appendNumberIfNotAuto(
  174. str, "min-width", node->getStyle().minDimensions[YGDimensionWidth]);
  175. appendNumberIfNotAuto(
  176. str, "min-height", node->getStyle().minDimensions[YGDimensionHeight]);
  177. if (node->getStyle().positionType != YGNode().getStyle().positionType) {
  178. appendFormatedString(
  179. str,
  180. "position: %s; ",
  181. YGPositionTypeToString(node->getStyle().positionType));
  182. }
  183. appendEdgeIfNotUndefined(
  184. str, "left", node->getStyle().position, YGEdgeLeft);
  185. appendEdgeIfNotUndefined(
  186. str, "right", node->getStyle().position, YGEdgeRight);
  187. appendEdgeIfNotUndefined(str, "top", node->getStyle().position, YGEdgeTop);
  188. appendEdgeIfNotUndefined(
  189. str, "bottom", node->getStyle().position, YGEdgeBottom);
  190. appendFormatedString(str, "\" ");
  191. if (node->getMeasure() != nullptr) {
  192. appendFormatedString(str, "has-custom-measure=\"true\"");
  193. }
  194. }
  195. appendFormatedString(str, ">");
  196. const uint32_t childCount = static_cast<uint32_t>(node->getChildren().size());
  197. if (options & YGPrintOptionsChildren && childCount > 0) {
  198. for (uint32_t i = 0; i < childCount; i++) {
  199. appendFormatedString(str, "\n");
  200. YGNodeToString(str, YGNodeGetChild(node, i), options, level + 1);
  201. }
  202. appendFormatedString(str, "\n");
  203. indent(str, level);
  204. }
  205. appendFormatedString(str, "</div>");
  206. }
  207. } // namespace yoga
  208. } // namespace facebook