packages feed

yoga 0.0.0.2 → 0.0.0.3

raw patch · 21 files changed

+7015/−4726 lines, 21 files

Files

lib/Yoga.hs view
@@ -476,8 +476,8 @@   (result, y, cs) <- renderNodeWithChildren parentInfo x children ptr f   return $ (result, Container y cs) foldRenderTree parentInfo (Leaf x) ptr f = do-  (result, y, []) <- renderNodeWithChildren parentInfo x [] ptr f-  return $ (result, Leaf y)+  (result, y, cs) <- renderNodeWithChildren parentInfo x [] ptr f+  return $ cs `seq` (result, Leaf y)  -- | Renders a layout with the user-supplied function. For each return value -- of type '(b, c)', we append the first result to the output of the previous
yoga.cabal view
@@ -2,7 +2,7 @@ -- see http://haskell.org/cabal/users-guide/  name:                yoga-version:             0.0.0.2+version:             0.0.0.3 synopsis:            Bindings to Facebook's Yoga layout library description:         The <https://facebook.github.com/yoga Yoga> library from                      <https://facebook.github.com/ Facebook> is a fast layout engine@@ -50,11 +50,23 @@                     YGNodePrint.h                     Yoga.h                     Yoga-internal.h+                    YGConfig.h+                    YGFloatOptional.h+                    YGLayout.h+                    YGNode.h+                    Utils.h+   c-sources:        yoga/YGNodePrint.cpp                     yoga/Yoga.cpp                     yoga/YGEnums.cpp+                    yoga/YGConfig.cpp+                    yoga/YGFloatOptional.cpp+                    yoga/YGLayout.cpp+                    yoga/YGNode.cpp+                    yoga/YGStyle.cpp+                    yoga/Utils.cpp -  cc-options:       -Dnullptr=NULL+  cc-options:       -Dnullptr=0   extra-libraries:  stdc++    exposed-modules:
+ yoga/Utils.cpp view
@@ -0,0 +1,70 @@+/*+ *  Copyright (c) Facebook, Inc. and its affiliates.+ *+ *  This source code is licensed under the MIT license found in the LICENSE+ *  file in the root directory of this source tree.+ *+ */+#include "Utils.h"++using namespace facebook;++YGFlexDirection YGFlexDirectionCross(+    const YGFlexDirection flexDirection,+    const YGDirection direction) {+  return YGFlexDirectionIsColumn(flexDirection)+      ? YGResolveFlexDirection(YGFlexDirectionRow, direction)+      : YGFlexDirectionColumn;+}++float YGFloatMax(const float a, const float b) {+  if (!yoga::isUndefined(a) && !yoga::isUndefined(b)) {+    return fmaxf(a, b);+  }+  return yoga::isUndefined(a) ? b : a;+}++float YGFloatMin(const float a, const float b) {+  if (!yoga::isUndefined(a) && !yoga::isUndefined(b)) {+    return fminf(a, b);+  }++  return yoga::isUndefined(a) ? b : a;+}++bool YGValueEqual(const YGValue a, const YGValue b) {+  if (a.unit != b.unit) {+    return false;+  }++  if (a.unit == YGUnitUndefined ||+      (yoga::isUndefined(a.value) && yoga::isUndefined(b.value))) {+    return true;+  }++  return fabs(a.value - b.value) < 0.0001f;+}++bool YGFloatsEqual(const float a, const float b) {+  if (!yoga::isUndefined(a) && !yoga::isUndefined(b)) {+    return fabs(a - b) < 0.0001f;+  }+  return yoga::isUndefined(a) && yoga::isUndefined(b);+}++float YGFloatSanitize(const float& val) {+  return yoga::isUndefined(val) ? 0 : val;+}++float YGUnwrapFloatOptional(const YGFloatOptional& op) {+  return op.isUndefined() ? YGUndefined : op.getValue();+}++YGFloatOptional YGFloatOptionalMax(+    const YGFloatOptional& op1,+    const YGFloatOptional& op2) {+  if (!op1.isUndefined() && !op2.isUndefined()) {+    return op1.getValue() > op2.getValue() ? op1 : op2;+  }+  return op1.isUndefined() ? op2 : op1;+}
+ yoga/Utils.h view
@@ -0,0 +1,148 @@+/**+ * Copyright (c) Facebook, Inc. and its affiliates.+ *+ * This source code is licensed under the MIT license found in the+ * LICENSE file in the root directory of this source tree.+ */++#pragma once+#include "YGNode.h"+#include "Yoga-internal.h"++// This struct is an helper model to hold the data for step 4 of flexbox+// algo, which is collecting the flex items in a line.+//+// - itemsOnLine: Number of items which can fit in a line considering the+// available Inner dimension, the flex items computed flexbasis and their+// margin. It may be different than the difference between start and end+// indicates because we skip over absolute-positioned items.+//+// - sizeConsumedOnCurrentLine: It is accumulation of the dimensions and margin+// of all the children on the current line. This will be used in order to either+// set the dimensions of the node if none already exist or to compute the+// remaining space left for the flexible children.+//+// - totalFlexGrowFactors: total flex grow factors of flex items which are to be+// layed in the current line+//+// - totalFlexShrinkFactors: total flex shrink factors of flex items which are+// to be layed in the current line+//+// - endOfLineIndex: Its the end index of the last flex item which was examined+// and it may or may not be part of the current line(as it may be absolutely+// positioned or inculding it may have caused to overshoot availableInnerDim)+//+// - relativeChildren: Maintain a vector of the child nodes that can shrink+// and/or grow.++struct YGCollectFlexItemsRowValues {+  uint32_t itemsOnLine;+  float sizeConsumedOnCurrentLine;+  float totalFlexGrowFactors;+  float totalFlexShrinkScaledFactors;+  uint32_t endOfLineIndex;+  std::vector<YGNodeRef> relativeChildren;+  float remainingFreeSpace;+  // The size of the mainDim for the row after considering size, padding, margin+  // and border of flex items. This is used to calculate maxLineDim after going+  // through all the rows to decide on the main axis size of owner.+  float mainDim;+  // The size of the crossDim for the row after considering size, padding,+  // margin and border of flex items. Used for calculating containers crossSize.+  float crossDim;+};++bool YGValueEqual(const YGValue a, const YGValue b);++// This custom float equality function returns true if either absolute+// difference between two floats is less than 0.0001f or both are undefined.+bool YGFloatsEqual(const float a, const float b);++// We need custom max function, since we want that, if one argument is+// YGUndefined then the max funtion should return the other argument as the max+// value. We wouldn't have needed a custom max function if YGUndefined was NAN+// as fmax has the same behaviour, but with NAN we cannot use `-ffast-math`+// compiler flag.+float YGFloatMax(const float a, const float b);++YGFloatOptional YGFloatOptionalMax(+    const YGFloatOptional& op1,+    const YGFloatOptional& op2);++// We need custom min function, since we want that, if one argument is+// YGUndefined then the min funtion should return the other argument as the min+// value. We wouldn't have needed a custom min function if YGUndefined was NAN+// as fmin has the same behaviour, but with NAN we cannot use `-ffast-math`+// compiler flag.+float YGFloatMin(const float a, const float b);++// This custom float comparision function compares the array of float with+// YGFloatsEqual, as the default float comparision operator will not work(Look+// at the comments of YGFloatsEqual function).+template <std::size_t size>+bool YGFloatArrayEqual(+    const std::array<float, size>& val1,+    const std::array<float, size>& val2) {+  bool areEqual = true;+  for (std::size_t i = 0; i < size && areEqual; ++i) {+    areEqual = YGFloatsEqual(val1[i], val2[i]);+  }+  return areEqual;+}++// This function returns 0 if YGFloatIsUndefined(val) is true and val otherwise+float YGFloatSanitize(const float& val);++// This function unwraps optional and returns YGUndefined if not defined or+// op.value otherwise+// TODO: Get rid off this function+float YGUnwrapFloatOptional(const YGFloatOptional& op);++YGFlexDirection YGFlexDirectionCross(+    const YGFlexDirection flexDirection,+    const YGDirection direction);++inline bool YGFlexDirectionIsRow(const YGFlexDirection flexDirection) {+  return flexDirection == YGFlexDirectionRow ||+      flexDirection == YGFlexDirectionRowReverse;+}++inline YGFloatOptional YGResolveValue(const YGValue value, const float ownerSize) {+  switch (value.unit) {+    case YGUnitUndefined:+    case YGUnitAuto:+      return YGFloatOptional();+    case YGUnitPoint:+      return YGFloatOptional(value.value);+    case YGUnitPercent:+      return YGFloatOptional(+          static_cast<float>(value.value * ownerSize * 0.01));+  }+  return YGFloatOptional();+}++inline bool YGFlexDirectionIsColumn(const YGFlexDirection flexDirection) {+  return flexDirection == YGFlexDirectionColumn ||+      flexDirection == YGFlexDirectionColumnReverse;+}++inline YGFlexDirection YGResolveFlexDirection(+    const YGFlexDirection flexDirection,+    const YGDirection direction) {+  if (direction == YGDirectionRTL) {+    if (flexDirection == YGFlexDirectionRow) {+      return YGFlexDirectionRowReverse;+    } else if (flexDirection == YGFlexDirectionRowReverse) {+      return YGFlexDirectionRow;+    }+  }++  return flexDirection;+}++static inline YGFloatOptional YGResolveValueMargin(+    const YGValue value,+    const float ownerSize) {+  return value.unit == YGUnitAuto ? YGFloatOptional(0)+                                  : YGResolveValue(value, ownerSize);+}
+ yoga/YGConfig.cpp view
@@ -0,0 +1,22 @@+/*+ *  Copyright (c) Facebook, Inc. and its affiliates.+ *+ *  This source code is licensed under the MIT license found in the LICENSE+ *  file in the root directory of this source tree.+ *+ */+#include "YGConfig.h"++const std::array<bool, YGExperimentalFeatureCount>+    kYGDefaultExperimentalFeatures = {{false}};++YGConfig::YGConfig(YGLogger logger)+    : experimentalFeatures(kYGDefaultExperimentalFeatures),+      useWebDefaults(false),+      useLegacyStretchBehaviour(false),+      shouldDiffLayoutWithoutLegacyStretchBehaviour(false),+      pointScaleFactor(1.0f),+      logger(logger),+      cloneNodeCallback(nullptr),+      context(nullptr),+      printTree(false) {}
+ yoga/YGConfig.h view
@@ -0,0 +1,24 @@+/*+ *  Copyright (c) Facebook, Inc. and its affiliates.+ *+ *  This source code is licensed under the MIT license found in the LICENSE+ *  file in the root directory of this source tree.+ *+ */+#pragma once+#include "Yoga-internal.h"+#include "Yoga.h"++struct YGConfig {+  std::array<bool, YGExperimentalFeatureCount> experimentalFeatures;+  bool useWebDefaults;+  bool useLegacyStretchBehaviour;+  bool shouldDiffLayoutWithoutLegacyStretchBehaviour;+  float pointScaleFactor;+  YGLogger logger;+  YGCloneNodeFunc cloneNodeCallback;+  void* context;+  bool printTree;++  YGConfig(YGLogger logger);+};
yoga/YGEnums.cpp view
@@ -1,228 +1,226 @@-/**
- * Copyright (c) 2014-present, Facebook, Inc.
- * All rights reserved.
- *
- * This source code is licensed under the BSD-style license found in the
- * LICENSE file in the root directory of this source tree. An additional grant
- * of patent rights can be found in the PATENTS file in the same directory.
- */
-
-#include "YGEnums.h"
-
-const char *YGAlignToString(const YGAlign value){
-  switch(value){
-    case YGAlignAuto:
-      return "auto";
-    case YGAlignFlexStart:
-      return "flex-start";
-    case YGAlignCenter:
-      return "center";
-    case YGAlignFlexEnd:
-      return "flex-end";
-    case YGAlignStretch:
-      return "stretch";
-    case YGAlignBaseline:
-      return "baseline";
-    case YGAlignSpaceBetween:
-      return "space-between";
-    case YGAlignSpaceAround:
-      return "space-around";
-  }
-  return "unknown";
-}
-
-const char *YGDimensionToString(const YGDimension value){
-  switch(value){
-    case YGDimensionWidth:
-      return "width";
-    case YGDimensionHeight:
-      return "height";
-  }
-  return "unknown";
-}
-
-const char *YGDirectionToString(const YGDirection value){
-  switch(value){
-    case YGDirectionInherit:
-      return "inherit";
-    case YGDirectionLTR:
-      return "ltr";
-    case YGDirectionRTL:
-      return "rtl";
-  }
-  return "unknown";
-}
-
-const char *YGDisplayToString(const YGDisplay value){
-  switch(value){
-    case YGDisplayFlex:
-      return "flex";
-    case YGDisplayNone:
-      return "none";
-  }
-  return "unknown";
-}
-
-const char *YGEdgeToString(const YGEdge value){
-  switch(value){
-    case YGEdgeLeft:
-      return "left";
-    case YGEdgeTop:
-      return "top";
-    case YGEdgeRight:
-      return "right";
-    case YGEdgeBottom:
-      return "bottom";
-    case YGEdgeStart:
-      return "start";
-    case YGEdgeEnd:
-      return "end";
-    case YGEdgeHorizontal:
-      return "horizontal";
-    case YGEdgeVertical:
-      return "vertical";
-    case YGEdgeAll:
-      return "all";
-  }
-  return "unknown";
-}
-
-const char *YGExperimentalFeatureToString(const YGExperimentalFeature value){
-  switch(value){
-    case YGExperimentalFeatureWebFlexBasis:
-      return "web-flex-basis";
-  }
-  return "unknown";
-}
-
-const char *YGFlexDirectionToString(const YGFlexDirection value){
-  switch(value){
-    case YGFlexDirectionColumn:
-      return "column";
-    case YGFlexDirectionColumnReverse:
-      return "column-reverse";
-    case YGFlexDirectionRow:
-      return "row";
-    case YGFlexDirectionRowReverse:
-      return "row-reverse";
-  }
-  return "unknown";
-}
-
-const char *YGJustifyToString(const YGJustify value){
-  switch(value){
-    case YGJustifyFlexStart:
-      return "flex-start";
-    case YGJustifyCenter:
-      return "center";
-    case YGJustifyFlexEnd:
-      return "flex-end";
-    case YGJustifySpaceBetween:
-      return "space-between";
-    case YGJustifySpaceAround:
-      return "space-around";
-    case YGJustifySpaceEvenly:
-      return "space-evenly";
-  }
-  return "unknown";
-}
-
-const char *YGLogLevelToString(const YGLogLevel value){
-  switch(value){
-    case YGLogLevelError:
-      return "error";
-    case YGLogLevelWarn:
-      return "warn";
-    case YGLogLevelInfo:
-      return "info";
-    case YGLogLevelDebug:
-      return "debug";
-    case YGLogLevelVerbose:
-      return "verbose";
-    case YGLogLevelFatal:
-      return "fatal";
-  }
-  return "unknown";
-}
-
-const char *YGMeasureModeToString(const YGMeasureMode value){
-  switch(value){
-    case YGMeasureModeUndefined:
-      return "undefined";
-    case YGMeasureModeExactly:
-      return "exactly";
-    case YGMeasureModeAtMost:
-      return "at-most";
-  }
-  return "unknown";
-}
-
-const char *YGNodeTypeToString(const YGNodeType value){
-  switch(value){
-    case YGNodeTypeDefault:
-      return "default";
-    case YGNodeTypeText:
-      return "text";
-  }
-  return "unknown";
-}
-
-const char *YGOverflowToString(const YGOverflow value){
-  switch(value){
-    case YGOverflowVisible:
-      return "visible";
-    case YGOverflowHidden:
-      return "hidden";
-    case YGOverflowScroll:
-      return "scroll";
-  }
-  return "unknown";
-}
-
-const char *YGPositionTypeToString(const YGPositionType value){
-  switch(value){
-    case YGPositionTypeRelative:
-      return "relative";
-    case YGPositionTypeAbsolute:
-      return "absolute";
-  }
-  return "unknown";
-}
-
-const char *YGPrintOptionsToString(const YGPrintOptions value){
-  switch(value){
-    case YGPrintOptionsLayout:
-      return "layout";
-    case YGPrintOptionsStyle:
-      return "style";
-    case YGPrintOptionsChildren:
-      return "children";
-  }
-  return "unknown";
-}
-
-const char *YGUnitToString(const YGUnit value){
-  switch(value){
-    case YGUnitUndefined:
-      return "undefined";
-    case YGUnitPoint:
-      return "point";
-    case YGUnitPercent:
-      return "percent";
-    case YGUnitAuto:
-      return "auto";
-  }
-  return "unknown";
-}
-
-const char *YGWrapToString(const YGWrap value){
-  switch(value){
-    case YGWrapNoWrap:
-      return "no-wrap";
-    case YGWrapWrap:
-      return "wrap";
-    case YGWrapWrapReverse:
-      return "wrap-reverse";
-  }
-  return "unknown";
-}
+/**+ * Copyright (c) Facebook, Inc. and its affiliates.+ *+ * This source code is licensed under the MIT license found in the+ * LICENSE file in the root directory of this source tree.+ */++#include "YGEnums.h"++const char *YGAlignToString(const YGAlign value){+  switch(value){+    case YGAlignAuto:+      return "auto";+    case YGAlignFlexStart:+      return "flex-start";+    case YGAlignCenter:+      return "center";+    case YGAlignFlexEnd:+      return "flex-end";+    case YGAlignStretch:+      return "stretch";+    case YGAlignBaseline:+      return "baseline";+    case YGAlignSpaceBetween:+      return "space-between";+    case YGAlignSpaceAround:+      return "space-around";+  }+  return "unknown";+}++const char *YGDimensionToString(const YGDimension value){+  switch(value){+    case YGDimensionWidth:+      return "width";+    case YGDimensionHeight:+      return "height";+  }+  return "unknown";+}++const char *YGDirectionToString(const YGDirection value){+  switch(value){+    case YGDirectionInherit:+      return "inherit";+    case YGDirectionLTR:+      return "ltr";+    case YGDirectionRTL:+      return "rtl";+  }+  return "unknown";+}++const char *YGDisplayToString(const YGDisplay value){+  switch(value){+    case YGDisplayFlex:+      return "flex";+    case YGDisplayNone:+      return "none";+  }+  return "unknown";+}++const char *YGEdgeToString(const YGEdge value){+  switch(value){+    case YGEdgeLeft:+      return "left";+    case YGEdgeTop:+      return "top";+    case YGEdgeRight:+      return "right";+    case YGEdgeBottom:+      return "bottom";+    case YGEdgeStart:+      return "start";+    case YGEdgeEnd:+      return "end";+    case YGEdgeHorizontal:+      return "horizontal";+    case YGEdgeVertical:+      return "vertical";+    case YGEdgeAll:+      return "all";+  }+  return "unknown";+}++const char *YGExperimentalFeatureToString(const YGExperimentalFeature value){+  switch(value){+    case YGExperimentalFeatureWebFlexBasis:+      return "web-flex-basis";+  }+  return "unknown";+}++const char *YGFlexDirectionToString(const YGFlexDirection value){+  switch(value){+    case YGFlexDirectionColumn:+      return "column";+    case YGFlexDirectionColumnReverse:+      return "column-reverse";+    case YGFlexDirectionRow:+      return "row";+    case YGFlexDirectionRowReverse:+      return "row-reverse";+  }+  return "unknown";+}++const char *YGJustifyToString(const YGJustify value){+  switch(value){+    case YGJustifyFlexStart:+      return "flex-start";+    case YGJustifyCenter:+      return "center";+    case YGJustifyFlexEnd:+      return "flex-end";+    case YGJustifySpaceBetween:+      return "space-between";+    case YGJustifySpaceAround:+      return "space-around";+    case YGJustifySpaceEvenly:+      return "space-evenly";+  }+  return "unknown";+}++const char *YGLogLevelToString(const YGLogLevel value){+  switch(value){+    case YGLogLevelError:+      return "error";+    case YGLogLevelWarn:+      return "warn";+    case YGLogLevelInfo:+      return "info";+    case YGLogLevelDebug:+      return "debug";+    case YGLogLevelVerbose:+      return "verbose";+    case YGLogLevelFatal:+      return "fatal";+  }+  return "unknown";+}++const char *YGMeasureModeToString(const YGMeasureMode value){+  switch(value){+    case YGMeasureModeUndefined:+      return "undefined";+    case YGMeasureModeExactly:+      return "exactly";+    case YGMeasureModeAtMost:+      return "at-most";+  }+  return "unknown";+}++const char *YGNodeTypeToString(const YGNodeType value){+  switch(value){+    case YGNodeTypeDefault:+      return "default";+    case YGNodeTypeText:+      return "text";+  }+  return "unknown";+}++const char *YGOverflowToString(const YGOverflow value){+  switch(value){+    case YGOverflowVisible:+      return "visible";+    case YGOverflowHidden:+      return "hidden";+    case YGOverflowScroll:+      return "scroll";+  }+  return "unknown";+}++const char *YGPositionTypeToString(const YGPositionType value){+  switch(value){+    case YGPositionTypeRelative:+      return "relative";+    case YGPositionTypeAbsolute:+      return "absolute";+  }+  return "unknown";+}++const char *YGPrintOptionsToString(const YGPrintOptions value){+  switch(value){+    case YGPrintOptionsLayout:+      return "layout";+    case YGPrintOptionsStyle:+      return "style";+    case YGPrintOptionsChildren:+      return "children";+  }+  return "unknown";+}++const char *YGUnitToString(const YGUnit value){+  switch(value){+    case YGUnitUndefined:+      return "undefined";+    case YGUnitPoint:+      return "point";+    case YGUnitPercent:+      return "percent";+    case YGUnitAuto:+      return "auto";+  }+  return "unknown";+}++const char *YGWrapToString(const YGWrap value){+  switch(value){+    case YGWrapNoWrap:+      return "no-wrap";+    case YGWrapWrap:+      return "wrap";+    case YGWrapWrapReverse:+      return "wrap-reverse";+  }+  return "unknown";+}
yoga/YGEnums.h view
@@ -1,157 +1,155 @@-/**
- * Copyright (c) 2014-present, Facebook, Inc.
- * All rights reserved.
- *
- * This source code is licensed under the BSD-style license found in the
- * LICENSE file in the root directory of this source tree. An additional grant
- * of patent rights can be found in the PATENTS file in the same directory.
- */
-
-#pragma once
-
-#include "YGMacros.h"
-
-YG_EXTERN_C_BEGIN
-
-#define YGAlignCount 8
-typedef YG_ENUM_BEGIN(YGAlign) {
-  YGAlignAuto,
-  YGAlignFlexStart,
-  YGAlignCenter,
-  YGAlignFlexEnd,
-  YGAlignStretch,
-  YGAlignBaseline,
-  YGAlignSpaceBetween,
-  YGAlignSpaceAround,
-} YG_ENUM_END(YGAlign);
-WIN_EXPORT const char *YGAlignToString(const YGAlign value);
-
-#define YGDimensionCount 2
-typedef YG_ENUM_BEGIN(YGDimension) {
-  YGDimensionWidth,
-  YGDimensionHeight,
-} YG_ENUM_END(YGDimension);
-WIN_EXPORT const char *YGDimensionToString(const YGDimension value);
-
-#define YGDirectionCount 3
-typedef YG_ENUM_BEGIN(YGDirection) {
-  YGDirectionInherit,
-  YGDirectionLTR,
-  YGDirectionRTL,
-} YG_ENUM_END(YGDirection);
-WIN_EXPORT const char *YGDirectionToString(const YGDirection value);
-
-#define YGDisplayCount 2
-typedef YG_ENUM_BEGIN(YGDisplay) {
-  YGDisplayFlex,
-  YGDisplayNone,
-} YG_ENUM_END(YGDisplay);
-WIN_EXPORT const char *YGDisplayToString(const YGDisplay value);
-
-#define YGEdgeCount 9
-typedef YG_ENUM_BEGIN(YGEdge) {
-  YGEdgeLeft,
-  YGEdgeTop,
-  YGEdgeRight,
-  YGEdgeBottom,
-  YGEdgeStart,
-  YGEdgeEnd,
-  YGEdgeHorizontal,
-  YGEdgeVertical,
-  YGEdgeAll,
-} YG_ENUM_END(YGEdge);
-WIN_EXPORT const char *YGEdgeToString(const YGEdge value);
-
-#define YGExperimentalFeatureCount 1
-typedef YG_ENUM_BEGIN(YGExperimentalFeature) {
-  YGExperimentalFeatureWebFlexBasis,
-} YG_ENUM_END(YGExperimentalFeature);
-WIN_EXPORT const char *YGExperimentalFeatureToString(const YGExperimentalFeature value);
-
-#define YGFlexDirectionCount 4
-typedef YG_ENUM_BEGIN(YGFlexDirection) {
-  YGFlexDirectionColumn,
-  YGFlexDirectionColumnReverse,
-  YGFlexDirectionRow,
-  YGFlexDirectionRowReverse,
-} YG_ENUM_END(YGFlexDirection);
-WIN_EXPORT const char *YGFlexDirectionToString(const YGFlexDirection value);
-
-#define YGJustifyCount 6
-typedef YG_ENUM_BEGIN(YGJustify){
-    YGJustifyFlexStart,
-    YGJustifyCenter,
-    YGJustifyFlexEnd,
-    YGJustifySpaceBetween,
-    YGJustifySpaceAround,
-    YGJustifySpaceEvenly,
-} YG_ENUM_END(YGJustify);
-WIN_EXPORT const char *YGJustifyToString(const YGJustify value);
-
-#define YGLogLevelCount 6
-typedef YG_ENUM_BEGIN(YGLogLevel) {
-  YGLogLevelError,
-  YGLogLevelWarn,
-  YGLogLevelInfo,
-  YGLogLevelDebug,
-  YGLogLevelVerbose,
-  YGLogLevelFatal,
-} YG_ENUM_END(YGLogLevel);
-WIN_EXPORT const char *YGLogLevelToString(const YGLogLevel value);
-
-#define YGMeasureModeCount 3
-typedef YG_ENUM_BEGIN(YGMeasureMode) {
-  YGMeasureModeUndefined,
-  YGMeasureModeExactly,
-  YGMeasureModeAtMost,
-} YG_ENUM_END(YGMeasureMode);
-WIN_EXPORT const char *YGMeasureModeToString(const YGMeasureMode value);
-
-#define YGNodeTypeCount 2
-typedef YG_ENUM_BEGIN(YGNodeType) {
-  YGNodeTypeDefault,
-  YGNodeTypeText,
-} YG_ENUM_END(YGNodeType);
-WIN_EXPORT const char *YGNodeTypeToString(const YGNodeType value);
-
-#define YGOverflowCount 3
-typedef YG_ENUM_BEGIN(YGOverflow) {
-  YGOverflowVisible,
-  YGOverflowHidden,
-  YGOverflowScroll,
-} YG_ENUM_END(YGOverflow);
-WIN_EXPORT const char *YGOverflowToString(const YGOverflow value);
-
-#define YGPositionTypeCount 2
-typedef YG_ENUM_BEGIN(YGPositionType) {
-  YGPositionTypeRelative,
-  YGPositionTypeAbsolute,
-} YG_ENUM_END(YGPositionType);
-WIN_EXPORT const char *YGPositionTypeToString(const YGPositionType value);
-
-#define YGPrintOptionsCount 3
-typedef YG_ENUM_BEGIN(YGPrintOptions) {
-  YGPrintOptionsLayout = 1,
-  YGPrintOptionsStyle = 2,
-  YGPrintOptionsChildren = 4,
-} YG_ENUM_END(YGPrintOptions);
-WIN_EXPORT const char *YGPrintOptionsToString(const YGPrintOptions value);
-
-#define YGUnitCount 4
-typedef YG_ENUM_BEGIN(YGUnit) {
-  YGUnitUndefined,
-  YGUnitPoint,
-  YGUnitPercent,
-  YGUnitAuto,
-} YG_ENUM_END(YGUnit);
-WIN_EXPORT const char *YGUnitToString(const YGUnit value);
-
-#define YGWrapCount 3
-typedef YG_ENUM_BEGIN(YGWrap) {
-  YGWrapNoWrap,
-  YGWrapWrap,
-  YGWrapWrapReverse,
-} YG_ENUM_END(YGWrap);
-WIN_EXPORT const char *YGWrapToString(const YGWrap value);
-
-YG_EXTERN_C_END
+/**+ * Copyright (c) Facebook, Inc. and its affiliates.+ *+ * This source code is licensed under the MIT license found in the+ * LICENSE file in the root directory of this source tree.+ */++#pragma once++#include "YGMacros.h"++YG_EXTERN_C_BEGIN++#define YGAlignCount 8+typedef YG_ENUM_BEGIN(YGAlign) {+  YGAlignAuto,+  YGAlignFlexStart,+  YGAlignCenter,+  YGAlignFlexEnd,+  YGAlignStretch,+  YGAlignBaseline,+  YGAlignSpaceBetween,+  YGAlignSpaceAround,+} YG_ENUM_END(YGAlign);+WIN_EXPORT const char *YGAlignToString(const YGAlign value);++#define YGDimensionCount 2+typedef YG_ENUM_BEGIN(YGDimension) {+  YGDimensionWidth,+  YGDimensionHeight,+} YG_ENUM_END(YGDimension);+WIN_EXPORT const char *YGDimensionToString(const YGDimension value);++#define YGDirectionCount 3+typedef YG_ENUM_BEGIN(YGDirection) {+  YGDirectionInherit,+  YGDirectionLTR,+  YGDirectionRTL,+} YG_ENUM_END(YGDirection);+WIN_EXPORT const char *YGDirectionToString(const YGDirection value);++#define YGDisplayCount 2+typedef YG_ENUM_BEGIN(YGDisplay) {+  YGDisplayFlex,+  YGDisplayNone,+} YG_ENUM_END(YGDisplay);+WIN_EXPORT const char *YGDisplayToString(const YGDisplay value);++#define YGEdgeCount 9+typedef YG_ENUM_BEGIN(YGEdge) {+  YGEdgeLeft,+  YGEdgeTop,+  YGEdgeRight,+  YGEdgeBottom,+  YGEdgeStart,+  YGEdgeEnd,+  YGEdgeHorizontal,+  YGEdgeVertical,+  YGEdgeAll,+} YG_ENUM_END(YGEdge);+WIN_EXPORT const char *YGEdgeToString(const YGEdge value);++#define YGExperimentalFeatureCount 1+typedef YG_ENUM_BEGIN(YGExperimentalFeature) {+  YGExperimentalFeatureWebFlexBasis,+} YG_ENUM_END(YGExperimentalFeature);+WIN_EXPORT const char *YGExperimentalFeatureToString(const YGExperimentalFeature value);++#define YGFlexDirectionCount 4+typedef YG_ENUM_BEGIN(YGFlexDirection) {+  YGFlexDirectionColumn,+  YGFlexDirectionColumnReverse,+  YGFlexDirectionRow,+  YGFlexDirectionRowReverse,+} YG_ENUM_END(YGFlexDirection);+WIN_EXPORT const char *YGFlexDirectionToString(const YGFlexDirection value);++#define YGJustifyCount 6+typedef YG_ENUM_BEGIN(YGJustify){+    YGJustifyFlexStart,+    YGJustifyCenter,+    YGJustifyFlexEnd,+    YGJustifySpaceBetween,+    YGJustifySpaceAround,+    YGJustifySpaceEvenly,+} YG_ENUM_END(YGJustify);+WIN_EXPORT const char *YGJustifyToString(const YGJustify value);++#define YGLogLevelCount 6+typedef YG_ENUM_BEGIN(YGLogLevel) {+  YGLogLevelError,+  YGLogLevelWarn,+  YGLogLevelInfo,+  YGLogLevelDebug,+  YGLogLevelVerbose,+  YGLogLevelFatal,+} YG_ENUM_END(YGLogLevel);+WIN_EXPORT const char *YGLogLevelToString(const YGLogLevel value);++#define YGMeasureModeCount 3+typedef YG_ENUM_BEGIN(YGMeasureMode) {+  YGMeasureModeUndefined,+  YGMeasureModeExactly,+  YGMeasureModeAtMost,+} YG_ENUM_END(YGMeasureMode);+WIN_EXPORT const char *YGMeasureModeToString(const YGMeasureMode value);++#define YGNodeTypeCount 2+typedef YG_ENUM_BEGIN(YGNodeType) {+  YGNodeTypeDefault,+  YGNodeTypeText,+} YG_ENUM_END(YGNodeType);+WIN_EXPORT const char *YGNodeTypeToString(const YGNodeType value);++#define YGOverflowCount 3+typedef YG_ENUM_BEGIN(YGOverflow) {+  YGOverflowVisible,+  YGOverflowHidden,+  YGOverflowScroll,+} YG_ENUM_END(YGOverflow);+WIN_EXPORT const char *YGOverflowToString(const YGOverflow value);++#define YGPositionTypeCount 2+typedef YG_ENUM_BEGIN(YGPositionType) {+  YGPositionTypeRelative,+  YGPositionTypeAbsolute,+} YG_ENUM_END(YGPositionType);+WIN_EXPORT const char *YGPositionTypeToString(const YGPositionType value);++#define YGPrintOptionsCount 3+typedef YG_ENUM_BEGIN(YGPrintOptions) {+  YGPrintOptionsLayout = 1,+  YGPrintOptionsStyle = 2,+  YGPrintOptionsChildren = 4,+} YG_ENUM_END(YGPrintOptions);+WIN_EXPORT const char *YGPrintOptionsToString(const YGPrintOptions value);++#define YGUnitCount 4+typedef YG_ENUM_BEGIN(YGUnit) {+  YGUnitUndefined,+  YGUnitPoint,+  YGUnitPercent,+  YGUnitAuto,+} YG_ENUM_END(YGUnit);+WIN_EXPORT const char *YGUnitToString(const YGUnit value);++#define YGWrapCount 3+typedef YG_ENUM_BEGIN(YGWrap) {+  YGWrapNoWrap,+  YGWrapWrap,+  YGWrapWrapReverse,+} YG_ENUM_END(YGWrap);+WIN_EXPORT const char *YGWrapToString(const YGWrap value);++YG_EXTERN_C_END
+ yoga/YGFloatOptional.cpp view
@@ -0,0 +1,84 @@+/*+ *  Copyright (c) Facebook, Inc. and its affiliates.+ *+ *  This source code is licensed under the MIT license found in the LICENSE+ *  file in the root directory of this source tree.+ *+ */+#include "YGFloatOptional.h"+#include <cstdlib>+#include <iostream>+#include "Yoga.h"+#include "Yoga-internal.h"++using namespace facebook;++YGFloatOptional::YGFloatOptional(float value) {+  if (yoga::isUndefined(value)) {+    isUndefined_ = true;+    value_ = 0;+  } else {+    value_ = value;+    isUndefined_ = false;+  }+}++float YGFloatOptional::getValue() const {+  if (isUndefined_) {+    // Abort, accessing a value of an undefined float optional+    std::cerr << "Tried to get value of an undefined YGFloatOptional\n";+    std::exit(EXIT_FAILURE);+  }+  return value_;+}++bool YGFloatOptional::operator==(const YGFloatOptional& op) const {+  if (isUndefined_ == op.isUndefined()) {+    return isUndefined_ || value_ == op.getValue();+  }+  return false;+}++bool YGFloatOptional::operator!=(const YGFloatOptional& op) const {+  return !(*this == op);+}++bool YGFloatOptional::operator==(float val) const {+  if (yoga::isUndefined(val) == isUndefined_) {+    return isUndefined_ || val == value_;+  }+  return false;+}++bool YGFloatOptional::operator!=(float val) const {+  return !(*this == val);+}++YGFloatOptional YGFloatOptional::operator+(const YGFloatOptional& op) {+  if (!isUndefined_ && !op.isUndefined_) {+    return YGFloatOptional(value_ + op.value_);+  }+  return YGFloatOptional();+}++bool YGFloatOptional::operator>(const YGFloatOptional& op) const {+  if (isUndefined_ || op.isUndefined_) {+    return false;+  }+  return value_ > op.value_;+}++bool YGFloatOptional::operator<(const YGFloatOptional& op) const {+  if (isUndefined_ || op.isUndefined_) {+    return false;+  }+  return value_ < op.value_;+}++bool YGFloatOptional::operator>=(const YGFloatOptional& op) const {+  return *this == op || *this > op;+}++bool YGFloatOptional::operator<=(const YGFloatOptional& op) const {+  return *this == op || *this < op;+}
+ yoga/YGFloatOptional.h view
@@ -0,0 +1,44 @@+/*+ *  Copyright (c) Facebook, Inc. and its affiliates.+ *+ *  This source code is licensed under the MIT license found in the LICENSE+ *  file in the root directory of this source tree.+ *+ */+#pragma once++struct YGFloatOptional {+ private:+  float value_;+  bool isUndefined_;++ public:+  explicit YGFloatOptional(float value);+  explicit YGFloatOptional() : value_(0), isUndefined_(true) {}++  // Program will terminate if the value of an undefined is accessed. Please+  // make sure to check if the optional is defined before calling this function.+  // To check if float optional is defined, use `isUndefined()`.+  float getValue() const;++  // Sets the value of float optional, and thus isUndefined is assigned false.+  void setValue(float val) {+    value_ = val;+    isUndefined_ = false;+  }++  bool isUndefined() const {+    return isUndefined_;+  }++  YGFloatOptional operator+(const YGFloatOptional& op);+  bool operator>(const YGFloatOptional& op) const;+  bool operator<(const YGFloatOptional& op) const;+  bool operator>=(const YGFloatOptional& op) const;+  bool operator<=(const YGFloatOptional& op) const;+  bool operator==(const YGFloatOptional& op) const;+  bool operator!=(const YGFloatOptional& op) const;++  bool operator==(float val) const;+  bool operator!=(float val) const;+};
+ yoga/YGLayout.cpp view
@@ -0,0 +1,63 @@+/*+ *  Copyright (c) Facebook, Inc. and its affiliates.+ *+ *  This source code is licensed under the MIT license found in the LICENSE+ *  file in the root directory of this source tree.+ *+ */+#include "YGLayout.h"+#include "Utils.h"++using namespace facebook;++const std::array<float, 2> kYGDefaultDimensionValues = {+    {YGUndefined, YGUndefined}};++YGLayout::YGLayout()+    : position(),+      dimensions(kYGDefaultDimensionValues),+      margin(),+      border(),+      padding(),+      direction(YGDirectionInherit),+      computedFlexBasisGeneration(0),+      computedFlexBasis(YGFloatOptional()),+      hadOverflow(false),+      generationCount(0),+      lastOwnerDirection((YGDirection)-1),+      nextCachedMeasurementsIndex(0),+      cachedMeasurements(),+      measuredDimensions(kYGDefaultDimensionValues),+      cachedLayout(YGCachedMeasurement()),+      didUseLegacyFlag(false),+      doesLegacyStretchFlagAffectsLayout(false) {}++bool YGLayout::operator==(YGLayout layout) const {+  bool isEqual = YGFloatArrayEqual(position, layout.position) &&+      YGFloatArrayEqual(dimensions, layout.dimensions) &&+      YGFloatArrayEqual(margin, layout.margin) &&+      YGFloatArrayEqual(border, layout.border) &&+      YGFloatArrayEqual(padding, layout.padding) &&+      direction == layout.direction && hadOverflow == layout.hadOverflow &&+      lastOwnerDirection == layout.lastOwnerDirection &&+      nextCachedMeasurementsIndex == layout.nextCachedMeasurementsIndex &&+      cachedLayout == layout.cachedLayout &&+      computedFlexBasis == layout.computedFlexBasis;++  for (uint32_t i = 0; i < YG_MAX_CACHED_RESULT_COUNT && isEqual; ++i) {+    isEqual = isEqual && cachedMeasurements[i] == layout.cachedMeasurements[i];+  }++  if (!yoga::isUndefined(measuredDimensions[0]) ||+      !yoga::isUndefined(layout.measuredDimensions[0])) {+    isEqual =+        isEqual && (measuredDimensions[0] == layout.measuredDimensions[0]);+  }+  if (!yoga::isUndefined(measuredDimensions[1]) ||+      !yoga::isUndefined(layout.measuredDimensions[1])) {+    isEqual =+        isEqual && (measuredDimensions[1] == layout.measuredDimensions[1]);+  }++  return isEqual;+}
+ yoga/YGLayout.h view
@@ -0,0 +1,44 @@+/*+ *  Copyright (c) Facebook, Inc. and its affiliates.+ *+ *  This source code is licensed under the MIT license found in the LICENSE+ *  file in the root directory of this source tree.+ *+ */+#pragma once+#include "YGFloatOptional.h"+#include "Yoga-internal.h"++struct YGLayout {+  std::array<float, 4> position;+  std::array<float, 2> dimensions;+  std::array<float, 6> margin;+  std::array<float, 6> border;+  std::array<float, 6> padding;+  YGDirection direction;++  uint32_t computedFlexBasisGeneration;+  YGFloatOptional computedFlexBasis;+  bool hadOverflow;++  // Instead of recomputing the entire layout every single time, we+  // cache some information to break early when nothing changed+  uint32_t generationCount;+  YGDirection lastOwnerDirection;++  uint32_t nextCachedMeasurementsIndex;+  std::array<YGCachedMeasurement, YG_MAX_CACHED_RESULT_COUNT>+      cachedMeasurements;+  std::array<float, 2> measuredDimensions;++  YGCachedMeasurement cachedLayout;+  bool didUseLegacyFlag;+  bool doesLegacyStretchFlagAffectsLayout;++  YGLayout();++  bool operator==(YGLayout layout) const;+  bool operator!=(YGLayout layout) const {+    return !(*this == layout);+  }+};
yoga/YGMacros.h view
@@ -1,47 +1,41 @@-/**
- * Copyright (c) 2014-present, Facebook, Inc.
- * All rights reserved.
- *
- * This source code is licensed under the BSD-style license found in the
- * LICENSE file in the root directory of this source tree. An additional grant
- * of patent rights can be found in the PATENTS file in the same directory.
- */
-
-#pragma once
-
-#ifdef __cplusplus
-#define YG_EXTERN_C_BEGIN extern "C" {
-#define YG_EXTERN_C_END }
-#else
-#define YG_EXTERN_C_BEGIN
-#define YG_EXTERN_C_END
-#endif
-
-#ifdef _WINDLL
-#define WIN_EXPORT __declspec(dllexport)
-#else
-#define WIN_EXPORT
-#endif
-
-#ifdef WINARMDLL
-#define WIN_STRUCT(type) type *
-#define WIN_STRUCT_REF(value) &value
-#else
-#define WIN_STRUCT(type) type
-#define WIN_STRUCT_REF(value) value
-#endif
-
-#ifndef FB_ASSERTIONS_ENABLED
-#define FB_ASSERTIONS_ENABLED 1
-#endif
-
-#ifdef NS_ENUM
-// Cannot use NSInteger as NSInteger has a different size than int (which is the default type of a
-// enum).
-// Therefor when linking the Yoga C library into obj-c the header is a missmatch for the Yoga ABI.
-#define YG_ENUM_BEGIN(name) NS_ENUM(int, name)
-#define YG_ENUM_END(name)
-#else
-#define YG_ENUM_BEGIN(name) enum name
-#define YG_ENUM_END(name) name
-#endif
+/**+ * Copyright (c) Facebook, Inc. and its affiliates.+ *+ * This source code is licensed under the MIT license found in the+ * LICENSE file in the root directory of this source tree.+ */++#pragma once++#ifdef __cplusplus+#define YG_EXTERN_C_BEGIN extern "C" {+#define YG_EXTERN_C_END }+#else+#define YG_EXTERN_C_BEGIN+#define YG_EXTERN_C_END+#endif++#ifdef _WINDLL+#define WIN_EXPORT __declspec(dllexport)+#else+#define WIN_EXPORT+#endif++#ifdef WINARMDLL+#define WIN_STRUCT(type) type *+#define WIN_STRUCT_REF(value) &value+#else+#define WIN_STRUCT(type) type+#define WIN_STRUCT_REF(value) value+#endif++#ifdef NS_ENUM+// Cannot use NSInteger as NSInteger has a different size than int (which is the default type of a+// enum).+// Therefor when linking the Yoga C library into obj-c the header is a missmatch for the Yoga ABI.+#define YG_ENUM_BEGIN(name) NS_ENUM(int, name)+#define YG_ENUM_END(name)+#else+#define YG_ENUM_BEGIN(name) enum name+#define YG_ENUM_END(name) name+#endif
+ yoga/YGNode.cpp view
@@ -0,0 +1,554 @@+/*+ *  Copyright (c) Facebook, Inc. and its affiliates.+ *+ *  This source code is licensed under the MIT license found in the LICENSE+ *  file in the root directory of this source tree.+ *+ */+#include "YGNode.h"+#include <iostream>+#include "Utils.h"++using namespace facebook;++YGFloatOptional YGNode::getLeadingPosition(+    const YGFlexDirection& axis,+    const float& axisSize) const {+  if (YGFlexDirectionIsRow(axis)) {+    const YGValue* leadingPosition =+        YGComputedEdgeValue(style_.position, YGEdgeStart, &YGValueUndefined);+    if (leadingPosition->unit != YGUnitUndefined) {+      return YGResolveValue(*leadingPosition, axisSize);+    }+  }++  const YGValue* leadingPosition =+      YGComputedEdgeValue(style_.position, leading[axis], &YGValueUndefined);++  return leadingPosition->unit == YGUnitUndefined+      ? YGFloatOptional(0)+      : YGResolveValue(*leadingPosition, axisSize);+}++YGFloatOptional YGNode::getTrailingPosition(+    const YGFlexDirection& axis,+    const float& axisSize) const {+  if (YGFlexDirectionIsRow(axis)) {+    const YGValue* trailingPosition =+        YGComputedEdgeValue(style_.position, YGEdgeEnd, &YGValueUndefined);+    if (trailingPosition->unit != YGUnitUndefined) {+      return YGResolveValue(*trailingPosition, axisSize);+    }+  }++  const YGValue* trailingPosition =+      YGComputedEdgeValue(style_.position, trailing[axis], &YGValueUndefined);++  return trailingPosition->unit == YGUnitUndefined+      ? YGFloatOptional(0)+      : YGResolveValue(*trailingPosition, axisSize);+}++bool YGNode::isLeadingPositionDefined(const YGFlexDirection& axis) const {+  return (YGFlexDirectionIsRow(axis) &&+          YGComputedEdgeValue(style_.position, YGEdgeStart, &YGValueUndefined)+                  ->unit != YGUnitUndefined) ||+      YGComputedEdgeValue(style_.position, leading[axis], &YGValueUndefined)+          ->unit != YGUnitUndefined;+}++bool YGNode::isTrailingPosDefined(const YGFlexDirection& axis) const {+  return (YGFlexDirectionIsRow(axis) &&+          YGComputedEdgeValue(style_.position, YGEdgeEnd, &YGValueUndefined)+                  ->unit != YGUnitUndefined) ||+      YGComputedEdgeValue(style_.position, trailing[axis], &YGValueUndefined)+          ->unit != YGUnitUndefined;+}++YGFloatOptional YGNode::getLeadingMargin(+    const YGFlexDirection& axis,+    const float& widthSize) const {+  if (YGFlexDirectionIsRow(axis) &&+      style_.margin[YGEdgeStart].unit != YGUnitUndefined) {+    return YGResolveValueMargin(style_.margin[YGEdgeStart], widthSize);+  }++  return YGResolveValueMargin(+      *YGComputedEdgeValue(style_.margin, leading[axis], &YGValueZero),+      widthSize);+}++YGFloatOptional YGNode::getTrailingMargin(+    const YGFlexDirection& axis,+    const float& widthSize) const {+  if (YGFlexDirectionIsRow(axis) &&+      style_.margin[YGEdgeEnd].unit != YGUnitUndefined) {+    return YGResolveValueMargin(style_.margin[YGEdgeEnd], widthSize);+  }++  return YGResolveValueMargin(+      *YGComputedEdgeValue(style_.margin, trailing[axis], &YGValueZero),+      widthSize);+}++YGFloatOptional YGNode::getMarginForAxis(+    const YGFlexDirection& axis,+    const float& widthSize) const {+  return getLeadingMargin(axis, widthSize) + getTrailingMargin(axis, widthSize);+}++// Setters++void YGNode::setMeasureFunc(YGMeasureFunc measureFunc) {+  if (measureFunc == nullptr) {+    measure_ = nullptr;+    // TODO: t18095186 Move nodeType to opt-in function and mark appropriate+    // places in Litho+    nodeType_ = YGNodeTypeDefault;+  } else {+    YGAssertWithNode(+        this,+        children_.size() == 0,+        "Cannot set measure function: Nodes with measure functions cannot have children.");+    measure_ = measureFunc;+    // TODO: t18095186 Move nodeType to opt-in function and mark appropriate+    // places in Litho+    setNodeType(YGNodeTypeText);+  }++  measure_ = measureFunc;+}++void YGNode::replaceChild(YGNodeRef child, uint32_t index) {+  children_[index] = child;+}++void YGNode::replaceChild(YGNodeRef oldChild, YGNodeRef newChild) {+  std::replace(children_.begin(), children_.end(), oldChild, newChild);+}++void YGNode::insertChild(YGNodeRef child, uint32_t index) {+  children_.insert(children_.begin() + index, child);+}++void YGNode::setDirty(bool isDirty) {+  if (isDirty == isDirty_) {+    return;+  }+  isDirty_ = isDirty;+  if (isDirty && dirtied_) {+    dirtied_(this);+  }+}++bool YGNode::removeChild(YGNodeRef child) {+  std::vector<YGNodeRef>::iterator p =+      std::find(children_.begin(), children_.end(), child);+  if (p != children_.end()) {+    children_.erase(p);+    return true;+  }+  return false;+}++void YGNode::removeChild(uint32_t index) {+  children_.erase(children_.begin() + index);+}++void YGNode::setLayoutDirection(YGDirection direction) {+  layout_.direction = direction;+}++void YGNode::setLayoutMargin(float margin, int index) {+  layout_.margin[index] = margin;+}++void YGNode::setLayoutBorder(float border, int index) {+  layout_.border[index] = border;+}++void YGNode::setLayoutPadding(float padding, int index) {+  layout_.padding[index] = padding;+}++void YGNode::setLayoutLastOwnerDirection(YGDirection direction) {+  layout_.lastOwnerDirection = direction;+}++void YGNode::setLayoutComputedFlexBasis(+    const YGFloatOptional& computedFlexBasis) {+  layout_.computedFlexBasis = computedFlexBasis;+}++void YGNode::setLayoutPosition(float position, int index) {+  layout_.position[index] = position;+}++void YGNode::setLayoutComputedFlexBasisGeneration(+    uint32_t computedFlexBasisGeneration) {+  layout_.computedFlexBasisGeneration = computedFlexBasisGeneration;+}++void YGNode::setLayoutMeasuredDimension(float measuredDimension, int index) {+  layout_.measuredDimensions[index] = measuredDimension;+}++void YGNode::setLayoutHadOverflow(bool hadOverflow) {+  layout_.hadOverflow = hadOverflow;+}++void YGNode::setLayoutDimension(float dimension, int index) {+  layout_.dimensions[index] = dimension;+}++// If both left and right are defined, then use left. Otherwise return+// +left or -right depending on which is defined.+YGFloatOptional YGNode::relativePosition(+    const YGFlexDirection& axis,+    const float& axisSize) const {+  if (isLeadingPositionDefined(axis)) {+    return getLeadingPosition(axis, axisSize);+  }++  YGFloatOptional trailingPosition = getTrailingPosition(axis, axisSize);+  if (!trailingPosition.isUndefined()) {+    trailingPosition.setValue(-1 * trailingPosition.getValue());+  }+  return trailingPosition;+}++void YGNode::setPosition(+    const YGDirection direction,+    const float mainSize,+    const float crossSize,+    const float ownerWidth) {+  /* Root nodes should be always layouted as LTR, so we don't return negative+   * values. */+  const YGDirection directionRespectingRoot =+      owner_ != nullptr ? direction : YGDirectionLTR;+  const YGFlexDirection mainAxis =+      YGResolveFlexDirection(style_.flexDirection, directionRespectingRoot);+  const YGFlexDirection crossAxis =+      YGFlexDirectionCross(mainAxis, directionRespectingRoot);++  const YGFloatOptional relativePositionMain =+      relativePosition(mainAxis, mainSize);+  const YGFloatOptional relativePositionCross =+      relativePosition(crossAxis, crossSize);++  setLayoutPosition(+      YGUnwrapFloatOptional(+          getLeadingMargin(mainAxis, ownerWidth) + relativePositionMain),+      leading[mainAxis]);+  setLayoutPosition(+      YGUnwrapFloatOptional(+          getTrailingMargin(mainAxis, ownerWidth) + relativePositionMain),+      trailing[mainAxis]);+  setLayoutPosition(+      YGUnwrapFloatOptional(+          getLeadingMargin(crossAxis, ownerWidth) + relativePositionCross),+      leading[crossAxis]);+  setLayoutPosition(+      YGUnwrapFloatOptional(+          getTrailingMargin(crossAxis, ownerWidth) + relativePositionCross),+      trailing[crossAxis]);+}++YGNode& YGNode::operator=(const YGNode& node) {+  if (&node == this) {+    return *this;+  }++  for (auto child : children_) {+    delete child;+  }++  context_ = node.getContext();+  print_ = node.getPrintFunc();+  hasNewLayout_ = node.getHasNewLayout();+  nodeType_ = node.getNodeType();+  measure_ = node.getMeasure();+  baseline_ = node.getBaseline();+  dirtied_ = node.getDirtied();+  style_ = node.style_;+  layout_ = node.layout_;+  lineIndex_ = node.getLineIndex();+  owner_ = node.getOwner();+  children_ = node.getChildren();+  config_ = node.getConfig();+  isDirty_ = node.isDirty();+  resolvedDimensions_ = node.getResolvedDimensions();++  return *this;+}++YGValue YGNode::marginLeadingValue(const YGFlexDirection axis) const {+  if (YGFlexDirectionIsRow(axis) &&+      style_.margin[YGEdgeStart].unit != YGUnitUndefined) {+    return style_.margin[YGEdgeStart];+  } else {+    return style_.margin[leading[axis]];+  }+}++YGValue YGNode::marginTrailingValue(const YGFlexDirection axis) const {+  if (YGFlexDirectionIsRow(axis) &&+      style_.margin[YGEdgeEnd].unit != YGUnitUndefined) {+    return style_.margin[YGEdgeEnd];+  } else {+    return style_.margin[trailing[axis]];+  }+}++YGValue YGNode::resolveFlexBasisPtr() const {+  YGValue flexBasis = style_.flexBasis;+  if (flexBasis.unit != YGUnitAuto && flexBasis.unit != YGUnitUndefined) {+    return flexBasis;+  }+  if (!style_.flex.isUndefined() && style_.flex.getValue() > 0.0f) {+    return config_->useWebDefaults ? YGValueAuto : YGValueZero;+  }+  return YGValueAuto;+}++void YGNode::resolveDimension() {+  for (uint32_t dim = YGDimensionWidth; dim < YGDimensionCount; dim++) {+    if (getStyle().maxDimensions[dim].unit != YGUnitUndefined &&+        YGValueEqual(+            getStyle().maxDimensions[dim], style_.minDimensions[dim])) {+      resolvedDimensions_[dim] = style_.maxDimensions[dim];+    } else {+      resolvedDimensions_[dim] = style_.dimensions[dim];+    }+  }+}++YGDirection YGNode::resolveDirection(const YGDirection ownerDirection) {+  if (style_.direction == YGDirectionInherit) {+    return ownerDirection > YGDirectionInherit ? ownerDirection+                                               : YGDirectionLTR;+  } else {+    return style_.direction;+  }+}++void YGNode::clearChildren() {+  children_.clear();+  children_.shrink_to_fit();+}++// Other Methods++void YGNode::cloneChildrenIfNeeded() {+  // YGNodeRemoveChild in yoga.cpp has a forked variant of this algorithm+  // optimized for deletions.++  const uint32_t childCount = static_cast<uint32_t>(children_.size());+  if (childCount == 0) {+    // This is an empty set. Nothing to clone.+    return;+  }++  const YGNodeRef firstChild = children_.front();+  if (firstChild->getOwner() == this) {+    // If the first child has this node as its owner, we assume that it is+    // already unique. We can do this because if we have it has a child, that+    // means that its owner was at some point cloned which made that subtree+    // immutable. We also assume that all its sibling are cloned as well.+    return;+  }++  const YGCloneNodeFunc cloneNodeCallback = config_->cloneNodeCallback;+  for (uint32_t i = 0; i < childCount; ++i) {+    const YGNodeRef oldChild = children_[i];+    YGNodeRef newChild = nullptr;+    if (cloneNodeCallback) {+      newChild = cloneNodeCallback(oldChild, this, i);+    }+    if (newChild == nullptr) {+      newChild = YGNodeClone(oldChild);+    }+    replaceChild(newChild, i);+    newChild->setOwner(this);+  }+}++void YGNode::markDirtyAndPropogate() {+  if (!isDirty_) {+    setDirty(true);+    setLayoutComputedFlexBasis(YGFloatOptional());+    if (owner_) {+      owner_->markDirtyAndPropogate();+    }+  }+}++void YGNode::markDirtyAndPropogateDownwards() {+  isDirty_ = true;+  for_each(children_.begin(), children_.end(), [](YGNodeRef childNode) {+    childNode->markDirtyAndPropogateDownwards();+  });+}++float YGNode::resolveFlexGrow() {+  // Root nodes flexGrow should always be 0+  if (owner_ == nullptr) {+    return 0.0;+  }+  if (!style_.flexGrow.isUndefined()) {+    return style_.flexGrow.getValue();+  }+  if (!style_.flex.isUndefined() && style_.flex.getValue() > 0.0f) {+    return style_.flex.getValue();+  }+  return kDefaultFlexGrow;+}++float YGNode::resolveFlexShrink() {+  if (owner_ == nullptr) {+    return 0.0;+  }+  if (!style_.flexShrink.isUndefined()) {+    return style_.flexShrink.getValue();+  }+  if (!config_->useWebDefaults && !style_.flex.isUndefined() &&+      style_.flex.getValue() < 0.0f) {+    return -style_.flex.getValue();+  }+  return config_->useWebDefaults ? kWebDefaultFlexShrink : kDefaultFlexShrink;+}++bool YGNode::isNodeFlexible() {+  return (+      (style_.positionType == YGPositionTypeRelative) &&+      (resolveFlexGrow() != 0 || resolveFlexShrink() != 0));+}++float YGNode::getLeadingBorder(const YGFlexDirection& axis) const {+  if (YGFlexDirectionIsRow(axis) &&+      style_.border[YGEdgeStart].unit != YGUnitUndefined &&+      !yoga::isUndefined(style_.border[YGEdgeStart].value) &&+      style_.border[YGEdgeStart].value >= 0.0f) {+    return style_.border[YGEdgeStart].value;+  }++  float computedEdgeValue =+      YGComputedEdgeValue(style_.border, leading[axis], &YGValueZero)->value;+  return YGFloatMax(computedEdgeValue, 0.0f);+}++float YGNode::getTrailingBorder(const YGFlexDirection& flexDirection) const {+  if (YGFlexDirectionIsRow(flexDirection) &&+      style_.border[YGEdgeEnd].unit != YGUnitUndefined &&+      !yoga::isUndefined(style_.border[YGEdgeEnd].value) &&+      style_.border[YGEdgeEnd].value >= 0.0f) {+    return style_.border[YGEdgeEnd].value;+  }++  float computedEdgeValue =+      YGComputedEdgeValue(style_.border, trailing[flexDirection], &YGValueZero)+          ->value;+  return YGFloatMax(computedEdgeValue, 0.0f);+}++YGFloatOptional YGNode::getLeadingPadding(+    const YGFlexDirection& axis,+    const float& widthSize) const {+  const YGFloatOptional& paddingEdgeStart =+      YGResolveValue(style_.padding[YGEdgeStart], widthSize);+  if (YGFlexDirectionIsRow(axis) &&+      style_.padding[YGEdgeStart].unit != YGUnitUndefined &&+      !paddingEdgeStart.isUndefined() && paddingEdgeStart.getValue() > 0.0f) {+    return paddingEdgeStart;+  }++  YGFloatOptional resolvedValue = YGResolveValue(+      *YGComputedEdgeValue(style_.padding, leading[axis], &YGValueZero),+      widthSize);+  return YGFloatOptionalMax(resolvedValue, YGFloatOptional(0.0f));+}++YGFloatOptional YGNode::getTrailingPadding(+    const YGFlexDirection& axis,+    const float& widthSize) const {+  if (YGFlexDirectionIsRow(axis) &&+      style_.padding[YGEdgeEnd].unit != YGUnitUndefined &&+      !YGResolveValue(style_.padding[YGEdgeEnd], widthSize).isUndefined() &&+      YGResolveValue(style_.padding[YGEdgeEnd], widthSize).getValue() >= 0.0f) {+    return YGResolveValue(style_.padding[YGEdgeEnd], widthSize);+  }++  YGFloatOptional resolvedValue = YGResolveValue(+      *YGComputedEdgeValue(style_.padding, trailing[axis], &YGValueZero),+      widthSize);++  return YGFloatOptionalMax(resolvedValue, YGFloatOptional(0.0f));+}++YGFloatOptional YGNode::getLeadingPaddingAndBorder(+    const YGFlexDirection& axis,+    const float& widthSize) const {+  return getLeadingPadding(axis, widthSize) ++      YGFloatOptional(getLeadingBorder(axis));+}++YGFloatOptional YGNode::getTrailingPaddingAndBorder(+    const YGFlexDirection& axis,+    const float& widthSize) const {+  return getTrailingPadding(axis, widthSize) ++      YGFloatOptional(getTrailingBorder(axis));+}++bool YGNode::didUseLegacyFlag() {+  bool didUseLegacyFlag = layout_.didUseLegacyFlag;+  if (didUseLegacyFlag) {+    return true;+  }+  for (const auto& child : children_) {+    if (child->layout_.didUseLegacyFlag) {+      didUseLegacyFlag = true;+      break;+    }+  }+  return didUseLegacyFlag;+}++void YGNode::setAndPropogateUseLegacyFlag(bool useLegacyFlag) {+  config_->useLegacyStretchBehaviour = useLegacyFlag;+  for_each(children_.begin(), children_.end(), [=](YGNodeRef childNode) {+    childNode->getConfig()->useLegacyStretchBehaviour = useLegacyFlag;+  });+}++void YGNode::setLayoutDoesLegacyFlagAffectsLayout(+    bool doesLegacyFlagAffectsLayout) {+  layout_.doesLegacyStretchFlagAffectsLayout = doesLegacyFlagAffectsLayout;+}++void YGNode::setLayoutDidUseLegacyFlag(bool didUseLegacyFlag) {+  layout_.didUseLegacyFlag = didUseLegacyFlag;+}++bool YGNode::isLayoutTreeEqualToNode(const YGNode& node) const {+  if (children_.size() != node.children_.size()) {+    return false;+  }+  if (layout_ != node.layout_) {+    return false;+  }+  if (children_.size() == 0) {+    return true;+  }++  bool isLayoutTreeEqual = true;+  YGNodeRef otherNodeChildren = nullptr;+  for (std::vector<YGNodeRef>::size_type i = 0; i < children_.size(); ++i) {+    otherNodeChildren = node.children_[i];+    isLayoutTreeEqual =+        children_[i]->isLayoutTreeEqualToNode(*otherNodeChildren);+    if (!isLayoutTreeEqual) {+      return false;+    }+  }+  return isLayoutTreeEqual;+}
+ yoga/YGNode.h view
@@ -0,0 +1,273 @@+/*+ *  Copyright (c) Facebook, Inc. and its affiliates.+ *+ *  This source code is licensed under the MIT license found in the LICENSE+ *  file in the root directory of this source tree.+ *+ */+#pragma once+#include <stdio.h>+#include "YGConfig.h"+#include "YGLayout.h"+#include "YGStyle.h"+#include "Yoga-internal.h"++struct YGNode {+ private:+  void* context_ = nullptr;+  YGPrintFunc print_ = nullptr;+  bool hasNewLayout_ = true;+  YGNodeType nodeType_ = YGNodeTypeDefault;+  YGMeasureFunc measure_ = nullptr;+  YGBaselineFunc baseline_ = nullptr;+  YGDirtiedFunc dirtied_ = nullptr;+  YGStyle style_ = {};+  YGLayout layout_ = {};+  uint32_t lineIndex_ = 0;+  YGNodeRef owner_ = nullptr;+  YGVector children_ = {};+  YGConfigRef config_ = nullptr;+  bool isDirty_ = false;+  std::array<YGValue, 2> resolvedDimensions_ = {+      {YGValueUndefined, YGValueUndefined}};++  YGFloatOptional relativePosition(+      const YGFlexDirection& axis,+      const float& axisSize) const;++ public:+  YGNode() = default;+  ~YGNode() = default; // cleanup of owner/children relationships in YGNodeFree+  explicit YGNode(const YGConfigRef newConfig) : config_(newConfig){};+  YGNode(const YGNode& node) = default;+  YGNode& operator=(const YGNode& node);++  // Getters+  void* getContext() const {+    return context_;+  }++  YGPrintFunc getPrintFunc() const {+    return print_;+  }++  bool getHasNewLayout() const {+    return hasNewLayout_;+  }++  YGNodeType getNodeType() const {+    return nodeType_;+  }++  YGMeasureFunc getMeasure() const {+    return measure_;+  }++  YGBaselineFunc getBaseline() const {+    return baseline_;+  }++  YGDirtiedFunc getDirtied() const {+    return dirtied_;+  }++  // For Performance reasons passing as reference.+  YGStyle& getStyle() {+    return style_;+  }++  const YGStyle& getStyle() const {+    return style_;+  }++  // For Performance reasons passing as reference.+  YGLayout& getLayout() {+    return layout_;+  }++  const YGLayout& getLayout() const {+    return layout_;+  }++  uint32_t getLineIndex() const {+    return lineIndex_;+  }++  // returns the YGNodeRef that owns this YGNode. An owner is used to identify+  // the YogaTree that a YGNode belongs to.+  // This method will return the parent of the YGNode when a YGNode only belongs+  // to one YogaTree or nullptr when the YGNode is shared between two or more+  // YogaTrees.+  YGNodeRef getOwner() const {+    return owner_;+  }++  // Deprecated, use getOwner() instead.+  YGNodeRef getParent() const {+    return getOwner();+  }++  const YGVector& getChildren() const {+    return children_;+  }++  YGNodeRef getChild(uint32_t index) const {+    return children_.at(index);+  }++  YGConfigRef getConfig() const {+    return config_;+  }++  bool isDirty() const {+    return isDirty_;+  }++  std::array<YGValue, 2> getResolvedDimensions() const {+    return resolvedDimensions_;+  }++  YGValue getResolvedDimension(int index) const {+    return resolvedDimensions_[index];+  }++  // Methods related to positions, margin, padding and border+  YGFloatOptional getLeadingPosition(+      const YGFlexDirection& axis,+      const float& axisSize) const;+  bool isLeadingPositionDefined(const YGFlexDirection& axis) const;+  bool isTrailingPosDefined(const YGFlexDirection& axis) const;+  YGFloatOptional getTrailingPosition(+      const YGFlexDirection& axis,+      const float& axisSize) const;+  YGFloatOptional getLeadingMargin(+      const YGFlexDirection& axis,+      const float& widthSize) const;+  YGFloatOptional getTrailingMargin(+      const YGFlexDirection& axis,+      const float& widthSize) const;+  float getLeadingBorder(const YGFlexDirection& flexDirection) const;+  float getTrailingBorder(const YGFlexDirection& flexDirection) const;+  YGFloatOptional getLeadingPadding(+      const YGFlexDirection& axis,+      const float& widthSize) const;+  YGFloatOptional getTrailingPadding(+      const YGFlexDirection& axis,+      const float& widthSize) const;+  YGFloatOptional getLeadingPaddingAndBorder(+      const YGFlexDirection& axis,+      const float& widthSize) const;+  YGFloatOptional getTrailingPaddingAndBorder(+      const YGFlexDirection& axis,+      const float& widthSize) const;+  YGFloatOptional getMarginForAxis(+      const YGFlexDirection& axis,+      const float& widthSize) const;+  // Setters++  void setContext(void* context) {+    context_ = context;+  }++  void setPrintFunc(YGPrintFunc printFunc) {+    print_ = printFunc;+  }++  void setHasNewLayout(bool hasNewLayout) {+    hasNewLayout_ = hasNewLayout;+  }++  void setNodeType(YGNodeType nodeType) {+    nodeType_ = nodeType;+  }++  void setStyleFlexDirection(YGFlexDirection direction) {+    style_.flexDirection = direction;+  }++  void setStyleAlignContent(YGAlign alignContent) {+    style_.alignContent = alignContent;+  }++  void setMeasureFunc(YGMeasureFunc measureFunc);++  void setBaseLineFunc(YGBaselineFunc baseLineFunc) {+    baseline_ = baseLineFunc;+  }++  void setDirtiedFunc(YGDirtiedFunc dirtiedFunc) {+    dirtied_ = dirtiedFunc;+  }++  void setStyle(const YGStyle& style) {+    style_ = style;+  }++  void setLayout(const YGLayout& layout) {+    layout_ = layout;+  }++  void setLineIndex(uint32_t lineIndex) {+    lineIndex_ = lineIndex;+  }++  void setOwner(YGNodeRef owner) {+    owner_ = owner;+  }++  void setChildren(const YGVector& children) {+    children_ = children;+  }++  // TODO: rvalue override for setChildren++  void setConfig(YGConfigRef config) {+    config_ = config;+  }++  void setDirty(bool isDirty);+  void setLayoutLastOwnerDirection(YGDirection direction);+  void setLayoutComputedFlexBasis(const YGFloatOptional& computedFlexBasis);+  void setLayoutComputedFlexBasisGeneration(+      uint32_t computedFlexBasisGeneration);+  void setLayoutMeasuredDimension(float measuredDimension, int index);+  void setLayoutHadOverflow(bool hadOverflow);+  void setLayoutDimension(float dimension, int index);+  void setLayoutDirection(YGDirection direction);+  void setLayoutMargin(float margin, int index);+  void setLayoutBorder(float border, int index);+  void setLayoutPadding(float padding, int index);+  void setLayoutPosition(float position, int index);+  void setPosition(+      const YGDirection direction,+      const float mainSize,+      const float crossSize,+      const float ownerWidth);+  void setAndPropogateUseLegacyFlag(bool useLegacyFlag);+  void setLayoutDoesLegacyFlagAffectsLayout(bool doesLegacyFlagAffectsLayout);+  void setLayoutDidUseLegacyFlag(bool didUseLegacyFlag);+  void markDirtyAndPropogateDownwards();++  // Other methods+  YGValue marginLeadingValue(const YGFlexDirection axis) const;+  YGValue marginTrailingValue(const YGFlexDirection axis) const;+  YGValue resolveFlexBasisPtr() const;+  void resolveDimension();+  YGDirection resolveDirection(const YGDirection ownerDirection);+  void clearChildren();+  /// Replaces the occurrences of oldChild with newChild+  void replaceChild(YGNodeRef oldChild, YGNodeRef newChild);+  void replaceChild(YGNodeRef child, uint32_t index);+  void insertChild(YGNodeRef child, uint32_t index);+  /// Removes the first occurrence of child+  bool removeChild(YGNodeRef child);+  void removeChild(uint32_t index);++  void cloneChildrenIfNeeded();+  void markDirtyAndPropogate();+  float resolveFlexGrow();+  float resolveFlexShrink();+  bool isNodeFlexible();+  bool didUseLegacyFlag();+  bool isLayoutTreeEqualToNode(const YGNode& node) const;+};
yoga/YGNodePrint.cpp view
@@ -1,220 +1,231 @@-/*
- * Copyright (c) 2017-present, Facebook, Inc.
- * All rights reserved.
- *
- * This source code is licensed under the BSD-style license found in the
- * LICENSE file in the root directory of this source tree. An additional grant
- * of patent rights can be found in the PATENTS file in the same directory.
- */
-
-#include "YGNodePrint.h"
-#include <stdarg.h>
-#include "YGEnums.h"
-#include "Yoga-internal.h"
-
-namespace facebook {
-namespace yoga {
-typedef std::string string;
-
-static void indent(string* base, uint32_t level) {
-  for (uint32_t i = 0; i < level; ++i) {
-    base->append("  ");
-  }
-}
-
-static bool areFourValuesEqual(const YGValue four[4]) {
-  return YGValueEqual(four[0], four[1]) && YGValueEqual(four[0], four[2]) &&
-      YGValueEqual(four[0], four[3]);
-}
-
-static void appendFormatedString(string* str, const char* fmt, ...) {
-  char buffer[1024];
-  va_list args;
-  va_start(args, fmt);
-  va_list argsCopy;
-  va_copy(argsCopy, args);
-  va_end(args);
-  vsnprintf(buffer, 1024, fmt, argsCopy);
-  va_end(argsCopy);
-  string result = string(buffer);
-  str->append(result);
-}
-
-static void
-appendFloatIfNotUndefined(string* base, const string key, const float num) {
-  if (!YGFloatIsUndefined(num)) {
-    appendFormatedString(base, "%s: %g; ", key.c_str(), num);
-  }
-}
-
-static void appendNumberIfNotUndefined(
-    string* base,
-    const string key,
-    const YGValue* const number) {
-  if (number->unit != YGUnitUndefined) {
-    if (number->unit == YGUnitAuto) {
-      base->append(key + ": auto; ");
-    } else {
-      string unit = number->unit == YGUnitPoint ? "px" : "%%";
-      appendFormatedString(
-          base, "%s: %g%s; ", key.c_str(), number->value, unit.c_str());
-    }
-  }
-}
-
-static void appendNumberIfNotAuto(
-    string* base,
-    const string key,
-    const YGValue* const number) {
-  if (number->unit != YGUnitAuto) {
-    appendNumberIfNotUndefined(base, key, number);
-  }
-}
-
-static void appendNumberIfNotZero(
-    string* base,
-    const string str,
-    const YGValue* const number) {
-  if (!YGFloatsEqual(number->value, 0)) {
-    appendNumberIfNotUndefined(base, str, number);
-  }
-}
-
-static void appendEdges(string* base, const string key, const YGValue* edges) {
-  if (areFourValuesEqual(edges)) {
-    appendNumberIfNotZero(base, key, &edges[YGEdgeLeft]);
-  } else {
-    for (int edge = YGEdgeLeft; edge != YGEdgeAll; ++edge) {
-      string str = key + "-" + YGEdgeToString(static_cast<YGEdge>(edge));
-      appendNumberIfNotZero(base, str, &edges[edge]);
-    }
-  }
-}
-
-static void appendEdgeIfNotUndefined(
-    string* base,
-    const string str,
-    const YGValue* edges,
-    const YGEdge edge) {
-  appendNumberIfNotUndefined(
-      base, str, YGComputedEdgeValue(edges, edge, &YGValueUndefined));
-}
-
-void YGNodeToString(
-    std::string* str,
-    YGNodeRef node,
-    YGPrintOptions options,
-    uint32_t level) {
-  indent(str, level);
-  appendFormatedString(str, "<div ");
-  if (node->print != nullptr) {
-    node->print(node);
-  }
-
-  if (options & YGPrintOptionsLayout) {
-    appendFormatedString(str, "layout=\"");
-    appendFormatedString(
-        str, "width: %g; ", node->layout.dimensions[YGDimensionWidth]);
-    appendFormatedString(
-        str, "height: %g; ", node->layout.dimensions[YGDimensionHeight]);
-    appendFormatedString(str, "top: %g; ", node->layout.position[YGEdgeTop]);
-    appendFormatedString(str, "left: %g;", node->layout.position[YGEdgeLeft]);
-    appendFormatedString(str, "\" ");
-  }
-
-  if (options & YGPrintOptionsStyle) {
-    appendFormatedString(str, "style=\"");
-    if (node->style.flexDirection != gYGNodeDefaults.style.flexDirection) {
-      appendFormatedString(
-          str,
-          "flex-direction: %s; ",
-          YGFlexDirectionToString(node->style.flexDirection));
-    }
-    if (node->style.justifyContent != gYGNodeDefaults.style.justifyContent) {
-      appendFormatedString(
-          str,
-          "justify-content: %s; ",
-          YGJustifyToString(node->style.justifyContent));
-    }
-    if (node->style.alignItems != gYGNodeDefaults.style.alignItems) {
-      appendFormatedString(
-          str, "align-items: %s; ", YGAlignToString(node->style.alignItems));
-    }
-    if (node->style.alignContent != gYGNodeDefaults.style.alignContent) {
-      appendFormatedString(
-          str,
-          "align-content: %s; ",
-          YGAlignToString(node->style.alignContent));
-    }
-    if (node->style.alignSelf != gYGNodeDefaults.style.alignSelf) {
-      appendFormatedString(
-          str, "align-self: %s; ", YGAlignToString(node->style.alignSelf));
-    }
-    appendFloatIfNotUndefined(str, "flex-grow", node->style.flexGrow);
-    appendFloatIfNotUndefined(str, "flex-shrink", node->style.flexShrink);
-    appendNumberIfNotAuto(str, "flex-basis", &node->style.flexBasis);
-    appendFloatIfNotUndefined(str, "flex", node->style.flex);
-
-    if (node->style.flexWrap != gYGNodeDefaults.style.flexWrap) {
-      appendFormatedString(
-          str, "flexWrap: %s; ", YGWrapToString(node->style.flexWrap));
-    }
-
-    if (node->style.overflow != gYGNodeDefaults.style.overflow) {
-      appendFormatedString(
-          str, "overflow: %s; ", YGOverflowToString(node->style.overflow));
-    }
-
-    if (node->style.display != gYGNodeDefaults.style.display) {
-      appendFormatedString(
-          str, "display: %s; ", YGDisplayToString(node->style.display));
-    }
-    appendEdges(str, "margin", node->style.margin);
-    appendEdges(str, "padding", node->style.padding);
-    appendEdges(str, "border", node->style.border);
-
-    appendNumberIfNotAuto(
-        str, "width", &node->style.dimensions[YGDimensionWidth]);
-    appendNumberIfNotAuto(
-        str, "height", &node->style.dimensions[YGDimensionHeight]);
-    appendNumberIfNotAuto(
-        str, "max-width", &node->style.maxDimensions[YGDimensionWidth]);
-    appendNumberIfNotAuto(
-        str, "max-height", &node->style.maxDimensions[YGDimensionHeight]);
-    appendNumberIfNotAuto(
-        str, "min-width", &node->style.minDimensions[YGDimensionWidth]);
-    appendNumberIfNotAuto(
-        str, "min-height", &node->style.minDimensions[YGDimensionHeight]);
-
-    if (node->style.positionType != gYGNodeDefaults.style.positionType) {
-      appendFormatedString(
-          str,
-          "position: %s; ",
-          YGPositionTypeToString(node->style.positionType));
-    }
-
-    appendEdgeIfNotUndefined(str, "left", node->style.position, YGEdgeLeft);
-    appendEdgeIfNotUndefined(str, "right", node->style.position, YGEdgeRight);
-    appendEdgeIfNotUndefined(str, "top", node->style.position, YGEdgeTop);
-    appendEdgeIfNotUndefined(str, "bottom", node->style.position, YGEdgeBottom);
-    appendFormatedString(str, "\" ");
-
-    if (node->measure != nullptr) {
-      appendFormatedString(str, "has-custom-measure=\"true\"");
-    }
-  }
-  appendFormatedString(str, ">");
-
-  const uint32_t childCount = node->children.size();
-  if (options & YGPrintOptionsChildren && childCount > 0) {
-    for (uint32_t i = 0; i < childCount; i++) {
-      appendFormatedString(str, "\n");
-      YGNodeToString(str, YGNodeGetChild(node, i), options, level + 1);
-    }
-    appendFormatedString(str, "\n");
-    indent(str, level);
-  }
-  appendFormatedString(str, "</div>");
-}
-} // namespace yoga
-} // namespace facebook
+/*+ * Copyright (c) Facebook, Inc. and its affiliates.+ *+ * This source code is licensed under the MIT license found in the+ * LICENSE file in the root directory of this source tree.+ */++#include "YGNodePrint.h"+#include <stdarg.h>+#include "YGEnums.h"+#include "YGNode.h"+#include "Yoga-internal.h"++namespace facebook {+namespace yoga {+typedef std::string string;++static void indent(string* base, uint32_t level) {+  for (uint32_t i = 0; i < level; ++i) {+    base->append("  ");+  }+}++static bool areFourValuesEqual(const std::array<YGValue, YGEdgeCount>& four) {+  return YGValueEqual(four[0], four[1]) && YGValueEqual(four[0], four[2]) &&+      YGValueEqual(four[0], four[3]);+}++static void appendFormatedString(string* str, const char* fmt, ...) {+  va_list args;+  va_start(args, fmt);+  va_list argsCopy;+  va_copy(argsCopy, args);+  std::vector<char> buf(1 + vsnprintf(NULL, 0, fmt, args));+  va_end(args);+  vsnprintf(buf.data(), buf.size(), fmt, argsCopy);+  va_end(argsCopy);+  string result = string(buf.begin(), buf.end() - 1);+  str->append(result);+}++static void appendFloatOptionalIfDefined(+    string* base,+    const string key,+    const YGFloatOptional num) {+  if (!num.isUndefined()) {+    appendFormatedString(base, "%s: %g; ", key.c_str(), num.getValue());+  }+}++static void appendNumberIfNotUndefined(+    string* base,+    const string key,+    const YGValue number) {+  if (number.unit != YGUnitUndefined) {+    if (number.unit == YGUnitAuto) {+      base->append(key + ": auto; ");+    } else {+      string unit = number.unit == YGUnitPoint ? "px" : "%%";+      appendFormatedString(+          base, "%s: %g%s; ", key.c_str(), number.value, unit.c_str());+    }+  }+}++static void+appendNumberIfNotAuto(string* base, const string& key, const YGValue number) {+  if (number.unit != YGUnitAuto) {+    appendNumberIfNotUndefined(base, key, number);+  }+}++static void+appendNumberIfNotZero(string* base, const string& str, const YGValue number) {++  if (number.unit == YGUnitAuto) {+    base->append(str + ": auto; ");+  } else if (!YGFloatsEqual(number.value, 0)) {+    appendNumberIfNotUndefined(base, str, number);+  }+}++static void appendEdges(+    string* base,+    const string& key,+    const std::array<YGValue, YGEdgeCount>& edges) {+  if (areFourValuesEqual(edges)) {+    appendNumberIfNotZero(base, key, edges[YGEdgeLeft]);+  } else {+    for (int edge = YGEdgeLeft; edge != YGEdgeAll; ++edge) {+      string str = key + "-" + YGEdgeToString(static_cast<YGEdge>(edge));+      appendNumberIfNotZero(base, str, edges[edge]);+    }+  }+}++static void appendEdgeIfNotUndefined(+    string* base,+    const string& str,+    const std::array<YGValue, YGEdgeCount>& edges,+    const YGEdge edge) {+  appendNumberIfNotUndefined(+      base, str, *YGComputedEdgeValue(edges, edge, &YGValueUndefined));+}++void YGNodeToString(+    std::string* str,+    YGNodeRef node,+    YGPrintOptions options,+    uint32_t level) {+  indent(str, level);+  appendFormatedString(str, "<div ");+  if (node->getPrintFunc() != nullptr) {+    node->getPrintFunc()(node);+  }++  if (options & YGPrintOptionsLayout) {+    appendFormatedString(str, "layout=\"");+    appendFormatedString(+        str, "width: %g; ", node->getLayout().dimensions[YGDimensionWidth]);+    appendFormatedString(+        str, "height: %g; ", node->getLayout().dimensions[YGDimensionHeight]);+    appendFormatedString(+        str, "top: %g; ", node->getLayout().position[YGEdgeTop]);+    appendFormatedString(+        str, "left: %g;", node->getLayout().position[YGEdgeLeft]);+    appendFormatedString(str, "\" ");+  }++  if (options & YGPrintOptionsStyle) {+    appendFormatedString(str, "style=\"");+    if (node->getStyle().flexDirection != YGNode().getStyle().flexDirection) {+      appendFormatedString(+          str,+          "flex-direction: %s; ",+          YGFlexDirectionToString(node->getStyle().flexDirection));+    }+    if (node->getStyle().justifyContent != YGNode().getStyle().justifyContent) {+      appendFormatedString(+          str,+          "justify-content: %s; ",+          YGJustifyToString(node->getStyle().justifyContent));+    }+    if (node->getStyle().alignItems != YGNode().getStyle().alignItems) {+      appendFormatedString(+          str,+          "align-items: %s; ",+          YGAlignToString(node->getStyle().alignItems));+    }+    if (node->getStyle().alignContent != YGNode().getStyle().alignContent) {+      appendFormatedString(+          str,+          "align-content: %s; ",+          YGAlignToString(node->getStyle().alignContent));+    }+    if (node->getStyle().alignSelf != YGNode().getStyle().alignSelf) {+      appendFormatedString(+          str, "align-self: %s; ", YGAlignToString(node->getStyle().alignSelf));+    }+    appendFloatOptionalIfDefined(str, "flex-grow", node->getStyle().flexGrow);+    appendFloatOptionalIfDefined(+        str, "flex-shrink", node->getStyle().flexShrink);+    appendNumberIfNotAuto(str, "flex-basis", node->getStyle().flexBasis);+    appendFloatOptionalIfDefined(str, "flex", node->getStyle().flex);++    if (node->getStyle().flexWrap != YGNode().getStyle().flexWrap) {+      appendFormatedString(+          str, "flexWrap: %s; ", YGWrapToString(node->getStyle().flexWrap));+    }++    if (node->getStyle().overflow != YGNode().getStyle().overflow) {+      appendFormatedString(+          str, "overflow: %s; ", YGOverflowToString(node->getStyle().overflow));+    }++    if (node->getStyle().display != YGNode().getStyle().display) {+      appendFormatedString(+          str, "display: %s; ", YGDisplayToString(node->getStyle().display));+    }+    appendEdges(str, "margin", node->getStyle().margin);+    appendEdges(str, "padding", node->getStyle().padding);+    appendEdges(str, "border", node->getStyle().border);++    appendNumberIfNotAuto(+        str, "width", node->getStyle().dimensions[YGDimensionWidth]);+    appendNumberIfNotAuto(+        str, "height", node->getStyle().dimensions[YGDimensionHeight]);+    appendNumberIfNotAuto(+        str, "max-width", node->getStyle().maxDimensions[YGDimensionWidth]);+    appendNumberIfNotAuto(+        str, "max-height", node->getStyle().maxDimensions[YGDimensionHeight]);+    appendNumberIfNotAuto(+        str, "min-width", node->getStyle().minDimensions[YGDimensionWidth]);+    appendNumberIfNotAuto(+        str, "min-height", node->getStyle().minDimensions[YGDimensionHeight]);++    if (node->getStyle().positionType != YGNode().getStyle().positionType) {+      appendFormatedString(+          str,+          "position: %s; ",+          YGPositionTypeToString(node->getStyle().positionType));+    }++    appendEdgeIfNotUndefined(+        str, "left", node->getStyle().position, YGEdgeLeft);+    appendEdgeIfNotUndefined(+        str, "right", node->getStyle().position, YGEdgeRight);+    appendEdgeIfNotUndefined(str, "top", node->getStyle().position, YGEdgeTop);+    appendEdgeIfNotUndefined(+        str, "bottom", node->getStyle().position, YGEdgeBottom);+    appendFormatedString(str, "\" ");++    if (node->getMeasure() != nullptr) {+      appendFormatedString(str, "has-custom-measure=\"true\"");+    }+  }+  appendFormatedString(str, ">");++  const uint32_t childCount = static_cast<uint32_t>(node->getChildren().size());+  if (options & YGPrintOptionsChildren && childCount > 0) {+    for (uint32_t i = 0; i < childCount; i++) {+      appendFormatedString(str, "\n");+      YGNodeToString(str, YGNodeGetChild(node, i), options, level + 1);+    }+    appendFormatedString(str, "\n");+    indent(str, level);+  }+  appendFormatedString(str, "</div>");+}+} // namespace yoga+} // namespace facebook
yoga/YGNodePrint.h view
@@ -1,24 +1,22 @@-/**
- * Copyright (c) 2014-present, Facebook, Inc.
- * All rights reserved.
- *
- * This source code is licensed under the BSD-style license found in the
- * LICENSE file in the root directory of this source tree. An additional grant
- * of patent rights can be found in the PATENTS file in the same directory.
- */
-#pragma once
-#include <string>
-
-#include "Yoga.h"
-
-namespace facebook {
-namespace yoga {
-
-void YGNodeToString(
-    std::string* str,
-    YGNodeRef node,
-    YGPrintOptions options,
-    uint32_t level);
-
-} // namespace yoga
-} // namespace facebook
+/**+ * Copyright (c) Facebook, Inc. and its affiliates.+ *+ * This source code is licensed under the MIT license found in the+ * LICENSE file in the root directory of this source tree.+ */+#pragma once+#include <string>++#include "Yoga.h"++namespace facebook {+namespace yoga {++void YGNodeToString(+    std::string* str,+    YGNodeRef node,+    YGPrintOptions options,+    uint32_t level);++} // namespace yoga+} // namespace facebook
+ yoga/YGStyle.cpp view
@@ -0,0 +1,100 @@+/*+ *  Copyright (c) Facebook, Inc. and its affiliates.+ *+ *  This source code is licensed under the MIT license found in the LICENSE+ *  file in the root directory of this source tree.+ *+ */+#include "YGStyle.h"++const YGValue kYGValueUndefined = {0, YGUnitUndefined};++const YGValue kYGValueAuto = {0, YGUnitAuto};++const std::array<YGValue, YGEdgeCount> kYGDefaultEdgeValuesUnit = {+    {kYGValueUndefined,+     kYGValueUndefined,+     kYGValueUndefined,+     kYGValueUndefined,+     kYGValueUndefined,+     kYGValueUndefined,+     kYGValueUndefined,+     kYGValueUndefined,+     kYGValueUndefined}};++const std::array<YGValue, 2> kYGDefaultDimensionValuesAutoUnit = {+    {kYGValueAuto, kYGValueAuto}};++const std::array<YGValue, 2> kYGDefaultDimensionValuesUnit = {+    {kYGValueUndefined, kYGValueUndefined}};++YGStyle::YGStyle()+    : direction(YGDirectionInherit),+      flexDirection(YGFlexDirectionColumn),+      justifyContent(YGJustifyFlexStart),+      alignContent(YGAlignFlexStart),+      alignItems(YGAlignStretch),+      alignSelf(YGAlignAuto),+      positionType(YGPositionTypeRelative),+      flexWrap(YGWrapNoWrap),+      overflow(YGOverflowVisible),+      display(YGDisplayFlex),+      flex(YGFloatOptional()),+      flexGrow(YGFloatOptional()),+      flexShrink(YGFloatOptional()),+      flexBasis(kYGValueAuto),+      margin(kYGDefaultEdgeValuesUnit),+      position(kYGDefaultEdgeValuesUnit),+      padding(kYGDefaultEdgeValuesUnit),+      border(kYGDefaultEdgeValuesUnit),+      dimensions(kYGDefaultDimensionValuesAutoUnit),+      minDimensions(kYGDefaultDimensionValuesUnit),+      maxDimensions(kYGDefaultDimensionValuesUnit),+      aspectRatio(YGFloatOptional()) {}++// Yoga specific properties, not compatible with flexbox specification+bool YGStyle::operator==(const YGStyle& style) {+  bool areNonFloatValuesEqual = direction == style.direction &&+      flexDirection == style.flexDirection &&+      justifyContent == style.justifyContent &&+      alignContent == style.alignContent && alignItems == style.alignItems &&+      alignSelf == style.alignSelf && positionType == style.positionType &&+      flexWrap == style.flexWrap && overflow == style.overflow &&+      display == style.display && YGValueEqual(flexBasis, style.flexBasis) &&+      YGValueArrayEqual(margin, style.margin) &&+      YGValueArrayEqual(position, style.position) &&+      YGValueArrayEqual(padding, style.padding) &&+      YGValueArrayEqual(border, style.border) &&+      YGValueArrayEqual(dimensions, style.dimensions) &&+      YGValueArrayEqual(minDimensions, style.minDimensions) &&+      YGValueArrayEqual(maxDimensions, style.maxDimensions);++  areNonFloatValuesEqual =+      areNonFloatValuesEqual && flex.isUndefined() == style.flex.isUndefined();+  if (areNonFloatValuesEqual && !flex.isUndefined() &&+      !style.flex.isUndefined()) {+    areNonFloatValuesEqual =+        areNonFloatValuesEqual && flex.getValue() == style.flex.getValue();+  }++  areNonFloatValuesEqual = areNonFloatValuesEqual &&+      flexGrow.isUndefined() == style.flexGrow.isUndefined();+  if (areNonFloatValuesEqual && !flexGrow.isUndefined()) {+    areNonFloatValuesEqual = areNonFloatValuesEqual &&+        flexGrow.getValue() == style.flexGrow.getValue();+  }++  areNonFloatValuesEqual = areNonFloatValuesEqual &&+      flexShrink.isUndefined() == style.flexShrink.isUndefined();+  if (areNonFloatValuesEqual && !style.flexShrink.isUndefined()) {+    areNonFloatValuesEqual = areNonFloatValuesEqual &&+        flexShrink.getValue() == style.flexShrink.getValue();+  }++  if (!(aspectRatio.isUndefined() && style.aspectRatio.isUndefined())) {+    areNonFloatValuesEqual = areNonFloatValuesEqual &&+        aspectRatio.getValue() == style.aspectRatio.getValue();+  }++  return areNonFloatValuesEqual;+}
yoga/Yoga-internal.h view
@@ -1,230 +1,120 @@-/**
- * Copyright (c) 2014-present, Facebook, Inc.
- * All rights reserved.
- *
- * This source code is licensed under the BSD-style license found in the
- * LICENSE file in the root directory of this source tree. An additional grant
- * of patent rights can be found in the PATENTS file in the same directory.
- */
-
-#pragma once
-#include <vector>
-
-#include "Yoga.h"
-
-typedef std::vector<YGNodeRef> YGVector;
-
-YG_EXTERN_C_BEGIN
-
-WIN_EXPORT float YGRoundValueToPixelGrid(const float value,
-                                         const float pointScaleFactor,
-                                         const bool forceCeil,
-                                         const bool forceFloor);
-
-YG_EXTERN_C_END
-
-typedef struct YGCachedMeasurement {
-  float availableWidth;
-  float availableHeight;
-  YGMeasureMode widthMeasureMode;
-  YGMeasureMode heightMeasureMode;
-
-  float computedWidth;
-  float computedHeight;
-} YGCachedMeasurement;
-
-// This value was chosen based on empiracle data. Even the most complicated
-// layouts should not require more than 16 entries to fit within the cache.
-#define YG_MAX_CACHED_RESULT_COUNT 16
-
-typedef struct YGLayout {
-  float position[4];
-  float dimensions[2];
-  float margin[6];
-  float border[6];
-  float padding[6];
-  YGDirection direction;
-
-  uint32_t computedFlexBasisGeneration;
-  float computedFlexBasis;
-  bool hadOverflow;
-
-  // Instead of recomputing the entire layout every single time, we
-  // cache some information to break early when nothing changed
-  uint32_t generationCount;
-  YGDirection lastParentDirection;
-
-  uint32_t nextCachedMeasurementsIndex;
-  YGCachedMeasurement cachedMeasurements[YG_MAX_CACHED_RESULT_COUNT];
-  float measuredDimensions[2];
-
-  YGCachedMeasurement cachedLayout;
-} YGLayout;
-
-typedef struct YGStyle {
-  YGDirection direction;
-  YGFlexDirection flexDirection;
-  YGJustify justifyContent;
-  YGAlign alignContent;
-  YGAlign alignItems;
-  YGAlign alignSelf;
-  YGPositionType positionType;
-  YGWrap flexWrap;
-  YGOverflow overflow;
-  YGDisplay display;
-  float flex;
-  float flexGrow;
-  float flexShrink;
-  YGValue flexBasis;
-  YGValue margin[YGEdgeCount];
-  YGValue position[YGEdgeCount];
-  YGValue padding[YGEdgeCount];
-  YGValue border[YGEdgeCount];
-  YGValue dimensions[2];
-  YGValue minDimensions[2];
-  YGValue maxDimensions[2];
-
-  // Yoga specific properties, not compatible with flexbox specification
-  float aspectRatio;
-} YGStyle;
-
-typedef struct YGConfig {
-  bool experimentalFeatures[YGExperimentalFeatureCount + 1];
-  bool useWebDefaults;
-  bool useLegacyStretchBehaviour;
-  float pointScaleFactor;
-  YGLogger logger;
-  YGNodeClonedFunc cloneNodeCallback;
-  void* context;
-} YGConfig;
-
-typedef struct YGNode {
-  YGStyle style;
-  YGLayout layout;
-  uint32_t lineIndex;
-
-  YGNodeRef parent;
-  YGVector children;
-
-  struct YGNode* nextChild;
-
-  YGMeasureFunc measure;
-  YGBaselineFunc baseline;
-  YGPrintFunc print;
-  YGConfigRef config;
-  void* context;
-
-  bool isDirty;
-  bool hasNewLayout;
-  YGNodeType nodeType;
-
-  YGValue const* resolvedDimensions[2];
-} YGNode;
-
-#define YG_UNDEFINED_VALUES \
-  { .value = YGUndefined, .unit = YGUnitUndefined }
-
-#define YG_AUTO_VALUES \
-  { .value = YGUndefined, .unit = YGUnitAuto }
-
-#define YG_DEFAULT_EDGE_VALUES_UNIT                                            \
-  {                                                                            \
-    [YGEdgeLeft] = YG_UNDEFINED_VALUES, [YGEdgeTop] = YG_UNDEFINED_VALUES,     \
-    [YGEdgeRight] = YG_UNDEFINED_VALUES, [YGEdgeBottom] = YG_UNDEFINED_VALUES, \
-    [YGEdgeStart] = YG_UNDEFINED_VALUES, [YGEdgeEnd] = YG_UNDEFINED_VALUES,    \
-    [YGEdgeHorizontal] = YG_UNDEFINED_VALUES,                                  \
-    [YGEdgeVertical] = YG_UNDEFINED_VALUES, [YGEdgeAll] = YG_UNDEFINED_VALUES, \
-  }
-
-#define YG_DEFAULT_DIMENSION_VALUES \
-  { [YGDimensionWidth] = YGUndefined, [YGDimensionHeight] = YGUndefined, }
-
-#define YG_DEFAULT_DIMENSION_VALUES_UNIT       \
-  {                                            \
-    [YGDimensionWidth] = YG_UNDEFINED_VALUES,  \
-    [YGDimensionHeight] = YG_UNDEFINED_VALUES, \
-  }
-
-#define YG_DEFAULT_DIMENSION_VALUES_AUTO_UNIT \
-  { [YGDimensionWidth] = YG_AUTO_VALUES, [YGDimensionHeight] = YG_AUTO_VALUES, }
-
-static const float kDefaultFlexGrow = 0.0f;
-static const float kDefaultFlexShrink = 0.0f;
-static const float kWebDefaultFlexShrink = 1.0f;
-
-static const YGStyle gYGNodeStyleDefaults = {
-    .direction = YGDirectionInherit,
-    .flexDirection = YGFlexDirectionColumn,
-    .justifyContent = YGJustifyFlexStart,
-    .alignContent = YGAlignFlexStart,
-    .alignItems = YGAlignStretch,
-    .alignSelf = YGAlignAuto,
-    .positionType = YGPositionTypeRelative,
-    .flexWrap = YGWrapNoWrap,
-    .overflow = YGOverflowVisible,
-    .display = YGDisplayFlex,
-    .flex = YGUndefined,
-    .flexGrow = YGUndefined,
-    .flexShrink = YGUndefined,
-    .flexBasis = YG_AUTO_VALUES,
-    .margin = YG_DEFAULT_EDGE_VALUES_UNIT,
-    .position = YG_DEFAULT_EDGE_VALUES_UNIT,
-    .padding = YG_DEFAULT_EDGE_VALUES_UNIT,
-    .border = YG_DEFAULT_EDGE_VALUES_UNIT,
-    .dimensions = YG_DEFAULT_DIMENSION_VALUES_AUTO_UNIT,
-    .minDimensions = YG_DEFAULT_DIMENSION_VALUES_UNIT,
-    .maxDimensions = YG_DEFAULT_DIMENSION_VALUES_UNIT,
-    .aspectRatio = YGUndefined,
-};
-
-static const YGLayout gYGNodeLayoutDefaults = {
-    .position = {},
-    .dimensions = YG_DEFAULT_DIMENSION_VALUES,
-    .margin = {},
-    .border = {},
-    .padding = {},
-    .direction = YGDirectionInherit,
-    .computedFlexBasisGeneration = 0,
-    .computedFlexBasis = YGUndefined,
-    .hadOverflow = false,
-    .generationCount = 0,
-    .lastParentDirection = (YGDirection)-1,
-    .nextCachedMeasurementsIndex = 0,
-    .cachedMeasurements = {},
-    .measuredDimensions = YG_DEFAULT_DIMENSION_VALUES,
-    .cachedLayout =
-        {
-            .availableWidth = 0,
-            .availableHeight = 0,
-            .widthMeasureMode = (YGMeasureMode)-1,
-            .heightMeasureMode = (YGMeasureMode)-1,
-            .computedWidth = -1,
-            .computedHeight = -1,
-        },
-};
-
-static const YGNode gYGNodeDefaults = {
-    .style = gYGNodeStyleDefaults,
-    .layout = gYGNodeLayoutDefaults,
-    .lineIndex = 0,
-    .parent = nullptr,
-    .children = YGVector(),
-    .nextChild = nullptr,
-    .measure = nullptr,
-    .baseline = nullptr,
-    .print = nullptr,
-    .config = nullptr,
-    .context = nullptr,
-    .isDirty = false,
-    .hasNewLayout = true,
-    .nodeType = YGNodeTypeDefault,
-    .resolvedDimensions = {[YGDimensionWidth] = &YGValueUndefined,
-                           [YGDimensionHeight] = &YGValueUndefined},
-};
-
-extern bool YGFloatsEqual(const float a, const float b);
-extern bool YGValueEqual(const YGValue a, const YGValue b);
-extern const YGValue* YGComputedEdgeValue(
-    const YGValue edges[YGEdgeCount],
-    const YGEdge edge,
-    const YGValue* const defaultValue);
+/*+ *  Copyright (c) Facebook, Inc. and its affiliates.+ *+ *  This source code is licensed under the MIT license found in the LICENSE+ *  file in the root directory of this source tree.+ *+ */+#pragma once+#include <algorithm>+#include <array>+#include <cmath>+#include <vector>+#include "Yoga.h"++using YGVector = std::vector<YGNodeRef>;++YG_EXTERN_C_BEGIN++WIN_EXPORT float YGRoundValueToPixelGrid(+    const float value,+    const float pointScaleFactor,+    const bool forceCeil,+    const bool forceFloor);++YG_EXTERN_C_END++namespace facebook {+namespace yoga {++inline bool isUndefined(float value) {+  // Value of a float in the case of it being not defined is 10.1E20. Earlier+  // it used to be NAN, the benefit of which was that if NAN is involved in any+  // mathematical expression the result was NAN. But since we want to have+  // `-ffast-math` flag being used by compiler which assumes that the floating+  // point values are not NAN and Inf, we represent YGUndefined as 10.1E20. But+  // now if YGUndefined is involved in any mathematical operations this+  // value(10.1E20) would change. So the following check makes sure that if the+  // value is outside a range (-10E8, 10E8) then it is undefined.+  return value >= 10E8 || value <= -10E8;+}++} // namespace yoga+} // namespace facebook++using namespace facebook;++extern const std::array<YGEdge, 4> trailing;+extern const std::array<YGEdge, 4> leading;+extern bool YGValueEqual(const YGValue a, const YGValue b);+extern const YGValue YGValueUndefined;+extern const YGValue YGValueAuto;+extern const YGValue YGValueZero;++template <std::size_t size>+bool YGValueArrayEqual(+    const std::array<YGValue, size> val1,+    const std::array<YGValue, size> val2) {+  bool areEqual = true;+  for (uint32_t i = 0; i < size && areEqual; ++i) {+    areEqual = YGValueEqual(val1[i], val2[i]);+  }+  return areEqual;+}++struct YGCachedMeasurement {+  float availableWidth;+  float availableHeight;+  YGMeasureMode widthMeasureMode;+  YGMeasureMode heightMeasureMode;++  float computedWidth;+  float computedHeight;++  YGCachedMeasurement()+      : availableWidth(0),+        availableHeight(0),+        widthMeasureMode((YGMeasureMode)-1),+        heightMeasureMode((YGMeasureMode)-1),+        computedWidth(-1),+        computedHeight(-1) {}++  bool operator==(YGCachedMeasurement measurement) const {+    bool isEqual = widthMeasureMode == measurement.widthMeasureMode &&+        heightMeasureMode == measurement.heightMeasureMode;++    if (!yoga::isUndefined(availableWidth) ||+        !yoga::isUndefined(measurement.availableWidth)) {+      isEqual = isEqual && availableWidth == measurement.availableWidth;+    }+    if (!yoga::isUndefined(availableHeight) ||+        !yoga::isUndefined(measurement.availableHeight)) {+      isEqual = isEqual && availableHeight == measurement.availableHeight;+    }+    if (!yoga::isUndefined(computedWidth) ||+        !yoga::isUndefined(measurement.computedWidth)) {+      isEqual = isEqual && computedWidth == measurement.computedWidth;+    }+    if (!yoga::isUndefined(computedHeight) ||+        !yoga::isUndefined(measurement.computedHeight)) {+      isEqual = isEqual && computedHeight == measurement.computedHeight;+    }++    return isEqual;+  }+};++// This value was chosen based on empiracle data. Even the most complicated+// layouts should not require more than 16 entries to fit within the cache.+#define YG_MAX_CACHED_RESULT_COUNT 16++static const float kDefaultFlexGrow = 0.0f;+static const float kDefaultFlexShrink = 0.0f;+static const float kWebDefaultFlexShrink = 1.0f;++extern bool YGFloatsEqual(const float a, const float b);+extern bool YGValueEqual(const YGValue a, const YGValue b);+extern const YGValue* YGComputedEdgeValue(+    const std::array<YGValue, YGEdgeCount>& edges,+    const YGEdge edge,+    const YGValue* const defaultValue);
yoga/Yoga.cpp view
@@ -1,3533 +1,4316 @@-/**
- * Copyright (c) 2014-present, Facebook, Inc.
- * All rights reserved.
- *
- * This source code is licensed under the BSD-style license found in the
- * LICENSE file in the root directory of this source tree. An additional grant
- * of patent rights can be found in the PATENTS file in the same directory.
- */
-
-#include "Yoga.h"
-#include <string.h>
-#include <algorithm>
-#include "YGNodePrint.h"
-#include "Yoga-internal.h"
-
-#ifdef _MSC_VER
-#include <float.h>
-#ifndef isnan
-#define isnan _isnan
-#endif
-#ifndef __cplusplus
-#define inline __inline
-#endif
-
-/* define fmaxf if < VC12 */
-#if _MSC_VER < 1800
-__forceinline const float fmaxf(const float a, const float b) {
-  return (a > b) ? a : b;
-}
-#endif
-#endif
-
-#ifdef ANDROID
-static int YGAndroidLog(const YGConfigRef config,
-                        const YGNodeRef node,
-                        YGLogLevel level,
-                        const char *format,
-                        va_list args);
-#else
-static int YGDefaultLog(const YGConfigRef config,
-                        const YGNodeRef node,
-                        YGLogLevel level,
-                        const char *format,
-                        va_list args);
-#endif
-
-static YGConfig gYGConfigDefaults = {
-    .experimentalFeatures =
-        {
-            [YGExperimentalFeatureWebFlexBasis] = false,
-        },
-    .useWebDefaults = false,
-    .useLegacyStretchBehaviour = false,
-    .pointScaleFactor = 1.0f,
-#ifdef ANDROID
-    .logger = &YGAndroidLog,
-#else
-    .logger = &YGDefaultLog,
-#endif
-    .cloneNodeCallback = nullptr,
-    .context = nullptr,
-};
-
-static void YGNodeMarkDirtyInternal(const YGNodeRef node);
-
-static YGValue YGValueZero = {.value = 0, .unit = YGUnitPoint};
-
-static bool YGNodeListDelete(YGVector& list, const YGNodeRef node) {
-  std::vector<YGNodeRef>::iterator p =
-      std::find(list.begin(), list.end(), node);
-  if (p != list.end()) {
-    list.erase(p);
-    return true;
-  }
-  return false;
-}
-
-#ifdef ANDROID
-#include <android/log.h>
-static int YGAndroidLog(const YGConfigRef config,
-                        const YGNodeRef node,
-                        YGLogLevel level,
-                        const char *format,
-                        va_list args) {
-  int androidLevel = YGLogLevelDebug;
-  switch (level) {
-    case YGLogLevelFatal:
-      androidLevel = ANDROID_LOG_FATAL;
-      break;
-    case YGLogLevelError:
-      androidLevel = ANDROID_LOG_ERROR;
-      break;
-    case YGLogLevelWarn:
-      androidLevel = ANDROID_LOG_WARN;
-      break;
-    case YGLogLevelInfo:
-      androidLevel = ANDROID_LOG_INFO;
-      break;
-    case YGLogLevelDebug:
-      androidLevel = ANDROID_LOG_DEBUG;
-      break;
-    case YGLogLevelVerbose:
-      androidLevel = ANDROID_LOG_VERBOSE;
-      break;
-  }
-  const int result = __android_log_vprint(androidLevel, "yoga", format, args);
-  return result;
-}
-#else
-#define YG_UNUSED(x) (void)(x);
-
-static int YGDefaultLog(const YGConfigRef config,
-                        const YGNodeRef node,
-                        YGLogLevel level,
-                        const char *format,
-                        va_list args) {
-  YG_UNUSED(config);
-  YG_UNUSED(node);
-  switch (level) {
-    case YGLogLevelError:
-    case YGLogLevelFatal:
-      return vfprintf(stderr, format, args);
-    case YGLogLevelWarn:
-    case YGLogLevelInfo:
-    case YGLogLevelDebug:
-    case YGLogLevelVerbose:
-    default:
-      return vprintf(format, args);
-  }
-}
-
-#undef YG_UNUSED
-#endif
-
-bool YGFloatIsUndefined(const float value) {
-  return isnan(value);
-}
-
-const YGValue* YGComputedEdgeValue(
-    const YGValue edges[YGEdgeCount],
-    const YGEdge edge,
-    const YGValue* const defaultValue) {
-  if (edges[edge].unit != YGUnitUndefined) {
-    return &edges[edge];
-  }
-
-  if ((edge == YGEdgeTop || edge == YGEdgeBottom) &&
-      edges[YGEdgeVertical].unit != YGUnitUndefined) {
-    return &edges[YGEdgeVertical];
-  }
-
-  if ((edge == YGEdgeLeft || edge == YGEdgeRight || edge == YGEdgeStart || edge == YGEdgeEnd) &&
-      edges[YGEdgeHorizontal].unit != YGUnitUndefined) {
-    return &edges[YGEdgeHorizontal];
-  }
-
-  if (edges[YGEdgeAll].unit != YGUnitUndefined) {
-    return &edges[YGEdgeAll];
-  }
-
-  if (edge == YGEdgeStart || edge == YGEdgeEnd) {
-    return &YGValueUndefined;
-  }
-
-  return defaultValue;
-}
-
-static inline float YGResolveValue(const YGValue *const value, const float parentSize) {
-  switch (value->unit) {
-    case YGUnitUndefined:
-    case YGUnitAuto:
-      return YGUndefined;
-    case YGUnitPoint:
-      return value->value;
-    case YGUnitPercent:
-      return value->value * parentSize / 100.0f;
-  }
-  return YGUndefined;
-}
-
-static inline float YGResolveValueMargin(const YGValue *const value, const float parentSize) {
-  return value->unit == YGUnitAuto ? 0 : YGResolveValue(value, parentSize);
-}
-
-int32_t gNodeInstanceCount = 0;
-int32_t gConfigInstanceCount = 0;
-
-WIN_EXPORT YGNodeRef YGNodeNewWithConfig(const YGConfigRef config) {
-  const YGNodeRef node = (const YGNodeRef)malloc(sizeof(YGNode));
-  YGAssertWithConfig(
-      config, node != nullptr, "Could not allocate memory for node");
-  gNodeInstanceCount++;
-
-  memcpy(node, &gYGNodeDefaults, sizeof(YGNode));
-  if (config->useWebDefaults) {
-    node->style.flexDirection = YGFlexDirectionRow;
-    node->style.alignContent = YGAlignStretch;
-  }
-  node->config = config;
-  return node;
-}
-
-YGNodeRef YGNodeNew(void) {
-  return YGNodeNewWithConfig(&gYGConfigDefaults);
-}
-
-YGNodeRef YGNodeClone(YGNodeRef oldNode) {
-  YGNodeRef node = new YGNode(*oldNode);
-  YGAssertWithConfig(
-      oldNode->config, node != nullptr, "Could not allocate memory for node");
-  gNodeInstanceCount++;
-  node->parent = nullptr;
-  return node;
-}
-
-void YGNodeFree(const YGNodeRef node) {
-  if (node->parent) {
-    YGNodeListDelete(node->parent->children, node);
-    node->parent = nullptr;
-  }
-
-  const uint32_t childCount = YGNodeGetChildCount(node);
-  for (uint32_t i = 0; i < childCount; i++) {
-    const YGNodeRef child = YGNodeGetChild(node, i);
-    child->parent = nullptr;
-  }
-
-  YGVector().swap(node->children);
-  free(node);
-  gNodeInstanceCount--;
-}
-
-void YGNodeFreeRecursive(const YGNodeRef root) {
-  while (YGNodeGetChildCount(root) > 0) {
-    const YGNodeRef child = YGNodeGetChild(root, 0);
-    if (child->parent != root) {
-      // Don't free shared nodes that we don't own.
-      break;
-    }
-    YGNodeRemoveChild(root, child);
-    YGNodeFreeRecursive(child);
-  }
-  YGNodeFree(root);
-}
-
-void YGNodeReset(const YGNodeRef node) {
-  YGAssertWithNode(node,
-                   YGNodeGetChildCount(node) == 0,
-                   "Cannot reset a node which still has children attached");
-  YGAssertWithNode(
-      node,
-      node->parent == nullptr,
-      "Cannot reset a node still attached to a parent");
-
-  YGVector().swap(node->children);
-
-  const YGConfigRef config = node->config;
-  memcpy(node, &gYGNodeDefaults, sizeof(YGNode));
-  if (config->useWebDefaults) {
-    node->style.flexDirection = YGFlexDirectionRow;
-    node->style.alignContent = YGAlignStretch;
-  }
-  node->config = config;
-}
-
-int32_t YGNodeGetInstanceCount(void) {
-  return gNodeInstanceCount;
-}
-
-int32_t YGConfigGetInstanceCount(void) {
-  return gConfigInstanceCount;
-}
-
-// Export only for C#
-YGConfigRef YGConfigGetDefault() {
-  return &gYGConfigDefaults;
-}
-
-YGConfigRef YGConfigNew(void) {
-  const YGConfigRef config = (const YGConfigRef)malloc(sizeof(YGConfig));
-  YGAssert(config != nullptr, "Could not allocate memory for config");
-
-  gConfigInstanceCount++;
-  memcpy(config, &gYGConfigDefaults, sizeof(YGConfig));
-  return config;
-}
-
-void YGConfigFree(const YGConfigRef config) {
-  free(config);
-  gConfigInstanceCount--;
-}
-
-void YGConfigCopy(const YGConfigRef dest, const YGConfigRef src) {
-  memcpy(dest, src, sizeof(YGConfig));
-}
-
-static void YGNodeMarkDirtyInternal(const YGNodeRef node) {
-  if (!node->isDirty) {
-    node->isDirty = true;
-    node->layout.computedFlexBasis = YGUndefined;
-    if (node->parent) {
-      YGNodeMarkDirtyInternal(node->parent);
-    }
-  }
-}
-
-void YGNodeSetMeasureFunc(const YGNodeRef node, YGMeasureFunc measureFunc) {
-  if (measureFunc == nullptr) {
-    node->measure = nullptr;
-    // TODO: t18095186 Move nodeType to opt-in function and mark appropriate places in Litho
-    node->nodeType = YGNodeTypeDefault;
-  } else {
-    YGAssertWithNode(
-        node,
-        YGNodeGetChildCount(node) == 0,
-        "Cannot set measure function: Nodes with measure functions cannot have children.");
-    node->measure = measureFunc;
-    // TODO: t18095186 Move nodeType to opt-in function and mark appropriate places in Litho
-    node->nodeType = YGNodeTypeText;
-  }
-}
-
-YGMeasureFunc YGNodeGetMeasureFunc(const YGNodeRef node) {
-  return node->measure;
-}
-
-void YGNodeSetBaselineFunc(const YGNodeRef node, YGBaselineFunc baselineFunc) {
-  node->baseline = baselineFunc;
-}
-
-YGBaselineFunc YGNodeGetBaselineFunc(const YGNodeRef node) {
-  return node->baseline;
-}
-
-static void YGCloneChildrenIfNeeded(const YGNodeRef parent) {
-  // YGNodeRemoveChild has a forked variant of this algorithm optimized for deletions.
-  const uint32_t childCount = YGNodeGetChildCount(parent);
-  if (childCount == 0) {
-    // This is an empty set. Nothing to clone.
-    return;
-  }
-
-  const YGNodeRef firstChild = YGNodeGetChild(parent, 0);
-  if (firstChild->parent == parent) {
-    // If the first child has this node as its parent, we assume that it is already unique.
-    // We can do this because if we have it has a child, that means that its parent was at some
-    // point cloned which made that subtree immutable.
-    // We also assume that all its sibling are cloned as well.
-    return;
-  }
-
-  const YGNodeClonedFunc cloneNodeCallback = parent->config->cloneNodeCallback;
-  for (uint32_t i = 0; i < childCount; i++) {
-    const YGNodeRef oldChild = parent->children[i];
-    const YGNodeRef newChild = YGNodeClone(oldChild);
-    parent->children[i] = newChild;
-    newChild->parent = parent;
-    if (cloneNodeCallback) {
-      cloneNodeCallback(oldChild, newChild, parent, i);
-    }
-  }
-}
-
-void YGNodeInsertChild(const YGNodeRef node, const YGNodeRef child, const uint32_t index) {
-  YGAssertWithNode(
-      node,
-      child->parent == nullptr,
-      "Child already has a parent, it must be removed first.");
-  YGAssertWithNode(
-      node,
-      node->measure == nullptr,
-      "Cannot add child: Nodes with measure functions cannot have children.");
-
-  YGCloneChildrenIfNeeded(node);
-  node->children.insert(node->children.begin() + index, child);
-  child->parent = node;
-  YGNodeMarkDirtyInternal(node);
-}
-
-void YGNodeRemoveChild(const YGNodeRef parent, const YGNodeRef excludedChild) {
-  // This algorithm is a forked variant from YGCloneChildrenIfNeeded that excludes a child.
-  const uint32_t childCount = YGNodeGetChildCount(parent);
-
-  if (childCount == 0) {
-    // This is an empty set. Nothing to remove.
-    return;
-  }
-  const YGNodeRef firstChild = YGNodeGetChild(parent, 0);
-  if (firstChild->parent == parent) {
-    // If the first child has this node as its parent, we assume that it is already unique.
-    // We can now try to delete a child in this list.
-    if (YGNodeListDelete(parent->children, excludedChild)) {
-      excludedChild->layout = gYGNodeDefaults.layout; // layout is no longer valid
-      excludedChild->parent = nullptr;
-      YGNodeMarkDirtyInternal(parent);
-    }
-    return;
-  }
-  // Otherwise we have to clone the node list except for the child we're trying to delete.
-  // We don't want to simply clone all children, because then the host will need to free
-  // the clone of the child that was just deleted.
-  const YGNodeClonedFunc cloneNodeCallback = parent->config->cloneNodeCallback;
-  uint32_t nextInsertIndex = 0;
-  for (uint32_t i = 0; i < childCount; i++) {
-    const YGNodeRef oldChild = parent->children[i];
-    if (excludedChild == oldChild) {
-      // Ignore the deleted child. Don't reset its layout or parent since it is still valid
-      // in the other parent. However, since this parent has now changed, we need to mark it
-      // as dirty.
-      YGNodeMarkDirtyInternal(parent);
-      continue;
-    }
-    const YGNodeRef newChild = YGNodeClone(oldChild);
-    parent->children[nextInsertIndex] = newChild;
-    newChild->parent = parent;
-    if (cloneNodeCallback) {
-      cloneNodeCallback(oldChild, newChild, parent, nextInsertIndex);
-    }
-    nextInsertIndex++;
-  }
-  while (nextInsertIndex < childCount) {
-    parent->children.erase(parent->children.begin() + nextInsertIndex);
-    nextInsertIndex++;
-  }
-}
-
-void YGNodeRemoveAllChildren(const YGNodeRef parent) {
-  const uint32_t childCount = YGNodeGetChildCount(parent);
-  if (childCount == 0) {
-    // This is an empty set already. Nothing to do.
-    return;
-  }
-  const YGNodeRef firstChild = YGNodeGetChild(parent, 0);
-  if (firstChild->parent == parent) {
-    // If the first child has this node as its parent, we assume that this child set is unique.
-    for (uint32_t i = 0; i < childCount; i++) {
-      const YGNodeRef oldChild = YGNodeGetChild(parent, i);
-      oldChild->layout = gYGNodeDefaults.layout; // layout is no longer valid
-      oldChild->parent = nullptr;
-    }
-    YGVector().swap(parent->children);
-    YGNodeMarkDirtyInternal(parent);
-    return;
-  }
-  // Otherwise, we are not the owner of the child set. We don't have to do anything to clear it.
-  parent->children = YGVector();
-  YGNodeMarkDirtyInternal(parent);
-}
-
-YGNodeRef YGNodeGetChild(const YGNodeRef node, const uint32_t index) {
-  if (index < node->children.size()) {
-    return node->children[index];
-  }
-  return nullptr;
-}
-
-YGNodeRef YGNodeGetParent(const YGNodeRef node) {
-  return node->parent;
-}
-
-uint32_t YGNodeGetChildCount(const YGNodeRef node) {
-  return node->children.size();
-}
-
-void YGNodeMarkDirty(const YGNodeRef node) {
-  YGAssertWithNode(
-      node,
-      node->measure != nullptr,
-      "Only leaf nodes with custom measure functions"
-      "should manually mark themselves as dirty");
-
-  YGNodeMarkDirtyInternal(node);
-}
-
-bool YGNodeIsDirty(const YGNodeRef node) {
-  return node->isDirty;
-}
-
-void YGNodeCopyStyle(const YGNodeRef dstNode, const YGNodeRef srcNode) {
-  if (memcmp(&dstNode->style, &srcNode->style, sizeof(YGStyle)) != 0) {
-    memcpy(&dstNode->style, &srcNode->style, sizeof(YGStyle));
-    YGNodeMarkDirtyInternal(dstNode);
-  }
-}
-
-static inline float YGResolveFlexGrow(const YGNodeRef node) {
-  // Root nodes flexGrow should always be 0
-  if (node->parent == nullptr) {
-    return 0.0;
-  }
-  if (!YGFloatIsUndefined(node->style.flexGrow)) {
-    return node->style.flexGrow;
-  }
-  if (!YGFloatIsUndefined(node->style.flex) && node->style.flex > 0.0f) {
-    return node->style.flex;
-  }
-  return kDefaultFlexGrow;
-}
-
-float YGNodeStyleGetFlexGrow(const YGNodeRef node) {
-  return YGFloatIsUndefined(node->style.flexGrow) ? kDefaultFlexGrow : node->style.flexGrow;
-}
-
-float YGNodeStyleGetFlexShrink(const YGNodeRef node) {
-  return YGFloatIsUndefined(node->style.flexShrink)
-             ? (node->config->useWebDefaults ? kWebDefaultFlexShrink : kDefaultFlexShrink)
-             : node->style.flexShrink;
-}
-
-static inline float YGNodeResolveFlexShrink(const YGNodeRef node) {
-  // Root nodes flexShrink should always be 0
-  if (node->parent == nullptr) {
-    return 0.0;
-  }
-  if (!YGFloatIsUndefined(node->style.flexShrink)) {
-    return node->style.flexShrink;
-  }
-  if (!node->config->useWebDefaults && !YGFloatIsUndefined(node->style.flex) &&
-      node->style.flex < 0.0f) {
-    return -node->style.flex;
-  }
-  return node->config->useWebDefaults ? kWebDefaultFlexShrink : kDefaultFlexShrink;
-}
-
-static inline const YGValue *YGNodeResolveFlexBasisPtr(const YGNodeRef node) {
-  if (node->style.flexBasis.unit != YGUnitAuto && node->style.flexBasis.unit != YGUnitUndefined) {
-    return &node->style.flexBasis;
-  }
-  if (!YGFloatIsUndefined(node->style.flex) && node->style.flex > 0.0f) {
-    return node->config->useWebDefaults ? &YGValueAuto : &YGValueZero;
-  }
-  return &YGValueAuto;
-}
-
-#define YG_NODE_PROPERTY_IMPL(type, name, paramName, instanceName) \
-  void YGNodeSet##name(const YGNodeRef node, type paramName) {     \
-    node->instanceName = paramName;                                \
-  }                                                                \
-                                                                   \
-  type YGNodeGet##name(const YGNodeRef node) {                     \
-    return node->instanceName;                                     \
-  }
-
-#define YG_NODE_STYLE_PROPERTY_SETTER_IMPL(type, name, paramName, instanceName) \
-  void YGNodeStyleSet##name(const YGNodeRef node, const type paramName) {       \
-    if (node->style.instanceName != paramName) {                                \
-      node->style.instanceName = paramName;                                     \
-      YGNodeMarkDirtyInternal(node);                                            \
-    }                                                                           \
-  }
-
-#define YG_NODE_STYLE_PROPERTY_SETTER_UNIT_IMPL(                               \
-    type, name, paramName, instanceName)                                       \
-  void YGNodeStyleSet##name(const YGNodeRef node, const type paramName) {      \
-    YGValue value = {                                                          \
-        .value = paramName,                                                    \
-        .unit = YGFloatIsUndefined(paramName) ? YGUnitUndefined : YGUnitPoint, \
-    };                                                                         \
-    if ((node->style.instanceName.value != value.value &&                      \
-         value.unit != YGUnitUndefined) ||                                     \
-        node->style.instanceName.unit != value.unit) {                         \
-      node->style.instanceName = value;                                        \
-      YGNodeMarkDirtyInternal(node);                                           \
-    }                                                                          \
-  }                                                                            \
-                                                                               \
-  void YGNodeStyleSet##name##Percent(                                          \
-      const YGNodeRef node, const type paramName) {                            \
-    YGValue value = {                                                          \
-        .value = paramName,                                                    \
-        .unit =                                                                \
-            YGFloatIsUndefined(paramName) ? YGUnitUndefined : YGUnitPercent,   \
-    };                                                                         \
-    if ((node->style.instanceName.value != value.value &&                      \
-         value.unit != YGUnitUndefined) ||                                     \
-        node->style.instanceName.unit != value.unit) {                         \
-      node->style.instanceName = value;                                        \
-      YGNodeMarkDirtyInternal(node);                                           \
-    }                                                                          \
-  }
-
-#define YG_NODE_STYLE_PROPERTY_SETTER_UNIT_AUTO_IMPL(                          \
-    type, name, paramName, instanceName)                                       \
-  void YGNodeStyleSet##name(const YGNodeRef node, const type paramName) {      \
-    YGValue value = {                                                          \
-        .value = paramName,                                                    \
-        .unit = YGFloatIsUndefined(paramName) ? YGUnitUndefined : YGUnitPoint, \
-    };                                                                         \
-    if ((node->style.instanceName.value != value.value &&                      \
-         value.unit != YGUnitUndefined) ||                                     \
-        node->style.instanceName.unit != value.unit) {                         \
-      node->style.instanceName = value;                                        \
-      YGNodeMarkDirtyInternal(node);                                           \
-    }                                                                          \
-  }                                                                            \
-                                                                               \
-  void YGNodeStyleSet##name##Percent(                                          \
-      const YGNodeRef node, const type paramName) {                            \
-    if (node->style.instanceName.value != paramName ||                         \
-        node->style.instanceName.unit != YGUnitPercent) {                      \
-      node->style.instanceName.value = paramName;                              \
-      node->style.instanceName.unit =                                          \
-          YGFloatIsUndefined(paramName) ? YGUnitAuto : YGUnitPercent;          \
-      YGNodeMarkDirtyInternal(node);                                           \
-    }                                                                          \
-  }                                                                            \
-                                                                               \
-  void YGNodeStyleSet##name##Auto(const YGNodeRef node) {                      \
-    if (node->style.instanceName.unit != YGUnitAuto) {                         \
-      node->style.instanceName.value = YGUndefined;                            \
-      node->style.instanceName.unit = YGUnitAuto;                              \
-      YGNodeMarkDirtyInternal(node);                                           \
-    }                                                                          \
-  }
-
-#define YG_NODE_STYLE_PROPERTY_IMPL(type, name, paramName, instanceName)  \
-  YG_NODE_STYLE_PROPERTY_SETTER_IMPL(type, name, paramName, instanceName) \
-                                                                          \
-  type YGNodeStyleGet##name(const YGNodeRef node) {                       \
-    return node->style.instanceName;                                      \
-  }
-
-#define YG_NODE_STYLE_PROPERTY_UNIT_IMPL(type, name, paramName, instanceName)   \
-  YG_NODE_STYLE_PROPERTY_SETTER_UNIT_IMPL(float, name, paramName, instanceName) \
-                                                                                \
-  type YGNodeStyleGet##name(const YGNodeRef node) {                             \
-    return node->style.instanceName;                                            \
-  }
-
-#define YG_NODE_STYLE_PROPERTY_UNIT_AUTO_IMPL(type, name, paramName, instanceName)   \
-  YG_NODE_STYLE_PROPERTY_SETTER_UNIT_AUTO_IMPL(float, name, paramName, instanceName) \
-                                                                                     \
-  type YGNodeStyleGet##name(const YGNodeRef node) {                                  \
-    return node->style.instanceName;                                                 \
-  }
-
-#define YG_NODE_STYLE_EDGE_PROPERTY_UNIT_AUTO_IMPL(type, name, instanceName) \
-  void YGNodeStyleSet##name##Auto(const YGNodeRef node, const YGEdge edge) { \
-    if (node->style.instanceName[edge].unit != YGUnitAuto) {                 \
-      node->style.instanceName[edge].value = YGUndefined;                    \
-      node->style.instanceName[edge].unit = YGUnitAuto;                      \
-      YGNodeMarkDirtyInternal(node);                                         \
-    }                                                                        \
-  }
-
-#define YG_NODE_STYLE_EDGE_PROPERTY_UNIT_IMPL(                                 \
-    type, name, paramName, instanceName)                                       \
-  void YGNodeStyleSet##name(                                                   \
-      const YGNodeRef node, const YGEdge edge, const float paramName) {        \
-    YGValue value = {                                                          \
-        .value = paramName,                                                    \
-        .unit = YGFloatIsUndefined(paramName) ? YGUnitUndefined : YGUnitPoint, \
-    };                                                                         \
-    if ((node->style.instanceName[edge].value != value.value &&                \
-         value.unit != YGUnitUndefined) ||                                     \
-        node->style.instanceName[edge].unit != value.unit) {                   \
-      node->style.instanceName[edge] = value;                                  \
-      YGNodeMarkDirtyInternal(node);                                           \
-    }                                                                          \
-  }                                                                            \
-                                                                               \
-  void YGNodeStyleSet##name##Percent(                                          \
-      const YGNodeRef node, const YGEdge edge, const float paramName) {        \
-    YGValue value = {                                                          \
-        .value = paramName,                                                    \
-        .unit =                                                                \
-            YGFloatIsUndefined(paramName) ? YGUnitUndefined : YGUnitPercent,   \
-    };                                                                         \
-    if ((node->style.instanceName[edge].value != value.value &&                \
-         value.unit != YGUnitUndefined) ||                                     \
-        node->style.instanceName[edge].unit != value.unit) {                   \
-      node->style.instanceName[edge] = value;                                  \
-      YGNodeMarkDirtyInternal(node);                                           \
-    }                                                                          \
-  }                                                                            \
-                                                                               \
-  WIN_STRUCT(type)                                                             \
-  YGNodeStyleGet##name(const YGNodeRef node, const YGEdge edge) {              \
-    return WIN_STRUCT_REF(node->style.instanceName[edge]);                     \
-  }
-
-#define YG_NODE_STYLE_EDGE_PROPERTY_IMPL(type, name, paramName, instanceName)  \
-  void YGNodeStyleSet##name(                                                   \
-      const YGNodeRef node, const YGEdge edge, const float paramName) {        \
-    YGValue value = {                                                          \
-        .value = paramName,                                                    \
-        .unit = YGFloatIsUndefined(paramName) ? YGUnitUndefined : YGUnitPoint, \
-    };                                                                         \
-    if ((node->style.instanceName[edge].value != value.value &&                \
-         value.unit != YGUnitUndefined) ||                                     \
-        node->style.instanceName[edge].unit != value.unit) {                   \
-      node->style.instanceName[edge] = value;                                  \
-      YGNodeMarkDirtyInternal(node);                                           \
-    }                                                                          \
-  }                                                                            \
-                                                                               \
-  float YGNodeStyleGet##name(const YGNodeRef node, const YGEdge edge) {        \
-    return node->style.instanceName[edge].value;                               \
-  }
-
-#define YG_NODE_LAYOUT_PROPERTY_IMPL(type, name, instanceName) \
-  type YGNodeLayoutGet##name(const YGNodeRef node) {           \
-    return node->layout.instanceName;                          \
-  }
-
-#define YG_NODE_LAYOUT_RESOLVED_PROPERTY_IMPL(type, name, instanceName) \
-  type YGNodeLayoutGet##name(const YGNodeRef node, const YGEdge edge) { \
-    YGAssertWithNode(                                                   \
-        node,                                                           \
-        edge <= YGEdgeEnd,                                              \
-        "Cannot get layout properties of multi-edge shorthands");       \
-                                                                        \
-    if (edge == YGEdgeLeft) {                                           \
-      if (node->layout.direction == YGDirectionRTL) {                   \
-        return node->layout.instanceName[YGEdgeEnd];                    \
-      } else {                                                          \
-        return node->layout.instanceName[YGEdgeStart];                  \
-      }                                                                 \
-    }                                                                   \
-                                                                        \
-    if (edge == YGEdgeRight) {                                          \
-      if (node->layout.direction == YGDirectionRTL) {                   \
-        return node->layout.instanceName[YGEdgeStart];                  \
-      } else {                                                          \
-        return node->layout.instanceName[YGEdgeEnd];                    \
-      }                                                                 \
-    }                                                                   \
-                                                                        \
-    return node->layout.instanceName[edge];                             \
-  }
-
-YG_NODE_PROPERTY_IMPL(void *, Context, context, context);
-YG_NODE_PROPERTY_IMPL(YGPrintFunc, PrintFunc, printFunc, print);
-YG_NODE_PROPERTY_IMPL(bool, HasNewLayout, hasNewLayout, hasNewLayout);
-YG_NODE_PROPERTY_IMPL(YGNodeType, NodeType, nodeType, nodeType);
-
-YG_NODE_STYLE_PROPERTY_IMPL(YGDirection, Direction, direction, direction);
-YG_NODE_STYLE_PROPERTY_IMPL(YGFlexDirection, FlexDirection, flexDirection, flexDirection);
-YG_NODE_STYLE_PROPERTY_IMPL(YGJustify, JustifyContent, justifyContent, justifyContent);
-YG_NODE_STYLE_PROPERTY_IMPL(YGAlign, AlignContent, alignContent, alignContent);
-YG_NODE_STYLE_PROPERTY_IMPL(YGAlign, AlignItems, alignItems, alignItems);
-YG_NODE_STYLE_PROPERTY_IMPL(YGAlign, AlignSelf, alignSelf, alignSelf);
-YG_NODE_STYLE_PROPERTY_IMPL(YGPositionType, PositionType, positionType, positionType);
-YG_NODE_STYLE_PROPERTY_IMPL(YGWrap, FlexWrap, flexWrap, flexWrap);
-YG_NODE_STYLE_PROPERTY_IMPL(YGOverflow, Overflow, overflow, overflow);
-YG_NODE_STYLE_PROPERTY_IMPL(YGDisplay, Display, display, display);
-
-YG_NODE_STYLE_PROPERTY_IMPL(float, Flex, flex, flex);
-YG_NODE_STYLE_PROPERTY_SETTER_IMPL(float, FlexGrow, flexGrow, flexGrow);
-YG_NODE_STYLE_PROPERTY_SETTER_IMPL(float, FlexShrink, flexShrink, flexShrink);
-YG_NODE_STYLE_PROPERTY_UNIT_AUTO_IMPL(YGValue, FlexBasis, flexBasis, flexBasis);
-
-YG_NODE_STYLE_EDGE_PROPERTY_UNIT_IMPL(YGValue, Position, position, position);
-YG_NODE_STYLE_EDGE_PROPERTY_UNIT_IMPL(YGValue, Margin, margin, margin);
-YG_NODE_STYLE_EDGE_PROPERTY_UNIT_AUTO_IMPL(YGValue, Margin, margin);
-YG_NODE_STYLE_EDGE_PROPERTY_UNIT_IMPL(YGValue, Padding, padding, padding);
-YG_NODE_STYLE_EDGE_PROPERTY_IMPL(float, Border, border, border);
-
-YG_NODE_STYLE_PROPERTY_UNIT_AUTO_IMPL(YGValue, Width, width, dimensions[YGDimensionWidth]);
-YG_NODE_STYLE_PROPERTY_UNIT_AUTO_IMPL(YGValue, Height, height, dimensions[YGDimensionHeight]);
-YG_NODE_STYLE_PROPERTY_UNIT_IMPL(YGValue, MinWidth, minWidth, minDimensions[YGDimensionWidth]);
-YG_NODE_STYLE_PROPERTY_UNIT_IMPL(YGValue, MinHeight, minHeight, minDimensions[YGDimensionHeight]);
-YG_NODE_STYLE_PROPERTY_UNIT_IMPL(YGValue, MaxWidth, maxWidth, maxDimensions[YGDimensionWidth]);
-YG_NODE_STYLE_PROPERTY_UNIT_IMPL(YGValue, MaxHeight, maxHeight, maxDimensions[YGDimensionHeight]);
-
-// Yoga specific properties, not compatible with flexbox specification
-YG_NODE_STYLE_PROPERTY_IMPL(float, AspectRatio, aspectRatio, aspectRatio);
-
-YG_NODE_LAYOUT_PROPERTY_IMPL(float, Left, position[YGEdgeLeft]);
-YG_NODE_LAYOUT_PROPERTY_IMPL(float, Top, position[YGEdgeTop]);
-YG_NODE_LAYOUT_PROPERTY_IMPL(float, Right, position[YGEdgeRight]);
-YG_NODE_LAYOUT_PROPERTY_IMPL(float, Bottom, position[YGEdgeBottom]);
-YG_NODE_LAYOUT_PROPERTY_IMPL(float, Width, dimensions[YGDimensionWidth]);
-YG_NODE_LAYOUT_PROPERTY_IMPL(float, Height, dimensions[YGDimensionHeight]);
-YG_NODE_LAYOUT_PROPERTY_IMPL(YGDirection, Direction, direction);
-YG_NODE_LAYOUT_PROPERTY_IMPL(bool, HadOverflow, hadOverflow);
-
-YG_NODE_LAYOUT_RESOLVED_PROPERTY_IMPL(float, Margin, margin);
-YG_NODE_LAYOUT_RESOLVED_PROPERTY_IMPL(float, Border, border);
-YG_NODE_LAYOUT_RESOLVED_PROPERTY_IMPL(float, Padding, padding);
-
-uint32_t gCurrentGenerationCount = 0;
-
-bool YGLayoutNodeInternal(const YGNodeRef node,
-                          const float availableWidth,
-                          const float availableHeight,
-                          const YGDirection parentDirection,
-                          const YGMeasureMode widthMeasureMode,
-                          const YGMeasureMode heightMeasureMode,
-                          const float parentWidth,
-                          const float parentHeight,
-                          const bool performLayout,
-                          const char *reason,
-                          const YGConfigRef config);
-
-bool YGValueEqual(const YGValue a, const YGValue b) {
-  if (a.unit != b.unit) {
-    return false;
-  }
-
-  if (a.unit == YGUnitUndefined) {
-    return true;
-  }
-
-  return fabs(a.value - b.value) < 0.0001f;
-}
-
-static inline void YGResolveDimensions(YGNodeRef node) {
-  for (uint32_t dim = YGDimensionWidth; dim < YGDimensionCount; dim++) {
-    if (node->style.maxDimensions[dim].unit != YGUnitUndefined &&
-        YGValueEqual(node->style.maxDimensions[dim], node->style.minDimensions[dim])) {
-      node->resolvedDimensions[dim] = &node->style.maxDimensions[dim];
-    } else {
-      node->resolvedDimensions[dim] = &node->style.dimensions[dim];
-    }
-  }
-}
-
-bool YGFloatsEqual(const float a, const float b) {
-  if (YGFloatIsUndefined(a)) {
-    return YGFloatIsUndefined(b);
-  }
-  return fabs(a - b) < 0.0001f;
-}
-
-static void YGNodePrintInternal(const YGNodeRef node,
-                                const YGPrintOptions options) {
-  std::string str;
-  facebook::yoga::YGNodeToString(&str, node, options, 0);
-  YGLog(node, YGLogLevelDebug, str.c_str());
-}
-
-void YGNodePrint(const YGNodeRef node, const YGPrintOptions options) {
-  YGNodePrintInternal(node, options);
-}
-
-static const YGEdge leading[4] = {
-        [YGFlexDirectionColumn] = YGEdgeTop,
-        [YGFlexDirectionColumnReverse] = YGEdgeBottom,
-        [YGFlexDirectionRow] = YGEdgeLeft,
-        [YGFlexDirectionRowReverse] = YGEdgeRight,
-};
-static const YGEdge trailing[4] = {
-        [YGFlexDirectionColumn] = YGEdgeBottom,
-        [YGFlexDirectionColumnReverse] = YGEdgeTop,
-        [YGFlexDirectionRow] = YGEdgeRight,
-        [YGFlexDirectionRowReverse] = YGEdgeLeft,
-};
-static const YGEdge pos[4] = {
-        [YGFlexDirectionColumn] = YGEdgeTop,
-        [YGFlexDirectionColumnReverse] = YGEdgeBottom,
-        [YGFlexDirectionRow] = YGEdgeLeft,
-        [YGFlexDirectionRowReverse] = YGEdgeRight,
-};
-static const YGDimension dim[4] = {
-        [YGFlexDirectionColumn] = YGDimensionHeight,
-        [YGFlexDirectionColumnReverse] = YGDimensionHeight,
-        [YGFlexDirectionRow] = YGDimensionWidth,
-        [YGFlexDirectionRowReverse] = YGDimensionWidth,
-};
-
-static inline bool YGFlexDirectionIsRow(const YGFlexDirection flexDirection) {
-  return flexDirection == YGFlexDirectionRow || flexDirection == YGFlexDirectionRowReverse;
-}
-
-static inline bool YGFlexDirectionIsColumn(const YGFlexDirection flexDirection) {
-  return flexDirection == YGFlexDirectionColumn || flexDirection == YGFlexDirectionColumnReverse;
-}
-
-static inline float YGNodeLeadingMargin(const YGNodeRef node,
-                                        const YGFlexDirection axis,
-                                        const float widthSize) {
-  if (YGFlexDirectionIsRow(axis) && node->style.margin[YGEdgeStart].unit != YGUnitUndefined) {
-    return YGResolveValueMargin(&node->style.margin[YGEdgeStart], widthSize);
-  }
-
-  return YGResolveValueMargin(YGComputedEdgeValue(node->style.margin, leading[axis], &YGValueZero),
-                              widthSize);
-}
-
-static float YGNodeTrailingMargin(const YGNodeRef node,
-                                  const YGFlexDirection axis,
-                                  const float widthSize) {
-  if (YGFlexDirectionIsRow(axis) && node->style.margin[YGEdgeEnd].unit != YGUnitUndefined) {
-    return YGResolveValueMargin(&node->style.margin[YGEdgeEnd], widthSize);
-  }
-
-  return YGResolveValueMargin(YGComputedEdgeValue(node->style.margin, trailing[axis], &YGValueZero),
-                              widthSize);
-}
-
-static float YGNodeLeadingPadding(const YGNodeRef node,
-                                  const YGFlexDirection axis,
-                                  const float widthSize) {
-  if (YGFlexDirectionIsRow(axis) && node->style.padding[YGEdgeStart].unit != YGUnitUndefined &&
-      YGResolveValue(&node->style.padding[YGEdgeStart], widthSize) >= 0.0f) {
-    return YGResolveValue(&node->style.padding[YGEdgeStart], widthSize);
-  }
-
-  return fmaxf(YGResolveValue(YGComputedEdgeValue(node->style.padding, leading[axis], &YGValueZero),
-                              widthSize),
-               0.0f);
-}
-
-static float YGNodeTrailingPadding(const YGNodeRef node,
-                                   const YGFlexDirection axis,
-                                   const float widthSize) {
-  if (YGFlexDirectionIsRow(axis) && node->style.padding[YGEdgeEnd].unit != YGUnitUndefined &&
-      YGResolveValue(&node->style.padding[YGEdgeEnd], widthSize) >= 0.0f) {
-    return YGResolveValue(&node->style.padding[YGEdgeEnd], widthSize);
-  }
-
-  return fmaxf(YGResolveValue(YGComputedEdgeValue(node->style.padding, trailing[axis], &YGValueZero),
-                              widthSize),
-               0.0f);
-}
-
-static float YGNodeLeadingBorder(const YGNodeRef node, const YGFlexDirection axis) {
-  if (YGFlexDirectionIsRow(axis) && node->style.border[YGEdgeStart].unit != YGUnitUndefined &&
-      node->style.border[YGEdgeStart].value >= 0.0f) {
-    return node->style.border[YGEdgeStart].value;
-  }
-
-  return fmaxf(YGComputedEdgeValue(node->style.border, leading[axis], &YGValueZero)->value, 0.0f);
-}
-
-static float YGNodeTrailingBorder(const YGNodeRef node, const YGFlexDirection axis) {
-  if (YGFlexDirectionIsRow(axis) && node->style.border[YGEdgeEnd].unit != YGUnitUndefined &&
-      node->style.border[YGEdgeEnd].value >= 0.0f) {
-    return node->style.border[YGEdgeEnd].value;
-  }
-
-  return fmaxf(YGComputedEdgeValue(node->style.border, trailing[axis], &YGValueZero)->value, 0.0f);
-}
-
-static inline float YGNodeLeadingPaddingAndBorder(const YGNodeRef node,
-                                                  const YGFlexDirection axis,
-                                                  const float widthSize) {
-  return YGNodeLeadingPadding(node, axis, widthSize) + YGNodeLeadingBorder(node, axis);
-}
-
-static inline float YGNodeTrailingPaddingAndBorder(const YGNodeRef node,
-                                                   const YGFlexDirection axis,
-                                                   const float widthSize) {
-  return YGNodeTrailingPadding(node, axis, widthSize) + YGNodeTrailingBorder(node, axis);
-}
-
-static inline float YGNodeMarginForAxis(const YGNodeRef node,
-                                        const YGFlexDirection axis,
-                                        const float widthSize) {
-  return YGNodeLeadingMargin(node, axis, widthSize) + YGNodeTrailingMargin(node, axis, widthSize);
-}
-
-static inline float YGNodePaddingAndBorderForAxis(const YGNodeRef node,
-                                                  const YGFlexDirection axis,
-                                                  const float widthSize) {
-  return YGNodeLeadingPaddingAndBorder(node, axis, widthSize) +
-         YGNodeTrailingPaddingAndBorder(node, axis, widthSize);
-}
-
-static inline YGAlign YGNodeAlignItem(const YGNodeRef node, const YGNodeRef child) {
-  const YGAlign align =
-      child->style.alignSelf == YGAlignAuto ? node->style.alignItems : child->style.alignSelf;
-  if (align == YGAlignBaseline && YGFlexDirectionIsColumn(node->style.flexDirection)) {
-    return YGAlignFlexStart;
-  }
-  return align;
-}
-
-static inline YGDirection YGNodeResolveDirection(const YGNodeRef node,
-                                                 const YGDirection parentDirection) {
-  if (node->style.direction == YGDirectionInherit) {
-    return parentDirection > YGDirectionInherit ? parentDirection : YGDirectionLTR;
-  } else {
-    return node->style.direction;
-  }
-}
-
-static float YGBaseline(const YGNodeRef node) {
-  if (node->baseline != nullptr) {
-    const float baseline = node->baseline(node,
-                                          node->layout.measuredDimensions[YGDimensionWidth],
-                                          node->layout.measuredDimensions[YGDimensionHeight]);
-    YGAssertWithNode(node,
-                     !YGFloatIsUndefined(baseline),
-                     "Expect custom baseline function to not return NaN");
-    return baseline;
-  }
-
-  YGNodeRef baselineChild = nullptr;
-  const uint32_t childCount = YGNodeGetChildCount(node);
-  for (uint32_t i = 0; i < childCount; i++) {
-    const YGNodeRef child = YGNodeGetChild(node, i);
-    if (child->lineIndex > 0) {
-      break;
-    }
-    if (child->style.positionType == YGPositionTypeAbsolute) {
-      continue;
-    }
-    if (YGNodeAlignItem(node, child) == YGAlignBaseline) {
-      baselineChild = child;
-      break;
-    }
-
-    if (baselineChild == nullptr) {
-      baselineChild = child;
-    }
-  }
-
-  if (baselineChild == nullptr) {
-    return node->layout.measuredDimensions[YGDimensionHeight];
-  }
-
-  const float baseline = YGBaseline(baselineChild);
-  return baseline + baselineChild->layout.position[YGEdgeTop];
-}
-
-static inline YGFlexDirection YGResolveFlexDirection(const YGFlexDirection flexDirection,
-                                                     const YGDirection direction) {
-  if (direction == YGDirectionRTL) {
-    if (flexDirection == YGFlexDirectionRow) {
-      return YGFlexDirectionRowReverse;
-    } else if (flexDirection == YGFlexDirectionRowReverse) {
-      return YGFlexDirectionRow;
-    }
-  }
-
-  return flexDirection;
-}
-
-static YGFlexDirection YGFlexDirectionCross(const YGFlexDirection flexDirection,
-                                            const YGDirection direction) {
-  return YGFlexDirectionIsColumn(flexDirection)
-             ? YGResolveFlexDirection(YGFlexDirectionRow, direction)
-             : YGFlexDirectionColumn;
-}
-
-static inline bool YGNodeIsFlex(const YGNodeRef node) {
-  return (node->style.positionType == YGPositionTypeRelative &&
-          (YGResolveFlexGrow(node) != 0 || YGNodeResolveFlexShrink(node) != 0));
-}
-
-static bool YGIsBaselineLayout(const YGNodeRef node) {
-  if (YGFlexDirectionIsColumn(node->style.flexDirection)) {
-    return false;
-  }
-  if (node->style.alignItems == YGAlignBaseline) {
-    return true;
-  }
-  const uint32_t childCount = YGNodeGetChildCount(node);
-  for (uint32_t i = 0; i < childCount; i++) {
-    const YGNodeRef child = YGNodeGetChild(node, i);
-    if (child->style.positionType == YGPositionTypeRelative &&
-        child->style.alignSelf == YGAlignBaseline) {
-      return true;
-    }
-  }
-
-  return false;
-}
-
-static inline float YGNodeDimWithMargin(const YGNodeRef node,
-                                        const YGFlexDirection axis,
-                                        const float widthSize) {
-  return node->layout.measuredDimensions[dim[axis]] + YGNodeLeadingMargin(node, axis, widthSize) +
-         YGNodeTrailingMargin(node, axis, widthSize);
-}
-
-static inline bool YGNodeIsStyleDimDefined(const YGNodeRef node,
-                                           const YGFlexDirection axis,
-                                           const float parentSize) {
-  return !(node->resolvedDimensions[dim[axis]]->unit == YGUnitAuto ||
-           node->resolvedDimensions[dim[axis]]->unit == YGUnitUndefined ||
-           (node->resolvedDimensions[dim[axis]]->unit == YGUnitPoint &&
-            node->resolvedDimensions[dim[axis]]->value < 0.0f) ||
-           (node->resolvedDimensions[dim[axis]]->unit == YGUnitPercent &&
-            (node->resolvedDimensions[dim[axis]]->value < 0.0f || YGFloatIsUndefined(parentSize))));
-}
-
-static inline bool YGNodeIsLayoutDimDefined(const YGNodeRef node, const YGFlexDirection axis) {
-  const float value = node->layout.measuredDimensions[dim[axis]];
-  return !YGFloatIsUndefined(value) && value >= 0.0f;
-}
-
-static inline bool YGNodeIsLeadingPosDefined(const YGNodeRef node, const YGFlexDirection axis) {
-  return (YGFlexDirectionIsRow(axis) &&
-          YGComputedEdgeValue(node->style.position, YGEdgeStart, &YGValueUndefined)->unit !=
-              YGUnitUndefined) ||
-         YGComputedEdgeValue(node->style.position, leading[axis], &YGValueUndefined)->unit !=
-             YGUnitUndefined;
-}
-
-static inline bool YGNodeIsTrailingPosDefined(const YGNodeRef node, const YGFlexDirection axis) {
-  return (YGFlexDirectionIsRow(axis) &&
-          YGComputedEdgeValue(node->style.position, YGEdgeEnd, &YGValueUndefined)->unit !=
-              YGUnitUndefined) ||
-         YGComputedEdgeValue(node->style.position, trailing[axis], &YGValueUndefined)->unit !=
-             YGUnitUndefined;
-}
-
-static float YGNodeLeadingPosition(const YGNodeRef node,
-                                   const YGFlexDirection axis,
-                                   const float axisSize) {
-  if (YGFlexDirectionIsRow(axis)) {
-    const YGValue *leadingPosition =
-        YGComputedEdgeValue(node->style.position, YGEdgeStart, &YGValueUndefined);
-    if (leadingPosition->unit != YGUnitUndefined) {
-      return YGResolveValue(leadingPosition, axisSize);
-    }
-  }
-
-  const YGValue *leadingPosition =
-      YGComputedEdgeValue(node->style.position, leading[axis], &YGValueUndefined);
-
-  return leadingPosition->unit == YGUnitUndefined ? 0.0f
-                                                  : YGResolveValue(leadingPosition, axisSize);
-}
-
-static float YGNodeTrailingPosition(const YGNodeRef node,
-                                    const YGFlexDirection axis,
-                                    const float axisSize) {
-  if (YGFlexDirectionIsRow(axis)) {
-    const YGValue *trailingPosition =
-        YGComputedEdgeValue(node->style.position, YGEdgeEnd, &YGValueUndefined);
-    if (trailingPosition->unit != YGUnitUndefined) {
-      return YGResolveValue(trailingPosition, axisSize);
-    }
-  }
-
-  const YGValue *trailingPosition =
-      YGComputedEdgeValue(node->style.position, trailing[axis], &YGValueUndefined);
-
-  return trailingPosition->unit == YGUnitUndefined ? 0.0f
-                                                   : YGResolveValue(trailingPosition, axisSize);
-}
-
-static float YGNodeBoundAxisWithinMinAndMax(const YGNodeRef node,
-                                            const YGFlexDirection axis,
-                                            const float value,
-                                            const float axisSize) {
-  float min = YGUndefined;
-  float max = YGUndefined;
-
-  if (YGFlexDirectionIsColumn(axis)) {
-    min = YGResolveValue(&node->style.minDimensions[YGDimensionHeight], axisSize);
-    max = YGResolveValue(&node->style.maxDimensions[YGDimensionHeight], axisSize);
-  } else if (YGFlexDirectionIsRow(axis)) {
-    min = YGResolveValue(&node->style.minDimensions[YGDimensionWidth], axisSize);
-    max = YGResolveValue(&node->style.maxDimensions[YGDimensionWidth], axisSize);
-  }
-
-  float boundValue = value;
-
-  if (!YGFloatIsUndefined(max) && max >= 0.0f && boundValue > max) {
-    boundValue = max;
-  }
-
-  if (!YGFloatIsUndefined(min) && min >= 0.0f && boundValue < min) {
-    boundValue = min;
-  }
-
-  return boundValue;
-}
-
-static inline YGValue *YGMarginLeadingValue(const YGNodeRef node, const YGFlexDirection axis) {
-  if (YGFlexDirectionIsRow(axis) && node->style.margin[YGEdgeStart].unit != YGUnitUndefined) {
-    return &node->style.margin[YGEdgeStart];
-  } else {
-    return &node->style.margin[leading[axis]];
-  }
-}
-
-static inline YGValue *YGMarginTrailingValue(const YGNodeRef node, const YGFlexDirection axis) {
-  if (YGFlexDirectionIsRow(axis) && node->style.margin[YGEdgeEnd].unit != YGUnitUndefined) {
-    return &node->style.margin[YGEdgeEnd];
-  } else {
-    return &node->style.margin[trailing[axis]];
-  }
-}
-
-// Like YGNodeBoundAxisWithinMinAndMax but also ensures that the value doesn't go
-// below the
-// padding and border amount.
-static inline float YGNodeBoundAxis(const YGNodeRef node,
-                                    const YGFlexDirection axis,
-                                    const float value,
-                                    const float axisSize,
-                                    const float widthSize) {
-  return fmaxf(YGNodeBoundAxisWithinMinAndMax(node, axis, value, axisSize),
-               YGNodePaddingAndBorderForAxis(node, axis, widthSize));
-}
-
-static void YGNodeSetChildTrailingPosition(const YGNodeRef node,
-                                           const YGNodeRef child,
-                                           const YGFlexDirection axis) {
-  const float size = child->layout.measuredDimensions[dim[axis]];
-  child->layout.position[trailing[axis]] =
-      node->layout.measuredDimensions[dim[axis]] - size - child->layout.position[pos[axis]];
-}
-
-// If both left and right are defined, then use left. Otherwise return
-// +left or -right depending on which is defined.
-static float YGNodeRelativePosition(const YGNodeRef node,
-                                    const YGFlexDirection axis,
-                                    const float axisSize) {
-  return YGNodeIsLeadingPosDefined(node, axis) ? YGNodeLeadingPosition(node, axis, axisSize)
-                                               : -YGNodeTrailingPosition(node, axis, axisSize);
-}
-
-static void YGConstrainMaxSizeForMode(const YGNodeRef node,
-                                      const enum YGFlexDirection axis,
-                                      const float parentAxisSize,
-                                      const float parentWidth,
-                                      YGMeasureMode *mode,
-                                      float *size) {
-  const float maxSize = YGResolveValue(&node->style.maxDimensions[dim[axis]], parentAxisSize) +
-                        YGNodeMarginForAxis(node, axis, parentWidth);
-  switch (*mode) {
-    case YGMeasureModeExactly:
-    case YGMeasureModeAtMost:
-      *size = (YGFloatIsUndefined(maxSize) || *size < maxSize) ? *size : maxSize;
-      break;
-    case YGMeasureModeUndefined:
-      if (!YGFloatIsUndefined(maxSize)) {
-        *mode = YGMeasureModeAtMost;
-        *size = maxSize;
-      }
-      break;
-  }
-}
-
-static void YGNodeSetPosition(const YGNodeRef node,
-                              const YGDirection direction,
-                              const float mainSize,
-                              const float crossSize,
-                              const float parentWidth) {
-  /* Root nodes should be always layouted as LTR, so we don't return negative values. */
-  const YGDirection directionRespectingRoot =
-      node->parent != nullptr ? direction : YGDirectionLTR;
-  const YGFlexDirection mainAxis =
-      YGResolveFlexDirection(node->style.flexDirection, directionRespectingRoot);
-  const YGFlexDirection crossAxis = YGFlexDirectionCross(mainAxis, directionRespectingRoot);
-
-  const float relativePositionMain = YGNodeRelativePosition(node, mainAxis, mainSize);
-  const float relativePositionCross = YGNodeRelativePosition(node, crossAxis, crossSize);
-
-  node->layout.position[leading[mainAxis]] =
-      YGNodeLeadingMargin(node, mainAxis, parentWidth) + relativePositionMain;
-  node->layout.position[trailing[mainAxis]] =
-      YGNodeTrailingMargin(node, mainAxis, parentWidth) + relativePositionMain;
-  node->layout.position[leading[crossAxis]] =
-      YGNodeLeadingMargin(node, crossAxis, parentWidth) + relativePositionCross;
-  node->layout.position[trailing[crossAxis]] =
-      YGNodeTrailingMargin(node, crossAxis, parentWidth) + relativePositionCross;
-}
-
-static void YGNodeComputeFlexBasisForChild(const YGNodeRef node,
-                                           const YGNodeRef child,
-                                           const float width,
-                                           const YGMeasureMode widthMode,
-                                           const float height,
-                                           const float parentWidth,
-                                           const float parentHeight,
-                                           const YGMeasureMode heightMode,
-                                           const YGDirection direction,
-                                           const YGConfigRef config) {
-  const YGFlexDirection mainAxis = YGResolveFlexDirection(node->style.flexDirection, direction);
-  const bool isMainAxisRow = YGFlexDirectionIsRow(mainAxis);
-  const float mainAxisSize = isMainAxisRow ? width : height;
-  const float mainAxisParentSize = isMainAxisRow ? parentWidth : parentHeight;
-
-  float childWidth;
-  float childHeight;
-  YGMeasureMode childWidthMeasureMode;
-  YGMeasureMode childHeightMeasureMode;
-
-  const float resolvedFlexBasis =
-      YGResolveValue(YGNodeResolveFlexBasisPtr(child), mainAxisParentSize);
-  const bool isRowStyleDimDefined = YGNodeIsStyleDimDefined(child, YGFlexDirectionRow, parentWidth);
-  const bool isColumnStyleDimDefined =
-      YGNodeIsStyleDimDefined(child, YGFlexDirectionColumn, parentHeight);
-
-  if (!YGFloatIsUndefined(resolvedFlexBasis) && !YGFloatIsUndefined(mainAxisSize)) {
-    if (YGFloatIsUndefined(child->layout.computedFlexBasis) ||
-        (YGConfigIsExperimentalFeatureEnabled(child->config, YGExperimentalFeatureWebFlexBasis) &&
-         child->layout.computedFlexBasisGeneration != gCurrentGenerationCount)) {
-      child->layout.computedFlexBasis =
-          fmaxf(resolvedFlexBasis, YGNodePaddingAndBorderForAxis(child, mainAxis, parentWidth));
-    }
-  } else if (isMainAxisRow && isRowStyleDimDefined) {
-    // The width is definite, so use that as the flex basis.
-    child->layout.computedFlexBasis =
-        fmaxf(YGResolveValue(child->resolvedDimensions[YGDimensionWidth], parentWidth),
-              YGNodePaddingAndBorderForAxis(child, YGFlexDirectionRow, parentWidth));
-  } else if (!isMainAxisRow && isColumnStyleDimDefined) {
-    // The height is definite, so use that as the flex basis.
-    child->layout.computedFlexBasis =
-        fmaxf(YGResolveValue(child->resolvedDimensions[YGDimensionHeight], parentHeight),
-              YGNodePaddingAndBorderForAxis(child, YGFlexDirectionColumn, parentWidth));
-  } else {
-    // Compute the flex basis and hypothetical main size (i.e. the clamped
-    // flex basis).
-    childWidth = YGUndefined;
-    childHeight = YGUndefined;
-    childWidthMeasureMode = YGMeasureModeUndefined;
-    childHeightMeasureMode = YGMeasureModeUndefined;
-
-    const float marginRow = YGNodeMarginForAxis(child, YGFlexDirectionRow, parentWidth);
-    const float marginColumn = YGNodeMarginForAxis(child, YGFlexDirectionColumn, parentWidth);
-
-    if (isRowStyleDimDefined) {
-      childWidth =
-          YGResolveValue(child->resolvedDimensions[YGDimensionWidth], parentWidth) + marginRow;
-      childWidthMeasureMode = YGMeasureModeExactly;
-    }
-    if (isColumnStyleDimDefined) {
-      childHeight =
-          YGResolveValue(child->resolvedDimensions[YGDimensionHeight], parentHeight) + marginColumn;
-      childHeightMeasureMode = YGMeasureModeExactly;
-    }
-
-    // The W3C spec doesn't say anything about the 'overflow' property,
-    // but all major browsers appear to implement the following logic.
-    if ((!isMainAxisRow && node->style.overflow == YGOverflowScroll) ||
-        node->style.overflow != YGOverflowScroll) {
-      if (YGFloatIsUndefined(childWidth) && !YGFloatIsUndefined(width)) {
-        childWidth = width;
-        childWidthMeasureMode = YGMeasureModeAtMost;
-      }
-    }
-
-    if ((isMainAxisRow && node->style.overflow == YGOverflowScroll) ||
-        node->style.overflow != YGOverflowScroll) {
-      if (YGFloatIsUndefined(childHeight) && !YGFloatIsUndefined(height)) {
-        childHeight = height;
-        childHeightMeasureMode = YGMeasureModeAtMost;
-      }
-    }
-
-    if (!YGFloatIsUndefined(child->style.aspectRatio)) {
-      if (!isMainAxisRow && childWidthMeasureMode == YGMeasureModeExactly) {
-        childHeight = (childWidth - marginRow) / child->style.aspectRatio;
-        childHeightMeasureMode = YGMeasureModeExactly;
-      } else if (isMainAxisRow && childHeightMeasureMode == YGMeasureModeExactly) {
-        childWidth = (childHeight - marginColumn) * child->style.aspectRatio;
-        childWidthMeasureMode = YGMeasureModeExactly;
-      }
-    }
-
-    // If child has no defined size in the cross axis and is set to stretch,
-    // set the cross
-    // axis to be measured exactly with the available inner width
-
-    const bool hasExactWidth = !YGFloatIsUndefined(width) && widthMode == YGMeasureModeExactly;
-    const bool childWidthStretch = YGNodeAlignItem(node, child) == YGAlignStretch &&
-                                   childWidthMeasureMode != YGMeasureModeExactly;
-    if (!isMainAxisRow && !isRowStyleDimDefined && hasExactWidth && childWidthStretch) {
-      childWidth = width;
-      childWidthMeasureMode = YGMeasureModeExactly;
-      if (!YGFloatIsUndefined(child->style.aspectRatio)) {
-        childHeight = (childWidth - marginRow) / child->style.aspectRatio;
-        childHeightMeasureMode = YGMeasureModeExactly;
-      }
-    }
-
-    const bool hasExactHeight = !YGFloatIsUndefined(height) && heightMode == YGMeasureModeExactly;
-    const bool childHeightStretch = YGNodeAlignItem(node, child) == YGAlignStretch &&
-                                    childHeightMeasureMode != YGMeasureModeExactly;
-    if (isMainAxisRow && !isColumnStyleDimDefined && hasExactHeight && childHeightStretch) {
-      childHeight = height;
-      childHeightMeasureMode = YGMeasureModeExactly;
-
-      if (!YGFloatIsUndefined(child->style.aspectRatio)) {
-        childWidth = (childHeight - marginColumn) * child->style.aspectRatio;
-        childWidthMeasureMode = YGMeasureModeExactly;
-      }
-    }
-
-    YGConstrainMaxSizeForMode(
-        child, YGFlexDirectionRow, parentWidth, parentWidth, &childWidthMeasureMode, &childWidth);
-    YGConstrainMaxSizeForMode(child,
-                              YGFlexDirectionColumn,
-                              parentHeight,
-                              parentWidth,
-                              &childHeightMeasureMode,
-                              &childHeight);
-
-    // Measure the child
-    YGLayoutNodeInternal(child,
-                         childWidth,
-                         childHeight,
-                         direction,
-                         childWidthMeasureMode,
-                         childHeightMeasureMode,
-                         parentWidth,
-                         parentHeight,
-                         false,
-                         "measure",
-                         config);
-
-    child->layout.computedFlexBasis =
-        fmaxf(child->layout.measuredDimensions[dim[mainAxis]],
-              YGNodePaddingAndBorderForAxis(child, mainAxis, parentWidth));
-  }
-
-  child->layout.computedFlexBasisGeneration = gCurrentGenerationCount;
-}
-
-static void YGNodeAbsoluteLayoutChild(const YGNodeRef node,
-                                      const YGNodeRef child,
-                                      const float width,
-                                      const YGMeasureMode widthMode,
-                                      const float height,
-                                      const YGDirection direction,
-                                      const YGConfigRef config) {
-  const YGFlexDirection mainAxis = YGResolveFlexDirection(node->style.flexDirection, direction);
-  const YGFlexDirection crossAxis = YGFlexDirectionCross(mainAxis, direction);
-  const bool isMainAxisRow = YGFlexDirectionIsRow(mainAxis);
-
-  float childWidth = YGUndefined;
-  float childHeight = YGUndefined;
-  YGMeasureMode childWidthMeasureMode = YGMeasureModeUndefined;
-  YGMeasureMode childHeightMeasureMode = YGMeasureModeUndefined;
-
-  const float marginRow = YGNodeMarginForAxis(child, YGFlexDirectionRow, width);
-  const float marginColumn = YGNodeMarginForAxis(child, YGFlexDirectionColumn, width);
-
-  if (YGNodeIsStyleDimDefined(child, YGFlexDirectionRow, width)) {
-    childWidth = YGResolveValue(child->resolvedDimensions[YGDimensionWidth], width) + marginRow;
-  } else {
-    // If the child doesn't have a specified width, compute the width based
-    // on the left/right
-    // offsets if they're defined.
-    if (YGNodeIsLeadingPosDefined(child, YGFlexDirectionRow) &&
-        YGNodeIsTrailingPosDefined(child, YGFlexDirectionRow)) {
-      childWidth = node->layout.measuredDimensions[YGDimensionWidth] -
-                   (YGNodeLeadingBorder(node, YGFlexDirectionRow) +
-                    YGNodeTrailingBorder(node, YGFlexDirectionRow)) -
-                   (YGNodeLeadingPosition(child, YGFlexDirectionRow, width) +
-                    YGNodeTrailingPosition(child, YGFlexDirectionRow, width));
-      childWidth = YGNodeBoundAxis(child, YGFlexDirectionRow, childWidth, width, width);
-    }
-  }
-
-  if (YGNodeIsStyleDimDefined(child, YGFlexDirectionColumn, height)) {
-    childHeight =
-        YGResolveValue(child->resolvedDimensions[YGDimensionHeight], height) + marginColumn;
-  } else {
-    // If the child doesn't have a specified height, compute the height
-    // based on the top/bottom
-    // offsets if they're defined.
-    if (YGNodeIsLeadingPosDefined(child, YGFlexDirectionColumn) &&
-        YGNodeIsTrailingPosDefined(child, YGFlexDirectionColumn)) {
-      childHeight = node->layout.measuredDimensions[YGDimensionHeight] -
-                    (YGNodeLeadingBorder(node, YGFlexDirectionColumn) +
-                     YGNodeTrailingBorder(node, YGFlexDirectionColumn)) -
-                    (YGNodeLeadingPosition(child, YGFlexDirectionColumn, height) +
-                     YGNodeTrailingPosition(child, YGFlexDirectionColumn, height));
-      childHeight = YGNodeBoundAxis(child, YGFlexDirectionColumn, childHeight, height, width);
-    }
-  }
-
-  // Exactly one dimension needs to be defined for us to be able to do aspect ratio
-  // calculation. One dimension being the anchor and the other being flexible.
-  if (YGFloatIsUndefined(childWidth) ^ YGFloatIsUndefined(childHeight)) {
-    if (!YGFloatIsUndefined(child->style.aspectRatio)) {
-      if (YGFloatIsUndefined(childWidth)) {
-        childWidth = marginRow + (childHeight - marginColumn) * child->style.aspectRatio;
-      } else if (YGFloatIsUndefined(childHeight)) {
-        childHeight = marginColumn + (childWidth - marginRow) / child->style.aspectRatio;
-      }
-    }
-  }
-
-  // If we're still missing one or the other dimension, measure the content.
-  if (YGFloatIsUndefined(childWidth) || YGFloatIsUndefined(childHeight)) {
-    childWidthMeasureMode =
-        YGFloatIsUndefined(childWidth) ? YGMeasureModeUndefined : YGMeasureModeExactly;
-    childHeightMeasureMode =
-        YGFloatIsUndefined(childHeight) ? YGMeasureModeUndefined : YGMeasureModeExactly;
-
-    // If the size of the parent is defined then try to constrain the absolute child to that size
-    // as well. This allows text within the absolute child to wrap to the size of its parent.
-    // This is the same behavior as many browsers implement.
-    if (!isMainAxisRow && YGFloatIsUndefined(childWidth) && widthMode != YGMeasureModeUndefined &&
-        width > 0) {
-      childWidth = width;
-      childWidthMeasureMode = YGMeasureModeAtMost;
-    }
-
-    YGLayoutNodeInternal(child,
-                         childWidth,
-                         childHeight,
-                         direction,
-                         childWidthMeasureMode,
-                         childHeightMeasureMode,
-                         childWidth,
-                         childHeight,
-                         false,
-                         "abs-measure",
-                         config);
-    childWidth = child->layout.measuredDimensions[YGDimensionWidth] +
-                 YGNodeMarginForAxis(child, YGFlexDirectionRow, width);
-    childHeight = child->layout.measuredDimensions[YGDimensionHeight] +
-                  YGNodeMarginForAxis(child, YGFlexDirectionColumn, width);
-  }
-
-  YGLayoutNodeInternal(child,
-                       childWidth,
-                       childHeight,
-                       direction,
-                       YGMeasureModeExactly,
-                       YGMeasureModeExactly,
-                       childWidth,
-                       childHeight,
-                       true,
-                       "abs-layout",
-                       config);
-
-  if (YGNodeIsTrailingPosDefined(child, mainAxis) && !YGNodeIsLeadingPosDefined(child, mainAxis)) {
-    child->layout.position[leading[mainAxis]] =
-        node->layout.measuredDimensions[dim[mainAxis]] -
-        child->layout.measuredDimensions[dim[mainAxis]] - YGNodeTrailingBorder(node, mainAxis) -
-        YGNodeTrailingMargin(child, mainAxis, width) -
-        YGNodeTrailingPosition(child, mainAxis, isMainAxisRow ? width : height);
-  } else if (!YGNodeIsLeadingPosDefined(child, mainAxis) &&
-             node->style.justifyContent == YGJustifyCenter) {
-    child->layout.position[leading[mainAxis]] = (node->layout.measuredDimensions[dim[mainAxis]] -
-                                                 child->layout.measuredDimensions[dim[mainAxis]]) /
-                                                2.0f;
-  } else if (!YGNodeIsLeadingPosDefined(child, mainAxis) &&
-             node->style.justifyContent == YGJustifyFlexEnd) {
-    child->layout.position[leading[mainAxis]] = (node->layout.measuredDimensions[dim[mainAxis]] -
-                                                 child->layout.measuredDimensions[dim[mainAxis]]);
-  }
-
-  if (YGNodeIsTrailingPosDefined(child, crossAxis) &&
-      !YGNodeIsLeadingPosDefined(child, crossAxis)) {
-    child->layout.position[leading[crossAxis]] =
-        node->layout.measuredDimensions[dim[crossAxis]] -
-        child->layout.measuredDimensions[dim[crossAxis]] - YGNodeTrailingBorder(node, crossAxis) -
-        YGNodeTrailingMargin(child, crossAxis, width) -
-        YGNodeTrailingPosition(child, crossAxis, isMainAxisRow ? height : width);
-  } else if (!YGNodeIsLeadingPosDefined(child, crossAxis) &&
-             YGNodeAlignItem(node, child) == YGAlignCenter) {
-    child->layout.position[leading[crossAxis]] =
-        (node->layout.measuredDimensions[dim[crossAxis]] -
-         child->layout.measuredDimensions[dim[crossAxis]]) /
-        2.0f;
-  } else if (!YGNodeIsLeadingPosDefined(child, crossAxis) &&
-             ((YGNodeAlignItem(node, child) == YGAlignFlexEnd) ^
-              (node->style.flexWrap == YGWrapWrapReverse))) {
-    child->layout.position[leading[crossAxis]] = (node->layout.measuredDimensions[dim[crossAxis]] -
-                                                  child->layout.measuredDimensions[dim[crossAxis]]);
-  }
-}
-
-static void YGNodeWithMeasureFuncSetMeasuredDimensions(const YGNodeRef node,
-                                                       const float availableWidth,
-                                                       const float availableHeight,
-                                                       const YGMeasureMode widthMeasureMode,
-                                                       const YGMeasureMode heightMeasureMode,
-                                                       const float parentWidth,
-                                                       const float parentHeight) {
-  YGAssertWithNode(
-      node,
-      node->measure != nullptr,
-      "Expected node to have custom measure function");
-
-  const float paddingAndBorderAxisRow =
-      YGNodePaddingAndBorderForAxis(node, YGFlexDirectionRow, availableWidth);
-  const float paddingAndBorderAxisColumn =
-      YGNodePaddingAndBorderForAxis(node, YGFlexDirectionColumn, availableWidth);
-  const float marginAxisRow = YGNodeMarginForAxis(node, YGFlexDirectionRow, availableWidth);
-  const float marginAxisColumn = YGNodeMarginForAxis(node, YGFlexDirectionColumn, availableWidth);
-
-  // We want to make sure we don't call measure with negative size
-  const float innerWidth = YGFloatIsUndefined(availableWidth)
-                               ? availableWidth
-                               : fmaxf(0, availableWidth - marginAxisRow - paddingAndBorderAxisRow);
-  const float innerHeight =
-      YGFloatIsUndefined(availableHeight)
-          ? availableHeight
-          : fmaxf(0, availableHeight - marginAxisColumn - paddingAndBorderAxisColumn);
-
-  if (widthMeasureMode == YGMeasureModeExactly && heightMeasureMode == YGMeasureModeExactly) {
-    // Don't bother sizing the text if both dimensions are already defined.
-    node->layout.measuredDimensions[YGDimensionWidth] = YGNodeBoundAxis(
-        node, YGFlexDirectionRow, availableWidth - marginAxisRow, parentWidth, parentWidth);
-    node->layout.measuredDimensions[YGDimensionHeight] = YGNodeBoundAxis(
-        node, YGFlexDirectionColumn, availableHeight - marginAxisColumn, parentHeight, parentWidth);
-  } else {
-    // Measure the text under the current constraints.
-    const YGSize measuredSize =
-        node->measure(node, innerWidth, widthMeasureMode, innerHeight, heightMeasureMode);
-
-    node->layout.measuredDimensions[YGDimensionWidth] =
-        YGNodeBoundAxis(node,
-                        YGFlexDirectionRow,
-                        (widthMeasureMode == YGMeasureModeUndefined ||
-                         widthMeasureMode == YGMeasureModeAtMost)
-                            ? measuredSize.width + paddingAndBorderAxisRow
-                            : availableWidth - marginAxisRow,
-                        parentWidth,
-                        parentWidth);
-    node->layout.measuredDimensions[YGDimensionHeight] =
-        YGNodeBoundAxis(node,
-                        YGFlexDirectionColumn,
-                        (heightMeasureMode == YGMeasureModeUndefined ||
-                         heightMeasureMode == YGMeasureModeAtMost)
-                            ? measuredSize.height + paddingAndBorderAxisColumn
-                            : availableHeight - marginAxisColumn,
-                        parentHeight,
-                        parentWidth);
-  }
-}
-
-// For nodes with no children, use the available values if they were provided,
-// or the minimum size as indicated by the padding and border sizes.
-static void YGNodeEmptyContainerSetMeasuredDimensions(const YGNodeRef node,
-                                                      const float availableWidth,
-                                                      const float availableHeight,
-                                                      const YGMeasureMode widthMeasureMode,
-                                                      const YGMeasureMode heightMeasureMode,
-                                                      const float parentWidth,
-                                                      const float parentHeight) {
-  const float paddingAndBorderAxisRow =
-      YGNodePaddingAndBorderForAxis(node, YGFlexDirectionRow, parentWidth);
-  const float paddingAndBorderAxisColumn =
-      YGNodePaddingAndBorderForAxis(node, YGFlexDirectionColumn, parentWidth);
-  const float marginAxisRow = YGNodeMarginForAxis(node, YGFlexDirectionRow, parentWidth);
-  const float marginAxisColumn = YGNodeMarginForAxis(node, YGFlexDirectionColumn, parentWidth);
-
-  node->layout.measuredDimensions[YGDimensionWidth] =
-      YGNodeBoundAxis(node,
-                      YGFlexDirectionRow,
-                      (widthMeasureMode == YGMeasureModeUndefined ||
-                       widthMeasureMode == YGMeasureModeAtMost)
-                          ? paddingAndBorderAxisRow
-                          : availableWidth - marginAxisRow,
-                      parentWidth,
-                      parentWidth);
-  node->layout.measuredDimensions[YGDimensionHeight] =
-      YGNodeBoundAxis(node,
-                      YGFlexDirectionColumn,
-                      (heightMeasureMode == YGMeasureModeUndefined ||
-                       heightMeasureMode == YGMeasureModeAtMost)
-                          ? paddingAndBorderAxisColumn
-                          : availableHeight - marginAxisColumn,
-                      parentHeight,
-                      parentWidth);
-}
-
-static bool YGNodeFixedSizeSetMeasuredDimensions(const YGNodeRef node,
-                                                 const float availableWidth,
-                                                 const float availableHeight,
-                                                 const YGMeasureMode widthMeasureMode,
-                                                 const YGMeasureMode heightMeasureMode,
-                                                 const float parentWidth,
-                                                 const float parentHeight) {
-  if ((widthMeasureMode == YGMeasureModeAtMost && availableWidth <= 0.0f) ||
-      (heightMeasureMode == YGMeasureModeAtMost && availableHeight <= 0.0f) ||
-      (widthMeasureMode == YGMeasureModeExactly && heightMeasureMode == YGMeasureModeExactly)) {
-    const float marginAxisColumn = YGNodeMarginForAxis(node, YGFlexDirectionColumn, parentWidth);
-    const float marginAxisRow = YGNodeMarginForAxis(node, YGFlexDirectionRow, parentWidth);
-
-    node->layout.measuredDimensions[YGDimensionWidth] =
-        YGNodeBoundAxis(node,
-                        YGFlexDirectionRow,
-                        YGFloatIsUndefined(availableWidth) ||
-                                (widthMeasureMode == YGMeasureModeAtMost && availableWidth < 0.0f)
-                            ? 0.0f
-                            : availableWidth - marginAxisRow,
-                        parentWidth,
-                        parentWidth);
-
-    node->layout.measuredDimensions[YGDimensionHeight] =
-        YGNodeBoundAxis(node,
-                        YGFlexDirectionColumn,
-                        YGFloatIsUndefined(availableHeight) ||
-                                (heightMeasureMode == YGMeasureModeAtMost && availableHeight < 0.0f)
-                            ? 0.0f
-                            : availableHeight - marginAxisColumn,
-                        parentHeight,
-                        parentWidth);
-
-    return true;
-  }
-
-  return false;
-}
-
-static void YGZeroOutLayoutRecursivly(const YGNodeRef node) {
-  memset(&(node->layout), 0, sizeof(YGLayout));
-  node->hasNewLayout = true;
-  YGCloneChildrenIfNeeded(node);
-  const uint32_t childCount = YGNodeGetChildCount(node);
-  for (uint32_t i = 0; i < childCount; i++) {
-    const YGNodeRef child = node->children[i];
-    YGZeroOutLayoutRecursivly(child);
-  }
-}
-
-//
-// This is the main routine that implements a subset of the flexbox layout
-// algorithm
-// described in the W3C YG documentation: https://www.w3.org/TR/YG3-flexbox/.
-//
-// Limitations of this algorithm, compared to the full standard:
-//  * Display property is always assumed to be 'flex' except for Text nodes,
-//  which
-//    are assumed to be 'inline-flex'.
-//  * The 'zIndex' property (or any form of z ordering) is not supported. Nodes
-//  are
-//    stacked in document order.
-//  * The 'order' property is not supported. The order of flex items is always
-//  defined
-//    by document order.
-//  * The 'visibility' property is always assumed to be 'visible'. Values of
-//  'collapse'
-//    and 'hidden' are not supported.
-//  * There is no support for forced breaks.
-//  * It does not support vertical inline directions (top-to-bottom or
-//  bottom-to-top text).
-//
-// Deviations from standard:
-//  * Section 4.5 of the spec indicates that all flex items have a default
-//  minimum
-//    main size. For text blocks, for example, this is the width of the widest
-//    word.
-//    Calculating the minimum width is expensive, so we forego it and assume a
-//    default
-//    minimum main size of 0.
-//  * Min/Max sizes in the main axis are not honored when resolving flexible
-//  lengths.
-//  * The spec indicates that the default value for 'flexDirection' is 'row',
-//  but
-//    the algorithm below assumes a default of 'column'.
-//
-// Input parameters:
-//    - node: current node to be sized and layed out
-//    - availableWidth & availableHeight: available size to be used for sizing
-//    the node
-//      or YGUndefined if the size is not available; interpretation depends on
-//      layout
-//      flags
-//    - parentDirection: the inline (text) direction within the parent
-//    (left-to-right or
-//      right-to-left)
-//    - widthMeasureMode: indicates the sizing rules for the width (see below
-//    for explanation)
-//    - heightMeasureMode: indicates the sizing rules for the height (see below
-//    for explanation)
-//    - performLayout: specifies whether the caller is interested in just the
-//    dimensions
-//      of the node or it requires the entire node and its subtree to be layed
-//      out
-//      (with final positions)
-//
-// Details:
-//    This routine is called recursively to lay out subtrees of flexbox
-//    elements. It uses the
-//    information in node.style, which is treated as a read-only input. It is
-//    responsible for
-//    setting the layout.direction and layout.measuredDimensions fields for the
-//    input node as well
-//    as the layout.position and layout.lineIndex fields for its child nodes.
-//    The
-//    layout.measuredDimensions field includes any border or padding for the
-//    node but does
-//    not include margins.
-//
-//    The spec describes four different layout modes: "fill available", "max
-//    content", "min
-//    content",
-//    and "fit content". Of these, we don't use "min content" because we don't
-//    support default
-//    minimum main sizes (see above for details). Each of our measure modes maps
-//    to a layout mode
-//    from the spec (https://www.w3.org/TR/YG3-sizing/#terms):
-//      - YGMeasureModeUndefined: max content
-//      - YGMeasureModeExactly: fill available
-//      - YGMeasureModeAtMost: fit content
-//
-//    When calling YGNodelayoutImpl and YGLayoutNodeInternal, if the caller passes
-//    an available size of
-//    undefined then it must also pass a measure mode of YGMeasureModeUndefined
-//    in that dimension.
-//
-static void YGNodelayoutImpl(const YGNodeRef node,
-                             const float availableWidth,
-                             const float availableHeight,
-                             const YGDirection parentDirection,
-                             const YGMeasureMode widthMeasureMode,
-                             const YGMeasureMode heightMeasureMode,
-                             const float parentWidth,
-                             const float parentHeight,
-                             const bool performLayout,
-                             const YGConfigRef config) {
-  YGAssertWithNode(node,
-                   YGFloatIsUndefined(availableWidth) ? widthMeasureMode == YGMeasureModeUndefined
-                                                      : true,
-                   "availableWidth is indefinite so widthMeasureMode must be "
-                   "YGMeasureModeUndefined");
-  YGAssertWithNode(node,
-                   YGFloatIsUndefined(availableHeight) ? heightMeasureMode == YGMeasureModeUndefined
-                                                       : true,
-                   "availableHeight is indefinite so heightMeasureMode must be "
-                   "YGMeasureModeUndefined");
-
-  // Set the resolved resolution in the node's layout.
-  const YGDirection direction = YGNodeResolveDirection(node, parentDirection);
-  node->layout.direction = direction;
-
-  const YGFlexDirection flexRowDirection = YGResolveFlexDirection(YGFlexDirectionRow, direction);
-  const YGFlexDirection flexColumnDirection =
-      YGResolveFlexDirection(YGFlexDirectionColumn, direction);
-
-  node->layout.margin[YGEdgeStart] = YGNodeLeadingMargin(node, flexRowDirection, parentWidth);
-  node->layout.margin[YGEdgeEnd] = YGNodeTrailingMargin(node, flexRowDirection, parentWidth);
-  node->layout.margin[YGEdgeTop] = YGNodeLeadingMargin(node, flexColumnDirection, parentWidth);
-  node->layout.margin[YGEdgeBottom] = YGNodeTrailingMargin(node, flexColumnDirection, parentWidth);
-
-  node->layout.border[YGEdgeStart] = YGNodeLeadingBorder(node, flexRowDirection);
-  node->layout.border[YGEdgeEnd] = YGNodeTrailingBorder(node, flexRowDirection);
-  node->layout.border[YGEdgeTop] = YGNodeLeadingBorder(node, flexColumnDirection);
-  node->layout.border[YGEdgeBottom] = YGNodeTrailingBorder(node, flexColumnDirection);
-
-  node->layout.padding[YGEdgeStart] = YGNodeLeadingPadding(node, flexRowDirection, parentWidth);
-  node->layout.padding[YGEdgeEnd] = YGNodeTrailingPadding(node, flexRowDirection, parentWidth);
-  node->layout.padding[YGEdgeTop] = YGNodeLeadingPadding(node, flexColumnDirection, parentWidth);
-  node->layout.padding[YGEdgeBottom] =
-      YGNodeTrailingPadding(node, flexColumnDirection, parentWidth);
-
-  if (node->measure) {
-    YGNodeWithMeasureFuncSetMeasuredDimensions(node,
-                                               availableWidth,
-                                               availableHeight,
-                                               widthMeasureMode,
-                                               heightMeasureMode,
-                                               parentWidth,
-                                               parentHeight);
-    return;
-  }
-
-  const uint32_t childCount = node->children.size();
-  if (childCount == 0) {
-    YGNodeEmptyContainerSetMeasuredDimensions(node,
-                                              availableWidth,
-                                              availableHeight,
-                                              widthMeasureMode,
-                                              heightMeasureMode,
-                                              parentWidth,
-                                              parentHeight);
-    return;
-  }
-
-  // If we're not being asked to perform a full layout we can skip the algorithm if we already know
-  // the size
-  if (!performLayout && YGNodeFixedSizeSetMeasuredDimensions(node,
-                                                             availableWidth,
-                                                             availableHeight,
-                                                             widthMeasureMode,
-                                                             heightMeasureMode,
-                                                             parentWidth,
-                                                             parentHeight)) {
-    return;
-  }
-
-  // At this point we know we're going to perform work. Ensure that each child has a mutable copy.
-  YGCloneChildrenIfNeeded(node);
-
-  // Reset layout flags, as they could have changed.
-  node->layout.hadOverflow = false;
-
-  // STEP 1: CALCULATE VALUES FOR REMAINDER OF ALGORITHM
-  const YGFlexDirection mainAxis = YGResolveFlexDirection(node->style.flexDirection, direction);
-  const YGFlexDirection crossAxis = YGFlexDirectionCross(mainAxis, direction);
-  const bool isMainAxisRow = YGFlexDirectionIsRow(mainAxis);
-  const YGJustify justifyContent = node->style.justifyContent;
-  const bool isNodeFlexWrap = node->style.flexWrap != YGWrapNoWrap;
-
-  const float mainAxisParentSize = isMainAxisRow ? parentWidth : parentHeight;
-  const float crossAxisParentSize = isMainAxisRow ? parentHeight : parentWidth;
-
-  YGNodeRef firstAbsoluteChild = nullptr;
-  YGNodeRef currentAbsoluteChild = nullptr;
-
-  const float leadingPaddingAndBorderMain =
-      YGNodeLeadingPaddingAndBorder(node, mainAxis, parentWidth);
-  const float trailingPaddingAndBorderMain =
-      YGNodeTrailingPaddingAndBorder(node, mainAxis, parentWidth);
-  const float leadingPaddingAndBorderCross =
-      YGNodeLeadingPaddingAndBorder(node, crossAxis, parentWidth);
-  const float paddingAndBorderAxisMain = YGNodePaddingAndBorderForAxis(node, mainAxis, parentWidth);
-  const float paddingAndBorderAxisCross =
-      YGNodePaddingAndBorderForAxis(node, crossAxis, parentWidth);
-
-  YGMeasureMode measureModeMainDim = isMainAxisRow ? widthMeasureMode : heightMeasureMode;
-  YGMeasureMode measureModeCrossDim = isMainAxisRow ? heightMeasureMode : widthMeasureMode;
-
-  const float paddingAndBorderAxisRow =
-      isMainAxisRow ? paddingAndBorderAxisMain : paddingAndBorderAxisCross;
-  const float paddingAndBorderAxisColumn =
-      isMainAxisRow ? paddingAndBorderAxisCross : paddingAndBorderAxisMain;
-
-  const float marginAxisRow = YGNodeMarginForAxis(node, YGFlexDirectionRow, parentWidth);
-  const float marginAxisColumn = YGNodeMarginForAxis(node, YGFlexDirectionColumn, parentWidth);
-
-  // STEP 2: DETERMINE AVAILABLE SIZE IN MAIN AND CROSS DIRECTIONS
-  const float minInnerWidth =
-      YGResolveValue(&node->style.minDimensions[YGDimensionWidth], parentWidth) -
-      paddingAndBorderAxisRow;
-  const float maxInnerWidth =
-      YGResolveValue(&node->style.maxDimensions[YGDimensionWidth], parentWidth) -
-      paddingAndBorderAxisRow;
-  const float minInnerHeight =
-      YGResolveValue(&node->style.minDimensions[YGDimensionHeight], parentHeight) -
-      paddingAndBorderAxisColumn;
-  const float maxInnerHeight =
-      YGResolveValue(&node->style.maxDimensions[YGDimensionHeight], parentHeight) -
-      paddingAndBorderAxisColumn;
-  const float minInnerMainDim = isMainAxisRow ? minInnerWidth : minInnerHeight;
-  const float maxInnerMainDim = isMainAxisRow ? maxInnerWidth : maxInnerHeight;
-
-  // Max dimension overrides predefined dimension value; Min dimension in turn overrides both of the
-  // above
-  float availableInnerWidth = availableWidth - marginAxisRow - paddingAndBorderAxisRow;
-  if (!YGFloatIsUndefined(availableInnerWidth)) {
-    // We want to make sure our available width does not violate min and max constraints
-    availableInnerWidth = fmaxf(fminf(availableInnerWidth, maxInnerWidth), minInnerWidth);
-  }
-
-  float availableInnerHeight = availableHeight - marginAxisColumn - paddingAndBorderAxisColumn;
-  if (!YGFloatIsUndefined(availableInnerHeight)) {
-    // We want to make sure our available height does not violate min and max constraints
-    availableInnerHeight = fmaxf(fminf(availableInnerHeight, maxInnerHeight), minInnerHeight);
-  }
-
-  float availableInnerMainDim = isMainAxisRow ? availableInnerWidth : availableInnerHeight;
-  const float availableInnerCrossDim = isMainAxisRow ? availableInnerHeight : availableInnerWidth;
-
-  // If there is only one child with flexGrow + flexShrink it means we can set the
-  // computedFlexBasis to 0 instead of measuring and shrinking / flexing the child to exactly
-  // match the remaining space
-  YGNodeRef singleFlexChild = nullptr;
-  if (measureModeMainDim == YGMeasureModeExactly) {
-    for (uint32_t i = 0; i < childCount; i++) {
-      const YGNodeRef child = YGNodeGetChild(node, i);
-      if (singleFlexChild) {
-        if (YGNodeIsFlex(child)) {
-          // There is already a flexible child, abort.
-          singleFlexChild = nullptr;
-          break;
-        }
-      } else if (YGResolveFlexGrow(child) > 0.0f && YGNodeResolveFlexShrink(child) > 0.0f) {
-        singleFlexChild = child;
-      }
-    }
-  }
-
-  float totalOuterFlexBasis = 0;
-
-  // STEP 3: DETERMINE FLEX BASIS FOR EACH ITEM
-  for (uint32_t i = 0; i < childCount; i++) {
-    const YGNodeRef child = node->children[i];
-    if (child->style.display == YGDisplayNone) {
-      YGZeroOutLayoutRecursivly(child);
-      child->hasNewLayout = true;
-      child->isDirty = false;
-      continue;
-    }
-    YGResolveDimensions(child);
-    if (performLayout) {
-      // Set the initial position (relative to the parent).
-      const YGDirection childDirection = YGNodeResolveDirection(child, direction);
-      YGNodeSetPosition(child,
-                        childDirection,
-                        availableInnerMainDim,
-                        availableInnerCrossDim,
-                        availableInnerWidth);
-    }
-
-    // Absolute-positioned children don't participate in flex layout. Add them
-    // to a list that we can process later.
-    if (child->style.positionType == YGPositionTypeAbsolute) {
-      // Store a private linked list of absolutely positioned children
-      // so that we can efficiently traverse them later.
-      if (firstAbsoluteChild == nullptr) {
-        firstAbsoluteChild = child;
-      }
-      if (currentAbsoluteChild != nullptr) {
-        currentAbsoluteChild->nextChild = child;
-      }
-      currentAbsoluteChild = child;
-      child->nextChild = nullptr;
-    } else {
-      if (child == singleFlexChild) {
-        child->layout.computedFlexBasisGeneration = gCurrentGenerationCount;
-        child->layout.computedFlexBasis = 0;
-      } else {
-        YGNodeComputeFlexBasisForChild(node,
-                                       child,
-                                       availableInnerWidth,
-                                       widthMeasureMode,
-                                       availableInnerHeight,
-                                       availableInnerWidth,
-                                       availableInnerHeight,
-                                       heightMeasureMode,
-                                       direction,
-                                       config);
-      }
-    }
-
-    totalOuterFlexBasis +=
-        child->layout.computedFlexBasis + YGNodeMarginForAxis(child, mainAxis, availableInnerWidth);
-    ;
-  }
-
-  const bool flexBasisOverflows = measureModeMainDim == YGMeasureModeUndefined
-                                      ? false
-                                      : totalOuterFlexBasis > availableInnerMainDim;
-  if (isNodeFlexWrap && flexBasisOverflows && measureModeMainDim == YGMeasureModeAtMost) {
-    measureModeMainDim = YGMeasureModeExactly;
-  }
-
-  // STEP 4: COLLECT FLEX ITEMS INTO FLEX LINES
-
-  // Indexes of children that represent the first and last items in the line.
-  uint32_t startOfLineIndex = 0;
-  uint32_t endOfLineIndex = 0;
-
-  // Number of lines.
-  uint32_t lineCount = 0;
-
-  // Accumulated cross dimensions of all lines so far.
-  float totalLineCrossDim = 0;
-
-  // Max main dimension of all the lines.
-  float maxLineMainDim = 0;
-
-  for (; endOfLineIndex < childCount; lineCount++, startOfLineIndex = endOfLineIndex) {
-    // Number of items on the currently line. May be different than the
-    // difference
-    // between start and end indicates because we skip over absolute-positioned
-    // items.
-    uint32_t itemsOnLine = 0;
-
-    // sizeConsumedOnCurrentLine is accumulation of the dimensions and margin
-    // of all the children on the current line. This will be used in order to
-    // either set the dimensions of the node if none already exist or to compute
-    // the remaining space left for the flexible children.
-    float sizeConsumedOnCurrentLine = 0;
-    float sizeConsumedOnCurrentLineIncludingMinConstraint = 0;
-
-    float totalFlexGrowFactors = 0;
-    float totalFlexShrinkScaledFactors = 0;
-
-    // Maintain a linked list of the child nodes that can shrink and/or grow.
-    YGNodeRef firstRelativeChild = nullptr;
-    YGNodeRef currentRelativeChild = nullptr;
-
-    // Add items to the current line until it's full or we run out of items.
-    for (uint32_t i = startOfLineIndex; i < childCount; i++, endOfLineIndex++) {
-      const YGNodeRef child = node->children[i];
-      if (child->style.display == YGDisplayNone) {
-        continue;
-      }
-      child->lineIndex = lineCount;
-
-      if (child->style.positionType != YGPositionTypeAbsolute) {
-        const float childMarginMainAxis = YGNodeMarginForAxis(child, mainAxis, availableInnerWidth);
-        const float flexBasisWithMaxConstraints =
-            fminf(YGResolveValue(&child->style.maxDimensions[dim[mainAxis]], mainAxisParentSize),
-                  child->layout.computedFlexBasis);
-        const float flexBasisWithMinAndMaxConstraints =
-            fmaxf(YGResolveValue(&child->style.minDimensions[dim[mainAxis]], mainAxisParentSize),
-                  flexBasisWithMaxConstraints);
-
-        // If this is a multi-line flow and this item pushes us over the
-        // available size, we've
-        // hit the end of the current line. Break out of the loop and lay out
-        // the current line.
-        if (sizeConsumedOnCurrentLineIncludingMinConstraint + flexBasisWithMinAndMaxConstraints +
-                    childMarginMainAxis >
-                availableInnerMainDim &&
-            isNodeFlexWrap && itemsOnLine > 0) {
-          break;
-        }
-
-        sizeConsumedOnCurrentLineIncludingMinConstraint +=
-            flexBasisWithMinAndMaxConstraints + childMarginMainAxis;
-        sizeConsumedOnCurrentLine += flexBasisWithMinAndMaxConstraints + childMarginMainAxis;
-        itemsOnLine++;
-
-        if (YGNodeIsFlex(child)) {
-          totalFlexGrowFactors += YGResolveFlexGrow(child);
-
-          // Unlike the grow factor, the shrink factor is scaled relative to the child dimension.
-          totalFlexShrinkScaledFactors +=
-              -YGNodeResolveFlexShrink(child) * child->layout.computedFlexBasis;
-        }
-
-        // Store a private linked list of children that need to be layed out.
-        if (firstRelativeChild == nullptr) {
-          firstRelativeChild = child;
-        }
-        if (currentRelativeChild != nullptr) {
-          currentRelativeChild->nextChild = child;
-        }
-        currentRelativeChild = child;
-        child->nextChild = nullptr;
-      }
-    }
-
-    // The total flex factor needs to be floored to 1.
-    if (totalFlexGrowFactors > 0 && totalFlexGrowFactors < 1) {
-      totalFlexGrowFactors = 1;
-    }
-
-    // The total flex shrink factor needs to be floored to 1.
-    if (totalFlexShrinkScaledFactors > 0 && totalFlexShrinkScaledFactors < 1) {
-      totalFlexShrinkScaledFactors = 1;
-    }
-
-    // If we don't need to measure the cross axis, we can skip the entire flex
-    // step.
-    const bool canSkipFlex = !performLayout && measureModeCrossDim == YGMeasureModeExactly;
-
-    // In order to position the elements in the main axis, we have two
-    // controls. The space between the beginning and the first element
-    // and the space between each two elements.
-    float leadingMainDim = 0;
-    float betweenMainDim = 0;
-
-    // STEP 5: RESOLVING FLEXIBLE LENGTHS ON MAIN AXIS
-    // Calculate the remaining available space that needs to be allocated.
-    // If the main dimension size isn't known, it is computed based on
-    // the line length, so there's no more space left to distribute.
-
-    bool sizeBasedOnContent = false;
-    // If we don't measure with exact main dimension we want to ensure we don't violate min and max
-    if (measureModeMainDim != YGMeasureModeExactly) {
-      if (!YGFloatIsUndefined(minInnerMainDim) && sizeConsumedOnCurrentLine < minInnerMainDim) {
-        availableInnerMainDim = minInnerMainDim;
-      } else if (!YGFloatIsUndefined(maxInnerMainDim) &&
-                 sizeConsumedOnCurrentLine > maxInnerMainDim) {
-        availableInnerMainDim = maxInnerMainDim;
-      } else {
-        if (!node->config->useLegacyStretchBehaviour &&
-            (totalFlexGrowFactors == 0 || YGResolveFlexGrow(node) == 0)) {
-          // If we don't have any children to flex or we can't flex the node itself,
-          // space we've used is all space we need. Root node also should be shrunk to minimum
-          availableInnerMainDim = sizeConsumedOnCurrentLine;
-        }
-        sizeBasedOnContent = !node->config->useLegacyStretchBehaviour;
-      }
-    }
-
-    float remainingFreeSpace = 0;
-    if (!sizeBasedOnContent && !YGFloatIsUndefined(availableInnerMainDim)) {
-      remainingFreeSpace = availableInnerMainDim - sizeConsumedOnCurrentLine;
-    } else if (sizeConsumedOnCurrentLine < 0) {
-      // availableInnerMainDim is indefinite which means the node is being sized based on its
-      // content.
-      // sizeConsumedOnCurrentLine is negative which means the node will allocate 0 points for
-      // its content. Consequently, remainingFreeSpace is 0 - sizeConsumedOnCurrentLine.
-      remainingFreeSpace = -sizeConsumedOnCurrentLine;
-    }
-
-    const float originalRemainingFreeSpace = remainingFreeSpace;
-    float deltaFreeSpace = 0;
-
-    if (!canSkipFlex) {
-      float childFlexBasis;
-      float flexShrinkScaledFactor;
-      float flexGrowFactor;
-      float baseMainSize;
-      float boundMainSize;
-
-      // Do two passes over the flex items to figure out how to distribute the
-      // remaining space.
-      // The first pass finds the items whose min/max constraints trigger,
-      // freezes them at those
-      // sizes, and excludes those sizes from the remaining space. The second
-      // pass sets the size
-      // of each flexible item. It distributes the remaining space amongst the
-      // items whose min/max
-      // constraints didn't trigger in pass 1. For the other items, it sets
-      // their sizes by forcing
-      // their min/max constraints to trigger again.
-      //
-      // This two pass approach for resolving min/max constraints deviates from
-      // the spec. The
-      // spec (https://www.w3.org/TR/YG-flexbox-1/#resolve-flexible-lengths)
-      // describes a process
-      // that needs to be repeated a variable number of times. The algorithm
-      // implemented here
-      // won't handle all cases but it was simpler to implement and it mitigates
-      // performance
-      // concerns because we know exactly how many passes it'll do.
-
-      // First pass: detect the flex items whose min/max constraints trigger
-      float deltaFlexShrinkScaledFactors = 0;
-      float deltaFlexGrowFactors = 0;
-      currentRelativeChild = firstRelativeChild;
-      while (currentRelativeChild != nullptr) {
-        childFlexBasis =
-            fminf(YGResolveValue(&currentRelativeChild->style.maxDimensions[dim[mainAxis]],
-                                 mainAxisParentSize),
-                  fmaxf(YGResolveValue(&currentRelativeChild->style.minDimensions[dim[mainAxis]],
-                                       mainAxisParentSize),
-                        currentRelativeChild->layout.computedFlexBasis));
-
-        if (remainingFreeSpace < 0) {
-          flexShrinkScaledFactor = -YGNodeResolveFlexShrink(currentRelativeChild) * childFlexBasis;
-
-          // Is this child able to shrink?
-          if (flexShrinkScaledFactor != 0) {
-            baseMainSize =
-                childFlexBasis +
-                remainingFreeSpace / totalFlexShrinkScaledFactors * flexShrinkScaledFactor;
-            boundMainSize = YGNodeBoundAxis(currentRelativeChild,
-                                            mainAxis,
-                                            baseMainSize,
-                                            availableInnerMainDim,
-                                            availableInnerWidth);
-            if (baseMainSize != boundMainSize) {
-              // By excluding this item's size and flex factor from remaining,
-              // this item's
-              // min/max constraints should also trigger in the second pass
-              // resulting in the
-              // item's size calculation being identical in the first and second
-              // passes.
-              deltaFreeSpace -= boundMainSize - childFlexBasis;
-              deltaFlexShrinkScaledFactors -= flexShrinkScaledFactor;
-            }
-          }
-        } else if (remainingFreeSpace > 0) {
-          flexGrowFactor = YGResolveFlexGrow(currentRelativeChild);
-
-          // Is this child able to grow?
-          if (flexGrowFactor != 0) {
-            baseMainSize =
-                childFlexBasis + remainingFreeSpace / totalFlexGrowFactors * flexGrowFactor;
-            boundMainSize = YGNodeBoundAxis(currentRelativeChild,
-                                            mainAxis,
-                                            baseMainSize,
-                                            availableInnerMainDim,
-                                            availableInnerWidth);
-
-            if (baseMainSize != boundMainSize) {
-              // By excluding this item's size and flex factor from remaining,
-              // this item's
-              // min/max constraints should also trigger in the second pass
-              // resulting in the
-              // item's size calculation being identical in the first and second
-              // passes.
-              deltaFreeSpace -= boundMainSize - childFlexBasis;
-              deltaFlexGrowFactors -= flexGrowFactor;
-            }
-          }
-        }
-
-        currentRelativeChild = currentRelativeChild->nextChild;
-      }
-
-      totalFlexShrinkScaledFactors += deltaFlexShrinkScaledFactors;
-      totalFlexGrowFactors += deltaFlexGrowFactors;
-      remainingFreeSpace += deltaFreeSpace;
-
-      // Second pass: resolve the sizes of the flexible items
-      deltaFreeSpace = 0;
-      currentRelativeChild = firstRelativeChild;
-      while (currentRelativeChild != nullptr) {
-        childFlexBasis =
-            fminf(YGResolveValue(&currentRelativeChild->style.maxDimensions[dim[mainAxis]],
-                                 mainAxisParentSize),
-                  fmaxf(YGResolveValue(&currentRelativeChild->style.minDimensions[dim[mainAxis]],
-                                       mainAxisParentSize),
-                        currentRelativeChild->layout.computedFlexBasis));
-        float updatedMainSize = childFlexBasis;
-
-        if (remainingFreeSpace < 0) {
-          flexShrinkScaledFactor = -YGNodeResolveFlexShrink(currentRelativeChild) * childFlexBasis;
-          // Is this child able to shrink?
-          if (flexShrinkScaledFactor != 0) {
-            float childSize;
-
-            if (totalFlexShrinkScaledFactors == 0) {
-              childSize = childFlexBasis + flexShrinkScaledFactor;
-            } else {
-              childSize =
-                  childFlexBasis +
-                  (remainingFreeSpace / totalFlexShrinkScaledFactors) * flexShrinkScaledFactor;
-            }
-
-            updatedMainSize = YGNodeBoundAxis(currentRelativeChild,
-                                              mainAxis,
-                                              childSize,
-                                              availableInnerMainDim,
-                                              availableInnerWidth);
-          }
-        } else if (remainingFreeSpace > 0) {
-          flexGrowFactor = YGResolveFlexGrow(currentRelativeChild);
-
-          // Is this child able to grow?
-          if (flexGrowFactor != 0) {
-            updatedMainSize =
-                YGNodeBoundAxis(currentRelativeChild,
-                                mainAxis,
-                                childFlexBasis +
-                                    remainingFreeSpace / totalFlexGrowFactors * flexGrowFactor,
-                                availableInnerMainDim,
-                                availableInnerWidth);
-          }
-        }
-
-        deltaFreeSpace -= updatedMainSize - childFlexBasis;
-
-        const float marginMain =
-            YGNodeMarginForAxis(currentRelativeChild, mainAxis, availableInnerWidth);
-        const float marginCross =
-            YGNodeMarginForAxis(currentRelativeChild, crossAxis, availableInnerWidth);
-
-        float childCrossSize;
-        float childMainSize = updatedMainSize + marginMain;
-        YGMeasureMode childCrossMeasureMode;
-        YGMeasureMode childMainMeasureMode = YGMeasureModeExactly;
-
-        if (!YGFloatIsUndefined(currentRelativeChild->style.aspectRatio)) {
-          childCrossSize =
-              isMainAxisRow
-                  ? (childMainSize - marginMain) / currentRelativeChild->style.aspectRatio
-                  : (childMainSize - marginMain) * currentRelativeChild->style.aspectRatio;
-          childCrossMeasureMode = YGMeasureModeExactly;
-
-          childCrossSize += marginCross;
-        } else if (!YGFloatIsUndefined(availableInnerCrossDim) &&
-                   !YGNodeIsStyleDimDefined(currentRelativeChild,
-                                            crossAxis,
-                                            availableInnerCrossDim) &&
-                   measureModeCrossDim == YGMeasureModeExactly &&
-                   !(isNodeFlexWrap && flexBasisOverflows) &&
-                   YGNodeAlignItem(node, currentRelativeChild) == YGAlignStretch &&
-                   YGMarginLeadingValue(currentRelativeChild, crossAxis)->unit != YGUnitAuto &&
-                   YGMarginTrailingValue(currentRelativeChild, crossAxis)->unit != YGUnitAuto) {
-          childCrossSize = availableInnerCrossDim;
-          childCrossMeasureMode = YGMeasureModeExactly;
-        } else if (!YGNodeIsStyleDimDefined(currentRelativeChild,
-                                            crossAxis,
-                                            availableInnerCrossDim)) {
-          childCrossSize = availableInnerCrossDim;
-          childCrossMeasureMode =
-              YGFloatIsUndefined(childCrossSize) ? YGMeasureModeUndefined : YGMeasureModeAtMost;
-        } else {
-          childCrossSize = YGResolveValue(currentRelativeChild->resolvedDimensions[dim[crossAxis]],
-                                          availableInnerCrossDim) +
-                           marginCross;
-          const bool isLoosePercentageMeasurement =
-              currentRelativeChild->resolvedDimensions[dim[crossAxis]]->unit == YGUnitPercent &&
-              measureModeCrossDim != YGMeasureModeExactly;
-          childCrossMeasureMode = YGFloatIsUndefined(childCrossSize) || isLoosePercentageMeasurement
-                                      ? YGMeasureModeUndefined
-                                      : YGMeasureModeExactly;
-        }
-
-        YGConstrainMaxSizeForMode(currentRelativeChild,
-                                  mainAxis,
-                                  availableInnerMainDim,
-                                  availableInnerWidth,
-                                  &childMainMeasureMode,
-                                  &childMainSize);
-        YGConstrainMaxSizeForMode(currentRelativeChild,
-                                  crossAxis,
-                                  availableInnerCrossDim,
-                                  availableInnerWidth,
-                                  &childCrossMeasureMode,
-                                  &childCrossSize);
-
-        const bool requiresStretchLayout =
-            !YGNodeIsStyleDimDefined(currentRelativeChild, crossAxis, availableInnerCrossDim) &&
-            YGNodeAlignItem(node, currentRelativeChild) == YGAlignStretch &&
-            YGMarginLeadingValue(currentRelativeChild, crossAxis)->unit != YGUnitAuto &&
-            YGMarginTrailingValue(currentRelativeChild, crossAxis)->unit != YGUnitAuto;
-
-        const float childWidth = isMainAxisRow ? childMainSize : childCrossSize;
-        const float childHeight = !isMainAxisRow ? childMainSize : childCrossSize;
-
-        const YGMeasureMode childWidthMeasureMode =
-            isMainAxisRow ? childMainMeasureMode : childCrossMeasureMode;
-        const YGMeasureMode childHeightMeasureMode =
-            !isMainAxisRow ? childMainMeasureMode : childCrossMeasureMode;
-
-        // Recursively call the layout algorithm for this child with the updated
-        // main size.
-        YGLayoutNodeInternal(currentRelativeChild,
-                             childWidth,
-                             childHeight,
-                             direction,
-                             childWidthMeasureMode,
-                             childHeightMeasureMode,
-                             availableInnerWidth,
-                             availableInnerHeight,
-                             performLayout && !requiresStretchLayout,
-                             "flex",
-                             config);
-        node->layout.hadOverflow |= currentRelativeChild->layout.hadOverflow;
-
-        currentRelativeChild = currentRelativeChild->nextChild;
-      }
-    }
-
-    remainingFreeSpace = originalRemainingFreeSpace + deltaFreeSpace;
-    node->layout.hadOverflow |= (remainingFreeSpace < 0);
-
-    // STEP 6: MAIN-AXIS JUSTIFICATION & CROSS-AXIS SIZE DETERMINATION
-
-    // At this point, all the children have their dimensions set in the main
-    // axis.
-    // Their dimensions are also set in the cross axis with the exception of
-    // items
-    // that are aligned "stretch". We need to compute these stretch values and
-    // set the final positions.
-
-    // If we are using "at most" rules in the main axis. Calculate the remaining space when
-    // constraint by the min size defined for the main axis.
-
-    if (measureModeMainDim == YGMeasureModeAtMost && remainingFreeSpace > 0) {
-      if (node->style.minDimensions[dim[mainAxis]].unit != YGUnitUndefined &&
-          YGResolveValue(&node->style.minDimensions[dim[mainAxis]], mainAxisParentSize) >= 0) {
-        remainingFreeSpace =
-            fmaxf(0,
-                  YGResolveValue(&node->style.minDimensions[dim[mainAxis]], mainAxisParentSize) -
-                      (availableInnerMainDim - remainingFreeSpace));
-      } else {
-        remainingFreeSpace = 0;
-      }
-    }
-
-    int numberOfAutoMarginsOnCurrentLine = 0;
-    for (uint32_t i = startOfLineIndex; i < endOfLineIndex; i++) {
-      const YGNodeRef child = node->children[i];
-      if (child->style.positionType == YGPositionTypeRelative) {
-        if (YGMarginLeadingValue(child, mainAxis)->unit == YGUnitAuto) {
-          numberOfAutoMarginsOnCurrentLine++;
-        }
-        if (YGMarginTrailingValue(child, mainAxis)->unit == YGUnitAuto) {
-          numberOfAutoMarginsOnCurrentLine++;
-        }
-      }
-    }
-
-    if (numberOfAutoMarginsOnCurrentLine == 0) {
-      switch (justifyContent) {
-        case YGJustifyCenter:
-          leadingMainDim = remainingFreeSpace / 2;
-          break;
-        case YGJustifyFlexEnd:
-          leadingMainDim = remainingFreeSpace;
-          break;
-        case YGJustifySpaceBetween:
-          if (itemsOnLine > 1) {
-            betweenMainDim = fmaxf(remainingFreeSpace, 0) / (itemsOnLine - 1);
-          } else {
-            betweenMainDim = 0;
-          }
-          break;
-        case YGJustifySpaceEvenly:
-          // Space is distributed evenly across all elements
-          betweenMainDim = remainingFreeSpace / (itemsOnLine + 1);
-          leadingMainDim = betweenMainDim;
-          break;
-        case YGJustifySpaceAround:
-          // Space on the edges is half of the space between elements
-          betweenMainDim = remainingFreeSpace / itemsOnLine;
-          leadingMainDim = betweenMainDim / 2;
-          break;
-        case YGJustifyFlexStart:
-          break;
-      }
-    }
-
-    float mainDim = leadingPaddingAndBorderMain + leadingMainDim;
-    float crossDim = 0;
-
-    for (uint32_t i = startOfLineIndex; i < endOfLineIndex; i++) {
-      const YGNodeRef child = node->children[i];
-      if (child->style.display == YGDisplayNone) {
-        continue;
-      }
-      if (child->style.positionType == YGPositionTypeAbsolute &&
-          YGNodeIsLeadingPosDefined(child, mainAxis)) {
-        if (performLayout) {
-          // In case the child is position absolute and has left/top being
-          // defined, we override the position to whatever the user said
-          // (and margin/border).
-          child->layout.position[pos[mainAxis]] =
-              YGNodeLeadingPosition(child, mainAxis, availableInnerMainDim) +
-              YGNodeLeadingBorder(node, mainAxis) +
-              YGNodeLeadingMargin(child, mainAxis, availableInnerWidth);
-        }
-      } else {
-        // Now that we placed the element, we need to update the variables.
-        // We need to do that only for relative elements. Absolute elements
-        // do not take part in that phase.
-        if (child->style.positionType == YGPositionTypeRelative) {
-          if (YGMarginLeadingValue(child, mainAxis)->unit == YGUnitAuto) {
-            mainDim += remainingFreeSpace / numberOfAutoMarginsOnCurrentLine;
-          }
-
-          if (performLayout) {
-            child->layout.position[pos[mainAxis]] += mainDim;
-          }
-
-          if (YGMarginTrailingValue(child, mainAxis)->unit == YGUnitAuto) {
-            mainDim += remainingFreeSpace / numberOfAutoMarginsOnCurrentLine;
-          }
-
-          if (canSkipFlex) {
-            // If we skipped the flex step, then we can't rely on the
-            // measuredDims because
-            // they weren't computed. This means we can't call YGNodeDimWithMargin.
-            mainDim += betweenMainDim + YGNodeMarginForAxis(child, mainAxis, availableInnerWidth) +
-                       child->layout.computedFlexBasis;
-            crossDim = availableInnerCrossDim;
-          } else {
-            // The main dimension is the sum of all the elements dimension plus the spacing.
-            mainDim += betweenMainDim + YGNodeDimWithMargin(child, mainAxis, availableInnerWidth);
-
-            // The cross dimension is the max of the elements dimension since
-            // there can only be one element in that cross dimension.
-            crossDim = fmaxf(crossDim, YGNodeDimWithMargin(child, crossAxis, availableInnerWidth));
-          }
-        } else if (performLayout) {
-          child->layout.position[pos[mainAxis]] +=
-              YGNodeLeadingBorder(node, mainAxis) + leadingMainDim;
-        }
-      }
-    }
-
-    mainDim += trailingPaddingAndBorderMain;
-
-    float containerCrossAxis = availableInnerCrossDim;
-    if (measureModeCrossDim == YGMeasureModeUndefined ||
-        measureModeCrossDim == YGMeasureModeAtMost) {
-      // Compute the cross axis from the max cross dimension of the children.
-      containerCrossAxis = YGNodeBoundAxis(node,
-                                           crossAxis,
-                                           crossDim + paddingAndBorderAxisCross,
-                                           crossAxisParentSize,
-                                           parentWidth) -
-                           paddingAndBorderAxisCross;
-    }
-
-    // If there's no flex wrap, the cross dimension is defined by the container.
-    if (!isNodeFlexWrap && measureModeCrossDim == YGMeasureModeExactly) {
-      crossDim = availableInnerCrossDim;
-    }
-
-    // Clamp to the min/max size specified on the container.
-    crossDim = YGNodeBoundAxis(node,
-                               crossAxis,
-                               crossDim + paddingAndBorderAxisCross,
-                               crossAxisParentSize,
-                               parentWidth) -
-               paddingAndBorderAxisCross;
-
-    // STEP 7: CROSS-AXIS ALIGNMENT
-    // We can skip child alignment if we're just measuring the container.
-    if (performLayout) {
-      for (uint32_t i = startOfLineIndex; i < endOfLineIndex; i++) {
-        const YGNodeRef child = node->children[i];
-        if (child->style.display == YGDisplayNone) {
-          continue;
-        }
-        if (child->style.positionType == YGPositionTypeAbsolute) {
-          // If the child is absolutely positioned and has a
-          // top/left/bottom/right
-          // set, override all the previously computed positions to set it
-          // correctly.
-          const bool isChildLeadingPosDefined = YGNodeIsLeadingPosDefined(child, crossAxis);
-          if (isChildLeadingPosDefined) {
-            child->layout.position[pos[crossAxis]] =
-                YGNodeLeadingPosition(child, crossAxis, availableInnerCrossDim) +
-                YGNodeLeadingBorder(node, crossAxis) +
-                YGNodeLeadingMargin(child, crossAxis, availableInnerWidth);
-          }
-          // If leading position is not defined or calculations result in Nan, default to border + margin
-          if (!isChildLeadingPosDefined || YGFloatIsUndefined(child->layout.position[pos[crossAxis]])) {
-            child->layout.position[pos[crossAxis]] =
-                YGNodeLeadingBorder(node, crossAxis) +
-                YGNodeLeadingMargin(child, crossAxis, availableInnerWidth);
-          }
-        } else {
-          float leadingCrossDim = leadingPaddingAndBorderCross;
-
-          // For a relative children, we're either using alignItems (parent) or
-          // alignSelf (child) in order to determine the position in the cross
-          // axis
-          const YGAlign alignItem = YGNodeAlignItem(node, child);
-
-          // If the child uses align stretch, we need to lay it out one more
-          // time, this time
-          // forcing the cross-axis size to be the computed cross size for the
-          // current line.
-          if (alignItem == YGAlignStretch &&
-              YGMarginLeadingValue(child, crossAxis)->unit != YGUnitAuto &&
-              YGMarginTrailingValue(child, crossAxis)->unit != YGUnitAuto) {
-            // If the child defines a definite size for its cross axis, there's
-            // no need to stretch.
-            if (!YGNodeIsStyleDimDefined(child, crossAxis, availableInnerCrossDim)) {
-              float childMainSize = child->layout.measuredDimensions[dim[mainAxis]];
-              float childCrossSize =
-                  !YGFloatIsUndefined(child->style.aspectRatio)
-                      ? ((YGNodeMarginForAxis(child, crossAxis, availableInnerWidth) +
-                          (isMainAxisRow ? childMainSize / child->style.aspectRatio
-                                         : childMainSize * child->style.aspectRatio)))
-                      : crossDim;
-
-              childMainSize += YGNodeMarginForAxis(child, mainAxis, availableInnerWidth);
-
-              YGMeasureMode childMainMeasureMode = YGMeasureModeExactly;
-              YGMeasureMode childCrossMeasureMode = YGMeasureModeExactly;
-              YGConstrainMaxSizeForMode(child,
-                                        mainAxis,
-                                        availableInnerMainDim,
-                                        availableInnerWidth,
-                                        &childMainMeasureMode,
-                                        &childMainSize);
-              YGConstrainMaxSizeForMode(child,
-                                        crossAxis,
-                                        availableInnerCrossDim,
-                                        availableInnerWidth,
-                                        &childCrossMeasureMode,
-                                        &childCrossSize);
-
-              const float childWidth = isMainAxisRow ? childMainSize : childCrossSize;
-              const float childHeight = !isMainAxisRow ? childMainSize : childCrossSize;
-
-              const YGMeasureMode childWidthMeasureMode =
-                  YGFloatIsUndefined(childWidth) ? YGMeasureModeUndefined : YGMeasureModeExactly;
-              const YGMeasureMode childHeightMeasureMode =
-                  YGFloatIsUndefined(childHeight) ? YGMeasureModeUndefined : YGMeasureModeExactly;
-
-              YGLayoutNodeInternal(child,
-                                   childWidth,
-                                   childHeight,
-                                   direction,
-                                   childWidthMeasureMode,
-                                   childHeightMeasureMode,
-                                   availableInnerWidth,
-                                   availableInnerHeight,
-                                   true,
-                                   "stretch",
-                                   config);
-            }
-          } else {
-            const float remainingCrossDim =
-                containerCrossAxis - YGNodeDimWithMargin(child, crossAxis, availableInnerWidth);
-
-            if (YGMarginLeadingValue(child, crossAxis)->unit == YGUnitAuto &&
-                YGMarginTrailingValue(child, crossAxis)->unit == YGUnitAuto) {
-              leadingCrossDim += fmaxf(0.0f, remainingCrossDim / 2);
-            } else if (YGMarginTrailingValue(child, crossAxis)->unit == YGUnitAuto) {
-              // No-Op
-            } else if (YGMarginLeadingValue(child, crossAxis)->unit == YGUnitAuto) {
-              leadingCrossDim += fmaxf(0.0f, remainingCrossDim);
-            } else if (alignItem == YGAlignFlexStart) {
-              // No-Op
-            } else if (alignItem == YGAlignCenter) {
-              leadingCrossDim += remainingCrossDim / 2;
-            } else {
-              leadingCrossDim += remainingCrossDim;
-            }
-          }
-          // And we apply the position
-          child->layout.position[pos[crossAxis]] += totalLineCrossDim + leadingCrossDim;
-        }
-      }
-    }
-
-    totalLineCrossDim += crossDim;
-    maxLineMainDim = fmaxf(maxLineMainDim, mainDim);
-  }
-
-  // STEP 8: MULTI-LINE CONTENT ALIGNMENT
-  if (performLayout && (lineCount > 1 || YGIsBaselineLayout(node)) &&
-      !YGFloatIsUndefined(availableInnerCrossDim)) {
-    const float remainingAlignContentDim = availableInnerCrossDim - totalLineCrossDim;
-
-    float crossDimLead = 0;
-    float currentLead = leadingPaddingAndBorderCross;
-
-    switch (node->style.alignContent) {
-      case YGAlignFlexEnd:
-        currentLead += remainingAlignContentDim;
-        break;
-      case YGAlignCenter:
-        currentLead += remainingAlignContentDim / 2;
-        break;
-      case YGAlignStretch:
-        if (availableInnerCrossDim > totalLineCrossDim) {
-          crossDimLead = remainingAlignContentDim / lineCount;
-        }
-        break;
-      case YGAlignSpaceAround:
-        if (availableInnerCrossDim > totalLineCrossDim) {
-          currentLead += remainingAlignContentDim / (2 * lineCount);
-          if (lineCount > 1) {
-            crossDimLead = remainingAlignContentDim / lineCount;
-          }
-        } else {
-          currentLead += remainingAlignContentDim / 2;
-        }
-        break;
-      case YGAlignSpaceBetween:
-        if (availableInnerCrossDim > totalLineCrossDim && lineCount > 1) {
-          crossDimLead = remainingAlignContentDim / (lineCount - 1);
-        }
-        break;
-      case YGAlignAuto:
-      case YGAlignFlexStart:
-      case YGAlignBaseline:
-        break;
-    }
-
-    uint32_t endIndex = 0;
-    for (uint32_t i = 0; i < lineCount; i++) {
-      const uint32_t startIndex = endIndex;
-      uint32_t ii;
-
-      // compute the line's height and find the endIndex
-      float lineHeight = 0;
-      float maxAscentForCurrentLine = 0;
-      float maxDescentForCurrentLine = 0;
-      for (ii = startIndex; ii < childCount; ii++) {
-        const YGNodeRef child = node->children[ii];
-        if (child->style.display == YGDisplayNone) {
-          continue;
-        }
-        if (child->style.positionType == YGPositionTypeRelative) {
-          if (child->lineIndex != i) {
-            break;
-          }
-          if (YGNodeIsLayoutDimDefined(child, crossAxis)) {
-            lineHeight = fmaxf(lineHeight,
-                               child->layout.measuredDimensions[dim[crossAxis]] +
-                                   YGNodeMarginForAxis(child, crossAxis, availableInnerWidth));
-          }
-          if (YGNodeAlignItem(node, child) == YGAlignBaseline) {
-            const float ascent =
-                YGBaseline(child) +
-                YGNodeLeadingMargin(child, YGFlexDirectionColumn, availableInnerWidth);
-            const float descent =
-                child->layout.measuredDimensions[YGDimensionHeight] +
-                YGNodeMarginForAxis(child, YGFlexDirectionColumn, availableInnerWidth) - ascent;
-            maxAscentForCurrentLine = fmaxf(maxAscentForCurrentLine, ascent);
-            maxDescentForCurrentLine = fmaxf(maxDescentForCurrentLine, descent);
-            lineHeight = fmaxf(lineHeight, maxAscentForCurrentLine + maxDescentForCurrentLine);
-          }
-        }
-      }
-      endIndex = ii;
-      lineHeight += crossDimLead;
-
-      if (performLayout) {
-        for (ii = startIndex; ii < endIndex; ii++) {
-          const YGNodeRef child = node->children[ii];
-          if (child->style.display == YGDisplayNone) {
-            continue;
-          }
-          if (child->style.positionType == YGPositionTypeRelative) {
-            switch (YGNodeAlignItem(node, child)) {
-              case YGAlignFlexStart: {
-                child->layout.position[pos[crossAxis]] =
-                    currentLead + YGNodeLeadingMargin(child, crossAxis, availableInnerWidth);
-                break;
-              }
-              case YGAlignFlexEnd: {
-                child->layout.position[pos[crossAxis]] =
-                    currentLead + lineHeight -
-                    YGNodeTrailingMargin(child, crossAxis, availableInnerWidth) -
-                    child->layout.measuredDimensions[dim[crossAxis]];
-                break;
-              }
-              case YGAlignCenter: {
-                float childHeight = child->layout.measuredDimensions[dim[crossAxis]];
-                child->layout.position[pos[crossAxis]] =
-                    currentLead + (lineHeight - childHeight) / 2;
-                break;
-              }
-              case YGAlignStretch: {
-                child->layout.position[pos[crossAxis]] =
-                    currentLead + YGNodeLeadingMargin(child, crossAxis, availableInnerWidth);
-
-                // Remeasure child with the line height as it as been only measured with the
-                // parents height yet.
-                if (!YGNodeIsStyleDimDefined(child, crossAxis, availableInnerCrossDim)) {
-                  const float childWidth =
-                      isMainAxisRow ? (child->layout.measuredDimensions[YGDimensionWidth] +
-                                       YGNodeMarginForAxis(child, mainAxis, availableInnerWidth))
-                                    : lineHeight;
-
-                  const float childHeight =
-                      !isMainAxisRow ? (child->layout.measuredDimensions[YGDimensionHeight] +
-                                        YGNodeMarginForAxis(child, crossAxis, availableInnerWidth))
-                                     : lineHeight;
-
-                  if (!(YGFloatsEqual(childWidth,
-                                      child->layout.measuredDimensions[YGDimensionWidth]) &&
-                        YGFloatsEqual(childHeight,
-                                      child->layout.measuredDimensions[YGDimensionHeight]))) {
-                    YGLayoutNodeInternal(child,
-                                         childWidth,
-                                         childHeight,
-                                         direction,
-                                         YGMeasureModeExactly,
-                                         YGMeasureModeExactly,
-                                         availableInnerWidth,
-                                         availableInnerHeight,
-                                         true,
-                                         "multiline-stretch",
-                                         config);
-                  }
-                }
-                break;
-              }
-              case YGAlignBaseline: {
-                child->layout.position[YGEdgeTop] =
-                    currentLead + maxAscentForCurrentLine - YGBaseline(child) +
-                    YGNodeLeadingPosition(child, YGFlexDirectionColumn, availableInnerCrossDim);
-                break;
-              }
-              case YGAlignAuto:
-              case YGAlignSpaceBetween:
-              case YGAlignSpaceAround:
-                break;
-            }
-          }
-        }
-      }
-
-      currentLead += lineHeight;
-    }
-  }
-
-  // STEP 9: COMPUTING FINAL DIMENSIONS
-  node->layout.measuredDimensions[YGDimensionWidth] = YGNodeBoundAxis(
-      node, YGFlexDirectionRow, availableWidth - marginAxisRow, parentWidth, parentWidth);
-  node->layout.measuredDimensions[YGDimensionHeight] = YGNodeBoundAxis(
-      node, YGFlexDirectionColumn, availableHeight - marginAxisColumn, parentHeight, parentWidth);
-
-  // If the user didn't specify a width or height for the node, set the
-  // dimensions based on the children.
-  if (measureModeMainDim == YGMeasureModeUndefined ||
-      (node->style.overflow != YGOverflowScroll && measureModeMainDim == YGMeasureModeAtMost)) {
-    // Clamp the size to the min/max size, if specified, and make sure it
-    // doesn't go below the padding and border amount.
-    node->layout.measuredDimensions[dim[mainAxis]] =
-        YGNodeBoundAxis(node, mainAxis, maxLineMainDim, mainAxisParentSize, parentWidth);
-  } else if (measureModeMainDim == YGMeasureModeAtMost &&
-             node->style.overflow == YGOverflowScroll) {
-    node->layout.measuredDimensions[dim[mainAxis]] = fmaxf(
-        fminf(availableInnerMainDim + paddingAndBorderAxisMain,
-              YGNodeBoundAxisWithinMinAndMax(node, mainAxis, maxLineMainDim, mainAxisParentSize)),
-        paddingAndBorderAxisMain);
-  }
-
-  if (measureModeCrossDim == YGMeasureModeUndefined ||
-      (node->style.overflow != YGOverflowScroll && measureModeCrossDim == YGMeasureModeAtMost)) {
-    // Clamp the size to the min/max size, if specified, and make sure it
-    // doesn't go below the padding and border amount.
-    node->layout.measuredDimensions[dim[crossAxis]] =
-        YGNodeBoundAxis(node,
-                        crossAxis,
-                        totalLineCrossDim + paddingAndBorderAxisCross,
-                        crossAxisParentSize,
-                        parentWidth);
-  } else if (measureModeCrossDim == YGMeasureModeAtMost &&
-             node->style.overflow == YGOverflowScroll) {
-    node->layout.measuredDimensions[dim[crossAxis]] =
-        fmaxf(fminf(availableInnerCrossDim + paddingAndBorderAxisCross,
-                    YGNodeBoundAxisWithinMinAndMax(node,
-                                                   crossAxis,
-                                                   totalLineCrossDim + paddingAndBorderAxisCross,
-                                                   crossAxisParentSize)),
-              paddingAndBorderAxisCross);
-  }
-
-  // As we only wrapped in normal direction yet, we need to reverse the positions on wrap-reverse.
-  if (performLayout && node->style.flexWrap == YGWrapWrapReverse) {
-    for (uint32_t i = 0; i < childCount; i++) {
-      const YGNodeRef child = YGNodeGetChild(node, i);
-      if (child->style.positionType == YGPositionTypeRelative) {
-        child->layout.position[pos[crossAxis]] = node->layout.measuredDimensions[dim[crossAxis]] -
-                                                 child->layout.position[pos[crossAxis]] -
-                                                 child->layout.measuredDimensions[dim[crossAxis]];
-      }
-    }
-  }
-
-  if (performLayout) {
-    // STEP 10: SIZING AND POSITIONING ABSOLUTE CHILDREN
-    for (currentAbsoluteChild = firstAbsoluteChild;
-         currentAbsoluteChild != nullptr;
-         currentAbsoluteChild = currentAbsoluteChild->nextChild) {
-      YGNodeAbsoluteLayoutChild(node,
-                                currentAbsoluteChild,
-                                availableInnerWidth,
-                                isMainAxisRow ? measureModeMainDim : measureModeCrossDim,
-                                availableInnerHeight,
-                                direction,
-                                config);
-    }
-
-    // STEP 11: SETTING TRAILING POSITIONS FOR CHILDREN
-    const bool needsMainTrailingPos =
-        mainAxis == YGFlexDirectionRowReverse || mainAxis == YGFlexDirectionColumnReverse;
-    const bool needsCrossTrailingPos =
-        crossAxis == YGFlexDirectionRowReverse || crossAxis == YGFlexDirectionColumnReverse;
-
-    // Set trailing position if necessary.
-    if (needsMainTrailingPos || needsCrossTrailingPos) {
-      for (uint32_t i = 0; i < childCount; i++) {
-        const YGNodeRef child = node->children[i];
-        if (child->style.display == YGDisplayNone) {
-          continue;
-        }
-        if (needsMainTrailingPos) {
-          YGNodeSetChildTrailingPosition(node, child, mainAxis);
-        }
-
-        if (needsCrossTrailingPos) {
-          YGNodeSetChildTrailingPosition(node, child, crossAxis);
-        }
-      }
-    }
-  }
-}
-
-uint32_t gDepth = 0;
-bool gPrintTree = false;
-bool gPrintChanges = false;
-bool gPrintSkips = false;
-
-static const char *spacer = "                                                            ";
-
-static const char *YGSpacer(const unsigned long level) {
-  const size_t spacerLen = strlen(spacer);
-  if (level > spacerLen) {
-    return &spacer[0];
-  } else {
-    return &spacer[spacerLen - level];
-  }
-}
-
-static const char *YGMeasureModeName(const YGMeasureMode mode, const bool performLayout) {
-  const char *kMeasureModeNames[YGMeasureModeCount] = {"UNDEFINED", "EXACTLY", "AT_MOST"};
-  const char *kLayoutModeNames[YGMeasureModeCount] = {"LAY_UNDEFINED",
-                                                      "LAY_EXACTLY",
-                                                      "LAY_AT_"
-                                                      "MOST"};
-
-  if (mode >= YGMeasureModeCount) {
-    return "";
-  }
-
-  return performLayout ? kLayoutModeNames[mode] : kMeasureModeNames[mode];
-}
-
-static inline bool YGMeasureModeSizeIsExactAndMatchesOldMeasuredSize(YGMeasureMode sizeMode,
-                                                                     float size,
-                                                                     float lastComputedSize) {
-  return sizeMode == YGMeasureModeExactly && YGFloatsEqual(size, lastComputedSize);
-}
-
-static inline bool YGMeasureModeOldSizeIsUnspecifiedAndStillFits(YGMeasureMode sizeMode,
-                                                                 float size,
-                                                                 YGMeasureMode lastSizeMode,
-                                                                 float lastComputedSize) {
-  return sizeMode == YGMeasureModeAtMost && lastSizeMode == YGMeasureModeUndefined &&
-         (size >= lastComputedSize || YGFloatsEqual(size, lastComputedSize));
-}
-
-static inline bool YGMeasureModeNewMeasureSizeIsStricterAndStillValid(YGMeasureMode sizeMode,
-                                                                      float size,
-                                                                      YGMeasureMode lastSizeMode,
-                                                                      float lastSize,
-                                                                      float lastComputedSize) {
-  return lastSizeMode == YGMeasureModeAtMost && sizeMode == YGMeasureModeAtMost &&
-         lastSize > size && (lastComputedSize <= size || YGFloatsEqual(size, lastComputedSize));
-}
-
-float YGRoundValueToPixelGrid(const float value,
-                              const float pointScaleFactor,
-                              const bool forceCeil,
-                              const bool forceFloor) {
-  float scaledValue = value * pointScaleFactor;
-  float fractial = fmodf(scaledValue, 1.0);
-  if (YGFloatsEqual(fractial, 0)) {
-    // First we check if the value is already rounded
-    scaledValue = scaledValue - fractial;
-  } else if (YGFloatsEqual(fractial, 1.0)) {
-    scaledValue = scaledValue - fractial + 1.0;
-  } else if (forceCeil) {
-    // Next we check if we need to use forced rounding
-    scaledValue = scaledValue - fractial + 1.0f;
-  } else if (forceFloor) {
-    scaledValue = scaledValue - fractial;
-  } else {
-    // Finally we just round the value
-    scaledValue = scaledValue - fractial +
-        (fractial > 0.5f || YGFloatsEqual(fractial, 0.5f) ? 1.0f : 0.0f);
-  }
-  return scaledValue / pointScaleFactor;
-}
-
-bool YGNodeCanUseCachedMeasurement(const YGMeasureMode widthMode,
-                                   const float width,
-                                   const YGMeasureMode heightMode,
-                                   const float height,
-                                   const YGMeasureMode lastWidthMode,
-                                   const float lastWidth,
-                                   const YGMeasureMode lastHeightMode,
-                                   const float lastHeight,
-                                   const float lastComputedWidth,
-                                   const float lastComputedHeight,
-                                   const float marginRow,
-                                   const float marginColumn,
-                                   const YGConfigRef config) {
-  if (lastComputedHeight < 0 || lastComputedWidth < 0) {
-    return false;
-  }
-  bool useRoundedComparison =
-      config != nullptr && config->pointScaleFactor != 0;
-  const float effectiveWidth =
-      useRoundedComparison ? YGRoundValueToPixelGrid(width, config->pointScaleFactor, false, false)
-                           : width;
-  const float effectiveHeight =
-      useRoundedComparison ? YGRoundValueToPixelGrid(height, config->pointScaleFactor, false, false)
-                           : height;
-  const float effectiveLastWidth =
-      useRoundedComparison
-          ? YGRoundValueToPixelGrid(lastWidth, config->pointScaleFactor, false, false)
-          : lastWidth;
-  const float effectiveLastHeight =
-      useRoundedComparison
-          ? YGRoundValueToPixelGrid(lastHeight, config->pointScaleFactor, false, false)
-          : lastHeight;
-
-  const bool hasSameWidthSpec =
-      lastWidthMode == widthMode && YGFloatsEqual(effectiveLastWidth, effectiveWidth);
-  const bool hasSameHeightSpec =
-      lastHeightMode == heightMode && YGFloatsEqual(effectiveLastHeight, effectiveHeight);
-
-  const bool widthIsCompatible =
-      hasSameWidthSpec || YGMeasureModeSizeIsExactAndMatchesOldMeasuredSize(widthMode,
-                                                                            width - marginRow,
-                                                                            lastComputedWidth) ||
-      YGMeasureModeOldSizeIsUnspecifiedAndStillFits(widthMode,
-                                                    width - marginRow,
-                                                    lastWidthMode,
-                                                    lastComputedWidth) ||
-      YGMeasureModeNewMeasureSizeIsStricterAndStillValid(
-          widthMode, width - marginRow, lastWidthMode, lastWidth, lastComputedWidth);
-
-  const bool heightIsCompatible =
-      hasSameHeightSpec || YGMeasureModeSizeIsExactAndMatchesOldMeasuredSize(heightMode,
-                                                                             height - marginColumn,
-                                                                             lastComputedHeight) ||
-      YGMeasureModeOldSizeIsUnspecifiedAndStillFits(heightMode,
-                                                    height - marginColumn,
-                                                    lastHeightMode,
-                                                    lastComputedHeight) ||
-      YGMeasureModeNewMeasureSizeIsStricterAndStillValid(
-          heightMode, height - marginColumn, lastHeightMode, lastHeight, lastComputedHeight);
-
-  return widthIsCompatible && heightIsCompatible;
-}
-
-//
-// This is a wrapper around the YGNodelayoutImpl function. It determines
-// whether the layout request is redundant and can be skipped.
-//
-// Parameters:
-//  Input parameters are the same as YGNodelayoutImpl (see above)
-//  Return parameter is true if layout was performed, false if skipped
-//
-bool YGLayoutNodeInternal(const YGNodeRef node,
-                          const float availableWidth,
-                          const float availableHeight,
-                          const YGDirection parentDirection,
-                          const YGMeasureMode widthMeasureMode,
-                          const YGMeasureMode heightMeasureMode,
-                          const float parentWidth,
-                          const float parentHeight,
-                          const bool performLayout,
-                          const char *reason,
-                          const YGConfigRef config) {
-  YGLayout *layout = &node->layout;
-
-  gDepth++;
-
-  const bool needToVisitNode =
-      (node->isDirty && layout->generationCount != gCurrentGenerationCount) ||
-      layout->lastParentDirection != parentDirection;
-
-  if (needToVisitNode) {
-    // Invalidate the cached results.
-    layout->nextCachedMeasurementsIndex = 0;
-    layout->cachedLayout.widthMeasureMode = (YGMeasureMode) -1;
-    layout->cachedLayout.heightMeasureMode = (YGMeasureMode) -1;
-    layout->cachedLayout.computedWidth = -1;
-    layout->cachedLayout.computedHeight = -1;
-  }
-
-  YGCachedMeasurement* cachedResults = nullptr;
-
-  // Determine whether the results are already cached. We maintain a separate
-  // cache for layouts and measurements. A layout operation modifies the
-  // positions
-  // and dimensions for nodes in the subtree. The algorithm assumes that each
-  // node
-  // gets layed out a maximum of one time per tree layout, but multiple
-  // measurements
-  // may be required to resolve all of the flex dimensions.
-  // We handle nodes with measure functions specially here because they are the
-  // most
-  // expensive to measure, so it's worth avoiding redundant measurements if at
-  // all possible.
-  if (node->measure) {
-    const float marginAxisRow = YGNodeMarginForAxis(node, YGFlexDirectionRow, parentWidth);
-    const float marginAxisColumn = YGNodeMarginForAxis(node, YGFlexDirectionColumn, parentWidth);
-
-    // First, try to use the layout cache.
-    if (YGNodeCanUseCachedMeasurement(widthMeasureMode,
-                                      availableWidth,
-                                      heightMeasureMode,
-                                      availableHeight,
-                                      layout->cachedLayout.widthMeasureMode,
-                                      layout->cachedLayout.availableWidth,
-                                      layout->cachedLayout.heightMeasureMode,
-                                      layout->cachedLayout.availableHeight,
-                                      layout->cachedLayout.computedWidth,
-                                      layout->cachedLayout.computedHeight,
-                                      marginAxisRow,
-                                      marginAxisColumn,
-                                      config)) {
-      cachedResults = &layout->cachedLayout;
-    } else {
-      // Try to use the measurement cache.
-      for (uint32_t i = 0; i < layout->nextCachedMeasurementsIndex; i++) {
-        if (YGNodeCanUseCachedMeasurement(widthMeasureMode,
-                                          availableWidth,
-                                          heightMeasureMode,
-                                          availableHeight,
-                                          layout->cachedMeasurements[i].widthMeasureMode,
-                                          layout->cachedMeasurements[i].availableWidth,
-                                          layout->cachedMeasurements[i].heightMeasureMode,
-                                          layout->cachedMeasurements[i].availableHeight,
-                                          layout->cachedMeasurements[i].computedWidth,
-                                          layout->cachedMeasurements[i].computedHeight,
-                                          marginAxisRow,
-                                          marginAxisColumn,
-                                          config)) {
-          cachedResults = &layout->cachedMeasurements[i];
-          break;
-        }
-      }
-    }
-  } else if (performLayout) {
-    if (YGFloatsEqual(layout->cachedLayout.availableWidth, availableWidth) &&
-        YGFloatsEqual(layout->cachedLayout.availableHeight, availableHeight) &&
-        layout->cachedLayout.widthMeasureMode == widthMeasureMode &&
-        layout->cachedLayout.heightMeasureMode == heightMeasureMode) {
-      cachedResults = &layout->cachedLayout;
-    }
-  } else {
-    for (uint32_t i = 0; i < layout->nextCachedMeasurementsIndex; i++) {
-      if (YGFloatsEqual(layout->cachedMeasurements[i].availableWidth, availableWidth) &&
-          YGFloatsEqual(layout->cachedMeasurements[i].availableHeight, availableHeight) &&
-          layout->cachedMeasurements[i].widthMeasureMode == widthMeasureMode &&
-          layout->cachedMeasurements[i].heightMeasureMode == heightMeasureMode) {
-        cachedResults = &layout->cachedMeasurements[i];
-        break;
-      }
-    }
-  }
-
-  if (!needToVisitNode && cachedResults != nullptr) {
-    layout->measuredDimensions[YGDimensionWidth] = cachedResults->computedWidth;
-    layout->measuredDimensions[YGDimensionHeight] = cachedResults->computedHeight;
-
-    if (gPrintChanges && gPrintSkips) {
-      YGLog(node, YGLogLevelVerbose, "%s%d.{[skipped] ", YGSpacer(gDepth), gDepth);
-      if (node->print) {
-        node->print(node);
-      }
-      YGLog(
-          node,
-          YGLogLevelVerbose,
-          "wm: %s, hm: %s, aw: %f ah: %f => d: (%f, %f) %s\n",
-          YGMeasureModeName(widthMeasureMode, performLayout),
-          YGMeasureModeName(heightMeasureMode, performLayout),
-          availableWidth,
-          availableHeight,
-          cachedResults->computedWidth,
-          cachedResults->computedHeight,
-          reason);
-    }
-  } else {
-    if (gPrintChanges) {
-      YGLog(
-          node,
-          YGLogLevelVerbose,
-          "%s%d.{%s",
-          YGSpacer(gDepth),
-          gDepth,
-          needToVisitNode ? "*" : "");
-      if (node->print) {
-        node->print(node);
-      }
-      YGLog(
-          node,
-          YGLogLevelVerbose,
-          "wm: %s, hm: %s, aw: %f ah: %f %s\n",
-          YGMeasureModeName(widthMeasureMode, performLayout),
-          YGMeasureModeName(heightMeasureMode, performLayout),
-          availableWidth,
-          availableHeight,
-          reason);
-    }
-
-    YGNodelayoutImpl(node,
-                     availableWidth,
-                     availableHeight,
-                     parentDirection,
-                     widthMeasureMode,
-                     heightMeasureMode,
-                     parentWidth,
-                     parentHeight,
-                     performLayout,
-                     config);
-
-    if (gPrintChanges) {
-      YGLog(
-          node,
-          YGLogLevelVerbose,
-          "%s%d.}%s",
-          YGSpacer(gDepth),
-          gDepth,
-          needToVisitNode ? "*" : "");
-      if (node->print) {
-        node->print(node);
-      }
-      YGLog(
-          node,
-          YGLogLevelVerbose,
-          "wm: %s, hm: %s, d: (%f, %f) %s\n",
-          YGMeasureModeName(widthMeasureMode, performLayout),
-          YGMeasureModeName(heightMeasureMode, performLayout),
-          layout->measuredDimensions[YGDimensionWidth],
-          layout->measuredDimensions[YGDimensionHeight],
-          reason);
-    }
-
-    layout->lastParentDirection = parentDirection;
-
-    if (cachedResults == nullptr) {
-      if (layout->nextCachedMeasurementsIndex == YG_MAX_CACHED_RESULT_COUNT) {
-        if (gPrintChanges) {
-          YGLog(node, YGLogLevelVerbose, "Out of cache entries!\n");
-        }
-        layout->nextCachedMeasurementsIndex = 0;
-      }
-
-      YGCachedMeasurement *newCacheEntry;
-      if (performLayout) {
-        // Use the single layout cache entry.
-        newCacheEntry = &layout->cachedLayout;
-      } else {
-        // Allocate a new measurement cache entry.
-        newCacheEntry = &layout->cachedMeasurements[layout->nextCachedMeasurementsIndex];
-        layout->nextCachedMeasurementsIndex++;
-      }
-
-      newCacheEntry->availableWidth = availableWidth;
-      newCacheEntry->availableHeight = availableHeight;
-      newCacheEntry->widthMeasureMode = widthMeasureMode;
-      newCacheEntry->heightMeasureMode = heightMeasureMode;
-      newCacheEntry->computedWidth = layout->measuredDimensions[YGDimensionWidth];
-      newCacheEntry->computedHeight = layout->measuredDimensions[YGDimensionHeight];
-    }
-  }
-
-  if (performLayout) {
-    node->layout.dimensions[YGDimensionWidth] = node->layout.measuredDimensions[YGDimensionWidth];
-    node->layout.dimensions[YGDimensionHeight] = node->layout.measuredDimensions[YGDimensionHeight];
-    node->hasNewLayout = true;
-    node->isDirty = false;
-  }
-
-  gDepth--;
-  layout->generationCount = gCurrentGenerationCount;
-  return (needToVisitNode || cachedResults == nullptr);
-}
-
-void YGConfigSetPointScaleFactor(const YGConfigRef config, const float pixelsInPoint) {
-  YGAssertWithConfig(config, pixelsInPoint >= 0.0f, "Scale factor should not be less than zero");
-
-  // We store points for Pixel as we will use it for rounding
-  if (pixelsInPoint == 0.0f) {
-    // Zero is used to skip rounding
-    config->pointScaleFactor = 0.0f;
-  } else {
-    config->pointScaleFactor = pixelsInPoint;
-  }
-}
-
-static void YGRoundToPixelGrid(const YGNodeRef node,
-                               const float pointScaleFactor,
-                               const float absoluteLeft,
-                               const float absoluteTop) {
-  if (pointScaleFactor == 0.0f) {
-    return;
-  }
-
-  const float nodeLeft = node->layout.position[YGEdgeLeft];
-  const float nodeTop = node->layout.position[YGEdgeTop];
-
-  const float nodeWidth = node->layout.dimensions[YGDimensionWidth];
-  const float nodeHeight = node->layout.dimensions[YGDimensionHeight];
-
-  const float absoluteNodeLeft = absoluteLeft + nodeLeft;
-  const float absoluteNodeTop = absoluteTop + nodeTop;
-
-  const float absoluteNodeRight = absoluteNodeLeft + nodeWidth;
-  const float absoluteNodeBottom = absoluteNodeTop + nodeHeight;
-
-  // If a node has a custom measure function we never want to round down its size as this could
-  // lead to unwanted text truncation.
-  const bool textRounding = node->nodeType == YGNodeTypeText;
-
-  node->layout.position[YGEdgeLeft] =
-      YGRoundValueToPixelGrid(nodeLeft, pointScaleFactor, false, textRounding);
-  node->layout.position[YGEdgeTop] =
-      YGRoundValueToPixelGrid(nodeTop, pointScaleFactor, false, textRounding);
-
-  // We multiply dimension by scale factor and if the result is close to the whole number, we don't
-  // have any fraction
-  // To verify if the result is close to whole number we want to check both floor and ceil numbers
-  const bool hasFractionalWidth = !YGFloatsEqual(fmodf(nodeWidth * pointScaleFactor, 1.0), 0) &&
-                                  !YGFloatsEqual(fmodf(nodeWidth * pointScaleFactor, 1.0), 1.0);
-  const bool hasFractionalHeight = !YGFloatsEqual(fmodf(nodeHeight * pointScaleFactor, 1.0), 0) &&
-                                   !YGFloatsEqual(fmodf(nodeHeight * pointScaleFactor, 1.0), 1.0);
-
-  node->layout.dimensions[YGDimensionWidth] =
-      YGRoundValueToPixelGrid(absoluteNodeRight,
-                              pointScaleFactor,
-                              (textRounding && hasFractionalWidth),
-                              (textRounding && !hasFractionalWidth)) -
-      YGRoundValueToPixelGrid(absoluteNodeLeft, pointScaleFactor, false, textRounding);
-  node->layout.dimensions[YGDimensionHeight] =
-      YGRoundValueToPixelGrid(absoluteNodeBottom,
-                              pointScaleFactor,
-                              (textRounding && hasFractionalHeight),
-                              (textRounding && !hasFractionalHeight)) -
-      YGRoundValueToPixelGrid(absoluteNodeTop, pointScaleFactor, false, textRounding);
-
-  const uint32_t childCount = node->children.size();
-  for (uint32_t i = 0; i < childCount; i++) {
-    YGRoundToPixelGrid(YGNodeGetChild(node, i), pointScaleFactor, absoluteNodeLeft, absoluteNodeTop);
-  }
-}
-
-void YGNodeCalculateLayout(const YGNodeRef node,
-                           const float parentWidth,
-                           const float parentHeight,
-                           const YGDirection parentDirection) {
-  // Increment the generation count. This will force the recursive routine to
-  // visit
-  // all dirty nodes at least once. Subsequent visits will be skipped if the
-  // input
-  // parameters don't change.
-  gCurrentGenerationCount++;
-
-  YGResolveDimensions(node);
-
-  float width = YGUndefined;
-  YGMeasureMode widthMeasureMode = YGMeasureModeUndefined;
-  if (YGNodeIsStyleDimDefined(node, YGFlexDirectionRow, parentWidth)) {
-    width = YGResolveValue(node->resolvedDimensions[dim[YGFlexDirectionRow]], parentWidth) +
-            YGNodeMarginForAxis(node, YGFlexDirectionRow, parentWidth);
-    widthMeasureMode = YGMeasureModeExactly;
-  } else if (YGResolveValue(&node->style.maxDimensions[YGDimensionWidth], parentWidth) >= 0.0f) {
-    width = YGResolveValue(&node->style.maxDimensions[YGDimensionWidth], parentWidth);
-    widthMeasureMode = YGMeasureModeAtMost;
-  } else {
-    width = parentWidth;
-    widthMeasureMode = YGFloatIsUndefined(width) ? YGMeasureModeUndefined : YGMeasureModeExactly;
-  }
-
-  float height = YGUndefined;
-  YGMeasureMode heightMeasureMode = YGMeasureModeUndefined;
-  if (YGNodeIsStyleDimDefined(node, YGFlexDirectionColumn, parentHeight)) {
-    height = YGResolveValue(node->resolvedDimensions[dim[YGFlexDirectionColumn]], parentHeight) +
-             YGNodeMarginForAxis(node, YGFlexDirectionColumn, parentWidth);
-    heightMeasureMode = YGMeasureModeExactly;
-  } else if (YGResolveValue(&node->style.maxDimensions[YGDimensionHeight], parentHeight) >= 0.0f) {
-    height = YGResolveValue(&node->style.maxDimensions[YGDimensionHeight], parentHeight);
-    heightMeasureMode = YGMeasureModeAtMost;
-  } else {
-    height = parentHeight;
-    heightMeasureMode = YGFloatIsUndefined(height) ? YGMeasureModeUndefined : YGMeasureModeExactly;
-  }
-
-  if (YGLayoutNodeInternal(node,
-                           width,
-                           height,
-                           parentDirection,
-                           widthMeasureMode,
-                           heightMeasureMode,
-                           parentWidth,
-                           parentHeight,
-                           true,
-                           "initial",
-                           node->config)) {
-    YGNodeSetPosition(node, node->layout.direction, parentWidth, parentHeight, parentWidth);
-    YGRoundToPixelGrid(node, node->config->pointScaleFactor, 0.0f, 0.0f);
-
-    if (gPrintTree) {
-      YGNodePrint(
-          node,
-          (YGPrintOptions)(
-              YGPrintOptionsLayout | YGPrintOptionsChildren |
-              YGPrintOptionsStyle));
-    }
-  }
-}
-
-void YGConfigSetLogger(const YGConfigRef config, YGLogger logger) {
-  if (logger != nullptr) {
-    config->logger = logger;
-  } else {
-#ifdef ANDROID
-    config->logger = &YGAndroidLog;
-#else
-    config->logger = &YGDefaultLog;
-#endif
-  }
-}
-
-static void YGVLog(const YGConfigRef config,
-                   const YGNodeRef node,
-                   YGLogLevel level,
-                   const char *format,
-                   va_list args) {
-  const YGConfigRef logConfig = config != nullptr ? config : &gYGConfigDefaults;
-  logConfig->logger(logConfig, node, level, format, args);
-
-  if (level == YGLogLevelFatal) {
-    abort();
-  }
-}
-
-void YGLogWithConfig(const YGConfigRef config, YGLogLevel level, const char *format, ...) {
-  va_list args;
-  va_start(args, format);
-  YGVLog(config, nullptr, level, format, args);
-  va_end(args);
-}
-
-void YGLog(const YGNodeRef node, YGLogLevel level, const char *format, ...) {
-  va_list args;
-  va_start(args, format);
-  YGVLog(node == nullptr ? nullptr : node->config, node, level, format, args);
-  va_end(args);
-}
-
-void YGAssert(const bool condition, const char *message) {
-  if (!condition) {
-    YGLog(nullptr, YGLogLevelFatal, "%s\n", message);
-  }
-}
-
-void YGAssertWithNode(const YGNodeRef node, const bool condition, const char *message) {
-  if (!condition) {
-    YGLog(node, YGLogLevelFatal, "%s\n", message);
-  }
-}
-
-void YGAssertWithConfig(const YGConfigRef config, const bool condition, const char *message) {
-  if (!condition) {
-    YGLogWithConfig(config, YGLogLevelFatal, "%s\n", message);
-  }
-}
-
-void YGConfigSetExperimentalFeatureEnabled(const YGConfigRef config,
-                                           const YGExperimentalFeature feature,
-                                           const bool enabled) {
-  config->experimentalFeatures[feature] = enabled;
-}
-
-inline bool YGConfigIsExperimentalFeatureEnabled(const YGConfigRef config,
-                                                 const YGExperimentalFeature feature) {
-  return config->experimentalFeatures[feature];
-}
-
-void YGConfigSetUseWebDefaults(const YGConfigRef config, const bool enabled) {
-  config->useWebDefaults = enabled;
-}
-
-void YGConfigSetUseLegacyStretchBehaviour(const YGConfigRef config,
-                                          const bool useLegacyStretchBehaviour) {
-  config->useLegacyStretchBehaviour = useLegacyStretchBehaviour;
-}
-
-bool YGConfigGetUseWebDefaults(const YGConfigRef config) {
-  return config->useWebDefaults;
-}
-
-void YGConfigSetContext(const YGConfigRef config, void *context) {
-  config->context = context;
-}
-
-void *YGConfigGetContext(const YGConfigRef config) {
-  return config->context;
-}
-
-void YGConfigSetNodeClonedFunc(const YGConfigRef config, const YGNodeClonedFunc callback) {
-  config->cloneNodeCallback = callback;
-}
+/*+ *  Copyright (c) Facebook, Inc. and its affiliates.+ *+ *  This source code is licensed under the MIT license found in the LICENSE+ *  file in the root directory of this source tree.+ *+ */++#include "Yoga.h"+#include <float.h>+#include <string.h>+#include <algorithm>+#include "Utils.h"+#include "YGNode.h"+#include "YGNodePrint.h"+#include "Yoga-internal.h"+#ifdef _MSC_VER+#include <float.h>++/* define fmaxf if < VC12 */+#if _MSC_VER < 1800+__forceinline const float fmaxf(const float a, const float b) {+  if (!YGFloatIsUndefined(a) && !YGFloatIsUndefined(b)) {+    return (a > b) ? a : b;+  }+  return YGFloatIsUndefined(a) ? b : a;+}+#endif+#endif++#ifdef ANDROID+static int YGAndroidLog(+    const YGConfigRef config,+    const YGNodeRef node,+    YGLogLevel level,+    const char* format,+    va_list args);+#else+static int YGDefaultLog(+    const YGConfigRef config,+    const YGNodeRef node,+    YGLogLevel level,+    const char* format,+    va_list args);+#endif++const YGValue YGValueZero = {0, YGUnitPoint};+const YGValue YGValueUndefined = {YGUndefined, YGUnitUndefined};+const YGValue YGValueAuto = {YGUndefined, YGUnitAuto};++bool operator==(const YGValue& lhs, const YGValue& rhs) {+  if ((lhs.unit == YGUnitUndefined && rhs.unit == YGUnitUndefined) ||+      (lhs.unit == YGUnitAuto && rhs.unit == YGUnitAuto)) {+    return true;+  }++  return lhs.unit == rhs.unit && lhs.value == rhs.value;+}++bool operator!=(const YGValue& lhs, const YGValue& rhs) {+  return !(lhs == rhs);+}++#ifdef ANDROID+#include <android/log.h>+static int YGAndroidLog(+    const YGConfigRef config,+    const YGNodeRef node,+    YGLogLevel level,+    const char* format,+    va_list args) {+  int androidLevel = YGLogLevelDebug;+  switch (level) {+    case YGLogLevelFatal:+      androidLevel = ANDROID_LOG_FATAL;+      break;+    case YGLogLevelError:+      androidLevel = ANDROID_LOG_ERROR;+      break;+    case YGLogLevelWarn:+      androidLevel = ANDROID_LOG_WARN;+      break;+    case YGLogLevelInfo:+      androidLevel = ANDROID_LOG_INFO;+      break;+    case YGLogLevelDebug:+      androidLevel = ANDROID_LOG_DEBUG;+      break;+    case YGLogLevelVerbose:+      androidLevel = ANDROID_LOG_VERBOSE;+      break;+  }+  const int result = __android_log_vprint(androidLevel, "yoga", format, args);+  return result;+}+#else+#define YG_UNUSED(x) (void)(x);++static int YGDefaultLog(+    const YGConfigRef config,+    const YGNodeRef node,+    YGLogLevel level,+    const char* format,+    va_list args) {+  YG_UNUSED(config);+  YG_UNUSED(node);+  switch (level) {+    case YGLogLevelError:+    case YGLogLevelFatal:+      return vfprintf(stderr, format, args);+    case YGLogLevelWarn:+    case YGLogLevelInfo:+    case YGLogLevelDebug:+    case YGLogLevelVerbose:+    default:+      return vprintf(format, args);+  }+}++#undef YG_UNUSED+#endif++bool YGFloatIsUndefined(const float value) {+  return facebook::yoga::isUndefined(value);+}++const YGValue* YGComputedEdgeValue(+    const std::array<YGValue, YGEdgeCount>& edges,+    const YGEdge edge,+    const YGValue* const defaultValue) {+  if (edges[edge].unit != YGUnitUndefined) {+    return &edges[edge];+  }++  if ((edge == YGEdgeTop || edge == YGEdgeBottom) &&+      edges[YGEdgeVertical].unit != YGUnitUndefined) {+    return &edges[YGEdgeVertical];+  }++  if ((edge == YGEdgeLeft || edge == YGEdgeRight || edge == YGEdgeStart ||+       edge == YGEdgeEnd) &&+      edges[YGEdgeHorizontal].unit != YGUnitUndefined) {+    return &edges[YGEdgeHorizontal];+  }++  if (edges[YGEdgeAll].unit != YGUnitUndefined) {+    return &edges[YGEdgeAll];+  }++  if (edge == YGEdgeStart || edge == YGEdgeEnd) {+    return &YGValueUndefined;+  }++  return defaultValue;+}++void* YGNodeGetContext(YGNodeRef node) {+  return node->getContext();+}++void YGNodeSetContext(YGNodeRef node, void* context) {+  return node->setContext(context);+}++YGMeasureFunc YGNodeGetMeasureFunc(YGNodeRef node) {+  return node->getMeasure();+}++void YGNodeSetMeasureFunc(YGNodeRef node, YGMeasureFunc measureFunc) {+  node->setMeasureFunc(measureFunc);+}++YGBaselineFunc YGNodeGetBaselineFunc(YGNodeRef node) {+  return node->getBaseline();+}++void YGNodeSetBaselineFunc(YGNodeRef node, YGBaselineFunc baselineFunc) {+  node->setBaseLineFunc(baselineFunc);+}++YGDirtiedFunc YGNodeGetDirtiedFunc(YGNodeRef node) {+  return node->getDirtied();+}++void YGNodeSetDirtiedFunc(YGNodeRef node, YGDirtiedFunc dirtiedFunc) {+  node->setDirtiedFunc(dirtiedFunc);+}++YGPrintFunc YGNodeGetPrintFunc(YGNodeRef node) {+  return node->getPrintFunc();+}++void YGNodeSetPrintFunc(YGNodeRef node, YGPrintFunc printFunc) {+  node->setPrintFunc(printFunc);+}++bool YGNodeGetHasNewLayout(YGNodeRef node) {+  return node->getHasNewLayout();+}++void YGConfigSetPrintTreeFlag(YGConfigRef config, bool enabled) {+  config->printTree = enabled;+}++void YGNodeSetHasNewLayout(YGNodeRef node, bool hasNewLayout) {+  node->setHasNewLayout(hasNewLayout);+}++YGNodeType YGNodeGetNodeType(YGNodeRef node) {+  return node->getNodeType();+}++void YGNodeSetNodeType(YGNodeRef node, YGNodeType nodeType) {+  return node->setNodeType(nodeType);+}++bool YGNodeIsDirty(YGNodeRef node) {+  return node->isDirty();+}++bool YGNodeLayoutGetDidUseLegacyFlag(const YGNodeRef node) {+  return node->didUseLegacyFlag();+}++void YGNodeMarkDirtyAndPropogateToDescendants(const YGNodeRef node) {+  return node->markDirtyAndPropogateDownwards();+}++int32_t gNodeInstanceCount = 0;+int32_t gConfigInstanceCount = 0;++WIN_EXPORT YGNodeRef YGNodeNewWithConfig(const YGConfigRef config) {+  const YGNodeRef node = new YGNode();+  YGAssertWithConfig(+      config, node != nullptr, "Could not allocate memory for node");+  gNodeInstanceCount++;++  if (config->useWebDefaults) {+    node->setStyleFlexDirection(YGFlexDirectionRow);+    node->setStyleAlignContent(YGAlignStretch);+  }+  node->setConfig(config);+  return node;+}++YGConfigRef YGConfigGetDefault() {+  static YGConfigRef defaultConfig = YGConfigNew();+  return defaultConfig;+}++YGNodeRef YGNodeNew(void) {+  return YGNodeNewWithConfig(YGConfigGetDefault());+}++YGNodeRef YGNodeClone(YGNodeRef oldNode) {+  YGNodeRef node = new YGNode(*oldNode);+  YGAssertWithConfig(+      oldNode->getConfig(),+      node != nullptr,+      "Could not allocate memory for node");+  gNodeInstanceCount++;+  node->setOwner(nullptr);+  return node;+}++static YGConfigRef YGConfigClone(const YGConfig& oldConfig) {+  const YGConfigRef config = new YGConfig(oldConfig);+  YGAssert(config != nullptr, "Could not allocate memory for config");+  if (config == nullptr) {+    abort();+  }+  gConfigInstanceCount++;+  return config;+}++static YGNodeRef YGNodeDeepClone(YGNodeRef oldNode) {+  YGNodeRef node = YGNodeClone(oldNode);+  YGVector vec = YGVector();+  vec.reserve(oldNode->getChildren().size());+  YGNodeRef childNode = nullptr;+  for (auto* item : oldNode->getChildren()) {+    childNode = YGNodeDeepClone(item);+    childNode->setOwner(node);+    vec.push_back(childNode);+  }+  node->setChildren(vec);++  if (oldNode->getConfig() != nullptr) {+    node->setConfig(YGConfigClone(*(oldNode->getConfig())));+  }++  return node;+}++void YGNodeFree(const YGNodeRef node) {+  if (YGNodeRef owner = node->getOwner()) {+    owner->removeChild(node);+    node->setOwner(nullptr);+  }++  const uint32_t childCount = YGNodeGetChildCount(node);+  for (uint32_t i = 0; i < childCount; i++) {+    const YGNodeRef child = YGNodeGetChild(node, i);+    child->setOwner(nullptr);+  }++  node->clearChildren();+  delete node;+  gNodeInstanceCount--;+}++static void YGConfigFreeRecursive(const YGNodeRef root) {+  if (root->getConfig() != nullptr) {+    gConfigInstanceCount--;+    delete root->getConfig();+  }+  // Delete configs recursively for childrens+  for (auto* child : root->getChildren()) {+    YGConfigFreeRecursive(child);+  }+}++void YGNodeFreeRecursive(const YGNodeRef root) {+  while (YGNodeGetChildCount(root) > 0) {+    const YGNodeRef child = YGNodeGetChild(root, 0);+    if (child->getOwner() != root) {+      // Don't free shared nodes that we don't own.+      break;+    }+    YGNodeRemoveChild(root, child);+    YGNodeFreeRecursive(child);+  }+  YGNodeFree(root);+}++void YGNodeReset(const YGNodeRef node) {+  YGAssertWithNode(+      node,+      YGNodeGetChildCount(node) == 0,+      "Cannot reset a node which still has children attached");+  YGAssertWithNode(+      node,+      node->getOwner() == nullptr,+      "Cannot reset a node still attached to a owner");++  node->clearChildren();++  const YGConfigRef config = node->getConfig();+  *node = YGNode();+  if (config->useWebDefaults) {+    node->setStyleFlexDirection(YGFlexDirectionRow);+    node->setStyleAlignContent(YGAlignStretch);+  }+  node->setConfig(config);+}++int32_t YGNodeGetInstanceCount(void) {+  return gNodeInstanceCount;+}++int32_t YGConfigGetInstanceCount(void) {+  return gConfigInstanceCount;+}++YGConfigRef YGConfigNew(void) {+#ifdef ANDROID+  const YGConfigRef config = new YGConfig(YGAndroidLog);+#else+  const YGConfigRef config = new YGConfig(YGDefaultLog);+#endif+  gConfigInstanceCount++;+  return config;+}++void YGConfigFree(const YGConfigRef config) {+  delete config;+  gConfigInstanceCount--;+}++void YGConfigCopy(const YGConfigRef dest, const YGConfigRef src) {+  memcpy(dest, src, sizeof(YGConfig));+}++void YGNodeInsertChild(+    const YGNodeRef node,+    const YGNodeRef child,+    const uint32_t index) {+  YGAssertWithNode(+      node,+      child->getOwner() == nullptr,+      "Child already has a owner, it must be removed first.");++  YGAssertWithNode(+      node,+      node->getMeasure() == nullptr,+      "Cannot add child: Nodes with measure functions cannot have children.");++  node->cloneChildrenIfNeeded();+  node->insertChild(child, index);+  YGNodeRef owner = child->getOwner() ? nullptr : node;+  child->setOwner(owner);+  node->markDirtyAndPropogate();+}++void YGNodeInsertSharedChild(+    const YGNodeRef node,+    const YGNodeRef child,+    const uint32_t index) {+  YGAssertWithNode(+      node,+      node->getMeasure() == nullptr,+      "Cannot add child: Nodes with measure functions cannot have children.");++  node->insertChild(child, index);+  child->setOwner(nullptr);+  node->markDirtyAndPropogate();+}++void YGNodeRemoveChild(const YGNodeRef owner, const YGNodeRef excludedChild) {+  // This algorithm is a forked variant from cloneChildrenIfNeeded in YGNode+  // that excludes a child.+  const uint32_t childCount = YGNodeGetChildCount(owner);++  if (childCount == 0) {+    // This is an empty set. Nothing to remove.+    return;+  }+  const YGNodeRef firstChild = YGNodeGetChild(owner, 0);+  if (firstChild->getOwner() == owner) {+    // If the first child has this node as its owner, we assume that it is+    // already unique. We can now try to delete a child in this list.+    if (owner->removeChild(excludedChild)) {+      excludedChild->setLayout(+          YGNode().getLayout()); // layout is no longer valid+      excludedChild->setOwner(nullptr);+      owner->markDirtyAndPropogate();+    }+    return;+  }+  // Otherwise we have to clone the node list except for the child we're trying+  // to delete. We don't want to simply clone all children, because then the+  // host will need to free the clone of the child that was just deleted.+  const YGCloneNodeFunc cloneNodeCallback =+      owner->getConfig()->cloneNodeCallback;+  uint32_t nextInsertIndex = 0;+  for (uint32_t i = 0; i < childCount; i++) {+    const YGNodeRef oldChild = owner->getChild(i);+    if (excludedChild == oldChild) {+      // Ignore the deleted child. Don't reset its layout or owner since it is+      // still valid in the other owner. However, since this owner has now+      // changed, we need to mark it as dirty.+      owner->markDirtyAndPropogate();+      continue;+    }+    YGNodeRef newChild = nullptr;+    if (cloneNodeCallback) {+      newChild = cloneNodeCallback(oldChild, owner, nextInsertIndex);+    }+    if (newChild == nullptr) {+      newChild = YGNodeClone(oldChild);+    }+    owner->replaceChild(newChild, nextInsertIndex);+    newChild->setOwner(owner);++    nextInsertIndex++;+  }+  while (nextInsertIndex < childCount) {+    owner->removeChild(nextInsertIndex);+    nextInsertIndex++;+  }+}++void YGNodeRemoveAllChildren(const YGNodeRef owner) {+  const uint32_t childCount = YGNodeGetChildCount(owner);+  if (childCount == 0) {+    // This is an empty set already. Nothing to do.+    return;+  }+  const YGNodeRef firstChild = YGNodeGetChild(owner, 0);+  if (firstChild->getOwner() == owner) {+    // If the first child has this node as its owner, we assume that this child+    // set is unique.+    for (uint32_t i = 0; i < childCount; i++) {+      const YGNodeRef oldChild = YGNodeGetChild(owner, i);+      oldChild->setLayout(YGNode().getLayout()); // layout is no longer valid+      oldChild->setOwner(nullptr);+    }+    owner->clearChildren();+    owner->markDirtyAndPropogate();+    return;+  }+  // Otherwise, we are not the owner of the child set. We don't have to do+  // anything to clear it.+  owner->setChildren(YGVector());+  owner->markDirtyAndPropogate();+}++static void YGNodeSetChildrenInternal(+    YGNodeRef const owner,+    const std::vector<YGNodeRef>& children) {+  if (!owner) {+    return;+  }+  if (children.size() == 0) {+    if (YGNodeGetChildCount(owner) > 0) {+      for (YGNodeRef const child : owner->getChildren()) {+        child->setLayout(YGLayout());+        child->setOwner(nullptr);+      }+      owner->setChildren(YGVector());+      owner->markDirtyAndPropogate();+    }+  } else {+    if (YGNodeGetChildCount(owner) > 0) {+      for (YGNodeRef const oldChild : owner->getChildren()) {+        // Our new children may have nodes in common with the old children. We+        // don't reset these common nodes.+        if (std::find(children.begin(), children.end(), oldChild) ==+            children.end()) {+          oldChild->setLayout(YGLayout());+          oldChild->setOwner(nullptr);+        }+      }+    }+    owner->setChildren(children);+    for (YGNodeRef child : children) {+      child->setOwner(owner);+    }+    owner->markDirtyAndPropogate();+  }+}++void YGNodeSetChildren(+    YGNodeRef const owner,+    const YGNodeRef c[],+    const uint32_t count) {+  const YGVector children = {c, c + count};+  YGNodeSetChildrenInternal(owner, children);+}++void YGNodeSetChildren(+    YGNodeRef const owner,+    const std::vector<YGNodeRef>& children) {+  YGNodeSetChildrenInternal(owner, children);+}++YGNodeRef YGNodeGetChild(const YGNodeRef node, const uint32_t index) {+  if (index < node->getChildren().size()) {+    return node->getChild(index);+  }+  return nullptr;+}++uint32_t YGNodeGetChildCount(const YGNodeRef node) {+  return static_cast<uint32_t>(node->getChildren().size());+}++YGNodeRef YGNodeGetOwner(const YGNodeRef node) {+  return node->getOwner();+}++YGNodeRef YGNodeGetParent(const YGNodeRef node) {+  return node->getOwner();+}++void YGNodeMarkDirty(const YGNodeRef node) {+  YGAssertWithNode(+      node,+      node->getMeasure() != nullptr,+      "Only leaf nodes with custom measure functions"+      "should manually mark themselves as dirty");++  node->markDirtyAndPropogate();+}++void YGNodeCopyStyle(const YGNodeRef dstNode, const YGNodeRef srcNode) {+  if (!(dstNode->getStyle() == srcNode->getStyle())) {+    dstNode->setStyle(srcNode->getStyle());+    dstNode->markDirtyAndPropogate();+  }+}++float YGNodeStyleGetFlexGrow(const YGNodeRef node) {+  return node->getStyle().flexGrow.isUndefined()+      ? kDefaultFlexGrow+      : node->getStyle().flexGrow.getValue();+}++float YGNodeStyleGetFlexShrink(const YGNodeRef node) {+  return node->getStyle().flexShrink.isUndefined()+      ? (node->getConfig()->useWebDefaults ? kWebDefaultFlexShrink+                                           : kDefaultFlexShrink)+      : node->getStyle().flexShrink.getValue();+}++namespace {++template <typename T, T YGStyle::*P>+struct StyleProp {+  static T get(YGNodeRef node) {+    return node->getStyle().*P;+  }+  static void set(YGNodeRef node, T newValue) {+    if (node->getStyle().*P != newValue) {+      node->getStyle().*P = newValue;+      node->markDirtyAndPropogate();+    }+  }+};++struct Value {+  template <YGUnit U>+  static YGValue create(float value) {+    return {+        YGFloatSanitize(value),+        YGFloatIsUndefined(value) ? YGUnitUndefined : U,+    };+  }+};++template <YGStyle::Dimensions YGStyle::*P>+struct DimensionProp {+  template <YGDimension idx>+  static WIN_STRUCT(YGValue) get(YGNodeRef node) {+    YGValue value = (node->getStyle().*P)[idx];+    if (value.unit == YGUnitUndefined || value.unit == YGUnitAuto) {+      value.value = YGUndefined;+    }+    return WIN_STRUCT_REF(value);+  }++  template <YGDimension idx, YGUnit U>+  static void set(YGNodeRef node, float newValue) {+    YGValue value = Value::create<U>(newValue);+    if (((node->getStyle().*P)[idx].value != value.value &&+         value.unit != YGUnitUndefined) ||+        (node->getStyle().*P)[idx].unit != value.unit) {+      (node->getStyle().*P)[idx] = value;+      node->markDirtyAndPropogate();+    }+  }+};++} // namespace++#define YG_NODE_STYLE_PROPERTY_SETTER_UNIT_AUTO_IMPL(                        \+    type, name, paramName, instanceName)                                     \+  void YGNodeStyleSet##name(const YGNodeRef node, const type paramName) {    \+    YGValue value = {                                                        \+        YGFloatSanitize(paramName),                                          \+        YGFloatIsUndefined(paramName) ? YGUnitUndefined : YGUnitPoint,       \+    };                                                                       \+    if ((node->getStyle().instanceName.value != value.value &&               \+         value.unit != YGUnitUndefined) ||                                   \+        node->getStyle().instanceName.unit != value.unit) {                  \+      node->getStyle().instanceName = value;                                 \+      node->markDirtyAndPropogate();                                         \+    }                                                                        \+  }                                                                          \+                                                                             \+  void YGNodeStyleSet##name##Percent(                                        \+      const YGNodeRef node, const type paramName) {                          \+    if (node->getStyle().instanceName.value != YGFloatSanitize(paramName) || \+        node->getStyle().instanceName.unit != YGUnitPercent) {               \+      node->getStyle().instanceName = YGFloatIsUndefined(paramName)          \+          ? YGValue{0, YGUnitAuto}                                           \+          : YGValue{paramName, YGUnitPercent};                               \+      node->markDirtyAndPropogate();                                         \+    }                                                                        \+  }                                                                          \+                                                                             \+  void YGNodeStyleSet##name##Auto(const YGNodeRef node) {                    \+    if (node->getStyle().instanceName.unit != YGUnitAuto) {                  \+      node->getStyle().instanceName = {0, YGUnitAuto};                       \+      node->markDirtyAndPropogate();                                         \+    }                                                                        \+  }++#define YG_NODE_STYLE_PROPERTY_UNIT_AUTO_IMPL(                       \+    type, name, paramName, instanceName)                             \+  YG_NODE_STYLE_PROPERTY_SETTER_UNIT_AUTO_IMPL(                      \+      float, name, paramName, instanceName)                          \+                                                                     \+  type YGNodeStyleGet##name(const YGNodeRef node) {                  \+    YGValue value = node->getStyle().instanceName;                   \+    if (value.unit == YGUnitUndefined || value.unit == YGUnitAuto) { \+      value.value = YGUndefined;                                     \+    }                                                                \+    return value;                                                    \+  }++#define YG_NODE_STYLE_EDGE_PROPERTY_UNIT_AUTO_IMPL(type, name, instanceName) \+  void YGNodeStyleSet##name##Auto(const YGNodeRef node, const YGEdge edge) { \+    if (node->getStyle().instanceName[edge].unit != YGUnitAuto) {            \+      node->getStyle().instanceName[edge] = {0, YGUnitAuto};                 \+      node->markDirtyAndPropogate();                                         \+    }                                                                        \+  }++#define YG_NODE_STYLE_EDGE_PROPERTY_UNIT_IMPL(                           \+    type, name, paramName, instanceName)                                 \+  void YGNodeStyleSet##name(                                             \+      const YGNodeRef node, const YGEdge edge, const float paramName) {  \+    YGValue value = {                                                    \+        YGFloatSanitize(paramName),                                      \+        YGFloatIsUndefined(paramName) ? YGUnitUndefined : YGUnitPoint,   \+    };                                                                   \+    if ((node->getStyle().instanceName[edge].value != value.value &&     \+         value.unit != YGUnitUndefined) ||                               \+        node->getStyle().instanceName[edge].unit != value.unit) {        \+      node->getStyle().instanceName[edge] = value;                       \+      node->markDirtyAndPropogate();                                     \+    }                                                                    \+  }                                                                      \+                                                                         \+  void YGNodeStyleSet##name##Percent(                                    \+      const YGNodeRef node, const YGEdge edge, const float paramName) {  \+    YGValue value = {                                                    \+        YGFloatSanitize(paramName),                                      \+        YGFloatIsUndefined(paramName) ? YGUnitUndefined : YGUnitPercent, \+    };                                                                   \+    if ((node->getStyle().instanceName[edge].value != value.value &&     \+         value.unit != YGUnitUndefined) ||                               \+        node->getStyle().instanceName[edge].unit != value.unit) {        \+      node->getStyle().instanceName[edge] = value;                       \+      node->markDirtyAndPropogate();                                     \+    }                                                                    \+  }                                                                      \+                                                                         \+  WIN_STRUCT(type)                                                       \+  YGNodeStyleGet##name(const YGNodeRef node, const YGEdge edge) {        \+    YGValue value = node->getStyle().instanceName[edge];                 \+    if (value.unit == YGUnitUndefined || value.unit == YGUnitAuto) {     \+      value.value = YGUndefined;                                         \+    }                                                                    \+    return WIN_STRUCT_REF(value);                                        \+  }++#define YG_NODE_LAYOUT_PROPERTY_IMPL(type, name, instanceName) \+  type YGNodeLayoutGet##name(const YGNodeRef node) {           \+    return node->getLayout().instanceName;                     \+  }++#define YG_NODE_LAYOUT_RESOLVED_PROPERTY_IMPL(type, name, instanceName) \+  type YGNodeLayoutGet##name(const YGNodeRef node, const YGEdge edge) { \+    YGAssertWithNode(                                                   \+        node,                                                           \+        edge <= YGEdgeEnd,                                              \+        "Cannot get layout properties of multi-edge shorthands");       \+                                                                        \+    if (edge == YGEdgeLeft) {                                           \+      if (node->getLayout().direction == YGDirectionRTL) {              \+        return node->getLayout().instanceName[YGEdgeEnd];               \+      } else {                                                          \+        return node->getLayout().instanceName[YGEdgeStart];             \+      }                                                                 \+    }                                                                   \+                                                                        \+    if (edge == YGEdgeRight) {                                          \+      if (node->getLayout().direction == YGDirectionRTL) {              \+        return node->getLayout().instanceName[YGEdgeStart];             \+      } else {                                                          \+        return node->getLayout().instanceName[YGEdgeEnd];               \+      }                                                                 \+    }                                                                   \+                                                                        \+    return node->getLayout().instanceName[edge];                        \+  }++void YGNodeStyleSetDirection(+    const YGNodeRef node,+    const YGDirection direction) {+  StyleProp<YGDirection, &YGStyle::direction>::set(node, direction);+}+YGDirection YGNodeStyleGetDirection(const YGNodeRef node) {+  return StyleProp<YGDirection, &YGStyle::direction>::get(node);+}++void YGNodeStyleSetFlexDirection(+    const YGNodeRef node,+    const YGFlexDirection flexDirection) {+  StyleProp<YGFlexDirection, &YGStyle::flexDirection>::set(node, flexDirection);+}+YGFlexDirection YGNodeStyleGetFlexDirection(const YGNodeRef node) {+  return StyleProp<YGFlexDirection, &YGStyle::flexDirection>::get(node);+}++void YGNodeStyleSetJustifyContent(+    const YGNodeRef node,+    const YGJustify justifyContent) {+  StyleProp<YGJustify, &YGStyle::justifyContent>::set(node, justifyContent);+}+YGJustify YGNodeStyleGetJustifyContent(const YGNodeRef node) {+  return StyleProp<YGJustify, &YGStyle::justifyContent>::get(node);+}++void YGNodeStyleSetAlignContent(+    const YGNodeRef node,+    const YGAlign alignContent) {+  StyleProp<YGAlign, &YGStyle::alignContent>::set(node, alignContent);+}+YGAlign YGNodeStyleGetAlignContent(const YGNodeRef node) {+  return StyleProp<YGAlign, &YGStyle::alignContent>::get(node);+}++void YGNodeStyleSetAlignItems(const YGNodeRef node, const YGAlign alignItems) {+  StyleProp<YGAlign, &YGStyle::alignItems>::set(node, alignItems);+}+YGAlign YGNodeStyleGetAlignItems(const YGNodeRef node) {+  return StyleProp<YGAlign, &YGStyle::alignItems>::get(node);+}++void YGNodeStyleSetAlignSelf(const YGNodeRef node, const YGAlign alignSelf) {+  StyleProp<YGAlign, &YGStyle::alignSelf>::set(node, alignSelf);+}+YGAlign YGNodeStyleGetAlignSelf(const YGNodeRef node) {+  return StyleProp<YGAlign, &YGStyle::alignSelf>::get(node);+}++void YGNodeStyleSetPositionType(+    const YGNodeRef node,+    const YGPositionType positionType) {+  StyleProp<YGPositionType, &YGStyle::positionType>::set(node, positionType);+}+YGPositionType YGNodeStyleGetPositionType(const YGNodeRef node) {+  return StyleProp<YGPositionType, &YGStyle::positionType>::get(node);+}++void YGNodeStyleSetFlexWrap(const YGNodeRef node, const YGWrap flexWrap) {+  StyleProp<YGWrap, &YGStyle::flexWrap>::set(node, flexWrap);+}+YGWrap YGNodeStyleGetFlexWrap(const YGNodeRef node) {+  return StyleProp<YGWrap, &YGStyle::flexWrap>::get(node);+}++void YGNodeStyleSetOverflow(const YGNodeRef node, const YGOverflow overflow) {+  StyleProp<YGOverflow, &YGStyle::overflow>::set(node, overflow);+}+YGOverflow YGNodeStyleGetOverflow(const YGNodeRef node) {+  return StyleProp<YGOverflow, &YGStyle::overflow>::get(node);+}++void YGNodeStyleSetDisplay(const YGNodeRef node, const YGDisplay display) {+  StyleProp<YGDisplay, &YGStyle::display>::set(node, display);+}+YGDisplay YGNodeStyleGetDisplay(const YGNodeRef node) {+  return StyleProp<YGDisplay, &YGStyle::display>::get(node);+}++// TODO(T26792433): Change the API to accept YGFloatOptional.+void YGNodeStyleSetFlex(const YGNodeRef node, const float flex) {+  if (node->getStyle().flex != flex) {+    node->getStyle().flex =+        YGFloatIsUndefined(flex) ? YGFloatOptional() : YGFloatOptional(flex);+    node->markDirtyAndPropogate();+  }+}++// TODO(T26792433): Change the API to accept YGFloatOptional.+float YGNodeStyleGetFlex(const YGNodeRef node) {+  return node->getStyle().flex.isUndefined() ? YGUndefined+                                             : node->getStyle().flex.getValue();+}++// TODO(T26792433): Change the API to accept YGFloatOptional.+void YGNodeStyleSetFlexGrow(const YGNodeRef node, const float flexGrow) {+  if (node->getStyle().flexGrow != flexGrow) {+    node->getStyle().flexGrow = YGFloatIsUndefined(flexGrow)+        ? YGFloatOptional()+        : YGFloatOptional(flexGrow);+    node->markDirtyAndPropogate();+  }+}++// TODO(T26792433): Change the API to accept YGFloatOptional.+void YGNodeStyleSetFlexShrink(const YGNodeRef node, const float flexShrink) {+  if (node->getStyle().flexShrink != flexShrink) {+    node->getStyle().flexShrink = YGFloatIsUndefined(flexShrink)+        ? YGFloatOptional()+        : YGFloatOptional(flexShrink);+    node->markDirtyAndPropogate();+  }+}++YGValue YGNodeStyleGetFlexBasis(const YGNodeRef node) {+  YGValue flexBasis = node->getStyle().flexBasis;+  if (flexBasis.unit == YGUnitUndefined || flexBasis.unit == YGUnitAuto) {+    // TODO(T26792433): Get rid off the use of YGUndefined at client side+    flexBasis.value = YGUndefined;+  }+  return flexBasis;+}++void YGNodeStyleSetFlexBasis(const YGNodeRef node, const float flexBasis) {+  YGValue value = {+      YGFloatSanitize(flexBasis),+      YGFloatIsUndefined(flexBasis) ? YGUnitUndefined : YGUnitPoint,+  };+  if ((node->getStyle().flexBasis.value != value.value &&+       value.unit != YGUnitUndefined) ||+      node->getStyle().flexBasis.unit != value.unit) {+    node->getStyle().flexBasis = value;+    node->markDirtyAndPropogate();+  }+}++void YGNodeStyleSetFlexBasisPercent(+    const YGNodeRef node,+    const float flexBasisPercent) {+  if (node->getStyle().flexBasis.value != flexBasisPercent ||+      node->getStyle().flexBasis.unit != YGUnitPercent) {+    node->getStyle().flexBasis = YGFloatIsUndefined(flexBasisPercent)+        ? YGValue{0, YGUnitAuto}+        : YGValue{flexBasisPercent, YGUnitPercent};+    node->markDirtyAndPropogate();+  }+}++void YGNodeStyleSetFlexBasisAuto(const YGNodeRef node) {+  if (node->getStyle().flexBasis.unit != YGUnitAuto) {+    node->getStyle().flexBasis = {0, YGUnitAuto};+    node->markDirtyAndPropogate();+  }+}++YG_NODE_STYLE_EDGE_PROPERTY_UNIT_IMPL(YGValue, Position, position, position);+YG_NODE_STYLE_EDGE_PROPERTY_UNIT_IMPL(YGValue, Margin, margin, margin);+YG_NODE_STYLE_EDGE_PROPERTY_UNIT_AUTO_IMPL(YGValue, Margin, margin);+YG_NODE_STYLE_EDGE_PROPERTY_UNIT_IMPL(YGValue, Padding, padding, padding);++// TODO(T26792433): Change the API to accept YGFloatOptional.+void YGNodeStyleSetBorder(+    const YGNodeRef node,+    const YGEdge edge,+    const float border) {+  YGValue value = {+      YGFloatSanitize(border),+      YGFloatIsUndefined(border) ? YGUnitUndefined : YGUnitPoint,+  };+  if ((node->getStyle().border[edge].value != value.value &&+       value.unit != YGUnitUndefined) ||+      node->getStyle().border[edge].unit != value.unit) {+    node->getStyle().border[edge] = value;+    node->markDirtyAndPropogate();+  }+}++float YGNodeStyleGetBorder(const YGNodeRef node, const YGEdge edge) {+  if (node->getStyle().border[edge].unit == YGUnitUndefined ||+      node->getStyle().border[edge].unit == YGUnitAuto) {+    // TODO(T26792433): Rather than returning YGUndefined, change the api to+    // return YGFloatOptional.+    return YGUndefined;+  }++  return node->getStyle().border[edge].value;+}++// Yoga specific properties, not compatible with flexbox specification++// TODO(T26792433): Change the API to accept YGFloatOptional.+float YGNodeStyleGetAspectRatio(const YGNodeRef node) {+  const YGFloatOptional op = node->getStyle().aspectRatio;+  return op.isUndefined() ? YGUndefined : op.getValue();+}++// TODO(T26792433): Change the API to accept YGFloatOptional.+void YGNodeStyleSetAspectRatio(const YGNodeRef node, const float aspectRatio) {+  if (node->getStyle().aspectRatio != aspectRatio) {+    node->getStyle().aspectRatio = YGFloatOptional(aspectRatio);+    node->markDirtyAndPropogate();+  }+}++YG_NODE_STYLE_PROPERTY_UNIT_AUTO_IMPL(+    YGValue,+    Width,+    width,+    dimensions[YGDimensionWidth]);+YG_NODE_STYLE_PROPERTY_UNIT_AUTO_IMPL(+    YGValue,+    Height,+    height,+    dimensions[YGDimensionHeight]);++void YGNodeStyleSetMinWidth(const YGNodeRef node, const float minWidth) {+  DimensionProp<&YGStyle::minDimensions>::set<YGDimensionWidth, YGUnitPoint>(+      node, minWidth);+}+void YGNodeStyleSetMinWidthPercent(const YGNodeRef node, const float minWidth) {+  DimensionProp<&YGStyle::minDimensions>::set<YGDimensionWidth, YGUnitPercent>(+      node, minWidth);+}+YGValue YGNodeStyleGetMinWidth(const YGNodeRef node) {+  return DimensionProp<&YGStyle::minDimensions>::get<YGDimensionWidth>(node);+};++void YGNodeStyleSetMinHeight(const YGNodeRef node, const float minHeight) {+  DimensionProp<&YGStyle::minDimensions>::set<YGDimensionHeight, YGUnitPoint>(+      node, minHeight);+}+void YGNodeStyleSetMinHeightPercent(+    const YGNodeRef node,+    const float minHeight) {+  DimensionProp<&YGStyle::minDimensions>::set<YGDimensionHeight, YGUnitPercent>(+      node, minHeight);+}+YGValue YGNodeStyleGetMinHeight(const YGNodeRef node) {+  return DimensionProp<&YGStyle::minDimensions>::get<YGDimensionHeight>(node);+};++void YGNodeStyleSetMaxWidth(const YGNodeRef node, const float maxWidth) {+  DimensionProp<&YGStyle::maxDimensions>::set<YGDimensionWidth, YGUnitPoint>(+      node, maxWidth);+}+void YGNodeStyleSetMaxWidthPercent(const YGNodeRef node, const float maxWidth) {+  DimensionProp<&YGStyle::maxDimensions>::set<YGDimensionWidth, YGUnitPercent>(+      node, maxWidth);+}+YGValue YGNodeStyleGetMaxWidth(const YGNodeRef node) {+  return DimensionProp<&YGStyle::maxDimensions>::get<YGDimensionWidth>(node);+};++void YGNodeStyleSetMaxHeight(const YGNodeRef node, const float maxHeight) {+  DimensionProp<&YGStyle::maxDimensions>::set<YGDimensionHeight, YGUnitPoint>(+      node, maxHeight);+}+void YGNodeStyleSetMaxHeightPercent(+    const YGNodeRef node,+    const float maxHeight) {+  DimensionProp<&YGStyle::maxDimensions>::set<YGDimensionHeight, YGUnitPercent>(+      node, maxHeight);+}+YGValue YGNodeStyleGetMaxHeight(const YGNodeRef node) {+  return DimensionProp<&YGStyle::maxDimensions>::get<YGDimensionHeight>(node);+};++YG_NODE_LAYOUT_PROPERTY_IMPL(float, Left, position[YGEdgeLeft]);+YG_NODE_LAYOUT_PROPERTY_IMPL(float, Top, position[YGEdgeTop]);+YG_NODE_LAYOUT_PROPERTY_IMPL(float, Right, position[YGEdgeRight]);+YG_NODE_LAYOUT_PROPERTY_IMPL(float, Bottom, position[YGEdgeBottom]);+YG_NODE_LAYOUT_PROPERTY_IMPL(float, Width, dimensions[YGDimensionWidth]);+YG_NODE_LAYOUT_PROPERTY_IMPL(float, Height, dimensions[YGDimensionHeight]);+YG_NODE_LAYOUT_PROPERTY_IMPL(YGDirection, Direction, direction);+YG_NODE_LAYOUT_PROPERTY_IMPL(bool, HadOverflow, hadOverflow);++YG_NODE_LAYOUT_RESOLVED_PROPERTY_IMPL(float, Margin, margin);+YG_NODE_LAYOUT_RESOLVED_PROPERTY_IMPL(float, Border, border);+YG_NODE_LAYOUT_RESOLVED_PROPERTY_IMPL(float, Padding, padding);++bool YGNodeLayoutGetDidLegacyStretchFlagAffectLayout(const YGNodeRef node) {+  return node->getLayout().doesLegacyStretchFlagAffectsLayout;+}++uint32_t gCurrentGenerationCount = 0;++bool YGLayoutNodeInternal(+    const YGNodeRef node,+    const float availableWidth,+    const float availableHeight,+    const YGDirection ownerDirection,+    const YGMeasureMode widthMeasureMode,+    const YGMeasureMode heightMeasureMode,+    const float ownerWidth,+    const float ownerHeight,+    const bool performLayout,+    const char* reason,+    const YGConfigRef config);++static void YGNodePrintInternal(+    const YGNodeRef node,+    const YGPrintOptions options) {+  std::string str;+  facebook::yoga::YGNodeToString(&str, node, options, 0);+  YGLog(node, YGLogLevelDebug, str.c_str());+}++void YGNodePrint(const YGNodeRef node, const YGPrintOptions options) {+  YGNodePrintInternal(node, options);+}++const std::array<YGEdge, 4> leading = {+    {YGEdgeTop, YGEdgeBottom, YGEdgeLeft, YGEdgeRight}};++const std::array<YGEdge, 4> trailing = {+    {YGEdgeBottom, YGEdgeTop, YGEdgeRight, YGEdgeLeft}};+static const std::array<YGEdge, 4> pos = {{+    YGEdgeTop,+    YGEdgeBottom,+    YGEdgeLeft,+    YGEdgeRight,+}};++static const std::array<YGDimension, 4> dim = {+    {YGDimensionHeight, YGDimensionHeight, YGDimensionWidth, YGDimensionWidth}};++static inline float YGNodePaddingAndBorderForAxis(+    const YGNodeRef node,+    const YGFlexDirection axis,+    const float widthSize) {+  return YGUnwrapFloatOptional(+      node->getLeadingPaddingAndBorder(axis, widthSize) ++      node->getTrailingPaddingAndBorder(axis, widthSize));+}++static inline YGAlign YGNodeAlignItem(+    const YGNodeRef node,+    const YGNodeRef child) {+  const YGAlign align = child->getStyle().alignSelf == YGAlignAuto+      ? node->getStyle().alignItems+      : child->getStyle().alignSelf;+  if (align == YGAlignBaseline &&+      YGFlexDirectionIsColumn(node->getStyle().flexDirection)) {+    return YGAlignFlexStart;+  }+  return align;+}++static float YGBaseline(const YGNodeRef node) {+  if (node->getBaseline() != nullptr) {+    const float baseline = node->getBaseline()(+        node,+        node->getLayout().measuredDimensions[YGDimensionWidth],+        node->getLayout().measuredDimensions[YGDimensionHeight]);+    YGAssertWithNode(+        node,+        !YGFloatIsUndefined(baseline),+        "Expect custom baseline function to not return NaN");+    return baseline;+  }++  YGNodeRef baselineChild = nullptr;+  const uint32_t childCount = YGNodeGetChildCount(node);+  for (uint32_t i = 0; i < childCount; i++) {+    const YGNodeRef child = YGNodeGetChild(node, i);+    if (child->getLineIndex() > 0) {+      break;+    }+    if (child->getStyle().positionType == YGPositionTypeAbsolute) {+      continue;+    }+    if (YGNodeAlignItem(node, child) == YGAlignBaseline) {+      baselineChild = child;+      break;+    }++    if (baselineChild == nullptr) {+      baselineChild = child;+    }+  }++  if (baselineChild == nullptr) {+    return node->getLayout().measuredDimensions[YGDimensionHeight];+  }++  const float baseline = YGBaseline(baselineChild);+  return baseline + baselineChild->getLayout().position[YGEdgeTop];+}++static bool YGIsBaselineLayout(const YGNodeRef node) {+  if (YGFlexDirectionIsColumn(node->getStyle().flexDirection)) {+    return false;+  }+  if (node->getStyle().alignItems == YGAlignBaseline) {+    return true;+  }+  const uint32_t childCount = YGNodeGetChildCount(node);+  for (uint32_t i = 0; i < childCount; i++) {+    const YGNodeRef child = YGNodeGetChild(node, i);+    if (child->getStyle().positionType == YGPositionTypeRelative &&+        child->getStyle().alignSelf == YGAlignBaseline) {+      return true;+    }+  }++  return false;+}++static inline float YGNodeDimWithMargin(+    const YGNodeRef node,+    const YGFlexDirection axis,+    const float widthSize) {+  return node->getLayout().measuredDimensions[dim[axis]] ++      YGUnwrapFloatOptional(+             node->getLeadingMargin(axis, widthSize) ++             node->getTrailingMargin(axis, widthSize));+}++static inline bool YGNodeIsStyleDimDefined(+    const YGNodeRef node,+    const YGFlexDirection axis,+    const float ownerSize) {+  bool isUndefined =+      YGFloatIsUndefined(node->getResolvedDimension(dim[axis]).value);+  return !(+      node->getResolvedDimension(dim[axis]).unit == YGUnitAuto ||+      node->getResolvedDimension(dim[axis]).unit == YGUnitUndefined ||+      (node->getResolvedDimension(dim[axis]).unit == YGUnitPoint &&+       !isUndefined && node->getResolvedDimension(dim[axis]).value < 0.0f) ||+      (node->getResolvedDimension(dim[axis]).unit == YGUnitPercent &&+       !isUndefined &&+       (node->getResolvedDimension(dim[axis]).value < 0.0f ||+        YGFloatIsUndefined(ownerSize))));+}++static inline bool YGNodeIsLayoutDimDefined(+    const YGNodeRef node,+    const YGFlexDirection axis) {+  const float value = node->getLayout().measuredDimensions[dim[axis]];+  return !YGFloatIsUndefined(value) && value >= 0.0f;+}++static YGFloatOptional YGNodeBoundAxisWithinMinAndMax(+    const YGNodeRef node,+    const YGFlexDirection& axis,+    const float& value,+    const float& axisSize) {+  YGFloatOptional min;+  YGFloatOptional max;++  if (YGFlexDirectionIsColumn(axis)) {+    min = YGResolveValue(+        node->getStyle().minDimensions[YGDimensionHeight], axisSize);+    max = YGResolveValue(+        node->getStyle().maxDimensions[YGDimensionHeight], axisSize);+  } else if (YGFlexDirectionIsRow(axis)) {+    min = YGResolveValue(+        node->getStyle().minDimensions[YGDimensionWidth], axisSize);+    max = YGResolveValue(+        node->getStyle().maxDimensions[YGDimensionWidth], axisSize);+  }++  if (!max.isUndefined() && max.getValue() >= 0 && value > max.getValue()) {+    return max;+  }++  if (!min.isUndefined() && min.getValue() >= 0 && value < min.getValue()) {+    return min;+  }++  return YGFloatOptional(value);+}++// Like YGNodeBoundAxisWithinMinAndMax but also ensures that the value doesn't+// go below the padding and border amount.+static inline float YGNodeBoundAxis(+    const YGNodeRef node,+    const YGFlexDirection axis,+    const float value,+    const float axisSize,+    const float widthSize) {+  return YGFloatMax(+      YGUnwrapFloatOptional(+          YGNodeBoundAxisWithinMinAndMax(node, axis, value, axisSize)),+      YGNodePaddingAndBorderForAxis(node, axis, widthSize));+}++static void YGNodeSetChildTrailingPosition(+    const YGNodeRef node,+    const YGNodeRef child,+    const YGFlexDirection axis) {+  const float size = child->getLayout().measuredDimensions[dim[axis]];+  child->setLayoutPosition(+      node->getLayout().measuredDimensions[dim[axis]] - size -+          child->getLayout().position[pos[axis]],+      trailing[axis]);+}++static void YGConstrainMaxSizeForMode(+    const YGNodeRef node,+    const enum YGFlexDirection axis,+    const float ownerAxisSize,+    const float ownerWidth,+    YGMeasureMode* mode,+    float* size) {+  const YGFloatOptional maxSize =+      YGResolveValue(node->getStyle().maxDimensions[dim[axis]], ownerAxisSize) ++      YGFloatOptional(node->getMarginForAxis(axis, ownerWidth));+  switch (*mode) {+    case YGMeasureModeExactly:+    case YGMeasureModeAtMost:+      *size = (maxSize.isUndefined() || *size < maxSize.getValue())+          ? *size+          : maxSize.getValue();+      break;+    case YGMeasureModeUndefined:+      if (!maxSize.isUndefined()) {+        *mode = YGMeasureModeAtMost;+        *size = maxSize.getValue();+      }+      break;+  }+}++static void YGNodeComputeFlexBasisForChild(+    const YGNodeRef node,+    const YGNodeRef child,+    const float width,+    const YGMeasureMode widthMode,+    const float height,+    const float ownerWidth,+    const float ownerHeight,+    const YGMeasureMode heightMode,+    const YGDirection direction,+    const YGConfigRef config) {+  const YGFlexDirection mainAxis =+      YGResolveFlexDirection(node->getStyle().flexDirection, direction);+  const bool isMainAxisRow = YGFlexDirectionIsRow(mainAxis);+  const float mainAxisSize = isMainAxisRow ? width : height;+  const float mainAxisownerSize = isMainAxisRow ? ownerWidth : ownerHeight;++  float childWidth;+  float childHeight;+  YGMeasureMode childWidthMeasureMode;+  YGMeasureMode childHeightMeasureMode;++  const YGFloatOptional resolvedFlexBasis =+      YGResolveValue(child->resolveFlexBasisPtr(), mainAxisownerSize);+  const bool isRowStyleDimDefined =+      YGNodeIsStyleDimDefined(child, YGFlexDirectionRow, ownerWidth);+  const bool isColumnStyleDimDefined =+      YGNodeIsStyleDimDefined(child, YGFlexDirectionColumn, ownerHeight);++  if (!resolvedFlexBasis.isUndefined() && !YGFloatIsUndefined(mainAxisSize)) {+    if (child->getLayout().computedFlexBasis.isUndefined() ||+        (YGConfigIsExperimentalFeatureEnabled(+             child->getConfig(), YGExperimentalFeatureWebFlexBasis) &&+         child->getLayout().computedFlexBasisGeneration !=+             gCurrentGenerationCount)) {+      const YGFloatOptional& paddingAndBorder = YGFloatOptional(+          YGNodePaddingAndBorderForAxis(child, mainAxis, ownerWidth));+      child->setLayoutComputedFlexBasis(+          YGFloatOptionalMax(resolvedFlexBasis, paddingAndBorder));+    }+  } else if (isMainAxisRow && isRowStyleDimDefined) {+    // The width is definite, so use that as the flex basis.+    const YGFloatOptional& paddingAndBorder = YGFloatOptional(+        YGNodePaddingAndBorderForAxis(child, YGFlexDirectionRow, ownerWidth));++    child->setLayoutComputedFlexBasis(YGFloatOptionalMax(+        YGResolveValue(+            child->getResolvedDimension(YGDimensionWidth), ownerWidth),+        paddingAndBorder));+  } else if (!isMainAxisRow && isColumnStyleDimDefined) {+    // The height is definite, so use that as the flex basis.+    const YGFloatOptional& paddingAndBorder =+        YGFloatOptional(YGNodePaddingAndBorderForAxis(+            child, YGFlexDirectionColumn, ownerWidth));+    child->setLayoutComputedFlexBasis(YGFloatOptionalMax(+        YGResolveValue(+            child->getResolvedDimension(YGDimensionHeight), ownerHeight),+        paddingAndBorder));+  } else {+    // Compute the flex basis and hypothetical main size (i.e. the clamped+    // flex basis).+    childWidth = YGUndefined;+    childHeight = YGUndefined;+    childWidthMeasureMode = YGMeasureModeUndefined;+    childHeightMeasureMode = YGMeasureModeUndefined;++    auto marginRow = YGUnwrapFloatOptional(+        child->getMarginForAxis(YGFlexDirectionRow, ownerWidth));+    auto marginColumn = YGUnwrapFloatOptional(+        child->getMarginForAxis(YGFlexDirectionColumn, ownerWidth));++    if (isRowStyleDimDefined) {+      childWidth =+          YGUnwrapFloatOptional(YGResolveValue(+              child->getResolvedDimension(YGDimensionWidth), ownerWidth)) ++          marginRow;+      childWidthMeasureMode = YGMeasureModeExactly;+    }+    if (isColumnStyleDimDefined) {+      childHeight =+          YGUnwrapFloatOptional(YGResolveValue(+              child->getResolvedDimension(YGDimensionHeight), ownerHeight)) ++          marginColumn;+      childHeightMeasureMode = YGMeasureModeExactly;+    }++    // The W3C spec doesn't say anything about the 'overflow' property,+    // but all major browsers appear to implement the following logic.+    if ((!isMainAxisRow && node->getStyle().overflow == YGOverflowScroll) ||+        node->getStyle().overflow != YGOverflowScroll) {+      if (YGFloatIsUndefined(childWidth) && !YGFloatIsUndefined(width)) {+        childWidth = width;+        childWidthMeasureMode = YGMeasureModeAtMost;+      }+    }++    if ((isMainAxisRow && node->getStyle().overflow == YGOverflowScroll) ||+        node->getStyle().overflow != YGOverflowScroll) {+      if (YGFloatIsUndefined(childHeight) && !YGFloatIsUndefined(height)) {+        childHeight = height;+        childHeightMeasureMode = YGMeasureModeAtMost;+      }+    }++    if (!child->getStyle().aspectRatio.isUndefined()) {+      if (!isMainAxisRow && childWidthMeasureMode == YGMeasureModeExactly) {+        childHeight = marginColumn ++            (childWidth - marginRow) / child->getStyle().aspectRatio.getValue();+        childHeightMeasureMode = YGMeasureModeExactly;+      } else if (+          isMainAxisRow && childHeightMeasureMode == YGMeasureModeExactly) {+        childWidth = marginRow ++            (childHeight - marginColumn) *+                child->getStyle().aspectRatio.getValue();+        childWidthMeasureMode = YGMeasureModeExactly;+      }+    }++    // If child has no defined size in the cross axis and is set to stretch,+    // set the cross+    // axis to be measured exactly with the available inner width++    const bool hasExactWidth =+        !YGFloatIsUndefined(width) && widthMode == YGMeasureModeExactly;+    const bool childWidthStretch =+        YGNodeAlignItem(node, child) == YGAlignStretch &&+        childWidthMeasureMode != YGMeasureModeExactly;+    if (!isMainAxisRow && !isRowStyleDimDefined && hasExactWidth &&+        childWidthStretch) {+      childWidth = width;+      childWidthMeasureMode = YGMeasureModeExactly;+      if (!child->getStyle().aspectRatio.isUndefined()) {+        childHeight =+            (childWidth - marginRow) / child->getStyle().aspectRatio.getValue();+        childHeightMeasureMode = YGMeasureModeExactly;+      }+    }++    const bool hasExactHeight =+        !YGFloatIsUndefined(height) && heightMode == YGMeasureModeExactly;+    const bool childHeightStretch =+        YGNodeAlignItem(node, child) == YGAlignStretch &&+        childHeightMeasureMode != YGMeasureModeExactly;+    if (isMainAxisRow && !isColumnStyleDimDefined && hasExactHeight &&+        childHeightStretch) {+      childHeight = height;+      childHeightMeasureMode = YGMeasureModeExactly;++      if (!child->getStyle().aspectRatio.isUndefined()) {+        childWidth = (childHeight - marginColumn) *+            child->getStyle().aspectRatio.getValue();+        childWidthMeasureMode = YGMeasureModeExactly;+      }+    }++    YGConstrainMaxSizeForMode(+        child,+        YGFlexDirectionRow,+        ownerWidth,+        ownerWidth,+        &childWidthMeasureMode,+        &childWidth);+    YGConstrainMaxSizeForMode(+        child,+        YGFlexDirectionColumn,+        ownerHeight,+        ownerWidth,+        &childHeightMeasureMode,+        &childHeight);++    // Measure the child+    YGLayoutNodeInternal(+        child,+        childWidth,+        childHeight,+        direction,+        childWidthMeasureMode,+        childHeightMeasureMode,+        ownerWidth,+        ownerHeight,+        false,+        "measure",+        config);++    child->setLayoutComputedFlexBasis(YGFloatOptional(YGFloatMax(+        child->getLayout().measuredDimensions[dim[mainAxis]],+        YGNodePaddingAndBorderForAxis(child, mainAxis, ownerWidth))));+  }+  child->setLayoutComputedFlexBasisGeneration(gCurrentGenerationCount);+}++static void YGNodeAbsoluteLayoutChild(+    const YGNodeRef node,+    const YGNodeRef child,+    const float width,+    const YGMeasureMode widthMode,+    const float height,+    const YGDirection direction,+    const YGConfigRef config) {+  const YGFlexDirection mainAxis =+      YGResolveFlexDirection(node->getStyle().flexDirection, direction);+  const YGFlexDirection crossAxis = YGFlexDirectionCross(mainAxis, direction);+  const bool isMainAxisRow = YGFlexDirectionIsRow(mainAxis);++  float childWidth = YGUndefined;+  float childHeight = YGUndefined;+  YGMeasureMode childWidthMeasureMode = YGMeasureModeUndefined;+  YGMeasureMode childHeightMeasureMode = YGMeasureModeUndefined;++  auto marginRow =+      YGUnwrapFloatOptional(child->getMarginForAxis(YGFlexDirectionRow, width));+  auto marginColumn = YGUnwrapFloatOptional(+      child->getMarginForAxis(YGFlexDirectionColumn, width));++  if (YGNodeIsStyleDimDefined(child, YGFlexDirectionRow, width)) {+    childWidth = YGUnwrapFloatOptional(YGResolveValue(+                     child->getResolvedDimension(YGDimensionWidth), width)) ++        marginRow;+  } else {+    // If the child doesn't have a specified width, compute the width based+    // on the left/right+    // offsets if they're defined.+    if (child->isLeadingPositionDefined(YGFlexDirectionRow) &&+        child->isTrailingPosDefined(YGFlexDirectionRow)) {+      childWidth = node->getLayout().measuredDimensions[YGDimensionWidth] -+          (node->getLeadingBorder(YGFlexDirectionRow) ++           node->getTrailingBorder(YGFlexDirectionRow)) -+          YGUnwrapFloatOptional(+                       child->getLeadingPosition(YGFlexDirectionRow, width) ++                       child->getTrailingPosition(YGFlexDirectionRow, width));+      childWidth =+          YGNodeBoundAxis(child, YGFlexDirectionRow, childWidth, width, width);+    }+  }++  if (YGNodeIsStyleDimDefined(child, YGFlexDirectionColumn, height)) {+    childHeight = YGUnwrapFloatOptional(YGResolveValue(+                      child->getResolvedDimension(YGDimensionHeight), height)) ++        marginColumn;+  } else {+    // If the child doesn't have a specified height, compute the height+    // based on the top/bottom+    // offsets if they're defined.+    if (child->isLeadingPositionDefined(YGFlexDirectionColumn) &&+        child->isTrailingPosDefined(YGFlexDirectionColumn)) {+      childHeight =+          node->getLayout().measuredDimensions[YGDimensionHeight] -+          (node->getLeadingBorder(YGFlexDirectionColumn) ++           node->getTrailingBorder(YGFlexDirectionColumn)) -+          YGUnwrapFloatOptional(+              child->getLeadingPosition(YGFlexDirectionColumn, height) ++              child->getTrailingPosition(YGFlexDirectionColumn, height));+      childHeight = YGNodeBoundAxis(+          child, YGFlexDirectionColumn, childHeight, height, width);+    }+  }++  // Exactly one dimension needs to be defined for us to be able to do aspect+  // ratio calculation. One dimension being the anchor and the other being+  // flexible.+  if (YGFloatIsUndefined(childWidth) ^ YGFloatIsUndefined(childHeight)) {+    if (!child->getStyle().aspectRatio.isUndefined()) {+      if (YGFloatIsUndefined(childWidth)) {+        childWidth = marginRow ++            (childHeight - marginColumn) *+                child->getStyle().aspectRatio.getValue();+      } else if (YGFloatIsUndefined(childHeight)) {+        childHeight = marginColumn ++            (childWidth - marginRow) / child->getStyle().aspectRatio.getValue();+      }+    }+  }++  // If we're still missing one or the other dimension, measure the content.+  if (YGFloatIsUndefined(childWidth) || YGFloatIsUndefined(childHeight)) {+    childWidthMeasureMode = YGFloatIsUndefined(childWidth)+        ? YGMeasureModeUndefined+        : YGMeasureModeExactly;+    childHeightMeasureMode = YGFloatIsUndefined(childHeight)+        ? YGMeasureModeUndefined+        : YGMeasureModeExactly;++    // If the size of the owner is defined then try to constrain the absolute+    // child to that size as well. This allows text within the absolute child to+    // wrap to the size of its owner. This is the same behavior as many browsers+    // implement.+    if (!isMainAxisRow && YGFloatIsUndefined(childWidth) &&+        widthMode != YGMeasureModeUndefined && !YGFloatIsUndefined(width) &&+        width > 0) {+      childWidth = width;+      childWidthMeasureMode = YGMeasureModeAtMost;+    }++    YGLayoutNodeInternal(+        child,+        childWidth,+        childHeight,+        direction,+        childWidthMeasureMode,+        childHeightMeasureMode,+        childWidth,+        childHeight,+        false,+        "abs-measure",+        config);+    childWidth = child->getLayout().measuredDimensions[YGDimensionWidth] ++        YGUnwrapFloatOptional(+                     child->getMarginForAxis(YGFlexDirectionRow, width));+    childHeight = child->getLayout().measuredDimensions[YGDimensionHeight] ++        YGUnwrapFloatOptional(+                      child->getMarginForAxis(YGFlexDirectionColumn, width));+  }++  YGLayoutNodeInternal(+      child,+      childWidth,+      childHeight,+      direction,+      YGMeasureModeExactly,+      YGMeasureModeExactly,+      childWidth,+      childHeight,+      true,+      "abs-layout",+      config);++  if (child->isTrailingPosDefined(mainAxis) &&+      !child->isLeadingPositionDefined(mainAxis)) {+    child->setLayoutPosition(+        node->getLayout().measuredDimensions[dim[mainAxis]] -+            child->getLayout().measuredDimensions[dim[mainAxis]] -+            node->getTrailingBorder(mainAxis) -+            YGUnwrapFloatOptional(child->getTrailingMargin(mainAxis, width)) -+            YGUnwrapFloatOptional(child->getTrailingPosition(+                mainAxis, isMainAxisRow ? width : height)),+        leading[mainAxis]);+  } else if (+      !child->isLeadingPositionDefined(mainAxis) &&+      node->getStyle().justifyContent == YGJustifyCenter) {+    child->setLayoutPosition(+        (node->getLayout().measuredDimensions[dim[mainAxis]] -+         child->getLayout().measuredDimensions[dim[mainAxis]]) /+            2.0f,+        leading[mainAxis]);+  } else if (+      !child->isLeadingPositionDefined(mainAxis) &&+      node->getStyle().justifyContent == YGJustifyFlexEnd) {+    child->setLayoutPosition(+        (node->getLayout().measuredDimensions[dim[mainAxis]] -+         child->getLayout().measuredDimensions[dim[mainAxis]]),+        leading[mainAxis]);+  }++  if (child->isTrailingPosDefined(crossAxis) &&+      !child->isLeadingPositionDefined(crossAxis)) {+    child->setLayoutPosition(+        node->getLayout().measuredDimensions[dim[crossAxis]] -+            child->getLayout().measuredDimensions[dim[crossAxis]] -+            node->getTrailingBorder(crossAxis) -+            YGUnwrapFloatOptional(child->getTrailingMargin(crossAxis, width)) -+            YGUnwrapFloatOptional(child->getTrailingPosition(+                crossAxis, isMainAxisRow ? height : width)),+        leading[crossAxis]);++  } else if (+      !child->isLeadingPositionDefined(crossAxis) &&+      YGNodeAlignItem(node, child) == YGAlignCenter) {+    child->setLayoutPosition(+        (node->getLayout().measuredDimensions[dim[crossAxis]] -+         child->getLayout().measuredDimensions[dim[crossAxis]]) /+            2.0f,+        leading[crossAxis]);+  } else if (+      !child->isLeadingPositionDefined(crossAxis) &&+      ((YGNodeAlignItem(node, child) == YGAlignFlexEnd) ^+       (node->getStyle().flexWrap == YGWrapWrapReverse))) {+    child->setLayoutPosition(+        (node->getLayout().measuredDimensions[dim[crossAxis]] -+         child->getLayout().measuredDimensions[dim[crossAxis]]),+        leading[crossAxis]);+  }+}++static void YGNodeWithMeasureFuncSetMeasuredDimensions(+    const YGNodeRef node,+    const float availableWidth,+    const float availableHeight,+    const YGMeasureMode widthMeasureMode,+    const YGMeasureMode heightMeasureMode,+    const float ownerWidth,+    const float ownerHeight) {+  YGAssertWithNode(+      node,+      node->getMeasure() != nullptr,+      "Expected node to have custom measure function");++  const float paddingAndBorderAxisRow =+      YGNodePaddingAndBorderForAxis(node, YGFlexDirectionRow, availableWidth);+  const float paddingAndBorderAxisColumn = YGNodePaddingAndBorderForAxis(+      node, YGFlexDirectionColumn, availableWidth);+  const float marginAxisRow = YGUnwrapFloatOptional(+      node->getMarginForAxis(YGFlexDirectionRow, availableWidth));+  const float marginAxisColumn = YGUnwrapFloatOptional(+      node->getMarginForAxis(YGFlexDirectionColumn, availableWidth));++  // We want to make sure we don't call measure with negative size+  const float innerWidth = YGFloatIsUndefined(availableWidth)+      ? availableWidth+      : YGFloatMax(0, availableWidth - marginAxisRow - paddingAndBorderAxisRow);+  const float innerHeight = YGFloatIsUndefined(availableHeight)+      ? availableHeight+      : YGFloatMax(+            0, availableHeight - marginAxisColumn - paddingAndBorderAxisColumn);++  if (widthMeasureMode == YGMeasureModeExactly &&+      heightMeasureMode == YGMeasureModeExactly) {+    // Don't bother sizing the text if both dimensions are already defined.+    node->setLayoutMeasuredDimension(+        YGNodeBoundAxis(+            node,+            YGFlexDirectionRow,+            availableWidth - marginAxisRow,+            ownerWidth,+            ownerWidth),+        YGDimensionWidth);+    node->setLayoutMeasuredDimension(+        YGNodeBoundAxis(+            node,+            YGFlexDirectionColumn,+            availableHeight - marginAxisColumn,+            ownerHeight,+            ownerWidth),+        YGDimensionHeight);+  } else {+    // Measure the text under the current constraints.+    const YGSize measuredSize = node->getMeasure()(+        node, innerWidth, widthMeasureMode, innerHeight, heightMeasureMode);++    node->setLayoutMeasuredDimension(+        YGNodeBoundAxis(+            node,+            YGFlexDirectionRow,+            (widthMeasureMode == YGMeasureModeUndefined ||+             widthMeasureMode == YGMeasureModeAtMost)+                ? measuredSize.width + paddingAndBorderAxisRow+                : availableWidth - marginAxisRow,+            ownerWidth,+            ownerWidth),+        YGDimensionWidth);++    node->setLayoutMeasuredDimension(+        YGNodeBoundAxis(+            node,+            YGFlexDirectionColumn,+            (heightMeasureMode == YGMeasureModeUndefined ||+             heightMeasureMode == YGMeasureModeAtMost)+                ? measuredSize.height + paddingAndBorderAxisColumn+                : availableHeight - marginAxisColumn,+            ownerHeight,+            ownerWidth),+        YGDimensionHeight);+  }+}++// For nodes with no children, use the available values if they were provided,+// or the minimum size as indicated by the padding and border sizes.+static void YGNodeEmptyContainerSetMeasuredDimensions(+    const YGNodeRef node,+    const float availableWidth,+    const float availableHeight,+    const YGMeasureMode widthMeasureMode,+    const YGMeasureMode heightMeasureMode,+    const float ownerWidth,+    const float ownerHeight) {+  const float paddingAndBorderAxisRow =+      YGNodePaddingAndBorderForAxis(node, YGFlexDirectionRow, ownerWidth);+  const float paddingAndBorderAxisColumn =+      YGNodePaddingAndBorderForAxis(node, YGFlexDirectionColumn, ownerWidth);+  const float marginAxisRow = YGUnwrapFloatOptional(+      node->getMarginForAxis(YGFlexDirectionRow, ownerWidth));+  const float marginAxisColumn = YGUnwrapFloatOptional(+      node->getMarginForAxis(YGFlexDirectionColumn, ownerWidth));++  node->setLayoutMeasuredDimension(+      YGNodeBoundAxis(+          node,+          YGFlexDirectionRow,+          (widthMeasureMode == YGMeasureModeUndefined ||+           widthMeasureMode == YGMeasureModeAtMost)+              ? paddingAndBorderAxisRow+              : availableWidth - marginAxisRow,+          ownerWidth,+          ownerWidth),+      YGDimensionWidth);++  node->setLayoutMeasuredDimension(+      YGNodeBoundAxis(+          node,+          YGFlexDirectionColumn,+          (heightMeasureMode == YGMeasureModeUndefined ||+           heightMeasureMode == YGMeasureModeAtMost)+              ? paddingAndBorderAxisColumn+              : availableHeight - marginAxisColumn,+          ownerHeight,+          ownerWidth),+      YGDimensionHeight);+}++static bool YGNodeFixedSizeSetMeasuredDimensions(+    const YGNodeRef node,+    const float availableWidth,+    const float availableHeight,+    const YGMeasureMode widthMeasureMode,+    const YGMeasureMode heightMeasureMode,+    const float ownerWidth,+    const float ownerHeight) {+  if ((!YGFloatIsUndefined(availableWidth) &&+       widthMeasureMode == YGMeasureModeAtMost && availableWidth <= 0.0f) ||+      (!YGFloatIsUndefined(availableHeight) &&+       heightMeasureMode == YGMeasureModeAtMost && availableHeight <= 0.0f) ||+      (widthMeasureMode == YGMeasureModeExactly &&+       heightMeasureMode == YGMeasureModeExactly)) {+    auto marginAxisColumn = YGUnwrapFloatOptional(+        node->getMarginForAxis(YGFlexDirectionColumn, ownerWidth));+    auto marginAxisRow = YGUnwrapFloatOptional(+        node->getMarginForAxis(YGFlexDirectionRow, ownerWidth));++    node->setLayoutMeasuredDimension(+        YGNodeBoundAxis(+            node,+            YGFlexDirectionRow,+            YGFloatIsUndefined(availableWidth) ||+                    (widthMeasureMode == YGMeasureModeAtMost &&+                     availableWidth < 0.0f)+                ? 0.0f+                : availableWidth - marginAxisRow,+            ownerWidth,+            ownerWidth),+        YGDimensionWidth);++    node->setLayoutMeasuredDimension(+        YGNodeBoundAxis(+            node,+            YGFlexDirectionColumn,+            YGFloatIsUndefined(availableHeight) ||+                    (heightMeasureMode == YGMeasureModeAtMost &&+                     availableHeight < 0.0f)+                ? 0.0f+                : availableHeight - marginAxisColumn,+            ownerHeight,+            ownerWidth),+        YGDimensionHeight);+    return true;+  }++  return false;+}++static void YGZeroOutLayoutRecursivly(const YGNodeRef node) {+  memset(&(node->getLayout()), 0, sizeof(YGLayout));+  node->setHasNewLayout(true);+  node->cloneChildrenIfNeeded();+  const uint32_t childCount = YGNodeGetChildCount(node);+  for (uint32_t i = 0; i < childCount; i++) {+    const YGNodeRef child = node->getChild(i);+    YGZeroOutLayoutRecursivly(child);+  }+}++static float YGNodeCalculateAvailableInnerDim(+    const YGNodeRef node,+    YGFlexDirection axis,+    float availableDim,+    float ownerDim) {+  YGFlexDirection direction =+      YGFlexDirectionIsRow(axis) ? YGFlexDirectionRow : YGFlexDirectionColumn;+  YGDimension dimension =+      YGFlexDirectionIsRow(axis) ? YGDimensionWidth : YGDimensionHeight;++  const float margin =+      YGUnwrapFloatOptional(node->getMarginForAxis(direction, ownerDim));+  const float paddingAndBorder =+      YGNodePaddingAndBorderForAxis(node, direction, ownerDim);++  float availableInnerDim = availableDim - margin - paddingAndBorder;+  // Max dimension overrides predefined dimension value; Min dimension in turn+  // overrides both of the above+  if (!YGFloatIsUndefined(availableInnerDim)) {+    // We want to make sure our available height does not violate min and max+    // constraints+    const YGFloatOptional minDimensionOptional =+        YGResolveValue(node->getStyle().minDimensions[dimension], ownerDim);+    const float minInnerDim = minDimensionOptional.isUndefined()+        ? 0.0f+        : minDimensionOptional.getValue() - paddingAndBorder;++    const YGFloatOptional maxDimensionOptional =+        YGResolveValue(node->getStyle().maxDimensions[dimension], ownerDim);++    const float maxInnerDim = maxDimensionOptional.isUndefined()+        ? FLT_MAX+        : maxDimensionOptional.getValue() - paddingAndBorder;+    availableInnerDim =+        YGFloatMax(YGFloatMin(availableInnerDim, maxInnerDim), minInnerDim);+  }++  return availableInnerDim;+}++static void YGNodeComputeFlexBasisForChildren(+    const YGNodeRef node,+    const float availableInnerWidth,+    const float availableInnerHeight,+    YGMeasureMode widthMeasureMode,+    YGMeasureMode heightMeasureMode,+    YGDirection direction,+    YGFlexDirection mainAxis,+    const YGConfigRef config,+    bool performLayout,+    float& totalOuterFlexBasis) {+  YGNodeRef singleFlexChild = nullptr;+  YGVector children = node->getChildren();+  YGMeasureMode measureModeMainDim =+      YGFlexDirectionIsRow(mainAxis) ? widthMeasureMode : heightMeasureMode;+  // If there is only one child with flexGrow + flexShrink it means we can set+  // the computedFlexBasis to 0 instead of measuring and shrinking / flexing the+  // child to exactly match the remaining space+  if (measureModeMainDim == YGMeasureModeExactly) {+    for (auto child : children) {+      if (child->isNodeFlexible()) {+        if (singleFlexChild != nullptr ||+            YGFloatsEqual(child->resolveFlexGrow(), 0.0f) ||+            YGFloatsEqual(child->resolveFlexShrink(), 0.0f)) {+          // There is already a flexible child, or this flexible child doesn't+          // have flexGrow and flexShrink, abort+          singleFlexChild = nullptr;+          break;+        } else {+          singleFlexChild = child;+        }+      }+    }+  }++  for (auto child : children) {+    child->resolveDimension();+    if (child->getStyle().display == YGDisplayNone) {+      YGZeroOutLayoutRecursivly(child);+      child->setHasNewLayout(true);+      child->setDirty(false);+      continue;+    }+    if (performLayout) {+      // Set the initial position (relative to the owner).+      const YGDirection childDirection = child->resolveDirection(direction);+      const float mainDim = YGFlexDirectionIsRow(mainAxis)+          ? availableInnerWidth+          : availableInnerHeight;+      const float crossDim = YGFlexDirectionIsRow(mainAxis)+          ? availableInnerHeight+          : availableInnerWidth;+      child->setPosition(+          childDirection, mainDim, crossDim, availableInnerWidth);+    }++    if (child->getStyle().positionType == YGPositionTypeAbsolute) {+      continue;+    }+    if (child == singleFlexChild) {+      child->setLayoutComputedFlexBasisGeneration(gCurrentGenerationCount);+      child->setLayoutComputedFlexBasis(YGFloatOptional(0));+    } else {+      YGNodeComputeFlexBasisForChild(+          node,+          child,+          availableInnerWidth,+          widthMeasureMode,+          availableInnerHeight,+          availableInnerWidth,+          availableInnerHeight,+          heightMeasureMode,+          direction,+          config);+    }++    totalOuterFlexBasis += YGUnwrapFloatOptional(+        child->getLayout().computedFlexBasis ++        child->getMarginForAxis(mainAxis, availableInnerWidth));+  }+}++// This function assumes that all the children of node have their+// computedFlexBasis properly computed(To do this use+// YGNodeComputeFlexBasisForChildren function).+// This function calculates YGCollectFlexItemsRowMeasurement+static YGCollectFlexItemsRowValues YGCalculateCollectFlexItemsRowValues(+    const YGNodeRef& node,+    const YGDirection ownerDirection,+    const float mainAxisownerSize,+    const float availableInnerWidth,+    const float availableInnerMainDim,+    const uint32_t startOfLineIndex,+    const uint32_t lineCount) {+  YGCollectFlexItemsRowValues flexAlgoRowMeasurement = {};+  flexAlgoRowMeasurement.relativeChildren.reserve(node->getChildren().size());++  float sizeConsumedOnCurrentLineIncludingMinConstraint = 0;+  const YGFlexDirection mainAxis = YGResolveFlexDirection(+      node->getStyle().flexDirection, node->resolveDirection(ownerDirection));+  const bool isNodeFlexWrap = node->getStyle().flexWrap != YGWrapNoWrap;++  // Add items to the current line until it's full or we run out of items.+  uint32_t endOfLineIndex = startOfLineIndex;+  for (; endOfLineIndex < node->getChildren().size(); endOfLineIndex++) {+    const YGNodeRef child = node->getChild(endOfLineIndex);+    if (child->getStyle().display == YGDisplayNone ||+        child->getStyle().positionType == YGPositionTypeAbsolute) {+      continue;+    }+    child->setLineIndex(lineCount);+    const float childMarginMainAxis = YGUnwrapFloatOptional(+        child->getMarginForAxis(mainAxis, availableInnerWidth));+    const float flexBasisWithMinAndMaxConstraints =+        YGUnwrapFloatOptional(YGNodeBoundAxisWithinMinAndMax(+            child,+            mainAxis,+            YGUnwrapFloatOptional(child->getLayout().computedFlexBasis),+            mainAxisownerSize));++    // If this is a multi-line flow and this item pushes us over the+    // available size, we've+    // hit the end of the current line. Break out of the loop and lay out+    // the current line.+    if (sizeConsumedOnCurrentLineIncludingMinConstraint ++                flexBasisWithMinAndMaxConstraints + childMarginMainAxis >+            availableInnerMainDim &&+        isNodeFlexWrap && flexAlgoRowMeasurement.itemsOnLine > 0) {+      break;+    }++    sizeConsumedOnCurrentLineIncludingMinConstraint +=+        flexBasisWithMinAndMaxConstraints + childMarginMainAxis;+    flexAlgoRowMeasurement.sizeConsumedOnCurrentLine +=+        flexBasisWithMinAndMaxConstraints + childMarginMainAxis;+    flexAlgoRowMeasurement.itemsOnLine++;++    if (child->isNodeFlexible()) {+      flexAlgoRowMeasurement.totalFlexGrowFactors += child->resolveFlexGrow();++      // Unlike the grow factor, the shrink factor is scaled relative to the+      // child dimension.+      flexAlgoRowMeasurement.totalFlexShrinkScaledFactors +=+          -child->resolveFlexShrink() *+          YGUnwrapFloatOptional(child->getLayout().computedFlexBasis);+    }++    flexAlgoRowMeasurement.relativeChildren.push_back(child);+  }++  // The total flex factor needs to be floored to 1.+  if (flexAlgoRowMeasurement.totalFlexGrowFactors > 0 &&+      flexAlgoRowMeasurement.totalFlexGrowFactors < 1) {+    flexAlgoRowMeasurement.totalFlexGrowFactors = 1;+  }++  // The total flex shrink factor needs to be floored to 1.+  if (flexAlgoRowMeasurement.totalFlexShrinkScaledFactors > 0 &&+      flexAlgoRowMeasurement.totalFlexShrinkScaledFactors < 1) {+    flexAlgoRowMeasurement.totalFlexShrinkScaledFactors = 1;+  }+  flexAlgoRowMeasurement.endOfLineIndex = endOfLineIndex;+  return flexAlgoRowMeasurement;+}++// It distributes the free space to the flexible items and ensures that the size+// of the flex items abide the min and max constraints. At the end of this+// function the child nodes would have proper size. Prior using this function+// please ensure that YGDistributeFreeSpaceFirstPass is called.+static float YGDistributeFreeSpaceSecondPass(+    YGCollectFlexItemsRowValues& collectedFlexItemsValues,+    const YGNodeRef node,+    const YGFlexDirection mainAxis,+    const YGFlexDirection crossAxis,+    const float mainAxisownerSize,+    const float availableInnerMainDim,+    const float availableInnerCrossDim,+    const float availableInnerWidth,+    const float availableInnerHeight,+    const bool flexBasisOverflows,+    const YGMeasureMode measureModeCrossDim,+    const bool performLayout,+    const YGConfigRef config) {+  float childFlexBasis = 0;+  float flexShrinkScaledFactor = 0;+  float flexGrowFactor = 0;+  float deltaFreeSpace = 0;+  const bool isMainAxisRow = YGFlexDirectionIsRow(mainAxis);+  const bool isNodeFlexWrap = node->getStyle().flexWrap != YGWrapNoWrap;++  for (auto currentRelativeChild : collectedFlexItemsValues.relativeChildren) {+    childFlexBasis = YGUnwrapFloatOptional(YGNodeBoundAxisWithinMinAndMax(+        currentRelativeChild,+        mainAxis,+        YGUnwrapFloatOptional(+            currentRelativeChild->getLayout().computedFlexBasis),+        mainAxisownerSize));+    float updatedMainSize = childFlexBasis;++    if (!YGFloatIsUndefined(collectedFlexItemsValues.remainingFreeSpace) &&+        collectedFlexItemsValues.remainingFreeSpace < 0) {+      flexShrinkScaledFactor =+          -currentRelativeChild->resolveFlexShrink() * childFlexBasis;+      // Is this child able to shrink?+      if (flexShrinkScaledFactor != 0) {+        float childSize;++        if (!YGFloatIsUndefined(+                collectedFlexItemsValues.totalFlexShrinkScaledFactors) &&+            collectedFlexItemsValues.totalFlexShrinkScaledFactors == 0) {+          childSize = childFlexBasis + flexShrinkScaledFactor;+        } else {+          childSize = childFlexBasis ++              (collectedFlexItemsValues.remainingFreeSpace /+               collectedFlexItemsValues.totalFlexShrinkScaledFactors) *+                  flexShrinkScaledFactor;+        }++        updatedMainSize = YGNodeBoundAxis(+            currentRelativeChild,+            mainAxis,+            childSize,+            availableInnerMainDim,+            availableInnerWidth);+      }+    } else if (+        !YGFloatIsUndefined(collectedFlexItemsValues.remainingFreeSpace) &&+        collectedFlexItemsValues.remainingFreeSpace > 0) {+      flexGrowFactor = currentRelativeChild->resolveFlexGrow();++      // Is this child able to grow?+      if (!YGFloatIsUndefined(flexGrowFactor) && flexGrowFactor != 0) {+        updatedMainSize = YGNodeBoundAxis(+            currentRelativeChild,+            mainAxis,+            childFlexBasis ++                collectedFlexItemsValues.remainingFreeSpace /+                    collectedFlexItemsValues.totalFlexGrowFactors *+                    flexGrowFactor,+            availableInnerMainDim,+            availableInnerWidth);+      }+    }++    deltaFreeSpace += updatedMainSize - childFlexBasis;++    const float marginMain = YGUnwrapFloatOptional(+        currentRelativeChild->getMarginForAxis(mainAxis, availableInnerWidth));+    const float marginCross = YGUnwrapFloatOptional(+        currentRelativeChild->getMarginForAxis(crossAxis, availableInnerWidth));++    float childCrossSize;+    float childMainSize = updatedMainSize + marginMain;+    YGMeasureMode childCrossMeasureMode;+    YGMeasureMode childMainMeasureMode = YGMeasureModeExactly;++    if (!currentRelativeChild->getStyle().aspectRatio.isUndefined()) {+      childCrossSize = isMainAxisRow ? (childMainSize - marginMain) /+              currentRelativeChild->getStyle().aspectRatio.getValue()+                                     : (childMainSize - marginMain) *+              currentRelativeChild->getStyle().aspectRatio.getValue();+      childCrossMeasureMode = YGMeasureModeExactly;++      childCrossSize += marginCross;+    } else if (+        !YGFloatIsUndefined(availableInnerCrossDim) &&+        !YGNodeIsStyleDimDefined(+            currentRelativeChild, crossAxis, availableInnerCrossDim) &&+        measureModeCrossDim == YGMeasureModeExactly &&+        !(isNodeFlexWrap && flexBasisOverflows) &&+        YGNodeAlignItem(node, currentRelativeChild) == YGAlignStretch &&+        currentRelativeChild->marginLeadingValue(crossAxis).unit !=+            YGUnitAuto &&+        currentRelativeChild->marginTrailingValue(crossAxis).unit !=+            YGUnitAuto) {+      childCrossSize = availableInnerCrossDim;+      childCrossMeasureMode = YGMeasureModeExactly;+    } else if (!YGNodeIsStyleDimDefined(+                   currentRelativeChild, crossAxis, availableInnerCrossDim)) {+      childCrossSize = availableInnerCrossDim;+      childCrossMeasureMode = YGFloatIsUndefined(childCrossSize)+          ? YGMeasureModeUndefined+          : YGMeasureModeAtMost;+    } else {+      childCrossSize =+          YGUnwrapFloatOptional(YGResolveValue(+              currentRelativeChild->getResolvedDimension(dim[crossAxis]),+              availableInnerCrossDim)) ++          marginCross;+      const bool isLoosePercentageMeasurement =+          currentRelativeChild->getResolvedDimension(dim[crossAxis]).unit ==+              YGUnitPercent &&+          measureModeCrossDim != YGMeasureModeExactly;+      childCrossMeasureMode =+          YGFloatIsUndefined(childCrossSize) || isLoosePercentageMeasurement+          ? YGMeasureModeUndefined+          : YGMeasureModeExactly;+    }++    YGConstrainMaxSizeForMode(+        currentRelativeChild,+        mainAxis,+        availableInnerMainDim,+        availableInnerWidth,+        &childMainMeasureMode,+        &childMainSize);+    YGConstrainMaxSizeForMode(+        currentRelativeChild,+        crossAxis,+        availableInnerCrossDim,+        availableInnerWidth,+        &childCrossMeasureMode,+        &childCrossSize);++    const bool requiresStretchLayout =+        !YGNodeIsStyleDimDefined(+            currentRelativeChild, crossAxis, availableInnerCrossDim) &&+        YGNodeAlignItem(node, currentRelativeChild) == YGAlignStretch &&+        currentRelativeChild->marginLeadingValue(crossAxis).unit !=+            YGUnitAuto &&+        currentRelativeChild->marginTrailingValue(crossAxis).unit != YGUnitAuto;++    const float childWidth = isMainAxisRow ? childMainSize : childCrossSize;+    const float childHeight = !isMainAxisRow ? childMainSize : childCrossSize;++    const YGMeasureMode childWidthMeasureMode =+        isMainAxisRow ? childMainMeasureMode : childCrossMeasureMode;+    const YGMeasureMode childHeightMeasureMode =+        !isMainAxisRow ? childMainMeasureMode : childCrossMeasureMode;++    // Recursively call the layout algorithm for this child with the updated+    // main size.+    YGLayoutNodeInternal(+        currentRelativeChild,+        childWidth,+        childHeight,+        node->getLayout().direction,+        childWidthMeasureMode,+        childHeightMeasureMode,+        availableInnerWidth,+        availableInnerHeight,+        performLayout && !requiresStretchLayout,+        "flex",+        config);+    node->setLayoutHadOverflow(+        node->getLayout().hadOverflow |+        currentRelativeChild->getLayout().hadOverflow);+  }+  return deltaFreeSpace;+}++// It distributes the free space to the flexible items.For those flexible items+// whose min and max constraints are triggered, those flex item's clamped size+// is removed from the remaingfreespace.+static void YGDistributeFreeSpaceFirstPass(+    YGCollectFlexItemsRowValues& collectedFlexItemsValues,+    const YGFlexDirection mainAxis,+    const float mainAxisownerSize,+    const float availableInnerMainDim,+    const float availableInnerWidth) {+  float flexShrinkScaledFactor = 0;+  float flexGrowFactor = 0;+  float baseMainSize = 0;+  float boundMainSize = 0;+  float deltaFreeSpace = 0;++  for (auto currentRelativeChild : collectedFlexItemsValues.relativeChildren) {+    float childFlexBasis = YGUnwrapFloatOptional(YGNodeBoundAxisWithinMinAndMax(+        currentRelativeChild,+        mainAxis,+        YGUnwrapFloatOptional(+            currentRelativeChild->getLayout().computedFlexBasis),+        mainAxisownerSize));++    if (collectedFlexItemsValues.remainingFreeSpace < 0) {+      flexShrinkScaledFactor =+          -currentRelativeChild->resolveFlexShrink() * childFlexBasis;++      // Is this child able to shrink?+      if (!YGFloatIsUndefined(flexShrinkScaledFactor) &&+          flexShrinkScaledFactor != 0) {+        baseMainSize = childFlexBasis ++            collectedFlexItemsValues.remainingFreeSpace /+                collectedFlexItemsValues.totalFlexShrinkScaledFactors *+                flexShrinkScaledFactor;+        boundMainSize = YGNodeBoundAxis(+            currentRelativeChild,+            mainAxis,+            baseMainSize,+            availableInnerMainDim,+            availableInnerWidth);+        if (!YGFloatIsUndefined(baseMainSize) &&+            !YGFloatIsUndefined(boundMainSize) &&+            baseMainSize != boundMainSize) {+          // By excluding this item's size and flex factor from remaining,+          // this item's+          // min/max constraints should also trigger in the second pass+          // resulting in the+          // item's size calculation being identical in the first and second+          // passes.+          deltaFreeSpace += boundMainSize - childFlexBasis;+          collectedFlexItemsValues.totalFlexShrinkScaledFactors -=+              flexShrinkScaledFactor;+        }+      }+    } else if (+        !YGFloatIsUndefined(collectedFlexItemsValues.remainingFreeSpace) &&+        collectedFlexItemsValues.remainingFreeSpace > 0) {+      flexGrowFactor = currentRelativeChild->resolveFlexGrow();++      // Is this child able to grow?+      if (!YGFloatIsUndefined(flexGrowFactor) && flexGrowFactor != 0) {+        baseMainSize = childFlexBasis ++            collectedFlexItemsValues.remainingFreeSpace /+                collectedFlexItemsValues.totalFlexGrowFactors * flexGrowFactor;+        boundMainSize = YGNodeBoundAxis(+            currentRelativeChild,+            mainAxis,+            baseMainSize,+            availableInnerMainDim,+            availableInnerWidth);++        if (!YGFloatIsUndefined(baseMainSize) &&+            !YGFloatIsUndefined(boundMainSize) &&+            baseMainSize != boundMainSize) {+          // By excluding this item's size and flex factor from remaining,+          // this item's+          // min/max constraints should also trigger in the second pass+          // resulting in the+          // item's size calculation being identical in the first and second+          // passes.+          deltaFreeSpace += boundMainSize - childFlexBasis;+          collectedFlexItemsValues.totalFlexGrowFactors -= flexGrowFactor;+        }+      }+    }+  }+  collectedFlexItemsValues.remainingFreeSpace -= deltaFreeSpace;+}++// Do two passes over the flex items to figure out how to distribute the+// remaining space.+// The first pass finds the items whose min/max constraints trigger,+// freezes them at those+// sizes, and excludes those sizes from the remaining space. The second+// pass sets the size+// of each flexible item. It distributes the remaining space amongst the+// items whose min/max+// constraints didn't trigger in pass 1. For the other items, it sets+// their sizes by forcing+// their min/max constraints to trigger again.+//+// This two pass approach for resolving min/max constraints deviates from+// the spec. The+// spec (https://www.w3.org/TR/YG-flexbox-1/#resolve-flexible-lengths)+// describes a process+// that needs to be repeated a variable number of times. The algorithm+// implemented here+// won't handle all cases but it was simpler to implement and it mitigates+// performance+// concerns because we know exactly how many passes it'll do.+//+// At the end of this function the child nodes would have the proper size+// assigned to them.+//+static void YGResolveFlexibleLength(+    const YGNodeRef node,+    YGCollectFlexItemsRowValues& collectedFlexItemsValues,+    const YGFlexDirection mainAxis,+    const YGFlexDirection crossAxis,+    const float mainAxisownerSize,+    const float availableInnerMainDim,+    const float availableInnerCrossDim,+    const float availableInnerWidth,+    const float availableInnerHeight,+    const bool flexBasisOverflows,+    const YGMeasureMode measureModeCrossDim,+    const bool performLayout,+    const YGConfigRef config) {+  const float originalFreeSpace = collectedFlexItemsValues.remainingFreeSpace;+  // First pass: detect the flex items whose min/max constraints trigger+  YGDistributeFreeSpaceFirstPass(+      collectedFlexItemsValues,+      mainAxis,+      mainAxisownerSize,+      availableInnerMainDim,+      availableInnerWidth);++  // Second pass: resolve the sizes of the flexible items+  const float distributedFreeSpace = YGDistributeFreeSpaceSecondPass(+      collectedFlexItemsValues,+      node,+      mainAxis,+      crossAxis,+      mainAxisownerSize,+      availableInnerMainDim,+      availableInnerCrossDim,+      availableInnerWidth,+      availableInnerHeight,+      flexBasisOverflows,+      measureModeCrossDim,+      performLayout,+      config);++  collectedFlexItemsValues.remainingFreeSpace =+      originalFreeSpace - distributedFreeSpace;+}++static void YGJustifyMainAxis(+    const YGNodeRef node,+    YGCollectFlexItemsRowValues& collectedFlexItemsValues,+    const uint32_t& startOfLineIndex,+    const YGFlexDirection& mainAxis,+    const YGFlexDirection& crossAxis,+    const YGMeasureMode& measureModeMainDim,+    const YGMeasureMode& measureModeCrossDim,+    const float& mainAxisownerSize,+    const float& ownerWidth,+    const float& availableInnerMainDim,+    const float& availableInnerCrossDim,+    const float& availableInnerWidth,+    const bool& performLayout) {+  const YGStyle& style = node->getStyle();+  const float leadingPaddingAndBorderMain = YGUnwrapFloatOptional(+      node->getLeadingPaddingAndBorder(mainAxis, ownerWidth));+  const float trailingPaddingAndBorderMain = YGUnwrapFloatOptional(+      node->getTrailingPaddingAndBorder(mainAxis, ownerWidth));+  // If we are using "at most" rules in the main axis, make sure that+  // remainingFreeSpace is 0 when min main dimension is not given+  if (measureModeMainDim == YGMeasureModeAtMost &&+      collectedFlexItemsValues.remainingFreeSpace > 0) {+    if (style.minDimensions[dim[mainAxis]].unit != YGUnitUndefined &&+        !YGResolveValue(style.minDimensions[dim[mainAxis]], mainAxisownerSize)+             .isUndefined()) {+      // This condition makes sure that if the size of main dimension(after+      // considering child nodes main dim, leading and trailing padding etc)+      // falls below min dimension, then the remainingFreeSpace is reassigned+      // considering the min dimension++      // `minAvailableMainDim` denotes minimum available space in which child+      // can be laid out, it will exclude space consumed by padding and border.+      const float minAvailableMainDim =+          YGUnwrapFloatOptional(YGResolveValue(+              style.minDimensions[dim[mainAxis]], mainAxisownerSize)) -+          leadingPaddingAndBorderMain - trailingPaddingAndBorderMain;+      const float occupiedSpaceByChildNodes =+          availableInnerMainDim - collectedFlexItemsValues.remainingFreeSpace;+      collectedFlexItemsValues.remainingFreeSpace =+          YGFloatMax(0, minAvailableMainDim - occupiedSpaceByChildNodes);+    } else {+      collectedFlexItemsValues.remainingFreeSpace = 0;+    }+  }++  int numberOfAutoMarginsOnCurrentLine = 0;+  for (uint32_t i = startOfLineIndex;+       i < collectedFlexItemsValues.endOfLineIndex;+       i++) {+    const YGNodeRef child = node->getChild(i);+    if (child->getStyle().positionType == YGPositionTypeRelative) {+      if (child->marginLeadingValue(mainAxis).unit == YGUnitAuto) {+        numberOfAutoMarginsOnCurrentLine++;+      }+      if (child->marginTrailingValue(mainAxis).unit == YGUnitAuto) {+        numberOfAutoMarginsOnCurrentLine++;+      }+    }+  }++  // In order to position the elements in the main axis, we have two+  // controls. The space between the beginning and the first element+  // and the space between each two elements.+  float leadingMainDim = 0;+  float betweenMainDim = 0;+  const YGJustify justifyContent = node->getStyle().justifyContent;++  if (numberOfAutoMarginsOnCurrentLine == 0) {+    switch (justifyContent) {+      case YGJustifyCenter:+        leadingMainDim = collectedFlexItemsValues.remainingFreeSpace / 2;+        break;+      case YGJustifyFlexEnd:+        leadingMainDim = collectedFlexItemsValues.remainingFreeSpace;+        break;+      case YGJustifySpaceBetween:+        if (collectedFlexItemsValues.itemsOnLine > 1) {+          betweenMainDim =+              YGFloatMax(collectedFlexItemsValues.remainingFreeSpace, 0) /+              (collectedFlexItemsValues.itemsOnLine - 1);+        } else {+          betweenMainDim = 0;+        }+        break;+      case YGJustifySpaceEvenly:+        // Space is distributed evenly across all elements+        betweenMainDim = collectedFlexItemsValues.remainingFreeSpace /+            (collectedFlexItemsValues.itemsOnLine + 1);+        leadingMainDim = betweenMainDim;+        break;+      case YGJustifySpaceAround:+        // Space on the edges is half of the space between elements+        betweenMainDim = collectedFlexItemsValues.remainingFreeSpace /+            collectedFlexItemsValues.itemsOnLine;+        leadingMainDim = betweenMainDim / 2;+        break;+      case YGJustifyFlexStart:+        break;+    }+  }++  collectedFlexItemsValues.mainDim =+      leadingPaddingAndBorderMain + leadingMainDim;+  collectedFlexItemsValues.crossDim = 0;++  float maxAscentForCurrentLine = 0;+  float maxDescentForCurrentLine = 0;+  bool isNodeBaselineLayout = YGIsBaselineLayout(node);+  for (uint32_t i = startOfLineIndex;+       i < collectedFlexItemsValues.endOfLineIndex;+       i++) {+    const YGNodeRef child = node->getChild(i);+    const YGStyle& childStyle = child->getStyle();+    const YGLayout childLayout = child->getLayout();+    if (childStyle.display == YGDisplayNone) {+      continue;+    }+    if (childStyle.positionType == YGPositionTypeAbsolute &&+        child->isLeadingPositionDefined(mainAxis)) {+      if (performLayout) {+        // In case the child is position absolute and has left/top being+        // defined, we override the position to whatever the user said+        // (and margin/border).+        child->setLayoutPosition(+            YGUnwrapFloatOptional(+                child->getLeadingPosition(mainAxis, availableInnerMainDim)) ++                node->getLeadingBorder(mainAxis) ++                YGUnwrapFloatOptional(+                    child->getLeadingMargin(mainAxis, availableInnerWidth)),+            pos[mainAxis]);+      }+    } else {+      // Now that we placed the element, we need to update the variables.+      // We need to do that only for relative elements. Absolute elements+      // do not take part in that phase.+      if (childStyle.positionType == YGPositionTypeRelative) {+        if (child->marginLeadingValue(mainAxis).unit == YGUnitAuto) {+          collectedFlexItemsValues.mainDim +=+              collectedFlexItemsValues.remainingFreeSpace /+              numberOfAutoMarginsOnCurrentLine;+        }++        if (performLayout) {+          child->setLayoutPosition(+              childLayout.position[pos[mainAxis]] ++                  collectedFlexItemsValues.mainDim,+              pos[mainAxis]);+        }++        if (child->marginTrailingValue(mainAxis).unit == YGUnitAuto) {+          collectedFlexItemsValues.mainDim +=+              collectedFlexItemsValues.remainingFreeSpace /+              numberOfAutoMarginsOnCurrentLine;+        }+        bool canSkipFlex =+            !performLayout && measureModeCrossDim == YGMeasureModeExactly;+        if (canSkipFlex) {+          // If we skipped the flex step, then we can't rely on the+          // measuredDims because+          // they weren't computed. This means we can't call+          // YGNodeDimWithMargin.+          collectedFlexItemsValues.mainDim += betweenMainDim ++              YGUnwrapFloatOptional(child->getMarginForAxis(+                  mainAxis, availableInnerWidth)) ++              YGUnwrapFloatOptional(childLayout.computedFlexBasis);+          collectedFlexItemsValues.crossDim = availableInnerCrossDim;+        } else {+          // The main dimension is the sum of all the elements dimension plus+          // the spacing.+          collectedFlexItemsValues.mainDim += betweenMainDim ++              YGNodeDimWithMargin(child, mainAxis, availableInnerWidth);++          if (isNodeBaselineLayout) {+            // If the child is baseline aligned then the cross dimension is+            // calculated by adding maxAscent and maxDescent from the baseline.+            const float ascent = YGBaseline(child) ++                YGUnwrapFloatOptional(child->getLeadingMargin(+                    YGFlexDirectionColumn, availableInnerWidth));+            const float descent =+                child->getLayout().measuredDimensions[YGDimensionHeight] ++                YGUnwrapFloatOptional(child->getMarginForAxis(+                    YGFlexDirectionColumn, availableInnerWidth)) -+                ascent;++            maxAscentForCurrentLine =+                YGFloatMax(maxAscentForCurrentLine, ascent);+            maxDescentForCurrentLine =+                YGFloatMax(maxDescentForCurrentLine, descent);+          } else {+            // The cross dimension is the max of the elements dimension since+            // there can only be one element in that cross dimension in the case+            // when the items are not baseline aligned+            collectedFlexItemsValues.crossDim = YGFloatMax(+                collectedFlexItemsValues.crossDim,+                YGNodeDimWithMargin(child, crossAxis, availableInnerWidth));+          }+        }+      } else if (performLayout) {+        child->setLayoutPosition(+            childLayout.position[pos[mainAxis]] ++                node->getLeadingBorder(mainAxis) + leadingMainDim,+            pos[mainAxis]);+      }+    }+  }+  collectedFlexItemsValues.mainDim += trailingPaddingAndBorderMain;++  if (isNodeBaselineLayout) {+    collectedFlexItemsValues.crossDim =+        maxAscentForCurrentLine + maxDescentForCurrentLine;+  }+}++//+// This is the main routine that implements a subset of the flexbox layout+// algorithm+// described in the W3C YG documentation: https://www.w3.org/TR/YG3-flexbox/.+//+// Limitations of this algorithm, compared to the full standard:+//  * Display property is always assumed to be 'flex' except for Text nodes,+//  which+//    are assumed to be 'inline-flex'.+//  * The 'zIndex' property (or any form of z ordering) is not supported. Nodes+//  are+//    stacked in document order.+//  * The 'order' property is not supported. The order of flex items is always+//  defined+//    by document order.+//  * The 'visibility' property is always assumed to be 'visible'. Values of+//  'collapse'+//    and 'hidden' are not supported.+//  * There is no support for forced breaks.+//  * It does not support vertical inline directions (top-to-bottom or+//  bottom-to-top text).+//+// Deviations from standard:+//  * Section 4.5 of the spec indicates that all flex items have a default+//  minimum+//    main size. For text blocks, for example, this is the width of the widest+//    word.+//    Calculating the minimum width is expensive, so we forego it and assume a+//    default+//    minimum main size of 0.+//  * Min/Max sizes in the main axis are not honored when resolving flexible+//  lengths.+//  * The spec indicates that the default value for 'flexDirection' is 'row',+//  but+//    the algorithm below assumes a default of 'column'.+//+// Input parameters:+//    - node: current node to be sized and layed out+//    - availableWidth & availableHeight: available size to be used for sizing+//    the node+//      or YGUndefined if the size is not available; interpretation depends on+//      layout+//      flags+//    - ownerDirection: the inline (text) direction within the owner+//    (left-to-right or+//      right-to-left)+//    - widthMeasureMode: indicates the sizing rules for the width (see below+//    for explanation)+//    - heightMeasureMode: indicates the sizing rules for the height (see below+//    for explanation)+//    - performLayout: specifies whether the caller is interested in just the+//    dimensions+//      of the node or it requires the entire node and its subtree to be layed+//      out+//      (with final positions)+//+// Details:+//    This routine is called recursively to lay out subtrees of flexbox+//    elements. It uses the+//    information in node.style, which is treated as a read-only input. It is+//    responsible for+//    setting the layout.direction and layout.measuredDimensions fields for the+//    input node as well+//    as the layout.position and layout.lineIndex fields for its child nodes.+//    The+//    layout.measuredDimensions field includes any border or padding for the+//    node but does+//    not include margins.+//+//    The spec describes four different layout modes: "fill available", "max+//    content", "min+//    content",+//    and "fit content". Of these, we don't use "min content" because we don't+//    support default+//    minimum main sizes (see above for details). Each of our measure modes maps+//    to a layout mode+//    from the spec (https://www.w3.org/TR/YG3-sizing/#terms):+//      - YGMeasureModeUndefined: max content+//      - YGMeasureModeExactly: fill available+//      - YGMeasureModeAtMost: fit content+//+//    When calling YGNodelayoutImpl and YGLayoutNodeInternal, if the caller+//    passes an available size of undefined then it must also pass a measure+//    mode of YGMeasureModeUndefined in that dimension.+//+static void YGNodelayoutImpl(+    const YGNodeRef node,+    const float availableWidth,+    const float availableHeight,+    const YGDirection ownerDirection,+    const YGMeasureMode widthMeasureMode,+    const YGMeasureMode heightMeasureMode,+    const float ownerWidth,+    const float ownerHeight,+    const bool performLayout,+    const YGConfigRef config) {+  YGAssertWithNode(+      node,+      YGFloatIsUndefined(availableWidth)+          ? widthMeasureMode == YGMeasureModeUndefined+          : true,+      "availableWidth is indefinite so widthMeasureMode must be "+      "YGMeasureModeUndefined");+  YGAssertWithNode(+      node,+      YGFloatIsUndefined(availableHeight)+          ? heightMeasureMode == YGMeasureModeUndefined+          : true,+      "availableHeight is indefinite so heightMeasureMode must be "+      "YGMeasureModeUndefined");++  // Set the resolved resolution in the node's layout.+  const YGDirection direction = node->resolveDirection(ownerDirection);+  node->setLayoutDirection(direction);++  const YGFlexDirection flexRowDirection =+      YGResolveFlexDirection(YGFlexDirectionRow, direction);+  const YGFlexDirection flexColumnDirection =+      YGResolveFlexDirection(YGFlexDirectionColumn, direction);++  node->setLayoutMargin(+      YGUnwrapFloatOptional(+          node->getLeadingMargin(flexRowDirection, ownerWidth)),+      YGEdgeStart);+  node->setLayoutMargin(+      YGUnwrapFloatOptional(+          node->getTrailingMargin(flexRowDirection, ownerWidth)),+      YGEdgeEnd);+  node->setLayoutMargin(+      YGUnwrapFloatOptional(+          node->getLeadingMargin(flexColumnDirection, ownerWidth)),+      YGEdgeTop);+  node->setLayoutMargin(+      YGUnwrapFloatOptional(+          node->getTrailingMargin(flexColumnDirection, ownerWidth)),+      YGEdgeBottom);++  node->setLayoutBorder(node->getLeadingBorder(flexRowDirection), YGEdgeStart);+  node->setLayoutBorder(node->getTrailingBorder(flexRowDirection), YGEdgeEnd);+  node->setLayoutBorder(node->getLeadingBorder(flexColumnDirection), YGEdgeTop);+  node->setLayoutBorder(+      node->getTrailingBorder(flexColumnDirection), YGEdgeBottom);++  node->setLayoutPadding(+      YGUnwrapFloatOptional(+          node->getLeadingPadding(flexRowDirection, ownerWidth)),+      YGEdgeStart);+  node->setLayoutPadding(+      YGUnwrapFloatOptional(+          node->getTrailingPadding(flexRowDirection, ownerWidth)),+      YGEdgeEnd);+  node->setLayoutPadding(+      YGUnwrapFloatOptional(+          node->getLeadingPadding(flexColumnDirection, ownerWidth)),+      YGEdgeTop);+  node->setLayoutPadding(+      YGUnwrapFloatOptional(+          node->getTrailingPadding(flexColumnDirection, ownerWidth)),+      YGEdgeBottom);++  if (node->getMeasure() != nullptr) {+    YGNodeWithMeasureFuncSetMeasuredDimensions(+        node,+        availableWidth,+        availableHeight,+        widthMeasureMode,+        heightMeasureMode,+        ownerWidth,+        ownerHeight);+    return;+  }++  const uint32_t childCount = YGNodeGetChildCount(node);+  if (childCount == 0) {+    YGNodeEmptyContainerSetMeasuredDimensions(+        node,+        availableWidth,+        availableHeight,+        widthMeasureMode,+        heightMeasureMode,+        ownerWidth,+        ownerHeight);+    return;+  }++  // If we're not being asked to perform a full layout we can skip the algorithm+  // if we already know the size+  if (!performLayout &&+      YGNodeFixedSizeSetMeasuredDimensions(+          node,+          availableWidth,+          availableHeight,+          widthMeasureMode,+          heightMeasureMode,+          ownerWidth,+          ownerHeight)) {+    return;+  }++  // At this point we know we're going to perform work. Ensure that each child+  // has a mutable copy.+  node->cloneChildrenIfNeeded();+  // Reset layout flags, as they could have changed.+  node->setLayoutHadOverflow(false);++  // STEP 1: CALCULATE VALUES FOR REMAINDER OF ALGORITHM+  const YGFlexDirection mainAxis =+      YGResolveFlexDirection(node->getStyle().flexDirection, direction);+  const YGFlexDirection crossAxis = YGFlexDirectionCross(mainAxis, direction);+  const bool isMainAxisRow = YGFlexDirectionIsRow(mainAxis);+  const bool isNodeFlexWrap = node->getStyle().flexWrap != YGWrapNoWrap;++  const float mainAxisownerSize = isMainAxisRow ? ownerWidth : ownerHeight;+  const float crossAxisownerSize = isMainAxisRow ? ownerHeight : ownerWidth;++  const float leadingPaddingAndBorderCross = YGUnwrapFloatOptional(+      node->getLeadingPaddingAndBorder(crossAxis, ownerWidth));+  const float paddingAndBorderAxisMain =+      YGNodePaddingAndBorderForAxis(node, mainAxis, ownerWidth);+  const float paddingAndBorderAxisCross =+      YGNodePaddingAndBorderForAxis(node, crossAxis, ownerWidth);++  YGMeasureMode measureModeMainDim =+      isMainAxisRow ? widthMeasureMode : heightMeasureMode;+  YGMeasureMode measureModeCrossDim =+      isMainAxisRow ? heightMeasureMode : widthMeasureMode;++  const float paddingAndBorderAxisRow =+      isMainAxisRow ? paddingAndBorderAxisMain : paddingAndBorderAxisCross;+  const float paddingAndBorderAxisColumn =+      isMainAxisRow ? paddingAndBorderAxisCross : paddingAndBorderAxisMain;++  const float marginAxisRow = YGUnwrapFloatOptional(+      node->getMarginForAxis(YGFlexDirectionRow, ownerWidth));+  const float marginAxisColumn = YGUnwrapFloatOptional(+      node->getMarginForAxis(YGFlexDirectionColumn, ownerWidth));++  const float minInnerWidth =+      YGUnwrapFloatOptional(YGResolveValue(+          node->getStyle().minDimensions[YGDimensionWidth], ownerWidth)) -+      paddingAndBorderAxisRow;+  const float maxInnerWidth =+      YGUnwrapFloatOptional(YGResolveValue(+          node->getStyle().maxDimensions[YGDimensionWidth], ownerWidth)) -+      paddingAndBorderAxisRow;+  const float minInnerHeight =+      YGUnwrapFloatOptional(YGResolveValue(+          node->getStyle().minDimensions[YGDimensionHeight], ownerHeight)) -+      paddingAndBorderAxisColumn;+  const float maxInnerHeight =+      YGUnwrapFloatOptional(YGResolveValue(+          node->getStyle().maxDimensions[YGDimensionHeight], ownerHeight)) -+      paddingAndBorderAxisColumn;++  const float minInnerMainDim = isMainAxisRow ? minInnerWidth : minInnerHeight;+  const float maxInnerMainDim = isMainAxisRow ? maxInnerWidth : maxInnerHeight;++  // STEP 2: DETERMINE AVAILABLE SIZE IN MAIN AND CROSS DIRECTIONS++  float availableInnerWidth = YGNodeCalculateAvailableInnerDim(+      node, YGFlexDirectionRow, availableWidth, ownerWidth);+  float availableInnerHeight = YGNodeCalculateAvailableInnerDim(+      node, YGFlexDirectionColumn, availableHeight, ownerHeight);++  float availableInnerMainDim =+      isMainAxisRow ? availableInnerWidth : availableInnerHeight;+  const float availableInnerCrossDim =+      isMainAxisRow ? availableInnerHeight : availableInnerWidth;++  float totalOuterFlexBasis = 0;++  // STEP 3: DETERMINE FLEX BASIS FOR EACH ITEM++  YGNodeComputeFlexBasisForChildren(+      node,+      availableInnerWidth,+      availableInnerHeight,+      widthMeasureMode,+      heightMeasureMode,+      direction,+      mainAxis,+      config,+      performLayout,+      totalOuterFlexBasis);++  const bool flexBasisOverflows = measureModeMainDim == YGMeasureModeUndefined+      ? false+      : totalOuterFlexBasis > availableInnerMainDim;+  if (isNodeFlexWrap && flexBasisOverflows &&+      measureModeMainDim == YGMeasureModeAtMost) {+    measureModeMainDim = YGMeasureModeExactly;+  }+  // STEP 4: COLLECT FLEX ITEMS INTO FLEX LINES++  // Indexes of children that represent the first and last items in the line.+  uint32_t startOfLineIndex = 0;+  uint32_t endOfLineIndex = 0;++  // Number of lines.+  uint32_t lineCount = 0;++  // Accumulated cross dimensions of all lines so far.+  float totalLineCrossDim = 0;++  // Max main dimension of all the lines.+  float maxLineMainDim = 0;+  YGCollectFlexItemsRowValues collectedFlexItemsValues;+  for (; endOfLineIndex < childCount;+       lineCount++, startOfLineIndex = endOfLineIndex) {+    collectedFlexItemsValues = YGCalculateCollectFlexItemsRowValues(+        node,+        ownerDirection,+        mainAxisownerSize,+        availableInnerWidth,+        availableInnerMainDim,+        startOfLineIndex,+        lineCount);+    endOfLineIndex = collectedFlexItemsValues.endOfLineIndex;++    // If we don't need to measure the cross axis, we can skip the entire flex+    // step.+    const bool canSkipFlex =+        !performLayout && measureModeCrossDim == YGMeasureModeExactly;++    // STEP 5: RESOLVING FLEXIBLE LENGTHS ON MAIN AXIS+    // Calculate the remaining available space that needs to be allocated.+    // If the main dimension size isn't known, it is computed based on+    // the line length, so there's no more space left to distribute.++    bool sizeBasedOnContent = false;+    // If we don't measure with exact main dimension we want to ensure we don't+    // violate min and max+    if (measureModeMainDim != YGMeasureModeExactly) {+      if (!YGFloatIsUndefined(minInnerMainDim) &&+          collectedFlexItemsValues.sizeConsumedOnCurrentLine <+              minInnerMainDim) {+        availableInnerMainDim = minInnerMainDim;+      } else if (+          !YGFloatIsUndefined(maxInnerMainDim) &&+          collectedFlexItemsValues.sizeConsumedOnCurrentLine >+              maxInnerMainDim) {+        availableInnerMainDim = maxInnerMainDim;+      } else {+        if (!node->getConfig()->useLegacyStretchBehaviour &&+            ((YGFloatIsUndefined(+                  collectedFlexItemsValues.totalFlexGrowFactors) &&+              collectedFlexItemsValues.totalFlexGrowFactors == 0) ||+             (YGFloatIsUndefined(node->resolveFlexGrow()) &&+              node->resolveFlexGrow() == 0))) {+          // If we don't have any children to flex or we can't flex the node+          // itself, space we've used is all space we need. Root node also+          // should be shrunk to minimum+          availableInnerMainDim =+              collectedFlexItemsValues.sizeConsumedOnCurrentLine;+        }++        if (node->getConfig()->useLegacyStretchBehaviour) {+          node->setLayoutDidUseLegacyFlag(true);+        }+        sizeBasedOnContent = !node->getConfig()->useLegacyStretchBehaviour;+      }+    }++    if (!sizeBasedOnContent && !YGFloatIsUndefined(availableInnerMainDim)) {+      collectedFlexItemsValues.remainingFreeSpace = availableInnerMainDim -+          collectedFlexItemsValues.sizeConsumedOnCurrentLine;+    } else if (collectedFlexItemsValues.sizeConsumedOnCurrentLine < 0) {+      // availableInnerMainDim is indefinite which means the node is being sized+      // based on its content. sizeConsumedOnCurrentLine is negative which means+      // the node will allocate 0 points for its content. Consequently,+      // remainingFreeSpace is 0 - sizeConsumedOnCurrentLine.+      collectedFlexItemsValues.remainingFreeSpace =+          -collectedFlexItemsValues.sizeConsumedOnCurrentLine;+    }++    if (!canSkipFlex) {+      YGResolveFlexibleLength(+          node,+          collectedFlexItemsValues,+          mainAxis,+          crossAxis,+          mainAxisownerSize,+          availableInnerMainDim,+          availableInnerCrossDim,+          availableInnerWidth,+          availableInnerHeight,+          flexBasisOverflows,+          measureModeCrossDim,+          performLayout,+          config);+    }++    node->setLayoutHadOverflow(+        node->getLayout().hadOverflow |+        (collectedFlexItemsValues.remainingFreeSpace < 0));++    // STEP 6: MAIN-AXIS JUSTIFICATION & CROSS-AXIS SIZE DETERMINATION++    // At this point, all the children have their dimensions set in the main+    // axis.+    // Their dimensions are also set in the cross axis with the exception of+    // items+    // that are aligned "stretch". We need to compute these stretch values and+    // set the final positions.++    YGJustifyMainAxis(+        node,+        collectedFlexItemsValues,+        startOfLineIndex,+        mainAxis,+        crossAxis,+        measureModeMainDim,+        measureModeCrossDim,+        mainAxisownerSize,+        ownerWidth,+        availableInnerMainDim,+        availableInnerCrossDim,+        availableInnerWidth,+        performLayout);++    float containerCrossAxis = availableInnerCrossDim;+    if (measureModeCrossDim == YGMeasureModeUndefined ||+        measureModeCrossDim == YGMeasureModeAtMost) {+      // Compute the cross axis from the max cross dimension of the children.+      containerCrossAxis =+          YGNodeBoundAxis(+              node,+              crossAxis,+              collectedFlexItemsValues.crossDim + paddingAndBorderAxisCross,+              crossAxisownerSize,+              ownerWidth) -+          paddingAndBorderAxisCross;+    }++    // If there's no flex wrap, the cross dimension is defined by the container.+    if (!isNodeFlexWrap && measureModeCrossDim == YGMeasureModeExactly) {+      collectedFlexItemsValues.crossDim = availableInnerCrossDim;+    }++    // Clamp to the min/max size specified on the container.+    collectedFlexItemsValues.crossDim =+        YGNodeBoundAxis(+            node,+            crossAxis,+            collectedFlexItemsValues.crossDim + paddingAndBorderAxisCross,+            crossAxisownerSize,+            ownerWidth) -+        paddingAndBorderAxisCross;++    // STEP 7: CROSS-AXIS ALIGNMENT+    // We can skip child alignment if we're just measuring the container.+    if (performLayout) {+      for (uint32_t i = startOfLineIndex; i < endOfLineIndex; i++) {+        const YGNodeRef child = node->getChild(i);+        if (child->getStyle().display == YGDisplayNone) {+          continue;+        }+        if (child->getStyle().positionType == YGPositionTypeAbsolute) {+          // If the child is absolutely positioned and has a+          // top/left/bottom/right set, override+          // all the previously computed positions to set it correctly.+          const bool isChildLeadingPosDefined =+              child->isLeadingPositionDefined(crossAxis);+          if (isChildLeadingPosDefined) {+            child->setLayoutPosition(+                YGUnwrapFloatOptional(child->getLeadingPosition(+                    crossAxis, availableInnerCrossDim)) ++                    node->getLeadingBorder(crossAxis) ++                    YGUnwrapFloatOptional(child->getLeadingMargin(+                        crossAxis, availableInnerWidth)),+                pos[crossAxis]);+          }+          // If leading position is not defined or calculations result in Nan,+          // default to border + margin+          if (!isChildLeadingPosDefined ||+              YGFloatIsUndefined(child->getLayout().position[pos[crossAxis]])) {+            child->setLayoutPosition(+                node->getLeadingBorder(crossAxis) ++                    YGUnwrapFloatOptional(child->getLeadingMargin(+                        crossAxis, availableInnerWidth)),+                pos[crossAxis]);+          }+        } else {+          float leadingCrossDim = leadingPaddingAndBorderCross;++          // For a relative children, we're either using alignItems (owner) or+          // alignSelf (child) in order to determine the position in the cross+          // axis+          const YGAlign alignItem = YGNodeAlignItem(node, child);++          // If the child uses align stretch, we need to lay it out one more+          // time, this time+          // forcing the cross-axis size to be the computed cross size for the+          // current line.+          if (alignItem == YGAlignStretch &&+              child->marginLeadingValue(crossAxis).unit != YGUnitAuto &&+              child->marginTrailingValue(crossAxis).unit != YGUnitAuto) {+            // If the child defines a definite size for its cross axis, there's+            // no need to stretch.+            if (!YGNodeIsStyleDimDefined(+                    child, crossAxis, availableInnerCrossDim)) {+              float childMainSize =+                  child->getLayout().measuredDimensions[dim[mainAxis]];+              float childCrossSize =+                  !child->getStyle().aspectRatio.isUndefined()+                  ? ((YGUnwrapFloatOptional(child->getMarginForAxis(+                          crossAxis, availableInnerWidth)) ++                      (isMainAxisRow ? childMainSize /+                               child->getStyle().aspectRatio.getValue()+                                     : childMainSize *+                               child->getStyle().aspectRatio.getValue())))+                  : collectedFlexItemsValues.crossDim;++              childMainSize += YGUnwrapFloatOptional(+                  child->getMarginForAxis(mainAxis, availableInnerWidth));++              YGMeasureMode childMainMeasureMode = YGMeasureModeExactly;+              YGMeasureMode childCrossMeasureMode = YGMeasureModeExactly;+              YGConstrainMaxSizeForMode(+                  child,+                  mainAxis,+                  availableInnerMainDim,+                  availableInnerWidth,+                  &childMainMeasureMode,+                  &childMainSize);+              YGConstrainMaxSizeForMode(+                  child,+                  crossAxis,+                  availableInnerCrossDim,+                  availableInnerWidth,+                  &childCrossMeasureMode,+                  &childCrossSize);++              const float childWidth =+                  isMainAxisRow ? childMainSize : childCrossSize;+              const float childHeight =+                  !isMainAxisRow ? childMainSize : childCrossSize;++              const YGMeasureMode childWidthMeasureMode =+                  YGFloatIsUndefined(childWidth) ? YGMeasureModeUndefined+                                                 : YGMeasureModeExactly;+              const YGMeasureMode childHeightMeasureMode =+                  YGFloatIsUndefined(childHeight) ? YGMeasureModeUndefined+                                                  : YGMeasureModeExactly;++              YGLayoutNodeInternal(+                  child,+                  childWidth,+                  childHeight,+                  direction,+                  childWidthMeasureMode,+                  childHeightMeasureMode,+                  availableInnerWidth,+                  availableInnerHeight,+                  true,+                  "stretch",+                  config);+            }+          } else {+            const float remainingCrossDim = containerCrossAxis -+                YGNodeDimWithMargin(child, crossAxis, availableInnerWidth);++            if (child->marginLeadingValue(crossAxis).unit == YGUnitAuto &&+                child->marginTrailingValue(crossAxis).unit == YGUnitAuto) {+              leadingCrossDim += YGFloatMax(0.0f, remainingCrossDim / 2);+            } else if (+                child->marginTrailingValue(crossAxis).unit == YGUnitAuto) {+              // No-Op+            } else if (+                child->marginLeadingValue(crossAxis).unit == YGUnitAuto) {+              leadingCrossDim += YGFloatMax(0.0f, remainingCrossDim);+            } else if (alignItem == YGAlignFlexStart) {+              // No-Op+            } else if (alignItem == YGAlignCenter) {+              leadingCrossDim += remainingCrossDim / 2;+            } else {+              leadingCrossDim += remainingCrossDim;+            }+          }+          // And we apply the position+          child->setLayoutPosition(+              child->getLayout().position[pos[crossAxis]] + totalLineCrossDim ++                  leadingCrossDim,+              pos[crossAxis]);+        }+      }+    }++    totalLineCrossDim += collectedFlexItemsValues.crossDim;+    maxLineMainDim =+        YGFloatMax(maxLineMainDim, collectedFlexItemsValues.mainDim);+  }++  // STEP 8: MULTI-LINE CONTENT ALIGNMENT+  // currentLead stores the size of the cross dim+  if (performLayout && (lineCount > 1 || YGIsBaselineLayout(node))) {+    float crossDimLead = 0;+    float currentLead = leadingPaddingAndBorderCross;+    if (!YGFloatIsUndefined(availableInnerCrossDim)) {+      const float remainingAlignContentDim =+          availableInnerCrossDim - totalLineCrossDim;+      switch (node->getStyle().alignContent) {+        case YGAlignFlexEnd:+          currentLead += remainingAlignContentDim;+          break;+        case YGAlignCenter:+          currentLead += remainingAlignContentDim / 2;+          break;+        case YGAlignStretch:+          if (availableInnerCrossDim > totalLineCrossDim) {+            crossDimLead = remainingAlignContentDim / lineCount;+          }+          break;+        case YGAlignSpaceAround:+          if (availableInnerCrossDim > totalLineCrossDim) {+            currentLead += remainingAlignContentDim / (2 * lineCount);+            if (lineCount > 1) {+              crossDimLead = remainingAlignContentDim / lineCount;+            }+          } else {+            currentLead += remainingAlignContentDim / 2;+          }+          break;+        case YGAlignSpaceBetween:+          if (availableInnerCrossDim > totalLineCrossDim && lineCount > 1) {+            crossDimLead = remainingAlignContentDim / (lineCount - 1);+          }+          break;+        case YGAlignAuto:+        case YGAlignFlexStart:+        case YGAlignBaseline:+          break;+      }+    }+    uint32_t endIndex = 0;+    for (uint32_t i = 0; i < lineCount; i++) {+      const uint32_t startIndex = endIndex;+      uint32_t ii;++      // compute the line's height and find the endIndex+      float lineHeight = 0;+      float maxAscentForCurrentLine = 0;+      float maxDescentForCurrentLine = 0;+      for (ii = startIndex; ii < childCount; ii++) {+        const YGNodeRef child = node->getChild(ii);+        if (child->getStyle().display == YGDisplayNone) {+          continue;+        }+        if (child->getStyle().positionType == YGPositionTypeRelative) {+          if (child->getLineIndex() != i) {+            break;+          }+          if (YGNodeIsLayoutDimDefined(child, crossAxis)) {+            lineHeight = YGFloatMax(+                lineHeight,+                child->getLayout().measuredDimensions[dim[crossAxis]] ++                    YGUnwrapFloatOptional(child->getMarginForAxis(+                        crossAxis, availableInnerWidth)));+          }+          if (YGNodeAlignItem(node, child) == YGAlignBaseline) {+            const float ascent = YGBaseline(child) ++                YGUnwrapFloatOptional(child->getLeadingMargin(+                    YGFlexDirectionColumn, availableInnerWidth));+            const float descent =+                child->getLayout().measuredDimensions[YGDimensionHeight] ++                YGUnwrapFloatOptional(child->getMarginForAxis(+                    YGFlexDirectionColumn, availableInnerWidth)) -+                ascent;+            maxAscentForCurrentLine =+                YGFloatMax(maxAscentForCurrentLine, ascent);+            maxDescentForCurrentLine =+                YGFloatMax(maxDescentForCurrentLine, descent);+            lineHeight = YGFloatMax(+                lineHeight, maxAscentForCurrentLine + maxDescentForCurrentLine);+          }+        }+      }+      endIndex = ii;+      lineHeight += crossDimLead;++      if (performLayout) {+        for (ii = startIndex; ii < endIndex; ii++) {+          const YGNodeRef child = node->getChild(ii);+          if (child->getStyle().display == YGDisplayNone) {+            continue;+          }+          if (child->getStyle().positionType == YGPositionTypeRelative) {+            switch (YGNodeAlignItem(node, child)) {+              case YGAlignFlexStart: {+                child->setLayoutPosition(+                    currentLead ++                        YGUnwrapFloatOptional(child->getLeadingMargin(+                            crossAxis, availableInnerWidth)),+                    pos[crossAxis]);+                break;+              }+              case YGAlignFlexEnd: {+                child->setLayoutPosition(+                    currentLead + lineHeight -+                        YGUnwrapFloatOptional(child->getTrailingMargin(+                            crossAxis, availableInnerWidth)) -+                        child->getLayout().measuredDimensions[dim[crossAxis]],+                    pos[crossAxis]);+                break;+              }+              case YGAlignCenter: {+                float childHeight =+                    child->getLayout().measuredDimensions[dim[crossAxis]];++                child->setLayoutPosition(+                    currentLead + (lineHeight - childHeight) / 2,+                    pos[crossAxis]);+                break;+              }+              case YGAlignStretch: {+                child->setLayoutPosition(+                    currentLead ++                        YGUnwrapFloatOptional(child->getLeadingMargin(+                            crossAxis, availableInnerWidth)),+                    pos[crossAxis]);++                // Remeasure child with the line height as it as been only+                // measured with the owners height yet.+                if (!YGNodeIsStyleDimDefined(+                        child, crossAxis, availableInnerCrossDim)) {+                  const float childWidth = isMainAxisRow+                      ? (child->getLayout()+                             .measuredDimensions[YGDimensionWidth] ++                         YGUnwrapFloatOptional(child->getMarginForAxis(+                             mainAxis, availableInnerWidth)))+                      : lineHeight;++                  const float childHeight = !isMainAxisRow+                      ? (child->getLayout()+                             .measuredDimensions[YGDimensionHeight] ++                         YGUnwrapFloatOptional(child->getMarginForAxis(+                             crossAxis, availableInnerWidth)))+                      : lineHeight;++                  if (!(YGFloatsEqual(+                            childWidth,+                            child->getLayout()+                                .measuredDimensions[YGDimensionWidth]) &&+                        YGFloatsEqual(+                            childHeight,+                            child->getLayout()+                                .measuredDimensions[YGDimensionHeight]))) {+                    YGLayoutNodeInternal(+                        child,+                        childWidth,+                        childHeight,+                        direction,+                        YGMeasureModeExactly,+                        YGMeasureModeExactly,+                        availableInnerWidth,+                        availableInnerHeight,+                        true,+                        "multiline-stretch",+                        config);+                  }+                }+                break;+              }+              case YGAlignBaseline: {+                child->setLayoutPosition(+                    currentLead + maxAscentForCurrentLine - YGBaseline(child) ++                        YGUnwrapFloatOptional(child->getLeadingPosition(+                            YGFlexDirectionColumn, availableInnerCrossDim)),+                    YGEdgeTop);++                break;+              }+              case YGAlignAuto:+              case YGAlignSpaceBetween:+              case YGAlignSpaceAround:+                break;+            }+          }+        }+      }+      currentLead += lineHeight;+    }+  }++  // STEP 9: COMPUTING FINAL DIMENSIONS++  node->setLayoutMeasuredDimension(+      YGNodeBoundAxis(+          node,+          YGFlexDirectionRow,+          availableWidth - marginAxisRow,+          ownerWidth,+          ownerWidth),+      YGDimensionWidth);++  node->setLayoutMeasuredDimension(+      YGNodeBoundAxis(+          node,+          YGFlexDirectionColumn,+          availableHeight - marginAxisColumn,+          ownerHeight,+          ownerWidth),+      YGDimensionHeight);++  // If the user didn't specify a width or height for the node, set the+  // dimensions based on the children.+  if (measureModeMainDim == YGMeasureModeUndefined ||+      (node->getStyle().overflow != YGOverflowScroll &&+       measureModeMainDim == YGMeasureModeAtMost)) {+    // Clamp the size to the min/max size, if specified, and make sure it+    // doesn't go below the padding and border amount.+    node->setLayoutMeasuredDimension(+        YGNodeBoundAxis(+            node, mainAxis, maxLineMainDim, mainAxisownerSize, ownerWidth),+        dim[mainAxis]);++  } else if (+      measureModeMainDim == YGMeasureModeAtMost &&+      node->getStyle().overflow == YGOverflowScroll) {+    node->setLayoutMeasuredDimension(+        YGFloatMax(+            YGFloatMin(+                availableInnerMainDim + paddingAndBorderAxisMain,+                YGUnwrapFloatOptional(YGNodeBoundAxisWithinMinAndMax(+                    node, mainAxis, maxLineMainDim, mainAxisownerSize))),+            paddingAndBorderAxisMain),+        dim[mainAxis]);+  }++  if (measureModeCrossDim == YGMeasureModeUndefined ||+      (node->getStyle().overflow != YGOverflowScroll &&+       measureModeCrossDim == YGMeasureModeAtMost)) {+    // Clamp the size to the min/max size, if specified, and make sure it+    // doesn't go below the padding and border amount.+    node->setLayoutMeasuredDimension(+        YGNodeBoundAxis(+            node,+            crossAxis,+            totalLineCrossDim + paddingAndBorderAxisCross,+            crossAxisownerSize,+            ownerWidth),+        dim[crossAxis]);++  } else if (+      measureModeCrossDim == YGMeasureModeAtMost &&+      node->getStyle().overflow == YGOverflowScroll) {+    node->setLayoutMeasuredDimension(+        YGFloatMax(+            YGFloatMin(+                availableInnerCrossDim + paddingAndBorderAxisCross,+                YGUnwrapFloatOptional(YGNodeBoundAxisWithinMinAndMax(+                    node,+                    crossAxis,+                    totalLineCrossDim + paddingAndBorderAxisCross,+                    crossAxisownerSize))),+            paddingAndBorderAxisCross),+        dim[crossAxis]);+  }++  // As we only wrapped in normal direction yet, we need to reverse the+  // positions on wrap-reverse.+  if (performLayout && node->getStyle().flexWrap == YGWrapWrapReverse) {+    for (uint32_t i = 0; i < childCount; i++) {+      const YGNodeRef child = YGNodeGetChild(node, i);+      if (child->getStyle().positionType == YGPositionTypeRelative) {+        child->setLayoutPosition(+            node->getLayout().measuredDimensions[dim[crossAxis]] -+                child->getLayout().position[pos[crossAxis]] -+                child->getLayout().measuredDimensions[dim[crossAxis]],+            pos[crossAxis]);+      }+    }+  }++  if (performLayout) {+    // STEP 10: SIZING AND POSITIONING ABSOLUTE CHILDREN+    for (auto child : node->getChildren()) {+      if (child->getStyle().positionType != YGPositionTypeAbsolute) {+        continue;+      }+      YGNodeAbsoluteLayoutChild(+          node,+          child,+          availableInnerWidth,+          isMainAxisRow ? measureModeMainDim : measureModeCrossDim,+          availableInnerHeight,+          direction,+          config);+    }++    // STEP 11: SETTING TRAILING POSITIONS FOR CHILDREN+    const bool needsMainTrailingPos = mainAxis == YGFlexDirectionRowReverse ||+        mainAxis == YGFlexDirectionColumnReverse;+    const bool needsCrossTrailingPos = crossAxis == YGFlexDirectionRowReverse ||+        crossAxis == YGFlexDirectionColumnReverse;++    // Set trailing position if necessary.+    if (needsMainTrailingPos || needsCrossTrailingPos) {+      for (uint32_t i = 0; i < childCount; i++) {+        const YGNodeRef child = node->getChild(i);+        if (child->getStyle().display == YGDisplayNone) {+          continue;+        }+        if (needsMainTrailingPos) {+          YGNodeSetChildTrailingPosition(node, child, mainAxis);+        }++        if (needsCrossTrailingPos) {+          YGNodeSetChildTrailingPosition(node, child, crossAxis);+        }+      }+    }+  }+}++uint32_t gDepth = 0;+bool gPrintChanges = false;+bool gPrintSkips = false;++static const char* spacer =+    "                                                            ";++static const char* YGSpacer(const unsigned long level) {+  const size_t spacerLen = strlen(spacer);+  if (level > spacerLen) {+    return &spacer[0];+  } else {+    return &spacer[spacerLen - level];+  }+}++static const char* YGMeasureModeName(+    const YGMeasureMode mode,+    const bool performLayout) {+  const char* kMeasureModeNames[YGMeasureModeCount] = {+      "UNDEFINED", "EXACTLY", "AT_MOST"};+  const char* kLayoutModeNames[YGMeasureModeCount] = {"LAY_UNDEFINED",+                                                      "LAY_EXACTLY",+                                                      "LAY_AT_"+                                                      "MOST"};++  if (mode >= YGMeasureModeCount) {+    return "";+  }++  return performLayout ? kLayoutModeNames[mode] : kMeasureModeNames[mode];+}++static inline bool YGMeasureModeSizeIsExactAndMatchesOldMeasuredSize(+    YGMeasureMode sizeMode,+    float size,+    float lastComputedSize) {+  return sizeMode == YGMeasureModeExactly &&+      YGFloatsEqual(size, lastComputedSize);+}++static inline bool YGMeasureModeOldSizeIsUnspecifiedAndStillFits(+    YGMeasureMode sizeMode,+    float size,+    YGMeasureMode lastSizeMode,+    float lastComputedSize) {+  return sizeMode == YGMeasureModeAtMost &&+      lastSizeMode == YGMeasureModeUndefined &&+      (size >= lastComputedSize || YGFloatsEqual(size, lastComputedSize));+}++static inline bool YGMeasureModeNewMeasureSizeIsStricterAndStillValid(+    YGMeasureMode sizeMode,+    float size,+    YGMeasureMode lastSizeMode,+    float lastSize,+    float lastComputedSize) {+  return lastSizeMode == YGMeasureModeAtMost &&+      sizeMode == YGMeasureModeAtMost && !YGFloatIsUndefined(lastSize) &&+      !YGFloatIsUndefined(size) && !YGFloatIsUndefined(lastComputedSize) &&+      lastSize > size &&+      (lastComputedSize <= size || YGFloatsEqual(size, lastComputedSize));+}++float YGRoundValueToPixelGrid(+    const float value,+    const float pointScaleFactor,+    const bool forceCeil,+    const bool forceFloor) {+  float scaledValue = value * pointScaleFactor;+  float fractial = fmodf(scaledValue, 1.0f);+  if (YGFloatsEqual(fractial, 0)) {+    // First we check if the value is already rounded+    scaledValue = scaledValue - fractial;+  } else if (YGFloatsEqual(fractial, 1.0f)) {+    scaledValue = scaledValue - fractial + 1.0f;+  } else if (forceCeil) {+    // Next we check if we need to use forced rounding+    scaledValue = scaledValue - fractial + 1.0f;+  } else if (forceFloor) {+    scaledValue = scaledValue - fractial;+  } else {+    // Finally we just round the value+    scaledValue = scaledValue - fractial ++        (!YGFloatIsUndefined(fractial) &&+                 (fractial > 0.5f || YGFloatsEqual(fractial, 0.5f))+             ? 1.0f+             : 0.0f);+  }+  return (YGFloatIsUndefined(scaledValue) ||+          YGFloatIsUndefined(pointScaleFactor))+      ? YGUndefined+      : scaledValue / pointScaleFactor;+}++bool YGNodeCanUseCachedMeasurement(+    const YGMeasureMode widthMode,+    const float width,+    const YGMeasureMode heightMode,+    const float height,+    const YGMeasureMode lastWidthMode,+    const float lastWidth,+    const YGMeasureMode lastHeightMode,+    const float lastHeight,+    const float lastComputedWidth,+    const float lastComputedHeight,+    const float marginRow,+    const float marginColumn,+    const YGConfigRef config) {+  if ((!YGFloatIsUndefined(lastComputedHeight) && lastComputedHeight < 0) ||+      (!YGFloatIsUndefined(lastComputedWidth) && lastComputedWidth < 0)) {+    return false;+  }+  bool useRoundedComparison =+      config != nullptr && config->pointScaleFactor != 0;+  const float effectiveWidth = useRoundedComparison+      ? YGRoundValueToPixelGrid(width, config->pointScaleFactor, false, false)+      : width;+  const float effectiveHeight = useRoundedComparison+      ? YGRoundValueToPixelGrid(height, config->pointScaleFactor, false, false)+      : height;+  const float effectiveLastWidth = useRoundedComparison+      ? YGRoundValueToPixelGrid(+            lastWidth, config->pointScaleFactor, false, false)+      : lastWidth;+  const float effectiveLastHeight = useRoundedComparison+      ? YGRoundValueToPixelGrid(+            lastHeight, config->pointScaleFactor, false, false)+      : lastHeight;++  const bool hasSameWidthSpec = lastWidthMode == widthMode &&+      YGFloatsEqual(effectiveLastWidth, effectiveWidth);+  const bool hasSameHeightSpec = lastHeightMode == heightMode &&+      YGFloatsEqual(effectiveLastHeight, effectiveHeight);++  const bool widthIsCompatible =+      hasSameWidthSpec ||+      YGMeasureModeSizeIsExactAndMatchesOldMeasuredSize(+          widthMode, width - marginRow, lastComputedWidth) ||+      YGMeasureModeOldSizeIsUnspecifiedAndStillFits(+          widthMode, width - marginRow, lastWidthMode, lastComputedWidth) ||+      YGMeasureModeNewMeasureSizeIsStricterAndStillValid(+          widthMode,+          width - marginRow,+          lastWidthMode,+          lastWidth,+          lastComputedWidth);++  const bool heightIsCompatible =+      hasSameHeightSpec ||+      YGMeasureModeSizeIsExactAndMatchesOldMeasuredSize(+          heightMode, height - marginColumn, lastComputedHeight) ||+      YGMeasureModeOldSizeIsUnspecifiedAndStillFits(+          heightMode,+          height - marginColumn,+          lastHeightMode,+          lastComputedHeight) ||+      YGMeasureModeNewMeasureSizeIsStricterAndStillValid(+          heightMode,+          height - marginColumn,+          lastHeightMode,+          lastHeight,+          lastComputedHeight);++  return widthIsCompatible && heightIsCompatible;+}++//+// This is a wrapper around the YGNodelayoutImpl function. It determines+// whether the layout request is redundant and can be skipped.+//+// Parameters:+//  Input parameters are the same as YGNodelayoutImpl (see above)+//  Return parameter is true if layout was performed, false if skipped+//+bool YGLayoutNodeInternal(+    const YGNodeRef node,+    const float availableWidth,+    const float availableHeight,+    const YGDirection ownerDirection,+    const YGMeasureMode widthMeasureMode,+    const YGMeasureMode heightMeasureMode,+    const float ownerWidth,+    const float ownerHeight,+    const bool performLayout,+    const char* reason,+    const YGConfigRef config) {+  YGLayout* layout = &node->getLayout();++  gDepth++;++  const bool needToVisitNode =+      (node->isDirty() && layout->generationCount != gCurrentGenerationCount) ||+      layout->lastOwnerDirection != ownerDirection;++  if (needToVisitNode) {+    // Invalidate the cached results.+    layout->nextCachedMeasurementsIndex = 0;+    layout->cachedLayout.widthMeasureMode = (YGMeasureMode)-1;+    layout->cachedLayout.heightMeasureMode = (YGMeasureMode)-1;+    layout->cachedLayout.computedWidth = -1;+    layout->cachedLayout.computedHeight = -1;+  }++  YGCachedMeasurement* cachedResults = nullptr;++  // Determine whether the results are already cached. We maintain a separate+  // cache for layouts and measurements. A layout operation modifies the+  // positions+  // and dimensions for nodes in the subtree. The algorithm assumes that each+  // node+  // gets layed out a maximum of one time per tree layout, but multiple+  // measurements+  // may be required to resolve all of the flex dimensions.+  // We handle nodes with measure functions specially here because they are the+  // most+  // expensive to measure, so it's worth avoiding redundant measurements if at+  // all possible.+  if (node->getMeasure() != nullptr) {+    const float marginAxisRow = YGUnwrapFloatOptional(+        node->getMarginForAxis(YGFlexDirectionRow, ownerWidth));+    const float marginAxisColumn = YGUnwrapFloatOptional(+        node->getMarginForAxis(YGFlexDirectionColumn, ownerWidth));++    // First, try to use the layout cache.+    if (YGNodeCanUseCachedMeasurement(+            widthMeasureMode,+            availableWidth,+            heightMeasureMode,+            availableHeight,+            layout->cachedLayout.widthMeasureMode,+            layout->cachedLayout.availableWidth,+            layout->cachedLayout.heightMeasureMode,+            layout->cachedLayout.availableHeight,+            layout->cachedLayout.computedWidth,+            layout->cachedLayout.computedHeight,+            marginAxisRow,+            marginAxisColumn,+            config)) {+      cachedResults = &layout->cachedLayout;+    } else {+      // Try to use the measurement cache.+      for (uint32_t i = 0; i < layout->nextCachedMeasurementsIndex; i++) {+        if (YGNodeCanUseCachedMeasurement(+                widthMeasureMode,+                availableWidth,+                heightMeasureMode,+                availableHeight,+                layout->cachedMeasurements[i].widthMeasureMode,+                layout->cachedMeasurements[i].availableWidth,+                layout->cachedMeasurements[i].heightMeasureMode,+                layout->cachedMeasurements[i].availableHeight,+                layout->cachedMeasurements[i].computedWidth,+                layout->cachedMeasurements[i].computedHeight,+                marginAxisRow,+                marginAxisColumn,+                config)) {+          cachedResults = &layout->cachedMeasurements[i];+          break;+        }+      }+    }+  } else if (performLayout) {+    if (YGFloatsEqual(layout->cachedLayout.availableWidth, availableWidth) &&+        YGFloatsEqual(layout->cachedLayout.availableHeight, availableHeight) &&+        layout->cachedLayout.widthMeasureMode == widthMeasureMode &&+        layout->cachedLayout.heightMeasureMode == heightMeasureMode) {+      cachedResults = &layout->cachedLayout;+    }+  } else {+    for (uint32_t i = 0; i < layout->nextCachedMeasurementsIndex; i++) {+      if (YGFloatsEqual(+              layout->cachedMeasurements[i].availableWidth, availableWidth) &&+          YGFloatsEqual(+              layout->cachedMeasurements[i].availableHeight, availableHeight) &&+          layout->cachedMeasurements[i].widthMeasureMode == widthMeasureMode &&+          layout->cachedMeasurements[i].heightMeasureMode ==+              heightMeasureMode) {+        cachedResults = &layout->cachedMeasurements[i];+        break;+      }+    }+  }++  if (!needToVisitNode && cachedResults != nullptr) {+    layout->measuredDimensions[YGDimensionWidth] = cachedResults->computedWidth;+    layout->measuredDimensions[YGDimensionHeight] =+        cachedResults->computedHeight;++    if (gPrintChanges && gPrintSkips) {+      YGLog(+          node,+          YGLogLevelVerbose,+          "%s%d.{[skipped] ",+          YGSpacer(gDepth),+          gDepth);+      if (node->getPrintFunc() != nullptr) {+        node->getPrintFunc()(node);+      }+      YGLog(+          node,+          YGLogLevelVerbose,+          "wm: %s, hm: %s, aw: %f ah: %f => d: (%f, %f) %s\n",+          YGMeasureModeName(widthMeasureMode, performLayout),+          YGMeasureModeName(heightMeasureMode, performLayout),+          availableWidth,+          availableHeight,+          cachedResults->computedWidth,+          cachedResults->computedHeight,+          reason);+    }+  } else {+    if (gPrintChanges) {+      YGLog(+          node,+          YGLogLevelVerbose,+          "%s%d.{%s",+          YGSpacer(gDepth),+          gDepth,+          needToVisitNode ? "*" : "");+      if (node->getPrintFunc() != nullptr) {+        node->getPrintFunc()(node);+      }+      YGLog(+          node,+          YGLogLevelVerbose,+          "wm: %s, hm: %s, aw: %f ah: %f %s\n",+          YGMeasureModeName(widthMeasureMode, performLayout),+          YGMeasureModeName(heightMeasureMode, performLayout),+          availableWidth,+          availableHeight,+          reason);+    }++    YGNodelayoutImpl(+        node,+        availableWidth,+        availableHeight,+        ownerDirection,+        widthMeasureMode,+        heightMeasureMode,+        ownerWidth,+        ownerHeight,+        performLayout,+        config);++    if (gPrintChanges) {+      YGLog(+          node,+          YGLogLevelVerbose,+          "%s%d.}%s",+          YGSpacer(gDepth),+          gDepth,+          needToVisitNode ? "*" : "");+      if (node->getPrintFunc() != nullptr) {+        node->getPrintFunc()(node);+      }+      YGLog(+          node,+          YGLogLevelVerbose,+          "wm: %s, hm: %s, d: (%f, %f) %s\n",+          YGMeasureModeName(widthMeasureMode, performLayout),+          YGMeasureModeName(heightMeasureMode, performLayout),+          layout->measuredDimensions[YGDimensionWidth],+          layout->measuredDimensions[YGDimensionHeight],+          reason);+    }++    layout->lastOwnerDirection = ownerDirection;++    if (cachedResults == nullptr) {+      if (layout->nextCachedMeasurementsIndex == YG_MAX_CACHED_RESULT_COUNT) {+        if (gPrintChanges) {+          YGLog(node, YGLogLevelVerbose, "Out of cache entries!\n");+        }+        layout->nextCachedMeasurementsIndex = 0;+      }++      YGCachedMeasurement* newCacheEntry;+      if (performLayout) {+        // Use the single layout cache entry.+        newCacheEntry = &layout->cachedLayout;+      } else {+        // Allocate a new measurement cache entry.+        newCacheEntry =+            &layout->cachedMeasurements[layout->nextCachedMeasurementsIndex];+        layout->nextCachedMeasurementsIndex++;+      }++      newCacheEntry->availableWidth = availableWidth;+      newCacheEntry->availableHeight = availableHeight;+      newCacheEntry->widthMeasureMode = widthMeasureMode;+      newCacheEntry->heightMeasureMode = heightMeasureMode;+      newCacheEntry->computedWidth =+          layout->measuredDimensions[YGDimensionWidth];+      newCacheEntry->computedHeight =+          layout->measuredDimensions[YGDimensionHeight];+    }+  }++  if (performLayout) {+    node->setLayoutDimension(+        node->getLayout().measuredDimensions[YGDimensionWidth],+        YGDimensionWidth);+    node->setLayoutDimension(+        node->getLayout().measuredDimensions[YGDimensionHeight],+        YGDimensionHeight);++    node->setHasNewLayout(true);+    node->setDirty(false);+  }++  gDepth--;+  layout->generationCount = gCurrentGenerationCount;+  return (needToVisitNode || cachedResults == nullptr);+}++void YGConfigSetPointScaleFactor(+    const YGConfigRef config,+    const float pixelsInPoint) {+  YGAssertWithConfig(+      config,+      pixelsInPoint >= 0.0f,+      "Scale factor should not be less than zero");++  // We store points for Pixel as we will use it for rounding+  if (pixelsInPoint == 0.0f) {+    // Zero is used to skip rounding+    config->pointScaleFactor = 0.0f;+  } else {+    config->pointScaleFactor = pixelsInPoint;+  }+}++static void YGRoundToPixelGrid(+    const YGNodeRef node,+    const float pointScaleFactor,+    const float absoluteLeft,+    const float absoluteTop) {+  if (pointScaleFactor == 0.0f) {+    return;+  }++  const float nodeLeft = node->getLayout().position[YGEdgeLeft];+  const float nodeTop = node->getLayout().position[YGEdgeTop];++  const float nodeWidth = node->getLayout().dimensions[YGDimensionWidth];+  const float nodeHeight = node->getLayout().dimensions[YGDimensionHeight];++  const float absoluteNodeLeft = absoluteLeft + nodeLeft;+  const float absoluteNodeTop = absoluteTop + nodeTop;++  const float absoluteNodeRight = absoluteNodeLeft + nodeWidth;+  const float absoluteNodeBottom = absoluteNodeTop + nodeHeight;++  // If a node has a custom measure function we never want to round down its+  // size as this could lead to unwanted text truncation.+  const bool textRounding = node->getNodeType() == YGNodeTypeText;++  node->setLayoutPosition(+      YGRoundValueToPixelGrid(nodeLeft, pointScaleFactor, false, textRounding),+      YGEdgeLeft);++  node->setLayoutPosition(+      YGRoundValueToPixelGrid(nodeTop, pointScaleFactor, false, textRounding),+      YGEdgeTop);++  // We multiply dimension by scale factor and if the result is close to the+  // whole number, we don't have any fraction To verify if the result is close+  // to whole number we want to check both floor and ceil numbers+  const bool hasFractionalWidth =+      !YGFloatsEqual(fmodf(nodeWidth * pointScaleFactor, 1.0), 0) &&+      !YGFloatsEqual(fmodf(nodeWidth * pointScaleFactor, 1.0), 1.0);+  const bool hasFractionalHeight =+      !YGFloatsEqual(fmodf(nodeHeight * pointScaleFactor, 1.0), 0) &&+      !YGFloatsEqual(fmodf(nodeHeight * pointScaleFactor, 1.0), 1.0);++  node->setLayoutDimension(+      YGRoundValueToPixelGrid(+          absoluteNodeRight,+          pointScaleFactor,+          (textRounding && hasFractionalWidth),+          (textRounding && !hasFractionalWidth)) -+          YGRoundValueToPixelGrid(+              absoluteNodeLeft, pointScaleFactor, false, textRounding),+      YGDimensionWidth);++  node->setLayoutDimension(+      YGRoundValueToPixelGrid(+          absoluteNodeBottom,+          pointScaleFactor,+          (textRounding && hasFractionalHeight),+          (textRounding && !hasFractionalHeight)) -+          YGRoundValueToPixelGrid(+              absoluteNodeTop, pointScaleFactor, false, textRounding),+      YGDimensionHeight);++  const uint32_t childCount = YGNodeGetChildCount(node);+  for (uint32_t i = 0; i < childCount; i++) {+    YGRoundToPixelGrid(+        YGNodeGetChild(node, i),+        pointScaleFactor,+        absoluteNodeLeft,+        absoluteNodeTop);+  }+}++void YGNodeCalculateLayout(+    const YGNodeRef node,+    const float ownerWidth,+    const float ownerHeight,+    const YGDirection ownerDirection) {+  // Increment the generation count. This will force the recursive routine to+  // visit+  // all dirty nodes at least once. Subsequent visits will be skipped if the+  // input+  // parameters don't change.+  gCurrentGenerationCount++;+  node->resolveDimension();+  float width = YGUndefined;+  YGMeasureMode widthMeasureMode = YGMeasureModeUndefined;+  if (YGNodeIsStyleDimDefined(node, YGFlexDirectionRow, ownerWidth)) {+    width = YGUnwrapFloatOptional(+        YGResolveValue(+            node->getResolvedDimension(dim[YGFlexDirectionRow]), ownerWidth) ++        node->getMarginForAxis(YGFlexDirectionRow, ownerWidth));+    widthMeasureMode = YGMeasureModeExactly;+  } else if (!YGResolveValue(+                  node->getStyle().maxDimensions[YGDimensionWidth], ownerWidth)+                  .isUndefined()) {+    width = YGUnwrapFloatOptional(YGResolveValue(+        node->getStyle().maxDimensions[YGDimensionWidth], ownerWidth));+    widthMeasureMode = YGMeasureModeAtMost;+  } else {+    width = ownerWidth;+    widthMeasureMode = YGFloatIsUndefined(width) ? YGMeasureModeUndefined+                                                 : YGMeasureModeExactly;+  }++  float height = YGUndefined;+  YGMeasureMode heightMeasureMode = YGMeasureModeUndefined;+  if (YGNodeIsStyleDimDefined(node, YGFlexDirectionColumn, ownerHeight)) {+    height = YGUnwrapFloatOptional(+        YGResolveValue(+            node->getResolvedDimension(dim[YGFlexDirectionColumn]),+            ownerHeight) ++        node->getMarginForAxis(YGFlexDirectionColumn, ownerWidth));+    heightMeasureMode = YGMeasureModeExactly;+  } else if (!YGResolveValue(+                  node->getStyle().maxDimensions[YGDimensionHeight],+                  ownerHeight)+                  .isUndefined()) {+    height = YGUnwrapFloatOptional(YGResolveValue(+        node->getStyle().maxDimensions[YGDimensionHeight], ownerHeight));+    heightMeasureMode = YGMeasureModeAtMost;+  } else {+    height = ownerHeight;+    heightMeasureMode = YGFloatIsUndefined(height) ? YGMeasureModeUndefined+                                                   : YGMeasureModeExactly;+  }+  if (YGLayoutNodeInternal(+          node,+          width,+          height,+          ownerDirection,+          widthMeasureMode,+          heightMeasureMode,+          ownerWidth,+          ownerHeight,+          true,+          "initial",+          node->getConfig())) {+    node->setPosition(+        node->getLayout().direction, ownerWidth, ownerHeight, ownerWidth);+    YGRoundToPixelGrid(node, node->getConfig()->pointScaleFactor, 0.0f, 0.0f);++    if (node->getConfig()->printTree) {+      YGNodePrint(+          node,+          (YGPrintOptions)(+              YGPrintOptionsLayout | YGPrintOptionsChildren |+              YGPrintOptionsStyle));+    }+  }++  // We want to get rid off `useLegacyStretchBehaviour` from YGConfig. But we+  // aren't sure whether client's of yoga have gotten rid off this flag or not.+  // So logging this in YGLayout would help to find out the call sites depending+  // on this flag. This check would be removed once we are sure no one is+  // dependent on this flag anymore. The flag+  // `shouldDiffLayoutWithoutLegacyStretchBehaviour` in YGConfig will help to+  // run experiments.+  if (node->getConfig()->shouldDiffLayoutWithoutLegacyStretchBehaviour &&+      node->didUseLegacyFlag()) {+    const YGNodeRef originalNode = YGNodeDeepClone(node);+    originalNode->resolveDimension();+    // Recursively mark nodes as dirty+    originalNode->markDirtyAndPropogateDownwards();+    gCurrentGenerationCount++;+    // Rerun the layout, and calculate the diff+    originalNode->setAndPropogateUseLegacyFlag(false);+    if (YGLayoutNodeInternal(+            originalNode,+            width,+            height,+            ownerDirection,+            widthMeasureMode,+            heightMeasureMode,+            ownerWidth,+            ownerHeight,+            true,+            "initial",+            originalNode->getConfig())) {+      originalNode->setPosition(+          originalNode->getLayout().direction,+          ownerWidth,+          ownerHeight,+          ownerWidth);+      YGRoundToPixelGrid(+          originalNode,+          originalNode->getConfig()->pointScaleFactor,+          0.0f,+          0.0f);++      // Set whether the two layouts are different or not.+      node->setLayoutDoesLegacyFlagAffectsLayout(+          !originalNode->isLayoutTreeEqualToNode(*node));++      if (originalNode->getConfig()->printTree) {+        YGNodePrint(+            originalNode,+            (YGPrintOptions)(+                YGPrintOptionsLayout | YGPrintOptionsChildren |+                YGPrintOptionsStyle));+      }+    }+    YGConfigFreeRecursive(originalNode);+    YGNodeFreeRecursive(originalNode);+  }+}++void YGConfigSetLogger(const YGConfigRef config, YGLogger logger) {+  if (logger != nullptr) {+    config->logger = logger;+  } else {+#ifdef ANDROID+    config->logger = &YGAndroidLog;+#else+    config->logger = &YGDefaultLog;+#endif+  }+}++void YGConfigSetShouldDiffLayoutWithoutLegacyStretchBehaviour(+    const YGConfigRef config,+    const bool shouldDiffLayout) {+  config->shouldDiffLayoutWithoutLegacyStretchBehaviour = shouldDiffLayout;+}++static void YGVLog(+    const YGConfigRef config,+    const YGNodeRef node,+    YGLogLevel level,+    const char* format,+    va_list args) {+  const YGConfigRef logConfig =+      config != nullptr ? config : YGConfigGetDefault();+  logConfig->logger(logConfig, node, level, format, args);++  if (level == YGLogLevelFatal) {+    abort();+  }+}++void YGLogWithConfig(+    const YGConfigRef config,+    YGLogLevel level,+    const char* format,+    ...) {+  va_list args;+  va_start(args, format);+  YGVLog(config, nullptr, level, format, args);+  va_end(args);+}++void YGLog(const YGNodeRef node, YGLogLevel level, const char* format, ...) {+  va_list args;+  va_start(args, format);+  YGVLog(+      node == nullptr ? nullptr : node->getConfig(), node, level, format, args);+  va_end(args);+}++void YGAssert(const bool condition, const char* message) {+  if (!condition) {+    YGLog(nullptr, YGLogLevelFatal, "%s\n", message);+  }+}++void YGAssertWithNode(+    const YGNodeRef node,+    const bool condition,+    const char* message) {+  if (!condition) {+    YGLog(node, YGLogLevelFatal, "%s\n", message);+  }+}++void YGAssertWithConfig(+    const YGConfigRef config,+    const bool condition,+    const char* message) {+  if (!condition) {+    YGLogWithConfig(config, YGLogLevelFatal, "%s\n", message);+  }+}++void YGConfigSetExperimentalFeatureEnabled(+    const YGConfigRef config,+    const YGExperimentalFeature feature,+    const bool enabled) {+  config->experimentalFeatures[feature] = enabled;+}++inline bool YGConfigIsExperimentalFeatureEnabled(+    const YGConfigRef config,+    const YGExperimentalFeature feature) {+  return config->experimentalFeatures[feature];+}++void YGConfigSetUseWebDefaults(const YGConfigRef config, const bool enabled) {+  config->useWebDefaults = enabled;+}++void YGConfigSetUseLegacyStretchBehaviour(+    const YGConfigRef config,+    const bool useLegacyStretchBehaviour) {+  config->useLegacyStretchBehaviour = useLegacyStretchBehaviour;+}++bool YGConfigGetUseWebDefaults(const YGConfigRef config) {+  return config->useWebDefaults;+}++void YGConfigSetContext(const YGConfigRef config, void* context) {+  config->context = context;+}++void* YGConfigGetContext(const YGConfigRef config) {+  return config->context;+}++void YGConfigSetCloneNodeFunc(+    const YGConfigRef config,+    const YGCloneNodeFunc callback) {+  config->cloneNodeCallback = callback;+}++static void YGTraverseChildrenPreOrder(+    const YGVector& children,+    const std::function<void(YGNodeRef node)>& f) {+  for (YGNodeRef node : children) {+    f(node);+    YGTraverseChildrenPreOrder(node->getChildren(), f);+  }+}++void YGTraversePreOrder(+    YGNodeRef const node,+    std::function<void(YGNodeRef node)>&& f) {+  if (!node) {+    return;+  }+  f(node);+  YGTraverseChildrenPreOrder(node->getChildren(), f);+}
yoga/Yoga.h view
@@ -1,283 +1,462 @@-/**
- * Copyright (c) 2014-present, Facebook, Inc.
- * All rights reserved.
- *
- * This source code is licensed under the BSD-style license found in the
- * LICENSE file in the root directory of this source tree. An additional grant
- * of patent rights can be found in the PATENTS file in the same directory.
- */
-
-#pragma once
-
-#include <assert.h>
-#include <math.h>
-#include <stdarg.h>
-#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-
-#ifndef __cplusplus
-#include <stdbool.h>
-#endif
-
-// Not defined in MSVC++
-#ifndef NAN
-static const unsigned long __nan[2] = {0xffffffff, 0x7fffffff};
-#define NAN (*(const float *) __nan)
-#endif
-
-#define YGUndefined NAN
-
-#include "YGEnums.h"
-#include "YGMacros.h"
-
-YG_EXTERN_C_BEGIN
-
-typedef struct YGSize {
-  float width;
-  float height;
-} YGSize;
-
-typedef struct YGValue {
-  float value;
-  YGUnit unit;
-} YGValue;
-
-static const YGValue YGValueUndefined = {YGUndefined, YGUnitUndefined};
-static const YGValue YGValueAuto = {YGUndefined, YGUnitAuto};
-
-typedef struct YGConfig *YGConfigRef;
-typedef struct YGNode *YGNodeRef;
-typedef YGSize (*YGMeasureFunc)(YGNodeRef node,
-                                float width,
-                                YGMeasureMode widthMode,
-                                float height,
-                                YGMeasureMode heightMode);
-typedef float (*YGBaselineFunc)(YGNodeRef node, const float width, const float height);
-typedef void (*YGPrintFunc)(YGNodeRef node);
-typedef int (*YGLogger)(const YGConfigRef config,
-                        const YGNodeRef node,
-                        YGLogLevel level,
-                        const char *format,
-                        va_list args);
-typedef void (*YGNodeClonedFunc)(YGNodeRef oldNode,
-                                 YGNodeRef newNode,
-                                 YGNodeRef parent,
-                                 int childIndex);
-
-// YGNode
-WIN_EXPORT YGNodeRef YGNodeNew(void);
-WIN_EXPORT YGNodeRef YGNodeNewWithConfig(const YGConfigRef config);
-WIN_EXPORT YGNodeRef YGNodeClone(const YGNodeRef node);
-WIN_EXPORT void YGNodeFree(const YGNodeRef node);
-WIN_EXPORT void YGNodeFreeRecursive(const YGNodeRef node);
-WIN_EXPORT void YGNodeReset(const YGNodeRef node);
-WIN_EXPORT int32_t YGNodeGetInstanceCount(void);
-
-WIN_EXPORT void YGNodeInsertChild(const YGNodeRef node,
-                                  const YGNodeRef child,
-                                  const uint32_t index);
-WIN_EXPORT void YGNodeRemoveChild(const YGNodeRef node, const YGNodeRef child);
-WIN_EXPORT void YGNodeRemoveAllChildren(const YGNodeRef node);
-WIN_EXPORT YGNodeRef YGNodeGetChild(const YGNodeRef node, const uint32_t index);
-WIN_EXPORT YGNodeRef YGNodeGetParent(const YGNodeRef node);
-WIN_EXPORT uint32_t YGNodeGetChildCount(const YGNodeRef node);
-
-WIN_EXPORT void YGNodeCalculateLayout(const YGNodeRef node,
-                                      const float availableWidth,
-                                      const float availableHeight,
-                                      const YGDirection parentDirection);
-
-// Mark a node as dirty. Only valid for nodes with a custom measure function
-// set.
-// YG knows when to mark all other nodes as dirty but because nodes with
-// measure functions
-// depends on information not known to YG they must perform this dirty
-// marking manually.
-WIN_EXPORT void YGNodeMarkDirty(const YGNodeRef node);
-WIN_EXPORT bool YGNodeIsDirty(const YGNodeRef node);
-
-WIN_EXPORT void YGNodePrint(const YGNodeRef node, const YGPrintOptions options);
-
-WIN_EXPORT bool YGFloatIsUndefined(const float value);
-
-WIN_EXPORT bool YGNodeCanUseCachedMeasurement(const YGMeasureMode widthMode,
-                                              const float width,
-                                              const YGMeasureMode heightMode,
-                                              const float height,
-                                              const YGMeasureMode lastWidthMode,
-                                              const float lastWidth,
-                                              const YGMeasureMode lastHeightMode,
-                                              const float lastHeight,
-                                              const float lastComputedWidth,
-                                              const float lastComputedHeight,
-                                              const float marginRow,
-                                              const float marginColumn,
-                                              const YGConfigRef config);
-
-WIN_EXPORT void YGNodeCopyStyle(const YGNodeRef dstNode, const YGNodeRef srcNode);
-
-#define YG_NODE_PROPERTY(type, name, paramName)                          \
-  WIN_EXPORT void YGNodeSet##name(const YGNodeRef node, type paramName); \
-  WIN_EXPORT type YGNodeGet##name(const YGNodeRef node);
-
-#define YG_NODE_STYLE_PROPERTY(type, name, paramName)                               \
-  WIN_EXPORT void YGNodeStyleSet##name(const YGNodeRef node, const type paramName); \
-  WIN_EXPORT type YGNodeStyleGet##name(const YGNodeRef node);
-
-#define YG_NODE_STYLE_PROPERTY_UNIT(type, name, paramName)                                    \
-  WIN_EXPORT void YGNodeStyleSet##name(const YGNodeRef node, const float paramName);          \
-  WIN_EXPORT void YGNodeStyleSet##name##Percent(const YGNodeRef node, const float paramName); \
-  WIN_EXPORT type YGNodeStyleGet##name(const YGNodeRef node);
-
-#define YG_NODE_STYLE_PROPERTY_UNIT_AUTO(type, name, paramName) \
-  YG_NODE_STYLE_PROPERTY_UNIT(type, name, paramName)            \
-  WIN_EXPORT void YGNodeStyleSet##name##Auto(const YGNodeRef node);
-
-#define YG_NODE_STYLE_EDGE_PROPERTY(type, name, paramName)    \
-  WIN_EXPORT void YGNodeStyleSet##name(const YGNodeRef node,  \
-                                       const YGEdge edge,     \
-                                       const type paramName); \
-  WIN_EXPORT type YGNodeStyleGet##name(const YGNodeRef node, const YGEdge edge);
-
-#define YG_NODE_STYLE_EDGE_PROPERTY_UNIT(type, name, paramName)         \
-  WIN_EXPORT void YGNodeStyleSet##name(const YGNodeRef node,            \
-                                       const YGEdge edge,               \
-                                       const float paramName);          \
-  WIN_EXPORT void YGNodeStyleSet##name##Percent(const YGNodeRef node,   \
-                                                const YGEdge edge,      \
-                                                const float paramName); \
-  WIN_EXPORT WIN_STRUCT(type) YGNodeStyleGet##name(const YGNodeRef node, const YGEdge edge);
-
-#define YG_NODE_STYLE_EDGE_PROPERTY_UNIT_AUTO(type, name) \
-  WIN_EXPORT void YGNodeStyleSet##name##Auto(const YGNodeRef node, const YGEdge edge);
-
-#define YG_NODE_LAYOUT_PROPERTY(type, name) \
-  WIN_EXPORT type YGNodeLayoutGet##name(const YGNodeRef node);
-
-#define YG_NODE_LAYOUT_EDGE_PROPERTY(type, name) \
-  WIN_EXPORT type YGNodeLayoutGet##name(const YGNodeRef node, const YGEdge edge);
-
-YG_NODE_PROPERTY(void *, Context, context);
-YG_NODE_PROPERTY(YGMeasureFunc, MeasureFunc, measureFunc);
-YG_NODE_PROPERTY(YGBaselineFunc, BaselineFunc, baselineFunc)
-YG_NODE_PROPERTY(YGPrintFunc, PrintFunc, printFunc);
-YG_NODE_PROPERTY(bool, HasNewLayout, hasNewLayout);
-YG_NODE_PROPERTY(YGNodeType, NodeType, nodeType);
-
-YG_NODE_STYLE_PROPERTY(YGDirection, Direction, direction);
-YG_NODE_STYLE_PROPERTY(YGFlexDirection, FlexDirection, flexDirection);
-YG_NODE_STYLE_PROPERTY(YGJustify, JustifyContent, justifyContent);
-YG_NODE_STYLE_PROPERTY(YGAlign, AlignContent, alignContent);
-YG_NODE_STYLE_PROPERTY(YGAlign, AlignItems, alignItems);
-YG_NODE_STYLE_PROPERTY(YGAlign, AlignSelf, alignSelf);
-YG_NODE_STYLE_PROPERTY(YGPositionType, PositionType, positionType);
-YG_NODE_STYLE_PROPERTY(YGWrap, FlexWrap, flexWrap);
-YG_NODE_STYLE_PROPERTY(YGOverflow, Overflow, overflow);
-YG_NODE_STYLE_PROPERTY(YGDisplay, Display, display);
-
-YG_NODE_STYLE_PROPERTY(float, Flex, flex);
-YG_NODE_STYLE_PROPERTY(float, FlexGrow, flexGrow);
-YG_NODE_STYLE_PROPERTY(float, FlexShrink, flexShrink);
-YG_NODE_STYLE_PROPERTY_UNIT_AUTO(YGValue, FlexBasis, flexBasis);
-
-YG_NODE_STYLE_EDGE_PROPERTY_UNIT(YGValue, Position, position);
-YG_NODE_STYLE_EDGE_PROPERTY_UNIT(YGValue, Margin, margin);
-YG_NODE_STYLE_EDGE_PROPERTY_UNIT_AUTO(YGValue, Margin);
-YG_NODE_STYLE_EDGE_PROPERTY_UNIT(YGValue, Padding, padding);
-YG_NODE_STYLE_EDGE_PROPERTY(float, Border, border);
-
-YG_NODE_STYLE_PROPERTY_UNIT_AUTO(YGValue, Width, width);
-YG_NODE_STYLE_PROPERTY_UNIT_AUTO(YGValue, Height, height);
-YG_NODE_STYLE_PROPERTY_UNIT(YGValue, MinWidth, minWidth);
-YG_NODE_STYLE_PROPERTY_UNIT(YGValue, MinHeight, minHeight);
-YG_NODE_STYLE_PROPERTY_UNIT(YGValue, MaxWidth, maxWidth);
-YG_NODE_STYLE_PROPERTY_UNIT(YGValue, MaxHeight, maxHeight);
-
-// Yoga specific properties, not compatible with flexbox specification
-// Aspect ratio control the size of the undefined dimension of a node.
-// Aspect ratio is encoded as a floating point value width/height. e.g. A value of 2 leads to a node
-// with a width twice the size of its height while a value of 0.5 gives the opposite effect.
-//
-// - On a node with a set width/height aspect ratio control the size of the unset dimension
-// - On a node with a set flex basis aspect ratio controls the size of the node in the cross axis if
-// unset
-// - On a node with a measure function aspect ratio works as though the measure function measures
-// the flex basis
-// - On a node with flex grow/shrink aspect ratio controls the size of the node in the cross axis if
-// unset
-// - Aspect ratio takes min/max dimensions into account
-YG_NODE_STYLE_PROPERTY(float, AspectRatio, aspectRatio);
-
-YG_NODE_LAYOUT_PROPERTY(float, Left);
-YG_NODE_LAYOUT_PROPERTY(float, Top);
-YG_NODE_LAYOUT_PROPERTY(float, Right);
-YG_NODE_LAYOUT_PROPERTY(float, Bottom);
-YG_NODE_LAYOUT_PROPERTY(float, Width);
-YG_NODE_LAYOUT_PROPERTY(float, Height);
-YG_NODE_LAYOUT_PROPERTY(YGDirection, Direction);
-YG_NODE_LAYOUT_PROPERTY(bool, HadOverflow);
-
-// Get the computed values for these nodes after performing layout. If they were set using
-// point values then the returned value will be the same as YGNodeStyleGetXXX. However if
-// they were set using a percentage value then the returned value is the computed value used
-// during layout.
-YG_NODE_LAYOUT_EDGE_PROPERTY(float, Margin);
-YG_NODE_LAYOUT_EDGE_PROPERTY(float, Border);
-YG_NODE_LAYOUT_EDGE_PROPERTY(float, Padding);
-
-WIN_EXPORT void YGConfigSetLogger(const YGConfigRef config, YGLogger logger);
-WIN_EXPORT void YGLog(const YGNodeRef node, YGLogLevel level, const char *message, ...);
-WIN_EXPORT void YGLogWithConfig(const YGConfigRef config, YGLogLevel level, const char *format, ...);
-WIN_EXPORT void YGAssert(const bool condition, const char *message);
-WIN_EXPORT void YGAssertWithNode(const YGNodeRef node, const bool condition, const char *message);
-WIN_EXPORT void YGAssertWithConfig(const YGConfigRef config,
-                                   const bool condition,
-                                   const char *message);
-
-// Set this to number of pixels in 1 point to round calculation results
-// If you want to avoid rounding - set PointScaleFactor to 0
-WIN_EXPORT void YGConfigSetPointScaleFactor(const YGConfigRef config, const float pixelsInPoint);
-
-// Yoga previously had an error where containers would take the maximum space possible instead of
-// the minimum
-// like they are supposed to. In practice this resulted in implicit behaviour similar to align-self:
-// stretch;
-// Because this was such a long-standing bug we must allow legacy users to switch back to this
-// behaviour.
-WIN_EXPORT void YGConfigSetUseLegacyStretchBehaviour(const YGConfigRef config,
-                                                     const bool useLegacyStretchBehaviour);
-
-// YGConfig
-WIN_EXPORT YGConfigRef YGConfigNew(void);
-WIN_EXPORT void YGConfigFree(const YGConfigRef config);
-WIN_EXPORT void YGConfigCopy(const YGConfigRef dest, const YGConfigRef src);
-WIN_EXPORT int32_t YGConfigGetInstanceCount(void);
-
-WIN_EXPORT void YGConfigSetExperimentalFeatureEnabled(const YGConfigRef config,
-                                                      const YGExperimentalFeature feature,
-                                                      const bool enabled);
-WIN_EXPORT bool YGConfigIsExperimentalFeatureEnabled(const YGConfigRef config,
-                                                     const YGExperimentalFeature feature);
-
-// Using the web defaults is the prefered configuration for new projects.
-// Usage of non web defaults should be considered as legacy.
-WIN_EXPORT void YGConfigSetUseWebDefaults(const YGConfigRef config, const bool enabled);
-WIN_EXPORT bool YGConfigGetUseWebDefaults(const YGConfigRef config);
-
-WIN_EXPORT void YGConfigSetNodeClonedFunc(const YGConfigRef config,
-                                          const YGNodeClonedFunc callback);
-
-// Export only for C#
-WIN_EXPORT YGConfigRef YGConfigGetDefault(void);
-
-WIN_EXPORT void YGConfigSetContext(const YGConfigRef config, void *context);
-WIN_EXPORT void *YGConfigGetContext(const YGConfigRef config);
-
-WIN_EXPORT float YGRoundValueToPixelGrid(
-    const float value,
-    const float pointScaleFactor,
-    const bool forceCeil,
-    const bool forceFloor);
-
-YG_EXTERN_C_END
+/*+ *  Copyright (c) Facebook, Inc. and its affiliates.+ *+ *  This source code is licensed under the MIT license found in the LICENSE+ *  file in the root directory of this source tree.+ *+ */+#pragma once++#include <assert.h>+#include <math.h>+#include <stdarg.h>+#include <stdint.h>+#include <stdio.h>+#include <stdlib.h>++#ifndef __cplusplus+#include <stdbool.h>+#endif++/** Large positive number signifies that the property(float) is undefined.+ *Earlier we used to have YGundefined as NAN, but the downside of this is that+ *we can't use -ffast-math compiler flag as it assumes all floating-point+ *calculation involve and result into finite numbers. For more information+ *regarding -ffast-math compiler flag in clang, have a look at+ *https://clang.llvm.org/docs/UsersManual.html#cmdoption-ffast-math+ **/+#define YGUndefined 10E20F++#include "YGEnums.h"+#include "YGMacros.h"++YG_EXTERN_C_BEGIN++typedef struct YGSize {+  float width;+  float height;+} YGSize;++typedef struct YGValue {+  float value;+  YGUnit unit;+} YGValue;++extern const YGValue YGValueUndefined;+extern const YGValue YGValueAuto;++#ifdef __cplusplus++extern bool operator==(const YGValue& lhs, const YGValue& rhs);+extern bool operator!=(const YGValue& lhs, const YGValue& rhs);++#endif++typedef struct YGConfig* YGConfigRef;++typedef struct YGNode* YGNodeRef;++typedef YGSize (*YGMeasureFunc)(+    YGNodeRef node,+    float width,+    YGMeasureMode widthMode,+    float height,+    YGMeasureMode heightMode);+typedef float (+    *YGBaselineFunc)(YGNodeRef node, const float width, const float height);+typedef void (*YGDirtiedFunc)(YGNodeRef node);+typedef void (*YGPrintFunc)(YGNodeRef node);+typedef int (*YGLogger)(+    const YGConfigRef config,+    const YGNodeRef node,+    YGLogLevel level,+    const char* format,+    va_list args);+typedef YGNodeRef (+    *YGCloneNodeFunc)(YGNodeRef oldNode, YGNodeRef owner, int childIndex);++// YGNode+WIN_EXPORT YGNodeRef YGNodeNew(void);+WIN_EXPORT YGNodeRef YGNodeNewWithConfig(const YGConfigRef config);+WIN_EXPORT YGNodeRef YGNodeClone(const YGNodeRef node);+WIN_EXPORT void YGNodeFree(const YGNodeRef node);+WIN_EXPORT void YGNodeFreeRecursive(const YGNodeRef node);+WIN_EXPORT void YGNodeReset(const YGNodeRef node);+WIN_EXPORT int32_t YGNodeGetInstanceCount(void);++WIN_EXPORT void YGNodeInsertChild(+    const YGNodeRef node,+    const YGNodeRef child,+    const uint32_t index);++// This function inserts the child YGNodeRef as a children of the node received+// by parameter and set the Owner of the child object to null. This function is+// expected to be called when using Yoga in persistent mode in order to share a+// YGNodeRef object as a child of two different Yoga trees. The child YGNodeRef+// is expected to be referenced from its original owner and from a clone of its+// original owner.+WIN_EXPORT void YGNodeInsertSharedChild(+    const YGNodeRef node,+    const YGNodeRef child,+    const uint32_t index);+WIN_EXPORT void YGNodeRemoveChild(const YGNodeRef node, const YGNodeRef child);+WIN_EXPORT void YGNodeRemoveAllChildren(const YGNodeRef node);+WIN_EXPORT YGNodeRef YGNodeGetChild(const YGNodeRef node, const uint32_t index);+WIN_EXPORT YGNodeRef YGNodeGetOwner(const YGNodeRef node);+WIN_EXPORT YGNodeRef YGNodeGetParent(const YGNodeRef node);+WIN_EXPORT uint32_t YGNodeGetChildCount(const YGNodeRef node);+WIN_EXPORT void YGNodeSetChildren(+    YGNodeRef const owner,+    const YGNodeRef children[],+    const uint32_t count);++WIN_EXPORT void YGNodeCalculateLayout(+    const YGNodeRef node,+    const float availableWidth,+    const float availableHeight,+    const YGDirection ownerDirection);++// Mark a node as dirty. Only valid for nodes with a custom measure function+// set.+// YG knows when to mark all other nodes as dirty but because nodes with+// measure functions+// depends on information not known to YG they must perform this dirty+// marking manually.+WIN_EXPORT void YGNodeMarkDirty(const YGNodeRef node);++// This function marks the current node and all its descendants as dirty. This+// function is added to test yoga benchmarks. This function is not expected to+// be used in production as calling `YGCalculateLayout` will cause the+// recalculation of each and every node.+WIN_EXPORT void YGNodeMarkDirtyAndPropogateToDescendants(const YGNodeRef node);++WIN_EXPORT void YGNodePrint(const YGNodeRef node, const YGPrintOptions options);++WIN_EXPORT bool YGFloatIsUndefined(const float value);++WIN_EXPORT bool YGNodeCanUseCachedMeasurement(+    const YGMeasureMode widthMode,+    const float width,+    const YGMeasureMode heightMode,+    const float height,+    const YGMeasureMode lastWidthMode,+    const float lastWidth,+    const YGMeasureMode lastHeightMode,+    const float lastHeight,+    const float lastComputedWidth,+    const float lastComputedHeight,+    const float marginRow,+    const float marginColumn,+    const YGConfigRef config);++WIN_EXPORT void YGNodeCopyStyle(+    const YGNodeRef dstNode,+    const YGNodeRef srcNode);++WIN_EXPORT void* YGNodeGetContext(YGNodeRef node);+WIN_EXPORT void YGNodeSetContext(YGNodeRef node, void* context);+void YGConfigSetPrintTreeFlag(YGConfigRef config, bool enabled);+YGMeasureFunc YGNodeGetMeasureFunc(YGNodeRef node);+WIN_EXPORT void YGNodeSetMeasureFunc(YGNodeRef node, YGMeasureFunc measureFunc);+YGBaselineFunc YGNodeGetBaselineFunc(YGNodeRef node);+void YGNodeSetBaselineFunc(YGNodeRef node, YGBaselineFunc baselineFunc);+YGDirtiedFunc YGNodeGetDirtiedFunc(YGNodeRef node);+void YGNodeSetDirtiedFunc(YGNodeRef node, YGDirtiedFunc dirtiedFunc);+YGPrintFunc YGNodeGetPrintFunc(YGNodeRef node);+void YGNodeSetPrintFunc(YGNodeRef node, YGPrintFunc printFunc);+bool YGNodeGetHasNewLayout(YGNodeRef node);+void YGNodeSetHasNewLayout(YGNodeRef node, bool hasNewLayout);+YGNodeType YGNodeGetNodeType(YGNodeRef node);+void YGNodeSetNodeType(YGNodeRef node, YGNodeType nodeType);+bool YGNodeIsDirty(YGNodeRef node);+bool YGNodeLayoutGetDidUseLegacyFlag(const YGNodeRef node);++WIN_EXPORT void YGNodeStyleSetDirection(+    const YGNodeRef node,+    const YGDirection direction);+WIN_EXPORT YGDirection YGNodeStyleGetDirection(const YGNodeRef node);++WIN_EXPORT void YGNodeStyleSetFlexDirection(+    const YGNodeRef node,+    const YGFlexDirection flexDirection);+WIN_EXPORT YGFlexDirection YGNodeStyleGetFlexDirection(const YGNodeRef node);++WIN_EXPORT void YGNodeStyleSetJustifyContent(+    const YGNodeRef node,+    const YGJustify justifyContent);+WIN_EXPORT YGJustify YGNodeStyleGetJustifyContent(const YGNodeRef node);++WIN_EXPORT void YGNodeStyleSetAlignContent(+    const YGNodeRef node,+    const YGAlign alignContent);+WIN_EXPORT YGAlign YGNodeStyleGetAlignContent(const YGNodeRef node);++WIN_EXPORT void YGNodeStyleSetAlignItems(+    const YGNodeRef node,+    const YGAlign alignItems);+WIN_EXPORT YGAlign YGNodeStyleGetAlignItems(const YGNodeRef node);++WIN_EXPORT void YGNodeStyleSetAlignSelf(+    const YGNodeRef node,+    const YGAlign alignSelf);+WIN_EXPORT YGAlign YGNodeStyleGetAlignSelf(const YGNodeRef node);++WIN_EXPORT void YGNodeStyleSetPositionType(+    const YGNodeRef node,+    const YGPositionType positionType);+WIN_EXPORT YGPositionType YGNodeStyleGetPositionType(const YGNodeRef node);++WIN_EXPORT void YGNodeStyleSetFlexWrap(+    const YGNodeRef node,+    const YGWrap flexWrap);+WIN_EXPORT YGWrap YGNodeStyleGetFlexWrap(const YGNodeRef node);++WIN_EXPORT void YGNodeStyleSetOverflow(+    const YGNodeRef node,+    const YGOverflow overflow);+WIN_EXPORT YGOverflow YGNodeStyleGetOverflow(const YGNodeRef node);++WIN_EXPORT void YGNodeStyleSetDisplay(+    const YGNodeRef node,+    const YGDisplay display);+WIN_EXPORT YGDisplay YGNodeStyleGetDisplay(const YGNodeRef node);++WIN_EXPORT void YGNodeStyleSetFlex(const YGNodeRef node, const float flex);+WIN_EXPORT float YGNodeStyleGetFlex(const YGNodeRef node);++WIN_EXPORT void YGNodeStyleSetFlexGrow(+    const YGNodeRef node,+    const float flexGrow);+WIN_EXPORT float YGNodeStyleGetFlexGrow(const YGNodeRef node);++WIN_EXPORT void YGNodeStyleSetFlexShrink(+    const YGNodeRef node,+    const float flexShrink);+WIN_EXPORT float YGNodeStyleGetFlexShrink(const YGNodeRef node);++WIN_EXPORT void YGNodeStyleSetFlexBasis(+    const YGNodeRef node,+    const float flexBasis);+WIN_EXPORT void YGNodeStyleSetFlexBasisPercent(+    const YGNodeRef node,+    const float flexBasis);+WIN_EXPORT void YGNodeStyleSetFlexBasisAuto(const YGNodeRef node);+WIN_EXPORT YGValue YGNodeStyleGetFlexBasis(const YGNodeRef node);++WIN_EXPORT void YGNodeStyleSetPosition(+    const YGNodeRef node,+    const YGEdge edge,+    const float position);+WIN_EXPORT void YGNodeStyleSetPositionPercent(+    const YGNodeRef node,+    const YGEdge edge,+    const float position);+WIN_EXPORT WIN_STRUCT(YGValue)+    YGNodeStyleGetPosition(const YGNodeRef node, const YGEdge edge);++WIN_EXPORT void YGNodeStyleSetMargin(+    const YGNodeRef node,+    const YGEdge edge,+    const float margin);+WIN_EXPORT void YGNodeStyleSetMarginPercent(+    const YGNodeRef node,+    const YGEdge edge,+    const float margin);+WIN_EXPORT void YGNodeStyleSetMarginAuto(+    const YGNodeRef node,+    const YGEdge edge);+WIN_EXPORT YGValue+YGNodeStyleGetMargin(const YGNodeRef node, const YGEdge edge);++WIN_EXPORT void YGNodeStyleSetPadding(+    const YGNodeRef node,+    const YGEdge edge,+    const float padding);+WIN_EXPORT void YGNodeStyleSetPaddingPercent(+    const YGNodeRef node,+    const YGEdge edge,+    const float padding);+WIN_EXPORT YGValue+YGNodeStyleGetPadding(const YGNodeRef node, const YGEdge edge);++WIN_EXPORT void YGNodeStyleSetBorder(+    const YGNodeRef node,+    const YGEdge edge,+    const float border);+WIN_EXPORT float YGNodeStyleGetBorder(const YGNodeRef node, const YGEdge edge);++WIN_EXPORT void YGNodeStyleSetWidth(const YGNodeRef node, const float width);+WIN_EXPORT void YGNodeStyleSetWidthPercent(+    const YGNodeRef node,+    const float width);+WIN_EXPORT void YGNodeStyleSetWidthAuto(const YGNodeRef node);+WIN_EXPORT YGValue YGNodeStyleGetWidth(const YGNodeRef node);++WIN_EXPORT void YGNodeStyleSetHeight(const YGNodeRef node, const float height);+WIN_EXPORT void YGNodeStyleSetHeightPercent(+    const YGNodeRef node,+    const float height);+WIN_EXPORT void YGNodeStyleSetHeightAuto(const YGNodeRef node);+WIN_EXPORT YGValue YGNodeStyleGetHeight(const YGNodeRef node);++WIN_EXPORT void YGNodeStyleSetMinWidth(+    const YGNodeRef node,+    const float minWidth);+WIN_EXPORT void YGNodeStyleSetMinWidthPercent(+    const YGNodeRef node,+    const float minWidth);+WIN_EXPORT YGValue YGNodeStyleGetMinWidth(const YGNodeRef node);++WIN_EXPORT void YGNodeStyleSetMinHeight(+    const YGNodeRef node,+    const float minHeight);+WIN_EXPORT void YGNodeStyleSetMinHeightPercent(+    const YGNodeRef node,+    const float minHeight);+WIN_EXPORT YGValue YGNodeStyleGetMinHeight(const YGNodeRef node);++WIN_EXPORT void YGNodeStyleSetMaxWidth(+    const YGNodeRef node,+    const float maxWidth);+WIN_EXPORT void YGNodeStyleSetMaxWidthPercent(+    const YGNodeRef node,+    const float maxWidth);+WIN_EXPORT YGValue YGNodeStyleGetMaxWidth(const YGNodeRef node);++WIN_EXPORT void YGNodeStyleSetMaxHeight(+    const YGNodeRef node,+    const float maxHeight);+WIN_EXPORT void YGNodeStyleSetMaxHeightPercent(+    const YGNodeRef node,+    const float maxHeight);+WIN_EXPORT YGValue YGNodeStyleGetMaxHeight(const YGNodeRef node);++// Yoga specific properties, not compatible with flexbox specification+// Aspect ratio control the size of the undefined dimension of a node.+// Aspect ratio is encoded as a floating point value width/height. e.g. A value+// of 2 leads to a node with a width twice the size of its height while a value+// of 0.5 gives the opposite effect.+//+// - On a node with a set width/height aspect ratio control the size of the+// unset dimension+// - On a node with a set flex basis aspect ratio controls the size of the node+// in the cross axis if unset+// - On a node with a measure function aspect ratio works as though the measure+// function measures the flex basis+// - On a node with flex grow/shrink aspect ratio controls the size of the node+// in the cross axis if unset+// - Aspect ratio takes min/max dimensions into account+WIN_EXPORT void YGNodeStyleSetAspectRatio(+    const YGNodeRef node,+    const float aspectRatio);+WIN_EXPORT float YGNodeStyleGetAspectRatio(const YGNodeRef node);++WIN_EXPORT float YGNodeLayoutGetLeft(const YGNodeRef node);+WIN_EXPORT float YGNodeLayoutGetTop(const YGNodeRef node);+WIN_EXPORT float YGNodeLayoutGetRight(const YGNodeRef node);+WIN_EXPORT float YGNodeLayoutGetBottom(const YGNodeRef node);+WIN_EXPORT float YGNodeLayoutGetWidth(const YGNodeRef node);+WIN_EXPORT float YGNodeLayoutGetHeight(const YGNodeRef node);+WIN_EXPORT YGDirection YGNodeLayoutGetDirection(const YGNodeRef node);+WIN_EXPORT bool YGNodeLayoutGetHadOverflow(const YGNodeRef node);+bool YGNodeLayoutGetDidLegacyStretchFlagAffectLayout(const YGNodeRef node);++// Get the computed values for these nodes after performing layout. If they were+// set using point values then the returned value will be the same as+// YGNodeStyleGetXXX. However if they were set using a percentage value then the+// returned value is the computed value used during layout.+WIN_EXPORT float YGNodeLayoutGetMargin(const YGNodeRef node, const YGEdge edge);+WIN_EXPORT float YGNodeLayoutGetBorder(const YGNodeRef node, const YGEdge edge);+WIN_EXPORT float YGNodeLayoutGetPadding(+    const YGNodeRef node,+    const YGEdge edge);++WIN_EXPORT void YGConfigSetLogger(const YGConfigRef config, YGLogger logger);+WIN_EXPORT void+YGLog(const YGNodeRef node, YGLogLevel level, const char* message, ...);+WIN_EXPORT void YGLogWithConfig(+    const YGConfigRef config,+    YGLogLevel level,+    const char* format,+    ...);+WIN_EXPORT void YGAssert(const bool condition, const char* message);+WIN_EXPORT void YGAssertWithNode(+    const YGNodeRef node,+    const bool condition,+    const char* message);+WIN_EXPORT void YGAssertWithConfig(+    const YGConfigRef config,+    const bool condition,+    const char* message);+// Set this to number of pixels in 1 point to round calculation results+// If you want to avoid rounding - set PointScaleFactor to 0+WIN_EXPORT void YGConfigSetPointScaleFactor(+    const YGConfigRef config,+    const float pixelsInPoint);+void YGConfigSetShouldDiffLayoutWithoutLegacyStretchBehaviour(+    const YGConfigRef config,+    const bool shouldDiffLayout);++// Yoga previously had an error where containers would take the maximum space+// possible instead of the minimum like they are supposed to. In practice this+// resulted in implicit behaviour similar to align-self: stretch; Because this+// was such a long-standing bug we must allow legacy users to switch back to+// this behaviour.+WIN_EXPORT void YGConfigSetUseLegacyStretchBehaviour(+    const YGConfigRef config,+    const bool useLegacyStretchBehaviour);++// YGConfig+WIN_EXPORT YGConfigRef YGConfigNew(void);+WIN_EXPORT void YGConfigFree(const YGConfigRef config);+WIN_EXPORT void YGConfigCopy(const YGConfigRef dest, const YGConfigRef src);+WIN_EXPORT int32_t YGConfigGetInstanceCount(void);++WIN_EXPORT void YGConfigSetExperimentalFeatureEnabled(+    const YGConfigRef config,+    const YGExperimentalFeature feature,+    const bool enabled);+WIN_EXPORT bool YGConfigIsExperimentalFeatureEnabled(+    const YGConfigRef config,+    const YGExperimentalFeature feature);++// Using the web defaults is the prefered configuration for new projects.+// Usage of non web defaults should be considered as legacy.+WIN_EXPORT void YGConfigSetUseWebDefaults(+    const YGConfigRef config,+    const bool enabled);+WIN_EXPORT bool YGConfigGetUseWebDefaults(const YGConfigRef config);++WIN_EXPORT void YGConfigSetCloneNodeFunc(+    const YGConfigRef config,+    const YGCloneNodeFunc callback);++// Export only for C#+WIN_EXPORT YGConfigRef YGConfigGetDefault(void);++WIN_EXPORT void YGConfigSetContext(const YGConfigRef config, void* context);+WIN_EXPORT void* YGConfigGetContext(const YGConfigRef config);++WIN_EXPORT float YGRoundValueToPixelGrid(+    const float value,+    const float pointScaleFactor,+    const bool forceCeil,+    const bool forceFloor);++YG_EXTERN_C_END++#ifdef __cplusplus++#include <functional>+#include <vector>++// Calls f on each node in the tree including the given node argument.+extern void YGTraversePreOrder(+    YGNodeRef const node,+    std::function<void(YGNodeRef node)>&& f);++extern void YGNodeSetChildren(+    YGNodeRef const owner,+    const std::vector<YGNodeRef>& children);++#endif