YGNodePrint.cpp 7.4 KB

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