[dali_1.3.25] Merge branch 'devel/master' 37/179537/1
authorgreynaga <g.reynaga@samsung.com>
Fri, 18 May 2018 11:04:21 +0000 (12:04 +0100)
committergreynaga <g.reynaga@samsung.com>
Fri, 18 May 2018 11:04:21 +0000 (12:04 +0100)
Change-Id: Ide312a0f2de229321ce383ed71aa74b5f569e073

227 files changed:
.gitignore
automated-tests/src/dali-toolkit-third-party/CMakeLists.txt
automated-tests/src/dali-toolkit-third-party/facebook-flexbox/layout-test-utils.c [deleted file]
automated-tests/src/dali-toolkit-third-party/facebook-flexbox/layout-test-utils.h [deleted file]
automated-tests/src/dali-toolkit-third-party/utc-Dali-Flexbox-Layout.cpp
automated-tests/src/dali-toolkit-third-party/yoga/YGAbsolutePositionTest.cpp [new file with mode: 0644]
automated-tests/src/dali-toolkit-third-party/yoga/YGAlignContentTest.cpp [new file with mode: 0644]
automated-tests/src/dali-toolkit-third-party/yoga/YGAlignItemsTest.cpp [new file with mode: 0644]
automated-tests/src/dali-toolkit-third-party/yoga/YGAlignSelfTest.cpp [new file with mode: 0644]
automated-tests/src/dali-toolkit-third-party/yoga/YGAndroidNewsFeed.cpp [new file with mode: 0644]
automated-tests/src/dali-toolkit-third-party/yoga/YGAspectRatioTest.cpp [new file with mode: 0644]
automated-tests/src/dali-toolkit-third-party/yoga/YGBaselineFuncTest.cpp [new file with mode: 0644]
automated-tests/src/dali-toolkit-third-party/yoga/YGBorderTest.cpp [new file with mode: 0644]
automated-tests/src/dali-toolkit-third-party/yoga/YGComputedMarginTest.cpp [new file with mode: 0644]
automated-tests/src/dali-toolkit-third-party/yoga/YGComputedPaddingTest.cpp [new file with mode: 0644]
automated-tests/src/dali-toolkit-third-party/yoga/YGDefaultValuesTest.cpp [new file with mode: 0644]
automated-tests/src/dali-toolkit-third-party/yoga/YGDimensionTest.cpp [new file with mode: 0644]
automated-tests/src/dali-toolkit-third-party/yoga/YGDirtiedTest.cpp [new file with mode: 0644]
automated-tests/src/dali-toolkit-third-party/yoga/YGDirtyMarkingTest.cpp [new file with mode: 0644]
automated-tests/src/dali-toolkit-third-party/yoga/YGDisplayTest.cpp [new file with mode: 0644]
automated-tests/src/dali-toolkit-third-party/yoga/YGEdgeTest.cpp [new file with mode: 0644]
automated-tests/src/dali-toolkit-third-party/yoga/YGFlexDirectionTest.cpp [new file with mode: 0644]
automated-tests/src/dali-toolkit-third-party/yoga/YGFlexTest.cpp [new file with mode: 0644]
automated-tests/src/dali-toolkit-third-party/yoga/YGFlexWrapTest.cpp [new file with mode: 0644]
automated-tests/src/dali-toolkit-third-party/yoga/YGHadOverflowTest.cpp [new file with mode: 0644]
automated-tests/src/dali-toolkit-third-party/yoga/YGInfiniteHeightTest.cpp [new file with mode: 0644]
automated-tests/src/dali-toolkit-third-party/yoga/YGJustifyContentTest.cpp [new file with mode: 0644]
automated-tests/src/dali-toolkit-third-party/yoga/YGLayoutDiffingTest.cpp [new file with mode: 0644]
automated-tests/src/dali-toolkit-third-party/yoga/YGLoggerTest.cpp [new file with mode: 0644]
automated-tests/src/dali-toolkit-third-party/yoga/YGMarginTest.cpp [new file with mode: 0644]
automated-tests/src/dali-toolkit-third-party/yoga/YGMeasureCacheTest.cpp [new file with mode: 0644]
automated-tests/src/dali-toolkit-third-party/yoga/YGMeasureModeTest.cpp [new file with mode: 0644]
automated-tests/src/dali-toolkit-third-party/yoga/YGMeasureTest.cpp [new file with mode: 0644]
automated-tests/src/dali-toolkit-third-party/yoga/YGMinMaxDimensionTest.cpp [new file with mode: 0644]
automated-tests/src/dali-toolkit-third-party/yoga/YGNodeChildTest.cpp [new file with mode: 0644]
automated-tests/src/dali-toolkit-third-party/yoga/YGPaddingTest.cpp [new file with mode: 0644]
automated-tests/src/dali-toolkit-third-party/yoga/YGPercentageTest.cpp [new file with mode: 0644]
automated-tests/src/dali-toolkit-third-party/yoga/YGPersistenceTest.cpp [new file with mode: 0644]
automated-tests/src/dali-toolkit-third-party/yoga/YGRelayoutTest.cpp [new file with mode: 0644]
automated-tests/src/dali-toolkit-third-party/yoga/YGRoundingFunctionTest.cpp [new file with mode: 0644]
automated-tests/src/dali-toolkit-third-party/yoga/YGRoundingMeasureFuncTest.cpp [new file with mode: 0644]
automated-tests/src/dali-toolkit-third-party/yoga/YGRoundingTest.cpp [new file with mode: 0644]
automated-tests/src/dali-toolkit-third-party/yoga/YGSizeOverflowTest.cpp [new file with mode: 0644]
automated-tests/src/dali-toolkit-third-party/yoga/YGStyleTest.cpp [new file with mode: 0644]
automated-tests/src/dali-toolkit-third-party/yoga/YGTraversalTest.cpp [new file with mode: 0644]
automated-tests/src/dali-toolkit-third-party/yoga/YGTreeMutationTest.cpp [new file with mode: 0644]
automated-tests/src/dali-toolkit-third-party/yoga/YGZeroOutLayoutRecursivlyTest.cpp [new file with mode: 0644]
automated-tests/src/dali-toolkit/CMakeLists.txt
automated-tests/src/dali-toolkit/dali-toolkit-test-utils/test-application.h
automated-tests/src/dali-toolkit/dali-toolkit-test-utils/test-gesture-manager.h
automated-tests/src/dali-toolkit/dali-toolkit-test-utils/test-gl-abstraction.h
automated-tests/src/dali-toolkit/dali-toolkit-test-utils/test-gl-sync-abstraction.h
automated-tests/src/dali-toolkit/dali-toolkit-test-utils/test-native-image.h
automated-tests/src/dali-toolkit/dali-toolkit-test-utils/test-platform-abstraction.h
automated-tests/src/dali-toolkit/dali-toolkit-test-utils/test-render-controller.h
automated-tests/src/dali-toolkit/dali-toolkit-test-utils/toolkit-application.cpp
automated-tests/src/dali-toolkit/dali-toolkit-test-utils/toolkit-clipboard-event-notifier.cpp
automated-tests/src/dali-toolkit/dali-toolkit-test-utils/toolkit-clipboard.h
automated-tests/src/dali-toolkit/dali-toolkit-test-utils/toolkit-event-thread-callback.h
automated-tests/src/dali-toolkit/dali-toolkit-test-utils/toolkit-file-loader.cpp
automated-tests/src/dali-toolkit/dali-toolkit-test-utils/toolkit-orientation.cpp
automated-tests/src/dali-toolkit/dali-toolkit-test-utils/toolkit-physical-keyboard.cpp
automated-tests/src/dali-toolkit/dali-toolkit-test-utils/toolkit-singleton-service.cpp
automated-tests/src/dali-toolkit/dali-toolkit-test-utils/toolkit-singleton-service.h [new file with mode: 0644]
automated-tests/src/dali-toolkit/dali-toolkit-test-utils/toolkit-style-monitor.cpp
automated-tests/src/dali-toolkit/dali-toolkit-test-utils/toolkit-test-application.h
automated-tests/src/dali-toolkit/dali-toolkit-test-utils/toolkit-timer.cpp
automated-tests/src/dali-toolkit/utc-Dali-ImageVisual.cpp
automated-tests/src/dali-toolkit/utc-Dali-Layouting.cpp [new file with mode: 0644]
build/tizen/dali-toolkit/Makefile.am
build/tizen/docs-internal/dali-internal.doxy.in
build/tizen/docs/dali.doxy.in
dali-toolkit/devel-api/builder/builder.h [changed mode: 0644->0755]
dali-toolkit/devel-api/builder/json-parser.h
dali-toolkit/devel-api/builder/tree-node.h
dali-toolkit/devel-api/controls/bloom-view/bloom-view.h
dali-toolkit/devel-api/controls/bubble-effect/bubble-emitter.h
dali-toolkit/devel-api/controls/buttons/toggle-button.h
dali-toolkit/devel-api/controls/control-devel.cpp
dali-toolkit/devel-api/controls/control-devel.h
dali-toolkit/devel-api/controls/control-wrapper-impl.h
dali-toolkit/devel-api/controls/control-wrapper.h
dali-toolkit/devel-api/controls/effects-view/effects-view.h
dali-toolkit/devel-api/controls/gaussian-blur-view/gaussian-blur-view.h
dali-toolkit/devel-api/controls/magnifier/magnifier.h
dali-toolkit/devel-api/controls/navigation-view/navigation-view.h
dali-toolkit/devel-api/controls/page-turn-view/page-factory.h
dali-toolkit/devel-api/controls/page-turn-view/page-turn-landscape-view.h
dali-toolkit/devel-api/controls/page-turn-view/page-turn-portrait-view.h
dali-toolkit/devel-api/controls/page-turn-view/page-turn-view.h
dali-toolkit/devel-api/controls/popup/confirmation-popup.h
dali-toolkit/devel-api/controls/popup/popup.h
dali-toolkit/devel-api/controls/shadow-view/shadow-view.h
dali-toolkit/devel-api/controls/super-blur-view/super-blur-view.h
dali-toolkit/devel-api/controls/text-controls/text-editor-devel.cpp
dali-toolkit/devel-api/controls/text-controls/text-editor-devel.h
dali-toolkit/devel-api/controls/text-controls/text-field-devel.cpp
dali-toolkit/devel-api/controls/text-controls/text-field-devel.h
dali-toolkit/devel-api/controls/text-controls/text-selection-popup.h
dali-toolkit/devel-api/controls/text-controls/text-selection-toolbar.h
dali-toolkit/devel-api/controls/tool-bar/tool-bar.h
dali-toolkit/devel-api/file.list
dali-toolkit/devel-api/focus-manager/keyboard-focus-manager-devel.h
dali-toolkit/devel-api/focus-manager/keyinput-focus-manager.h
dali-toolkit/devel-api/image-loader/async-image-loader-devel.h
dali-toolkit/devel-api/image-loader/atlas-upload-observer.h
dali-toolkit/devel-api/image-loader/image-atlas.h
dali-toolkit/devel-api/image-loader/texture-manager.h [changed mode: 0644->0755]
dali-toolkit/devel-api/layouting/child-layout-data.h [new file with mode: 0644]
dali-toolkit/devel-api/layouting/hbox-layout.cpp [new file with mode: 0644]
dali-toolkit/devel-api/layouting/hbox-layout.h [new file with mode: 0644]
dali-toolkit/devel-api/layouting/layout-controller.cpp [new file with mode: 0644]
dali-toolkit/devel-api/layouting/layout-controller.h [new file with mode: 0644]
dali-toolkit/devel-api/layouting/layout-group-impl.cpp [new file with mode: 0644]
dali-toolkit/devel-api/layouting/layout-group-impl.h [new file with mode: 0644]
dali-toolkit/devel-api/layouting/layout-group.cpp [new file with mode: 0644]
dali-toolkit/devel-api/layouting/layout-group.h [new file with mode: 0644]
dali-toolkit/devel-api/layouting/layout-item-impl.cpp [new file with mode: 0644]
dali-toolkit/devel-api/layouting/layout-item-impl.h [new file with mode: 0644]
dali-toolkit/devel-api/layouting/layout-item.cpp [new file with mode: 0644]
dali-toolkit/devel-api/layouting/layout-item.h [new file with mode: 0644]
dali-toolkit/devel-api/layouting/layout-length.h [new file with mode: 0644]
dali-toolkit/devel-api/layouting/layout-parent-impl.h [new file with mode: 0644]
dali-toolkit/devel-api/layouting/layout-size.h [new file with mode: 0644]
dali-toolkit/devel-api/layouting/measure-spec.h [new file with mode: 0644]
dali-toolkit/devel-api/layouting/measured-size.h [new file with mode: 0644]
dali-toolkit/devel-api/layouting/vbox-layout.cpp [new file with mode: 0644]
dali-toolkit/devel-api/layouting/vbox-layout.h [new file with mode: 0644]
dali-toolkit/devel-api/scripting/script-plugin.h
dali-toolkit/devel-api/scripting/script.h
dali-toolkit/devel-api/styling/style-manager-devel.h
dali-toolkit/devel-api/transition-effects/cube-transition-cross-effect.h
dali-toolkit/devel-api/transition-effects/cube-transition-effect.h [changed mode: 0644->0755]
dali-toolkit/devel-api/transition-effects/cube-transition-fold-effect.h
dali-toolkit/devel-api/transition-effects/cube-transition-wave-effect.h
dali-toolkit/devel-api/visual-factory/transition-data.h [changed mode: 0644->0755]
dali-toolkit/devel-api/visual-factory/visual-base.h [changed mode: 0644->0755]
dali-toolkit/devel-api/visual-factory/visual-factory.h
dali-toolkit/internal/builder/builder-impl.h [changed mode: 0644->0755]
dali-toolkit/internal/builder/json-parser-state.h
dali-toolkit/internal/builder/tree-node-manipulator.h
dali-toolkit/internal/controls/control/control-data-impl.cpp
dali-toolkit/internal/controls/control/control-data-impl.h
dali-toolkit/internal/controls/flex-container/flex-container-impl.cpp
dali-toolkit/internal/controls/flex-container/flex-container-impl.h
dali-toolkit/internal/controls/scrollable/item-view/grid-layout.h
dali-toolkit/internal/file.list
dali-toolkit/internal/layouting/hbox-layout-impl.cpp [new file with mode: 0644]
dali-toolkit/internal/layouting/hbox-layout-impl.h [new file with mode: 0644]
dali-toolkit/internal/layouting/layout-controller-debug.cpp [new file with mode: 0644]
dali-toolkit/internal/layouting/layout-controller-debug.h [new file with mode: 0644]
dali-toolkit/internal/layouting/layout-controller-impl.cpp [new file with mode: 0644]
dali-toolkit/internal/layouting/layout-controller-impl.h [new file with mode: 0644]
dali-toolkit/internal/layouting/layout-group-data-impl.cpp [new file with mode: 0644]
dali-toolkit/internal/layouting/layout-group-data-impl.h [new file with mode: 0644]
dali-toolkit/internal/layouting/layout-item-data-impl.cpp [new file with mode: 0644]
dali-toolkit/internal/layouting/layout-item-data-impl.h [new file with mode: 0644]
dali-toolkit/internal/layouting/vbox-layout-impl.cpp [new file with mode: 0644]
dali-toolkit/internal/layouting/vbox-layout-impl.h [new file with mode: 0644]
dali-toolkit/internal/visuals/texture-upload-observer.h
dali-toolkit/internal/visuals/visual-base-data-impl.cpp
dali-toolkit/internal/visuals/visual-base-impl.cpp
dali-toolkit/internal/visuals/visual-base-impl.h
dali-toolkit/public-api/accessibility-manager/accessibility-manager.h [changed mode: 0644->0755]
dali-toolkit/public-api/controls/alignment/alignment.h
dali-toolkit/public-api/controls/buttons/button.h
dali-toolkit/public-api/controls/buttons/check-box-button.h
dali-toolkit/public-api/controls/buttons/push-button.h
dali-toolkit/public-api/controls/buttons/radio-button.h
dali-toolkit/public-api/controls/control-impl.h
dali-toolkit/public-api/controls/control.h
dali-toolkit/public-api/controls/flex-container/flex-container.h
dali-toolkit/public-api/controls/image-view/image-view.h
dali-toolkit/public-api/controls/model3d-view/model3d-view.h
dali-toolkit/public-api/controls/progress-bar/progress-bar.h
dali-toolkit/public-api/controls/scroll-bar/scroll-bar.h
dali-toolkit/public-api/controls/scrollable/item-view/default-item-layout.h
dali-toolkit/public-api/controls/scrollable/item-view/item-factory.h
dali-toolkit/public-api/controls/scrollable/item-view/item-layout.h
dali-toolkit/public-api/controls/scrollable/item-view/item-view.h
dali-toolkit/public-api/controls/scrollable/scroll-view/scroll-view-constraints.h [changed mode: 0644->0755]
dali-toolkit/public-api/controls/scrollable/scroll-view/scroll-view-effect.h [changed mode: 0644->0755]
dali-toolkit/public-api/controls/scrollable/scroll-view/scroll-view-page-path-effect.h [changed mode: 0644->0755]
dali-toolkit/public-api/controls/scrollable/scroll-view/scroll-view.h
dali-toolkit/public-api/controls/scrollable/scrollable.h
dali-toolkit/public-api/controls/slider/slider.h
dali-toolkit/public-api/controls/table-view/table-view.h
dali-toolkit/public-api/controls/text-controls/text-editor.h
dali-toolkit/public-api/controls/text-controls/text-field.h
dali-toolkit/public-api/controls/text-controls/text-label.h
dali-toolkit/public-api/controls/video-view/video-view.h
dali-toolkit/public-api/dali-toolkit-common.h [new file with mode: 0755]
dali-toolkit/public-api/dali-toolkit-version.cpp
dali-toolkit/public-api/dali-toolkit-version.h [changed mode: 0644->0755]
dali-toolkit/public-api/enums.h
dali-toolkit/public-api/file.list
dali-toolkit/public-api/focus-manager/keyboard-focus-manager.h
dali-toolkit/public-api/image-loader/async-image-loader.h [changed mode: 0644->0755]
dali-toolkit/public-api/image-loader/sync-image-loader.h [changed mode: 0644->0755]
dali-toolkit/public-api/styling/style-manager.h
dali-toolkit/third-party/facebook-flexbox/layout.c [deleted file]
dali-toolkit/third-party/facebook-flexbox/layout.h [deleted file]
dali-toolkit/third-party/file.list
dali-toolkit/third-party/yoga/Utils.cpp [new file with mode: 0644]
dali-toolkit/third-party/yoga/Utils.h [new file with mode: 0644]
dali-toolkit/third-party/yoga/YGConfig.cpp [new file with mode: 0644]
dali-toolkit/third-party/yoga/YGConfig.h [new file with mode: 0644]
dali-toolkit/third-party/yoga/YGEnums.cpp [new file with mode: 0644]
dali-toolkit/third-party/yoga/YGEnums.h [new file with mode: 0644]
dali-toolkit/third-party/yoga/YGFloatOptional.cpp [new file with mode: 0644]
dali-toolkit/third-party/yoga/YGFloatOptional.h [new file with mode: 0644]
dali-toolkit/third-party/yoga/YGLayout.cpp [new file with mode: 0644]
dali-toolkit/third-party/yoga/YGLayout.h [new file with mode: 0644]
dali-toolkit/third-party/yoga/YGMacros.h [new file with mode: 0644]
dali-toolkit/third-party/yoga/YGNode.cpp [new file with mode: 0644]
dali-toolkit/third-party/yoga/YGNode.h [new file with mode: 0644]
dali-toolkit/third-party/yoga/YGNodePrint.cpp [new file with mode: 0644]
dali-toolkit/third-party/yoga/YGNodePrint.h [new file with mode: 0644]
dali-toolkit/third-party/yoga/YGStyle.cpp [new file with mode: 0644]
dali-toolkit/third-party/yoga/YGStyle.h [new file with mode: 0644]
dali-toolkit/third-party/yoga/Yoga-internal.h [new file with mode: 0644]
dali-toolkit/third-party/yoga/Yoga.cpp [new file with mode: 0644]
dali-toolkit/third-party/yoga/Yoga.h [new file with mode: 0644]
packaging/dali-toolkit.spec
plugins/dali-script-v8/src/dali-script-v8.cpp
plugins/dali-script-v8/src/dali-script-v8.h
plugins/dali-script-v8/src/dali-wrapper.h

index d2fa7ba..1f638ab 100644 (file)
@@ -37,3 +37,5 @@ dali.doxy
 /build/tizen/.cov
 /build/desktop
 /packaging/home*
+.vscode/
+core
index 43c4be3..e9ff79a 100644 (file)
@@ -40,7 +40,6 @@ LIST(APPEND TC_SOURCES
    ../dali-toolkit/dali-toolkit-test-utils/test-render-controller.cpp
    ../dali-toolkit/dali-toolkit-test-utils/test-trace-call-stack.cpp
    ../dali-toolkit/dali-toolkit-test-utils/test-native-image.cpp
-   facebook-flexbox/layout-test-utils.c
 )
 
 
@@ -50,6 +49,10 @@ PKG_CHECK_MODULES(${CAPI_LIB} REQUIRED
     dali-toolkit
 )
 
+# Locate GTest
+cmake_minimum_required(VERSION 2.6)
+find_package(GTest REQUIRED)
+
 #ADD_COMPILE_OPTIONS( -O0 -ggdb --coverage -Wall -Werror )
 # ADD_COMPILE_OPTIONS( ${${CAPI_LIB}_CFLAGS_OTHER} )
 # This works for a homogenous C++ project, but not for mixed C++/C project
@@ -65,14 +68,17 @@ ENDFOREACH(directory ${CAPI_LIB_LIBRARY_DIRS})
 
 INCLUDE_DIRECTORIES(
     ../../../
+    ../../../dali-toolkit/third-party
     ${${CAPI_LIB}_INCLUDE_DIRS}
     ../dali-toolkit/dali-toolkit-test-utils
+    ${GTEST_INCLUDE_DIRS}
 )
 
 ADD_EXECUTABLE(${EXEC_NAME} ${EXEC_NAME}.cpp ${TC_SOURCES})
 TARGET_LINK_LIBRARIES(${EXEC_NAME}
     ${${CAPI_LIB}_LIBRARIES}
     -lpthread --coverage
+    ${GTEST_LIBRARIES}
 )
 
 INSTALL(PROGRAMS ${EXEC_NAME}
diff --git a/automated-tests/src/dali-toolkit-third-party/facebook-flexbox/layout-test-utils.c b/automated-tests/src/dali-toolkit-third-party/facebook-flexbox/layout-test-utils.c
deleted file mode 100644 (file)
index 58c42c4..0000000
+++ /dev/null
@@ -1,8461 +0,0 @@
-/**
- * Copyright (c) 2014, 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 "layout-test-utils.h"
-#include <stdlib.h>
-
-#ifdef _MSC_VER
-#include <float.h>
-#define isnan _isnan
-
-/* define fmaxf & fminf if < VC12 */
-#if _MSC_VER < 1800
-inline float fmaxf(const float a, const float b) {
-  return (a > b) ? a : b;
-}
-inline float fminf(const float a, const float b) {
-  return (a < b) ? a : b;
-}
-#endif
-#endif
-
-  /** START_GENERATED **/
-#define SMALL_WIDTH 35
-#define SMALL_HEIGHT 18
-#define BIG_WIDTH 172
-#define BIG_HEIGHT 36
-#define BIG_MIN_WIDTH 100
-#define SMALL_TEXT "small"
-#define LONG_TEXT "loooooooooong with space"
-#define MEASURE_WITH_RATIO_2 "measureWithRatio2"
-#define MEASURE_WITH_MATCH_PARENT "measureWithMatchParent"
-  /** END_GENERATED **/
-
-typedef struct failed_test_t {
-  struct failed_test_t *next;
-  const char *name;
-  css_node_t *style;
-  css_node_t *expected;
-} failed_test_t;
-
-static failed_test_t *failed_test_head = NULL;
-static failed_test_t *failed_test_tail = NULL;
-static void add_failed_test(const char *name, css_node_t *style, css_node_t *expected) {
-  failed_test_t *failed_test = (failed_test_t *)malloc(sizeof(failed_test_t));
-  failed_test->next = NULL;
-  failed_test->name = name;
-  failed_test->style = style;
-  failed_test->expected = expected;
-
-  if (!failed_test_head) {
-    failed_test_head = failed_test;
-    failed_test_tail = failed_test;
-  } else {
-    failed_test_tail->next = failed_test;
-    failed_test_tail = failed_test;
-  }
-}
-
-static bool eq(float a, float b) {
-  return fabs(a - b) < 0.0001;
-}
-
-static bool are_layout_equal(css_node_t *a, css_node_t *b) {
-  if (!eq(a->layout.dimensions[CSS_WIDTH], b->layout.dimensions[CSS_WIDTH]) ||
-      !eq(a->layout.dimensions[CSS_HEIGHT], b->layout.dimensions[CSS_HEIGHT]) ||
-      !eq(a->layout.position[CSS_TOP], b->layout.position[CSS_TOP]) ||
-      !eq(a->layout.position[CSS_LEFT], b->layout.position[CSS_LEFT]) ||
-      !eq(a->children_count, b->children_count)) {
-    return false;
-  }
-  int i;
-  for (i = 0; i < a->children_count; ++i) {
-    if (!are_layout_equal(a->get_child(a->context, i), b->get_child(b->context, i))) {
-      return false;
-    }
-  }
-  return true;
-}
-
-css_dim_t measure(void *context, float width, css_measure_mode_t widthMode, float height, css_measure_mode_t heightMode) {
-  const char *text = (const char *)context;
-  css_dim_t dim;
-  if (strcmp(text, SMALL_TEXT) == 0) {
-    if (widthMode == CSS_MEASURE_MODE_UNDEFINED) {
-      width = 1000000;
-    }
-    dim.dimensions[CSS_WIDTH] = fminf(SMALL_WIDTH, width);
-    dim.dimensions[CSS_HEIGHT] = SMALL_HEIGHT;
-    return dim;
-  }
-  if (strcmp(text, LONG_TEXT) == 0) {
-    if (widthMode == CSS_MEASURE_MODE_UNDEFINED) {
-      width = 1000000;
-    }
-    dim.dimensions[CSS_WIDTH] = width >= BIG_WIDTH ? BIG_WIDTH : fmaxf(BIG_MIN_WIDTH, width);
-    dim.dimensions[CSS_HEIGHT] = width >= BIG_WIDTH ? SMALL_HEIGHT : BIG_HEIGHT;
-    return dim;
-  }
-
-  if (strcmp(text, MEASURE_WITH_RATIO_2) == 0) {
-    if (widthMode != CSS_MEASURE_MODE_UNDEFINED) {
-      dim.dimensions[CSS_WIDTH] = width;
-      dim.dimensions[CSS_HEIGHT] = width * 2;
-    } else if (heightMode != CSS_MEASURE_MODE_UNDEFINED) {
-      dim.dimensions[CSS_WIDTH] = height * 2;
-      dim.dimensions[CSS_HEIGHT] = height;
-    } else {
-      dim.dimensions[CSS_WIDTH] = 99999;
-      dim.dimensions[CSS_HEIGHT] = 99999;
-    }
-    return dim;
-  }
-
-  if (strcmp(text, MEASURE_WITH_MATCH_PARENT) == 0) {
-    if (widthMode == CSS_MEASURE_MODE_UNDEFINED) {
-      width = 99999;
-    }
-    if (heightMode == CSS_MEASURE_MODE_UNDEFINED) {
-      height = 99999;
-    }
-    dim.dimensions[CSS_WIDTH] = width;
-    dim.dimensions[CSS_HEIGHT] = height;
-    return dim;
-  }
-
-  // Should not go here
-  dim.dimensions[CSS_WIDTH] = CSS_UNDEFINED;
-  dim.dimensions[CSS_HEIGHT] = CSS_UNDEFINED;
-  return dim;
-}
-
-static int test_ran_count = 0;
-void test(const char *name, css_node_t *style, css_node_t *expected_layout) {
-  ++test_ran_count;
-  layoutNode(style, CSS_UNDEFINED, CSS_UNDEFINED, (css_direction_t)-1);
-
-  if (!are_layout_equal(style, expected_layout)) {
-    printf("%sF%s", "\x1B[31m", "\x1B[0m");
-    add_failed_test(name, style, expected_layout);
-  } else {
-    printf("%s.%s", "\x1B[32m", "\x1B[0m");
-    free_css_node(style);
-    free_css_node(expected_layout);
-  }
-}
-
-bool tests_finished() {
-  failed_test_t *failed_test = failed_test_head;
-  printf("\n");
-
-  int tests_failed = 0;
-  while (failed_test) {
-    printf("%sFAIL%s %s\n", "\x1B[31m", "\x1B[0m", failed_test->name);
-
-    printf("Input:    ");
-    print_css_node(failed_test->style, (css_print_options_t)(CSS_PRINT_STYLE | CSS_PRINT_CHILDREN));
-    printf("Output:   ");
-    print_css_node(failed_test->style, (css_print_options_t)(CSS_PRINT_LAYOUT | CSS_PRINT_CHILDREN));
-
-    printf("Expected: ");
-    print_css_node(failed_test->expected, (css_print_options_t)(CSS_PRINT_LAYOUT | CSS_PRINT_CHILDREN));
-
-    free_css_node(failed_test->style);
-    free_css_node(failed_test->expected);
-
-    failed_test_t *next_failed_test = failed_test->next;
-    free(failed_test);
-    failed_test = next_failed_test;
-
-    tests_failed++;
-  }
-  printf("\n\n");
-
-  if (tests_failed > 0) {
-    printf("TESTS FAILED: %d\n", tests_failed);
-    return false;
-  } else {
-    printf("ALL TESTS PASSED: %d tests ran.\n", test_ran_count);
-    return true;
-  }
-}
-
-static css_node_t* get_child(void *context, int i) {
-  css_node_t* children = (css_node_t*)context;
-  return &children[i];
-}
-
-static bool is_dirty(void *context) {
-  (void)context; // remove unused warning
-  return true;
-}
-
-static void init_test_css_node(css_node_t *node) {
-  node->get_child = get_child;
-  node->is_dirty = is_dirty;
-}
-
-css_node_t *new_test_css_node(void) {
-  css_node_t *node = new_css_node();
-  init_test_css_node(node);
-  return node;
-}
-
-void init_css_node_children(css_node_t *node, int children_count) {
-  node->context = calloc((size_t)children_count, sizeof(css_node_t));
-  int i;
-  for (i = 0; i < children_count; ++i) {
-    init_css_node(node->get_child(node->context, i));
-    init_test_css_node(node->get_child(node->context, i));
-  }
-  node->children_count = children_count;
-}
-
-// @generated by transpile.html
-
-bool perform_layout_test()
-{
-  /** START_GENERATED **/
-  {
-    css_node_t *root_node = new_test_css_node();
-    {
-      css_node_t *node_0 = root_node;
-      node_0->style.dimensions[CSS_WIDTH] = 100;
-      node_0->style.dimensions[CSS_HEIGHT] = 200;
-    }
-
-    css_node_t *root_layout = new_test_css_node();
-    {
-      css_node_t *node_0 = root_layout;
-      node_0->layout.position[CSS_TOP] = 0;
-      node_0->layout.position[CSS_LEFT] = 0;
-      node_0->layout.dimensions[CSS_WIDTH] = 100;
-      node_0->layout.dimensions[CSS_HEIGHT] = 200;
-    }
-
-    test("should layout a single node with width and height", root_node, root_layout);
-  }
-
-  {
-    css_node_t *root_node = new_test_css_node();
-    {
-      css_node_t *node_0 = root_node;
-      node_0->style.dimensions[CSS_WIDTH] = 1000;
-      node_0->style.dimensions[CSS_HEIGHT] = 1000;
-      init_css_node_children(node_0, 3);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->style.dimensions[CSS_WIDTH] = 500;
-        node_1->style.dimensions[CSS_HEIGHT] = 500;
-        node_1 = node_0->get_child(node_0->context, 1);
-        node_1->style.dimensions[CSS_WIDTH] = 250;
-        node_1->style.dimensions[CSS_HEIGHT] = 250;
-        node_1 = node_0->get_child(node_0->context, 2);
-        node_1->style.dimensions[CSS_WIDTH] = 125;
-        node_1->style.dimensions[CSS_HEIGHT] = 125;
-      }
-    }
-
-    css_node_t *root_layout = new_test_css_node();
-    {
-      css_node_t *node_0 = root_layout;
-      node_0->layout.position[CSS_TOP] = 0;
-      node_0->layout.position[CSS_LEFT] = 0;
-      node_0->layout.dimensions[CSS_WIDTH] = 1000;
-      node_0->layout.dimensions[CSS_HEIGHT] = 1000;
-      init_css_node_children(node_0, 3);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->layout.position[CSS_TOP] = 0;
-        node_1->layout.position[CSS_LEFT] = 0;
-        node_1->layout.dimensions[CSS_WIDTH] = 500;
-        node_1->layout.dimensions[CSS_HEIGHT] = 500;
-        node_1 = node_0->get_child(node_0->context, 1);
-        node_1->layout.position[CSS_TOP] = 500;
-        node_1->layout.position[CSS_LEFT] = 0;
-        node_1->layout.dimensions[CSS_WIDTH] = 250;
-        node_1->layout.dimensions[CSS_HEIGHT] = 250;
-        node_1 = node_0->get_child(node_0->context, 2);
-        node_1->layout.position[CSS_TOP] = 750;
-        node_1->layout.position[CSS_LEFT] = 0;
-        node_1->layout.dimensions[CSS_WIDTH] = 125;
-        node_1->layout.dimensions[CSS_HEIGHT] = 125;
-      }
-    }
-
-    test("should layout node with children", root_node, root_layout);
-  }
-
-  {
-    css_node_t *root_node = new_test_css_node();
-    {
-      css_node_t *node_0 = root_node;
-      node_0->style.flex_direction = CSS_FLEX_DIRECTION_COLUMN_REVERSE;
-      node_0->style.dimensions[CSS_WIDTH] = 1000;
-      node_0->style.dimensions[CSS_HEIGHT] = 1000;
-      init_css_node_children(node_0, 3);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->style.dimensions[CSS_WIDTH] = 500;
-        node_1->style.dimensions[CSS_HEIGHT] = 500;
-        node_1 = node_0->get_child(node_0->context, 1);
-        node_1->style.dimensions[CSS_WIDTH] = 250;
-        node_1->style.dimensions[CSS_HEIGHT] = 250;
-        node_1 = node_0->get_child(node_0->context, 2);
-        node_1->style.dimensions[CSS_WIDTH] = 125;
-        node_1->style.dimensions[CSS_HEIGHT] = 125;
-      }
-    }
-
-    css_node_t *root_layout = new_test_css_node();
-    {
-      css_node_t *node_0 = root_layout;
-      node_0->layout.position[CSS_TOP] = 0;
-      node_0->layout.position[CSS_LEFT] = 0;
-      node_0->layout.dimensions[CSS_WIDTH] = 1000;
-      node_0->layout.dimensions[CSS_HEIGHT] = 1000;
-      init_css_node_children(node_0, 3);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->layout.position[CSS_TOP] = 500;
-        node_1->layout.position[CSS_LEFT] = 0;
-        node_1->layout.dimensions[CSS_WIDTH] = 500;
-        node_1->layout.dimensions[CSS_HEIGHT] = 500;
-        node_1 = node_0->get_child(node_0->context, 1);
-        node_1->layout.position[CSS_TOP] = 250;
-        node_1->layout.position[CSS_LEFT] = 0;
-        node_1->layout.dimensions[CSS_WIDTH] = 250;
-        node_1->layout.dimensions[CSS_HEIGHT] = 250;
-        node_1 = node_0->get_child(node_0->context, 2);
-        node_1->layout.position[CSS_TOP] = 125;
-        node_1->layout.position[CSS_LEFT] = 0;
-        node_1->layout.dimensions[CSS_WIDTH] = 125;
-        node_1->layout.dimensions[CSS_HEIGHT] = 125;
-      }
-    }
-
-    test("should layout node with children in reverse", root_node, root_layout);
-  }
-
-  {
-    css_node_t *root_node = new_test_css_node();
-    {
-      css_node_t *node_0 = root_node;
-      node_0->style.dimensions[CSS_WIDTH] = 1000;
-      node_0->style.dimensions[CSS_HEIGHT] = 1000;
-      init_css_node_children(node_0, 2);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->style.dimensions[CSS_WIDTH] = 500;
-        node_1->style.dimensions[CSS_HEIGHT] = 500;
-        node_1 = node_0->get_child(node_0->context, 1);
-        node_1->style.dimensions[CSS_WIDTH] = 500;
-        node_1->style.dimensions[CSS_HEIGHT] = 500;
-        init_css_node_children(node_1, 2);
-        {
-          css_node_t *node_2;
-          node_2 = node_1->get_child(node_1->context, 0);
-          node_2->style.dimensions[CSS_WIDTH] = 250;
-          node_2->style.dimensions[CSS_HEIGHT] = 250;
-          node_2 = node_1->get_child(node_1->context, 1);
-          node_2->style.dimensions[CSS_WIDTH] = 250;
-          node_2->style.dimensions[CSS_HEIGHT] = 250;
-        }
-      }
-    }
-
-    css_node_t *root_layout = new_test_css_node();
-    {
-      css_node_t *node_0 = root_layout;
-      node_0->layout.position[CSS_TOP] = 0;
-      node_0->layout.position[CSS_LEFT] = 0;
-      node_0->layout.dimensions[CSS_WIDTH] = 1000;
-      node_0->layout.dimensions[CSS_HEIGHT] = 1000;
-      init_css_node_children(node_0, 2);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->layout.position[CSS_TOP] = 0;
-        node_1->layout.position[CSS_LEFT] = 0;
-        node_1->layout.dimensions[CSS_WIDTH] = 500;
-        node_1->layout.dimensions[CSS_HEIGHT] = 500;
-        node_1 = node_0->get_child(node_0->context, 1);
-        node_1->layout.position[CSS_TOP] = 500;
-        node_1->layout.position[CSS_LEFT] = 0;
-        node_1->layout.dimensions[CSS_WIDTH] = 500;
-        node_1->layout.dimensions[CSS_HEIGHT] = 500;
-        init_css_node_children(node_1, 2);
-        {
-          css_node_t *node_2;
-          node_2 = node_1->get_child(node_1->context, 0);
-          node_2->layout.position[CSS_TOP] = 0;
-          node_2->layout.position[CSS_LEFT] = 0;
-          node_2->layout.dimensions[CSS_WIDTH] = 250;
-          node_2->layout.dimensions[CSS_HEIGHT] = 250;
-          node_2 = node_1->get_child(node_1->context, 1);
-          node_2->layout.position[CSS_TOP] = 250;
-          node_2->layout.position[CSS_LEFT] = 0;
-          node_2->layout.dimensions[CSS_WIDTH] = 250;
-          node_2->layout.dimensions[CSS_HEIGHT] = 250;
-        }
-      }
-    }
-
-    test("should layout node with nested children", root_node, root_layout);
-  }
-
-  {
-    css_node_t *root_node = new_test_css_node();
-    {
-      css_node_t *node_0 = root_node;
-      node_0->style.flex_direction = CSS_FLEX_DIRECTION_COLUMN_REVERSE;
-      node_0->style.dimensions[CSS_WIDTH] = 1000;
-      node_0->style.dimensions[CSS_HEIGHT] = 1000;
-      init_css_node_children(node_0, 2);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->style.dimensions[CSS_WIDTH] = 500;
-        node_1->style.dimensions[CSS_HEIGHT] = 500;
-        node_1 = node_0->get_child(node_0->context, 1);
-        node_1->style.flex_direction = CSS_FLEX_DIRECTION_COLUMN_REVERSE;
-        node_1->style.dimensions[CSS_WIDTH] = 500;
-        node_1->style.dimensions[CSS_HEIGHT] = 500;
-        init_css_node_children(node_1, 2);
-        {
-          css_node_t *node_2;
-          node_2 = node_1->get_child(node_1->context, 0);
-          node_2->style.dimensions[CSS_WIDTH] = 250;
-          node_2->style.dimensions[CSS_HEIGHT] = 250;
-          node_2 = node_1->get_child(node_1->context, 1);
-          node_2->style.dimensions[CSS_WIDTH] = 250;
-          node_2->style.dimensions[CSS_HEIGHT] = 250;
-        }
-      }
-    }
-
-    css_node_t *root_layout = new_test_css_node();
-    {
-      css_node_t *node_0 = root_layout;
-      node_0->layout.position[CSS_TOP] = 0;
-      node_0->layout.position[CSS_LEFT] = 0;
-      node_0->layout.dimensions[CSS_WIDTH] = 1000;
-      node_0->layout.dimensions[CSS_HEIGHT] = 1000;
-      init_css_node_children(node_0, 2);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->layout.position[CSS_TOP] = 500;
-        node_1->layout.position[CSS_LEFT] = 0;
-        node_1->layout.dimensions[CSS_WIDTH] = 500;
-        node_1->layout.dimensions[CSS_HEIGHT] = 500;
-        node_1 = node_0->get_child(node_0->context, 1);
-        node_1->layout.position[CSS_TOP] = 0;
-        node_1->layout.position[CSS_LEFT] = 0;
-        node_1->layout.dimensions[CSS_WIDTH] = 500;
-        node_1->layout.dimensions[CSS_HEIGHT] = 500;
-        init_css_node_children(node_1, 2);
-        {
-          css_node_t *node_2;
-          node_2 = node_1->get_child(node_1->context, 0);
-          node_2->layout.position[CSS_TOP] = 250;
-          node_2->layout.position[CSS_LEFT] = 0;
-          node_2->layout.dimensions[CSS_WIDTH] = 250;
-          node_2->layout.dimensions[CSS_HEIGHT] = 250;
-          node_2 = node_1->get_child(node_1->context, 1);
-          node_2->layout.position[CSS_TOP] = 0;
-          node_2->layout.position[CSS_LEFT] = 0;
-          node_2->layout.dimensions[CSS_WIDTH] = 250;
-          node_2->layout.dimensions[CSS_HEIGHT] = 250;
-        }
-      }
-    }
-
-    test("should layout node with nested children in reverse", root_node, root_layout);
-  }
-
-  {
-    css_node_t *root_node = new_test_css_node();
-    {
-      css_node_t *node_0 = root_node;
-      node_0->style.dimensions[CSS_WIDTH] = 100;
-      node_0->style.dimensions[CSS_HEIGHT] = 200;
-      node_0->style.margin[CSS_LEFT] = 10;
-      node_0->style.margin[CSS_TOP] = 10;
-      node_0->style.margin[CSS_RIGHT] = 10;
-      node_0->style.margin[CSS_BOTTOM] = 10;
-      node_0->style.margin[CSS_START] = 10;
-      node_0->style.margin[CSS_END] = 10;
-    }
-
-    css_node_t *root_layout = new_test_css_node();
-    {
-      css_node_t *node_0 = root_layout;
-      node_0->layout.position[CSS_TOP] = 10;
-      node_0->layout.position[CSS_LEFT] = 10;
-      node_0->layout.dimensions[CSS_WIDTH] = 100;
-      node_0->layout.dimensions[CSS_HEIGHT] = 200;
-    }
-
-    test("should layout node with margin", root_node, root_layout);
-  }
-
-  {
-    css_node_t *root_node = new_test_css_node();
-    {
-      css_node_t *node_0 = root_node;
-      node_0->style.dimensions[CSS_WIDTH] = 1000;
-      node_0->style.dimensions[CSS_HEIGHT] = 1000;
-      node_0->style.margin[CSS_LEFT] = 10;
-      node_0->style.margin[CSS_TOP] = 10;
-      node_0->style.margin[CSS_RIGHT] = 10;
-      node_0->style.margin[CSS_BOTTOM] = 10;
-      node_0->style.margin[CSS_START] = 10;
-      node_0->style.margin[CSS_END] = 10;
-      init_css_node_children(node_0, 3);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->style.dimensions[CSS_WIDTH] = 100;
-        node_1->style.dimensions[CSS_HEIGHT] = 100;
-        node_1->style.margin[CSS_LEFT] = 50;
-        node_1->style.margin[CSS_TOP] = 50;
-        node_1->style.margin[CSS_RIGHT] = 50;
-        node_1->style.margin[CSS_BOTTOM] = 50;
-        node_1->style.margin[CSS_START] = 50;
-        node_1->style.margin[CSS_END] = 50;
-        node_1 = node_0->get_child(node_0->context, 1);
-        node_1->style.dimensions[CSS_WIDTH] = 100;
-        node_1->style.dimensions[CSS_HEIGHT] = 100;
-        node_1->style.margin[CSS_LEFT] = 25;
-        node_1->style.margin[CSS_TOP] = 25;
-        node_1->style.margin[CSS_RIGHT] = 25;
-        node_1->style.margin[CSS_BOTTOM] = 25;
-        node_1->style.margin[CSS_START] = 25;
-        node_1->style.margin[CSS_END] = 25;
-        node_1 = node_0->get_child(node_0->context, 2);
-        node_1->style.dimensions[CSS_WIDTH] = 100;
-        node_1->style.dimensions[CSS_HEIGHT] = 100;
-        node_1->style.margin[CSS_LEFT] = 10;
-        node_1->style.margin[CSS_TOP] = 10;
-        node_1->style.margin[CSS_RIGHT] = 10;
-        node_1->style.margin[CSS_BOTTOM] = 10;
-        node_1->style.margin[CSS_START] = 10;
-        node_1->style.margin[CSS_END] = 10;
-      }
-    }
-
-    css_node_t *root_layout = new_test_css_node();
-    {
-      css_node_t *node_0 = root_layout;
-      node_0->layout.position[CSS_TOP] = 10;
-      node_0->layout.position[CSS_LEFT] = 10;
-      node_0->layout.dimensions[CSS_WIDTH] = 1000;
-      node_0->layout.dimensions[CSS_HEIGHT] = 1000;
-      init_css_node_children(node_0, 3);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->layout.position[CSS_TOP] = 50;
-        node_1->layout.position[CSS_LEFT] = 50;
-        node_1->layout.dimensions[CSS_WIDTH] = 100;
-        node_1->layout.dimensions[CSS_HEIGHT] = 100;
-        node_1 = node_0->get_child(node_0->context, 1);
-        node_1->layout.position[CSS_TOP] = 225;
-        node_1->layout.position[CSS_LEFT] = 25;
-        node_1->layout.dimensions[CSS_WIDTH] = 100;
-        node_1->layout.dimensions[CSS_HEIGHT] = 100;
-        node_1 = node_0->get_child(node_0->context, 2);
-        node_1->layout.position[CSS_TOP] = 360;
-        node_1->layout.position[CSS_LEFT] = 10;
-        node_1->layout.dimensions[CSS_WIDTH] = 100;
-        node_1->layout.dimensions[CSS_HEIGHT] = 100;
-      }
-    }
-
-    test("should layout node with several children", root_node, root_layout);
-  }
-
-  {
-    css_node_t *root_node = new_test_css_node();
-    {
-      css_node_t *node_0 = root_node;
-      node_0->style.flex_direction = CSS_FLEX_DIRECTION_COLUMN_REVERSE;
-      node_0->style.dimensions[CSS_WIDTH] = 1000;
-      node_0->style.dimensions[CSS_HEIGHT] = 1000;
-      node_0->style.margin[CSS_LEFT] = 10;
-      node_0->style.margin[CSS_TOP] = 10;
-      node_0->style.margin[CSS_RIGHT] = 10;
-      node_0->style.margin[CSS_BOTTOM] = 10;
-      node_0->style.margin[CSS_START] = 10;
-      node_0->style.margin[CSS_END] = 10;
-      init_css_node_children(node_0, 3);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->style.dimensions[CSS_WIDTH] = 100;
-        node_1->style.dimensions[CSS_HEIGHT] = 100;
-        node_1->style.margin[CSS_LEFT] = 50;
-        node_1->style.margin[CSS_TOP] = 50;
-        node_1->style.margin[CSS_RIGHT] = 50;
-        node_1->style.margin[CSS_BOTTOM] = 50;
-        node_1->style.margin[CSS_START] = 50;
-        node_1->style.margin[CSS_END] = 50;
-        node_1 = node_0->get_child(node_0->context, 1);
-        node_1->style.dimensions[CSS_WIDTH] = 100;
-        node_1->style.dimensions[CSS_HEIGHT] = 100;
-        node_1->style.margin[CSS_LEFT] = 25;
-        node_1->style.margin[CSS_TOP] = 25;
-        node_1->style.margin[CSS_RIGHT] = 25;
-        node_1->style.margin[CSS_BOTTOM] = 25;
-        node_1->style.margin[CSS_START] = 25;
-        node_1->style.margin[CSS_END] = 25;
-        node_1 = node_0->get_child(node_0->context, 2);
-        node_1->style.dimensions[CSS_WIDTH] = 100;
-        node_1->style.dimensions[CSS_HEIGHT] = 100;
-        node_1->style.margin[CSS_LEFT] = 10;
-        node_1->style.margin[CSS_TOP] = 10;
-        node_1->style.margin[CSS_RIGHT] = 10;
-        node_1->style.margin[CSS_BOTTOM] = 10;
-        node_1->style.margin[CSS_START] = 10;
-        node_1->style.margin[CSS_END] = 10;
-      }
-    }
-
-    css_node_t *root_layout = new_test_css_node();
-    {
-      css_node_t *node_0 = root_layout;
-      node_0->layout.position[CSS_TOP] = 10;
-      node_0->layout.position[CSS_LEFT] = 10;
-      node_0->layout.dimensions[CSS_WIDTH] = 1000;
-      node_0->layout.dimensions[CSS_HEIGHT] = 1000;
-      init_css_node_children(node_0, 3);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->layout.position[CSS_TOP] = 850;
-        node_1->layout.position[CSS_LEFT] = 50;
-        node_1->layout.dimensions[CSS_WIDTH] = 100;
-        node_1->layout.dimensions[CSS_HEIGHT] = 100;
-        node_1 = node_0->get_child(node_0->context, 1);
-        node_1->layout.position[CSS_TOP] = 675;
-        node_1->layout.position[CSS_LEFT] = 25;
-        node_1->layout.dimensions[CSS_WIDTH] = 100;
-        node_1->layout.dimensions[CSS_HEIGHT] = 100;
-        node_1 = node_0->get_child(node_0->context, 2);
-        node_1->layout.position[CSS_TOP] = 540;
-        node_1->layout.position[CSS_LEFT] = 10;
-        node_1->layout.dimensions[CSS_WIDTH] = 100;
-        node_1->layout.dimensions[CSS_HEIGHT] = 100;
-      }
-    }
-
-    test("should layout node with several children in reverse", root_node, root_layout);
-  }
-
-  {
-    css_node_t *root_node = new_test_css_node();
-    {
-      css_node_t *node_0 = root_node;
-      node_0->style.direction = CSS_DIRECTION_RTL;
-      node_0->style.flex_direction = CSS_FLEX_DIRECTION_ROW_REVERSE;
-      node_0->style.dimensions[CSS_WIDTH] = 1000;
-      node_0->style.dimensions[CSS_HEIGHT] = 1000;
-      init_css_node_children(node_0, 2);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->style.dimensions[CSS_WIDTH] = 100;
-        node_1->style.dimensions[CSS_HEIGHT] = 200;
-        node_1 = node_0->get_child(node_0->context, 1);
-        node_1->style.dimensions[CSS_WIDTH] = 300;
-        node_1->style.dimensions[CSS_HEIGHT] = 150;
-      }
-    }
-
-    css_node_t *root_layout = new_test_css_node();
-    {
-      css_node_t *node_0 = root_layout;
-      node_0->layout.position[CSS_TOP] = 0;
-      node_0->layout.position[CSS_LEFT] = 0;
-      node_0->layout.dimensions[CSS_WIDTH] = 1000;
-      node_0->layout.dimensions[CSS_HEIGHT] = 1000;
-      init_css_node_children(node_0, 2);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->layout.position[CSS_TOP] = 0;
-        node_1->layout.position[CSS_LEFT] = 0;
-        node_1->layout.dimensions[CSS_WIDTH] = 100;
-        node_1->layout.dimensions[CSS_HEIGHT] = 200;
-        node_1 = node_0->get_child(node_0->context, 1);
-        node_1->layout.position[CSS_TOP] = 0;
-        node_1->layout.position[CSS_LEFT] = 100;
-        node_1->layout.dimensions[CSS_WIDTH] = 300;
-        node_1->layout.dimensions[CSS_HEIGHT] = 150;
-      }
-    }
-
-    test("should layout rtl with reverse correctly", root_node, root_layout);
-  }
-
-  {
-    css_node_t *root_node = new_test_css_node();
-    {
-      css_node_t *node_0 = root_node;
-      node_0->style.flex_direction = CSS_FLEX_DIRECTION_ROW;
-      node_0->style.dimensions[CSS_WIDTH] = 1000;
-      node_0->style.dimensions[CSS_HEIGHT] = 1000;
-      init_css_node_children(node_0, 2);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->style.dimensions[CSS_WIDTH] = 100;
-        node_1->style.dimensions[CSS_HEIGHT] = 200;
-        node_1 = node_0->get_child(node_0->context, 1);
-        node_1->style.dimensions[CSS_WIDTH] = 300;
-        node_1->style.dimensions[CSS_HEIGHT] = 150;
-      }
-    }
-
-    css_node_t *root_layout = new_test_css_node();
-    {
-      css_node_t *node_0 = root_layout;
-      node_0->layout.position[CSS_TOP] = 0;
-      node_0->layout.position[CSS_LEFT] = 0;
-      node_0->layout.dimensions[CSS_WIDTH] = 1000;
-      node_0->layout.dimensions[CSS_HEIGHT] = 1000;
-      init_css_node_children(node_0, 2);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->layout.position[CSS_TOP] = 0;
-        node_1->layout.position[CSS_LEFT] = 0;
-        node_1->layout.dimensions[CSS_WIDTH] = 100;
-        node_1->layout.dimensions[CSS_HEIGHT] = 200;
-        node_1 = node_0->get_child(node_0->context, 1);
-        node_1->layout.position[CSS_TOP] = 0;
-        node_1->layout.position[CSS_LEFT] = 100;
-        node_1->layout.dimensions[CSS_WIDTH] = 300;
-        node_1->layout.dimensions[CSS_HEIGHT] = 150;
-      }
-    }
-
-    test("should layout node with row flex direction", root_node, root_layout);
-  }
-
-  {
-    css_node_t *root_node = new_test_css_node();
-    {
-      css_node_t *node_0 = root_node;
-      node_0->style.direction = CSS_DIRECTION_RTL;
-      node_0->style.flex_direction = CSS_FLEX_DIRECTION_ROW;
-      node_0->style.dimensions[CSS_WIDTH] = 1000;
-      node_0->style.dimensions[CSS_HEIGHT] = 1000;
-      init_css_node_children(node_0, 2);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->style.dimensions[CSS_WIDTH] = 100;
-        node_1->style.dimensions[CSS_HEIGHT] = 200;
-        node_1 = node_0->get_child(node_0->context, 1);
-        node_1->style.dimensions[CSS_WIDTH] = 300;
-        node_1->style.dimensions[CSS_HEIGHT] = 150;
-      }
-    }
-
-    css_node_t *root_layout = new_test_css_node();
-    {
-      css_node_t *node_0 = root_layout;
-      node_0->layout.position[CSS_TOP] = 0;
-      node_0->layout.position[CSS_LEFT] = 0;
-      node_0->layout.dimensions[CSS_WIDTH] = 1000;
-      node_0->layout.dimensions[CSS_HEIGHT] = 1000;
-      init_css_node_children(node_0, 2);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->layout.position[CSS_TOP] = 0;
-        node_1->layout.position[CSS_LEFT] = 900;
-        node_1->layout.dimensions[CSS_WIDTH] = 100;
-        node_1->layout.dimensions[CSS_HEIGHT] = 200;
-        node_1 = node_0->get_child(node_0->context, 1);
-        node_1->layout.position[CSS_TOP] = 0;
-        node_1->layout.position[CSS_LEFT] = 600;
-        node_1->layout.dimensions[CSS_WIDTH] = 300;
-        node_1->layout.dimensions[CSS_HEIGHT] = 150;
-      }
-    }
-
-    test("should layout node with row flex direction in rtl", root_node, root_layout);
-  }
-
-  {
-    css_node_t *root_node = new_test_css_node();
-    {
-      css_node_t *node_0 = root_node;
-      node_0->style.dimensions[CSS_WIDTH] = 300;
-      init_css_node_children(node_0, 2);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->style.dimensions[CSS_WIDTH] = 100;
-        node_1->style.dimensions[CSS_HEIGHT] = 200;
-        node_1 = node_0->get_child(node_0->context, 1);
-        node_1->style.dimensions[CSS_WIDTH] = 300;
-        node_1->style.dimensions[CSS_HEIGHT] = 150;
-      }
-    }
-
-    css_node_t *root_layout = new_test_css_node();
-    {
-      css_node_t *node_0 = root_layout;
-      node_0->layout.position[CSS_TOP] = 0;
-      node_0->layout.position[CSS_LEFT] = 0;
-      node_0->layout.dimensions[CSS_WIDTH] = 300;
-      node_0->layout.dimensions[CSS_HEIGHT] = 350;
-      init_css_node_children(node_0, 2);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->layout.position[CSS_TOP] = 0;
-        node_1->layout.position[CSS_LEFT] = 0;
-        node_1->layout.dimensions[CSS_WIDTH] = 100;
-        node_1->layout.dimensions[CSS_HEIGHT] = 200;
-        node_1 = node_0->get_child(node_0->context, 1);
-        node_1->layout.position[CSS_TOP] = 200;
-        node_1->layout.position[CSS_LEFT] = 0;
-        node_1->layout.dimensions[CSS_WIDTH] = 300;
-        node_1->layout.dimensions[CSS_HEIGHT] = 150;
-      }
-    }
-
-    test("should layout node based on children main dimensions", root_node, root_layout);
-  }
-
-  {
-    css_node_t *root_node = new_test_css_node();
-    {
-      css_node_t *node_0 = root_node;
-      node_0->style.flex_direction = CSS_FLEX_DIRECTION_COLUMN_REVERSE;
-      node_0->style.dimensions[CSS_WIDTH] = 300;
-      init_css_node_children(node_0, 2);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->style.dimensions[CSS_WIDTH] = 100;
-        node_1->style.dimensions[CSS_HEIGHT] = 200;
-        node_1 = node_0->get_child(node_0->context, 1);
-        node_1->style.dimensions[CSS_WIDTH] = 300;
-        node_1->style.dimensions[CSS_HEIGHT] = 150;
-      }
-    }
-
-    css_node_t *root_layout = new_test_css_node();
-    {
-      css_node_t *node_0 = root_layout;
-      node_0->layout.position[CSS_TOP] = 0;
-      node_0->layout.position[CSS_LEFT] = 0;
-      node_0->layout.dimensions[CSS_WIDTH] = 300;
-      node_0->layout.dimensions[CSS_HEIGHT] = 350;
-      init_css_node_children(node_0, 2);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->layout.position[CSS_TOP] = 150;
-        node_1->layout.position[CSS_LEFT] = 0;
-        node_1->layout.dimensions[CSS_WIDTH] = 100;
-        node_1->layout.dimensions[CSS_HEIGHT] = 200;
-        node_1 = node_0->get_child(node_0->context, 1);
-        node_1->layout.position[CSS_TOP] = 0;
-        node_1->layout.position[CSS_LEFT] = 0;
-        node_1->layout.dimensions[CSS_WIDTH] = 300;
-        node_1->layout.dimensions[CSS_HEIGHT] = 150;
-      }
-    }
-
-    test("should layout node based on children main dimensions in reverse", root_node, root_layout);
-  }
-
-  {
-    css_node_t *root_node = new_test_css_node();
-    {
-      css_node_t *node_0 = root_node;
-      node_0->style.dimensions[CSS_WIDTH] = 1000;
-      node_0->style.dimensions[CSS_HEIGHT] = 1000;
-      init_css_node_children(node_0, 2);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->style.dimensions[CSS_WIDTH] = 100;
-        node_1->style.dimensions[CSS_HEIGHT] = 200;
-        node_1 = node_0->get_child(node_0->context, 1);
-        node_1->style.flex = 1;
-        node_1->style.dimensions[CSS_WIDTH] = 100;
-      }
-    }
-
-    css_node_t *root_layout = new_test_css_node();
-    {
-      css_node_t *node_0 = root_layout;
-      node_0->layout.position[CSS_TOP] = 0;
-      node_0->layout.position[CSS_LEFT] = 0;
-      node_0->layout.dimensions[CSS_WIDTH] = 1000;
-      node_0->layout.dimensions[CSS_HEIGHT] = 1000;
-      init_css_node_children(node_0, 2);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->layout.position[CSS_TOP] = 0;
-        node_1->layout.position[CSS_LEFT] = 0;
-        node_1->layout.dimensions[CSS_WIDTH] = 100;
-        node_1->layout.dimensions[CSS_HEIGHT] = 200;
-        node_1 = node_0->get_child(node_0->context, 1);
-        node_1->layout.position[CSS_TOP] = 200;
-        node_1->layout.position[CSS_LEFT] = 0;
-        node_1->layout.dimensions[CSS_WIDTH] = 100;
-        node_1->layout.dimensions[CSS_HEIGHT] = 800;
-      }
-    }
-
-    test("should layout node with just flex", root_node, root_layout);
-  }
-
-  {
-    css_node_t *root_node = new_test_css_node();
-    {
-      css_node_t *node_0 = root_node;
-      node_0->style.flex_direction = CSS_FLEX_DIRECTION_COLUMN_REVERSE;
-      node_0->style.dimensions[CSS_WIDTH] = 1000;
-      node_0->style.dimensions[CSS_HEIGHT] = 1000;
-      init_css_node_children(node_0, 2);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->style.dimensions[CSS_WIDTH] = 100;
-        node_1->style.dimensions[CSS_HEIGHT] = 200;
-        node_1 = node_0->get_child(node_0->context, 1);
-        node_1->style.flex = 1;
-        node_1->style.dimensions[CSS_WIDTH] = 100;
-      }
-    }
-
-    css_node_t *root_layout = new_test_css_node();
-    {
-      css_node_t *node_0 = root_layout;
-      node_0->layout.position[CSS_TOP] = 0;
-      node_0->layout.position[CSS_LEFT] = 0;
-      node_0->layout.dimensions[CSS_WIDTH] = 1000;
-      node_0->layout.dimensions[CSS_HEIGHT] = 1000;
-      init_css_node_children(node_0, 2);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->layout.position[CSS_TOP] = 800;
-        node_1->layout.position[CSS_LEFT] = 0;
-        node_1->layout.dimensions[CSS_WIDTH] = 100;
-        node_1->layout.dimensions[CSS_HEIGHT] = 200;
-        node_1 = node_0->get_child(node_0->context, 1);
-        node_1->layout.position[CSS_TOP] = 0;
-        node_1->layout.position[CSS_LEFT] = 0;
-        node_1->layout.dimensions[CSS_WIDTH] = 100;
-        node_1->layout.dimensions[CSS_HEIGHT] = 800;
-      }
-    }
-
-    test("should layout node with just flex in reverse", root_node, root_layout);
-  }
-
-  {
-    css_node_t *root_node = new_test_css_node();
-    {
-      css_node_t *node_0 = root_node;
-      node_0->style.dimensions[CSS_WIDTH] = 1000;
-      node_0->style.dimensions[CSS_HEIGHT] = 1000;
-      init_css_node_children(node_0, 1);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->style.flex = 1;
-        node_1->style.dimensions[CSS_WIDTH] = 1000;
-        init_css_node_children(node_1, 1);
-        {
-          css_node_t *node_2;
-          node_2 = node_1->get_child(node_1->context, 0);
-          node_2->style.flex = 1;
-          node_2->style.dimensions[CSS_WIDTH] = 1000;
-          init_css_node_children(node_2, 1);
-          {
-            css_node_t *node_3;
-            node_3 = node_2->get_child(node_2->context, 0);
-            node_3->style.flex = 1;
-            node_3->style.dimensions[CSS_WIDTH] = 1000;
-          }
-        }
-      }
-    }
-
-    css_node_t *root_layout = new_test_css_node();
-    {
-      css_node_t *node_0 = root_layout;
-      node_0->layout.position[CSS_TOP] = 0;
-      node_0->layout.position[CSS_LEFT] = 0;
-      node_0->layout.dimensions[CSS_WIDTH] = 1000;
-      node_0->layout.dimensions[CSS_HEIGHT] = 1000;
-      init_css_node_children(node_0, 1);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->layout.position[CSS_TOP] = 0;
-        node_1->layout.position[CSS_LEFT] = 0;
-        node_1->layout.dimensions[CSS_WIDTH] = 1000;
-        node_1->layout.dimensions[CSS_HEIGHT] = 1000;
-        init_css_node_children(node_1, 1);
-        {
-          css_node_t *node_2;
-          node_2 = node_1->get_child(node_1->context, 0);
-          node_2->layout.position[CSS_TOP] = 0;
-          node_2->layout.position[CSS_LEFT] = 0;
-          node_2->layout.dimensions[CSS_WIDTH] = 1000;
-          node_2->layout.dimensions[CSS_HEIGHT] = 1000;
-          init_css_node_children(node_2, 1);
-          {
-            css_node_t *node_3;
-            node_3 = node_2->get_child(node_2->context, 0);
-            node_3->layout.position[CSS_TOP] = 0;
-            node_3->layout.position[CSS_LEFT] = 0;
-            node_3->layout.dimensions[CSS_WIDTH] = 1000;
-            node_3->layout.dimensions[CSS_HEIGHT] = 1000;
-          }
-        }
-      }
-    }
-
-    test("should layout node with flex recursively", root_node, root_layout);
-  }
-
-  {
-    css_node_t *root_node = new_test_css_node();
-    {
-      css_node_t *node_0 = root_node;
-      node_0->style.flex_direction = CSS_FLEX_DIRECTION_COLUMN_REVERSE;
-      node_0->style.dimensions[CSS_WIDTH] = 1000;
-      node_0->style.dimensions[CSS_HEIGHT] = 1000;
-      init_css_node_children(node_0, 1);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->style.flex_direction = CSS_FLEX_DIRECTION_COLUMN_REVERSE;
-        node_1->style.flex = 1;
-        node_1->style.dimensions[CSS_WIDTH] = 1000;
-        init_css_node_children(node_1, 1);
-        {
-          css_node_t *node_2;
-          node_2 = node_1->get_child(node_1->context, 0);
-          node_2->style.flex_direction = CSS_FLEX_DIRECTION_COLUMN_REVERSE;
-          node_2->style.flex = 1;
-          node_2->style.dimensions[CSS_WIDTH] = 1000;
-          init_css_node_children(node_2, 1);
-          {
-            css_node_t *node_3;
-            node_3 = node_2->get_child(node_2->context, 0);
-            node_3->style.flex_direction = CSS_FLEX_DIRECTION_COLUMN_REVERSE;
-            node_3->style.flex = 1;
-            node_3->style.dimensions[CSS_WIDTH] = 1000;
-          }
-        }
-      }
-    }
-
-    css_node_t *root_layout = new_test_css_node();
-    {
-      css_node_t *node_0 = root_layout;
-      node_0->layout.position[CSS_TOP] = 0;
-      node_0->layout.position[CSS_LEFT] = 0;
-      node_0->layout.dimensions[CSS_WIDTH] = 1000;
-      node_0->layout.dimensions[CSS_HEIGHT] = 1000;
-      init_css_node_children(node_0, 1);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->layout.position[CSS_TOP] = 0;
-        node_1->layout.position[CSS_LEFT] = 0;
-        node_1->layout.dimensions[CSS_WIDTH] = 1000;
-        node_1->layout.dimensions[CSS_HEIGHT] = 1000;
-        init_css_node_children(node_1, 1);
-        {
-          css_node_t *node_2;
-          node_2 = node_1->get_child(node_1->context, 0);
-          node_2->layout.position[CSS_TOP] = 0;
-          node_2->layout.position[CSS_LEFT] = 0;
-          node_2->layout.dimensions[CSS_WIDTH] = 1000;
-          node_2->layout.dimensions[CSS_HEIGHT] = 1000;
-          init_css_node_children(node_2, 1);
-          {
-            css_node_t *node_3;
-            node_3 = node_2->get_child(node_2->context, 0);
-            node_3->layout.position[CSS_TOP] = 0;
-            node_3->layout.position[CSS_LEFT] = 0;
-            node_3->layout.dimensions[CSS_WIDTH] = 1000;
-            node_3->layout.dimensions[CSS_HEIGHT] = 1000;
-          }
-        }
-      }
-    }
-
-    test("should layout node with flex recursively in reverse", root_node, root_layout);
-  }
-
-  {
-    css_node_t *root_node = new_test_css_node();
-    {
-      css_node_t *node_0 = root_node;
-      node_0->style.dimensions[CSS_WIDTH] = 1000;
-      node_0->style.dimensions[CSS_HEIGHT] = 1000;
-      node_0->style.margin[CSS_LEFT] = 5;
-      node_0->style.margin[CSS_TOP] = 10;
-      init_css_node_children(node_0, 2);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->style.dimensions[CSS_WIDTH] = 100;
-        node_1->style.dimensions[CSS_HEIGHT] = 100;
-        node_1->style.margin[CSS_LEFT] = 15;
-        node_1->style.margin[CSS_TOP] = 50;
-        node_1->style.margin[CSS_BOTTOM] = 20;
-        node_1 = node_0->get_child(node_0->context, 1);
-        node_1->style.dimensions[CSS_WIDTH] = 100;
-        node_1->style.dimensions[CSS_HEIGHT] = 100;
-        node_1->style.margin[CSS_LEFT] = 30;
-      }
-    }
-
-    css_node_t *root_layout = new_test_css_node();
-    {
-      css_node_t *node_0 = root_layout;
-      node_0->layout.position[CSS_TOP] = 10;
-      node_0->layout.position[CSS_LEFT] = 5;
-      node_0->layout.dimensions[CSS_WIDTH] = 1000;
-      node_0->layout.dimensions[CSS_HEIGHT] = 1000;
-      init_css_node_children(node_0, 2);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->layout.position[CSS_TOP] = 50;
-        node_1->layout.position[CSS_LEFT] = 15;
-        node_1->layout.dimensions[CSS_WIDTH] = 100;
-        node_1->layout.dimensions[CSS_HEIGHT] = 100;
-        node_1 = node_0->get_child(node_0->context, 1);
-        node_1->layout.position[CSS_TOP] = 170;
-        node_1->layout.position[CSS_LEFT] = 30;
-        node_1->layout.dimensions[CSS_WIDTH] = 100;
-        node_1->layout.dimensions[CSS_HEIGHT] = 100;
-      }
-    }
-
-    test("should layout node with targeted margin", root_node, root_layout);
-  }
-
-  {
-    css_node_t *root_node = new_test_css_node();
-    {
-      css_node_t *node_0 = root_node;
-      node_0->style.flex_direction = CSS_FLEX_DIRECTION_COLUMN_REVERSE;
-      node_0->style.dimensions[CSS_WIDTH] = 1000;
-      node_0->style.dimensions[CSS_HEIGHT] = 1000;
-      node_0->style.margin[CSS_LEFT] = 5;
-      node_0->style.margin[CSS_TOP] = 10;
-      init_css_node_children(node_0, 2);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->style.dimensions[CSS_WIDTH] = 100;
-        node_1->style.dimensions[CSS_HEIGHT] = 100;
-        node_1->style.margin[CSS_LEFT] = 15;
-        node_1->style.margin[CSS_TOP] = 50;
-        node_1->style.margin[CSS_BOTTOM] = 20;
-        node_1 = node_0->get_child(node_0->context, 1);
-        node_1->style.dimensions[CSS_WIDTH] = 100;
-        node_1->style.dimensions[CSS_HEIGHT] = 100;
-        node_1->style.margin[CSS_LEFT] = 30;
-      }
-    }
-
-    css_node_t *root_layout = new_test_css_node();
-    {
-      css_node_t *node_0 = root_layout;
-      node_0->layout.position[CSS_TOP] = 10;
-      node_0->layout.position[CSS_LEFT] = 5;
-      node_0->layout.dimensions[CSS_WIDTH] = 1000;
-      node_0->layout.dimensions[CSS_HEIGHT] = 1000;
-      init_css_node_children(node_0, 2);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->layout.position[CSS_TOP] = 880;
-        node_1->layout.position[CSS_LEFT] = 15;
-        node_1->layout.dimensions[CSS_WIDTH] = 100;
-        node_1->layout.dimensions[CSS_HEIGHT] = 100;
-        node_1 = node_0->get_child(node_0->context, 1);
-        node_1->layout.position[CSS_TOP] = 730;
-        node_1->layout.position[CSS_LEFT] = 30;
-        node_1->layout.dimensions[CSS_WIDTH] = 100;
-        node_1->layout.dimensions[CSS_HEIGHT] = 100;
-      }
-    }
-
-    test("should layout node with targeted margin in reverse", root_node, root_layout);
-  }
-
-  {
-    css_node_t *root_node = new_test_css_node();
-    {
-      css_node_t *node_0 = root_node;
-      node_0->style.justify_content = CSS_JUSTIFY_FLEX_START;
-      node_0->style.dimensions[CSS_WIDTH] = 1000;
-      node_0->style.dimensions[CSS_HEIGHT] = 1000;
-      init_css_node_children(node_0, 2);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->style.dimensions[CSS_WIDTH] = 100;
-        node_1->style.dimensions[CSS_HEIGHT] = 100;
-        node_1 = node_0->get_child(node_0->context, 1);
-        node_1->style.dimensions[CSS_WIDTH] = 100;
-        node_1->style.dimensions[CSS_HEIGHT] = 100;
-      }
-    }
-
-    css_node_t *root_layout = new_test_css_node();
-    {
-      css_node_t *node_0 = root_layout;
-      node_0->layout.position[CSS_TOP] = 0;
-      node_0->layout.position[CSS_LEFT] = 0;
-      node_0->layout.dimensions[CSS_WIDTH] = 1000;
-      node_0->layout.dimensions[CSS_HEIGHT] = 1000;
-      init_css_node_children(node_0, 2);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->layout.position[CSS_TOP] = 0;
-        node_1->layout.position[CSS_LEFT] = 0;
-        node_1->layout.dimensions[CSS_WIDTH] = 100;
-        node_1->layout.dimensions[CSS_HEIGHT] = 100;
-        node_1 = node_0->get_child(node_0->context, 1);
-        node_1->layout.position[CSS_TOP] = 100;
-        node_1->layout.position[CSS_LEFT] = 0;
-        node_1->layout.dimensions[CSS_WIDTH] = 100;
-        node_1->layout.dimensions[CSS_HEIGHT] = 100;
-      }
-    }
-
-    test("should layout node with justifyContent: flex-start", root_node, root_layout);
-  }
-
-  {
-    css_node_t *root_node = new_test_css_node();
-    {
-      css_node_t *node_0 = root_node;
-      node_0->style.flex_direction = CSS_FLEX_DIRECTION_COLUMN_REVERSE;
-      node_0->style.justify_content = CSS_JUSTIFY_FLEX_START;
-      node_0->style.dimensions[CSS_WIDTH] = 1000;
-      node_0->style.dimensions[CSS_HEIGHT] = 1000;
-      init_css_node_children(node_0, 2);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->style.dimensions[CSS_WIDTH] = 100;
-        node_1->style.dimensions[CSS_HEIGHT] = 100;
-        node_1 = node_0->get_child(node_0->context, 1);
-        node_1->style.dimensions[CSS_WIDTH] = 100;
-        node_1->style.dimensions[CSS_HEIGHT] = 100;
-      }
-    }
-
-    css_node_t *root_layout = new_test_css_node();
-    {
-      css_node_t *node_0 = root_layout;
-      node_0->layout.position[CSS_TOP] = 0;
-      node_0->layout.position[CSS_LEFT] = 0;
-      node_0->layout.dimensions[CSS_WIDTH] = 1000;
-      node_0->layout.dimensions[CSS_HEIGHT] = 1000;
-      init_css_node_children(node_0, 2);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->layout.position[CSS_TOP] = 900;
-        node_1->layout.position[CSS_LEFT] = 0;
-        node_1->layout.dimensions[CSS_WIDTH] = 100;
-        node_1->layout.dimensions[CSS_HEIGHT] = 100;
-        node_1 = node_0->get_child(node_0->context, 1);
-        node_1->layout.position[CSS_TOP] = 800;
-        node_1->layout.position[CSS_LEFT] = 0;
-        node_1->layout.dimensions[CSS_WIDTH] = 100;
-        node_1->layout.dimensions[CSS_HEIGHT] = 100;
-      }
-    }
-
-    test("should layout node with justifyContent: flex-start in reverse", root_node, root_layout);
-  }
-
-  {
-    css_node_t *root_node = new_test_css_node();
-    {
-      css_node_t *node_0 = root_node;
-      node_0->style.justify_content = CSS_JUSTIFY_FLEX_END;
-      node_0->style.dimensions[CSS_WIDTH] = 1000;
-      node_0->style.dimensions[CSS_HEIGHT] = 1000;
-      init_css_node_children(node_0, 2);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->style.dimensions[CSS_WIDTH] = 100;
-        node_1->style.dimensions[CSS_HEIGHT] = 100;
-        node_1 = node_0->get_child(node_0->context, 1);
-        node_1->style.dimensions[CSS_WIDTH] = 100;
-        node_1->style.dimensions[CSS_HEIGHT] = 100;
-      }
-    }
-
-    css_node_t *root_layout = new_test_css_node();
-    {
-      css_node_t *node_0 = root_layout;
-      node_0->layout.position[CSS_TOP] = 0;
-      node_0->layout.position[CSS_LEFT] = 0;
-      node_0->layout.dimensions[CSS_WIDTH] = 1000;
-      node_0->layout.dimensions[CSS_HEIGHT] = 1000;
-      init_css_node_children(node_0, 2);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->layout.position[CSS_TOP] = 800;
-        node_1->layout.position[CSS_LEFT] = 0;
-        node_1->layout.dimensions[CSS_WIDTH] = 100;
-        node_1->layout.dimensions[CSS_HEIGHT] = 100;
-        node_1 = node_0->get_child(node_0->context, 1);
-        node_1->layout.position[CSS_TOP] = 900;
-        node_1->layout.position[CSS_LEFT] = 0;
-        node_1->layout.dimensions[CSS_WIDTH] = 100;
-        node_1->layout.dimensions[CSS_HEIGHT] = 100;
-      }
-    }
-
-    test("should layout node with justifyContent: flex-end", root_node, root_layout);
-  }
-
-  {
-    css_node_t *root_node = new_test_css_node();
-    {
-      css_node_t *node_0 = root_node;
-      node_0->style.flex_direction = CSS_FLEX_DIRECTION_COLUMN_REVERSE;
-      node_0->style.justify_content = CSS_JUSTIFY_FLEX_END;
-      node_0->style.dimensions[CSS_WIDTH] = 1000;
-      node_0->style.dimensions[CSS_HEIGHT] = 1000;
-      init_css_node_children(node_0, 2);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->style.dimensions[CSS_WIDTH] = 100;
-        node_1->style.dimensions[CSS_HEIGHT] = 100;
-        node_1 = node_0->get_child(node_0->context, 1);
-        node_1->style.dimensions[CSS_WIDTH] = 100;
-        node_1->style.dimensions[CSS_HEIGHT] = 100;
-      }
-    }
-
-    css_node_t *root_layout = new_test_css_node();
-    {
-      css_node_t *node_0 = root_layout;
-      node_0->layout.position[CSS_TOP] = 0;
-      node_0->layout.position[CSS_LEFT] = 0;
-      node_0->layout.dimensions[CSS_WIDTH] = 1000;
-      node_0->layout.dimensions[CSS_HEIGHT] = 1000;
-      init_css_node_children(node_0, 2);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->layout.position[CSS_TOP] = 100;
-        node_1->layout.position[CSS_LEFT] = 0;
-        node_1->layout.dimensions[CSS_WIDTH] = 100;
-        node_1->layout.dimensions[CSS_HEIGHT] = 100;
-        node_1 = node_0->get_child(node_0->context, 1);
-        node_1->layout.position[CSS_TOP] = 0;
-        node_1->layout.position[CSS_LEFT] = 0;
-        node_1->layout.dimensions[CSS_WIDTH] = 100;
-        node_1->layout.dimensions[CSS_HEIGHT] = 100;
-      }
-    }
-
-    test("should layout node with justifyContent: flex-end in reverse", root_node, root_layout);
-  }
-
-  {
-    css_node_t *root_node = new_test_css_node();
-    {
-      css_node_t *node_0 = root_node;
-      node_0->style.justify_content = CSS_JUSTIFY_SPACE_BETWEEN;
-      node_0->style.dimensions[CSS_WIDTH] = 1000;
-      node_0->style.dimensions[CSS_HEIGHT] = 1000;
-      init_css_node_children(node_0, 2);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->style.dimensions[CSS_WIDTH] = 100;
-        node_1->style.dimensions[CSS_HEIGHT] = 100;
-        node_1 = node_0->get_child(node_0->context, 1);
-        node_1->style.dimensions[CSS_WIDTH] = 100;
-        node_1->style.dimensions[CSS_HEIGHT] = 100;
-      }
-    }
-
-    css_node_t *root_layout = new_test_css_node();
-    {
-      css_node_t *node_0 = root_layout;
-      node_0->layout.position[CSS_TOP] = 0;
-      node_0->layout.position[CSS_LEFT] = 0;
-      node_0->layout.dimensions[CSS_WIDTH] = 1000;
-      node_0->layout.dimensions[CSS_HEIGHT] = 1000;
-      init_css_node_children(node_0, 2);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->layout.position[CSS_TOP] = 0;
-        node_1->layout.position[CSS_LEFT] = 0;
-        node_1->layout.dimensions[CSS_WIDTH] = 100;
-        node_1->layout.dimensions[CSS_HEIGHT] = 100;
-        node_1 = node_0->get_child(node_0->context, 1);
-        node_1->layout.position[CSS_TOP] = 900;
-        node_1->layout.position[CSS_LEFT] = 0;
-        node_1->layout.dimensions[CSS_WIDTH] = 100;
-        node_1->layout.dimensions[CSS_HEIGHT] = 100;
-      }
-    }
-
-    test("should layout node with justifyContent: space-between", root_node, root_layout);
-  }
-
-  {
-    css_node_t *root_node = new_test_css_node();
-    {
-      css_node_t *node_0 = root_node;
-      node_0->style.flex_direction = CSS_FLEX_DIRECTION_COLUMN_REVERSE;
-      node_0->style.justify_content = CSS_JUSTIFY_SPACE_BETWEEN;
-      node_0->style.dimensions[CSS_WIDTH] = 1000;
-      node_0->style.dimensions[CSS_HEIGHT] = 1000;
-      init_css_node_children(node_0, 2);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->style.dimensions[CSS_WIDTH] = 100;
-        node_1->style.dimensions[CSS_HEIGHT] = 100;
-        node_1 = node_0->get_child(node_0->context, 1);
-        node_1->style.dimensions[CSS_WIDTH] = 100;
-        node_1->style.dimensions[CSS_HEIGHT] = 100;
-      }
-    }
-
-    css_node_t *root_layout = new_test_css_node();
-    {
-      css_node_t *node_0 = root_layout;
-      node_0->layout.position[CSS_TOP] = 0;
-      node_0->layout.position[CSS_LEFT] = 0;
-      node_0->layout.dimensions[CSS_WIDTH] = 1000;
-      node_0->layout.dimensions[CSS_HEIGHT] = 1000;
-      init_css_node_children(node_0, 2);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->layout.position[CSS_TOP] = 900;
-        node_1->layout.position[CSS_LEFT] = 0;
-        node_1->layout.dimensions[CSS_WIDTH] = 100;
-        node_1->layout.dimensions[CSS_HEIGHT] = 100;
-        node_1 = node_0->get_child(node_0->context, 1);
-        node_1->layout.position[CSS_TOP] = 0;
-        node_1->layout.position[CSS_LEFT] = 0;
-        node_1->layout.dimensions[CSS_WIDTH] = 100;
-        node_1->layout.dimensions[CSS_HEIGHT] = 100;
-      }
-    }
-
-    test("should layout node with justifyContent: space-between in reverse", root_node, root_layout);
-  }
-
-  {
-    css_node_t *root_node = new_test_css_node();
-    {
-      css_node_t *node_0 = root_node;
-      node_0->style.justify_content = CSS_JUSTIFY_SPACE_AROUND;
-      node_0->style.dimensions[CSS_WIDTH] = 1000;
-      node_0->style.dimensions[CSS_HEIGHT] = 1000;
-      init_css_node_children(node_0, 2);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->style.dimensions[CSS_WIDTH] = 100;
-        node_1->style.dimensions[CSS_HEIGHT] = 100;
-        node_1 = node_0->get_child(node_0->context, 1);
-        node_1->style.dimensions[CSS_WIDTH] = 100;
-        node_1->style.dimensions[CSS_HEIGHT] = 100;
-      }
-    }
-
-    css_node_t *root_layout = new_test_css_node();
-    {
-      css_node_t *node_0 = root_layout;
-      node_0->layout.position[CSS_TOP] = 0;
-      node_0->layout.position[CSS_LEFT] = 0;
-      node_0->layout.dimensions[CSS_WIDTH] = 1000;
-      node_0->layout.dimensions[CSS_HEIGHT] = 1000;
-      init_css_node_children(node_0, 2);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->layout.position[CSS_TOP] = 200;
-        node_1->layout.position[CSS_LEFT] = 0;
-        node_1->layout.dimensions[CSS_WIDTH] = 100;
-        node_1->layout.dimensions[CSS_HEIGHT] = 100;
-        node_1 = node_0->get_child(node_0->context, 1);
-        node_1->layout.position[CSS_TOP] = 700;
-        node_1->layout.position[CSS_LEFT] = 0;
-        node_1->layout.dimensions[CSS_WIDTH] = 100;
-        node_1->layout.dimensions[CSS_HEIGHT] = 100;
-      }
-    }
-
-    test("should layout node with justifyContent: space-around", root_node, root_layout);
-  }
-
-  {
-    css_node_t *root_node = new_test_css_node();
-    {
-      css_node_t *node_0 = root_node;
-      node_0->style.flex_direction = CSS_FLEX_DIRECTION_COLUMN_REVERSE;
-      node_0->style.justify_content = CSS_JUSTIFY_SPACE_AROUND;
-      node_0->style.dimensions[CSS_WIDTH] = 1000;
-      node_0->style.dimensions[CSS_HEIGHT] = 1000;
-      init_css_node_children(node_0, 2);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->style.dimensions[CSS_WIDTH] = 100;
-        node_1->style.dimensions[CSS_HEIGHT] = 100;
-        node_1 = node_0->get_child(node_0->context, 1);
-        node_1->style.dimensions[CSS_WIDTH] = 100;
-        node_1->style.dimensions[CSS_HEIGHT] = 100;
-      }
-    }
-
-    css_node_t *root_layout = new_test_css_node();
-    {
-      css_node_t *node_0 = root_layout;
-      node_0->layout.position[CSS_TOP] = 0;
-      node_0->layout.position[CSS_LEFT] = 0;
-      node_0->layout.dimensions[CSS_WIDTH] = 1000;
-      node_0->layout.dimensions[CSS_HEIGHT] = 1000;
-      init_css_node_children(node_0, 2);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->layout.position[CSS_TOP] = 700;
-        node_1->layout.position[CSS_LEFT] = 0;
-        node_1->layout.dimensions[CSS_WIDTH] = 100;
-        node_1->layout.dimensions[CSS_HEIGHT] = 100;
-        node_1 = node_0->get_child(node_0->context, 1);
-        node_1->layout.position[CSS_TOP] = 200;
-        node_1->layout.position[CSS_LEFT] = 0;
-        node_1->layout.dimensions[CSS_WIDTH] = 100;
-        node_1->layout.dimensions[CSS_HEIGHT] = 100;
-      }
-    }
-
-    test("should layout node with justifyContent: space-around in reverse", root_node, root_layout);
-  }
-
-  {
-    css_node_t *root_node = new_test_css_node();
-    {
-      css_node_t *node_0 = root_node;
-      node_0->style.justify_content = CSS_JUSTIFY_CENTER;
-      node_0->style.dimensions[CSS_WIDTH] = 1000;
-      node_0->style.dimensions[CSS_HEIGHT] = 1000;
-      init_css_node_children(node_0, 2);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->style.dimensions[CSS_WIDTH] = 100;
-        node_1->style.dimensions[CSS_HEIGHT] = 100;
-        node_1 = node_0->get_child(node_0->context, 1);
-        node_1->style.dimensions[CSS_WIDTH] = 100;
-        node_1->style.dimensions[CSS_HEIGHT] = 100;
-      }
-    }
-
-    css_node_t *root_layout = new_test_css_node();
-    {
-      css_node_t *node_0 = root_layout;
-      node_0->layout.position[CSS_TOP] = 0;
-      node_0->layout.position[CSS_LEFT] = 0;
-      node_0->layout.dimensions[CSS_WIDTH] = 1000;
-      node_0->layout.dimensions[CSS_HEIGHT] = 1000;
-      init_css_node_children(node_0, 2);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->layout.position[CSS_TOP] = 400;
-        node_1->layout.position[CSS_LEFT] = 0;
-        node_1->layout.dimensions[CSS_WIDTH] = 100;
-        node_1->layout.dimensions[CSS_HEIGHT] = 100;
-        node_1 = node_0->get_child(node_0->context, 1);
-        node_1->layout.position[CSS_TOP] = 500;
-        node_1->layout.position[CSS_LEFT] = 0;
-        node_1->layout.dimensions[CSS_WIDTH] = 100;
-        node_1->layout.dimensions[CSS_HEIGHT] = 100;
-      }
-    }
-
-    test("should layout node with justifyContent: center", root_node, root_layout);
-  }
-
-  {
-    css_node_t *root_node = new_test_css_node();
-    {
-      css_node_t *node_0 = root_node;
-      node_0->style.flex_direction = CSS_FLEX_DIRECTION_COLUMN_REVERSE;
-      node_0->style.justify_content = CSS_JUSTIFY_CENTER;
-      node_0->style.dimensions[CSS_WIDTH] = 1000;
-      node_0->style.dimensions[CSS_HEIGHT] = 1000;
-      init_css_node_children(node_0, 2);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->style.dimensions[CSS_WIDTH] = 100;
-        node_1->style.dimensions[CSS_HEIGHT] = 100;
-        node_1 = node_0->get_child(node_0->context, 1);
-        node_1->style.dimensions[CSS_WIDTH] = 100;
-        node_1->style.dimensions[CSS_HEIGHT] = 100;
-      }
-    }
-
-    css_node_t *root_layout = new_test_css_node();
-    {
-      css_node_t *node_0 = root_layout;
-      node_0->layout.position[CSS_TOP] = 0;
-      node_0->layout.position[CSS_LEFT] = 0;
-      node_0->layout.dimensions[CSS_WIDTH] = 1000;
-      node_0->layout.dimensions[CSS_HEIGHT] = 1000;
-      init_css_node_children(node_0, 2);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->layout.position[CSS_TOP] = 500;
-        node_1->layout.position[CSS_LEFT] = 0;
-        node_1->layout.dimensions[CSS_WIDTH] = 100;
-        node_1->layout.dimensions[CSS_HEIGHT] = 100;
-        node_1 = node_0->get_child(node_0->context, 1);
-        node_1->layout.position[CSS_TOP] = 400;
-        node_1->layout.position[CSS_LEFT] = 0;
-        node_1->layout.dimensions[CSS_WIDTH] = 100;
-        node_1->layout.dimensions[CSS_HEIGHT] = 100;
-      }
-    }
-
-    test("should layout node with justifyContent: center in reverse", root_node, root_layout);
-  }
-
-  {
-    css_node_t *root_node = new_test_css_node();
-    {
-      css_node_t *node_0 = root_node;
-      node_0->style.dimensions[CSS_WIDTH] = 1000;
-      node_0->style.dimensions[CSS_HEIGHT] = 1000;
-      init_css_node_children(node_0, 1);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->style.flex = 1;
-        node_1->style.dimensions[CSS_WIDTH] = 100;
-        node_1->style.dimensions[CSS_HEIGHT] = 100;
-      }
-    }
-
-    css_node_t *root_layout = new_test_css_node();
-    {
-      css_node_t *node_0 = root_layout;
-      node_0->layout.position[CSS_TOP] = 0;
-      node_0->layout.position[CSS_LEFT] = 0;
-      node_0->layout.dimensions[CSS_WIDTH] = 1000;
-      node_0->layout.dimensions[CSS_HEIGHT] = 1000;
-      init_css_node_children(node_0, 1);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->layout.position[CSS_TOP] = 0;
-        node_1->layout.position[CSS_LEFT] = 0;
-        node_1->layout.dimensions[CSS_WIDTH] = 100;
-        node_1->layout.dimensions[CSS_HEIGHT] = 1000;
-      }
-    }
-
-    test("should layout node with flex override height", root_node, root_layout);
-  }
-
-  {
-    css_node_t *root_node = new_test_css_node();
-    {
-      css_node_t *node_0 = root_node;
-      node_0->style.align_items = CSS_ALIGN_FLEX_START;
-      node_0->style.dimensions[CSS_WIDTH] = 1000;
-      node_0->style.dimensions[CSS_HEIGHT] = 1000;
-      init_css_node_children(node_0, 2);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->style.dimensions[CSS_WIDTH] = 200;
-        node_1->style.dimensions[CSS_HEIGHT] = 100;
-        node_1 = node_0->get_child(node_0->context, 1);
-        node_1->style.dimensions[CSS_WIDTH] = 100;
-        node_1->style.dimensions[CSS_HEIGHT] = 100;
-      }
-    }
-
-    css_node_t *root_layout = new_test_css_node();
-    {
-      css_node_t *node_0 = root_layout;
-      node_0->layout.position[CSS_TOP] = 0;
-      node_0->layout.position[CSS_LEFT] = 0;
-      node_0->layout.dimensions[CSS_WIDTH] = 1000;
-      node_0->layout.dimensions[CSS_HEIGHT] = 1000;
-      init_css_node_children(node_0, 2);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->layout.position[CSS_TOP] = 0;
-        node_1->layout.position[CSS_LEFT] = 0;
-        node_1->layout.dimensions[CSS_WIDTH] = 200;
-        node_1->layout.dimensions[CSS_HEIGHT] = 100;
-        node_1 = node_0->get_child(node_0->context, 1);
-        node_1->layout.position[CSS_TOP] = 100;
-        node_1->layout.position[CSS_LEFT] = 0;
-        node_1->layout.dimensions[CSS_WIDTH] = 100;
-        node_1->layout.dimensions[CSS_HEIGHT] = 100;
-      }
-    }
-
-    test("should layout node with alignItems: flex-start", root_node, root_layout);
-  }
-
-  {
-    css_node_t *root_node = new_test_css_node();
-    {
-      css_node_t *node_0 = root_node;
-      node_0->style.flex_direction = CSS_FLEX_DIRECTION_COLUMN_REVERSE;
-      node_0->style.align_items = CSS_ALIGN_FLEX_START;
-      node_0->style.dimensions[CSS_WIDTH] = 1000;
-      node_0->style.dimensions[CSS_HEIGHT] = 1000;
-      init_css_node_children(node_0, 2);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->style.dimensions[CSS_WIDTH] = 200;
-        node_1->style.dimensions[CSS_HEIGHT] = 100;
-        node_1 = node_0->get_child(node_0->context, 1);
-        node_1->style.dimensions[CSS_WIDTH] = 100;
-        node_1->style.dimensions[CSS_HEIGHT] = 100;
-      }
-    }
-
-    css_node_t *root_layout = new_test_css_node();
-    {
-      css_node_t *node_0 = root_layout;
-      node_0->layout.position[CSS_TOP] = 0;
-      node_0->layout.position[CSS_LEFT] = 0;
-      node_0->layout.dimensions[CSS_WIDTH] = 1000;
-      node_0->layout.dimensions[CSS_HEIGHT] = 1000;
-      init_css_node_children(node_0, 2);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->layout.position[CSS_TOP] = 900;
-        node_1->layout.position[CSS_LEFT] = 0;
-        node_1->layout.dimensions[CSS_WIDTH] = 200;
-        node_1->layout.dimensions[CSS_HEIGHT] = 100;
-        node_1 = node_0->get_child(node_0->context, 1);
-        node_1->layout.position[CSS_TOP] = 800;
-        node_1->layout.position[CSS_LEFT] = 0;
-        node_1->layout.dimensions[CSS_WIDTH] = 100;
-        node_1->layout.dimensions[CSS_HEIGHT] = 100;
-      }
-    }
-
-    test("should layout node with alignItems: flex-start in reverse", root_node, root_layout);
-  }
-
-  {
-    css_node_t *root_node = new_test_css_node();
-    {
-      css_node_t *node_0 = root_node;
-      node_0->style.align_items = CSS_ALIGN_CENTER;
-      node_0->style.dimensions[CSS_WIDTH] = 1000;
-      node_0->style.dimensions[CSS_HEIGHT] = 1000;
-      init_css_node_children(node_0, 2);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->style.dimensions[CSS_WIDTH] = 200;
-        node_1->style.dimensions[CSS_HEIGHT] = 100;
-        node_1 = node_0->get_child(node_0->context, 1);
-        node_1->style.dimensions[CSS_WIDTH] = 100;
-        node_1->style.dimensions[CSS_HEIGHT] = 100;
-      }
-    }
-
-    css_node_t *root_layout = new_test_css_node();
-    {
-      css_node_t *node_0 = root_layout;
-      node_0->layout.position[CSS_TOP] = 0;
-      node_0->layout.position[CSS_LEFT] = 0;
-      node_0->layout.dimensions[CSS_WIDTH] = 1000;
-      node_0->layout.dimensions[CSS_HEIGHT] = 1000;
-      init_css_node_children(node_0, 2);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->layout.position[CSS_TOP] = 0;
-        node_1->layout.position[CSS_LEFT] = 400;
-        node_1->layout.dimensions[CSS_WIDTH] = 200;
-        node_1->layout.dimensions[CSS_HEIGHT] = 100;
-        node_1 = node_0->get_child(node_0->context, 1);
-        node_1->layout.position[CSS_TOP] = 100;
-        node_1->layout.position[CSS_LEFT] = 450;
-        node_1->layout.dimensions[CSS_WIDTH] = 100;
-        node_1->layout.dimensions[CSS_HEIGHT] = 100;
-      }
-    }
-
-    test("should layout node with alignItems: center", root_node, root_layout);
-  }
-
-  {
-    css_node_t *root_node = new_test_css_node();
-    {
-      css_node_t *node_0 = root_node;
-      node_0->style.flex_direction = CSS_FLEX_DIRECTION_COLUMN_REVERSE;
-      node_0->style.align_items = CSS_ALIGN_CENTER;
-      node_0->style.dimensions[CSS_WIDTH] = 1000;
-      node_0->style.dimensions[CSS_HEIGHT] = 1000;
-      init_css_node_children(node_0, 2);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->style.dimensions[CSS_WIDTH] = 200;
-        node_1->style.dimensions[CSS_HEIGHT] = 100;
-        node_1 = node_0->get_child(node_0->context, 1);
-        node_1->style.dimensions[CSS_WIDTH] = 100;
-        node_1->style.dimensions[CSS_HEIGHT] = 100;
-      }
-    }
-
-    css_node_t *root_layout = new_test_css_node();
-    {
-      css_node_t *node_0 = root_layout;
-      node_0->layout.position[CSS_TOP] = 0;
-      node_0->layout.position[CSS_LEFT] = 0;
-      node_0->layout.dimensions[CSS_WIDTH] = 1000;
-      node_0->layout.dimensions[CSS_HEIGHT] = 1000;
-      init_css_node_children(node_0, 2);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->layout.position[CSS_TOP] = 900;
-        node_1->layout.position[CSS_LEFT] = 400;
-        node_1->layout.dimensions[CSS_WIDTH] = 200;
-        node_1->layout.dimensions[CSS_HEIGHT] = 100;
-        node_1 = node_0->get_child(node_0->context, 1);
-        node_1->layout.position[CSS_TOP] = 800;
-        node_1->layout.position[CSS_LEFT] = 450;
-        node_1->layout.dimensions[CSS_WIDTH] = 100;
-        node_1->layout.dimensions[CSS_HEIGHT] = 100;
-      }
-    }
-
-    test("should layout node with alignItems: center in reverse", root_node, root_layout);
-  }
-
-  {
-    css_node_t *root_node = new_test_css_node();
-    {
-      css_node_t *node_0 = root_node;
-      node_0->style.align_items = CSS_ALIGN_FLEX_END;
-      node_0->style.dimensions[CSS_WIDTH] = 1000;
-      node_0->style.dimensions[CSS_HEIGHT] = 1000;
-      init_css_node_children(node_0, 2);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->style.dimensions[CSS_WIDTH] = 200;
-        node_1->style.dimensions[CSS_HEIGHT] = 100;
-        node_1 = node_0->get_child(node_0->context, 1);
-        node_1->style.dimensions[CSS_WIDTH] = 100;
-        node_1->style.dimensions[CSS_HEIGHT] = 100;
-      }
-    }
-
-    css_node_t *root_layout = new_test_css_node();
-    {
-      css_node_t *node_0 = root_layout;
-      node_0->layout.position[CSS_TOP] = 0;
-      node_0->layout.position[CSS_LEFT] = 0;
-      node_0->layout.dimensions[CSS_WIDTH] = 1000;
-      node_0->layout.dimensions[CSS_HEIGHT] = 1000;
-      init_css_node_children(node_0, 2);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->layout.position[CSS_TOP] = 0;
-        node_1->layout.position[CSS_LEFT] = 800;
-        node_1->layout.dimensions[CSS_WIDTH] = 200;
-        node_1->layout.dimensions[CSS_HEIGHT] = 100;
-        node_1 = node_0->get_child(node_0->context, 1);
-        node_1->layout.position[CSS_TOP] = 100;
-        node_1->layout.position[CSS_LEFT] = 900;
-        node_1->layout.dimensions[CSS_WIDTH] = 100;
-        node_1->layout.dimensions[CSS_HEIGHT] = 100;
-      }
-    }
-
-    test("should layout node with alignItems: flex-end", root_node, root_layout);
-  }
-
-  {
-    css_node_t *root_node = new_test_css_node();
-    {
-      css_node_t *node_0 = root_node;
-      node_0->style.flex_direction = CSS_FLEX_DIRECTION_COLUMN_REVERSE;
-      node_0->style.align_items = CSS_ALIGN_FLEX_END;
-      node_0->style.dimensions[CSS_WIDTH] = 1000;
-      node_0->style.dimensions[CSS_HEIGHT] = 1000;
-      init_css_node_children(node_0, 2);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->style.dimensions[CSS_WIDTH] = 200;
-        node_1->style.dimensions[CSS_HEIGHT] = 100;
-        node_1 = node_0->get_child(node_0->context, 1);
-        node_1->style.dimensions[CSS_WIDTH] = 100;
-        node_1->style.dimensions[CSS_HEIGHT] = 100;
-      }
-    }
-
-    css_node_t *root_layout = new_test_css_node();
-    {
-      css_node_t *node_0 = root_layout;
-      node_0->layout.position[CSS_TOP] = 0;
-      node_0->layout.position[CSS_LEFT] = 0;
-      node_0->layout.dimensions[CSS_WIDTH] = 1000;
-      node_0->layout.dimensions[CSS_HEIGHT] = 1000;
-      init_css_node_children(node_0, 2);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->layout.position[CSS_TOP] = 900;
-        node_1->layout.position[CSS_LEFT] = 800;
-        node_1->layout.dimensions[CSS_WIDTH] = 200;
-        node_1->layout.dimensions[CSS_HEIGHT] = 100;
-        node_1 = node_0->get_child(node_0->context, 1);
-        node_1->layout.position[CSS_TOP] = 800;
-        node_1->layout.position[CSS_LEFT] = 900;
-        node_1->layout.dimensions[CSS_WIDTH] = 100;
-        node_1->layout.dimensions[CSS_HEIGHT] = 100;
-      }
-    }
-
-    test("should layout node with alignItems: flex-end in reverse", root_node, root_layout);
-  }
-
-  {
-    css_node_t *root_node = new_test_css_node();
-    {
-      css_node_t *node_0 = root_node;
-      node_0->style.align_items = CSS_ALIGN_FLEX_END;
-      node_0->style.dimensions[CSS_WIDTH] = 1000;
-      node_0->style.dimensions[CSS_HEIGHT] = 1000;
-      init_css_node_children(node_0, 2);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->style.dimensions[CSS_WIDTH] = 200;
-        node_1->style.dimensions[CSS_HEIGHT] = 100;
-        node_1 = node_0->get_child(node_0->context, 1);
-        node_1->style.align_self = CSS_ALIGN_CENTER;
-        node_1->style.dimensions[CSS_WIDTH] = 100;
-        node_1->style.dimensions[CSS_HEIGHT] = 100;
-      }
-    }
-
-    css_node_t *root_layout = new_test_css_node();
-    {
-      css_node_t *node_0 = root_layout;
-      node_0->layout.position[CSS_TOP] = 0;
-      node_0->layout.position[CSS_LEFT] = 0;
-      node_0->layout.dimensions[CSS_WIDTH] = 1000;
-      node_0->layout.dimensions[CSS_HEIGHT] = 1000;
-      init_css_node_children(node_0, 2);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->layout.position[CSS_TOP] = 0;
-        node_1->layout.position[CSS_LEFT] = 800;
-        node_1->layout.dimensions[CSS_WIDTH] = 200;
-        node_1->layout.dimensions[CSS_HEIGHT] = 100;
-        node_1 = node_0->get_child(node_0->context, 1);
-        node_1->layout.position[CSS_TOP] = 100;
-        node_1->layout.position[CSS_LEFT] = 450;
-        node_1->layout.dimensions[CSS_WIDTH] = 100;
-        node_1->layout.dimensions[CSS_HEIGHT] = 100;
-      }
-    }
-
-    test("should layout node with alignSelf overrides alignItems", root_node, root_layout);
-  }
-
-  {
-    css_node_t *root_node = new_test_css_node();
-    {
-      css_node_t *node_0 = root_node;
-      node_0->style.flex_direction = CSS_FLEX_DIRECTION_COLUMN_REVERSE;
-      node_0->style.align_items = CSS_ALIGN_FLEX_END;
-      node_0->style.dimensions[CSS_WIDTH] = 1000;
-      node_0->style.dimensions[CSS_HEIGHT] = 1000;
-      init_css_node_children(node_0, 2);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->style.dimensions[CSS_WIDTH] = 200;
-        node_1->style.dimensions[CSS_HEIGHT] = 100;
-        node_1 = node_0->get_child(node_0->context, 1);
-        node_1->style.align_self = CSS_ALIGN_CENTER;
-        node_1->style.dimensions[CSS_WIDTH] = 100;
-        node_1->style.dimensions[CSS_HEIGHT] = 100;
-      }
-    }
-
-    css_node_t *root_layout = new_test_css_node();
-    {
-      css_node_t *node_0 = root_layout;
-      node_0->layout.position[CSS_TOP] = 0;
-      node_0->layout.position[CSS_LEFT] = 0;
-      node_0->layout.dimensions[CSS_WIDTH] = 1000;
-      node_0->layout.dimensions[CSS_HEIGHT] = 1000;
-      init_css_node_children(node_0, 2);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->layout.position[CSS_TOP] = 900;
-        node_1->layout.position[CSS_LEFT] = 800;
-        node_1->layout.dimensions[CSS_WIDTH] = 200;
-        node_1->layout.dimensions[CSS_HEIGHT] = 100;
-        node_1 = node_0->get_child(node_0->context, 1);
-        node_1->layout.position[CSS_TOP] = 800;
-        node_1->layout.position[CSS_LEFT] = 450;
-        node_1->layout.dimensions[CSS_WIDTH] = 100;
-        node_1->layout.dimensions[CSS_HEIGHT] = 100;
-      }
-    }
-
-    test("should layout node with alignSelf overrides alignItems in reverse", root_node, root_layout);
-  }
-
-  {
-    css_node_t *root_node = new_test_css_node();
-    {
-      css_node_t *node_0 = root_node;
-      node_0->style.align_items = CSS_ALIGN_STRETCH;
-      node_0->style.dimensions[CSS_WIDTH] = 1000;
-      node_0->style.dimensions[CSS_HEIGHT] = 1000;
-      init_css_node_children(node_0, 1);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->style.dimensions[CSS_HEIGHT] = 100;
-      }
-    }
-
-    css_node_t *root_layout = new_test_css_node();
-    {
-      css_node_t *node_0 = root_layout;
-      node_0->layout.position[CSS_TOP] = 0;
-      node_0->layout.position[CSS_LEFT] = 0;
-      node_0->layout.dimensions[CSS_WIDTH] = 1000;
-      node_0->layout.dimensions[CSS_HEIGHT] = 1000;
-      init_css_node_children(node_0, 1);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->layout.position[CSS_TOP] = 0;
-        node_1->layout.position[CSS_LEFT] = 0;
-        node_1->layout.dimensions[CSS_WIDTH] = 1000;
-        node_1->layout.dimensions[CSS_HEIGHT] = 100;
-      }
-    }
-
-    test("should layout node with alignItem: stretch", root_node, root_layout);
-  }
-
-  {
-    css_node_t *root_node = new_test_css_node();
-    {
-      css_node_t *node_0 = root_node;
-      node_0->style.flex_direction = CSS_FLEX_DIRECTION_COLUMN_REVERSE;
-      node_0->style.align_items = CSS_ALIGN_STRETCH;
-      node_0->style.dimensions[CSS_WIDTH] = 1000;
-      node_0->style.dimensions[CSS_HEIGHT] = 1000;
-      init_css_node_children(node_0, 1);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->style.dimensions[CSS_HEIGHT] = 100;
-      }
-    }
-
-    css_node_t *root_layout = new_test_css_node();
-    {
-      css_node_t *node_0 = root_layout;
-      node_0->layout.position[CSS_TOP] = 0;
-      node_0->layout.position[CSS_LEFT] = 0;
-      node_0->layout.dimensions[CSS_WIDTH] = 1000;
-      node_0->layout.dimensions[CSS_HEIGHT] = 1000;
-      init_css_node_children(node_0, 1);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->layout.position[CSS_TOP] = 900;
-        node_1->layout.position[CSS_LEFT] = 0;
-        node_1->layout.dimensions[CSS_WIDTH] = 1000;
-        node_1->layout.dimensions[CSS_HEIGHT] = 100;
-      }
-    }
-
-    test("should layout node with alignItem: stretch in reverse", root_node, root_layout);
-  }
-
-  {
-    css_node_t *root_node = new_test_css_node();
-    {
-      css_node_t *node_0 = root_node;
-      init_css_node_children(node_0, 1);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-      }
-    }
-
-    css_node_t *root_layout = new_test_css_node();
-    {
-      css_node_t *node_0 = root_layout;
-      node_0->layout.position[CSS_TOP] = 0;
-      node_0->layout.position[CSS_LEFT] = 0;
-      node_0->layout.dimensions[CSS_WIDTH] = 0;
-      node_0->layout.dimensions[CSS_HEIGHT] = 0;
-      init_css_node_children(node_0, 1);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->layout.position[CSS_TOP] = 0;
-        node_1->layout.position[CSS_LEFT] = 0;
-        node_1->layout.dimensions[CSS_WIDTH] = 0;
-        node_1->layout.dimensions[CSS_HEIGHT] = 0;
-      }
-    }
-
-    test("should layout empty node", root_node, root_layout);
-  }
-
-  {
-    css_node_t *root_node = new_test_css_node();
-    {
-      css_node_t *node_0 = root_node;
-      node_0->style.flex_direction = CSS_FLEX_DIRECTION_COLUMN_REVERSE;
-      init_css_node_children(node_0, 1);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-      }
-    }
-
-    css_node_t *root_layout = new_test_css_node();
-    {
-      css_node_t *node_0 = root_layout;
-      node_0->layout.position[CSS_TOP] = 0;
-      node_0->layout.position[CSS_LEFT] = 0;
-      node_0->layout.dimensions[CSS_WIDTH] = 0;
-      node_0->layout.dimensions[CSS_HEIGHT] = 0;
-      init_css_node_children(node_0, 1);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->layout.position[CSS_TOP] = 0;
-        node_1->layout.position[CSS_LEFT] = 0;
-        node_1->layout.dimensions[CSS_WIDTH] = 0;
-        node_1->layout.dimensions[CSS_HEIGHT] = 0;
-      }
-    }
-
-    test("should layout empty node in reverse", root_node, root_layout);
-  }
-
-  {
-    css_node_t *root_node = new_test_css_node();
-    {
-      css_node_t *node_0 = root_node;
-      init_css_node_children(node_0, 1);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->style.margin[CSS_LEFT] = 5;
-        node_1->style.margin[CSS_TOP] = 5;
-        node_1->style.margin[CSS_RIGHT] = 5;
-        node_1->style.margin[CSS_BOTTOM] = 5;
-        node_1->style.margin[CSS_START] = 5;
-        node_1->style.margin[CSS_END] = 5;
-      }
-    }
-
-    css_node_t *root_layout = new_test_css_node();
-    {
-      css_node_t *node_0 = root_layout;
-      node_0->layout.position[CSS_TOP] = 0;
-      node_0->layout.position[CSS_LEFT] = 0;
-      node_0->layout.dimensions[CSS_WIDTH] = 10;
-      node_0->layout.dimensions[CSS_HEIGHT] = 10;
-      init_css_node_children(node_0, 1);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->layout.position[CSS_TOP] = 5;
-        node_1->layout.position[CSS_LEFT] = 5;
-        node_1->layout.dimensions[CSS_WIDTH] = 0;
-        node_1->layout.dimensions[CSS_HEIGHT] = 0;
-      }
-    }
-
-    test("should layout child with margin", root_node, root_layout);
-  }
-
-  {
-    css_node_t *root_node = new_test_css_node();
-    {
-      css_node_t *node_0 = root_node;
-      node_0->style.flex_direction = CSS_FLEX_DIRECTION_COLUMN_REVERSE;
-      init_css_node_children(node_0, 1);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->style.margin[CSS_LEFT] = 5;
-        node_1->style.margin[CSS_TOP] = 5;
-        node_1->style.margin[CSS_RIGHT] = 5;
-        node_1->style.margin[CSS_BOTTOM] = 5;
-        node_1->style.margin[CSS_START] = 5;
-        node_1->style.margin[CSS_END] = 5;
-      }
-    }
-
-    css_node_t *root_layout = new_test_css_node();
-    {
-      css_node_t *node_0 = root_layout;
-      node_0->layout.position[CSS_TOP] = 0;
-      node_0->layout.position[CSS_LEFT] = 0;
-      node_0->layout.dimensions[CSS_WIDTH] = 10;
-      node_0->layout.dimensions[CSS_HEIGHT] = 10;
-      init_css_node_children(node_0, 1);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->layout.position[CSS_TOP] = 5;
-        node_1->layout.position[CSS_LEFT] = 5;
-        node_1->layout.dimensions[CSS_WIDTH] = 0;
-        node_1->layout.dimensions[CSS_HEIGHT] = 0;
-      }
-    }
-
-    test("should layout child with margin in reverse", root_node, root_layout);
-  }
-
-  {
-    css_node_t *root_node = new_test_css_node();
-    {
-      css_node_t *node_0 = root_node;
-      node_0->style.dimensions[CSS_HEIGHT] = 100;
-      init_css_node_children(node_0, 2);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->style.dimensions[CSS_HEIGHT] = 100;
-        node_1 = node_0->get_child(node_0->context, 1);
-        node_1->style.dimensions[CSS_HEIGHT] = 200;
-      }
-    }
-
-    css_node_t *root_layout = new_test_css_node();
-    {
-      css_node_t *node_0 = root_layout;
-      node_0->layout.position[CSS_TOP] = 0;
-      node_0->layout.position[CSS_LEFT] = 0;
-      node_0->layout.dimensions[CSS_WIDTH] = 0;
-      node_0->layout.dimensions[CSS_HEIGHT] = 100;
-      init_css_node_children(node_0, 2);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->layout.position[CSS_TOP] = 0;
-        node_1->layout.position[CSS_LEFT] = 0;
-        node_1->layout.dimensions[CSS_WIDTH] = 0;
-        node_1->layout.dimensions[CSS_HEIGHT] = 100;
-        node_1 = node_0->get_child(node_0->context, 1);
-        node_1->layout.position[CSS_TOP] = 100;
-        node_1->layout.position[CSS_LEFT] = 0;
-        node_1->layout.dimensions[CSS_WIDTH] = 0;
-        node_1->layout.dimensions[CSS_HEIGHT] = 200;
-      }
-    }
-
-    test("should not shrink children if not enough space", root_node, root_layout);
-  }
-
-  {
-    css_node_t *root_node = new_test_css_node();
-    {
-      css_node_t *node_0 = root_node;
-      node_0->style.flex_direction = CSS_FLEX_DIRECTION_COLUMN_REVERSE;
-      node_0->style.dimensions[CSS_HEIGHT] = 100;
-      init_css_node_children(node_0, 2);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->style.dimensions[CSS_HEIGHT] = 100;
-        node_1 = node_0->get_child(node_0->context, 1);
-        node_1->style.dimensions[CSS_HEIGHT] = 200;
-      }
-    }
-
-    css_node_t *root_layout = new_test_css_node();
-    {
-      css_node_t *node_0 = root_layout;
-      node_0->layout.position[CSS_TOP] = 0;
-      node_0->layout.position[CSS_LEFT] = 0;
-      node_0->layout.dimensions[CSS_WIDTH] = 0;
-      node_0->layout.dimensions[CSS_HEIGHT] = 100;
-      init_css_node_children(node_0, 2);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->layout.position[CSS_TOP] = 0;
-        node_1->layout.position[CSS_LEFT] = 0;
-        node_1->layout.dimensions[CSS_WIDTH] = 0;
-        node_1->layout.dimensions[CSS_HEIGHT] = 100;
-        node_1 = node_0->get_child(node_0->context, 1);
-        node_1->layout.position[CSS_TOP] = -200;
-        node_1->layout.position[CSS_LEFT] = 0;
-        node_1->layout.dimensions[CSS_WIDTH] = 0;
-        node_1->layout.dimensions[CSS_HEIGHT] = 200;
-      }
-    }
-
-    test("should not shrink children if not enough space in reverse", root_node, root_layout);
-  }
-
-  {
-    css_node_t *root_node = new_test_css_node();
-    {
-      css_node_t *node_0 = root_node;
-      node_0->style.justify_content = CSS_JUSTIFY_CENTER;
-    }
-
-    css_node_t *root_layout = new_test_css_node();
-    {
-      css_node_t *node_0 = root_layout;
-      node_0->layout.position[CSS_TOP] = 0;
-      node_0->layout.position[CSS_LEFT] = 0;
-      node_0->layout.dimensions[CSS_WIDTH] = 0;
-      node_0->layout.dimensions[CSS_HEIGHT] = 0;
-    }
-
-    test("should layout for center", root_node, root_layout);
-  }
-
-  {
-    css_node_t *root_node = new_test_css_node();
-    {
-      css_node_t *node_0 = root_node;
-      node_0->style.justify_content = CSS_JUSTIFY_FLEX_END;
-      node_0->style.dimensions[CSS_HEIGHT] = 100;
-      init_css_node_children(node_0, 1);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->style.margin[CSS_TOP] = 10;
-      }
-    }
-
-    css_node_t *root_layout = new_test_css_node();
-    {
-      css_node_t *node_0 = root_layout;
-      node_0->layout.position[CSS_TOP] = 0;
-      node_0->layout.position[CSS_LEFT] = 0;
-      node_0->layout.dimensions[CSS_WIDTH] = 0;
-      node_0->layout.dimensions[CSS_HEIGHT] = 100;
-      init_css_node_children(node_0, 1);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->layout.position[CSS_TOP] = 100;
-        node_1->layout.position[CSS_LEFT] = 0;
-        node_1->layout.dimensions[CSS_WIDTH] = 0;
-        node_1->layout.dimensions[CSS_HEIGHT] = 0;
-      }
-    }
-
-    test("should layout flex-end taking into account margin", root_node, root_layout);
-  }
-
-  {
-    css_node_t *root_node = new_test_css_node();
-    {
-      css_node_t *node_0 = root_node;
-      node_0->style.flex_direction = CSS_FLEX_DIRECTION_COLUMN_REVERSE;
-      node_0->style.justify_content = CSS_JUSTIFY_FLEX_END;
-      node_0->style.dimensions[CSS_HEIGHT] = 100;
-      init_css_node_children(node_0, 1);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->style.margin[CSS_TOP] = 10;
-      }
-    }
-
-    css_node_t *root_layout = new_test_css_node();
-    {
-      css_node_t *node_0 = root_layout;
-      node_0->layout.position[CSS_TOP] = 0;
-      node_0->layout.position[CSS_LEFT] = 0;
-      node_0->layout.dimensions[CSS_WIDTH] = 0;
-      node_0->layout.dimensions[CSS_HEIGHT] = 100;
-      init_css_node_children(node_0, 1);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->layout.position[CSS_TOP] = 10;
-        node_1->layout.position[CSS_LEFT] = 0;
-        node_1->layout.dimensions[CSS_WIDTH] = 0;
-        node_1->layout.dimensions[CSS_HEIGHT] = 0;
-      }
-    }
-
-    test("should layout flex-end taking into account margin in reverse", root_node, root_layout);
-  }
-
-  {
-    css_node_t *root_node = new_test_css_node();
-    {
-      css_node_t *node_0 = root_node;
-      init_css_node_children(node_0, 1);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->style.align_items = CSS_ALIGN_FLEX_END;
-        init_css_node_children(node_1, 2);
-        {
-          css_node_t *node_2;
-          node_2 = node_1->get_child(node_1->context, 0);
-          node_2->style.margin[CSS_LEFT] = 10;
-          node_2->style.margin[CSS_TOP] = 10;
-          node_2->style.margin[CSS_RIGHT] = 10;
-          node_2->style.margin[CSS_BOTTOM] = 10;
-          node_2->style.margin[CSS_START] = 10;
-          node_2->style.margin[CSS_END] = 10;
-          node_2 = node_1->get_child(node_1->context, 1);
-          node_2->style.dimensions[CSS_HEIGHT] = 100;
-        }
-      }
-    }
-
-    css_node_t *root_layout = new_test_css_node();
-    {
-      css_node_t *node_0 = root_layout;
-      node_0->layout.position[CSS_TOP] = 0;
-      node_0->layout.position[CSS_LEFT] = 0;
-      node_0->layout.dimensions[CSS_WIDTH] = 20;
-      node_0->layout.dimensions[CSS_HEIGHT] = 120;
-      init_css_node_children(node_0, 1);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->layout.position[CSS_TOP] = 0;
-        node_1->layout.position[CSS_LEFT] = 0;
-        node_1->layout.dimensions[CSS_WIDTH] = 20;
-        node_1->layout.dimensions[CSS_HEIGHT] = 120;
-        init_css_node_children(node_1, 2);
-        {
-          css_node_t *node_2;
-          node_2 = node_1->get_child(node_1->context, 0);
-          node_2->layout.position[CSS_TOP] = 10;
-          node_2->layout.position[CSS_LEFT] = 10;
-          node_2->layout.dimensions[CSS_WIDTH] = 0;
-          node_2->layout.dimensions[CSS_HEIGHT] = 0;
-          node_2 = node_1->get_child(node_1->context, 1);
-          node_2->layout.position[CSS_TOP] = 20;
-          node_2->layout.position[CSS_LEFT] = 20;
-          node_2->layout.dimensions[CSS_WIDTH] = 0;
-          node_2->layout.dimensions[CSS_HEIGHT] = 100;
-        }
-      }
-    }
-
-    test("should layout alignItems with margin", root_node, root_layout);
-  }
-
-  {
-    css_node_t *root_node = new_test_css_node();
-    {
-      css_node_t *node_0 = root_node;
-      init_css_node_children(node_0, 1);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->style.flex_direction = CSS_FLEX_DIRECTION_COLUMN_REVERSE;
-        node_1->style.align_items = CSS_ALIGN_FLEX_END;
-        init_css_node_children(node_1, 2);
-        {
-          css_node_t *node_2;
-          node_2 = node_1->get_child(node_1->context, 0);
-          node_2->style.margin[CSS_LEFT] = 10;
-          node_2->style.margin[CSS_TOP] = 10;
-          node_2->style.margin[CSS_RIGHT] = 10;
-          node_2->style.margin[CSS_BOTTOM] = 10;
-          node_2->style.margin[CSS_START] = 10;
-          node_2->style.margin[CSS_END] = 10;
-          node_2 = node_1->get_child(node_1->context, 1);
-          node_2->style.dimensions[CSS_HEIGHT] = 100;
-        }
-      }
-    }
-
-    css_node_t *root_layout = new_test_css_node();
-    {
-      css_node_t *node_0 = root_layout;
-      node_0->layout.position[CSS_TOP] = 0;
-      node_0->layout.position[CSS_LEFT] = 0;
-      node_0->layout.dimensions[CSS_WIDTH] = 20;
-      node_0->layout.dimensions[CSS_HEIGHT] = 120;
-      init_css_node_children(node_0, 1);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->layout.position[CSS_TOP] = 0;
-        node_1->layout.position[CSS_LEFT] = 0;
-        node_1->layout.dimensions[CSS_WIDTH] = 20;
-        node_1->layout.dimensions[CSS_HEIGHT] = 120;
-        init_css_node_children(node_1, 2);
-        {
-          css_node_t *node_2;
-          node_2 = node_1->get_child(node_1->context, 0);
-          node_2->layout.position[CSS_TOP] = 110;
-          node_2->layout.position[CSS_LEFT] = 10;
-          node_2->layout.dimensions[CSS_WIDTH] = 0;
-          node_2->layout.dimensions[CSS_HEIGHT] = 0;
-          node_2 = node_1->get_child(node_1->context, 1);
-          node_2->layout.position[CSS_TOP] = 0;
-          node_2->layout.position[CSS_LEFT] = 20;
-          node_2->layout.dimensions[CSS_WIDTH] = 0;
-          node_2->layout.dimensions[CSS_HEIGHT] = 100;
-        }
-      }
-    }
-
-    test("should layout alignItems with margin in reverse", root_node, root_layout);
-  }
-
-  {
-    css_node_t *root_node = new_test_css_node();
-    {
-      css_node_t *node_0 = root_node;
-      init_css_node_children(node_0, 1);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->style.flex = 1;
-      }
-    }
-
-    css_node_t *root_layout = new_test_css_node();
-    {
-      css_node_t *node_0 = root_layout;
-      node_0->layout.position[CSS_TOP] = 0;
-      node_0->layout.position[CSS_LEFT] = 0;
-      node_0->layout.dimensions[CSS_WIDTH] = 0;
-      node_0->layout.dimensions[CSS_HEIGHT] = 0;
-      init_css_node_children(node_0, 1);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->layout.position[CSS_TOP] = 0;
-        node_1->layout.position[CSS_LEFT] = 0;
-        node_1->layout.dimensions[CSS_WIDTH] = 0;
-        node_1->layout.dimensions[CSS_HEIGHT] = 0;
-      }
-    }
-
-    test("should layout flex inside of an empty element", root_node, root_layout);
-  }
-
-  {
-    css_node_t *root_node = new_test_css_node();
-    {
-      css_node_t *node_0 = root_node;
-      node_0->style.align_items = CSS_ALIGN_STRETCH;
-      init_css_node_children(node_0, 1);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->style.margin[CSS_LEFT] = 10;
-      }
-    }
-
-    css_node_t *root_layout = new_test_css_node();
-    {
-      css_node_t *node_0 = root_layout;
-      node_0->layout.position[CSS_TOP] = 0;
-      node_0->layout.position[CSS_LEFT] = 0;
-      node_0->layout.dimensions[CSS_WIDTH] = 10;
-      node_0->layout.dimensions[CSS_HEIGHT] = 0;
-      init_css_node_children(node_0, 1);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->layout.position[CSS_TOP] = 0;
-        node_1->layout.position[CSS_LEFT] = 10;
-        node_1->layout.dimensions[CSS_WIDTH] = 0;
-        node_1->layout.dimensions[CSS_HEIGHT] = 0;
-      }
-    }
-
-    test("should layout alignItems stretch and margin", root_node, root_layout);
-  }
-
-  {
-    css_node_t *root_node = new_test_css_node();
-    {
-      css_node_t *node_0 = root_node;
-      node_0->style.flex_direction = CSS_FLEX_DIRECTION_COLUMN_REVERSE;
-      node_0->style.align_items = CSS_ALIGN_STRETCH;
-      init_css_node_children(node_0, 1);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->style.margin[CSS_LEFT] = 10;
-      }
-    }
-
-    css_node_t *root_layout = new_test_css_node();
-    {
-      css_node_t *node_0 = root_layout;
-      node_0->layout.position[CSS_TOP] = 0;
-      node_0->layout.position[CSS_LEFT] = 0;
-      node_0->layout.dimensions[CSS_WIDTH] = 10;
-      node_0->layout.dimensions[CSS_HEIGHT] = 0;
-      init_css_node_children(node_0, 1);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->layout.position[CSS_TOP] = 0;
-        node_1->layout.position[CSS_LEFT] = 10;
-        node_1->layout.dimensions[CSS_WIDTH] = 0;
-        node_1->layout.dimensions[CSS_HEIGHT] = 0;
-      }
-    }
-
-    test("should layout alignItems stretch and margin in reverse", root_node, root_layout);
-  }
-
-  {
-    css_node_t *root_node = new_test_css_node();
-    {
-      css_node_t *node_0 = root_node;
-      node_0->style.padding[CSS_LEFT] = 5;
-      node_0->style.padding[CSS_TOP] = 5;
-      node_0->style.padding[CSS_RIGHT] = 5;
-      node_0->style.padding[CSS_BOTTOM] = 5;
-      node_0->style.padding[CSS_START] = 5;
-      node_0->style.padding[CSS_END] = 5;
-    }
-
-    css_node_t *root_layout = new_test_css_node();
-    {
-      css_node_t *node_0 = root_layout;
-      node_0->layout.position[CSS_TOP] = 0;
-      node_0->layout.position[CSS_LEFT] = 0;
-      node_0->layout.dimensions[CSS_WIDTH] = 10;
-      node_0->layout.dimensions[CSS_HEIGHT] = 10;
-    }
-
-    test("should layout node with padding", root_node, root_layout);
-  }
-
-  {
-    css_node_t *root_node = new_test_css_node();
-    {
-      css_node_t *node_0 = root_node;
-      node_0->style.padding[CSS_LEFT] = 5;
-      node_0->style.padding[CSS_TOP] = 5;
-      node_0->style.padding[CSS_RIGHT] = 5;
-      node_0->style.padding[CSS_BOTTOM] = 5;
-      node_0->style.padding[CSS_START] = 5;
-      node_0->style.padding[CSS_END] = 5;
-      init_css_node_children(node_0, 1);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-      }
-    }
-
-    css_node_t *root_layout = new_test_css_node();
-    {
-      css_node_t *node_0 = root_layout;
-      node_0->layout.position[CSS_TOP] = 0;
-      node_0->layout.position[CSS_LEFT] = 0;
-      node_0->layout.dimensions[CSS_WIDTH] = 10;
-      node_0->layout.dimensions[CSS_HEIGHT] = 10;
-      init_css_node_children(node_0, 1);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->layout.position[CSS_TOP] = 5;
-        node_1->layout.position[CSS_LEFT] = 5;
-        node_1->layout.dimensions[CSS_WIDTH] = 0;
-        node_1->layout.dimensions[CSS_HEIGHT] = 0;
-      }
-    }
-
-    test("should layout node with padding and a child", root_node, root_layout);
-  }
-
-  {
-    css_node_t *root_node = new_test_css_node();
-    {
-      css_node_t *node_0 = root_node;
-      node_0->style.padding[CSS_LEFT] = 5;
-      node_0->style.padding[CSS_TOP] = 5;
-      node_0->style.padding[CSS_RIGHT] = 5;
-      node_0->style.padding[CSS_BOTTOM] = 5;
-      node_0->style.padding[CSS_START] = 5;
-      node_0->style.padding[CSS_END] = 5;
-      init_css_node_children(node_0, 1);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->style.margin[CSS_LEFT] = 5;
-        node_1->style.margin[CSS_TOP] = 5;
-        node_1->style.margin[CSS_RIGHT] = 5;
-        node_1->style.margin[CSS_BOTTOM] = 5;
-        node_1->style.margin[CSS_START] = 5;
-        node_1->style.margin[CSS_END] = 5;
-      }
-    }
-
-    css_node_t *root_layout = new_test_css_node();
-    {
-      css_node_t *node_0 = root_layout;
-      node_0->layout.position[CSS_TOP] = 0;
-      node_0->layout.position[CSS_LEFT] = 0;
-      node_0->layout.dimensions[CSS_WIDTH] = 20;
-      node_0->layout.dimensions[CSS_HEIGHT] = 20;
-      init_css_node_children(node_0, 1);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->layout.position[CSS_TOP] = 10;
-        node_1->layout.position[CSS_LEFT] = 10;
-        node_1->layout.dimensions[CSS_WIDTH] = 0;
-        node_1->layout.dimensions[CSS_HEIGHT] = 0;
-      }
-    }
-
-    test("should layout node with padding and a child with margin", root_node, root_layout);
-  }
-
-  {
-    css_node_t *root_node = new_test_css_node();
-    {
-      css_node_t *node_0 = root_node;
-      init_css_node_children(node_0, 1);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->style.align_self = CSS_ALIGN_STRETCH;
-        node_1->style.padding[CSS_LEFT] = 10;
-        node_1->style.padding[CSS_TOP] = 10;
-        node_1->style.padding[CSS_RIGHT] = 10;
-        node_1->style.padding[CSS_BOTTOM] = 10;
-        node_1->style.padding[CSS_START] = 10;
-        node_1->style.padding[CSS_END] = 10;
-      }
-    }
-
-    css_node_t *root_layout = new_test_css_node();
-    {
-      css_node_t *node_0 = root_layout;
-      node_0->layout.position[CSS_TOP] = 0;
-      node_0->layout.position[CSS_LEFT] = 0;
-      node_0->layout.dimensions[CSS_WIDTH] = 20;
-      node_0->layout.dimensions[CSS_HEIGHT] = 20;
-      init_css_node_children(node_0, 1);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->layout.position[CSS_TOP] = 0;
-        node_1->layout.position[CSS_LEFT] = 0;
-        node_1->layout.dimensions[CSS_WIDTH] = 20;
-        node_1->layout.dimensions[CSS_HEIGHT] = 20;
-      }
-    }
-
-    test("should layout node with padding and stretch", root_node, root_layout);
-  }
-
-  {
-    css_node_t *root_node = new_test_css_node();
-    {
-      css_node_t *node_0 = root_node;
-      node_0->style.padding[CSS_LEFT] = 50;
-      node_0->style.padding[CSS_TOP] = 50;
-      node_0->style.padding[CSS_RIGHT] = 50;
-      node_0->style.padding[CSS_BOTTOM] = 50;
-      node_0->style.padding[CSS_START] = 50;
-      node_0->style.padding[CSS_END] = 50;
-      init_css_node_children(node_0, 1);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->style.align_self = CSS_ALIGN_STRETCH;
-        node_1->style.padding[CSS_LEFT] = 10;
-        node_1->style.padding[CSS_TOP] = 10;
-        node_1->style.padding[CSS_RIGHT] = 10;
-        node_1->style.padding[CSS_BOTTOM] = 10;
-        node_1->style.padding[CSS_START] = 10;
-        node_1->style.padding[CSS_END] = 10;
-      }
-    }
-
-    css_node_t *root_layout = new_test_css_node();
-    {
-      css_node_t *node_0 = root_layout;
-      node_0->layout.position[CSS_TOP] = 0;
-      node_0->layout.position[CSS_LEFT] = 0;
-      node_0->layout.dimensions[CSS_WIDTH] = 120;
-      node_0->layout.dimensions[CSS_HEIGHT] = 120;
-      init_css_node_children(node_0, 1);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->layout.position[CSS_TOP] = 50;
-        node_1->layout.position[CSS_LEFT] = 50;
-        node_1->layout.dimensions[CSS_WIDTH] = 20;
-        node_1->layout.dimensions[CSS_HEIGHT] = 20;
-      }
-    }
-
-    test("should layout node with inner & outer padding and stretch", root_node, root_layout);
-  }
-
-  {
-    css_node_t *root_node = new_test_css_node();
-    {
-      css_node_t *node_0 = root_node;
-      init_css_node_children(node_0, 1);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->style.align_self = CSS_ALIGN_STRETCH;
-        init_css_node_children(node_1, 1);
-        {
-          css_node_t *node_2;
-          node_2 = node_1->get_child(node_1->context, 0);
-          node_2->style.margin[CSS_LEFT] = 16;
-          node_2->style.margin[CSS_TOP] = 16;
-          node_2->style.margin[CSS_RIGHT] = 16;
-          node_2->style.margin[CSS_BOTTOM] = 16;
-          node_2->style.margin[CSS_START] = 16;
-          node_2->style.margin[CSS_END] = 16;
-        }
-      }
-    }
-
-    css_node_t *root_layout = new_test_css_node();
-    {
-      css_node_t *node_0 = root_layout;
-      node_0->layout.position[CSS_TOP] = 0;
-      node_0->layout.position[CSS_LEFT] = 0;
-      node_0->layout.dimensions[CSS_WIDTH] = 32;
-      node_0->layout.dimensions[CSS_HEIGHT] = 32;
-      init_css_node_children(node_0, 1);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->layout.position[CSS_TOP] = 0;
-        node_1->layout.position[CSS_LEFT] = 0;
-        node_1->layout.dimensions[CSS_WIDTH] = 32;
-        node_1->layout.dimensions[CSS_HEIGHT] = 32;
-        init_css_node_children(node_1, 1);
-        {
-          css_node_t *node_2;
-          node_2 = node_1->get_child(node_1->context, 0);
-          node_2->layout.position[CSS_TOP] = 16;
-          node_2->layout.position[CSS_LEFT] = 16;
-          node_2->layout.dimensions[CSS_WIDTH] = 0;
-          node_2->layout.dimensions[CSS_HEIGHT] = 0;
-        }
-      }
-    }
-
-    test("should layout node with stretch and child with margin", root_node, root_layout);
-  }
-
-  {
-    css_node_t *root_node = new_test_css_node();
-    {
-      css_node_t *node_0 = root_node;
-      node_0->style.position[CSS_LEFT] = 5;
-      node_0->style.position[CSS_TOP] = 5;
-    }
-
-    css_node_t *root_layout = new_test_css_node();
-    {
-      css_node_t *node_0 = root_layout;
-      node_0->layout.position[CSS_TOP] = 5;
-      node_0->layout.position[CSS_LEFT] = 5;
-      node_0->layout.dimensions[CSS_WIDTH] = 0;
-      node_0->layout.dimensions[CSS_HEIGHT] = 0;
-    }
-
-    test("should layout node with top and left", root_node, root_layout);
-  }
-
-  {
-    css_node_t *root_node = new_test_css_node();
-    {
-      css_node_t *node_0 = root_node;
-      node_0->style.justify_content = CSS_JUSTIFY_SPACE_AROUND;
-      node_0->style.dimensions[CSS_HEIGHT] = 10;
-      node_0->style.padding[CSS_TOP] = 5;
-      init_css_node_children(node_0, 1);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-      }
-    }
-
-    css_node_t *root_layout = new_test_css_node();
-    {
-      css_node_t *node_0 = root_layout;
-      node_0->layout.position[CSS_TOP] = 0;
-      node_0->layout.position[CSS_LEFT] = 0;
-      node_0->layout.dimensions[CSS_WIDTH] = 0;
-      node_0->layout.dimensions[CSS_HEIGHT] = 10;
-      init_css_node_children(node_0, 1);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->layout.position[CSS_TOP] = 7.5;
-        node_1->layout.position[CSS_LEFT] = 0;
-        node_1->layout.dimensions[CSS_WIDTH] = 0;
-        node_1->layout.dimensions[CSS_HEIGHT] = 0;
-      }
-    }
-
-    test("should layout node with height, padding and space-around", root_node, root_layout);
-  }
-
-  {
-    css_node_t *root_node = new_test_css_node();
-    {
-      css_node_t *node_0 = root_node;
-      node_0->style.position[CSS_BOTTOM] = 5;
-    }
-
-    css_node_t *root_layout = new_test_css_node();
-    {
-      css_node_t *node_0 = root_layout;
-      node_0->layout.position[CSS_TOP] = -5;
-      node_0->layout.position[CSS_LEFT] = 0;
-      node_0->layout.dimensions[CSS_WIDTH] = 0;
-      node_0->layout.dimensions[CSS_HEIGHT] = 0;
-    }
-
-    test("should layout node with bottom", root_node, root_layout);
-  }
-
-  {
-    css_node_t *root_node = new_test_css_node();
-    {
-      css_node_t *node_0 = root_node;
-      node_0->style.position[CSS_TOP] = 10;
-      node_0->style.position[CSS_BOTTOM] = 5;
-    }
-
-    css_node_t *root_layout = new_test_css_node();
-    {
-      css_node_t *node_0 = root_layout;
-      node_0->layout.position[CSS_TOP] = 10;
-      node_0->layout.position[CSS_LEFT] = 0;
-      node_0->layout.dimensions[CSS_WIDTH] = 0;
-      node_0->layout.dimensions[CSS_HEIGHT] = 0;
-    }
-
-    test("should layout node with both top and bottom", root_node, root_layout);
-  }
-
-  {
-    css_node_t *root_node = new_test_css_node();
-    {
-      css_node_t *node_0 = root_node;
-      node_0->style.flex_direction = CSS_FLEX_DIRECTION_ROW;
-      node_0->style.dimensions[CSS_WIDTH] = 500;
-      init_css_node_children(node_0, 3);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->style.flex = 1;
-        node_1 = node_0->get_child(node_0->context, 1);
-        node_1->style.position_type = CSS_POSITION_ABSOLUTE;
-        node_1->style.dimensions[CSS_WIDTH] = 50;
-        node_1 = node_0->get_child(node_0->context, 2);
-        node_1->style.flex = 1;
-      }
-    }
-
-    css_node_t *root_layout = new_test_css_node();
-    {
-      css_node_t *node_0 = root_layout;
-      node_0->layout.position[CSS_TOP] = 0;
-      node_0->layout.position[CSS_LEFT] = 0;
-      node_0->layout.dimensions[CSS_WIDTH] = 500;
-      node_0->layout.dimensions[CSS_HEIGHT] = 0;
-      init_css_node_children(node_0, 3);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->layout.position[CSS_TOP] = 0;
-        node_1->layout.position[CSS_LEFT] = 0;
-        node_1->layout.dimensions[CSS_WIDTH] = 250;
-        node_1->layout.dimensions[CSS_HEIGHT] = 0;
-        node_1 = node_0->get_child(node_0->context, 1);
-        node_1->layout.position[CSS_TOP] = 0;
-        node_1->layout.position[CSS_LEFT] = 250;
-        node_1->layout.dimensions[CSS_WIDTH] = 50;
-        node_1->layout.dimensions[CSS_HEIGHT] = 0;
-        node_1 = node_0->get_child(node_0->context, 2);
-        node_1->layout.position[CSS_TOP] = 0;
-        node_1->layout.position[CSS_LEFT] = 250;
-        node_1->layout.dimensions[CSS_WIDTH] = 250;
-        node_1->layout.dimensions[CSS_HEIGHT] = 0;
-      }
-    }
-
-    test("should layout node with position: absolute", root_node, root_layout);
-  }
-
-  {
-    css_node_t *root_node = new_test_css_node();
-    {
-      css_node_t *node_0 = root_node;
-      init_css_node_children(node_0, 1);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->style.position_type = CSS_POSITION_ABSOLUTE;
-        node_1->style.margin[CSS_RIGHT] = 15;
-      }
-    }
-
-    css_node_t *root_layout = new_test_css_node();
-    {
-      css_node_t *node_0 = root_layout;
-      node_0->layout.position[CSS_TOP] = 0;
-      node_0->layout.position[CSS_LEFT] = 0;
-      node_0->layout.dimensions[CSS_WIDTH] = 0;
-      node_0->layout.dimensions[CSS_HEIGHT] = 0;
-      init_css_node_children(node_0, 1);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->layout.position[CSS_TOP] = 0;
-        node_1->layout.position[CSS_LEFT] = 0;
-        node_1->layout.dimensions[CSS_WIDTH] = 0;
-        node_1->layout.dimensions[CSS_HEIGHT] = 0;
-      }
-    }
-
-    test("should layout node with child with position: absolute and margin", root_node, root_layout);
-  }
-
-  {
-    css_node_t *root_node = new_test_css_node();
-    {
-      css_node_t *node_0 = root_node;
-      init_css_node_children(node_0, 1);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->style.align_self = CSS_ALIGN_CENTER;
-        node_1->style.position_type = CSS_POSITION_ABSOLUTE;
-        node_1->style.padding[CSS_RIGHT] = 12;
-      }
-    }
-
-    css_node_t *root_layout = new_test_css_node();
-    {
-      css_node_t *node_0 = root_layout;
-      node_0->layout.position[CSS_TOP] = 0;
-      node_0->layout.position[CSS_LEFT] = 0;
-      node_0->layout.dimensions[CSS_WIDTH] = 0;
-      node_0->layout.dimensions[CSS_HEIGHT] = 0;
-      init_css_node_children(node_0, 1);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->layout.position[CSS_TOP] = 0;
-        node_1->layout.position[CSS_LEFT] = 0;
-        node_1->layout.dimensions[CSS_WIDTH] = 12;
-        node_1->layout.dimensions[CSS_HEIGHT] = 0;
-      }
-    }
-
-    test("should layout node with position: absolute, padding and alignSelf: center", root_node, root_layout);
-  }
-
-  {
-    css_node_t *root_node = new_test_css_node();
-    {
-      css_node_t *node_0 = root_node;
-      node_0->style.dimensions[CSS_HEIGHT] = 5;
-      node_0->style.padding[CSS_BOTTOM] = 20;
-    }
-
-    css_node_t *root_layout = new_test_css_node();
-    {
-      css_node_t *node_0 = root_layout;
-      node_0->layout.position[CSS_TOP] = 0;
-      node_0->layout.position[CSS_LEFT] = 0;
-      node_0->layout.dimensions[CSS_WIDTH] = 0;
-      node_0->layout.dimensions[CSS_HEIGHT] = 20;
-    }
-
-    test("should work with height smaller than paddingBottom", root_node, root_layout);
-  }
-
-  {
-    css_node_t *root_node = new_test_css_node();
-    {
-      css_node_t *node_0 = root_node;
-      node_0->style.dimensions[CSS_WIDTH] = 5;
-      node_0->style.padding[CSS_LEFT] = 20;
-    }
-
-    css_node_t *root_layout = new_test_css_node();
-    {
-      css_node_t *node_0 = root_layout;
-      node_0->layout.position[CSS_TOP] = 0;
-      node_0->layout.position[CSS_LEFT] = 0;
-      node_0->layout.dimensions[CSS_WIDTH] = 20;
-      node_0->layout.dimensions[CSS_HEIGHT] = 0;
-    }
-
-    test("should work with width smaller than paddingLeft", root_node, root_layout);
-  }
-
-  {
-    css_node_t *root_node = new_test_css_node();
-    {
-      css_node_t *node_0 = root_node;
-      init_css_node_children(node_0, 2);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        init_css_node_children(node_1, 1);
-        {
-          css_node_t *node_2;
-          node_2 = node_1->get_child(node_1->context, 0);
-          node_2->style.dimensions[CSS_WIDTH] = 400;
-        }
-        node_1 = node_0->get_child(node_0->context, 1);
-        node_1->style.align_self = CSS_ALIGN_STRETCH;
-        node_1->style.dimensions[CSS_WIDTH] = 200;
-      }
-    }
-
-    css_node_t *root_layout = new_test_css_node();
-    {
-      css_node_t *node_0 = root_layout;
-      node_0->layout.position[CSS_TOP] = 0;
-      node_0->layout.position[CSS_LEFT] = 0;
-      node_0->layout.dimensions[CSS_WIDTH] = 400;
-      node_0->layout.dimensions[CSS_HEIGHT] = 0;
-      init_css_node_children(node_0, 2);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->layout.position[CSS_TOP] = 0;
-        node_1->layout.position[CSS_LEFT] = 0;
-        node_1->layout.dimensions[CSS_WIDTH] = 400;
-        node_1->layout.dimensions[CSS_HEIGHT] = 0;
-        init_css_node_children(node_1, 1);
-        {
-          css_node_t *node_2;
-          node_2 = node_1->get_child(node_1->context, 0);
-          node_2->layout.position[CSS_TOP] = 0;
-          node_2->layout.position[CSS_LEFT] = 0;
-          node_2->layout.dimensions[CSS_WIDTH] = 400;
-          node_2->layout.dimensions[CSS_HEIGHT] = 0;
-        }
-        node_1 = node_0->get_child(node_0->context, 1);
-        node_1->layout.position[CSS_TOP] = 0;
-        node_1->layout.position[CSS_LEFT] = 0;
-        node_1->layout.dimensions[CSS_WIDTH] = 200;
-        node_1->layout.dimensions[CSS_HEIGHT] = 0;
-      }
-    }
-
-    test("should layout node with specified width and stretch", root_node, root_layout);
-  }
-
-  {
-    css_node_t *root_node = new_test_css_node();
-    {
-      css_node_t *node_0 = root_node;
-      node_0->style.padding[CSS_LEFT] = 5;
-      node_0->style.padding[CSS_TOP] = 5;
-      node_0->style.padding[CSS_RIGHT] = 5;
-      node_0->style.padding[CSS_BOTTOM] = 5;
-      node_0->style.padding[CSS_START] = 5;
-      node_0->style.padding[CSS_END] = 5;
-      init_css_node_children(node_0, 1);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->style.position_type = CSS_POSITION_ABSOLUTE;
-      }
-    }
-
-    css_node_t *root_layout = new_test_css_node();
-    {
-      css_node_t *node_0 = root_layout;
-      node_0->layout.position[CSS_TOP] = 0;
-      node_0->layout.position[CSS_LEFT] = 0;
-      node_0->layout.dimensions[CSS_WIDTH] = 10;
-      node_0->layout.dimensions[CSS_HEIGHT] = 10;
-      init_css_node_children(node_0, 1);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->layout.position[CSS_TOP] = 5;
-        node_1->layout.position[CSS_LEFT] = 5;
-        node_1->layout.dimensions[CSS_WIDTH] = 0;
-        node_1->layout.dimensions[CSS_HEIGHT] = 0;
-      }
-    }
-
-    test("should layout node with padding and child with position absolute", root_node, root_layout);
-  }
-
-  {
-    css_node_t *root_node = new_test_css_node();
-    {
-      css_node_t *node_0 = root_node;
-      init_css_node_children(node_0, 2);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->style.dimensions[CSS_HEIGHT] = 100;
-        node_1 = node_0->get_child(node_0->context, 1);
-        node_1->style.position_type = CSS_POSITION_ABSOLUTE;
-        node_1->style.position[CSS_LEFT] = 10;
-        node_1->style.position[CSS_TOP] = 10;
-      }
-    }
-
-    css_node_t *root_layout = new_test_css_node();
-    {
-      css_node_t *node_0 = root_layout;
-      node_0->layout.position[CSS_TOP] = 0;
-      node_0->layout.position[CSS_LEFT] = 0;
-      node_0->layout.dimensions[CSS_WIDTH] = 0;
-      node_0->layout.dimensions[CSS_HEIGHT] = 100;
-      init_css_node_children(node_0, 2);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->layout.position[CSS_TOP] = 0;
-        node_1->layout.position[CSS_LEFT] = 0;
-        node_1->layout.dimensions[CSS_WIDTH] = 0;
-        node_1->layout.dimensions[CSS_HEIGHT] = 100;
-        node_1 = node_0->get_child(node_0->context, 1);
-        node_1->layout.position[CSS_TOP] = 10;
-        node_1->layout.position[CSS_LEFT] = 10;
-        node_1->layout.dimensions[CSS_WIDTH] = 0;
-        node_1->layout.dimensions[CSS_HEIGHT] = 0;
-      }
-    }
-
-    test("should layout node with position absolute, top and left", root_node, root_layout);
-  }
-
-  {
-    css_node_t *root_node = new_test_css_node();
-    {
-      css_node_t *node_0 = root_node;
-      node_0->style.padding[CSS_LEFT] = 20;
-      node_0->style.padding[CSS_TOP] = 20;
-      node_0->style.padding[CSS_RIGHT] = 20;
-      node_0->style.padding[CSS_BOTTOM] = 20;
-      node_0->style.padding[CSS_START] = 20;
-      node_0->style.padding[CSS_END] = 20;
-      init_css_node_children(node_0, 1);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->style.position_type = CSS_POSITION_ABSOLUTE;
-        node_1->style.position[CSS_LEFT] = 5;
-      }
-    }
-
-    css_node_t *root_layout = new_test_css_node();
-    {
-      css_node_t *node_0 = root_layout;
-      node_0->layout.position[CSS_TOP] = 0;
-      node_0->layout.position[CSS_LEFT] = 0;
-      node_0->layout.dimensions[CSS_WIDTH] = 40;
-      node_0->layout.dimensions[CSS_HEIGHT] = 40;
-      init_css_node_children(node_0, 1);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->layout.position[CSS_TOP] = 20;
-        node_1->layout.position[CSS_LEFT] = 5;
-        node_1->layout.dimensions[CSS_WIDTH] = 0;
-        node_1->layout.dimensions[CSS_HEIGHT] = 0;
-      }
-    }
-
-    test("should layout node with padding and child position absolute, left", root_node, root_layout);
-  }
-
-  {
-    css_node_t *root_node = new_test_css_node();
-    {
-      css_node_t *node_0 = root_node;
-      init_css_node_children(node_0, 1);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->style.position_type = CSS_POSITION_ABSOLUTE;
-        node_1->style.margin[CSS_TOP] = 5;
-        node_1->style.position[CSS_TOP] = 5;
-      }
-    }
-
-    css_node_t *root_layout = new_test_css_node();
-    {
-      css_node_t *node_0 = root_layout;
-      node_0->layout.position[CSS_TOP] = 0;
-      node_0->layout.position[CSS_LEFT] = 0;
-      node_0->layout.dimensions[CSS_WIDTH] = 0;
-      node_0->layout.dimensions[CSS_HEIGHT] = 0;
-      init_css_node_children(node_0, 1);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->layout.position[CSS_TOP] = 10;
-        node_1->layout.position[CSS_LEFT] = 0;
-        node_1->layout.dimensions[CSS_WIDTH] = 0;
-        node_1->layout.dimensions[CSS_HEIGHT] = 0;
-      }
-    }
-
-    test("should layout node with position: absolute, top and marginTop", root_node, root_layout);
-  }
-
-  {
-    css_node_t *root_node = new_test_css_node();
-    {
-      css_node_t *node_0 = root_node;
-      init_css_node_children(node_0, 1);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->style.position_type = CSS_POSITION_ABSOLUTE;
-        node_1->style.margin[CSS_LEFT] = 5;
-        node_1->style.position[CSS_LEFT] = 5;
-      }
-    }
-
-    css_node_t *root_layout = new_test_css_node();
-    {
-      css_node_t *node_0 = root_layout;
-      node_0->layout.position[CSS_TOP] = 0;
-      node_0->layout.position[CSS_LEFT] = 0;
-      node_0->layout.dimensions[CSS_WIDTH] = 0;
-      node_0->layout.dimensions[CSS_HEIGHT] = 0;
-      init_css_node_children(node_0, 1);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->layout.position[CSS_TOP] = 0;
-        node_1->layout.position[CSS_LEFT] = 10;
-        node_1->layout.dimensions[CSS_WIDTH] = 0;
-        node_1->layout.dimensions[CSS_HEIGHT] = 0;
-      }
-    }
-
-    test("should layout node with position: absolute, left and marginLeft", root_node, root_layout);
-  }
-
-  {
-    css_node_t *root_node = new_test_css_node();
-    {
-      css_node_t *node_0 = root_node;
-      node_0->style.justify_content = CSS_JUSTIFY_SPACE_AROUND;
-      node_0->style.dimensions[CSS_HEIGHT] = 200;
-      init_css_node_children(node_0, 2);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->style.position_type = CSS_POSITION_ABSOLUTE;
-        node_1 = node_0->get_child(node_0->context, 1);
-      }
-    }
-
-    css_node_t *root_layout = new_test_css_node();
-    {
-      css_node_t *node_0 = root_layout;
-      node_0->layout.position[CSS_TOP] = 0;
-      node_0->layout.position[CSS_LEFT] = 0;
-      node_0->layout.dimensions[CSS_WIDTH] = 0;
-      node_0->layout.dimensions[CSS_HEIGHT] = 200;
-      init_css_node_children(node_0, 2);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->layout.position[CSS_TOP] = 100;
-        node_1->layout.position[CSS_LEFT] = 0;
-        node_1->layout.dimensions[CSS_WIDTH] = 0;
-        node_1->layout.dimensions[CSS_HEIGHT] = 0;
-        node_1 = node_0->get_child(node_0->context, 1);
-        node_1->layout.position[CSS_TOP] = 100;
-        node_1->layout.position[CSS_LEFT] = 0;
-        node_1->layout.dimensions[CSS_WIDTH] = 0;
-        node_1->layout.dimensions[CSS_HEIGHT] = 0;
-      }
-    }
-
-    test("should layout node with space-around and child position absolute", root_node, root_layout);
-  }
-
-  {
-    css_node_t *root_node = new_test_css_node();
-    {
-      css_node_t *node_0 = root_node;
-      node_0->style.flex_direction = CSS_FLEX_DIRECTION_COLUMN_REVERSE;
-      node_0->style.justify_content = CSS_JUSTIFY_SPACE_AROUND;
-      node_0->style.dimensions[CSS_HEIGHT] = 200;
-      init_css_node_children(node_0, 2);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->style.position_type = CSS_POSITION_ABSOLUTE;
-        node_1 = node_0->get_child(node_0->context, 1);
-      }
-    }
-
-    css_node_t *root_layout = new_test_css_node();
-    {
-      css_node_t *node_0 = root_layout;
-      node_0->layout.position[CSS_TOP] = 0;
-      node_0->layout.position[CSS_LEFT] = 0;
-      node_0->layout.dimensions[CSS_WIDTH] = 0;
-      node_0->layout.dimensions[CSS_HEIGHT] = 200;
-      init_css_node_children(node_0, 2);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->layout.position[CSS_TOP] = 100;
-        node_1->layout.position[CSS_LEFT] = 0;
-        node_1->layout.dimensions[CSS_WIDTH] = 0;
-        node_1->layout.dimensions[CSS_HEIGHT] = 0;
-        node_1 = node_0->get_child(node_0->context, 1);
-        node_1->layout.position[CSS_TOP] = 100;
-        node_1->layout.position[CSS_LEFT] = 0;
-        node_1->layout.dimensions[CSS_WIDTH] = 0;
-        node_1->layout.dimensions[CSS_HEIGHT] = 0;
-      }
-    }
-
-    test("should layout node with space-around and child position absolute in reverse", root_node, root_layout);
-  }
-
-  {
-    css_node_t *root_node = new_test_css_node();
-    {
-      css_node_t *node_0 = root_node;
-      node_0->style.flex_direction = CSS_FLEX_DIRECTION_ROW;
-      node_0->style.dimensions[CSS_WIDTH] = 700;
-      init_css_node_children(node_0, 1);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->style.flex = 1;
-        node_1->style.margin[CSS_LEFT] = 5;
-      }
-    }
-
-    css_node_t *root_layout = new_test_css_node();
-    {
-      css_node_t *node_0 = root_layout;
-      node_0->layout.position[CSS_TOP] = 0;
-      node_0->layout.position[CSS_LEFT] = 0;
-      node_0->layout.dimensions[CSS_WIDTH] = 700;
-      node_0->layout.dimensions[CSS_HEIGHT] = 0;
-      init_css_node_children(node_0, 1);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->layout.position[CSS_TOP] = 0;
-        node_1->layout.position[CSS_LEFT] = 5;
-        node_1->layout.dimensions[CSS_WIDTH] = 695;
-        node_1->layout.dimensions[CSS_HEIGHT] = 0;
-      }
-    }
-
-    test("should layout node with flex and main margin", root_node, root_layout);
-  }
-
-  {
-    css_node_t *root_node = new_test_css_node();
-    {
-      css_node_t *node_0 = root_node;
-      node_0->style.direction = CSS_DIRECTION_RTL;
-      node_0->style.flex_direction = CSS_FLEX_DIRECTION_ROW;
-      node_0->style.dimensions[CSS_WIDTH] = 700;
-      init_css_node_children(node_0, 1);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->style.flex = 1;
-        node_1->style.margin[CSS_RIGHT] = 5;
-      }
-    }
-
-    css_node_t *root_layout = new_test_css_node();
-    {
-      css_node_t *node_0 = root_layout;
-      node_0->layout.position[CSS_TOP] = 0;
-      node_0->layout.position[CSS_LEFT] = 0;
-      node_0->layout.dimensions[CSS_WIDTH] = 700;
-      node_0->layout.dimensions[CSS_HEIGHT] = 0;
-      init_css_node_children(node_0, 1);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->layout.position[CSS_TOP] = 0;
-        node_1->layout.position[CSS_LEFT] = 0;
-        node_1->layout.dimensions[CSS_WIDTH] = 695;
-        node_1->layout.dimensions[CSS_HEIGHT] = 0;
-      }
-    }
-
-    test("should layout node with flex and main margin in rtl", root_node, root_layout);
-  }
-
-  {
-    css_node_t *root_node = new_test_css_node();
-    {
-      css_node_t *node_0 = root_node;
-      node_0->style.flex_direction = CSS_FLEX_DIRECTION_ROW;
-      node_0->style.dimensions[CSS_WIDTH] = 700;
-      init_css_node_children(node_0, 2);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->style.flex = 1;
-        node_1 = node_0->get_child(node_0->context, 1);
-        node_1->style.flex = 1;
-        node_1->style.padding[CSS_RIGHT] = 5;
-      }
-    }
-
-    css_node_t *root_layout = new_test_css_node();
-    {
-      css_node_t *node_0 = root_layout;
-      node_0->layout.position[CSS_TOP] = 0;
-      node_0->layout.position[CSS_LEFT] = 0;
-      node_0->layout.dimensions[CSS_WIDTH] = 700;
-      node_0->layout.dimensions[CSS_HEIGHT] = 0;
-      init_css_node_children(node_0, 2);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->layout.position[CSS_TOP] = 0;
-        node_1->layout.position[CSS_LEFT] = 0;
-        node_1->layout.dimensions[CSS_WIDTH] = 347.5;
-        node_1->layout.dimensions[CSS_HEIGHT] = 0;
-        node_1 = node_0->get_child(node_0->context, 1);
-        node_1->layout.position[CSS_TOP] = 0;
-        node_1->layout.position[CSS_LEFT] = 347.5;
-        node_1->layout.dimensions[CSS_WIDTH] = 352.5;
-        node_1->layout.dimensions[CSS_HEIGHT] = 0;
-      }
-    }
-
-    test("should layout node with multiple flex and padding", root_node, root_layout);
-  }
-
-  {
-    css_node_t *root_node = new_test_css_node();
-    {
-      css_node_t *node_0 = root_node;
-      node_0->style.direction = CSS_DIRECTION_RTL;
-      node_0->style.flex_direction = CSS_FLEX_DIRECTION_ROW;
-      node_0->style.dimensions[CSS_WIDTH] = 700;
-      init_css_node_children(node_0, 2);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->style.flex = 1;
-        node_1 = node_0->get_child(node_0->context, 1);
-        node_1->style.flex = 1;
-        node_1->style.padding[CSS_LEFT] = 5;
-      }
-    }
-
-    css_node_t *root_layout = new_test_css_node();
-    {
-      css_node_t *node_0 = root_layout;
-      node_0->layout.position[CSS_TOP] = 0;
-      node_0->layout.position[CSS_LEFT] = 0;
-      node_0->layout.dimensions[CSS_WIDTH] = 700;
-      node_0->layout.dimensions[CSS_HEIGHT] = 0;
-      init_css_node_children(node_0, 2);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->layout.position[CSS_TOP] = 0;
-        node_1->layout.position[CSS_LEFT] = 352.5;
-        node_1->layout.dimensions[CSS_WIDTH] = 347.5;
-        node_1->layout.dimensions[CSS_HEIGHT] = 0;
-        node_1 = node_0->get_child(node_0->context, 1);
-        node_1->layout.position[CSS_TOP] = 0;
-        node_1->layout.position[CSS_LEFT] = 0;
-        node_1->layout.dimensions[CSS_WIDTH] = 352.5;
-        node_1->layout.dimensions[CSS_HEIGHT] = 0;
-      }
-    }
-
-    test("should layout node with multiple flex and padding in rtl", root_node, root_layout);
-  }
-
-  {
-    css_node_t *root_node = new_test_css_node();
-    {
-      css_node_t *node_0 = root_node;
-      node_0->style.flex_direction = CSS_FLEX_DIRECTION_ROW;
-      node_0->style.dimensions[CSS_WIDTH] = 700;
-      init_css_node_children(node_0, 2);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->style.flex = 1;
-        node_1 = node_0->get_child(node_0->context, 1);
-        node_1->style.flex = 1;
-        node_1->style.margin[CSS_LEFT] = 5;
-      }
-    }
-
-    css_node_t *root_layout = new_test_css_node();
-    {
-      css_node_t *node_0 = root_layout;
-      node_0->layout.position[CSS_TOP] = 0;
-      node_0->layout.position[CSS_LEFT] = 0;
-      node_0->layout.dimensions[CSS_WIDTH] = 700;
-      node_0->layout.dimensions[CSS_HEIGHT] = 0;
-      init_css_node_children(node_0, 2);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->layout.position[CSS_TOP] = 0;
-        node_1->layout.position[CSS_LEFT] = 0;
-        node_1->layout.dimensions[CSS_WIDTH] = 347.5;
-        node_1->layout.dimensions[CSS_HEIGHT] = 0;
-        node_1 = node_0->get_child(node_0->context, 1);
-        node_1->layout.position[CSS_TOP] = 0;
-        node_1->layout.position[CSS_LEFT] = 352.5;
-        node_1->layout.dimensions[CSS_WIDTH] = 347.5;
-        node_1->layout.dimensions[CSS_HEIGHT] = 0;
-      }
-    }
-
-    test("should layout node with multiple flex and margin", root_node, root_layout);
-  }
-
-  {
-    css_node_t *root_node = new_test_css_node();
-    {
-      css_node_t *node_0 = root_node;
-      node_0->style.direction = CSS_DIRECTION_RTL;
-      node_0->style.flex_direction = CSS_FLEX_DIRECTION_ROW;
-      node_0->style.dimensions[CSS_WIDTH] = 700;
-      init_css_node_children(node_0, 2);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->style.flex = 1;
-        node_1 = node_0->get_child(node_0->context, 1);
-        node_1->style.flex = 1;
-        node_1->style.margin[CSS_RIGHT] = 5;
-      }
-    }
-
-    css_node_t *root_layout = new_test_css_node();
-    {
-      css_node_t *node_0 = root_layout;
-      node_0->layout.position[CSS_TOP] = 0;
-      node_0->layout.position[CSS_LEFT] = 0;
-      node_0->layout.dimensions[CSS_WIDTH] = 700;
-      node_0->layout.dimensions[CSS_HEIGHT] = 0;
-      init_css_node_children(node_0, 2);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->layout.position[CSS_TOP] = 0;
-        node_1->layout.position[CSS_LEFT] = 352.5;
-        node_1->layout.dimensions[CSS_WIDTH] = 347.5;
-        node_1->layout.dimensions[CSS_HEIGHT] = 0;
-        node_1 = node_0->get_child(node_0->context, 1);
-        node_1->layout.position[CSS_TOP] = 0;
-        node_1->layout.position[CSS_LEFT] = 0;
-        node_1->layout.dimensions[CSS_WIDTH] = 347.5;
-        node_1->layout.dimensions[CSS_HEIGHT] = 0;
-      }
-    }
-
-    test("should layout node with multiple flex and margin in rtl", root_node, root_layout);
-  }
-
-  {
-    css_node_t *root_node = new_test_css_node();
-    {
-      css_node_t *node_0 = root_node;
-      node_0->style.dimensions[CSS_HEIGHT] = 300;
-      init_css_node_children(node_0, 2);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->style.dimensions[CSS_HEIGHT] = 600;
-        node_1 = node_0->get_child(node_0->context, 1);
-        node_1->style.flex = 1;
-      }
-    }
-
-    css_node_t *root_layout = new_test_css_node();
-    {
-      css_node_t *node_0 = root_layout;
-      node_0->layout.position[CSS_TOP] = 0;
-      node_0->layout.position[CSS_LEFT] = 0;
-      node_0->layout.dimensions[CSS_WIDTH] = 0;
-      node_0->layout.dimensions[CSS_HEIGHT] = 300;
-      init_css_node_children(node_0, 2);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->layout.position[CSS_TOP] = 0;
-        node_1->layout.position[CSS_LEFT] = 0;
-        node_1->layout.dimensions[CSS_WIDTH] = 0;
-        node_1->layout.dimensions[CSS_HEIGHT] = 600;
-        node_1 = node_0->get_child(node_0->context, 1);
-        node_1->layout.position[CSS_TOP] = 600;
-        node_1->layout.position[CSS_LEFT] = 0;
-        node_1->layout.dimensions[CSS_WIDTH] = 0;
-        node_1->layout.dimensions[CSS_HEIGHT] = 0;
-      }
-    }
-
-    test("should layout node with flex and overflow", root_node, root_layout);
-  }
-
-  {
-    css_node_t *root_node = new_test_css_node();
-    {
-      css_node_t *node_0 = root_node;
-      node_0->style.flex_direction = CSS_FLEX_DIRECTION_ROW;
-      node_0->style.dimensions[CSS_WIDTH] = 600;
-      init_css_node_children(node_0, 1);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->style.position_type = CSS_POSITION_ABSOLUTE;
-        node_1->style.flex = 1;
-      }
-    }
-
-    css_node_t *root_layout = new_test_css_node();
-    {
-      css_node_t *node_0 = root_layout;
-      node_0->layout.position[CSS_TOP] = 0;
-      node_0->layout.position[CSS_LEFT] = 0;
-      node_0->layout.dimensions[CSS_WIDTH] = 600;
-      node_0->layout.dimensions[CSS_HEIGHT] = 0;
-      init_css_node_children(node_0, 1);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->layout.position[CSS_TOP] = 0;
-        node_1->layout.position[CSS_LEFT] = 0;
-        node_1->layout.dimensions[CSS_WIDTH] = 0;
-        node_1->layout.dimensions[CSS_HEIGHT] = 0;
-      }
-    }
-
-    test("should layout node with flex and position absolute", root_node, root_layout);
-  }
-
-  {
-    css_node_t *root_node = new_test_css_node();
-    {
-      css_node_t *node_0 = root_node;
-      node_0->style.direction = CSS_DIRECTION_RTL;
-      node_0->style.flex_direction = CSS_FLEX_DIRECTION_ROW;
-      node_0->style.dimensions[CSS_WIDTH] = 600;
-      init_css_node_children(node_0, 1);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->style.position_type = CSS_POSITION_ABSOLUTE;
-        node_1->style.flex = 1;
-      }
-    }
-
-    css_node_t *root_layout = new_test_css_node();
-    {
-      css_node_t *node_0 = root_layout;
-      node_0->layout.position[CSS_TOP] = 0;
-      node_0->layout.position[CSS_LEFT] = 0;
-      node_0->layout.dimensions[CSS_WIDTH] = 600;
-      node_0->layout.dimensions[CSS_HEIGHT] = 0;
-      init_css_node_children(node_0, 1);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->layout.position[CSS_TOP] = 0;
-        node_1->layout.position[CSS_LEFT] = 600;
-        node_1->layout.dimensions[CSS_WIDTH] = 0;
-        node_1->layout.dimensions[CSS_HEIGHT] = 0;
-      }
-    }
-
-    test("should layout node with flex and position absolute in rtl", root_node, root_layout);
-  }
-
-  {
-    css_node_t *root_node = new_test_css_node();
-    {
-      css_node_t *node_0 = root_node;
-      node_0->style.dimensions[CSS_HEIGHT] = 500;
-      init_css_node_children(node_0, 2);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->style.flex = 1;
-        node_1 = node_0->get_child(node_0->context, 1);
-        node_1->style.position_type = CSS_POSITION_ABSOLUTE;
-        node_1->style.flex = 1;
-      }
-    }
-
-    css_node_t *root_layout = new_test_css_node();
-    {
-      css_node_t *node_0 = root_layout;
-      node_0->layout.position[CSS_TOP] = 0;
-      node_0->layout.position[CSS_LEFT] = 0;
-      node_0->layout.dimensions[CSS_WIDTH] = 0;
-      node_0->layout.dimensions[CSS_HEIGHT] = 500;
-      init_css_node_children(node_0, 2);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->layout.position[CSS_TOP] = 0;
-        node_1->layout.position[CSS_LEFT] = 0;
-        node_1->layout.dimensions[CSS_WIDTH] = 0;
-        node_1->layout.dimensions[CSS_HEIGHT] = 500;
-        node_1 = node_0->get_child(node_0->context, 1);
-        node_1->layout.position[CSS_TOP] = 500;
-        node_1->layout.position[CSS_LEFT] = 0;
-        node_1->layout.dimensions[CSS_WIDTH] = 0;
-        node_1->layout.dimensions[CSS_HEIGHT] = 0;
-      }
-    }
-
-    test("should layout node with double flex and position absolute", root_node, root_layout);
-  }
-
-  {
-    css_node_t *root_node = new_test_css_node();
-    {
-      css_node_t *node_0 = root_node;
-      node_0->style.border[CSS_LEFT] = 5;
-      node_0->style.border[CSS_TOP] = 5;
-      node_0->style.border[CSS_RIGHT] = 5;
-      node_0->style.border[CSS_BOTTOM] = 5;
-      node_0->style.border[CSS_START] = 5;
-      node_0->style.border[CSS_END] = 5;
-    }
-
-    css_node_t *root_layout = new_test_css_node();
-    {
-      css_node_t *node_0 = root_layout;
-      node_0->layout.position[CSS_TOP] = 0;
-      node_0->layout.position[CSS_LEFT] = 0;
-      node_0->layout.dimensions[CSS_WIDTH] = 10;
-      node_0->layout.dimensions[CSS_HEIGHT] = 10;
-    }
-
-    test("should layout node with borderWidth", root_node, root_layout);
-  }
-
-  {
-    css_node_t *root_node = new_test_css_node();
-    {
-      css_node_t *node_0 = root_node;
-      node_0->style.border[CSS_TOP] = 1;
-      init_css_node_children(node_0, 1);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->style.position_type = CSS_POSITION_ABSOLUTE;
-        node_1->style.position[CSS_TOP] = -1;
-      }
-    }
-
-    css_node_t *root_layout = new_test_css_node();
-    {
-      css_node_t *node_0 = root_layout;
-      node_0->layout.position[CSS_TOP] = 0;
-      node_0->layout.position[CSS_LEFT] = 0;
-      node_0->layout.dimensions[CSS_WIDTH] = 0;
-      node_0->layout.dimensions[CSS_HEIGHT] = 1;
-      init_css_node_children(node_0, 1);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->layout.position[CSS_TOP] = 0;
-        node_1->layout.position[CSS_LEFT] = 0;
-        node_1->layout.dimensions[CSS_WIDTH] = 0;
-        node_1->layout.dimensions[CSS_HEIGHT] = 0;
-      }
-    }
-
-    test("should layout node with borderWidth and position: absolute, top", root_node, root_layout);
-  }
-
-  {
-    css_node_t *root_node = new_test_css_node();
-    {
-      css_node_t *node_0 = root_node;
-      node_0->style.border[CSS_LEFT] = 1;
-      node_0->style.border[CSS_TOP] = 1;
-      node_0->style.border[CSS_RIGHT] = 1;
-      node_0->style.border[CSS_BOTTOM] = 1;
-      node_0->style.border[CSS_START] = 1;
-      node_0->style.border[CSS_END] = 1;
-      init_css_node_children(node_0, 1);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->style.position_type = CSS_POSITION_ABSOLUTE;
-        node_1->style.position[CSS_LEFT] = 5;
-      }
-    }
-
-    css_node_t *root_layout = new_test_css_node();
-    {
-      css_node_t *node_0 = root_layout;
-      node_0->layout.position[CSS_TOP] = 0;
-      node_0->layout.position[CSS_LEFT] = 0;
-      node_0->layout.dimensions[CSS_WIDTH] = 2;
-      node_0->layout.dimensions[CSS_HEIGHT] = 2;
-      init_css_node_children(node_0, 1);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->layout.position[CSS_TOP] = 1;
-        node_1->layout.position[CSS_LEFT] = 6;
-        node_1->layout.dimensions[CSS_WIDTH] = 0;
-        node_1->layout.dimensions[CSS_HEIGHT] = 0;
-      }
-    }
-
-    test("should layout node with borderWidth and position: absolute, top. cross axis", root_node, root_layout);
-  }
-
-  {
-    css_node_t *root_node = new_test_css_node();
-    {
-      css_node_t *node_0 = root_node;
-      node_0->style.dimensions[CSS_WIDTH] = 50;
-      init_css_node_children(node_0, 1);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->style.align_self = CSS_ALIGN_STRETCH;
-        node_1->style.margin[CSS_LEFT] = 20;
-        node_1->style.padding[CSS_LEFT] = 20;
-        node_1->style.padding[CSS_TOP] = 20;
-        node_1->style.padding[CSS_RIGHT] = 20;
-        node_1->style.padding[CSS_BOTTOM] = 20;
-        node_1->style.padding[CSS_START] = 20;
-        node_1->style.padding[CSS_END] = 20;
-      }
-    }
-
-    css_node_t *root_layout = new_test_css_node();
-    {
-      css_node_t *node_0 = root_layout;
-      node_0->layout.position[CSS_TOP] = 0;
-      node_0->layout.position[CSS_LEFT] = 0;
-      node_0->layout.dimensions[CSS_WIDTH] = 50;
-      node_0->layout.dimensions[CSS_HEIGHT] = 40;
-      init_css_node_children(node_0, 1);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->layout.position[CSS_TOP] = 0;
-        node_1->layout.position[CSS_LEFT] = 20;
-        node_1->layout.dimensions[CSS_WIDTH] = 40;
-        node_1->layout.dimensions[CSS_HEIGHT] = 40;
-      }
-    }
-
-    test("should correctly take into account min padding for stretch", root_node, root_layout);
-  }
-
-  {
-    css_node_t *root_node = new_test_css_node();
-    {
-      css_node_t *node_0 = root_node;
-      node_0->style.dimensions[CSS_WIDTH] = -31;
-      init_css_node_children(node_0, 1);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->style.border[CSS_RIGHT] = 5;
-      }
-    }
-
-    css_node_t *root_layout = new_test_css_node();
-    {
-      css_node_t *node_0 = root_layout;
-      node_0->layout.position[CSS_TOP] = 0;
-      node_0->layout.position[CSS_LEFT] = 0;
-      node_0->layout.dimensions[CSS_WIDTH] = 5;
-      node_0->layout.dimensions[CSS_HEIGHT] = 0;
-      init_css_node_children(node_0, 1);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->layout.position[CSS_TOP] = 0;
-        node_1->layout.position[CSS_LEFT] = 0;
-        node_1->layout.dimensions[CSS_WIDTH] = 5;
-        node_1->layout.dimensions[CSS_HEIGHT] = 0;
-      }
-    }
-
-    test("should layout node with negative width", root_node, root_layout);
-  }
-
-  {
-    css_node_t *root_node = new_test_css_node();
-    {
-      css_node_t *node_0 = root_node;
-      node_0->style.flex_direction = CSS_FLEX_DIRECTION_ROW;
-      node_0->style.border[CSS_RIGHT] = 1;
-      init_css_node_children(node_0, 1);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->style.margin[CSS_RIGHT] = -8;
-      }
-    }
-
-    css_node_t *root_layout = new_test_css_node();
-    {
-      css_node_t *node_0 = root_layout;
-      node_0->layout.position[CSS_TOP] = 0;
-      node_0->layout.position[CSS_LEFT] = 0;
-      node_0->layout.dimensions[CSS_WIDTH] = 1;
-      node_0->layout.dimensions[CSS_HEIGHT] = 0;
-      init_css_node_children(node_0, 1);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->layout.position[CSS_TOP] = 0;
-        node_1->layout.position[CSS_LEFT] = 0;
-        node_1->layout.dimensions[CSS_WIDTH] = 0;
-        node_1->layout.dimensions[CSS_HEIGHT] = 0;
-      }
-    }
-
-    test("should handle negative margin and min padding correctly", root_node, root_layout);
-  }
-
-  {
-    css_node_t *root_node = new_test_css_node();
-    {
-      css_node_t *node_0 = root_node;
-      node_0->style.direction = CSS_DIRECTION_RTL;
-      node_0->style.flex_direction = CSS_FLEX_DIRECTION_ROW;
-      node_0->style.border[CSS_LEFT] = 1;
-      init_css_node_children(node_0, 1);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->style.margin[CSS_LEFT] = -8;
-      }
-    }
-
-    css_node_t *root_layout = new_test_css_node();
-    {
-      css_node_t *node_0 = root_layout;
-      node_0->layout.position[CSS_TOP] = 0;
-      node_0->layout.position[CSS_LEFT] = 0;
-      node_0->layout.dimensions[CSS_WIDTH] = 1;
-      node_0->layout.dimensions[CSS_HEIGHT] = 0;
-      init_css_node_children(node_0, 1);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->layout.position[CSS_TOP] = 0;
-        node_1->layout.position[CSS_LEFT] = 1;
-        node_1->layout.dimensions[CSS_WIDTH] = 0;
-        node_1->layout.dimensions[CSS_HEIGHT] = 0;
-      }
-    }
-
-    test("should handle negative margin and min padding correctly in rtl", root_node, root_layout);
-  }
-
-  {
-    css_node_t *root_node = new_test_css_node();
-    {
-      css_node_t *node_0 = root_node;
-      node_0->measure = measure;
-      node_0->context = "small";
-    }
-
-    css_node_t *root_layout = new_test_css_node();
-    {
-      css_node_t *node_0 = root_layout;
-      node_0->layout.position[CSS_TOP] = 0;
-      node_0->layout.position[CSS_LEFT] = 0;
-      node_0->layout.dimensions[CSS_WIDTH] = 35;
-      node_0->layout.dimensions[CSS_HEIGHT] = 18;
-    }
-
-    test("should layout node with just text", root_node, root_layout);
-  }
-
-  {
-    css_node_t *root_node = new_test_css_node();
-    {
-      css_node_t *node_0 = root_node;
-      node_0->style.dimensions[CSS_WIDTH] = 100;
-      node_0->measure = measure;
-      node_0->context = "measureWithRatio2";
-    }
-
-    css_node_t *root_layout = new_test_css_node();
-    {
-      css_node_t *node_0 = root_layout;
-      node_0->layout.position[CSS_TOP] = 0;
-      node_0->layout.position[CSS_LEFT] = 0;
-      node_0->layout.dimensions[CSS_WIDTH] = 100;
-      node_0->layout.dimensions[CSS_HEIGHT] = 200;
-    }
-
-    test("should layout node with fixed width and custom measure function", root_node, root_layout);
-  }
-
-  {
-    css_node_t *root_node = new_test_css_node();
-    {
-      css_node_t *node_0 = root_node;
-      node_0->style.dimensions[CSS_HEIGHT] = 100;
-      node_0->measure = measure;
-      node_0->context = "measureWithRatio2";
-    }
-
-    css_node_t *root_layout = new_test_css_node();
-    {
-      css_node_t *node_0 = root_layout;
-      node_0->layout.position[CSS_TOP] = 0;
-      node_0->layout.position[CSS_LEFT] = 0;
-      node_0->layout.dimensions[CSS_WIDTH] = 200;
-      node_0->layout.dimensions[CSS_HEIGHT] = 100;
-    }
-
-    test("should layout node with fixed height and custom measure function", root_node, root_layout);
-  }
-
-  {
-    css_node_t *root_node = new_test_css_node();
-    {
-      css_node_t *node_0 = root_node;
-      node_0->style.dimensions[CSS_WIDTH] = 100;
-      node_0->style.dimensions[CSS_HEIGHT] = 100;
-      node_0->measure = measure;
-      node_0->context = "measureWithRatio2";
-    }
-
-    css_node_t *root_layout = new_test_css_node();
-    {
-      css_node_t *node_0 = root_layout;
-      node_0->layout.position[CSS_TOP] = 0;
-      node_0->layout.position[CSS_LEFT] = 0;
-      node_0->layout.dimensions[CSS_WIDTH] = 100;
-      node_0->layout.dimensions[CSS_HEIGHT] = 100;
-    }
-
-    test("should layout node with fixed height and fixed width, ignoring custom measure function", root_node, root_layout);
-  }
-
-  {
-    css_node_t *root_node = new_test_css_node();
-    {
-      css_node_t *node_0 = root_node;
-      node_0->measure = measure;
-      node_0->context = "measureWithRatio2";
-    }
-
-    css_node_t *root_layout = new_test_css_node();
-    {
-      css_node_t *node_0 = root_layout;
-      node_0->layout.position[CSS_TOP] = 0;
-      node_0->layout.position[CSS_LEFT] = 0;
-      node_0->layout.dimensions[CSS_WIDTH] = 99999;
-      node_0->layout.dimensions[CSS_HEIGHT] = 99999;
-    }
-
-    test("should layout node with no fixed dimension and custom measure function", root_node, root_layout);
-  }
-
-  {
-    css_node_t *root_node = new_test_css_node();
-    {
-      css_node_t *node_0 = root_node;
-      node_0->style.flex_direction = CSS_FLEX_DIRECTION_COLUMN;
-      node_0->style.dimensions[CSS_WIDTH] = 320;
-      init_css_node_children(node_0, 2);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->measure = measure;
-        node_1->context = "measureWithRatio2";
-        node_1 = node_0->get_child(node_0->context, 1);
-        node_1->style.flex_direction = CSS_FLEX_DIRECTION_ROW;
-        node_1->style.dimensions[CSS_HEIGHT] = 100;
-        init_css_node_children(node_1, 2);
-        {
-          css_node_t *node_2;
-          node_2 = node_1->get_child(node_1->context, 0);
-          node_2->measure = measure;
-          node_2->context = "measureWithRatio2";
-          node_2 = node_1->get_child(node_1->context, 1);
-          node_2->measure = measure;
-          node_2->context = "measureWithRatio2";
-        }
-      }
-    }
-
-    css_node_t *root_layout = new_test_css_node();
-    {
-      css_node_t *node_0 = root_layout;
-      node_0->layout.position[CSS_TOP] = 0;
-      node_0->layout.position[CSS_LEFT] = 0;
-      node_0->layout.dimensions[CSS_WIDTH] = 320;
-      node_0->layout.dimensions[CSS_HEIGHT] = 740;
-      init_css_node_children(node_0, 2);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->layout.position[CSS_TOP] = 0;
-        node_1->layout.position[CSS_LEFT] = 0;
-        node_1->layout.dimensions[CSS_WIDTH] = 320;
-        node_1->layout.dimensions[CSS_HEIGHT] = 640;
-        node_1 = node_0->get_child(node_0->context, 1);
-        node_1->layout.position[CSS_TOP] = 640;
-        node_1->layout.position[CSS_LEFT] = 0;
-        node_1->layout.dimensions[CSS_WIDTH] = 320;
-        node_1->layout.dimensions[CSS_HEIGHT] = 100;
-        init_css_node_children(node_1, 2);
-        {
-          css_node_t *node_2;
-          node_2 = node_1->get_child(node_1->context, 0);
-          node_2->layout.position[CSS_TOP] = 0;
-          node_2->layout.position[CSS_LEFT] = 0;
-          node_2->layout.dimensions[CSS_WIDTH] = 200;
-          node_2->layout.dimensions[CSS_HEIGHT] = 100;
-          node_2 = node_1->get_child(node_1->context, 1);
-          node_2->layout.position[CSS_TOP] = 0;
-          node_2->layout.position[CSS_LEFT] = 200;
-          node_2->layout.dimensions[CSS_WIDTH] = 200;
-          node_2->layout.dimensions[CSS_HEIGHT] = 100;
-        }
-      }
-    }
-
-    test("should layout node with nested stacks and custom measure function", root_node, root_layout);
-  }
-
-  {
-    css_node_t *root_node = new_test_css_node();
-    {
-      css_node_t *node_0 = root_node;
-      node_0->style.dimensions[CSS_WIDTH] = 10;
-      node_0->measure = measure;
-      node_0->context = "small";
-    }
-
-    css_node_t *root_layout = new_test_css_node();
-    {
-      css_node_t *node_0 = root_layout;
-      node_0->layout.position[CSS_TOP] = 0;
-      node_0->layout.position[CSS_LEFT] = 0;
-      node_0->layout.dimensions[CSS_WIDTH] = 10;
-      node_0->layout.dimensions[CSS_HEIGHT] = 18;
-    }
-
-    test("should layout node with text and width", root_node, root_layout);
-  }
-
-  {
-    css_node_t *root_node = new_test_css_node();
-    {
-      css_node_t *node_0 = root_node;
-      node_0->measure = measure;
-      node_0->context = "loooooooooong with space";
-    }
-
-    css_node_t *root_layout = new_test_css_node();
-    {
-      css_node_t *node_0 = root_layout;
-      node_0->layout.position[CSS_TOP] = 0;
-      node_0->layout.position[CSS_LEFT] = 0;
-      node_0->layout.dimensions[CSS_WIDTH] = 172;
-      node_0->layout.dimensions[CSS_HEIGHT] = 18;
-    }
-
-    test("should layout node with text, padding and margin", root_node, root_layout);
-  }
-
-  {
-    css_node_t *root_node = new_test_css_node();
-    {
-      css_node_t *node_0 = root_node;
-      node_0->style.dimensions[CSS_WIDTH] = 300;
-      init_css_node_children(node_0, 1);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->style.align_self = CSS_ALIGN_STRETCH;
-        init_css_node_children(node_1, 1);
-        {
-          css_node_t *node_2;
-          node_2 = node_1->get_child(node_1->context, 0);
-          node_2->style.align_self = CSS_ALIGN_STRETCH;
-        }
-      }
-    }
-
-    css_node_t *root_layout = new_test_css_node();
-    {
-      css_node_t *node_0 = root_layout;
-      node_0->layout.position[CSS_TOP] = 0;
-      node_0->layout.position[CSS_LEFT] = 0;
-      node_0->layout.dimensions[CSS_WIDTH] = 300;
-      node_0->layout.dimensions[CSS_HEIGHT] = 0;
-      init_css_node_children(node_0, 1);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->layout.position[CSS_TOP] = 0;
-        node_1->layout.position[CSS_LEFT] = 0;
-        node_1->layout.dimensions[CSS_WIDTH] = 300;
-        node_1->layout.dimensions[CSS_HEIGHT] = 0;
-        init_css_node_children(node_1, 1);
-        {
-          css_node_t *node_2;
-          node_2 = node_1->get_child(node_1->context, 0);
-          node_2->layout.position[CSS_TOP] = 0;
-          node_2->layout.position[CSS_LEFT] = 0;
-          node_2->layout.dimensions[CSS_WIDTH] = 300;
-          node_2->layout.dimensions[CSS_HEIGHT] = 0;
-        }
-      }
-    }
-
-    test("should layout node with nested alignSelf: stretch", root_node, root_layout);
-  }
-
-  {
-    css_node_t *root_node = new_test_css_node();
-    {
-      css_node_t *node_0 = root_node;
-      init_css_node_children(node_0, 1);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->style.flex_direction = CSS_FLEX_DIRECTION_ROW;
-        node_1->style.dimensions[CSS_WIDTH] = 500;
-        init_css_node_children(node_1, 1);
-        {
-          css_node_t *node_2;
-          node_2 = node_1->get_child(node_1->context, 0);
-          node_2->style.flex = 1;
-          node_2->measure = measure;
-          node_2->context = "loooooooooong with space";
-        }
-      }
-    }
-
-    css_node_t *root_layout = new_test_css_node();
-    {
-      css_node_t *node_0 = root_layout;
-      node_0->layout.position[CSS_TOP] = 0;
-      node_0->layout.position[CSS_LEFT] = 0;
-      node_0->layout.dimensions[CSS_WIDTH] = 500;
-      node_0->layout.dimensions[CSS_HEIGHT] = 18;
-      init_css_node_children(node_0, 1);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->layout.position[CSS_TOP] = 0;
-        node_1->layout.position[CSS_LEFT] = 0;
-        node_1->layout.dimensions[CSS_WIDTH] = 500;
-        node_1->layout.dimensions[CSS_HEIGHT] = 18;
-        init_css_node_children(node_1, 1);
-        {
-          css_node_t *node_2;
-          node_2 = node_1->get_child(node_1->context, 0);
-          node_2->layout.position[CSS_TOP] = 0;
-          node_2->layout.position[CSS_LEFT] = 0;
-          node_2->layout.dimensions[CSS_WIDTH] = 500;
-          node_2->layout.dimensions[CSS_HEIGHT] = 18;
-        }
-      }
-    }
-
-    test("should layout node with text and flex", root_node, root_layout);
-  }
-
-  {
-    css_node_t *root_node = new_test_css_node();
-    {
-      css_node_t *node_0 = root_node;
-      init_css_node_children(node_0, 1);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->style.direction = CSS_DIRECTION_RTL;
-        node_1->style.flex_direction = CSS_FLEX_DIRECTION_ROW;
-        node_1->style.dimensions[CSS_WIDTH] = 500;
-        init_css_node_children(node_1, 1);
-        {
-          css_node_t *node_2;
-          node_2 = node_1->get_child(node_1->context, 0);
-          node_2->style.flex = 1;
-          node_2->measure = measure;
-          node_2->context = "loooooooooong with space";
-        }
-      }
-    }
-
-    css_node_t *root_layout = new_test_css_node();
-    {
-      css_node_t *node_0 = root_layout;
-      node_0->layout.position[CSS_TOP] = 0;
-      node_0->layout.position[CSS_LEFT] = 0;
-      node_0->layout.dimensions[CSS_WIDTH] = 500;
-      node_0->layout.dimensions[CSS_HEIGHT] = 18;
-      init_css_node_children(node_0, 1);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->layout.position[CSS_TOP] = 0;
-        node_1->layout.position[CSS_LEFT] = 0;
-        node_1->layout.dimensions[CSS_WIDTH] = 500;
-        node_1->layout.dimensions[CSS_HEIGHT] = 18;
-        init_css_node_children(node_1, 1);
-        {
-          css_node_t *node_2;
-          node_2 = node_1->get_child(node_1->context, 0);
-          node_2->layout.position[CSS_TOP] = 0;
-          node_2->layout.position[CSS_LEFT] = 0;
-          node_2->layout.dimensions[CSS_WIDTH] = 500;
-          node_2->layout.dimensions[CSS_HEIGHT] = 18;
-        }
-      }
-    }
-
-    test("should layout node with text and flex in rtl", root_node, root_layout);
-  }
-
-  {
-    css_node_t *root_node = new_test_css_node();
-    {
-      css_node_t *node_0 = root_node;
-      node_0->style.dimensions[CSS_WIDTH] = 130;
-      init_css_node_children(node_0, 1);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->style.align_items = CSS_ALIGN_STRETCH;
-        node_1->style.align_self = CSS_ALIGN_STRETCH;
-        init_css_node_children(node_1, 1);
-        {
-          css_node_t *node_2;
-          node_2 = node_1->get_child(node_1->context, 0);
-          node_2->measure = measure;
-          node_2->context = "loooooooooong with space";
-        }
-      }
-    }
-
-    css_node_t *root_layout = new_test_css_node();
-    {
-      css_node_t *node_0 = root_layout;
-      node_0->layout.position[CSS_TOP] = 0;
-      node_0->layout.position[CSS_LEFT] = 0;
-      node_0->layout.dimensions[CSS_WIDTH] = 130;
-      node_0->layout.dimensions[CSS_HEIGHT] = 36;
-      init_css_node_children(node_0, 1);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->layout.position[CSS_TOP] = 0;
-        node_1->layout.position[CSS_LEFT] = 0;
-        node_1->layout.dimensions[CSS_WIDTH] = 130;
-        node_1->layout.dimensions[CSS_HEIGHT] = 36;
-        init_css_node_children(node_1, 1);
-        {
-          css_node_t *node_2;
-          node_2 = node_1->get_child(node_1->context, 0);
-          node_2->layout.position[CSS_TOP] = 0;
-          node_2->layout.position[CSS_LEFT] = 0;
-          node_2->layout.dimensions[CSS_WIDTH] = 130;
-          node_2->layout.dimensions[CSS_HEIGHT] = 36;
-        }
-      }
-    }
-
-    test("should layout node with text and stretch", root_node, root_layout);
-  }
-
-  {
-    css_node_t *root_node = new_test_css_node();
-    {
-      css_node_t *node_0 = root_node;
-      node_0->style.dimensions[CSS_WIDTH] = 200;
-      init_css_node_children(node_0, 1);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->style.align_items = CSS_ALIGN_STRETCH;
-        node_1->style.align_self = CSS_ALIGN_STRETCH;
-        init_css_node_children(node_1, 1);
-        {
-          css_node_t *node_2;
-          node_2 = node_1->get_child(node_1->context, 0);
-          node_2->style.dimensions[CSS_WIDTH] = 130;
-          node_2->measure = measure;
-          node_2->context = "loooooooooong with space";
-        }
-      }
-    }
-
-    css_node_t *root_layout = new_test_css_node();
-    {
-      css_node_t *node_0 = root_layout;
-      node_0->layout.position[CSS_TOP] = 0;
-      node_0->layout.position[CSS_LEFT] = 0;
-      node_0->layout.dimensions[CSS_WIDTH] = 200;
-      node_0->layout.dimensions[CSS_HEIGHT] = 36;
-      init_css_node_children(node_0, 1);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->layout.position[CSS_TOP] = 0;
-        node_1->layout.position[CSS_LEFT] = 0;
-        node_1->layout.dimensions[CSS_WIDTH] = 200;
-        node_1->layout.dimensions[CSS_HEIGHT] = 36;
-        init_css_node_children(node_1, 1);
-        {
-          css_node_t *node_2;
-          node_2 = node_1->get_child(node_1->context, 0);
-          node_2->layout.position[CSS_TOP] = 0;
-          node_2->layout.position[CSS_LEFT] = 0;
-          node_2->layout.dimensions[CSS_WIDTH] = 130;
-          node_2->layout.dimensions[CSS_HEIGHT] = 36;
-        }
-      }
-    }
-
-    test("should layout node with text stretch and width", root_node, root_layout);
-  }
-
-  {
-    css_node_t *root_node = new_test_css_node();
-    {
-      css_node_t *node_0 = root_node;
-      node_0->style.align_self = CSS_ALIGN_FLEX_START;
-      node_0->style.dimensions[CSS_WIDTH] = 100;
-      init_css_node_children(node_0, 1);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->style.align_self = CSS_ALIGN_FLEX_START;
-        node_1->measure = measure;
-        node_1->context = "loooooooooong with space";
-      }
-    }
-
-    css_node_t *root_layout = new_test_css_node();
-    {
-      css_node_t *node_0 = root_layout;
-      node_0->layout.position[CSS_TOP] = 0;
-      node_0->layout.position[CSS_LEFT] = 0;
-      node_0->layout.dimensions[CSS_WIDTH] = 100;
-      node_0->layout.dimensions[CSS_HEIGHT] = 36;
-      init_css_node_children(node_0, 1);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->layout.position[CSS_TOP] = 0;
-        node_1->layout.position[CSS_LEFT] = 0;
-        node_1->layout.dimensions[CSS_WIDTH] = 100;
-        node_1->layout.dimensions[CSS_HEIGHT] = 36;
-      }
-    }
-
-    test("should layout node with text bounded by parent", root_node, root_layout);
-  }
-
-  {
-    css_node_t *root_node = new_test_css_node();
-    {
-      css_node_t *node_0 = root_node;
-      node_0->style.align_self = CSS_ALIGN_FLEX_START;
-      node_0->style.dimensions[CSS_WIDTH] = 100;
-      node_0->style.padding[CSS_LEFT] = 10;
-      node_0->style.padding[CSS_TOP] = 10;
-      node_0->style.padding[CSS_RIGHT] = 10;
-      node_0->style.padding[CSS_BOTTOM] = 10;
-      node_0->style.padding[CSS_START] = 10;
-      node_0->style.padding[CSS_END] = 10;
-      init_css_node_children(node_0, 1);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->style.align_self = CSS_ALIGN_FLEX_START;
-        node_1->style.margin[CSS_LEFT] = 10;
-        node_1->style.margin[CSS_TOP] = 10;
-        node_1->style.margin[CSS_RIGHT] = 10;
-        node_1->style.margin[CSS_BOTTOM] = 10;
-        node_1->style.margin[CSS_START] = 10;
-        node_1->style.margin[CSS_END] = 10;
-        init_css_node_children(node_1, 1);
-        {
-          css_node_t *node_2;
-          node_2 = node_1->get_child(node_1->context, 0);
-          node_2->measure = measure;
-          node_2->context = "loooooooooong with space";
-        }
-      }
-    }
-
-    css_node_t *root_layout = new_test_css_node();
-    {
-      css_node_t *node_0 = root_layout;
-      node_0->layout.position[CSS_TOP] = 0;
-      node_0->layout.position[CSS_LEFT] = 0;
-      node_0->layout.dimensions[CSS_WIDTH] = 100;
-      node_0->layout.dimensions[CSS_HEIGHT] = 76;
-      init_css_node_children(node_0, 1);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->layout.position[CSS_TOP] = 20;
-        node_1->layout.position[CSS_LEFT] = 20;
-        node_1->layout.dimensions[CSS_WIDTH] = 100;
-        node_1->layout.dimensions[CSS_HEIGHT] = 36;
-        init_css_node_children(node_1, 1);
-        {
-          css_node_t *node_2;
-          node_2 = node_1->get_child(node_1->context, 0);
-          node_2->layout.position[CSS_TOP] = 0;
-          node_2->layout.position[CSS_LEFT] = 0;
-          node_2->layout.dimensions[CSS_WIDTH] = 100;
-          node_2->layout.dimensions[CSS_HEIGHT] = 36;
-        }
-      }
-    }
-
-    test("should layout node with text bounded by grand-parent", root_node, root_layout);
-  }
-
-  {
-    css_node_t *root_node = new_test_css_node();
-    {
-      css_node_t *node_0 = root_node;
-      node_0->style.justify_content = CSS_JUSTIFY_SPACE_BETWEEN;
-      node_0->style.dimensions[CSS_HEIGHT] = 100;
-      init_css_node_children(node_0, 2);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->style.dimensions[CSS_HEIGHT] = 900;
-        node_1 = node_0->get_child(node_0->context, 1);
-      }
-    }
-
-    css_node_t *root_layout = new_test_css_node();
-    {
-      css_node_t *node_0 = root_layout;
-      node_0->layout.position[CSS_TOP] = 0;
-      node_0->layout.position[CSS_LEFT] = 0;
-      node_0->layout.dimensions[CSS_WIDTH] = 0;
-      node_0->layout.dimensions[CSS_HEIGHT] = 100;
-      init_css_node_children(node_0, 2);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->layout.position[CSS_TOP] = 0;
-        node_1->layout.position[CSS_LEFT] = 0;
-        node_1->layout.dimensions[CSS_WIDTH] = 0;
-        node_1->layout.dimensions[CSS_HEIGHT] = 900;
-        node_1 = node_0->get_child(node_0->context, 1);
-        node_1->layout.position[CSS_TOP] = 900;
-        node_1->layout.position[CSS_LEFT] = 0;
-        node_1->layout.dimensions[CSS_WIDTH] = 0;
-        node_1->layout.dimensions[CSS_HEIGHT] = 0;
-      }
-    }
-
-    test("should layout space-between when remaining space is negative", root_node, root_layout);
-  }
-
-  {
-    css_node_t *root_node = new_test_css_node();
-    {
-      css_node_t *node_0 = root_node;
-      node_0->style.flex_direction = CSS_FLEX_DIRECTION_COLUMN_REVERSE;
-      node_0->style.justify_content = CSS_JUSTIFY_SPACE_BETWEEN;
-      node_0->style.dimensions[CSS_HEIGHT] = 100;
-      init_css_node_children(node_0, 2);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->style.dimensions[CSS_HEIGHT] = 900;
-        node_1 = node_0->get_child(node_0->context, 1);
-      }
-    }
-
-    css_node_t *root_layout = new_test_css_node();
-    {
-      css_node_t *node_0 = root_layout;
-      node_0->layout.position[CSS_TOP] = 0;
-      node_0->layout.position[CSS_LEFT] = 0;
-      node_0->layout.dimensions[CSS_WIDTH] = 0;
-      node_0->layout.dimensions[CSS_HEIGHT] = 100;
-      init_css_node_children(node_0, 2);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->layout.position[CSS_TOP] = -800;
-        node_1->layout.position[CSS_LEFT] = 0;
-        node_1->layout.dimensions[CSS_WIDTH] = 0;
-        node_1->layout.dimensions[CSS_HEIGHT] = 900;
-        node_1 = node_0->get_child(node_0->context, 1);
-        node_1->layout.position[CSS_TOP] = -800;
-        node_1->layout.position[CSS_LEFT] = 0;
-        node_1->layout.dimensions[CSS_WIDTH] = 0;
-        node_1->layout.dimensions[CSS_HEIGHT] = 0;
-      }
-    }
-
-    test("should layout space-between when remaining space is negative in reverse", root_node, root_layout);
-  }
-
-  {
-    css_node_t *root_node = new_test_css_node();
-    {
-      css_node_t *node_0 = root_node;
-      node_0->style.flex_direction = CSS_FLEX_DIRECTION_ROW;
-      node_0->style.justify_content = CSS_JUSTIFY_FLEX_END;
-      node_0->style.dimensions[CSS_WIDTH] = 200;
-      init_css_node_children(node_0, 1);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->style.dimensions[CSS_WIDTH] = 900;
-      }
-    }
-
-    css_node_t *root_layout = new_test_css_node();
-    {
-      css_node_t *node_0 = root_layout;
-      node_0->layout.position[CSS_TOP] = 0;
-      node_0->layout.position[CSS_LEFT] = 0;
-      node_0->layout.dimensions[CSS_WIDTH] = 200;
-      node_0->layout.dimensions[CSS_HEIGHT] = 0;
-      init_css_node_children(node_0, 1);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->layout.position[CSS_TOP] = 0;
-        node_1->layout.position[CSS_LEFT] = -700;
-        node_1->layout.dimensions[CSS_WIDTH] = 900;
-        node_1->layout.dimensions[CSS_HEIGHT] = 0;
-      }
-    }
-
-    test("should layout flex-end when remaining space is negative", root_node, root_layout);
-  }
-
-  {
-    css_node_t *root_node = new_test_css_node();
-    {
-      css_node_t *node_0 = root_node;
-      node_0->style.direction = CSS_DIRECTION_RTL;
-      node_0->style.flex_direction = CSS_FLEX_DIRECTION_ROW;
-      node_0->style.justify_content = CSS_JUSTIFY_FLEX_END;
-      node_0->style.dimensions[CSS_WIDTH] = 200;
-      init_css_node_children(node_0, 1);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->style.dimensions[CSS_WIDTH] = 900;
-      }
-    }
-
-    css_node_t *root_layout = new_test_css_node();
-    {
-      css_node_t *node_0 = root_layout;
-      node_0->layout.position[CSS_TOP] = 0;
-      node_0->layout.position[CSS_LEFT] = 0;
-      node_0->layout.dimensions[CSS_WIDTH] = 200;
-      node_0->layout.dimensions[CSS_HEIGHT] = 0;
-      init_css_node_children(node_0, 1);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->layout.position[CSS_TOP] = 0;
-        node_1->layout.position[CSS_LEFT] = 0;
-        node_1->layout.dimensions[CSS_WIDTH] = 900;
-        node_1->layout.dimensions[CSS_HEIGHT] = 0;
-      }
-    }
-
-    test("should layout flex-end when remaining space is negative in rtl", root_node, root_layout);
-  }
-
-  {
-    css_node_t *root_node = new_test_css_node();
-    {
-      css_node_t *node_0 = root_node;
-      init_css_node_children(node_0, 1);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->style.flex_direction = CSS_FLEX_DIRECTION_ROW;
-        node_1->style.dimensions[CSS_WIDTH] = 200;
-        init_css_node_children(node_1, 1);
-        {
-          css_node_t *node_2;
-          node_2 = node_1->get_child(node_1->context, 0);
-          node_2->style.margin[CSS_LEFT] = 20;
-          node_2->style.margin[CSS_TOP] = 20;
-          node_2->style.margin[CSS_RIGHT] = 20;
-          node_2->style.margin[CSS_BOTTOM] = 20;
-          node_2->style.margin[CSS_START] = 20;
-          node_2->style.margin[CSS_END] = 20;
-          node_2->measure = measure;
-          node_2->context = "loooooooooong with space";
-        }
-      }
-    }
-
-    css_node_t *root_layout = new_test_css_node();
-    {
-      css_node_t *node_0 = root_layout;
-      node_0->layout.position[CSS_TOP] = 0;
-      node_0->layout.position[CSS_LEFT] = 0;
-      node_0->layout.dimensions[CSS_WIDTH] = 200;
-      node_0->layout.dimensions[CSS_HEIGHT] = 58;
-      init_css_node_children(node_0, 1);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->layout.position[CSS_TOP] = 0;
-        node_1->layout.position[CSS_LEFT] = 0;
-        node_1->layout.dimensions[CSS_WIDTH] = 200;
-        node_1->layout.dimensions[CSS_HEIGHT] = 58;
-        init_css_node_children(node_1, 1);
-        {
-          css_node_t *node_2;
-          node_2 = node_1->get_child(node_1->context, 0);
-          node_2->layout.position[CSS_TOP] = 20;
-          node_2->layout.position[CSS_LEFT] = 20;
-          node_2->layout.dimensions[CSS_WIDTH] = 172;
-          node_2->layout.dimensions[CSS_HEIGHT] = 18;
-        }
-      }
-    }
-
-    test("should layout text with flexDirection row", root_node, root_layout);
-  }
-
-  {
-    css_node_t *root_node = new_test_css_node();
-    {
-      css_node_t *node_0 = root_node;
-      node_0->style.direction = CSS_DIRECTION_RTL;
-      init_css_node_children(node_0, 1);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->style.flex_direction = CSS_FLEX_DIRECTION_ROW;
-        node_1->style.dimensions[CSS_WIDTH] = 200;
-        init_css_node_children(node_1, 1);
-        {
-          css_node_t *node_2;
-          node_2 = node_1->get_child(node_1->context, 0);
-          node_2->style.margin[CSS_LEFT] = 20;
-          node_2->style.margin[CSS_TOP] = 20;
-          node_2->style.margin[CSS_RIGHT] = 20;
-          node_2->style.margin[CSS_BOTTOM] = 20;
-          node_2->style.margin[CSS_START] = 20;
-          node_2->style.margin[CSS_END] = 20;
-          node_2->measure = measure;
-          node_2->context = "loooooooooong with space";
-        }
-      }
-    }
-
-    css_node_t *root_layout = new_test_css_node();
-    {
-      css_node_t *node_0 = root_layout;
-      node_0->layout.position[CSS_TOP] = 0;
-      node_0->layout.position[CSS_LEFT] = 0;
-      node_0->layout.dimensions[CSS_WIDTH] = 200;
-      node_0->layout.dimensions[CSS_HEIGHT] = 58;
-      init_css_node_children(node_0, 1);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->layout.position[CSS_TOP] = 0;
-        node_1->layout.position[CSS_LEFT] = 0;
-        node_1->layout.dimensions[CSS_WIDTH] = 200;
-        node_1->layout.dimensions[CSS_HEIGHT] = 58;
-        init_css_node_children(node_1, 1);
-        {
-          css_node_t *node_2;
-          node_2 = node_1->get_child(node_1->context, 0);
-          node_2->layout.position[CSS_TOP] = 20;
-          node_2->layout.position[CSS_LEFT] = 8;
-          node_2->layout.dimensions[CSS_WIDTH] = 172;
-          node_2->layout.dimensions[CSS_HEIGHT] = 18;
-        }
-      }
-    }
-
-    test("should layout text with flexDirection row in rtl", root_node, root_layout);
-  }
-
-  {
-    css_node_t *root_node = new_test_css_node();
-    {
-      css_node_t *node_0 = root_node;
-      init_css_node_children(node_0, 1);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->style.dimensions[CSS_WIDTH] = 200;
-        init_css_node_children(node_1, 1);
-        {
-          css_node_t *node_2;
-          node_2 = node_1->get_child(node_1->context, 0);
-          node_2->style.margin[CSS_LEFT] = 20;
-          node_2->style.margin[CSS_TOP] = 20;
-          node_2->style.margin[CSS_RIGHT] = 20;
-          node_2->style.margin[CSS_BOTTOM] = 20;
-          node_2->style.margin[CSS_START] = 20;
-          node_2->style.margin[CSS_END] = 20;
-          node_2->measure = measure;
-          node_2->context = "loooooooooong with space";
-        }
-      }
-    }
-
-    css_node_t *root_layout = new_test_css_node();
-    {
-      css_node_t *node_0 = root_layout;
-      node_0->layout.position[CSS_TOP] = 0;
-      node_0->layout.position[CSS_LEFT] = 0;
-      node_0->layout.dimensions[CSS_WIDTH] = 200;
-      node_0->layout.dimensions[CSS_HEIGHT] = 76;
-      init_css_node_children(node_0, 1);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->layout.position[CSS_TOP] = 0;
-        node_1->layout.position[CSS_LEFT] = 0;
-        node_1->layout.dimensions[CSS_WIDTH] = 200;
-        node_1->layout.dimensions[CSS_HEIGHT] = 76;
-        init_css_node_children(node_1, 1);
-        {
-          css_node_t *node_2;
-          node_2 = node_1->get_child(node_1->context, 0);
-          node_2->layout.position[CSS_TOP] = 20;
-          node_2->layout.position[CSS_LEFT] = 20;
-          node_2->layout.dimensions[CSS_WIDTH] = 160;
-          node_2->layout.dimensions[CSS_HEIGHT] = 36;
-        }
-      }
-    }
-
-    test("should layout with text and margin", root_node, root_layout);
-  }
-
-  {
-    css_node_t *root_node = new_test_css_node();
-    {
-      css_node_t *node_0 = root_node;
-      node_0->style.dimensions[CSS_WIDTH] = 100;
-      node_0->style.dimensions[CSS_HEIGHT] = 100;
-      init_css_node_children(node_0, 1);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->style.position_type = CSS_POSITION_ABSOLUTE;
-        node_1->style.position[CSS_LEFT] = 0;
-        node_1->style.position[CSS_TOP] = 0;
-        node_1->style.position[CSS_RIGHT] = 0;
-        node_1->style.position[CSS_BOTTOM] = 0;
-      }
-    }
-
-    css_node_t *root_layout = new_test_css_node();
-    {
-      css_node_t *node_0 = root_layout;
-      node_0->layout.position[CSS_TOP] = 0;
-      node_0->layout.position[CSS_LEFT] = 0;
-      node_0->layout.dimensions[CSS_WIDTH] = 100;
-      node_0->layout.dimensions[CSS_HEIGHT] = 100;
-      init_css_node_children(node_0, 1);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->layout.position[CSS_TOP] = 0;
-        node_1->layout.position[CSS_LEFT] = 0;
-        node_1->layout.dimensions[CSS_WIDTH] = 100;
-        node_1->layout.dimensions[CSS_HEIGHT] = 100;
-      }
-    }
-
-    test("should layout with position absolute, top, left, bottom, right", root_node, root_layout);
-  }
-
-  {
-    css_node_t *root_node = new_test_css_node();
-    {
-      css_node_t *node_0 = root_node;
-      node_0->style.align_self = CSS_ALIGN_FLEX_START;
-      node_0->style.dimensions[CSS_WIDTH] = 100;
-      node_0->style.dimensions[CSS_HEIGHT] = 100;
-      init_css_node_children(node_0, 2);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->style.align_self = CSS_ALIGN_FLEX_START;
-        node_1->style.flex = 2.5;
-        node_1 = node_0->get_child(node_0->context, 1);
-        node_1->style.align_self = CSS_ALIGN_FLEX_START;
-        node_1->style.flex = 7.5;
-      }
-    }
-
-    css_node_t *root_layout = new_test_css_node();
-    {
-      css_node_t *node_0 = root_layout;
-      node_0->layout.position[CSS_TOP] = 0;
-      node_0->layout.position[CSS_LEFT] = 0;
-      node_0->layout.dimensions[CSS_WIDTH] = 100;
-      node_0->layout.dimensions[CSS_HEIGHT] = 100;
-      init_css_node_children(node_0, 2);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->layout.position[CSS_TOP] = 0;
-        node_1->layout.position[CSS_LEFT] = 0;
-        node_1->layout.dimensions[CSS_WIDTH] = 0;
-        node_1->layout.dimensions[CSS_HEIGHT] = 25;
-        node_1 = node_0->get_child(node_0->context, 1);
-        node_1->layout.position[CSS_TOP] = 25;
-        node_1->layout.position[CSS_LEFT] = 0;
-        node_1->layout.dimensions[CSS_WIDTH] = 0;
-        node_1->layout.dimensions[CSS_HEIGHT] = 75;
-      }
-    }
-
-    test("should layout with arbitrary flex", root_node, root_layout);
-  }
-
-  {
-    css_node_t *root_node = new_test_css_node();
-    {
-      css_node_t *node_0 = root_node;
-      node_0->style.flex_direction = CSS_FLEX_DIRECTION_COLUMN_REVERSE;
-      node_0->style.align_self = CSS_ALIGN_FLEX_START;
-      node_0->style.dimensions[CSS_WIDTH] = 100;
-      node_0->style.dimensions[CSS_HEIGHT] = 100;
-      init_css_node_children(node_0, 2);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->style.align_self = CSS_ALIGN_FLEX_START;
-        node_1->style.flex = 2.5;
-        node_1 = node_0->get_child(node_0->context, 1);
-        node_1->style.align_self = CSS_ALIGN_FLEX_START;
-        node_1->style.flex = 7.5;
-      }
-    }
-
-    css_node_t *root_layout = new_test_css_node();
-    {
-      css_node_t *node_0 = root_layout;
-      node_0->layout.position[CSS_TOP] = 0;
-      node_0->layout.position[CSS_LEFT] = 0;
-      node_0->layout.dimensions[CSS_WIDTH] = 100;
-      node_0->layout.dimensions[CSS_HEIGHT] = 100;
-      init_css_node_children(node_0, 2);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->layout.position[CSS_TOP] = 75;
-        node_1->layout.position[CSS_LEFT] = 0;
-        node_1->layout.dimensions[CSS_WIDTH] = 0;
-        node_1->layout.dimensions[CSS_HEIGHT] = 25;
-        node_1 = node_0->get_child(node_0->context, 1);
-        node_1->layout.position[CSS_TOP] = 0;
-        node_1->layout.position[CSS_LEFT] = 0;
-        node_1->layout.dimensions[CSS_WIDTH] = 0;
-        node_1->layout.dimensions[CSS_HEIGHT] = 75;
-      }
-    }
-
-    test("should layout with arbitrary flex in reverse", root_node, root_layout);
-  }
-
-  {
-    css_node_t *root_node = new_test_css_node();
-    {
-      css_node_t *node_0 = root_node;
-      node_0->style.flex_direction = CSS_FLEX_DIRECTION_COLUMN_REVERSE;
-      node_0->style.align_self = CSS_ALIGN_FLEX_START;
-      node_0->style.dimensions[CSS_WIDTH] = 100;
-      node_0->style.dimensions[CSS_HEIGHT] = 100;
-      init_css_node_children(node_0, 2);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->style.align_self = CSS_ALIGN_FLEX_START;
-        node_1->style.flex = -2.5;
-        node_1 = node_0->get_child(node_0->context, 1);
-        node_1->style.align_self = CSS_ALIGN_FLEX_START;
-        node_1->style.flex = 0;
-      }
-    }
-
-    css_node_t *root_layout = new_test_css_node();
-    {
-      css_node_t *node_0 = root_layout;
-      node_0->layout.position[CSS_TOP] = 0;
-      node_0->layout.position[CSS_LEFT] = 0;
-      node_0->layout.dimensions[CSS_WIDTH] = 100;
-      node_0->layout.dimensions[CSS_HEIGHT] = 100;
-      init_css_node_children(node_0, 2);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->layout.position[CSS_TOP] = 100;
-        node_1->layout.position[CSS_LEFT] = 0;
-        node_1->layout.dimensions[CSS_WIDTH] = 0;
-        node_1->layout.dimensions[CSS_HEIGHT] = 0;
-        node_1 = node_0->get_child(node_0->context, 1);
-        node_1->layout.position[CSS_TOP] = 100;
-        node_1->layout.position[CSS_LEFT] = 0;
-        node_1->layout.dimensions[CSS_WIDTH] = 0;
-        node_1->layout.dimensions[CSS_HEIGHT] = 0;
-      }
-    }
-
-    test("should layout with negative flex in reverse", root_node, root_layout);
-  }
-
-  {
-    css_node_t *root_node = new_test_css_node();
-    {
-      css_node_t *node_0 = root_node;
-      init_css_node_children(node_0, 2);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->style.dimensions[CSS_WIDTH] = 50;
-        node_1->style.dimensions[CSS_HEIGHT] = 100;
-        node_1 = node_0->get_child(node_0->context, 1);
-        node_1->style.position_type = CSS_POSITION_ABSOLUTE;
-        node_1->style.position[CSS_LEFT] = 0;
-        node_1->style.position[CSS_RIGHT] = 0;
-      }
-    }
-
-    css_node_t *root_layout = new_test_css_node();
-    {
-      css_node_t *node_0 = root_layout;
-      node_0->layout.position[CSS_TOP] = 0;
-      node_0->layout.position[CSS_LEFT] = 0;
-      node_0->layout.dimensions[CSS_WIDTH] = 50;
-      node_0->layout.dimensions[CSS_HEIGHT] = 100;
-      init_css_node_children(node_0, 2);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->layout.position[CSS_TOP] = 0;
-        node_1->layout.position[CSS_LEFT] = 0;
-        node_1->layout.dimensions[CSS_WIDTH] = 50;
-        node_1->layout.dimensions[CSS_HEIGHT] = 100;
-        node_1 = node_0->get_child(node_0->context, 1);
-        node_1->layout.position[CSS_TOP] = 100;
-        node_1->layout.position[CSS_LEFT] = 0;
-        node_1->layout.dimensions[CSS_WIDTH] = 50;
-        node_1->layout.dimensions[CSS_HEIGHT] = 0;
-      }
-    }
-
-    test("should layout with position: absolute and another sibling", root_node, root_layout);
-  }
-
-  {
-    css_node_t *root_node = new_test_css_node();
-    {
-      css_node_t *node_0 = root_node;
-      node_0->style.dimensions[CSS_HEIGHT] = 100;
-      init_css_node_children(node_0, 1);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->style.position_type = CSS_POSITION_ABSOLUTE;
-        node_1->style.position[CSS_TOP] = 0;
-        node_1->style.position[CSS_BOTTOM] = 20;
-      }
-    }
-
-    css_node_t *root_layout = new_test_css_node();
-    {
-      css_node_t *node_0 = root_layout;
-      node_0->layout.position[CSS_TOP] = 0;
-      node_0->layout.position[CSS_LEFT] = 0;
-      node_0->layout.dimensions[CSS_WIDTH] = 0;
-      node_0->layout.dimensions[CSS_HEIGHT] = 100;
-      init_css_node_children(node_0, 1);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->layout.position[CSS_TOP] = 0;
-        node_1->layout.position[CSS_LEFT] = 0;
-        node_1->layout.dimensions[CSS_WIDTH] = 0;
-        node_1->layout.dimensions[CSS_HEIGHT] = 80;
-      }
-    }
-
-    test("should calculate height properly with position: absolute top and bottom", root_node, root_layout);
-  }
-
-  {
-    css_node_t *root_node = new_test_css_node();
-    {
-      css_node_t *node_0 = root_node;
-      node_0->style.dimensions[CSS_WIDTH] = 200;
-      node_0->style.dimensions[CSS_HEIGHT] = 200;
-      init_css_node_children(node_0, 1);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->style.justify_content = CSS_JUSTIFY_CENTER;
-        node_1->style.position_type = CSS_POSITION_ABSOLUTE;
-        node_1->style.position[CSS_LEFT] = 0;
-        node_1->style.position[CSS_TOP] = 0;
-        node_1->style.position[CSS_RIGHT] = 0;
-        node_1->style.position[CSS_BOTTOM] = 0;
-        init_css_node_children(node_1, 1);
-        {
-          css_node_t *node_2;
-          node_2 = node_1->get_child(node_1->context, 0);
-          node_2->style.dimensions[CSS_WIDTH] = 100;
-          node_2->style.dimensions[CSS_HEIGHT] = 100;
-        }
-      }
-    }
-
-    css_node_t *root_layout = new_test_css_node();
-    {
-      css_node_t *node_0 = root_layout;
-      node_0->layout.position[CSS_TOP] = 0;
-      node_0->layout.position[CSS_LEFT] = 0;
-      node_0->layout.dimensions[CSS_WIDTH] = 200;
-      node_0->layout.dimensions[CSS_HEIGHT] = 200;
-      init_css_node_children(node_0, 1);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->layout.position[CSS_TOP] = 0;
-        node_1->layout.position[CSS_LEFT] = 0;
-        node_1->layout.dimensions[CSS_WIDTH] = 200;
-        node_1->layout.dimensions[CSS_HEIGHT] = 200;
-        init_css_node_children(node_1, 1);
-        {
-          css_node_t *node_2;
-          node_2 = node_1->get_child(node_1->context, 0);
-          node_2->layout.position[CSS_TOP] = 50;
-          node_2->layout.position[CSS_LEFT] = 0;
-          node_2->layout.dimensions[CSS_WIDTH] = 100;
-          node_2->layout.dimensions[CSS_HEIGHT] = 100;
-        }
-      }
-    }
-
-    test("should layout with complicated position: absolute and justifyContent: center combo", root_node, root_layout);
-  }
-
-  {
-    css_node_t *root_node = new_test_css_node();
-    {
-      css_node_t *node_0 = root_node;
-      node_0->style.dimensions[CSS_HEIGHT] = 100;
-      init_css_node_children(node_0, 1);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->style.position_type = CSS_POSITION_ABSOLUTE;
-        node_1->style.position[CSS_BOTTOM] = 0;
-      }
-    }
-
-    css_node_t *root_layout = new_test_css_node();
-    {
-      css_node_t *node_0 = root_layout;
-      node_0->layout.position[CSS_TOP] = 0;
-      node_0->layout.position[CSS_LEFT] = 0;
-      node_0->layout.dimensions[CSS_WIDTH] = 0;
-      node_0->layout.dimensions[CSS_HEIGHT] = 100;
-      init_css_node_children(node_0, 1);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->layout.position[CSS_TOP] = 100;
-        node_1->layout.position[CSS_LEFT] = 0;
-        node_1->layout.dimensions[CSS_WIDTH] = 0;
-        node_1->layout.dimensions[CSS_HEIGHT] = 0;
-      }
-    }
-
-    test("should calculate top properly with position: absolute bottom", root_node, root_layout);
-  }
-
-  {
-    css_node_t *root_node = new_test_css_node();
-    {
-      css_node_t *node_0 = root_node;
-      node_0->style.dimensions[CSS_WIDTH] = 100;
-      init_css_node_children(node_0, 1);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->style.position_type = CSS_POSITION_ABSOLUTE;
-        node_1->style.position[CSS_RIGHT] = 0;
-      }
-    }
-
-    css_node_t *root_layout = new_test_css_node();
-    {
-      css_node_t *node_0 = root_layout;
-      node_0->layout.position[CSS_TOP] = 0;
-      node_0->layout.position[CSS_LEFT] = 0;
-      node_0->layout.dimensions[CSS_WIDTH] = 100;
-      node_0->layout.dimensions[CSS_HEIGHT] = 0;
-      init_css_node_children(node_0, 1);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->layout.position[CSS_TOP] = 0;
-        node_1->layout.position[CSS_LEFT] = 100;
-        node_1->layout.dimensions[CSS_WIDTH] = 0;
-        node_1->layout.dimensions[CSS_HEIGHT] = 0;
-      }
-    }
-
-    test("should calculate left properly with position: absolute right", root_node, root_layout);
-  }
-
-  {
-    css_node_t *root_node = new_test_css_node();
-    {
-      css_node_t *node_0 = root_node;
-      node_0->style.dimensions[CSS_HEIGHT] = 100;
-      init_css_node_children(node_0, 1);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->style.position_type = CSS_POSITION_ABSOLUTE;
-        node_1->style.dimensions[CSS_HEIGHT] = 10;
-        node_1->style.position[CSS_BOTTOM] = 0;
-      }
-    }
-
-    css_node_t *root_layout = new_test_css_node();
-    {
-      css_node_t *node_0 = root_layout;
-      node_0->layout.position[CSS_TOP] = 0;
-      node_0->layout.position[CSS_LEFT] = 0;
-      node_0->layout.dimensions[CSS_WIDTH] = 0;
-      node_0->layout.dimensions[CSS_HEIGHT] = 100;
-      init_css_node_children(node_0, 1);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->layout.position[CSS_TOP] = 90;
-        node_1->layout.position[CSS_LEFT] = 0;
-        node_1->layout.dimensions[CSS_WIDTH] = 0;
-        node_1->layout.dimensions[CSS_HEIGHT] = 10;
-      }
-    }
-
-    test("should calculate top properly with position: absolute bottom and height", root_node, root_layout);
-  }
-
-  {
-    css_node_t *root_node = new_test_css_node();
-    {
-      css_node_t *node_0 = root_node;
-      node_0->style.dimensions[CSS_WIDTH] = 100;
-      init_css_node_children(node_0, 1);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->style.position_type = CSS_POSITION_ABSOLUTE;
-        node_1->style.dimensions[CSS_WIDTH] = 10;
-        node_1->style.position[CSS_RIGHT] = 0;
-      }
-    }
-
-    css_node_t *root_layout = new_test_css_node();
-    {
-      css_node_t *node_0 = root_layout;
-      node_0->layout.position[CSS_TOP] = 0;
-      node_0->layout.position[CSS_LEFT] = 0;
-      node_0->layout.dimensions[CSS_WIDTH] = 100;
-      node_0->layout.dimensions[CSS_HEIGHT] = 0;
-      init_css_node_children(node_0, 1);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->layout.position[CSS_TOP] = 0;
-        node_1->layout.position[CSS_LEFT] = 90;
-        node_1->layout.dimensions[CSS_WIDTH] = 10;
-        node_1->layout.dimensions[CSS_HEIGHT] = 0;
-      }
-    }
-
-    test("should calculate left properly with position: absolute right and width", root_node, root_layout);
-  }
-
-  {
-    css_node_t *root_node = new_test_css_node();
-    {
-      css_node_t *node_0 = root_node;
-      init_css_node_children(node_0, 1);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->style.position_type = CSS_POSITION_ABSOLUTE;
-        node_1->style.dimensions[CSS_HEIGHT] = 10;
-        node_1->style.position[CSS_BOTTOM] = 0;
-      }
-    }
-
-    css_node_t *root_layout = new_test_css_node();
-    {
-      css_node_t *node_0 = root_layout;
-      node_0->layout.position[CSS_TOP] = 0;
-      node_0->layout.position[CSS_LEFT] = 0;
-      node_0->layout.dimensions[CSS_WIDTH] = 0;
-      node_0->layout.dimensions[CSS_HEIGHT] = 0;
-      init_css_node_children(node_0, 1);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->layout.position[CSS_TOP] = -10;
-        node_1->layout.position[CSS_LEFT] = 0;
-        node_1->layout.dimensions[CSS_WIDTH] = 0;
-        node_1->layout.dimensions[CSS_HEIGHT] = 10;
-      }
-    }
-
-    test("should calculate top properly with position: absolute right, width, and no parent dimensions", root_node, root_layout);
-  }
-
-  {
-    css_node_t *root_node = new_test_css_node();
-    {
-      css_node_t *node_0 = root_node;
-      init_css_node_children(node_0, 1);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->style.position_type = CSS_POSITION_ABSOLUTE;
-        node_1->style.dimensions[CSS_WIDTH] = 10;
-        node_1->style.position[CSS_RIGHT] = 0;
-      }
-    }
-
-    css_node_t *root_layout = new_test_css_node();
-    {
-      css_node_t *node_0 = root_layout;
-      node_0->layout.position[CSS_TOP] = 0;
-      node_0->layout.position[CSS_LEFT] = 0;
-      node_0->layout.dimensions[CSS_WIDTH] = 0;
-      node_0->layout.dimensions[CSS_HEIGHT] = 0;
-      init_css_node_children(node_0, 1);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->layout.position[CSS_TOP] = 0;
-        node_1->layout.position[CSS_LEFT] = -10;
-        node_1->layout.dimensions[CSS_WIDTH] = 10;
-        node_1->layout.dimensions[CSS_HEIGHT] = 0;
-      }
-    }
-
-    test("should calculate left properly with position: absolute right, width, and no parent dimensions", root_node, root_layout);
-  }
-
-  {
-    css_node_t *root_node = new_test_css_node();
-    {
-      css_node_t *node_0 = root_node;
-      node_0->style.justify_content = CSS_JUSTIFY_SPACE_BETWEEN;
-      init_css_node_children(node_0, 1);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->style.border[CSS_BOTTOM] = 1;
-      }
-    }
-
-    css_node_t *root_layout = new_test_css_node();
-    {
-      css_node_t *node_0 = root_layout;
-      node_0->layout.position[CSS_TOP] = 0;
-      node_0->layout.position[CSS_LEFT] = 0;
-      node_0->layout.dimensions[CSS_WIDTH] = 0;
-      node_0->layout.dimensions[CSS_HEIGHT] = 1;
-      init_css_node_children(node_0, 1);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->layout.position[CSS_TOP] = 0;
-        node_1->layout.position[CSS_LEFT] = 0;
-        node_1->layout.dimensions[CSS_WIDTH] = 0;
-        node_1->layout.dimensions[CSS_HEIGHT] = 1;
-      }
-    }
-
-    test("should layout border bottom inside of justify content space between container", root_node, root_layout);
-  }
-
-  {
-    css_node_t *root_node = new_test_css_node();
-    {
-      css_node_t *node_0 = root_node;
-      node_0->style.justify_content = CSS_JUSTIFY_CENTER;
-      init_css_node_children(node_0, 1);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->style.margin[CSS_TOP] = -6;
-      }
-    }
-
-    css_node_t *root_layout = new_test_css_node();
-    {
-      css_node_t *node_0 = root_layout;
-      node_0->layout.position[CSS_TOP] = 0;
-      node_0->layout.position[CSS_LEFT] = 0;
-      node_0->layout.dimensions[CSS_WIDTH] = 0;
-      node_0->layout.dimensions[CSS_HEIGHT] = 0;
-      init_css_node_children(node_0, 1);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->layout.position[CSS_TOP] = -3;
-        node_1->layout.position[CSS_LEFT] = 0;
-        node_1->layout.dimensions[CSS_WIDTH] = 0;
-        node_1->layout.dimensions[CSS_HEIGHT] = 0;
-      }
-    }
-
-    test("should layout negative margin top inside of justify content center container", root_node, root_layout);
-  }
-
-  {
-    css_node_t *root_node = new_test_css_node();
-    {
-      css_node_t *node_0 = root_node;
-      node_0->style.justify_content = CSS_JUSTIFY_CENTER;
-      init_css_node_children(node_0, 1);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->style.margin[CSS_TOP] = 20;
-      }
-    }
-
-    css_node_t *root_layout = new_test_css_node();
-    {
-      css_node_t *node_0 = root_layout;
-      node_0->layout.position[CSS_TOP] = 0;
-      node_0->layout.position[CSS_LEFT] = 0;
-      node_0->layout.dimensions[CSS_WIDTH] = 0;
-      node_0->layout.dimensions[CSS_HEIGHT] = 20;
-      init_css_node_children(node_0, 1);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->layout.position[CSS_TOP] = 20;
-        node_1->layout.position[CSS_LEFT] = 0;
-        node_1->layout.dimensions[CSS_WIDTH] = 0;
-        node_1->layout.dimensions[CSS_HEIGHT] = 0;
-      }
-    }
-
-    test("should layout positive margin top inside of justify content center container", root_node, root_layout);
-  }
-
-  {
-    css_node_t *root_node = new_test_css_node();
-    {
-      css_node_t *node_0 = root_node;
-      node_0->style.justify_content = CSS_JUSTIFY_FLEX_END;
-      node_0->style.border[CSS_BOTTOM] = 5;
-      init_css_node_children(node_0, 1);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-      }
-    }
-
-    css_node_t *root_layout = new_test_css_node();
-    {
-      css_node_t *node_0 = root_layout;
-      node_0->layout.position[CSS_TOP] = 0;
-      node_0->layout.position[CSS_LEFT] = 0;
-      node_0->layout.dimensions[CSS_WIDTH] = 0;
-      node_0->layout.dimensions[CSS_HEIGHT] = 5;
-      init_css_node_children(node_0, 1);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->layout.position[CSS_TOP] = 0;
-        node_1->layout.position[CSS_LEFT] = 0;
-        node_1->layout.dimensions[CSS_WIDTH] = 0;
-        node_1->layout.dimensions[CSS_HEIGHT] = 0;
-      }
-    }
-
-    test("should layout border bottom and flex end with an empty child", root_node, root_layout);
-  }
-
-  {
-    css_node_t *root_node = new_test_css_node();
-    {
-      css_node_t *node_0 = root_node;
-      node_0->style.dimensions[CSS_WIDTH] = 800;
-      init_css_node_children(node_0, 1);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->style.position[CSS_LEFT] = 5;
-        init_css_node_children(node_1, 1);
-        {
-          css_node_t *node_2;
-          node_2 = node_1->get_child(node_1->context, 0);
-        }
-      }
-    }
-
-    css_node_t *root_layout = new_test_css_node();
-    {
-      css_node_t *node_0 = root_layout;
-      node_0->layout.position[CSS_TOP] = 0;
-      node_0->layout.position[CSS_LEFT] = 0;
-      node_0->layout.dimensions[CSS_WIDTH] = 800;
-      node_0->layout.dimensions[CSS_HEIGHT] = 0;
-      init_css_node_children(node_0, 1);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->layout.position[CSS_TOP] = 0;
-        node_1->layout.position[CSS_LEFT] = 5;
-        node_1->layout.dimensions[CSS_WIDTH] = 800;
-        node_1->layout.dimensions[CSS_HEIGHT] = 0;
-        init_css_node_children(node_1, 1);
-        {
-          css_node_t *node_2;
-          node_2 = node_1->get_child(node_1->context, 0);
-          node_2->layout.position[CSS_TOP] = 0;
-          node_2->layout.position[CSS_LEFT] = 0;
-          node_2->layout.dimensions[CSS_WIDTH] = 800;
-          node_2->layout.dimensions[CSS_HEIGHT] = 0;
-        }
-      }
-    }
-
-    test("should layout with children of a contain with left", root_node, root_layout);
-  }
-
-  {
-    css_node_t *root_node = new_test_css_node();
-    {
-      css_node_t *node_0 = root_node;
-      node_0->style.flex_direction = CSS_FLEX_DIRECTION_ROW;
-      node_0->style.flex_wrap = CSS_WRAP;
-      node_0->style.dimensions[CSS_WIDTH] = 100;
-      init_css_node_children(node_0, 3);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->style.dimensions[CSS_WIDTH] = 40;
-        node_1->style.dimensions[CSS_HEIGHT] = 10;
-        node_1 = node_0->get_child(node_0->context, 1);
-        node_1->style.dimensions[CSS_WIDTH] = 40;
-        node_1->style.dimensions[CSS_HEIGHT] = 10;
-        node_1 = node_0->get_child(node_0->context, 2);
-        node_1->style.dimensions[CSS_WIDTH] = 40;
-        node_1->style.dimensions[CSS_HEIGHT] = 10;
-      }
-    }
-
-    css_node_t *root_layout = new_test_css_node();
-    {
-      css_node_t *node_0 = root_layout;
-      node_0->layout.position[CSS_TOP] = 0;
-      node_0->layout.position[CSS_LEFT] = 0;
-      node_0->layout.dimensions[CSS_WIDTH] = 100;
-      node_0->layout.dimensions[CSS_HEIGHT] = 20;
-      init_css_node_children(node_0, 3);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->layout.position[CSS_TOP] = 0;
-        node_1->layout.position[CSS_LEFT] = 0;
-        node_1->layout.dimensions[CSS_WIDTH] = 40;
-        node_1->layout.dimensions[CSS_HEIGHT] = 10;
-        node_1 = node_0->get_child(node_0->context, 1);
-        node_1->layout.position[CSS_TOP] = 0;
-        node_1->layout.position[CSS_LEFT] = 40;
-        node_1->layout.dimensions[CSS_WIDTH] = 40;
-        node_1->layout.dimensions[CSS_HEIGHT] = 10;
-        node_1 = node_0->get_child(node_0->context, 2);
-        node_1->layout.position[CSS_TOP] = 10;
-        node_1->layout.position[CSS_LEFT] = 0;
-        node_1->layout.dimensions[CSS_WIDTH] = 40;
-        node_1->layout.dimensions[CSS_HEIGHT] = 10;
-      }
-    }
-
-    test("should layout flex-wrap", root_node, root_layout);
-  }
-
-  {
-    css_node_t *root_node = new_test_css_node();
-    {
-      css_node_t *node_0 = root_node;
-      node_0->style.direction = CSS_DIRECTION_RTL;
-      node_0->style.flex_direction = CSS_FLEX_DIRECTION_ROW;
-      node_0->style.flex_wrap = CSS_WRAP;
-      node_0->style.dimensions[CSS_WIDTH] = 100;
-      init_css_node_children(node_0, 3);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->style.dimensions[CSS_WIDTH] = 40;
-        node_1->style.dimensions[CSS_HEIGHT] = 10;
-        node_1 = node_0->get_child(node_0->context, 1);
-        node_1->style.dimensions[CSS_WIDTH] = 40;
-        node_1->style.dimensions[CSS_HEIGHT] = 10;
-        node_1 = node_0->get_child(node_0->context, 2);
-        node_1->style.dimensions[CSS_WIDTH] = 40;
-        node_1->style.dimensions[CSS_HEIGHT] = 10;
-      }
-    }
-
-    css_node_t *root_layout = new_test_css_node();
-    {
-      css_node_t *node_0 = root_layout;
-      node_0->layout.position[CSS_TOP] = 0;
-      node_0->layout.position[CSS_LEFT] = 0;
-      node_0->layout.dimensions[CSS_WIDTH] = 100;
-      node_0->layout.dimensions[CSS_HEIGHT] = 20;
-      init_css_node_children(node_0, 3);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->layout.position[CSS_TOP] = 0;
-        node_1->layout.position[CSS_LEFT] = 60;
-        node_1->layout.dimensions[CSS_WIDTH] = 40;
-        node_1->layout.dimensions[CSS_HEIGHT] = 10;
-        node_1 = node_0->get_child(node_0->context, 1);
-        node_1->layout.position[CSS_TOP] = 0;
-        node_1->layout.position[CSS_LEFT] = 20;
-        node_1->layout.dimensions[CSS_WIDTH] = 40;
-        node_1->layout.dimensions[CSS_HEIGHT] = 10;
-        node_1 = node_0->get_child(node_0->context, 2);
-        node_1->layout.position[CSS_TOP] = 10;
-        node_1->layout.position[CSS_LEFT] = 60;
-        node_1->layout.dimensions[CSS_WIDTH] = 40;
-        node_1->layout.dimensions[CSS_HEIGHT] = 10;
-      }
-    }
-
-    test("should layout flex-wrap in rtl", root_node, root_layout);
-  }
-
-  {
-    css_node_t *root_node = new_test_css_node();
-    {
-      css_node_t *node_0 = root_node;
-      node_0->style.flex_wrap = CSS_WRAP;
-      node_0->style.dimensions[CSS_HEIGHT] = 100;
-      init_css_node_children(node_0, 2);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->style.dimensions[CSS_HEIGHT] = 100;
-        node_1 = node_0->get_child(node_0->context, 1);
-        node_1->style.dimensions[CSS_HEIGHT] = 200;
-      }
-    }
-
-    css_node_t *root_layout = new_test_css_node();
-    {
-      css_node_t *node_0 = root_layout;
-      node_0->layout.position[CSS_TOP] = 0;
-      node_0->layout.position[CSS_LEFT] = 0;
-      node_0->layout.dimensions[CSS_WIDTH] = 0;
-      node_0->layout.dimensions[CSS_HEIGHT] = 100;
-      init_css_node_children(node_0, 2);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->layout.position[CSS_TOP] = 0;
-        node_1->layout.position[CSS_LEFT] = 0;
-        node_1->layout.dimensions[CSS_WIDTH] = 0;
-        node_1->layout.dimensions[CSS_HEIGHT] = 100;
-        node_1 = node_0->get_child(node_0->context, 1);
-        node_1->layout.position[CSS_TOP] = 0;
-        node_1->layout.position[CSS_LEFT] = 0;
-        node_1->layout.dimensions[CSS_WIDTH] = 0;
-        node_1->layout.dimensions[CSS_HEIGHT] = 200;
-      }
-    }
-
-    test("should layout flex wrap with a line bigger than container", root_node, root_layout);
-  }
-
-  {
-    css_node_t *root_node = new_test_css_node();
-    {
-      css_node_t *node_0 = root_node;
-      node_0->style.dimensions[CSS_WIDTH] = 100;
-      node_0->style.dimensions[CSS_HEIGHT] = 200;
-      node_0->style.maxDimensions[CSS_WIDTH] = 90;
-      node_0->style.maxDimensions[CSS_HEIGHT] = 190;
-    }
-
-    css_node_t *root_layout = new_test_css_node();
-    {
-      css_node_t *node_0 = root_layout;
-      node_0->layout.position[CSS_TOP] = 0;
-      node_0->layout.position[CSS_LEFT] = 0;
-      node_0->layout.dimensions[CSS_WIDTH] = 90;
-      node_0->layout.dimensions[CSS_HEIGHT] = 190;
-    }
-
-    test("should use max bounds", root_node, root_layout);
-  }
-
-  {
-    css_node_t *root_node = new_test_css_node();
-    {
-      css_node_t *node_0 = root_node;
-      node_0->style.dimensions[CSS_WIDTH] = 100;
-      node_0->style.dimensions[CSS_HEIGHT] = 200;
-      node_0->style.minDimensions[CSS_WIDTH] = 110;
-      node_0->style.minDimensions[CSS_HEIGHT] = 210;
-    }
-
-    css_node_t *root_layout = new_test_css_node();
-    {
-      css_node_t *node_0 = root_layout;
-      node_0->layout.position[CSS_TOP] = 0;
-      node_0->layout.position[CSS_LEFT] = 0;
-      node_0->layout.dimensions[CSS_WIDTH] = 110;
-      node_0->layout.dimensions[CSS_HEIGHT] = 210;
-    }
-
-    test("should use min bounds", root_node, root_layout);
-  }
-
-  {
-    css_node_t *root_node = new_test_css_node();
-    {
-      css_node_t *node_0 = root_node;
-      node_0->style.dimensions[CSS_WIDTH] = 100;
-      node_0->style.dimensions[CSS_HEIGHT] = 200;
-      node_0->style.maxDimensions[CSS_WIDTH] = 90;
-      node_0->style.maxDimensions[CSS_HEIGHT] = 190;
-      node_0->style.minDimensions[CSS_WIDTH] = 110;
-      node_0->style.minDimensions[CSS_HEIGHT] = 210;
-    }
-
-    css_node_t *root_layout = new_test_css_node();
-    {
-      css_node_t *node_0 = root_layout;
-      node_0->layout.position[CSS_TOP] = 0;
-      node_0->layout.position[CSS_LEFT] = 0;
-      node_0->layout.dimensions[CSS_WIDTH] = 110;
-      node_0->layout.dimensions[CSS_HEIGHT] = 210;
-    }
-
-    test("should use min bounds over max bounds", root_node, root_layout);
-  }
-
-  {
-    css_node_t *root_node = new_test_css_node();
-    {
-      css_node_t *node_0 = root_node;
-      node_0->style.dimensions[CSS_WIDTH] = 100;
-      node_0->style.dimensions[CSS_HEIGHT] = 200;
-      node_0->style.maxDimensions[CSS_WIDTH] = 80;
-      node_0->style.maxDimensions[CSS_HEIGHT] = 180;
-      node_0->style.minDimensions[CSS_WIDTH] = 90;
-      node_0->style.minDimensions[CSS_HEIGHT] = 190;
-    }
-
-    css_node_t *root_layout = new_test_css_node();
-    {
-      css_node_t *node_0 = root_layout;
-      node_0->layout.position[CSS_TOP] = 0;
-      node_0->layout.position[CSS_LEFT] = 0;
-      node_0->layout.dimensions[CSS_WIDTH] = 90;
-      node_0->layout.dimensions[CSS_HEIGHT] = 190;
-    }
-
-    test("should use min bounds over max bounds and natural width", root_node, root_layout);
-  }
-
-  {
-    css_node_t *root_node = new_test_css_node();
-    {
-      css_node_t *node_0 = root_node;
-      node_0->style.dimensions[CSS_WIDTH] = 100;
-      node_0->style.dimensions[CSS_HEIGHT] = 200;
-      node_0->style.minDimensions[CSS_WIDTH] = -10;
-      node_0->style.minDimensions[CSS_HEIGHT] = -20;
-    }
-
-    css_node_t *root_layout = new_test_css_node();
-    {
-      css_node_t *node_0 = root_layout;
-      node_0->layout.position[CSS_TOP] = 0;
-      node_0->layout.position[CSS_LEFT] = 0;
-      node_0->layout.dimensions[CSS_WIDTH] = 100;
-      node_0->layout.dimensions[CSS_HEIGHT] = 200;
-    }
-
-    test("should ignore negative min bounds", root_node, root_layout);
-  }
-
-  {
-    css_node_t *root_node = new_test_css_node();
-    {
-      css_node_t *node_0 = root_node;
-      node_0->style.dimensions[CSS_WIDTH] = 100;
-      node_0->style.dimensions[CSS_HEIGHT] = 200;
-      node_0->style.maxDimensions[CSS_WIDTH] = -10;
-      node_0->style.maxDimensions[CSS_HEIGHT] = -20;
-    }
-
-    css_node_t *root_layout = new_test_css_node();
-    {
-      css_node_t *node_0 = root_layout;
-      node_0->layout.position[CSS_TOP] = 0;
-      node_0->layout.position[CSS_LEFT] = 0;
-      node_0->layout.dimensions[CSS_WIDTH] = 100;
-      node_0->layout.dimensions[CSS_HEIGHT] = 200;
-    }
-
-    test("should ignore negative max bounds", root_node, root_layout);
-  }
-
-  {
-    css_node_t *root_node = new_test_css_node();
-    {
-      css_node_t *node_0 = root_node;
-      node_0->style.maxDimensions[CSS_WIDTH] = 30;
-      node_0->style.maxDimensions[CSS_HEIGHT] = 10;
-      node_0->style.padding[CSS_LEFT] = 20;
-      node_0->style.padding[CSS_TOP] = 15;
-      node_0->style.padding[CSS_RIGHT] = 20;
-      node_0->style.padding[CSS_BOTTOM] = 15;
-    }
-
-    css_node_t *root_layout = new_test_css_node();
-    {
-      css_node_t *node_0 = root_layout;
-      node_0->layout.position[CSS_TOP] = 0;
-      node_0->layout.position[CSS_LEFT] = 0;
-      node_0->layout.dimensions[CSS_WIDTH] = 40;
-      node_0->layout.dimensions[CSS_HEIGHT] = 30;
-    }
-
-    test("should use padded size over max bounds", root_node, root_layout);
-  }
-
-  {
-    css_node_t *root_node = new_test_css_node();
-    {
-      css_node_t *node_0 = root_node;
-      node_0->style.minDimensions[CSS_WIDTH] = 50;
-      node_0->style.minDimensions[CSS_HEIGHT] = 40;
-      node_0->style.padding[CSS_LEFT] = 20;
-      node_0->style.padding[CSS_TOP] = 15;
-      node_0->style.padding[CSS_RIGHT] = 20;
-      node_0->style.padding[CSS_BOTTOM] = 15;
-    }
-
-    css_node_t *root_layout = new_test_css_node();
-    {
-      css_node_t *node_0 = root_layout;
-      node_0->layout.position[CSS_TOP] = 0;
-      node_0->layout.position[CSS_LEFT] = 0;
-      node_0->layout.dimensions[CSS_WIDTH] = 50;
-      node_0->layout.dimensions[CSS_HEIGHT] = 40;
-    }
-
-    test("should use min size over padded size", root_node, root_layout);
-  }
-
-  {
-    css_node_t *root_node = new_test_css_node();
-    {
-      css_node_t *node_0 = root_node;
-      node_0->style.flex_direction = CSS_FLEX_DIRECTION_ROW;
-      node_0->style.dimensions[CSS_WIDTH] = 300;
-      node_0->style.dimensions[CSS_HEIGHT] = 200;
-      init_css_node_children(node_0, 3);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->style.flex = 1;
-        node_1 = node_0->get_child(node_0->context, 1);
-        node_1->style.flex = 1;
-        node_1->style.minDimensions[CSS_WIDTH] = 200;
-        node_1 = node_0->get_child(node_0->context, 2);
-        node_1->style.flex = 1;
-      }
-    }
-
-    css_node_t *root_layout = new_test_css_node();
-    {
-      css_node_t *node_0 = root_layout;
-      node_0->layout.position[CSS_TOP] = 0;
-      node_0->layout.position[CSS_LEFT] = 0;
-      node_0->layout.dimensions[CSS_WIDTH] = 300;
-      node_0->layout.dimensions[CSS_HEIGHT] = 200;
-      init_css_node_children(node_0, 3);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->layout.position[CSS_TOP] = 0;
-        node_1->layout.position[CSS_LEFT] = 0;
-        node_1->layout.dimensions[CSS_WIDTH] = 50;
-        node_1->layout.dimensions[CSS_HEIGHT] = 200;
-        node_1 = node_0->get_child(node_0->context, 1);
-        node_1->layout.position[CSS_TOP] = 0;
-        node_1->layout.position[CSS_LEFT] = 50;
-        node_1->layout.dimensions[CSS_WIDTH] = 200;
-        node_1->layout.dimensions[CSS_HEIGHT] = 200;
-        node_1 = node_0->get_child(node_0->context, 2);
-        node_1->layout.position[CSS_TOP] = 0;
-        node_1->layout.position[CSS_LEFT] = 250;
-        node_1->layout.dimensions[CSS_WIDTH] = 50;
-        node_1->layout.dimensions[CSS_HEIGHT] = 200;
-      }
-    }
-
-    test("should override flex direction size with min bounds", root_node, root_layout);
-  }
-
-  {
-    css_node_t *root_node = new_test_css_node();
-    {
-      css_node_t *node_0 = root_node;
-      node_0->style.direction = CSS_DIRECTION_RTL;
-      node_0->style.flex_direction = CSS_FLEX_DIRECTION_ROW;
-      node_0->style.dimensions[CSS_WIDTH] = 300;
-      node_0->style.dimensions[CSS_HEIGHT] = 200;
-      init_css_node_children(node_0, 3);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->style.flex = 1;
-        node_1 = node_0->get_child(node_0->context, 1);
-        node_1->style.flex = 1;
-        node_1->style.minDimensions[CSS_WIDTH] = 200;
-        node_1 = node_0->get_child(node_0->context, 2);
-        node_1->style.flex = 1;
-      }
-    }
-
-    css_node_t *root_layout = new_test_css_node();
-    {
-      css_node_t *node_0 = root_layout;
-      node_0->layout.position[CSS_TOP] = 0;
-      node_0->layout.position[CSS_LEFT] = 0;
-      node_0->layout.dimensions[CSS_WIDTH] = 300;
-      node_0->layout.dimensions[CSS_HEIGHT] = 200;
-      init_css_node_children(node_0, 3);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->layout.position[CSS_TOP] = 0;
-        node_1->layout.position[CSS_LEFT] = 250;
-        node_1->layout.dimensions[CSS_WIDTH] = 50;
-        node_1->layout.dimensions[CSS_HEIGHT] = 200;
-        node_1 = node_0->get_child(node_0->context, 1);
-        node_1->layout.position[CSS_TOP] = 0;
-        node_1->layout.position[CSS_LEFT] = 50;
-        node_1->layout.dimensions[CSS_WIDTH] = 200;
-        node_1->layout.dimensions[CSS_HEIGHT] = 200;
-        node_1 = node_0->get_child(node_0->context, 2);
-        node_1->layout.position[CSS_TOP] = 0;
-        node_1->layout.position[CSS_LEFT] = 0;
-        node_1->layout.dimensions[CSS_WIDTH] = 50;
-        node_1->layout.dimensions[CSS_HEIGHT] = 200;
-      }
-    }
-
-    test("should override flex direction size with min bounds in rtl", root_node, root_layout);
-  }
-
-  {
-    css_node_t *root_node = new_test_css_node();
-    {
-      css_node_t *node_0 = root_node;
-      node_0->style.flex_direction = CSS_FLEX_DIRECTION_ROW;
-      node_0->style.dimensions[CSS_WIDTH] = 300;
-      node_0->style.dimensions[CSS_HEIGHT] = 200;
-      init_css_node_children(node_0, 3);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->style.flex = 1;
-        node_1 = node_0->get_child(node_0->context, 1);
-        node_1->style.flex = 1;
-        node_1->style.maxDimensions[CSS_WIDTH] = 110;
-        node_1->style.minDimensions[CSS_WIDTH] = 90;
-        node_1 = node_0->get_child(node_0->context, 2);
-        node_1->style.flex = 1;
-      }
-    }
-
-    css_node_t *root_layout = new_test_css_node();
-    {
-      css_node_t *node_0 = root_layout;
-      node_0->layout.position[CSS_TOP] = 0;
-      node_0->layout.position[CSS_LEFT] = 0;
-      node_0->layout.dimensions[CSS_WIDTH] = 300;
-      node_0->layout.dimensions[CSS_HEIGHT] = 200;
-      init_css_node_children(node_0, 3);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->layout.position[CSS_TOP] = 0;
-        node_1->layout.position[CSS_LEFT] = 0;
-        node_1->layout.dimensions[CSS_WIDTH] = 100;
-        node_1->layout.dimensions[CSS_HEIGHT] = 200;
-        node_1 = node_0->get_child(node_0->context, 1);
-        node_1->layout.position[CSS_TOP] = 0;
-        node_1->layout.position[CSS_LEFT] = 100;
-        node_1->layout.dimensions[CSS_WIDTH] = 100;
-        node_1->layout.dimensions[CSS_HEIGHT] = 200;
-        node_1 = node_0->get_child(node_0->context, 2);
-        node_1->layout.position[CSS_TOP] = 0;
-        node_1->layout.position[CSS_LEFT] = 200;
-        node_1->layout.dimensions[CSS_WIDTH] = 100;
-        node_1->layout.dimensions[CSS_HEIGHT] = 200;
-      }
-    }
-
-    test("should not override flex direction size within bounds", root_node, root_layout);
-  }
-
-  {
-    css_node_t *root_node = new_test_css_node();
-    {
-      css_node_t *node_0 = root_node;
-      node_0->style.direction = CSS_DIRECTION_RTL;
-      node_0->style.flex_direction = CSS_FLEX_DIRECTION_ROW;
-      node_0->style.dimensions[CSS_WIDTH] = 300;
-      node_0->style.dimensions[CSS_HEIGHT] = 200;
-      init_css_node_children(node_0, 3);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->style.flex = 1;
-        node_1 = node_0->get_child(node_0->context, 1);
-        node_1->style.flex = 1;
-        node_1->style.maxDimensions[CSS_WIDTH] = 110;
-        node_1->style.minDimensions[CSS_WIDTH] = 90;
-        node_1 = node_0->get_child(node_0->context, 2);
-        node_1->style.flex = 1;
-      }
-    }
-
-    css_node_t *root_layout = new_test_css_node();
-    {
-      css_node_t *node_0 = root_layout;
-      node_0->layout.position[CSS_TOP] = 0;
-      node_0->layout.position[CSS_LEFT] = 0;
-      node_0->layout.dimensions[CSS_WIDTH] = 300;
-      node_0->layout.dimensions[CSS_HEIGHT] = 200;
-      init_css_node_children(node_0, 3);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->layout.position[CSS_TOP] = 0;
-        node_1->layout.position[CSS_LEFT] = 200;
-        node_1->layout.dimensions[CSS_WIDTH] = 100;
-        node_1->layout.dimensions[CSS_HEIGHT] = 200;
-        node_1 = node_0->get_child(node_0->context, 1);
-        node_1->layout.position[CSS_TOP] = 0;
-        node_1->layout.position[CSS_LEFT] = 100;
-        node_1->layout.dimensions[CSS_WIDTH] = 100;
-        node_1->layout.dimensions[CSS_HEIGHT] = 200;
-        node_1 = node_0->get_child(node_0->context, 2);
-        node_1->layout.position[CSS_TOP] = 0;
-        node_1->layout.position[CSS_LEFT] = 0;
-        node_1->layout.dimensions[CSS_WIDTH] = 100;
-        node_1->layout.dimensions[CSS_HEIGHT] = 200;
-      }
-    }
-
-    test("should not override flex direction size within bounds in rtl", root_node, root_layout);
-  }
-
-  {
-    css_node_t *root_node = new_test_css_node();
-    {
-      css_node_t *node_0 = root_node;
-      node_0->style.flex_direction = CSS_FLEX_DIRECTION_ROW;
-      node_0->style.dimensions[CSS_WIDTH] = 300;
-      node_0->style.dimensions[CSS_HEIGHT] = 200;
-      init_css_node_children(node_0, 3);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->style.flex = 1;
-        node_1 = node_0->get_child(node_0->context, 1);
-        node_1->style.flex = 1;
-        node_1->style.maxDimensions[CSS_WIDTH] = 60;
-        node_1 = node_0->get_child(node_0->context, 2);
-        node_1->style.flex = 1;
-      }
-    }
-
-    css_node_t *root_layout = new_test_css_node();
-    {
-      css_node_t *node_0 = root_layout;
-      node_0->layout.position[CSS_TOP] = 0;
-      node_0->layout.position[CSS_LEFT] = 0;
-      node_0->layout.dimensions[CSS_WIDTH] = 300;
-      node_0->layout.dimensions[CSS_HEIGHT] = 200;
-      init_css_node_children(node_0, 3);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->layout.position[CSS_TOP] = 0;
-        node_1->layout.position[CSS_LEFT] = 0;
-        node_1->layout.dimensions[CSS_WIDTH] = 120;
-        node_1->layout.dimensions[CSS_HEIGHT] = 200;
-        node_1 = node_0->get_child(node_0->context, 1);
-        node_1->layout.position[CSS_TOP] = 0;
-        node_1->layout.position[CSS_LEFT] = 120;
-        node_1->layout.dimensions[CSS_WIDTH] = 60;
-        node_1->layout.dimensions[CSS_HEIGHT] = 200;
-        node_1 = node_0->get_child(node_0->context, 2);
-        node_1->layout.position[CSS_TOP] = 0;
-        node_1->layout.position[CSS_LEFT] = 180;
-        node_1->layout.dimensions[CSS_WIDTH] = 120;
-        node_1->layout.dimensions[CSS_HEIGHT] = 200;
-      }
-    }
-
-    test("should override flex direction size with max bounds", root_node, root_layout);
-  }
-
-  {
-    css_node_t *root_node = new_test_css_node();
-    {
-      css_node_t *node_0 = root_node;
-      node_0->style.direction = CSS_DIRECTION_RTL;
-      node_0->style.flex_direction = CSS_FLEX_DIRECTION_ROW;
-      node_0->style.dimensions[CSS_WIDTH] = 300;
-      node_0->style.dimensions[CSS_HEIGHT] = 200;
-      init_css_node_children(node_0, 3);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->style.flex = 1;
-        node_1 = node_0->get_child(node_0->context, 1);
-        node_1->style.flex = 1;
-        node_1->style.maxDimensions[CSS_WIDTH] = 60;
-        node_1 = node_0->get_child(node_0->context, 2);
-        node_1->style.flex = 1;
-      }
-    }
-
-    css_node_t *root_layout = new_test_css_node();
-    {
-      css_node_t *node_0 = root_layout;
-      node_0->layout.position[CSS_TOP] = 0;
-      node_0->layout.position[CSS_LEFT] = 0;
-      node_0->layout.dimensions[CSS_WIDTH] = 300;
-      node_0->layout.dimensions[CSS_HEIGHT] = 200;
-      init_css_node_children(node_0, 3);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->layout.position[CSS_TOP] = 0;
-        node_1->layout.position[CSS_LEFT] = 180;
-        node_1->layout.dimensions[CSS_WIDTH] = 120;
-        node_1->layout.dimensions[CSS_HEIGHT] = 200;
-        node_1 = node_0->get_child(node_0->context, 1);
-        node_1->layout.position[CSS_TOP] = 0;
-        node_1->layout.position[CSS_LEFT] = 120;
-        node_1->layout.dimensions[CSS_WIDTH] = 60;
-        node_1->layout.dimensions[CSS_HEIGHT] = 200;
-        node_1 = node_0->get_child(node_0->context, 2);
-        node_1->layout.position[CSS_TOP] = 0;
-        node_1->layout.position[CSS_LEFT] = 0;
-        node_1->layout.dimensions[CSS_WIDTH] = 120;
-        node_1->layout.dimensions[CSS_HEIGHT] = 200;
-      }
-    }
-
-    test("should override flex direction size with max bounds in rtl", root_node, root_layout);
-  }
-
-  {
-    css_node_t *root_node = new_test_css_node();
-    {
-      css_node_t *node_0 = root_node;
-      node_0->style.flex_direction = CSS_FLEX_DIRECTION_ROW;
-      node_0->style.dimensions[CSS_WIDTH] = 300;
-      node_0->style.dimensions[CSS_HEIGHT] = 200;
-      init_css_node_children(node_0, 3);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->style.flex = 1;
-        node_1->style.maxDimensions[CSS_WIDTH] = 60;
-        node_1 = node_0->get_child(node_0->context, 1);
-        node_1->style.flex = 1;
-        node_1->style.maxDimensions[CSS_WIDTH] = 60;
-        node_1 = node_0->get_child(node_0->context, 2);
-        node_1->style.flex = 1;
-        node_1->style.maxDimensions[CSS_WIDTH] = 60;
-      }
-    }
-
-    css_node_t *root_layout = new_test_css_node();
-    {
-      css_node_t *node_0 = root_layout;
-      node_0->layout.position[CSS_TOP] = 0;
-      node_0->layout.position[CSS_LEFT] = 0;
-      node_0->layout.dimensions[CSS_WIDTH] = 300;
-      node_0->layout.dimensions[CSS_HEIGHT] = 200;
-      init_css_node_children(node_0, 3);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->layout.position[CSS_TOP] = 0;
-        node_1->layout.position[CSS_LEFT] = 0;
-        node_1->layout.dimensions[CSS_WIDTH] = 60;
-        node_1->layout.dimensions[CSS_HEIGHT] = 200;
-        node_1 = node_0->get_child(node_0->context, 1);
-        node_1->layout.position[CSS_TOP] = 0;
-        node_1->layout.position[CSS_LEFT] = 60;
-        node_1->layout.dimensions[CSS_WIDTH] = 60;
-        node_1->layout.dimensions[CSS_HEIGHT] = 200;
-        node_1 = node_0->get_child(node_0->context, 2);
-        node_1->layout.position[CSS_TOP] = 0;
-        node_1->layout.position[CSS_LEFT] = 120;
-        node_1->layout.dimensions[CSS_WIDTH] = 60;
-        node_1->layout.dimensions[CSS_HEIGHT] = 200;
-      }
-    }
-
-    test("should ignore flex size if fully max bound", root_node, root_layout);
-  }
-
-  {
-    css_node_t *root_node = new_test_css_node();
-    {
-      css_node_t *node_0 = root_node;
-      node_0->style.direction = CSS_DIRECTION_RTL;
-      node_0->style.flex_direction = CSS_FLEX_DIRECTION_ROW;
-      node_0->style.dimensions[CSS_WIDTH] = 300;
-      node_0->style.dimensions[CSS_HEIGHT] = 200;
-      init_css_node_children(node_0, 3);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->style.flex = 1;
-        node_1->style.maxDimensions[CSS_WIDTH] = 60;
-        node_1 = node_0->get_child(node_0->context, 1);
-        node_1->style.flex = 1;
-        node_1->style.maxDimensions[CSS_WIDTH] = 60;
-        node_1 = node_0->get_child(node_0->context, 2);
-        node_1->style.flex = 1;
-        node_1->style.maxDimensions[CSS_WIDTH] = 60;
-      }
-    }
-
-    css_node_t *root_layout = new_test_css_node();
-    {
-      css_node_t *node_0 = root_layout;
-      node_0->layout.position[CSS_TOP] = 0;
-      node_0->layout.position[CSS_LEFT] = 0;
-      node_0->layout.dimensions[CSS_WIDTH] = 300;
-      node_0->layout.dimensions[CSS_HEIGHT] = 200;
-      init_css_node_children(node_0, 3);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->layout.position[CSS_TOP] = 0;
-        node_1->layout.position[CSS_LEFT] = 240;
-        node_1->layout.dimensions[CSS_WIDTH] = 60;
-        node_1->layout.dimensions[CSS_HEIGHT] = 200;
-        node_1 = node_0->get_child(node_0->context, 1);
-        node_1->layout.position[CSS_TOP] = 0;
-        node_1->layout.position[CSS_LEFT] = 180;
-        node_1->layout.dimensions[CSS_WIDTH] = 60;
-        node_1->layout.dimensions[CSS_HEIGHT] = 200;
-        node_1 = node_0->get_child(node_0->context, 2);
-        node_1->layout.position[CSS_TOP] = 0;
-        node_1->layout.position[CSS_LEFT] = 120;
-        node_1->layout.dimensions[CSS_WIDTH] = 60;
-        node_1->layout.dimensions[CSS_HEIGHT] = 200;
-      }
-    }
-
-    test("should ignore flex size if fully max bound in rtl", root_node, root_layout);
-  }
-
-  {
-    css_node_t *root_node = new_test_css_node();
-    {
-      css_node_t *node_0 = root_node;
-      node_0->style.flex_direction = CSS_FLEX_DIRECTION_ROW;
-      node_0->style.dimensions[CSS_WIDTH] = 300;
-      node_0->style.dimensions[CSS_HEIGHT] = 200;
-      init_css_node_children(node_0, 3);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->style.flex = 1;
-        node_1->style.minDimensions[CSS_WIDTH] = 120;
-        node_1 = node_0->get_child(node_0->context, 1);
-        node_1->style.flex = 1;
-        node_1->style.minDimensions[CSS_WIDTH] = 120;
-        node_1 = node_0->get_child(node_0->context, 2);
-        node_1->style.flex = 1;
-        node_1->style.minDimensions[CSS_WIDTH] = 120;
-      }
-    }
-
-    css_node_t *root_layout = new_test_css_node();
-    {
-      css_node_t *node_0 = root_layout;
-      node_0->layout.position[CSS_TOP] = 0;
-      node_0->layout.position[CSS_LEFT] = 0;
-      node_0->layout.dimensions[CSS_WIDTH] = 300;
-      node_0->layout.dimensions[CSS_HEIGHT] = 200;
-      init_css_node_children(node_0, 3);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->layout.position[CSS_TOP] = 0;
-        node_1->layout.position[CSS_LEFT] = 0;
-        node_1->layout.dimensions[CSS_WIDTH] = 120;
-        node_1->layout.dimensions[CSS_HEIGHT] = 200;
-        node_1 = node_0->get_child(node_0->context, 1);
-        node_1->layout.position[CSS_TOP] = 0;
-        node_1->layout.position[CSS_LEFT] = 120;
-        node_1->layout.dimensions[CSS_WIDTH] = 120;
-        node_1->layout.dimensions[CSS_HEIGHT] = 200;
-        node_1 = node_0->get_child(node_0->context, 2);
-        node_1->layout.position[CSS_TOP] = 0;
-        node_1->layout.position[CSS_LEFT] = 240;
-        node_1->layout.dimensions[CSS_WIDTH] = 120;
-        node_1->layout.dimensions[CSS_HEIGHT] = 200;
-      }
-    }
-
-    test("should ignore flex size if fully min bound", root_node, root_layout);
-  }
-
-  {
-    css_node_t *root_node = new_test_css_node();
-    {
-      css_node_t *node_0 = root_node;
-      node_0->style.direction = CSS_DIRECTION_RTL;
-      node_0->style.flex_direction = CSS_FLEX_DIRECTION_ROW;
-      node_0->style.dimensions[CSS_WIDTH] = 300;
-      node_0->style.dimensions[CSS_HEIGHT] = 200;
-      init_css_node_children(node_0, 3);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->style.flex = 1;
-        node_1->style.minDimensions[CSS_WIDTH] = 120;
-        node_1 = node_0->get_child(node_0->context, 1);
-        node_1->style.flex = 1;
-        node_1->style.minDimensions[CSS_WIDTH] = 120;
-        node_1 = node_0->get_child(node_0->context, 2);
-        node_1->style.flex = 1;
-        node_1->style.minDimensions[CSS_WIDTH] = 120;
-      }
-    }
-
-    css_node_t *root_layout = new_test_css_node();
-    {
-      css_node_t *node_0 = root_layout;
-      node_0->layout.position[CSS_TOP] = 0;
-      node_0->layout.position[CSS_LEFT] = 0;
-      node_0->layout.dimensions[CSS_WIDTH] = 300;
-      node_0->layout.dimensions[CSS_HEIGHT] = 200;
-      init_css_node_children(node_0, 3);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->layout.position[CSS_TOP] = 0;
-        node_1->layout.position[CSS_LEFT] = 180;
-        node_1->layout.dimensions[CSS_WIDTH] = 120;
-        node_1->layout.dimensions[CSS_HEIGHT] = 200;
-        node_1 = node_0->get_child(node_0->context, 1);
-        node_1->layout.position[CSS_TOP] = 0;
-        node_1->layout.position[CSS_LEFT] = 60;
-        node_1->layout.dimensions[CSS_WIDTH] = 120;
-        node_1->layout.dimensions[CSS_HEIGHT] = 200;
-        node_1 = node_0->get_child(node_0->context, 2);
-        node_1->layout.position[CSS_TOP] = 0;
-        node_1->layout.position[CSS_LEFT] = -60;
-        node_1->layout.dimensions[CSS_WIDTH] = 120;
-        node_1->layout.dimensions[CSS_HEIGHT] = 200;
-      }
-    }
-
-    test("should ignore flex size if fully min bound in rtl", root_node, root_layout);
-  }
-
-  {
-    css_node_t *root_node = new_test_css_node();
-    {
-      css_node_t *node_0 = root_node;
-      node_0->style.dimensions[CSS_WIDTH] = 300;
-      node_0->style.dimensions[CSS_HEIGHT] = 200;
-      init_css_node_children(node_0, 1);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->style.flex = 1;
-        node_1->style.maxDimensions[CSS_WIDTH] = 310;
-        node_1->style.minDimensions[CSS_WIDTH] = 290;
-      }
-    }
-
-    css_node_t *root_layout = new_test_css_node();
-    {
-      css_node_t *node_0 = root_layout;
-      node_0->layout.position[CSS_TOP] = 0;
-      node_0->layout.position[CSS_LEFT] = 0;
-      node_0->layout.dimensions[CSS_WIDTH] = 300;
-      node_0->layout.dimensions[CSS_HEIGHT] = 200;
-      init_css_node_children(node_0, 1);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->layout.position[CSS_TOP] = 0;
-        node_1->layout.position[CSS_LEFT] = 0;
-        node_1->layout.dimensions[CSS_WIDTH] = 300;
-        node_1->layout.dimensions[CSS_HEIGHT] = 200;
-      }
-    }
-
-    test("should pre-fill child size within bounds", root_node, root_layout);
-  }
-
-  {
-    css_node_t *root_node = new_test_css_node();
-    {
-      css_node_t *node_0 = root_node;
-      node_0->style.dimensions[CSS_WIDTH] = 300;
-      node_0->style.dimensions[CSS_HEIGHT] = 200;
-      init_css_node_children(node_0, 1);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->style.flex = 1;
-        node_1->style.maxDimensions[CSS_WIDTH] = 290;
-      }
-    }
-
-    css_node_t *root_layout = new_test_css_node();
-    {
-      css_node_t *node_0 = root_layout;
-      node_0->layout.position[CSS_TOP] = 0;
-      node_0->layout.position[CSS_LEFT] = 0;
-      node_0->layout.dimensions[CSS_WIDTH] = 300;
-      node_0->layout.dimensions[CSS_HEIGHT] = 200;
-      init_css_node_children(node_0, 1);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->layout.position[CSS_TOP] = 0;
-        node_1->layout.position[CSS_LEFT] = 0;
-        node_1->layout.dimensions[CSS_WIDTH] = 290;
-        node_1->layout.dimensions[CSS_HEIGHT] = 200;
-      }
-    }
-
-    test("should pre-fill child size within max bound", root_node, root_layout);
-  }
-
-  {
-    css_node_t *root_node = new_test_css_node();
-    {
-      css_node_t *node_0 = root_node;
-      node_0->style.dimensions[CSS_WIDTH] = 300;
-      node_0->style.dimensions[CSS_HEIGHT] = 200;
-      init_css_node_children(node_0, 1);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->style.flex = 1;
-        node_1->style.minDimensions[CSS_WIDTH] = 310;
-      }
-    }
-
-    css_node_t *root_layout = new_test_css_node();
-    {
-      css_node_t *node_0 = root_layout;
-      node_0->layout.position[CSS_TOP] = 0;
-      node_0->layout.position[CSS_LEFT] = 0;
-      node_0->layout.dimensions[CSS_WIDTH] = 300;
-      node_0->layout.dimensions[CSS_HEIGHT] = 200;
-      init_css_node_children(node_0, 1);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->layout.position[CSS_TOP] = 0;
-        node_1->layout.position[CSS_LEFT] = 0;
-        node_1->layout.dimensions[CSS_WIDTH] = 310;
-        node_1->layout.dimensions[CSS_HEIGHT] = 200;
-      }
-    }
-
-    test("should pre-fill child size within min bounds", root_node, root_layout);
-  }
-
-  {
-    css_node_t *root_node = new_test_css_node();
-    {
-      css_node_t *node_0 = root_node;
-      node_0->style.maxDimensions[CSS_WIDTH] = 300;
-      node_0->style.maxDimensions[CSS_HEIGHT] = 700;
-      node_0->style.minDimensions[CSS_WIDTH] = 100;
-      node_0->style.minDimensions[CSS_HEIGHT] = 500;
-      init_css_node_children(node_0, 2);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->style.dimensions[CSS_WIDTH] = 200;
-        node_1->style.dimensions[CSS_HEIGHT] = 300;
-        node_1 = node_0->get_child(node_0->context, 1);
-        node_1->style.dimensions[CSS_WIDTH] = 200;
-        node_1->style.dimensions[CSS_HEIGHT] = 300;
-      }
-    }
-
-    css_node_t *root_layout = new_test_css_node();
-    {
-      css_node_t *node_0 = root_layout;
-      node_0->layout.position[CSS_TOP] = 0;
-      node_0->layout.position[CSS_LEFT] = 0;
-      node_0->layout.dimensions[CSS_WIDTH] = 200;
-      node_0->layout.dimensions[CSS_HEIGHT] = 600;
-      init_css_node_children(node_0, 2);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->layout.position[CSS_TOP] = 0;
-        node_1->layout.position[CSS_LEFT] = 0;
-        node_1->layout.dimensions[CSS_WIDTH] = 200;
-        node_1->layout.dimensions[CSS_HEIGHT] = 300;
-        node_1 = node_0->get_child(node_0->context, 1);
-        node_1->layout.position[CSS_TOP] = 300;
-        node_1->layout.position[CSS_LEFT] = 0;
-        node_1->layout.dimensions[CSS_WIDTH] = 200;
-        node_1->layout.dimensions[CSS_HEIGHT] = 300;
-      }
-    }
-
-    test("should set parents size based on bounded children", root_node, root_layout);
-  }
-
-  {
-    css_node_t *root_node = new_test_css_node();
-    {
-      css_node_t *node_0 = root_node;
-      node_0->style.maxDimensions[CSS_WIDTH] = 100;
-      node_0->style.maxDimensions[CSS_HEIGHT] = 500;
-      init_css_node_children(node_0, 2);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->style.dimensions[CSS_WIDTH] = 200;
-        node_1->style.dimensions[CSS_HEIGHT] = 300;
-        node_1 = node_0->get_child(node_0->context, 1);
-        node_1->style.dimensions[CSS_WIDTH] = 200;
-        node_1->style.dimensions[CSS_HEIGHT] = 300;
-      }
-    }
-
-    css_node_t *root_layout = new_test_css_node();
-    {
-      css_node_t *node_0 = root_layout;
-      node_0->layout.position[CSS_TOP] = 0;
-      node_0->layout.position[CSS_LEFT] = 0;
-      node_0->layout.dimensions[CSS_WIDTH] = 100;
-      node_0->layout.dimensions[CSS_HEIGHT] = 500;
-      init_css_node_children(node_0, 2);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->layout.position[CSS_TOP] = 0;
-        node_1->layout.position[CSS_LEFT] = 0;
-        node_1->layout.dimensions[CSS_WIDTH] = 200;
-        node_1->layout.dimensions[CSS_HEIGHT] = 300;
-        node_1 = node_0->get_child(node_0->context, 1);
-        node_1->layout.position[CSS_TOP] = 300;
-        node_1->layout.position[CSS_LEFT] = 0;
-        node_1->layout.dimensions[CSS_WIDTH] = 200;
-        node_1->layout.dimensions[CSS_HEIGHT] = 300;
-      }
-    }
-
-    test("should set parents size based on max bounded children", root_node, root_layout);
-  }
-
-  {
-    css_node_t *root_node = new_test_css_node();
-    {
-      css_node_t *node_0 = root_node;
-      node_0->style.minDimensions[CSS_WIDTH] = 300;
-      node_0->style.minDimensions[CSS_HEIGHT] = 700;
-      init_css_node_children(node_0, 2);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->style.dimensions[CSS_WIDTH] = 200;
-        node_1->style.dimensions[CSS_HEIGHT] = 300;
-        node_1 = node_0->get_child(node_0->context, 1);
-        node_1->style.dimensions[CSS_WIDTH] = 200;
-        node_1->style.dimensions[CSS_HEIGHT] = 300;
-      }
-    }
-
-    css_node_t *root_layout = new_test_css_node();
-    {
-      css_node_t *node_0 = root_layout;
-      node_0->layout.position[CSS_TOP] = 0;
-      node_0->layout.position[CSS_LEFT] = 0;
-      node_0->layout.dimensions[CSS_WIDTH] = 300;
-      node_0->layout.dimensions[CSS_HEIGHT] = 700;
-      init_css_node_children(node_0, 2);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->layout.position[CSS_TOP] = 0;
-        node_1->layout.position[CSS_LEFT] = 0;
-        node_1->layout.dimensions[CSS_WIDTH] = 200;
-        node_1->layout.dimensions[CSS_HEIGHT] = 300;
-        node_1 = node_0->get_child(node_0->context, 1);
-        node_1->layout.position[CSS_TOP] = 300;
-        node_1->layout.position[CSS_LEFT] = 0;
-        node_1->layout.dimensions[CSS_WIDTH] = 200;
-        node_1->layout.dimensions[CSS_HEIGHT] = 300;
-      }
-    }
-
-    test("should set parents size based on min bounded children", root_node, root_layout);
-  }
-
-  {
-    css_node_t *root_node = new_test_css_node();
-    {
-      css_node_t *node_0 = root_node;
-      node_0->style.align_items = CSS_ALIGN_STRETCH;
-      node_0->style.dimensions[CSS_WIDTH] = 1000;
-      init_css_node_children(node_0, 1);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->style.dimensions[CSS_HEIGHT] = 100;
-        node_1->style.maxDimensions[CSS_WIDTH] = 1100;
-        node_1->style.maxDimensions[CSS_HEIGHT] = 110;
-        node_1->style.minDimensions[CSS_WIDTH] = 900;
-        node_1->style.minDimensions[CSS_HEIGHT] = 90;
-      }
-    }
-
-    css_node_t *root_layout = new_test_css_node();
-    {
-      css_node_t *node_0 = root_layout;
-      node_0->layout.position[CSS_TOP] = 0;
-      node_0->layout.position[CSS_LEFT] = 0;
-      node_0->layout.dimensions[CSS_WIDTH] = 1000;
-      node_0->layout.dimensions[CSS_HEIGHT] = 100;
-      init_css_node_children(node_0, 1);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->layout.position[CSS_TOP] = 0;
-        node_1->layout.position[CSS_LEFT] = 0;
-        node_1->layout.dimensions[CSS_WIDTH] = 1000;
-        node_1->layout.dimensions[CSS_HEIGHT] = 100;
-      }
-    }
-
-    test("should keep stretched size within bounds", root_node, root_layout);
-  }
-
-  {
-    css_node_t *root_node = new_test_css_node();
-    {
-      css_node_t *node_0 = root_node;
-      node_0->style.align_items = CSS_ALIGN_STRETCH;
-      node_0->style.dimensions[CSS_WIDTH] = 1000;
-      init_css_node_children(node_0, 1);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->style.dimensions[CSS_HEIGHT] = 100;
-        node_1->style.maxDimensions[CSS_WIDTH] = 900;
-        node_1->style.maxDimensions[CSS_HEIGHT] = 90;
-      }
-    }
-
-    css_node_t *root_layout = new_test_css_node();
-    {
-      css_node_t *node_0 = root_layout;
-      node_0->layout.position[CSS_TOP] = 0;
-      node_0->layout.position[CSS_LEFT] = 0;
-      node_0->layout.dimensions[CSS_WIDTH] = 1000;
-      node_0->layout.dimensions[CSS_HEIGHT] = 90;
-      init_css_node_children(node_0, 1);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->layout.position[CSS_TOP] = 0;
-        node_1->layout.position[CSS_LEFT] = 0;
-        node_1->layout.dimensions[CSS_WIDTH] = 900;
-        node_1->layout.dimensions[CSS_HEIGHT] = 90;
-      }
-    }
-
-    test("should keep stretched size within max bounds", root_node, root_layout);
-  }
-
-  {
-    css_node_t *root_node = new_test_css_node();
-    {
-      css_node_t *node_0 = root_node;
-      node_0->style.align_items = CSS_ALIGN_STRETCH;
-      node_0->style.dimensions[CSS_WIDTH] = 1000;
-      init_css_node_children(node_0, 1);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->style.dimensions[CSS_HEIGHT] = 100;
-        node_1->style.minDimensions[CSS_WIDTH] = 1100;
-        node_1->style.minDimensions[CSS_HEIGHT] = 110;
-      }
-    }
-
-    css_node_t *root_layout = new_test_css_node();
-    {
-      css_node_t *node_0 = root_layout;
-      node_0->layout.position[CSS_TOP] = 0;
-      node_0->layout.position[CSS_LEFT] = 0;
-      node_0->layout.dimensions[CSS_WIDTH] = 1000;
-      node_0->layout.dimensions[CSS_HEIGHT] = 110;
-      init_css_node_children(node_0, 1);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->layout.position[CSS_TOP] = 0;
-        node_1->layout.position[CSS_LEFT] = 0;
-        node_1->layout.dimensions[CSS_WIDTH] = 1100;
-        node_1->layout.dimensions[CSS_HEIGHT] = 110;
-      }
-    }
-
-    test("should keep stretched size within min bounds", root_node, root_layout);
-  }
-
-  {
-    css_node_t *root_node = new_test_css_node();
-    {
-      css_node_t *node_0 = root_node;
-      node_0->style.flex_direction = CSS_FLEX_DIRECTION_ROW;
-      node_0->style.dimensions[CSS_WIDTH] = 1000;
-      init_css_node_children(node_0, 1);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->style.dimensions[CSS_HEIGHT] = 100;
-        node_1->style.minDimensions[CSS_WIDTH] = 100;
-        node_1->style.minDimensions[CSS_HEIGHT] = 110;
-      }
-    }
-
-    css_node_t *root_layout = new_test_css_node();
-    {
-      css_node_t *node_0 = root_layout;
-      node_0->layout.position[CSS_TOP] = 0;
-      node_0->layout.position[CSS_LEFT] = 0;
-      node_0->layout.dimensions[CSS_WIDTH] = 1000;
-      node_0->layout.dimensions[CSS_HEIGHT] = 110;
-      init_css_node_children(node_0, 1);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->layout.position[CSS_TOP] = 0;
-        node_1->layout.position[CSS_LEFT] = 0;
-        node_1->layout.dimensions[CSS_WIDTH] = 100;
-        node_1->layout.dimensions[CSS_HEIGHT] = 110;
-      }
-    }
-
-    test("should keep cross axis size within min bounds", root_node, root_layout);
-  }
-
-  {
-    css_node_t *root_node = new_test_css_node();
-    {
-      css_node_t *node_0 = root_node;
-      node_0->style.direction = CSS_DIRECTION_RTL;
-      node_0->style.flex_direction = CSS_FLEX_DIRECTION_ROW;
-      node_0->style.dimensions[CSS_WIDTH] = 1000;
-      init_css_node_children(node_0, 1);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->style.dimensions[CSS_HEIGHT] = 100;
-        node_1->style.minDimensions[CSS_WIDTH] = 100;
-        node_1->style.minDimensions[CSS_HEIGHT] = 110;
-      }
-    }
-
-    css_node_t *root_layout = new_test_css_node();
-    {
-      css_node_t *node_0 = root_layout;
-      node_0->layout.position[CSS_TOP] = 0;
-      node_0->layout.position[CSS_LEFT] = 0;
-      node_0->layout.dimensions[CSS_WIDTH] = 1000;
-      node_0->layout.dimensions[CSS_HEIGHT] = 110;
-      init_css_node_children(node_0, 1);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->layout.position[CSS_TOP] = 0;
-        node_1->layout.position[CSS_LEFT] = 900;
-        node_1->layout.dimensions[CSS_WIDTH] = 100;
-        node_1->layout.dimensions[CSS_HEIGHT] = 110;
-      }
-    }
-
-    test("should keep cross axis size within min bounds in rtl", root_node, root_layout);
-  }
-
-  {
-    css_node_t *root_node = new_test_css_node();
-    {
-      css_node_t *node_0 = root_node;
-      node_0->style.dimensions[CSS_WIDTH] = 1000;
-      node_0->style.dimensions[CSS_HEIGHT] = 1000;
-      init_css_node_children(node_0, 1);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->style.position_type = CSS_POSITION_ABSOLUTE;
-        node_1->style.maxDimensions[CSS_WIDTH] = 500;
-        node_1->style.maxDimensions[CSS_HEIGHT] = 600;
-        node_1->style.position[CSS_LEFT] = 100;
-        node_1->style.position[CSS_TOP] = 100;
-        node_1->style.position[CSS_RIGHT] = 100;
-        node_1->style.position[CSS_BOTTOM] = 100;
-      }
-    }
-
-    css_node_t *root_layout = new_test_css_node();
-    {
-      css_node_t *node_0 = root_layout;
-      node_0->layout.position[CSS_TOP] = 0;
-      node_0->layout.position[CSS_LEFT] = 0;
-      node_0->layout.dimensions[CSS_WIDTH] = 1000;
-      node_0->layout.dimensions[CSS_HEIGHT] = 1000;
-      init_css_node_children(node_0, 1);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->layout.position[CSS_TOP] = 100;
-        node_1->layout.position[CSS_LEFT] = 100;
-        node_1->layout.dimensions[CSS_WIDTH] = 500;
-        node_1->layout.dimensions[CSS_HEIGHT] = 600;
-      }
-    }
-
-    test("should layout node with position absolute, top and left and max bounds", root_node, root_layout);
-  }
-
-  {
-    css_node_t *root_node = new_test_css_node();
-    {
-      css_node_t *node_0 = root_node;
-      node_0->style.dimensions[CSS_WIDTH] = 1000;
-      node_0->style.dimensions[CSS_HEIGHT] = 1000;
-      init_css_node_children(node_0, 1);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->style.position_type = CSS_POSITION_ABSOLUTE;
-        node_1->style.minDimensions[CSS_WIDTH] = 900;
-        node_1->style.minDimensions[CSS_HEIGHT] = 1000;
-        node_1->style.position[CSS_LEFT] = 100;
-        node_1->style.position[CSS_TOP] = 100;
-        node_1->style.position[CSS_RIGHT] = 100;
-        node_1->style.position[CSS_BOTTOM] = 100;
-      }
-    }
-
-    css_node_t *root_layout = new_test_css_node();
-    {
-      css_node_t *node_0 = root_layout;
-      node_0->layout.position[CSS_TOP] = 0;
-      node_0->layout.position[CSS_LEFT] = 0;
-      node_0->layout.dimensions[CSS_WIDTH] = 1000;
-      node_0->layout.dimensions[CSS_HEIGHT] = 1000;
-      init_css_node_children(node_0, 1);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->layout.position[CSS_TOP] = 100;
-        node_1->layout.position[CSS_LEFT] = 100;
-        node_1->layout.dimensions[CSS_WIDTH] = 900;
-        node_1->layout.dimensions[CSS_HEIGHT] = 1000;
-      }
-    }
-
-    test("should layout node with position absolute, top and left and min bounds", root_node, root_layout);
-  }
-
-  {
-    css_node_t *root_node = new_test_css_node();
-    {
-      css_node_t *node_0 = root_node;
-      node_0->style.dimensions[CSS_WIDTH] = 400;
-      node_0->style.dimensions[CSS_HEIGHT] = 400;
-      init_css_node_children(node_0, 1);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->style.position_type = CSS_POSITION_ABSOLUTE;
-        node_1->style.padding[CSS_LEFT] = 10;
-        node_1->style.padding[CSS_TOP] = 10;
-        node_1->style.padding[CSS_RIGHT] = 10;
-        node_1->style.padding[CSS_BOTTOM] = 10;
-        node_1->style.padding[CSS_START] = 10;
-        node_1->style.padding[CSS_END] = 10;
-        node_1->style.position[CSS_LEFT] = 100;
-        node_1->style.position[CSS_TOP] = 100;
-        node_1->style.position[CSS_RIGHT] = 100;
-        node_1->style.position[CSS_BOTTOM] = 100;
-        init_css_node_children(node_1, 1);
-        {
-          css_node_t *node_2;
-          node_2 = node_1->get_child(node_1->context, 0);
-          node_2->style.position_type = CSS_POSITION_ABSOLUTE;
-          node_2->style.position[CSS_LEFT] = 10;
-          node_2->style.position[CSS_TOP] = 10;
-          node_2->style.position[CSS_RIGHT] = 10;
-          node_2->style.position[CSS_BOTTOM] = 10;
-        }
-      }
-    }
-
-    css_node_t *root_layout = new_test_css_node();
-    {
-      css_node_t *node_0 = root_layout;
-      node_0->layout.position[CSS_TOP] = 0;
-      node_0->layout.position[CSS_LEFT] = 0;
-      node_0->layout.dimensions[CSS_WIDTH] = 400;
-      node_0->layout.dimensions[CSS_HEIGHT] = 400;
-      init_css_node_children(node_0, 1);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->layout.position[CSS_TOP] = 100;
-        node_1->layout.position[CSS_LEFT] = 100;
-        node_1->layout.dimensions[CSS_WIDTH] = 200;
-        node_1->layout.dimensions[CSS_HEIGHT] = 200;
-        init_css_node_children(node_1, 1);
-        {
-          css_node_t *node_2;
-          node_2 = node_1->get_child(node_1->context, 0);
-          node_2->layout.position[CSS_TOP] = 10;
-          node_2->layout.position[CSS_LEFT] = 10;
-          node_2->layout.dimensions[CSS_WIDTH] = 180;
-          node_2->layout.dimensions[CSS_HEIGHT] = 180;
-        }
-      }
-    }
-
-    test("should layout absolutely positioned node with absolutely positioned padded parent", root_node, root_layout);
-  }
-
-  {
-    css_node_t *root_node = new_test_css_node();
-    {
-      css_node_t *node_0 = root_node;
-      node_0->style.dimensions[CSS_WIDTH] = 400;
-      node_0->style.dimensions[CSS_HEIGHT] = 400;
-      init_css_node_children(node_0, 1);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->style.position_type = CSS_POSITION_ABSOLUTE;
-        node_1->style.padding[CSS_LEFT] = 10;
-        node_1->style.padding[CSS_TOP] = 10;
-        node_1->style.padding[CSS_RIGHT] = 10;
-        node_1->style.padding[CSS_BOTTOM] = 10;
-        node_1->style.padding[CSS_START] = 10;
-        node_1->style.padding[CSS_END] = 10;
-        node_1->style.border[CSS_LEFT] = 1;
-        node_1->style.border[CSS_TOP] = 1;
-        node_1->style.border[CSS_RIGHT] = 1;
-        node_1->style.border[CSS_BOTTOM] = 1;
-        node_1->style.border[CSS_START] = 1;
-        node_1->style.border[CSS_END] = 1;
-        node_1->style.position[CSS_LEFT] = 100;
-        node_1->style.position[CSS_TOP] = 100;
-        node_1->style.position[CSS_RIGHT] = 100;
-        node_1->style.position[CSS_BOTTOM] = 100;
-        init_css_node_children(node_1, 1);
-        {
-          css_node_t *node_2;
-          node_2 = node_1->get_child(node_1->context, 0);
-          node_2->style.position_type = CSS_POSITION_ABSOLUTE;
-          node_2->style.position[CSS_LEFT] = 10;
-          node_2->style.position[CSS_TOP] = 10;
-          node_2->style.position[CSS_RIGHT] = 10;
-          node_2->style.position[CSS_BOTTOM] = 10;
-        }
-      }
-    }
-
-    css_node_t *root_layout = new_test_css_node();
-    {
-      css_node_t *node_0 = root_layout;
-      node_0->layout.position[CSS_TOP] = 0;
-      node_0->layout.position[CSS_LEFT] = 0;
-      node_0->layout.dimensions[CSS_WIDTH] = 400;
-      node_0->layout.dimensions[CSS_HEIGHT] = 400;
-      init_css_node_children(node_0, 1);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->layout.position[CSS_TOP] = 100;
-        node_1->layout.position[CSS_LEFT] = 100;
-        node_1->layout.dimensions[CSS_WIDTH] = 200;
-        node_1->layout.dimensions[CSS_HEIGHT] = 200;
-        init_css_node_children(node_1, 1);
-        {
-          css_node_t *node_2;
-          node_2 = node_1->get_child(node_1->context, 0);
-          node_2->layout.position[CSS_TOP] = 11;
-          node_2->layout.position[CSS_LEFT] = 11;
-          node_2->layout.dimensions[CSS_WIDTH] = 178;
-          node_2->layout.dimensions[CSS_HEIGHT] = 178;
-        }
-      }
-    }
-
-    test("should layout absolutely positioned node with absolutely positioned padded and bordered parent", root_node, root_layout);
-  }
-
-  {
-    css_node_t *root_node = new_test_css_node();
-    {
-      css_node_t *node_0 = root_node;
-      node_0->style.dimensions[CSS_WIDTH] = 400;
-      node_0->style.dimensions[CSS_HEIGHT] = 400;
-      init_css_node_children(node_0, 1);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->style.flex = 1;
-        node_1->style.padding[CSS_LEFT] = 10;
-        node_1->style.padding[CSS_TOP] = 10;
-        node_1->style.padding[CSS_RIGHT] = 10;
-        node_1->style.padding[CSS_BOTTOM] = 10;
-        node_1->style.padding[CSS_START] = 10;
-        node_1->style.padding[CSS_END] = 10;
-        init_css_node_children(node_1, 1);
-        {
-          css_node_t *node_2;
-          node_2 = node_1->get_child(node_1->context, 0);
-          node_2->style.position_type = CSS_POSITION_ABSOLUTE;
-          node_2->style.position[CSS_LEFT] = 10;
-          node_2->style.position[CSS_TOP] = 10;
-          node_2->style.position[CSS_RIGHT] = 10;
-          node_2->style.position[CSS_BOTTOM] = 10;
-        }
-      }
-    }
-
-    css_node_t *root_layout = new_test_css_node();
-    {
-      css_node_t *node_0 = root_layout;
-      node_0->layout.position[CSS_TOP] = 0;
-      node_0->layout.position[CSS_LEFT] = 0;
-      node_0->layout.dimensions[CSS_WIDTH] = 400;
-      node_0->layout.dimensions[CSS_HEIGHT] = 400;
-      init_css_node_children(node_0, 1);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->layout.position[CSS_TOP] = 0;
-        node_1->layout.position[CSS_LEFT] = 0;
-        node_1->layout.dimensions[CSS_WIDTH] = 400;
-        node_1->layout.dimensions[CSS_HEIGHT] = 400;
-        init_css_node_children(node_1, 1);
-        {
-          css_node_t *node_2;
-          node_2 = node_1->get_child(node_1->context, 0);
-          node_2->layout.position[CSS_TOP] = 10;
-          node_2->layout.position[CSS_LEFT] = 10;
-          node_2->layout.dimensions[CSS_WIDTH] = 380;
-          node_2->layout.dimensions[CSS_HEIGHT] = 380;
-        }
-      }
-    }
-
-    test("should layout absolutely positioned node with padded flex 1 parent", root_node, root_layout);
-  }
-
-  {
-    css_node_t *root_node = new_test_css_node();
-    {
-      css_node_t *node_0 = root_node;
-      node_0->style.direction = CSS_DIRECTION_RTL;
-      node_0->style.dimensions[CSS_WIDTH] = 200;
-      node_0->style.dimensions[CSS_HEIGHT] = 200;
-      init_css_node_children(node_0, 2);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->style.flex_direction = CSS_FLEX_DIRECTION_ROW;
-        init_css_node_children(node_1, 2);
-        {
-          css_node_t *node_2;
-          node_2 = node_1->get_child(node_1->context, 0);
-          node_2->style.dimensions[CSS_WIDTH] = 50;
-          node_2->style.dimensions[CSS_HEIGHT] = 50;
-          node_2 = node_1->get_child(node_1->context, 1);
-          node_2->style.dimensions[CSS_WIDTH] = 50;
-          node_2->style.dimensions[CSS_HEIGHT] = 50;
-        }
-        node_1 = node_0->get_child(node_0->context, 1);
-        node_1->style.direction = CSS_DIRECTION_LTR;
-        node_1->style.flex_direction = CSS_FLEX_DIRECTION_ROW;
-        init_css_node_children(node_1, 2);
-        {
-          css_node_t *node_2;
-          node_2 = node_1->get_child(node_1->context, 0);
-          node_2->style.dimensions[CSS_WIDTH] = 50;
-          node_2->style.dimensions[CSS_HEIGHT] = 50;
-          node_2 = node_1->get_child(node_1->context, 1);
-          node_2->style.dimensions[CSS_WIDTH] = 50;
-          node_2->style.dimensions[CSS_HEIGHT] = 50;
-        }
-      }
-    }
-
-    css_node_t *root_layout = new_test_css_node();
-    {
-      css_node_t *node_0 = root_layout;
-      node_0->layout.position[CSS_TOP] = 0;
-      node_0->layout.position[CSS_LEFT] = 0;
-      node_0->layout.dimensions[CSS_WIDTH] = 200;
-      node_0->layout.dimensions[CSS_HEIGHT] = 200;
-      init_css_node_children(node_0, 2);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->layout.position[CSS_TOP] = 0;
-        node_1->layout.position[CSS_LEFT] = 0;
-        node_1->layout.dimensions[CSS_WIDTH] = 200;
-        node_1->layout.dimensions[CSS_HEIGHT] = 50;
-        init_css_node_children(node_1, 2);
-        {
-          css_node_t *node_2;
-          node_2 = node_1->get_child(node_1->context, 0);
-          node_2->layout.position[CSS_TOP] = 0;
-          node_2->layout.position[CSS_LEFT] = 150;
-          node_2->layout.dimensions[CSS_WIDTH] = 50;
-          node_2->layout.dimensions[CSS_HEIGHT] = 50;
-          node_2 = node_1->get_child(node_1->context, 1);
-          node_2->layout.position[CSS_TOP] = 0;
-          node_2->layout.position[CSS_LEFT] = 100;
-          node_2->layout.dimensions[CSS_WIDTH] = 50;
-          node_2->layout.dimensions[CSS_HEIGHT] = 50;
-        }
-        node_1 = node_0->get_child(node_0->context, 1);
-        node_1->layout.position[CSS_TOP] = 50;
-        node_1->layout.position[CSS_LEFT] = 0;
-        node_1->layout.dimensions[CSS_WIDTH] = 200;
-        node_1->layout.dimensions[CSS_HEIGHT] = 50;
-        init_css_node_children(node_1, 2);
-        {
-          css_node_t *node_2;
-          node_2 = node_1->get_child(node_1->context, 0);
-          node_2->layout.position[CSS_TOP] = 0;
-          node_2->layout.position[CSS_LEFT] = 0;
-          node_2->layout.dimensions[CSS_WIDTH] = 50;
-          node_2->layout.dimensions[CSS_HEIGHT] = 50;
-          node_2 = node_1->get_child(node_1->context, 1);
-          node_2->layout.position[CSS_TOP] = 0;
-          node_2->layout.position[CSS_LEFT] = 50;
-          node_2->layout.dimensions[CSS_WIDTH] = 50;
-          node_2->layout.dimensions[CSS_HEIGHT] = 50;
-        }
-      }
-    }
-
-    test("should layout nested nodes with mixed directions", root_node, root_layout);
-  }
-
-  {
-    css_node_t *root_node = new_test_css_node();
-    {
-      css_node_t *node_0 = root_node;
-      node_0->style.flex_direction = CSS_FLEX_DIRECTION_ROW;
-      node_0->style.justify_content = CSS_JUSTIFY_SPACE_BETWEEN;
-      node_0->style.flex_wrap = CSS_WRAP;
-      node_0->style.dimensions[CSS_WIDTH] = 320;
-      node_0->style.dimensions[CSS_HEIGHT] = 200;
-      init_css_node_children(node_0, 6);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->style.dimensions[CSS_WIDTH] = 100;
-        node_1->style.dimensions[CSS_HEIGHT] = 100;
-        node_1 = node_0->get_child(node_0->context, 1);
-        node_1->style.dimensions[CSS_WIDTH] = 100;
-        node_1->style.dimensions[CSS_HEIGHT] = 100;
-        node_1 = node_0->get_child(node_0->context, 2);
-        node_1->style.dimensions[CSS_WIDTH] = 100;
-        node_1->style.dimensions[CSS_HEIGHT] = 100;
-        node_1 = node_0->get_child(node_0->context, 3);
-        node_1->style.dimensions[CSS_WIDTH] = 100;
-        node_1->style.dimensions[CSS_HEIGHT] = 100;
-        node_1 = node_0->get_child(node_0->context, 4);
-        node_1->style.dimensions[CSS_WIDTH] = 100;
-        node_1->style.dimensions[CSS_HEIGHT] = 100;
-        node_1 = node_0->get_child(node_0->context, 5);
-        node_1->style.dimensions[CSS_WIDTH] = 100;
-        node_1->style.dimensions[CSS_HEIGHT] = 100;
-      }
-    }
-
-    css_node_t *root_layout = new_test_css_node();
-    {
-      css_node_t *node_0 = root_layout;
-      node_0->layout.position[CSS_TOP] = 0;
-      node_0->layout.position[CSS_LEFT] = 0;
-      node_0->layout.dimensions[CSS_WIDTH] = 320;
-      node_0->layout.dimensions[CSS_HEIGHT] = 200;
-      init_css_node_children(node_0, 6);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->layout.position[CSS_TOP] = 0;
-        node_1->layout.position[CSS_LEFT] = 0;
-        node_1->layout.dimensions[CSS_WIDTH] = 100;
-        node_1->layout.dimensions[CSS_HEIGHT] = 100;
-        node_1 = node_0->get_child(node_0->context, 1);
-        node_1->layout.position[CSS_TOP] = 0;
-        node_1->layout.position[CSS_LEFT] = 110;
-        node_1->layout.dimensions[CSS_WIDTH] = 100;
-        node_1->layout.dimensions[CSS_HEIGHT] = 100;
-        node_1 = node_0->get_child(node_0->context, 2);
-        node_1->layout.position[CSS_TOP] = 0;
-        node_1->layout.position[CSS_LEFT] = 220;
-        node_1->layout.dimensions[CSS_WIDTH] = 100;
-        node_1->layout.dimensions[CSS_HEIGHT] = 100;
-        node_1 = node_0->get_child(node_0->context, 3);
-        node_1->layout.position[CSS_TOP] = 100;
-        node_1->layout.position[CSS_LEFT] = 0;
-        node_1->layout.dimensions[CSS_WIDTH] = 100;
-        node_1->layout.dimensions[CSS_HEIGHT] = 100;
-        node_1 = node_0->get_child(node_0->context, 4);
-        node_1->layout.position[CSS_TOP] = 100;
-        node_1->layout.position[CSS_LEFT] = 110;
-        node_1->layout.dimensions[CSS_WIDTH] = 100;
-        node_1->layout.dimensions[CSS_HEIGHT] = 100;
-        node_1 = node_0->get_child(node_0->context, 5);
-        node_1->layout.position[CSS_TOP] = 100;
-        node_1->layout.position[CSS_LEFT] = 220;
-        node_1->layout.dimensions[CSS_WIDTH] = 100;
-        node_1->layout.dimensions[CSS_HEIGHT] = 100;
-      }
-    }
-
-    test("should correctly space wrapped nodes", root_node, root_layout);
-  }
-
-  {
-    css_node_t *root_node = new_test_css_node();
-    {
-      css_node_t *node_0 = root_node;
-      node_0->style.dimensions[CSS_WIDTH] = 200;
-      node_0->style.padding[CSS_LEFT] = 5;
-      node_0->style.padding[CSS_RIGHT] = 5;
-      node_0->style.padding[CSS_START] = 15;
-      node_0->style.padding[CSS_END] = 15;
-      init_css_node_children(node_0, 1);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->style.dimensions[CSS_HEIGHT] = 50;
-      }
-    }
-
-    css_node_t *root_layout = new_test_css_node();
-    {
-      css_node_t *node_0 = root_layout;
-      node_0->layout.position[CSS_TOP] = 0;
-      node_0->layout.position[CSS_LEFT] = 0;
-      node_0->layout.dimensions[CSS_WIDTH] = 200;
-      node_0->layout.dimensions[CSS_HEIGHT] = 50;
-      init_css_node_children(node_0, 1);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->layout.position[CSS_TOP] = 0;
-        node_1->layout.position[CSS_LEFT] = 15;
-        node_1->layout.dimensions[CSS_WIDTH] = 170;
-        node_1->layout.dimensions[CSS_HEIGHT] = 50;
-      }
-    }
-
-    test("should give start/end padding precedence over left/right padding", root_node, root_layout);
-  }
-
-  {
-    css_node_t *root_node = new_test_css_node();
-    {
-      css_node_t *node_0 = root_node;
-      node_0->style.dimensions[CSS_WIDTH] = 200;
-      init_css_node_children(node_0, 1);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->style.dimensions[CSS_HEIGHT] = 50;
-        node_1->style.margin[CSS_LEFT] = 5;
-        node_1->style.margin[CSS_RIGHT] = 5;
-        node_1->style.margin[CSS_START] = 15;
-        node_1->style.margin[CSS_END] = 15;
-      }
-    }
-
-    css_node_t *root_layout = new_test_css_node();
-    {
-      css_node_t *node_0 = root_layout;
-      node_0->layout.position[CSS_TOP] = 0;
-      node_0->layout.position[CSS_LEFT] = 0;
-      node_0->layout.dimensions[CSS_WIDTH] = 200;
-      node_0->layout.dimensions[CSS_HEIGHT] = 50;
-      init_css_node_children(node_0, 1);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->layout.position[CSS_TOP] = 0;
-        node_1->layout.position[CSS_LEFT] = 15;
-        node_1->layout.dimensions[CSS_WIDTH] = 170;
-        node_1->layout.dimensions[CSS_HEIGHT] = 50;
-      }
-    }
-
-    test("should give start/end margin precedence over left/right margin", root_node, root_layout);
-  }
-
-  {
-    css_node_t *root_node = new_test_css_node();
-    {
-      css_node_t *node_0 = root_node;
-      node_0->style.dimensions[CSS_WIDTH] = 200;
-      node_0->style.border[CSS_LEFT] = 5;
-      node_0->style.border[CSS_RIGHT] = 5;
-      node_0->style.border[CSS_START] = 15;
-      node_0->style.border[CSS_END] = 15;
-      init_css_node_children(node_0, 1);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->style.dimensions[CSS_HEIGHT] = 50;
-      }
-    }
-
-    css_node_t *root_layout = new_test_css_node();
-    {
-      css_node_t *node_0 = root_layout;
-      node_0->layout.position[CSS_TOP] = 0;
-      node_0->layout.position[CSS_LEFT] = 0;
-      node_0->layout.dimensions[CSS_WIDTH] = 200;
-      node_0->layout.dimensions[CSS_HEIGHT] = 50;
-      init_css_node_children(node_0, 1);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->layout.position[CSS_TOP] = 0;
-        node_1->layout.position[CSS_LEFT] = 15;
-        node_1->layout.dimensions[CSS_WIDTH] = 170;
-        node_1->layout.dimensions[CSS_HEIGHT] = 50;
-      }
-    }
-
-    test("should give start/end border precedence over left/right border", root_node, root_layout);
-  }
-
-  {
-    css_node_t *root_node = new_test_css_node();
-    {
-      css_node_t *node_0 = root_node;
-      node_0->style.dimensions[CSS_WIDTH] = 200;
-      node_0->style.padding[CSS_START] = 15;
-      node_0->style.padding[CSS_END] = 5;
-      init_css_node_children(node_0, 1);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->style.dimensions[CSS_HEIGHT] = 50;
-      }
-    }
-
-    css_node_t *root_layout = new_test_css_node();
-    {
-      css_node_t *node_0 = root_layout;
-      node_0->layout.position[CSS_TOP] = 0;
-      node_0->layout.position[CSS_LEFT] = 0;
-      node_0->layout.dimensions[CSS_WIDTH] = 200;
-      node_0->layout.dimensions[CSS_HEIGHT] = 50;
-      init_css_node_children(node_0, 1);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->layout.position[CSS_TOP] = 0;
-        node_1->layout.position[CSS_LEFT] = 15;
-        node_1->layout.dimensions[CSS_WIDTH] = 180;
-        node_1->layout.dimensions[CSS_HEIGHT] = 50;
-      }
-    }
-
-    test("should layout node with correct start/end padding", root_node, root_layout);
-  }
-
-  {
-    css_node_t *root_node = new_test_css_node();
-    {
-      css_node_t *node_0 = root_node;
-      node_0->style.direction = CSS_DIRECTION_RTL;
-      node_0->style.dimensions[CSS_WIDTH] = 200;
-      node_0->style.padding[CSS_START] = 15;
-      node_0->style.padding[CSS_END] = 5;
-      init_css_node_children(node_0, 1);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->style.dimensions[CSS_HEIGHT] = 50;
-      }
-    }
-
-    css_node_t *root_layout = new_test_css_node();
-    {
-      css_node_t *node_0 = root_layout;
-      node_0->layout.position[CSS_TOP] = 0;
-      node_0->layout.position[CSS_LEFT] = 0;
-      node_0->layout.dimensions[CSS_WIDTH] = 200;
-      node_0->layout.dimensions[CSS_HEIGHT] = 50;
-      init_css_node_children(node_0, 1);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->layout.position[CSS_TOP] = 0;
-        node_1->layout.position[CSS_LEFT] = 5;
-        node_1->layout.dimensions[CSS_WIDTH] = 180;
-        node_1->layout.dimensions[CSS_HEIGHT] = 50;
-      }
-    }
-
-    test("should layout node with correct start/end padding in rtl", root_node, root_layout);
-  }
-
-  {
-    css_node_t *root_node = new_test_css_node();
-    {
-      css_node_t *node_0 = root_node;
-      node_0->style.dimensions[CSS_WIDTH] = 200;
-      init_css_node_children(node_0, 1);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->style.dimensions[CSS_HEIGHT] = 50;
-        node_1->style.margin[CSS_START] = 15;
-        node_1->style.margin[CSS_END] = 5;
-      }
-    }
-
-    css_node_t *root_layout = new_test_css_node();
-    {
-      css_node_t *node_0 = root_layout;
-      node_0->layout.position[CSS_TOP] = 0;
-      node_0->layout.position[CSS_LEFT] = 0;
-      node_0->layout.dimensions[CSS_WIDTH] = 200;
-      node_0->layout.dimensions[CSS_HEIGHT] = 50;
-      init_css_node_children(node_0, 1);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->layout.position[CSS_TOP] = 0;
-        node_1->layout.position[CSS_LEFT] = 15;
-        node_1->layout.dimensions[CSS_WIDTH] = 180;
-        node_1->layout.dimensions[CSS_HEIGHT] = 50;
-      }
-    }
-
-    test("should layout node with correct start/end margin", root_node, root_layout);
-  }
-
-  {
-    css_node_t *root_node = new_test_css_node();
-    {
-      css_node_t *node_0 = root_node;
-      node_0->style.dimensions[CSS_WIDTH] = 200;
-      init_css_node_children(node_0, 1);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->style.direction = CSS_DIRECTION_RTL;
-        node_1->style.dimensions[CSS_HEIGHT] = 50;
-        node_1->style.margin[CSS_START] = 15;
-        node_1->style.margin[CSS_END] = 5;
-      }
-    }
-
-    css_node_t *root_layout = new_test_css_node();
-    {
-      css_node_t *node_0 = root_layout;
-      node_0->layout.position[CSS_TOP] = 0;
-      node_0->layout.position[CSS_LEFT] = 0;
-      node_0->layout.dimensions[CSS_WIDTH] = 200;
-      node_0->layout.dimensions[CSS_HEIGHT] = 50;
-      init_css_node_children(node_0, 1);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->layout.position[CSS_TOP] = 0;
-        node_1->layout.position[CSS_LEFT] = 5;
-        node_1->layout.dimensions[CSS_WIDTH] = 180;
-        node_1->layout.dimensions[CSS_HEIGHT] = 50;
-      }
-    }
-
-    test("should layout node with correct start/end margin in rtl", root_node, root_layout);
-  }
-
-  {
-    css_node_t *root_node = new_test_css_node();
-    {
-      css_node_t *node_0 = root_node;
-      node_0->style.dimensions[CSS_WIDTH] = 200;
-      node_0->style.border[CSS_START] = 15;
-      node_0->style.border[CSS_END] = 5;
-      init_css_node_children(node_0, 1);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->style.dimensions[CSS_HEIGHT] = 50;
-      }
-    }
-
-    css_node_t *root_layout = new_test_css_node();
-    {
-      css_node_t *node_0 = root_layout;
-      node_0->layout.position[CSS_TOP] = 0;
-      node_0->layout.position[CSS_LEFT] = 0;
-      node_0->layout.dimensions[CSS_WIDTH] = 200;
-      node_0->layout.dimensions[CSS_HEIGHT] = 50;
-      init_css_node_children(node_0, 1);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->layout.position[CSS_TOP] = 0;
-        node_1->layout.position[CSS_LEFT] = 15;
-        node_1->layout.dimensions[CSS_WIDTH] = 180;
-        node_1->layout.dimensions[CSS_HEIGHT] = 50;
-      }
-    }
-
-    test("should layout node with correct start/end border", root_node, root_layout);
-  }
-
-  {
-    css_node_t *root_node = new_test_css_node();
-    {
-      css_node_t *node_0 = root_node;
-      node_0->style.direction = CSS_DIRECTION_RTL;
-      node_0->style.dimensions[CSS_WIDTH] = 200;
-      node_0->style.border[CSS_START] = 15;
-      node_0->style.border[CSS_END] = 5;
-      init_css_node_children(node_0, 1);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->style.dimensions[CSS_HEIGHT] = 50;
-      }
-    }
-
-    css_node_t *root_layout = new_test_css_node();
-    {
-      css_node_t *node_0 = root_layout;
-      node_0->layout.position[CSS_TOP] = 0;
-      node_0->layout.position[CSS_LEFT] = 0;
-      node_0->layout.dimensions[CSS_WIDTH] = 200;
-      node_0->layout.dimensions[CSS_HEIGHT] = 50;
-      init_css_node_children(node_0, 1);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->layout.position[CSS_TOP] = 0;
-        node_1->layout.position[CSS_LEFT] = 5;
-        node_1->layout.dimensions[CSS_WIDTH] = 180;
-        node_1->layout.dimensions[CSS_HEIGHT] = 50;
-      }
-    }
-
-    test("should layout node with correct start/end border in rtl", root_node, root_layout);
-  }
-
-  {
-    css_node_t *root_node = new_test_css_node();
-    {
-      css_node_t *node_0 = root_node;
-      node_0->style.dimensions[CSS_WIDTH] = 200;
-      init_css_node_children(node_0, 1);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->style.dimensions[CSS_WIDTH] = 0;
-      }
-    }
-
-    css_node_t *root_layout = new_test_css_node();
-    {
-      css_node_t *node_0 = root_layout;
-      node_0->layout.position[CSS_TOP] = 0;
-      node_0->layout.position[CSS_LEFT] = 0;
-      node_0->layout.dimensions[CSS_WIDTH] = 200;
-      node_0->layout.dimensions[CSS_HEIGHT] = 0;
-      init_css_node_children(node_0, 1);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->layout.position[CSS_TOP] = 0;
-        node_1->layout.position[CSS_LEFT] = 0;
-        node_1->layout.dimensions[CSS_WIDTH] = 0;
-        node_1->layout.dimensions[CSS_HEIGHT] = 0;
-      }
-    }
-
-    test("should layout node with a 0 width", root_node, root_layout);
-  }
-
-  {
-    css_node_t *root_node = new_test_css_node();
-    {
-      css_node_t *node_0 = root_node;
-      node_0->style.flex_direction = CSS_FLEX_DIRECTION_ROW;
-      node_0->style.align_items = CSS_ALIGN_FLEX_START;
-      node_0->style.dimensions[CSS_WIDTH] = 100;
-      node_0->style.dimensions[CSS_HEIGHT] = 10;
-      init_css_node_children(node_0, 2);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->style.dimensions[CSS_WIDTH] = 50;
-        node_1->style.dimensions[CSS_HEIGHT] = 10;
-        node_1 = node_0->get_child(node_0->context, 1);
-        node_1->style.flex_direction = CSS_FLEX_DIRECTION_COLUMN;
-        node_1->style.align_items = CSS_ALIGN_FLEX_START;
-        node_1->style.flex = 1;
-        node_1->style.dimensions[CSS_HEIGHT] = 10;
-        init_css_node_children(node_1, 1);
-        {
-          css_node_t *node_2;
-          node_2 = node_1->get_child(node_1->context, 0);
-          node_2->style.flex = 1;
-          node_2->style.dimensions[CSS_HEIGHT] = 10;
-          node_2->measure = measure;
-          node_2->context = "measureWithMatchParent";
-        }
-      }
-    }
-
-    css_node_t *root_layout = new_test_css_node();
-    {
-      css_node_t *node_0 = root_layout;
-      node_0->layout.position[CSS_TOP] = 0;
-      node_0->layout.position[CSS_LEFT] = 0;
-      node_0->layout.dimensions[CSS_WIDTH] = 100;
-      node_0->layout.dimensions[CSS_HEIGHT] = 10;
-      init_css_node_children(node_0, 2);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->layout.position[CSS_TOP] = 0;
-        node_1->layout.position[CSS_LEFT] = 0;
-        node_1->layout.dimensions[CSS_WIDTH] = 50;
-        node_1->layout.dimensions[CSS_HEIGHT] = 10;
-        node_1 = node_0->get_child(node_0->context, 1);
-        node_1->layout.position[CSS_TOP] = 0;
-        node_1->layout.position[CSS_LEFT] = 50;
-        node_1->layout.dimensions[CSS_WIDTH] = 50;
-        node_1->layout.dimensions[CSS_HEIGHT] = 10;
-        init_css_node_children(node_1, 1);
-        {
-          css_node_t *node_2;
-          node_2 = node_1->get_child(node_1->context, 0);
-          node_2->layout.position[CSS_TOP] = 0;
-          node_2->layout.position[CSS_LEFT] = 0;
-          node_2->layout.dimensions[CSS_WIDTH] = 50;
-          node_2->layout.dimensions[CSS_HEIGHT] = 10;
-        }
-      }
-    }
-
-    test("should correctly progagate size contraints from flexible parents", root_node, root_layout);
-  }
-
-  {
-    css_node_t *root_node = new_test_css_node();
-    {
-      css_node_t *node_0 = root_node;
-      node_0->style.flex_direction = CSS_FLEX_DIRECTION_ROW;
-      node_0->style.align_items = CSS_ALIGN_STRETCH;
-      node_0->style.dimensions[CSS_WIDTH] = 150;
-      init_css_node_children(node_0, 2);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->style.flex_direction = CSS_FLEX_DIRECTION_ROW;
-        node_1->style.margin[CSS_LEFT] = 10;
-        node_1->style.margin[CSS_TOP] = 10;
-        init_css_node_children(node_1, 1);
-        {
-          css_node_t *node_2;
-          node_2 = node_1->get_child(node_1->context, 0);
-          node_2->style.flex_direction = CSS_FLEX_DIRECTION_ROW;
-          init_css_node_children(node_2, 1);
-          {
-            css_node_t *node_3;
-            node_3 = node_2->get_child(node_2->context, 0);
-            node_3->style.align_self = CSS_ALIGN_CENTER;
-          }
-        }
-        node_1 = node_0->get_child(node_0->context, 1);
-        node_1->style.dimensions[CSS_HEIGHT] = 150;
-      }
-    }
-
-    css_node_t *root_layout = new_test_css_node();
-    {
-      css_node_t *node_0 = root_layout;
-      node_0->layout.position[CSS_TOP] = 0;
-      node_0->layout.position[CSS_LEFT] = 0;
-      node_0->layout.dimensions[CSS_WIDTH] = 150;
-      node_0->layout.dimensions[CSS_HEIGHT] = 150;
-      init_css_node_children(node_0, 2);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->layout.position[CSS_TOP] = 10;
-        node_1->layout.position[CSS_LEFT] = 10;
-        node_1->layout.dimensions[CSS_WIDTH] = 0;
-        node_1->layout.dimensions[CSS_HEIGHT] = 140;
-        init_css_node_children(node_1, 1);
-        {
-          css_node_t *node_2;
-          node_2 = node_1->get_child(node_1->context, 0);
-          node_2->layout.position[CSS_TOP] = 0;
-          node_2->layout.position[CSS_LEFT] = 0;
-          node_2->layout.dimensions[CSS_WIDTH] = 0;
-          node_2->layout.dimensions[CSS_HEIGHT] = 140;
-          init_css_node_children(node_2, 1);
-          {
-            css_node_t *node_3;
-            node_3 = node_2->get_child(node_2->context, 0);
-            node_3->layout.position[CSS_TOP] = 70;
-            node_3->layout.position[CSS_LEFT] = 0;
-            node_3->layout.dimensions[CSS_WIDTH] = 0;
-            node_3->layout.dimensions[CSS_HEIGHT] = 0;
-          }
-        }
-        node_1 = node_0->get_child(node_0->context, 1);
-        node_1->layout.position[CSS_TOP] = 0;
-        node_1->layout.position[CSS_LEFT] = 10;
-        node_1->layout.dimensions[CSS_WIDTH] = 0;
-        node_1->layout.dimensions[CSS_HEIGHT] = 150;
-      }
-    }
-
-    test("should layout content of an item which is stretched late", root_node, root_layout);
-  }
-
-  {
-    css_node_t *root_node = new_test_css_node();
-    {
-      css_node_t *node_0 = root_node;
-      init_css_node_children(node_0, 2);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        init_css_node_children(node_1, 1);
-        {
-          css_node_t *node_2;
-          node_2 = node_1->get_child(node_1->context, 0);
-          node_2->style.dimensions[CSS_WIDTH] = 200;
-          node_2->style.dimensions[CSS_HEIGHT] = 200;
-        }
-        node_1 = node_0->get_child(node_0->context, 1);
-        node_1->style.margin[CSS_LEFT] = 10;
-        node_1->style.margin[CSS_TOP] = 10;
-        init_css_node_children(node_1, 1);
-        {
-          css_node_t *node_2;
-          node_2 = node_1->get_child(node_1->context, 0);
-        }
-      }
-    }
-
-    css_node_t *root_layout = new_test_css_node();
-    {
-      css_node_t *node_0 = root_layout;
-      node_0->layout.position[CSS_TOP] = 0;
-      node_0->layout.position[CSS_LEFT] = 0;
-      node_0->layout.dimensions[CSS_WIDTH] = 200;
-      node_0->layout.dimensions[CSS_HEIGHT] = 210;
-      init_css_node_children(node_0, 2);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->layout.position[CSS_TOP] = 0;
-        node_1->layout.position[CSS_LEFT] = 0;
-        node_1->layout.dimensions[CSS_WIDTH] = 200;
-        node_1->layout.dimensions[CSS_HEIGHT] = 200;
-        init_css_node_children(node_1, 1);
-        {
-          css_node_t *node_2;
-          node_2 = node_1->get_child(node_1->context, 0);
-          node_2->layout.position[CSS_TOP] = 0;
-          node_2->layout.position[CSS_LEFT] = 0;
-          node_2->layout.dimensions[CSS_WIDTH] = 200;
-          node_2->layout.dimensions[CSS_HEIGHT] = 200;
-        }
-        node_1 = node_0->get_child(node_0->context, 1);
-        node_1->layout.position[CSS_TOP] = 210;
-        node_1->layout.position[CSS_LEFT] = 10;
-        node_1->layout.dimensions[CSS_WIDTH] = 190;
-        node_1->layout.dimensions[CSS_HEIGHT] = 0;
-        init_css_node_children(node_1, 1);
-        {
-          css_node_t *node_2;
-          node_2 = node_1->get_child(node_1->context, 0);
-          node_2->layout.position[CSS_TOP] = 0;
-          node_2->layout.position[CSS_LEFT] = 0;
-          node_2->layout.dimensions[CSS_WIDTH] = 190;
-          node_2->layout.dimensions[CSS_HEIGHT] = 0;
-        }
-      }
-    }
-
-    test("should layout items whose positioning is determined by sibling tree branches", root_node, root_layout);
-  }
-
-  {
-    css_node_t *root_node = new_test_css_node();
-    {
-      css_node_t *node_0 = root_node;
-      node_0->style.flex_direction = CSS_FLEX_DIRECTION_ROW;
-      init_css_node_children(node_0, 3);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->style.align_self = CSS_ALIGN_FLEX_START;
-        node_1->style.margin[CSS_LEFT] = 10;
-        node_1->style.margin[CSS_TOP] = 10;
-        node_1 = node_0->get_child(node_0->context, 1);
-        node_1->style.align_self = CSS_ALIGN_STRETCH;
-        node_1->style.dimensions[CSS_WIDTH] = 1;
-        node_1 = node_0->get_child(node_0->context, 2);
-        node_1->style.dimensions[CSS_HEIGHT] = 150;
-      }
-    }
-
-    css_node_t *root_layout = new_test_css_node();
-    {
-      css_node_t *node_0 = root_layout;
-      node_0->layout.position[CSS_TOP] = 0;
-      node_0->layout.position[CSS_LEFT] = 0;
-      node_0->layout.dimensions[CSS_WIDTH] = 11;
-      node_0->layout.dimensions[CSS_HEIGHT] = 150;
-      init_css_node_children(node_0, 3);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->layout.position[CSS_TOP] = 10;
-        node_1->layout.position[CSS_LEFT] = 10;
-        node_1->layout.dimensions[CSS_WIDTH] = 0;
-        node_1->layout.dimensions[CSS_HEIGHT] = 0;
-        node_1 = node_0->get_child(node_0->context, 1);
-        node_1->layout.position[CSS_TOP] = 0;
-        node_1->layout.position[CSS_LEFT] = 10;
-        node_1->layout.dimensions[CSS_WIDTH] = 1;
-        node_1->layout.dimensions[CSS_HEIGHT] = 150;
-        node_1 = node_0->get_child(node_0->context, 2);
-        node_1->layout.position[CSS_TOP] = 0;
-        node_1->layout.position[CSS_LEFT] = 11;
-        node_1->layout.dimensions[CSS_WIDTH] = 0;
-        node_1->layout.dimensions[CSS_HEIGHT] = 150;
-      }
-    }
-
-    test("should layout child whose cross axis is undefined and whose alignSelf is stretch", root_node, root_layout);
-  }
-
-  {
-    css_node_t *root_node = new_test_css_node();
-    {
-      css_node_t *node_0 = root_node;
-      node_0->style.flex_direction = CSS_FLEX_DIRECTION_ROW;
-      init_css_node_children(node_0, 2);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        init_css_node_children(node_1, 1);
-        {
-          css_node_t *node_2;
-          node_2 = node_1->get_child(node_1->context, 0);
-          node_2->style.dimensions[CSS_WIDTH] = 100;
-          node_2->style.dimensions[CSS_HEIGHT] = 100;
-        }
-        node_1 = node_0->get_child(node_0->context, 1);
-        node_1->style.dimensions[CSS_WIDTH] = 100;
-        init_css_node_children(node_1, 1);
-        {
-          css_node_t *node_2;
-          node_2 = node_1->get_child(node_1->context, 0);
-          node_2->style.flex_direction = CSS_FLEX_DIRECTION_COLUMN;
-          node_2->style.align_items = CSS_ALIGN_CENTER;
-          init_css_node_children(node_2, 1);
-          {
-            css_node_t *node_3;
-            node_3 = node_2->get_child(node_2->context, 0);
-            node_3->style.dimensions[CSS_WIDTH] = 50;
-            node_3->style.dimensions[CSS_HEIGHT] = 50;
-          }
-        }
-      }
-    }
-
-    css_node_t *root_layout = new_test_css_node();
-    {
-      css_node_t *node_0 = root_layout;
-      node_0->layout.position[CSS_TOP] = 0;
-      node_0->layout.position[CSS_LEFT] = 0;
-      node_0->layout.dimensions[CSS_WIDTH] = 200;
-      node_0->layout.dimensions[CSS_HEIGHT] = 100;
-      init_css_node_children(node_0, 2);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->layout.position[CSS_TOP] = 0;
-        node_1->layout.position[CSS_LEFT] = 0;
-        node_1->layout.dimensions[CSS_WIDTH] = 100;
-        node_1->layout.dimensions[CSS_HEIGHT] = 100;
-        init_css_node_children(node_1, 1);
-        {
-          css_node_t *node_2;
-          node_2 = node_1->get_child(node_1->context, 0);
-          node_2->layout.position[CSS_TOP] = 0;
-          node_2->layout.position[CSS_LEFT] = 0;
-          node_2->layout.dimensions[CSS_WIDTH] = 100;
-          node_2->layout.dimensions[CSS_HEIGHT] = 100;
-        }
-        node_1 = node_0->get_child(node_0->context, 1);
-        node_1->layout.position[CSS_TOP] = 0;
-        node_1->layout.position[CSS_LEFT] = 100;
-        node_1->layout.dimensions[CSS_WIDTH] = 100;
-        node_1->layout.dimensions[CSS_HEIGHT] = 100;
-        init_css_node_children(node_1, 1);
-        {
-          css_node_t *node_2;
-          node_2 = node_1->get_child(node_1->context, 0);
-          node_2->layout.position[CSS_TOP] = 0;
-          node_2->layout.position[CSS_LEFT] = 0;
-          node_2->layout.dimensions[CSS_WIDTH] = 100;
-          node_2->layout.dimensions[CSS_HEIGHT] = 50;
-          init_css_node_children(node_2, 1);
-          {
-            css_node_t *node_3;
-            node_3 = node_2->get_child(node_2->context, 0);
-            node_3->layout.position[CSS_TOP] = 0;
-            node_3->layout.position[CSS_LEFT] = 25;
-            node_3->layout.dimensions[CSS_WIDTH] = 50;
-            node_3->layout.dimensions[CSS_HEIGHT] = 50;
-          }
-        }
-      }
-    }
-
-    test("should center items correctly inside a stretched layout", root_node, root_layout);
-  }
-
-  {
-    css_node_t *root_node = new_test_css_node();
-    {
-      css_node_t *node_0 = root_node;
-      node_0->style.flex_direction = CSS_FLEX_DIRECTION_ROW;
-      node_0->style.align_content = CSS_ALIGN_STRETCH;
-      node_0->style.align_items = CSS_ALIGN_FLEX_START;
-      node_0->style.flex_wrap = CSS_WRAP;
-      node_0->style.dimensions[CSS_WIDTH] = 300;
-      node_0->style.dimensions[CSS_HEIGHT] = 380;
-      init_css_node_children(node_0, 15);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->style.dimensions[CSS_WIDTH] = 50;
-        node_1->style.dimensions[CSS_HEIGHT] = 50;
-        node_1->style.margin[CSS_LEFT] = 10;
-        node_1->style.margin[CSS_TOP] = 10;
-        node_1->style.margin[CSS_RIGHT] = 10;
-        node_1->style.margin[CSS_BOTTOM] = 10;
-        node_1->style.margin[CSS_START] = 10;
-        node_1->style.margin[CSS_END] = 10;
-        node_1 = node_0->get_child(node_0->context, 1);
-        node_1->style.dimensions[CSS_WIDTH] = 50;
-        node_1->style.dimensions[CSS_HEIGHT] = 50;
-        node_1->style.margin[CSS_LEFT] = 10;
-        node_1->style.margin[CSS_TOP] = 10;
-        node_1->style.margin[CSS_RIGHT] = 10;
-        node_1->style.margin[CSS_BOTTOM] = 10;
-        node_1->style.margin[CSS_START] = 10;
-        node_1->style.margin[CSS_END] = 10;
-        node_1 = node_0->get_child(node_0->context, 2);
-        node_1->style.dimensions[CSS_WIDTH] = 50;
-        node_1->style.dimensions[CSS_HEIGHT] = 50;
-        node_1->style.margin[CSS_LEFT] = 10;
-        node_1->style.margin[CSS_TOP] = 10;
-        node_1->style.margin[CSS_RIGHT] = 10;
-        node_1->style.margin[CSS_BOTTOM] = 10;
-        node_1->style.margin[CSS_START] = 10;
-        node_1->style.margin[CSS_END] = 10;
-        node_1 = node_0->get_child(node_0->context, 3);
-        node_1->style.dimensions[CSS_WIDTH] = 50;
-        node_1->style.dimensions[CSS_HEIGHT] = 50;
-        node_1->style.margin[CSS_LEFT] = 10;
-        node_1->style.margin[CSS_TOP] = 10;
-        node_1->style.margin[CSS_RIGHT] = 10;
-        node_1->style.margin[CSS_BOTTOM] = 10;
-        node_1->style.margin[CSS_START] = 10;
-        node_1->style.margin[CSS_END] = 10;
-        node_1 = node_0->get_child(node_0->context, 4);
-        node_1->style.dimensions[CSS_WIDTH] = 50;
-        node_1->style.dimensions[CSS_HEIGHT] = 100;
-        node_1->style.margin[CSS_LEFT] = 10;
-        node_1->style.margin[CSS_TOP] = 10;
-        node_1->style.margin[CSS_RIGHT] = 10;
-        node_1->style.margin[CSS_BOTTOM] = 10;
-        node_1->style.margin[CSS_START] = 10;
-        node_1->style.margin[CSS_END] = 10;
-        node_1 = node_0->get_child(node_0->context, 5);
-        node_1->style.align_self = CSS_ALIGN_FLEX_START;
-        node_1->style.dimensions[CSS_WIDTH] = 50;
-        node_1->style.dimensions[CSS_HEIGHT] = 50;
-        node_1->style.margin[CSS_LEFT] = 10;
-        node_1->style.margin[CSS_TOP] = 10;
-        node_1->style.margin[CSS_RIGHT] = 10;
-        node_1->style.margin[CSS_BOTTOM] = 10;
-        node_1->style.margin[CSS_START] = 10;
-        node_1->style.margin[CSS_END] = 10;
-        node_1 = node_0->get_child(node_0->context, 6);
-        node_1->style.dimensions[CSS_WIDTH] = 50;
-        node_1->style.dimensions[CSS_HEIGHT] = 50;
-        node_1->style.margin[CSS_LEFT] = 10;
-        node_1->style.margin[CSS_TOP] = 10;
-        node_1->style.margin[CSS_RIGHT] = 10;
-        node_1->style.margin[CSS_BOTTOM] = 10;
-        node_1->style.margin[CSS_START] = 10;
-        node_1->style.margin[CSS_END] = 10;
-        node_1 = node_0->get_child(node_0->context, 7);
-        node_1->style.dimensions[CSS_WIDTH] = 50;
-        node_1->style.dimensions[CSS_HEIGHT] = 100;
-        node_1->style.margin[CSS_LEFT] = 10;
-        node_1->style.margin[CSS_TOP] = 10;
-        node_1->style.margin[CSS_RIGHT] = 10;
-        node_1->style.margin[CSS_BOTTOM] = 10;
-        node_1->style.margin[CSS_START] = 10;
-        node_1->style.margin[CSS_END] = 10;
-        node_1 = node_0->get_child(node_0->context, 8);
-        node_1->style.dimensions[CSS_WIDTH] = 50;
-        node_1->style.dimensions[CSS_HEIGHT] = 50;
-        node_1->style.margin[CSS_LEFT] = 10;
-        node_1->style.margin[CSS_TOP] = 10;
-        node_1->style.margin[CSS_RIGHT] = 10;
-        node_1->style.margin[CSS_BOTTOM] = 10;
-        node_1->style.margin[CSS_START] = 10;
-        node_1->style.margin[CSS_END] = 10;
-        node_1 = node_0->get_child(node_0->context, 9);
-        node_1->style.dimensions[CSS_WIDTH] = 50;
-        node_1->style.dimensions[CSS_HEIGHT] = 50;
-        node_1->style.margin[CSS_LEFT] = 10;
-        node_1->style.margin[CSS_TOP] = 10;
-        node_1->style.margin[CSS_RIGHT] = 10;
-        node_1->style.margin[CSS_BOTTOM] = 10;
-        node_1->style.margin[CSS_START] = 10;
-        node_1->style.margin[CSS_END] = 10;
-        node_1 = node_0->get_child(node_0->context, 10);
-        node_1->style.align_self = CSS_ALIGN_FLEX_START;
-        node_1->style.dimensions[CSS_WIDTH] = 50;
-        node_1->style.dimensions[CSS_HEIGHT] = 50;
-        node_1->style.margin[CSS_LEFT] = 10;
-        node_1->style.margin[CSS_TOP] = 10;
-        node_1->style.margin[CSS_RIGHT] = 10;
-        node_1->style.margin[CSS_BOTTOM] = 10;
-        node_1->style.margin[CSS_START] = 10;
-        node_1->style.margin[CSS_END] = 10;
-        node_1 = node_0->get_child(node_0->context, 11);
-        node_1->style.dimensions[CSS_WIDTH] = 50;
-        node_1->style.dimensions[CSS_HEIGHT] = 50;
-        node_1->style.margin[CSS_LEFT] = 10;
-        node_1->style.margin[CSS_TOP] = 10;
-        node_1->style.margin[CSS_RIGHT] = 10;
-        node_1->style.margin[CSS_BOTTOM] = 10;
-        node_1->style.margin[CSS_START] = 10;
-        node_1->style.margin[CSS_END] = 10;
-        node_1 = node_0->get_child(node_0->context, 12);
-        node_1->style.dimensions[CSS_WIDTH] = 50;
-        node_1->style.dimensions[CSS_HEIGHT] = 50;
-        node_1->style.margin[CSS_LEFT] = 10;
-        node_1->style.margin[CSS_TOP] = 10;
-        node_1->style.margin[CSS_RIGHT] = 10;
-        node_1->style.margin[CSS_BOTTOM] = 10;
-        node_1->style.margin[CSS_START] = 10;
-        node_1->style.margin[CSS_END] = 10;
-        node_1 = node_0->get_child(node_0->context, 13);
-        node_1->style.align_self = CSS_ALIGN_FLEX_START;
-        node_1->style.dimensions[CSS_WIDTH] = 50;
-        node_1->style.dimensions[CSS_HEIGHT] = 50;
-        node_1->style.margin[CSS_LEFT] = 10;
-        node_1->style.margin[CSS_TOP] = 10;
-        node_1->style.margin[CSS_RIGHT] = 10;
-        node_1->style.margin[CSS_BOTTOM] = 10;
-        node_1->style.margin[CSS_START] = 10;
-        node_1->style.margin[CSS_END] = 10;
-        node_1 = node_0->get_child(node_0->context, 14);
-        node_1->style.dimensions[CSS_WIDTH] = 50;
-        node_1->style.dimensions[CSS_HEIGHT] = 50;
-        node_1->style.margin[CSS_LEFT] = 10;
-        node_1->style.margin[CSS_TOP] = 10;
-        node_1->style.margin[CSS_RIGHT] = 10;
-        node_1->style.margin[CSS_BOTTOM] = 10;
-        node_1->style.margin[CSS_START] = 10;
-        node_1->style.margin[CSS_END] = 10;
-      }
-    }
-
-    css_node_t *root_layout = new_test_css_node();
-    {
-      css_node_t *node_0 = root_layout;
-      node_0->layout.position[CSS_TOP] = 0;
-      node_0->layout.position[CSS_LEFT] = 0;
-      node_0->layout.dimensions[CSS_WIDTH] = 300;
-      node_0->layout.dimensions[CSS_HEIGHT] = 380;
-      init_css_node_children(node_0, 15);
-      {
-        css_node_t *node_1;
-        node_1 = node_0->get_child(node_0->context, 0);
-        node_1->layout.position[CSS_TOP] = 10;
-        node_1->layout.position[CSS_LEFT] = 10;
-        node_1->layout.dimensions[CSS_WIDTH] = 50;
-        node_1->layout.dimensions[CSS_HEIGHT] = 50;
-        node_1 = node_0->get_child(node_0->context, 1);
-        node_1->layout.position[CSS_TOP] = 10;
-        node_1->layout.position[CSS_LEFT] = 80;
-        node_1->layout.dimensions[CSS_WIDTH] = 50;
-        node_1->layout.dimensions[CSS_HEIGHT] = 50;
-        node_1 = node_0->get_child(node_0->context, 2);
-        node_1->layout.position[CSS_TOP] = 10;
-        node_1->layout.position[CSS_LEFT] = 150;
-        node_1->layout.dimensions[CSS_WIDTH] = 50;
-        node_1->layout.dimensions[CSS_HEIGHT] = 50;
-        node_1 = node_0->get_child(node_0->context, 3);
-        node_1->layout.position[CSS_TOP] = 10;
-        node_1->layout.position[CSS_LEFT] = 220;
-        node_1->layout.dimensions[CSS_WIDTH] = 50;
-        node_1->layout.dimensions[CSS_HEIGHT] = 50;
-        node_1 = node_0->get_child(node_0->context, 4);
-        node_1->layout.position[CSS_TOP] = 92.5;
-        node_1->layout.position[CSS_LEFT] = 10;
-        node_1->layout.dimensions[CSS_WIDTH] = 50;
-        node_1->layout.dimensions[CSS_HEIGHT] = 100;
-        node_1 = node_0->get_child(node_0->context, 5);
-        node_1->layout.position[CSS_TOP] = 92.5;
-        node_1->layout.position[CSS_LEFT] = 80;
-        node_1->layout.dimensions[CSS_WIDTH] = 50;
-        node_1->layout.dimensions[CSS_HEIGHT] = 50;
-        node_1 = node_0->get_child(node_0->context, 6);
-        node_1->layout.position[CSS_TOP] = 92.5;
-        node_1->layout.position[CSS_LEFT] = 150;
-        node_1->layout.dimensions[CSS_WIDTH] = 50;
-        node_1->layout.dimensions[CSS_HEIGHT] = 50;
-        node_1 = node_0->get_child(node_0->context, 7);
-        node_1->layout.position[CSS_TOP] = 92.5;
-        node_1->layout.position[CSS_LEFT] = 220;
-        node_1->layout.dimensions[CSS_WIDTH] = 50;
-        node_1->layout.dimensions[CSS_HEIGHT] = 100;
-        node_1 = node_0->get_child(node_0->context, 8);
-        node_1->layout.position[CSS_TOP] = 225;
-        node_1->layout.position[CSS_LEFT] = 10;
-        node_1->layout.dimensions[CSS_WIDTH] = 50;
-        node_1->layout.dimensions[CSS_HEIGHT] = 50;
-        node_1 = node_0->get_child(node_0->context, 9);
-        node_1->layout.position[CSS_TOP] = 225;
-        node_1->layout.position[CSS_LEFT] = 80;
-        node_1->layout.dimensions[CSS_WIDTH] = 50;
-        node_1->layout.dimensions[CSS_HEIGHT] = 50;
-        node_1 = node_0->get_child(node_0->context, 10);
-        node_1->layout.position[CSS_TOP] = 225;
-        node_1->layout.position[CSS_LEFT] = 150;
-        node_1->layout.dimensions[CSS_WIDTH] = 50;
-        node_1->layout.dimensions[CSS_HEIGHT] = 50;
-        node_1 = node_0->get_child(node_0->context, 11);
-        node_1->layout.position[CSS_TOP] = 225;
-        node_1->layout.position[CSS_LEFT] = 220;
-        node_1->layout.dimensions[CSS_WIDTH] = 50;
-        node_1->layout.dimensions[CSS_HEIGHT] = 50;
-        node_1 = node_0->get_child(node_0->context, 12);
-        node_1->layout.position[CSS_TOP] = 307.5;
-        node_1->layout.position[CSS_LEFT] = 10;
-        node_1->layout.dimensions[CSS_WIDTH] = 50;
-        node_1->layout.dimensions[CSS_HEIGHT] = 50;
-        node_1 = node_0->get_child(node_0->context, 13);
-        node_1->layout.position[CSS_TOP] = 307.5;
-        node_1->layout.position[CSS_LEFT] = 80;
-        node_1->layout.dimensions[CSS_WIDTH] = 50;
-        node_1->layout.dimensions[CSS_HEIGHT] = 50;
-        node_1 = node_0->get_child(node_0->context, 14);
-        node_1->layout.position[CSS_TOP] = 307.5;
-        node_1->layout.position[CSS_LEFT] = 150;
-        node_1->layout.dimensions[CSS_WIDTH] = 50;
-        node_1->layout.dimensions[CSS_HEIGHT] = 50;
-      }
-    }
-
-    test("should layout with alignContent: stretch, and alignItems: flex-start", root_node, root_layout);
-  }
-  /** END_GENERATED **/
-  return tests_finished();
-}
diff --git a/automated-tests/src/dali-toolkit-third-party/facebook-flexbox/layout-test-utils.h b/automated-tests/src/dali-toolkit-third-party/facebook-flexbox/layout-test-utils.h
deleted file mode 100644 (file)
index 7513141..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-/**
- * Copyright (c) 2014, 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 <stdio.h>
-#include <string.h>
-
-#include <dali-toolkit/third-party/facebook-flexbox/layout.h>
-
-void test(const char *name, css_node_t *style, css_node_t *expected_layout);
-bool tests_finished(void);
-css_dim_t measure(void *context, float width, css_measure_mode_t widthMode, float height, css_measure_mode_t heightMode);
-void init_css_node_children(css_node_t *node, int children_count);
-css_node_t *new_test_css_node(void);
-bool perform_layout_test(void);
index 83f932e..832d73e 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2018 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  */
 
 #include <dali-toolkit-test-suite-utils.h>
-
-extern "C"
-{
-#include "facebook-flexbox/layout-test-utils.h"
-}
+// GTest fails to compile with "error: return-statement with a value, in function returning 'void'" error
+// if using dali assert function so define new assert with returning void.
+#define _ASSERT_H_
+#define assert(exp) \
+    if (!(exp)) { \
+        fprintf(stderr, \
+            "Assert fail in %s:%d\n", __FILE__, __LINE__); \
+        fprintf(stderr, \
+            "Following expression is not true:\n" \
+                "%s\n", #exp); \
+        return; \
+    }
+#include <gtest/gtest.h>
+#undef GTEST_HAS_DEATH_TEST
+#include "yoga/YGFlexTest.cpp"
+#include "yoga/YGAlignContentTest.cpp"
+#include "yoga/YGComputedMarginTest.cpp"
+#include "yoga/YGZeroOutLayoutRecursivlyTest.cpp"
+#include "yoga/YGRoundingTest.cpp"
+#include "yoga/YGTreeMutationTest.cpp"
+#include "yoga/YGMeasureCacheTest.cpp"
+#include "yoga/YGTraversalTest.cpp"
+#include "yoga/YGAlignItemsTest.cpp"
+#include "yoga/YGComputedPaddingTest.cpp"
+#include "yoga/YGDimensionTest.cpp"
+#include "yoga/YGDefaultValuesTest.cpp"
+#include "yoga/YGMinMaxDimensionTest.cpp"
+#include "yoga/YGPaddingTest.cpp"
+#include "yoga/YGLoggerTest.cpp"
+#include "yoga/YGAbsolutePositionTest.cpp"
+#include "yoga/YGBorderTest.cpp"
+#include "yoga/YGDirtiedTest.cpp"
+#include "yoga/YGRoundingMeasureFuncTest.cpp"
+#include "yoga/YGEdgeTest.cpp"
+#include "yoga/YGAlignSelfTest.cpp"
+#include "yoga/YGMeasureTest.cpp"
+#include "yoga/YGFlexDirectionTest.cpp"
+#include "yoga/YGHadOverflowTest.cpp"
+#include "yoga/YGNodeChildTest.cpp"
+#include "yoga/YGRoundingFunctionTest.cpp"
+#include "yoga/YGPersistenceTest.cpp"
+#include "yoga/YGPercentageTest.cpp"
+#include "yoga/YGStyleTest.cpp"
+#include "yoga/YGMarginTest.cpp"
+#include "yoga/YGLayoutDiffingTest.cpp"
+#include "yoga/YGBaselineFuncTest.cpp"
+#include "yoga/YGAspectRatioTest.cpp"
+#include "yoga/YGSizeOverflowTest.cpp"
+#include "yoga/YGDirtyMarkingTest.cpp"
+#include "yoga/YGMeasureModeTest.cpp"
+#include "yoga/YGJustifyContentTest.cpp"
+#include "yoga/YGInfiniteHeightTest.cpp"
+#include "yoga/YGRelayoutTest.cpp"
+#include "yoga/YGDisplayTest.cpp"
+#include "yoga/YGFlexWrapTest.cpp"
 
 //////////////////////////////////////////////////////////
 
@@ -28,9 +78,11 @@ int UtcDaliFlexboxLayoutTest(void)
 {
   ToolkitTestApplication application;
   tet_infoline("UtcDaliFlexboxLayoutTest");
+  int argc = 0;
+  testing::InitGoogleTest( &argc, static_cast<char**>(nullptr) );
 
   // The test function is a 3rd party function that should return true if the test passes
-  if( perform_layout_test() )
+  if( !RUN_ALL_TESTS() )
   {
     tet_result(TET_PASS);
   }
diff --git a/automated-tests/src/dali-toolkit-third-party/yoga/YGAbsolutePositionTest.cpp b/automated-tests/src/dali-toolkit-third-party/yoga/YGAbsolutePositionTest.cpp
new file mode 100644 (file)
index 0000000..a319cf1
--- /dev/null
@@ -0,0 +1,1031 @@
+/**
+ * Copyright (c) 2014-present, Facebook, Inc.
+ *
+ * This source code is licensed under the MIT license found in the
+ * LICENSE file in the root directory of this source tree.
+ */
+
+// @Generated by gentest/gentest.rb from gentest/fixtures/YGAbsolutePositionTest.html
+
+#include <gtest/gtest.h>
+#include <yoga/Yoga.h>
+
+TEST(YogaTest, absolute_layout_width_height_start_top) {
+  const YGConfigRef config = YGConfigNew();
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root, 100);
+  YGNodeStyleSetHeight(root, 100);
+
+  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetPositionType(root_child0, YGPositionTypeAbsolute);
+  YGNodeStyleSetPosition(root_child0, YGEdgeStart, 10);
+  YGNodeStyleSetPosition(root_child0, YGEdgeTop, 10);
+  YGNodeStyleSetWidth(root_child0, 10);
+  YGNodeStyleSetHeight(root_child0, 10);
+  YGNodeInsertChild(root, root_child0, 0);
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child0));
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(80, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child0));
+
+  YGNodeFreeRecursive(root);
+
+  YGConfigFree(config);
+}
+
+TEST(YogaTest, absolute_layout_width_height_end_bottom) {
+  const YGConfigRef config = YGConfigNew();
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root, 100);
+  YGNodeStyleSetHeight(root, 100);
+
+  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetPositionType(root_child0, YGPositionTypeAbsolute);
+  YGNodeStyleSetPosition(root_child0, YGEdgeEnd, 10);
+  YGNodeStyleSetPosition(root_child0, YGEdgeBottom, 10);
+  YGNodeStyleSetWidth(root_child0, 10);
+  YGNodeStyleSetHeight(root_child0, 10);
+  YGNodeInsertChild(root, root_child0, 0);
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(80, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(80, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child0));
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(80, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child0));
+
+  YGNodeFreeRecursive(root);
+
+  YGConfigFree(config);
+}
+
+TEST(YogaTest, absolute_layout_start_top_end_bottom) {
+  const YGConfigRef config = YGConfigNew();
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root, 100);
+  YGNodeStyleSetHeight(root, 100);
+
+  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetPositionType(root_child0, YGPositionTypeAbsolute);
+  YGNodeStyleSetPosition(root_child0, YGEdgeStart, 10);
+  YGNodeStyleSetPosition(root_child0, YGEdgeTop, 10);
+  YGNodeStyleSetPosition(root_child0, YGEdgeEnd, 10);
+  YGNodeStyleSetPosition(root_child0, YGEdgeBottom, 10);
+  YGNodeInsertChild(root, root_child0, 0);
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(80, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(80, YGNodeLayoutGetHeight(root_child0));
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(80, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(80, YGNodeLayoutGetHeight(root_child0));
+
+  YGNodeFreeRecursive(root);
+
+  YGConfigFree(config);
+}
+
+TEST(YogaTest, absolute_layout_width_height_start_top_end_bottom) {
+  const YGConfigRef config = YGConfigNew();
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root, 100);
+  YGNodeStyleSetHeight(root, 100);
+
+  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetPositionType(root_child0, YGPositionTypeAbsolute);
+  YGNodeStyleSetPosition(root_child0, YGEdgeStart, 10);
+  YGNodeStyleSetPosition(root_child0, YGEdgeTop, 10);
+  YGNodeStyleSetPosition(root_child0, YGEdgeEnd, 10);
+  YGNodeStyleSetPosition(root_child0, YGEdgeBottom, 10);
+  YGNodeStyleSetWidth(root_child0, 10);
+  YGNodeStyleSetHeight(root_child0, 10);
+  YGNodeInsertChild(root, root_child0, 0);
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child0));
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(80, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child0));
+
+  YGNodeFreeRecursive(root);
+
+  YGConfigFree(config);
+}
+
+TEST(YogaTest, do_not_clamp_height_of_absolute_node_to_height_of_its_overflow_hidden_parent) {
+  const YGConfigRef config = YGConfigNew();
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexDirection(root, YGFlexDirectionRow);
+  YGNodeStyleSetOverflow(root, YGOverflowHidden);
+  YGNodeStyleSetWidth(root, 50);
+  YGNodeStyleSetHeight(root, 50);
+
+  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetPositionType(root_child0, YGPositionTypeAbsolute);
+  YGNodeStyleSetPosition(root_child0, YGEdgeStart, 0);
+  YGNodeStyleSetPosition(root_child0, YGEdgeTop, 0);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  const YGNodeRef root_child0_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child0_child0, 100);
+  YGNodeStyleSetHeight(root_child0_child0, 100);
+  YGNodeInsertChild(root_child0, root_child0_child0, 0);
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0_child0));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child0_child0));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child0_child0));
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(-50, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0_child0));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child0_child0));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child0_child0));
+
+  YGNodeFreeRecursive(root);
+
+  YGConfigFree(config);
+}
+
+TEST(YogaTest, absolute_layout_within_border) {
+  const YGConfigRef config = YGConfigNew();
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  YGNodeStyleSetMargin(root, YGEdgeLeft, 10);
+  YGNodeStyleSetMargin(root, YGEdgeTop, 10);
+  YGNodeStyleSetMargin(root, YGEdgeRight, 10);
+  YGNodeStyleSetMargin(root, YGEdgeBottom, 10);
+  YGNodeStyleSetPadding(root, YGEdgeLeft, 10);
+  YGNodeStyleSetPadding(root, YGEdgeTop, 10);
+  YGNodeStyleSetPadding(root, YGEdgeRight, 10);
+  YGNodeStyleSetPadding(root, YGEdgeBottom, 10);
+  YGNodeStyleSetBorder(root, YGEdgeLeft, 10);
+  YGNodeStyleSetBorder(root, YGEdgeTop, 10);
+  YGNodeStyleSetBorder(root, YGEdgeRight, 10);
+  YGNodeStyleSetBorder(root, YGEdgeBottom, 10);
+  YGNodeStyleSetWidth(root, 100);
+  YGNodeStyleSetHeight(root, 100);
+
+  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetPositionType(root_child0, YGPositionTypeAbsolute);
+  YGNodeStyleSetPosition(root_child0, YGEdgeLeft, 0);
+  YGNodeStyleSetPosition(root_child0, YGEdgeTop, 0);
+  YGNodeStyleSetWidth(root_child0, 50);
+  YGNodeStyleSetHeight(root_child0, 50);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  const YGNodeRef root_child1 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetPositionType(root_child1, YGPositionTypeAbsolute);
+  YGNodeStyleSetPosition(root_child1, YGEdgeRight, 0);
+  YGNodeStyleSetPosition(root_child1, YGEdgeBottom, 0);
+  YGNodeStyleSetWidth(root_child1, 50);
+  YGNodeStyleSetHeight(root_child1, 50);
+  YGNodeInsertChild(root, root_child1, 1);
+
+  const YGNodeRef root_child2 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetPositionType(root_child2, YGPositionTypeAbsolute);
+  YGNodeStyleSetPosition(root_child2, YGEdgeLeft, 0);
+  YGNodeStyleSetPosition(root_child2, YGEdgeTop, 0);
+  YGNodeStyleSetMargin(root_child2, YGEdgeLeft, 10);
+  YGNodeStyleSetMargin(root_child2, YGEdgeTop, 10);
+  YGNodeStyleSetMargin(root_child2, YGEdgeRight, 10);
+  YGNodeStyleSetMargin(root_child2, YGEdgeBottom, 10);
+  YGNodeStyleSetWidth(root_child2, 50);
+  YGNodeStyleSetHeight(root_child2, 50);
+  YGNodeInsertChild(root, root_child2, 2);
+
+  const YGNodeRef root_child3 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetPositionType(root_child3, YGPositionTypeAbsolute);
+  YGNodeStyleSetPosition(root_child3, YGEdgeRight, 0);
+  YGNodeStyleSetPosition(root_child3, YGEdgeBottom, 0);
+  YGNodeStyleSetMargin(root_child3, YGEdgeLeft, 10);
+  YGNodeStyleSetMargin(root_child3, YGEdgeTop, 10);
+  YGNodeStyleSetMargin(root_child3, YGEdgeRight, 10);
+  YGNodeStyleSetMargin(root_child3, YGEdgeBottom, 10);
+  YGNodeStyleSetWidth(root_child3, 50);
+  YGNodeStyleSetHeight(root_child3, 50);
+  YGNodeInsertChild(root, root_child3, 3);
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(40, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(40, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child1));
+
+  ASSERT_FLOAT_EQ(20, YGNodeLayoutGetLeft(root_child2));
+  ASSERT_FLOAT_EQ(20, YGNodeLayoutGetTop(root_child2));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child2));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child2));
+
+  ASSERT_FLOAT_EQ(30, YGNodeLayoutGetLeft(root_child3));
+  ASSERT_FLOAT_EQ(30, YGNodeLayoutGetTop(root_child3));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child3));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child3));
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);
+
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(40, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(40, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child1));
+
+  ASSERT_FLOAT_EQ(20, YGNodeLayoutGetLeft(root_child2));
+  ASSERT_FLOAT_EQ(20, YGNodeLayoutGetTop(root_child2));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child2));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child2));
+
+  ASSERT_FLOAT_EQ(30, YGNodeLayoutGetLeft(root_child3));
+  ASSERT_FLOAT_EQ(30, YGNodeLayoutGetTop(root_child3));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child3));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child3));
+
+  YGNodeFreeRecursive(root);
+
+  YGConfigFree(config);
+}
+
+TEST(YogaTest, absolute_layout_align_items_and_justify_content_center) {
+  const YGConfigRef config = YGConfigNew();
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  YGNodeStyleSetJustifyContent(root, YGJustifyCenter);
+  YGNodeStyleSetAlignItems(root, YGAlignCenter);
+  YGNodeStyleSetFlexGrow(root, 1);
+  YGNodeStyleSetWidth(root, 110);
+  YGNodeStyleSetHeight(root, 100);
+
+  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetPositionType(root_child0, YGPositionTypeAbsolute);
+  YGNodeStyleSetWidth(root_child0, 60);
+  YGNodeStyleSetHeight(root_child0, 40);
+  YGNodeInsertChild(root, root_child0, 0);
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(110, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(25, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(30, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(60, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(40, YGNodeLayoutGetHeight(root_child0));
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(110, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(25, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(30, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(60, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(40, YGNodeLayoutGetHeight(root_child0));
+
+  YGNodeFreeRecursive(root);
+
+  YGConfigFree(config);
+}
+
+TEST(YogaTest, absolute_layout_align_items_and_justify_content_flex_end) {
+  const YGConfigRef config = YGConfigNew();
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  YGNodeStyleSetJustifyContent(root, YGJustifyFlexEnd);
+  YGNodeStyleSetAlignItems(root, YGAlignFlexEnd);
+  YGNodeStyleSetFlexGrow(root, 1);
+  YGNodeStyleSetWidth(root, 110);
+  YGNodeStyleSetHeight(root, 100);
+
+  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetPositionType(root_child0, YGPositionTypeAbsolute);
+  YGNodeStyleSetWidth(root_child0, 60);
+  YGNodeStyleSetHeight(root_child0, 40);
+  YGNodeInsertChild(root, root_child0, 0);
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(110, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(60, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(60, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(40, YGNodeLayoutGetHeight(root_child0));
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(110, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(60, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(60, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(40, YGNodeLayoutGetHeight(root_child0));
+
+  YGNodeFreeRecursive(root);
+
+  YGConfigFree(config);
+}
+
+TEST(YogaTest, absolute_layout_justify_content_center) {
+  const YGConfigRef config = YGConfigNew();
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  YGNodeStyleSetJustifyContent(root, YGJustifyCenter);
+  YGNodeStyleSetFlexGrow(root, 1);
+  YGNodeStyleSetWidth(root, 110);
+  YGNodeStyleSetHeight(root, 100);
+
+  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetPositionType(root_child0, YGPositionTypeAbsolute);
+  YGNodeStyleSetWidth(root_child0, 60);
+  YGNodeStyleSetHeight(root_child0, 40);
+  YGNodeInsertChild(root, root_child0, 0);
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(110, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(30, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(60, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(40, YGNodeLayoutGetHeight(root_child0));
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(110, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(30, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(60, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(40, YGNodeLayoutGetHeight(root_child0));
+
+  YGNodeFreeRecursive(root);
+
+  YGConfigFree(config);
+}
+
+TEST(YogaTest, absolute_layout_align_items_center) {
+  const YGConfigRef config = YGConfigNew();
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  YGNodeStyleSetAlignItems(root, YGAlignCenter);
+  YGNodeStyleSetFlexGrow(root, 1);
+  YGNodeStyleSetWidth(root, 110);
+  YGNodeStyleSetHeight(root, 100);
+
+  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetPositionType(root_child0, YGPositionTypeAbsolute);
+  YGNodeStyleSetWidth(root_child0, 60);
+  YGNodeStyleSetHeight(root_child0, 40);
+  YGNodeInsertChild(root, root_child0, 0);
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(110, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(25, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(60, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(40, YGNodeLayoutGetHeight(root_child0));
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(110, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(25, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(60, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(40, YGNodeLayoutGetHeight(root_child0));
+
+  YGNodeFreeRecursive(root);
+
+  YGConfigFree(config);
+}
+
+TEST(YogaTest, absolute_layout_align_items_center_on_child_only) {
+  const YGConfigRef config = YGConfigNew();
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexGrow(root, 1);
+  YGNodeStyleSetWidth(root, 110);
+  YGNodeStyleSetHeight(root, 100);
+
+  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetAlignSelf(root_child0, YGAlignCenter);
+  YGNodeStyleSetPositionType(root_child0, YGPositionTypeAbsolute);
+  YGNodeStyleSetWidth(root_child0, 60);
+  YGNodeStyleSetHeight(root_child0, 40);
+  YGNodeInsertChild(root, root_child0, 0);
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(110, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(25, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(60, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(40, YGNodeLayoutGetHeight(root_child0));
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(110, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(25, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(60, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(40, YGNodeLayoutGetHeight(root_child0));
+
+  YGNodeFreeRecursive(root);
+
+  YGConfigFree(config);
+}
+
+TEST(YogaTest, absolute_layout_align_items_and_justify_content_center_and_top_position) {
+  const YGConfigRef config = YGConfigNew();
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  YGNodeStyleSetJustifyContent(root, YGJustifyCenter);
+  YGNodeStyleSetAlignItems(root, YGAlignCenter);
+  YGNodeStyleSetFlexGrow(root, 1);
+  YGNodeStyleSetWidth(root, 110);
+  YGNodeStyleSetHeight(root, 100);
+
+  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetPositionType(root_child0, YGPositionTypeAbsolute);
+  YGNodeStyleSetPosition(root_child0, YGEdgeTop, 10);
+  YGNodeStyleSetWidth(root_child0, 60);
+  YGNodeStyleSetHeight(root_child0, 40);
+  YGNodeInsertChild(root, root_child0, 0);
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(110, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(25, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(60, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(40, YGNodeLayoutGetHeight(root_child0));
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(110, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(25, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(60, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(40, YGNodeLayoutGetHeight(root_child0));
+
+  YGNodeFreeRecursive(root);
+
+  YGConfigFree(config);
+}
+
+TEST(YogaTest, absolute_layout_align_items_and_justify_content_center_and_bottom_position) {
+  const YGConfigRef config = YGConfigNew();
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  YGNodeStyleSetJustifyContent(root, YGJustifyCenter);
+  YGNodeStyleSetAlignItems(root, YGAlignCenter);
+  YGNodeStyleSetFlexGrow(root, 1);
+  YGNodeStyleSetWidth(root, 110);
+  YGNodeStyleSetHeight(root, 100);
+
+  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetPositionType(root_child0, YGPositionTypeAbsolute);
+  YGNodeStyleSetPosition(root_child0, YGEdgeBottom, 10);
+  YGNodeStyleSetWidth(root_child0, 60);
+  YGNodeStyleSetHeight(root_child0, 40);
+  YGNodeInsertChild(root, root_child0, 0);
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(110, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(25, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(60, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(40, YGNodeLayoutGetHeight(root_child0));
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(110, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(25, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(60, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(40, YGNodeLayoutGetHeight(root_child0));
+
+  YGNodeFreeRecursive(root);
+
+  YGConfigFree(config);
+}
+
+TEST(YogaTest, absolute_layout_align_items_and_justify_content_center_and_left_position) {
+  const YGConfigRef config = YGConfigNew();
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  YGNodeStyleSetJustifyContent(root, YGJustifyCenter);
+  YGNodeStyleSetAlignItems(root, YGAlignCenter);
+  YGNodeStyleSetFlexGrow(root, 1);
+  YGNodeStyleSetWidth(root, 110);
+  YGNodeStyleSetHeight(root, 100);
+
+  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetPositionType(root_child0, YGPositionTypeAbsolute);
+  YGNodeStyleSetPosition(root_child0, YGEdgeLeft, 5);
+  YGNodeStyleSetWidth(root_child0, 60);
+  YGNodeStyleSetHeight(root_child0, 40);
+  YGNodeInsertChild(root, root_child0, 0);
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(110, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(5, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(30, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(60, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(40, YGNodeLayoutGetHeight(root_child0));
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(110, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(5, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(30, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(60, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(40, YGNodeLayoutGetHeight(root_child0));
+
+  YGNodeFreeRecursive(root);
+
+  YGConfigFree(config);
+}
+
+TEST(YogaTest, absolute_layout_align_items_and_justify_content_center_and_right_position) {
+  const YGConfigRef config = YGConfigNew();
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  YGNodeStyleSetJustifyContent(root, YGJustifyCenter);
+  YGNodeStyleSetAlignItems(root, YGAlignCenter);
+  YGNodeStyleSetFlexGrow(root, 1);
+  YGNodeStyleSetWidth(root, 110);
+  YGNodeStyleSetHeight(root, 100);
+
+  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetPositionType(root_child0, YGPositionTypeAbsolute);
+  YGNodeStyleSetPosition(root_child0, YGEdgeRight, 5);
+  YGNodeStyleSetWidth(root_child0, 60);
+  YGNodeStyleSetHeight(root_child0, 40);
+  YGNodeInsertChild(root, root_child0, 0);
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(110, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(45, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(30, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(60, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(40, YGNodeLayoutGetHeight(root_child0));
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(110, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(45, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(30, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(60, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(40, YGNodeLayoutGetHeight(root_child0));
+
+  YGNodeFreeRecursive(root);
+
+  YGConfigFree(config);
+}
+
+TEST(YogaTest, position_root_with_rtl_should_position_withoutdirection) {
+  const YGConfigRef config = YGConfigNew();
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  YGNodeStyleSetPosition(root, YGEdgeLeft, 72);
+  YGNodeStyleSetWidth(root, 52);
+  YGNodeStyleSetHeight(root, 52);
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(72, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(52, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(52, YGNodeLayoutGetHeight(root));
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);
+
+  ASSERT_FLOAT_EQ(72, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(52, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(52, YGNodeLayoutGetHeight(root));
+
+  YGNodeFreeRecursive(root);
+
+  YGConfigFree(config);
+}
+
+TEST(YogaTest, absolute_layout_percentage_bottom_based_on_parent_height) {
+  const YGConfigRef config = YGConfigNew();
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root, 100);
+  YGNodeStyleSetHeight(root, 200);
+
+  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetPositionType(root_child0, YGPositionTypeAbsolute);
+  YGNodeStyleSetPositionPercent(root_child0, YGEdgeTop, 50);
+  YGNodeStyleSetWidth(root_child0, 10);
+  YGNodeStyleSetHeight(root_child0, 10);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  const YGNodeRef root_child1 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetPositionType(root_child1, YGPositionTypeAbsolute);
+  YGNodeStyleSetPositionPercent(root_child1, YGEdgeBottom, 50);
+  YGNodeStyleSetWidth(root_child1, 10);
+  YGNodeStyleSetHeight(root_child1, 10);
+  YGNodeInsertChild(root, root_child1, 1);
+
+  const YGNodeRef root_child2 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetPositionType(root_child2, YGPositionTypeAbsolute);
+  YGNodeStyleSetPositionPercent(root_child2, YGEdgeTop, 10);
+  YGNodeStyleSetPositionPercent(root_child2, YGEdgeBottom, 10);
+  YGNodeStyleSetWidth(root_child2, 10);
+  YGNodeInsertChild(root, root_child2, 2);
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(200, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(90, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child1));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child2));
+  ASSERT_FLOAT_EQ(20, YGNodeLayoutGetTop(root_child2));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetWidth(root_child2));
+  ASSERT_FLOAT_EQ(160, YGNodeLayoutGetHeight(root_child2));
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(200, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(90, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(90, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(90, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child1));
+
+  ASSERT_FLOAT_EQ(90, YGNodeLayoutGetLeft(root_child2));
+  ASSERT_FLOAT_EQ(20, YGNodeLayoutGetTop(root_child2));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetWidth(root_child2));
+  ASSERT_FLOAT_EQ(160, YGNodeLayoutGetHeight(root_child2));
+
+  YGNodeFreeRecursive(root);
+
+  YGConfigFree(config);
+}
+
+TEST(YogaTest, absolute_layout_in_wrap_reverse_column_container) {
+  const YGConfigRef config = YGConfigNew();
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexWrap(root, YGWrapWrapReverse);
+  YGNodeStyleSetWidth(root, 100);
+  YGNodeStyleSetHeight(root, 100);
+
+  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetPositionType(root_child0, YGPositionTypeAbsolute);
+  YGNodeStyleSetWidth(root_child0, 20);
+  YGNodeStyleSetHeight(root_child0, 20);
+  YGNodeInsertChild(root, root_child0, 0);
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(80, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(20, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(20, YGNodeLayoutGetHeight(root_child0));
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(20, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(20, YGNodeLayoutGetHeight(root_child0));
+
+  YGNodeFreeRecursive(root);
+
+  YGConfigFree(config);
+}
+
+TEST(YogaTest, absolute_layout_in_wrap_reverse_row_container) {
+  const YGConfigRef config = YGConfigNew();
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexDirection(root, YGFlexDirectionRow);
+  YGNodeStyleSetFlexWrap(root, YGWrapWrapReverse);
+  YGNodeStyleSetWidth(root, 100);
+  YGNodeStyleSetHeight(root, 100);
+
+  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetPositionType(root_child0, YGPositionTypeAbsolute);
+  YGNodeStyleSetWidth(root_child0, 20);
+  YGNodeStyleSetHeight(root_child0, 20);
+  YGNodeInsertChild(root, root_child0, 0);
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(80, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(20, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(20, YGNodeLayoutGetHeight(root_child0));
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(80, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(80, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(20, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(20, YGNodeLayoutGetHeight(root_child0));
+
+  YGNodeFreeRecursive(root);
+
+  YGConfigFree(config);
+}
+
+TEST(YogaTest, absolute_layout_in_wrap_reverse_column_container_flex_end) {
+  const YGConfigRef config = YGConfigNew();
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexWrap(root, YGWrapWrapReverse);
+  YGNodeStyleSetWidth(root, 100);
+  YGNodeStyleSetHeight(root, 100);
+
+  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetAlignSelf(root_child0, YGAlignFlexEnd);
+  YGNodeStyleSetPositionType(root_child0, YGPositionTypeAbsolute);
+  YGNodeStyleSetWidth(root_child0, 20);
+  YGNodeStyleSetHeight(root_child0, 20);
+  YGNodeInsertChild(root, root_child0, 0);
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(20, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(20, YGNodeLayoutGetHeight(root_child0));
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(80, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(20, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(20, YGNodeLayoutGetHeight(root_child0));
+
+  YGNodeFreeRecursive(root);
+
+  YGConfigFree(config);
+}
+
+TEST(YogaTest, absolute_layout_in_wrap_reverse_row_container_flex_end) {
+  const YGConfigRef config = YGConfigNew();
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexDirection(root, YGFlexDirectionRow);
+  YGNodeStyleSetFlexWrap(root, YGWrapWrapReverse);
+  YGNodeStyleSetWidth(root, 100);
+  YGNodeStyleSetHeight(root, 100);
+
+  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetAlignSelf(root_child0, YGAlignFlexEnd);
+  YGNodeStyleSetPositionType(root_child0, YGPositionTypeAbsolute);
+  YGNodeStyleSetWidth(root_child0, 20);
+  YGNodeStyleSetHeight(root_child0, 20);
+  YGNodeInsertChild(root, root_child0, 0);
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(20, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(20, YGNodeLayoutGetHeight(root_child0));
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(80, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(20, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(20, YGNodeLayoutGetHeight(root_child0));
+
+  YGNodeFreeRecursive(root);
+
+  YGConfigFree(config);
+}
diff --git a/automated-tests/src/dali-toolkit-third-party/yoga/YGAlignContentTest.cpp b/automated-tests/src/dali-toolkit-third-party/yoga/YGAlignContentTest.cpp
new file mode 100644 (file)
index 0000000..7cd5c09
--- /dev/null
@@ -0,0 +1,1878 @@
+/**
+ * Copyright (c) 2014-present, Facebook, Inc.
+ *
+ * This source code is licensed under the MIT license found in the
+ * LICENSE file in the root directory of this source tree.
+ */
+
+// @Generated by gentest/gentest.rb from gentest/fixtures/YGAlignContentTest.html
+
+#include <gtest/gtest.h>
+#include <yoga/Yoga.h>
+
+TEST(YogaTest, align_content_flex_start) {
+  const YGConfigRef config = YGConfigNew();
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexDirection(root, YGFlexDirectionRow);
+  YGNodeStyleSetFlexWrap(root, YGWrapWrap);
+  YGNodeStyleSetWidth(root, 130);
+  YGNodeStyleSetHeight(root, 100);
+
+  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child0, 50);
+  YGNodeStyleSetHeight(root_child0, 10);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  const YGNodeRef root_child1 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child1, 50);
+  YGNodeStyleSetHeight(root_child1, 10);
+  YGNodeInsertChild(root, root_child1, 1);
+
+  const YGNodeRef root_child2 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child2, 50);
+  YGNodeStyleSetHeight(root_child2, 10);
+  YGNodeInsertChild(root, root_child2, 2);
+
+  const YGNodeRef root_child3 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child3, 50);
+  YGNodeStyleSetHeight(root_child3, 10);
+  YGNodeInsertChild(root, root_child3, 3);
+
+  const YGNodeRef root_child4 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child4, 50);
+  YGNodeStyleSetHeight(root_child4, 10);
+  YGNodeInsertChild(root, root_child4, 4);
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(130, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child1));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child2));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetTop(root_child2));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child2));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child2));
+
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetLeft(root_child3));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetTop(root_child3));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child3));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child3));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child4));
+  ASSERT_FLOAT_EQ(20, YGNodeLayoutGetTop(root_child4));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child4));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child4));
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(130, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(80, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(30, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child1));
+
+  ASSERT_FLOAT_EQ(80, YGNodeLayoutGetLeft(root_child2));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetTop(root_child2));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child2));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child2));
+
+  ASSERT_FLOAT_EQ(30, YGNodeLayoutGetLeft(root_child3));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetTop(root_child3));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child3));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child3));
+
+  ASSERT_FLOAT_EQ(80, YGNodeLayoutGetLeft(root_child4));
+  ASSERT_FLOAT_EQ(20, YGNodeLayoutGetTop(root_child4));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child4));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child4));
+
+  YGNodeFreeRecursive(root);
+
+  YGConfigFree(config);
+}
+
+TEST(YogaTest, align_content_flex_start_without_height_on_children) {
+  const YGConfigRef config = YGConfigNew();
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexWrap(root, YGWrapWrap);
+  YGNodeStyleSetWidth(root, 100);
+  YGNodeStyleSetHeight(root, 100);
+
+  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child0, 50);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  const YGNodeRef root_child1 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child1, 50);
+  YGNodeStyleSetHeight(root_child1, 10);
+  YGNodeInsertChild(root, root_child1, 1);
+
+  const YGNodeRef root_child2 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child2, 50);
+  YGNodeInsertChild(root, root_child2, 2);
+
+  const YGNodeRef root_child3 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child3, 50);
+  YGNodeStyleSetHeight(root_child3, 10);
+  YGNodeInsertChild(root, root_child3, 3);
+
+  const YGNodeRef root_child4 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child4, 50);
+  YGNodeInsertChild(root, root_child4, 4);
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child1));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child2));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetTop(root_child2));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child2));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetHeight(root_child2));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child3));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetTop(root_child3));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child3));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child3));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child4));
+  ASSERT_FLOAT_EQ(20, YGNodeLayoutGetTop(root_child4));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child4));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetHeight(root_child4));
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child1));
+
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetLeft(root_child2));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetTop(root_child2));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child2));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetHeight(root_child2));
+
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetLeft(root_child3));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetTop(root_child3));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child3));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child3));
+
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetLeft(root_child4));
+  ASSERT_FLOAT_EQ(20, YGNodeLayoutGetTop(root_child4));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child4));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetHeight(root_child4));
+
+  YGNodeFreeRecursive(root);
+
+  YGConfigFree(config);
+}
+
+TEST(YogaTest, align_content_flex_start_with_flex) {
+  const YGConfigRef config = YGConfigNew();
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexWrap(root, YGWrapWrap);
+  YGNodeStyleSetWidth(root, 100);
+  YGNodeStyleSetHeight(root, 120);
+
+  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexGrow(root_child0, 1);
+  YGNodeStyleSetFlexBasisPercent(root_child0, 0);
+  YGNodeStyleSetWidth(root_child0, 50);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  const YGNodeRef root_child1 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexGrow(root_child1, 1);
+  YGNodeStyleSetFlexBasisPercent(root_child1, 0);
+  YGNodeStyleSetWidth(root_child1, 50);
+  YGNodeStyleSetHeight(root_child1, 10);
+  YGNodeInsertChild(root, root_child1, 1);
+
+  const YGNodeRef root_child2 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child2, 50);
+  YGNodeInsertChild(root, root_child2, 2);
+
+  const YGNodeRef root_child3 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexGrow(root_child3, 1);
+  YGNodeStyleSetFlexShrink(root_child3, 1);
+  YGNodeStyleSetFlexBasisPercent(root_child3, 0);
+  YGNodeStyleSetWidth(root_child3, 50);
+  YGNodeInsertChild(root, root_child3, 3);
+
+  const YGNodeRef root_child4 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child4, 50);
+  YGNodeInsertChild(root, root_child4, 4);
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(120, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(40, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(40, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(40, YGNodeLayoutGetHeight(root_child1));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child2));
+  ASSERT_FLOAT_EQ(80, YGNodeLayoutGetTop(root_child2));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child2));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetHeight(root_child2));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child3));
+  ASSERT_FLOAT_EQ(80, YGNodeLayoutGetTop(root_child3));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child3));
+  ASSERT_FLOAT_EQ(40, YGNodeLayoutGetHeight(root_child3));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child4));
+  ASSERT_FLOAT_EQ(120, YGNodeLayoutGetTop(root_child4));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child4));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetHeight(root_child4));
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(120, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(40, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(40, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(40, YGNodeLayoutGetHeight(root_child1));
+
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetLeft(root_child2));
+  ASSERT_FLOAT_EQ(80, YGNodeLayoutGetTop(root_child2));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child2));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetHeight(root_child2));
+
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetLeft(root_child3));
+  ASSERT_FLOAT_EQ(80, YGNodeLayoutGetTop(root_child3));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child3));
+  ASSERT_FLOAT_EQ(40, YGNodeLayoutGetHeight(root_child3));
+
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetLeft(root_child4));
+  ASSERT_FLOAT_EQ(120, YGNodeLayoutGetTop(root_child4));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child4));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetHeight(root_child4));
+
+  YGNodeFreeRecursive(root);
+
+  YGConfigFree(config);
+}
+
+TEST(YogaTest, align_content_flex_end) {
+  const YGConfigRef config = YGConfigNew();
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  YGNodeStyleSetAlignContent(root, YGAlignFlexEnd);
+  YGNodeStyleSetFlexWrap(root, YGWrapWrap);
+  YGNodeStyleSetWidth(root, 100);
+  YGNodeStyleSetHeight(root, 100);
+
+  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child0, 50);
+  YGNodeStyleSetHeight(root_child0, 10);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  const YGNodeRef root_child1 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child1, 50);
+  YGNodeStyleSetHeight(root_child1, 10);
+  YGNodeInsertChild(root, root_child1, 1);
+
+  const YGNodeRef root_child2 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child2, 50);
+  YGNodeStyleSetHeight(root_child2, 10);
+  YGNodeInsertChild(root, root_child2, 2);
+
+  const YGNodeRef root_child3 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child3, 50);
+  YGNodeStyleSetHeight(root_child3, 10);
+  YGNodeInsertChild(root, root_child3, 3);
+
+  const YGNodeRef root_child4 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child4, 50);
+  YGNodeStyleSetHeight(root_child4, 10);
+  YGNodeInsertChild(root, root_child4, 4);
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child1));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child2));
+  ASSERT_FLOAT_EQ(20, YGNodeLayoutGetTop(root_child2));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child2));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child2));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child3));
+  ASSERT_FLOAT_EQ(30, YGNodeLayoutGetTop(root_child3));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child3));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child3));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child4));
+  ASSERT_FLOAT_EQ(40, YGNodeLayoutGetTop(root_child4));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child4));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child4));
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child1));
+
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetLeft(root_child2));
+  ASSERT_FLOAT_EQ(20, YGNodeLayoutGetTop(root_child2));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child2));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child2));
+
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetLeft(root_child3));
+  ASSERT_FLOAT_EQ(30, YGNodeLayoutGetTop(root_child3));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child3));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child3));
+
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetLeft(root_child4));
+  ASSERT_FLOAT_EQ(40, YGNodeLayoutGetTop(root_child4));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child4));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child4));
+
+  YGNodeFreeRecursive(root);
+
+  YGConfigFree(config);
+}
+
+TEST(YogaTest, align_content_stretch) {
+  const YGConfigRef config = YGConfigNew();
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  YGNodeStyleSetAlignContent(root, YGAlignStretch);
+  YGNodeStyleSetFlexWrap(root, YGWrapWrap);
+  YGNodeStyleSetWidth(root, 150);
+  YGNodeStyleSetHeight(root, 100);
+
+  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child0, 50);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  const YGNodeRef root_child1 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child1, 50);
+  YGNodeInsertChild(root, root_child1, 1);
+
+  const YGNodeRef root_child2 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child2, 50);
+  YGNodeInsertChild(root, root_child2, 2);
+
+  const YGNodeRef root_child3 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child3, 50);
+  YGNodeInsertChild(root, root_child3, 3);
+
+  const YGNodeRef root_child4 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child4, 50);
+  YGNodeInsertChild(root, root_child4, 4);
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(150, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetHeight(root_child1));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child2));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child2));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child2));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetHeight(root_child2));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child3));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child3));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child3));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetHeight(root_child3));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child4));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child4));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child4));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetHeight(root_child4));
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(150, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetHeight(root_child1));
+
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetLeft(root_child2));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child2));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child2));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetHeight(root_child2));
+
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetLeft(root_child3));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child3));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child3));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetHeight(root_child3));
+
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetLeft(root_child4));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child4));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child4));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetHeight(root_child4));
+
+  YGNodeFreeRecursive(root);
+
+  YGConfigFree(config);
+}
+
+TEST(YogaTest, align_content_spacebetween) {
+  const YGConfigRef config = YGConfigNew();
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexDirection(root, YGFlexDirectionRow);
+  YGNodeStyleSetAlignContent(root, YGAlignSpaceBetween);
+  YGNodeStyleSetFlexWrap(root, YGWrapWrap);
+  YGNodeStyleSetWidth(root, 130);
+  YGNodeStyleSetHeight(root, 100);
+
+  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child0, 50);
+  YGNodeStyleSetHeight(root_child0, 10);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  const YGNodeRef root_child1 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child1, 50);
+  YGNodeStyleSetHeight(root_child1, 10);
+  YGNodeInsertChild(root, root_child1, 1);
+
+  const YGNodeRef root_child2 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child2, 50);
+  YGNodeStyleSetHeight(root_child2, 10);
+  YGNodeInsertChild(root, root_child2, 2);
+
+  const YGNodeRef root_child3 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child3, 50);
+  YGNodeStyleSetHeight(root_child3, 10);
+  YGNodeInsertChild(root, root_child3, 3);
+
+  const YGNodeRef root_child4 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child4, 50);
+  YGNodeStyleSetHeight(root_child4, 10);
+  YGNodeInsertChild(root, root_child4, 4);
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(130, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child1));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child2));
+  ASSERT_FLOAT_EQ(45, YGNodeLayoutGetTop(root_child2));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child2));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child2));
+
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetLeft(root_child3));
+  ASSERT_FLOAT_EQ(45, YGNodeLayoutGetTop(root_child3));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child3));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child3));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child4));
+  ASSERT_FLOAT_EQ(90, YGNodeLayoutGetTop(root_child4));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child4));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child4));
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(130, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(80, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(30, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child1));
+
+  ASSERT_FLOAT_EQ(80, YGNodeLayoutGetLeft(root_child2));
+  ASSERT_FLOAT_EQ(45, YGNodeLayoutGetTop(root_child2));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child2));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child2));
+
+  ASSERT_FLOAT_EQ(30, YGNodeLayoutGetLeft(root_child3));
+  ASSERT_FLOAT_EQ(45, YGNodeLayoutGetTop(root_child3));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child3));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child3));
+
+  ASSERT_FLOAT_EQ(80, YGNodeLayoutGetLeft(root_child4));
+  ASSERT_FLOAT_EQ(90, YGNodeLayoutGetTop(root_child4));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child4));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child4));
+
+  YGNodeFreeRecursive(root);
+
+  YGConfigFree(config);
+}
+
+TEST(YogaTest, align_content_spacearound) {
+  const YGConfigRef config = YGConfigNew();
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexDirection(root, YGFlexDirectionRow);
+  YGNodeStyleSetAlignContent(root, YGAlignSpaceAround);
+  YGNodeStyleSetFlexWrap(root, YGWrapWrap);
+  YGNodeStyleSetWidth(root, 140);
+  YGNodeStyleSetHeight(root, 120);
+
+  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child0, 50);
+  YGNodeStyleSetHeight(root_child0, 10);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  const YGNodeRef root_child1 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child1, 50);
+  YGNodeStyleSetHeight(root_child1, 10);
+  YGNodeInsertChild(root, root_child1, 1);
+
+  const YGNodeRef root_child2 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child2, 50);
+  YGNodeStyleSetHeight(root_child2, 10);
+  YGNodeInsertChild(root, root_child2, 2);
+
+  const YGNodeRef root_child3 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child3, 50);
+  YGNodeStyleSetHeight(root_child3, 10);
+  YGNodeInsertChild(root, root_child3, 3);
+
+  const YGNodeRef root_child4 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child4, 50);
+  YGNodeStyleSetHeight(root_child4, 10);
+  YGNodeInsertChild(root, root_child4, 4);
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(140, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(120, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(15, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(15, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child1));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child2));
+  ASSERT_FLOAT_EQ(55, YGNodeLayoutGetTop(root_child2));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child2));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child2));
+
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetLeft(root_child3));
+  ASSERT_FLOAT_EQ(55, YGNodeLayoutGetTop(root_child3));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child3));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child3));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child4));
+  ASSERT_FLOAT_EQ(95, YGNodeLayoutGetTop(root_child4));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child4));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child4));
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(140, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(120, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(90, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(15, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(40, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(15, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child1));
+
+  ASSERT_FLOAT_EQ(90, YGNodeLayoutGetLeft(root_child2));
+  ASSERT_FLOAT_EQ(55, YGNodeLayoutGetTop(root_child2));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child2));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child2));
+
+  ASSERT_FLOAT_EQ(40, YGNodeLayoutGetLeft(root_child3));
+  ASSERT_FLOAT_EQ(55, YGNodeLayoutGetTop(root_child3));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child3));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child3));
+
+  ASSERT_FLOAT_EQ(90, YGNodeLayoutGetLeft(root_child4));
+  ASSERT_FLOAT_EQ(95, YGNodeLayoutGetTop(root_child4));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child4));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child4));
+
+  YGNodeFreeRecursive(root);
+
+  YGConfigFree(config);
+}
+
+TEST(YogaTest, align_content_stretch_row) {
+  const YGConfigRef config = YGConfigNew();
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexDirection(root, YGFlexDirectionRow);
+  YGNodeStyleSetAlignContent(root, YGAlignStretch);
+  YGNodeStyleSetFlexWrap(root, YGWrapWrap);
+  YGNodeStyleSetWidth(root, 150);
+  YGNodeStyleSetHeight(root, 100);
+
+  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child0, 50);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  const YGNodeRef root_child1 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child1, 50);
+  YGNodeInsertChild(root, root_child1, 1);
+
+  const YGNodeRef root_child2 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child2, 50);
+  YGNodeInsertChild(root, root_child2, 2);
+
+  const YGNodeRef root_child3 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child3, 50);
+  YGNodeInsertChild(root, root_child3, 3);
+
+  const YGNodeRef root_child4 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child4, 50);
+  YGNodeInsertChild(root, root_child4, 4);
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(150, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child1));
+
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetLeft(root_child2));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child2));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child2));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child2));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child3));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetTop(root_child3));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child3));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child3));
+
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetLeft(root_child4));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetTop(root_child4));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child4));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child4));
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(150, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child1));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child2));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child2));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child2));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child2));
+
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetLeft(root_child3));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetTop(root_child3));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child3));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child3));
+
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetLeft(root_child4));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetTop(root_child4));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child4));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child4));
+
+  YGNodeFreeRecursive(root);
+
+  YGConfigFree(config);
+}
+
+TEST(YogaTest, align_content_stretch_row_with_children) {
+  const YGConfigRef config = YGConfigNew();
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexDirection(root, YGFlexDirectionRow);
+  YGNodeStyleSetAlignContent(root, YGAlignStretch);
+  YGNodeStyleSetFlexWrap(root, YGWrapWrap);
+  YGNodeStyleSetWidth(root, 150);
+  YGNodeStyleSetHeight(root, 100);
+
+  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child0, 50);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  const YGNodeRef root_child0_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexGrow(root_child0_child0, 1);
+  YGNodeStyleSetFlexShrink(root_child0_child0, 1);
+  YGNodeStyleSetFlexBasisPercent(root_child0_child0, 0);
+  YGNodeInsertChild(root_child0, root_child0_child0, 0);
+
+  const YGNodeRef root_child1 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child1, 50);
+  YGNodeInsertChild(root, root_child1, 1);
+
+  const YGNodeRef root_child2 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child2, 50);
+  YGNodeInsertChild(root, root_child2, 2);
+
+  const YGNodeRef root_child3 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child3, 50);
+  YGNodeInsertChild(root, root_child3, 3);
+
+  const YGNodeRef root_child4 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child4, 50);
+  YGNodeInsertChild(root, root_child4, 4);
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(150, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child0_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child0_child0));
+
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child1));
+
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetLeft(root_child2));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child2));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child2));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child2));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child3));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetTop(root_child3));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child3));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child3));
+
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetLeft(root_child4));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetTop(root_child4));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child4));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child4));
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(150, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child0_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child0_child0));
+
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child1));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child2));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child2));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child2));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child2));
+
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetLeft(root_child3));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetTop(root_child3));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child3));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child3));
+
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetLeft(root_child4));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetTop(root_child4));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child4));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child4));
+
+  YGNodeFreeRecursive(root);
+
+  YGConfigFree(config);
+}
+
+TEST(YogaTest, align_content_stretch_row_with_flex) {
+  const YGConfigRef config = YGConfigNew();
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexDirection(root, YGFlexDirectionRow);
+  YGNodeStyleSetAlignContent(root, YGAlignStretch);
+  YGNodeStyleSetFlexWrap(root, YGWrapWrap);
+  YGNodeStyleSetWidth(root, 150);
+  YGNodeStyleSetHeight(root, 100);
+
+  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child0, 50);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  const YGNodeRef root_child1 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexGrow(root_child1, 1);
+  YGNodeStyleSetFlexShrink(root_child1, 1);
+  YGNodeStyleSetFlexBasisPercent(root_child1, 0);
+  YGNodeStyleSetWidth(root_child1, 50);
+  YGNodeInsertChild(root, root_child1, 1);
+
+  const YGNodeRef root_child2 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child2, 50);
+  YGNodeInsertChild(root, root_child2, 2);
+
+  const YGNodeRef root_child3 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexGrow(root_child3, 1);
+  YGNodeStyleSetFlexShrink(root_child3, 1);
+  YGNodeStyleSetFlexBasisPercent(root_child3, 0);
+  YGNodeStyleSetWidth(root_child3, 50);
+  YGNodeInsertChild(root, root_child3, 3);
+
+  const YGNodeRef root_child4 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child4, 50);
+  YGNodeInsertChild(root, root_child4, 4);
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(150, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child1));
+
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetLeft(root_child2));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child2));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child2));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child2));
+
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetLeft(root_child3));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child3));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetWidth(root_child3));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child3));
+
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetLeft(root_child4));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child4));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child4));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child4));
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(150, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child1));
+
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetLeft(root_child2));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child2));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child2));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child2));
+
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetLeft(root_child3));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child3));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetWidth(root_child3));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child3));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child4));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child4));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child4));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child4));
+
+  YGNodeFreeRecursive(root);
+
+  YGConfigFree(config);
+}
+
+TEST(YogaTest, align_content_stretch_row_with_flex_no_shrink) {
+  const YGConfigRef config = YGConfigNew();
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexDirection(root, YGFlexDirectionRow);
+  YGNodeStyleSetAlignContent(root, YGAlignStretch);
+  YGNodeStyleSetFlexWrap(root, YGWrapWrap);
+  YGNodeStyleSetWidth(root, 150);
+  YGNodeStyleSetHeight(root, 100);
+
+  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child0, 50);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  const YGNodeRef root_child1 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexGrow(root_child1, 1);
+  YGNodeStyleSetFlexShrink(root_child1, 1);
+  YGNodeStyleSetFlexBasisPercent(root_child1, 0);
+  YGNodeStyleSetWidth(root_child1, 50);
+  YGNodeInsertChild(root, root_child1, 1);
+
+  const YGNodeRef root_child2 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child2, 50);
+  YGNodeInsertChild(root, root_child2, 2);
+
+  const YGNodeRef root_child3 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexGrow(root_child3, 1);
+  YGNodeStyleSetFlexBasisPercent(root_child3, 0);
+  YGNodeStyleSetWidth(root_child3, 50);
+  YGNodeInsertChild(root, root_child3, 3);
+
+  const YGNodeRef root_child4 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child4, 50);
+  YGNodeInsertChild(root, root_child4, 4);
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(150, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child1));
+
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetLeft(root_child2));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child2));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child2));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child2));
+
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetLeft(root_child3));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child3));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetWidth(root_child3));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child3));
+
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetLeft(root_child4));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child4));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child4));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child4));
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(150, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child1));
+
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetLeft(root_child2));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child2));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child2));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child2));
+
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetLeft(root_child3));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child3));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetWidth(root_child3));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child3));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child4));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child4));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child4));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child4));
+
+  YGNodeFreeRecursive(root);
+
+  YGConfigFree(config);
+}
+
+TEST(YogaTest, align_content_stretch_row_with_margin) {
+  const YGConfigRef config = YGConfigNew();
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexDirection(root, YGFlexDirectionRow);
+  YGNodeStyleSetAlignContent(root, YGAlignStretch);
+  YGNodeStyleSetFlexWrap(root, YGWrapWrap);
+  YGNodeStyleSetWidth(root, 150);
+  YGNodeStyleSetHeight(root, 100);
+
+  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child0, 50);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  const YGNodeRef root_child1 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetMargin(root_child1, YGEdgeLeft, 10);
+  YGNodeStyleSetMargin(root_child1, YGEdgeTop, 10);
+  YGNodeStyleSetMargin(root_child1, YGEdgeRight, 10);
+  YGNodeStyleSetMargin(root_child1, YGEdgeBottom, 10);
+  YGNodeStyleSetWidth(root_child1, 50);
+  YGNodeInsertChild(root, root_child1, 1);
+
+  const YGNodeRef root_child2 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child2, 50);
+  YGNodeInsertChild(root, root_child2, 2);
+
+  const YGNodeRef root_child3 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetMargin(root_child3, YGEdgeLeft, 10);
+  YGNodeStyleSetMargin(root_child3, YGEdgeTop, 10);
+  YGNodeStyleSetMargin(root_child3, YGEdgeRight, 10);
+  YGNodeStyleSetMargin(root_child3, YGEdgeBottom, 10);
+  YGNodeStyleSetWidth(root_child3, 50);
+  YGNodeInsertChild(root, root_child3, 3);
+
+  const YGNodeRef root_child4 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child4, 50);
+  YGNodeInsertChild(root, root_child4, 4);
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(150, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(40, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(60, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(20, YGNodeLayoutGetHeight(root_child1));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child2));
+  ASSERT_FLOAT_EQ(40, YGNodeLayoutGetTop(root_child2));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child2));
+  ASSERT_FLOAT_EQ(40, YGNodeLayoutGetHeight(root_child2));
+
+  ASSERT_FLOAT_EQ(60, YGNodeLayoutGetLeft(root_child3));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetTop(root_child3));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child3));
+  ASSERT_FLOAT_EQ(20, YGNodeLayoutGetHeight(root_child3));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child4));
+  ASSERT_FLOAT_EQ(80, YGNodeLayoutGetTop(root_child4));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child4));
+  ASSERT_FLOAT_EQ(20, YGNodeLayoutGetHeight(root_child4));
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(150, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(40, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(40, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(20, YGNodeLayoutGetHeight(root_child1));
+
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetLeft(root_child2));
+  ASSERT_FLOAT_EQ(40, YGNodeLayoutGetTop(root_child2));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child2));
+  ASSERT_FLOAT_EQ(40, YGNodeLayoutGetHeight(root_child2));
+
+  ASSERT_FLOAT_EQ(40, YGNodeLayoutGetLeft(root_child3));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetTop(root_child3));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child3));
+  ASSERT_FLOAT_EQ(20, YGNodeLayoutGetHeight(root_child3));
+
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetLeft(root_child4));
+  ASSERT_FLOAT_EQ(80, YGNodeLayoutGetTop(root_child4));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child4));
+  ASSERT_FLOAT_EQ(20, YGNodeLayoutGetHeight(root_child4));
+
+  YGNodeFreeRecursive(root);
+
+  YGConfigFree(config);
+}
+
+TEST(YogaTest, align_content_stretch_row_with_padding) {
+  const YGConfigRef config = YGConfigNew();
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexDirection(root, YGFlexDirectionRow);
+  YGNodeStyleSetAlignContent(root, YGAlignStretch);
+  YGNodeStyleSetFlexWrap(root, YGWrapWrap);
+  YGNodeStyleSetWidth(root, 150);
+  YGNodeStyleSetHeight(root, 100);
+
+  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child0, 50);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  const YGNodeRef root_child1 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetPadding(root_child1, YGEdgeLeft, 10);
+  YGNodeStyleSetPadding(root_child1, YGEdgeTop, 10);
+  YGNodeStyleSetPadding(root_child1, YGEdgeRight, 10);
+  YGNodeStyleSetPadding(root_child1, YGEdgeBottom, 10);
+  YGNodeStyleSetWidth(root_child1, 50);
+  YGNodeInsertChild(root, root_child1, 1);
+
+  const YGNodeRef root_child2 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child2, 50);
+  YGNodeInsertChild(root, root_child2, 2);
+
+  const YGNodeRef root_child3 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetPadding(root_child3, YGEdgeLeft, 10);
+  YGNodeStyleSetPadding(root_child3, YGEdgeTop, 10);
+  YGNodeStyleSetPadding(root_child3, YGEdgeRight, 10);
+  YGNodeStyleSetPadding(root_child3, YGEdgeBottom, 10);
+  YGNodeStyleSetWidth(root_child3, 50);
+  YGNodeInsertChild(root, root_child3, 3);
+
+  const YGNodeRef root_child4 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child4, 50);
+  YGNodeInsertChild(root, root_child4, 4);
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(150, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child1));
+
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetLeft(root_child2));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child2));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child2));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child2));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child3));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetTop(root_child3));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child3));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child3));
+
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetLeft(root_child4));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetTop(root_child4));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child4));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child4));
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(150, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child1));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child2));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child2));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child2));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child2));
+
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetLeft(root_child3));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetTop(root_child3));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child3));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child3));
+
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetLeft(root_child4));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetTop(root_child4));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child4));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child4));
+
+  YGNodeFreeRecursive(root);
+
+  YGConfigFree(config);
+}
+
+TEST(YogaTest, align_content_stretch_row_with_single_row) {
+  const YGConfigRef config = YGConfigNew();
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexDirection(root, YGFlexDirectionRow);
+  YGNodeStyleSetAlignContent(root, YGAlignStretch);
+  YGNodeStyleSetFlexWrap(root, YGWrapWrap);
+  YGNodeStyleSetWidth(root, 150);
+  YGNodeStyleSetHeight(root, 100);
+
+  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child0, 50);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  const YGNodeRef root_child1 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child1, 50);
+  YGNodeInsertChild(root, root_child1, 1);
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(150, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child1));
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(150, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child1));
+
+  YGNodeFreeRecursive(root);
+
+  YGConfigFree(config);
+}
+
+TEST(YogaTest, align_content_stretch_row_with_fixed_height) {
+  const YGConfigRef config = YGConfigNew();
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexDirection(root, YGFlexDirectionRow);
+  YGNodeStyleSetAlignContent(root, YGAlignStretch);
+  YGNodeStyleSetFlexWrap(root, YGWrapWrap);
+  YGNodeStyleSetWidth(root, 150);
+  YGNodeStyleSetHeight(root, 100);
+
+  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child0, 50);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  const YGNodeRef root_child1 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child1, 50);
+  YGNodeStyleSetHeight(root_child1, 60);
+  YGNodeInsertChild(root, root_child1, 1);
+
+  const YGNodeRef root_child2 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child2, 50);
+  YGNodeInsertChild(root, root_child2, 2);
+
+  const YGNodeRef root_child3 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child3, 50);
+  YGNodeInsertChild(root, root_child3, 3);
+
+  const YGNodeRef root_child4 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child4, 50);
+  YGNodeInsertChild(root, root_child4, 4);
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(150, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(80, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(60, YGNodeLayoutGetHeight(root_child1));
+
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetLeft(root_child2));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child2));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child2));
+  ASSERT_FLOAT_EQ(80, YGNodeLayoutGetHeight(root_child2));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child3));
+  ASSERT_FLOAT_EQ(80, YGNodeLayoutGetTop(root_child3));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child3));
+  ASSERT_FLOAT_EQ(20, YGNodeLayoutGetHeight(root_child3));
+
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetLeft(root_child4));
+  ASSERT_FLOAT_EQ(80, YGNodeLayoutGetTop(root_child4));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child4));
+  ASSERT_FLOAT_EQ(20, YGNodeLayoutGetHeight(root_child4));
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(150, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(80, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(60, YGNodeLayoutGetHeight(root_child1));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child2));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child2));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child2));
+  ASSERT_FLOAT_EQ(80, YGNodeLayoutGetHeight(root_child2));
+
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetLeft(root_child3));
+  ASSERT_FLOAT_EQ(80, YGNodeLayoutGetTop(root_child3));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child3));
+  ASSERT_FLOAT_EQ(20, YGNodeLayoutGetHeight(root_child3));
+
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetLeft(root_child4));
+  ASSERT_FLOAT_EQ(80, YGNodeLayoutGetTop(root_child4));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child4));
+  ASSERT_FLOAT_EQ(20, YGNodeLayoutGetHeight(root_child4));
+
+  YGNodeFreeRecursive(root);
+
+  YGConfigFree(config);
+}
+
+TEST(YogaTest, align_content_stretch_row_with_max_height) {
+  const YGConfigRef config = YGConfigNew();
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexDirection(root, YGFlexDirectionRow);
+  YGNodeStyleSetAlignContent(root, YGAlignStretch);
+  YGNodeStyleSetFlexWrap(root, YGWrapWrap);
+  YGNodeStyleSetWidth(root, 150);
+  YGNodeStyleSetHeight(root, 100);
+
+  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child0, 50);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  const YGNodeRef root_child1 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child1, 50);
+  YGNodeStyleSetMaxHeight(root_child1, 20);
+  YGNodeInsertChild(root, root_child1, 1);
+
+  const YGNodeRef root_child2 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child2, 50);
+  YGNodeInsertChild(root, root_child2, 2);
+
+  const YGNodeRef root_child3 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child3, 50);
+  YGNodeInsertChild(root, root_child3, 3);
+
+  const YGNodeRef root_child4 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child4, 50);
+  YGNodeInsertChild(root, root_child4, 4);
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(150, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(20, YGNodeLayoutGetHeight(root_child1));
+
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetLeft(root_child2));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child2));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child2));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child2));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child3));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetTop(root_child3));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child3));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child3));
+
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetLeft(root_child4));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetTop(root_child4));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child4));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child4));
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(150, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(20, YGNodeLayoutGetHeight(root_child1));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child2));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child2));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child2));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child2));
+
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetLeft(root_child3));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetTop(root_child3));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child3));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child3));
+
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetLeft(root_child4));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetTop(root_child4));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child4));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child4));
+
+  YGNodeFreeRecursive(root);
+
+  YGConfigFree(config);
+}
+
+TEST(YogaTest, align_content_stretch_row_with_min_height) {
+  const YGConfigRef config = YGConfigNew();
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexDirection(root, YGFlexDirectionRow);
+  YGNodeStyleSetAlignContent(root, YGAlignStretch);
+  YGNodeStyleSetFlexWrap(root, YGWrapWrap);
+  YGNodeStyleSetWidth(root, 150);
+  YGNodeStyleSetHeight(root, 100);
+
+  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child0, 50);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  const YGNodeRef root_child1 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child1, 50);
+  YGNodeStyleSetMinHeight(root_child1, 80);
+  YGNodeInsertChild(root, root_child1, 1);
+
+  const YGNodeRef root_child2 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child2, 50);
+  YGNodeInsertChild(root, root_child2, 2);
+
+  const YGNodeRef root_child3 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child3, 50);
+  YGNodeInsertChild(root, root_child3, 3);
+
+  const YGNodeRef root_child4 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child4, 50);
+  YGNodeInsertChild(root, root_child4, 4);
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(150, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(90, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(90, YGNodeLayoutGetHeight(root_child1));
+
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetLeft(root_child2));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child2));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child2));
+  ASSERT_FLOAT_EQ(90, YGNodeLayoutGetHeight(root_child2));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child3));
+  ASSERT_FLOAT_EQ(90, YGNodeLayoutGetTop(root_child3));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child3));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child3));
+
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetLeft(root_child4));
+  ASSERT_FLOAT_EQ(90, YGNodeLayoutGetTop(root_child4));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child4));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child4));
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(150, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(90, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(90, YGNodeLayoutGetHeight(root_child1));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child2));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child2));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child2));
+  ASSERT_FLOAT_EQ(90, YGNodeLayoutGetHeight(root_child2));
+
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetLeft(root_child3));
+  ASSERT_FLOAT_EQ(90, YGNodeLayoutGetTop(root_child3));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child3));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child3));
+
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetLeft(root_child4));
+  ASSERT_FLOAT_EQ(90, YGNodeLayoutGetTop(root_child4));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child4));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child4));
+
+  YGNodeFreeRecursive(root);
+
+  YGConfigFree(config);
+}
+
+TEST(YogaTest, align_content_stretch_column) {
+  const YGConfigRef config = YGConfigNew();
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  YGNodeStyleSetAlignContent(root, YGAlignStretch);
+  YGNodeStyleSetFlexWrap(root, YGWrapWrap);
+  YGNodeStyleSetWidth(root, 100);
+  YGNodeStyleSetHeight(root, 150);
+
+  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetHeight(root_child0, 50);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  const YGNodeRef root_child0_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexGrow(root_child0_child0, 1);
+  YGNodeStyleSetFlexShrink(root_child0_child0, 1);
+  YGNodeStyleSetFlexBasisPercent(root_child0_child0, 0);
+  YGNodeInsertChild(root_child0, root_child0_child0, 0);
+
+  const YGNodeRef root_child1 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexGrow(root_child1, 1);
+  YGNodeStyleSetFlexShrink(root_child1, 1);
+  YGNodeStyleSetFlexBasisPercent(root_child1, 0);
+  YGNodeStyleSetHeight(root_child1, 50);
+  YGNodeInsertChild(root, root_child1, 1);
+
+  const YGNodeRef root_child2 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetHeight(root_child2, 50);
+  YGNodeInsertChild(root, root_child2, 2);
+
+  const YGNodeRef root_child3 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetHeight(root_child3, 50);
+  YGNodeInsertChild(root, root_child3, 3);
+
+  const YGNodeRef root_child4 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetHeight(root_child4, 50);
+  YGNodeInsertChild(root, root_child4, 4);
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(150, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child0_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child0_child0));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetHeight(root_child1));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child2));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetTop(root_child2));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child2));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child2));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child3));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetTop(root_child3));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child3));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child3));
+
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetLeft(root_child4));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child4));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child4));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child4));
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(150, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child0_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child0_child0));
+
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetHeight(root_child1));
+
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetLeft(root_child2));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetTop(root_child2));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child2));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child2));
+
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetLeft(root_child3));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetTop(root_child3));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child3));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child3));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child4));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child4));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child4));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child4));
+
+  YGNodeFreeRecursive(root);
+
+  YGConfigFree(config);
+}
+
+TEST(YogaTest, align_content_stretch_is_not_overriding_align_items) {
+  const YGConfigRef config = YGConfigNew();
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  YGNodeStyleSetAlignContent(root, YGAlignStretch);
+
+  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexDirection(root_child0, YGFlexDirectionRow);
+  YGNodeStyleSetAlignContent(root_child0, YGAlignStretch);
+  YGNodeStyleSetAlignItems(root_child0, YGAlignCenter);
+  YGNodeStyleSetWidth(root_child0, 100);
+  YGNodeStyleSetHeight(root_child0, 100);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  const YGNodeRef root_child0_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetAlignContent(root_child0_child0, YGAlignStretch);
+  YGNodeStyleSetWidth(root_child0_child0, 10);
+  YGNodeStyleSetHeight(root_child0_child0, 10);
+  YGNodeInsertChild(root_child0, root_child0_child0, 0);
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0_child0));
+  ASSERT_FLOAT_EQ(45, YGNodeLayoutGetTop(root_child0_child0));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetWidth(root_child0_child0));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child0_child0));
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(90, YGNodeLayoutGetLeft(root_child0_child0));
+  ASSERT_FLOAT_EQ(45, YGNodeLayoutGetTop(root_child0_child0));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetWidth(root_child0_child0));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child0_child0));
+
+  YGNodeFreeRecursive(root);
+
+  YGConfigFree(config);
+}
diff --git a/automated-tests/src/dali-toolkit-third-party/yoga/YGAlignItemsTest.cpp b/automated-tests/src/dali-toolkit-third-party/yoga/YGAlignItemsTest.cpp
new file mode 100644 (file)
index 0000000..fd5e424
--- /dev/null
@@ -0,0 +1,2158 @@
+/**
+ * Copyright (c) 2014-present, Facebook, Inc.
+ *
+ * This source code is licensed under the MIT license found in the
+ * LICENSE file in the root directory of this source tree.
+ */
+
+// @Generated by gentest/gentest.rb from gentest/fixtures/YGAlignItemsTest.html
+
+#include <gtest/gtest.h>
+#include <yoga/Yoga.h>
+
+TEST(YogaTest, align_items_stretch) {
+  const YGConfigRef config = YGConfigNew();
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root, 100);
+  YGNodeStyleSetHeight(root, 100);
+
+  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetHeight(root_child0, 10);
+  YGNodeInsertChild(root, root_child0, 0);
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child0));
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child0));
+
+  YGNodeFreeRecursive(root);
+
+  YGConfigFree(config);
+}
+
+TEST(YogaTest, align_items_center) {
+  const YGConfigRef config = YGConfigNew();
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  YGNodeStyleSetAlignItems(root, YGAlignCenter);
+  YGNodeStyleSetWidth(root, 100);
+  YGNodeStyleSetHeight(root, 100);
+
+  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child0, 10);
+  YGNodeStyleSetHeight(root_child0, 10);
+  YGNodeInsertChild(root, root_child0, 0);
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(45, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child0));
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(45, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child0));
+
+  YGNodeFreeRecursive(root);
+
+  YGConfigFree(config);
+}
+
+TEST(YogaTest, align_items_flex_start) {
+  const YGConfigRef config = YGConfigNew();
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  YGNodeStyleSetAlignItems(root, YGAlignFlexStart);
+  YGNodeStyleSetWidth(root, 100);
+  YGNodeStyleSetHeight(root, 100);
+
+  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child0, 10);
+  YGNodeStyleSetHeight(root_child0, 10);
+  YGNodeInsertChild(root, root_child0, 0);
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child0));
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(90, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child0));
+
+  YGNodeFreeRecursive(root);
+
+  YGConfigFree(config);
+}
+
+TEST(YogaTest, align_items_flex_end) {
+  const YGConfigRef config = YGConfigNew();
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  YGNodeStyleSetAlignItems(root, YGAlignFlexEnd);
+  YGNodeStyleSetWidth(root, 100);
+  YGNodeStyleSetHeight(root, 100);
+
+  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child0, 10);
+  YGNodeStyleSetHeight(root_child0, 10);
+  YGNodeInsertChild(root, root_child0, 0);
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(90, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child0));
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child0));
+
+  YGNodeFreeRecursive(root);
+
+  YGConfigFree(config);
+}
+
+TEST(YogaTest, align_baseline) {
+  const YGConfigRef config = YGConfigNew();
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexDirection(root, YGFlexDirectionRow);
+  YGNodeStyleSetAlignItems(root, YGAlignBaseline);
+  YGNodeStyleSetWidth(root, 100);
+  YGNodeStyleSetHeight(root, 100);
+
+  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child0, 50);
+  YGNodeStyleSetHeight(root_child0, 50);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  const YGNodeRef root_child1 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child1, 50);
+  YGNodeStyleSetHeight(root_child1, 20);
+  YGNodeInsertChild(root, root_child1, 1);
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(30, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(20, YGNodeLayoutGetHeight(root_child1));
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(30, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(20, YGNodeLayoutGetHeight(root_child1));
+
+  YGNodeFreeRecursive(root);
+
+  YGConfigFree(config);
+}
+
+TEST(YogaTest, align_baseline_child) {
+  const YGConfigRef config = YGConfigNew();
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexDirection(root, YGFlexDirectionRow);
+  YGNodeStyleSetAlignItems(root, YGAlignBaseline);
+  YGNodeStyleSetWidth(root, 100);
+  YGNodeStyleSetHeight(root, 100);
+
+  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child0, 50);
+  YGNodeStyleSetHeight(root_child0, 50);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  const YGNodeRef root_child1 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child1, 50);
+  YGNodeStyleSetHeight(root_child1, 20);
+  YGNodeInsertChild(root, root_child1, 1);
+
+  const YGNodeRef root_child1_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child1_child0, 50);
+  YGNodeStyleSetHeight(root_child1_child0, 10);
+  YGNodeInsertChild(root_child1, root_child1_child0, 0);
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(40, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(20, YGNodeLayoutGetHeight(root_child1));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child1_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child1_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child1_child0));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child1_child0));
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(40, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(20, YGNodeLayoutGetHeight(root_child1));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child1_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child1_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child1_child0));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child1_child0));
+
+  YGNodeFreeRecursive(root);
+
+  YGConfigFree(config);
+}
+
+TEST(YogaTest, align_baseline_child_multiline) {
+  const YGConfigRef config = YGConfigNew();
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexDirection(root, YGFlexDirectionRow);
+  YGNodeStyleSetAlignItems(root, YGAlignBaseline);
+  YGNodeStyleSetWidth(root, 100);
+  YGNodeStyleSetHeight(root, 100);
+
+  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child0, 50);
+  YGNodeStyleSetHeight(root_child0, 60);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  const YGNodeRef root_child1 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexDirection(root_child1, YGFlexDirectionRow);
+  YGNodeStyleSetFlexWrap(root_child1, YGWrapWrap);
+  YGNodeStyleSetWidth(root_child1, 50);
+  YGNodeStyleSetHeight(root_child1, 25);
+  YGNodeInsertChild(root, root_child1, 1);
+
+  const YGNodeRef root_child1_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child1_child0, 25);
+  YGNodeStyleSetHeight(root_child1_child0, 20);
+  YGNodeInsertChild(root_child1, root_child1_child0, 0);
+
+  const YGNodeRef root_child1_child1 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child1_child1, 25);
+  YGNodeStyleSetHeight(root_child1_child1, 10);
+  YGNodeInsertChild(root_child1, root_child1_child1, 1);
+
+  const YGNodeRef root_child1_child2 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child1_child2, 25);
+  YGNodeStyleSetHeight(root_child1_child2, 20);
+  YGNodeInsertChild(root_child1, root_child1_child2, 2);
+
+  const YGNodeRef root_child1_child3 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child1_child3, 25);
+  YGNodeStyleSetHeight(root_child1_child3, 10);
+  YGNodeInsertChild(root_child1, root_child1_child3, 3);
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(60, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(40, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(25, YGNodeLayoutGetHeight(root_child1));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child1_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child1_child0));
+  ASSERT_FLOAT_EQ(25, YGNodeLayoutGetWidth(root_child1_child0));
+  ASSERT_FLOAT_EQ(20, YGNodeLayoutGetHeight(root_child1_child0));
+
+  ASSERT_FLOAT_EQ(25, YGNodeLayoutGetLeft(root_child1_child1));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child1_child1));
+  ASSERT_FLOAT_EQ(25, YGNodeLayoutGetWidth(root_child1_child1));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child1_child1));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child1_child2));
+  ASSERT_FLOAT_EQ(20, YGNodeLayoutGetTop(root_child1_child2));
+  ASSERT_FLOAT_EQ(25, YGNodeLayoutGetWidth(root_child1_child2));
+  ASSERT_FLOAT_EQ(20, YGNodeLayoutGetHeight(root_child1_child2));
+
+  ASSERT_FLOAT_EQ(25, YGNodeLayoutGetLeft(root_child1_child3));
+  ASSERT_FLOAT_EQ(20, YGNodeLayoutGetTop(root_child1_child3));
+  ASSERT_FLOAT_EQ(25, YGNodeLayoutGetWidth(root_child1_child3));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child1_child3));
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(60, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(40, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(25, YGNodeLayoutGetHeight(root_child1));
+
+  ASSERT_FLOAT_EQ(25, YGNodeLayoutGetLeft(root_child1_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child1_child0));
+  ASSERT_FLOAT_EQ(25, YGNodeLayoutGetWidth(root_child1_child0));
+  ASSERT_FLOAT_EQ(20, YGNodeLayoutGetHeight(root_child1_child0));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child1_child1));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child1_child1));
+  ASSERT_FLOAT_EQ(25, YGNodeLayoutGetWidth(root_child1_child1));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child1_child1));
+
+  ASSERT_FLOAT_EQ(25, YGNodeLayoutGetLeft(root_child1_child2));
+  ASSERT_FLOAT_EQ(20, YGNodeLayoutGetTop(root_child1_child2));
+  ASSERT_FLOAT_EQ(25, YGNodeLayoutGetWidth(root_child1_child2));
+  ASSERT_FLOAT_EQ(20, YGNodeLayoutGetHeight(root_child1_child2));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child1_child3));
+  ASSERT_FLOAT_EQ(20, YGNodeLayoutGetTop(root_child1_child3));
+  ASSERT_FLOAT_EQ(25, YGNodeLayoutGetWidth(root_child1_child3));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child1_child3));
+
+  YGNodeFreeRecursive(root);
+
+  YGConfigFree(config);
+}
+
+TEST(YogaTest, align_baseline_child_multiline_override) {
+  const YGConfigRef config = YGConfigNew();
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexDirection(root, YGFlexDirectionRow);
+  YGNodeStyleSetAlignItems(root, YGAlignBaseline);
+  YGNodeStyleSetWidth(root, 100);
+  YGNodeStyleSetHeight(root, 100);
+
+  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child0, 50);
+  YGNodeStyleSetHeight(root_child0, 60);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  const YGNodeRef root_child1 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexDirection(root_child1, YGFlexDirectionRow);
+  YGNodeStyleSetFlexWrap(root_child1, YGWrapWrap);
+  YGNodeStyleSetWidth(root_child1, 50);
+  YGNodeStyleSetHeight(root_child1, 25);
+  YGNodeInsertChild(root, root_child1, 1);
+
+  const YGNodeRef root_child1_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child1_child0, 25);
+  YGNodeStyleSetHeight(root_child1_child0, 20);
+  YGNodeInsertChild(root_child1, root_child1_child0, 0);
+
+  const YGNodeRef root_child1_child1 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetAlignSelf(root_child1_child1, YGAlignBaseline);
+  YGNodeStyleSetWidth(root_child1_child1, 25);
+  YGNodeStyleSetHeight(root_child1_child1, 10);
+  YGNodeInsertChild(root_child1, root_child1_child1, 1);
+
+  const YGNodeRef root_child1_child2 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child1_child2, 25);
+  YGNodeStyleSetHeight(root_child1_child2, 20);
+  YGNodeInsertChild(root_child1, root_child1_child2, 2);
+
+  const YGNodeRef root_child1_child3 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetAlignSelf(root_child1_child3, YGAlignBaseline);
+  YGNodeStyleSetWidth(root_child1_child3, 25);
+  YGNodeStyleSetHeight(root_child1_child3, 10);
+  YGNodeInsertChild(root_child1, root_child1_child3, 3);
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(60, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(25, YGNodeLayoutGetHeight(root_child1));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child1_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child1_child0));
+  ASSERT_FLOAT_EQ(25, YGNodeLayoutGetWidth(root_child1_child0));
+  ASSERT_FLOAT_EQ(20, YGNodeLayoutGetHeight(root_child1_child0));
+
+  ASSERT_FLOAT_EQ(25, YGNodeLayoutGetLeft(root_child1_child1));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child1_child1));
+  ASSERT_FLOAT_EQ(25, YGNodeLayoutGetWidth(root_child1_child1));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child1_child1));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child1_child2));
+  ASSERT_FLOAT_EQ(20, YGNodeLayoutGetTop(root_child1_child2));
+  ASSERT_FLOAT_EQ(25, YGNodeLayoutGetWidth(root_child1_child2));
+  ASSERT_FLOAT_EQ(20, YGNodeLayoutGetHeight(root_child1_child2));
+
+  ASSERT_FLOAT_EQ(25, YGNodeLayoutGetLeft(root_child1_child3));
+  ASSERT_FLOAT_EQ(20, YGNodeLayoutGetTop(root_child1_child3));
+  ASSERT_FLOAT_EQ(25, YGNodeLayoutGetWidth(root_child1_child3));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child1_child3));
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(60, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(25, YGNodeLayoutGetHeight(root_child1));
+
+  ASSERT_FLOAT_EQ(25, YGNodeLayoutGetLeft(root_child1_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child1_child0));
+  ASSERT_FLOAT_EQ(25, YGNodeLayoutGetWidth(root_child1_child0));
+  ASSERT_FLOAT_EQ(20, YGNodeLayoutGetHeight(root_child1_child0));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child1_child1));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child1_child1));
+  ASSERT_FLOAT_EQ(25, YGNodeLayoutGetWidth(root_child1_child1));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child1_child1));
+
+  ASSERT_FLOAT_EQ(25, YGNodeLayoutGetLeft(root_child1_child2));
+  ASSERT_FLOAT_EQ(20, YGNodeLayoutGetTop(root_child1_child2));
+  ASSERT_FLOAT_EQ(25, YGNodeLayoutGetWidth(root_child1_child2));
+  ASSERT_FLOAT_EQ(20, YGNodeLayoutGetHeight(root_child1_child2));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child1_child3));
+  ASSERT_FLOAT_EQ(20, YGNodeLayoutGetTop(root_child1_child3));
+  ASSERT_FLOAT_EQ(25, YGNodeLayoutGetWidth(root_child1_child3));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child1_child3));
+
+  YGNodeFreeRecursive(root);
+
+  YGConfigFree(config);
+}
+
+TEST(YogaTest, align_baseline_child_multiline_no_override_on_secondline) {
+  const YGConfigRef config = YGConfigNew();
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexDirection(root, YGFlexDirectionRow);
+  YGNodeStyleSetAlignItems(root, YGAlignBaseline);
+  YGNodeStyleSetWidth(root, 100);
+  YGNodeStyleSetHeight(root, 100);
+
+  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child0, 50);
+  YGNodeStyleSetHeight(root_child0, 60);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  const YGNodeRef root_child1 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexDirection(root_child1, YGFlexDirectionRow);
+  YGNodeStyleSetFlexWrap(root_child1, YGWrapWrap);
+  YGNodeStyleSetWidth(root_child1, 50);
+  YGNodeStyleSetHeight(root_child1, 25);
+  YGNodeInsertChild(root, root_child1, 1);
+
+  const YGNodeRef root_child1_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child1_child0, 25);
+  YGNodeStyleSetHeight(root_child1_child0, 20);
+  YGNodeInsertChild(root_child1, root_child1_child0, 0);
+
+  const YGNodeRef root_child1_child1 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child1_child1, 25);
+  YGNodeStyleSetHeight(root_child1_child1, 10);
+  YGNodeInsertChild(root_child1, root_child1_child1, 1);
+
+  const YGNodeRef root_child1_child2 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child1_child2, 25);
+  YGNodeStyleSetHeight(root_child1_child2, 20);
+  YGNodeInsertChild(root_child1, root_child1_child2, 2);
+
+  const YGNodeRef root_child1_child3 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetAlignSelf(root_child1_child3, YGAlignBaseline);
+  YGNodeStyleSetWidth(root_child1_child3, 25);
+  YGNodeStyleSetHeight(root_child1_child3, 10);
+  YGNodeInsertChild(root_child1, root_child1_child3, 3);
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(60, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(40, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(25, YGNodeLayoutGetHeight(root_child1));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child1_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child1_child0));
+  ASSERT_FLOAT_EQ(25, YGNodeLayoutGetWidth(root_child1_child0));
+  ASSERT_FLOAT_EQ(20, YGNodeLayoutGetHeight(root_child1_child0));
+
+  ASSERT_FLOAT_EQ(25, YGNodeLayoutGetLeft(root_child1_child1));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child1_child1));
+  ASSERT_FLOAT_EQ(25, YGNodeLayoutGetWidth(root_child1_child1));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child1_child1));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child1_child2));
+  ASSERT_FLOAT_EQ(20, YGNodeLayoutGetTop(root_child1_child2));
+  ASSERT_FLOAT_EQ(25, YGNodeLayoutGetWidth(root_child1_child2));
+  ASSERT_FLOAT_EQ(20, YGNodeLayoutGetHeight(root_child1_child2));
+
+  ASSERT_FLOAT_EQ(25, YGNodeLayoutGetLeft(root_child1_child3));
+  ASSERT_FLOAT_EQ(20, YGNodeLayoutGetTop(root_child1_child3));
+  ASSERT_FLOAT_EQ(25, YGNodeLayoutGetWidth(root_child1_child3));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child1_child3));
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(60, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(40, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(25, YGNodeLayoutGetHeight(root_child1));
+
+  ASSERT_FLOAT_EQ(25, YGNodeLayoutGetLeft(root_child1_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child1_child0));
+  ASSERT_FLOAT_EQ(25, YGNodeLayoutGetWidth(root_child1_child0));
+  ASSERT_FLOAT_EQ(20, YGNodeLayoutGetHeight(root_child1_child0));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child1_child1));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child1_child1));
+  ASSERT_FLOAT_EQ(25, YGNodeLayoutGetWidth(root_child1_child1));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child1_child1));
+
+  ASSERT_FLOAT_EQ(25, YGNodeLayoutGetLeft(root_child1_child2));
+  ASSERT_FLOAT_EQ(20, YGNodeLayoutGetTop(root_child1_child2));
+  ASSERT_FLOAT_EQ(25, YGNodeLayoutGetWidth(root_child1_child2));
+  ASSERT_FLOAT_EQ(20, YGNodeLayoutGetHeight(root_child1_child2));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child1_child3));
+  ASSERT_FLOAT_EQ(20, YGNodeLayoutGetTop(root_child1_child3));
+  ASSERT_FLOAT_EQ(25, YGNodeLayoutGetWidth(root_child1_child3));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child1_child3));
+
+  YGNodeFreeRecursive(root);
+
+  YGConfigFree(config);
+}
+
+TEST(YogaTest, align_baseline_child_top) {
+  const YGConfigRef config = YGConfigNew();
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexDirection(root, YGFlexDirectionRow);
+  YGNodeStyleSetAlignItems(root, YGAlignBaseline);
+  YGNodeStyleSetWidth(root, 100);
+  YGNodeStyleSetHeight(root, 100);
+
+  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetPosition(root_child0, YGEdgeTop, 10);
+  YGNodeStyleSetWidth(root_child0, 50);
+  YGNodeStyleSetHeight(root_child0, 50);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  const YGNodeRef root_child1 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child1, 50);
+  YGNodeStyleSetHeight(root_child1, 20);
+  YGNodeInsertChild(root, root_child1, 1);
+
+  const YGNodeRef root_child1_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child1_child0, 50);
+  YGNodeStyleSetHeight(root_child1_child0, 10);
+  YGNodeInsertChild(root_child1, root_child1_child0, 0);
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(40, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(20, YGNodeLayoutGetHeight(root_child1));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child1_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child1_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child1_child0));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child1_child0));
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(40, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(20, YGNodeLayoutGetHeight(root_child1));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child1_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child1_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child1_child0));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child1_child0));
+
+  YGNodeFreeRecursive(root);
+
+  YGConfigFree(config);
+}
+
+TEST(YogaTest, align_baseline_child_top2) {
+  const YGConfigRef config = YGConfigNew();
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexDirection(root, YGFlexDirectionRow);
+  YGNodeStyleSetAlignItems(root, YGAlignBaseline);
+  YGNodeStyleSetWidth(root, 100);
+  YGNodeStyleSetHeight(root, 100);
+
+  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child0, 50);
+  YGNodeStyleSetHeight(root_child0, 50);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  const YGNodeRef root_child1 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetPosition(root_child1, YGEdgeTop, 5);
+  YGNodeStyleSetWidth(root_child1, 50);
+  YGNodeStyleSetHeight(root_child1, 20);
+  YGNodeInsertChild(root, root_child1, 1);
+
+  const YGNodeRef root_child1_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child1_child0, 50);
+  YGNodeStyleSetHeight(root_child1_child0, 10);
+  YGNodeInsertChild(root_child1, root_child1_child0, 0);
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(45, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(20, YGNodeLayoutGetHeight(root_child1));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child1_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child1_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child1_child0));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child1_child0));
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(45, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(20, YGNodeLayoutGetHeight(root_child1));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child1_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child1_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child1_child0));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child1_child0));
+
+  YGNodeFreeRecursive(root);
+
+  YGConfigFree(config);
+}
+
+TEST(YogaTest, align_baseline_double_nested_child) {
+  const YGConfigRef config = YGConfigNew();
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexDirection(root, YGFlexDirectionRow);
+  YGNodeStyleSetAlignItems(root, YGAlignBaseline);
+  YGNodeStyleSetWidth(root, 100);
+  YGNodeStyleSetHeight(root, 100);
+
+  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child0, 50);
+  YGNodeStyleSetHeight(root_child0, 50);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  const YGNodeRef root_child0_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child0_child0, 50);
+  YGNodeStyleSetHeight(root_child0_child0, 20);
+  YGNodeInsertChild(root_child0, root_child0_child0, 0);
+
+  const YGNodeRef root_child1 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child1, 50);
+  YGNodeStyleSetHeight(root_child1, 20);
+  YGNodeInsertChild(root, root_child1, 1);
+
+  const YGNodeRef root_child1_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child1_child0, 50);
+  YGNodeStyleSetHeight(root_child1_child0, 15);
+  YGNodeInsertChild(root_child1, root_child1_child0, 0);
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child0_child0));
+  ASSERT_FLOAT_EQ(20, YGNodeLayoutGetHeight(root_child0_child0));
+
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(5, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(20, YGNodeLayoutGetHeight(root_child1));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child1_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child1_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child1_child0));
+  ASSERT_FLOAT_EQ(15, YGNodeLayoutGetHeight(root_child1_child0));
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child0_child0));
+  ASSERT_FLOAT_EQ(20, YGNodeLayoutGetHeight(root_child0_child0));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(5, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(20, YGNodeLayoutGetHeight(root_child1));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child1_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child1_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child1_child0));
+  ASSERT_FLOAT_EQ(15, YGNodeLayoutGetHeight(root_child1_child0));
+
+  YGNodeFreeRecursive(root);
+
+  YGConfigFree(config);
+}
+
+TEST(YogaTest, align_baseline_column) {
+  const YGConfigRef config = YGConfigNew();
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  YGNodeStyleSetAlignItems(root, YGAlignBaseline);
+  YGNodeStyleSetWidth(root, 100);
+  YGNodeStyleSetHeight(root, 100);
+
+  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child0, 50);
+  YGNodeStyleSetHeight(root_child0, 50);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  const YGNodeRef root_child1 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child1, 50);
+  YGNodeStyleSetHeight(root_child1, 20);
+  YGNodeInsertChild(root, root_child1, 1);
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(20, YGNodeLayoutGetHeight(root_child1));
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(20, YGNodeLayoutGetHeight(root_child1));
+
+  YGNodeFreeRecursive(root);
+
+  YGConfigFree(config);
+}
+
+TEST(YogaTest, align_baseline_child_margin) {
+  const YGConfigRef config = YGConfigNew();
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexDirection(root, YGFlexDirectionRow);
+  YGNodeStyleSetAlignItems(root, YGAlignBaseline);
+  YGNodeStyleSetWidth(root, 100);
+  YGNodeStyleSetHeight(root, 100);
+
+  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetMargin(root_child0, YGEdgeLeft, 5);
+  YGNodeStyleSetMargin(root_child0, YGEdgeTop, 5);
+  YGNodeStyleSetMargin(root_child0, YGEdgeRight, 5);
+  YGNodeStyleSetMargin(root_child0, YGEdgeBottom, 5);
+  YGNodeStyleSetWidth(root_child0, 50);
+  YGNodeStyleSetHeight(root_child0, 50);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  const YGNodeRef root_child1 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child1, 50);
+  YGNodeStyleSetHeight(root_child1, 20);
+  YGNodeInsertChild(root, root_child1, 1);
+
+  const YGNodeRef root_child1_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetMargin(root_child1_child0, YGEdgeLeft, 1);
+  YGNodeStyleSetMargin(root_child1_child0, YGEdgeTop, 1);
+  YGNodeStyleSetMargin(root_child1_child0, YGEdgeRight, 1);
+  YGNodeStyleSetMargin(root_child1_child0, YGEdgeBottom, 1);
+  YGNodeStyleSetWidth(root_child1_child0, 50);
+  YGNodeStyleSetHeight(root_child1_child0, 10);
+  YGNodeInsertChild(root_child1, root_child1_child0, 0);
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(5, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(5, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(60, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(44, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(20, YGNodeLayoutGetHeight(root_child1));
+
+  ASSERT_FLOAT_EQ(1, YGNodeLayoutGetLeft(root_child1_child0));
+  ASSERT_FLOAT_EQ(1, YGNodeLayoutGetTop(root_child1_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child1_child0));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child1_child0));
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(45, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(5, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(-10, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(44, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(20, YGNodeLayoutGetHeight(root_child1));
+
+  ASSERT_FLOAT_EQ(-1, YGNodeLayoutGetLeft(root_child1_child0));
+  ASSERT_FLOAT_EQ(1, YGNodeLayoutGetTop(root_child1_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child1_child0));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child1_child0));
+
+  YGNodeFreeRecursive(root);
+
+  YGConfigFree(config);
+}
+
+TEST(YogaTest, align_baseline_child_padding) {
+  const YGConfigRef config = YGConfigNew();
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexDirection(root, YGFlexDirectionRow);
+  YGNodeStyleSetAlignItems(root, YGAlignBaseline);
+  YGNodeStyleSetPadding(root, YGEdgeLeft, 5);
+  YGNodeStyleSetPadding(root, YGEdgeTop, 5);
+  YGNodeStyleSetPadding(root, YGEdgeRight, 5);
+  YGNodeStyleSetPadding(root, YGEdgeBottom, 5);
+  YGNodeStyleSetWidth(root, 100);
+  YGNodeStyleSetHeight(root, 100);
+
+  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child0, 50);
+  YGNodeStyleSetHeight(root_child0, 50);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  const YGNodeRef root_child1 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetPadding(root_child1, YGEdgeLeft, 5);
+  YGNodeStyleSetPadding(root_child1, YGEdgeTop, 5);
+  YGNodeStyleSetPadding(root_child1, YGEdgeRight, 5);
+  YGNodeStyleSetPadding(root_child1, YGEdgeBottom, 5);
+  YGNodeStyleSetWidth(root_child1, 50);
+  YGNodeStyleSetHeight(root_child1, 20);
+  YGNodeInsertChild(root, root_child1, 1);
+
+  const YGNodeRef root_child1_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child1_child0, 50);
+  YGNodeStyleSetHeight(root_child1_child0, 10);
+  YGNodeInsertChild(root_child1, root_child1_child0, 0);
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(5, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(5, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(55, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(40, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(20, YGNodeLayoutGetHeight(root_child1));
+
+  ASSERT_FLOAT_EQ(5, YGNodeLayoutGetLeft(root_child1_child0));
+  ASSERT_FLOAT_EQ(5, YGNodeLayoutGetTop(root_child1_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child1_child0));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child1_child0));
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(45, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(5, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(-5, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(40, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(20, YGNodeLayoutGetHeight(root_child1));
+
+  ASSERT_FLOAT_EQ(-5, YGNodeLayoutGetLeft(root_child1_child0));
+  ASSERT_FLOAT_EQ(5, YGNodeLayoutGetTop(root_child1_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child1_child0));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child1_child0));
+
+  YGNodeFreeRecursive(root);
+
+  YGConfigFree(config);
+}
+
+TEST(YogaTest, align_baseline_multiline) {
+  const YGConfigRef config = YGConfigNew();
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexDirection(root, YGFlexDirectionRow);
+  YGNodeStyleSetAlignItems(root, YGAlignBaseline);
+  YGNodeStyleSetFlexWrap(root, YGWrapWrap);
+  YGNodeStyleSetWidth(root, 100);
+  YGNodeStyleSetHeight(root, 100);
+
+  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child0, 50);
+  YGNodeStyleSetHeight(root_child0, 50);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  const YGNodeRef root_child1 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child1, 50);
+  YGNodeStyleSetHeight(root_child1, 20);
+  YGNodeInsertChild(root, root_child1, 1);
+
+  const YGNodeRef root_child1_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child1_child0, 50);
+  YGNodeStyleSetHeight(root_child1_child0, 10);
+  YGNodeInsertChild(root_child1, root_child1_child0, 0);
+
+  const YGNodeRef root_child2 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child2, 50);
+  YGNodeStyleSetHeight(root_child2, 20);
+  YGNodeInsertChild(root, root_child2, 2);
+
+  const YGNodeRef root_child2_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child2_child0, 50);
+  YGNodeStyleSetHeight(root_child2_child0, 10);
+  YGNodeInsertChild(root_child2, root_child2_child0, 0);
+
+  const YGNodeRef root_child3 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child3, 50);
+  YGNodeStyleSetHeight(root_child3, 50);
+  YGNodeInsertChild(root, root_child3, 3);
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(40, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(20, YGNodeLayoutGetHeight(root_child1));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child1_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child1_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child1_child0));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child1_child0));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child2));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetTop(root_child2));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child2));
+  ASSERT_FLOAT_EQ(20, YGNodeLayoutGetHeight(root_child2));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child2_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child2_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child2_child0));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child2_child0));
+
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetLeft(root_child3));
+  ASSERT_FLOAT_EQ(60, YGNodeLayoutGetTop(root_child3));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child3));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child3));
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(40, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(20, YGNodeLayoutGetHeight(root_child1));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child1_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child1_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child1_child0));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child1_child0));
+
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetLeft(root_child2));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetTop(root_child2));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child2));
+  ASSERT_FLOAT_EQ(20, YGNodeLayoutGetHeight(root_child2));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child2_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child2_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child2_child0));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child2_child0));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child3));
+  ASSERT_FLOAT_EQ(60, YGNodeLayoutGetTop(root_child3));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child3));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child3));
+
+  YGNodeFreeRecursive(root);
+
+  YGConfigFree(config);
+}
+
+TEST(YogaTest, align_baseline_multiline_column) {
+  const YGConfigRef config = YGConfigNew();
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  YGNodeStyleSetAlignItems(root, YGAlignBaseline);
+  YGNodeStyleSetFlexWrap(root, YGWrapWrap);
+  YGNodeStyleSetWidth(root, 100);
+  YGNodeStyleSetHeight(root, 100);
+
+  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child0, 50);
+  YGNodeStyleSetHeight(root_child0, 50);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  const YGNodeRef root_child1 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child1, 30);
+  YGNodeStyleSetHeight(root_child1, 50);
+  YGNodeInsertChild(root, root_child1, 1);
+
+  const YGNodeRef root_child1_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child1_child0, 20);
+  YGNodeStyleSetHeight(root_child1_child0, 20);
+  YGNodeInsertChild(root_child1, root_child1_child0, 0);
+
+  const YGNodeRef root_child2 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child2, 40);
+  YGNodeStyleSetHeight(root_child2, 70);
+  YGNodeInsertChild(root, root_child2, 2);
+
+  const YGNodeRef root_child2_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child2_child0, 10);
+  YGNodeStyleSetHeight(root_child2_child0, 10);
+  YGNodeInsertChild(root_child2, root_child2_child0, 0);
+
+  const YGNodeRef root_child3 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child3, 50);
+  YGNodeStyleSetHeight(root_child3, 20);
+  YGNodeInsertChild(root, root_child3, 3);
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(30, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child1));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child1_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child1_child0));
+  ASSERT_FLOAT_EQ(20, YGNodeLayoutGetWidth(root_child1_child0));
+  ASSERT_FLOAT_EQ(20, YGNodeLayoutGetHeight(root_child1_child0));
+
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetLeft(root_child2));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child2));
+  ASSERT_FLOAT_EQ(40, YGNodeLayoutGetWidth(root_child2));
+  ASSERT_FLOAT_EQ(70, YGNodeLayoutGetHeight(root_child2));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child2_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child2_child0));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetWidth(root_child2_child0));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child2_child0));
+
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetLeft(root_child3));
+  ASSERT_FLOAT_EQ(70, YGNodeLayoutGetTop(root_child3));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child3));
+  ASSERT_FLOAT_EQ(20, YGNodeLayoutGetHeight(root_child3));
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(70, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(30, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child1));
+
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetLeft(root_child1_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child1_child0));
+  ASSERT_FLOAT_EQ(20, YGNodeLayoutGetWidth(root_child1_child0));
+  ASSERT_FLOAT_EQ(20, YGNodeLayoutGetHeight(root_child1_child0));
+
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetLeft(root_child2));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child2));
+  ASSERT_FLOAT_EQ(40, YGNodeLayoutGetWidth(root_child2));
+  ASSERT_FLOAT_EQ(70, YGNodeLayoutGetHeight(root_child2));
+
+  ASSERT_FLOAT_EQ(30, YGNodeLayoutGetLeft(root_child2_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child2_child0));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetWidth(root_child2_child0));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child2_child0));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child3));
+  ASSERT_FLOAT_EQ(70, YGNodeLayoutGetTop(root_child3));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child3));
+  ASSERT_FLOAT_EQ(20, YGNodeLayoutGetHeight(root_child3));
+
+  YGNodeFreeRecursive(root);
+
+  YGConfigFree(config);
+}
+
+TEST(YogaTest, align_baseline_multiline_column2) {
+  const YGConfigRef config = YGConfigNew();
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  YGNodeStyleSetAlignItems(root, YGAlignBaseline);
+  YGNodeStyleSetFlexWrap(root, YGWrapWrap);
+  YGNodeStyleSetWidth(root, 100);
+  YGNodeStyleSetHeight(root, 100);
+
+  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child0, 50);
+  YGNodeStyleSetHeight(root_child0, 50);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  const YGNodeRef root_child1 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child1, 30);
+  YGNodeStyleSetHeight(root_child1, 50);
+  YGNodeInsertChild(root, root_child1, 1);
+
+  const YGNodeRef root_child1_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child1_child0, 20);
+  YGNodeStyleSetHeight(root_child1_child0, 20);
+  YGNodeInsertChild(root_child1, root_child1_child0, 0);
+
+  const YGNodeRef root_child2 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child2, 40);
+  YGNodeStyleSetHeight(root_child2, 70);
+  YGNodeInsertChild(root, root_child2, 2);
+
+  const YGNodeRef root_child2_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child2_child0, 10);
+  YGNodeStyleSetHeight(root_child2_child0, 10);
+  YGNodeInsertChild(root_child2, root_child2_child0, 0);
+
+  const YGNodeRef root_child3 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child3, 50);
+  YGNodeStyleSetHeight(root_child3, 20);
+  YGNodeInsertChild(root, root_child3, 3);
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(30, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child1));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child1_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child1_child0));
+  ASSERT_FLOAT_EQ(20, YGNodeLayoutGetWidth(root_child1_child0));
+  ASSERT_FLOAT_EQ(20, YGNodeLayoutGetHeight(root_child1_child0));
+
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetLeft(root_child2));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child2));
+  ASSERT_FLOAT_EQ(40, YGNodeLayoutGetWidth(root_child2));
+  ASSERT_FLOAT_EQ(70, YGNodeLayoutGetHeight(root_child2));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child2_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child2_child0));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetWidth(root_child2_child0));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child2_child0));
+
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetLeft(root_child3));
+  ASSERT_FLOAT_EQ(70, YGNodeLayoutGetTop(root_child3));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child3));
+  ASSERT_FLOAT_EQ(20, YGNodeLayoutGetHeight(root_child3));
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(70, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(30, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child1));
+
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetLeft(root_child1_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child1_child0));
+  ASSERT_FLOAT_EQ(20, YGNodeLayoutGetWidth(root_child1_child0));
+  ASSERT_FLOAT_EQ(20, YGNodeLayoutGetHeight(root_child1_child0));
+
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetLeft(root_child2));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child2));
+  ASSERT_FLOAT_EQ(40, YGNodeLayoutGetWidth(root_child2));
+  ASSERT_FLOAT_EQ(70, YGNodeLayoutGetHeight(root_child2));
+
+  ASSERT_FLOAT_EQ(30, YGNodeLayoutGetLeft(root_child2_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child2_child0));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetWidth(root_child2_child0));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child2_child0));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child3));
+  ASSERT_FLOAT_EQ(70, YGNodeLayoutGetTop(root_child3));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child3));
+  ASSERT_FLOAT_EQ(20, YGNodeLayoutGetHeight(root_child3));
+
+  YGNodeFreeRecursive(root);
+
+  YGConfigFree(config);
+}
+
+TEST(YogaTest, align_baseline_multiline_row_and_column) {
+  const YGConfigRef config = YGConfigNew();
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexDirection(root, YGFlexDirectionRow);
+  YGNodeStyleSetAlignItems(root, YGAlignBaseline);
+  YGNodeStyleSetFlexWrap(root, YGWrapWrap);
+  YGNodeStyleSetWidth(root, 100);
+  YGNodeStyleSetHeight(root, 100);
+
+  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child0, 50);
+  YGNodeStyleSetHeight(root_child0, 50);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  const YGNodeRef root_child1 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child1, 50);
+  YGNodeStyleSetHeight(root_child1, 50);
+  YGNodeInsertChild(root, root_child1, 1);
+
+  const YGNodeRef root_child1_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child1_child0, 50);
+  YGNodeStyleSetHeight(root_child1_child0, 10);
+  YGNodeInsertChild(root_child1, root_child1_child0, 0);
+
+  const YGNodeRef root_child2 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child2, 50);
+  YGNodeStyleSetHeight(root_child2, 20);
+  YGNodeInsertChild(root, root_child2, 2);
+
+  const YGNodeRef root_child2_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child2_child0, 50);
+  YGNodeStyleSetHeight(root_child2_child0, 10);
+  YGNodeInsertChild(root_child2, root_child2_child0, 0);
+
+  const YGNodeRef root_child3 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child3, 50);
+  YGNodeStyleSetHeight(root_child3, 20);
+  YGNodeInsertChild(root, root_child3, 3);
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(40, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child1));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child1_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child1_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child1_child0));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child1_child0));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child2));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetTop(root_child2));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child2));
+  ASSERT_FLOAT_EQ(20, YGNodeLayoutGetHeight(root_child2));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child2_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child2_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child2_child0));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child2_child0));
+
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetLeft(root_child3));
+  ASSERT_FLOAT_EQ(90, YGNodeLayoutGetTop(root_child3));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child3));
+  ASSERT_FLOAT_EQ(20, YGNodeLayoutGetHeight(root_child3));
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(40, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child1));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child1_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child1_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child1_child0));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child1_child0));
+
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetLeft(root_child2));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetTop(root_child2));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child2));
+  ASSERT_FLOAT_EQ(20, YGNodeLayoutGetHeight(root_child2));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child2_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child2_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child2_child0));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child2_child0));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child3));
+  ASSERT_FLOAT_EQ(90, YGNodeLayoutGetTop(root_child3));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child3));
+  ASSERT_FLOAT_EQ(20, YGNodeLayoutGetHeight(root_child3));
+
+  YGNodeFreeRecursive(root);
+
+  YGConfigFree(config);
+}
+
+TEST(YogaTest, align_items_center_child_with_margin_bigger_than_parent) {
+  const YGConfigRef config = YGConfigNew();
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  YGNodeStyleSetJustifyContent(root, YGJustifyCenter);
+  YGNodeStyleSetAlignItems(root, YGAlignCenter);
+  YGNodeStyleSetWidth(root, 52);
+  YGNodeStyleSetHeight(root, 52);
+
+  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetAlignItems(root_child0, YGAlignCenter);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  const YGNodeRef root_child0_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetMargin(root_child0_child0, YGEdgeLeft, 10);
+  YGNodeStyleSetMargin(root_child0_child0, YGEdgeRight, 10);
+  YGNodeStyleSetWidth(root_child0_child0, 52);
+  YGNodeStyleSetHeight(root_child0_child0, 52);
+  YGNodeInsertChild(root_child0, root_child0_child0, 0);
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(52, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(52, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(-10, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(72, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(52, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetLeft(root_child0_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0_child0));
+  ASSERT_FLOAT_EQ(52, YGNodeLayoutGetWidth(root_child0_child0));
+  ASSERT_FLOAT_EQ(52, YGNodeLayoutGetHeight(root_child0_child0));
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(52, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(52, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(-10, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(72, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(52, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetLeft(root_child0_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0_child0));
+  ASSERT_FLOAT_EQ(52, YGNodeLayoutGetWidth(root_child0_child0));
+  ASSERT_FLOAT_EQ(52, YGNodeLayoutGetHeight(root_child0_child0));
+
+  YGNodeFreeRecursive(root);
+
+  YGConfigFree(config);
+}
+
+TEST(YogaTest, align_items_flex_end_child_with_margin_bigger_than_parent) {
+  const YGConfigRef config = YGConfigNew();
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  YGNodeStyleSetJustifyContent(root, YGJustifyCenter);
+  YGNodeStyleSetAlignItems(root, YGAlignCenter);
+  YGNodeStyleSetWidth(root, 52);
+  YGNodeStyleSetHeight(root, 52);
+
+  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetAlignItems(root_child0, YGAlignFlexEnd);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  const YGNodeRef root_child0_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetMargin(root_child0_child0, YGEdgeLeft, 10);
+  YGNodeStyleSetMargin(root_child0_child0, YGEdgeRight, 10);
+  YGNodeStyleSetWidth(root_child0_child0, 52);
+  YGNodeStyleSetHeight(root_child0_child0, 52);
+  YGNodeInsertChild(root_child0, root_child0_child0, 0);
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(52, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(52, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(-10, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(72, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(52, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetLeft(root_child0_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0_child0));
+  ASSERT_FLOAT_EQ(52, YGNodeLayoutGetWidth(root_child0_child0));
+  ASSERT_FLOAT_EQ(52, YGNodeLayoutGetHeight(root_child0_child0));
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(52, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(52, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(-10, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(72, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(52, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetLeft(root_child0_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0_child0));
+  ASSERT_FLOAT_EQ(52, YGNodeLayoutGetWidth(root_child0_child0));
+  ASSERT_FLOAT_EQ(52, YGNodeLayoutGetHeight(root_child0_child0));
+
+  YGNodeFreeRecursive(root);
+
+  YGConfigFree(config);
+}
+
+TEST(YogaTest, align_items_center_child_without_margin_bigger_than_parent) {
+  const YGConfigRef config = YGConfigNew();
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  YGNodeStyleSetJustifyContent(root, YGJustifyCenter);
+  YGNodeStyleSetAlignItems(root, YGAlignCenter);
+  YGNodeStyleSetWidth(root, 52);
+  YGNodeStyleSetHeight(root, 52);
+
+  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetAlignItems(root_child0, YGAlignCenter);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  const YGNodeRef root_child0_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child0_child0, 72);
+  YGNodeStyleSetHeight(root_child0_child0, 72);
+  YGNodeInsertChild(root_child0, root_child0_child0, 0);
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(52, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(52, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(-10, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(-10, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(72, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(72, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0_child0));
+  ASSERT_FLOAT_EQ(72, YGNodeLayoutGetWidth(root_child0_child0));
+  ASSERT_FLOAT_EQ(72, YGNodeLayoutGetHeight(root_child0_child0));
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(52, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(52, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(-10, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(-10, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(72, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(72, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0_child0));
+  ASSERT_FLOAT_EQ(72, YGNodeLayoutGetWidth(root_child0_child0));
+  ASSERT_FLOAT_EQ(72, YGNodeLayoutGetHeight(root_child0_child0));
+
+  YGNodeFreeRecursive(root);
+
+  YGConfigFree(config);
+}
+
+TEST(YogaTest, align_items_flex_end_child_without_margin_bigger_than_parent) {
+  const YGConfigRef config = YGConfigNew();
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  YGNodeStyleSetJustifyContent(root, YGJustifyCenter);
+  YGNodeStyleSetAlignItems(root, YGAlignCenter);
+  YGNodeStyleSetWidth(root, 52);
+  YGNodeStyleSetHeight(root, 52);
+
+  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetAlignItems(root_child0, YGAlignFlexEnd);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  const YGNodeRef root_child0_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child0_child0, 72);
+  YGNodeStyleSetHeight(root_child0_child0, 72);
+  YGNodeInsertChild(root_child0, root_child0_child0, 0);
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(52, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(52, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(-10, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(-10, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(72, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(72, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0_child0));
+  ASSERT_FLOAT_EQ(72, YGNodeLayoutGetWidth(root_child0_child0));
+  ASSERT_FLOAT_EQ(72, YGNodeLayoutGetHeight(root_child0_child0));
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(52, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(52, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(-10, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(-10, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(72, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(72, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0_child0));
+  ASSERT_FLOAT_EQ(72, YGNodeLayoutGetWidth(root_child0_child0));
+  ASSERT_FLOAT_EQ(72, YGNodeLayoutGetHeight(root_child0_child0));
+
+  YGNodeFreeRecursive(root);
+
+  YGConfigFree(config);
+}
+
+TEST(YogaTest, align_center_should_size_based_on_content) {
+  const YGConfigRef config = YGConfigNew();
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  YGNodeStyleSetAlignItems(root, YGAlignCenter);
+  YGNodeStyleSetMargin(root, YGEdgeTop, 20);
+  YGNodeStyleSetWidth(root, 100);
+  YGNodeStyleSetHeight(root, 100);
+
+  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetJustifyContent(root_child0, YGJustifyCenter);
+  YGNodeStyleSetFlexShrink(root_child0, 1);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  const YGNodeRef root_child0_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexGrow(root_child0_child0, 1);
+  YGNodeStyleSetFlexShrink(root_child0_child0, 1);
+  YGNodeInsertChild(root_child0, root_child0_child0, 0);
+
+  const YGNodeRef root_child0_child0_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child0_child0_child0, 20);
+  YGNodeStyleSetHeight(root_child0_child0_child0, 20);
+  YGNodeInsertChild(root_child0_child0, root_child0_child0_child0, 0);
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(20, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(40, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(20, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(20, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0_child0));
+  ASSERT_FLOAT_EQ(20, YGNodeLayoutGetWidth(root_child0_child0));
+  ASSERT_FLOAT_EQ(20, YGNodeLayoutGetHeight(root_child0_child0));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0_child0_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0_child0_child0));
+  ASSERT_FLOAT_EQ(20, YGNodeLayoutGetWidth(root_child0_child0_child0));
+  ASSERT_FLOAT_EQ(20, YGNodeLayoutGetHeight(root_child0_child0_child0));
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(20, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(40, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(20, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(20, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0_child0));
+  ASSERT_FLOAT_EQ(20, YGNodeLayoutGetWidth(root_child0_child0));
+  ASSERT_FLOAT_EQ(20, YGNodeLayoutGetHeight(root_child0_child0));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0_child0_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0_child0_child0));
+  ASSERT_FLOAT_EQ(20, YGNodeLayoutGetWidth(root_child0_child0_child0));
+  ASSERT_FLOAT_EQ(20, YGNodeLayoutGetHeight(root_child0_child0_child0));
+
+  YGNodeFreeRecursive(root);
+
+  YGConfigFree(config);
+}
+
+TEST(YogaTest, align_strech_should_size_based_on_parent) {
+  const YGConfigRef config = YGConfigNew();
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  YGNodeStyleSetMargin(root, YGEdgeTop, 20);
+  YGNodeStyleSetWidth(root, 100);
+  YGNodeStyleSetHeight(root, 100);
+
+  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetJustifyContent(root_child0, YGJustifyCenter);
+  YGNodeStyleSetFlexShrink(root_child0, 1);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  const YGNodeRef root_child0_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexGrow(root_child0_child0, 1);
+  YGNodeStyleSetFlexShrink(root_child0_child0, 1);
+  YGNodeInsertChild(root_child0, root_child0_child0, 0);
+
+  const YGNodeRef root_child0_child0_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child0_child0_child0, 20);
+  YGNodeStyleSetHeight(root_child0_child0_child0, 20);
+  YGNodeInsertChild(root_child0_child0, root_child0_child0_child0, 0);
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(20, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(20, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0_child0));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child0_child0));
+  ASSERT_FLOAT_EQ(20, YGNodeLayoutGetHeight(root_child0_child0));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0_child0_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0_child0_child0));
+  ASSERT_FLOAT_EQ(20, YGNodeLayoutGetWidth(root_child0_child0_child0));
+  ASSERT_FLOAT_EQ(20, YGNodeLayoutGetHeight(root_child0_child0_child0));
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(20, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(20, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0_child0));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child0_child0));
+  ASSERT_FLOAT_EQ(20, YGNodeLayoutGetHeight(root_child0_child0));
+
+  ASSERT_FLOAT_EQ(80, YGNodeLayoutGetLeft(root_child0_child0_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0_child0_child0));
+  ASSERT_FLOAT_EQ(20, YGNodeLayoutGetWidth(root_child0_child0_child0));
+  ASSERT_FLOAT_EQ(20, YGNodeLayoutGetHeight(root_child0_child0_child0));
+
+  YGNodeFreeRecursive(root);
+
+  YGConfigFree(config);
+}
+
+TEST(YogaTest, align_flex_start_with_shrinking_children) {
+  const YGConfigRef config = YGConfigNew();
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root, 500);
+  YGNodeStyleSetHeight(root, 500);
+
+  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetAlignItems(root_child0, YGAlignFlexStart);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  const YGNodeRef root_child0_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexGrow(root_child0_child0, 1);
+  YGNodeStyleSetFlexShrink(root_child0_child0, 1);
+  YGNodeInsertChild(root_child0, root_child0_child0, 0);
+
+  const YGNodeRef root_child0_child0_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexGrow(root_child0_child0_child0, 1);
+  YGNodeStyleSetFlexShrink(root_child0_child0_child0, 1);
+  YGNodeInsertChild(root_child0_child0, root_child0_child0_child0, 0);
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(500, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(500, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(500, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetWidth(root_child0_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetHeight(root_child0_child0));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0_child0_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0_child0_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetWidth(root_child0_child0_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetHeight(root_child0_child0_child0));
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(500, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(500, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(500, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(500, YGNodeLayoutGetLeft(root_child0_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetWidth(root_child0_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetHeight(root_child0_child0));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0_child0_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0_child0_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetWidth(root_child0_child0_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetHeight(root_child0_child0_child0));
+
+  YGNodeFreeRecursive(root);
+
+  YGConfigFree(config);
+}
+
+TEST(YogaTest, align_flex_start_with_stretching_children) {
+  const YGConfigRef config = YGConfigNew();
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root, 500);
+  YGNodeStyleSetHeight(root, 500);
+
+  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  const YGNodeRef root_child0_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexGrow(root_child0_child0, 1);
+  YGNodeStyleSetFlexShrink(root_child0_child0, 1);
+  YGNodeInsertChild(root_child0, root_child0_child0, 0);
+
+  const YGNodeRef root_child0_child0_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexGrow(root_child0_child0_child0, 1);
+  YGNodeStyleSetFlexShrink(root_child0_child0_child0, 1);
+  YGNodeInsertChild(root_child0_child0, root_child0_child0_child0, 0);
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(500, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(500, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(500, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0_child0));
+  ASSERT_FLOAT_EQ(500, YGNodeLayoutGetWidth(root_child0_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetHeight(root_child0_child0));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0_child0_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0_child0_child0));
+  ASSERT_FLOAT_EQ(500, YGNodeLayoutGetWidth(root_child0_child0_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetHeight(root_child0_child0_child0));
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(500, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(500, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(500, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0_child0));
+  ASSERT_FLOAT_EQ(500, YGNodeLayoutGetWidth(root_child0_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetHeight(root_child0_child0));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0_child0_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0_child0_child0));
+  ASSERT_FLOAT_EQ(500, YGNodeLayoutGetWidth(root_child0_child0_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetHeight(root_child0_child0_child0));
+
+  YGNodeFreeRecursive(root);
+
+  YGConfigFree(config);
+}
+
+TEST(YogaTest, align_flex_start_with_shrinking_children_with_stretch) {
+  const YGConfigRef config = YGConfigNew();
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root, 500);
+  YGNodeStyleSetHeight(root, 500);
+
+  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetAlignItems(root_child0, YGAlignFlexStart);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  const YGNodeRef root_child0_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexGrow(root_child0_child0, 1);
+  YGNodeStyleSetFlexShrink(root_child0_child0, 1);
+  YGNodeInsertChild(root_child0, root_child0_child0, 0);
+
+  const YGNodeRef root_child0_child0_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexGrow(root_child0_child0_child0, 1);
+  YGNodeStyleSetFlexShrink(root_child0_child0_child0, 1);
+  YGNodeInsertChild(root_child0_child0, root_child0_child0_child0, 0);
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(500, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(500, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(500, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetWidth(root_child0_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetHeight(root_child0_child0));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0_child0_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0_child0_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetWidth(root_child0_child0_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetHeight(root_child0_child0_child0));
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(500, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(500, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(500, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(500, YGNodeLayoutGetLeft(root_child0_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetWidth(root_child0_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetHeight(root_child0_child0));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0_child0_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0_child0_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetWidth(root_child0_child0_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetHeight(root_child0_child0_child0));
+
+  YGNodeFreeRecursive(root);
+
+  YGConfigFree(config);
+}
diff --git a/automated-tests/src/dali-toolkit-third-party/yoga/YGAlignSelfTest.cpp b/automated-tests/src/dali-toolkit-third-party/yoga/YGAlignSelfTest.cpp
new file mode 100644 (file)
index 0000000..00bb7b9
--- /dev/null
@@ -0,0 +1,249 @@
+/**
+ * Copyright (c) 2014-present, Facebook, Inc.
+ *
+ * This source code is licensed under the MIT license found in the
+ * LICENSE file in the root directory of this source tree.
+ */
+
+// @Generated by gentest/gentest.rb from gentest/fixtures/YGAlignSelfTest.html
+
+#include <gtest/gtest.h>
+#include <yoga/Yoga.h>
+
+TEST(YogaTest, align_self_center) {
+  const YGConfigRef config = YGConfigNew();
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root, 100);
+  YGNodeStyleSetHeight(root, 100);
+
+  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetAlignSelf(root_child0, YGAlignCenter);
+  YGNodeStyleSetWidth(root_child0, 10);
+  YGNodeStyleSetHeight(root_child0, 10);
+  YGNodeInsertChild(root, root_child0, 0);
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(45, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child0));
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(45, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child0));
+
+  YGNodeFreeRecursive(root);
+
+  YGConfigFree(config);
+}
+
+TEST(YogaTest, align_self_flex_end) {
+  const YGConfigRef config = YGConfigNew();
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root, 100);
+  YGNodeStyleSetHeight(root, 100);
+
+  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetAlignSelf(root_child0, YGAlignFlexEnd);
+  YGNodeStyleSetWidth(root_child0, 10);
+  YGNodeStyleSetHeight(root_child0, 10);
+  YGNodeInsertChild(root, root_child0, 0);
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(90, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child0));
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child0));
+
+  YGNodeFreeRecursive(root);
+
+  YGConfigFree(config);
+}
+
+TEST(YogaTest, align_self_flex_start) {
+  const YGConfigRef config = YGConfigNew();
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root, 100);
+  YGNodeStyleSetHeight(root, 100);
+
+  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetAlignSelf(root_child0, YGAlignFlexStart);
+  YGNodeStyleSetWidth(root_child0, 10);
+  YGNodeStyleSetHeight(root_child0, 10);
+  YGNodeInsertChild(root, root_child0, 0);
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child0));
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(90, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child0));
+
+  YGNodeFreeRecursive(root);
+
+  YGConfigFree(config);
+}
+
+TEST(YogaTest, align_self_flex_end_override_flex_start) {
+  const YGConfigRef config = YGConfigNew();
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  YGNodeStyleSetAlignItems(root, YGAlignFlexStart);
+  YGNodeStyleSetWidth(root, 100);
+  YGNodeStyleSetHeight(root, 100);
+
+  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetAlignSelf(root_child0, YGAlignFlexEnd);
+  YGNodeStyleSetWidth(root_child0, 10);
+  YGNodeStyleSetHeight(root_child0, 10);
+  YGNodeInsertChild(root, root_child0, 0);
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(90, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child0));
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child0));
+
+  YGNodeFreeRecursive(root);
+
+  YGConfigFree(config);
+}
+
+TEST(YogaTest, align_self_baseline) {
+  const YGConfigRef config = YGConfigNew();
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexDirection(root, YGFlexDirectionRow);
+  YGNodeStyleSetWidth(root, 100);
+  YGNodeStyleSetHeight(root, 100);
+
+  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetAlignSelf(root_child0, YGAlignBaseline);
+  YGNodeStyleSetWidth(root_child0, 50);
+  YGNodeStyleSetHeight(root_child0, 50);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  const YGNodeRef root_child1 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetAlignSelf(root_child1, YGAlignBaseline);
+  YGNodeStyleSetWidth(root_child1, 50);
+  YGNodeStyleSetHeight(root_child1, 20);
+  YGNodeInsertChild(root, root_child1, 1);
+
+  const YGNodeRef root_child1_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child1_child0, 50);
+  YGNodeStyleSetHeight(root_child1_child0, 10);
+  YGNodeInsertChild(root_child1, root_child1_child0, 0);
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(40, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(20, YGNodeLayoutGetHeight(root_child1));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child1_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child1_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child1_child0));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child1_child0));
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(40, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(20, YGNodeLayoutGetHeight(root_child1));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child1_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child1_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child1_child0));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child1_child0));
+
+  YGNodeFreeRecursive(root);
+
+  YGConfigFree(config);
+}
diff --git a/automated-tests/src/dali-toolkit-third-party/yoga/YGAndroidNewsFeed.cpp b/automated-tests/src/dali-toolkit-third-party/yoga/YGAndroidNewsFeed.cpp
new file mode 100644 (file)
index 0000000..fb3f073
--- /dev/null
@@ -0,0 +1,445 @@
+/**
+ * Copyright (c) 2014-present, Facebook, Inc.
+ *
+ * This source code is licensed under the MIT license found in the
+ * LICENSE file in the root directory of this source tree.
+ */
+
+// @Generated by gentest/gentest.rb from gentest/fixtures/YGAndroidNewsFeed.html
+
+#include <gtest/gtest.h>
+#include <yoga/Yoga.h>
+
+TEST(YogaTest, android_news_feed) {
+  const YGConfigRef config = YGConfigNew();
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  YGNodeStyleSetAlignContent(root, YGAlignStretch);
+  YGNodeStyleSetWidth(root, 1080);
+
+  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  const YGNodeRef root_child0_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetAlignContent(root_child0_child0, YGAlignStretch);
+  YGNodeInsertChild(root_child0, root_child0_child0, 0);
+
+  const YGNodeRef root_child0_child0_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetAlignContent(root_child0_child0_child0, YGAlignStretch);
+  YGNodeInsertChild(root_child0_child0, root_child0_child0_child0, 0);
+
+  const YGNodeRef root_child0_child0_child0_child0 =
+      YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexDirection(
+      root_child0_child0_child0_child0, YGFlexDirectionRow);
+  YGNodeStyleSetAlignContent(root_child0_child0_child0_child0, YGAlignStretch);
+  YGNodeStyleSetAlignItems(root_child0_child0_child0_child0, YGAlignFlexStart);
+  YGNodeStyleSetMargin(root_child0_child0_child0_child0, YGEdgeStart, 36);
+  YGNodeStyleSetMargin(root_child0_child0_child0_child0, YGEdgeTop, 24);
+  YGNodeInsertChild(
+      root_child0_child0_child0, root_child0_child0_child0_child0, 0);
+
+  const YGNodeRef root_child0_child0_child0_child0_child0 =
+      YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexDirection(
+      root_child0_child0_child0_child0_child0, YGFlexDirectionRow);
+  YGNodeStyleSetAlignContent(
+      root_child0_child0_child0_child0_child0, YGAlignStretch);
+  YGNodeInsertChild(
+      root_child0_child0_child0_child0,
+      root_child0_child0_child0_child0_child0,
+      0);
+
+  const YGNodeRef root_child0_child0_child0_child0_child0_child0 =
+      YGNodeNewWithConfig(config);
+  YGNodeStyleSetAlignContent(
+      root_child0_child0_child0_child0_child0_child0, YGAlignStretch);
+  YGNodeStyleSetWidth(root_child0_child0_child0_child0_child0_child0, 120);
+  YGNodeStyleSetHeight(root_child0_child0_child0_child0_child0_child0, 120);
+  YGNodeInsertChild(
+      root_child0_child0_child0_child0_child0,
+      root_child0_child0_child0_child0_child0_child0,
+      0);
+
+  const YGNodeRef root_child0_child0_child0_child0_child1 =
+      YGNodeNewWithConfig(config);
+  YGNodeStyleSetAlignContent(
+      root_child0_child0_child0_child0_child1, YGAlignStretch);
+  YGNodeStyleSetFlexShrink(root_child0_child0_child0_child0_child1, 1);
+  YGNodeStyleSetMargin(
+      root_child0_child0_child0_child0_child1, YGEdgeRight, 36);
+  YGNodeStyleSetPadding(
+      root_child0_child0_child0_child0_child1, YGEdgeLeft, 36);
+  YGNodeStyleSetPadding(root_child0_child0_child0_child0_child1, YGEdgeTop, 21);
+  YGNodeStyleSetPadding(
+      root_child0_child0_child0_child0_child1, YGEdgeRight, 36);
+  YGNodeStyleSetPadding(
+      root_child0_child0_child0_child0_child1, YGEdgeBottom, 18);
+  YGNodeInsertChild(
+      root_child0_child0_child0_child0,
+      root_child0_child0_child0_child0_child1,
+      1);
+
+  const YGNodeRef root_child0_child0_child0_child0_child1_child0 =
+      YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexDirection(
+      root_child0_child0_child0_child0_child1_child0, YGFlexDirectionRow);
+  YGNodeStyleSetAlignContent(
+      root_child0_child0_child0_child0_child1_child0, YGAlignStretch);
+  YGNodeStyleSetFlexShrink(root_child0_child0_child0_child0_child1_child0, 1);
+  YGNodeInsertChild(
+      root_child0_child0_child0_child0_child1,
+      root_child0_child0_child0_child0_child1_child0,
+      0);
+
+  const YGNodeRef root_child0_child0_child0_child0_child1_child1 =
+      YGNodeNewWithConfig(config);
+  YGNodeStyleSetAlignContent(
+      root_child0_child0_child0_child0_child1_child1, YGAlignStretch);
+  YGNodeStyleSetFlexShrink(root_child0_child0_child0_child0_child1_child1, 1);
+  YGNodeInsertChild(
+      root_child0_child0_child0_child0_child1,
+      root_child0_child0_child0_child0_child1_child1,
+      1);
+
+  const YGNodeRef root_child0_child0_child1 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetAlignContent(root_child0_child0_child1, YGAlignStretch);
+  YGNodeInsertChild(root_child0_child0, root_child0_child0_child1, 1);
+
+  const YGNodeRef root_child0_child0_child1_child0 =
+      YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexDirection(
+      root_child0_child0_child1_child0, YGFlexDirectionRow);
+  YGNodeStyleSetAlignContent(root_child0_child0_child1_child0, YGAlignStretch);
+  YGNodeStyleSetAlignItems(root_child0_child0_child1_child0, YGAlignFlexStart);
+  YGNodeStyleSetMargin(root_child0_child0_child1_child0, YGEdgeStart, 174);
+  YGNodeStyleSetMargin(root_child0_child0_child1_child0, YGEdgeTop, 24);
+  YGNodeInsertChild(
+      root_child0_child0_child1, root_child0_child0_child1_child0, 0);
+
+  const YGNodeRef root_child0_child0_child1_child0_child0 =
+      YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexDirection(
+      root_child0_child0_child1_child0_child0, YGFlexDirectionRow);
+  YGNodeStyleSetAlignContent(
+      root_child0_child0_child1_child0_child0, YGAlignStretch);
+  YGNodeInsertChild(
+      root_child0_child0_child1_child0,
+      root_child0_child0_child1_child0_child0,
+      0);
+
+  const YGNodeRef root_child0_child0_child1_child0_child0_child0 =
+      YGNodeNewWithConfig(config);
+  YGNodeStyleSetAlignContent(
+      root_child0_child0_child1_child0_child0_child0, YGAlignStretch);
+  YGNodeStyleSetWidth(root_child0_child0_child1_child0_child0_child0, 72);
+  YGNodeStyleSetHeight(root_child0_child0_child1_child0_child0_child0, 72);
+  YGNodeInsertChild(
+      root_child0_child0_child1_child0_child0,
+      root_child0_child0_child1_child0_child0_child0,
+      0);
+
+  const YGNodeRef root_child0_child0_child1_child0_child1 =
+      YGNodeNewWithConfig(config);
+  YGNodeStyleSetAlignContent(
+      root_child0_child0_child1_child0_child1, YGAlignStretch);
+  YGNodeStyleSetFlexShrink(root_child0_child0_child1_child0_child1, 1);
+  YGNodeStyleSetMargin(
+      root_child0_child0_child1_child0_child1, YGEdgeRight, 36);
+  YGNodeStyleSetPadding(
+      root_child0_child0_child1_child0_child1, YGEdgeLeft, 36);
+  YGNodeStyleSetPadding(root_child0_child0_child1_child0_child1, YGEdgeTop, 21);
+  YGNodeStyleSetPadding(
+      root_child0_child0_child1_child0_child1, YGEdgeRight, 36);
+  YGNodeStyleSetPadding(
+      root_child0_child0_child1_child0_child1, YGEdgeBottom, 18);
+  YGNodeInsertChild(
+      root_child0_child0_child1_child0,
+      root_child0_child0_child1_child0_child1,
+      1);
+
+  const YGNodeRef root_child0_child0_child1_child0_child1_child0 =
+      YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexDirection(
+      root_child0_child0_child1_child0_child1_child0, YGFlexDirectionRow);
+  YGNodeStyleSetAlignContent(
+      root_child0_child0_child1_child0_child1_child0, YGAlignStretch);
+  YGNodeStyleSetFlexShrink(root_child0_child0_child1_child0_child1_child0, 1);
+  YGNodeInsertChild(
+      root_child0_child0_child1_child0_child1,
+      root_child0_child0_child1_child0_child1_child0,
+      0);
+
+  const YGNodeRef root_child0_child0_child1_child0_child1_child1 =
+      YGNodeNewWithConfig(config);
+  YGNodeStyleSetAlignContent(
+      root_child0_child0_child1_child0_child1_child1, YGAlignStretch);
+  YGNodeStyleSetFlexShrink(root_child0_child0_child1_child0_child1_child1, 1);
+  YGNodeInsertChild(
+      root_child0_child0_child1_child0_child1,
+      root_child0_child0_child1_child0_child1_child1,
+      1);
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(1080, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(240, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(1080, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(240, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0_child0));
+  ASSERT_FLOAT_EQ(1080, YGNodeLayoutGetWidth(root_child0_child0));
+  ASSERT_FLOAT_EQ(240, YGNodeLayoutGetHeight(root_child0_child0));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0_child0_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0_child0_child0));
+  ASSERT_FLOAT_EQ(1080, YGNodeLayoutGetWidth(root_child0_child0_child0));
+  ASSERT_FLOAT_EQ(144, YGNodeLayoutGetHeight(root_child0_child0_child0));
+
+  ASSERT_FLOAT_EQ(36, YGNodeLayoutGetLeft(root_child0_child0_child0_child0));
+  ASSERT_FLOAT_EQ(24, YGNodeLayoutGetTop(root_child0_child0_child0_child0));
+  ASSERT_FLOAT_EQ(1044, YGNodeLayoutGetWidth(root_child0_child0_child0_child0));
+  ASSERT_FLOAT_EQ(120, YGNodeLayoutGetHeight(root_child0_child0_child0_child0));
+
+  ASSERT_FLOAT_EQ(
+      0, YGNodeLayoutGetLeft(root_child0_child0_child0_child0_child0));
+  ASSERT_FLOAT_EQ(
+      0, YGNodeLayoutGetTop(root_child0_child0_child0_child0_child0));
+  ASSERT_FLOAT_EQ(
+      120, YGNodeLayoutGetWidth(root_child0_child0_child0_child0_child0));
+  ASSERT_FLOAT_EQ(
+      120, YGNodeLayoutGetHeight(root_child0_child0_child0_child0_child0));
+
+  ASSERT_FLOAT_EQ(
+      0, YGNodeLayoutGetLeft(root_child0_child0_child0_child0_child0_child0));
+  ASSERT_FLOAT_EQ(
+      0, YGNodeLayoutGetTop(root_child0_child0_child0_child0_child0_child0));
+  ASSERT_FLOAT_EQ(
+      120,
+      YGNodeLayoutGetWidth(root_child0_child0_child0_child0_child0_child0));
+  ASSERT_FLOAT_EQ(
+      120,
+      YGNodeLayoutGetHeight(root_child0_child0_child0_child0_child0_child0));
+
+  ASSERT_FLOAT_EQ(
+      120, YGNodeLayoutGetLeft(root_child0_child0_child0_child0_child1));
+  ASSERT_FLOAT_EQ(
+      0, YGNodeLayoutGetTop(root_child0_child0_child0_child0_child1));
+  ASSERT_FLOAT_EQ(
+      72, YGNodeLayoutGetWidth(root_child0_child0_child0_child0_child1));
+  ASSERT_FLOAT_EQ(
+      39, YGNodeLayoutGetHeight(root_child0_child0_child0_child0_child1));
+
+  ASSERT_FLOAT_EQ(
+      36, YGNodeLayoutGetLeft(root_child0_child0_child0_child0_child1_child0));
+  ASSERT_FLOAT_EQ(
+      21, YGNodeLayoutGetTop(root_child0_child0_child0_child0_child1_child0));
+  ASSERT_FLOAT_EQ(
+      0, YGNodeLayoutGetWidth(root_child0_child0_child0_child0_child1_child0));
+  ASSERT_FLOAT_EQ(
+      0, YGNodeLayoutGetHeight(root_child0_child0_child0_child0_child1_child0));
+
+  ASSERT_FLOAT_EQ(
+      36, YGNodeLayoutGetLeft(root_child0_child0_child0_child0_child1_child1));
+  ASSERT_FLOAT_EQ(
+      21, YGNodeLayoutGetTop(root_child0_child0_child0_child0_child1_child1));
+  ASSERT_FLOAT_EQ(
+      0, YGNodeLayoutGetWidth(root_child0_child0_child0_child0_child1_child1));
+  ASSERT_FLOAT_EQ(
+      0, YGNodeLayoutGetHeight(root_child0_child0_child0_child0_child1_child1));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0_child0_child1));
+  ASSERT_FLOAT_EQ(144, YGNodeLayoutGetTop(root_child0_child0_child1));
+  ASSERT_FLOAT_EQ(1080, YGNodeLayoutGetWidth(root_child0_child0_child1));
+  ASSERT_FLOAT_EQ(96, YGNodeLayoutGetHeight(root_child0_child0_child1));
+
+  ASSERT_FLOAT_EQ(174, YGNodeLayoutGetLeft(root_child0_child0_child1_child0));
+  ASSERT_FLOAT_EQ(24, YGNodeLayoutGetTop(root_child0_child0_child1_child0));
+  ASSERT_FLOAT_EQ(906, YGNodeLayoutGetWidth(root_child0_child0_child1_child0));
+  ASSERT_FLOAT_EQ(72, YGNodeLayoutGetHeight(root_child0_child0_child1_child0));
+
+  ASSERT_FLOAT_EQ(
+      0, YGNodeLayoutGetLeft(root_child0_child0_child1_child0_child0));
+  ASSERT_FLOAT_EQ(
+      0, YGNodeLayoutGetTop(root_child0_child0_child1_child0_child0));
+  ASSERT_FLOAT_EQ(
+      72, YGNodeLayoutGetWidth(root_child0_child0_child1_child0_child0));
+  ASSERT_FLOAT_EQ(
+      72, YGNodeLayoutGetHeight(root_child0_child0_child1_child0_child0));
+
+  ASSERT_FLOAT_EQ(
+      0, YGNodeLayoutGetLeft(root_child0_child0_child1_child0_child0_child0));
+  ASSERT_FLOAT_EQ(
+      0, YGNodeLayoutGetTop(root_child0_child0_child1_child0_child0_child0));
+  ASSERT_FLOAT_EQ(
+      72, YGNodeLayoutGetWidth(root_child0_child0_child1_child0_child0_child0));
+  ASSERT_FLOAT_EQ(
+      72,
+      YGNodeLayoutGetHeight(root_child0_child0_child1_child0_child0_child0));
+
+  ASSERT_FLOAT_EQ(
+      72, YGNodeLayoutGetLeft(root_child0_child0_child1_child0_child1));
+  ASSERT_FLOAT_EQ(
+      0, YGNodeLayoutGetTop(root_child0_child0_child1_child0_child1));
+  ASSERT_FLOAT_EQ(
+      72, YGNodeLayoutGetWidth(root_child0_child0_child1_child0_child1));
+  ASSERT_FLOAT_EQ(
+      39, YGNodeLayoutGetHeight(root_child0_child0_child1_child0_child1));
+
+  ASSERT_FLOAT_EQ(
+      36, YGNodeLayoutGetLeft(root_child0_child0_child1_child0_child1_child0));
+  ASSERT_FLOAT_EQ(
+      21, YGNodeLayoutGetTop(root_child0_child0_child1_child0_child1_child0));
+  ASSERT_FLOAT_EQ(
+      0, YGNodeLayoutGetWidth(root_child0_child0_child1_child0_child1_child0));
+  ASSERT_FLOAT_EQ(
+      0, YGNodeLayoutGetHeight(root_child0_child0_child1_child0_child1_child0));
+
+  ASSERT_FLOAT_EQ(
+      36, YGNodeLayoutGetLeft(root_child0_child0_child1_child0_child1_child1));
+  ASSERT_FLOAT_EQ(
+      21, YGNodeLayoutGetTop(root_child0_child0_child1_child0_child1_child1));
+  ASSERT_FLOAT_EQ(
+      0, YGNodeLayoutGetWidth(root_child0_child0_child1_child0_child1_child1));
+  ASSERT_FLOAT_EQ(
+      0, YGNodeLayoutGetHeight(root_child0_child0_child1_child0_child1_child1));
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(1080, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(240, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(1080, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(240, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0_child0));
+  ASSERT_FLOAT_EQ(1080, YGNodeLayoutGetWidth(root_child0_child0));
+  ASSERT_FLOAT_EQ(240, YGNodeLayoutGetHeight(root_child0_child0));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0_child0_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0_child0_child0));
+  ASSERT_FLOAT_EQ(1080, YGNodeLayoutGetWidth(root_child0_child0_child0));
+  ASSERT_FLOAT_EQ(144, YGNodeLayoutGetHeight(root_child0_child0_child0));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0_child0_child0_child0));
+  ASSERT_FLOAT_EQ(24, YGNodeLayoutGetTop(root_child0_child0_child0_child0));
+  ASSERT_FLOAT_EQ(1044, YGNodeLayoutGetWidth(root_child0_child0_child0_child0));
+  ASSERT_FLOAT_EQ(120, YGNodeLayoutGetHeight(root_child0_child0_child0_child0));
+
+  ASSERT_FLOAT_EQ(
+      924, YGNodeLayoutGetLeft(root_child0_child0_child0_child0_child0));
+  ASSERT_FLOAT_EQ(
+      0, YGNodeLayoutGetTop(root_child0_child0_child0_child0_child0));
+  ASSERT_FLOAT_EQ(
+      120, YGNodeLayoutGetWidth(root_child0_child0_child0_child0_child0));
+  ASSERT_FLOAT_EQ(
+      120, YGNodeLayoutGetHeight(root_child0_child0_child0_child0_child0));
+
+  ASSERT_FLOAT_EQ(
+      0, YGNodeLayoutGetLeft(root_child0_child0_child0_child0_child0_child0));
+  ASSERT_FLOAT_EQ(
+      0, YGNodeLayoutGetTop(root_child0_child0_child0_child0_child0_child0));
+  ASSERT_FLOAT_EQ(
+      120,
+      YGNodeLayoutGetWidth(root_child0_child0_child0_child0_child0_child0));
+  ASSERT_FLOAT_EQ(
+      120,
+      YGNodeLayoutGetHeight(root_child0_child0_child0_child0_child0_child0));
+
+  ASSERT_FLOAT_EQ(
+      816, YGNodeLayoutGetLeft(root_child0_child0_child0_child0_child1));
+  ASSERT_FLOAT_EQ(
+      0, YGNodeLayoutGetTop(root_child0_child0_child0_child0_child1));
+  ASSERT_FLOAT_EQ(
+      72, YGNodeLayoutGetWidth(root_child0_child0_child0_child0_child1));
+  ASSERT_FLOAT_EQ(
+      39, YGNodeLayoutGetHeight(root_child0_child0_child0_child0_child1));
+
+  ASSERT_FLOAT_EQ(
+      36, YGNodeLayoutGetLeft(root_child0_child0_child0_child0_child1_child0));
+  ASSERT_FLOAT_EQ(
+      21, YGNodeLayoutGetTop(root_child0_child0_child0_child0_child1_child0));
+  ASSERT_FLOAT_EQ(
+      0, YGNodeLayoutGetWidth(root_child0_child0_child0_child0_child1_child0));
+  ASSERT_FLOAT_EQ(
+      0, YGNodeLayoutGetHeight(root_child0_child0_child0_child0_child1_child0));
+
+  ASSERT_FLOAT_EQ(
+      36, YGNodeLayoutGetLeft(root_child0_child0_child0_child0_child1_child1));
+  ASSERT_FLOAT_EQ(
+      21, YGNodeLayoutGetTop(root_child0_child0_child0_child0_child1_child1));
+  ASSERT_FLOAT_EQ(
+      0, YGNodeLayoutGetWidth(root_child0_child0_child0_child0_child1_child1));
+  ASSERT_FLOAT_EQ(
+      0, YGNodeLayoutGetHeight(root_child0_child0_child0_child0_child1_child1));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0_child0_child1));
+  ASSERT_FLOAT_EQ(144, YGNodeLayoutGetTop(root_child0_child0_child1));
+  ASSERT_FLOAT_EQ(1080, YGNodeLayoutGetWidth(root_child0_child0_child1));
+  ASSERT_FLOAT_EQ(96, YGNodeLayoutGetHeight(root_child0_child0_child1));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0_child0_child1_child0));
+  ASSERT_FLOAT_EQ(24, YGNodeLayoutGetTop(root_child0_child0_child1_child0));
+  ASSERT_FLOAT_EQ(906, YGNodeLayoutGetWidth(root_child0_child0_child1_child0));
+  ASSERT_FLOAT_EQ(72, YGNodeLayoutGetHeight(root_child0_child0_child1_child0));
+
+  ASSERT_FLOAT_EQ(
+      834, YGNodeLayoutGetLeft(root_child0_child0_child1_child0_child0));
+  ASSERT_FLOAT_EQ(
+      0, YGNodeLayoutGetTop(root_child0_child0_child1_child0_child0));
+  ASSERT_FLOAT_EQ(
+      72, YGNodeLayoutGetWidth(root_child0_child0_child1_child0_child0));
+  ASSERT_FLOAT_EQ(
+      72, YGNodeLayoutGetHeight(root_child0_child0_child1_child0_child0));
+
+  ASSERT_FLOAT_EQ(
+      0, YGNodeLayoutGetLeft(root_child0_child0_child1_child0_child0_child0));
+  ASSERT_FLOAT_EQ(
+      0, YGNodeLayoutGetTop(root_child0_child0_child1_child0_child0_child0));
+  ASSERT_FLOAT_EQ(
+      72, YGNodeLayoutGetWidth(root_child0_child0_child1_child0_child0_child0));
+  ASSERT_FLOAT_EQ(
+      72,
+      YGNodeLayoutGetHeight(root_child0_child0_child1_child0_child0_child0));
+
+  ASSERT_FLOAT_EQ(
+      726, YGNodeLayoutGetLeft(root_child0_child0_child1_child0_child1));
+  ASSERT_FLOAT_EQ(
+      0, YGNodeLayoutGetTop(root_child0_child0_child1_child0_child1));
+  ASSERT_FLOAT_EQ(
+      72, YGNodeLayoutGetWidth(root_child0_child0_child1_child0_child1));
+  ASSERT_FLOAT_EQ(
+      39, YGNodeLayoutGetHeight(root_child0_child0_child1_child0_child1));
+
+  ASSERT_FLOAT_EQ(
+      36, YGNodeLayoutGetLeft(root_child0_child0_child1_child0_child1_child0));
+  ASSERT_FLOAT_EQ(
+      21, YGNodeLayoutGetTop(root_child0_child0_child1_child0_child1_child0));
+  ASSERT_FLOAT_EQ(
+      0, YGNodeLayoutGetWidth(root_child0_child0_child1_child0_child1_child0));
+  ASSERT_FLOAT_EQ(
+      0, YGNodeLayoutGetHeight(root_child0_child0_child1_child0_child1_child0));
+
+  ASSERT_FLOAT_EQ(
+      36, YGNodeLayoutGetLeft(root_child0_child0_child1_child0_child1_child1));
+  ASSERT_FLOAT_EQ(
+      21, YGNodeLayoutGetTop(root_child0_child0_child1_child0_child1_child1));
+  ASSERT_FLOAT_EQ(
+      0, YGNodeLayoutGetWidth(root_child0_child0_child1_child0_child1_child1));
+  ASSERT_FLOAT_EQ(
+      0, YGNodeLayoutGetHeight(root_child0_child0_child1_child0_child1_child1));
+
+  YGNodeFreeRecursive(root);
+
+  YGConfigFree(config);
+}
diff --git a/automated-tests/src/dali-toolkit-third-party/yoga/YGAspectRatioTest.cpp b/automated-tests/src/dali-toolkit-third-party/yoga/YGAspectRatioTest.cpp
new file mode 100644 (file)
index 0000000..c49133e
--- /dev/null
@@ -0,0 +1,898 @@
+/**
+ * Copyright (c) 2014-present, Facebook, Inc.
+ *
+ * This source code is licensed under the MIT license found in the
+ * LICENSE file in the root directory of this source tree.
+ */
+
+#include <gtest/gtest.h>
+#include <yoga/YGNode.h>
+#include <yoga/Yoga.h>
+
+static YGSize _measure_for_aspect_ratio(YGNodeRef node,
+                                                               float width,
+                                                               YGMeasureMode widthMode,
+                                                               float height,
+                                                               YGMeasureMode heightMode) {
+  return YGSize{
+      .width = widthMode == YGMeasureModeExactly ? width : 50,
+      .height = heightMode == YGMeasureModeExactly ? height : 50,
+  };
+}
+
+TEST(YogaTest, aspect_ratio_cross_defined) {
+  const YGNodeRef root = YGNodeNew();
+  YGNodeStyleSetAlignItems(root, YGAlignFlexStart);
+  YGNodeStyleSetWidth(root, 100);
+  YGNodeStyleSetHeight(root, 100);
+
+  const YGNodeRef root_child0 = YGNodeNew();
+  YGNodeStyleSetWidth(root_child0, 50);
+  YGNodeStyleSetAspectRatio(root_child0, 1);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_EQ(50, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_EQ(50, YGNodeLayoutGetHeight(root_child0));
+
+  YGNodeFreeRecursive(root);
+}
+
+TEST(YogaTest, aspect_ratio_main_defined) {
+  const YGNodeRef root = YGNodeNew();
+  YGNodeStyleSetAlignItems(root, YGAlignFlexStart);
+  YGNodeStyleSetWidth(root, 100);
+  YGNodeStyleSetHeight(root, 100);
+
+  const YGNodeRef root_child0 = YGNodeNew();
+  YGNodeStyleSetHeight(root_child0, 50);
+  YGNodeStyleSetAspectRatio(root_child0, 1);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_EQ(50, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_EQ(50, YGNodeLayoutGetHeight(root_child0));
+
+  YGNodeFreeRecursive(root);
+}
+
+TEST(YogaTest, aspect_ratio_both_dimensions_defined_row) {
+  const YGNodeRef root = YGNodeNew();
+  YGNodeStyleSetFlexDirection(root, YGFlexDirectionRow);
+  YGNodeStyleSetAlignItems(root, YGAlignFlexStart);
+  YGNodeStyleSetWidth(root, 100);
+  YGNodeStyleSetHeight(root, 100);
+
+  const YGNodeRef root_child0 = YGNodeNew();
+  YGNodeStyleSetWidth(root_child0, 100);
+  YGNodeStyleSetHeight(root_child0, 50);
+  YGNodeStyleSetAspectRatio(root_child0, 1);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_EQ(100, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_EQ(100, YGNodeLayoutGetHeight(root_child0));
+
+  YGNodeFreeRecursive(root);
+}
+
+TEST(YogaTest, aspect_ratio_both_dimensions_defined_column) {
+  const YGNodeRef root = YGNodeNew();
+  YGNodeStyleSetAlignItems(root, YGAlignFlexStart);
+  YGNodeStyleSetWidth(root, 100);
+  YGNodeStyleSetHeight(root, 100);
+
+  const YGNodeRef root_child0 = YGNodeNew();
+  YGNodeStyleSetWidth(root_child0, 100);
+  YGNodeStyleSetHeight(root_child0, 50);
+  YGNodeStyleSetAspectRatio(root_child0, 1);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_EQ(50, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_EQ(50, YGNodeLayoutGetHeight(root_child0));
+
+  YGNodeFreeRecursive(root);
+}
+
+TEST(YogaTest, aspect_ratio_align_stretch) {
+  const YGNodeRef root = YGNodeNew();
+  YGNodeStyleSetWidth(root, 100);
+  YGNodeStyleSetHeight(root, 100);
+
+  const YGNodeRef root_child0 = YGNodeNew();
+  YGNodeStyleSetAspectRatio(root_child0, 1);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_EQ(100, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_EQ(100, YGNodeLayoutGetHeight(root_child0));
+
+  YGNodeFreeRecursive(root);
+}
+
+TEST(YogaTest, aspect_ratio_flex_grow) {
+  const YGNodeRef root = YGNodeNew();
+  YGNodeStyleSetAlignItems(root, YGAlignFlexStart);
+  YGNodeStyleSetWidth(root, 100);
+  YGNodeStyleSetHeight(root, 100);
+
+  const YGNodeRef root_child0 = YGNodeNew();
+  YGNodeStyleSetHeight(root_child0, 50);
+  YGNodeStyleSetFlexGrow(root_child0, 1);
+  YGNodeStyleSetAspectRatio(root_child0, 1);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_EQ(100, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_EQ(100, YGNodeLayoutGetHeight(root_child0));
+
+  YGNodeFreeRecursive(root);
+}
+
+TEST(YogaTest, aspect_ratio_flex_shrink) {
+  const YGNodeRef root = YGNodeNew();
+  YGNodeStyleSetAlignItems(root, YGAlignFlexStart);
+  YGNodeStyleSetWidth(root, 100);
+  YGNodeStyleSetHeight(root, 100);
+
+  const YGNodeRef root_child0 = YGNodeNew();
+  YGNodeStyleSetHeight(root_child0, 150);
+  YGNodeStyleSetFlexShrink(root_child0, 1);
+  YGNodeStyleSetAspectRatio(root_child0, 1);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_EQ(100, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_EQ(100, YGNodeLayoutGetHeight(root_child0));
+
+  YGNodeFreeRecursive(root);
+}
+
+TEST(YogaTest, aspect_ratio_flex_shrink_2) {
+  const YGNodeRef root = YGNodeNew();
+  YGNodeStyleSetWidth(root, 100);
+  YGNodeStyleSetHeight(root, 100);
+
+  const YGNodeRef root_child0 = YGNodeNew();
+  YGNodeStyleSetHeightPercent(root_child0, 100);
+  YGNodeStyleSetFlexShrink(root_child0, 1);
+  YGNodeStyleSetAspectRatio(root_child0, 1);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  const YGNodeRef root_child1 = YGNodeNew();
+  YGNodeStyleSetHeightPercent(root_child1, 100);
+  YGNodeStyleSetFlexShrink(root_child1, 1);
+  YGNodeStyleSetAspectRatio(root_child1, 1);
+  YGNodeInsertChild(root, root_child1, 1);
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_EQ(50, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_EQ(50, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_EQ(0, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_EQ(50, YGNodeLayoutGetTop(root_child1));
+  ASSERT_EQ(50, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_EQ(50, YGNodeLayoutGetHeight(root_child1));
+
+  YGNodeFreeRecursive(root);
+}
+
+TEST(YogaTest, aspect_ratio_basis) {
+  const YGNodeRef root = YGNodeNew();
+  YGNodeStyleSetAlignItems(root, YGAlignFlexStart);
+  YGNodeStyleSetWidth(root, 100);
+  YGNodeStyleSetHeight(root, 100);
+
+  const YGNodeRef root_child0 = YGNodeNew();
+  YGNodeStyleSetFlexBasis(root_child0, 50);
+  YGNodeStyleSetAspectRatio(root_child0, 1);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_EQ(50, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_EQ(50, YGNodeLayoutGetHeight(root_child0));
+
+  YGNodeFreeRecursive(root);
+}
+
+TEST(YogaTest, aspect_ratio_absolute_layout_width_defined) {
+  const YGNodeRef root = YGNodeNew();
+  YGNodeStyleSetWidth(root, 100);
+  YGNodeStyleSetHeight(root, 100);
+
+  const YGNodeRef root_child0 = YGNodeNew();
+  YGNodeStyleSetPositionType(root_child0, YGPositionTypeAbsolute);
+  YGNodeStyleSetPosition(root_child0, YGEdgeLeft, 0);
+  YGNodeStyleSetPosition(root_child0, YGEdgeTop, 0);
+  YGNodeStyleSetWidth(root_child0, 50);
+  YGNodeStyleSetAspectRatio(root_child0, 1);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_EQ(50, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_EQ(50, YGNodeLayoutGetHeight(root_child0));
+
+  YGNodeFreeRecursive(root);
+}
+
+TEST(YogaTest, aspect_ratio_absolute_layout_height_defined) {
+  const YGNodeRef root = YGNodeNew();
+  YGNodeStyleSetWidth(root, 100);
+  YGNodeStyleSetHeight(root, 100);
+
+  const YGNodeRef root_child0 = YGNodeNew();
+  YGNodeStyleSetPositionType(root_child0, YGPositionTypeAbsolute);
+  YGNodeStyleSetPosition(root_child0, YGEdgeLeft, 0);
+  YGNodeStyleSetPosition(root_child0, YGEdgeTop, 0);
+  YGNodeStyleSetHeight(root_child0, 50);
+  YGNodeStyleSetAspectRatio(root_child0, 1);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_EQ(50, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_EQ(50, YGNodeLayoutGetHeight(root_child0));
+
+  YGNodeFreeRecursive(root);
+}
+
+TEST(YogaTest, aspect_ratio_with_max_cross_defined) {
+  const YGNodeRef root = YGNodeNew();
+  YGNodeStyleSetAlignItems(root, YGAlignFlexStart);
+  YGNodeStyleSetWidth(root, 100);
+  YGNodeStyleSetHeight(root, 100);
+
+  const YGNodeRef root_child0 = YGNodeNew();
+  YGNodeStyleSetHeight(root_child0, 50);
+  YGNodeStyleSetMaxWidth(root_child0, 40);
+  YGNodeStyleSetAspectRatio(root_child0, 1);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_EQ(40, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_EQ(50, YGNodeLayoutGetHeight(root_child0));
+
+  YGNodeFreeRecursive(root);
+}
+
+TEST(YogaTest, aspect_ratio_with_max_main_defined) {
+  const YGNodeRef root = YGNodeNew();
+  YGNodeStyleSetAlignItems(root, YGAlignFlexStart);
+  YGNodeStyleSetWidth(root, 100);
+  YGNodeStyleSetHeight(root, 100);
+
+  const YGNodeRef root_child0 = YGNodeNew();
+  YGNodeStyleSetWidth(root_child0, 50);
+  YGNodeStyleSetMaxHeight(root_child0, 40);
+  YGNodeStyleSetAspectRatio(root_child0, 1);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_EQ(40, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_EQ(40, YGNodeLayoutGetHeight(root_child0));
+
+  YGNodeFreeRecursive(root);
+}
+
+TEST(YogaTest, aspect_ratio_with_min_cross_defined) {
+  const YGNodeRef root = YGNodeNew();
+  YGNodeStyleSetAlignItems(root, YGAlignFlexStart);
+  YGNodeStyleSetWidth(root, 100);
+  YGNodeStyleSetHeight(root, 100);
+
+  const YGNodeRef root_child0 = YGNodeNew();
+  YGNodeStyleSetHeight(root_child0, 30);
+  YGNodeStyleSetMinWidth(root_child0, 40);
+  YGNodeStyleSetAspectRatio(root_child0, 1);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_EQ(40, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_EQ(30, YGNodeLayoutGetHeight(root_child0));
+
+  YGNodeFreeRecursive(root);
+}
+
+TEST(YogaTest, aspect_ratio_with_min_main_defined) {
+  const YGNodeRef root = YGNodeNew();
+  YGNodeStyleSetAlignItems(root, YGAlignFlexStart);
+  YGNodeStyleSetWidth(root, 100);
+  YGNodeStyleSetHeight(root, 100);
+
+  const YGNodeRef root_child0 = YGNodeNew();
+  YGNodeStyleSetWidth(root_child0, 30);
+  YGNodeStyleSetMinHeight(root_child0, 40);
+  YGNodeStyleSetAspectRatio(root_child0, 1);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_EQ(40, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_EQ(40, YGNodeLayoutGetHeight(root_child0));
+
+  YGNodeFreeRecursive(root);
+}
+
+TEST(YogaTest, aspect_ratio_double_cross) {
+  const YGNodeRef root = YGNodeNew();
+  YGNodeStyleSetAlignItems(root, YGAlignFlexStart);
+  YGNodeStyleSetWidth(root, 100);
+  YGNodeStyleSetHeight(root, 100);
+
+  const YGNodeRef root_child0 = YGNodeNew();
+  YGNodeStyleSetHeight(root_child0, 50);
+  YGNodeStyleSetAspectRatio(root_child0, 2);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_EQ(100, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_EQ(50, YGNodeLayoutGetHeight(root_child0));
+
+  YGNodeFreeRecursive(root);
+}
+
+TEST(YogaTest, aspect_ratio_half_cross) {
+  const YGNodeRef root = YGNodeNew();
+  YGNodeStyleSetAlignItems(root, YGAlignFlexStart);
+  YGNodeStyleSetWidth(root, 100);
+  YGNodeStyleSetHeight(root, 100);
+
+  const YGNodeRef root_child0 = YGNodeNew();
+  YGNodeStyleSetHeight(root_child0, 100);
+  YGNodeStyleSetAspectRatio(root_child0, 0.5);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_EQ(50, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_EQ(100, YGNodeLayoutGetHeight(root_child0));
+
+  YGNodeFreeRecursive(root);
+}
+
+TEST(YogaTest, aspect_ratio_double_main) {
+  const YGNodeRef root = YGNodeNew();
+  YGNodeStyleSetAlignItems(root, YGAlignFlexStart);
+  YGNodeStyleSetWidth(root, 100);
+  YGNodeStyleSetHeight(root, 100);
+
+  const YGNodeRef root_child0 = YGNodeNew();
+  YGNodeStyleSetWidth(root_child0, 50);
+  YGNodeStyleSetAspectRatio(root_child0, 0.5);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_EQ(50, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_EQ(100, YGNodeLayoutGetHeight(root_child0));
+
+  YGNodeFreeRecursive(root);
+}
+
+TEST(YogaTest, aspect_ratio_half_main) {
+  const YGNodeRef root = YGNodeNew();
+  YGNodeStyleSetAlignItems(root, YGAlignFlexStart);
+  YGNodeStyleSetWidth(root, 100);
+  YGNodeStyleSetHeight(root, 100);
+
+  const YGNodeRef root_child0 = YGNodeNew();
+  YGNodeStyleSetWidth(root_child0, 100);
+  YGNodeStyleSetAspectRatio(root_child0, 2);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_EQ(100, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_EQ(50, YGNodeLayoutGetHeight(root_child0));
+
+  YGNodeFreeRecursive(root);
+}
+
+TEST(YogaTest, aspect_ratio_with_measure_func) {
+  const YGNodeRef root = YGNodeNew();
+  YGNodeStyleSetAlignItems(root, YGAlignFlexStart);
+  YGNodeStyleSetWidth(root, 100);
+  YGNodeStyleSetHeight(root, 100);
+
+  const YGNodeRef root_child0 = YGNodeNew();
+  root_child0->setMeasureFunc(_measure_for_aspect_ratio);
+  YGNodeStyleSetAspectRatio(root_child0, 1);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_EQ(50, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_EQ(50, YGNodeLayoutGetHeight(root_child0));
+
+  YGNodeFreeRecursive(root);
+}
+
+TEST(YogaTest, aspect_ratio_width_height_flex_grow_row) {
+  const YGNodeRef root = YGNodeNew();
+  YGNodeStyleSetFlexDirection(root, YGFlexDirectionRow);
+  YGNodeStyleSetAlignItems(root, YGAlignFlexStart);
+  YGNodeStyleSetWidth(root, 100);
+  YGNodeStyleSetHeight(root, 200);
+
+  const YGNodeRef root_child0 = YGNodeNew();
+  YGNodeStyleSetWidth(root_child0, 50);
+  YGNodeStyleSetHeight(root_child0, 50);
+  YGNodeStyleSetFlexGrow(root_child0, 1);
+  YGNodeStyleSetAspectRatio(root_child0, 1);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_EQ(100, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_EQ(100, YGNodeLayoutGetHeight(root_child0));
+
+  YGNodeFreeRecursive(root);
+}
+
+TEST(YogaTest, aspect_ratio_width_height_flex_grow_column) {
+  const YGNodeRef root = YGNodeNew();
+  YGNodeStyleSetAlignItems(root, YGAlignFlexStart);
+  YGNodeStyleSetWidth(root, 200);
+  YGNodeStyleSetHeight(root, 100);
+
+  const YGNodeRef root_child0 = YGNodeNew();
+  YGNodeStyleSetWidth(root_child0, 50);
+  YGNodeStyleSetHeight(root_child0, 50);
+  YGNodeStyleSetFlexGrow(root_child0, 1);
+  YGNodeStyleSetAspectRatio(root_child0, 1);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_EQ(100, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_EQ(100, YGNodeLayoutGetHeight(root_child0));
+
+  YGNodeFreeRecursive(root);
+}
+
+TEST(YogaTest, aspect_ratio_height_as_flex_basis) {
+  const YGNodeRef root = YGNodeNew();
+  YGNodeStyleSetAlignItems(root, YGAlignFlexStart);
+  YGNodeStyleSetFlexDirection(root, YGFlexDirectionRow);
+  YGNodeStyleSetWidth(root, 200);
+  YGNodeStyleSetHeight(root, 200);
+
+  const YGNodeRef root_child0 = YGNodeNew();
+  YGNodeStyleSetHeight(root_child0, 50);
+  YGNodeStyleSetFlexGrow(root_child0, 1);
+  YGNodeStyleSetAspectRatio(root_child0, 1);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  const YGNodeRef root_child1 = YGNodeNew();
+  YGNodeStyleSetHeight(root_child1, 100);
+  YGNodeStyleSetFlexGrow(root_child1, 1);
+  YGNodeStyleSetAspectRatio(root_child1, 1);
+  YGNodeInsertChild(root, root_child1, 1);
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_EQ(75, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_EQ(75, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_EQ(75, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_EQ(0, YGNodeLayoutGetTop(root_child1));
+  ASSERT_EQ(125, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_EQ(125, YGNodeLayoutGetHeight(root_child1));
+
+  YGNodeFreeRecursive(root);
+}
+
+TEST(YogaTest, aspect_ratio_width_as_flex_basis) {
+  const YGNodeRef root = YGNodeNew();
+  YGNodeStyleSetAlignItems(root, YGAlignFlexStart);
+  YGNodeStyleSetWidth(root, 200);
+  YGNodeStyleSetHeight(root, 200);
+
+  const YGNodeRef root_child0 = YGNodeNew();
+  YGNodeStyleSetWidth(root_child0, 50);
+  YGNodeStyleSetFlexGrow(root_child0, 1);
+  YGNodeStyleSetAspectRatio(root_child0, 1);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  const YGNodeRef root_child1 = YGNodeNew();
+  YGNodeStyleSetWidth(root_child1, 100);
+  YGNodeStyleSetFlexGrow(root_child1, 1);
+  YGNodeStyleSetAspectRatio(root_child1, 1);
+  YGNodeInsertChild(root, root_child1, 1);
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_EQ(75, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_EQ(75, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_EQ(0, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_EQ(75, YGNodeLayoutGetTop(root_child1));
+  ASSERT_EQ(125, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_EQ(125, YGNodeLayoutGetHeight(root_child1));
+
+  YGNodeFreeRecursive(root);
+}
+
+TEST(YogaTest, aspect_ratio_overrides_flex_grow_row) {
+  const YGNodeRef root = YGNodeNew();
+  YGNodeStyleSetAlignItems(root, YGAlignFlexStart);
+  YGNodeStyleSetFlexDirection(root, YGFlexDirectionRow);
+  YGNodeStyleSetWidth(root, 100);
+  YGNodeStyleSetHeight(root, 100);
+
+  const YGNodeRef root_child0 = YGNodeNew();
+  YGNodeStyleSetWidth(root_child0, 50);
+  YGNodeStyleSetFlexGrow(root_child0, 1);
+  YGNodeStyleSetAspectRatio(root_child0, 0.5);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_EQ(100, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_EQ(200, YGNodeLayoutGetHeight(root_child0));
+
+  YGNodeFreeRecursive(root);
+}
+
+TEST(YogaTest, aspect_ratio_overrides_flex_grow_column) {
+  const YGNodeRef root = YGNodeNew();
+  YGNodeStyleSetAlignItems(root, YGAlignFlexStart);
+  YGNodeStyleSetWidth(root, 100);
+  YGNodeStyleSetHeight(root, 100);
+
+  const YGNodeRef root_child0 = YGNodeNew();
+  YGNodeStyleSetHeight(root_child0, 50);
+  YGNodeStyleSetFlexGrow(root_child0, 1);
+  YGNodeStyleSetAspectRatio(root_child0, 2);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_EQ(200, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_EQ(100, YGNodeLayoutGetHeight(root_child0));
+
+  YGNodeFreeRecursive(root);
+}
+
+TEST(YogaTest, aspect_ratio_left_right_absolute) {
+  const YGNodeRef root = YGNodeNew();
+  YGNodeStyleSetWidth(root, 100);
+  YGNodeStyleSetHeight(root, 100);
+
+  const YGNodeRef root_child0 = YGNodeNew();
+  YGNodeStyleSetPositionType(root_child0, YGPositionTypeAbsolute);
+  YGNodeStyleSetPosition(root_child0, YGEdgeLeft, 10);
+  YGNodeStyleSetPosition(root_child0, YGEdgeTop, 10);
+  YGNodeStyleSetPosition(root_child0, YGEdgeRight, 10);
+  YGNodeStyleSetAspectRatio(root_child0, 1);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_EQ(10, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_EQ(10, YGNodeLayoutGetTop(root_child0));
+  ASSERT_EQ(80, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_EQ(80, YGNodeLayoutGetHeight(root_child0));
+
+  YGNodeFreeRecursive(root);
+}
+
+TEST(YogaTest, aspect_ratio_top_bottom_absolute) {
+  const YGNodeRef root = YGNodeNew();
+  YGNodeStyleSetWidth(root, 100);
+  YGNodeStyleSetHeight(root, 100);
+
+  const YGNodeRef root_child0 = YGNodeNew();
+  YGNodeStyleSetPositionType(root_child0, YGPositionTypeAbsolute);
+  YGNodeStyleSetPosition(root_child0, YGEdgeLeft, 10);
+  YGNodeStyleSetPosition(root_child0, YGEdgeTop, 10);
+  YGNodeStyleSetPosition(root_child0, YGEdgeBottom, 10);
+  YGNodeStyleSetAspectRatio(root_child0, 1);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_EQ(10, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_EQ(10, YGNodeLayoutGetTop(root_child0));
+  ASSERT_EQ(80, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_EQ(80, YGNodeLayoutGetHeight(root_child0));
+
+  YGNodeFreeRecursive(root);
+}
+
+TEST(YogaTest, aspect_ratio_width_overrides_align_stretch_row) {
+  const YGNodeRef root = YGNodeNew();
+  YGNodeStyleSetFlexDirection(root, YGFlexDirectionRow);
+  YGNodeStyleSetWidth(root, 100);
+  YGNodeStyleSetHeight(root, 100);
+
+  const YGNodeRef root_child0 = YGNodeNew();
+  YGNodeStyleSetWidth(root_child0, 50);
+  YGNodeStyleSetAspectRatio(root_child0, 1);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_EQ(50, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_EQ(50, YGNodeLayoutGetHeight(root_child0));
+
+  YGNodeFreeRecursive(root);
+}
+
+TEST(YogaTest, aspect_ratio_height_overrides_align_stretch_column) {
+  const YGNodeRef root = YGNodeNew();
+  YGNodeStyleSetWidth(root, 100);
+  YGNodeStyleSetHeight(root, 100);
+
+  const YGNodeRef root_child0 = YGNodeNew();
+  YGNodeStyleSetHeight(root_child0, 50);
+  YGNodeStyleSetAspectRatio(root_child0, 1);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_EQ(50, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_EQ(50, YGNodeLayoutGetHeight(root_child0));
+
+  YGNodeFreeRecursive(root);
+}
+
+TEST(YogaTest, aspect_ratio_allow_child_overflow_parent_size) {
+  const YGNodeRef root = YGNodeNew();
+  YGNodeStyleSetAlignItems(root, YGAlignFlexStart);
+  YGNodeStyleSetWidth(root, 100);
+
+  const YGNodeRef root_child0 = YGNodeNew();
+  YGNodeStyleSetHeight(root_child0, 50);
+  YGNodeStyleSetAspectRatio(root_child0, 4);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_EQ(100, YGNodeLayoutGetWidth(root));
+  ASSERT_EQ(50, YGNodeLayoutGetHeight(root));
+
+  ASSERT_EQ(200, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_EQ(50, YGNodeLayoutGetHeight(root_child0));
+
+  YGNodeFreeRecursive(root);
+}
+
+TEST(YogaTest, aspect_ratio_defined_main_with_margin) {
+  const YGNodeRef root = YGNodeNew();
+  YGNodeStyleSetAlignItems(root, YGAlignCenter);
+  YGNodeStyleSetJustifyContent(root, YGJustifyCenter);
+  YGNodeStyleSetWidth(root, 100);
+  YGNodeStyleSetHeight(root, 100);
+
+  const YGNodeRef root_child0 = YGNodeNew();
+  YGNodeStyleSetHeight(root_child0, 50);
+  YGNodeStyleSetAspectRatio(root_child0, 1);
+  YGNodeStyleSetMargin(root_child0, YGEdgeLeft, 10);
+  YGNodeStyleSetMargin(root_child0, YGEdgeRight, 10);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_EQ(100, YGNodeLayoutGetWidth(root));
+  ASSERT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_EQ(50, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_EQ(50, YGNodeLayoutGetHeight(root_child0));
+
+  YGNodeFreeRecursive(root);
+}
+
+TEST(YogaTest, aspect_ratio_defined_cross_with_margin) {
+  const YGNodeRef root = YGNodeNew();
+  YGNodeStyleSetAlignItems(root, YGAlignCenter);
+  YGNodeStyleSetJustifyContent(root, YGJustifyCenter);
+  YGNodeStyleSetWidth(root, 100);
+  YGNodeStyleSetHeight(root, 100);
+
+  const YGNodeRef root_child0 = YGNodeNew();
+  YGNodeStyleSetWidth(root_child0, 50);
+  YGNodeStyleSetAspectRatio(root_child0, 1);
+  YGNodeStyleSetMargin(root_child0, YGEdgeLeft, 10);
+  YGNodeStyleSetMargin(root_child0, YGEdgeRight, 10);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_EQ(100, YGNodeLayoutGetWidth(root));
+  ASSERT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_EQ(50, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_EQ(50, YGNodeLayoutGetHeight(root_child0));
+
+  YGNodeFreeRecursive(root);
+}
+
+TEST(YogaTest, aspect_ratio_defined_cross_with_main_margin) {
+  const YGNodeRef root = YGNodeNew();
+  YGNodeStyleSetAlignItems(root, YGAlignCenter);
+  YGNodeStyleSetJustifyContent(root, YGJustifyCenter);
+  YGNodeStyleSetWidth(root, 100);
+  YGNodeStyleSetHeight(root, 100);
+
+  const YGNodeRef root_child0 = YGNodeNew();
+  YGNodeStyleSetWidth(root_child0, 50);
+  YGNodeStyleSetAspectRatio(root_child0, 1);
+  YGNodeStyleSetMargin(root_child0, YGEdgeTop, 10);
+  YGNodeStyleSetMargin(root_child0, YGEdgeBottom, 10);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_EQ(100, YGNodeLayoutGetWidth(root));
+  ASSERT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_EQ(50, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_EQ(50, YGNodeLayoutGetHeight(root_child0));
+
+  YGNodeFreeRecursive(root);
+}
+
+TEST(YogaTest, aspect_ratio_should_prefer_explicit_height) {
+  const YGConfigRef config = YGConfigNew();
+  YGConfigSetUseWebDefaults(config, true);
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexDirection(root, YGFlexDirectionColumn);
+
+  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexDirection(root_child0, YGFlexDirectionColumn);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  const YGNodeRef root_child0_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexDirection(root_child0_child0, YGFlexDirectionColumn);
+  YGNodeStyleSetHeight(root_child0_child0, 100);
+  YGNodeStyleSetAspectRatio(root_child0_child0, 2);
+  YGNodeInsertChild(root_child0, root_child0_child0, 0);
+
+  YGNodeCalculateLayout(root, 100, 200, YGDirectionLTR);
+
+  ASSERT_EQ(100, YGNodeLayoutGetWidth(root));
+  ASSERT_EQ(200, YGNodeLayoutGetHeight(root));
+
+  ASSERT_EQ(100, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_EQ(100, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_EQ(200, YGNodeLayoutGetWidth(root_child0_child0));
+  ASSERT_EQ(100, YGNodeLayoutGetHeight(root_child0_child0));
+
+  YGNodeFreeRecursive(root);
+}
+
+TEST(YogaTest, aspect_ratio_should_prefer_explicit_width) {
+  const YGConfigRef config = YGConfigNew();
+  YGConfigSetUseWebDefaults(config, true);
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexDirection(root, YGFlexDirectionRow);
+
+  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexDirection(root_child0, YGFlexDirectionRow);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  const YGNodeRef root_child0_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexDirection(root_child0_child0, YGFlexDirectionRow);
+  YGNodeStyleSetWidth(root_child0_child0, 100);
+  YGNodeStyleSetAspectRatio(root_child0_child0, 0.5);
+  YGNodeInsertChild(root_child0, root_child0_child0, 0);
+
+  YGNodeCalculateLayout(root, 200, 100, YGDirectionLTR);
+
+  ASSERT_EQ(200, YGNodeLayoutGetWidth(root));
+  ASSERT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_EQ(100, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_EQ(100, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_EQ(100, YGNodeLayoutGetWidth(root_child0_child0));
+  ASSERT_EQ(200, YGNodeLayoutGetHeight(root_child0_child0));
+
+  YGNodeFreeRecursive(root);
+}
+
+TEST(YogaTest, aspect_ratio_should_prefer_flexed_dimension) {
+  const YGConfigRef config = YGConfigNew();
+  YGConfigSetUseWebDefaults(config, true);
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+
+  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexDirection(root_child0, YGFlexDirectionColumn);
+  YGNodeStyleSetAspectRatio(root_child0, 2);
+  YGNodeStyleSetFlexGrow(root_child0, 1);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  const YGNodeRef root_child0_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetAspectRatio(root_child0_child0, 4);
+  YGNodeStyleSetFlexGrow(root_child0_child0, 1);
+  YGNodeInsertChild(root_child0, root_child0_child0, 0);
+
+  YGNodeCalculateLayout(root, 100, 100, YGDirectionLTR);
+
+  ASSERT_EQ(100, YGNodeLayoutGetWidth(root));
+  ASSERT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_EQ(100, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_EQ(50, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_EQ(200, YGNodeLayoutGetWidth(root_child0_child0));
+  ASSERT_EQ(50, YGNodeLayoutGetHeight(root_child0_child0));
+
+  YGNodeFreeRecursive(root);
+}
diff --git a/automated-tests/src/dali-toolkit-third-party/yoga/YGBaselineFuncTest.cpp b/automated-tests/src/dali-toolkit-third-party/yoga/YGBaselineFuncTest.cpp
new file mode 100644 (file)
index 0000000..c8d1ff1
--- /dev/null
@@ -0,0 +1,62 @@
+/**
+ * Copyright (c) 2014-present, Facebook, Inc.
+ *
+ * This source code is licensed under the MIT license found in the
+ * LICENSE file in the root directory of this source tree.
+ */
+
+#include <gtest/gtest.h>
+#include <yoga/YGNode.h>
+#include <yoga/Yoga.h>
+
+static float _baseline(YGNodeRef node, const float width, const float height) {
+  float* baseline = (float*)node->getContext();
+  return *baseline;
+}
+
+TEST(YogaTest, align_baseline_customer_func) {
+  const YGNodeRef root = YGNodeNew();
+  YGNodeStyleSetFlexDirection(root, YGFlexDirectionRow);
+  YGNodeStyleSetAlignItems(root, YGAlignBaseline);
+  YGNodeStyleSetWidth(root, 100);
+  YGNodeStyleSetHeight(root, 100);
+
+  const YGNodeRef root_child0 = YGNodeNew();
+  YGNodeStyleSetWidth(root_child0, 50);
+  YGNodeStyleSetHeight(root_child0, 50);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  const YGNodeRef root_child1 = YGNodeNew();
+  YGNodeStyleSetWidth(root_child1, 50);
+  YGNodeStyleSetHeight(root_child1, 20);
+  YGNodeInsertChild(root, root_child1, 1);
+
+  float baselineValue = 10;
+  const YGNodeRef root_child1_child0 = YGNodeNew();
+  root_child1_child0->setContext(&baselineValue);
+  YGNodeStyleSetWidth(root_child1_child0, 50);
+  root_child1_child0->setBaseLineFunc(_baseline);
+  YGNodeStyleSetHeight(root_child1_child0, 20);
+  YGNodeInsertChild(root_child1, root_child1_child0, 0);
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(40, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(20, YGNodeLayoutGetHeight(root_child1));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child1_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child1_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child1_child0));
+  ASSERT_FLOAT_EQ(20, YGNodeLayoutGetHeight(root_child1_child0));
+}
diff --git a/automated-tests/src/dali-toolkit-third-party/yoga/YGBorderTest.cpp b/automated-tests/src/dali-toolkit-third-party/yoga/YGBorderTest.cpp
new file mode 100644 (file)
index 0000000..d4e6376
--- /dev/null
@@ -0,0 +1,212 @@
+/**
+ * Copyright (c) 2014-present, Facebook, Inc.
+ *
+ * This source code is licensed under the MIT license found in the
+ * LICENSE file in the root directory of this source tree.
+ */
+
+// @Generated by gentest/gentest.rb from gentest/fixtures/YGBorderTest.html
+
+#include <gtest/gtest.h>
+#include <yoga/Yoga.h>
+
+TEST(YogaTest, border_no_size) {
+  const YGConfigRef config = YGConfigNew();
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  YGNodeStyleSetBorder(root, YGEdgeLeft, 10);
+  YGNodeStyleSetBorder(root, YGEdgeTop, 10);
+  YGNodeStyleSetBorder(root, YGEdgeRight, 10);
+  YGNodeStyleSetBorder(root, YGEdgeBottom, 10);
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(20, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(20, YGNodeLayoutGetHeight(root));
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(20, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(20, YGNodeLayoutGetHeight(root));
+
+  YGNodeFreeRecursive(root);
+
+  YGConfigFree(config);
+}
+
+TEST(YogaTest, border_container_match_child) {
+  const YGConfigRef config = YGConfigNew();
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  YGNodeStyleSetBorder(root, YGEdgeLeft, 10);
+  YGNodeStyleSetBorder(root, YGEdgeTop, 10);
+  YGNodeStyleSetBorder(root, YGEdgeRight, 10);
+  YGNodeStyleSetBorder(root, YGEdgeBottom, 10);
+
+  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child0, 10);
+  YGNodeStyleSetHeight(root_child0, 10);
+  YGNodeInsertChild(root, root_child0, 0);
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(30, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(30, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child0));
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(30, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(30, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child0));
+
+  YGNodeFreeRecursive(root);
+
+  YGConfigFree(config);
+}
+
+TEST(YogaTest, border_flex_child) {
+  const YGConfigRef config = YGConfigNew();
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  YGNodeStyleSetBorder(root, YGEdgeLeft, 10);
+  YGNodeStyleSetBorder(root, YGEdgeTop, 10);
+  YGNodeStyleSetBorder(root, YGEdgeRight, 10);
+  YGNodeStyleSetBorder(root, YGEdgeBottom, 10);
+  YGNodeStyleSetWidth(root, 100);
+  YGNodeStyleSetHeight(root, 100);
+
+  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexGrow(root_child0, 1);
+  YGNodeStyleSetWidth(root_child0, 10);
+  YGNodeInsertChild(root, root_child0, 0);
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(80, YGNodeLayoutGetHeight(root_child0));
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(80, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(80, YGNodeLayoutGetHeight(root_child0));
+
+  YGNodeFreeRecursive(root);
+
+  YGConfigFree(config);
+}
+
+TEST(YogaTest, border_stretch_child) {
+  const YGConfigRef config = YGConfigNew();
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  YGNodeStyleSetBorder(root, YGEdgeLeft, 10);
+  YGNodeStyleSetBorder(root, YGEdgeTop, 10);
+  YGNodeStyleSetBorder(root, YGEdgeRight, 10);
+  YGNodeStyleSetBorder(root, YGEdgeBottom, 10);
+  YGNodeStyleSetWidth(root, 100);
+  YGNodeStyleSetHeight(root, 100);
+
+  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetHeight(root_child0, 10);
+  YGNodeInsertChild(root, root_child0, 0);
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(80, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child0));
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(80, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child0));
+
+  YGNodeFreeRecursive(root);
+
+  YGConfigFree(config);
+}
+
+TEST(YogaTest, border_center_child) {
+  const YGConfigRef config = YGConfigNew();
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  YGNodeStyleSetJustifyContent(root, YGJustifyCenter);
+  YGNodeStyleSetAlignItems(root, YGAlignCenter);
+  YGNodeStyleSetBorder(root, YGEdgeStart, 10);
+  YGNodeStyleSetBorder(root, YGEdgeEnd, 20);
+  YGNodeStyleSetBorder(root, YGEdgeBottom, 20);
+  YGNodeStyleSetWidth(root, 100);
+  YGNodeStyleSetHeight(root, 100);
+
+  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child0, 10);
+  YGNodeStyleSetHeight(root_child0, 10);
+  YGNodeInsertChild(root, root_child0, 0);
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(40, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(35, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child0));
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(35, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child0));
+
+  YGNodeFreeRecursive(root);
+
+  YGConfigFree(config);
+}
diff --git a/automated-tests/src/dali-toolkit-third-party/yoga/YGComputedMarginTest.cpp b/automated-tests/src/dali-toolkit-third-party/yoga/YGComputedMarginTest.cpp
new file mode 100644 (file)
index 0000000..9cbbe4e
--- /dev/null
@@ -0,0 +1,28 @@
+/**
+ * Copyright (c) 2014-present, Facebook, Inc.
+ *
+ * This source code is licensed under the MIT license found in the
+ * LICENSE file in the root directory of this source tree.
+ */
+
+#include <gtest/gtest.h>
+#include <yoga/Yoga.h>
+
+TEST(YogaTest, computed_layout_margin) {
+  const YGNodeRef root = YGNodeNew();
+  YGNodeStyleSetWidth(root, 100);
+  YGNodeStyleSetHeight(root, 100);
+  YGNodeStyleSetMarginPercent(root, YGEdgeStart, 10);
+
+  YGNodeCalculateLayout(root, 100, 100, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetMargin(root, YGEdgeLeft));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetMargin(root, YGEdgeRight));
+
+  YGNodeCalculateLayout(root, 100, 100, YGDirectionRTL);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetMargin(root, YGEdgeLeft));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetMargin(root, YGEdgeRight));
+
+  YGNodeFreeRecursive(root);
+}
diff --git a/automated-tests/src/dali-toolkit-third-party/yoga/YGComputedPaddingTest.cpp b/automated-tests/src/dali-toolkit-third-party/yoga/YGComputedPaddingTest.cpp
new file mode 100644 (file)
index 0000000..bf31fe7
--- /dev/null
@@ -0,0 +1,28 @@
+/**
+ * Copyright (c) 2014-present, Facebook, Inc.
+ *
+ * This source code is licensed under the MIT license found in the
+ * LICENSE file in the root directory of this source tree.
+ */
+
+#include <gtest/gtest.h>
+#include <yoga/Yoga.h>
+
+TEST(YogaTest, computed_layout_padding) {
+  const YGNodeRef root = YGNodeNew();
+  YGNodeStyleSetWidth(root, 100);
+  YGNodeStyleSetHeight(root, 100);
+  YGNodeStyleSetPaddingPercent(root, YGEdgeStart, 10);
+
+  YGNodeCalculateLayout(root, 100, 100, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetPadding(root, YGEdgeLeft));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetPadding(root, YGEdgeRight));
+
+  YGNodeCalculateLayout(root, 100, 100, YGDirectionRTL);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetPadding(root, YGEdgeLeft));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetPadding(root, YGEdgeRight));
+
+  YGNodeFreeRecursive(root);
+}
diff --git a/automated-tests/src/dali-toolkit-third-party/yoga/YGDefaultValuesTest.cpp b/automated-tests/src/dali-toolkit-third-party/yoga/YGDefaultValuesTest.cpp
new file mode 100644 (file)
index 0000000..ca14386
--- /dev/null
@@ -0,0 +1,164 @@
+/**
+ * Copyright (c) 2014-present, Facebook, Inc.
+ *
+ * This source code is licensed under the MIT license found in the
+ * LICENSE file in the root directory of this source tree.
+ */
+
+#include <gtest/gtest.h>
+#include <yoga/Yoga.h>
+
+TEST(YogaTest, assert_default_values) {
+  const YGNodeRef root = YGNodeNew();
+
+  ASSERT_EQ(0, YGNodeGetChildCount(root));
+  ASSERT_EQ(NULL, YGNodeGetChild(root, 1));
+
+  ASSERT_EQ(YGDirectionInherit, YGNodeStyleGetDirection(root));
+  ASSERT_EQ(YGFlexDirectionColumn, YGNodeStyleGetFlexDirection(root));
+  ASSERT_EQ(YGJustifyFlexStart, YGNodeStyleGetJustifyContent(root));
+  ASSERT_EQ(YGAlignFlexStart, YGNodeStyleGetAlignContent(root));
+  ASSERT_EQ(YGAlignStretch, YGNodeStyleGetAlignItems(root));
+  ASSERT_EQ(YGAlignAuto, YGNodeStyleGetAlignSelf(root));
+  ASSERT_EQ(YGPositionTypeRelative, YGNodeStyleGetPositionType(root));
+  ASSERT_EQ(YGWrapNoWrap, YGNodeStyleGetFlexWrap(root));
+  ASSERT_EQ(YGOverflowVisible, YGNodeStyleGetOverflow(root));
+  ASSERT_FLOAT_EQ(0, YGNodeStyleGetFlexGrow(root));
+  ASSERT_FLOAT_EQ(0, YGNodeStyleGetFlexShrink(root));
+  ASSERT_EQ(YGNodeStyleGetFlexBasis(root).unit, YGUnitAuto);
+
+  ASSERT_EQ(YGNodeStyleGetPosition(root, YGEdgeLeft).unit, YGUnitUndefined);
+  ASSERT_EQ(YGNodeStyleGetPosition(root, YGEdgeTop).unit, YGUnitUndefined);
+  ASSERT_EQ(YGNodeStyleGetPosition(root, YGEdgeRight).unit, YGUnitUndefined);
+  ASSERT_EQ(YGNodeStyleGetPosition(root, YGEdgeBottom).unit, YGUnitUndefined);
+  ASSERT_EQ(YGNodeStyleGetPosition(root, YGEdgeStart).unit, YGUnitUndefined);
+  ASSERT_EQ(YGNodeStyleGetPosition(root, YGEdgeEnd).unit, YGUnitUndefined);
+
+  ASSERT_EQ(YGNodeStyleGetMargin(root, YGEdgeLeft).unit, YGUnitUndefined);
+  ASSERT_EQ(YGNodeStyleGetMargin(root, YGEdgeTop).unit, YGUnitUndefined);
+  ASSERT_EQ(YGNodeStyleGetMargin(root, YGEdgeRight).unit, YGUnitUndefined);
+  ASSERT_EQ(YGNodeStyleGetMargin(root, YGEdgeBottom).unit, YGUnitUndefined);
+  ASSERT_EQ(YGNodeStyleGetMargin(root, YGEdgeStart).unit, YGUnitUndefined);
+  ASSERT_EQ(YGNodeStyleGetMargin(root, YGEdgeEnd).unit, YGUnitUndefined);
+
+  ASSERT_EQ(YGNodeStyleGetPadding(root, YGEdgeLeft).unit, YGUnitUndefined);
+  ASSERT_EQ(YGNodeStyleGetPadding(root, YGEdgeTop).unit, YGUnitUndefined);
+  ASSERT_EQ(YGNodeStyleGetPadding(root, YGEdgeRight).unit, YGUnitUndefined);
+  ASSERT_EQ(YGNodeStyleGetPadding(root, YGEdgeBottom).unit, YGUnitUndefined);
+  ASSERT_EQ(YGNodeStyleGetPadding(root, YGEdgeStart).unit, YGUnitUndefined);
+  ASSERT_EQ(YGNodeStyleGetPadding(root, YGEdgeEnd).unit, YGUnitUndefined);
+
+  ASSERT_TRUE(YGFloatIsUndefined(YGNodeStyleGetBorder(root, YGEdgeLeft)));
+  ASSERT_TRUE(YGFloatIsUndefined(YGNodeStyleGetBorder(root, YGEdgeTop)));
+  ASSERT_TRUE(YGFloatIsUndefined(YGNodeStyleGetBorder(root, YGEdgeRight)));
+  ASSERT_TRUE(YGFloatIsUndefined(YGNodeStyleGetBorder(root, YGEdgeBottom)));
+  ASSERT_TRUE(YGFloatIsUndefined(YGNodeStyleGetBorder(root, YGEdgeStart)));
+  ASSERT_TRUE(YGFloatIsUndefined(YGNodeStyleGetBorder(root, YGEdgeEnd)));
+
+  ASSERT_EQ(YGNodeStyleGetWidth(root).unit, YGUnitAuto);
+  ASSERT_EQ(YGNodeStyleGetHeight(root).unit, YGUnitAuto);
+  ASSERT_EQ(YGNodeStyleGetMinWidth(root).unit, YGUnitUndefined);
+  ASSERT_EQ(YGNodeStyleGetMinHeight(root).unit, YGUnitUndefined);
+  ASSERT_EQ(YGNodeStyleGetMaxWidth(root).unit, YGUnitUndefined);
+  ASSERT_EQ(YGNodeStyleGetMaxHeight(root).unit, YGUnitUndefined);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetRight(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetBottom(root));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetMargin(root, YGEdgeLeft));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetMargin(root, YGEdgeTop));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetMargin(root, YGEdgeRight));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetMargin(root, YGEdgeBottom));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetPadding(root, YGEdgeLeft));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetPadding(root, YGEdgeTop));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetPadding(root, YGEdgeRight));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetPadding(root, YGEdgeBottom));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetBorder(root, YGEdgeLeft));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetBorder(root, YGEdgeTop));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetBorder(root, YGEdgeRight));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetBorder(root, YGEdgeBottom));
+
+  ASSERT_TRUE(YGFloatIsUndefined(YGNodeLayoutGetWidth(root)));
+  ASSERT_TRUE(YGFloatIsUndefined(YGNodeLayoutGetHeight(root)));
+  ASSERT_EQ(YGDirectionInherit, YGNodeLayoutGetDirection(root));
+
+  YGNodeFreeRecursive(root);
+}
+
+TEST(YogaTest, assert_webdefault_values) {
+  YGConfig *config = YGConfigNew();
+  YGConfigSetUseWebDefaults(config, true);
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+
+  ASSERT_EQ(YGFlexDirectionRow, YGNodeStyleGetFlexDirection(root));
+  ASSERT_EQ(YGAlignStretch, YGNodeStyleGetAlignContent(root));
+  ASSERT_FLOAT_EQ(1.0f, YGNodeStyleGetFlexShrink(root));
+
+  YGNodeFreeRecursive(root);
+  YGConfigFree(config);
+}
+
+TEST(YogaTest, assert_webdefault_values_reset) {
+  YGConfig *config = YGConfigNew();
+  YGConfigSetUseWebDefaults(config, true);
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  YGNodeReset(root);
+
+  ASSERT_EQ(YGFlexDirectionRow, YGNodeStyleGetFlexDirection(root));
+  ASSERT_EQ(YGAlignStretch, YGNodeStyleGetAlignContent(root));
+  ASSERT_FLOAT_EQ(1.0f, YGNodeStyleGetFlexShrink(root));
+
+  YGNodeFreeRecursive(root);
+  YGConfigFree(config);
+}
+
+TEST(YogaTest, assert_legacy_stretch_behaviour) {
+  YGConfig *config = YGConfigNew();
+  YGConfigSetUseLegacyStretchBehaviour(config, true);
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root, 500);
+  YGNodeStyleSetHeight(root, 500);
+
+  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetAlignItems(root_child0, YGAlignFlexStart);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  const YGNodeRef root_child0_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexGrow(root_child0_child0, 1);
+  YGNodeStyleSetFlexShrink(root_child0_child0, 1);
+  YGNodeInsertChild(root_child0, root_child0_child0, 0);
+
+  const YGNodeRef root_child0_child0_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexGrow(root_child0_child0_child0, 1);
+  YGNodeStyleSetFlexShrink(root_child0_child0_child0, 1);
+  YGNodeInsertChild(root_child0_child0, root_child0_child0_child0, 0);
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(500, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(500, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(500, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(500, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetWidth(root_child0_child0));
+  ASSERT_FLOAT_EQ(500, YGNodeLayoutGetHeight(root_child0_child0));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0_child0_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0_child0_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetWidth(root_child0_child0_child0));
+  ASSERT_FLOAT_EQ(500, YGNodeLayoutGetHeight(root_child0_child0_child0));
+
+  YGNodeFreeRecursive(root);
+
+  YGConfigFree(config);
+}
diff --git a/automated-tests/src/dali-toolkit-third-party/yoga/YGDimensionTest.cpp b/automated-tests/src/dali-toolkit-third-party/yoga/YGDimensionTest.cpp
new file mode 100644 (file)
index 0000000..42fc123
--- /dev/null
@@ -0,0 +1,100 @@
+/**
+ * Copyright (c) 2014-present, Facebook, Inc.
+ *
+ * This source code is licensed under the MIT license found in the
+ * LICENSE file in the root directory of this source tree.
+ */
+
+// @Generated by gentest/gentest.rb from gentest/fixtures/YGDimensionTest.html
+
+#include <gtest/gtest.h>
+#include <yoga/Yoga.h>
+
+TEST(YogaTest, wrap_child) {
+  const YGConfigRef config = YGConfigNew();
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+
+  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child0, 100);
+  YGNodeStyleSetHeight(root_child0, 100);
+  YGNodeInsertChild(root, root_child0, 0);
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child0));
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child0));
+
+  YGNodeFreeRecursive(root);
+
+  YGConfigFree(config);
+}
+
+TEST(YogaTest, wrap_grandchild) {
+  const YGConfigRef config = YGConfigNew();
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+
+  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  const YGNodeRef root_child0_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child0_child0, 100);
+  YGNodeStyleSetHeight(root_child0_child0, 100);
+  YGNodeInsertChild(root_child0, root_child0_child0, 0);
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0_child0));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child0_child0));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child0_child0));
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0_child0));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child0_child0));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child0_child0));
+
+  YGNodeFreeRecursive(root);
+
+  YGConfigFree(config);
+}
diff --git a/automated-tests/src/dali-toolkit-third-party/yoga/YGDirtiedTest.cpp b/automated-tests/src/dali-toolkit-third-party/yoga/YGDirtiedTest.cpp
new file mode 100644 (file)
index 0000000..bb0c05d
--- /dev/null
@@ -0,0 +1,107 @@
+/**
+ * Copyright (c) 2014-present, Facebook, Inc.
+ *
+ * This source code is licensed under the MIT license found in the
+ * LICENSE file in the root directory of this source tree.
+ */
+
+#include <gtest/gtest.h>
+#include <yoga/YGNode.h>
+
+static void _dirtied(YGNodeRef node) {
+  int* dirtiedCount = (int*)node->getContext();
+  (*dirtiedCount)++;
+}
+
+TEST(YogaTest, dirtied) {
+  const YGNodeRef root = YGNodeNew();
+  YGNodeStyleSetAlignItems(root, YGAlignFlexStart);
+  YGNodeStyleSetWidth(root, 100);
+  YGNodeStyleSetHeight(root, 100);
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  int dirtiedCount = 0;
+  root->setContext(&dirtiedCount);
+  root->setDirtiedFunc(_dirtied);
+
+  ASSERT_EQ(0, dirtiedCount);
+
+  // `_dirtied` MUST be called in case of explicit dirtying.
+  root->setDirty(true);
+  ASSERT_EQ(1, dirtiedCount);
+
+  // `_dirtied` MUST be called ONCE.
+  root->setDirty(true);
+  ASSERT_EQ(1, dirtiedCount);
+}
+
+TEST(YogaTest, dirtied_propagation) {
+  const YGNodeRef root = YGNodeNew();
+  YGNodeStyleSetAlignItems(root, YGAlignFlexStart);
+  YGNodeStyleSetWidth(root, 100);
+  YGNodeStyleSetHeight(root, 100);
+
+  const YGNodeRef root_child0 = YGNodeNew();
+  YGNodeStyleSetWidth(root_child0, 50);
+  YGNodeStyleSetHeight(root_child0, 20);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  const YGNodeRef root_child1 = YGNodeNew();
+  YGNodeStyleSetWidth(root_child1, 50);
+  YGNodeStyleSetHeight(root_child1, 20);
+  YGNodeInsertChild(root, root_child1, 1);
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  int dirtiedCount = 0;
+  root->setContext(&dirtiedCount);
+  root->setDirtiedFunc(_dirtied);
+
+  ASSERT_EQ(0, dirtiedCount);
+
+  // `_dirtied` MUST be called for the first time.
+  root_child0->markDirtyAndPropogate();
+  ASSERT_EQ(1, dirtiedCount);
+
+  // `_dirtied` must NOT be called for the second time.
+  root_child0->markDirtyAndPropogate();
+  ASSERT_EQ(1, dirtiedCount);
+}
+
+TEST(YogaTest, dirtied_hierarchy) {
+  const YGNodeRef root = YGNodeNew();
+  YGNodeStyleSetAlignItems(root, YGAlignFlexStart);
+  YGNodeStyleSetWidth(root, 100);
+  YGNodeStyleSetHeight(root, 100);
+
+  const YGNodeRef root_child0 = YGNodeNew();
+  YGNodeStyleSetWidth(root_child0, 50);
+  YGNodeStyleSetHeight(root_child0, 20);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  const YGNodeRef root_child1 = YGNodeNew();
+  YGNodeStyleSetWidth(root_child1, 50);
+  YGNodeStyleSetHeight(root_child1, 20);
+  YGNodeInsertChild(root, root_child1, 1);
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  int dirtiedCount = 0;
+  root_child0->setContext(&dirtiedCount);
+  root_child0->setDirtiedFunc(_dirtied);
+
+  ASSERT_EQ(0, dirtiedCount);
+
+  // `_dirtied` must NOT be called for descendants.
+  root->markDirtyAndPropogate();
+  ASSERT_EQ(0, dirtiedCount);
+
+  // `_dirtied` must NOT be called for the sibling node.
+  root_child1->markDirtyAndPropogate();
+  ASSERT_EQ(0, dirtiedCount);
+
+  // `_dirtied` MUST be called in case of explicit dirtying.
+  root_child0->markDirtyAndPropogate();
+  ASSERT_EQ(1, dirtiedCount);
+}
diff --git a/automated-tests/src/dali-toolkit-third-party/yoga/YGDirtyMarkingTest.cpp b/automated-tests/src/dali-toolkit-third-party/yoga/YGDirtyMarkingTest.cpp
new file mode 100644 (file)
index 0000000..d951f53
--- /dev/null
@@ -0,0 +1,159 @@
+/**
+ * Copyright (c) 2014-present, Facebook, Inc.
+ *
+ * This source code is licensed under the MIT license found in the
+ * LICENSE file in the root directory of this source tree.
+ */
+
+#include <gtest/gtest.h>
+#include <yoga/YGNode.h>
+
+TEST(YogaTest, dirty_propagation) {
+  const YGNodeRef root = YGNodeNew();
+  YGNodeStyleSetAlignItems(root, YGAlignFlexStart);
+  YGNodeStyleSetWidth(root, 100);
+  YGNodeStyleSetHeight(root, 100);
+
+  const YGNodeRef root_child0 = YGNodeNew();
+  YGNodeStyleSetWidth(root_child0, 50);
+  YGNodeStyleSetHeight(root_child0, 20);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  const YGNodeRef root_child1 = YGNodeNew();
+  YGNodeStyleSetWidth(root_child1, 50);
+  YGNodeStyleSetHeight(root_child1, 20);
+  YGNodeInsertChild(root, root_child1, 1);
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  YGNodeStyleSetWidth(root_child0, 20);
+
+  EXPECT_TRUE(root_child0->isDirty());
+  EXPECT_FALSE(root_child1->isDirty());
+  EXPECT_TRUE(root->isDirty());
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  EXPECT_FALSE(root_child0->isDirty());
+  EXPECT_FALSE(root_child1->isDirty());
+  EXPECT_FALSE(root->isDirty());
+
+  YGNodeFreeRecursive(root);
+}
+
+TEST(YogaTest, dirty_propagation_only_if_prop_changed) {
+  const YGNodeRef root = YGNodeNew();
+  YGNodeStyleSetAlignItems(root, YGAlignFlexStart);
+  YGNodeStyleSetWidth(root, 100);
+  YGNodeStyleSetHeight(root, 100);
+
+  const YGNodeRef root_child0 = YGNodeNew();
+  YGNodeStyleSetWidth(root_child0, 50);
+  YGNodeStyleSetHeight(root_child0, 20);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  const YGNodeRef root_child1 = YGNodeNew();
+  YGNodeStyleSetWidth(root_child1, 50);
+  YGNodeStyleSetHeight(root_child1, 20);
+  YGNodeInsertChild(root, root_child1, 1);
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  YGNodeStyleSetWidth(root_child0, 50);
+
+  EXPECT_FALSE(root_child0->isDirty());
+  EXPECT_FALSE(root_child1->isDirty());
+  EXPECT_FALSE(root->isDirty());
+
+  YGNodeFreeRecursive(root);
+}
+
+TEST(YogaTest, dirty_mark_all_children_as_dirty_when_display_changes) {
+  const YGNodeRef root = YGNodeNew();
+  YGNodeStyleSetFlexDirection(root, YGFlexDirectionRow);
+  YGNodeStyleSetHeight(root, 100);
+
+  const YGNodeRef child0 = YGNodeNew();
+  YGNodeStyleSetFlexGrow(child0, 1);
+  const YGNodeRef child1 = YGNodeNew();
+  YGNodeStyleSetFlexGrow(child1, 1);
+
+  const YGNodeRef child1_child0 = YGNodeNew();
+  const YGNodeRef child1_child0_child0 = YGNodeNew();
+  YGNodeStyleSetWidth(child1_child0_child0, 8);
+  YGNodeStyleSetHeight(child1_child0_child0, 16);
+
+  YGNodeInsertChild(child1_child0, child1_child0_child0, 0);
+
+  YGNodeInsertChild(child1, child1_child0, 0);
+  YGNodeInsertChild(root, child0, 0);
+  YGNodeInsertChild(root, child1, 0);
+
+  YGNodeStyleSetDisplay(child0, YGDisplayFlex);
+  YGNodeStyleSetDisplay(child1, YGDisplayNone);
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetWidth(child1_child0_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetHeight(child1_child0_child0));
+
+  YGNodeStyleSetDisplay(child0, YGDisplayNone);
+  YGNodeStyleSetDisplay(child1, YGDisplayFlex);
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+  ASSERT_FLOAT_EQ(8, YGNodeLayoutGetWidth(child1_child0_child0));
+  ASSERT_FLOAT_EQ(16, YGNodeLayoutGetHeight(child1_child0_child0));
+
+  YGNodeStyleSetDisplay(child0, YGDisplayFlex);
+  YGNodeStyleSetDisplay(child1, YGDisplayNone);
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetWidth(child1_child0_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetHeight(child1_child0_child0));
+
+  YGNodeStyleSetDisplay(child0, YGDisplayNone);
+  YGNodeStyleSetDisplay(child1, YGDisplayFlex);
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+  ASSERT_FLOAT_EQ(8, YGNodeLayoutGetWidth(child1_child0_child0));
+  ASSERT_FLOAT_EQ(16, YGNodeLayoutGetHeight(child1_child0_child0));
+
+  YGNodeFreeRecursive(root);
+}
+
+TEST(YogaTest, dirty_node_only_if_children_are_actually_removed) {
+  const YGNodeRef root = YGNodeNew();
+  YGNodeStyleSetAlignItems(root, YGAlignFlexStart);
+  YGNodeStyleSetWidth(root, 50);
+  YGNodeStyleSetHeight(root, 50);
+
+  const YGNodeRef child0 = YGNodeNew();
+  YGNodeStyleSetWidth(child0, 50);
+  YGNodeStyleSetHeight(child0, 25);
+  YGNodeInsertChild(root, child0, 0);
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  const YGNodeRef child1 = YGNodeNew();
+  YGNodeRemoveChild(root, child1);
+  EXPECT_FALSE(root->isDirty());
+  YGNodeFree(child1);
+
+  YGNodeRemoveChild(root, child0);
+  EXPECT_TRUE(root->isDirty());
+  YGNodeFree(child0);
+
+  YGNodeFreeRecursive(root);
+}
+
+TEST(YogaTest, dirty_node_only_if_undefined_values_gets_set_to_undefined) {
+  const YGNodeRef root = YGNodeNew();
+  YGNodeStyleSetWidth(root, 50);
+  YGNodeStyleSetHeight(root, 50);
+  YGNodeStyleSetMinWidth(root, YGUndefined);
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  EXPECT_FALSE(root->isDirty());
+
+  YGNodeStyleSetMinWidth(root, YGUndefined);
+
+  EXPECT_FALSE(root->isDirty());
+
+  YGNodeFreeRecursive(root);
+}
diff --git a/automated-tests/src/dali-toolkit-third-party/yoga/YGDisplayTest.cpp b/automated-tests/src/dali-toolkit-third-party/yoga/YGDisplayTest.cpp
new file mode 100644 (file)
index 0000000..45256ac
--- /dev/null
@@ -0,0 +1,332 @@
+/**
+ * Copyright (c) 2014-present, Facebook, Inc.
+ *
+ * This source code is licensed under the MIT license found in the
+ * LICENSE file in the root directory of this source tree.
+ */
+
+// @Generated by gentest/gentest.rb from gentest/fixtures/YGDisplayTest.html
+
+#include <gtest/gtest.h>
+#include <yoga/Yoga.h>
+
+TEST(YogaTest, display_none) {
+  const YGConfigRef config = YGConfigNew();
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexDirection(root, YGFlexDirectionRow);
+  YGNodeStyleSetWidth(root, 100);
+  YGNodeStyleSetHeight(root, 100);
+
+  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexGrow(root_child0, 1);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  const YGNodeRef root_child1 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexGrow(root_child1, 1);
+  YGNodeStyleSetDisplay(root_child1, YGDisplayNone);
+  YGNodeInsertChild(root, root_child1, 1);
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetHeight(root_child1));
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetHeight(root_child1));
+
+  YGNodeFreeRecursive(root);
+
+  YGConfigFree(config);
+}
+
+TEST(YogaTest, display_none_fixed_size) {
+  const YGConfigRef config = YGConfigNew();
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexDirection(root, YGFlexDirectionRow);
+  YGNodeStyleSetWidth(root, 100);
+  YGNodeStyleSetHeight(root, 100);
+
+  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexGrow(root_child0, 1);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  const YGNodeRef root_child1 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child1, 20);
+  YGNodeStyleSetHeight(root_child1, 20);
+  YGNodeStyleSetDisplay(root_child1, YGDisplayNone);
+  YGNodeInsertChild(root, root_child1, 1);
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetHeight(root_child1));
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetHeight(root_child1));
+
+  YGNodeFreeRecursive(root);
+
+  YGConfigFree(config);
+}
+
+TEST(YogaTest, display_none_with_margin) {
+  const YGConfigRef config = YGConfigNew();
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexDirection(root, YGFlexDirectionRow);
+  YGNodeStyleSetWidth(root, 100);
+  YGNodeStyleSetHeight(root, 100);
+
+  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetMargin(root_child0, YGEdgeLeft, 10);
+  YGNodeStyleSetMargin(root_child0, YGEdgeTop, 10);
+  YGNodeStyleSetMargin(root_child0, YGEdgeRight, 10);
+  YGNodeStyleSetMargin(root_child0, YGEdgeBottom, 10);
+  YGNodeStyleSetWidth(root_child0, 20);
+  YGNodeStyleSetHeight(root_child0, 20);
+  YGNodeStyleSetDisplay(root_child0, YGDisplayNone);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  const YGNodeRef root_child1 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexGrow(root_child1, 1);
+  YGNodeInsertChild(root, root_child1, 1);
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child1));
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child1));
+
+  YGNodeFreeRecursive(root);
+
+  YGConfigFree(config);
+}
+
+TEST(YogaTest, display_none_with_child) {
+  const YGConfigRef config = YGConfigNew();
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexDirection(root, YGFlexDirectionRow);
+  YGNodeStyleSetWidth(root, 100);
+  YGNodeStyleSetHeight(root, 100);
+
+  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexGrow(root_child0, 1);
+  YGNodeStyleSetFlexShrink(root_child0, 1);
+  YGNodeStyleSetFlexBasisPercent(root_child0, 0);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  const YGNodeRef root_child1 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexGrow(root_child1, 1);
+  YGNodeStyleSetFlexShrink(root_child1, 1);
+  YGNodeStyleSetFlexBasisPercent(root_child1, 0);
+  YGNodeStyleSetDisplay(root_child1, YGDisplayNone);
+  YGNodeInsertChild(root, root_child1, 1);
+
+  const YGNodeRef root_child1_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexGrow(root_child1_child0, 1);
+  YGNodeStyleSetFlexShrink(root_child1_child0, 1);
+  YGNodeStyleSetFlexBasisPercent(root_child1_child0, 0);
+  YGNodeStyleSetWidth(root_child1_child0, 20);
+  YGNodeStyleSetMinWidth(root_child1_child0, 0);
+  YGNodeStyleSetMinHeight(root_child1_child0, 0);
+  YGNodeInsertChild(root_child1, root_child1_child0, 0);
+
+  const YGNodeRef root_child2 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexGrow(root_child2, 1);
+  YGNodeStyleSetFlexShrink(root_child2, 1);
+  YGNodeStyleSetFlexBasisPercent(root_child2, 0);
+  YGNodeInsertChild(root, root_child2, 2);
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetHeight(root_child1));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child1_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child1_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetWidth(root_child1_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetHeight(root_child1_child0));
+
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetLeft(root_child2));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child2));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child2));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child2));
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetHeight(root_child1));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child1_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child1_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetWidth(root_child1_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetHeight(root_child1_child0));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child2));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child2));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child2));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child2));
+
+  YGNodeFreeRecursive(root);
+
+  YGConfigFree(config);
+}
+
+TEST(YogaTest, display_none_with_position) {
+  const YGConfigRef config = YGConfigNew();
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexDirection(root, YGFlexDirectionRow);
+  YGNodeStyleSetWidth(root, 100);
+  YGNodeStyleSetHeight(root, 100);
+
+  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexGrow(root_child0, 1);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  const YGNodeRef root_child1 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexGrow(root_child1, 1);
+  YGNodeStyleSetPosition(root_child1, YGEdgeTop, 10);
+  YGNodeStyleSetDisplay(root_child1, YGDisplayNone);
+  YGNodeInsertChild(root, root_child1, 1);
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetHeight(root_child1));
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetHeight(root_child1));
+
+  YGNodeFreeRecursive(root);
+
+  YGConfigFree(config);
+}
diff --git a/automated-tests/src/dali-toolkit-third-party/yoga/YGEdgeTest.cpp b/automated-tests/src/dali-toolkit-third-party/yoga/YGEdgeTest.cpp
new file mode 100644 (file)
index 0000000..02de146
--- /dev/null
@@ -0,0 +1,161 @@
+/**
+ * Copyright (c) 2014-present, Facebook, Inc.
+ *
+ * This source code is licensed under the MIT license found in the
+ * LICENSE file in the root directory of this source tree.
+ */
+
+#include <gtest/gtest.h>
+#include <yoga/Yoga.h>
+
+TEST(YogaTest, start_overrides) {
+  const YGNodeRef root = YGNodeNew();
+  YGNodeStyleSetFlexDirection(root, YGFlexDirectionRow);
+  YGNodeStyleSetWidth(root, 100);
+  YGNodeStyleSetHeight(root, 100);
+
+  const YGNodeRef root_child0 = YGNodeNew();
+  YGNodeStyleSetFlexGrow(root_child0, 1);
+  YGNodeStyleSetMargin(root_child0, YGEdgeStart, 10);
+  YGNodeStyleSetMargin(root_child0, YGEdgeLeft, 20);
+  YGNodeStyleSetMargin(root_child0, YGEdgeRight, 20);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(20, YGNodeLayoutGetRight(root_child0));
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);
+  ASSERT_FLOAT_EQ(20, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetRight(root_child0));
+
+  YGNodeFreeRecursive(root);
+}
+
+TEST(YogaTest, end_overrides) {
+  const YGNodeRef root = YGNodeNew();
+  YGNodeStyleSetFlexDirection(root, YGFlexDirectionRow);
+  YGNodeStyleSetWidth(root, 100);
+  YGNodeStyleSetHeight(root, 100);
+
+  const YGNodeRef root_child0 = YGNodeNew();
+  YGNodeStyleSetFlexGrow(root_child0, 1);
+  YGNodeStyleSetMargin(root_child0, YGEdgeEnd, 10);
+  YGNodeStyleSetMargin(root_child0, YGEdgeLeft, 20);
+  YGNodeStyleSetMargin(root_child0, YGEdgeRight, 20);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+  ASSERT_FLOAT_EQ(20, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetRight(root_child0));
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(20, YGNodeLayoutGetRight(root_child0));
+
+  YGNodeFreeRecursive(root);
+}
+
+TEST(YogaTest, horizontal_overridden) {
+  const YGNodeRef root = YGNodeNew();
+  YGNodeStyleSetFlexDirection(root, YGFlexDirectionRow);
+  YGNodeStyleSetWidth(root, 100);
+  YGNodeStyleSetHeight(root, 100);
+
+  const YGNodeRef root_child0 = YGNodeNew();
+  YGNodeStyleSetFlexGrow(root_child0, 1);
+  YGNodeStyleSetMargin(root_child0, YGEdgeHorizontal, 10);
+  YGNodeStyleSetMargin(root_child0, YGEdgeLeft, 20);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+  ASSERT_FLOAT_EQ(20, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetRight(root_child0));
+
+  YGNodeFreeRecursive(root);
+}
+
+TEST(YogaTest, vertical_overridden) {
+  const YGNodeRef root = YGNodeNew();
+  YGNodeStyleSetFlexDirection(root, YGFlexDirectionColumn);
+  YGNodeStyleSetWidth(root, 100);
+  YGNodeStyleSetHeight(root, 100);
+
+  const YGNodeRef root_child0 = YGNodeNew();
+  YGNodeStyleSetFlexGrow(root_child0, 1);
+  YGNodeStyleSetMargin(root_child0, YGEdgeVertical, 10);
+  YGNodeStyleSetMargin(root_child0, YGEdgeTop, 20);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+  ASSERT_FLOAT_EQ(20, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetBottom(root_child0));
+
+  YGNodeFreeRecursive(root);
+}
+
+TEST(YogaTest, horizontal_overrides_all) {
+  const YGNodeRef root = YGNodeNew();
+  YGNodeStyleSetFlexDirection(root, YGFlexDirectionColumn);
+  YGNodeStyleSetWidth(root, 100);
+  YGNodeStyleSetHeight(root, 100);
+
+  const YGNodeRef root_child0 = YGNodeNew();
+  YGNodeStyleSetFlexGrow(root_child0, 1);
+  YGNodeStyleSetMargin(root_child0, YGEdgeHorizontal, 10);
+  YGNodeStyleSetMargin(root_child0, YGEdgeAll, 20);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(20, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetRight(root_child0));
+  ASSERT_FLOAT_EQ(20, YGNodeLayoutGetBottom(root_child0));
+
+  YGNodeFreeRecursive(root);
+}
+
+TEST(YogaTest, vertical_overrides_all) {
+  const YGNodeRef root = YGNodeNew();
+  YGNodeStyleSetFlexDirection(root, YGFlexDirectionColumn);
+  YGNodeStyleSetWidth(root, 100);
+  YGNodeStyleSetHeight(root, 100);
+
+  const YGNodeRef root_child0 = YGNodeNew();
+  YGNodeStyleSetFlexGrow(root_child0, 1);
+  YGNodeStyleSetMargin(root_child0, YGEdgeVertical, 10);
+  YGNodeStyleSetMargin(root_child0, YGEdgeAll, 20);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+  ASSERT_FLOAT_EQ(20, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(20, YGNodeLayoutGetRight(root_child0));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetBottom(root_child0));
+
+  YGNodeFreeRecursive(root);
+}
+
+TEST(YogaTest, all_overridden) {
+  const YGNodeRef root = YGNodeNew();
+  YGNodeStyleSetFlexDirection(root, YGFlexDirectionColumn);
+  YGNodeStyleSetWidth(root, 100);
+  YGNodeStyleSetHeight(root, 100);
+
+  const YGNodeRef root_child0 = YGNodeNew();
+  YGNodeStyleSetFlexGrow(root_child0, 1);
+  YGNodeStyleSetMargin(root_child0, YGEdgeLeft, 10);
+  YGNodeStyleSetMargin(root_child0, YGEdgeTop, 10);
+  YGNodeStyleSetMargin(root_child0, YGEdgeRight, 10);
+  YGNodeStyleSetMargin(root_child0, YGEdgeBottom, 10);
+  YGNodeStyleSetMargin(root_child0, YGEdgeAll, 20);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetRight(root_child0));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetBottom(root_child0));
+
+  YGNodeFreeRecursive(root);
+}
diff --git a/automated-tests/src/dali-toolkit-third-party/yoga/YGFlexDirectionTest.cpp b/automated-tests/src/dali-toolkit-third-party/yoga/YGFlexDirectionTest.cpp
new file mode 100644 (file)
index 0000000..93e0942
--- /dev/null
@@ -0,0 +1,415 @@
+/**
+ * Copyright (c) 2014-present, Facebook, Inc.
+ *
+ * This source code is licensed under the MIT license found in the
+ * LICENSE file in the root directory of this source tree.
+ */
+
+// @Generated by gentest/gentest.rb from gentest/fixtures/YGFlexDirectionTest.html
+
+#include <gtest/gtest.h>
+#include <yoga/Yoga.h>
+
+TEST(YogaTest, flex_direction_column_no_height) {
+  const YGConfigRef config = YGConfigNew();
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root, 100);
+
+  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetHeight(root_child0, 10);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  const YGNodeRef root_child1 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetHeight(root_child1, 10);
+  YGNodeInsertChild(root, root_child1, 1);
+
+  const YGNodeRef root_child2 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetHeight(root_child2, 10);
+  YGNodeInsertChild(root, root_child2, 2);
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(30, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child1));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child2));
+  ASSERT_FLOAT_EQ(20, YGNodeLayoutGetTop(root_child2));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child2));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child2));
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(30, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child1));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child2));
+  ASSERT_FLOAT_EQ(20, YGNodeLayoutGetTop(root_child2));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child2));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child2));
+
+  YGNodeFreeRecursive(root);
+
+  YGConfigFree(config);
+}
+
+TEST(YogaTest, flex_direction_row_no_width) {
+  const YGConfigRef config = YGConfigNew();
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexDirection(root, YGFlexDirectionRow);
+  YGNodeStyleSetHeight(root, 100);
+
+  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child0, 10);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  const YGNodeRef root_child1 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child1, 10);
+  YGNodeInsertChild(root, root_child1, 1);
+
+  const YGNodeRef root_child2 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child2, 10);
+  YGNodeInsertChild(root, root_child2, 2);
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(30, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child1));
+
+  ASSERT_FLOAT_EQ(20, YGNodeLayoutGetLeft(root_child2));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child2));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetWidth(root_child2));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child2));
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(30, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(20, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child1));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child2));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child2));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetWidth(root_child2));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child2));
+
+  YGNodeFreeRecursive(root);
+
+  YGConfigFree(config);
+}
+
+TEST(YogaTest, flex_direction_column) {
+  const YGConfigRef config = YGConfigNew();
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root, 100);
+  YGNodeStyleSetHeight(root, 100);
+
+  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetHeight(root_child0, 10);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  const YGNodeRef root_child1 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetHeight(root_child1, 10);
+  YGNodeInsertChild(root, root_child1, 1);
+
+  const YGNodeRef root_child2 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetHeight(root_child2, 10);
+  YGNodeInsertChild(root, root_child2, 2);
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child1));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child2));
+  ASSERT_FLOAT_EQ(20, YGNodeLayoutGetTop(root_child2));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child2));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child2));
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child1));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child2));
+  ASSERT_FLOAT_EQ(20, YGNodeLayoutGetTop(root_child2));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child2));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child2));
+
+  YGNodeFreeRecursive(root);
+
+  YGConfigFree(config);
+}
+
+TEST(YogaTest, flex_direction_row) {
+  const YGConfigRef config = YGConfigNew();
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexDirection(root, YGFlexDirectionRow);
+  YGNodeStyleSetWidth(root, 100);
+  YGNodeStyleSetHeight(root, 100);
+
+  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child0, 10);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  const YGNodeRef root_child1 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child1, 10);
+  YGNodeInsertChild(root, root_child1, 1);
+
+  const YGNodeRef root_child2 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child2, 10);
+  YGNodeInsertChild(root, root_child2, 2);
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child1));
+
+  ASSERT_FLOAT_EQ(20, YGNodeLayoutGetLeft(root_child2));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child2));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetWidth(root_child2));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child2));
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(90, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(80, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child1));
+
+  ASSERT_FLOAT_EQ(70, YGNodeLayoutGetLeft(root_child2));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child2));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetWidth(root_child2));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child2));
+
+  YGNodeFreeRecursive(root);
+
+  YGConfigFree(config);
+}
+
+TEST(YogaTest, flex_direction_column_reverse) {
+  const YGConfigRef config = YGConfigNew();
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexDirection(root, YGFlexDirectionColumnReverse);
+  YGNodeStyleSetWidth(root, 100);
+  YGNodeStyleSetHeight(root, 100);
+
+  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetHeight(root_child0, 10);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  const YGNodeRef root_child1 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetHeight(root_child1, 10);
+  YGNodeInsertChild(root, root_child1, 1);
+
+  const YGNodeRef root_child2 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetHeight(root_child2, 10);
+  YGNodeInsertChild(root, root_child2, 2);
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(90, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(80, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child1));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child2));
+  ASSERT_FLOAT_EQ(70, YGNodeLayoutGetTop(root_child2));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child2));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child2));
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(90, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(80, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child1));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child2));
+  ASSERT_FLOAT_EQ(70, YGNodeLayoutGetTop(root_child2));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child2));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child2));
+
+  YGNodeFreeRecursive(root);
+
+  YGConfigFree(config);
+}
+
+TEST(YogaTest, flex_direction_row_reverse) {
+  const YGConfigRef config = YGConfigNew();
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexDirection(root, YGFlexDirectionRowReverse);
+  YGNodeStyleSetWidth(root, 100);
+  YGNodeStyleSetHeight(root, 100);
+
+  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child0, 10);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  const YGNodeRef root_child1 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child1, 10);
+  YGNodeInsertChild(root, root_child1, 1);
+
+  const YGNodeRef root_child2 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child2, 10);
+  YGNodeInsertChild(root, root_child2, 2);
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(90, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(80, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child1));
+
+  ASSERT_FLOAT_EQ(70, YGNodeLayoutGetLeft(root_child2));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child2));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetWidth(root_child2));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child2));
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child1));
+
+  ASSERT_FLOAT_EQ(20, YGNodeLayoutGetLeft(root_child2));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child2));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetWidth(root_child2));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child2));
+
+  YGNodeFreeRecursive(root);
+
+  YGConfigFree(config);
+}
diff --git a/automated-tests/src/dali-toolkit-third-party/yoga/YGFlexTest.cpp b/automated-tests/src/dali-toolkit-third-party/yoga/YGFlexTest.cpp
new file mode 100644 (file)
index 0000000..e1a8ba8
--- /dev/null
@@ -0,0 +1,491 @@
+/**
+ * Copyright (c) 2014-present, Facebook, Inc.
+ *
+ * This source code is licensed under the MIT license found in the
+ * LICENSE file in the root directory of this source tree.
+ */
+
+// @Generated by gentest/gentest.rb from gentest/fixtures/YGFlexTest.html
+
+#include <gtest/gtest.h>
+#include <yoga/Yoga.h>
+
+TEST(YogaTest, flex_basis_flex_grow_column) {
+  const YGConfigRef config = YGConfigNew();
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root, 100);
+  YGNodeStyleSetHeight(root, 100);
+
+  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexGrow(root_child0, 1);
+  YGNodeStyleSetFlexBasis(root_child0, 50);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  const YGNodeRef root_child1 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexGrow(root_child1, 1);
+  YGNodeInsertChild(root, root_child1, 1);
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(75, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(75, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(25, YGNodeLayoutGetHeight(root_child1));
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(75, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(75, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(25, YGNodeLayoutGetHeight(root_child1));
+
+  YGNodeFreeRecursive(root);
+
+  YGConfigFree(config);
+}
+
+TEST(YogaTest, flex_basis_flex_grow_row) {
+  const YGConfigRef config = YGConfigNew();
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexDirection(root, YGFlexDirectionRow);
+  YGNodeStyleSetWidth(root, 100);
+  YGNodeStyleSetHeight(root, 100);
+
+  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexGrow(root_child0, 1);
+  YGNodeStyleSetFlexBasis(root_child0, 50);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  const YGNodeRef root_child1 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexGrow(root_child1, 1);
+  YGNodeInsertChild(root, root_child1, 1);
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(75, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(75, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(25, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child1));
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(25, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(75, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(25, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child1));
+
+  YGNodeFreeRecursive(root);
+
+  YGConfigFree(config);
+}
+
+TEST(YogaTest, flex_basis_flex_shrink_column) {
+  const YGConfigRef config = YGConfigNew();
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root, 100);
+  YGNodeStyleSetHeight(root, 100);
+
+  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexShrink(root_child0, 1);
+  YGNodeStyleSetFlexBasis(root_child0, 100);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  const YGNodeRef root_child1 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexBasis(root_child1, 50);
+  YGNodeInsertChild(root, root_child1, 1);
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child1));
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child1));
+
+  YGNodeFreeRecursive(root);
+
+  YGConfigFree(config);
+}
+
+TEST(YogaTest, flex_basis_flex_shrink_row) {
+  const YGConfigRef config = YGConfigNew();
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexDirection(root, YGFlexDirectionRow);
+  YGNodeStyleSetWidth(root, 100);
+  YGNodeStyleSetHeight(root, 100);
+
+  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexShrink(root_child0, 1);
+  YGNodeStyleSetFlexBasis(root_child0, 100);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  const YGNodeRef root_child1 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexBasis(root_child1, 50);
+  YGNodeInsertChild(root, root_child1, 1);
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child1));
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child1));
+
+  YGNodeFreeRecursive(root);
+
+  YGConfigFree(config);
+}
+
+TEST(YogaTest, flex_shrink_to_zero) {
+  const YGConfigRef config = YGConfigNew();
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  YGNodeStyleSetHeight(root, 75);
+
+  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child0, 50);
+  YGNodeStyleSetHeight(root_child0, 50);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  const YGNodeRef root_child1 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexShrink(root_child1, 1);
+  YGNodeStyleSetWidth(root_child1, 50);
+  YGNodeStyleSetHeight(root_child1, 50);
+  YGNodeInsertChild(root, root_child1, 1);
+
+  const YGNodeRef root_child2 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child2, 50);
+  YGNodeStyleSetHeight(root_child2, 50);
+  YGNodeInsertChild(root, root_child2, 2);
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(75, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetHeight(root_child1));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child2));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetTop(root_child2));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child2));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child2));
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(75, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetHeight(root_child1));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child2));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetTop(root_child2));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child2));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child2));
+
+  YGNodeFreeRecursive(root);
+
+  YGConfigFree(config);
+}
+
+TEST(YogaTest, flex_basis_overrides_main_size) {
+  const YGConfigRef config = YGConfigNew();
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root, 100);
+  YGNodeStyleSetHeight(root, 100);
+
+  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexGrow(root_child0, 1);
+  YGNodeStyleSetFlexBasis(root_child0, 50);
+  YGNodeStyleSetHeight(root_child0, 20);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  const YGNodeRef root_child1 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexGrow(root_child1, 1);
+  YGNodeStyleSetHeight(root_child1, 10);
+  YGNodeInsertChild(root, root_child1, 1);
+
+  const YGNodeRef root_child2 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexGrow(root_child2, 1);
+  YGNodeStyleSetHeight(root_child2, 10);
+  YGNodeInsertChild(root, root_child2, 2);
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(60, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(60, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(20, YGNodeLayoutGetHeight(root_child1));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child2));
+  ASSERT_FLOAT_EQ(80, YGNodeLayoutGetTop(root_child2));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child2));
+  ASSERT_FLOAT_EQ(20, YGNodeLayoutGetHeight(root_child2));
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(60, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(60, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(20, YGNodeLayoutGetHeight(root_child1));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child2));
+  ASSERT_FLOAT_EQ(80, YGNodeLayoutGetTop(root_child2));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child2));
+  ASSERT_FLOAT_EQ(20, YGNodeLayoutGetHeight(root_child2));
+
+  YGNodeFreeRecursive(root);
+
+  YGConfigFree(config);
+}
+
+TEST(YogaTest, flex_grow_shrink_at_most) {
+  const YGConfigRef config = YGConfigNew();
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root, 100);
+  YGNodeStyleSetHeight(root, 100);
+
+  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  const YGNodeRef root_child0_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexGrow(root_child0_child0, 1);
+  YGNodeStyleSetFlexShrink(root_child0_child0, 1);
+  YGNodeInsertChild(root_child0, root_child0_child0, 0);
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0_child0));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child0_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetHeight(root_child0_child0));
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0_child0));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child0_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetHeight(root_child0_child0));
+
+  YGNodeFreeRecursive(root);
+
+  YGConfigFree(config);
+}
+
+TEST(YogaTest, flex_grow_less_than_factor_one) {
+  const YGConfigRef config = YGConfigNew();
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root, 200);
+  YGNodeStyleSetHeight(root, 500);
+
+  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexGrow(root_child0, 0.2f);
+  YGNodeStyleSetFlexBasis(root_child0, 40);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  const YGNodeRef root_child1 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexGrow(root_child1, 0.2f);
+  YGNodeInsertChild(root, root_child1, 1);
+
+  const YGNodeRef root_child2 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexGrow(root_child2, 0.4f);
+  YGNodeInsertChild(root, root_child2, 2);
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(200, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(500, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(200, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(132, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(132, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(200, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(92, YGNodeLayoutGetHeight(root_child1));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child2));
+  ASSERT_FLOAT_EQ(224, YGNodeLayoutGetTop(root_child2));
+  ASSERT_FLOAT_EQ(200, YGNodeLayoutGetWidth(root_child2));
+  ASSERT_FLOAT_EQ(184, YGNodeLayoutGetHeight(root_child2));
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(200, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(500, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(200, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(132, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(132, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(200, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(92, YGNodeLayoutGetHeight(root_child1));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child2));
+  ASSERT_FLOAT_EQ(224, YGNodeLayoutGetTop(root_child2));
+  ASSERT_FLOAT_EQ(200, YGNodeLayoutGetWidth(root_child2));
+  ASSERT_FLOAT_EQ(184, YGNodeLayoutGetHeight(root_child2));
+
+  YGNodeFreeRecursive(root);
+
+  YGConfigFree(config);
+}
diff --git a/automated-tests/src/dali-toolkit-third-party/yoga/YGFlexWrapTest.cpp b/automated-tests/src/dali-toolkit-third-party/yoga/YGFlexWrapTest.cpp
new file mode 100644 (file)
index 0000000..e8e5458
--- /dev/null
@@ -0,0 +1,1735 @@
+/**
+ * Copyright (c) 2014-present, Facebook, Inc.
+ *
+ * This source code is licensed under the MIT license found in the
+ * LICENSE file in the root directory of this source tree.
+ */
+
+// @Generated by gentest/gentest.rb from gentest/fixtures/YGFlexWrapTest.html
+
+#include <gtest/gtest.h>
+#include <yoga/Yoga.h>
+
+TEST(YogaTest, wrap_column) {
+  const YGConfigRef config = YGConfigNew();
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexWrap(root, YGWrapWrap);
+  YGNodeStyleSetHeight(root, 100);
+
+  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child0, 30);
+  YGNodeStyleSetHeight(root_child0, 30);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  const YGNodeRef root_child1 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child1, 30);
+  YGNodeStyleSetHeight(root_child1, 30);
+  YGNodeInsertChild(root, root_child1, 1);
+
+  const YGNodeRef root_child2 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child2, 30);
+  YGNodeStyleSetHeight(root_child2, 30);
+  YGNodeInsertChild(root, root_child2, 2);
+
+  const YGNodeRef root_child3 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child3, 30);
+  YGNodeStyleSetHeight(root_child3, 30);
+  YGNodeInsertChild(root, root_child3, 3);
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(60, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(30, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(30, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(30, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(30, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(30, YGNodeLayoutGetHeight(root_child1));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child2));
+  ASSERT_FLOAT_EQ(60, YGNodeLayoutGetTop(root_child2));
+  ASSERT_FLOAT_EQ(30, YGNodeLayoutGetWidth(root_child2));
+  ASSERT_FLOAT_EQ(30, YGNodeLayoutGetHeight(root_child2));
+
+  ASSERT_FLOAT_EQ(30, YGNodeLayoutGetLeft(root_child3));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child3));
+  ASSERT_FLOAT_EQ(30, YGNodeLayoutGetWidth(root_child3));
+  ASSERT_FLOAT_EQ(30, YGNodeLayoutGetHeight(root_child3));
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(60, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(30, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(30, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(30, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(30, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(30, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(30, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(30, YGNodeLayoutGetHeight(root_child1));
+
+  ASSERT_FLOAT_EQ(30, YGNodeLayoutGetLeft(root_child2));
+  ASSERT_FLOAT_EQ(60, YGNodeLayoutGetTop(root_child2));
+  ASSERT_FLOAT_EQ(30, YGNodeLayoutGetWidth(root_child2));
+  ASSERT_FLOAT_EQ(30, YGNodeLayoutGetHeight(root_child2));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child3));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child3));
+  ASSERT_FLOAT_EQ(30, YGNodeLayoutGetWidth(root_child3));
+  ASSERT_FLOAT_EQ(30, YGNodeLayoutGetHeight(root_child3));
+
+  YGNodeFreeRecursive(root);
+
+  YGConfigFree(config);
+}
+
+TEST(YogaTest, wrap_row) {
+  const YGConfigRef config = YGConfigNew();
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexDirection(root, YGFlexDirectionRow);
+  YGNodeStyleSetFlexWrap(root, YGWrapWrap);
+  YGNodeStyleSetWidth(root, 100);
+
+  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child0, 30);
+  YGNodeStyleSetHeight(root_child0, 30);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  const YGNodeRef root_child1 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child1, 30);
+  YGNodeStyleSetHeight(root_child1, 30);
+  YGNodeInsertChild(root, root_child1, 1);
+
+  const YGNodeRef root_child2 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child2, 30);
+  YGNodeStyleSetHeight(root_child2, 30);
+  YGNodeInsertChild(root, root_child2, 2);
+
+  const YGNodeRef root_child3 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child3, 30);
+  YGNodeStyleSetHeight(root_child3, 30);
+  YGNodeInsertChild(root, root_child3, 3);
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(60, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(30, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(30, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(30, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(30, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(30, YGNodeLayoutGetHeight(root_child1));
+
+  ASSERT_FLOAT_EQ(60, YGNodeLayoutGetLeft(root_child2));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child2));
+  ASSERT_FLOAT_EQ(30, YGNodeLayoutGetWidth(root_child2));
+  ASSERT_FLOAT_EQ(30, YGNodeLayoutGetHeight(root_child2));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child3));
+  ASSERT_FLOAT_EQ(30, YGNodeLayoutGetTop(root_child3));
+  ASSERT_FLOAT_EQ(30, YGNodeLayoutGetWidth(root_child3));
+  ASSERT_FLOAT_EQ(30, YGNodeLayoutGetHeight(root_child3));
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(60, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(70, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(30, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(30, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(40, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(30, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(30, YGNodeLayoutGetHeight(root_child1));
+
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetLeft(root_child2));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child2));
+  ASSERT_FLOAT_EQ(30, YGNodeLayoutGetWidth(root_child2));
+  ASSERT_FLOAT_EQ(30, YGNodeLayoutGetHeight(root_child2));
+
+  ASSERT_FLOAT_EQ(70, YGNodeLayoutGetLeft(root_child3));
+  ASSERT_FLOAT_EQ(30, YGNodeLayoutGetTop(root_child3));
+  ASSERT_FLOAT_EQ(30, YGNodeLayoutGetWidth(root_child3));
+  ASSERT_FLOAT_EQ(30, YGNodeLayoutGetHeight(root_child3));
+
+  YGNodeFreeRecursive(root);
+
+  YGConfigFree(config);
+}
+
+TEST(YogaTest, wrap_row_align_items_flex_end) {
+  const YGConfigRef config = YGConfigNew();
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexDirection(root, YGFlexDirectionRow);
+  YGNodeStyleSetAlignItems(root, YGAlignFlexEnd);
+  YGNodeStyleSetFlexWrap(root, YGWrapWrap);
+  YGNodeStyleSetWidth(root, 100);
+
+  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child0, 30);
+  YGNodeStyleSetHeight(root_child0, 10);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  const YGNodeRef root_child1 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child1, 30);
+  YGNodeStyleSetHeight(root_child1, 20);
+  YGNodeInsertChild(root, root_child1, 1);
+
+  const YGNodeRef root_child2 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child2, 30);
+  YGNodeStyleSetHeight(root_child2, 30);
+  YGNodeInsertChild(root, root_child2, 2);
+
+  const YGNodeRef root_child3 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child3, 30);
+  YGNodeStyleSetHeight(root_child3, 30);
+  YGNodeInsertChild(root, root_child3, 3);
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(60, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(20, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(30, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(30, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(30, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(20, YGNodeLayoutGetHeight(root_child1));
+
+  ASSERT_FLOAT_EQ(60, YGNodeLayoutGetLeft(root_child2));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child2));
+  ASSERT_FLOAT_EQ(30, YGNodeLayoutGetWidth(root_child2));
+  ASSERT_FLOAT_EQ(30, YGNodeLayoutGetHeight(root_child2));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child3));
+  ASSERT_FLOAT_EQ(30, YGNodeLayoutGetTop(root_child3));
+  ASSERT_FLOAT_EQ(30, YGNodeLayoutGetWidth(root_child3));
+  ASSERT_FLOAT_EQ(30, YGNodeLayoutGetHeight(root_child3));
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(60, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(70, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(20, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(30, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(40, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(30, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(20, YGNodeLayoutGetHeight(root_child1));
+
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetLeft(root_child2));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child2));
+  ASSERT_FLOAT_EQ(30, YGNodeLayoutGetWidth(root_child2));
+  ASSERT_FLOAT_EQ(30, YGNodeLayoutGetHeight(root_child2));
+
+  ASSERT_FLOAT_EQ(70, YGNodeLayoutGetLeft(root_child3));
+  ASSERT_FLOAT_EQ(30, YGNodeLayoutGetTop(root_child3));
+  ASSERT_FLOAT_EQ(30, YGNodeLayoutGetWidth(root_child3));
+  ASSERT_FLOAT_EQ(30, YGNodeLayoutGetHeight(root_child3));
+
+  YGNodeFreeRecursive(root);
+
+  YGConfigFree(config);
+}
+
+TEST(YogaTest, wrap_row_align_items_center) {
+  const YGConfigRef config = YGConfigNew();
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexDirection(root, YGFlexDirectionRow);
+  YGNodeStyleSetAlignItems(root, YGAlignCenter);
+  YGNodeStyleSetFlexWrap(root, YGWrapWrap);
+  YGNodeStyleSetWidth(root, 100);
+
+  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child0, 30);
+  YGNodeStyleSetHeight(root_child0, 10);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  const YGNodeRef root_child1 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child1, 30);
+  YGNodeStyleSetHeight(root_child1, 20);
+  YGNodeInsertChild(root, root_child1, 1);
+
+  const YGNodeRef root_child2 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child2, 30);
+  YGNodeStyleSetHeight(root_child2, 30);
+  YGNodeInsertChild(root, root_child2, 2);
+
+  const YGNodeRef root_child3 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child3, 30);
+  YGNodeStyleSetHeight(root_child3, 30);
+  YGNodeInsertChild(root, root_child3, 3);
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(60, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(30, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(30, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(5, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(30, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(20, YGNodeLayoutGetHeight(root_child1));
+
+  ASSERT_FLOAT_EQ(60, YGNodeLayoutGetLeft(root_child2));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child2));
+  ASSERT_FLOAT_EQ(30, YGNodeLayoutGetWidth(root_child2));
+  ASSERT_FLOAT_EQ(30, YGNodeLayoutGetHeight(root_child2));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child3));
+  ASSERT_FLOAT_EQ(30, YGNodeLayoutGetTop(root_child3));
+  ASSERT_FLOAT_EQ(30, YGNodeLayoutGetWidth(root_child3));
+  ASSERT_FLOAT_EQ(30, YGNodeLayoutGetHeight(root_child3));
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(60, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(70, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(30, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(40, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(5, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(30, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(20, YGNodeLayoutGetHeight(root_child1));
+
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetLeft(root_child2));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child2));
+  ASSERT_FLOAT_EQ(30, YGNodeLayoutGetWidth(root_child2));
+  ASSERT_FLOAT_EQ(30, YGNodeLayoutGetHeight(root_child2));
+
+  ASSERT_FLOAT_EQ(70, YGNodeLayoutGetLeft(root_child3));
+  ASSERT_FLOAT_EQ(30, YGNodeLayoutGetTop(root_child3));
+  ASSERT_FLOAT_EQ(30, YGNodeLayoutGetWidth(root_child3));
+  ASSERT_FLOAT_EQ(30, YGNodeLayoutGetHeight(root_child3));
+
+  YGNodeFreeRecursive(root);
+
+  YGConfigFree(config);
+}
+
+TEST(YogaTest, flex_wrap_children_with_min_main_overriding_flex_basis) {
+  const YGConfigRef config = YGConfigNew();
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexDirection(root, YGFlexDirectionRow);
+  YGNodeStyleSetFlexWrap(root, YGWrapWrap);
+  YGNodeStyleSetWidth(root, 100);
+
+  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexBasis(root_child0, 50);
+  YGNodeStyleSetMinWidth(root_child0, 55);
+  YGNodeStyleSetHeight(root_child0, 50);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  const YGNodeRef root_child1 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexBasis(root_child1, 50);
+  YGNodeStyleSetMinWidth(root_child1, 55);
+  YGNodeStyleSetHeight(root_child1, 50);
+  YGNodeInsertChild(root, root_child1, 1);
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(55, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(55, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child1));
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(45, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(55, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(45, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(55, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child1));
+
+  YGNodeFreeRecursive(root);
+
+  YGConfigFree(config);
+}
+
+TEST(YogaTest, flex_wrap_wrap_to_child_height) {
+  const YGConfigRef config = YGConfigNew();
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+
+  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexDirection(root_child0, YGFlexDirectionRow);
+  YGNodeStyleSetAlignItems(root_child0, YGAlignFlexStart);
+  YGNodeStyleSetFlexWrap(root_child0, YGWrapWrap);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  const YGNodeRef root_child0_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child0_child0, 100);
+  YGNodeInsertChild(root_child0, root_child0_child0, 0);
+
+  const YGNodeRef root_child0_child0_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child0_child0_child0, 100);
+  YGNodeStyleSetHeight(root_child0_child0_child0, 100);
+  YGNodeInsertChild(root_child0_child0, root_child0_child0_child0, 0);
+
+  const YGNodeRef root_child1 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child1, 100);
+  YGNodeStyleSetHeight(root_child1, 100);
+  YGNodeInsertChild(root, root_child1, 1);
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(200, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0_child0));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child0_child0));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child0_child0));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0_child0_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0_child0_child0));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child0_child0_child0));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child0_child0_child0));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child1));
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(200, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0_child0));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child0_child0));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child0_child0));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0_child0_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0_child0_child0));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child0_child0_child0));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child0_child0_child0));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child1));
+
+  YGNodeFreeRecursive(root);
+
+  YGConfigFree(config);
+}
+
+TEST(YogaTest, flex_wrap_align_stretch_fits_one_row) {
+  const YGConfigRef config = YGConfigNew();
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexDirection(root, YGFlexDirectionRow);
+  YGNodeStyleSetFlexWrap(root, YGWrapWrap);
+  YGNodeStyleSetWidth(root, 150);
+  YGNodeStyleSetHeight(root, 100);
+
+  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child0, 50);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  const YGNodeRef root_child1 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child1, 50);
+  YGNodeInsertChild(root, root_child1, 1);
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(150, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child1));
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(150, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child1));
+
+  YGNodeFreeRecursive(root);
+
+  YGConfigFree(config);
+}
+
+TEST(YogaTest, wrap_reverse_row_align_content_flex_start) {
+  const YGConfigRef config = YGConfigNew();
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexDirection(root, YGFlexDirectionRow);
+  YGNodeStyleSetFlexWrap(root, YGWrapWrapReverse);
+  YGNodeStyleSetWidth(root, 100);
+
+  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child0, 30);
+  YGNodeStyleSetHeight(root_child0, 10);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  const YGNodeRef root_child1 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child1, 30);
+  YGNodeStyleSetHeight(root_child1, 20);
+  YGNodeInsertChild(root, root_child1, 1);
+
+  const YGNodeRef root_child2 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child2, 30);
+  YGNodeStyleSetHeight(root_child2, 30);
+  YGNodeInsertChild(root, root_child2, 2);
+
+  const YGNodeRef root_child3 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child3, 30);
+  YGNodeStyleSetHeight(root_child3, 40);
+  YGNodeInsertChild(root, root_child3, 3);
+
+  const YGNodeRef root_child4 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child4, 30);
+  YGNodeStyleSetHeight(root_child4, 50);
+  YGNodeInsertChild(root, root_child4, 4);
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(80, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(70, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(30, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(30, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(60, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(30, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(20, YGNodeLayoutGetHeight(root_child1));
+
+  ASSERT_FLOAT_EQ(60, YGNodeLayoutGetLeft(root_child2));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetTop(root_child2));
+  ASSERT_FLOAT_EQ(30, YGNodeLayoutGetWidth(root_child2));
+  ASSERT_FLOAT_EQ(30, YGNodeLayoutGetHeight(root_child2));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child3));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetTop(root_child3));
+  ASSERT_FLOAT_EQ(30, YGNodeLayoutGetWidth(root_child3));
+  ASSERT_FLOAT_EQ(40, YGNodeLayoutGetHeight(root_child3));
+
+  ASSERT_FLOAT_EQ(30, YGNodeLayoutGetLeft(root_child4));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child4));
+  ASSERT_FLOAT_EQ(30, YGNodeLayoutGetWidth(root_child4));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child4));
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(80, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(70, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(70, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(30, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(40, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(60, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(30, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(20, YGNodeLayoutGetHeight(root_child1));
+
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetLeft(root_child2));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetTop(root_child2));
+  ASSERT_FLOAT_EQ(30, YGNodeLayoutGetWidth(root_child2));
+  ASSERT_FLOAT_EQ(30, YGNodeLayoutGetHeight(root_child2));
+
+  ASSERT_FLOAT_EQ(70, YGNodeLayoutGetLeft(root_child3));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetTop(root_child3));
+  ASSERT_FLOAT_EQ(30, YGNodeLayoutGetWidth(root_child3));
+  ASSERT_FLOAT_EQ(40, YGNodeLayoutGetHeight(root_child3));
+
+  ASSERT_FLOAT_EQ(40, YGNodeLayoutGetLeft(root_child4));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child4));
+  ASSERT_FLOAT_EQ(30, YGNodeLayoutGetWidth(root_child4));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child4));
+
+  YGNodeFreeRecursive(root);
+
+  YGConfigFree(config);
+}
+
+TEST(YogaTest, wrap_reverse_row_align_content_center) {
+  const YGConfigRef config = YGConfigNew();
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexDirection(root, YGFlexDirectionRow);
+  YGNodeStyleSetAlignContent(root, YGAlignCenter);
+  YGNodeStyleSetFlexWrap(root, YGWrapWrapReverse);
+  YGNodeStyleSetWidth(root, 100);
+
+  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child0, 30);
+  YGNodeStyleSetHeight(root_child0, 10);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  const YGNodeRef root_child1 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child1, 30);
+  YGNodeStyleSetHeight(root_child1, 20);
+  YGNodeInsertChild(root, root_child1, 1);
+
+  const YGNodeRef root_child2 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child2, 30);
+  YGNodeStyleSetHeight(root_child2, 30);
+  YGNodeInsertChild(root, root_child2, 2);
+
+  const YGNodeRef root_child3 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child3, 30);
+  YGNodeStyleSetHeight(root_child3, 40);
+  YGNodeInsertChild(root, root_child3, 3);
+
+  const YGNodeRef root_child4 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child4, 30);
+  YGNodeStyleSetHeight(root_child4, 50);
+  YGNodeInsertChild(root, root_child4, 4);
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(80, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(70, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(30, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(30, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(60, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(30, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(20, YGNodeLayoutGetHeight(root_child1));
+
+  ASSERT_FLOAT_EQ(60, YGNodeLayoutGetLeft(root_child2));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetTop(root_child2));
+  ASSERT_FLOAT_EQ(30, YGNodeLayoutGetWidth(root_child2));
+  ASSERT_FLOAT_EQ(30, YGNodeLayoutGetHeight(root_child2));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child3));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetTop(root_child3));
+  ASSERT_FLOAT_EQ(30, YGNodeLayoutGetWidth(root_child3));
+  ASSERT_FLOAT_EQ(40, YGNodeLayoutGetHeight(root_child3));
+
+  ASSERT_FLOAT_EQ(30, YGNodeLayoutGetLeft(root_child4));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child4));
+  ASSERT_FLOAT_EQ(30, YGNodeLayoutGetWidth(root_child4));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child4));
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(80, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(70, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(70, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(30, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(40, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(60, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(30, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(20, YGNodeLayoutGetHeight(root_child1));
+
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetLeft(root_child2));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetTop(root_child2));
+  ASSERT_FLOAT_EQ(30, YGNodeLayoutGetWidth(root_child2));
+  ASSERT_FLOAT_EQ(30, YGNodeLayoutGetHeight(root_child2));
+
+  ASSERT_FLOAT_EQ(70, YGNodeLayoutGetLeft(root_child3));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetTop(root_child3));
+  ASSERT_FLOAT_EQ(30, YGNodeLayoutGetWidth(root_child3));
+  ASSERT_FLOAT_EQ(40, YGNodeLayoutGetHeight(root_child3));
+
+  ASSERT_FLOAT_EQ(40, YGNodeLayoutGetLeft(root_child4));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child4));
+  ASSERT_FLOAT_EQ(30, YGNodeLayoutGetWidth(root_child4));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child4));
+
+  YGNodeFreeRecursive(root);
+
+  YGConfigFree(config);
+}
+
+TEST(YogaTest, wrap_reverse_row_single_line_different_size) {
+  const YGConfigRef config = YGConfigNew();
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexDirection(root, YGFlexDirectionRow);
+  YGNodeStyleSetFlexWrap(root, YGWrapWrapReverse);
+  YGNodeStyleSetWidth(root, 300);
+
+  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child0, 30);
+  YGNodeStyleSetHeight(root_child0, 10);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  const YGNodeRef root_child1 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child1, 30);
+  YGNodeStyleSetHeight(root_child1, 20);
+  YGNodeInsertChild(root, root_child1, 1);
+
+  const YGNodeRef root_child2 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child2, 30);
+  YGNodeStyleSetHeight(root_child2, 30);
+  YGNodeInsertChild(root, root_child2, 2);
+
+  const YGNodeRef root_child3 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child3, 30);
+  YGNodeStyleSetHeight(root_child3, 40);
+  YGNodeInsertChild(root, root_child3, 3);
+
+  const YGNodeRef root_child4 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child4, 30);
+  YGNodeStyleSetHeight(root_child4, 50);
+  YGNodeInsertChild(root, root_child4, 4);
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(300, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(40, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(30, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(30, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(30, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(30, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(20, YGNodeLayoutGetHeight(root_child1));
+
+  ASSERT_FLOAT_EQ(60, YGNodeLayoutGetLeft(root_child2));
+  ASSERT_FLOAT_EQ(20, YGNodeLayoutGetTop(root_child2));
+  ASSERT_FLOAT_EQ(30, YGNodeLayoutGetWidth(root_child2));
+  ASSERT_FLOAT_EQ(30, YGNodeLayoutGetHeight(root_child2));
+
+  ASSERT_FLOAT_EQ(90, YGNodeLayoutGetLeft(root_child3));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetTop(root_child3));
+  ASSERT_FLOAT_EQ(30, YGNodeLayoutGetWidth(root_child3));
+  ASSERT_FLOAT_EQ(40, YGNodeLayoutGetHeight(root_child3));
+
+  ASSERT_FLOAT_EQ(120, YGNodeLayoutGetLeft(root_child4));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child4));
+  ASSERT_FLOAT_EQ(30, YGNodeLayoutGetWidth(root_child4));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child4));
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(300, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(270, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(40, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(30, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(240, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(30, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(30, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(20, YGNodeLayoutGetHeight(root_child1));
+
+  ASSERT_FLOAT_EQ(210, YGNodeLayoutGetLeft(root_child2));
+  ASSERT_FLOAT_EQ(20, YGNodeLayoutGetTop(root_child2));
+  ASSERT_FLOAT_EQ(30, YGNodeLayoutGetWidth(root_child2));
+  ASSERT_FLOAT_EQ(30, YGNodeLayoutGetHeight(root_child2));
+
+  ASSERT_FLOAT_EQ(180, YGNodeLayoutGetLeft(root_child3));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetTop(root_child3));
+  ASSERT_FLOAT_EQ(30, YGNodeLayoutGetWidth(root_child3));
+  ASSERT_FLOAT_EQ(40, YGNodeLayoutGetHeight(root_child3));
+
+  ASSERT_FLOAT_EQ(150, YGNodeLayoutGetLeft(root_child4));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child4));
+  ASSERT_FLOAT_EQ(30, YGNodeLayoutGetWidth(root_child4));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child4));
+
+  YGNodeFreeRecursive(root);
+
+  YGConfigFree(config);
+}
+
+TEST(YogaTest, wrap_reverse_row_align_content_stretch) {
+  const YGConfigRef config = YGConfigNew();
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexDirection(root, YGFlexDirectionRow);
+  YGNodeStyleSetAlignContent(root, YGAlignStretch);
+  YGNodeStyleSetFlexWrap(root, YGWrapWrapReverse);
+  YGNodeStyleSetWidth(root, 100);
+
+  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child0, 30);
+  YGNodeStyleSetHeight(root_child0, 10);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  const YGNodeRef root_child1 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child1, 30);
+  YGNodeStyleSetHeight(root_child1, 20);
+  YGNodeInsertChild(root, root_child1, 1);
+
+  const YGNodeRef root_child2 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child2, 30);
+  YGNodeStyleSetHeight(root_child2, 30);
+  YGNodeInsertChild(root, root_child2, 2);
+
+  const YGNodeRef root_child3 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child3, 30);
+  YGNodeStyleSetHeight(root_child3, 40);
+  YGNodeInsertChild(root, root_child3, 3);
+
+  const YGNodeRef root_child4 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child4, 30);
+  YGNodeStyleSetHeight(root_child4, 50);
+  YGNodeInsertChild(root, root_child4, 4);
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(80, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(70, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(30, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(30, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(60, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(30, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(20, YGNodeLayoutGetHeight(root_child1));
+
+  ASSERT_FLOAT_EQ(60, YGNodeLayoutGetLeft(root_child2));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetTop(root_child2));
+  ASSERT_FLOAT_EQ(30, YGNodeLayoutGetWidth(root_child2));
+  ASSERT_FLOAT_EQ(30, YGNodeLayoutGetHeight(root_child2));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child3));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetTop(root_child3));
+  ASSERT_FLOAT_EQ(30, YGNodeLayoutGetWidth(root_child3));
+  ASSERT_FLOAT_EQ(40, YGNodeLayoutGetHeight(root_child3));
+
+  ASSERT_FLOAT_EQ(30, YGNodeLayoutGetLeft(root_child4));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child4));
+  ASSERT_FLOAT_EQ(30, YGNodeLayoutGetWidth(root_child4));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child4));
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(80, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(70, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(70, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(30, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(40, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(60, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(30, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(20, YGNodeLayoutGetHeight(root_child1));
+
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetLeft(root_child2));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetTop(root_child2));
+  ASSERT_FLOAT_EQ(30, YGNodeLayoutGetWidth(root_child2));
+  ASSERT_FLOAT_EQ(30, YGNodeLayoutGetHeight(root_child2));
+
+  ASSERT_FLOAT_EQ(70, YGNodeLayoutGetLeft(root_child3));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetTop(root_child3));
+  ASSERT_FLOAT_EQ(30, YGNodeLayoutGetWidth(root_child3));
+  ASSERT_FLOAT_EQ(40, YGNodeLayoutGetHeight(root_child3));
+
+  ASSERT_FLOAT_EQ(40, YGNodeLayoutGetLeft(root_child4));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child4));
+  ASSERT_FLOAT_EQ(30, YGNodeLayoutGetWidth(root_child4));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child4));
+
+  YGNodeFreeRecursive(root);
+
+  YGConfigFree(config);
+}
+
+TEST(YogaTest, wrap_reverse_row_align_content_space_around) {
+  const YGConfigRef config = YGConfigNew();
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexDirection(root, YGFlexDirectionRow);
+  YGNodeStyleSetAlignContent(root, YGAlignSpaceAround);
+  YGNodeStyleSetFlexWrap(root, YGWrapWrapReverse);
+  YGNodeStyleSetWidth(root, 100);
+
+  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child0, 30);
+  YGNodeStyleSetHeight(root_child0, 10);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  const YGNodeRef root_child1 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child1, 30);
+  YGNodeStyleSetHeight(root_child1, 20);
+  YGNodeInsertChild(root, root_child1, 1);
+
+  const YGNodeRef root_child2 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child2, 30);
+  YGNodeStyleSetHeight(root_child2, 30);
+  YGNodeInsertChild(root, root_child2, 2);
+
+  const YGNodeRef root_child3 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child3, 30);
+  YGNodeStyleSetHeight(root_child3, 40);
+  YGNodeInsertChild(root, root_child3, 3);
+
+  const YGNodeRef root_child4 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child4, 30);
+  YGNodeStyleSetHeight(root_child4, 50);
+  YGNodeInsertChild(root, root_child4, 4);
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(80, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(70, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(30, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(30, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(60, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(30, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(20, YGNodeLayoutGetHeight(root_child1));
+
+  ASSERT_FLOAT_EQ(60, YGNodeLayoutGetLeft(root_child2));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetTop(root_child2));
+  ASSERT_FLOAT_EQ(30, YGNodeLayoutGetWidth(root_child2));
+  ASSERT_FLOAT_EQ(30, YGNodeLayoutGetHeight(root_child2));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child3));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetTop(root_child3));
+  ASSERT_FLOAT_EQ(30, YGNodeLayoutGetWidth(root_child3));
+  ASSERT_FLOAT_EQ(40, YGNodeLayoutGetHeight(root_child3));
+
+  ASSERT_FLOAT_EQ(30, YGNodeLayoutGetLeft(root_child4));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child4));
+  ASSERT_FLOAT_EQ(30, YGNodeLayoutGetWidth(root_child4));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child4));
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(80, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(70, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(70, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(30, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(40, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(60, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(30, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(20, YGNodeLayoutGetHeight(root_child1));
+
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetLeft(root_child2));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetTop(root_child2));
+  ASSERT_FLOAT_EQ(30, YGNodeLayoutGetWidth(root_child2));
+  ASSERT_FLOAT_EQ(30, YGNodeLayoutGetHeight(root_child2));
+
+  ASSERT_FLOAT_EQ(70, YGNodeLayoutGetLeft(root_child3));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetTop(root_child3));
+  ASSERT_FLOAT_EQ(30, YGNodeLayoutGetWidth(root_child3));
+  ASSERT_FLOAT_EQ(40, YGNodeLayoutGetHeight(root_child3));
+
+  ASSERT_FLOAT_EQ(40, YGNodeLayoutGetLeft(root_child4));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child4));
+  ASSERT_FLOAT_EQ(30, YGNodeLayoutGetWidth(root_child4));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child4));
+
+  YGNodeFreeRecursive(root);
+
+  YGConfigFree(config);
+}
+
+TEST(YogaTest, wrap_reverse_column_fixed_size) {
+  const YGConfigRef config = YGConfigNew();
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  YGNodeStyleSetAlignItems(root, YGAlignCenter);
+  YGNodeStyleSetFlexWrap(root, YGWrapWrapReverse);
+  YGNodeStyleSetWidth(root, 200);
+  YGNodeStyleSetHeight(root, 100);
+
+  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child0, 30);
+  YGNodeStyleSetHeight(root_child0, 10);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  const YGNodeRef root_child1 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child1, 30);
+  YGNodeStyleSetHeight(root_child1, 20);
+  YGNodeInsertChild(root, root_child1, 1);
+
+  const YGNodeRef root_child2 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child2, 30);
+  YGNodeStyleSetHeight(root_child2, 30);
+  YGNodeInsertChild(root, root_child2, 2);
+
+  const YGNodeRef root_child3 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child3, 30);
+  YGNodeStyleSetHeight(root_child3, 40);
+  YGNodeInsertChild(root, root_child3, 3);
+
+  const YGNodeRef root_child4 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child4, 30);
+  YGNodeStyleSetHeight(root_child4, 50);
+  YGNodeInsertChild(root, root_child4, 4);
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(200, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(170, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(30, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(170, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(30, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(20, YGNodeLayoutGetHeight(root_child1));
+
+  ASSERT_FLOAT_EQ(170, YGNodeLayoutGetLeft(root_child2));
+  ASSERT_FLOAT_EQ(30, YGNodeLayoutGetTop(root_child2));
+  ASSERT_FLOAT_EQ(30, YGNodeLayoutGetWidth(root_child2));
+  ASSERT_FLOAT_EQ(30, YGNodeLayoutGetHeight(root_child2));
+
+  ASSERT_FLOAT_EQ(170, YGNodeLayoutGetLeft(root_child3));
+  ASSERT_FLOAT_EQ(60, YGNodeLayoutGetTop(root_child3));
+  ASSERT_FLOAT_EQ(30, YGNodeLayoutGetWidth(root_child3));
+  ASSERT_FLOAT_EQ(40, YGNodeLayoutGetHeight(root_child3));
+
+  ASSERT_FLOAT_EQ(140, YGNodeLayoutGetLeft(root_child4));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child4));
+  ASSERT_FLOAT_EQ(30, YGNodeLayoutGetWidth(root_child4));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child4));
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(200, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(30, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(30, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(20, YGNodeLayoutGetHeight(root_child1));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child2));
+  ASSERT_FLOAT_EQ(30, YGNodeLayoutGetTop(root_child2));
+  ASSERT_FLOAT_EQ(30, YGNodeLayoutGetWidth(root_child2));
+  ASSERT_FLOAT_EQ(30, YGNodeLayoutGetHeight(root_child2));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child3));
+  ASSERT_FLOAT_EQ(60, YGNodeLayoutGetTop(root_child3));
+  ASSERT_FLOAT_EQ(30, YGNodeLayoutGetWidth(root_child3));
+  ASSERT_FLOAT_EQ(40, YGNodeLayoutGetHeight(root_child3));
+
+  ASSERT_FLOAT_EQ(30, YGNodeLayoutGetLeft(root_child4));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child4));
+  ASSERT_FLOAT_EQ(30, YGNodeLayoutGetWidth(root_child4));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child4));
+
+  YGNodeFreeRecursive(root);
+
+  YGConfigFree(config);
+}
+
+TEST(YogaTest, wrapped_row_within_align_items_center) {
+  const YGConfigRef config = YGConfigNew();
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  YGNodeStyleSetAlignItems(root, YGAlignCenter);
+  YGNodeStyleSetWidth(root, 200);
+  YGNodeStyleSetHeight(root, 200);
+
+  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexDirection(root_child0, YGFlexDirectionRow);
+  YGNodeStyleSetFlexWrap(root_child0, YGWrapWrap);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  const YGNodeRef root_child0_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child0_child0, 150);
+  YGNodeStyleSetHeight(root_child0_child0, 80);
+  YGNodeInsertChild(root_child0, root_child0_child0, 0);
+
+  const YGNodeRef root_child0_child1 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child0_child1, 80);
+  YGNodeStyleSetHeight(root_child0_child1, 80);
+  YGNodeInsertChild(root_child0, root_child0_child1, 1);
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(200, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(200, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(200, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(160, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0_child0));
+  ASSERT_FLOAT_EQ(150, YGNodeLayoutGetWidth(root_child0_child0));
+  ASSERT_FLOAT_EQ(80, YGNodeLayoutGetHeight(root_child0_child0));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0_child1));
+  ASSERT_FLOAT_EQ(80, YGNodeLayoutGetTop(root_child0_child1));
+  ASSERT_FLOAT_EQ(80, YGNodeLayoutGetWidth(root_child0_child1));
+  ASSERT_FLOAT_EQ(80, YGNodeLayoutGetHeight(root_child0_child1));
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(200, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(200, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(200, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(160, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetLeft(root_child0_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0_child0));
+  ASSERT_FLOAT_EQ(150, YGNodeLayoutGetWidth(root_child0_child0));
+  ASSERT_FLOAT_EQ(80, YGNodeLayoutGetHeight(root_child0_child0));
+
+  ASSERT_FLOAT_EQ(120, YGNodeLayoutGetLeft(root_child0_child1));
+  ASSERT_FLOAT_EQ(80, YGNodeLayoutGetTop(root_child0_child1));
+  ASSERT_FLOAT_EQ(80, YGNodeLayoutGetWidth(root_child0_child1));
+  ASSERT_FLOAT_EQ(80, YGNodeLayoutGetHeight(root_child0_child1));
+
+  YGNodeFreeRecursive(root);
+
+  YGConfigFree(config);
+}
+
+TEST(YogaTest, wrapped_row_within_align_items_flex_start) {
+  const YGConfigRef config = YGConfigNew();
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  YGNodeStyleSetAlignItems(root, YGAlignFlexStart);
+  YGNodeStyleSetWidth(root, 200);
+  YGNodeStyleSetHeight(root, 200);
+
+  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexDirection(root_child0, YGFlexDirectionRow);
+  YGNodeStyleSetFlexWrap(root_child0, YGWrapWrap);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  const YGNodeRef root_child0_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child0_child0, 150);
+  YGNodeStyleSetHeight(root_child0_child0, 80);
+  YGNodeInsertChild(root_child0, root_child0_child0, 0);
+
+  const YGNodeRef root_child0_child1 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child0_child1, 80);
+  YGNodeStyleSetHeight(root_child0_child1, 80);
+  YGNodeInsertChild(root_child0, root_child0_child1, 1);
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(200, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(200, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(200, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(160, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0_child0));
+  ASSERT_FLOAT_EQ(150, YGNodeLayoutGetWidth(root_child0_child0));
+  ASSERT_FLOAT_EQ(80, YGNodeLayoutGetHeight(root_child0_child0));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0_child1));
+  ASSERT_FLOAT_EQ(80, YGNodeLayoutGetTop(root_child0_child1));
+  ASSERT_FLOAT_EQ(80, YGNodeLayoutGetWidth(root_child0_child1));
+  ASSERT_FLOAT_EQ(80, YGNodeLayoutGetHeight(root_child0_child1));
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(200, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(200, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(200, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(160, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetLeft(root_child0_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0_child0));
+  ASSERT_FLOAT_EQ(150, YGNodeLayoutGetWidth(root_child0_child0));
+  ASSERT_FLOAT_EQ(80, YGNodeLayoutGetHeight(root_child0_child0));
+
+  ASSERT_FLOAT_EQ(120, YGNodeLayoutGetLeft(root_child0_child1));
+  ASSERT_FLOAT_EQ(80, YGNodeLayoutGetTop(root_child0_child1));
+  ASSERT_FLOAT_EQ(80, YGNodeLayoutGetWidth(root_child0_child1));
+  ASSERT_FLOAT_EQ(80, YGNodeLayoutGetHeight(root_child0_child1));
+
+  YGNodeFreeRecursive(root);
+
+  YGConfigFree(config);
+}
+
+TEST(YogaTest, wrapped_row_within_align_items_flex_end) {
+  const YGConfigRef config = YGConfigNew();
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  YGNodeStyleSetAlignItems(root, YGAlignFlexEnd);
+  YGNodeStyleSetWidth(root, 200);
+  YGNodeStyleSetHeight(root, 200);
+
+  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexDirection(root_child0, YGFlexDirectionRow);
+  YGNodeStyleSetFlexWrap(root_child0, YGWrapWrap);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  const YGNodeRef root_child0_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child0_child0, 150);
+  YGNodeStyleSetHeight(root_child0_child0, 80);
+  YGNodeInsertChild(root_child0, root_child0_child0, 0);
+
+  const YGNodeRef root_child0_child1 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child0_child1, 80);
+  YGNodeStyleSetHeight(root_child0_child1, 80);
+  YGNodeInsertChild(root_child0, root_child0_child1, 1);
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(200, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(200, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(200, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(160, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0_child0));
+  ASSERT_FLOAT_EQ(150, YGNodeLayoutGetWidth(root_child0_child0));
+  ASSERT_FLOAT_EQ(80, YGNodeLayoutGetHeight(root_child0_child0));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0_child1));
+  ASSERT_FLOAT_EQ(80, YGNodeLayoutGetTop(root_child0_child1));
+  ASSERT_FLOAT_EQ(80, YGNodeLayoutGetWidth(root_child0_child1));
+  ASSERT_FLOAT_EQ(80, YGNodeLayoutGetHeight(root_child0_child1));
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(200, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(200, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(200, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(160, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetLeft(root_child0_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0_child0));
+  ASSERT_FLOAT_EQ(150, YGNodeLayoutGetWidth(root_child0_child0));
+  ASSERT_FLOAT_EQ(80, YGNodeLayoutGetHeight(root_child0_child0));
+
+  ASSERT_FLOAT_EQ(120, YGNodeLayoutGetLeft(root_child0_child1));
+  ASSERT_FLOAT_EQ(80, YGNodeLayoutGetTop(root_child0_child1));
+  ASSERT_FLOAT_EQ(80, YGNodeLayoutGetWidth(root_child0_child1));
+  ASSERT_FLOAT_EQ(80, YGNodeLayoutGetHeight(root_child0_child1));
+
+  YGNodeFreeRecursive(root);
+
+  YGConfigFree(config);
+}
+
+TEST(YogaTest, wrapped_column_max_height) {
+  const YGConfigRef config = YGConfigNew();
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  YGNodeStyleSetJustifyContent(root, YGJustifyCenter);
+  YGNodeStyleSetAlignContent(root, YGAlignCenter);
+  YGNodeStyleSetAlignItems(root, YGAlignCenter);
+  YGNodeStyleSetFlexWrap(root, YGWrapWrap);
+  YGNodeStyleSetWidth(root, 700);
+  YGNodeStyleSetHeight(root, 500);
+
+  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child0, 100);
+  YGNodeStyleSetHeight(root_child0, 500);
+  YGNodeStyleSetMaxHeight(root_child0, 200);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  const YGNodeRef root_child1 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetMargin(root_child1, YGEdgeLeft, 20);
+  YGNodeStyleSetMargin(root_child1, YGEdgeTop, 20);
+  YGNodeStyleSetMargin(root_child1, YGEdgeRight, 20);
+  YGNodeStyleSetMargin(root_child1, YGEdgeBottom, 20);
+  YGNodeStyleSetWidth(root_child1, 200);
+  YGNodeStyleSetHeight(root_child1, 200);
+  YGNodeInsertChild(root, root_child1, 1);
+
+  const YGNodeRef root_child2 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child2, 100);
+  YGNodeStyleSetHeight(root_child2, 100);
+  YGNodeInsertChild(root, root_child2, 2);
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(700, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(500, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(250, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(30, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(200, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(200, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(250, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(200, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(200, YGNodeLayoutGetHeight(root_child1));
+
+  ASSERT_FLOAT_EQ(420, YGNodeLayoutGetLeft(root_child2));
+  ASSERT_FLOAT_EQ(200, YGNodeLayoutGetTop(root_child2));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child2));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child2));
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(700, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(500, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(350, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(30, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(200, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(300, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(250, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(200, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(200, YGNodeLayoutGetHeight(root_child1));
+
+  ASSERT_FLOAT_EQ(180, YGNodeLayoutGetLeft(root_child2));
+  ASSERT_FLOAT_EQ(200, YGNodeLayoutGetTop(root_child2));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child2));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child2));
+
+  YGNodeFreeRecursive(root);
+
+  YGConfigFree(config);
+}
+
+TEST(YogaTest, wrapped_column_max_height_flex) {
+  const YGConfigRef config = YGConfigNew();
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  YGNodeStyleSetJustifyContent(root, YGJustifyCenter);
+  YGNodeStyleSetAlignContent(root, YGAlignCenter);
+  YGNodeStyleSetAlignItems(root, YGAlignCenter);
+  YGNodeStyleSetFlexWrap(root, YGWrapWrap);
+  YGNodeStyleSetWidth(root, 700);
+  YGNodeStyleSetHeight(root, 500);
+
+  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexGrow(root_child0, 1);
+  YGNodeStyleSetFlexShrink(root_child0, 1);
+  YGNodeStyleSetFlexBasisPercent(root_child0, 0);
+  YGNodeStyleSetWidth(root_child0, 100);
+  YGNodeStyleSetHeight(root_child0, 500);
+  YGNodeStyleSetMaxHeight(root_child0, 200);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  const YGNodeRef root_child1 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexGrow(root_child1, 1);
+  YGNodeStyleSetFlexShrink(root_child1, 1);
+  YGNodeStyleSetFlexBasisPercent(root_child1, 0);
+  YGNodeStyleSetMargin(root_child1, YGEdgeLeft, 20);
+  YGNodeStyleSetMargin(root_child1, YGEdgeTop, 20);
+  YGNodeStyleSetMargin(root_child1, YGEdgeRight, 20);
+  YGNodeStyleSetMargin(root_child1, YGEdgeBottom, 20);
+  YGNodeStyleSetWidth(root_child1, 200);
+  YGNodeStyleSetHeight(root_child1, 200);
+  YGNodeInsertChild(root, root_child1, 1);
+
+  const YGNodeRef root_child2 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child2, 100);
+  YGNodeStyleSetHeight(root_child2, 100);
+  YGNodeInsertChild(root, root_child2, 2);
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(700, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(500, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(300, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(180, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(250, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(200, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(200, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(180, YGNodeLayoutGetHeight(root_child1));
+
+  ASSERT_FLOAT_EQ(300, YGNodeLayoutGetLeft(root_child2));
+  ASSERT_FLOAT_EQ(400, YGNodeLayoutGetTop(root_child2));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child2));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child2));
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(700, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(500, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(300, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(180, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(250, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(200, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(200, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(180, YGNodeLayoutGetHeight(root_child1));
+
+  ASSERT_FLOAT_EQ(300, YGNodeLayoutGetLeft(root_child2));
+  ASSERT_FLOAT_EQ(400, YGNodeLayoutGetTop(root_child2));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child2));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child2));
+
+  YGNodeFreeRecursive(root);
+
+  YGConfigFree(config);
+}
+
+TEST(YogaTest, wrap_nodes_with_content_sizing_overflowing_margin) {
+  const YGConfigRef config = YGConfigNew();
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root, 500);
+  YGNodeStyleSetHeight(root, 500);
+
+  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexDirection(root_child0, YGFlexDirectionRow);
+  YGNodeStyleSetFlexWrap(root_child0, YGWrapWrap);
+  YGNodeStyleSetWidth(root_child0, 85);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  const YGNodeRef root_child0_child0 = YGNodeNewWithConfig(config);
+  YGNodeInsertChild(root_child0, root_child0_child0, 0);
+
+  const YGNodeRef root_child0_child0_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child0_child0_child0, 40);
+  YGNodeStyleSetHeight(root_child0_child0_child0, 40);
+  YGNodeInsertChild(root_child0_child0, root_child0_child0_child0, 0);
+
+  const YGNodeRef root_child0_child1 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetMargin(root_child0_child1, YGEdgeRight, 10);
+  YGNodeInsertChild(root_child0, root_child0_child1, 1);
+
+  const YGNodeRef root_child0_child1_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child0_child1_child0, 40);
+  YGNodeStyleSetHeight(root_child0_child1_child0, 40);
+  YGNodeInsertChild(root_child0_child1, root_child0_child1_child0, 0);
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(500, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(500, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(85, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(80, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0_child0));
+  ASSERT_FLOAT_EQ(40, YGNodeLayoutGetWidth(root_child0_child0));
+  ASSERT_FLOAT_EQ(40, YGNodeLayoutGetHeight(root_child0_child0));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0_child0_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0_child0_child0));
+  ASSERT_FLOAT_EQ(40, YGNodeLayoutGetWidth(root_child0_child0_child0));
+  ASSERT_FLOAT_EQ(40, YGNodeLayoutGetHeight(root_child0_child0_child0));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0_child1));
+  ASSERT_FLOAT_EQ(40, YGNodeLayoutGetTop(root_child0_child1));
+  ASSERT_FLOAT_EQ(40, YGNodeLayoutGetWidth(root_child0_child1));
+  ASSERT_FLOAT_EQ(40, YGNodeLayoutGetHeight(root_child0_child1));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0_child1_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0_child1_child0));
+  ASSERT_FLOAT_EQ(40, YGNodeLayoutGetWidth(root_child0_child1_child0));
+  ASSERT_FLOAT_EQ(40, YGNodeLayoutGetHeight(root_child0_child1_child0));
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(500, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(500, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(415, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(85, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(80, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(45, YGNodeLayoutGetLeft(root_child0_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0_child0));
+  ASSERT_FLOAT_EQ(40, YGNodeLayoutGetWidth(root_child0_child0));
+  ASSERT_FLOAT_EQ(40, YGNodeLayoutGetHeight(root_child0_child0));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0_child0_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0_child0_child0));
+  ASSERT_FLOAT_EQ(40, YGNodeLayoutGetWidth(root_child0_child0_child0));
+  ASSERT_FLOAT_EQ(40, YGNodeLayoutGetHeight(root_child0_child0_child0));
+
+  ASSERT_FLOAT_EQ(35, YGNodeLayoutGetLeft(root_child0_child1));
+  ASSERT_FLOAT_EQ(40, YGNodeLayoutGetTop(root_child0_child1));
+  ASSERT_FLOAT_EQ(40, YGNodeLayoutGetWidth(root_child0_child1));
+  ASSERT_FLOAT_EQ(40, YGNodeLayoutGetHeight(root_child0_child1));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0_child1_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0_child1_child0));
+  ASSERT_FLOAT_EQ(40, YGNodeLayoutGetWidth(root_child0_child1_child0));
+  ASSERT_FLOAT_EQ(40, YGNodeLayoutGetHeight(root_child0_child1_child0));
+
+  YGNodeFreeRecursive(root);
+
+  YGConfigFree(config);
+}
+
+TEST(YogaTest, wrap_nodes_with_content_sizing_margin_cross) {
+  const YGConfigRef config = YGConfigNew();
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root, 500);
+  YGNodeStyleSetHeight(root, 500);
+
+  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexDirection(root_child0, YGFlexDirectionRow);
+  YGNodeStyleSetFlexWrap(root_child0, YGWrapWrap);
+  YGNodeStyleSetWidth(root_child0, 70);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  const YGNodeRef root_child0_child0 = YGNodeNewWithConfig(config);
+  YGNodeInsertChild(root_child0, root_child0_child0, 0);
+
+  const YGNodeRef root_child0_child0_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child0_child0_child0, 40);
+  YGNodeStyleSetHeight(root_child0_child0_child0, 40);
+  YGNodeInsertChild(root_child0_child0, root_child0_child0_child0, 0);
+
+  const YGNodeRef root_child0_child1 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetMargin(root_child0_child1, YGEdgeTop, 10);
+  YGNodeInsertChild(root_child0, root_child0_child1, 1);
+
+  const YGNodeRef root_child0_child1_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child0_child1_child0, 40);
+  YGNodeStyleSetHeight(root_child0_child1_child0, 40);
+  YGNodeInsertChild(root_child0_child1, root_child0_child1_child0, 0);
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(500, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(500, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(70, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(90, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0_child0));
+  ASSERT_FLOAT_EQ(40, YGNodeLayoutGetWidth(root_child0_child0));
+  ASSERT_FLOAT_EQ(40, YGNodeLayoutGetHeight(root_child0_child0));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0_child0_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0_child0_child0));
+  ASSERT_FLOAT_EQ(40, YGNodeLayoutGetWidth(root_child0_child0_child0));
+  ASSERT_FLOAT_EQ(40, YGNodeLayoutGetHeight(root_child0_child0_child0));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0_child1));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetTop(root_child0_child1));
+  ASSERT_FLOAT_EQ(40, YGNodeLayoutGetWidth(root_child0_child1));
+  ASSERT_FLOAT_EQ(40, YGNodeLayoutGetHeight(root_child0_child1));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0_child1_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0_child1_child0));
+  ASSERT_FLOAT_EQ(40, YGNodeLayoutGetWidth(root_child0_child1_child0));
+  ASSERT_FLOAT_EQ(40, YGNodeLayoutGetHeight(root_child0_child1_child0));
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(500, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(500, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(430, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(70, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(90, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(30, YGNodeLayoutGetLeft(root_child0_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0_child0));
+  ASSERT_FLOAT_EQ(40, YGNodeLayoutGetWidth(root_child0_child0));
+  ASSERT_FLOAT_EQ(40, YGNodeLayoutGetHeight(root_child0_child0));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0_child0_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0_child0_child0));
+  ASSERT_FLOAT_EQ(40, YGNodeLayoutGetWidth(root_child0_child0_child0));
+  ASSERT_FLOAT_EQ(40, YGNodeLayoutGetHeight(root_child0_child0_child0));
+
+  ASSERT_FLOAT_EQ(30, YGNodeLayoutGetLeft(root_child0_child1));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetTop(root_child0_child1));
+  ASSERT_FLOAT_EQ(40, YGNodeLayoutGetWidth(root_child0_child1));
+  ASSERT_FLOAT_EQ(40, YGNodeLayoutGetHeight(root_child0_child1));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0_child1_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0_child1_child0));
+  ASSERT_FLOAT_EQ(40, YGNodeLayoutGetWidth(root_child0_child1_child0));
+  ASSERT_FLOAT_EQ(40, YGNodeLayoutGetHeight(root_child0_child1_child0));
+
+  YGNodeFreeRecursive(root);
+
+  YGConfigFree(config);
+}
diff --git a/automated-tests/src/dali-toolkit-third-party/yoga/YGHadOverflowTest.cpp b/automated-tests/src/dali-toolkit-third-party/yoga/YGHadOverflowTest.cpp
new file mode 100644 (file)
index 0000000..39cb20a
--- /dev/null
@@ -0,0 +1,127 @@
+// Copyright 2004-present Facebook. All Rights Reserved.
+
+#include <gtest/gtest.h>
+#include <yoga/Yoga.h>
+
+using namespace ::testing;
+
+class YogaTest_HadOverflowTests : public testing::Test {
+protected:
+  YogaTest_HadOverflowTests() {
+    config = YGConfigNew();
+    root = YGNodeNewWithConfig(config);
+    YGNodeStyleSetWidth(root, 200);
+    YGNodeStyleSetHeight(root, 100);
+    YGNodeStyleSetFlexDirection(root, YGFlexDirectionColumn);
+    YGNodeStyleSetFlexWrap(root, YGWrapNoWrap);
+  }
+
+  ~YogaTest_HadOverflowTests() {
+    YGNodeFreeRecursive(root);
+    YGConfigFree(config);
+  }
+
+  YGNodeRef root;
+  YGConfigRef config;
+};
+
+TEST_F(YogaTest_HadOverflowTests, children_overflow_no_wrap_and_no_flex_children) {
+  const YGNodeRef child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(child0, 80);
+  YGNodeStyleSetHeight(child0, 40);
+  YGNodeStyleSetMargin(child0, YGEdgeTop, 10);
+  YGNodeStyleSetMargin(child0, YGEdgeBottom, 15);
+  YGNodeInsertChild(root, child0, 0);
+  const YGNodeRef child1 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(child1, 80);
+  YGNodeStyleSetHeight(child1, 40);
+  YGNodeStyleSetMargin(child1, YGEdgeBottom, 5);
+  YGNodeInsertChild(root, child1, 1);
+
+  YGNodeCalculateLayout(root, 200, 100, YGDirectionLTR);
+
+  ASSERT_TRUE(YGNodeLayoutGetHadOverflow(root));
+}
+
+TEST_F(YogaTest_HadOverflowTests, spacing_overflow_no_wrap_and_no_flex_children) {
+  const YGNodeRef child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(child0, 80);
+  YGNodeStyleSetHeight(child0, 40);
+  YGNodeStyleSetMargin(child0, YGEdgeTop, 10);
+  YGNodeStyleSetMargin(child0, YGEdgeBottom, 10);
+  YGNodeInsertChild(root, child0, 0);
+  const YGNodeRef child1 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(child1, 80);
+  YGNodeStyleSetHeight(child1, 40);
+  YGNodeStyleSetMargin(child1, YGEdgeBottom, 5);
+  YGNodeInsertChild(root, child1, 1);
+
+  YGNodeCalculateLayout(root, 200, 100, YGDirectionLTR);
+
+  ASSERT_TRUE(YGNodeLayoutGetHadOverflow(root));
+}
+
+TEST_F(YogaTest_HadOverflowTests, no_overflow_no_wrap_and_flex_children) {
+  const YGNodeRef child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(child0, 80);
+  YGNodeStyleSetHeight(child0, 40);
+  YGNodeStyleSetMargin(child0, YGEdgeTop, 10);
+  YGNodeStyleSetMargin(child0, YGEdgeBottom, 10);
+  YGNodeInsertChild(root, child0, 0);
+  const YGNodeRef child1 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(child1, 80);
+  YGNodeStyleSetHeight(child1, 40);
+  YGNodeStyleSetMargin(child1, YGEdgeBottom, 5);
+  YGNodeStyleSetFlexShrink(child1, 1);
+  YGNodeInsertChild(root, child1, 1);
+
+  YGNodeCalculateLayout(root, 200, 100, YGDirectionLTR);
+
+  ASSERT_FALSE(YGNodeLayoutGetHadOverflow(root));
+}
+
+TEST_F(YogaTest_HadOverflowTests, hadOverflow_gets_reset_if_not_logger_valid) {
+  const YGNodeRef child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(child0, 80);
+  YGNodeStyleSetHeight(child0, 40);
+  YGNodeStyleSetMargin(child0, YGEdgeTop, 10);
+  YGNodeStyleSetMargin(child0, YGEdgeBottom, 10);
+  YGNodeInsertChild(root, child0, 0);
+  const YGNodeRef child1 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(child1, 80);
+  YGNodeStyleSetHeight(child1, 40);
+  YGNodeStyleSetMargin(child1, YGEdgeBottom, 5);
+  YGNodeInsertChild(root, child1, 1);
+
+  YGNodeCalculateLayout(root, 200, 100, YGDirectionLTR);
+
+  ASSERT_TRUE(YGNodeLayoutGetHadOverflow(root));
+
+  YGNodeStyleSetFlexShrink(child1, 1);
+
+  YGNodeCalculateLayout(root, 200, 100, YGDirectionLTR);
+
+  ASSERT_FALSE(YGNodeLayoutGetHadOverflow(root));
+}
+
+TEST_F(YogaTest_HadOverflowTests, spacing_overflow_in_nested_nodes) {
+  const YGNodeRef child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(child0, 80);
+  YGNodeStyleSetHeight(child0, 40);
+  YGNodeStyleSetMargin(child0, YGEdgeTop, 10);
+  YGNodeStyleSetMargin(child0, YGEdgeBottom, 10);
+  YGNodeInsertChild(root, child0, 0);
+  const YGNodeRef child1 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(child1, 80);
+  YGNodeStyleSetHeight(child1, 40);
+  YGNodeInsertChild(root, child1, 1);
+  const YGNodeRef child1_1 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(child1_1, 80);
+  YGNodeStyleSetHeight(child1_1, 40);
+  YGNodeStyleSetMargin(child1_1, YGEdgeBottom, 5);
+  YGNodeInsertChild(child1, child1_1, 0);
+
+  YGNodeCalculateLayout(root, 200, 100, YGDirectionLTR);
+
+  ASSERT_TRUE(YGNodeLayoutGetHadOverflow(root));
+}
diff --git a/automated-tests/src/dali-toolkit-third-party/yoga/YGInfiniteHeightTest.cpp b/automated-tests/src/dali-toolkit-third-party/yoga/YGInfiniteHeightTest.cpp
new file mode 100644 (file)
index 0000000..a557b3d
--- /dev/null
@@ -0,0 +1,53 @@
+/**
+ * Copyright (c) 2014-present, Facebook, Inc.
+ *
+ * This source code is licensed under the MIT license found in the
+ * LICENSE file in the root directory of this source tree.
+ */
+
+#include <gtest/gtest.h>
+#include <yoga/Yoga.h>
+
+// This test isn't correct from the Flexbox standard standpoint,
+// because percentages are calculated with parent constraints.
+// However, we need to make sure we fail gracefully in this case, not returning NaN
+TEST(YogaTest, percent_absolute_position_infinite_height) {
+  const YGConfigRef config = YGConfigNew();
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexDirection(root, YGFlexDirectionRow);
+  YGNodeStyleSetWidth(root, 300);
+
+  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child0, 300);
+  YGNodeStyleSetHeight(root_child0, 300);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  const YGNodeRef root_child1 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetPositionType(root_child1, YGPositionTypeAbsolute);
+  YGNodeStyleSetPositionPercent(root_child1, YGEdgeLeft, 20);
+  YGNodeStyleSetPositionPercent(root_child1, YGEdgeTop, 20);
+  YGNodeStyleSetWidthPercent(root_child1, 20);
+  YGNodeStyleSetHeightPercent(root_child1, 20);
+  YGNodeInsertChild(root, root_child1, 1);
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(300, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(300, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(300, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(300, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(60, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(60, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetHeight(root_child1));
+
+  YGNodeFreeRecursive(root);
+
+  YGConfigFree(config);
+}
diff --git a/automated-tests/src/dali-toolkit-third-party/yoga/YGJustifyContentTest.cpp b/automated-tests/src/dali-toolkit-third-party/yoga/YGJustifyContentTest.cpp
new file mode 100644 (file)
index 0000000..e5d4216
--- /dev/null
@@ -0,0 +1,999 @@
+/**
+ * Copyright (c) 2014-present, Facebook, Inc.
+ *
+ * This source code is licensed under the MIT license found in the
+ * LICENSE file in the root directory of this source tree.
+ */
+
+// @Generated by gentest/gentest.rb from gentest/fixtures/YGJustifyContentTest.html
+
+#include <gtest/gtest.h>
+#include <yoga/Yoga.h>
+
+TEST(YogaTest, justify_content_row_flex_start) {
+  const YGConfigRef config = YGConfigNew();
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexDirection(root, YGFlexDirectionRow);
+  YGNodeStyleSetWidth(root, 102);
+  YGNodeStyleSetHeight(root, 102);
+
+  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child0, 10);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  const YGNodeRef root_child1 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child1, 10);
+  YGNodeInsertChild(root, root_child1, 1);
+
+  const YGNodeRef root_child2 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child2, 10);
+  YGNodeInsertChild(root, root_child2, 2);
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(102, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(102, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(102, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(102, YGNodeLayoutGetHeight(root_child1));
+
+  ASSERT_FLOAT_EQ(20, YGNodeLayoutGetLeft(root_child2));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child2));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetWidth(root_child2));
+  ASSERT_FLOAT_EQ(102, YGNodeLayoutGetHeight(root_child2));
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(102, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(102, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(92, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(102, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(82, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(102, YGNodeLayoutGetHeight(root_child1));
+
+  ASSERT_FLOAT_EQ(72, YGNodeLayoutGetLeft(root_child2));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child2));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetWidth(root_child2));
+  ASSERT_FLOAT_EQ(102, YGNodeLayoutGetHeight(root_child2));
+
+  YGNodeFreeRecursive(root);
+
+  YGConfigFree(config);
+}
+
+TEST(YogaTest, justify_content_row_flex_end) {
+  const YGConfigRef config = YGConfigNew();
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexDirection(root, YGFlexDirectionRow);
+  YGNodeStyleSetJustifyContent(root, YGJustifyFlexEnd);
+  YGNodeStyleSetWidth(root, 102);
+  YGNodeStyleSetHeight(root, 102);
+
+  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child0, 10);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  const YGNodeRef root_child1 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child1, 10);
+  YGNodeInsertChild(root, root_child1, 1);
+
+  const YGNodeRef root_child2 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child2, 10);
+  YGNodeInsertChild(root, root_child2, 2);
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(102, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(102, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(72, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(102, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(82, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(102, YGNodeLayoutGetHeight(root_child1));
+
+  ASSERT_FLOAT_EQ(92, YGNodeLayoutGetLeft(root_child2));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child2));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetWidth(root_child2));
+  ASSERT_FLOAT_EQ(102, YGNodeLayoutGetHeight(root_child2));
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(102, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(102, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(20, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(102, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(102, YGNodeLayoutGetHeight(root_child1));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child2));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child2));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetWidth(root_child2));
+  ASSERT_FLOAT_EQ(102, YGNodeLayoutGetHeight(root_child2));
+
+  YGNodeFreeRecursive(root);
+
+  YGConfigFree(config);
+}
+
+TEST(YogaTest, justify_content_row_center) {
+  const YGConfigRef config = YGConfigNew();
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexDirection(root, YGFlexDirectionRow);
+  YGNodeStyleSetJustifyContent(root, YGJustifyCenter);
+  YGNodeStyleSetWidth(root, 102);
+  YGNodeStyleSetHeight(root, 102);
+
+  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child0, 10);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  const YGNodeRef root_child1 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child1, 10);
+  YGNodeInsertChild(root, root_child1, 1);
+
+  const YGNodeRef root_child2 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child2, 10);
+  YGNodeInsertChild(root, root_child2, 2);
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(102, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(102, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(36, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(102, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(46, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(102, YGNodeLayoutGetHeight(root_child1));
+
+  ASSERT_FLOAT_EQ(56, YGNodeLayoutGetLeft(root_child2));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child2));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetWidth(root_child2));
+  ASSERT_FLOAT_EQ(102, YGNodeLayoutGetHeight(root_child2));
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(102, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(102, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(56, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(102, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(46, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(102, YGNodeLayoutGetHeight(root_child1));
+
+  ASSERT_FLOAT_EQ(36, YGNodeLayoutGetLeft(root_child2));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child2));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetWidth(root_child2));
+  ASSERT_FLOAT_EQ(102, YGNodeLayoutGetHeight(root_child2));
+
+  YGNodeFreeRecursive(root);
+
+  YGConfigFree(config);
+}
+
+TEST(YogaTest, justify_content_row_space_between) {
+  const YGConfigRef config = YGConfigNew();
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexDirection(root, YGFlexDirectionRow);
+  YGNodeStyleSetJustifyContent(root, YGJustifySpaceBetween);
+  YGNodeStyleSetWidth(root, 102);
+  YGNodeStyleSetHeight(root, 102);
+
+  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child0, 10);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  const YGNodeRef root_child1 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child1, 10);
+  YGNodeInsertChild(root, root_child1, 1);
+
+  const YGNodeRef root_child2 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child2, 10);
+  YGNodeInsertChild(root, root_child2, 2);
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(102, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(102, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(102, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(46, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(102, YGNodeLayoutGetHeight(root_child1));
+
+  ASSERT_FLOAT_EQ(92, YGNodeLayoutGetLeft(root_child2));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child2));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetWidth(root_child2));
+  ASSERT_FLOAT_EQ(102, YGNodeLayoutGetHeight(root_child2));
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(102, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(102, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(92, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(102, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(46, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(102, YGNodeLayoutGetHeight(root_child1));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child2));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child2));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetWidth(root_child2));
+  ASSERT_FLOAT_EQ(102, YGNodeLayoutGetHeight(root_child2));
+
+  YGNodeFreeRecursive(root);
+
+  YGConfigFree(config);
+}
+
+TEST(YogaTest, justify_content_row_space_around) {
+  const YGConfigRef config = YGConfigNew();
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexDirection(root, YGFlexDirectionRow);
+  YGNodeStyleSetJustifyContent(root, YGJustifySpaceAround);
+  YGNodeStyleSetWidth(root, 102);
+  YGNodeStyleSetHeight(root, 102);
+
+  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child0, 10);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  const YGNodeRef root_child1 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child1, 10);
+  YGNodeInsertChild(root, root_child1, 1);
+
+  const YGNodeRef root_child2 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child2, 10);
+  YGNodeInsertChild(root, root_child2, 2);
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(102, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(102, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(12, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(102, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(46, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(102, YGNodeLayoutGetHeight(root_child1));
+
+  ASSERT_FLOAT_EQ(80, YGNodeLayoutGetLeft(root_child2));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child2));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetWidth(root_child2));
+  ASSERT_FLOAT_EQ(102, YGNodeLayoutGetHeight(root_child2));
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(102, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(102, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(80, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(102, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(46, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(102, YGNodeLayoutGetHeight(root_child1));
+
+  ASSERT_FLOAT_EQ(12, YGNodeLayoutGetLeft(root_child2));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child2));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetWidth(root_child2));
+  ASSERT_FLOAT_EQ(102, YGNodeLayoutGetHeight(root_child2));
+
+  YGNodeFreeRecursive(root);
+
+  YGConfigFree(config);
+}
+
+TEST(YogaTest, justify_content_column_flex_start) {
+  const YGConfigRef config = YGConfigNew();
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root, 102);
+  YGNodeStyleSetHeight(root, 102);
+
+  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetHeight(root_child0, 10);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  const YGNodeRef root_child1 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetHeight(root_child1, 10);
+  YGNodeInsertChild(root, root_child1, 1);
+
+  const YGNodeRef root_child2 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetHeight(root_child2, 10);
+  YGNodeInsertChild(root, root_child2, 2);
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(102, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(102, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(102, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(102, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child1));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child2));
+  ASSERT_FLOAT_EQ(20, YGNodeLayoutGetTop(root_child2));
+  ASSERT_FLOAT_EQ(102, YGNodeLayoutGetWidth(root_child2));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child2));
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(102, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(102, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(102, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(102, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child1));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child2));
+  ASSERT_FLOAT_EQ(20, YGNodeLayoutGetTop(root_child2));
+  ASSERT_FLOAT_EQ(102, YGNodeLayoutGetWidth(root_child2));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child2));
+
+  YGNodeFreeRecursive(root);
+
+  YGConfigFree(config);
+}
+
+TEST(YogaTest, justify_content_column_flex_end) {
+  const YGConfigRef config = YGConfigNew();
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  YGNodeStyleSetJustifyContent(root, YGJustifyFlexEnd);
+  YGNodeStyleSetWidth(root, 102);
+  YGNodeStyleSetHeight(root, 102);
+
+  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetHeight(root_child0, 10);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  const YGNodeRef root_child1 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetHeight(root_child1, 10);
+  YGNodeInsertChild(root, root_child1, 1);
+
+  const YGNodeRef root_child2 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetHeight(root_child2, 10);
+  YGNodeInsertChild(root, root_child2, 2);
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(102, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(102, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(72, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(102, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(82, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(102, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child1));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child2));
+  ASSERT_FLOAT_EQ(92, YGNodeLayoutGetTop(root_child2));
+  ASSERT_FLOAT_EQ(102, YGNodeLayoutGetWidth(root_child2));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child2));
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(102, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(102, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(72, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(102, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(82, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(102, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child1));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child2));
+  ASSERT_FLOAT_EQ(92, YGNodeLayoutGetTop(root_child2));
+  ASSERT_FLOAT_EQ(102, YGNodeLayoutGetWidth(root_child2));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child2));
+
+  YGNodeFreeRecursive(root);
+
+  YGConfigFree(config);
+}
+
+TEST(YogaTest, justify_content_column_center) {
+  const YGConfigRef config = YGConfigNew();
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  YGNodeStyleSetJustifyContent(root, YGJustifyCenter);
+  YGNodeStyleSetWidth(root, 102);
+  YGNodeStyleSetHeight(root, 102);
+
+  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetHeight(root_child0, 10);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  const YGNodeRef root_child1 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetHeight(root_child1, 10);
+  YGNodeInsertChild(root, root_child1, 1);
+
+  const YGNodeRef root_child2 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetHeight(root_child2, 10);
+  YGNodeInsertChild(root, root_child2, 2);
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(102, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(102, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(36, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(102, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(46, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(102, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child1));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child2));
+  ASSERT_FLOAT_EQ(56, YGNodeLayoutGetTop(root_child2));
+  ASSERT_FLOAT_EQ(102, YGNodeLayoutGetWidth(root_child2));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child2));
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(102, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(102, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(36, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(102, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(46, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(102, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child1));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child2));
+  ASSERT_FLOAT_EQ(56, YGNodeLayoutGetTop(root_child2));
+  ASSERT_FLOAT_EQ(102, YGNodeLayoutGetWidth(root_child2));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child2));
+
+  YGNodeFreeRecursive(root);
+
+  YGConfigFree(config);
+}
+
+TEST(YogaTest, justify_content_column_space_between) {
+  const YGConfigRef config = YGConfigNew();
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  YGNodeStyleSetJustifyContent(root, YGJustifySpaceBetween);
+  YGNodeStyleSetWidth(root, 102);
+  YGNodeStyleSetHeight(root, 102);
+
+  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetHeight(root_child0, 10);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  const YGNodeRef root_child1 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetHeight(root_child1, 10);
+  YGNodeInsertChild(root, root_child1, 1);
+
+  const YGNodeRef root_child2 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetHeight(root_child2, 10);
+  YGNodeInsertChild(root, root_child2, 2);
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(102, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(102, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(102, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(46, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(102, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child1));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child2));
+  ASSERT_FLOAT_EQ(92, YGNodeLayoutGetTop(root_child2));
+  ASSERT_FLOAT_EQ(102, YGNodeLayoutGetWidth(root_child2));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child2));
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(102, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(102, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(102, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(46, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(102, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child1));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child2));
+  ASSERT_FLOAT_EQ(92, YGNodeLayoutGetTop(root_child2));
+  ASSERT_FLOAT_EQ(102, YGNodeLayoutGetWidth(root_child2));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child2));
+
+  YGNodeFreeRecursive(root);
+
+  YGConfigFree(config);
+}
+
+TEST(YogaTest, justify_content_column_space_around) {
+  const YGConfigRef config = YGConfigNew();
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  YGNodeStyleSetJustifyContent(root, YGJustifySpaceAround);
+  YGNodeStyleSetWidth(root, 102);
+  YGNodeStyleSetHeight(root, 102);
+
+  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetHeight(root_child0, 10);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  const YGNodeRef root_child1 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetHeight(root_child1, 10);
+  YGNodeInsertChild(root, root_child1, 1);
+
+  const YGNodeRef root_child2 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetHeight(root_child2, 10);
+  YGNodeInsertChild(root, root_child2, 2);
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(102, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(102, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(12, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(102, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(46, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(102, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child1));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child2));
+  ASSERT_FLOAT_EQ(80, YGNodeLayoutGetTop(root_child2));
+  ASSERT_FLOAT_EQ(102, YGNodeLayoutGetWidth(root_child2));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child2));
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(102, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(102, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(12, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(102, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(46, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(102, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child1));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child2));
+  ASSERT_FLOAT_EQ(80, YGNodeLayoutGetTop(root_child2));
+  ASSERT_FLOAT_EQ(102, YGNodeLayoutGetWidth(root_child2));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child2));
+
+  YGNodeFreeRecursive(root);
+
+  YGConfigFree(config);
+}
+
+TEST(YogaTest, justify_content_row_min_width_and_margin) {
+  const YGConfigRef config = YGConfigNew();
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexDirection(root, YGFlexDirectionRow);
+  YGNodeStyleSetJustifyContent(root, YGJustifyCenter);
+  YGNodeStyleSetMargin(root, YGEdgeLeft, 100);
+  YGNodeStyleSetMinWidth(root, 50);
+
+  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child0, 20);
+  YGNodeStyleSetHeight(root_child0, 20);
+  YGNodeInsertChild(root, root_child0, 0);
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(20, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(15, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(20, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(20, YGNodeLayoutGetHeight(root_child0));
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);
+
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(20, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(15, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(20, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(20, YGNodeLayoutGetHeight(root_child0));
+
+  YGNodeFreeRecursive(root);
+
+  YGConfigFree(config);
+}
+
+TEST(YogaTest, justify_content_row_max_width_and_margin) {
+  const YGConfigRef config = YGConfigNew();
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexDirection(root, YGFlexDirectionRow);
+  YGNodeStyleSetJustifyContent(root, YGJustifyCenter);
+  YGNodeStyleSetMargin(root, YGEdgeLeft, 100);
+  YGNodeStyleSetWidth(root, 100);
+  YGNodeStyleSetMaxWidth(root, 80);
+
+  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child0, 20);
+  YGNodeStyleSetHeight(root_child0, 20);
+  YGNodeInsertChild(root, root_child0, 0);
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(80, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(20, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(30, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(20, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(20, YGNodeLayoutGetHeight(root_child0));
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);
+
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(80, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(20, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(30, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(20, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(20, YGNodeLayoutGetHeight(root_child0));
+
+  YGNodeFreeRecursive(root);
+
+  YGConfigFree(config);
+}
+
+TEST(YogaTest, justify_content_column_min_height_and_margin) {
+  const YGConfigRef config = YGConfigNew();
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  YGNodeStyleSetJustifyContent(root, YGJustifyCenter);
+  YGNodeStyleSetMargin(root, YGEdgeTop, 100);
+  YGNodeStyleSetMinHeight(root, 50);
+
+  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child0, 20);
+  YGNodeStyleSetHeight(root_child0, 20);
+  YGNodeInsertChild(root, root_child0, 0);
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(20, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(15, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(20, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(20, YGNodeLayoutGetHeight(root_child0));
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(20, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(15, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(20, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(20, YGNodeLayoutGetHeight(root_child0));
+
+  YGNodeFreeRecursive(root);
+
+  YGConfigFree(config);
+}
+
+TEST(YogaTest, justify_content_colunn_max_height_and_margin) {
+  const YGConfigRef config = YGConfigNew();
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  YGNodeStyleSetJustifyContent(root, YGJustifyCenter);
+  YGNodeStyleSetMargin(root, YGEdgeTop, 100);
+  YGNodeStyleSetHeight(root, 100);
+  YGNodeStyleSetMaxHeight(root, 80);
+
+  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child0, 20);
+  YGNodeStyleSetHeight(root_child0, 20);
+  YGNodeInsertChild(root, root_child0, 0);
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(20, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(80, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(30, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(20, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(20, YGNodeLayoutGetHeight(root_child0));
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(20, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(80, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(30, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(20, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(20, YGNodeLayoutGetHeight(root_child0));
+
+  YGNodeFreeRecursive(root);
+
+  YGConfigFree(config);
+}
+
+TEST(YogaTest, justify_content_column_space_evenly) {
+  const YGConfigRef config = YGConfigNew();
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  YGNodeStyleSetJustifyContent(root, YGJustifySpaceEvenly);
+  YGNodeStyleSetWidth(root, 102);
+  YGNodeStyleSetHeight(root, 102);
+
+  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetHeight(root_child0, 10);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  const YGNodeRef root_child1 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetHeight(root_child1, 10);
+  YGNodeInsertChild(root, root_child1, 1);
+
+  const YGNodeRef root_child2 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetHeight(root_child2, 10);
+  YGNodeInsertChild(root, root_child2, 2);
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(102, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(102, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(18, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(102, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(46, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(102, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child1));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child2));
+  ASSERT_FLOAT_EQ(74, YGNodeLayoutGetTop(root_child2));
+  ASSERT_FLOAT_EQ(102, YGNodeLayoutGetWidth(root_child2));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child2));
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(102, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(102, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(18, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(102, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(46, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(102, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child1));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child2));
+  ASSERT_FLOAT_EQ(74, YGNodeLayoutGetTop(root_child2));
+  ASSERT_FLOAT_EQ(102, YGNodeLayoutGetWidth(root_child2));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child2));
+
+  YGNodeFreeRecursive(root);
+
+  YGConfigFree(config);
+}
+
+TEST(YogaTest, justify_content_row_space_evenly) {
+  const YGConfigRef config = YGConfigNew();
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexDirection(root, YGFlexDirectionRow);
+  YGNodeStyleSetJustifyContent(root, YGJustifySpaceEvenly);
+  YGNodeStyleSetWidth(root, 102);
+  YGNodeStyleSetHeight(root, 102);
+
+  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetHeight(root_child0, 10);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  const YGNodeRef root_child1 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetHeight(root_child1, 10);
+  YGNodeInsertChild(root, root_child1, 1);
+
+  const YGNodeRef root_child2 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetHeight(root_child2, 10);
+  YGNodeInsertChild(root, root_child2, 2);
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(102, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(102, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(26, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(51, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child1));
+
+  ASSERT_FLOAT_EQ(77, YGNodeLayoutGetLeft(root_child2));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child2));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetWidth(root_child2));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child2));
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(102, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(102, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(77, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(51, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child1));
+
+  ASSERT_FLOAT_EQ(26, YGNodeLayoutGetLeft(root_child2));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child2));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetWidth(root_child2));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child2));
+
+  YGNodeFreeRecursive(root);
+
+  YGConfigFree(config);
+}
diff --git a/automated-tests/src/dali-toolkit-third-party/yoga/YGLayoutDiffingTest.cpp b/automated-tests/src/dali-toolkit-third-party/yoga/YGLayoutDiffingTest.cpp
new file mode 100644 (file)
index 0000000..a04e87d
--- /dev/null
@@ -0,0 +1,87 @@
+/**
+ * Copyright (c) 2014-present, Facebook, Inc.
+ *
+ * This source code is licensed under the MIT license found in the
+ * LICENSE file in the root directory of this source tree.
+ */
+
+#include <gtest/gtest.h>
+#include <yoga/YGNode.h>
+#include <yoga/Yoga.h>
+
+TEST(YogaTest, assert_layout_trees_are_same) {
+  YGConfig* config = YGConfigNew();
+  YGConfigSetUseLegacyStretchBehaviour(config, true);
+  const YGNodeRef root1 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root1, 500);
+  YGNodeStyleSetHeight(root1, 500);
+
+  const YGNodeRef root1_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetAlignItems(root1_child0, YGAlignFlexStart);
+  YGNodeInsertChild(root1, root1_child0, 0);
+
+  const YGNodeRef root1_child0_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexGrow(root1_child0_child0, 1);
+  YGNodeStyleSetFlexShrink(root1_child0_child0, 1);
+  YGNodeInsertChild(root1_child0, root1_child0_child0, 0);
+
+  const YGNodeRef root1_child0_child0_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexGrow(root1_child0_child0_child0, 1);
+  YGNodeStyleSetFlexShrink(root1_child0_child0_child0, 1);
+  YGNodeInsertChild(root1_child0_child0, root1_child0_child0_child0, 0);
+
+  const int32_t cal1_configInstanceCount = YGConfigGetInstanceCount();
+  const int32_t cal1_nodeInstanceCount = YGNodeGetInstanceCount();
+
+  YGNodeCalculateLayout(root1, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_EQ(YGConfigGetInstanceCount(), cal1_configInstanceCount);
+  ASSERT_EQ(YGNodeGetInstanceCount(), cal1_nodeInstanceCount);
+
+  const YGNodeRef root2 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root2, 500);
+  YGNodeStyleSetHeight(root2, 500);
+
+  const YGNodeRef root2_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetAlignItems(root2_child0, YGAlignFlexStart);
+  YGNodeInsertChild(root2, root2_child0, 0);
+
+  const YGNodeRef root2_child0_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexGrow(root2_child0_child0, 1);
+  YGNodeStyleSetFlexShrink(root2_child0_child0, 1);
+  YGNodeInsertChild(root2_child0, root2_child0_child0, 0);
+
+  const YGNodeRef root2_child0_child0_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexGrow(root2_child0_child0_child0, 1);
+  YGNodeStyleSetFlexShrink(root2_child0_child0_child0, 1);
+  YGNodeInsertChild(root2_child0_child0, root2_child0_child0_child0, 0);
+
+  const int32_t cal2_configInstanceCount = YGConfigGetInstanceCount();
+  const int32_t cal2_nodeInstanceCount = YGNodeGetInstanceCount();
+
+  YGNodeCalculateLayout(root2, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_EQ(YGConfigGetInstanceCount(), cal2_configInstanceCount);
+  ASSERT_EQ(YGNodeGetInstanceCount(), cal2_nodeInstanceCount);
+
+  ASSERT_TRUE(YGNodeLayoutGetDidUseLegacyFlag(root1));
+  ASSERT_TRUE(YGNodeLayoutGetDidUseLegacyFlag(root2));
+  ASSERT_TRUE(root1->isLayoutTreeEqualToNode(*root2));
+
+  YGNodeStyleSetAlignItems(root2, YGAlignFlexEnd);
+
+  const int32_t cal3_configInstanceCount = YGConfigGetInstanceCount();
+  const int32_t cal3_nodeInstanceCount = YGNodeGetInstanceCount();
+
+  YGNodeCalculateLayout(root2, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_EQ(YGConfigGetInstanceCount(), cal3_configInstanceCount);
+  ASSERT_EQ(YGNodeGetInstanceCount(), cal3_nodeInstanceCount);
+
+  ASSERT_FALSE(root1->isLayoutTreeEqualToNode(*root2));
+
+  YGNodeFreeRecursive(root1);
+  YGNodeFreeRecursive(root2);
+
+  YGConfigFree(config);
+}
diff --git a/automated-tests/src/dali-toolkit-third-party/yoga/YGLoggerTest.cpp b/automated-tests/src/dali-toolkit-third-party/yoga/YGLoggerTest.cpp
new file mode 100644 (file)
index 0000000..1b84ee6
--- /dev/null
@@ -0,0 +1,87 @@
+/**
+ * Copyright (c) 2014-present, Facebook, Inc.
+ *
+ * This source code is licensed under the MIT license found in the
+ * LICENSE file in the root directory of this source tree.
+ */
+
+#include <gtest/gtest.h>
+#include <stdarg.h>
+#include <yoga/Yoga.h>
+
+namespace {
+char writeBuffer[4096];
+int _unmanagedLogger(const YGConfigRef config,
+                     const YGNodeRef node,
+                     YGLogLevel level,
+                     const char *format,
+                     va_list args) {
+  return vsnprintf(writeBuffer + strlen(writeBuffer),
+                   sizeof(writeBuffer) - strlen(writeBuffer),
+                   format,
+                   args);
+}
+}
+
+TEST(YogaTest, logger_default_node_should_print_no_style_info) {
+  writeBuffer[0] = '\0';
+  const YGConfigRef config = YGConfigNew();
+  YGConfigSetLogger(config, _unmanagedLogger);
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  YGNodeCalculateLayout(root, YGUnitUndefined, YGUnitUndefined, YGDirectionLTR);
+  YGNodePrint(root,
+              (YGPrintOptions)(YGPrintOptionsLayout | YGPrintOptionsChildren |
+                               YGPrintOptionsStyle));
+  YGConfigSetLogger(config, NULL);
+  YGNodeFree(root);
+
+  const char *expected = "<div layout=\"width: 0; height: 0; top: 0; left: 0;\" style=\"\" ></div>";
+  ASSERT_STREQ(expected, writeBuffer);
+}
+
+TEST(YogaTest, logger_node_with_percentage_absolute_position_and_margin) {
+  writeBuffer[0] = '\0';
+  const YGConfigRef config = YGConfigNew();
+  YGConfigSetLogger(config, _unmanagedLogger);
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  YGNodeStyleSetPositionType(root, YGPositionTypeAbsolute);
+  YGNodeStyleSetWidthPercent(root, 50);
+  YGNodeStyleSetHeightPercent(root, 75);
+  YGNodeStyleSetFlex(root, 1);
+  YGNodeStyleSetMargin(root, YGEdgeRight, 10);
+  YGNodeStyleSetMarginAuto(root, YGEdgeLeft);
+  YGNodeCalculateLayout(root, YGUnitUndefined, YGUnitUndefined, YGDirectionLTR);
+  YGNodePrint(root,
+              (YGPrintOptions)(YGPrintOptionsLayout | YGPrintOptionsChildren |
+                               YGPrintOptionsStyle));
+  YGConfigSetLogger(config, NULL);
+  YGNodeFree(root);
+
+  const char *expected = "<div layout=\"width: 0; height: 0; top: 0; left: 0;\" style=\"flex: 1; "
+                         "margin-left: auto; margin-right: 10px; width: 50%; height: 75%; "
+                         "position: absolute; \" ></div>";
+  ASSERT_STREQ(expected, writeBuffer);
+}
+
+TEST(YogaTest, logger_node_with_children_should_print_indented) {
+  writeBuffer[0] = '\0';
+  const YGConfigRef config = YGConfigNew();
+  YGConfigSetLogger(config, _unmanagedLogger);
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  const YGNodeRef child0 = YGNodeNewWithConfig(config);
+  const YGNodeRef child1 = YGNodeNewWithConfig(config);
+  YGNodeInsertChild(root, child0, 0);
+  YGNodeInsertChild(root, child1, 1);
+  YGNodeCalculateLayout(root, YGUnitUndefined, YGUnitUndefined, YGDirectionLTR);
+  YGNodePrint(root,
+              (YGPrintOptions)(YGPrintOptionsLayout | YGPrintOptionsChildren |
+                               YGPrintOptionsStyle));
+  YGConfigSetLogger(config, NULL);
+  YGNodeFreeRecursive(root);
+
+  const char *expected = "<div layout=\"width: 0; height: 0; top: 0; left: 0;\" style=\"\" >\n  "
+                         "<div layout=\"width: 0; height: 0; top: 0; left: 0;\" style=\"\" "
+                         "></div>\n  <div layout=\"width: 0; height: 0; top: 0; left: 0;\" "
+                         "style=\"\" ></div>\n</div>";
+  ASSERT_STREQ(expected, writeBuffer);
+}
diff --git a/automated-tests/src/dali-toolkit-third-party/yoga/YGMarginTest.cpp b/automated-tests/src/dali-toolkit-third-party/yoga/YGMarginTest.cpp
new file mode 100644 (file)
index 0000000..593cd2f
--- /dev/null
@@ -0,0 +1,1717 @@
+/**
+ * Copyright (c) 2014-present, Facebook, Inc.
+ *
+ * This source code is licensed under the MIT license found in the
+ * LICENSE file in the root directory of this source tree.
+ */
+
+// @Generated by gentest/gentest.rb from gentest/fixtures/YGMarginTest.html
+
+#include <gtest/gtest.h>
+#include <yoga/Yoga.h>
+
+TEST(YogaTest, margin_start) {
+  const YGConfigRef config = YGConfigNew();
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexDirection(root, YGFlexDirectionRow);
+  YGNodeStyleSetWidth(root, 100);
+  YGNodeStyleSetHeight(root, 100);
+
+  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetMargin(root_child0, YGEdgeStart, 10);
+  YGNodeStyleSetWidth(root_child0, 10);
+  YGNodeInsertChild(root, root_child0, 0);
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child0));
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(80, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child0));
+
+  YGNodeFreeRecursive(root);
+
+  YGConfigFree(config);
+}
+
+TEST(YogaTest, margin_top) {
+  const YGConfigRef config = YGConfigNew();
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root, 100);
+  YGNodeStyleSetHeight(root, 100);
+
+  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetMargin(root_child0, YGEdgeTop, 10);
+  YGNodeStyleSetHeight(root_child0, 10);
+  YGNodeInsertChild(root, root_child0, 0);
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child0));
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child0));
+
+  YGNodeFreeRecursive(root);
+
+  YGConfigFree(config);
+}
+
+TEST(YogaTest, margin_end) {
+  const YGConfigRef config = YGConfigNew();
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexDirection(root, YGFlexDirectionRow);
+  YGNodeStyleSetJustifyContent(root, YGJustifyFlexEnd);
+  YGNodeStyleSetWidth(root, 100);
+  YGNodeStyleSetHeight(root, 100);
+
+  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetMargin(root_child0, YGEdgeEnd, 10);
+  YGNodeStyleSetWidth(root_child0, 10);
+  YGNodeInsertChild(root, root_child0, 0);
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(80, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child0));
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child0));
+
+  YGNodeFreeRecursive(root);
+
+  YGConfigFree(config);
+}
+
+TEST(YogaTest, margin_bottom) {
+  const YGConfigRef config = YGConfigNew();
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  YGNodeStyleSetJustifyContent(root, YGJustifyFlexEnd);
+  YGNodeStyleSetWidth(root, 100);
+  YGNodeStyleSetHeight(root, 100);
+
+  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetMargin(root_child0, YGEdgeBottom, 10);
+  YGNodeStyleSetHeight(root_child0, 10);
+  YGNodeInsertChild(root, root_child0, 0);
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(80, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child0));
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(80, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child0));
+
+  YGNodeFreeRecursive(root);
+
+  YGConfigFree(config);
+}
+
+TEST(YogaTest, margin_and_flex_row) {
+  const YGConfigRef config = YGConfigNew();
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexDirection(root, YGFlexDirectionRow);
+  YGNodeStyleSetWidth(root, 100);
+  YGNodeStyleSetHeight(root, 100);
+
+  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexGrow(root_child0, 1);
+  YGNodeStyleSetMargin(root_child0, YGEdgeStart, 10);
+  YGNodeStyleSetMargin(root_child0, YGEdgeEnd, 10);
+  YGNodeInsertChild(root, root_child0, 0);
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(80, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child0));
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(80, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child0));
+
+  YGNodeFreeRecursive(root);
+
+  YGConfigFree(config);
+}
+
+TEST(YogaTest, margin_and_flex_column) {
+  const YGConfigRef config = YGConfigNew();
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root, 100);
+  YGNodeStyleSetHeight(root, 100);
+
+  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexGrow(root_child0, 1);
+  YGNodeStyleSetMargin(root_child0, YGEdgeTop, 10);
+  YGNodeStyleSetMargin(root_child0, YGEdgeBottom, 10);
+  YGNodeInsertChild(root, root_child0, 0);
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(80, YGNodeLayoutGetHeight(root_child0));
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(80, YGNodeLayoutGetHeight(root_child0));
+
+  YGNodeFreeRecursive(root);
+
+  YGConfigFree(config);
+}
+
+TEST(YogaTest, margin_and_stretch_row) {
+  const YGConfigRef config = YGConfigNew();
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexDirection(root, YGFlexDirectionRow);
+  YGNodeStyleSetWidth(root, 100);
+  YGNodeStyleSetHeight(root, 100);
+
+  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexGrow(root_child0, 1);
+  YGNodeStyleSetMargin(root_child0, YGEdgeTop, 10);
+  YGNodeStyleSetMargin(root_child0, YGEdgeBottom, 10);
+  YGNodeInsertChild(root, root_child0, 0);
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(80, YGNodeLayoutGetHeight(root_child0));
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(80, YGNodeLayoutGetHeight(root_child0));
+
+  YGNodeFreeRecursive(root);
+
+  YGConfigFree(config);
+}
+
+TEST(YogaTest, margin_and_stretch_column) {
+  const YGConfigRef config = YGConfigNew();
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root, 100);
+  YGNodeStyleSetHeight(root, 100);
+
+  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexGrow(root_child0, 1);
+  YGNodeStyleSetMargin(root_child0, YGEdgeStart, 10);
+  YGNodeStyleSetMargin(root_child0, YGEdgeEnd, 10);
+  YGNodeInsertChild(root, root_child0, 0);
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(80, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child0));
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(80, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child0));
+
+  YGNodeFreeRecursive(root);
+
+  YGConfigFree(config);
+}
+
+TEST(YogaTest, margin_with_sibling_row) {
+  const YGConfigRef config = YGConfigNew();
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexDirection(root, YGFlexDirectionRow);
+  YGNodeStyleSetWidth(root, 100);
+  YGNodeStyleSetHeight(root, 100);
+
+  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexGrow(root_child0, 1);
+  YGNodeStyleSetMargin(root_child0, YGEdgeEnd, 10);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  const YGNodeRef root_child1 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexGrow(root_child1, 1);
+  YGNodeInsertChild(root, root_child1, 1);
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(45, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(55, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(45, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child1));
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(55, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(45, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(45, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child1));
+
+  YGNodeFreeRecursive(root);
+
+  YGConfigFree(config);
+}
+
+TEST(YogaTest, margin_with_sibling_column) {
+  const YGConfigRef config = YGConfigNew();
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root, 100);
+  YGNodeStyleSetHeight(root, 100);
+
+  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexGrow(root_child0, 1);
+  YGNodeStyleSetMargin(root_child0, YGEdgeBottom, 10);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  const YGNodeRef root_child1 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexGrow(root_child1, 1);
+  YGNodeInsertChild(root, root_child1, 1);
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(45, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(55, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(45, YGNodeLayoutGetHeight(root_child1));
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(45, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(55, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(45, YGNodeLayoutGetHeight(root_child1));
+
+  YGNodeFreeRecursive(root);
+
+  YGConfigFree(config);
+}
+
+TEST(YogaTest, margin_auto_bottom) {
+  const YGConfigRef config = YGConfigNew();
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  YGNodeStyleSetAlignItems(root, YGAlignCenter);
+  YGNodeStyleSetWidth(root, 200);
+  YGNodeStyleSetHeight(root, 200);
+
+  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetMarginAuto(root_child0, YGEdgeBottom);
+  YGNodeStyleSetWidth(root_child0, 50);
+  YGNodeStyleSetHeight(root_child0, 50);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  const YGNodeRef root_child1 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child1, 50);
+  YGNodeStyleSetHeight(root_child1, 50);
+  YGNodeInsertChild(root, root_child1, 1);
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(200, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(200, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(75, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(75, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(150, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child1));
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(200, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(200, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(75, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(75, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(150, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child1));
+
+  YGNodeFreeRecursive(root);
+
+  YGConfigFree(config);
+}
+
+TEST(YogaTest, margin_auto_top) {
+  const YGConfigRef config = YGConfigNew();
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  YGNodeStyleSetAlignItems(root, YGAlignCenter);
+  YGNodeStyleSetWidth(root, 200);
+  YGNodeStyleSetHeight(root, 200);
+
+  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetMarginAuto(root_child0, YGEdgeTop);
+  YGNodeStyleSetWidth(root_child0, 50);
+  YGNodeStyleSetHeight(root_child0, 50);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  const YGNodeRef root_child1 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child1, 50);
+  YGNodeStyleSetHeight(root_child1, 50);
+  YGNodeInsertChild(root, root_child1, 1);
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(200, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(200, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(75, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(75, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(150, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child1));
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(200, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(200, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(75, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(75, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(150, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child1));
+
+  YGNodeFreeRecursive(root);
+
+  YGConfigFree(config);
+}
+
+TEST(YogaTest, margin_auto_bottom_and_top) {
+  const YGConfigRef config = YGConfigNew();
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  YGNodeStyleSetAlignItems(root, YGAlignCenter);
+  YGNodeStyleSetWidth(root, 200);
+  YGNodeStyleSetHeight(root, 200);
+
+  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetMarginAuto(root_child0, YGEdgeTop);
+  YGNodeStyleSetMarginAuto(root_child0, YGEdgeBottom);
+  YGNodeStyleSetWidth(root_child0, 50);
+  YGNodeStyleSetHeight(root_child0, 50);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  const YGNodeRef root_child1 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child1, 50);
+  YGNodeStyleSetHeight(root_child1, 50);
+  YGNodeInsertChild(root, root_child1, 1);
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(200, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(200, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(75, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(75, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(150, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child1));
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(200, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(200, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(75, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(75, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(150, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child1));
+
+  YGNodeFreeRecursive(root);
+
+  YGConfigFree(config);
+}
+
+TEST(YogaTest, margin_auto_bottom_and_top_justify_center) {
+  const YGConfigRef config = YGConfigNew();
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  YGNodeStyleSetJustifyContent(root, YGJustifyCenter);
+  YGNodeStyleSetWidth(root, 200);
+  YGNodeStyleSetHeight(root, 200);
+
+  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetMarginAuto(root_child0, YGEdgeTop);
+  YGNodeStyleSetMarginAuto(root_child0, YGEdgeBottom);
+  YGNodeStyleSetWidth(root_child0, 50);
+  YGNodeStyleSetHeight(root_child0, 50);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  const YGNodeRef root_child1 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child1, 50);
+  YGNodeStyleSetHeight(root_child1, 50);
+  YGNodeInsertChild(root, root_child1, 1);
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(200, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(200, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(150, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child1));
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(200, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(200, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(150, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(150, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(150, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child1));
+
+  YGNodeFreeRecursive(root);
+
+  YGConfigFree(config);
+}
+
+TEST(YogaTest, margin_auto_mutiple_children_column) {
+  const YGConfigRef config = YGConfigNew();
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  YGNodeStyleSetAlignItems(root, YGAlignCenter);
+  YGNodeStyleSetWidth(root, 200);
+  YGNodeStyleSetHeight(root, 200);
+
+  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetMarginAuto(root_child0, YGEdgeTop);
+  YGNodeStyleSetWidth(root_child0, 50);
+  YGNodeStyleSetHeight(root_child0, 50);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  const YGNodeRef root_child1 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetMarginAuto(root_child1, YGEdgeTop);
+  YGNodeStyleSetWidth(root_child1, 50);
+  YGNodeStyleSetHeight(root_child1, 50);
+  YGNodeInsertChild(root, root_child1, 1);
+
+  const YGNodeRef root_child2 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child2, 50);
+  YGNodeStyleSetHeight(root_child2, 50);
+  YGNodeInsertChild(root, root_child2, 2);
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(200, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(200, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(75, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(25, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(75, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child1));
+
+  ASSERT_FLOAT_EQ(75, YGNodeLayoutGetLeft(root_child2));
+  ASSERT_FLOAT_EQ(150, YGNodeLayoutGetTop(root_child2));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child2));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child2));
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(200, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(200, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(75, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(25, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(75, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child1));
+
+  ASSERT_FLOAT_EQ(75, YGNodeLayoutGetLeft(root_child2));
+  ASSERT_FLOAT_EQ(150, YGNodeLayoutGetTop(root_child2));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child2));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child2));
+
+  YGNodeFreeRecursive(root);
+
+  YGConfigFree(config);
+}
+
+TEST(YogaTest, margin_auto_mutiple_children_row) {
+  const YGConfigRef config = YGConfigNew();
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexDirection(root, YGFlexDirectionRow);
+  YGNodeStyleSetAlignItems(root, YGAlignCenter);
+  YGNodeStyleSetWidth(root, 200);
+  YGNodeStyleSetHeight(root, 200);
+
+  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetMarginAuto(root_child0, YGEdgeRight);
+  YGNodeStyleSetWidth(root_child0, 50);
+  YGNodeStyleSetHeight(root_child0, 50);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  const YGNodeRef root_child1 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetMarginAuto(root_child1, YGEdgeRight);
+  YGNodeStyleSetWidth(root_child1, 50);
+  YGNodeStyleSetHeight(root_child1, 50);
+  YGNodeInsertChild(root, root_child1, 1);
+
+  const YGNodeRef root_child2 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child2, 50);
+  YGNodeStyleSetHeight(root_child2, 50);
+  YGNodeInsertChild(root, root_child2, 2);
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(200, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(200, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(75, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(75, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(75, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child1));
+
+  ASSERT_FLOAT_EQ(150, YGNodeLayoutGetLeft(root_child2));
+  ASSERT_FLOAT_EQ(75, YGNodeLayoutGetTop(root_child2));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child2));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child2));
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(200, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(200, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(125, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(75, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(75, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child1));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child2));
+  ASSERT_FLOAT_EQ(75, YGNodeLayoutGetTop(root_child2));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child2));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child2));
+
+  YGNodeFreeRecursive(root);
+
+  YGConfigFree(config);
+}
+
+TEST(YogaTest, margin_auto_left_and_right_column) {
+  const YGConfigRef config = YGConfigNew();
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexDirection(root, YGFlexDirectionRow);
+  YGNodeStyleSetAlignItems(root, YGAlignCenter);
+  YGNodeStyleSetWidth(root, 200);
+  YGNodeStyleSetHeight(root, 200);
+
+  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetMarginAuto(root_child0, YGEdgeLeft);
+  YGNodeStyleSetMarginAuto(root_child0, YGEdgeRight);
+  YGNodeStyleSetWidth(root_child0, 50);
+  YGNodeStyleSetHeight(root_child0, 50);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  const YGNodeRef root_child1 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child1, 50);
+  YGNodeStyleSetHeight(root_child1, 50);
+  YGNodeInsertChild(root, root_child1, 1);
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(200, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(200, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(75, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(150, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(75, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child1));
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(200, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(200, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(75, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(75, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child1));
+
+  YGNodeFreeRecursive(root);
+
+  YGConfigFree(config);
+}
+
+TEST(YogaTest, margin_auto_left_and_right) {
+  const YGConfigRef config = YGConfigNew();
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root, 200);
+  YGNodeStyleSetHeight(root, 200);
+
+  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetMarginAuto(root_child0, YGEdgeLeft);
+  YGNodeStyleSetMarginAuto(root_child0, YGEdgeRight);
+  YGNodeStyleSetWidth(root_child0, 50);
+  YGNodeStyleSetHeight(root_child0, 50);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  const YGNodeRef root_child1 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child1, 50);
+  YGNodeStyleSetHeight(root_child1, 50);
+  YGNodeInsertChild(root, root_child1, 1);
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(200, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(200, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(75, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child1));
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(200, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(200, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(75, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(150, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child1));
+
+  YGNodeFreeRecursive(root);
+
+  YGConfigFree(config);
+}
+
+TEST(YogaTest, margin_auto_start_and_end_column) {
+  const YGConfigRef config = YGConfigNew();
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexDirection(root, YGFlexDirectionRow);
+  YGNodeStyleSetAlignItems(root, YGAlignCenter);
+  YGNodeStyleSetWidth(root, 200);
+  YGNodeStyleSetHeight(root, 200);
+
+  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetMarginAuto(root_child0, YGEdgeStart);
+  YGNodeStyleSetMarginAuto(root_child0, YGEdgeEnd);
+  YGNodeStyleSetWidth(root_child0, 50);
+  YGNodeStyleSetHeight(root_child0, 50);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  const YGNodeRef root_child1 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child1, 50);
+  YGNodeStyleSetHeight(root_child1, 50);
+  YGNodeInsertChild(root, root_child1, 1);
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(200, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(200, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(75, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(150, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(75, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child1));
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(200, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(200, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(75, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(75, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child1));
+
+  YGNodeFreeRecursive(root);
+
+  YGConfigFree(config);
+}
+
+TEST(YogaTest, margin_auto_start_and_end) {
+  const YGConfigRef config = YGConfigNew();
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root, 200);
+  YGNodeStyleSetHeight(root, 200);
+
+  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetMarginAuto(root_child0, YGEdgeStart);
+  YGNodeStyleSetMarginAuto(root_child0, YGEdgeEnd);
+  YGNodeStyleSetWidth(root_child0, 50);
+  YGNodeStyleSetHeight(root_child0, 50);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  const YGNodeRef root_child1 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child1, 50);
+  YGNodeStyleSetHeight(root_child1, 50);
+  YGNodeInsertChild(root, root_child1, 1);
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(200, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(200, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(75, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child1));
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(200, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(200, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(75, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(150, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child1));
+
+  YGNodeFreeRecursive(root);
+
+  YGConfigFree(config);
+}
+
+TEST(YogaTest, margin_auto_left_and_right_column_and_center) {
+  const YGConfigRef config = YGConfigNew();
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  YGNodeStyleSetAlignItems(root, YGAlignCenter);
+  YGNodeStyleSetWidth(root, 200);
+  YGNodeStyleSetHeight(root, 200);
+
+  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetMarginAuto(root_child0, YGEdgeLeft);
+  YGNodeStyleSetMarginAuto(root_child0, YGEdgeRight);
+  YGNodeStyleSetWidth(root_child0, 50);
+  YGNodeStyleSetHeight(root_child0, 50);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  const YGNodeRef root_child1 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child1, 50);
+  YGNodeStyleSetHeight(root_child1, 50);
+  YGNodeInsertChild(root, root_child1, 1);
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(200, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(200, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(75, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(75, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child1));
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(200, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(200, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(75, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(75, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child1));
+
+  YGNodeFreeRecursive(root);
+
+  YGConfigFree(config);
+}
+
+TEST(YogaTest, margin_auto_left) {
+  const YGConfigRef config = YGConfigNew();
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  YGNodeStyleSetAlignItems(root, YGAlignCenter);
+  YGNodeStyleSetWidth(root, 200);
+  YGNodeStyleSetHeight(root, 200);
+
+  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetMarginAuto(root_child0, YGEdgeLeft);
+  YGNodeStyleSetWidth(root_child0, 50);
+  YGNodeStyleSetHeight(root_child0, 50);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  const YGNodeRef root_child1 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child1, 50);
+  YGNodeStyleSetHeight(root_child1, 50);
+  YGNodeInsertChild(root, root_child1, 1);
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(200, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(200, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(150, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(75, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child1));
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(200, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(200, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(150, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(75, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child1));
+
+  YGNodeFreeRecursive(root);
+
+  YGConfigFree(config);
+}
+
+TEST(YogaTest, margin_auto_right) {
+  const YGConfigRef config = YGConfigNew();
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  YGNodeStyleSetAlignItems(root, YGAlignCenter);
+  YGNodeStyleSetWidth(root, 200);
+  YGNodeStyleSetHeight(root, 200);
+
+  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetMarginAuto(root_child0, YGEdgeRight);
+  YGNodeStyleSetWidth(root_child0, 50);
+  YGNodeStyleSetHeight(root_child0, 50);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  const YGNodeRef root_child1 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child1, 50);
+  YGNodeStyleSetHeight(root_child1, 50);
+  YGNodeInsertChild(root, root_child1, 1);
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(200, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(200, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(75, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child1));
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(200, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(200, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(75, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child1));
+
+  YGNodeFreeRecursive(root);
+
+  YGConfigFree(config);
+}
+
+TEST(YogaTest, margin_auto_left_and_right_strech) {
+  const YGConfigRef config = YGConfigNew();
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexDirection(root, YGFlexDirectionRow);
+  YGNodeStyleSetWidth(root, 200);
+  YGNodeStyleSetHeight(root, 200);
+
+  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetMarginAuto(root_child0, YGEdgeLeft);
+  YGNodeStyleSetMarginAuto(root_child0, YGEdgeRight);
+  YGNodeStyleSetWidth(root_child0, 50);
+  YGNodeStyleSetHeight(root_child0, 50);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  const YGNodeRef root_child1 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child1, 50);
+  YGNodeStyleSetHeight(root_child1, 50);
+  YGNodeInsertChild(root, root_child1, 1);
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(200, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(200, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(150, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child1));
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(200, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(200, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child1));
+
+  YGNodeFreeRecursive(root);
+
+  YGConfigFree(config);
+}
+
+TEST(YogaTest, margin_auto_top_and_bottom_strech) {
+  const YGConfigRef config = YGConfigNew();
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root, 200);
+  YGNodeStyleSetHeight(root, 200);
+
+  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetMarginAuto(root_child0, YGEdgeTop);
+  YGNodeStyleSetMarginAuto(root_child0, YGEdgeBottom);
+  YGNodeStyleSetWidth(root_child0, 50);
+  YGNodeStyleSetHeight(root_child0, 50);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  const YGNodeRef root_child1 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child1, 50);
+  YGNodeStyleSetHeight(root_child1, 50);
+  YGNodeInsertChild(root, root_child1, 1);
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(200, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(200, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(150, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child1));
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(200, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(200, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(150, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(150, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(150, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child1));
+
+  YGNodeFreeRecursive(root);
+
+  YGConfigFree(config);
+}
+
+TEST(YogaTest, margin_should_not_be_part_of_max_height) {
+  const YGConfigRef config = YGConfigNew();
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root, 250);
+  YGNodeStyleSetHeight(root, 250);
+
+  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetMargin(root_child0, YGEdgeTop, 20);
+  YGNodeStyleSetWidth(root_child0, 100);
+  YGNodeStyleSetHeight(root_child0, 100);
+  YGNodeStyleSetMaxHeight(root_child0, 100);
+  YGNodeInsertChild(root, root_child0, 0);
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(250, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(250, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(20, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child0));
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(250, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(250, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(150, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(20, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child0));
+
+  YGNodeFreeRecursive(root);
+
+  YGConfigFree(config);
+}
+
+TEST(YogaTest, margin_should_not_be_part_of_max_width) {
+  const YGConfigRef config = YGConfigNew();
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root, 250);
+  YGNodeStyleSetHeight(root, 250);
+
+  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetMargin(root_child0, YGEdgeLeft, 20);
+  YGNodeStyleSetWidth(root_child0, 100);
+  YGNodeStyleSetMaxWidth(root_child0, 100);
+  YGNodeStyleSetHeight(root_child0, 100);
+  YGNodeInsertChild(root, root_child0, 0);
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(250, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(250, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(20, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child0));
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(250, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(250, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(150, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child0));
+
+  YGNodeFreeRecursive(root);
+
+  YGConfigFree(config);
+}
+
+TEST(YogaTest, margin_auto_left_right_child_bigger_than_parent) {
+  const YGConfigRef config = YGConfigNew();
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  YGNodeStyleSetJustifyContent(root, YGJustifyCenter);
+  YGNodeStyleSetWidth(root, 52);
+  YGNodeStyleSetHeight(root, 52);
+
+  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetMarginAuto(root_child0, YGEdgeLeft);
+  YGNodeStyleSetMarginAuto(root_child0, YGEdgeRight);
+  YGNodeStyleSetWidth(root_child0, 72);
+  YGNodeStyleSetHeight(root_child0, 72);
+  YGNodeInsertChild(root, root_child0, 0);
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(52, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(52, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(-10, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(72, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(72, YGNodeLayoutGetHeight(root_child0));
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(52, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(52, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(-20, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(-10, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(72, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(72, YGNodeLayoutGetHeight(root_child0));
+
+  YGNodeFreeRecursive(root);
+
+  YGConfigFree(config);
+}
+
+TEST(YogaTest, margin_auto_left_child_bigger_than_parent) {
+  const YGConfigRef config = YGConfigNew();
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  YGNodeStyleSetJustifyContent(root, YGJustifyCenter);
+  YGNodeStyleSetWidth(root, 52);
+  YGNodeStyleSetHeight(root, 52);
+
+  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetMarginAuto(root_child0, YGEdgeLeft);
+  YGNodeStyleSetWidth(root_child0, 72);
+  YGNodeStyleSetHeight(root_child0, 72);
+  YGNodeInsertChild(root, root_child0, 0);
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(52, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(52, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(-10, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(72, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(72, YGNodeLayoutGetHeight(root_child0));
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(52, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(52, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(-20, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(-10, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(72, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(72, YGNodeLayoutGetHeight(root_child0));
+
+  YGNodeFreeRecursive(root);
+
+  YGConfigFree(config);
+}
+
+TEST(YogaTest, margin_fix_left_auto_right_child_bigger_than_parent) {
+  const YGConfigRef config = YGConfigNew();
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  YGNodeStyleSetJustifyContent(root, YGJustifyCenter);
+  YGNodeStyleSetWidth(root, 52);
+  YGNodeStyleSetHeight(root, 52);
+
+  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetMargin(root_child0, YGEdgeLeft, 10);
+  YGNodeStyleSetMarginAuto(root_child0, YGEdgeRight);
+  YGNodeStyleSetWidth(root_child0, 72);
+  YGNodeStyleSetHeight(root_child0, 72);
+  YGNodeInsertChild(root, root_child0, 0);
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(52, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(52, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(-10, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(72, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(72, YGNodeLayoutGetHeight(root_child0));
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(52, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(52, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(-20, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(-10, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(72, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(72, YGNodeLayoutGetHeight(root_child0));
+
+  YGNodeFreeRecursive(root);
+
+  YGConfigFree(config);
+}
+
+TEST(YogaTest, margin_auto_left_fix_right_child_bigger_than_parent) {
+  const YGConfigRef config = YGConfigNew();
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  YGNodeStyleSetJustifyContent(root, YGJustifyCenter);
+  YGNodeStyleSetWidth(root, 52);
+  YGNodeStyleSetHeight(root, 52);
+
+  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetMarginAuto(root_child0, YGEdgeLeft);
+  YGNodeStyleSetMargin(root_child0, YGEdgeRight, 10);
+  YGNodeStyleSetWidth(root_child0, 72);
+  YGNodeStyleSetHeight(root_child0, 72);
+  YGNodeInsertChild(root, root_child0, 0);
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(52, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(52, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(-10, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(72, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(72, YGNodeLayoutGetHeight(root_child0));
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(52, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(52, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(-30, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(-10, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(72, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(72, YGNodeLayoutGetHeight(root_child0));
+
+  YGNodeFreeRecursive(root);
+
+  YGConfigFree(config);
+}
+
+TEST(YogaTest, margin_auto_top_stretching_child) {
+  const YGConfigRef config = YGConfigNew();
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  YGNodeStyleSetAlignItems(root, YGAlignCenter);
+  YGNodeStyleSetWidth(root, 200);
+  YGNodeStyleSetHeight(root, 200);
+
+  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexGrow(root_child0, 1);
+  YGNodeStyleSetFlexShrink(root_child0, 1);
+  YGNodeStyleSetFlexBasisPercent(root_child0, 0);
+  YGNodeStyleSetMarginAuto(root_child0, YGEdgeTop);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  const YGNodeRef root_child1 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child1, 50);
+  YGNodeStyleSetHeight(root_child1, 50);
+  YGNodeInsertChild(root, root_child1, 1);
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(200, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(200, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(150, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(75, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(150, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child1));
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(200, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(200, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(150, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(75, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(150, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child1));
+
+  YGNodeFreeRecursive(root);
+
+  YGConfigFree(config);
+}
+
+TEST(YogaTest, margin_auto_left_stretching_child) {
+  const YGConfigRef config = YGConfigNew();
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  YGNodeStyleSetAlignItems(root, YGAlignCenter);
+  YGNodeStyleSetWidth(root, 200);
+  YGNodeStyleSetHeight(root, 200);
+
+  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexGrow(root_child0, 1);
+  YGNodeStyleSetFlexShrink(root_child0, 1);
+  YGNodeStyleSetFlexBasisPercent(root_child0, 0);
+  YGNodeStyleSetMarginAuto(root_child0, YGEdgeLeft);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  const YGNodeRef root_child1 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child1, 50);
+  YGNodeStyleSetHeight(root_child1, 50);
+  YGNodeInsertChild(root, root_child1, 1);
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(200, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(200, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(200, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(150, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(75, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(150, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child1));
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(200, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(200, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(200, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(150, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(75, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(150, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child1));
+
+  YGNodeFreeRecursive(root);
+
+  YGConfigFree(config);
+}
diff --git a/automated-tests/src/dali-toolkit-third-party/yoga/YGMeasureCacheTest.cpp b/automated-tests/src/dali-toolkit-third-party/yoga/YGMeasureCacheTest.cpp
new file mode 100644 (file)
index 0000000..91f1891
--- /dev/null
@@ -0,0 +1,176 @@
+/**
+ * Copyright (c) 2014-present, Facebook, Inc.
+ *
+ * This source code is licensed under the MIT license found in the
+ * LICENSE file in the root directory of this source tree.
+ */
+
+#include <gtest/gtest.h>
+#include <yoga/YGNode.h>
+#include <yoga/Yoga.h>
+
+static YGSize _measureMax(YGNodeRef node,
+                          float width,
+                          YGMeasureMode widthMode,
+                          float height,
+                          YGMeasureMode heightMode) {
+  int* measureCount = (int*)node->getContext();
+  (*measureCount)++;
+
+  return YGSize{
+      .width = widthMode == YGMeasureModeUndefined ? 10 : width,
+      .height = heightMode == YGMeasureModeUndefined ? 10 : height,
+  };
+}
+
+static YGSize _measureMin(YGNodeRef node,
+                          float width,
+                          YGMeasureMode widthMode,
+                          float height,
+                          YGMeasureMode heightMode) {
+  int* measureCount = (int*)node->getContext();
+  *measureCount = *measureCount + 1;
+  return YGSize{
+      .width =
+          widthMode == YGMeasureModeUndefined || (widthMode == YGMeasureModeAtMost && width > 10)
+              ? 10
+              : width,
+      .height =
+          heightMode == YGMeasureModeUndefined || (heightMode == YGMeasureModeAtMost && height > 10)
+              ? 10
+              : height,
+  };
+}
+
+static YGSize _measure_84_49(YGNodeRef node,
+                             float width,
+                             YGMeasureMode widthMode,
+                             float height,
+                             YGMeasureMode heightMode) {
+  int* measureCount = (int*)node->getContext();
+  if (measureCount) {
+    (*measureCount)++;
+  }
+
+  return YGSize{
+      .width = 84.f, .height = 49.f,
+  };
+}
+
+TEST(YogaTest, measure_once_single_flexible_child) {
+  const YGNodeRef root = YGNodeNew();
+  YGNodeStyleSetFlexDirection(root, YGFlexDirectionRow);
+  YGNodeStyleSetAlignItems(root, YGAlignFlexStart);
+  YGNodeStyleSetWidth(root, 100);
+  YGNodeStyleSetHeight(root, 100);
+
+  const YGNodeRef root_child0 = YGNodeNew();
+  int measureCount = 0;
+  root_child0->setContext(&measureCount);
+  root_child0->setMeasureFunc(_measureMax);
+  YGNodeStyleSetFlexGrow(root_child0, 1);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_EQ(1, measureCount);
+
+  YGNodeFreeRecursive(root);
+}
+
+TEST(YogaTest, remeasure_with_same_exact_width_larger_than_needed_height) {
+  const YGNodeRef root = YGNodeNew();
+
+  const YGNodeRef root_child0 = YGNodeNew();
+  int measureCount = 0;
+  root_child0->setContext(&measureCount);
+  root_child0->setMeasureFunc(_measureMin);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  YGNodeCalculateLayout(root, 100, 100, YGDirectionLTR);
+  YGNodeCalculateLayout(root, 100, 50, YGDirectionLTR);
+
+  ASSERT_EQ(1, measureCount);
+
+  YGNodeFreeRecursive(root);
+}
+
+TEST(YogaTest, remeasure_with_same_atmost_width_larger_than_needed_height) {
+  const YGNodeRef root = YGNodeNew();
+  YGNodeStyleSetAlignItems(root, YGAlignFlexStart);
+
+  const YGNodeRef root_child0 = YGNodeNew();
+  int measureCount = 0;
+  root_child0->setContext(&measureCount);
+  root_child0->setMeasureFunc(_measureMin);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  YGNodeCalculateLayout(root, 100, 100, YGDirectionLTR);
+  YGNodeCalculateLayout(root, 100, 50, YGDirectionLTR);
+
+  ASSERT_EQ(1, measureCount);
+
+  YGNodeFreeRecursive(root);
+}
+
+TEST(YogaTest, remeasure_with_computed_width_larger_than_needed_height) {
+  const YGNodeRef root = YGNodeNew();
+  YGNodeStyleSetAlignItems(root, YGAlignFlexStart);
+
+  const YGNodeRef root_child0 = YGNodeNew();
+  int measureCount = 0;
+  root_child0->setContext(&measureCount);
+  root_child0->setMeasureFunc(_measureMin);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  YGNodeCalculateLayout(root, 100, 100, YGDirectionLTR);
+  YGNodeStyleSetAlignItems(root, YGAlignStretch);
+  YGNodeCalculateLayout(root, 10, 50, YGDirectionLTR);
+
+  ASSERT_EQ(1, measureCount);
+
+  YGNodeFreeRecursive(root);
+}
+
+TEST(YogaTest, remeasure_with_atmost_computed_width_undefined_height) {
+  const YGNodeRef root = YGNodeNew();
+  YGNodeStyleSetAlignItems(root, YGAlignFlexStart);
+
+  const YGNodeRef root_child0 = YGNodeNew();
+  int measureCount = 0;
+  root_child0->setContext(&measureCount);
+  root_child0->setMeasureFunc(_measureMin);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  YGNodeCalculateLayout(root, 100, YGUndefined, YGDirectionLTR);
+  YGNodeCalculateLayout(root, 10, YGUndefined, YGDirectionLTR);
+
+  ASSERT_EQ(1, measureCount);
+
+  YGNodeFreeRecursive(root);
+}
+
+TEST(YogaTest, remeasure_with_already_measured_value_smaller_but_still_float_equal) {
+  int measureCount = 0;
+
+  const YGNodeRef root = YGNodeNew();
+  YGNodeStyleSetWidth(root, 288.f);
+  YGNodeStyleSetHeight(root, 288.f);
+  YGNodeStyleSetFlexDirection(root, YGFlexDirectionRow);
+
+  const YGNodeRef root_child0 = YGNodeNew();
+  YGNodeStyleSetPadding(root_child0, YGEdgeAll, 2.88f);
+  YGNodeStyleSetFlexDirection(root_child0, YGFlexDirectionRow);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  const YGNodeRef root_child0_child0 = YGNodeNew();
+  root_child0_child0->setContext(&measureCount);
+  root_child0_child0->setMeasureFunc(_measure_84_49);
+  YGNodeInsertChild(root_child0, root_child0_child0, 0);
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  YGNodeFreeRecursive(root);
+
+  ASSERT_EQ(1, measureCount);
+}
diff --git a/automated-tests/src/dali-toolkit-third-party/yoga/YGMeasureModeTest.cpp b/automated-tests/src/dali-toolkit-third-party/yoga/YGMeasureModeTest.cpp
new file mode 100644 (file)
index 0000000..8e52894
--- /dev/null
@@ -0,0 +1,326 @@
+/**
+ * Copyright (c) 2014-present, Facebook, Inc.
+ *
+ * This source code is licensed under the MIT license found in the
+ * LICENSE file in the root directory of this source tree.
+ */
+
+#include <gtest/gtest.h>
+#include <yoga/YGNode.h>
+#include <yoga/Yoga.h>
+
+struct _MeasureConstraint {
+  float width;
+  YGMeasureMode widthMode;
+  float height;
+  YGMeasureMode heightMode;
+};
+
+struct _MeasureConstraintList {
+  uint32_t length;
+  struct _MeasureConstraint *constraints;
+};
+
+static YGSize _measure_for_mode_test(YGNodeRef node,
+                                                        float width,
+                                                        YGMeasureMode widthMode,
+                                                        float height,
+                                                        YGMeasureMode heightMode) {
+  struct _MeasureConstraintList* constraintList =
+      (struct _MeasureConstraintList*)node->getContext();
+  struct _MeasureConstraint *constraints = constraintList->constraints;
+  uint32_t currentIndex = constraintList->length;
+  (&constraints[currentIndex])->width = width;
+  (&constraints[currentIndex])->widthMode = widthMode;
+  (&constraints[currentIndex])->height = height;
+  (&constraints[currentIndex])->heightMode = heightMode;
+  constraintList->length = currentIndex + 1;
+
+  return YGSize{
+      .width = widthMode == YGMeasureModeUndefined ? 10 : width,
+      .height = heightMode == YGMeasureModeUndefined ? 10 : width,
+  };
+}
+
+TEST(YogaTest, exactly_measure_stretched_child_column) {
+  struct _MeasureConstraintList constraintList = _MeasureConstraintList{
+      .length = 0,
+      .constraints = (struct _MeasureConstraint *) malloc(10 * sizeof(struct _MeasureConstraint)),
+  };
+
+  const YGNodeRef root = YGNodeNew();
+  YGNodeStyleSetWidth(root, 100);
+  YGNodeStyleSetHeight(root, 100);
+
+  const YGNodeRef root_child0 = YGNodeNew();
+  //  root_child0->setContext(&constraintList);
+  root_child0->setContext(&constraintList);
+  root_child0->setMeasureFunc(_measure_for_mode_test);
+  //  root_child0->setMeasureFunc(_measure_for_mode_test);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_EQ(1, constraintList.length);
+
+  ASSERT_FLOAT_EQ(100, constraintList.constraints[0].width);
+  ASSERT_EQ(YGMeasureModeExactly, constraintList.constraints[0].widthMode);
+
+  free(constraintList.constraints);
+  YGNodeFreeRecursive(root);
+}
+
+TEST(YogaTest, exactly_measure_stretched_child_row) {
+  struct _MeasureConstraintList constraintList = _MeasureConstraintList{
+      .length = 0,
+      .constraints = (struct _MeasureConstraint *) malloc(10 * sizeof(struct _MeasureConstraint)),
+  };
+
+  const YGNodeRef root = YGNodeNew();
+  YGNodeStyleSetFlexDirection(root, YGFlexDirectionRow);
+  YGNodeStyleSetWidth(root, 100);
+  YGNodeStyleSetHeight(root, 100);
+
+  const YGNodeRef root_child0 = YGNodeNew();
+  //  root_child0->setContext(&constraintList);
+  root_child0->setContext(&constraintList);
+  root_child0->setMeasureFunc(_measure_for_mode_test);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_EQ(1, constraintList.length);
+
+  ASSERT_FLOAT_EQ(100, constraintList.constraints[0].height);
+  ASSERT_EQ(YGMeasureModeExactly, constraintList.constraints[0].heightMode);
+
+  free(constraintList.constraints);
+  YGNodeFreeRecursive(root);
+}
+
+TEST(YogaTest, at_most_main_axis_column) {
+  struct _MeasureConstraintList constraintList = _MeasureConstraintList{
+      .length = 0,
+      .constraints = (struct _MeasureConstraint *) malloc(10 * sizeof(struct _MeasureConstraint)),
+  };
+
+  const YGNodeRef root = YGNodeNew();
+  YGNodeStyleSetWidth(root, 100);
+  YGNodeStyleSetHeight(root, 100);
+
+  const YGNodeRef root_child0 = YGNodeNew();
+  root_child0->setContext(&constraintList);
+  root_child0->setMeasureFunc(_measure_for_mode_test);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_EQ(1, constraintList.length);
+
+  ASSERT_FLOAT_EQ(100, constraintList.constraints[0].height);
+  ASSERT_EQ(YGMeasureModeAtMost, constraintList.constraints[0].heightMode);
+
+  free(constraintList.constraints);
+  YGNodeFreeRecursive(root);
+}
+
+TEST(YogaTest, at_most_cross_axis_column) {
+  struct _MeasureConstraintList constraintList = _MeasureConstraintList{
+      .length = 0,
+      .constraints = (struct _MeasureConstraint *) malloc(10 * sizeof(struct _MeasureConstraint)),
+  };
+
+  const YGNodeRef root = YGNodeNew();
+  YGNodeStyleSetAlignItems(root, YGAlignFlexStart);
+  YGNodeStyleSetWidth(root, 100);
+  YGNodeStyleSetHeight(root, 100);
+
+  const YGNodeRef root_child0 = YGNodeNew();
+  root_child0->setContext(&constraintList);
+  root_child0->setMeasureFunc(_measure_for_mode_test);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_EQ(1, constraintList.length);
+
+  ASSERT_FLOAT_EQ(100, constraintList.constraints[0].width);
+  ASSERT_EQ(YGMeasureModeAtMost, constraintList.constraints[0].widthMode);
+
+  free(constraintList.constraints);
+  YGNodeFreeRecursive(root);
+}
+
+TEST(YogaTest, at_most_main_axis_row) {
+  struct _MeasureConstraintList constraintList = _MeasureConstraintList{
+      .length = 0,
+      .constraints = (struct _MeasureConstraint *) malloc(10 * sizeof(struct _MeasureConstraint)),
+  };
+
+  const YGNodeRef root = YGNodeNew();
+  YGNodeStyleSetFlexDirection(root, YGFlexDirectionRow);
+  YGNodeStyleSetWidth(root, 100);
+  YGNodeStyleSetHeight(root, 100);
+
+  const YGNodeRef root_child0 = YGNodeNew();
+  root_child0->setContext(&constraintList);
+  root_child0->setMeasureFunc(_measure_for_mode_test);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_EQ(1, constraintList.length);
+
+  ASSERT_FLOAT_EQ(100, constraintList.constraints[0].width);
+  ASSERT_EQ(YGMeasureModeAtMost, constraintList.constraints[0].widthMode);
+
+  free(constraintList.constraints);
+  YGNodeFreeRecursive(root);
+}
+
+TEST(YogaTest, at_most_cross_axis_row) {
+  struct _MeasureConstraintList constraintList = _MeasureConstraintList{
+      .length = 0,
+      .constraints = (struct _MeasureConstraint *) malloc(10 * sizeof(struct _MeasureConstraint)),
+  };
+
+  const YGNodeRef root = YGNodeNew();
+  YGNodeStyleSetFlexDirection(root, YGFlexDirectionRow);
+  YGNodeStyleSetAlignItems(root, YGAlignFlexStart);
+  YGNodeStyleSetWidth(root, 100);
+  YGNodeStyleSetHeight(root, 100);
+
+  const YGNodeRef root_child0 = YGNodeNew();
+  root_child0->setContext(&constraintList);
+  root_child0->setMeasureFunc(_measure_for_mode_test);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_EQ(1, constraintList.length);
+
+  ASSERT_FLOAT_EQ(100, constraintList.constraints[0].height);
+  ASSERT_EQ(YGMeasureModeAtMost, constraintList.constraints[0].heightMode);
+
+  free(constraintList.constraints);
+  YGNodeFreeRecursive(root);
+}
+
+TEST(YogaTest, flex_child) {
+  struct _MeasureConstraintList constraintList = _MeasureConstraintList{
+      .length = 0,
+      .constraints = (struct _MeasureConstraint *) malloc(10 * sizeof(struct _MeasureConstraint)),
+  };
+
+  const YGNodeRef root = YGNodeNew();
+  YGNodeStyleSetHeight(root, 100);
+
+  const YGNodeRef root_child0 = YGNodeNew();
+  YGNodeStyleSetFlexGrow(root_child0, 1);
+  root_child0->setContext(&constraintList);
+  root_child0->setMeasureFunc(_measure_for_mode_test);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_EQ(2, constraintList.length);
+
+  ASSERT_FLOAT_EQ(100, constraintList.constraints[0].height);
+  ASSERT_EQ(YGMeasureModeAtMost, constraintList.constraints[0].heightMode);
+
+  ASSERT_FLOAT_EQ(100, constraintList.constraints[1].height);
+  ASSERT_EQ(YGMeasureModeExactly, constraintList.constraints[1].heightMode);
+
+  free(constraintList.constraints);
+  YGNodeFreeRecursive(root);
+}
+
+TEST(YogaTest, flex_child_with_flex_basis) {
+  struct _MeasureConstraintList constraintList = _MeasureConstraintList{
+      .length = 0,
+      .constraints = (struct _MeasureConstraint *) malloc(10 * sizeof(struct _MeasureConstraint)),
+  };
+
+  const YGNodeRef root = YGNodeNew();
+  YGNodeStyleSetHeight(root, 100);
+
+  const YGNodeRef root_child0 = YGNodeNew();
+  YGNodeStyleSetFlexGrow(root_child0, 1);
+  YGNodeStyleSetFlexBasis(root_child0, 0);
+  root_child0->setContext(&constraintList);
+  root_child0->setMeasureFunc(_measure_for_mode_test);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_EQ(1, constraintList.length);
+
+  ASSERT_FLOAT_EQ(100, constraintList.constraints[0].height);
+  ASSERT_EQ(YGMeasureModeExactly, constraintList.constraints[0].heightMode);
+
+  free(constraintList.constraints);
+  YGNodeFreeRecursive(root);
+}
+
+TEST(YogaTest, overflow_scroll_column) {
+  struct _MeasureConstraintList constraintList = _MeasureConstraintList{
+      .length = 0,
+      .constraints = (struct _MeasureConstraint *) malloc(10 * sizeof(struct _MeasureConstraint)),
+  };
+
+  const YGNodeRef root = YGNodeNew();
+  YGNodeStyleSetAlignItems(root, YGAlignFlexStart);
+  YGNodeStyleSetOverflow(root, YGOverflowScroll);
+  YGNodeStyleSetHeight(root, 100);
+  YGNodeStyleSetWidth(root, 100);
+
+  const YGNodeRef root_child0 = YGNodeNew();
+  root_child0->setContext(&constraintList);
+  root_child0->setMeasureFunc(_measure_for_mode_test);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_EQ(1, constraintList.length);
+
+  ASSERT_FLOAT_EQ(100, constraintList.constraints[0].width);
+  ASSERT_EQ(YGMeasureModeAtMost, constraintList.constraints[0].widthMode);
+
+  ASSERT_TRUE(YGFloatIsUndefined(constraintList.constraints[0].height));
+  ASSERT_EQ(YGMeasureModeUndefined, constraintList.constraints[0].heightMode);
+
+  free(constraintList.constraints);
+  YGNodeFreeRecursive(root);
+}
+
+TEST(YogaTest, overflow_scroll_row) {
+  struct _MeasureConstraintList constraintList = _MeasureConstraintList{
+      .length = 0,
+      .constraints = (struct _MeasureConstraint *) malloc(10 * sizeof(struct _MeasureConstraint)),
+  };
+
+  const YGNodeRef root = YGNodeNew();
+  YGNodeStyleSetAlignItems(root, YGAlignFlexStart);
+  YGNodeStyleSetFlexDirection(root, YGFlexDirectionRow);
+  YGNodeStyleSetOverflow(root, YGOverflowScroll);
+  YGNodeStyleSetHeight(root, 100);
+  YGNodeStyleSetWidth(root, 100);
+
+  const YGNodeRef root_child0 = YGNodeNew();
+  root_child0->setContext(&constraintList);
+  root_child0->setMeasureFunc(_measure_for_mode_test);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_EQ(1, constraintList.length);
+
+  ASSERT_TRUE(YGFloatIsUndefined(constraintList.constraints[0].width));
+  ASSERT_EQ(YGMeasureModeUndefined, constraintList.constraints[0].widthMode);
+
+  ASSERT_FLOAT_EQ(100, constraintList.constraints[0].height);
+  ASSERT_EQ(YGMeasureModeAtMost, constraintList.constraints[0].heightMode);
+
+  free(constraintList.constraints);
+  YGNodeFreeRecursive(root);
+}
diff --git a/automated-tests/src/dali-toolkit-third-party/yoga/YGMeasureTest.cpp b/automated-tests/src/dali-toolkit-third-party/yoga/YGMeasureTest.cpp
new file mode 100644 (file)
index 0000000..aea2cd5
--- /dev/null
@@ -0,0 +1,689 @@
+/**
+ * Copyright (c) 2014-present, Facebook, Inc.
+ *
+ * This source code is licensed under the MIT license found in the
+ * LICENSE file in the root directory of this source tree.
+ */
+
+#include <gtest/gtest.h>
+#include <yoga/YGNode.h>
+#include <yoga/Yoga.h>
+
+static YGSize _measure(YGNodeRef node,
+                       float width,
+                       YGMeasureMode widthMode,
+                       float height,
+                       YGMeasureMode heightMode) {
+  int* measureCount = (int*)node->getContext();
+  if (measureCount) {
+    (*measureCount)++;
+  }
+
+  return YGSize{
+      .width = 10, .height = 10,
+  };
+}
+
+static YGSize _simulate_wrapping_text(YGNodeRef node,
+                                      float width,
+                                      YGMeasureMode widthMode,
+                                      float height,
+                                      YGMeasureMode heightMode) {
+  if (widthMode == YGMeasureModeUndefined || width >= 68) {
+    return YGSize{.width = 68, .height = 16};
+  }
+
+  return YGSize{
+      .width = 50, .height = 32,
+  };
+}
+
+static YGSize _measure_assert_negative(YGNodeRef node,
+                                       float width,
+                                       YGMeasureMode widthMode,
+                                       float height,
+                                       YGMeasureMode heightMode) {
+  EXPECT_GE(width, 0);
+  EXPECT_GE(height, 0);
+
+  return YGSize{
+    .width = 0, .height = 0,
+  };
+}
+
+TEST(YogaTest, dont_measure_single_grow_shrink_child) {
+  const YGNodeRef root = YGNodeNew();
+  YGNodeStyleSetWidth(root, 100);
+  YGNodeStyleSetHeight(root, 100);
+
+  int measureCount = 0;
+
+  const YGNodeRef root_child0 = YGNodeNew();
+  root_child0->setContext(&measureCount);
+  root_child0->setMeasureFunc(_measure);
+  YGNodeStyleSetFlexGrow(root_child0, 1);
+  YGNodeStyleSetFlexShrink(root_child0, 1);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_EQ(0, measureCount);
+
+  YGNodeFreeRecursive(root);
+}
+
+TEST(YogaTest, measure_absolute_child_with_no_constraints) {
+  const YGNodeRef root = YGNodeNew();
+
+  const YGNodeRef root_child0 = YGNodeNew();
+  YGNodeInsertChild(root, root_child0, 0);
+
+  int measureCount = 0;
+
+  const YGNodeRef root_child0_child0 = YGNodeNew();
+  YGNodeStyleSetPositionType(root_child0_child0, YGPositionTypeAbsolute);
+  root_child0_child0->setContext(&measureCount);
+  root_child0_child0->setMeasureFunc(_measure);
+  YGNodeInsertChild(root_child0, root_child0_child0, 0);
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_EQ(1, measureCount);
+
+  YGNodeFreeRecursive(root);
+}
+
+TEST(YogaTest, dont_measure_when_min_equals_max) {
+  const YGNodeRef root = YGNodeNew();
+  YGNodeStyleSetAlignItems(root, YGAlignFlexStart);
+  YGNodeStyleSetWidth(root, 100);
+  YGNodeStyleSetHeight(root, 100);
+
+  int measureCount = 0;
+
+  const YGNodeRef root_child0 = YGNodeNew();
+  root_child0->setContext(&measureCount);
+  root_child0->setMeasureFunc(_measure);
+  YGNodeStyleSetMinWidth(root_child0, 10);
+  YGNodeStyleSetMaxWidth(root_child0, 10);
+  YGNodeStyleSetMinHeight(root_child0, 10);
+  YGNodeStyleSetMaxHeight(root_child0, 10);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_EQ(0, measureCount);
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child0));
+
+  YGNodeFreeRecursive(root);
+}
+
+TEST(YogaTest, dont_measure_when_min_equals_max_percentages) {
+  const YGNodeRef root = YGNodeNew();
+  YGNodeStyleSetAlignItems(root, YGAlignFlexStart);
+  YGNodeStyleSetWidth(root, 100);
+  YGNodeStyleSetHeight(root, 100);
+
+  int measureCount = 0;
+
+  const YGNodeRef root_child0 = YGNodeNew();
+  root_child0->setContext(&measureCount);
+  root_child0->setMeasureFunc(_measure);
+  YGNodeStyleSetMinWidthPercent(root_child0, 10);
+  YGNodeStyleSetMaxWidthPercent(root_child0, 10);
+  YGNodeStyleSetMinHeightPercent(root_child0, 10);
+  YGNodeStyleSetMaxHeightPercent(root_child0, 10);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_EQ(0, measureCount);
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child0));
+
+  YGNodeFreeRecursive(root);
+}
+
+
+TEST(YogaTest, measure_nodes_with_margin_auto_and_stretch) {
+  const YGNodeRef root = YGNodeNew();
+  YGNodeStyleSetWidth(root, 500);
+  YGNodeStyleSetHeight(root, 500);
+
+  const YGNodeRef root_child0 = YGNodeNew();
+  root_child0->setMeasureFunc(_measure);
+  YGNodeStyleSetMarginAuto(root_child0, YGEdgeLeft);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  EXPECT_EQ(490, YGNodeLayoutGetLeft(root_child0));
+  EXPECT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  EXPECT_EQ(10, YGNodeLayoutGetWidth(root_child0));
+  EXPECT_EQ(10, YGNodeLayoutGetHeight(root_child0));
+
+  YGNodeFreeRecursive(root);
+}
+
+TEST(YogaTest, dont_measure_when_min_equals_max_mixed_width_percent) {
+  const YGNodeRef root = YGNodeNew();
+  YGNodeStyleSetAlignItems(root, YGAlignFlexStart);
+  YGNodeStyleSetWidth(root, 100);
+  YGNodeStyleSetHeight(root, 100);
+
+  int measureCount = 0;
+
+  const YGNodeRef root_child0 = YGNodeNew();
+  root_child0->setContext(&measureCount);
+  root_child0->setMeasureFunc(_measure);
+  YGNodeStyleSetMinWidthPercent(root_child0, 10);
+  YGNodeStyleSetMaxWidthPercent(root_child0, 10);
+  YGNodeStyleSetMinHeight(root_child0, 10);
+  YGNodeStyleSetMaxHeight(root_child0, 10);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_EQ(0, measureCount);
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child0));
+
+  YGNodeFreeRecursive(root);
+}
+
+TEST(YogaTest, dont_measure_when_min_equals_max_mixed_height_percent) {
+  const YGNodeRef root = YGNodeNew();
+  YGNodeStyleSetAlignItems(root, YGAlignFlexStart);
+  YGNodeStyleSetWidth(root, 100);
+  YGNodeStyleSetHeight(root, 100);
+
+  int measureCount = 0;
+
+  const YGNodeRef root_child0 = YGNodeNew();
+  root_child0->setContext(&measureCount);
+  root_child0->setMeasureFunc(_measure);
+  YGNodeStyleSetMinWidth(root_child0, 10);
+  YGNodeStyleSetMaxWidth(root_child0, 10);
+  YGNodeStyleSetMinHeightPercent(root_child0, 10);
+  YGNodeStyleSetMaxHeightPercent(root_child0, 10);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_EQ(0, measureCount);
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child0));
+
+  YGNodeFreeRecursive(root);
+}
+
+TEST(YogaTest, measure_enough_size_should_be_in_single_line) {
+  const YGNodeRef root = YGNodeNew();
+  YGNodeStyleSetWidth(root, 100);
+
+  const YGNodeRef root_child0 = YGNodeNew();
+  YGNodeStyleSetAlignSelf(root_child0, YGAlignFlexStart);
+  root_child0->setMeasureFunc(_simulate_wrapping_text);
+
+  YGNodeInsertChild(root, root_child0, 0);
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(68, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(16, YGNodeLayoutGetHeight(root_child0));
+
+  YGNodeFreeRecursive(root);
+}
+
+TEST(YogaTest, measure_not_enough_size_should_wrap) {
+  const YGNodeRef root = YGNodeNew();
+  YGNodeStyleSetWidth(root, 55);
+
+  const YGNodeRef root_child0 = YGNodeNew();
+  YGNodeStyleSetAlignSelf(root_child0, YGAlignFlexStart);
+  //  YGNodeSetMeasureFunc(root_child0, _simulate_wrapping_text);
+  root_child0->setMeasureFunc(_simulate_wrapping_text);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(32, YGNodeLayoutGetHeight(root_child0));
+
+  YGNodeFreeRecursive(root);
+}
+
+TEST(YogaTest, measure_zero_space_should_grow) {
+  const YGNodeRef root = YGNodeNew();
+  YGNodeStyleSetHeight(root, 200);
+  YGNodeStyleSetFlexDirection(root, YGFlexDirectionColumn);
+  YGNodeStyleSetFlexGrow(root, 0);
+
+  int measureCount = 0;
+
+  const YGNodeRef root_child0 = YGNodeNew();
+  YGNodeStyleSetFlexDirection(root_child0, YGFlexDirectionColumn);
+  YGNodeStyleSetPadding(root_child0, YGEdgeAll, 100);
+  root_child0->setContext(&measureCount);
+  root_child0->setMeasureFunc(_measure);
+
+  YGNodeInsertChild(root, root_child0, 0);
+
+  YGNodeCalculateLayout(root, 282, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(282, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+
+  YGNodeFreeRecursive(root);
+}
+
+TEST(YogaTest, measure_flex_direction_row_and_padding) {
+  const YGConfigRef config = YGConfigNew();
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexDirection(root, YGFlexDirectionRow);
+  YGNodeStyleSetPadding(root, YGEdgeLeft, 25);
+  YGNodeStyleSetPadding(root, YGEdgeTop, 25);
+  YGNodeStyleSetPadding(root, YGEdgeRight, 25);
+  YGNodeStyleSetPadding(root, YGEdgeBottom, 25);
+  YGNodeStyleSetWidth(root, 50);
+  YGNodeStyleSetHeight(root, 50);
+
+  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+  root_child0->setMeasureFunc(_simulate_wrapping_text);
+  //  YGNodeSetMeasureFunc(root_child0, _simulate_wrapping_text);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  const YGNodeRef root_child1 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child1, 5);
+  YGNodeStyleSetHeight(root_child1, 5);
+  YGNodeInsertChild(root, root_child1, 1);
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(25, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(25, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(75, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(25, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(5, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(5, YGNodeLayoutGetHeight(root_child1));
+
+  YGNodeFreeRecursive(root);
+
+  YGConfigFree(config);
+}
+
+TEST(YogaTest, measure_flex_direction_column_and_padding) {
+  const YGConfigRef config = YGConfigNew();
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  YGNodeStyleSetMargin(root, YGEdgeTop, 20);
+  YGNodeStyleSetPadding(root, YGEdgeAll, 25);
+  YGNodeStyleSetWidth(root, 50);
+  YGNodeStyleSetHeight(root, 50);
+
+  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+  root_child0->setMeasureFunc(_simulate_wrapping_text);
+  //  YGNodeSetMeasureFunc(root_child0, _simulate_wrapping_text);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  const YGNodeRef root_child1 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child1, 5);
+  YGNodeStyleSetHeight(root_child1, 5);
+  YGNodeInsertChild(root, root_child1, 1);
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(20, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(25, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(25, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(32, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(25, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(57, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(5, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(5, YGNodeLayoutGetHeight(root_child1));
+
+  YGNodeFreeRecursive(root);
+
+  YGConfigFree(config);
+}
+
+TEST(YogaTest, measure_flex_direction_row_no_padding) {
+  const YGConfigRef config = YGConfigNew();
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexDirection(root, YGFlexDirectionRow);
+  YGNodeStyleSetMargin(root, YGEdgeTop, 20);
+  YGNodeStyleSetWidth(root, 50);
+  YGNodeStyleSetHeight(root, 50);
+
+  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+  //  YGNodeSetMeasureFunc(root_child0, _simulate_wrapping_text);
+  root_child0->setMeasureFunc(_simulate_wrapping_text);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  const YGNodeRef root_child1 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child1, 5);
+  YGNodeStyleSetHeight(root_child1, 5);
+  YGNodeInsertChild(root, root_child1, 1);
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(20, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(5, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(5, YGNodeLayoutGetHeight(root_child1));
+
+  YGNodeFreeRecursive(root);
+
+  YGConfigFree(config);
+}
+
+TEST(YogaTest, measure_flex_direction_row_no_padding_align_items_flexstart) {
+  const YGConfigRef config = YGConfigNew();
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexDirection(root, YGFlexDirectionRow);
+  YGNodeStyleSetMargin(root, YGEdgeTop, 20);
+  YGNodeStyleSetWidth(root, 50);
+  YGNodeStyleSetHeight(root, 50);
+  YGNodeStyleSetAlignItems(root, YGAlignFlexStart);
+
+  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+  root_child0->setMeasureFunc(_simulate_wrapping_text);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  const YGNodeRef root_child1 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child1, 5);
+  YGNodeStyleSetHeight(root_child1, 5);
+  YGNodeInsertChild(root, root_child1, 1);
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(20, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(32, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(5, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(5, YGNodeLayoutGetHeight(root_child1));
+
+  YGNodeFreeRecursive(root);
+
+  YGConfigFree(config);
+}
+
+TEST(YogaTest, measure_with_fixed_size) {
+  const YGConfigRef config = YGConfigNew();
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  YGNodeStyleSetMargin(root, YGEdgeTop, 20);
+  YGNodeStyleSetPadding(root, YGEdgeAll, 25);
+  YGNodeStyleSetWidth(root, 50);
+  YGNodeStyleSetHeight(root, 50);
+
+  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+  root_child0->setMeasureFunc(_simulate_wrapping_text);
+  YGNodeStyleSetWidth(root_child0, 10);
+  YGNodeStyleSetHeight(root_child0, 10);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  const YGNodeRef root_child1 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child1, 5);
+  YGNodeStyleSetHeight(root_child1, 5);
+  YGNodeInsertChild(root, root_child1, 1);
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(20, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(25, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(25, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(25, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(35, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(5, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(5, YGNodeLayoutGetHeight(root_child1));
+
+  YGNodeFreeRecursive(root);
+
+  YGConfigFree(config);
+}
+
+TEST(YogaTest, measure_with_flex_shrink) {
+  const YGConfigRef config = YGConfigNew();
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  YGNodeStyleSetMargin(root, YGEdgeTop, 20);
+  YGNodeStyleSetPadding(root, YGEdgeAll, 25);
+  YGNodeStyleSetWidth(root, 50);
+  YGNodeStyleSetHeight(root, 50);
+
+  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+  root_child0->setMeasureFunc(_simulate_wrapping_text);
+  YGNodeStyleSetFlexShrink(root_child0, 1);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  const YGNodeRef root_child1 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child1, 5);
+  YGNodeStyleSetHeight(root_child1, 5);
+  YGNodeInsertChild(root, root_child1, 1);
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(20, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(25, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(25, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(25, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(25, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(5, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(5, YGNodeLayoutGetHeight(root_child1));
+
+  YGNodeFreeRecursive(root);
+
+  YGConfigFree(config);
+}
+
+TEST(YogaTest, measure_no_padding) {
+  const YGConfigRef config = YGConfigNew();
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  YGNodeStyleSetMargin(root, YGEdgeTop, 20);
+  YGNodeStyleSetWidth(root, 50);
+  YGNodeStyleSetHeight(root, 50);
+
+  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+  root_child0->setMeasureFunc(_simulate_wrapping_text);
+  YGNodeStyleSetFlexShrink(root_child0, 1);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  const YGNodeRef root_child1 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child1, 5);
+  YGNodeStyleSetHeight(root_child1, 5);
+  YGNodeInsertChild(root, root_child1, 1);
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(20, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(32, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(32, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(5, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(5, YGNodeLayoutGetHeight(root_child1));
+
+  YGNodeFreeRecursive(root);
+
+  YGConfigFree(config);
+}
+
+#if GTEST_HAS_DEATH_TEST
+TEST(YogaDeathTest, cannot_add_child_to_node_with_measure_func) {
+  const YGNodeRef root = YGNodeNew();
+  root->setMeasureFunc(_measure);
+
+  const YGNodeRef root_child0 = YGNodeNew();
+  ASSERT_DEATH(YGNodeInsertChild(root, root_child0, 0), "Cannot add child.*");
+  YGNodeFree(root_child0);
+  YGNodeFreeRecursive(root);
+}
+
+TEST(YogaDeathTest, cannot_add_nonnull_measure_func_to_non_leaf_node) {
+  const YGNodeRef root = YGNodeNew();
+  const YGNodeRef root_child0 = YGNodeNew();
+  YGNodeInsertChild(root, root_child0, 0);
+  ASSERT_DEATH(root->setMeasureFunc(_measure), "Cannot set measure function.*");
+  YGNodeFreeRecursive(root);
+}
+
+#endif
+
+TEST(YogaTest, can_nullify_measure_func_on_any_node) {
+  const YGNodeRef root = YGNodeNew();
+  YGNodeInsertChild(root, YGNodeNew(), 0);
+  root->setMeasureFunc(nullptr);
+  ASSERT_TRUE(root->getMeasure() == NULL);
+  YGNodeFreeRecursive(root);
+}
+
+TEST(YogaTest, cant_call_negative_measure) {
+  const YGConfigRef config = YGConfigNew();
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexDirection(root, YGFlexDirectionColumn);
+  YGNodeStyleSetWidth(root, 50);
+  YGNodeStyleSetHeight(root, 10);
+
+  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+  root_child0->setMeasureFunc(_measure_assert_negative);
+  YGNodeStyleSetMargin(root_child0, YGEdgeTop, 20);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  YGNodeFreeRecursive(root);
+  YGConfigFree(config);
+}
+
+TEST(YogaTest, cant_call_negative_measure_horizontal) {
+  const YGConfigRef config = YGConfigNew();
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexDirection(root, YGFlexDirectionRow);
+  YGNodeStyleSetWidth(root, 10);
+  YGNodeStyleSetHeight(root, 20);
+
+  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+  root_child0->setMeasureFunc(_measure_assert_negative);
+  YGNodeStyleSetMargin(root_child0, YGEdgeStart, 20);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  YGNodeFreeRecursive(root);
+  YGConfigFree(config);
+}
+
+static YGSize _measure_90_10(YGNodeRef node,
+  float width,
+  YGMeasureMode widthMode,
+  float height,
+  YGMeasureMode heightMode) {
+
+  return YGSize{
+    .width = 90, .height = 10,
+  };
+}
+
+TEST(YogaTest, percent_with_text_node) {
+  const YGConfigRef config = YGConfigNew();
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexDirection(root, YGFlexDirectionRow);
+  YGNodeStyleSetJustifyContent(root, YGJustifySpaceBetween);
+  YGNodeStyleSetAlignItems(root, YGAlignCenter);
+  YGNodeStyleSetWidth(root, 100);
+  YGNodeStyleSetHeight(root, 80);
+
+  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  const YGNodeRef root_child1 = YGNodeNewWithConfig(config);
+  root_child1->setMeasureFunc(_measure_90_10);
+  YGNodeStyleSetMaxWidthPercent(root_child1, 50);
+  YGNodeStyleSetPaddingPercent(root_child1, YGEdgeTop, 50);
+  YGNodeInsertChild(root, root_child1, 1);
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(80, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(40, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(15, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child1));
+
+  YGNodeFreeRecursive(root);
+
+  YGConfigFree(config);
+}
diff --git a/automated-tests/src/dali-toolkit-third-party/yoga/YGMinMaxDimensionTest.cpp b/automated-tests/src/dali-toolkit-third-party/yoga/YGMinMaxDimensionTest.cpp
new file mode 100644 (file)
index 0000000..515bdfd
--- /dev/null
@@ -0,0 +1,1297 @@
+/**
+ * Copyright (c) 2014-present, Facebook, Inc.
+ *
+ * This source code is licensed under the MIT license found in the
+ * LICENSE file in the root directory of this source tree.
+ */
+
+// @Generated by gentest/gentest.rb from gentest/fixtures/YGMinMaxDimensionTest.html
+
+#include <gtest/gtest.h>
+#include <yoga/Yoga.h>
+
+TEST(YogaTest, max_width) {
+  const YGConfigRef config = YGConfigNew();
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root, 100);
+  YGNodeStyleSetHeight(root, 100);
+
+  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetMaxWidth(root_child0, 50);
+  YGNodeStyleSetHeight(root_child0, 10);
+  YGNodeInsertChild(root, root_child0, 0);
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child0));
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child0));
+
+  YGNodeFreeRecursive(root);
+
+  YGConfigFree(config);
+}
+
+TEST(YogaTest, max_height) {
+  const YGConfigRef config = YGConfigNew();
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexDirection(root, YGFlexDirectionRow);
+  YGNodeStyleSetWidth(root, 100);
+  YGNodeStyleSetHeight(root, 100);
+
+  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child0, 10);
+  YGNodeStyleSetMaxHeight(root_child0, 50);
+  YGNodeInsertChild(root, root_child0, 0);
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child0));
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(90, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child0));
+
+  YGNodeFreeRecursive(root);
+
+  YGConfigFree(config);
+}
+
+TEST(YogaTest, min_height) {
+  const YGConfigRef config = YGConfigNew();
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root, 100);
+  YGNodeStyleSetHeight(root, 100);
+
+  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexGrow(root_child0, 1);
+  YGNodeStyleSetMinHeight(root_child0, 60);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  const YGNodeRef root_child1 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexGrow(root_child1, 1);
+  YGNodeInsertChild(root, root_child1, 1);
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(80, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(80, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(20, YGNodeLayoutGetHeight(root_child1));
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(80, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(80, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(20, YGNodeLayoutGetHeight(root_child1));
+
+  YGNodeFreeRecursive(root);
+
+  YGConfigFree(config);
+}
+
+TEST(YogaTest, min_width) {
+  const YGConfigRef config = YGConfigNew();
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexDirection(root, YGFlexDirectionRow);
+  YGNodeStyleSetWidth(root, 100);
+  YGNodeStyleSetHeight(root, 100);
+
+  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexGrow(root_child0, 1);
+  YGNodeStyleSetMinWidth(root_child0, 60);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  const YGNodeRef root_child1 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexGrow(root_child1, 1);
+  YGNodeInsertChild(root, root_child1, 1);
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(80, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(80, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(20, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child1));
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(20, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(80, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(20, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child1));
+
+  YGNodeFreeRecursive(root);
+
+  YGConfigFree(config);
+}
+
+TEST(YogaTest, justify_content_min_max) {
+  const YGConfigRef config = YGConfigNew();
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  YGNodeStyleSetJustifyContent(root, YGJustifyCenter);
+  YGNodeStyleSetWidth(root, 100);
+  YGNodeStyleSetMinHeight(root, 100);
+  YGNodeStyleSetMaxHeight(root, 200);
+
+  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child0, 60);
+  YGNodeStyleSetHeight(root_child0, 60);
+  YGNodeInsertChild(root, root_child0, 0);
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(20, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(60, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(60, YGNodeLayoutGetHeight(root_child0));
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(40, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(20, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(60, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(60, YGNodeLayoutGetHeight(root_child0));
+
+  YGNodeFreeRecursive(root);
+
+  YGConfigFree(config);
+}
+
+TEST(YogaTest, align_items_min_max) {
+  const YGConfigRef config = YGConfigNew();
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  YGNodeStyleSetAlignItems(root, YGAlignCenter);
+  YGNodeStyleSetMinWidth(root, 100);
+  YGNodeStyleSetMaxWidth(root, 200);
+  YGNodeStyleSetHeight(root, 100);
+
+  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child0, 60);
+  YGNodeStyleSetHeight(root_child0, 60);
+  YGNodeInsertChild(root, root_child0, 0);
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(20, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(60, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(60, YGNodeLayoutGetHeight(root_child0));
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(20, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(60, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(60, YGNodeLayoutGetHeight(root_child0));
+
+  YGNodeFreeRecursive(root);
+
+  YGConfigFree(config);
+}
+
+TEST(YogaTest, justify_content_overflow_min_max) {
+  const YGConfigRef config = YGConfigNew();
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  YGNodeStyleSetJustifyContent(root, YGJustifyCenter);
+  YGNodeStyleSetMinHeight(root, 100);
+  YGNodeStyleSetMaxHeight(root, 110);
+
+  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child0, 50);
+  YGNodeStyleSetHeight(root_child0, 50);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  const YGNodeRef root_child1 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child1, 50);
+  YGNodeStyleSetHeight(root_child1, 50);
+  YGNodeInsertChild(root, root_child1, 1);
+
+  const YGNodeRef root_child2 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child2, 50);
+  YGNodeStyleSetHeight(root_child2, 50);
+  YGNodeInsertChild(root, root_child2, 2);
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(110, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(-20, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(30, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child1));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child2));
+  ASSERT_FLOAT_EQ(80, YGNodeLayoutGetTop(root_child2));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child2));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child2));
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(110, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(-20, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(30, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child1));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child2));
+  ASSERT_FLOAT_EQ(80, YGNodeLayoutGetTop(root_child2));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child2));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child2));
+
+  YGNodeFreeRecursive(root);
+
+  YGConfigFree(config);
+}
+
+TEST(YogaTest, flex_grow_to_min) {
+  const YGConfigRef config = YGConfigNew();
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root, 100);
+  YGNodeStyleSetMinHeight(root, 100);
+  YGNodeStyleSetMaxHeight(root, 500);
+
+  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexGrow(root_child0, 1);
+  YGNodeStyleSetFlexShrink(root_child0, 1);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  const YGNodeRef root_child1 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetHeight(root_child1, 50);
+  YGNodeInsertChild(root, root_child1, 1);
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child1));
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child1));
+
+  YGNodeFreeRecursive(root);
+
+  YGConfigFree(config);
+}
+
+TEST(YogaTest, flex_grow_in_at_most_container) {
+  const YGConfigRef config = YGConfigNew();
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexDirection(root, YGFlexDirectionRow);
+  YGNodeStyleSetAlignItems(root, YGAlignFlexStart);
+  YGNodeStyleSetWidth(root, 100);
+  YGNodeStyleSetHeight(root, 100);
+
+  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexDirection(root_child0, YGFlexDirectionRow);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  const YGNodeRef root_child0_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexGrow(root_child0_child0, 1);
+  YGNodeStyleSetFlexBasis(root_child0_child0, 0);
+  YGNodeInsertChild(root_child0, root_child0_child0, 0);
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetWidth(root_child0_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetHeight(root_child0_child0));
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetWidth(root_child0_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetHeight(root_child0_child0));
+
+  YGNodeFreeRecursive(root);
+
+  YGConfigFree(config);
+}
+
+TEST(YogaTest, flex_grow_child) {
+  const YGConfigRef config = YGConfigNew();
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexDirection(root, YGFlexDirectionRow);
+
+  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexGrow(root_child0, 1);
+  YGNodeStyleSetFlexBasis(root_child0, 0);
+  YGNodeStyleSetHeight(root_child0, 100);
+  YGNodeInsertChild(root, root_child0, 0);
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child0));
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child0));
+
+  YGNodeFreeRecursive(root);
+
+  YGConfigFree(config);
+}
+
+TEST(YogaTest, flex_grow_within_constrained_min_max_column) {
+  const YGConfigRef config = YGConfigNew();
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  YGNodeStyleSetMinHeight(root, 100);
+  YGNodeStyleSetMaxHeight(root, 200);
+
+  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexGrow(root_child0, 1);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  const YGNodeRef root_child1 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetHeight(root_child1, 50);
+  YGNodeInsertChild(root, root_child1, 1);
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child1));
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child1));
+
+  YGNodeFreeRecursive(root);
+
+  YGConfigFree(config);
+}
+
+TEST(YogaTest, flex_grow_within_max_width) {
+  const YGConfigRef config = YGConfigNew();
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root, 200);
+  YGNodeStyleSetHeight(root, 100);
+
+  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexDirection(root_child0, YGFlexDirectionRow);
+  YGNodeStyleSetMaxWidth(root_child0, 100);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  const YGNodeRef root_child0_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexGrow(root_child0_child0, 1);
+  YGNodeStyleSetHeight(root_child0_child0, 20);
+  YGNodeInsertChild(root_child0, root_child0_child0, 0);
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(200, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(20, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0_child0));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child0_child0));
+  ASSERT_FLOAT_EQ(20, YGNodeLayoutGetHeight(root_child0_child0));
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(200, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(20, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0_child0));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child0_child0));
+  ASSERT_FLOAT_EQ(20, YGNodeLayoutGetHeight(root_child0_child0));
+
+  YGNodeFreeRecursive(root);
+
+  YGConfigFree(config);
+}
+
+TEST(YogaTest, flex_grow_within_constrained_max_width) {
+  const YGConfigRef config = YGConfigNew();
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root, 200);
+  YGNodeStyleSetHeight(root, 100);
+
+  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexDirection(root_child0, YGFlexDirectionRow);
+  YGNodeStyleSetMaxWidth(root_child0, 300);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  const YGNodeRef root_child0_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexGrow(root_child0_child0, 1);
+  YGNodeStyleSetHeight(root_child0_child0, 20);
+  YGNodeInsertChild(root_child0, root_child0_child0, 0);
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(200, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(200, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(20, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0_child0));
+  ASSERT_FLOAT_EQ(200, YGNodeLayoutGetWidth(root_child0_child0));
+  ASSERT_FLOAT_EQ(20, YGNodeLayoutGetHeight(root_child0_child0));
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(200, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(200, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(20, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0_child0));
+  ASSERT_FLOAT_EQ(200, YGNodeLayoutGetWidth(root_child0_child0));
+  ASSERT_FLOAT_EQ(20, YGNodeLayoutGetHeight(root_child0_child0));
+
+  YGNodeFreeRecursive(root);
+
+  YGConfigFree(config);
+}
+
+TEST(YogaTest, flex_root_ignored) {
+  const YGConfigRef config = YGConfigNew();
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexGrow(root, 1);
+  YGNodeStyleSetWidth(root, 100);
+  YGNodeStyleSetMinHeight(root, 100);
+  YGNodeStyleSetMaxHeight(root, 500);
+
+  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexGrow(root_child0, 1);
+  YGNodeStyleSetFlexBasis(root_child0, 200);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  const YGNodeRef root_child1 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetHeight(root_child1, 100);
+  YGNodeInsertChild(root, root_child1, 1);
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(300, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(200, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(200, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child1));
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(300, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(200, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(200, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child1));
+
+  YGNodeFreeRecursive(root);
+
+  YGConfigFree(config);
+}
+
+TEST(YogaTest, flex_grow_root_minimized) {
+  const YGConfigRef config = YGConfigNew();
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root, 100);
+  YGNodeStyleSetMinHeight(root, 100);
+  YGNodeStyleSetMaxHeight(root, 500);
+
+  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexGrow(root_child0, 1);
+  YGNodeStyleSetMinHeight(root_child0, 100);
+  YGNodeStyleSetMaxHeight(root_child0, 500);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  const YGNodeRef root_child0_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexGrow(root_child0_child0, 1);
+  YGNodeStyleSetFlexBasis(root_child0_child0, 200);
+  YGNodeInsertChild(root_child0, root_child0_child0, 0);
+
+  const YGNodeRef root_child0_child1 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetHeight(root_child0_child1, 100);
+  YGNodeInsertChild(root_child0, root_child0_child1, 1);
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(300, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(300, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0_child0));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child0_child0));
+  ASSERT_FLOAT_EQ(200, YGNodeLayoutGetHeight(root_child0_child0));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0_child1));
+  ASSERT_FLOAT_EQ(200, YGNodeLayoutGetTop(root_child0_child1));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child0_child1));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child0_child1));
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(300, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(300, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0_child0));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child0_child0));
+  ASSERT_FLOAT_EQ(200, YGNodeLayoutGetHeight(root_child0_child0));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0_child1));
+  ASSERT_FLOAT_EQ(200, YGNodeLayoutGetTop(root_child0_child1));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child0_child1));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child0_child1));
+
+  YGNodeFreeRecursive(root);
+
+  YGConfigFree(config);
+}
+
+TEST(YogaTest, flex_grow_height_maximized) {
+  const YGConfigRef config = YGConfigNew();
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root, 100);
+  YGNodeStyleSetHeight(root, 500);
+
+  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexGrow(root_child0, 1);
+  YGNodeStyleSetMinHeight(root_child0, 100);
+  YGNodeStyleSetMaxHeight(root_child0, 500);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  const YGNodeRef root_child0_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexGrow(root_child0_child0, 1);
+  YGNodeStyleSetFlexBasis(root_child0_child0, 200);
+  YGNodeInsertChild(root_child0, root_child0_child0, 0);
+
+  const YGNodeRef root_child0_child1 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetHeight(root_child0_child1, 100);
+  YGNodeInsertChild(root_child0, root_child0_child1, 1);
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(500, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(500, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0_child0));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child0_child0));
+  ASSERT_FLOAT_EQ(400, YGNodeLayoutGetHeight(root_child0_child0));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0_child1));
+  ASSERT_FLOAT_EQ(400, YGNodeLayoutGetTop(root_child0_child1));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child0_child1));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child0_child1));
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(500, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(500, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0_child0));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child0_child0));
+  ASSERT_FLOAT_EQ(400, YGNodeLayoutGetHeight(root_child0_child0));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0_child1));
+  ASSERT_FLOAT_EQ(400, YGNodeLayoutGetTop(root_child0_child1));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child0_child1));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child0_child1));
+
+  YGNodeFreeRecursive(root);
+
+  YGConfigFree(config);
+}
+
+TEST(YogaTest, flex_grow_within_constrained_min_row) {
+  const YGConfigRef config = YGConfigNew();
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexDirection(root, YGFlexDirectionRow);
+  YGNodeStyleSetMinWidth(root, 100);
+  YGNodeStyleSetHeight(root, 100);
+
+  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexGrow(root_child0, 1);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  const YGNodeRef root_child1 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child1, 50);
+  YGNodeInsertChild(root, root_child1, 1);
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child1));
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child1));
+
+  YGNodeFreeRecursive(root);
+
+  YGConfigFree(config);
+}
+
+TEST(YogaTest, flex_grow_within_constrained_min_column) {
+  const YGConfigRef config = YGConfigNew();
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  YGNodeStyleSetMinHeight(root, 100);
+
+  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexGrow(root_child0, 1);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  const YGNodeRef root_child1 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetHeight(root_child1, 50);
+  YGNodeInsertChild(root, root_child1, 1);
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child1));
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child1));
+
+  YGNodeFreeRecursive(root);
+
+  YGConfigFree(config);
+}
+
+TEST(YogaTest, flex_grow_within_constrained_max_row) {
+  const YGConfigRef config = YGConfigNew();
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root, 200);
+
+  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexDirection(root_child0, YGFlexDirectionRow);
+  YGNodeStyleSetMaxWidth(root_child0, 100);
+  YGNodeStyleSetHeight(root_child0, 100);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  const YGNodeRef root_child0_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexShrink(root_child0_child0, 1);
+  YGNodeStyleSetFlexBasis(root_child0_child0, 100);
+  YGNodeInsertChild(root_child0, root_child0_child0, 0);
+
+  const YGNodeRef root_child0_child1 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child0_child1, 50);
+  YGNodeInsertChild(root_child0, root_child0_child1, 1);
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(200, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child0_child0));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child0_child0));
+
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetLeft(root_child0_child1));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0_child1));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child0_child1));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child0_child1));
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(200, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetLeft(root_child0_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child0_child0));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child0_child0));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0_child1));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0_child1));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child0_child1));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child0_child1));
+
+  YGNodeFreeRecursive(root);
+
+  YGConfigFree(config);
+}
+
+TEST(YogaTest, flex_grow_within_constrained_max_column) {
+  const YGConfigRef config = YGConfigNew();
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root, 100);
+  YGNodeStyleSetMaxHeight(root, 100);
+
+  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexShrink(root_child0, 1);
+  YGNodeStyleSetFlexBasis(root_child0, 100);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  const YGNodeRef root_child1 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetHeight(root_child1, 50);
+  YGNodeInsertChild(root, root_child1, 1);
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child1));
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child1));
+
+  YGNodeFreeRecursive(root);
+
+  YGConfigFree(config);
+}
+
+TEST(YogaTest, child_min_max_width_flexing) {
+  const YGConfigRef config = YGConfigNew();
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexDirection(root, YGFlexDirectionRow);
+  YGNodeStyleSetWidth(root, 120);
+  YGNodeStyleSetHeight(root, 50);
+
+  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexGrow(root_child0, 1);
+  YGNodeStyleSetFlexBasis(root_child0, 0);
+  YGNodeStyleSetMinWidth(root_child0, 60);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  const YGNodeRef root_child1 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexGrow(root_child1, 1);
+  YGNodeStyleSetFlexBasisPercent(root_child1, 50);
+  YGNodeStyleSetMaxWidth(root_child1, 20);
+  YGNodeInsertChild(root, root_child1, 1);
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(120, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(20, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child1));
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(120, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(20, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(20, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child1));
+
+  YGNodeFreeRecursive(root);
+
+  YGConfigFree(config);
+}
+
+TEST(YogaTest, min_width_overrides_width) {
+  const YGConfigRef config = YGConfigNew();
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root, 50);
+  YGNodeStyleSetMinWidth(root, 100);
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetHeight(root));
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetHeight(root));
+
+  YGNodeFreeRecursive(root);
+
+  YGConfigFree(config);
+}
+
+TEST(YogaTest, max_width_overrides_width) {
+  const YGConfigRef config = YGConfigNew();
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root, 200);
+  YGNodeStyleSetMaxWidth(root, 100);
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetHeight(root));
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetHeight(root));
+
+  YGNodeFreeRecursive(root);
+
+  YGConfigFree(config);
+}
+
+TEST(YogaTest, min_height_overrides_height) {
+  const YGConfigRef config = YGConfigNew();
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  YGNodeStyleSetHeight(root, 50);
+  YGNodeStyleSetMinHeight(root, 100);
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  YGNodeFreeRecursive(root);
+
+  YGConfigFree(config);
+}
+
+TEST(YogaTest, max_height_overrides_height) {
+  const YGConfigRef config = YGConfigNew();
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  YGNodeStyleSetHeight(root, 200);
+  YGNodeStyleSetMaxHeight(root, 100);
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  YGNodeFreeRecursive(root);
+
+  YGConfigFree(config);
+}
+
+TEST(YogaTest, min_max_percent_no_width_height) {
+  const YGConfigRef config = YGConfigNew();
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  YGNodeStyleSetAlignItems(root, YGAlignFlexStart);
+  YGNodeStyleSetWidth(root, 100);
+  YGNodeStyleSetHeight(root, 100);
+
+  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetMinWidthPercent(root_child0, 10);
+  YGNodeStyleSetMaxWidthPercent(root_child0, 10);
+  YGNodeStyleSetMinHeightPercent(root_child0, 10);
+  YGNodeStyleSetMaxHeightPercent(root_child0, 10);
+  YGNodeInsertChild(root, root_child0, 0);
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child0));
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(90, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child0));
+
+  YGNodeFreeRecursive(root);
+
+  YGConfigFree(config);
+}
diff --git a/automated-tests/src/dali-toolkit-third-party/yoga/YGNodeChildTest.cpp b/automated-tests/src/dali-toolkit-third-party/yoga/YGNodeChildTest.cpp
new file mode 100644 (file)
index 0000000..9d6bb48
--- /dev/null
@@ -0,0 +1,34 @@
+/**
+ * Copyright (c) 2014-present, Facebook, Inc.
+ *
+ * This source code is licensed under the MIT license found in the
+ * LICENSE file in the root directory of this source tree.
+ */
+
+#include <gtest/gtest.h>
+#include <yoga/Yoga.h>
+
+TEST(YogaTest, reset_layout_when_child_removed) {
+  const YGNodeRef root = YGNodeNew();
+
+  const YGNodeRef root_child0 = YGNodeNew();
+  YGNodeStyleSetWidth(root_child0, 100);
+  YGNodeStyleSetHeight(root_child0, 100);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_EQ(100, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_EQ(100, YGNodeLayoutGetHeight(root_child0));
+
+  YGNodeRemoveChild(root, root_child0);
+
+  ASSERT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_TRUE(YGFloatIsUndefined(YGNodeLayoutGetWidth(root_child0)));
+  ASSERT_TRUE(YGFloatIsUndefined(YGNodeLayoutGetHeight(root_child0)));
+
+  YGNodeFreeRecursive(root);
+}
diff --git a/automated-tests/src/dali-toolkit-third-party/yoga/YGPaddingTest.cpp b/automated-tests/src/dali-toolkit-third-party/yoga/YGPaddingTest.cpp
new file mode 100644 (file)
index 0000000..f0d3752
--- /dev/null
@@ -0,0 +1,258 @@
+/**
+ * Copyright (c) 2014-present, Facebook, Inc.
+ *
+ * This source code is licensed under the MIT license found in the
+ * LICENSE file in the root directory of this source tree.
+ */
+
+// @Generated by gentest/gentest.rb from gentest/fixtures/YGPaddingTest.html
+
+#include <gtest/gtest.h>
+#include <yoga/Yoga.h>
+
+TEST(YogaTest, padding_no_size) {
+  const YGConfigRef config = YGConfigNew();
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  YGNodeStyleSetPadding(root, YGEdgeLeft, 10);
+  YGNodeStyleSetPadding(root, YGEdgeTop, 10);
+  YGNodeStyleSetPadding(root, YGEdgeRight, 10);
+  YGNodeStyleSetPadding(root, YGEdgeBottom, 10);
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(20, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(20, YGNodeLayoutGetHeight(root));
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(20, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(20, YGNodeLayoutGetHeight(root));
+
+  YGNodeFreeRecursive(root);
+
+  YGConfigFree(config);
+}
+
+TEST(YogaTest, padding_container_match_child) {
+  const YGConfigRef config = YGConfigNew();
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  YGNodeStyleSetPadding(root, YGEdgeLeft, 10);
+  YGNodeStyleSetPadding(root, YGEdgeTop, 10);
+  YGNodeStyleSetPadding(root, YGEdgeRight, 10);
+  YGNodeStyleSetPadding(root, YGEdgeBottom, 10);
+
+  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child0, 10);
+  YGNodeStyleSetHeight(root_child0, 10);
+  YGNodeInsertChild(root, root_child0, 0);
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(30, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(30, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child0));
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(30, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(30, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child0));
+
+  YGNodeFreeRecursive(root);
+
+  YGConfigFree(config);
+}
+
+TEST(YogaTest, padding_flex_child) {
+  const YGConfigRef config = YGConfigNew();
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  YGNodeStyleSetPadding(root, YGEdgeLeft, 10);
+  YGNodeStyleSetPadding(root, YGEdgeTop, 10);
+  YGNodeStyleSetPadding(root, YGEdgeRight, 10);
+  YGNodeStyleSetPadding(root, YGEdgeBottom, 10);
+  YGNodeStyleSetWidth(root, 100);
+  YGNodeStyleSetHeight(root, 100);
+
+  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexGrow(root_child0, 1);
+  YGNodeStyleSetWidth(root_child0, 10);
+  YGNodeInsertChild(root, root_child0, 0);
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(80, YGNodeLayoutGetHeight(root_child0));
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(80, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(80, YGNodeLayoutGetHeight(root_child0));
+
+  YGNodeFreeRecursive(root);
+
+  YGConfigFree(config);
+}
+
+TEST(YogaTest, padding_stretch_child) {
+  const YGConfigRef config = YGConfigNew();
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  YGNodeStyleSetPadding(root, YGEdgeLeft, 10);
+  YGNodeStyleSetPadding(root, YGEdgeTop, 10);
+  YGNodeStyleSetPadding(root, YGEdgeRight, 10);
+  YGNodeStyleSetPadding(root, YGEdgeBottom, 10);
+  YGNodeStyleSetWidth(root, 100);
+  YGNodeStyleSetHeight(root, 100);
+
+  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetHeight(root_child0, 10);
+  YGNodeInsertChild(root, root_child0, 0);
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(80, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child0));
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(80, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child0));
+
+  YGNodeFreeRecursive(root);
+
+  YGConfigFree(config);
+}
+
+TEST(YogaTest, padding_center_child) {
+  const YGConfigRef config = YGConfigNew();
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  YGNodeStyleSetJustifyContent(root, YGJustifyCenter);
+  YGNodeStyleSetAlignItems(root, YGAlignCenter);
+  YGNodeStyleSetPadding(root, YGEdgeStart, 10);
+  YGNodeStyleSetPadding(root, YGEdgeEnd, 20);
+  YGNodeStyleSetPadding(root, YGEdgeBottom, 20);
+  YGNodeStyleSetWidth(root, 100);
+  YGNodeStyleSetHeight(root, 100);
+
+  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child0, 10);
+  YGNodeStyleSetHeight(root_child0, 10);
+  YGNodeInsertChild(root, root_child0, 0);
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(40, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(35, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child0));
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(35, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child0));
+
+  YGNodeFreeRecursive(root);
+
+  YGConfigFree(config);
+}
+
+TEST(YogaTest, child_with_padding_align_end) {
+  const YGConfigRef config = YGConfigNew();
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  YGNodeStyleSetJustifyContent(root, YGJustifyFlexEnd);
+  YGNodeStyleSetAlignItems(root, YGAlignFlexEnd);
+  YGNodeStyleSetWidth(root, 200);
+  YGNodeStyleSetHeight(root, 200);
+
+  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetPadding(root_child0, YGEdgeLeft, 20);
+  YGNodeStyleSetPadding(root_child0, YGEdgeTop, 20);
+  YGNodeStyleSetPadding(root_child0, YGEdgeRight, 20);
+  YGNodeStyleSetPadding(root_child0, YGEdgeBottom, 20);
+  YGNodeStyleSetWidth(root_child0, 100);
+  YGNodeStyleSetHeight(root_child0, 100);
+  YGNodeInsertChild(root, root_child0, 0);
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(200, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(200, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child0));
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(200, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(200, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child0));
+
+  YGNodeFreeRecursive(root);
+
+  YGConfigFree(config);
+}
diff --git a/automated-tests/src/dali-toolkit-third-party/yoga/YGPercentageTest.cpp b/automated-tests/src/dali-toolkit-third-party/yoga/YGPercentageTest.cpp
new file mode 100644 (file)
index 0000000..2be0459
--- /dev/null
@@ -0,0 +1,1194 @@
+/**
+ * Copyright (c) 2014-present, Facebook, Inc.
+ *
+ * This source code is licensed under the MIT license found in the
+ * LICENSE file in the root directory of this source tree.
+ */
+
+// @Generated by gentest/gentest.rb from gentest/fixtures/YGPercentageTest.html
+
+#include <gtest/gtest.h>
+#include <yoga/Yoga.h>
+
+TEST(YogaTest, percentage_width_height) {
+  const YGConfigRef config = YGConfigNew();
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexDirection(root, YGFlexDirectionRow);
+  YGNodeStyleSetWidth(root, 200);
+  YGNodeStyleSetHeight(root, 200);
+
+  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidthPercent(root_child0, 30);
+  YGNodeStyleSetHeightPercent(root_child0, 30);
+  YGNodeInsertChild(root, root_child0, 0);
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(200, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(200, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(60, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(60, YGNodeLayoutGetHeight(root_child0));
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(200, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(200, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(140, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(60, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(60, YGNodeLayoutGetHeight(root_child0));
+
+  YGNodeFreeRecursive(root);
+
+  YGConfigFree(config);
+}
+
+TEST(YogaTest, percentage_position_left_top) {
+  const YGConfigRef config = YGConfigNew();
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexDirection(root, YGFlexDirectionRow);
+  YGNodeStyleSetWidth(root, 400);
+  YGNodeStyleSetHeight(root, 400);
+
+  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetPositionPercent(root_child0, YGEdgeLeft, 10);
+  YGNodeStyleSetPositionPercent(root_child0, YGEdgeTop, 20);
+  YGNodeStyleSetWidthPercent(root_child0, 45);
+  YGNodeStyleSetHeightPercent(root_child0, 55);
+  YGNodeInsertChild(root, root_child0, 0);
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(400, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(400, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(40, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(80, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(180, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(220, YGNodeLayoutGetHeight(root_child0));
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(400, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(400, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(260, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(80, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(180, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(220, YGNodeLayoutGetHeight(root_child0));
+
+  YGNodeFreeRecursive(root);
+
+  YGConfigFree(config);
+}
+
+TEST(YogaTest, percentage_position_bottom_right) {
+  const YGConfigRef config = YGConfigNew();
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexDirection(root, YGFlexDirectionRow);
+  YGNodeStyleSetWidth(root, 500);
+  YGNodeStyleSetHeight(root, 500);
+
+  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetPositionPercent(root_child0, YGEdgeRight, 20);
+  YGNodeStyleSetPositionPercent(root_child0, YGEdgeBottom, 10);
+  YGNodeStyleSetWidthPercent(root_child0, 55);
+  YGNodeStyleSetHeightPercent(root_child0, 15);
+  YGNodeInsertChild(root, root_child0, 0);
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(500, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(500, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(-100, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(-50, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(275, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(75, YGNodeLayoutGetHeight(root_child0));
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(500, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(500, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(125, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(-50, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(275, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(75, YGNodeLayoutGetHeight(root_child0));
+
+  YGNodeFreeRecursive(root);
+
+  YGConfigFree(config);
+}
+
+TEST(YogaTest, percentage_flex_basis) {
+  const YGConfigRef config = YGConfigNew();
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexDirection(root, YGFlexDirectionRow);
+  YGNodeStyleSetWidth(root, 200);
+  YGNodeStyleSetHeight(root, 200);
+
+  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexGrow(root_child0, 1);
+  YGNodeStyleSetFlexBasisPercent(root_child0, 50);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  const YGNodeRef root_child1 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexGrow(root_child1, 1);
+  YGNodeStyleSetFlexBasisPercent(root_child1, 25);
+  YGNodeInsertChild(root, root_child1, 1);
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(200, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(200, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(125, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(200, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(125, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(75, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(200, YGNodeLayoutGetHeight(root_child1));
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(200, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(200, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(75, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(125, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(200, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(75, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(200, YGNodeLayoutGetHeight(root_child1));
+
+  YGNodeFreeRecursive(root);
+
+  YGConfigFree(config);
+}
+
+TEST(YogaTest, percentage_flex_basis_cross) {
+  const YGConfigRef config = YGConfigNew();
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root, 200);
+  YGNodeStyleSetHeight(root, 200);
+
+  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexGrow(root_child0, 1);
+  YGNodeStyleSetFlexBasisPercent(root_child0, 50);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  const YGNodeRef root_child1 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexGrow(root_child1, 1);
+  YGNodeStyleSetFlexBasisPercent(root_child1, 25);
+  YGNodeInsertChild(root, root_child1, 1);
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(200, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(200, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(200, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(125, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(125, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(200, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(75, YGNodeLayoutGetHeight(root_child1));
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(200, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(200, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(200, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(125, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(125, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(200, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(75, YGNodeLayoutGetHeight(root_child1));
+
+  YGNodeFreeRecursive(root);
+
+  YGConfigFree(config);
+}
+
+TEST(YogaTest, percentage_flex_basis_cross_min_height) {
+  const YGConfigRef config = YGConfigNew();
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root, 200);
+  YGNodeStyleSetHeight(root, 200);
+
+  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexGrow(root_child0, 1);
+  YGNodeStyleSetMinHeightPercent(root_child0, 60);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  const YGNodeRef root_child1 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexGrow(root_child1, 2);
+  YGNodeStyleSetMinHeightPercent(root_child1, 10);
+  YGNodeInsertChild(root, root_child1, 1);
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(200, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(200, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(200, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(140, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(140, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(200, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(60, YGNodeLayoutGetHeight(root_child1));
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(200, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(200, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(200, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(140, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(140, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(200, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(60, YGNodeLayoutGetHeight(root_child1));
+
+  YGNodeFreeRecursive(root);
+
+  YGConfigFree(config);
+}
+
+TEST(YogaTest, percentage_flex_basis_main_max_height) {
+  const YGConfigRef config = YGConfigNew();
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexDirection(root, YGFlexDirectionRow);
+  YGNodeStyleSetWidth(root, 200);
+  YGNodeStyleSetHeight(root, 200);
+
+  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexGrow(root_child0, 1);
+  YGNodeStyleSetFlexBasisPercent(root_child0, 10);
+  YGNodeStyleSetMaxHeightPercent(root_child0, 60);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  const YGNodeRef root_child1 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexGrow(root_child1, 4);
+  YGNodeStyleSetFlexBasisPercent(root_child1, 10);
+  YGNodeStyleSetMaxHeightPercent(root_child1, 20);
+  YGNodeInsertChild(root, root_child1, 1);
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(200, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(200, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(52, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(120, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(52, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(148, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(40, YGNodeLayoutGetHeight(root_child1));
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(200, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(200, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(148, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(52, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(120, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(148, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(40, YGNodeLayoutGetHeight(root_child1));
+
+  YGNodeFreeRecursive(root);
+
+  YGConfigFree(config);
+}
+
+TEST(YogaTest, percentage_flex_basis_cross_max_height) {
+  const YGConfigRef config = YGConfigNew();
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root, 200);
+  YGNodeStyleSetHeight(root, 200);
+
+  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexGrow(root_child0, 1);
+  YGNodeStyleSetFlexBasisPercent(root_child0, 10);
+  YGNodeStyleSetMaxHeightPercent(root_child0, 60);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  const YGNodeRef root_child1 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexGrow(root_child1, 4);
+  YGNodeStyleSetFlexBasisPercent(root_child1, 10);
+  YGNodeStyleSetMaxHeightPercent(root_child1, 20);
+  YGNodeInsertChild(root, root_child1, 1);
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(200, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(200, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(200, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(120, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(120, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(200, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(40, YGNodeLayoutGetHeight(root_child1));
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(200, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(200, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(200, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(120, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(120, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(200, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(40, YGNodeLayoutGetHeight(root_child1));
+
+  YGNodeFreeRecursive(root);
+
+  YGConfigFree(config);
+}
+
+TEST(YogaTest, percentage_flex_basis_main_max_width) {
+  const YGConfigRef config = YGConfigNew();
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexDirection(root, YGFlexDirectionRow);
+  YGNodeStyleSetWidth(root, 200);
+  YGNodeStyleSetHeight(root, 200);
+
+  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexGrow(root_child0, 1);
+  YGNodeStyleSetFlexBasisPercent(root_child0, 15);
+  YGNodeStyleSetMaxWidthPercent(root_child0, 60);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  const YGNodeRef root_child1 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexGrow(root_child1, 4);
+  YGNodeStyleSetFlexBasisPercent(root_child1, 10);
+  YGNodeStyleSetMaxWidthPercent(root_child1, 20);
+  YGNodeInsertChild(root, root_child1, 1);
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(200, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(200, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(120, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(200, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(120, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(40, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(200, YGNodeLayoutGetHeight(root_child1));
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(200, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(200, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(80, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(120, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(200, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(40, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(40, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(200, YGNodeLayoutGetHeight(root_child1));
+
+  YGNodeFreeRecursive(root);
+
+  YGConfigFree(config);
+}
+
+TEST(YogaTest, percentage_flex_basis_cross_max_width) {
+  const YGConfigRef config = YGConfigNew();
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root, 200);
+  YGNodeStyleSetHeight(root, 200);
+
+  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexGrow(root_child0, 1);
+  YGNodeStyleSetFlexBasisPercent(root_child0, 10);
+  YGNodeStyleSetMaxWidthPercent(root_child0, 60);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  const YGNodeRef root_child1 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexGrow(root_child1, 4);
+  YGNodeStyleSetFlexBasisPercent(root_child1, 15);
+  YGNodeStyleSetMaxWidthPercent(root_child1, 20);
+  YGNodeInsertChild(root, root_child1, 1);
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(200, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(200, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(120, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(40, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(150, YGNodeLayoutGetHeight(root_child1));
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(200, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(200, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(80, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(120, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(160, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(40, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(150, YGNodeLayoutGetHeight(root_child1));
+
+  YGNodeFreeRecursive(root);
+
+  YGConfigFree(config);
+}
+
+TEST(YogaTest, percentage_flex_basis_main_min_width) {
+  const YGConfigRef config = YGConfigNew();
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexDirection(root, YGFlexDirectionRow);
+  YGNodeStyleSetWidth(root, 200);
+  YGNodeStyleSetHeight(root, 200);
+
+  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexGrow(root_child0, 1);
+  YGNodeStyleSetFlexBasisPercent(root_child0, 15);
+  YGNodeStyleSetMinWidthPercent(root_child0, 60);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  const YGNodeRef root_child1 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexGrow(root_child1, 4);
+  YGNodeStyleSetFlexBasisPercent(root_child1, 10);
+  YGNodeStyleSetMinWidthPercent(root_child1, 20);
+  YGNodeInsertChild(root, root_child1, 1);
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(200, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(200, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(120, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(200, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(120, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(80, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(200, YGNodeLayoutGetHeight(root_child1));
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(200, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(200, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(80, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(120, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(200, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(80, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(200, YGNodeLayoutGetHeight(root_child1));
+
+  YGNodeFreeRecursive(root);
+
+  YGConfigFree(config);
+}
+
+TEST(YogaTest, percentage_flex_basis_cross_min_width) {
+  const YGConfigRef config = YGConfigNew();
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root, 200);
+  YGNodeStyleSetHeight(root, 200);
+
+  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexGrow(root_child0, 1);
+  YGNodeStyleSetFlexBasisPercent(root_child0, 10);
+  YGNodeStyleSetMinWidthPercent(root_child0, 60);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  const YGNodeRef root_child1 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexGrow(root_child1, 4);
+  YGNodeStyleSetFlexBasisPercent(root_child1, 15);
+  YGNodeStyleSetMinWidthPercent(root_child1, 20);
+  YGNodeInsertChild(root, root_child1, 1);
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(200, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(200, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(200, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(200, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(150, YGNodeLayoutGetHeight(root_child1));
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(200, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(200, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(200, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(200, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(150, YGNodeLayoutGetHeight(root_child1));
+
+  YGNodeFreeRecursive(root);
+
+  YGConfigFree(config);
+}
+
+TEST(YogaTest, percentage_multiple_nested_with_padding_margin_and_percentage_values) {
+  const YGConfigRef config = YGConfigNew();
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root, 200);
+  YGNodeStyleSetHeight(root, 200);
+
+  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexGrow(root_child0, 1);
+  YGNodeStyleSetFlexBasisPercent(root_child0, 10);
+  YGNodeStyleSetMargin(root_child0, YGEdgeLeft, 5);
+  YGNodeStyleSetMargin(root_child0, YGEdgeTop, 5);
+  YGNodeStyleSetMargin(root_child0, YGEdgeRight, 5);
+  YGNodeStyleSetMargin(root_child0, YGEdgeBottom, 5);
+  YGNodeStyleSetPadding(root_child0, YGEdgeLeft, 3);
+  YGNodeStyleSetPadding(root_child0, YGEdgeTop, 3);
+  YGNodeStyleSetPadding(root_child0, YGEdgeRight, 3);
+  YGNodeStyleSetPadding(root_child0, YGEdgeBottom, 3);
+  YGNodeStyleSetMinWidthPercent(root_child0, 60);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  const YGNodeRef root_child0_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetMargin(root_child0_child0, YGEdgeLeft, 5);
+  YGNodeStyleSetMargin(root_child0_child0, YGEdgeTop, 5);
+  YGNodeStyleSetMargin(root_child0_child0, YGEdgeRight, 5);
+  YGNodeStyleSetMargin(root_child0_child0, YGEdgeBottom, 5);
+  YGNodeStyleSetPaddingPercent(root_child0_child0, YGEdgeLeft, 3);
+  YGNodeStyleSetPaddingPercent(root_child0_child0, YGEdgeTop, 3);
+  YGNodeStyleSetPaddingPercent(root_child0_child0, YGEdgeRight, 3);
+  YGNodeStyleSetPaddingPercent(root_child0_child0, YGEdgeBottom, 3);
+  YGNodeStyleSetWidthPercent(root_child0_child0, 50);
+  YGNodeInsertChild(root_child0, root_child0_child0, 0);
+
+  const YGNodeRef root_child0_child0_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetMarginPercent(root_child0_child0_child0, YGEdgeLeft, 5);
+  YGNodeStyleSetMarginPercent(root_child0_child0_child0, YGEdgeTop, 5);
+  YGNodeStyleSetMarginPercent(root_child0_child0_child0, YGEdgeRight, 5);
+  YGNodeStyleSetMarginPercent(root_child0_child0_child0, YGEdgeBottom, 5);
+  YGNodeStyleSetPadding(root_child0_child0_child0, YGEdgeLeft, 3);
+  YGNodeStyleSetPadding(root_child0_child0_child0, YGEdgeTop, 3);
+  YGNodeStyleSetPadding(root_child0_child0_child0, YGEdgeRight, 3);
+  YGNodeStyleSetPadding(root_child0_child0_child0, YGEdgeBottom, 3);
+  YGNodeStyleSetWidthPercent(root_child0_child0_child0, 45);
+  YGNodeInsertChild(root_child0_child0, root_child0_child0_child0, 0);
+
+  const YGNodeRef root_child1 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexGrow(root_child1, 4);
+  YGNodeStyleSetFlexBasisPercent(root_child1, 15);
+  YGNodeStyleSetMinWidthPercent(root_child1, 20);
+  YGNodeInsertChild(root, root_child1, 1);
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(200, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(200, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(5, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(5, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(190, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(48, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(8, YGNodeLayoutGetLeft(root_child0_child0));
+  ASSERT_FLOAT_EQ(8, YGNodeLayoutGetTop(root_child0_child0));
+  ASSERT_FLOAT_EQ(92, YGNodeLayoutGetWidth(root_child0_child0));
+  ASSERT_FLOAT_EQ(25, YGNodeLayoutGetHeight(root_child0_child0));
+
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetLeft(root_child0_child0_child0));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetTop(root_child0_child0_child0));
+  ASSERT_FLOAT_EQ(36, YGNodeLayoutGetWidth(root_child0_child0_child0));
+  ASSERT_FLOAT_EQ(6, YGNodeLayoutGetHeight(root_child0_child0_child0));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(58, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(200, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(142, YGNodeLayoutGetHeight(root_child1));
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(200, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(200, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(5, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(5, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(190, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(48, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(90, YGNodeLayoutGetLeft(root_child0_child0));
+  ASSERT_FLOAT_EQ(8, YGNodeLayoutGetTop(root_child0_child0));
+  ASSERT_FLOAT_EQ(92, YGNodeLayoutGetWidth(root_child0_child0));
+  ASSERT_FLOAT_EQ(25, YGNodeLayoutGetHeight(root_child0_child0));
+
+  ASSERT_FLOAT_EQ(46, YGNodeLayoutGetLeft(root_child0_child0_child0));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetTop(root_child0_child0_child0));
+  ASSERT_FLOAT_EQ(36, YGNodeLayoutGetWidth(root_child0_child0_child0));
+  ASSERT_FLOAT_EQ(6, YGNodeLayoutGetHeight(root_child0_child0_child0));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(58, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(200, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(142, YGNodeLayoutGetHeight(root_child1));
+
+  YGNodeFreeRecursive(root);
+
+  YGConfigFree(config);
+}
+
+TEST(YogaTest, percentage_margin_should_calculate_based_only_on_width) {
+  const YGConfigRef config = YGConfigNew();
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root, 200);
+  YGNodeStyleSetHeight(root, 100);
+
+  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexGrow(root_child0, 1);
+  YGNodeStyleSetMarginPercent(root_child0, YGEdgeLeft, 10);
+  YGNodeStyleSetMarginPercent(root_child0, YGEdgeTop, 10);
+  YGNodeStyleSetMarginPercent(root_child0, YGEdgeRight, 10);
+  YGNodeStyleSetMarginPercent(root_child0, YGEdgeBottom, 10);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  const YGNodeRef root_child0_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child0_child0, 10);
+  YGNodeStyleSetHeight(root_child0_child0, 10);
+  YGNodeInsertChild(root_child0, root_child0_child0, 0);
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(200, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(20, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(20, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(160, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(60, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0_child0));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetWidth(root_child0_child0));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child0_child0));
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(200, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(20, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(20, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(160, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(60, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(150, YGNodeLayoutGetLeft(root_child0_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0_child0));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetWidth(root_child0_child0));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child0_child0));
+
+  YGNodeFreeRecursive(root);
+
+  YGConfigFree(config);
+}
+
+TEST(YogaTest, percentage_padding_should_calculate_based_only_on_width) {
+  const YGConfigRef config = YGConfigNew();
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root, 200);
+  YGNodeStyleSetHeight(root, 100);
+
+  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexGrow(root_child0, 1);
+  YGNodeStyleSetPaddingPercent(root_child0, YGEdgeLeft, 10);
+  YGNodeStyleSetPaddingPercent(root_child0, YGEdgeTop, 10);
+  YGNodeStyleSetPaddingPercent(root_child0, YGEdgeRight, 10);
+  YGNodeStyleSetPaddingPercent(root_child0, YGEdgeBottom, 10);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  const YGNodeRef root_child0_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child0_child0, 10);
+  YGNodeStyleSetHeight(root_child0_child0, 10);
+  YGNodeInsertChild(root_child0, root_child0_child0, 0);
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(200, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(200, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(20, YGNodeLayoutGetLeft(root_child0_child0));
+  ASSERT_FLOAT_EQ(20, YGNodeLayoutGetTop(root_child0_child0));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetWidth(root_child0_child0));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child0_child0));
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(200, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(200, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(170, YGNodeLayoutGetLeft(root_child0_child0));
+  ASSERT_FLOAT_EQ(20, YGNodeLayoutGetTop(root_child0_child0));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetWidth(root_child0_child0));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child0_child0));
+
+  YGNodeFreeRecursive(root);
+
+  YGConfigFree(config);
+}
+
+TEST(YogaTest, percentage_absolute_position) {
+  const YGConfigRef config = YGConfigNew();
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root, 200);
+  YGNodeStyleSetHeight(root, 100);
+
+  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetPositionType(root_child0, YGPositionTypeAbsolute);
+  YGNodeStyleSetPositionPercent(root_child0, YGEdgeLeft, 30);
+  YGNodeStyleSetPositionPercent(root_child0, YGEdgeTop, 10);
+  YGNodeStyleSetWidth(root_child0, 10);
+  YGNodeStyleSetHeight(root_child0, 10);
+  YGNodeInsertChild(root, root_child0, 0);
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(200, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(60, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child0));
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(200, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(60, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child0));
+
+  YGNodeFreeRecursive(root);
+
+  YGConfigFree(config);
+}
+
+TEST(YogaTest, percentage_width_height_undefined_parent_size) {
+  const YGConfigRef config = YGConfigNew();
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+
+  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidthPercent(root_child0, 50);
+  YGNodeStyleSetHeightPercent(root_child0, 50);
+  YGNodeInsertChild(root, root_child0, 0);
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetHeight(root_child0));
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetHeight(root_child0));
+
+  YGNodeFreeRecursive(root);
+
+  YGConfigFree(config);
+}
+
+TEST(YogaTest, percent_within_flex_grow) {
+  const YGConfigRef config = YGConfigNew();
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexDirection(root, YGFlexDirectionRow);
+  YGNodeStyleSetWidth(root, 350);
+  YGNodeStyleSetHeight(root, 100);
+
+  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child0, 100);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  const YGNodeRef root_child1 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexGrow(root_child1, 1);
+  YGNodeInsertChild(root, root_child1, 1);
+
+  const YGNodeRef root_child1_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidthPercent(root_child1_child0, 100);
+  YGNodeInsertChild(root_child1, root_child1_child0, 0);
+
+  const YGNodeRef root_child2 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child2, 100);
+  YGNodeInsertChild(root, root_child2, 2);
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(350, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(150, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child1));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child1_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child1_child0));
+  ASSERT_FLOAT_EQ(150, YGNodeLayoutGetWidth(root_child1_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetHeight(root_child1_child0));
+
+  ASSERT_FLOAT_EQ(250, YGNodeLayoutGetLeft(root_child2));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child2));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child2));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child2));
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(350, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(250, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(150, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child1));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child1_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child1_child0));
+  ASSERT_FLOAT_EQ(150, YGNodeLayoutGetWidth(root_child1_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetHeight(root_child1_child0));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child2));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child2));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child2));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child2));
+
+  YGNodeFreeRecursive(root);
+
+  YGConfigFree(config);
+}
+
+TEST(YogaTest, percentage_container_in_wrapping_container) {
+  const YGConfigRef config = YGConfigNew();
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  YGNodeStyleSetJustifyContent(root, YGJustifyCenter);
+  YGNodeStyleSetAlignItems(root, YGAlignCenter);
+  YGNodeStyleSetWidth(root, 200);
+  YGNodeStyleSetHeight(root, 200);
+
+  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  const YGNodeRef root_child0_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexDirection(root_child0_child0, YGFlexDirectionRow);
+  YGNodeStyleSetJustifyContent(root_child0_child0, YGJustifyCenter);
+  YGNodeStyleSetWidthPercent(root_child0_child0, 100);
+  YGNodeInsertChild(root_child0, root_child0_child0, 0);
+
+  const YGNodeRef root_child0_child0_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child0_child0_child0, 50);
+  YGNodeStyleSetHeight(root_child0_child0_child0, 50);
+  YGNodeInsertChild(root_child0_child0, root_child0_child0_child0, 0);
+
+  const YGNodeRef root_child0_child0_child1 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child0_child0_child1, 50);
+  YGNodeStyleSetHeight(root_child0_child0_child1, 50);
+  YGNodeInsertChild(root_child0_child0, root_child0_child0_child1, 1);
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(200, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(200, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(75, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0_child0));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child0_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child0_child0));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0_child0_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0_child0_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child0_child0_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child0_child0_child0));
+
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetLeft(root_child0_child0_child1));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0_child0_child1));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child0_child0_child1));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child0_child0_child1));
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(200, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(200, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(75, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0_child0));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child0_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child0_child0));
+
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetLeft(root_child0_child0_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0_child0_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child0_child0_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child0_child0_child0));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0_child0_child1));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0_child0_child1));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child0_child0_child1));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child0_child0_child1));
+
+  YGNodeFreeRecursive(root);
+
+  YGConfigFree(config);
+}
+
+TEST(YogaTest, percent_absolute_position) {
+  const YGConfigRef config = YGConfigNew();
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root, 60);
+  YGNodeStyleSetHeight(root, 50);
+
+  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexDirection(root_child0, YGFlexDirectionRow);
+  YGNodeStyleSetPositionType(root_child0, YGPositionTypeAbsolute);
+  YGNodeStyleSetPositionPercent(root_child0, YGEdgeLeft, 50);
+  YGNodeStyleSetWidthPercent(root_child0, 100);
+  YGNodeStyleSetHeight(root_child0, 50);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  const YGNodeRef root_child0_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidthPercent(root_child0_child0, 100);
+  YGNodeInsertChild(root_child0, root_child0_child0, 0);
+
+  const YGNodeRef root_child0_child1 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidthPercent(root_child0_child1, 100);
+  YGNodeInsertChild(root_child0, root_child0_child1, 1);
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(60, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(30, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(60, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0_child0));
+  ASSERT_FLOAT_EQ(60, YGNodeLayoutGetWidth(root_child0_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child0_child0));
+
+  ASSERT_FLOAT_EQ(60, YGNodeLayoutGetLeft(root_child0_child1));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0_child1));
+  ASSERT_FLOAT_EQ(60, YGNodeLayoutGetWidth(root_child0_child1));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child0_child1));
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(60, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(30, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(60, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0_child0));
+  ASSERT_FLOAT_EQ(60, YGNodeLayoutGetWidth(root_child0_child0));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child0_child0));
+
+  ASSERT_FLOAT_EQ(-60, YGNodeLayoutGetLeft(root_child0_child1));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0_child1));
+  ASSERT_FLOAT_EQ(60, YGNodeLayoutGetWidth(root_child0_child1));
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child0_child1));
+
+  YGNodeFreeRecursive(root);
+
+  YGConfigFree(config);
+}
diff --git a/automated-tests/src/dali-toolkit-third-party/yoga/YGPersistenceTest.cpp b/automated-tests/src/dali-toolkit-third-party/yoga/YGPersistenceTest.cpp
new file mode 100644 (file)
index 0000000..9df861a
--- /dev/null
@@ -0,0 +1,250 @@
+/**
+ * Copyright (c) 2014-present, Facebook, Inc.
+ *
+ * This source code is licensed under the MIT license found in the
+ * LICENSE file in the root directory of this source tree.
+ */
+
+// @Generated by gentest/gentest.rb from gentest/fixtures/YGPercentageTest.html
+
+#include <gtest/gtest.h>
+#include <yoga/Yoga.h>
+
+TEST(YogaTest, cloning_shared_root) {
+  const YGConfigRef config = YGConfigNew();
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root, 100);
+  YGNodeStyleSetHeight(root, 100);
+
+  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexGrow(root_child0, 1);
+  YGNodeStyleSetFlexBasis(root_child0, 50);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  const YGNodeRef root_child1 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexGrow(root_child1, 1);
+  YGNodeInsertChild(root, root_child1, 1);
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(75, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(75, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(25, YGNodeLayoutGetHeight(root_child1));
+
+  const YGNodeRef root2 = YGNodeClone(root);
+  YGNodeStyleSetWidth(root2, 100);
+
+  ASSERT_EQ(2, YGNodeGetChildCount(root2));
+  // The children should have referential equality at this point.
+  ASSERT_EQ(root_child0, YGNodeGetChild(root2, 0));
+  ASSERT_EQ(root_child1, YGNodeGetChild(root2, 1));
+
+  YGNodeCalculateLayout(root2, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_EQ(2, YGNodeGetChildCount(root2));
+  // Relayout with no changed input should result in referential equality.
+  ASSERT_EQ(root_child0, YGNodeGetChild(root2, 0));
+  ASSERT_EQ(root_child1, YGNodeGetChild(root2, 1));
+
+  YGNodeStyleSetWidth(root2, 150);
+  YGNodeStyleSetHeight(root2, 200);
+  YGNodeCalculateLayout(root2, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_EQ(2, YGNodeGetChildCount(root2));
+  // Relayout with changed input should result in cloned children.
+  const YGNodeRef root2_child0 = YGNodeGetChild(root2, 0);
+  const YGNodeRef root2_child1 = YGNodeGetChild(root2, 1);
+  ASSERT_NE(root_child0, root2_child0);
+  ASSERT_NE(root_child1, root2_child1);
+
+  // Everything in the root should remain unchanged.
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(75, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(75, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(25, YGNodeLayoutGetHeight(root_child1));
+
+  // The new root now has new layout.
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root2));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root2));
+  ASSERT_FLOAT_EQ(150, YGNodeLayoutGetWidth(root2));
+  ASSERT_FLOAT_EQ(200, YGNodeLayoutGetHeight(root2));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root2_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root2_child0));
+  ASSERT_FLOAT_EQ(150, YGNodeLayoutGetWidth(root2_child0));
+  ASSERT_FLOAT_EQ(125, YGNodeLayoutGetHeight(root2_child0));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root2_child1));
+  ASSERT_FLOAT_EQ(125, YGNodeLayoutGetTop(root2_child1));
+  ASSERT_FLOAT_EQ(150, YGNodeLayoutGetWidth(root2_child1));
+  ASSERT_FLOAT_EQ(75, YGNodeLayoutGetHeight(root2_child1));
+
+  YGNodeFreeRecursive(root2);
+
+  YGNodeFreeRecursive(root);
+
+  YGConfigFree(config);
+}
+
+TEST(YogaTest, mutating_children_of_a_clone_clones) {
+  const YGConfigRef config = YGConfigNew();
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  ASSERT_EQ(0, YGNodeGetChildCount(root));
+
+  const YGNodeRef root2 = YGNodeClone(root);
+  ASSERT_EQ(0, YGNodeGetChildCount(root2));
+
+  const YGNodeRef root2_child0 = YGNodeNewWithConfig(config);
+  YGNodeInsertChild(root2, root2_child0, 0);
+
+  ASSERT_EQ(0, YGNodeGetChildCount(root));
+  ASSERT_EQ(1, YGNodeGetChildCount(root2));
+
+  const YGNodeRef root3 = YGNodeClone(root2);
+  ASSERT_EQ(1, YGNodeGetChildCount(root2));
+  ASSERT_EQ(1, YGNodeGetChildCount(root3));
+  ASSERT_EQ(YGNodeGetChild(root2, 0), YGNodeGetChild(root3, 0));
+
+  const YGNodeRef root3_child1 = YGNodeNewWithConfig(config);
+  YGNodeInsertChild(root3, root3_child1, 1);
+  ASSERT_EQ(1, YGNodeGetChildCount(root2));
+  ASSERT_EQ(2, YGNodeGetChildCount(root3));
+  ASSERT_EQ(root3_child1, YGNodeGetChild(root3, 1));
+  ASSERT_NE(YGNodeGetChild(root2, 0), YGNodeGetChild(root3, 0));
+
+  const YGNodeRef root4 = YGNodeClone(root3);
+  ASSERT_EQ(root3_child1, YGNodeGetChild(root4, 1));
+
+  YGNodeRemoveChild(root4, root3_child1);
+  ASSERT_EQ(2, YGNodeGetChildCount(root3));
+  ASSERT_EQ(1, YGNodeGetChildCount(root4));
+  ASSERT_NE(YGNodeGetChild(root3, 0), YGNodeGetChild(root4, 0));
+
+  YGNodeFreeRecursive(root4);
+  YGNodeFreeRecursive(root3);
+  YGNodeFreeRecursive(root2);
+  YGNodeFreeRecursive(root);
+
+  YGConfigFree(config);
+}
+
+TEST(YogaTest, cloning_two_levels) {
+  const YGConfigRef config = YGConfigNew();
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root, 100);
+  YGNodeStyleSetHeight(root, 100);
+
+  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexGrow(root_child0, 1);
+  YGNodeStyleSetFlexBasis(root_child0, 15);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  const YGNodeRef root_child1 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexGrow(root_child1, 1);
+  YGNodeInsertChild(root, root_child1, 1);
+
+  const YGNodeRef root_child1_0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexBasis(root_child1_0, 10);
+  YGNodeStyleSetFlexGrow(root_child1_0, 1);
+  YGNodeInsertChild(root_child1, root_child1_0, 0);
+
+  const YGNodeRef root_child1_1 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexBasis(root_child1_1, 25);
+  YGNodeInsertChild(root_child1, root_child1_1, 1);
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(40, YGNodeLayoutGetHeight(root_child0));
+  ASSERT_FLOAT_EQ(60, YGNodeLayoutGetHeight(root_child1));
+  ASSERT_FLOAT_EQ(35, YGNodeLayoutGetHeight(root_child1_0));
+  ASSERT_FLOAT_EQ(25, YGNodeLayoutGetHeight(root_child1_1));
+
+  const YGNodeRef root2_child0 = YGNodeClone(root_child0);
+  const YGNodeRef root2_child1 = YGNodeClone(root_child1);
+  const YGNodeRef root2 = YGNodeClone(root);
+
+  YGNodeStyleSetFlexGrow(root2_child0, 0);
+  YGNodeStyleSetFlexBasis(root2_child0, 40);
+
+  YGNodeRemoveAllChildren(root2);
+  YGNodeInsertChild(root2, root2_child0, 0);
+  YGNodeInsertChild(root2, root2_child1, 1);
+  ASSERT_EQ(2, YGNodeGetChildCount(root2));
+
+  YGNodeCalculateLayout(root2, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  // Original root is unchanged
+  ASSERT_FLOAT_EQ(40, YGNodeLayoutGetHeight(root_child0));
+  ASSERT_FLOAT_EQ(60, YGNodeLayoutGetHeight(root_child1));
+  ASSERT_FLOAT_EQ(35, YGNodeLayoutGetHeight(root_child1_0));
+  ASSERT_FLOAT_EQ(25, YGNodeLayoutGetHeight(root_child1_1));
+
+  // New root has new layout at the top
+  ASSERT_FLOAT_EQ(40, YGNodeLayoutGetHeight(root2_child0));
+  ASSERT_FLOAT_EQ(60, YGNodeLayoutGetHeight(root2_child1));
+
+  // The deeper children are untouched.
+  ASSERT_EQ(YGNodeGetChild(root2_child1, 0), root_child1_0);
+  ASSERT_EQ(YGNodeGetChild(root2_child1, 1), root_child1_1);
+
+  YGNodeFreeRecursive(root2);
+  YGNodeFreeRecursive(root);
+
+  YGConfigFree(config);
+}
+
+TEST(YogaTest, cloning_and_freeing) {
+  const int32_t initialInstanceCount = YGNodeGetInstanceCount();
+
+  const YGConfigRef config = YGConfigNew();
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root, 100);
+  YGNodeStyleSetHeight(root, 100);
+  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+  YGNodeInsertChild(root, root_child0, 0);
+  const YGNodeRef root_child1 = YGNodeNewWithConfig(config);
+  YGNodeInsertChild(root, root_child1, 1);
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  const YGNodeRef root2 = YGNodeClone(root);
+
+  // Freeing the original root should be safe as long as we don't free its
+  // children.
+  YGNodeFree(root);
+
+  YGNodeCalculateLayout(root2, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  YGNodeFreeRecursive(root2);
+
+  YGNodeFree(root_child0);
+  YGNodeFree(root_child1);
+
+  YGConfigFree(config);
+
+  ASSERT_EQ(initialInstanceCount, YGNodeGetInstanceCount());
+}
diff --git a/automated-tests/src/dali-toolkit-third-party/yoga/YGRelayoutTest.cpp b/automated-tests/src/dali-toolkit-third-party/yoga/YGRelayoutTest.cpp
new file mode 100644 (file)
index 0000000..cbda524
--- /dev/null
@@ -0,0 +1,50 @@
+/**
+ * Copyright (c) 2014-present, Facebook, Inc.
+ *
+ * This source code is licensed under the MIT license found in the
+ * LICENSE file in the root directory of this source tree.
+ */
+
+#include <gtest/gtest.h>
+#include <yoga/Yoga.h>
+
+TEST(YogaTest, dont_cache_computed_flex_basis_between_layouts) {
+  const YGConfigRef config = YGConfigNew();
+  YGConfigSetExperimentalFeatureEnabled(config, YGExperimentalFeatureWebFlexBasis, true);
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  YGNodeStyleSetHeightPercent(root, 100);
+  YGNodeStyleSetWidthPercent(root, 100);
+
+  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexBasisPercent(root_child0, 100);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  YGNodeCalculateLayout(root, 100, YGUndefined, YGDirectionLTR);
+  YGNodeCalculateLayout(root, 100, 100, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child0));
+
+  YGNodeFreeRecursive(root);
+
+  YGConfigFree(config);
+}
+
+TEST(YogaTest, recalculate_resolvedDimonsion_onchange) {
+  const YGNodeRef root = YGNodeNew();
+
+  const YGNodeRef root_child0 = YGNodeNew();
+  YGNodeStyleSetMinHeight(root_child0, 10);
+  YGNodeStyleSetMaxHeight(root_child0, 10);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child0));
+
+  YGNodeStyleSetMinHeight(root_child0, YGUndefined);
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetHeight(root_child0));
+
+  YGNodeFreeRecursive(root);
+}
diff --git a/automated-tests/src/dali-toolkit-third-party/yoga/YGRoundingFunctionTest.cpp b/automated-tests/src/dali-toolkit-third-party/yoga/YGRoundingFunctionTest.cpp
new file mode 100644 (file)
index 0000000..82eba44
--- /dev/null
@@ -0,0 +1,28 @@
+/**
+ * Copyright (c) 2014-present, Facebook, Inc.
+ *
+ * This source code is licensed under the MIT license found in the
+ * LICENSE file in the root directory of this source tree.
+ */
+
+#include <gtest/gtest.h>
+#include <yoga/Yoga.h>
+#include <yoga/Yoga-internal.h>
+
+TEST(YogaTest, rounding_value) {
+  // Test that whole numbers are rounded to whole despite ceil/floor flags
+  ASSERT_FLOAT_EQ(6.0, YGRoundValueToPixelGrid(6.000001, 2.0, false, false));
+  ASSERT_FLOAT_EQ(6.0, YGRoundValueToPixelGrid(6.000001, 2.0, true, false));
+  ASSERT_FLOAT_EQ(6.0, YGRoundValueToPixelGrid(6.000001, 2.0, false, true));
+  ASSERT_FLOAT_EQ(6.0, YGRoundValueToPixelGrid(5.999999, 2.0, false, false));
+  ASSERT_FLOAT_EQ(6.0, YGRoundValueToPixelGrid(5.999999, 2.0, true, false));
+  ASSERT_FLOAT_EQ(6.0, YGRoundValueToPixelGrid(5.999999, 2.0, false, true));
+
+  // Test that numbers with fraction are rounded correctly accounting for ceil/floor flags
+  ASSERT_FLOAT_EQ(6.0, YGRoundValueToPixelGrid(6.01, 2.0, false, false));
+  ASSERT_FLOAT_EQ(6.5, YGRoundValueToPixelGrid(6.01, 2.0, true, false));
+  ASSERT_FLOAT_EQ(6.0, YGRoundValueToPixelGrid(6.01, 2.0, false, true));
+  ASSERT_FLOAT_EQ(6.0, YGRoundValueToPixelGrid(5.99, 2.0, false, false));
+  ASSERT_FLOAT_EQ(6.0, YGRoundValueToPixelGrid(5.99, 2.0, true, false));
+  ASSERT_FLOAT_EQ(5.5, YGRoundValueToPixelGrid(5.99, 2.0, false, true));
+}
diff --git a/automated-tests/src/dali-toolkit-third-party/yoga/YGRoundingMeasureFuncTest.cpp b/automated-tests/src/dali-toolkit-third-party/yoga/YGRoundingMeasureFuncTest.cpp
new file mode 100644 (file)
index 0000000..33820c4
--- /dev/null
@@ -0,0 +1,130 @@
+/**
+ * Copyright (c) 2014-present, Facebook, Inc.
+ *
+ * This source code is licensed under the MIT license found in the
+ * LICENSE file in the root directory of this source tree.
+ */
+
+#include <gtest/gtest.h>
+#include <yoga/YGNode.h>
+#include <yoga/Yoga.h>
+
+static YGSize _measureFloor(YGNodeRef node,
+                            float width,
+                            YGMeasureMode widthMode,
+                            float height,
+                            YGMeasureMode heightMode) {
+  return YGSize{
+      width = 10.2f, height = 10.2f,
+  };
+}
+
+static YGSize _measureCeil(YGNodeRef node,
+                           float width,
+                           YGMeasureMode widthMode,
+                           float height,
+                           YGMeasureMode heightMode) {
+  return YGSize{
+      width = 10.5f, height = 10.5f,
+  };
+}
+
+static YGSize _measureFractial(YGNodeRef node,
+  float width,
+  YGMeasureMode widthMode,
+  float height,
+  YGMeasureMode heightMode) {
+  return YGSize{
+    width = 0.5f, height = 0.5f,
+  };
+}
+
+TEST(YogaTest, rounding_feature_with_custom_measure_func_floor) {
+  const YGConfigRef config = YGConfigNew();
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+
+  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+  root_child0->setMeasureFunc(_measureFloor);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  YGConfigSetPointScaleFactor(config, 0.0f);
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);
+
+  ASSERT_FLOAT_EQ(10.2, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(10.2, YGNodeLayoutGetHeight(root_child0));
+
+  YGConfigSetPointScaleFactor(config, 1.0f);
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(11, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(11, YGNodeLayoutGetHeight(root_child0));
+
+  YGConfigSetPointScaleFactor(config, 2.0f);
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);
+
+  ASSERT_FLOAT_EQ(10.5, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(10.5, YGNodeLayoutGetHeight(root_child0));
+
+  YGConfigSetPointScaleFactor(config, 4.0f);
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(10.25, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(10.25, YGNodeLayoutGetHeight(root_child0));
+
+  YGConfigSetPointScaleFactor(config, 1.0f / 3.0f);
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);
+
+  ASSERT_FLOAT_EQ(12.0, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(12.0, YGNodeLayoutGetHeight(root_child0));
+
+  YGNodeFreeRecursive(root);
+
+  YGConfigFree(config);
+}
+
+TEST(YogaTest, rounding_feature_with_custom_measure_func_ceil) {
+  const YGConfigRef config = YGConfigNew();
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+
+  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+  root_child0->setMeasureFunc(_measureCeil);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  YGConfigSetPointScaleFactor(config, 1.0f);
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(11, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(11, YGNodeLayoutGetHeight(root_child0));
+
+  YGNodeFreeRecursive(root);
+
+  YGConfigFree(config);
+}
+
+TEST(YogaTest, rounding_feature_with_custom_measure_and_fractial_matching_scale) {
+  const YGConfigRef config = YGConfigNew();
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+
+  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetPosition(root_child0, YGEdgeLeft, 73.625);
+  root_child0->setMeasureFunc(_measureFractial);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  YGConfigSetPointScaleFactor(config, 2.0f);
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(0.5, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(0.5, YGNodeLayoutGetHeight(root_child0));
+  ASSERT_FLOAT_EQ(73.5, YGNodeLayoutGetLeft(root_child0));
+
+  YGNodeFreeRecursive(root);
+
+  YGConfigFree(config);
+}
diff --git a/automated-tests/src/dali-toolkit-third-party/yoga/YGRoundingTest.cpp b/automated-tests/src/dali-toolkit-third-party/yoga/YGRoundingTest.cpp
new file mode 100644 (file)
index 0000000..303e9f0
--- /dev/null
@@ -0,0 +1,1077 @@
+/**
+ * Copyright (c) 2014-present, Facebook, Inc.
+ *
+ * This source code is licensed under the MIT license found in the
+ * LICENSE file in the root directory of this source tree.
+ */
+
+// @Generated by gentest/gentest.rb from gentest/fixtures/YGRoundingTest.html
+
+#include <gtest/gtest.h>
+#include <yoga/Yoga.h>
+
+TEST(YogaTest, rounding_flex_basis_flex_grow_row_width_of_100) {
+  const YGConfigRef config = YGConfigNew();
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexDirection(root, YGFlexDirectionRow);
+  YGNodeStyleSetWidth(root, 100);
+  YGNodeStyleSetHeight(root, 100);
+
+  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexGrow(root_child0, 1);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  const YGNodeRef root_child1 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexGrow(root_child1, 1);
+  YGNodeInsertChild(root, root_child1, 1);
+
+  const YGNodeRef root_child2 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexGrow(root_child2, 1);
+  YGNodeInsertChild(root, root_child2, 2);
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(33, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(33, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(34, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child1));
+
+  ASSERT_FLOAT_EQ(67, YGNodeLayoutGetLeft(root_child2));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child2));
+  ASSERT_FLOAT_EQ(33, YGNodeLayoutGetWidth(root_child2));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child2));
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(67, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(33, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(33, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(34, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child1));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child2));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child2));
+  ASSERT_FLOAT_EQ(33, YGNodeLayoutGetWidth(root_child2));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child2));
+
+  YGNodeFreeRecursive(root);
+
+  YGConfigFree(config);
+}
+
+TEST(YogaTest, rounding_flex_basis_flex_grow_row_prime_number_width) {
+  const YGConfigRef config = YGConfigNew();
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexDirection(root, YGFlexDirectionRow);
+  YGNodeStyleSetWidth(root, 113);
+  YGNodeStyleSetHeight(root, 100);
+
+  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexGrow(root_child0, 1);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  const YGNodeRef root_child1 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexGrow(root_child1, 1);
+  YGNodeInsertChild(root, root_child1, 1);
+
+  const YGNodeRef root_child2 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexGrow(root_child2, 1);
+  YGNodeInsertChild(root, root_child2, 2);
+
+  const YGNodeRef root_child3 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexGrow(root_child3, 1);
+  YGNodeInsertChild(root, root_child3, 3);
+
+  const YGNodeRef root_child4 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexGrow(root_child4, 1);
+  YGNodeInsertChild(root, root_child4, 4);
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(113, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(23, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(23, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(22, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child1));
+
+  ASSERT_FLOAT_EQ(45, YGNodeLayoutGetLeft(root_child2));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child2));
+  ASSERT_FLOAT_EQ(23, YGNodeLayoutGetWidth(root_child2));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child2));
+
+  ASSERT_FLOAT_EQ(68, YGNodeLayoutGetLeft(root_child3));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child3));
+  ASSERT_FLOAT_EQ(22, YGNodeLayoutGetWidth(root_child3));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child3));
+
+  ASSERT_FLOAT_EQ(90, YGNodeLayoutGetLeft(root_child4));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child4));
+  ASSERT_FLOAT_EQ(23, YGNodeLayoutGetWidth(root_child4));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child4));
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(113, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(90, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(23, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(68, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(22, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child1));
+
+  ASSERT_FLOAT_EQ(45, YGNodeLayoutGetLeft(root_child2));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child2));
+  ASSERT_FLOAT_EQ(23, YGNodeLayoutGetWidth(root_child2));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child2));
+
+  ASSERT_FLOAT_EQ(23, YGNodeLayoutGetLeft(root_child3));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child3));
+  ASSERT_FLOAT_EQ(22, YGNodeLayoutGetWidth(root_child3));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child3));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child4));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child4));
+  ASSERT_FLOAT_EQ(23, YGNodeLayoutGetWidth(root_child4));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child4));
+
+  YGNodeFreeRecursive(root);
+
+  YGConfigFree(config);
+}
+
+TEST(YogaTest, rounding_flex_basis_flex_shrink_row) {
+  const YGConfigRef config = YGConfigNew();
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexDirection(root, YGFlexDirectionRow);
+  YGNodeStyleSetWidth(root, 101);
+  YGNodeStyleSetHeight(root, 100);
+
+  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexShrink(root_child0, 1);
+  YGNodeStyleSetFlexBasis(root_child0, 100);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  const YGNodeRef root_child1 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexBasis(root_child1, 25);
+  YGNodeInsertChild(root, root_child1, 1);
+
+  const YGNodeRef root_child2 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexBasis(root_child2, 25);
+  YGNodeInsertChild(root, root_child2, 2);
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(101, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(51, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(51, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(25, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child1));
+
+  ASSERT_FLOAT_EQ(76, YGNodeLayoutGetLeft(root_child2));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child2));
+  ASSERT_FLOAT_EQ(25, YGNodeLayoutGetWidth(root_child2));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child2));
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(101, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(50, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(51, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(25, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(25, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child1));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child2));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child2));
+  ASSERT_FLOAT_EQ(25, YGNodeLayoutGetWidth(root_child2));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child2));
+
+  YGNodeFreeRecursive(root);
+
+  YGConfigFree(config);
+}
+
+TEST(YogaTest, rounding_flex_basis_overrides_main_size) {
+  const YGConfigRef config = YGConfigNew();
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root, 100);
+  YGNodeStyleSetHeight(root, 113);
+
+  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexGrow(root_child0, 1);
+  YGNodeStyleSetFlexBasis(root_child0, 50);
+  YGNodeStyleSetHeight(root_child0, 20);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  const YGNodeRef root_child1 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexGrow(root_child1, 1);
+  YGNodeStyleSetHeight(root_child1, 10);
+  YGNodeInsertChild(root, root_child1, 1);
+
+  const YGNodeRef root_child2 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexGrow(root_child2, 1);
+  YGNodeStyleSetHeight(root_child2, 10);
+  YGNodeInsertChild(root, root_child2, 2);
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(113, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(64, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(64, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(25, YGNodeLayoutGetHeight(root_child1));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child2));
+  ASSERT_FLOAT_EQ(89, YGNodeLayoutGetTop(root_child2));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child2));
+  ASSERT_FLOAT_EQ(24, YGNodeLayoutGetHeight(root_child2));
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(113, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(64, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(64, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(25, YGNodeLayoutGetHeight(root_child1));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child2));
+  ASSERT_FLOAT_EQ(89, YGNodeLayoutGetTop(root_child2));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child2));
+  ASSERT_FLOAT_EQ(24, YGNodeLayoutGetHeight(root_child2));
+
+  YGNodeFreeRecursive(root);
+
+  YGConfigFree(config);
+}
+
+TEST(YogaTest, rounding_total_fractial) {
+  const YGConfigRef config = YGConfigNew();
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root, 87.4f);
+  YGNodeStyleSetHeight(root, 113.4f);
+
+  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexGrow(root_child0, 0.7f);
+  YGNodeStyleSetFlexBasis(root_child0, 50.3f);
+  YGNodeStyleSetHeight(root_child0, 20.3f);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  const YGNodeRef root_child1 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexGrow(root_child1, 1.6f);
+  YGNodeStyleSetHeight(root_child1, 10);
+  YGNodeInsertChild(root, root_child1, 1);
+
+  const YGNodeRef root_child2 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexGrow(root_child2, 1.1f);
+  YGNodeStyleSetHeight(root_child2, 10.7f);
+  YGNodeInsertChild(root, root_child2, 2);
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(87, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(113, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(87, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(59, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(59, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(87, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(30, YGNodeLayoutGetHeight(root_child1));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child2));
+  ASSERT_FLOAT_EQ(89, YGNodeLayoutGetTop(root_child2));
+  ASSERT_FLOAT_EQ(87, YGNodeLayoutGetWidth(root_child2));
+  ASSERT_FLOAT_EQ(24, YGNodeLayoutGetHeight(root_child2));
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(87, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(113, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(87, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(59, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(59, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(87, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(30, YGNodeLayoutGetHeight(root_child1));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child2));
+  ASSERT_FLOAT_EQ(89, YGNodeLayoutGetTop(root_child2));
+  ASSERT_FLOAT_EQ(87, YGNodeLayoutGetWidth(root_child2));
+  ASSERT_FLOAT_EQ(24, YGNodeLayoutGetHeight(root_child2));
+
+  YGNodeFreeRecursive(root);
+
+  YGConfigFree(config);
+}
+
+TEST(YogaTest, rounding_total_fractial_nested) {
+  const YGConfigRef config = YGConfigNew();
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root, 87.4f);
+  YGNodeStyleSetHeight(root, 113.4f);
+
+  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexGrow(root_child0, 0.7f);
+  YGNodeStyleSetFlexBasis(root_child0, 50.3f);
+  YGNodeStyleSetHeight(root_child0, 20.3f);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  const YGNodeRef root_child0_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexGrow(root_child0_child0, 1);
+  YGNodeStyleSetFlexBasis(root_child0_child0, 0.3f);
+  YGNodeStyleSetPosition(root_child0_child0, YGEdgeBottom, 13.3f);
+  YGNodeStyleSetHeight(root_child0_child0, 9.9f);
+  YGNodeInsertChild(root_child0, root_child0_child0, 0);
+
+  const YGNodeRef root_child0_child1 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexGrow(root_child0_child1, 4);
+  YGNodeStyleSetFlexBasis(root_child0_child1, 0.3f);
+  YGNodeStyleSetPosition(root_child0_child1, YGEdgeTop, 13.3f);
+  YGNodeStyleSetHeight(root_child0_child1, 1.1f);
+  YGNodeInsertChild(root_child0, root_child0_child1, 1);
+
+  const YGNodeRef root_child1 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexGrow(root_child1, 1.6f);
+  YGNodeStyleSetHeight(root_child1, 10);
+  YGNodeInsertChild(root, root_child1, 1);
+
+  const YGNodeRef root_child2 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexGrow(root_child2, 1.1f);
+  YGNodeStyleSetHeight(root_child2, 10.7f);
+  YGNodeInsertChild(root, root_child2, 2);
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(87, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(113, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(87, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(59, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0_child0));
+  ASSERT_FLOAT_EQ(-13, YGNodeLayoutGetTop(root_child0_child0));
+  ASSERT_FLOAT_EQ(87, YGNodeLayoutGetWidth(root_child0_child0));
+  ASSERT_FLOAT_EQ(12, YGNodeLayoutGetHeight(root_child0_child0));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0_child1));
+  ASSERT_FLOAT_EQ(25, YGNodeLayoutGetTop(root_child0_child1));
+  ASSERT_FLOAT_EQ(87, YGNodeLayoutGetWidth(root_child0_child1));
+  ASSERT_FLOAT_EQ(47, YGNodeLayoutGetHeight(root_child0_child1));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(59, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(87, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(30, YGNodeLayoutGetHeight(root_child1));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child2));
+  ASSERT_FLOAT_EQ(89, YGNodeLayoutGetTop(root_child2));
+  ASSERT_FLOAT_EQ(87, YGNodeLayoutGetWidth(root_child2));
+  ASSERT_FLOAT_EQ(24, YGNodeLayoutGetHeight(root_child2));
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(87, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(113, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(87, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(59, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0_child0));
+  ASSERT_FLOAT_EQ(-13, YGNodeLayoutGetTop(root_child0_child0));
+  ASSERT_FLOAT_EQ(87, YGNodeLayoutGetWidth(root_child0_child0));
+  ASSERT_FLOAT_EQ(12, YGNodeLayoutGetHeight(root_child0_child0));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0_child1));
+  ASSERT_FLOAT_EQ(25, YGNodeLayoutGetTop(root_child0_child1));
+  ASSERT_FLOAT_EQ(87, YGNodeLayoutGetWidth(root_child0_child1));
+  ASSERT_FLOAT_EQ(47, YGNodeLayoutGetHeight(root_child0_child1));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(59, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(87, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(30, YGNodeLayoutGetHeight(root_child1));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child2));
+  ASSERT_FLOAT_EQ(89, YGNodeLayoutGetTop(root_child2));
+  ASSERT_FLOAT_EQ(87, YGNodeLayoutGetWidth(root_child2));
+  ASSERT_FLOAT_EQ(24, YGNodeLayoutGetHeight(root_child2));
+
+  YGNodeFreeRecursive(root);
+
+  YGConfigFree(config);
+}
+
+TEST(YogaTest, rounding_fractial_input_1) {
+  const YGConfigRef config = YGConfigNew();
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root, 100);
+  YGNodeStyleSetHeight(root, 113.4f);
+
+  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexGrow(root_child0, 1);
+  YGNodeStyleSetFlexBasis(root_child0, 50);
+  YGNodeStyleSetHeight(root_child0, 20);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  const YGNodeRef root_child1 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexGrow(root_child1, 1);
+  YGNodeStyleSetHeight(root_child1, 10);
+  YGNodeInsertChild(root, root_child1, 1);
+
+  const YGNodeRef root_child2 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexGrow(root_child2, 1);
+  YGNodeStyleSetHeight(root_child2, 10);
+  YGNodeInsertChild(root, root_child2, 2);
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(113, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(64, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(64, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(25, YGNodeLayoutGetHeight(root_child1));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child2));
+  ASSERT_FLOAT_EQ(89, YGNodeLayoutGetTop(root_child2));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child2));
+  ASSERT_FLOAT_EQ(24, YGNodeLayoutGetHeight(root_child2));
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(113, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(64, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(64, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(25, YGNodeLayoutGetHeight(root_child1));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child2));
+  ASSERT_FLOAT_EQ(89, YGNodeLayoutGetTop(root_child2));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child2));
+  ASSERT_FLOAT_EQ(24, YGNodeLayoutGetHeight(root_child2));
+
+  YGNodeFreeRecursive(root);
+
+  YGConfigFree(config);
+}
+
+TEST(YogaTest, rounding_fractial_input_2) {
+  const YGConfigRef config = YGConfigNew();
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root, 100);
+  YGNodeStyleSetHeight(root, 113.6f);
+
+  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexGrow(root_child0, 1);
+  YGNodeStyleSetFlexBasis(root_child0, 50);
+  YGNodeStyleSetHeight(root_child0, 20);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  const YGNodeRef root_child1 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexGrow(root_child1, 1);
+  YGNodeStyleSetHeight(root_child1, 10);
+  YGNodeInsertChild(root, root_child1, 1);
+
+  const YGNodeRef root_child2 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexGrow(root_child2, 1);
+  YGNodeStyleSetHeight(root_child2, 10);
+  YGNodeInsertChild(root, root_child2, 2);
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(114, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(65, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(65, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(24, YGNodeLayoutGetHeight(root_child1));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child2));
+  ASSERT_FLOAT_EQ(89, YGNodeLayoutGetTop(root_child2));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child2));
+  ASSERT_FLOAT_EQ(25, YGNodeLayoutGetHeight(root_child2));
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(114, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(65, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(65, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(24, YGNodeLayoutGetHeight(root_child1));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child2));
+  ASSERT_FLOAT_EQ(89, YGNodeLayoutGetTop(root_child2));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child2));
+  ASSERT_FLOAT_EQ(25, YGNodeLayoutGetHeight(root_child2));
+
+  YGNodeFreeRecursive(root);
+
+  YGConfigFree(config);
+}
+
+TEST(YogaTest, rounding_fractial_input_3) {
+  const YGConfigRef config = YGConfigNew();
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  YGNodeStyleSetPosition(root, YGEdgeTop, 0.3f);
+  YGNodeStyleSetWidth(root, 100);
+  YGNodeStyleSetHeight(root, 113.4f);
+
+  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexGrow(root_child0, 1);
+  YGNodeStyleSetFlexBasis(root_child0, 50);
+  YGNodeStyleSetHeight(root_child0, 20);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  const YGNodeRef root_child1 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexGrow(root_child1, 1);
+  YGNodeStyleSetHeight(root_child1, 10);
+  YGNodeInsertChild(root, root_child1, 1);
+
+  const YGNodeRef root_child2 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexGrow(root_child2, 1);
+  YGNodeStyleSetHeight(root_child2, 10);
+  YGNodeInsertChild(root, root_child2, 2);
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(114, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(65, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(64, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(24, YGNodeLayoutGetHeight(root_child1));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child2));
+  ASSERT_FLOAT_EQ(89, YGNodeLayoutGetTop(root_child2));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child2));
+  ASSERT_FLOAT_EQ(25, YGNodeLayoutGetHeight(root_child2));
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(114, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(65, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(64, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(24, YGNodeLayoutGetHeight(root_child1));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child2));
+  ASSERT_FLOAT_EQ(89, YGNodeLayoutGetTop(root_child2));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child2));
+  ASSERT_FLOAT_EQ(25, YGNodeLayoutGetHeight(root_child2));
+
+  YGNodeFreeRecursive(root);
+
+  YGConfigFree(config);
+}
+
+TEST(YogaTest, rounding_fractial_input_4) {
+  const YGConfigRef config = YGConfigNew();
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  YGNodeStyleSetPosition(root, YGEdgeTop, 0.7f);
+  YGNodeStyleSetWidth(root, 100);
+  YGNodeStyleSetHeight(root, 113.4f);
+
+  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexGrow(root_child0, 1);
+  YGNodeStyleSetFlexBasis(root_child0, 50);
+  YGNodeStyleSetHeight(root_child0, 20);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  const YGNodeRef root_child1 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexGrow(root_child1, 1);
+  YGNodeStyleSetHeight(root_child1, 10);
+  YGNodeInsertChild(root, root_child1, 1);
+
+  const YGNodeRef root_child2 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexGrow(root_child2, 1);
+  YGNodeStyleSetHeight(root_child2, 10);
+  YGNodeInsertChild(root, root_child2, 2);
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(1, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(113, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(64, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(64, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(25, YGNodeLayoutGetHeight(root_child1));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child2));
+  ASSERT_FLOAT_EQ(89, YGNodeLayoutGetTop(root_child2));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child2));
+  ASSERT_FLOAT_EQ(24, YGNodeLayoutGetHeight(root_child2));
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(1, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(113, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(64, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(64, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(25, YGNodeLayoutGetHeight(root_child1));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child2));
+  ASSERT_FLOAT_EQ(89, YGNodeLayoutGetTop(root_child2));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child2));
+  ASSERT_FLOAT_EQ(24, YGNodeLayoutGetHeight(root_child2));
+
+  YGNodeFreeRecursive(root);
+
+  YGConfigFree(config);
+}
+
+TEST(YogaTest, rounding_inner_node_controversy_horizontal) {
+  const YGConfigRef config = YGConfigNew();
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexDirection(root, YGFlexDirectionRow);
+  YGNodeStyleSetWidth(root, 320);
+
+  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexGrow(root_child0, 1);
+  YGNodeStyleSetHeight(root_child0, 10);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  const YGNodeRef root_child1 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexGrow(root_child1, 1);
+  YGNodeStyleSetHeight(root_child1, 10);
+  YGNodeInsertChild(root, root_child1, 1);
+
+  const YGNodeRef root_child1_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexGrow(root_child1_child0, 1);
+  YGNodeStyleSetHeight(root_child1_child0, 10);
+  YGNodeInsertChild(root_child1, root_child1_child0, 0);
+
+  const YGNodeRef root_child2 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexGrow(root_child2, 1);
+  YGNodeStyleSetHeight(root_child2, 10);
+  YGNodeInsertChild(root, root_child2, 2);
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(320, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(107, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(107, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(106, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child1));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child1_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child1_child0));
+  ASSERT_FLOAT_EQ(106, YGNodeLayoutGetWidth(root_child1_child0));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child1_child0));
+
+  ASSERT_FLOAT_EQ(213, YGNodeLayoutGetLeft(root_child2));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child2));
+  ASSERT_FLOAT_EQ(107, YGNodeLayoutGetWidth(root_child2));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child2));
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(320, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(213, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(107, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(107, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(106, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child1));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child1_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child1_child0));
+  ASSERT_FLOAT_EQ(106, YGNodeLayoutGetWidth(root_child1_child0));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child1_child0));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child2));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child2));
+  ASSERT_FLOAT_EQ(107, YGNodeLayoutGetWidth(root_child2));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child2));
+
+  YGNodeFreeRecursive(root);
+
+  YGConfigFree(config);
+}
+
+TEST(YogaTest, rounding_inner_node_controversy_vertical) {
+  const YGConfigRef config = YGConfigNew();
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  YGNodeStyleSetHeight(root, 320);
+
+  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexGrow(root_child0, 1);
+  YGNodeStyleSetWidth(root_child0, 10);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  const YGNodeRef root_child1 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexGrow(root_child1, 1);
+  YGNodeStyleSetWidth(root_child1, 10);
+  YGNodeInsertChild(root, root_child1, 1);
+
+  const YGNodeRef root_child1_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexGrow(root_child1_child0, 1);
+  YGNodeStyleSetWidth(root_child1_child0, 10);
+  YGNodeInsertChild(root_child1, root_child1_child0, 0);
+
+  const YGNodeRef root_child2 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexGrow(root_child2, 1);
+  YGNodeStyleSetWidth(root_child2, 10);
+  YGNodeInsertChild(root, root_child2, 2);
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(320, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(107, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(107, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(106, YGNodeLayoutGetHeight(root_child1));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child1_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child1_child0));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetWidth(root_child1_child0));
+  ASSERT_FLOAT_EQ(106, YGNodeLayoutGetHeight(root_child1_child0));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child2));
+  ASSERT_FLOAT_EQ(213, YGNodeLayoutGetTop(root_child2));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetWidth(root_child2));
+  ASSERT_FLOAT_EQ(107, YGNodeLayoutGetHeight(root_child2));
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(320, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(107, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(107, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(106, YGNodeLayoutGetHeight(root_child1));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child1_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child1_child0));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetWidth(root_child1_child0));
+  ASSERT_FLOAT_EQ(106, YGNodeLayoutGetHeight(root_child1_child0));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child2));
+  ASSERT_FLOAT_EQ(213, YGNodeLayoutGetTop(root_child2));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetWidth(root_child2));
+  ASSERT_FLOAT_EQ(107, YGNodeLayoutGetHeight(root_child2));
+
+  YGNodeFreeRecursive(root);
+
+  YGConfigFree(config);
+}
+
+TEST(YogaTest, rounding_inner_node_controversy_combined) {
+  const YGConfigRef config = YGConfigNew();
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexDirection(root, YGFlexDirectionRow);
+  YGNodeStyleSetWidth(root, 640);
+  YGNodeStyleSetHeight(root, 320);
+
+  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexGrow(root_child0, 1);
+  YGNodeStyleSetHeightPercent(root_child0, 100);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  const YGNodeRef root_child1 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexGrow(root_child1, 1);
+  YGNodeStyleSetHeightPercent(root_child1, 100);
+  YGNodeInsertChild(root, root_child1, 1);
+
+  const YGNodeRef root_child1_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexGrow(root_child1_child0, 1);
+  YGNodeStyleSetWidthPercent(root_child1_child0, 100);
+  YGNodeInsertChild(root_child1, root_child1_child0, 0);
+
+  const YGNodeRef root_child1_child1 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexGrow(root_child1_child1, 1);
+  YGNodeStyleSetWidthPercent(root_child1_child1, 100);
+  YGNodeInsertChild(root_child1, root_child1_child1, 1);
+
+  const YGNodeRef root_child1_child1_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexGrow(root_child1_child1_child0, 1);
+  YGNodeStyleSetWidthPercent(root_child1_child1_child0, 100);
+  YGNodeInsertChild(root_child1_child1, root_child1_child1_child0, 0);
+
+  const YGNodeRef root_child1_child2 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexGrow(root_child1_child2, 1);
+  YGNodeStyleSetWidthPercent(root_child1_child2, 100);
+  YGNodeInsertChild(root_child1, root_child1_child2, 2);
+
+  const YGNodeRef root_child2 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetFlexGrow(root_child2, 1);
+  YGNodeStyleSetHeightPercent(root_child2, 100);
+  YGNodeInsertChild(root, root_child2, 2);
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(640, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(320, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(213, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(320, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(213, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(214, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(320, YGNodeLayoutGetHeight(root_child1));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child1_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child1_child0));
+  ASSERT_FLOAT_EQ(214, YGNodeLayoutGetWidth(root_child1_child0));
+  ASSERT_FLOAT_EQ(107, YGNodeLayoutGetHeight(root_child1_child0));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child1_child1));
+  ASSERT_FLOAT_EQ(107, YGNodeLayoutGetTop(root_child1_child1));
+  ASSERT_FLOAT_EQ(214, YGNodeLayoutGetWidth(root_child1_child1));
+  ASSERT_FLOAT_EQ(106, YGNodeLayoutGetHeight(root_child1_child1));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child1_child1_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child1_child1_child0));
+  ASSERT_FLOAT_EQ(214, YGNodeLayoutGetWidth(root_child1_child1_child0));
+  ASSERT_FLOAT_EQ(106, YGNodeLayoutGetHeight(root_child1_child1_child0));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child1_child2));
+  ASSERT_FLOAT_EQ(213, YGNodeLayoutGetTop(root_child1_child2));
+  ASSERT_FLOAT_EQ(214, YGNodeLayoutGetWidth(root_child1_child2));
+  ASSERT_FLOAT_EQ(107, YGNodeLayoutGetHeight(root_child1_child2));
+
+  ASSERT_FLOAT_EQ(427, YGNodeLayoutGetLeft(root_child2));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child2));
+  ASSERT_FLOAT_EQ(213, YGNodeLayoutGetWidth(root_child2));
+  ASSERT_FLOAT_EQ(320, YGNodeLayoutGetHeight(root_child2));
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(640, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(320, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(427, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(213, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(320, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(213, YGNodeLayoutGetLeft(root_child1));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child1));
+  ASSERT_FLOAT_EQ(214, YGNodeLayoutGetWidth(root_child1));
+  ASSERT_FLOAT_EQ(320, YGNodeLayoutGetHeight(root_child1));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child1_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child1_child0));
+  ASSERT_FLOAT_EQ(214, YGNodeLayoutGetWidth(root_child1_child0));
+  ASSERT_FLOAT_EQ(107, YGNodeLayoutGetHeight(root_child1_child0));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child1_child1));
+  ASSERT_FLOAT_EQ(107, YGNodeLayoutGetTop(root_child1_child1));
+  ASSERT_FLOAT_EQ(214, YGNodeLayoutGetWidth(root_child1_child1));
+  ASSERT_FLOAT_EQ(106, YGNodeLayoutGetHeight(root_child1_child1));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child1_child1_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child1_child1_child0));
+  ASSERT_FLOAT_EQ(214, YGNodeLayoutGetWidth(root_child1_child1_child0));
+  ASSERT_FLOAT_EQ(106, YGNodeLayoutGetHeight(root_child1_child1_child0));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child1_child2));
+  ASSERT_FLOAT_EQ(213, YGNodeLayoutGetTop(root_child1_child2));
+  ASSERT_FLOAT_EQ(214, YGNodeLayoutGetWidth(root_child1_child2));
+  ASSERT_FLOAT_EQ(107, YGNodeLayoutGetHeight(root_child1_child2));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child2));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child2));
+  ASSERT_FLOAT_EQ(213, YGNodeLayoutGetWidth(root_child2));
+  ASSERT_FLOAT_EQ(320, YGNodeLayoutGetHeight(root_child2));
+
+  YGNodeFreeRecursive(root);
+
+  YGConfigFree(config);
+}
diff --git a/automated-tests/src/dali-toolkit-third-party/yoga/YGSizeOverflowTest.cpp b/automated-tests/src/dali-toolkit-third-party/yoga/YGSizeOverflowTest.cpp
new file mode 100644 (file)
index 0000000..3fbcb30
--- /dev/null
@@ -0,0 +1,173 @@
+/**
+ * Copyright (c) 2014-present, Facebook, Inc.
+ *
+ * This source code is licensed under the MIT license found in the
+ * LICENSE file in the root directory of this source tree.
+ */
+
+// @Generated by gentest/gentest.rb from gentest/fixtures/YGSizeOverflowTest.html
+
+#include <gtest/gtest.h>
+#include <yoga/Yoga.h>
+
+TEST(YogaTest, nested_overflowing_child) {
+  const YGConfigRef config = YGConfigNew();
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root, 100);
+  YGNodeStyleSetHeight(root, 100);
+
+  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  const YGNodeRef root_child0_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child0_child0, 200);
+  YGNodeStyleSetHeight(root_child0_child0, 200);
+  YGNodeInsertChild(root_child0, root_child0_child0, 0);
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(200, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0_child0));
+  ASSERT_FLOAT_EQ(200, YGNodeLayoutGetWidth(root_child0_child0));
+  ASSERT_FLOAT_EQ(200, YGNodeLayoutGetHeight(root_child0_child0));
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(200, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(-100, YGNodeLayoutGetLeft(root_child0_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0_child0));
+  ASSERT_FLOAT_EQ(200, YGNodeLayoutGetWidth(root_child0_child0));
+  ASSERT_FLOAT_EQ(200, YGNodeLayoutGetHeight(root_child0_child0));
+
+  YGNodeFreeRecursive(root);
+
+  YGConfigFree(config);
+}
+
+TEST(YogaTest, nested_overflowing_child_in_constraint_parent) {
+  const YGConfigRef config = YGConfigNew();
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root, 100);
+  YGNodeStyleSetHeight(root, 100);
+
+  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child0, 100);
+  YGNodeStyleSetHeight(root_child0, 100);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  const YGNodeRef root_child0_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child0_child0, 200);
+  YGNodeStyleSetHeight(root_child0_child0, 200);
+  YGNodeInsertChild(root_child0, root_child0_child0, 0);
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0_child0));
+  ASSERT_FLOAT_EQ(200, YGNodeLayoutGetWidth(root_child0_child0));
+  ASSERT_FLOAT_EQ(200, YGNodeLayoutGetHeight(root_child0_child0));
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(-100, YGNodeLayoutGetLeft(root_child0_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0_child0));
+  ASSERT_FLOAT_EQ(200, YGNodeLayoutGetWidth(root_child0_child0));
+  ASSERT_FLOAT_EQ(200, YGNodeLayoutGetHeight(root_child0_child0));
+
+  YGNodeFreeRecursive(root);
+
+  YGConfigFree(config);
+}
+
+TEST(YogaTest, parent_wrap_child_size_overflowing_parent) {
+  const YGConfigRef config = YGConfigNew();
+
+  const YGNodeRef root = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root, 100);
+  YGNodeStyleSetHeight(root, 100);
+
+  const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child0, 100);
+  YGNodeInsertChild(root, root_child0, 0);
+
+  const YGNodeRef root_child0_child0 = YGNodeNewWithConfig(config);
+  YGNodeStyleSetWidth(root_child0_child0, 100);
+  YGNodeStyleSetHeight(root_child0_child0, 200);
+  YGNodeInsertChild(root_child0, root_child0_child0, 0);
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(200, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0_child0));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child0_child0));
+  ASSERT_FLOAT_EQ(200, YGNodeLayoutGetHeight(root_child0_child0));
+
+  YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child0));
+  ASSERT_FLOAT_EQ(200, YGNodeLayoutGetHeight(root_child0));
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0_child0));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0_child0));
+  ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child0_child0));
+  ASSERT_FLOAT_EQ(200, YGNodeLayoutGetHeight(root_child0_child0));
+
+  YGNodeFreeRecursive(root);
+
+  YGConfigFree(config);
+}
diff --git a/automated-tests/src/dali-toolkit-third-party/yoga/YGStyleTest.cpp b/automated-tests/src/dali-toolkit-third-party/yoga/YGStyleTest.cpp
new file mode 100644 (file)
index 0000000..08b7be2
--- /dev/null
@@ -0,0 +1,82 @@
+/**
+ * Copyright (c) 2014-present, Facebook, Inc.
+ *
+ * This source code is licensed under the MIT license found in the
+ * LICENSE file in the root directory of this source tree.
+ */
+
+#include <gtest/gtest.h>
+#include <yoga/YGNode.h>
+#include <iostream>
+
+TEST(YogaTest, copy_style_same) {
+  const YGNodeRef node0 = YGNodeNew();
+  const YGNodeRef node1 = YGNodeNew();
+  ASSERT_FALSE(node0->isDirty());
+
+  YGNodeCopyStyle(node0, node1);
+  ASSERT_FALSE(node0->isDirty());
+
+  YGNodeFree(node0);
+  YGNodeFree(node1);
+}
+
+TEST(YogaTest, copy_style_modified) {
+  const YGNodeRef node0 = YGNodeNew();
+  ASSERT_FALSE(node0->isDirty());
+  ASSERT_EQ(YGFlexDirectionColumn, YGNodeStyleGetFlexDirection(node0));
+  ASSERT_FALSE(YGNodeStyleGetMaxHeight(node0).unit != YGUnitUndefined);
+
+  const YGNodeRef node1 = YGNodeNew();
+  YGNodeStyleSetFlexDirection(node1, YGFlexDirectionRow);
+  YGNodeStyleSetMaxHeight(node1, 10);
+
+  YGNodeCopyStyle(node0, node1);
+  ASSERT_TRUE(node0->isDirty());
+  ASSERT_EQ(YGFlexDirectionRow, YGNodeStyleGetFlexDirection(node0));
+  ASSERT_FLOAT_EQ(10, YGNodeStyleGetMaxHeight(node0).value);
+
+  YGNodeFree(node0);
+  YGNodeFree(node1);
+}
+
+TEST(YogaTest, copy_style_modified_same) {
+  const YGNodeRef node0 = YGNodeNew();
+  YGNodeStyleSetFlexDirection(node0, YGFlexDirectionRow);
+  YGNodeStyleSetMaxHeight(node0, 10);
+  YGNodeCalculateLayout(node0, YGUndefined, YGUndefined, YGDirectionLTR);
+  ASSERT_FALSE(node0->isDirty());
+
+  const YGNodeRef node1 = YGNodeNew();
+  YGNodeStyleSetFlexDirection(node1, YGFlexDirectionRow);
+  YGNodeStyleSetMaxHeight(node1, 10);
+
+  YGNodeCopyStyle(node0, node1);
+  ASSERT_FALSE(node0->isDirty());
+
+  YGNodeFree(node0);
+  YGNodeFree(node1);
+}
+
+TEST(YogaTest, initialise_flexShrink_flexGrow) {
+  const YGNodeRef node0 = YGNodeNew();
+  YGNodeStyleSetFlexShrink(node0, 1);
+  ASSERT_EQ(1, YGNodeStyleGetFlexShrink(node0));
+
+  YGNodeStyleSetFlexShrink(node0, YGUndefined);
+  YGNodeStyleSetFlexGrow(node0, 3);
+  ASSERT_EQ(
+      0,
+      YGNodeStyleGetFlexShrink(
+          node0)); // Default value is Zero, if flex shrink is not defined
+  ASSERT_EQ(3, YGNodeStyleGetFlexGrow(node0));
+
+  YGNodeStyleSetFlexGrow(node0, YGUndefined);
+  YGNodeStyleSetFlexShrink(node0, 3);
+  ASSERT_EQ(
+      0,
+      YGNodeStyleGetFlexGrow(
+          node0)); // Default value is Zero, if flex grow is not defined
+  ASSERT_EQ(3, YGNodeStyleGetFlexShrink(node0));
+  YGNodeFree(node0);
+}
diff --git a/automated-tests/src/dali-toolkit-third-party/yoga/YGTraversalTest.cpp b/automated-tests/src/dali-toolkit-third-party/yoga/YGTraversalTest.cpp
new file mode 100644 (file)
index 0000000..3c4771d
--- /dev/null
@@ -0,0 +1,34 @@
+/**
+ * Copyright (c) 2014-present, Facebook, Inc.
+ *
+ * This source code is licensed under the MIT license found in the
+ * LICENSE file in the root directory of this source tree.
+ */
+
+#include <gtest/gtest.h>
+#include <yoga/Yoga.h>
+
+TEST(YogaTest, pre_order_traversal) {
+  YGNodeRef const root = YGNodeNew();
+  YGNodeRef const root_child0 = YGNodeNew();
+  YGNodeRef const root_child1 = YGNodeNew();
+  YGNodeRef const root_child0_child0 = YGNodeNew();
+  
+  YGNodeSetChildren(root, {root_child0, root_child1});
+  YGNodeInsertChild(root_child0, root_child0_child0, 0);
+  
+  std::vector<YGNodeRef> visited;
+  YGTraversePreOrder(root, [&visited](YGNodeRef node) {
+    visited.push_back(node);
+  });
+  
+  const std::vector<YGNodeRef> expected = {
+    root,
+    root_child0,
+    root_child0_child0,
+    root_child1
+  };
+  ASSERT_EQ(visited, expected);
+
+  YGNodeFreeRecursive(root);
+}
diff --git a/automated-tests/src/dali-toolkit-third-party/yoga/YGTreeMutationTest.cpp b/automated-tests/src/dali-toolkit-third-party/yoga/YGTreeMutationTest.cpp
new file mode 100644 (file)
index 0000000..273f22a
--- /dev/null
@@ -0,0 +1,111 @@
+/**
+ * Copyright (c) 2014-present, Facebook, Inc.
+ *
+ * This source code is licensed under the MIT license found in the
+ * LICENSE file in the root directory of this source tree.
+ */
+
+#include <gtest/gtest.h>
+#include <yoga/Yoga.h>
+
+static std::vector<YGNodeRef> getChildren(YGNodeRef const node)
+{
+  const uint32_t count = YGNodeGetChildCount(node);
+  std::vector<YGNodeRef> children;
+  children.reserve(count);
+  for (uint32_t i = 0 ; i < count ; i++) {
+    children.push_back(YGNodeGetChild(node, i));
+  }
+  return children;
+}
+
+TEST(YogaTest, set_children_adds_children_to_parent) {
+  YGNodeRef const root = YGNodeNew();
+  YGNodeRef const root_child0 = YGNodeNew();
+  YGNodeRef const root_child1 = YGNodeNew();
+
+  YGNodeSetChildren(root, {root_child0, root_child1});
+
+  const std::vector<YGNodeRef> children = getChildren(root);
+  const std::vector<YGNodeRef> expectedChildren = {root_child0, root_child1};
+  ASSERT_EQ(children, expectedChildren);
+
+  const std::vector<YGNodeRef> owners = {YGNodeGetOwner(root_child0), YGNodeGetOwner(root_child1)};
+  const std::vector<YGNodeRef> expectedOwners = {root, root};
+  ASSERT_EQ(owners, expectedOwners);
+
+  YGNodeFreeRecursive(root);
+}
+
+TEST(YogaTest, set_children_to_empty_removes_old_children) {
+  YGNodeRef const root = YGNodeNew();
+  YGNodeRef const root_child0 = YGNodeNew();
+  YGNodeRef const root_child1 = YGNodeNew();
+
+  YGNodeSetChildren(root, {root_child0, root_child1});
+  YGNodeSetChildren(root, {});
+
+  const std::vector<YGNodeRef> children = getChildren(root);
+  const std::vector<YGNodeRef> expectedChildren = {};
+  ASSERT_EQ(children, expectedChildren);
+
+  const std::vector<YGNodeRef> owners = {YGNodeGetOwner(root_child0), YGNodeGetOwner(root_child1)};
+  const std::vector<YGNodeRef> expectedOwners = {nullptr, nullptr};
+  ASSERT_EQ(owners, expectedOwners);
+
+  YGNodeFreeRecursive(root);
+}
+
+TEST(YogaTest, set_children_replaces_non_common_children) {
+  YGNodeRef const root = YGNodeNew();
+  YGNodeRef const root_child0 = YGNodeNew();
+  YGNodeRef const root_child1 = YGNodeNew();
+
+  YGNodeSetChildren(root, {root_child0, root_child1});
+
+  YGNodeRef const root_child2 = YGNodeNew();
+  YGNodeRef const root_child3 = YGNodeNew();
+
+  YGNodeSetChildren(root, {root_child2, root_child3});
+
+  const std::vector<YGNodeRef> children = getChildren(root);
+  const std::vector<YGNodeRef> expectedChildren = {root_child2, root_child3};
+  ASSERT_EQ(children, expectedChildren);
+
+  const std::vector<YGNodeRef> owners = {YGNodeGetOwner(root_child0), YGNodeGetOwner(root_child1)};
+  const std::vector<YGNodeRef> expectedOwners = {nullptr, nullptr};
+  ASSERT_EQ(owners, expectedOwners);
+
+  YGNodeFreeRecursive(root);
+  YGNodeFree(root_child0);
+  YGNodeFree(root_child1);
+}
+
+TEST(YogaTest, set_children_keeps_and_reorders_common_children) {
+  YGNodeRef const root = YGNodeNew();
+  YGNodeRef const root_child0 = YGNodeNew();
+  YGNodeRef const root_child1 = YGNodeNew();
+  YGNodeRef const root_child2 = YGNodeNew();
+
+  YGNodeSetChildren(root, {root_child0, root_child1, root_child2});
+
+  YGNodeRef const root_child3 = YGNodeNew();
+
+  YGNodeSetChildren(root, {root_child2, root_child1, root_child3});
+
+  const std::vector<YGNodeRef> children = getChildren(root);
+  const std::vector<YGNodeRef> expectedChildren = {root_child2, root_child1, root_child3};
+  ASSERT_EQ(children, expectedChildren);
+
+  const std::vector<YGNodeRef> owners = {
+    YGNodeGetOwner(root_child0),
+    YGNodeGetOwner(root_child1),
+    YGNodeGetOwner(root_child2),
+    YGNodeGetOwner(root_child3)
+  };
+  const std::vector<YGNodeRef> expectedOwners = {nullptr, root, root, root};
+  ASSERT_EQ(owners, expectedOwners);
+
+  YGNodeFreeRecursive(root);
+  YGNodeFree(root_child0);
+}
diff --git a/automated-tests/src/dali-toolkit-third-party/yoga/YGZeroOutLayoutRecursivlyTest.cpp b/automated-tests/src/dali-toolkit-third-party/yoga/YGZeroOutLayoutRecursivlyTest.cpp
new file mode 100644 (file)
index 0000000..92e7c8a
--- /dev/null
@@ -0,0 +1,37 @@
+/**
+ * Copyright (c) 2014-present, Facebook, Inc.
+ *
+ * This source code is licensed under the MIT license found in the
+ * LICENSE file in the root directory of this source tree.
+ */
+
+#include <gtest/gtest.h>
+#include <yoga/Yoga.h>
+
+TEST(YogaTest, zero_out_layout) {
+  const YGNodeRef root = YGNodeNew();
+  YGNodeStyleSetFlexDirection(root, YGFlexDirectionRow);
+  YGNodeStyleSetWidth(root, 200);
+  YGNodeStyleSetHeight(root, 200);
+
+  const YGNodeRef child = YGNodeNew();
+  YGNodeInsertChild(root, child, 0);
+  YGNodeStyleSetWidth(child, 100);
+  YGNodeStyleSetHeight(child, 100);
+  YGNodeStyleSetMargin(child, YGEdgeTop, 10);
+  YGNodeStyleSetPadding(child, YGEdgeTop, 10);
+
+  YGNodeCalculateLayout(root, 100, 100, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetMargin(child, YGEdgeTop));
+  ASSERT_FLOAT_EQ(10, YGNodeLayoutGetPadding(child, YGEdgeTop));
+
+  YGNodeStyleSetDisplay(child, YGDisplayNone);
+
+  YGNodeCalculateLayout(root, 100, 100, YGDirectionLTR);
+
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetMargin(child, YGEdgeTop));
+  ASSERT_FLOAT_EQ(0, YGNodeLayoutGetPadding(child, YGEdgeTop));
+
+  YGNodeFreeRecursive(root);
+}
index c754d35..a839b3f 100755 (executable)
@@ -7,110 +7,110 @@ SET(CAPI_LIB "dali-toolkit")
 
 # List of test case sources (Only these get parsed for test cases)
 SET(TC_SOURCES
-   utc-Dali-Alignment.cpp
-   utc-Dali-AnimatedImageVisual.cpp
-   utc-Dali-BloomView.cpp
-   utc-Dali-BubbleEmitter.cpp
-   utc-Dali-Builder.cpp
-   utc-Dali-CheckBoxButton.cpp
-   utc-Dali-ConfirmationPopup.cpp
-   utc-Dali-CubeTransitionEffect.cpp
-   utc-Dali-EffectsView.cpp
-   utc-Dali-FlexContainer.cpp
-   utc-Dali-GaussianBlurView.cpp
-   utc-Dali-ImageView.cpp
-   utc-Dali-ImageVisual.cpp
-   utc-Dali-JsonParser.cpp
-   utc-Dali-KeyInputFocusManager.cpp
-   utc-Dali-PageTurnView.cpp
-   utc-Dali-Script.cpp
-   utc-Dali-ScrollBar.cpp
-   utc-Dali-ScrollView.cpp
-   utc-Dali-ShaderEffects.cpp
-   utc-Dali-ShadowView.cpp
-   utc-Dali-Slider.cpp
-   utc-Dali-TableView.cpp
-   utc-Dali-TextEditor.cpp
-   utc-Dali-TextField.cpp
-   utc-Dali-TextLabel.cpp
-   utc-Dali-TextSelectionPopup.cpp
-   utc-Dali-TextSelectionPopupMirroringLTR.cpp
-   utc-Dali-TextSelectionPopupMirroringRTL.cpp
-   utc-Dali-TextureManager.cpp
-   utc-Dali-ToolBar.cpp
-   utc-Dali-Tooltip.cpp
-   utc-Dali-TransitionData.cpp
-   utc-Dali-Button.cpp
-   utc-Dali-Control.cpp
-   utc-Dali-ControlImpl.cpp
-   utc-Dali-AccessibilityManager.cpp
-   utc-Dali-ItemLayout.cpp
-   utc-Dali-ItemView.cpp
-   utc-Dali-KeyboardFocusManager.cpp
-   utc-Dali-Magnifier.cpp
-   utc-Dali-NavigationView.cpp
-   utc-Dali-Popup.cpp
-   utc-Dali-ProgressBar.cpp
-   utc-Dali-PushButton.cpp
-   utc-Dali-RadioButton.cpp
-   utc-Dali-ToggleButton.cpp
-   utc-Dali-ScrollViewEffect.cpp
-   utc-Dali-SuperBlurView.cpp
-   utc-Dali-Toolkit.cpp
-   utc-Dali-Model3dView.cpp
-   utc-Dali-Visual.cpp
-   utc-Dali-VisualFactory.cpp
-   utc-Dali-ImageAtlas.cpp
-   utc-Dali-VideoView.cpp
-   utc-Dali-AsyncImageLoader.cpp
-   utc-Dali-SyncImageLoader.cpp
-   utc-Dali-ControlWrapper.cpp
+  utc-Dali-Layouting.cpp
+  utc-Dali-Alignment.cpp
+  utc-Dali-AnimatedImageVisual.cpp
+  utc-Dali-BloomView.cpp
+  utc-Dali-BubbleEmitter.cpp
+  utc-Dali-Builder.cpp
+  utc-Dali-CheckBoxButton.cpp
+  utc-Dali-ConfirmationPopup.cpp
+  utc-Dali-CubeTransitionEffect.cpp
+  utc-Dali-EffectsView.cpp
+  utc-Dali-FlexContainer.cpp
+  utc-Dali-GaussianBlurView.cpp
+  utc-Dali-ImageView.cpp
+  utc-Dali-ImageVisual.cpp
+  utc-Dali-JsonParser.cpp
+  utc-Dali-KeyInputFocusManager.cpp
+  utc-Dali-PageTurnView.cpp
+  utc-Dali-Script.cpp
+  utc-Dali-ScrollBar.cpp
+  utc-Dali-ScrollView.cpp
+  utc-Dali-ShaderEffects.cpp
+  utc-Dali-ShadowView.cpp
+  utc-Dali-Slider.cpp
+  utc-Dali-TableView.cpp
+  utc-Dali-TextEditor.cpp
+  utc-Dali-TextField.cpp
+  utc-Dali-TextLabel.cpp
+  utc-Dali-TextSelectionPopup.cpp
+  utc-Dali-TextSelectionPopupMirroringLTR.cpp
+  utc-Dali-TextSelectionPopupMirroringRTL.cpp
+  utc-Dali-TextureManager.cpp
+  utc-Dali-ToolBar.cpp
+  utc-Dali-Tooltip.cpp
+  utc-Dali-TransitionData.cpp
+  utc-Dali-Button.cpp
+  utc-Dali-Control.cpp
+  utc-Dali-ControlImpl.cpp
+  utc-Dali-AccessibilityManager.cpp
+  utc-Dali-ItemLayout.cpp
+  utc-Dali-ItemView.cpp
+  utc-Dali-KeyboardFocusManager.cpp
+  utc-Dali-Magnifier.cpp
+  utc-Dali-NavigationView.cpp
+  utc-Dali-Popup.cpp
+  utc-Dali-ProgressBar.cpp
+  utc-Dali-PushButton.cpp
+  utc-Dali-RadioButton.cpp
+  utc-Dali-ToggleButton.cpp
+  utc-Dali-ScrollViewEffect.cpp
+  utc-Dali-SuperBlurView.cpp
+  utc-Dali-Toolkit.cpp
+  utc-Dali-Model3dView.cpp
+  utc-Dali-Visual.cpp
+  utc-Dali-VisualFactory.cpp
+  utc-Dali-ImageAtlas.cpp
+  utc-Dali-VideoView.cpp
+  utc-Dali-AsyncImageLoader.cpp
+  utc-Dali-SyncImageLoader.cpp
+  utc-Dali-ControlWrapper.cpp
 )
 
 # Append list of test harness files (Won't get parsed for test cases)
 LIST(APPEND TC_SOURCES
-   dali-toolkit-test-utils/toolkit-adaptor.cpp
-   dali-toolkit-test-utils/toolkit-accessibility-adaptor.cpp
-   dali-toolkit-test-utils/toolkit-application.cpp
-   dali-toolkit-test-utils/toolkit-clipboard.cpp
-   dali-toolkit-test-utils/toolkit-clipboard-event-notifier.cpp
-   dali-toolkit-test-utils/toolkit-event-thread-callback.cpp
-   dali-toolkit-test-utils/toolkit-environment-variable.cpp
-   dali-toolkit-test-utils/toolkit-input-method-context.cpp
-   dali-toolkit-test-utils/toolkit-orientation.cpp
-   dali-toolkit-test-utils/toolkit-physical-keyboard.cpp
-   dali-toolkit-test-utils/toolkit-style-monitor.cpp
-   dali-toolkit-test-utils/toolkit-singleton-service.cpp
-   dali-toolkit-test-utils/toolkit-timer.cpp
-   dali-toolkit-test-utils/toolkit-tts-player.cpp
-   dali-toolkit-test-utils/toolkit-native-image-source.cpp
-   dali-toolkit-test-utils/toolkit-video-player.cpp
-   dali-toolkit-test-utils/toolkit-trigger-event-factory.cpp
-   dali-toolkit-test-utils/dali-test-suite-utils.cpp
-   dali-toolkit-test-utils/dummy-control.cpp
-   dali-toolkit-test-utils/mesh-builder.cpp
-   dali-toolkit-test-utils/test-actor-utils.cpp
-   dali-toolkit-test-utils/test-animation-data.cpp
-   dali-toolkit-test-utils/test-application.cpp
-   dali-toolkit-test-utils/test-button.cpp
-   dali-toolkit-test-utils/test-harness.cpp
-   dali-toolkit-test-utils/test-gesture-manager.cpp
-   dali-toolkit-test-utils/test-gl-abstraction.cpp
-   dali-toolkit-test-utils/test-gl-sync-abstraction.cpp
-   dali-toolkit-test-utils/test-platform-abstraction.cpp
-   dali-toolkit-test-utils/test-render-controller.cpp
-   dali-toolkit-test-utils/test-trace-call-stack.cpp
-   dali-toolkit-test-utils/test-native-image.cpp
+  dali-toolkit-test-utils/toolkit-adaptor.cpp
+  dali-toolkit-test-utils/toolkit-accessibility-adaptor.cpp
+  dali-toolkit-test-utils/toolkit-application.cpp
+  dali-toolkit-test-utils/toolkit-clipboard.cpp
+  dali-toolkit-test-utils/toolkit-clipboard-event-notifier.cpp
+  dali-toolkit-test-utils/toolkit-event-thread-callback.cpp
+  dali-toolkit-test-utils/toolkit-environment-variable.cpp
+  dali-toolkit-test-utils/toolkit-input-method-context.cpp
+  dali-toolkit-test-utils/toolkit-orientation.cpp
+  dali-toolkit-test-utils/toolkit-physical-keyboard.cpp
+  dali-toolkit-test-utils/toolkit-style-monitor.cpp
+  dali-toolkit-test-utils/toolkit-singleton-service.cpp
+  dali-toolkit-test-utils/toolkit-timer.cpp
+  dali-toolkit-test-utils/toolkit-tts-player.cpp
+  dali-toolkit-test-utils/toolkit-native-image-source.cpp
+  dali-toolkit-test-utils/toolkit-video-player.cpp
+  dali-toolkit-test-utils/toolkit-trigger-event-factory.cpp
+  dali-toolkit-test-utils/dali-test-suite-utils.cpp
+  dali-toolkit-test-utils/dummy-control.cpp
+  dali-toolkit-test-utils/mesh-builder.cpp
+  dali-toolkit-test-utils/test-actor-utils.cpp
+  dali-toolkit-test-utils/test-animation-data.cpp
+  dali-toolkit-test-utils/test-application.cpp
+  dali-toolkit-test-utils/test-button.cpp
+  dali-toolkit-test-utils/test-harness.cpp
+  dali-toolkit-test-utils/test-gesture-manager.cpp
+  dali-toolkit-test-utils/test-gl-abstraction.cpp
+  dali-toolkit-test-utils/test-gl-sync-abstraction.cpp
+  dali-toolkit-test-utils/test-platform-abstraction.cpp
+  dali-toolkit-test-utils/test-render-controller.cpp
+  dali-toolkit-test-utils/test-trace-call-stack.cpp
+  dali-toolkit-test-utils/test-native-image.cpp
 )
 
-
 PKG_CHECK_MODULES(${CAPI_LIB} REQUIRED
-    dali-core
-    dali-adaptor
-    dali-toolkit
+  dali-core
+  dali-adaptor
+  dali-toolkit
 )
 
-ADD_COMPILE_OPTIONS( -O0 -ggdb --coverage -Wall -Werror )
+ADD_COMPILE_OPTIONS( -O0 -ggdb --coverage -Wall -Werror -DDEBUG_ENABLED)
 ADD_COMPILE_OPTIONS( ${${CAPI_LIB}_CFLAGS_OTHER} )
 
 ADD_DEFINITIONS(-DTEST_RESOURCE_DIR=\"${CMAKE_CURRENT_SOURCE_DIR}/../../resources\" )
index 747b488..6b8b236 100644 (file)
@@ -2,7 +2,7 @@
 #define __DALI_TEST_APPLICATION_H__
 
 /*
- * Copyright (c) 2017 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2018 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -31,7 +31,7 @@
 namespace Dali
 {
 
-class DALI_IMPORT_API TestApplication : public ConnectionTracker
+class DALI_CORE_API TestApplication : public ConnectionTracker
 {
 public:
 
index 4c0b766..6fddd30 100644 (file)
@@ -2,7 +2,7 @@
 #define __DALI_TEST_GESTURE_MANAGER_H__
 
 /*
- * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2018 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -28,7 +28,7 @@ namespace Dali
 /**
  * Concrete implementation of the gesture manager class.
  */
-class DALI_IMPORT_API TestGestureManager : public Dali::Integration::GestureManager
+class DALI_CORE_API TestGestureManager : public Dali::Integration::GestureManager
 {
 
 public:
index b306c3e..c68573b 100644 (file)
@@ -2,7 +2,7 @@
 #define TEST_GL_ABSTRACTION_H
 
 /*
- * Copyright (c) 2017 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2018 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -49,7 +49,7 @@ static const char *mStdAttribs[MAX_ATTRIBUTE_CACHE_SIZE] =
     "aBoneIndices"  // ATTRIB_BONE_INDICES
 };
 
-class DALI_IMPORT_API TestGlAbstraction: public Dali::Integration::GlAbstraction
+class DALI_CORE_API TestGlAbstraction: public Dali::Integration::GlAbstraction
 {
 public:
   TestGlAbstraction();
index 8ce96a4..979987b 100644 (file)
@@ -2,7 +2,7 @@
 #define __TEST_GL_SYNC_ABSTRACTION_H__
 
 /*
- * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2018 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -31,7 +31,7 @@
 namespace Dali
 {
 
-class DALI_IMPORT_API TestSyncObject : public Integration::GlSyncAbstraction::SyncObject
+class DALI_CORE_API TestSyncObject : public Integration::GlSyncAbstraction::SyncObject
 {
 public:
   TestSyncObject(TraceCallStack& trace);
@@ -44,7 +44,7 @@ public:
 /**
  * Class to emulate the GL sync functions with tracing
  */
-class DALI_IMPORT_API TestGlSyncAbstraction: public Integration::GlSyncAbstraction
+class DALI_CORE_API TestGlSyncAbstraction: public Integration::GlSyncAbstraction
 {
 public:
   /**
index 896ce52..5cb4b27 100644 (file)
@@ -2,7 +2,7 @@
 #define __TEST_NATIVE_IMAGE_H__
 
 /*
- * Copyright (c) 2017 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2018 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -30,7 +30,7 @@ class TestNativeImageNoExt;
 typedef IntrusivePtr<TestNativeImage> TestNativeImagePointer;
 typedef IntrusivePtr<TestNativeImageNoExt> TestNativeImageNoExtPointer;
 
-class DALI_IMPORT_API TestNativeImageExtension: public Dali::NativeImageInterface::Extension
+class DALI_CORE_API TestNativeImageExtension: public Dali::NativeImageInterface::Extension
 {
 public:
   inline const char* GetCustomFragmentPreFix(){return "#extension GL_OES_EGL_image_external:require\n";}
@@ -40,7 +40,7 @@ public:
 
 };
 
-class DALI_IMPORT_API TestNativeImage : public Dali::NativeImageInterface
+class DALI_CORE_API TestNativeImage : public Dali::NativeImageInterface
 {
 public:
   static TestNativeImagePointer New(int width, int height);
@@ -71,7 +71,7 @@ public:
 };
 
 
-class DALI_IMPORT_API TestNativeImageNoExt : public Dali::NativeImageInterface
+class DALI_CORE_API TestNativeImageNoExt : public Dali::NativeImageInterface
 {
 public:
   static TestNativeImageNoExtPointer New(int width, int height);
index 201e29d..f31561e 100644 (file)
@@ -2,7 +2,7 @@
 #define __DALI_TEST_PLATFORM_ABSTRACTION_H__
 
 /*
- * Copyright (c) 2017 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2018 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -36,7 +36,7 @@ namespace Dali
 /**
  * Concrete implementation of the platform abstraction class.
  */
-class DALI_IMPORT_API TestPlatformAbstraction : public Dali::Integration::PlatformAbstraction
+class DALI_CORE_API TestPlatformAbstraction : public Dali::Integration::PlatformAbstraction
 {
 
 public:
index 3ad63d3..7c785f1 100644 (file)
@@ -2,7 +2,7 @@
 #define __TEST_RENDER_CONTROLLER_H__
 
 /*
- * Copyright (c) 2017 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2018 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -25,7 +25,7 @@
 namespace Dali
 {
 
-class DALI_IMPORT_API TestRenderController : public Dali::Integration::RenderController
+class DALI_CORE_API TestRenderController : public Dali::Integration::RenderController
 {
 public:
   TestRenderController();
index ce17641..271d6ec 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2018 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -17,7 +17,7 @@
 
 #include "toolkit-application.h"
 
-#include <dali/public-api/common/dali-common.h>
+#include <dali-toolkit/public-api/dali-toolkit-common.h>
 #include <dali/public-api/signals/dali-signal.h>
 #include <dali/devel-api/adaptor-framework/orientation.h>
 
index a9f7956..cbfe93e 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2018 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -17,7 +17,7 @@
 
 #include "toolkit-clipboard-event-notifier.h"
 
-#include <dali/public-api/common/dali-common.h>
+#include <dali-toolkit/public-api/dali-toolkit-common.h>
 #include <dali/public-api/object/base-object.h>
 #include <dali/public-api/signals/dali-signal.h>
 
index 0f9cb42..aa13ef0 100644 (file)
@@ -2,7 +2,7 @@
 #define  __TOOLKIT_CLIPBOARD_H__
 
 /*
- * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2018 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
index d718e10..f3dc134 100644 (file)
@@ -2,7 +2,7 @@
 #define __DALI_TOOLKIT_EVENT_THREAD_CALLBACK_H__
 
 /*
- * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2018 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
 #define __DALI_EVENT_THREAD_CALLBACK_H_
 
 // EXTERNAL INCLUDES
-#include <dali/public-api/common/dali-common.h>
+#include <dali-toolkit/public-api/dali-toolkit-common.h>
 #include <dali/public-api/signals/callback.h>
 
 namespace Dali
 {
 
-class DALI_IMPORT_API EventThreadCallback
+class DALI_TOOLKIT_API EventThreadCallback
 {
 public:
 
index 5cc6ad1..d1611c7 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2018 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -15,7 +15,7 @@
  */
 
 #include <string>
-#include <dali/public-api/common/dali-common.h>
+#include <dali-toolkit/public-api/dali-toolkit-common.h>
 #include <dali/public-api/object/base-handle.h>
 #include <dali/devel-api/adaptor-framework/file-loader.h>
 
index b1b5660..4018f37 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2018 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -17,7 +17,7 @@
 
 #include <dali/devel-api/adaptor-framework/orientation.h>
 
-#include <dali/public-api/common/dali-common.h>
+#include <dali-toolkit/public-api/dali-toolkit-common.h>
 #include <dali/public-api/object/base-object.h>
 #include <dali/public-api/signals/dali-signal.h>
 
index de4a86e..9cb217a 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2018 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -17,7 +17,7 @@
 
 #include "toolkit-physical-keyboard.h"
 
-#include <dali/public-api/common/dali-common.h>
+#include <dali-toolkit/public-api/dali-toolkit-common.h>
 #include <dali/public-api/object/base-object.h>
 #include <dali/public-api/signals/dali-signal.h>
 
index d8efd70..e8c2e8d 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2018 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -15,9 +15,9 @@
  *
  */
 
-#include <dali/devel-api/adaptor-framework/singleton-service.h>
+#include <toolkit-singleton-service.h>
 
-#include <dali/public-api/common/dali-common.h>
+#include <dali-toolkit/public-api/dali-toolkit-common.h>
 #include <dali/public-api/object/base-object.h>
 #include <dali/devel-api/common/map-wrapper.h>
 #include <dali/public-api/signals/dali-signal.h>
@@ -74,6 +74,13 @@ public:
     if( singleton )
     {
       mSingletonContainer.insert( SingletonPair( info.name(), singleton ) );
+
+      Integration::Processor* processor = dynamic_cast<Integration::Processor*>( &singleton.GetBaseObject() );
+      if( processor )
+      {
+        Integration::Core& core = mTestApplication->GetCore();
+        core.RegisterProcessor( *processor );
+      }
     }
   }
 
@@ -100,6 +107,11 @@ public:
     return object;
   }
 
+  void SetApplication( Dali::TestApplication& testApplication )
+  {
+    mTestApplication = &testApplication;
+  }
+
 private:
 
   /**
@@ -132,6 +144,7 @@ private:
   typedef SingletonContainer::const_iterator SingletonConstIter;
 
   SingletonContainer mSingletonContainer; ///< The container to look up singleton by its type name
+  TestApplication* mTestApplication;
 };
 
 } // namespace Adaptor
@@ -192,3 +205,14 @@ SingletonService::SingletonService( Internal::Adaptor::SingletonService* singlet
 }
 
 } // namespace Dali
+
+
+namespace Test
+{
+
+void SetApplication( Dali::SingletonService singletonService, TestApplication& testApplication )
+{
+  GetImplementation( singletonService ).SetApplication( testApplication );
+}
+
+} // Test
diff --git a/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/toolkit-singleton-service.h b/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/toolkit-singleton-service.h
new file mode 100644 (file)
index 0000000..7f57f55
--- /dev/null
@@ -0,0 +1,30 @@
+#ifndef DALI_TOOLKIT_TEST_SINGLETON_SERVICE_H
+#define DALI_TOOLKIT_TEST_SINGLETON_SERVICE_H
+
+/*
+ * Copyright (c) 2018 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <dali/devel-api/adaptor-framework/singleton-service.h>
+#include "test-application.h"
+
+namespace Test
+{
+
+void SetApplication( Dali::SingletonService singletonService, TestApplication& testApplication );
+
+} // Test
+
+#endif //DALI_TOOLKIT_TEST_SINGLETON_SERVICE_H
index a15a793..18c086f 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2018 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -19,7 +19,7 @@
 #include "toolkit-style-monitor.h"
 
 // EXTERNAL INCLUDES
-#include <dali/public-api/common/dali-common.h>
+#include <dali-toolkit/public-api/dali-toolkit-common.h>
 #include <dali/public-api/common/vector-wrapper.h>
 #include <dali/public-api/object/base-object.h>
 #include <dali/public-api/signals/dali-signal.h>
index 5cc5bef..1301b8f 100644 (file)
@@ -2,7 +2,7 @@
 #define __DALI_TOOLKIT_TEST_APPLICATION_H__
 
 /*
- * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2018 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -23,6 +23,7 @@
 #include <dali/devel-api/text-abstraction/font-client.h>
 #include <dali/integration-api/adaptors/adaptor.h>
 #include <toolkit-adaptor-impl.h>
+#include <toolkit-singleton-service.h>
 
 namespace Dali
 {
@@ -41,6 +42,8 @@ public:
   : TestApplication( false, surfaceWidth, surfaceHeight, horizontalDpi, verticalDpi )
   {
     Initialize();
+    auto singletonService = SingletonService::Get();
+    Test::SetApplication( singletonService, *this );
 
     // set the DPI value for font rendering
     Dali::TextAbstraction::FontClient fontClient = Dali::TextAbstraction::FontClient::Get();
index aff00f8..f9c89da 100644 (file)
@@ -18,7 +18,7 @@
 #include "toolkit-timer.h"
 
 // INTERNAL INCLUDES
-#include <dali/public-api/common/dali-common.h>
+#include <dali-toolkit/public-api/dali-toolkit-common.h>
 #include <dali/public-api/object/base-object.h>
 #include <dali/public-api/signals/dali-signal.h>
 
index 8b17338..5cbfc89 100644 (file)
@@ -890,6 +890,95 @@ int UtcDaliImageVisualAnimateOpacity(void)
   END_TEST;
 }
 
+
+
+int UtcDaliImageVisualAnimateOpacity02(void)
+{
+  ToolkitTestApplication application;
+  tet_infoline( "Animate image visual opacity" );
+
+  application.GetPlatform().SetClosestImageSize( Vector2(100, 100) );
+
+  VisualFactory factory = VisualFactory::Get();
+  Property::Map propertyMap;
+  propertyMap.Insert(Visual::Property::TYPE,  Visual::IMAGE);
+  propertyMap.Insert(ImageVisual::Property::URL, TEST_IMAGE_FILE_NAME );
+  propertyMap.Insert("opacity", 0.5f);
+  propertyMap.Insert(ImageVisual::Property::SYNCHRONOUS_LOADING, true);
+  Visual::Base visual = factory.CreateVisual( propertyMap );
+
+  DummyControl actor = DummyControl::New(true);
+  Impl::DummyControl& dummyImpl = static_cast<Impl::DummyControl&>(actor.GetImplementation());
+  dummyImpl.RegisterVisual( DummyControl::Property::TEST_VISUAL, visual );
+
+  actor.SetSize(2000, 2000);
+  actor.SetParentOrigin(ParentOrigin::CENTER);
+  actor.SetColor(Color::BLACK);
+
+  tet_infoline( "Test that the opacity doesn't animate when actor not staged" );
+
+  Property::Array array;
+
+  Property::Map map;
+  map["target"] = "testVisual";
+  map["property"] = "opacity";
+  map["initialValue"] = 0.0f;
+  map["targetValue"] = 1.0f;
+  map["animator"] = Property::Map()
+    .Add("alphaFunction", "LINEAR")
+    .Add("timePeriod", Property::Map()
+         .Add("delay", 0.0f)
+         .Add("duration", 4.0f));
+
+  Property::Map map2;
+  map2["target"] = "testVisual";
+  map2["property"] = "size";
+  map2["targetValue"] = Vector2(1.0f, 1.0f);
+
+  array.Add( map ).Add(map2);
+
+  Dali::Toolkit::TransitionData transition = TransitionData::New( array );
+  Animation animation = dummyImpl.CreateTransition( transition );
+
+  Stage::GetCurrent().Add(actor);
+  application.SendNotification();
+  application.Render(0);     // Ensure animation starts
+
+  DALI_TEST_EQUALS( actor.GetRendererCount(), 1u, TEST_LOCATION);
+
+  Renderer renderer = actor.GetRendererAt(0);
+  Property::Value blendModeValue = renderer.GetProperty( Renderer::Property::BLEND_MODE );
+  DALI_TEST_EQUALS( blendModeValue.Get<int>(), (int)BlendMode::AUTO, TEST_LOCATION );
+
+  animation = dummyImpl.CreateTransition( transition );
+  animation.Play();
+
+  application.SendNotification();
+  application.Render(0);     // Ensure animation starts
+  application.Render(2000u); // Halfway point through animation
+  application.SendNotification(); // Handle any signals
+
+  blendModeValue = renderer.GetProperty( Renderer::Property::BLEND_MODE );
+  DALI_TEST_EQUALS( blendModeValue.Get<int>(), (int)BlendMode::ON, TEST_LOCATION );
+
+  Vector4 color;
+  DALI_TEST_CHECK( application.GetGlAbstraction().GetUniformValue< Vector4 >( "uColor", color ) );
+  DALI_TEST_EQUALS( color.a, 0.5f, TEST_LOCATION );
+
+  application.Render(2001u); // end
+  application.SendNotification(); // ensure animation finished signal is sent
+
+  DALI_TEST_CHECK( application.GetGlAbstraction().GetUniformValue< Vector4 >( "uColor", color ) );
+  DALI_TEST_EQUALS( color.a, 1.0f, TEST_LOCATION );
+
+  blendModeValue = renderer.GetProperty( Renderer::Property::BLEND_MODE );
+  DALI_TEST_EQUALS( blendModeValue.Get<int>(), (int)BlendMode::AUTO, TEST_LOCATION );
+
+  END_TEST;
+}
+
+
+
 int UtcDaliImageVisualAnimatePixelArea(void)
 {
   ToolkitTestApplication application;
diff --git a/automated-tests/src/dali-toolkit/utc-Dali-Layouting.cpp b/automated-tests/src/dali-toolkit/utc-Dali-Layouting.cpp
new file mode 100644 (file)
index 0000000..989ad95
--- /dev/null
@@ -0,0 +1,613 @@
+/*
+ * Copyright (c) 2018 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <iostream>
+#include <stdlib.h>
+#include <dali-toolkit-test-suite-utils.h>
+#include <dali-toolkit/dali-toolkit.h>
+#include <dali/devel-api/adaptor-framework/pixel-buffer.h>
+#include <dali-toolkit/devel-api/image-loader/texture-manager.h>
+#include <dali-toolkit/devel-api/controls/control-devel.h>
+#include <dali-toolkit/devel-api/layouting/hbox-layout.h>
+#include <dali-toolkit/devel-api/layouting/vbox-layout.h>
+//#include <dali-toolkit/internal/controls/control/control-data-impl-debug.h>
+
+using namespace Dali;
+using namespace Toolkit;
+
+void utc_dali_toolkit_layouting_startup(void)
+{
+  test_return_value = TET_UNDEF;
+}
+
+void utc_dali_toolkit_layouting_cleanup(void)
+{
+  test_return_value = TET_PASS;
+}
+
+
+Control CreateLeafControl( int width, int height )
+{
+  auto control = Control::New();
+  control.SetName( "Leaf" );
+
+  auto pixelBuffer = Devel::PixelBuffer::New( 1, 1, Pixel::RGB888 );
+  unsigned char* pixels = pixelBuffer.GetBuffer();
+  pixels[0] = 0xff;
+  pixels[1] = 0x00;
+  pixels[2] = 0x00;
+  auto texture = Texture::New( TextureType::TEXTURE_2D, Pixel::RGB888, 1, 1 );
+  auto pixelData = Devel::PixelBuffer::Convert( pixelBuffer );
+  texture.Upload( pixelData );
+  std::string url = TextureManager::AddTexture( texture );
+
+  Property::Map map;
+  map[ Visual::Property::TYPE ] = Visual::IMAGE;
+  map[ ImageVisual::Property::URL ] = url;
+  map[ ImageVisual::Property::DESIRED_WIDTH ] = (float) width;
+  map[ ImageVisual::Property::DESIRED_HEIGHT ] = (float) height;
+  control.SetProperty( Control::Property::BACKGROUND, map );
+  return control;
+}
+
+int UtcDaliLayouting_HboxLayout01(void)
+{
+  ToolkitTestApplication application;
+  tet_infoline(" UtcDaliLayouting_HboxLayout01");
+
+  Stage stage = Stage::GetCurrent();
+  auto hbox = Control::New();
+  auto hboxLayout = HboxLayout::New();
+  hboxLayout.SetCellPadding( LayoutSize( 10, 0 ) );
+  DevelControl::SetLayout( hbox, hboxLayout );
+  hbox.SetName( "HBox");
+
+  std::vector< Control > controls;
+  controls.push_back( CreateLeafControl( 40, 40 ) );
+  controls.push_back( CreateLeafControl( 60, 40 ) );
+  controls.push_back( CreateLeafControl( 80, 40 ) );
+  controls.push_back( CreateLeafControl( 100, 40 ) );
+
+  for( auto&& iter : controls )
+  {
+    hbox.Add( iter );
+  }
+  hbox.SetParentOrigin( ParentOrigin::CENTER );
+  hbox.SetAnchorPoint( AnchorPoint::CENTER );
+  stage.Add( hbox );
+
+  // Ensure layouting happens
+  application.SendNotification();
+  application.Render();
+
+  // hbox centers elements vertically, it fills test harness stage, which is 480x800.
+  // hbox left justifies elements
+  DALI_TEST_EQUALS( controls[0].GetProperty<Vector3>( Actor::Property::POSITION ), Vector3( 0.0f, 380.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[1].GetProperty<Vector3>( Actor::Property::POSITION ), Vector3( 50.0f, 380.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[2].GetProperty<Vector3>( Actor::Property::POSITION ), Vector3( 120.0f, 380.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[3].GetProperty<Vector3>( Actor::Property::POSITION ), Vector3( 210.0f, 380.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+
+  DALI_TEST_EQUALS( controls[0].GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 40.0f, 40.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[1].GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 60.0f, 40.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[2].GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 80.0f, 40.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[3].GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 100.0f, 40.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+
+  END_TEST;
+}
+
+
+
+
+int UtcDaliLayouting_HboxLayout02(void)
+{
+  ToolkitTestApplication application;
+  tet_infoline(" UtcDaliLayouting_HboxLayout02 Test nested hboxes with default spec of WRAP_CONTENT");
+
+  Stage stage = Stage::GetCurrent();
+
+  auto hbox1 = Control::New();
+  auto hboxLayout1 = HboxLayout::New();
+  DevelControl::SetLayout( hbox1, hboxLayout1 );
+
+  auto hbox2 = Control::New();
+  auto hboxLayout2 = HboxLayout::New();
+  DevelControl::SetLayout( hbox2, hboxLayout2 );
+
+  hbox1.SetName( "HBox1");
+  hbox2.SetName( "HBox2");
+
+  std::vector< Control > controls;
+  controls.push_back( CreateLeafControl( 20, 40 ) );
+  controls.push_back( CreateLeafControl( 30, 50 ) );
+  controls.push_back( CreateLeafControl( 40, 60 ) );
+  controls.push_back( CreateLeafControl( 50, 70 ) );
+
+  controls.push_back( CreateLeafControl( 25, 40 ) );
+  controls.push_back( CreateLeafControl( 35, 50 ) );
+  controls.push_back( CreateLeafControl( 45, 60 ) );
+  controls.push_back( CreateLeafControl( 55, 70 ) );
+
+  int counter=0;
+  for( auto&& iter : controls )
+  {
+    if( counter < 4 )
+    {
+      hbox1.Add( iter );
+    }
+    else
+    {
+      hbox2.Add( iter );
+    }
+    ++counter;
+  }
+  hbox1.SetParentOrigin( ParentOrigin::CENTER );
+  hbox1.SetAnchorPoint( AnchorPoint::CENTER );
+  hbox2.SetParentOrigin( ParentOrigin::CENTER );
+  hbox2.SetAnchorPoint( AnchorPoint::CENTER );
+
+  auto hbox3 = Control::New();
+  auto hboxLayout3 = HboxLayout::New();
+  DevelControl::SetLayout( hbox3, hboxLayout3 );
+
+  hbox3.SetParentOrigin( ParentOrigin::CENTER );
+  hbox3.SetName( "HBox3");
+  hbox3.Add( hbox1 );
+  hbox3.Add( hbox2 );
+
+  stage.Add( hbox3 );
+
+  // Ensure layouting happens
+  application.SendNotification();
+  application.Render();
+
+
+  // hbox centers elements vertically, it fills test harness stage, which is 480x800.
+  // hbox left justifies elements
+  DALI_TEST_EQUALS( controls[0].GetProperty<Vector3>( Actor::Property::POSITION ), Vector3(  0.0f, 15.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[1].GetProperty<Vector3>( Actor::Property::POSITION ), Vector3( 20.0f, 10.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[2].GetProperty<Vector3>( Actor::Property::POSITION ), Vector3( 50.0f,  5.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[3].GetProperty<Vector3>( Actor::Property::POSITION ), Vector3( 90.0f,  0.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+
+  DALI_TEST_EQUALS( controls[0].GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 20.0f, 40.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[1].GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 30.0f, 50.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[2].GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 40.0f, 60.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[3].GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 50.0f, 70.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+
+
+  DALI_TEST_EQUALS( controls[4].GetProperty<Vector3>( Actor::Property::POSITION ), Vector3(  0.0f, 15.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[5].GetProperty<Vector3>( Actor::Property::POSITION ), Vector3( 25.0f, 10.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[6].GetProperty<Vector3>( Actor::Property::POSITION ), Vector3( 60.0f,  5.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[7].GetProperty<Vector3>( Actor::Property::POSITION ), Vector3( 105.0f,  0.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+
+  DALI_TEST_EQUALS( controls[4].GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 25.0f, 40.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[5].GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 35.0f, 50.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[6].GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 45.0f, 60.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[7].GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 55.0f, 70.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+
+  // Test hbox1 and 2 are sized to wrap their content
+  DALI_TEST_EQUALS( hbox1.GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 140.0f, 70.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( hbox2.GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 160.0f, 70.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( hbox1.GetProperty<Vector3>( Actor::Property::POSITION ), Vector3( 0.0f, 365.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( hbox2.GetProperty<Vector3>( Actor::Property::POSITION ), Vector3( 140.0f, 365.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+
+  // Test hbox3 matches parent (root layer)
+  DALI_TEST_EQUALS( hbox3.GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 480.0f, 800.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( hbox3.GetProperty<Vector3>( Actor::Property::POSITION ), Vector3( 0.0f, 0.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+
+  END_TEST;
+}
+
+
+int UtcDaliLayouting_HboxLayout03(void)
+{
+  ToolkitTestApplication application;
+  tet_infoline(" UtcDaliLayouting_HboxLayout03 Test nested hboxes with MATCH_PARENT");
+
+  Stage stage = Stage::GetCurrent();
+
+  auto hbox1 = Control::New();
+  auto hboxLayout1 = HboxLayout::New();
+  DevelControl::SetLayout( hbox1, hboxLayout1 );
+
+  auto hbox2 = Control::New();
+  auto hboxLayout2 = HboxLayout::New();
+  DevelControl::SetLayout( hbox2, hboxLayout2 );
+
+  hbox1.SetName( "HBox1");
+  hbox2.SetName( "HBox2");
+  hbox1.SetProperty( Toolkit::LayoutItem::ChildProperty::WIDTH_SPECIFICATION, ChildLayoutData::MATCH_PARENT );
+  hbox1.SetProperty( Toolkit::LayoutItem::ChildProperty::HEIGHT_SPECIFICATION, ChildLayoutData::MATCH_PARENT );
+  hbox2.SetProperty( Toolkit::LayoutItem::ChildProperty::WIDTH_SPECIFICATION, ChildLayoutData::MATCH_PARENT );
+  hbox2.SetProperty( Toolkit::LayoutItem::ChildProperty::HEIGHT_SPECIFICATION, ChildLayoutData::MATCH_PARENT );
+
+  std::vector< Control > controls;
+  controls.push_back( CreateLeafControl( 20, 40 ) );
+  controls.push_back( CreateLeafControl( 30, 50 ) );
+  controls.push_back( CreateLeafControl( 40, 60 ) );
+  controls.push_back( CreateLeafControl( 50, 70 ) );
+
+  controls.push_back( CreateLeafControl( 25, 40 ) );
+  controls.push_back( CreateLeafControl( 35, 50 ) );
+  controls.push_back( CreateLeafControl( 45, 60 ) );
+  controls.push_back( CreateLeafControl( 55, 70 ) );
+
+  int counter=0;
+  for( auto&& iter : controls )
+  {
+    if( counter < 4 )
+    {
+      hbox1.Add( iter );
+    }
+    else
+    {
+      hbox2.Add( iter );
+    }
+    ++counter;
+  }
+  hbox1.SetParentOrigin( ParentOrigin::CENTER );
+  hbox1.SetAnchorPoint( AnchorPoint::CENTER );
+  hbox2.SetParentOrigin( ParentOrigin::CENTER );
+  hbox2.SetAnchorPoint( AnchorPoint::CENTER );
+
+  auto hbox3 = Control::New();
+  auto hboxLayout3 = HboxLayout::New();
+  DevelControl::SetLayout( hbox3, hboxLayout3);
+
+  hbox3.SetParentOrigin( ParentOrigin::CENTER );
+  hbox3.SetName( "HBox3");
+  hbox3.Add( hbox1 );
+  hbox3.Add( hbox2 );
+
+  stage.Add( hbox3 );
+
+  //std::ostringstream oss;
+  //DumpControlHierarchy( oss, Stage::GetCurrent().GetRootLayer() );
+  //printf("Control hierarchy: \n%s\n", oss.str().c_str() );
+
+  // Ensure layouting happens
+  application.SendNotification();
+  application.Render();
+
+
+  // hbox centers elements vertically, it fills test harness stage, which is 480x800.
+  // hbox left justifies elements
+  DALI_TEST_EQUALS( controls[0].GetProperty<Vector3>( Actor::Property::POSITION ), Vector3( 0.0f, 380.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[1].GetProperty<Vector3>( Actor::Property::POSITION ), Vector3( 20.0f,375.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[2].GetProperty<Vector3>( Actor::Property::POSITION ), Vector3( 50.0f,370.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[3].GetProperty<Vector3>( Actor::Property::POSITION ), Vector3( 90.0f,365.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+
+  DALI_TEST_EQUALS( controls[0].GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 20.0f, 40.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[1].GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 30.0f, 50.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[2].GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 40.0f, 60.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[3].GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 50.0f, 70.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+
+  DALI_TEST_EQUALS( controls[4].GetProperty<Vector3>( Actor::Property::POSITION ), Vector3(  0.0f, 380.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[5].GetProperty<Vector3>( Actor::Property::POSITION ), Vector3( 25.0f, 375.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[6].GetProperty<Vector3>( Actor::Property::POSITION ), Vector3( 60.0f, 370.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[7].GetProperty<Vector3>( Actor::Property::POSITION ), Vector3( 105.0f,365.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+
+  DALI_TEST_EQUALS( controls[4].GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 25.0f, 40.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[5].GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 35.0f, 50.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[6].GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 45.0f, 60.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[7].GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 55.0f, 70.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+
+  DALI_TEST_EQUALS( hbox1.GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 480.0f, 800.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( hbox2.GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 480.0f, 800.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( hbox1.GetProperty<Vector3>( Actor::Property::POSITION ), Vector3( 0.0f, 0.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( hbox2.GetProperty<Vector3>( Actor::Property::POSITION ), Vector3( 480.0f, 0.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+
+  // Test hbox3 matches parent (root layer)
+  DALI_TEST_EQUALS( hbox3.GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 480.0f, 800.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( hbox3.GetProperty<Vector3>( Actor::Property::POSITION ), Vector3( 0.0f, 0.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+
+  END_TEST;
+}
+
+
+
+
+int UtcDaliLayouting_HboxLayout04(void)
+{
+  ToolkitTestApplication application;
+  tet_infoline(" UtcDaliLayouting_HboxLayout04 Test nested hboxes with explicit WRAP_CONTENT");
+
+  Stage stage = Stage::GetCurrent();
+
+  auto hbox1 = Control::New();
+  auto hboxLayout1 = HboxLayout::New();
+  DevelControl::SetLayout( hbox1, hboxLayout1 );
+
+  auto hbox2 = Control::New();
+  auto hboxLayout2 = HboxLayout::New();
+  DevelControl::SetLayout( hbox2, hboxLayout2 );
+
+  hbox1.SetName( "HBox1"); // Default spec is to wrap content
+  hbox2.SetName( "HBox2");
+  hbox1.SetProperty( Toolkit::LayoutItem::ChildProperty::WIDTH_SPECIFICATION, ChildLayoutData::WRAP_CONTENT );
+  hbox1.SetProperty( Toolkit::LayoutItem::ChildProperty::HEIGHT_SPECIFICATION, ChildLayoutData::WRAP_CONTENT );
+  hbox2.SetProperty( Toolkit::LayoutItem::ChildProperty::WIDTH_SPECIFICATION, ChildLayoutData::WRAP_CONTENT );
+  hbox2.SetProperty( Toolkit::LayoutItem::ChildProperty::HEIGHT_SPECIFICATION, ChildLayoutData::WRAP_CONTENT );
+
+  std::vector< Control > controls;
+  controls.push_back( CreateLeafControl( 80, 40 ) );
+  controls.push_back( CreateLeafControl( 80, 50 ) );
+  controls.push_back( CreateLeafControl( 80, 60 ) );
+  controls.push_back( CreateLeafControl( 80, 70 ) );
+
+  controls.push_back( CreateLeafControl( 80, 40 ) );
+  controls.push_back( CreateLeafControl( 80, 50 ) );
+  controls.push_back( CreateLeafControl( 80, 60 ) );
+  controls.push_back( CreateLeafControl( 80, 70 ) );
+
+  int counter=0;
+  for( auto&& iter : controls )
+  {
+    if( counter < 4 )
+    {
+      hbox1.Add( iter );
+    }
+    else
+    {
+      hbox2.Add( iter );
+    }
+    ++counter;
+  }
+
+  controls[6].SetProperty( Toolkit::LayoutItem::ChildProperty::HEIGHT_SPECIFICATION, ChildLayoutData::MATCH_PARENT );
+  auto hbox3 = Control::New();
+  auto hboxLayout3 = HboxLayout::New();
+  DevelControl::SetLayout( hbox3, hboxLayout3 );
+
+  hbox3.SetParentOrigin( ParentOrigin::CENTER );
+  hbox3.SetName( "HBox3");
+  hbox3.Add( hbox1 );
+  hbox3.Add( hbox2 );
+  stage.Add( hbox3 );
+
+  //std::ostringstream oss;
+  //DumpControlHierarchy( oss, Stage::GetCurrent().GetRootLayer() );
+  //printf("Control hierarchy: \n%s\n", oss.str().c_str() );
+
+  // Ensure layouting happens
+  application.SendNotification();
+  application.Render();
+
+
+  DALI_TEST_EQUALS( controls[0].GetProperty<Vector3>( Actor::Property::POSITION ), Vector3( 0.0f, 15.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[1].GetProperty<Vector3>( Actor::Property::POSITION ), Vector3( 80.0f,10.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[2].GetProperty<Vector3>( Actor::Property::POSITION ), Vector3( 160.0f, 5.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[3].GetProperty<Vector3>( Actor::Property::POSITION ), Vector3( 240.0f, 0.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+
+  DALI_TEST_EQUALS( controls[0].GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 80.0f, 40.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[1].GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 80.0f, 50.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[2].GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 80.0f, 60.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[3].GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 80.0f, 70.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+
+  DALI_TEST_EQUALS( controls[4].GetProperty<Vector3>( Actor::Property::POSITION ), Vector3(  0.0f, 15.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[5].GetProperty<Vector3>( Actor::Property::POSITION ), Vector3( 80.0f, 10.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[6].GetProperty<Vector3>( Actor::Property::POSITION ), Vector3( 160.0f, 0.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[7].GetProperty<Vector3>( Actor::Property::POSITION ), Vector3( 240.0f, 0.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+
+  DALI_TEST_EQUALS( controls[4].GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 80.0f, 40.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[5].GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 80.0f, 50.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[6].GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 80.0f, 70.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[7].GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 80.0f, 70.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+
+  DALI_TEST_EQUALS( hbox1.GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 320.0f, 70.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( hbox2.GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 320.0f, 70.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( hbox1.GetProperty<Vector3>( Actor::Property::POSITION ), Vector3( 0.0f, 365.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( hbox2.GetProperty<Vector3>( Actor::Property::POSITION ), Vector3( 320.0f, 365.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+
+
+  // Test hbox3 matches parent (root layer)
+  DALI_TEST_EQUALS( hbox3.GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 480.0f, 800.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( hbox3.GetProperty<Vector3>( Actor::Property::POSITION ), Vector3( 0.0f, 0.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+
+  END_TEST;
+}
+
+
+int UtcDaliLayouting_VboxLayout01(void)
+{
+  ToolkitTestApplication application;
+  tet_infoline(" UtcDaliLayouting_VboxLayout01");
+
+  Stage stage = Stage::GetCurrent();
+  auto vbox = Control::New();
+  auto vboxLayout = VboxLayout::New();
+  DevelControl::SetLayout( vbox, vboxLayout );
+  vbox.SetName( "Vbox");
+
+  std::vector< Control > controls;
+  controls.push_back( CreateLeafControl( 40, 40 ) );
+  controls.push_back( CreateLeafControl( 60, 60 ) );
+  controls.push_back( CreateLeafControl( 80, 80 ) );
+  controls.push_back( CreateLeafControl( 100, 100 ) );
+
+  for( auto&& iter : controls )
+  {
+    vbox.Add( iter );
+  }
+  vbox.SetParentOrigin( ParentOrigin::CENTER );
+  vbox.SetAnchorPoint( AnchorPoint::CENTER );
+  stage.Add( vbox );
+
+  controls[2].SetProperty( Toolkit::LayoutItem::ChildProperty::WIDTH_SPECIFICATION, ChildLayoutData::MATCH_PARENT );
+
+  // Check it.
+  DALI_TEST_EQUALS( controls[2].GetProperty( Toolkit::LayoutItem::ChildProperty::WIDTH_SPECIFICATION ), Property::Value( ChildLayoutData::MATCH_PARENT ), TEST_LOCATION );
+
+  // Ensure layouting happens
+  application.SendNotification();
+  application.Render();
+
+  // vbox centers elements horizontally, it fills test harness stage, which is 480x800.
+  DALI_TEST_EQUALS( controls[0].GetProperty<Vector3>( Actor::Property::POSITION ), Vector3( 220.0f, 0.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[1].GetProperty<Vector3>( Actor::Property::POSITION ), Vector3( 210.0f, 40.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[2].GetProperty<Vector3>( Actor::Property::POSITION ), Vector3( 0.0f, 100.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[3].GetProperty<Vector3>( Actor::Property::POSITION ), Vector3( 190.0f, 180.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+
+  DALI_TEST_EQUALS( controls[0].GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 40.0f, 40.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[1].GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 60.0f, 60.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[2].GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 480.0f, 80.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[3].GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 100.0f, 100.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+
+  END_TEST;
+}
+
+int UtcDaliLayouting_VboxLayout02(void)
+{
+  ToolkitTestApplication application;
+  tet_infoline(" UtcDaliLayouting_VboxLayout01");
+
+  Stage stage = Stage::GetCurrent();
+
+  // @todo Can't set specification properties on root control. Really need to make LayoutController a root
+  // LayoutGroup for this to happen automatically.
+  //
+  // For this test, add an hbox instead
+  auto hbox = Control::New();
+  auto hboxLayout = HboxLayout::New();
+  DevelControl::SetLayout( hbox, hboxLayout );
+  hbox.SetName( "Hbox");
+  stage.Add( hbox );
+
+  auto vbox = Control::New();
+  auto vboxLayout = VboxLayout::New();
+  DevelControl::SetLayout( vbox, vboxLayout );
+  vbox.SetName( "Vbox");
+  hbox.Add( vbox );
+
+  vbox.SetProperty( Toolkit::LayoutItem::ChildProperty::WIDTH_SPECIFICATION, ChildLayoutData::WRAP_CONTENT );
+  vbox.SetProperty( Toolkit::LayoutItem::ChildProperty::HEIGHT_SPECIFICATION, ChildLayoutData::MATCH_PARENT );
+
+  std::vector< Control > controls;
+  controls.push_back( CreateLeafControl( 40, 40 ) );
+  controls.push_back( CreateLeafControl( 60, 60 ) );
+  controls.push_back( CreateLeafControl( 80, 80 ) );
+  controls.push_back( CreateLeafControl( 100, 100 ) );
+
+  for( auto&& iter : controls )
+  {
+    vbox.Add( iter );
+  }
+  vbox.SetParentOrigin( ParentOrigin::CENTER );
+  vbox.SetAnchorPoint( AnchorPoint::CENTER );
+
+  controls[2].SetProperty( Toolkit::LayoutItem::ChildProperty::WIDTH_SPECIFICATION, ChildLayoutData::MATCH_PARENT );
+
+  // Check it.
+  DALI_TEST_EQUALS( controls[2].GetProperty( Toolkit::LayoutItem::ChildProperty::WIDTH_SPECIFICATION ), Property::Value( ChildLayoutData::MATCH_PARENT ), TEST_LOCATION );
+
+  // Ensure layouting happens
+  application.SendNotification();
+  application.Render();
+
+  DALI_TEST_EQUALS( hbox.GetProperty<Vector3>(Actor::Property::POSITION), Vector3(0,0,0),TEST_LOCATION);
+  DALI_TEST_EQUALS( hbox.GetProperty<Vector3>(Actor::Property::SIZE), Vector3(480,800,0),TEST_LOCATION);
+
+  // vbox centers elements horizontally, it should wrap it's content horizontally, i.e. it should take the width of the largest element (100)
+  DALI_TEST_EQUALS( vbox.GetProperty<Vector3>( Actor::Property::POSITION ), Vector3( 0.0f, 0.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( vbox.GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 100.0f, 800.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+
+  // 3rd control is set to match parent - this should also be 100 wide
+  DALI_TEST_EQUALS( controls[0].GetProperty<Vector3>( Actor::Property::POSITION ), Vector3( 30.0f, 0.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[1].GetProperty<Vector3>( Actor::Property::POSITION ), Vector3( 20.0f, 40.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[2].GetProperty<Vector3>( Actor::Property::POSITION ), Vector3( 0.0f, 100.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[3].GetProperty<Vector3>( Actor::Property::POSITION ), Vector3( 0.0f, 180.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+
+  DALI_TEST_EQUALS( controls[0].GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 40.0f, 40.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[1].GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 60.0f, 60.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[2].GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 100.0f, 80.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[3].GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 100.0f, 100.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+
+  END_TEST;
+}
+
+
+int UtcDaliLayouting_VboxLayout03(void)
+{
+  ToolkitTestApplication application;
+  tet_infoline(" UtcDaliLayouting_VboxLayout03 test with cell padding set");
+
+  Stage stage = Stage::GetCurrent();
+
+  // @todo Can't set specification properties on root control. Really need to make LayoutController a root
+  // LayoutGroup for this to happen automatically.
+  //
+  // For this test, add an hbox instead
+  auto hbox = Control::New();
+  auto hboxLayout = HboxLayout::New();
+  DevelControl::SetLayout( hbox, hboxLayout );
+  hbox.SetName( "Hbox");
+  stage.Add( hbox );
+
+  auto vbox = Control::New();
+  auto vboxLayout = VboxLayout::New();
+  vboxLayout.SetCellPadding( LayoutSize( 0, 10 ) );
+
+  DALI_TEST_EQUALS( vboxLayout.GetCellPadding(), LayoutSize( 0, 10 ), TEST_LOCATION );
+
+  DevelControl::SetLayout( vbox, vboxLayout );
+  vbox.SetName( "Vbox");
+  hbox.Add( vbox );
+
+  vbox.SetProperty( Toolkit::LayoutItem::ChildProperty::WIDTH_SPECIFICATION, ChildLayoutData::WRAP_CONTENT );
+  vbox.SetProperty( Toolkit::LayoutItem::ChildProperty::HEIGHT_SPECIFICATION, ChildLayoutData::MATCH_PARENT );
+
+  std::vector< Control > controls;
+  controls.push_back( CreateLeafControl( 40, 40 ) );
+  controls.push_back( CreateLeafControl( 60, 60 ) );
+  controls.push_back( CreateLeafControl( 80, 80 ) );
+  controls.push_back( CreateLeafControl( 100, 100 ) );
+
+  for( auto&& iter : controls )
+  {
+    vbox.Add( iter );
+  }
+  vbox.SetParentOrigin( ParentOrigin::CENTER );
+  vbox.SetAnchorPoint( AnchorPoint::CENTER );
+
+  controls[2].SetProperty( Toolkit::LayoutItem::ChildProperty::WIDTH_SPECIFICATION, ChildLayoutData::MATCH_PARENT );
+
+  // Check it.
+  DALI_TEST_EQUALS( controls[2].GetProperty( Toolkit::LayoutItem::ChildProperty::WIDTH_SPECIFICATION ), Property::Value( ChildLayoutData::MATCH_PARENT ), TEST_LOCATION );
+
+  // Ensure layouting happens
+  application.SendNotification();
+  application.Render();
+
+  DALI_TEST_EQUALS( hbox.GetProperty<Vector3>(Actor::Property::POSITION), Vector3(0,0,0),TEST_LOCATION);
+  DALI_TEST_EQUALS( hbox.GetProperty<Vector3>(Actor::Property::SIZE), Vector3(480,800,0),TEST_LOCATION);
+
+  // vbox centers elements horizontally, it should wrap it's content horizontally, i.e. it should take the width of the largest element (100)
+  DALI_TEST_EQUALS( vbox.GetProperty<Vector3>( Actor::Property::POSITION ), Vector3( 0.0f, 0.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( vbox.GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 100.0f, 800.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+
+  // 3rd control is set to match parent - this should also be 100 wide
+  DALI_TEST_EQUALS( controls[0].GetProperty<Vector3>( Actor::Property::POSITION ), Vector3( 30.0f, 0.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[1].GetProperty<Vector3>( Actor::Property::POSITION ), Vector3( 20.0f, 50.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[2].GetProperty<Vector3>( Actor::Property::POSITION ), Vector3( 0.0f, 120.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[3].GetProperty<Vector3>( Actor::Property::POSITION ), Vector3( 0.0f, 210.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+
+  DALI_TEST_EQUALS( controls[0].GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 40.0f, 40.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[1].GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 60.0f, 60.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[2].GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 100.0f, 80.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[3].GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 100.0f, 100.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+
+  END_TEST;
+}
index 542d064..29fe4a0 100644 (file)
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2017 Samsung Electronics Co., Ltd.
+# Copyright (c) 2018 Samsung Electronics Co., Ltd.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
@@ -144,6 +144,8 @@ develapishadowviewdir =         $(develapicontrolsdir)/shadow-view
 develapisuperblurviewdir =      $(develapicontrolsdir)/super-blur-view
 develapifocusmanagerdir =       $(develapidir)/focus-manager
 develapiimageloaderdir =        $(develapidir)/image-loader
+develapilayoutingdir =          $(develapidir)/layouting
+develapilayoutingcontrolsdir =  $(develapidir)/controls/layouting
 develapiscriptingdir =          $(develapidir)/scripting
 develapishadereffectsdir =      $(develapidir)/shader-effects
 develapistylingdir =            $(develapidir)/styling
@@ -166,6 +168,8 @@ develapieffectsview_HEADERS =       $(devel_api_effects_view_header_files)
 develapifocusmanager_HEADERS =      $(devel_api_focus_manager_header_files)
 develapigaussianblurview_HEADERS =  $(devel_api_gaussian_blur_view_header_files)
 develapiimageloader_HEADERS =       $(devel_api_image_loader_header_files)
+develapilayoutingcontrols_HEADERS = $(devel_api_layouting_controls_header_files)
+develapilayouting_HEADERS =         $(devel_api_layouting_header_files)
 develapimagnifier_HEADERS =         $(devel_api_magnifier_header_files)
 develapinavigationview_HEADERS =    $(devel_api_navigation_view_header_files)
 develapipageturnview_HEADERS =      $(devel_api_page_turn_view_header_files)
index 7ba3d11..61264b4 100644 (file)
@@ -2172,7 +2172,7 @@ INCLUDE_FILE_PATTERNS  =
 # recursively expanded use the := operator instead of the = operator.
 # This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
 
-PREDEFINED             = DALI_IMPORT_API \
+PREDEFINED             = DALI_TOOLKIT_API \
                          DALI_INTERNAL \
                          __attribute__ \
                          ((visibility \
index 941fdbc..98106dc 100755 (executable)
@@ -2147,7 +2147,7 @@ INCLUDE_FILE_PATTERNS  =
 # recursively expanded use the := operator instead of the = operator.
 # This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
 
-PREDEFINED             = DALI_IMPORT_API \
+PREDEFINED             = DALI_TOOLKIT_API \
                          DALI_INTERNAL \
                          __attribute__ \
                          ((visibility \
old mode 100644 (file)
new mode 100755 (executable)
index 422a517..fb76667
@@ -2,7 +2,7 @@
 #define __DALI_TOOLKIT_UIBUILDER_H__
 
 /*
- * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2018 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -25,6 +25,9 @@
 #include <dali/devel-api/animation/path-constrainer.h>
 #include <dali/public-api/images/frame-buffer-image.h>
 
+// INTERNAL INCLUDES
+#include <dali-toolkit/public-api/dali-toolkit-common.h>
+
 namespace Dali
 {
 
@@ -118,7 +121,7 @@ class Builder;
  *
  */
 
-class DALI_IMPORT_API Builder : public BaseHandle
+class DALI_TOOLKIT_API Builder : public BaseHandle
  {
  public:
    /**
index 05b8e80..645b985 100644 (file)
@@ -2,7 +2,7 @@
 #define __DALI_JSON_PARSER_H__
 
 /*
- * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2018 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -41,7 +41,7 @@ class JsonParser;
 /*
  * Parses JSON
  */
-class DALI_IMPORT_API JsonParser : public BaseHandle
+class DALI_TOOLKIT_API JsonParser : public BaseHandle
 {
 public:
 
index c63bf1f..0bc10cb 100644 (file)
@@ -2,7 +2,7 @@
 #define __DALI_SCRIPT_TREE_NODE_H__
 
 /*
- * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2018 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -21,7 +21,7 @@
 // EXTERNAL INCLUDES
 #include <utility> // pair
 #include <iterator>
-#include <dali/public-api/common/dali-common.h>
+#include <dali-toolkit/public-api/dali-toolkit-common.h>
 
 namespace Dali
 {
@@ -42,7 +42,7 @@ class TreeNodeManipulator;
  * TreeNode does not own its string data which is held by a container eg JsonParser
  * Modification operations should be done through a container.
  */
-class DALI_IMPORT_API TreeNode
+class DALI_TOOLKIT_API TreeNode
 {
 public:
   /*
index 23cc950..b6c3a88 100644 (file)
@@ -2,7 +2,7 @@
 #define __DALI_TOOLKIT_BLOOM_VIEW_H__
 
 /*
- * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2018 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -90,7 +90,7 @@ class BloomView;
  *  Stage::GetCurrent().Remove(bloomView);\n
  *  bloomView.Deactivate();\n
  */
-class DALI_IMPORT_API BloomView : public Control
+class DALI_TOOLKIT_API BloomView : public Control
 {
 public:
 
index 3bbdce9..450d3a2 100644 (file)
@@ -2,7 +2,7 @@
 #define __DALI_TOOLKIT_BUBBLE_EMMITER_H__
 
 /*
- * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2018 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -41,7 +41,7 @@ namespace Internal DALI_INTERNAL
  *
  * This is done by applying BubbleEffect to multiple specifically created meshActors.
  */
-class DALI_IMPORT_API BubbleEmitter : public Control
+class DALI_TOOLKIT_API BubbleEmitter : public Control
 {
 public:
 
index 2e61901..4d761d7 100644 (file)
@@ -2,7 +2,7 @@
 #define __DALI_TOOLKIT_TOGGLE_BUTTON_H__
 
 /*
- * Copyright (c) 2017 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2018 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -98,7 +98,7 @@ class ToggleButton;
  *
  * See Button for more detail on signals and modifying states via properties.
  */
-class DALI_IMPORT_API ToggleButton : public Button
+class DALI_TOOLKIT_API ToggleButton : public Button
 {
 public:
   /**
index a9a83dd..29ceb14 100755 (executable)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2018 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -89,6 +89,15 @@ Dali::Animation CreateTransition( Internal::Control& control, const Toolkit::Tra
   return controlDataImpl.CreateTransition( handle );
 }
 
+
+void AddTransitions( Internal::Control& control,
+                     Dali::Animation animation,
+                     const Toolkit::TransitionData& transitionData )
+{
+  Internal::Control::Impl& controlDataImpl = Internal::Control::Impl::Get( control );
+  controlDataImpl.AddTransitions( animation, transitionData );
+}
+
 void DoAction( Control& control, Dali::Property::Index visualIndex, Dali::Property::Index actionId, const Dali::Property::Value attributes )
 {
   Internal::Control& controlInternal = Toolkit::Internal::GetImplementation( control );
@@ -101,6 +110,32 @@ void SetInputMethodContext( Internal::Control& control, InputMethodContext& inpu
   Internal::Control::Impl::Get( control ).SetInputMethodContext( inputMethodContext );
 }
 
+Toolkit::LayoutItem GetLayout( Control control )
+{
+  const Internal::Control& internalControl = Toolkit::Internal::GetImplementation( control );
+  const Internal::Control::Impl& controlDataImpl = Internal::Control::Impl::Get( internalControl );
+  return Toolkit::LayoutItem( controlDataImpl.GetLayout().Get() );
+}
+
+Toolkit::LayoutItem GetLayout( Internal::Control& control )
+{
+  Internal::Control::Impl& controlDataImpl = Internal::Control::Impl::Get( control );
+  return Toolkit::LayoutItem( controlDataImpl.GetLayout().Get() );
+}
+
+void SetLayout( Internal::Control& control, Toolkit::LayoutItem layout )
+{
+  Internal::Control::Impl& controlDataImpl = Internal::Control::Impl::Get( control );
+  controlDataImpl.SetLayout( GetImplementation( layout ) );
+}
+
+void SetLayout( Control control, Toolkit::LayoutItem layout )
+{
+  Internal::Control& internalControl = Toolkit::Internal::GetImplementation( control );
+  Internal::Control::Impl& controlDataImpl = Internal::Control::Impl::Get( internalControl );
+  controlDataImpl.SetLayout( GetImplementation( layout ) );
+}
+
 } // namespace DevelControl
 
 } // namespace Toolkit
index 1fece4f..9a9e27e 100755 (executable)
@@ -2,7 +2,7 @@
 #define DALI_TOOLKIT_CONTROL_DEVEL_H
 
 /*
- * Copyright (c) 2017 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2018 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -23,6 +23,7 @@
 // INTERNAL INCLUDES
 #include <dali-toolkit/public-api/controls/control.h>
 #include <dali-toolkit/devel-api/visual-factory/visual-base.h>
+#include <dali-toolkit/devel-api/layouting/layout-item.h>
 
 namespace Dali
 {
@@ -132,7 +133,7 @@ enum
  * @note If the depth-index is not set on the visual, then it is set to be above the currently registered visuals.
  * @note If replacing a visual, then the depth-index of the visual being replaced is used for the visual.
  */
-DALI_IMPORT_API void RegisterVisual( Internal::Control& control, Dali::Property::Index index, Toolkit::Visual::Base& visual );
+DALI_TOOLKIT_API void RegisterVisual( Internal::Control& control, Dali::Property::Index index, Toolkit::Visual::Base& visual );
 
 /**
  * @brief Register a visual by Property Index with a depth index.
@@ -148,7 +149,7 @@ DALI_IMPORT_API void RegisterVisual( Internal::Control& control, Dali::Property:
  * @see Visual::Base::GetDepthIndex()
  * @see Visual::Base::SetDepthIndex()
  */
-DALI_IMPORT_API void RegisterVisual( Internal::Control& control, Dali::Property::Index index, Toolkit::Visual::Base& visual, int depthIndex );
+DALI_TOOLKIT_API void RegisterVisual( Internal::Control& control, Dali::Property::Index index, Toolkit::Visual::Base& visual, int depthIndex );
 
 /**
  * @brief Register a visual by Property Index with the option of enabling/disabling it.
@@ -163,7 +164,7 @@ DALI_IMPORT_API void RegisterVisual( Internal::Control& control, Dali::Property:
  *
  * @see EnableVisual()
  */
-DALI_IMPORT_API void RegisterVisual( Internal::Control& control, Dali::Property::Index index, Toolkit::Visual::Base& visual, bool enabled );
+DALI_TOOLKIT_API void RegisterVisual( Internal::Control& control, Dali::Property::Index index, Toolkit::Visual::Base& visual, bool enabled );
 
 /**
  * @brief Register a visual by Property Index with a depth index with the option of enabling/disabling it.
@@ -178,7 +179,7 @@ DALI_IMPORT_API void RegisterVisual( Internal::Control& control, Dali::Property:
  * @see Visual::Base::GetDepthIndex()
  * @see Visual::Base::SetDepthIndex()
  */
-DALI_IMPORT_API void RegisterVisual( Internal::Control& control, Dali::Property::Index index, Toolkit::Visual::Base& visual, bool enabled, int depthIndex );
+DALI_TOOLKIT_API void RegisterVisual( Internal::Control& control, Dali::Property::Index index, Toolkit::Visual::Base& visual, bool enabled, int depthIndex );
 
 /**
  * @brief Erase the entry matching the given index from the list of registered visuals
@@ -186,7 +187,7 @@ DALI_IMPORT_API void RegisterVisual( Internal::Control& control, Dali::Property:
  * @param[in] control The control
  * @param[in] index The Property index of the visual, used to reference visual
  */
-DALI_IMPORT_API void UnregisterVisual( Internal::Control& control, Dali::Property::Index index );
+DALI_TOOLKIT_API void UnregisterVisual( Internal::Control& control, Dali::Property::Index index );
 
 /**
  * @brief Retrieve the visual associated with the given property index.
@@ -196,7 +197,7 @@ DALI_IMPORT_API void UnregisterVisual( Internal::Control& control, Dali::Propert
  * @return The registered visual if exist, otherwise empty handle.
  * @note For managing object life-cycle, do not store the returned visual as a member which increments its reference count.
  */
-DALI_IMPORT_API Toolkit::Visual::Base GetVisual( const Internal::Control& control, Dali::Property::Index index );
+DALI_TOOLKIT_API Toolkit::Visual::Base GetVisual( const Internal::Control& control, Dali::Property::Index index );
 
 /**
  * @brief Sets the given visual to be displayed or not when parent staged.
@@ -205,7 +206,7 @@ DALI_IMPORT_API Toolkit::Visual::Base GetVisual( const Internal::Control& contro
  * @param[in] index The Property index of the visual
  * @param[in] enable flag to set enabled or disabled.
  */
-DALI_IMPORT_API void EnableVisual( Internal::Control& control, Dali::Property::Index index, bool enable );
+DALI_TOOLKIT_API void EnableVisual( Internal::Control& control, Dali::Property::Index index, bool enable );
 
 /**
  * @brief Queries if the given visual is to be displayed when parent staged.
@@ -214,7 +215,24 @@ DALI_IMPORT_API void EnableVisual( Internal::Control& control, Dali::Property::I
  * @param[in] index The Property index of the visual
  * @return bool whether visual is enabled or not
  */
-DALI_IMPORT_API bool IsVisualEnabled( const Internal::Control& control, Dali::Property::Index index );
+DALI_TOOLKIT_API bool IsVisualEnabled( const Internal::Control& control, Dali::Property::Index index );
+
+
+/**
+ * @brief Add a transition effect on the control to the given animation
+ *
+ * Only generates an animator if the properties described in the transition
+ * data are staged (e.g. the visual is Enabled and the control is on stage).
+ * Otherwise the target values are stored, and will get set onto the properties
+ * when the visual is next staged.
+ *
+ * @param[in] control The control
+ * @param[in] animation The Animation to add valid transitions to
+ * @param[in] transitionData The transition data describing the effect to create
+ */
+DALI_TOOLKIT_API void AddTransitions( Internal::Control& control,
+                                      Dali::Animation animation,
+                                      const Toolkit::TransitionData& transitionData );
 
 /**
  * @brief Create a transition effect on the control.
@@ -229,7 +247,8 @@ DALI_IMPORT_API bool IsVisualEnabled( const Internal::Control& control, Dali::Pr
  * @return A handle to an animation defined with the given effect, or an empty
  * handle if no properties match.
  */
-DALI_IMPORT_API Dali::Animation CreateTransition( Internal::Control& control, const Toolkit::TransitionData& transitionData );
+DALI_TOOLKIT_API Dali::Animation CreateTransition( Internal::Control& control,
+                                                   const Toolkit::TransitionData& transitionData );
 
 /**
  * @brief Perform an action on a visual registered to this control.
@@ -241,7 +260,7 @@ DALI_IMPORT_API Dali::Animation CreateTransition( Internal::Control& control, co
  * @param[in] actionId The action to perform.  See Visual to find supported actions.
  * @param[in] attributes Optional attributes for the action.
  */
-DALI_IMPORT_API void DoAction( Control& control, Dali::Property::Index visualIndex, Dali::Property::Index actionId, const Dali::Property::Value attributes );
+DALI_TOOLKIT_API void DoAction( Control& control, Dali::Property::Index visualIndex, Dali::Property::Index actionId, const Dali::Property::Value attributes );
 
 /**
  * @brief Set input method context.
@@ -249,7 +268,37 @@ DALI_IMPORT_API void DoAction( Control& control, Dali::Property::Index visualInd
  * @param[in] control The control.
  * @param[in] inputMethodContext The input method context.
  */
-DALI_IMPORT_API void SetInputMethodContext( Internal::Control& control, InputMethodContext& inputMethodContext );
+DALI_TOOLKIT_API void SetInputMethodContext( Internal::Control& control, InputMethodContext& inputMethodContext );
+
+/*
+ * @brief Get the layout associated with this control, if any.
+ *
+ * @return A handle to the layout, or empty.
+ */
+DALI_TOOLKIT_API Toolkit::LayoutItem GetLayout( Internal::Control& control );
+
+/*
+ * @brief Get the layout associated with a control, if any.
+ *
+ * @return A handle to the layout, or empty.
+ */
+DALI_TOOLKIT_API Toolkit::LayoutItem GetLayout( Control control );
+
+/**
+ * @brief Set the layout on this control.
+ *
+ * @param[in] control The internal Control to set the layout on
+ * @param[in] layout Pointer to the layout
+ */
+DALI_TOOLKIT_API void SetLayout( Internal::Control& control, Toolkit::LayoutItem layout );
+
+/**
+ * @brief Set the layout on a control.
+ *
+ * @param[in] control The Control to set the layout on
+ * @param[in] layout Pointer to the layout
+ */
+DALI_TOOLKIT_API void SetLayout( Control control, Toolkit::LayoutItem layout );
 
 } // namespace DevelControl
 
index e5c371d..10130f7 100755 (executable)
@@ -2,7 +2,7 @@
 #define DALI_TOOLKIT_INTERNAL_CONTROL_WRAPPER_H
 
 /*
- * Copyright (c) 2017 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2018 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -45,7 +45,7 @@ typedef IntrusivePtr< ControlWrapper > ControlWrapperPtr;
 /**
  * @copydoc Toolkit::ControlWrapper
  */
-class DALI_IMPORT_API ControlWrapper : public Control
+class DALI_TOOLKIT_API ControlWrapper : public Control
 {
 public:
 
index b50852b..fecab4f 100644 (file)
@@ -2,7 +2,7 @@
 #define DALI_TOOLKIT_CONTROL_WRAPPER_H
 
 /*
- * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2018 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -37,7 +37,7 @@ class ControlWrapper;
  *
  * The implementation of the ControlWrapper must be supplied; see Internal::ControlWrapper for more details.
  */
-class DALI_IMPORT_API ControlWrapper : public Control
+class DALI_TOOLKIT_API ControlWrapper : public Control
 {
 
 public:
index b734b41..6196617 100644 (file)
@@ -2,7 +2,7 @@
 #define __DALI_TOOLKIT_EFFECTS_VIEW_H__
 
 /*
- * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2018 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -60,7 +60,7 @@ class EffectsView;
  * // optionally set a clear color
  * effectsView.SetBackgroundColor( Vector4( 0.0f, 0.0f, 0.0f, 0.0f ) );
  */
-class DALI_IMPORT_API EffectsView : public Control
+class DALI_TOOLKIT_API EffectsView : public Control
 {
 public:
 
index 5364217..58894a9 100644 (file)
@@ -2,7 +2,7 @@
 #define __DALI_TOOLKIT_GAUSSIAN_BLUR_EFFECT_H__
 
 /*
- * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2018 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -103,7 +103,7 @@ class BloomView;
  * @remarks This is an experimental feature and might not be supported in the next release.
  * We do recommend not to use this class.
  */
-class DALI_IMPORT_API GaussianBlurView : public Control
+class DALI_TOOLKIT_API GaussianBlurView : public Control
 {
 public:
   /**
index e898326..ab31ba6 100644 (file)
@@ -2,7 +2,7 @@
 #define __DALI_TOOLKIT_MAGNIFIER_H__
 
 /*
- * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2018 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -41,7 +41,7 @@ class Magnifier;
  * to the stage as a separate overlay. In addition to the contents, an optional frame
  * is displayed around the magnified contents.
  */
-class DALI_IMPORT_API Magnifier : public Control
+class DALI_TOOLKIT_API Magnifier : public Control
 {
 public:
 
index 1ff0f65..113792f 100644 (file)
@@ -2,7 +2,7 @@
 #define DALI_TOOLKIT_NAVIGATION_VIEW_H
 
 /*
- * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2018 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -42,7 +42,7 @@ class NavigationView;
  * When pop is called on the NavigationView, the current tree of Actors are removed and the previous set added back.
  * If pop is called on the last set of Actors then they remain, nothing is popped.
  */
-class DALI_IMPORT_API NavigationView : public Control
+class DALI_TOOLKIT_API NavigationView : public Control
 {
 
 public:
index 64432b4..bc6e17a 100644 (file)
@@ -2,7 +2,7 @@
 #define __DALI_TOOLKIT_PAGE_FACTORY_H__
 
 /*
- * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2018 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -21,6 +21,9 @@
 // EXTERNAL INCLUDES
 #include <dali/public-api/rendering/texture.h>
 
+// INTERNAL INCLUDES
+#include <dali-toolkit/public-api/dali-toolkit-common.h>
+
 namespace Dali
 {
 
@@ -33,7 +36,7 @@ namespace Toolkit
  *
  * @SINCE_1_1.4
  */
-class DALI_IMPORT_API PageFactory
+class DALI_TOOLKIT_API PageFactory
 {
 public:
 
index 9460b21..a170aa2 100644 (file)
@@ -2,7 +2,7 @@
 #define __DALI_TOOLKIT_PAGE_TURN_LANDSCAPE_VIEW_H__
 
 /*
- * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2018 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -37,7 +37,7 @@ class PageTurnLandscapeView;
  * @brief PageTurnLandscapeView provides a page turn view in landscape mode
  * @SINCE_1_0.0
  */
-class DALI_IMPORT_API PageTurnLandscapeView : public PageTurnView
+class DALI_TOOLKIT_API PageTurnLandscapeView : public PageTurnView
 {
 public:
   /**
index 506c9ad..e28bb6c 100644 (file)
@@ -2,7 +2,7 @@
 #define __DALI_TOOLKIT_PAGE_TURN_PORTRAIT_VIEW_H__
 
 /*
- * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2018 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -38,7 +38,7 @@ class PageTurnPortraitView;
  *
  * @SINCE_1_1.4
  */
-class DALI_IMPORT_API PageTurnPortraitView : public PageTurnView
+class DALI_TOOLKIT_API PageTurnPortraitView : public PageTurnView
 {
 public:
   /**
index 2c71d32..a4705e4 100644 (file)
@@ -2,7 +2,7 @@
 #define __DALI_TOOLKIT_PAGE_TURN_VIEW_H__
 
 /*
- * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2018 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -63,7 +63,7 @@ class PageTurnView;
  *
  * @SINCE_1_1.4
  */
-class DALI_IMPORT_API PageTurnView : public Control
+class DALI_TOOLKIT_API PageTurnView : public Control
 {
 public:
 
index 4cd620b..940840b 100644 (file)
@@ -2,7 +2,7 @@
 #define __DALI_TOOLKIT_CONFIRMATION_POPUP_H__
 
 /*
- * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2018 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -48,7 +48,7 @@ class ConfirmationPopup;
  * | controlSignalOk     | controlOk                | connectSignalOkSelected                  |
  * | controlSignalCancel | controlCancel            | connectSignalCancelSelected              |
  */
-class DALI_IMPORT_API ConfirmationPopup : public Popup
+class DALI_TOOLKIT_API ConfirmationPopup : public Popup
 {
 public:
 
index 3d3d915..2cc0636 100644 (file)
@@ -2,7 +2,7 @@
 #define __DALI_TOOLKIT_POPUP_H__
 
 /*
- * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2018 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -52,7 +52,7 @@ class Popup;
  * | hiding            | @ref HidingSignal()          |
  * | hidden            | @ref HiddenSignal()          |
  */
-class DALI_IMPORT_API Popup : public Control
+class DALI_TOOLKIT_API Popup : public Control
 {
 
 public:
index 4b43e5f..c37cfb1 100644 (file)
@@ -2,7 +2,7 @@
 #define __DALI_TOOLKIT_SHADOW_VIEW_H__
 
 /*
- * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2018 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -99,7 +99,7 @@ class ShadowView;
  *  shadowView.Deactivate();
  *  @endcode
  */
-class DALI_IMPORT_API ShadowView : public Control
+class DALI_TOOLKIT_API ShadowView : public Control
 {
 public:
 
index f63ddd5..b82e039 100644 (file)
@@ -2,7 +2,7 @@
 #define __DALI_TOOLKIT_SUPER_BLUR_VIEW_H__
 
 /*
- * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2018 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -52,7 +52,7 @@ class SuperBlurView;
  *  blurAnimation.AnimateTo( Property( blurView, blurView.GetBlurStrengthPropertyIndex() ), ... );\n
  *  blurAnimation.Play();\n
  */
-class DALI_IMPORT_API SuperBlurView : public Control
+class DALI_TOOLKIT_API SuperBlurView : public Control
 {
 public:
 
index 875e270..97ee0fa 100755 (executable)
@@ -1,8 +1,5 @@
-#ifndef DALI_TOOLKIT_TEXT_EDITOR_DEVEL_H
-#define DALI_TOOLKIT_TEXT_EDITOR_DEVEL_H
-
 /*
- * Copyright (c) 2017 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2018 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -40,6 +37,4 @@ InputMethodContext GetInputMethodContext( TextEditor textEditor )
 
 } // namespace Toolkit
 
-} // namespace Dali
-
-#endif // DALI_TOOLKIT_TEXT_EDITOR_DEVEL_H
+} // namespace Dali
\ No newline at end of file
index fd2d4bb..7bed333 100755 (executable)
@@ -2,7 +2,7 @@
 #define DALI_TOOLKIT_TEXT_EDITOR_DEVEL_H
 
 /*
- * Copyright (c) 2017 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2018 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -121,7 +121,7 @@ namespace Property
  * @param[in] textEditor The instance of TextEditor.
  * @return InputMethodContext instance.
  */
-DALI_IMPORT_API InputMethodContext GetInputMethodContext( TextEditor textEditor );
+DALI_TOOLKIT_API InputMethodContext GetInputMethodContext( TextEditor textEditor );
 
 } // namespace DevelTextEditor
 
index c73bb5e..f9b739c 100755 (executable)
@@ -1,8 +1,5 @@
-#ifndef DALI_TOOLKIT_TEXT_FIELD_DEVEL_H
-#define DALI_TOOLKIT_TEXT_FIELD_DEVEL_H
-
 /*
- * Copyright (c) 2017 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2018 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -41,5 +38,3 @@ InputMethodContext GetInputMethodContext( TextField textField )
 } // namespace Toolkit
 
 } // namespace Dali
-
-#endif // DALI_TOOLKIT_TEXT_FIELD_DEVEL_H
index 5075358..dea5ded 100755 (executable)
@@ -2,7 +2,7 @@
 #define DALI_TOOLKIT_TEXT_FIELD_DEVEL_H
 
 /*
- * Copyright (c) 2017 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2018 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -110,7 +110,7 @@ namespace Property
  * @param[in] textField The instance of TextField.
  * @return InputMethodContext instance.
  */
-DALI_IMPORT_API InputMethodContext GetInputMethodContext( TextField textField );
+DALI_TOOLKIT_API InputMethodContext GetInputMethodContext( TextField textField );
 
 } // namespace DevelText
 
index 31cf939..9e9ee48 100644 (file)
@@ -2,7 +2,7 @@
 #define __DALI_TOOLKIT_TEXT_SELECTION_POPUP_H__
 
 /*
- * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2018 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -44,7 +44,7 @@ class TextSelectionPopup;
  *
  *
  */
-class DALI_IMPORT_API TextSelectionPopup : public Control
+class DALI_TOOLKIT_API TextSelectionPopup : public Control
 {
 public:
 
index 6193f77..43b7c72 100644 (file)
@@ -2,7 +2,7 @@
 #define __DALI_TOOLKIT_TEXT_SELECTION_TOOLBAR_H__
 
 /*
- * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2018 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -42,7 +42,7 @@ class TextSelectionToolbar;
  *
  *
  */
-class DALI_IMPORT_API TextSelectionToolbar : public Control
+class DALI_TOOLKIT_API TextSelectionToolbar : public Control
 {
 public:
 
index b9f2c19..8725bb3 100644 (file)
@@ -2,7 +2,7 @@
 #define __DALI_TOOLKIT_TOOL_BAR_H__
 
 /*
- * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2018 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -43,7 +43,7 @@ class ToolBar;
  * is not forbidden, it adds controls on the left group with a size of 10% of the total tool bar size.
  * Dali::Actor::Remove() method does nothing.
  */
-class DALI_IMPORT_API ToolBar : public Control
+class DALI_TOOLKIT_API ToolBar : public Control
 {
 public:
   static const Toolkit::Alignment::Padding DEFAULT_PADDING; ///< Default padding space between controls. By default all values are set to 0.
index a04fc74..674bcd1 100755 (executable)
@@ -31,6 +31,13 @@ devel_api_src_files = \
   $(devel_api_src_dir)/image-loader/atlas-upload-observer.cpp \
   $(devel_api_src_dir)/image-loader/image-atlas.cpp \
   $(devel_api_src_dir)/image-loader/texture-manager.cpp \
+  $(devel_api_src_dir)/layouting/hbox-layout.cpp \
+  $(devel_api_src_dir)/layouting/vbox-layout.cpp \
+  $(devel_api_src_dir)/layouting/layout-item.cpp \
+  $(devel_api_src_dir)/layouting/layout-item-impl.cpp \
+  $(devel_api_src_dir)/layouting/layout-controller.cpp \
+  $(devel_api_src_dir)/layouting/layout-group.cpp \
+  $(devel_api_src_dir)/layouting/layout-group-impl.cpp \
   $(devel_api_src_dir)/scripting/script.cpp \
   $(devel_api_src_dir)/styling/style-manager-devel.cpp \
   $(devel_api_src_dir)/transition-effects/cube-transition-cross-effect.cpp \
@@ -71,6 +78,21 @@ devel_api_builder_header_files = \
 devel_api_effects_view_header_files = \
   $(devel_api_src_dir)/controls/effects-view/effects-view.h
 
+devel_api_layouting_header_files = \
+  $(devel_api_src_dir)/layouting/child-layout-data.h \
+  $(devel_api_src_dir)/layouting/hbox-layout.h \
+  $(devel_api_src_dir)/layouting/vbox-layout.h \
+  $(devel_api_src_dir)/layouting/layout-item.h \
+  $(devel_api_src_dir)/layouting/layout-item-impl.h \
+  $(devel_api_src_dir)/layouting/layout-controller.h \
+  $(devel_api_src_dir)/layouting/layout-group.h \
+  $(devel_api_src_dir)/layouting/layout-group-impl.h \
+  $(devel_api_src_dir)/layouting/layout-length.h \
+  $(devel_api_src_dir)/layouting/layout-size.h \
+  $(devel_api_src_dir)/layouting/measured-size.h \
+  $(devel_api_src_dir)/layouting/layout-parent-impl.h \
+  $(devel_api_src_dir)/layouting/measure-spec.h
+
 devel_api_magnifier_header_files = \
   $(devel_api_src_dir)/controls/magnifier/magnifier.h
 
index 36a78d7..4aa1887 100644 (file)
@@ -2,7 +2,7 @@
 #define DALI_TOOLKIT_KEYBOARD_FOCUS_MANAGER_DEVEL_H
 
 /*
- * Copyright (c) 2017 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2018 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -69,7 +69,7 @@ public:
  * @param[in] interface The user's implementation of CustomAlgorithmInterface
  * @see DevelKeyboardFocusManager::CustomAlgorithmInterface
  */
-DALI_IMPORT_API void SetCustomAlgorithm(KeyboardFocusManager keyboardFocusManager, CustomAlgorithmInterface& interface);
+DALI_TOOLKIT_API void SetCustomAlgorithm(KeyboardFocusManager keyboardFocusManager, CustomAlgorithmInterface& interface);
 
 } // namespace DevelKeyboardFocusManager
 
index 3161990..dd43152 100644 (file)
@@ -2,7 +2,7 @@
 #define __DALI_TOOLKIT_KEYINPUT_FOCUS_MANAGER_H__
 
 /*
- * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2018 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -45,7 +45,7 @@ class KeyInputFocusManager;
  * |----------------------|-----------------------------------|
  * | keyInputFocusChanged | @ref KeyInputFocusChangedSignal() |
  */
-class DALI_IMPORT_API KeyInputFocusManager : public BaseHandle
+class DALI_TOOLKIT_API KeyInputFocusManager : public BaseHandle
 {
 public:
 
index 2af2be9..7cb64c5 100644 (file)
@@ -2,7 +2,7 @@
 #define DALI_TOOLKIT_DEVEL_API_IMAGE_LOADER_ASYNC_IMAGE_LOADER_DEVEL_H
 
 /*
- * Copyright (c) 2017 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2018 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -34,7 +34,7 @@ typedef Signal< void ( uint32_t, Devel::PixelBuffer ) > PixelBufferLoadedSignalT
  * Connect to this signal if you want to load a PixelBuffer instead of a PixelData.
  * @note Connecting to this signal prevents the emission of the ImageLoadedSignal.
  */
-DALI_IMPORT_API PixelBufferLoadedSignalType&  PixelBufferLoadedSignal( AsyncImageLoader asyncImageLoader );
+DALI_TOOLKIT_API PixelBufferLoadedSignalType&  PixelBufferLoadedSignal( AsyncImageLoader asyncImageLoader );
 
 }
 } // Toolkit
index 2688c1a..53d1c0e 100644 (file)
@@ -2,7 +2,7 @@
 #define DALI_TOOLKIT_ATLAS_UPLOAD_OBSERVER_H
 
 /*
- * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2018 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -18,7 +18,7 @@
  *
  */
 
-#include <dali/public-api/common/dali-common.h>
+#include <dali-toolkit/public-api/dali-toolkit-common.h>
 #include <dali/public-api/common/dali-vector.h>
 #include <dali/public-api/signals/callback.h>
 
@@ -39,7 +39,7 @@ class ImageAtlas;
  *
  * Derived class should implement the UploadCompleted method which would get executed once the texture is ready.
  */
-class DALI_IMPORT_API AtlasUploadObserver
+class DALI_TOOLKIT_API AtlasUploadObserver
 {
 public:
 
index a0305fd..991c624 100644 (file)
@@ -1,7 +1,7 @@
 #ifndef DALI_TOOLKIT_IMAGE_ATLAS_H
 #define DALI_TOOLKIT_IMAGE_ATLAS_H
 /*
- * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2018 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -47,7 +47,7 @@ class ImageAtlas;
  * Only images with url provided or pixel data are supported for uploading.
  * The images are loaded by a worker thread to avoid blocking the main event thread.
  */
-class DALI_IMPORT_API ImageAtlas : public BaseHandle
+class DALI_TOOLKIT_API ImageAtlas : public BaseHandle
 {
 public:
 
old mode 100644 (file)
new mode 100755 (executable)
index ce4bf3d..46d3ef9
@@ -2,7 +2,7 @@
 #define DALI_TOOLKIT_DEVEL_API_TEXTURE_MANAGER_H
 
 /*
- * Copyright (c) 2017 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2018 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -20,6 +20,9 @@
 // EXTERNAL INCLUDES
 #include <dali/public-api/rendering/texture-set.h>
 
+// INTERNAL INCLUDES
+#include <dali-toolkit/public-api/dali-toolkit-common.h>
+
 namespace Dali
 {
 
@@ -41,7 +44,7 @@ namespace TextureManager
  * @param[in] texture the Texture to add
  * @return the Url string representing this texture
  */
-DALI_IMPORT_API std::string AddTexture( Texture& texture );
+DALI_TOOLKIT_API std::string AddTexture( Texture& texture );
 
 /**
  * @brief Add a TextureSet to texture manager
@@ -51,7 +54,7 @@ DALI_IMPORT_API std::string AddTexture( Texture& texture );
  * @param[in] textureSet the TextureSet to add
  * @return the Url string representing this texture
  */
-DALI_IMPORT_API std::string AddTexture( TextureSet& textureSet );
+DALI_TOOLKIT_API std::string AddTexture( TextureSet& textureSet );
 
 /**
  * @brief Removes a TextureSet from toolkit
@@ -59,7 +62,7 @@ DALI_IMPORT_API std::string AddTexture( TextureSet& textureSet );
  * @param[in] textureUrl to remove
  * @return the handle to the TextureSet or empty handle in case TextureSet is not found
  */
-DALI_IMPORT_API TextureSet RemoveTexture( const std::string& textureUrl );
+DALI_TOOLKIT_API TextureSet RemoveTexture( const std::string& textureUrl );
 
 } // TextureManager
 
diff --git a/dali-toolkit/devel-api/layouting/child-layout-data.h b/dali-toolkit/devel-api/layouting/child-layout-data.h
new file mode 100644 (file)
index 0000000..f3af733
--- /dev/null
@@ -0,0 +1,37 @@
+#ifndef DALI_TOOLKIT_LAYOUTING_CHILD_LAYOUT_DATA_H
+#define DALI_TOOLKIT_LAYOUTING_CHILD_LAYOUT_DATA_H
+
+/*
+ * Copyright (c) 2018 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+namespace Dali
+{
+namespace Toolkit
+{
+
+// used in property system - must be integer values.
+namespace ChildLayoutData
+{
+static const int MATCH_PARENT = -1; ///< Constant which indicates child size should match parent size
+static const int WRAP_CONTENT = -2; ///< Constant which indicates parent should take the smallest size possible to wrap it's children with their desired size
+
+} // namespace ChildLayoutData
+
+} // namespace Toolkit
+} // namespace Dali
+
+#endif // DALI_TOOLKIT_LAYOUTING_CHILD_LAYOUT_DATA_H
diff --git a/dali-toolkit/devel-api/layouting/hbox-layout.cpp b/dali-toolkit/devel-api/layouting/hbox-layout.cpp
new file mode 100644 (file)
index 0000000..7f05745
--- /dev/null
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2018 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//CLASS HEADER
+#include <dali-toolkit/devel-api/layouting/hbox-layout.h>
+
+//EXTERNAL HEADERS
+//INTERNAL HEADERS
+#include <dali-toolkit/internal/layouting/hbox-layout-impl.h>
+
+namespace Dali
+{
+namespace Toolkit
+{
+
+HboxLayout::HboxLayout()
+{
+}
+
+HboxLayout HboxLayout::New()
+{
+  Internal::HboxLayoutPtr internal = Internal::HboxLayout::New();
+  return HboxLayout( internal.Get() );
+}
+
+HboxLayout HboxLayout::DownCast( BaseHandle handle )
+{
+  return HboxLayout( dynamic_cast< Dali::Toolkit::Internal::HboxLayout*>( handle.GetObjectPtr() ) );
+}
+
+HboxLayout::HboxLayout( const HboxLayout& other )
+: LayoutGroup( other )
+{
+}
+
+HboxLayout& HboxLayout::operator=( const HboxLayout& other )
+{
+  if( &other != this )
+  {
+    LayoutGroup::operator=( other );
+  }
+  return *this;
+}
+
+void HboxLayout::SetCellPadding( LayoutSize size )
+{
+  GetImplementation(*this).SetCellPadding( size );
+}
+
+LayoutSize HboxLayout::GetCellPadding()
+{
+  return GetImplementation(*this).GetCellPadding();
+}
+
+HboxLayout::HboxLayout( Dali::Toolkit::Internal::HboxLayout* object )
+: LayoutGroup( object )
+{
+}
+
+} // namespace Toolkit
+} // namespace Dali
diff --git a/dali-toolkit/devel-api/layouting/hbox-layout.h b/dali-toolkit/devel-api/layouting/hbox-layout.h
new file mode 100644 (file)
index 0000000..62c4bf7
--- /dev/null
@@ -0,0 +1,137 @@
+#ifndef DALI_TOOLKIT_LAYOUTING_HBOX_LAYOUT_H
+#define DALI_TOOLKIT_LAYOUTING_HBOX_LAYOUT_H
+
+/*
+ * Copyright (c) 2018 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <dali/public-api/common/dali-common.h>
+#include <dali/public-api/object/base-handle.h>
+#include <dali-toolkit/devel-api/layouting/layout-group.h>
+#include <dali-toolkit/devel-api/layouting/layout-size.h>
+#include <dali-toolkit/public-api/toolkit-property-index-ranges.h>
+
+namespace Dali
+{
+namespace Toolkit
+{
+
+namespace Internal DALI_INTERNAL
+{
+class HboxLayout;
+}
+
+/**
+ * This class implements a horizontal box layout, automatically handling
+ * right to left or left to right direction change.
+ */
+class DALI_IMPORT_API HboxLayout : public LayoutGroup
+{
+public:
+
+  enum PropertyRange
+  {
+    CHILD_PROPERTY_START_INDEX = LayoutGroup::CHILD_PROPERTY_START_INDEX+100,
+    CHILD_PROPERTY_END_INDEX   = CHILD_PROPERTY_START_INDEX+1000
+  };
+
+  struct Property
+  {
+    // @todo When we can have event-only properties for BaseObject, this will be useful.
+    enum
+    {
+      CELL_PADDING = PROPERTY_REGISTRATION_START_INDEX + 2000
+    };
+  };
+
+  struct ChildProperty
+  {
+    enum
+    {
+      WEIGHT = CHILD_PROPERTY_START_INDEX
+    };
+  };
+
+  /**
+   * @brief Creates an uninitialized HboxLayout handle.
+   *
+   * Initialize it using HboxLayout::New().
+   * Calling member functions with an uninitialized handle is not allowed.
+   */
+  HboxLayout();
+
+  /**
+   * @brief Creates a HboxLayout object.
+   */
+  static HboxLayout New();
+
+  /**
+   * @brief Downcasts a handle to a HboxLayout handle.
+   *
+   * If handle points to a HboxLayout, the downcast produces a valid handle.
+   * If not, the returned handle is left uninitialized.
+
+   * @param[in] handle to an object
+   * @return Handle to a HboxLayout or an uninitialized handle
+   */
+  static HboxLayout DownCast( BaseHandle handle );
+
+  /**
+   * @brief Copy constructor
+   */
+  HboxLayout( const HboxLayout& other );
+
+  /**
+   * @brief Assigment operator
+   */
+  HboxLayout& operator=( const HboxLayout& other );
+
+  /**
+   * @brief Default destructor.
+   *
+   * This is non-virtual, since derived Handle types must not contain data or virtual methods
+   */
+  ~HboxLayout()=default;
+
+  /**
+   * @brief Set the padding between cells in the layout
+   *
+   * @param[in] size The padding between cells.
+   */
+  void SetCellPadding( LayoutSize size );
+
+  /**
+   * @brief Get the padding between cells in the layout
+   *
+   * @return The padding between cells.
+   */
+  LayoutSize GetCellPadding();
+
+public: // Not intended for application developers
+
+  /// @cond internal
+  /**
+   * @brief This constructor is used by HboxLayout::New() methods.
+   *
+   * @param[in] actor A pointer to a newly allocated Dali resource
+   */
+  explicit DALI_INTERNAL HboxLayout( Internal::HboxLayout* body );
+  /// @endcond
+};
+
+} // namespace Toolkit
+} // namespace Dali
+
+#endif // DALI_TOOLKIT_LAYOUTING_HBOX_LAYOUT_H
diff --git a/dali-toolkit/devel-api/layouting/layout-controller.cpp b/dali-toolkit/devel-api/layouting/layout-controller.cpp
new file mode 100644 (file)
index 0000000..645fe48
--- /dev/null
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2018 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// CLASS HEADER
+#include <dali-toolkit/devel-api/layouting/layout-controller.h>
+
+// EXTERNAL INCLUDES
+#include <dali/devel-api/adaptor-framework/singleton-service.h>
+
+// INTERNAL INCLUDES
+#include <dali-toolkit/internal/layouting/layout-controller-impl.h>
+
+
+namespace Dali
+{
+namespace Toolkit
+{
+
+LayoutController::LayoutController()
+{
+}
+
+LayoutController::~LayoutController()
+{
+}
+
+LayoutController LayoutController::Get()
+{
+  LayoutController layoutController;
+
+  SingletonService singletonService( SingletonService::Get() );
+  if ( singletonService )
+  {
+    Dali::BaseHandle handle = singletonService.GetSingleton( typeid(LayoutController) );
+    if( handle )
+    {
+      // If so, downcast the handle of singleton to layout controller
+      layoutController = LayoutController( dynamic_cast<Internal::LayoutController*>( handle.GetObjectPtr() ) );
+    }
+
+    if( !layoutController )
+    {
+      // If not, create the layout controller and register it as a singleton
+      Internal::LayoutController* impl = new Internal::LayoutController();
+      layoutController = LayoutController( impl );
+      impl->Initialize();
+
+      // Registering the singleton will automatically register the processor with Core.
+      singletonService.Register( typeid(layoutController), layoutController );
+    }
+  }
+
+  return layoutController;
+}
+
+void LayoutController::RequestLayout( LayoutItem layout )
+{
+  GetImpl(*this).RequestLayout( GetImplementation( layout ) );
+}
+
+LayoutController::LayoutController( Internal::LayoutController *impl )
+: BaseHandle( impl )
+{
+}
+
+} //namespace Toolkit
+} //namespace Dali
diff --git a/dali-toolkit/devel-api/layouting/layout-controller.h b/dali-toolkit/devel-api/layouting/layout-controller.h
new file mode 100644 (file)
index 0000000..db5cc5b
--- /dev/null
@@ -0,0 +1,84 @@
+#ifndef DALI_TOOLKIT_DEVEL_LAYOUT_CONTROLLER_H
+#define DALI_TOOLKIT_DEVEL_LAYOUT_CONTROLLER_H
+/*
+ * Copyright (c) 2018 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <dali/public-api/object/base-handle.h>
+#include <dali/public-api/common/dali-common.h>
+#include <dali-toolkit/public-api/controls/control.h>
+#include <dali-toolkit/devel-api/layouting/layout-item.h>
+#include <dali-toolkit/devel-api/layouting/layout-group.h>
+
+namespace Dali
+{
+namespace Toolkit
+{
+
+namespace Internal
+{
+class LayoutController;
+}
+
+/**
+ * @brief Controls the process of layouting the control tree. It provides methods to enable
+ * controls to re-layout and internal systems to separately measure and layout controls.
+ */
+class DALI_IMPORT_API LayoutController : public BaseHandle
+{
+public:
+  /**
+   * @brief Constructor - create an uninitialized handle.
+   *
+   * This can be initialized with LayoutController::Get().
+   * Calling member functions with an uninitialized handle is not allowed.
+   */
+  LayoutController();
+
+  /**
+   * @brief Destructor.
+   *
+   * This is non-virtual since derived Handle types must not contain data or virtual methods.
+   */
+  ~LayoutController();
+
+  /**
+   * @brief Gets the singleton of the LayoutController object.
+   *
+   * @return A handle to the LayoutController object.
+   */
+  static LayoutController Get();
+
+  /**
+   * @brief Request for a particular layout (wrapping a control or a visual) to be measured and laid out.
+   * @param[in] layout The layout to measure & relayout.
+   */
+  void RequestLayout( LayoutItem layout );
+
+public:
+  /// @cond internal
+  /**
+   * @brief This constructor is used by LayoutController::New() methods.
+   *
+   * @param[in] actor A pointer to a newly allocated Dali resource
+   */
+  explicit DALI_INTERNAL LayoutController( Internal::LayoutController *impl );
+  /// @endcond
+};
+
+} // namespace Toolkit
+} // namespace Dali
+
+#endif // DALI_TOOLKIT_DEVEL_LAYOUT_CONTROLLER_H
diff --git a/dali-toolkit/devel-api/layouting/layout-group-impl.cpp b/dali-toolkit/devel-api/layouting/layout-group-impl.cpp
new file mode 100644 (file)
index 0000000..21fb391
--- /dev/null
@@ -0,0 +1,447 @@
+/*
+ * Copyright (c) 2018 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// CLASS HEADER
+#include <dali/public-api/object/type-registry-helper.h>
+#include <dali/devel-api/actors/actor-devel.h>
+#include <dali/devel-api/object/handle-devel.h>
+#include <dali-toolkit/devel-api/layouting/layout-group-impl.h>
+#include <dali-toolkit/internal/layouting/layout-group-data-impl.h>
+#include <dali-toolkit/public-api/controls/control-impl.h>
+#include <dali-toolkit/internal/controls/control/control-data-impl.h>
+
+
+namespace
+{
+const char* MARGIN_SPECIFICATION_NAME( "marginSpec" );
+}
+
+namespace Dali
+{
+namespace Toolkit
+{
+namespace Internal
+{
+
+LayoutGroup::LayoutGroup()
+: mImpl( new LayoutGroup::Impl() ),
+  mSlotDelegate(this)
+{
+}
+
+LayoutGroup::~LayoutGroup()
+{
+  // An object with a unique_ptr to an opaque structure must define it's destructor in the translation unit
+  // where the opaque structure is defined. It cannot use the default method in the header file.
+}
+
+Toolkit::LayoutGroup::LayoutId LayoutGroup::Add( LayoutItem& child )
+{
+  LayoutParent* oldParent = child.GetParent();
+  if( oldParent )
+  {
+    LayoutGroupPtr parentGroup( dynamic_cast< LayoutGroup* >( oldParent ) );
+    if( parentGroup )
+    {
+      parentGroup->Remove( child );
+    }
+  }
+
+  Impl::ChildLayout childLayout;
+  childLayout.layoutId = mImpl->mNextLayoutId++;
+  childLayout.child = &child;
+  mImpl->mChildren.emplace_back( childLayout );
+
+  auto owner = child.GetOwner();
+
+  // If the owner does not have any LayoutItem child properties, add them
+  if( ! DevelHandle::DoesCustomPropertyExist( owner, Toolkit::LayoutItem::ChildProperty::WIDTH_SPECIFICATION ) )
+  {
+    // Set default properties for LayoutGroup and LayoutItem.
+    // Deriving classes can override OnChildAdd() to add their own default properties
+    GenerateDefaultChildPropertyValues( owner );
+  }
+
+  // Inform deriving classes that this child has been added
+  OnChildAdd( *childLayout.child.Get() );
+
+  // Now listen to future changes to the child properties.
+  DevelHandle::PropertySetSignal(owner).Connect( this, &LayoutGroup::OnSetChildProperties );
+
+  RequestLayout();
+
+  return childLayout.layoutId;
+}
+
+void LayoutGroup::Remove( Toolkit::LayoutGroup::LayoutId childId )
+{
+  for( auto iter = mImpl->mChildren.begin() ; iter != mImpl->mChildren.end() ; ++iter )
+  {
+    if( iter->layoutId == childId )
+    {
+      OnChildRemove( *iter->child.Get() );
+      mImpl->mChildren.erase(iter);
+      break;
+    }
+  }
+  RequestLayout();
+}
+
+void LayoutGroup::Remove( LayoutItem& child )
+{
+  for( auto iter = mImpl->mChildren.begin() ; iter != mImpl->mChildren.end() ; ++iter )
+  {
+    if( iter->child.Get() == &child )
+    {
+      OnChildRemove( *iter->child.Get() );
+      mImpl->mChildren.erase(iter);
+      break;
+    }
+  }
+  RequestLayout();
+}
+
+void LayoutGroup::RemoveAll()
+{
+  for( auto iter = mImpl->mChildren.begin() ; iter != mImpl->mChildren.end() ; ++iter )
+  {
+    OnChildRemove( *iter->child.Get() );
+    iter = mImpl->mChildren.erase(iter);
+  }
+}
+
+unsigned int LayoutGroup::GetChildCount() const
+{
+  return mImpl->mChildren.size();
+}
+
+LayoutItemPtr LayoutGroup::GetChildAt( unsigned int index ) const
+{
+  DALI_ASSERT_ALWAYS( index < mImpl->mChildren.size() );
+  return mImpl->mChildren[ index ].child;
+}
+
+LayoutItemPtr LayoutGroup::GetChild( Toolkit::LayoutGroup::LayoutId childId ) const
+{
+  for( auto&& childLayout : mImpl->mChildren )
+  {
+    if( childLayout.layoutId == childId )
+    {
+      return childLayout.child;
+    }
+  }
+  return NULL;
+}
+
+Toolkit::LayoutGroup::LayoutId LayoutGroup::GetChildId( LayoutItem& child ) const
+{
+  for( auto&& childLayout : mImpl->mChildren )
+  {
+    if( childLayout.child.Get() == &child )
+    {
+      return childLayout.layoutId;
+    }
+  }
+  return Toolkit::LayoutGroup::UNKNOWN_ID;
+}
+
+void LayoutGroup::OnChildAdd( LayoutItem& child )
+{
+}
+
+void LayoutGroup::OnChildRemove( LayoutItem& child )
+{
+}
+
+void LayoutGroup::DoInitialize()
+{
+}
+
+void LayoutGroup::DoRegisterChildProperties( const std::string& containerType )
+{
+}
+
+void LayoutGroup::OnSetChildProperties( Handle& handle, Property::Index index, Property::Value value )
+{
+  if ( ( index >= CHILD_PROPERTY_REGISTRATION_START_INDEX ) && ( index <= CHILD_PROPERTY_REGISTRATION_MAX_INDEX ) )
+  {
+    // If any child properties are set, must perform relayout
+    RequestLayout();
+  }
+}
+
+void LayoutGroup::GenerateDefaultChildPropertyValues( Handle child )
+{
+  child.SetProperty( Toolkit::LayoutItem::ChildProperty::WIDTH_SPECIFICATION,
+                     Toolkit::ChildLayoutData::WRAP_CONTENT );
+  child.SetProperty( Toolkit::LayoutItem::ChildProperty::HEIGHT_SPECIFICATION,
+                     Toolkit::ChildLayoutData::WRAP_CONTENT );
+  child.SetProperty( Toolkit::LayoutGroup::ChildProperty::MARGIN_SPECIFICATION, Extents() );
+}
+
+void LayoutGroup::MeasureChildren( MeasureSpec widthMeasureSpec, MeasureSpec heightMeasureSpec)
+{
+  for( auto&& child : mImpl->mChildren )
+  {
+    //if( (child.mViewFlags & Impl::VISIBILITY_MASK) != Impl::GONE ) // Use owner visibility/enabled/ready
+    {
+      MeasureChild( child.child, widthMeasureSpec, heightMeasureSpec );
+    }
+  }
+}
+
+void LayoutGroup::MeasureChild( LayoutItemPtr child,
+                                MeasureSpec parentWidthMeasureSpec,
+                                MeasureSpec parentHeightMeasureSpec )
+{
+  auto childOwner = child->GetOwner();
+  auto desiredWidth = childOwner.GetProperty<int>( Toolkit::LayoutItem::ChildProperty::WIDTH_SPECIFICATION );
+  auto desiredHeight = childOwner.GetProperty<int>( Toolkit::LayoutItem::ChildProperty::HEIGHT_SPECIFICATION );
+
+  auto padding = GetPadding();
+
+  const MeasureSpec childWidthMeasureSpec = GetChildMeasureSpec( parentWidthMeasureSpec,
+                                                                 padding.start + padding.end,
+                                                                 desiredWidth);
+  const MeasureSpec childHeightMeasureSpec = GetChildMeasureSpec( parentHeightMeasureSpec,
+                                                                  padding.top + padding.bottom,
+                                                                  desiredHeight);
+
+  child->Measure( childWidthMeasureSpec, childHeightMeasureSpec );
+}
+
+void LayoutGroup::MeasureChildWithMargins( LayoutItemPtr child,
+                                           MeasureSpec parentWidthMeasureSpec, LayoutLength widthUsed,
+                                           MeasureSpec parentHeightMeasureSpec, LayoutLength heightUsed)
+{
+  auto childOwner = child->GetOwner();
+  auto desiredWidth = childOwner.GetProperty<int>( Toolkit::LayoutItem::ChildProperty::WIDTH_SPECIFICATION );
+  auto desiredHeight = childOwner.GetProperty<int>( Toolkit::LayoutItem::ChildProperty::HEIGHT_SPECIFICATION );
+  auto desiredMargin = childOwner.GetProperty<Extents>( Toolkit::LayoutGroup::ChildProperty::MARGIN_SPECIFICATION );
+  auto padding = GetPadding();
+
+  MeasureSpec childWidthMeasureSpec = GetChildMeasureSpec( parentWidthMeasureSpec,
+                                                           padding.start + padding.end +
+                                                           desiredMargin.start + desiredMargin.end +
+                                                           widthUsed, desiredWidth );
+
+  MeasureSpec childHeightMeasureSpec = GetChildMeasureSpec( parentHeightMeasureSpec,
+                                                            padding.top + padding.bottom +
+                                                            desiredMargin.top + desiredMargin.end +
+                                                            heightUsed, desiredHeight );
+
+  child->Measure( childWidthMeasureSpec, childHeightMeasureSpec );
+}
+
+
+MeasureSpec LayoutGroup::GetChildMeasureSpec(
+  MeasureSpec  measureSpec,
+  LayoutLength padding,
+  LayoutLength childDimension )
+{
+  auto specMode = measureSpec.GetMode();
+  LayoutLength specSize = measureSpec.GetSize();
+
+  auto size = std::max( LayoutLength(0), specSize - padding );
+
+  MeasureSpec::IntType resultSize = 0;
+  MeasureSpec::Mode resultMode = MeasureSpec::Mode::UNSPECIFIED;
+
+  switch( specMode )
+  {
+    // Parent has imposed an exact size on us
+    case MeasureSpec::Mode::EXACTLY:
+    {
+
+      if (childDimension == Toolkit::ChildLayoutData::MATCH_PARENT)
+      {
+        // Child wants to be our size. So be it.
+        resultSize = size;
+        resultMode = MeasureSpec::Mode::EXACTLY;
+      }
+      else if (childDimension == Toolkit::ChildLayoutData::WRAP_CONTENT)
+      {
+        // Child wants to determine its own size. It can't be
+        // bigger than us.
+        resultSize = size;
+        resultMode = MeasureSpec::Mode::AT_MOST;
+      }
+      else
+      {
+        resultSize = childDimension;
+        resultMode = MeasureSpec::Mode::EXACTLY;
+      }
+
+      break;
+    }
+
+      // Parent has imposed a maximum size on us
+    case MeasureSpec::Mode::AT_MOST:
+    {
+      if (childDimension == Toolkit::ChildLayoutData::MATCH_PARENT)
+      {
+        // Child wants to be our size, but our size is not fixed.
+        // Constrain child to not be bigger than us.
+        resultSize = size;
+        resultMode = MeasureSpec::Mode::AT_MOST;
+      }
+      else if (childDimension == Toolkit::ChildLayoutData::WRAP_CONTENT)
+      {
+        // Child wants to determine its own size. It can't be
+        // bigger than us.
+        resultSize = size;
+        resultMode = MeasureSpec::Mode::AT_MOST;
+      }
+      else
+      {
+        // Child wants a specific size... so be it
+        resultSize = childDimension;
+        resultMode = MeasureSpec::Mode::EXACTLY;
+      }
+
+      break;
+    }
+
+      // Parent asked to see how big we want to be
+    case MeasureSpec::Mode::UNSPECIFIED:
+    {
+      if (childDimension == Toolkit::ChildLayoutData::MATCH_PARENT)
+      {
+        // Child wants to be our size... find out how big it should be
+        resultSize = LayoutItem::Impl::sUseZeroUnspecifiedMeasureSpec ? LayoutLength(0) : size;
+        resultMode = MeasureSpec::Mode::UNSPECIFIED;
+      }
+      else if (childDimension == Toolkit::ChildLayoutData::WRAP_CONTENT)
+      {
+        // Child wants to determine its own size.... find out how big
+        // it should be
+        resultSize = LayoutItem::Impl::sUseZeroUnspecifiedMeasureSpec ? LayoutLength(0) : size;
+        resultMode = MeasureSpec::Mode::UNSPECIFIED;
+      }
+      else
+      {
+        // Child wants a specific size... let him have it
+        resultSize = childDimension;
+        resultMode = MeasureSpec::Mode::EXACTLY;
+      }
+      break;
+    }
+  }
+
+  //noinspection ResourceType
+  return MeasureSpec( resultSize, resultMode );
+}
+
+
+void LayoutGroup::OnInitialize()
+{
+  auto control = Toolkit::Control::DownCast( GetOwner() );
+
+  if( control )
+  {
+    // Take ownership of existing children
+    for( unsigned int childIndex = 0 ; childIndex < control.GetChildCount(); ++childIndex )
+    {
+      ChildAddedToOwner( control.GetChildAt( childIndex ) );
+    }
+
+    DevelActor::ChildAddedSignal( control ).Connect( mSlotDelegate, &LayoutGroup::ChildAddedToOwner );
+    DevelActor::ChildRemovedSignal( control ).Connect( mSlotDelegate, &LayoutGroup::ChildRemovedFromOwner );
+    DevelHandle::PropertySetSignal( control ).Connect( mSlotDelegate, &LayoutGroup::OnOwnerPropertySet );
+  }
+}
+
+void LayoutGroup::OnRegisterChildProperties( const std::string& containerType )
+{
+  auto typeInfo = TypeRegistry::Get().GetTypeInfo( containerType );
+  if( typeInfo )
+  {
+    Property::IndexContainer indices;
+    typeInfo.GetChildPropertyIndices( indices );
+
+    if( std::find( indices.Begin(), indices.End(), Toolkit::LayoutGroup::ChildProperty::MARGIN_SPECIFICATION ) ==
+        indices.End() )
+    {
+      ChildPropertyRegistration( typeInfo.GetName(), MARGIN_SPECIFICATION_NAME, Toolkit::LayoutGroup::ChildProperty::MARGIN_SPECIFICATION, Property::EXTENTS );
+    }
+  }
+
+  DoRegisterChildProperties( containerType );
+}
+
+void LayoutGroup::OnUnparent()
+{
+  RemoveAll();
+}
+
+void LayoutGroup::ChildAddedToOwner( Actor child )
+{
+  LayoutItemPtr childLayout;
+  Toolkit::Control control = Toolkit::Control::DownCast( child );
+
+  if( control ) // Can only support adding Controls, not Actors to layout
+  {
+    Internal::Control& childControlImpl = GetImplementation( control );
+    Internal::Control::Impl& childControlDataImpl = Internal::Control::Impl::Get( childControlImpl );
+    childLayout = childControlDataImpl.GetLayout();
+
+    if( ! childLayout )
+    {
+      // If the child doesn't already have a layout, then create a LayoutItem for it.
+      childLayout = LayoutItem::New( control );
+      childLayout->SetAnimateLayout( IsLayoutAnimated() ); // @todo this essentially forces animation inheritance. Bad?
+
+      auto desiredSize = control.GetNaturalSize();
+      childControlDataImpl.SetLayout( *childLayout.Get() );
+
+      // HBoxLayout will apply default layout data for this object
+      child.SetProperty( Toolkit::LayoutItem::ChildProperty::WIDTH_SPECIFICATION, LayoutLength::IntType( desiredSize.width ) );
+      child.SetProperty( Toolkit::LayoutItem::ChildProperty::HEIGHT_SPECIFICATION, LayoutLength::IntType( desiredSize.height ) );
+      child.SetProperty( Toolkit::LayoutGroup::ChildProperty::MARGIN_SPECIFICATION, Extents() );
+    }
+
+    Add( *childLayout.Get() );
+  }
+}
+
+void LayoutGroup::ChildRemovedFromOwner( Actor child )
+{
+  Toolkit::Control control = Toolkit::Control::DownCast( child );
+  if( control )
+  {
+    Internal::Control& childControlImpl = GetImplementation( control );
+    Internal::Control::Impl& childControlDataImpl = Internal::Control::Impl::Get( childControlImpl );
+    auto childLayout = childControlDataImpl.GetLayout();
+    if( childLayout )
+    {
+      Remove( *childLayout.Get() );
+    }
+  }
+}
+
+void LayoutGroup::OnOwnerPropertySet( Handle& handle, Property::Index index, Property::Value value )
+{
+  auto actor = Actor::DownCast( handle );
+  if( actor && index == Actor::Property::LAYOUT_DIRECTION )
+  {
+    RequestLayout();
+  }
+}
+
+
+} // namespace Internal
+} // namespace Toolkit
+} // namespace Dali
diff --git a/dali-toolkit/devel-api/layouting/layout-group-impl.h b/dali-toolkit/devel-api/layouting/layout-group-impl.h
new file mode 100644 (file)
index 0000000..025950c
--- /dev/null
@@ -0,0 +1,297 @@
+#ifndef DALI_TOOLKIT_INTERNAL_LAYOUTING_LAYOUT_GROUP_H
+#define DALI_TOOLKIT_INTERNAL_LAYOUTING_LAYOUT_GROUP_H
+/*
+ * Copyright (c) 2018 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <memory>
+
+#include <dali/public-api/common/intrusive-ptr.h>
+#include <dali/public-api/actors/actor-enumerations.h>
+#include <dali/public-api/signals/connection-tracker.h>
+#include <dali-toolkit/devel-api/layouting/child-layout-data.h>
+#include <dali-toolkit/devel-api/layouting/layout-group.h>
+#include <dali-toolkit/devel-api/layouting/layout-item-impl.h>
+
+namespace Dali
+{
+namespace Toolkit
+{
+namespace Internal
+{
+
+class LayoutGroup;
+using LayoutGroupPtr = IntrusivePtr<LayoutGroup>;
+
+/**
+ * LayoutGroup is an abstract class that provides child layout management and basic measuring and layouting.
+ *
+ * Deriving classes should override LayoutItem::DoInitialize for second stage initialization,
+ * LayoutGroup::DoRegisterChildProperties to register child property types with the owner,
+ * LayoutGroup::OnChildAdd to apply default child property values to the child.
+ * Deriving classes may override LayoutGroup::OnChildRemove.
+ *
+ * Deriving classes must also override OnMeasure and OnLayout as follows:
+ *
+ * OnMeasure should measure each child using LayoutGroup::MeasureChildWithMargins or LayoutGroup::MeasureChild.
+ * We recommend calling LayoutItem::ResolveSizeAndState() to resolve measure specs.
+ * If some children don't fit, then they can be measured again with different MeasureSpecs as required.
+ *
+ * After measurement, the derived class must also call SetMeasuredDimensions to set it's own requested size.
+ *
+ * OnLayout should use it's own layout parameters and the measured children's size to determine the children's
+ * position and size; it should then call Layout() on the child layout to layout the child and it's hierarchy.
+ */
+class DALI_IMPORT_API LayoutGroup : public LayoutItem,
+                                    public ConnectionTracker
+{
+public:
+  /**
+   * Constructor. Returns an initialized object
+   */
+  LayoutGroup();
+
+protected:
+  /**
+   * Virtual destructor may only be called by Unreference()
+   */
+  virtual ~LayoutGroup();
+
+public:
+  LayoutGroup( const LayoutGroup& copy ) = delete;
+  LayoutGroup& operator=( const LayoutGroup& rhs ) = delete;
+
+  /**
+   * @brief Add a layout child to this group.
+   *
+   * @param[in] layoutChild The child to add
+   * @return The layout id of this child.
+   */
+  Toolkit::LayoutGroup::LayoutId Add( LayoutItem& layoutChild );
+
+  /**
+   * @brief Remove a layout child from this group.
+   * @param[in] childId The layout child id
+   */
+  void Remove( Toolkit::LayoutGroup::LayoutId childId );
+
+  /**
+   * @brief Remove a layout child from this group
+   * @param[in] child The layout child
+   */
+  void Remove( LayoutItem& child );
+
+  /**
+   * @brief Remove all layout children.
+   *
+   * @note This will not unparent owner's children
+   */
+  void RemoveAll();
+
+
+  /**
+   * @brief Get the number of children contained by this layout group
+   *
+   * @return the number of children
+   */
+  unsigned int GetChildCount() const;
+
+  /**
+   * Get the child layout at the given index
+   */
+  LayoutItemPtr GetChildAt( unsigned int childIndex ) const;
+
+  /**
+   * Get the child layout id of the given child
+   */
+  Toolkit::LayoutGroup::LayoutId GetChildId( LayoutItem& child ) const;
+
+  /**
+   * @brief Get the layout child with the given layout id.
+   * @note child id's start at 1, and follow the insertion order
+   * @param[in] childId the layout id of the child within this group
+   * @return A pointer to the child layout
+   */
+  LayoutItemPtr GetChild( Toolkit::LayoutGroup::LayoutId childId ) const;
+
+  template <typename T>
+    LayoutItemPtr GetChild( T childId ) = delete; // Prevent implicit casting of int/uint to LayoutId
+
+  /**
+   * Callback when child is added to container.
+   * Derived classes can use this to set their own child properties on the child layout's owner.
+   */
+  virtual void OnChildAdd( LayoutItem& child );
+
+  /**
+   * Callback when child is removed from container.
+   */
+  virtual void OnChildRemove( LayoutItem& child );
+
+  /**
+   * @brief Calculate the right measure spec for this child.
+   *
+   * Does the hard part of MeasureChildren: figuring out the MeasureSpec to
+   * pass to a particular child. This method figures out the right MeasureSpec
+   * for one dimension (height or width) of one child view.
+   *
+   * The goal is to combine information from our MeasureSpec with the
+   * LayoutParams of the child to get the best possible results. For example,
+   * if the this view knows its size (because its MeasureSpec has a mode of
+   * EXACTLY), and the child has indicated in its LayoutParams that it wants
+   * to be the same size as the parent, the parent should ask the child to
+   * layout given an exact size.
+   *
+   * @param measureSpec The requirements for this view
+   *
+   * @param padding The padding of this view for the current dimension
+   *        and margins, if applicable
+   *
+   * @param childDimension How big the child wants to be in the
+   *        current dimension
+   * @return a MeasureSpec for the child
+   */
+  static MeasureSpec GetChildMeasureSpec( MeasureSpec measureSpec,
+                                          LayoutLength padding,
+                                          LayoutLength childDimension );
+
+protected:
+  /**
+   * @brief Second stage initialization method for deriving classes to override
+   */
+  virtual void DoInitialize();
+
+  /**
+   * @brief Method for derived classes to implement in order to register child
+   * property types with the container.
+   *
+   * @param[in] containerType The fully qualified typename of the container
+   */
+  virtual void DoRegisterChildProperties( const std::string& containerType );
+
+  /**
+   * Create default child property values suitable for this layout group or derived layouter
+   */
+  virtual void GenerateDefaultChildPropertyValues( Handle child );
+
+  /**
+   * Ask all of the children of this view to measure themselves, taking into
+   * account both the MeasureSpec requirements for this view and its padding.
+   * The heavy lifting is done in GetChildMeasureSpec.
+   *
+   * @param widthMeasureSpec The width requirements for this view
+   * @param heightMeasureSpec The height requirements for this view
+   */
+  virtual void MeasureChildren( MeasureSpec widthMeasureSpec, MeasureSpec heightMeasureSpec );
+
+  /**
+   * Ask one of the children of this view to measure itself, taking into
+   * account both the MeasureSpec requirements for this view and its padding.
+   * The heavy lifting is done in GetChildMeasureSpec.
+   *
+   * @param child The child to measure
+   * @param parentWidthMeasureSpec The width requirements for this view
+   * @param parentHeightMeasureSpec The height requirements for this view
+   */
+  virtual void MeasureChild( LayoutItemPtr child, MeasureSpec parentWidthMeasureSpec, MeasureSpec parentHeightMeasureSpec );
+
+  /**
+   * Ask one of the children of this view to measure itself, taking into
+   * account both the MeasureSpec requirements for this view and its padding
+   * and margins. The child must have MarginLayoutParams The heavy lifting is
+   * done in GetChildMeasureSpec.
+   *
+   * @param child The child to measure
+   * @param parentWidthMeasureSpec The width requirements for this view
+   * @param widthUsed Extra space that has been used up by the parent
+   *        horizontally (possibly by other children of the parent)
+   * @param parentHeightMeasureSpec The height requirements for this view
+   * @param heightUsed Extra space that has been used up by the parent
+   *        vertically (possibly by other children of the parent)
+   */
+  virtual void MeasureChildWithMargins( LayoutItemPtr child,
+                                        MeasureSpec parentWidthMeasureSpec,
+                                        LayoutLength widthUsed,
+                                        MeasureSpec parentHeightMeasureSpec,
+                                        LayoutLength heightUsed );
+
+private:
+  /**
+   * Second stage initialization for LayoutGroup only.
+   * This will call DoInitialize on most derived class.
+   */
+  void OnInitialize() override final;
+
+  /**
+   * @copydoc LayoutItem::OnRegisterChildProperties()
+   */
+  void OnRegisterChildProperties( const std::string& containerType ) override final;
+
+  /**
+   * @copydoc LayoutItem::OnUnparent
+   */
+  void OnUnparent() override final;
+
+  /**
+   * Callback when child is added to owner
+   */
+  void ChildAddedToOwner( Actor child );
+
+  /**
+   * Callback when child is removed from owner
+   */
+  void ChildRemovedFromOwner( Actor child );
+
+  /**
+   * Callback when an owner property is set. Triggers a relayout if it's a child property
+   */
+  void OnOwnerPropertySet( Handle& handle, Property::Index index, Property::Value value );
+
+  /**
+   * Callback when a child property is set on any given child
+   * @param[in] handle The handle to the child
+   * @param[in] index The index of the property that has been set
+   * @param[in] value The new value of the property
+   */
+  void OnSetChildProperties( Handle& handle, Property::Index index, Property::Value value );
+
+public:
+  class Impl; // Class declaration is public so we can add devel API's in the future
+
+private:
+  std::unique_ptr<Impl> mImpl; // The implementation data for this class.
+  SlotDelegate<LayoutGroup> mSlotDelegate; ///< Slot delegate allows this class to connect safely to signals
+};
+
+} //namespace Internal
+
+inline Internal::LayoutGroup& GetImplementation( Dali::Toolkit::LayoutGroup& handle )
+{
+  DALI_ASSERT_ALWAYS( handle && "LayoutGroup handle is empty" );
+  BaseObject& object = handle.GetBaseObject();
+  return static_cast< Internal::LayoutGroup& >( object );
+}
+
+inline const Internal::LayoutGroup& GetImplementation( const Dali::Toolkit::LayoutGroup& handle )
+{
+  DALI_ASSERT_ALWAYS( handle && "LayoutGroup handle is empty" );
+  const BaseObject& object = handle.GetBaseObject();
+  return static_cast< const Internal::LayoutGroup& >( object );
+}
+
+}//namespace Toolkit
+}//namespace Dali
+
+#endif // DALI_TOOLKIT_INTERNAL_LAYOUTING_LAYOUT_GROUP_H
diff --git a/dali-toolkit/devel-api/layouting/layout-group.cpp b/dali-toolkit/devel-api/layouting/layout-group.cpp
new file mode 100644 (file)
index 0000000..dd36ddc
--- /dev/null
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2018 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <dali-toolkit/devel-api/layouting/layout-group.h>
+#include <dali-toolkit/devel-api/layouting/layout-group-impl.h>
+
+namespace Dali
+{
+namespace Toolkit
+{
+
+LayoutGroup::LayoutGroup()
+: LayoutItem()
+{
+}
+
+LayoutGroup::LayoutId LayoutGroup::Add( LayoutItem& child )
+{
+  return GetImplementation( *this ).Add( GetImplementation(child) );
+}
+
+void LayoutGroup::Remove( LayoutGroup::LayoutId childId )
+{
+  GetImplementation( *this ).Remove( childId );
+}
+
+void LayoutGroup::Remove( LayoutItem& child )
+{
+  GetImplementation( *this ).Remove( GetImplementation(child) );
+}
+
+LayoutItem LayoutGroup::GetChild( LayoutGroup::LayoutId childId ) const
+{
+  Internal::LayoutItemPtr child = GetImplementation( *this ).GetChild( childId );
+  return LayoutItem( child.Get() );
+}
+
+LayoutItem LayoutGroup::GetChildAt( unsigned int childId ) const
+{
+  Internal::LayoutItemPtr child = GetImplementation( *this ).GetChildAt( childId );
+  return LayoutItem( child.Get() );
+}
+
+unsigned int LayoutGroup::GetChildCount() const
+{
+  return GetImplementation( *this ).GetChildCount();
+}
+
+LayoutGroup::LayoutGroup( Internal::LayoutGroup* layoutGroup )
+: LayoutItem( layoutGroup )
+{
+}
+
+} // namespace Toolkit
+} // namespace Dali
diff --git a/dali-toolkit/devel-api/layouting/layout-group.h b/dali-toolkit/devel-api/layouting/layout-group.h
new file mode 100644 (file)
index 0000000..d006775
--- /dev/null
@@ -0,0 +1,174 @@
+#ifndef DALI_TOOLKIT_LAYOUTING_LAYOUT_GROUP_H
+#define DALI_TOOLKIT_LAYOUTING_LAYOUT_GROUP_H
+/*
+ * Copyright (c) 2018 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <memory>
+#include <dali/public-api/common/dali-common.h>
+#include <dali/public-api/actors/actor-enumerations.h>
+#include <dali-toolkit/devel-api/layouting/layout-item.h>
+#include <dali-toolkit/devel-api/layouting/measure-spec.h>
+
+namespace Dali
+{
+namespace Toolkit
+{
+
+namespace Internal
+{
+class LayoutGroup;
+}
+
+
+/**
+ * A layout that has layout children. Implements LayoutItem.
+ * It can both layout it's children, and be laid out by a parent container.
+ *
+ * A layout group automatically handles adding a Control container's children to itself,
+ * both on startup and on child add/remove. If this functionality is not desired, this needs
+ * splitting into two classes; one that manages just the layout part, and the other which
+ * handles Actor hierarchy. (@todo Consider doing this anyway...)
+ *
+ * This handle class allows the application to set up layout properties for the layout group;
+ * it doesn't access measure/layout directly.
+ *
+ * To write a new layout, inherit from both LayoutGroup handle and Internal::LayoutGroup body.
+ *
+ */
+class DALI_IMPORT_API LayoutGroup : public LayoutItem
+{
+public:
+  using LayoutId = unsigned int;
+  static const unsigned int UNKNOWN_ID = 0;
+
+  enum PropertyRange
+  {
+    CHILD_PROPERTY_START_INDEX = CHILD_PROPERTY_REGISTRATION_START_INDEX+100,
+    CHILD_PROPERTY_END_INDEX   = CHILD_PROPERTY_START_INDEX+1000
+  };
+
+  struct ChildProperty
+  {
+    enum
+    {
+      MARGIN_SPECIFICATION = CHILD_PROPERTY_START_INDEX,
+    };
+  };
+
+
+  /**
+   * @brief Creates an uninitialized LayoutGroup handle.
+   *
+   * LayoutGroup is intended as a base class, and as such, does not have a New method.
+   *
+   * Calling member functions with an uninitialized handle is not allowed.
+   */
+  LayoutGroup();
+
+  /**
+   * @brief Default Destructor.
+   *
+   * This is non-virtual since derived Handle types must not contain data or virtual methods.
+   */
+  ~LayoutGroup() = default;
+
+  /**
+   * @brief Copy constructor
+   */
+  LayoutGroup(const LayoutGroup& copy) = default;
+
+  /**
+   * @brief Assigment operator
+   */
+  LayoutGroup& operator=(const LayoutGroup& rhs) = default;
+
+  /**
+   * @brief Downcasts a handle to a LayoutGroup handle.
+   *
+   * If handle points to a LayoutGroup, the downcast produces a valid handle.
+   * If not, the returned handle is left uninitialized.
+
+   * @param[in] handle to an object
+   * @return Handle to a LayoutGroup or an uninitialized handle
+   */
+  static LayoutGroup DownCast( BaseHandle handle );
+
+  /**
+   * @brief Add a child layout to the layout group
+   *
+   * @param[in] childLayout The layout to add.
+   * @return an Id of the child.
+   */
+  LayoutId Add( LayoutItem& childLayout );
+
+  /**
+   * @brief Add a child layout to the layout group
+   *
+   * @param[in] childId the id of the child to remove
+   */
+  void Remove( LayoutId childId );
+
+  /**
+   * @brief Remove a child layout from the layout group
+   *
+   * @param[in] childLayout The layout to remove.
+   */
+  void Remove( LayoutItem& childLayout );
+
+  /**
+   * @brief Get the child at the given index.
+   *
+   * @param[in] index The index of the child.
+   */
+  LayoutItem GetChildAt( unsigned int index ) const;
+
+  /**
+   * @brief Get the count of the children of the layout
+   *
+   * @return the count of the children of the layout
+   */
+  unsigned int GetChildCount() const ;
+
+  /**
+   * @brief Get the child referenced by childId.
+   *
+   * @param[in] childId The id of the child to get
+   * @return A handle to the child layout, or empty if not found
+   */
+  LayoutItem GetChild( LayoutId childId ) const ;
+
+  /**
+   * Delete template method to remove implicit casting to integer types.
+   */
+  template <typename T>
+    LayoutItem GetChild( T childId ) = delete;
+
+public:
+  /// @cond internal
+  /**
+   * @brief This constructor is used by LayoutGroup::New() methods.
+   *
+   * @param[in] actor A pointer to a newly allocated Dali resource
+   */
+  explicit LayoutGroup( Internal::LayoutGroup* layoutGroup );
+  /// @endcond
+};
+
+
+} // namespace Toolkit
+} // namespace Dali
+
+#endif // DALI_TOOLKIT_LAYOUTING_LAYOUT_GROUP_H
diff --git a/dali-toolkit/devel-api/layouting/layout-item-impl.cpp b/dali-toolkit/devel-api/layouting/layout-item-impl.cpp
new file mode 100644 (file)
index 0000000..f6bd7f8
--- /dev/null
@@ -0,0 +1,436 @@
+/*
+ * Copyright (c) 2018 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <dali/integration-api/debug.h>
+
+#include <dali/public-api/animation/animation.h>
+#include <dali/public-api/object/type-registry-helper.h>
+#include <dali-toolkit/public-api/controls/control.h>
+#include <dali-toolkit/devel-api/layouting/layout-item-impl.h>
+#include <dali-toolkit/internal/layouting/layout-item-data-impl.h>
+
+#if defined(DEBUG_ENABLED)
+    Debug::Filter* gLayoutFilter = Debug::Filter::New( Debug::Verbose, false, "LOG_LAYOUT" );
+#endif
+
+namespace
+{
+const char* WIDTH_SPECIFICATION_NAME( "widthSpecification" );
+const char* HEIGHT_SPECIFICATION_NAME( "heightSpecification" );
+
+const float DEFAULT_TRANSITION_DURATION( 0.5f );
+}
+
+namespace Dali
+{
+namespace Toolkit
+{
+namespace Internal
+{
+
+LayoutItem::LayoutItem()
+: mImpl( new LayoutItem::Impl() ),
+  mSlotDelegate( this )
+{
+}
+
+LayoutItem::~LayoutItem()
+{
+  // An object with a unique_ptr to an opaque structure must define it's destructor in the translation unit
+  // where the opaque structure is defined. It cannot use the default method in the header file.
+}
+
+LayoutItemPtr LayoutItem::New( Handle& owner )
+{
+  LayoutItemPtr layoutPtr = new LayoutItem();
+  return layoutPtr;
+}
+
+void LayoutItem::Initialize( Handle& owner, const std::string& containerType )
+{
+  mImpl->mOwner = &(owner.GetBaseObject());
+  RegisterChildProperties( containerType );
+  OnInitialize(); // Ensure direct deriving class gets initialized
+  RequestLayout();
+}
+
+Handle LayoutItem::GetOwner() const
+{
+  return Handle::DownCast(BaseHandle(mImpl->mOwner));
+}
+
+void LayoutItem::Unparent()
+{
+  // Enable directly derived types to first remove children
+  OnUnparent();
+
+  // Last, clear owner
+  mImpl->mOwner = NULL;
+}
+
+void LayoutItem::SetAnimateLayout( bool animateLayout )
+{
+  mImpl->mAnimated = animateLayout;
+}
+
+bool LayoutItem::IsLayoutAnimated() const
+{
+  return mImpl->mAnimated;
+}
+
+void LayoutItem::RegisterChildProperties( const std::string& containerType )
+{
+  // Call on derived types
+  auto typeInfo = TypeRegistry::Get().GetTypeInfo( containerType );
+  if( typeInfo )
+  {
+    Property::IndexContainer indices;
+    typeInfo.GetChildPropertyIndices( indices );
+
+    if( std::find( indices.Begin(), indices.End(), Toolkit::LayoutItem::ChildProperty::WIDTH_SPECIFICATION ) ==
+        indices.End() )
+    {
+      ChildPropertyRegistration( typeInfo.GetName(), WIDTH_SPECIFICATION_NAME,
+                                 Toolkit::LayoutItem::ChildProperty::WIDTH_SPECIFICATION, Property::INTEGER );
+
+      ChildPropertyRegistration( typeInfo.GetName(), HEIGHT_SPECIFICATION_NAME,
+                                 Toolkit::LayoutItem::ChildProperty::HEIGHT_SPECIFICATION, Property::INTEGER );
+    }
+
+    OnRegisterChildProperties( containerType );
+  }
+}
+
+void LayoutItem::OnRegisterChildProperties( const std::string& containerType )
+{
+}
+
+
+void LayoutItem::Measure( MeasureSpec widthMeasureSpec, MeasureSpec heightMeasureSpec )
+{
+  const bool forceLayout = mImpl->GetPrivateFlag( Impl::PRIVATE_FLAG_FORCE_LAYOUT );
+
+  const bool specChanged =
+    ( widthMeasureSpec  != mImpl->mOldWidthMeasureSpec ) ||
+    ( heightMeasureSpec != mImpl->mOldHeightMeasureSpec );
+
+  const bool isSpecExactly =
+    ( widthMeasureSpec.GetMode() == MeasureSpec::Mode::EXACTLY ) &&
+    ( heightMeasureSpec.GetMode() == MeasureSpec::Mode::EXACTLY );
+
+  const bool matchesSpecSize =
+    ( GetMeasuredWidth() == widthMeasureSpec.GetSize() ) &&
+    ( GetMeasuredHeight() == heightMeasureSpec.GetSize() );
+
+  const bool needsLayout = specChanged && ( !isSpecExactly || !matchesSpecSize );
+
+  if( forceLayout || needsLayout)
+  {
+    mImpl->ClearPrivateFlag( Impl::PRIVATE_FLAG_MEASURED_DIMENSION_SET );
+
+    //resolveRtlPropertiesIfNeeded();
+
+    int cacheIndex = -1;  // = forceLayout ? -1 : mMeasureCache.indexOfKey(key);
+    if( cacheIndex < 0 ) //|| sIgnoreMeasureCache )
+    {
+      // measure ourselves, this should set the measured dimension flag back
+      OnMeasure( widthMeasureSpec, heightMeasureSpec );
+      mImpl->ClearPrivateFlag( Impl::PRIVATE_FLAG_MEASURE_NEEDED_BEFORE_LAYOUT );
+    }
+    else
+    {
+      mImpl->SetPrivateFlag( Impl::PRIVATE_FLAG_MEASURE_NEEDED_BEFORE_LAYOUT );
+    }
+
+    // flag not set, setMeasuredDimension() was not invoked, we raise an exception to warn the developer
+    DALI_ASSERT_ALWAYS( mImpl->GetPrivateFlag( Impl::PRIVATE_FLAG_MEASURED_DIMENSION_SET ) &&
+                        "Layout's OnMeasure() did not set the measured dimension by calling setMeasuredDimension()" );
+    mImpl->SetPrivateFlag( Impl::PRIVATE_FLAG_LAYOUT_REQUIRED );
+  }
+
+  mImpl->mOldWidthMeasureSpec = widthMeasureSpec;
+  mImpl->mOldHeightMeasureSpec = heightMeasureSpec;
+
+  //mMeasureCache.put(key, ((long) mMeasuredWidth) << 32 | (long) mMeasuredHeight & 0xffffffffL); // suppress sign extension
+}
+
+void LayoutItem::Layout( LayoutLength l, LayoutLength t, LayoutLength r, LayoutLength b )
+{
+  if( mImpl->GetPrivateFlag( Impl::PRIVATE_FLAG_MEASURE_NEEDED_BEFORE_LAYOUT ) )
+  {
+    OnMeasure( mImpl->mOldWidthMeasureSpec, mImpl->mOldHeightMeasureSpec );
+    mImpl->ClearPrivateFlag( Impl::PRIVATE_FLAG_MEASURE_NEEDED_BEFORE_LAYOUT );
+  }
+
+  bool changed = SetFrame( l, t, r, b );
+
+  if( changed || mImpl->GetPrivateFlag( Impl::PRIVATE_FLAG_LAYOUT_REQUIRED ) )
+  {
+    OnLayout( changed, l, t, r, b );
+    mImpl->ClearPrivateFlag( Impl::PRIVATE_FLAG_LAYOUT_REQUIRED );
+  }
+
+  mImpl->ClearPrivateFlag( Impl::PRIVATE_FLAG_FORCE_LAYOUT );
+  mImpl->SetPrivateFlag( Impl::PRIVATE_FLAG_IS_LAID_OUT );
+}
+
+LayoutLength LayoutItem::GetMinimumWidth() const
+{
+  return mImpl->mMinimumSize.GetWidth();
+}
+
+LayoutLength LayoutItem::GetMinimumHeight() const
+{
+  return mImpl->mMinimumSize.GetHeight();
+}
+
+void LayoutItem::SetMinimumWidth( LayoutLength minimumWidth )
+{
+  mImpl->mMinimumSize.SetWidth( minimumWidth );
+  RequestLayout();
+}
+
+void LayoutItem::SetMinimumHeight( LayoutLength minimumHeight )
+{
+  mImpl->mMinimumSize.SetHeight( minimumHeight );
+  RequestLayout();
+}
+
+Extents LayoutItem::GetPadding() const
+{
+  return mImpl->mPadding;
+}
+
+LayoutLength LayoutItem::GetDefaultSize( LayoutLength size, MeasureSpec measureSpec )
+{
+  LayoutLength result = size;
+  auto specMode = measureSpec.GetMode();
+  auto specSize = measureSpec.GetSize();
+
+  switch (specMode)
+  {
+    case MeasureSpec::Mode::UNSPECIFIED:
+    {
+      result = size;
+      break;
+    }
+    case MeasureSpec::Mode::AT_MOST:
+    case MeasureSpec::Mode::EXACTLY:
+    {
+      result = specSize;
+      break;
+    }
+  }
+  return result;
+}
+
+void LayoutItem::OnMeasure( MeasureSpec widthMeasureSpec, MeasureSpec heightMeasureSpec)
+{
+  SetMeasuredDimensions( GetDefaultSize( GetSuggestedMinimumWidth(), widthMeasureSpec ),
+                         GetDefaultSize( GetSuggestedMinimumHeight(), heightMeasureSpec ) );
+}
+
+void LayoutItem::OnLayout( bool changed, LayoutLength left, LayoutLength top, LayoutLength right, LayoutLength bottom )
+{
+}
+
+LayoutParent* LayoutItem::GetParent()
+{
+  return mImpl->mLayoutParent;
+}
+
+void LayoutItem::RequestLayout()
+{
+  // @todo Enforce failure if called in Measure/Layout passes.
+  mImpl->SetPrivateFlag( Impl::PRIVATE_FLAG_FORCE_LAYOUT );
+  Toolkit::LayoutController layoutController = Toolkit::LayoutController::Get();
+  layoutController.RequestLayout( Toolkit::LayoutItem(this) );
+}
+
+bool LayoutItem::IsLayoutRequested() const
+{
+  return mImpl->GetPrivateFlag( Impl::PRIVATE_FLAG_FORCE_LAYOUT );
+}
+
+void LayoutItem::SetMeasuredDimensions( MeasuredSize measuredWidth, MeasuredSize measuredHeight )
+{
+  mImpl->SetPrivateFlag( Impl::PRIVATE_FLAG_MEASURED_DIMENSION_SET );
+  mImpl->mMeasuredWidth = measuredWidth;
+  mImpl->mMeasuredHeight = measuredHeight;
+}
+
+LayoutLength LayoutItem::GetMeasuredWidth() const
+{
+  // Get the size portion of the measured width
+  return  mImpl->mMeasuredWidth.GetSize();
+}
+
+LayoutLength LayoutItem::GetMeasuredHeight() const
+{
+  return  mImpl->mMeasuredHeight.GetSize();
+}
+
+MeasuredSize LayoutItem::GetMeasuredWidthAndState() const
+{
+  return mImpl->mMeasuredWidth;
+}
+
+MeasuredSize LayoutItem::GetMeasuredHeightAndState() const
+{
+  return mImpl->mMeasuredHeight;
+}
+
+LayoutLength LayoutItem::GetSuggestedMinimumWidth() const
+{
+  auto owner = GetOwner();
+  auto actor = Actor::DownCast(owner);
+  auto naturalSize = actor ? actor.GetNaturalSize() : Vector3::ZERO;
+
+  return std::max( mImpl->mMinimumSize.GetWidth(), LayoutLength::IntType( naturalSize.width ) );
+}
+
+LayoutLength LayoutItem::GetSuggestedMinimumHeight() const
+{
+  auto owner = GetOwner();
+  auto actor = Actor::DownCast(owner);
+  auto naturalSize = actor ? actor.GetNaturalSize() : Vector3::ZERO;
+
+  return std::max( mImpl->mMinimumSize.GetHeight(), LayoutLength::IntType(naturalSize.height) );
+}
+
+MeasuredSize LayoutItem::ResolveSizeAndState( LayoutLength size, MeasureSpec measureSpec, MeasuredSize::State childMeasuredState )
+{
+  auto specMode = measureSpec.GetMode();
+  LayoutLength specSize = measureSpec.GetSize();
+  MeasuredSize result;
+
+  switch( specMode )
+  {
+    case MeasureSpec::Mode::AT_MOST:
+    {
+      if (specSize < size)
+      {
+        result = MeasuredSize( specSize, MeasuredSize::MEASURED_SIZE_TOO_SMALL );
+      }
+      else
+      {
+        result.SetSize( size );
+      }
+      break;
+    }
+
+    case MeasureSpec::Mode::EXACTLY:
+    {
+      result.SetSize( specSize );
+      break;
+    }
+
+    case MeasureSpec::Mode::UNSPECIFIED:
+    default:
+    {
+      result.SetSize( size );
+      break;
+    }
+  }
+
+  result.SetState( childMeasuredState );
+  return result;
+}
+
+
+bool LayoutItem::SetFrame( LayoutLength left, LayoutLength top, LayoutLength right, LayoutLength bottom )
+{
+  bool changed = false;
+
+  DALI_LOG_INFO( gLayoutFilter, Debug::Verbose, "LayoutItem::SetFrame(%d, %d, %d, %d)\n", left.mValue, top.mValue, right.mValue, bottom.mValue );
+
+  if( mImpl->mLeft != left || mImpl->mRight != right || mImpl->mTop != top || mImpl->mBottom != bottom )
+  {
+    changed = true;
+
+    auto oldWidth = mImpl->mRight - mImpl->mLeft;
+    auto oldHeight = mImpl->mBottom - mImpl->mTop;
+    auto newWidth = right - left;
+    auto newHeight = bottom - top;
+    bool sizeChanged = (newWidth != oldWidth) || (newHeight != oldHeight);
+
+    mImpl->mLeft = left;
+    mImpl->mTop = top;
+    mImpl->mRight = right;
+    mImpl->mBottom = bottom;
+
+    mImpl->SetPrivateFlag( Impl::PRIVATE_FLAG_HAS_BOUNDS );
+
+
+    // Reflect up to parent control
+    auto owner = GetOwner();
+    auto actor = Actor::DownCast(owner);
+    if( actor )
+    {
+      if( mImpl->mAnimated )
+      {
+        auto animation = Animation::New( 0.5f );
+        animation.AnimateTo( Property( actor, Actor::Property::POSITION ),
+                             Vector3( float(left.mValue), float(top.mValue), 0.0f ) );
+        animation.AnimateTo( Property( actor, Actor::Property::SIZE ),
+                             Vector3( right-left, bottom-top, 0.0f ) );
+        animation.FinishedSignal().Connect( mSlotDelegate, &LayoutItem::OnLayoutAnimationFinished );
+        animation.Play();
+      }
+      else
+      {
+        // @todo Collate into list of Property & Property::Value pairs.
+        actor.SetPosition( Vector3( float(left.mValue), float(top.mValue), 0.0f ) );
+        actor.SetSize( Vector3( right-left, bottom-top, 0.0f ) );
+      }
+    }
+
+    if( sizeChanged )
+    {
+      SizeChange( LayoutSize( newWidth, newHeight ), LayoutSize( oldWidth, oldHeight ) );
+    }
+  }
+  return changed;
+}
+
+void LayoutItem::OnLayoutAnimationFinished( Animation& animation )
+{
+  auto owner = GetOwner();
+  auto actor = Actor::DownCast(owner);
+  if( actor )
+  {
+    actor.SetSize( Vector3( mImpl->mRight-mImpl->mLeft, mImpl->mBottom-mImpl->mTop, 0.0f ) );
+  }
+}
+
+void LayoutItem::SizeChange( LayoutSize newSize, LayoutSize oldSize)
+{
+  OnSizeChanged( newSize, oldSize );
+}
+
+
+void LayoutItem::OnSizeChanged( LayoutSize newSize, LayoutSize oldSize )
+{
+}
+
+void LayoutItem::OnInitialize()
+{
+}
+
+
+} // namespace Internal
+} // namespace Toolkit
+} // namespace Dali
diff --git a/dali-toolkit/devel-api/layouting/layout-item-impl.h b/dali-toolkit/devel-api/layouting/layout-item-impl.h
new file mode 100644 (file)
index 0000000..fb12913
--- /dev/null
@@ -0,0 +1,461 @@
+#ifndef DALI_TOOLKIT_INTERNAL_LAYOUTING_LAYOUT_ITEM_H
+#define DALI_TOOLKIT_INTERNAL_LAYOUTING_LAYOUT_ITEM_H
+/*
+ * Copyright (c) 2018 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <memory>
+
+#include <dali/public-api/common/intrusive-ptr.h>
+#include <dali/public-api/object/base-object.h>
+#include <dali/public-api/object/type-registry.h>
+#include <dali/public-api/actors/actor-enumerations.h>
+#include <dali-toolkit/devel-api/layouting/child-layout-data.h>
+#include <dali-toolkit/devel-api/layouting/layout-item.h>
+#include <dali-toolkit/devel-api/layouting/layout-parent-impl.h>
+#include <dali-toolkit/devel-api/layouting/layout-controller.h>
+#include <dali-toolkit/devel-api/layouting/layout-size.h>
+#include <dali-toolkit/devel-api/layouting/measure-spec.h>
+#include <dali-toolkit/devel-api/layouting/measured-size.h>
+
+namespace Dali
+{
+namespace Toolkit
+{
+namespace Internal
+{
+
+class LayoutItem;
+using LayoutItemPtr = IntrusivePtr<LayoutItem>;
+
+
+/**
+ * Base class for layouts.
+ */
+class DALI_IMPORT_API LayoutItem : public BaseObject,
+                                   public LayoutParent
+{
+public:
+  /**
+   * Constructor.
+   */
+  LayoutItem();
+
+protected:
+  /**
+   * A reference counted object may only be deleted by calling Unreference()
+   */
+  virtual ~LayoutItem();
+
+public:
+
+/**
+   * @brief Construct
+   *
+   * @param[in] owner The owner (container view / child view / visual ) of this layout
+   * @return a new LayoutItem object
+   */
+  static LayoutItemPtr New( Handle& owner );
+
+  /**
+   * @brief Remove the default copy constructor
+   */
+  LayoutItem(const LayoutItem& copy)=delete;
+
+  /**
+   * @brief Remove the default assignment operator
+   */
+  LayoutItem& operator=(const LayoutItem& rhs)=delete;
+
+  /**
+   * @brief Initialize the layout with it's owner and owner's type name
+   * @param[in] owner a handle to the owner container
+   * @param[in] containerType the type name of the owner container
+   */
+  void Initialize( Handle& owner, const std::string& containerType );
+
+  /**
+   * @brief Get a handle to the owner of this layout
+   *
+   * @return a handle to the owner of this layout
+   */
+  Handle GetOwner() const;
+
+  /**
+   * @brief Unparent this layout from it's owner, and remove any layout children in derived types
+   */
+  void Unparent();
+
+  /**
+   * @brief Set whether this layout should be animated or not
+   *
+   * @param[in] animateLayout True if the layout should be animated when applied
+   */
+  void SetAnimateLayout( bool animateLayout );
+
+  /**
+   * @brief Get whether this layout should be animated or not
+   *
+   * @return True if the layout should be animated when applied
+   */
+  bool IsLayoutAnimated() const;
+
+  /**
+   * @brief Register child properties of layout with owner type.
+   *
+   * The Actor hierarchy uses these registered properties in the type
+   * system to ensure child custom properties are properly initialized.
+   *
+   * @param[in] containerType The type of the containing view (owner)
+   */
+  void RegisterChildProperties( const std::string& containerType );
+
+  /**
+   * @brief  This is called to find out how big a layout should be.
+   *
+   * The parent supplies constraint information in the width and height parameters.
+   *
+   * The actual measurement work of a layout is performed in
+   * {@link #OnMeasure(MeasureSpec, MeasureSpec)}, called by this method. Therefore, only
+   * {@link #OnMeasure(MeasureSpec, MeasureSpec)} can and must be overridden by subclasses.
+   *
+   * @param[in] widthMeasureSpec Horizontal space requirements as imposed by the parent
+   * @param[in] heightMeasureSpec Vertical space requirements as imposed by the parent
+   *
+   * @see #OnMeasure(MeasureSpec, MeasureSpec)
+   */
+  void Measure( MeasureSpec widthMeasureSpec, MeasureSpec heightMeasureSpec );
+
+  /**
+   * @brief Assign a size and position to a layout and all of its descendants.
+   *
+   * This is the second phase of the layout mechanism.  (The first is measuring). In this phase, each parent
+   * calls layout on all of its children to position them.  This is typically done using the child
+   * measurements that were stored in the measure pass.
+   *
+   * Derived classes with children should override OnLayout. In that method, they should call Layout on each
+   * of their children.
+   *
+   * @param[in] left position, relative to parent
+   * @param[in] top position, relative to parent
+   * @param[in] right position, relative to parent
+   * @param[in] bottom position, relative to parent
+   */
+  void Layout( LayoutLength left, LayoutLength top, LayoutLength right, LayoutLength bottom );
+
+  /**
+   * @brief Utility to return a default size.
+   *
+   * Uses the supplied size if the MeasureSpec imposed no constraints. Will get larger if allowed by the
+   * MeasureSpec.
+   *
+   * @param[in] size Default size for this layout
+   * @param[in] measureSpec Constraints imposed by the parent
+   * @return The size this layout should be.
+   */
+  static LayoutLength GetDefaultSize( LayoutLength size, MeasureSpec measureSpec );
+
+  /**
+   * @copydoc LayoutParent::GetParent
+   */
+  virtual LayoutParent* GetParent() override;
+
+  /**
+   * @brief Request that this layout is re-laid out.
+   *
+   * This will make this layout and all it's parent layouts dirty.
+   */
+  void RequestLayout();
+
+  /**
+   * @brief Predicate to determine if this layout has been requested to re-layout
+   *
+   * @return True if a layout request has occured on this layout
+   */
+  bool IsLayoutRequested() const;
+
+  /**
+   * @brief Get the measured width (without any measurement flags).
+   *
+   * This method should be used only during measurement and layout calculations.
+   *
+   * Use {@link Dali::Actor::GetTargetSize()} to see how wide a control is after layout
+   */
+  LayoutLength GetMeasuredWidth() const;
+
+  /**
+   * @brief Get the measured height (without any measurement flags).
+   *
+   * This method should be used only during measurement and layout calculations.
+   *
+   * Use {@link Dali::Actor::GetTargetSize()} to see how high a control is after layout
+   */
+  LayoutLength GetMeasuredHeight() const;
+
+  /**
+   * @brief Get the measured width and state.
+   *
+   * This method should be used only during measurement and layout calculations.
+   *
+   * Use {@link Dali::Actor::GetTargetSize()} to see how wide a view is after layout
+   */
+  MeasuredSize GetMeasuredWidthAndState() const;
+
+  /**
+   * @brief Get the measured height and state.
+   *
+   * This method should be used only during measurement and layout calculations.
+   *
+   * Use {@link Dali::Actor::GetTargetSize()} to see how high a view is after layout
+   */
+  MeasuredSize GetMeasuredHeightAndState() const;
+
+  /**
+   * @brief Returns the suggested minimum width that the layout should use.
+   *
+   * This returns the maximum of the layout's minimum width and the background's minimum width
+   *
+   * When being used in {@link #OnMeasure()}, the caller should still
+   * ensure the returned width is within the requirements of the parent.
+   *
+   * @return The suggested minimum width of the layout.
+   */
+  LayoutLength GetSuggestedMinimumWidth() const;
+
+  /**
+   * @brief Returns the suggested minimum height that the layout should use.
+   *
+   * This returns the maximum of the layout's minimum height and the background's minimum height
+   *
+   * When being used in {@link #OnMeasure()}, the caller should still
+   * ensure the returned height is within the requirements of the parent.
+   *
+   * @return The suggested minimum height of the layout.
+   */
+  LayoutLength GetSuggestedMinimumHeight() const;
+
+  /**
+   * @brief Sets the minimum width of the layout.
+   *
+   * It is not guaranteed the layout will be able to achieve this minimum width (for example, if its parent
+   * layout constrains it with less available width).
+   *
+   * @param[in] minWidth The minimum width the layout will try to be, in pixels
+   *
+   * @see #GetMinimumWidth()
+   */
+  void SetMinimumWidth( LayoutLength minWidth );
+
+  /**
+   * @brief Sets the minimum height of the layout.
+   *
+   * It is not guaranteed the layout will be able to achieve this minimum height (for example, if its parent
+   * layout constrains it with less available height).
+   *
+   * @param[in] minHeight The minimum height the layout will try to be, in pixels
+   *
+   * @see #GetMinimumHeight()
+   */
+  void SetMinimumHeight( LayoutLength minHeight );
+
+  /**
+   * @brief Returns the minimum width of the layout.
+   *
+   * @return the minimum width the layout will try to be, in pixels
+   *
+   * @see #SetMinimumWidth(LayoutLength)
+   */
+  LayoutLength GetMinimumWidth() const;
+
+  /**
+   * @brief Returns the minimum height of the layout.
+   *
+   * @return the minimum height the layout will try to be, in pixels
+   *
+   * @see #SetMinimumHeight(LayoutLength)
+   */
+  LayoutLength GetMinimumHeight() const;
+
+  /**
+   * Get the padding information
+   * @return The padding information
+   */
+  Extents GetPadding() const;
+
+protected:
+  /**
+   * @brief Allow directly deriving classes to remove layout children when unparented
+   */
+  virtual void OnUnparent(){};
+
+  /**
+   * @brief Ensure direct derived types register their child properties with the owner
+   *
+   * @param[in] containerType The type name of the owner container
+   */
+  virtual void OnRegisterChildProperties( const std::string& containerType );
+
+
+  /**
+   * @brief Measure the layout and its content to determine the measured width and the
+   * measured height.
+   *
+   * This method is invoked by {@link #Measure(MeasureSpec, MeasureSpec)} and
+   * should be overridden by subclasses to provide accurate and efficient
+   * measurement of their contents.
+   *
+   * <strong>CONTRACT:</strong> When overriding this method, you
+   * <em>must</em> call {@link #SetMeasuredDimensions(MeasuredSize,MeasuredSize)} to store the
+   * measured width and height of this layout. Failure to do so will trigger an
+   * <code>IllegalStateException</code>, thrown by
+   * {@link #Measure(MeasureSpec,MeasureSpec)}. Calling the superclass'
+   * {@link #OnMeasure(MeasureSpec,MeasureSpec)} is a valid use.
+   *
+   * The base class implementation of measure defaults to the background size,
+   * unless a larger size is allowed by the MeasureSpec. Subclasses should
+   * override {@link #OnMeasure(MeasureSpec,MeasureSpec)} to provide better measurements of
+   * their content.
+   *
+   * If this method is overridden, it is the subclass's responsibility to make
+   * sure the measured height and width are at least the layout's minimum height
+   * and width ({@link #GetSuggestedMinimumHeight()} and
+   * {@link #GetSuggestedMinimumWidth()}).
+   *
+   * @param[in] widthMeasureSpec horizontal space requirements as imposed by the parent.
+   *                             The requirements are encoded with
+   *                             {@link MeasureSpec}.
+   * @param[in] heightMeasureSpec vertical space requirements as imposed by the parent.
+   *                              The requirements are encoded with
+   *                              {@link MeasureSpec}.
+   *
+   * @see #GetMeasuredWidth()
+   * @see #GetMeasuredHeight()
+   * @see #GetSuggestedMinimumHeight()
+   * @see #GetSuggestedMinimumWidth()
+   * @see MeasureSpec#GetMode(int)
+   * @see MeasureSpec#GetSize(int)
+   */
+  virtual void OnMeasure( MeasureSpec widthMeasureSpec, MeasureSpec heightMeasureSpec );
+
+  /**
+   * @brief Called from Layout() when this layout should assign a size and position to each of its children.
+   *
+   * Derived classes with children should override this method and call Layout() on each of their children.
+   *
+   * @param[in] changed This is a new size or position for this layout
+   * @param[in] left Left position, relative to parent
+   * @param[in] top Top position, relative to parent
+   * @param[in] right Right position, relative to parent
+   * @param[in] bottom Bottom position, relative to parent
+   */
+  virtual void OnLayout( bool changed, LayoutLength left, LayoutLength top, LayoutLength right, LayoutLength bottom );
+
+
+  /**
+   * @brief This method must be called by {@link #OnMeasure(MeasureSpec,MeasureSpec)} to store the
+   * measured width and measured height.
+   *
+   * Failing to do so will trigger an exception at measurement time.
+   *
+   * @param[in] measuredWidth The measured width of this layout. This may have a state of
+   * {@link MeasuredSize::MEASURED_SIZE_TOO_SMALL}
+   *
+   * @param[in] measuredHeight The measured height of this layout. This may have a state of
+   * {@link MeasuredSize::MEASURED_SIZE_TOO_SMALL}
+   */
+  void SetMeasuredDimensions( MeasuredSize measuredWidth, MeasuredSize measuredHeight );
+
+  /**
+   * @brief Utility to reconcile a desired size and state, with constraints imposed by a MeasureSpec.
+   *
+   * @param[in] size How big the layout wants to be.
+   * @param[in] measureSpec Constraints imposed by the parent.
+   * @param[in] childMeasuredState Size information bit mask for the layout's children.
+   *
+   * @return A measured size, which may indicate that it is too small.
+   */
+  static MeasuredSize ResolveSizeAndState( LayoutLength size, MeasureSpec measureSpec,
+                                           MeasuredSize::State childMeasuredState );
+
+  /**
+   * @brief Sets the frame (the size and position) of the layout onto it's owner
+   *
+   * @todo Consider instead, collating properties into LayoutCollector in order to set/animate them all
+   * in one block.
+   * @param[in] left The horizontal position of the left edge of this frame within the parent layout
+   * @param[in] top The vertical position of the top edge of this frame within the parent layout
+   * @param[in] right The horizontal position of the right edge of this frame within the parent layout
+   * @param[in] bottom The vertical position of the bottom edge of this frame within the parent layout
+   */
+  bool SetFrame( LayoutLength left, LayoutLength top, LayoutLength right, LayoutLength bottom );
+
+  /**
+   * Virtual method to inform derived classes when the layout size changed
+   * @param[in] newSize The new size of the layout
+   * @param[in] oldSize The old size of the layout
+   */
+  virtual void OnSizeChanged( LayoutSize newSize, LayoutSize oldSize );
+
+
+  /**
+   * @brief Initialization method for LayoutGroup to override
+   */
+  virtual void OnInitialize();
+
+private:
+  /**
+   * @brief Called to change the size of the layout.
+   *
+   * @param[in] newSize The new size of the layout
+   * @param[in] oldSize The old size of the layout
+   */
+  void SizeChange( LayoutSize newSize, LayoutSize oldSize );
+
+  /**
+   * @brief Triggered when a layout animation finished.
+   *
+   * @param[in] animation  A handle to the layout animation
+   */
+  void OnLayoutAnimationFinished( Animation& animation );
+
+public:
+  class Impl; // Class declaration is public so we can add devel API's in the future
+
+
+private:
+  std::unique_ptr<Impl> mImpl; ///< Implementation class holds all the data
+  SlotDelegate<LayoutItem> mSlotDelegate;
+};
+
+} //namespace Internal
+
+inline Internal::LayoutItem& GetImplementation( Dali::Toolkit::LayoutItem& handle )
+{
+  DALI_ASSERT_ALWAYS( handle && "LayoutItem handle is empty" );
+  BaseObject& object = handle.GetBaseObject();
+  return static_cast< Internal::LayoutItem& >( object );
+}
+
+inline const Internal::LayoutItem& GetImplementation( const Dali::Toolkit::LayoutItem& handle )
+{
+  DALI_ASSERT_ALWAYS( handle && "LayoutItem handle is empty" );
+  const BaseObject& object = handle.GetBaseObject();
+  return static_cast< const Internal::LayoutItem& >( object );
+}
+
+} //namespace Toolkit
+} //namespace Dali
+
+#endif // DALI_TOOLKIT_INTERNAL_LAYOUTING_LAYOUT_ITEM_H
diff --git a/dali-toolkit/devel-api/layouting/layout-item.cpp b/dali-toolkit/devel-api/layouting/layout-item.cpp
new file mode 100644 (file)
index 0000000..153c134
--- /dev/null
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2018 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <dali-toolkit/devel-api/layouting/layout-item.h>
+#include <dali-toolkit/devel-api/layouting/layout-item-impl.h>
+
+namespace Dali
+{
+namespace Toolkit
+{
+
+LayoutItem::LayoutItem()
+: BaseHandle()
+{
+}
+
+LayoutItem LayoutItem::New( Handle& handle )
+{
+  Internal::LayoutItemPtr layout = Internal::LayoutItem::New( handle );
+  return LayoutItem( layout.Get() );
+}
+
+LayoutItem::LayoutItem( Internal::LayoutItem* LayoutItem )
+: BaseHandle( LayoutItem )
+{
+}
+
+Handle LayoutItem::GetOwner() const
+{
+  return GetImplementation( *this ).GetOwner();
+}
+
+void LayoutItem::SetAnimateLayout( bool animateLayout )
+{
+  GetImplementation( *this ).SetAnimateLayout( animateLayout );
+}
+
+bool LayoutItem::IsLayoutAnimated() const
+{
+  return GetImplementation( *this ).IsLayoutAnimated();
+}
+
+} // namespace Toolkit
+
+} // namespace Dali
diff --git a/dali-toolkit/devel-api/layouting/layout-item.h b/dali-toolkit/devel-api/layouting/layout-item.h
new file mode 100644 (file)
index 0000000..3bb96bb
--- /dev/null
@@ -0,0 +1,132 @@
+#ifndef DALI_TOOLKIT_LAYOUTING_LAYOUT_ITEM_H
+#define DALI_TOOLKIT_LAYOUTING_LAYOUT_ITEM_H
+/*
+ * Copyright (c) 2018 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <memory>
+#include <cstdint>
+#include <dali/public-api/common/dali-common.h>
+#include <dali/public-api/actors/actor-enumerations.h>
+#include <dali/public-api/object/base-handle.h>
+#include <dali/public-api/object/property-index-ranges.h>
+#include <dali-toolkit/devel-api/layouting/child-layout-data.h>
+#include <dali-toolkit/devel-api/layouting/measure-spec.h>
+
+namespace Dali
+{
+namespace Toolkit
+{
+
+namespace Internal
+{
+class LayoutItem;
+}
+
+using LayoutId = unsigned int;
+
+
+/**
+ * Base class for layouts. It is used to layout a control (or visual).
+ * It can be laid out by a LayoutGroup.
+ */
+class DALI_IMPORT_API LayoutItem : public BaseHandle
+{
+public:
+
+  enum PropertyRange
+  {
+    CHILD_PROPERTY_START_INDEX = CHILD_PROPERTY_REGISTRATION_START_INDEX, ///< Start index is used by child properties
+    CHILD_PROPERTY_END_INDEX   = CHILD_PROPERTY_REGISTRATION_START_INDEX+1000 ///< Reserving 1000 property indices
+  };
+
+  struct ChildProperty
+  {
+    enum
+    {
+      WIDTH_SPECIFICATION = ///< Child property to specify desired width (May use MATCH_PARENT/WRAP_CONTENT)
+        CHILD_PROPERTY_START_INDEX,
+      HEIGHT_SPECIFICATION ///< Child property to specify desired height (May use MATCH_PARENT/WRAP_CONTENT)
+    };
+  };
+
+  /**
+   * @brief Default constructor which provides an uninitialized Dali::LayoutItem.
+   */
+  LayoutItem();
+
+  /**
+   * @brief Default destructor
+   */
+  ~LayoutItem()=default;
+
+  /**
+   * @brief Create an initialized LayoutItem
+   *
+   * @param[in] handle A handle to the object that this layout for, e.g. a Control or a Visual::Base
+   * @warning This is an interim function, and will be deleted when all controls have layouts
+   * @todo Ensure that this warning is implemented
+   */
+  static LayoutItem New( Handle& handle );
+
+  /**
+   * @brief Copy constructor
+   * @param[in] copy The LayoutItem to copy.
+   */
+  LayoutItem(const LayoutItem& copy) = default;
+
+  /**
+   * @brief Assignment operator
+   * @param[in] rhs The LayoutItem to copy
+   */
+  LayoutItem& operator=( const LayoutItem& rhs ) = default;
+
+  /**
+   * @brief Get a handle to the control or visual this layout represents.
+   *
+   * @return
+   */
+  Handle GetOwner() const;
+
+  /**
+   * @brief Set whether this layout should be animated or not
+   *
+   * @param[in] animateLayout True if the layout should be animated when applied
+   */
+  void SetAnimateLayout( bool animateLayout );
+
+  /**
+   * @brief Predicate to determine whether this layout should be animated when applied
+   *
+   * @return True if the layout should be animated when applied
+   */
+  bool IsLayoutAnimated() const;
+
+public:
+  /// @cond internal
+  /**
+   * @brief This constructor is used by LayoutItem::New() methods.
+   *
+   * @param[in] actor A pointer to a newly allocated Dali resource
+   */
+  explicit DALI_INTERNAL LayoutItem( Internal::LayoutItem* LayoutItem );
+  /// @endcond
+};
+
+
+}//namespace Toolkit
+}//namespace Dali
+
+#endif // DALI_TOOLKIT_LAYOUTING_LAYOUT_ITEM_H
diff --git a/dali-toolkit/devel-api/layouting/layout-length.h b/dali-toolkit/devel-api/layouting/layout-length.h
new file mode 100644 (file)
index 0000000..94f7ae0
--- /dev/null
@@ -0,0 +1,191 @@
+#ifndef DALI_TOOLKIT_DEVEL_LAYOUT_LENGTH_H
+#define DALI_TOOLKIT_DEVEL_LAYOUT_LENGTH_H
+
+/*
+ * Copyright (c) 2018 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include <cstdint>
+#include <iostream>
+
+namespace Dali
+{
+namespace Toolkit
+{
+
+/**
+ * @brief A type that represents a layout length.
+ *
+ * Currently, this implies pixels, but could be extended to handle device dependant sizes, etc.
+ */
+class LayoutLength
+{
+public:
+  using IntType = int;
+
+  LayoutLength( IntType value )
+  : mValue( value )
+  {
+  }
+
+  LayoutLength( const LayoutLength& layoutLength )
+  : mValue( layoutLength.mValue )
+  {
+  }
+
+  LayoutLength& operator=(const LayoutLength& rhs)
+  {
+    mValue = rhs.mValue;
+    return *this;
+  }
+
+  bool operator==( const LayoutLength& rhs )
+  {
+    return mValue == rhs.mValue;
+  }
+
+  bool operator==( LayoutLength::IntType rhs )
+  {
+    return mValue == rhs;
+  }
+
+  bool operator!=( const LayoutLength& rhs )
+  {
+    return !operator==(rhs);
+  }
+
+  bool operator<( const LayoutLength& rhs )
+  {
+    return mValue < rhs.mValue;
+  }
+
+  bool operator<( const LayoutLength rhs ) const
+  {
+    return mValue < rhs.mValue;
+  }
+
+  bool operator<=( const LayoutLength& rhs )
+  {
+    return mValue <= rhs.mValue;
+  }
+  bool operator<=( LayoutLength rhs )
+  {
+    return mValue <= rhs.mValue;
+  }
+  bool operator>( const LayoutLength& rhs )
+  {
+    return mValue > rhs.mValue;
+  }
+  bool operator>( LayoutLength rhs )
+  {
+    return mValue > rhs.mValue;
+  }
+  bool operator>=( const LayoutLength& rhs )
+  {
+    return mValue >= rhs.mValue;
+  }
+  bool operator>=( LayoutLength rhs )
+  {
+    return mValue >= rhs.mValue;
+  }
+
+  LayoutLength operator+( const LayoutLength& rhs )
+  {
+    return mValue + rhs.mValue;
+  }
+
+  LayoutLength operator+( LayoutLength::IntType rhs )
+  {
+    return mValue + rhs;
+  }
+
+  LayoutLength operator-( const LayoutLength& rhs )
+  {
+    return mValue - rhs.mValue;
+  }
+  LayoutLength operator-( LayoutLength::IntType rhs )
+  {
+    return mValue - rhs;
+  }
+
+  LayoutLength& operator+=( const LayoutLength& rhs )
+  {
+    mValue += rhs.mValue;
+    return *this;
+  }
+  LayoutLength& operator+=( LayoutLength::IntType rhs )
+  {
+    mValue += rhs;
+    return *this;
+  }
+
+  LayoutLength& operator-=( const LayoutLength& rhs )
+  {
+    mValue -= rhs.mValue;
+    return *this;
+  }
+
+  LayoutLength& operator-=( LayoutLength::IntType rhs )
+  {
+    mValue -= rhs;
+    return *this;
+  }
+
+  LayoutLength operator/( const LayoutLength& rhs )
+  {
+    return mValue / rhs.mValue;
+  }
+  LayoutLength operator/(  LayoutLength::IntType rhs )
+  {
+    return mValue / rhs;
+  }
+
+  LayoutLength operator*( const LayoutLength& rhs )
+  {
+    return mValue * rhs.mValue;
+  }
+  LayoutLength operator*( LayoutLength::IntType rhs )
+  {
+    return mValue * rhs;
+  }
+  LayoutLength operator*( float rhs )
+  {
+    return LayoutLength(LayoutLength::IntType(float(mValue) * rhs));
+  }
+
+  operator float()
+  {
+    return float( mValue );
+  }
+
+  IntType mValue;
+};
+
+/**
+ * @brief Prints a LayoutLength
+ *
+ * @param[in] o The output stream operator
+ * @param[in] layoutLength the layout length to print
+ * @return The output stream operator
+ */
+inline std::ostream& operator<<( std::ostream& o, const LayoutLength& layoutLength )
+{
+  return o<<layoutLength.mValue;
+}
+
+} // namespace Toolkit
+
+} // namespace Dali
+
+#endif //DALI_TOOLKIT_DEVEL_LAYOUT_LENGTH_H
diff --git a/dali-toolkit/devel-api/layouting/layout-parent-impl.h b/dali-toolkit/devel-api/layouting/layout-parent-impl.h
new file mode 100644 (file)
index 0000000..392a2ab
--- /dev/null
@@ -0,0 +1,52 @@
+#ifndef DALI_TOOLKIT_INTERNAL_LAYOUTING_LAYOUT_PARENT_H
+#define DALI_TOOLKIT_INTERNAL_LAYOUTING_LAYOUT_PARENT_H
+
+/*
+ * Copyright (c) 2018 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+namespace Dali
+{
+namespace Toolkit
+{
+namespace Internal
+{
+
+/**
+ * Interface that allows a layout to determine its layout parent.
+ *
+ * Needed to prevent circular inheritance - most LayoutBases have a parent,
+ * but parenting is provided by LayoutGroup, which is a sub-class of LayoutBase.
+ */
+class DALI_IMPORT_API LayoutParent
+{
+public:
+  /**
+   * Get the parent of this layout.
+   */
+  virtual LayoutParent* GetParent() = 0;
+
+protected:
+  virtual ~LayoutParent()
+  {
+  }
+};
+
+
+} // namespace Internal
+} // namespace Toolkit
+} // namespace Dali
+
+#endif //DALI_TOOLKIT_INTERNAL_LAYOUTING_LAYOUT_PARENT_H
diff --git a/dali-toolkit/devel-api/layouting/layout-size.h b/dali-toolkit/devel-api/layouting/layout-size.h
new file mode 100644 (file)
index 0000000..c5ab2dd
--- /dev/null
@@ -0,0 +1,119 @@
+#ifndef DALI_TOOLKIT_DEVEL_LAYOUT_SIZE_H
+#define DALI_TOOLKIT_DEVEL_LAYOUT_SIZE_H
+
+/*
+ * Copyright (c) 2018 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <dali-toolkit/devel-api/layouting/layout-length.h>
+
+namespace Dali
+{
+namespace Toolkit
+{
+
+/**
+ * This class represents a layout size (width and height)
+ */
+class LayoutSize
+{
+public:
+  LayoutSize()
+  : x(0u),
+    y(0u)
+  {
+  }
+
+  LayoutSize( LayoutLength::IntType anX, LayoutLength::IntType aY )
+  : x( anX ),
+    y( aY )
+  {
+  }
+
+  LayoutSize( const LayoutSize& layoutSize )
+  : x( layoutSize.x ),
+    y( layoutSize.y )
+  {
+  }
+
+  LayoutSize& operator=(const LayoutSize& rhs)
+  {
+    x = rhs.x;
+    y = rhs.y;
+    return *this;
+  }
+
+  LayoutLength::IntType GetWidth()
+  {
+    return width;
+  }
+
+  LayoutLength::IntType GetHeight()
+  {
+    return height;
+  }
+
+  void SetWidth(LayoutLength::IntType value)
+  {
+    width=value;
+  }
+  void SetHeight(LayoutLength::IntType value)
+  {
+    height=value;
+  }
+  void SetWidth(LayoutLength value)
+  {
+    width=value.mValue;
+  }
+  void SetHeight(LayoutLength value)
+  {
+    height=value.mValue;
+  }
+
+  bool operator==( const LayoutSize& rhs )
+  {
+    return x==rhs.x && y==rhs.y;
+  }
+
+  union
+  {
+    LayoutLength::IntType x;
+    LayoutLength::IntType width;
+  };
+
+  union
+  {
+    LayoutLength::IntType y;
+    LayoutLength::IntType height;
+  };
+};
+
+/**
+ * @brief Prints a LayoutSize
+ *
+ * @param[in] o The output stream operator
+ * @param[in] layoutSize the layout size to print
+ * @return The output stream operator
+ */
+inline std::ostream& operator<< (std::ostream& o, const LayoutSize& layoutSize)
+{
+  return o << "[" << layoutSize.x << ", " << layoutSize.y << "]";
+}
+
+} // namespace Toolkit
+
+} // namespace Dali
+
+#endif //DALI_TOOLKIT_DEVEL_LAYOUT_SIZE_H
diff --git a/dali-toolkit/devel-api/layouting/measure-spec.h b/dali-toolkit/devel-api/layouting/measure-spec.h
new file mode 100644 (file)
index 0000000..f766247
--- /dev/null
@@ -0,0 +1,147 @@
+#ifndef DALI_TOOLKIT_LAYOUTING_MEASURE_SPEC_H
+#define DALI_TOOLKIT_LAYOUTING_MEASURE_SPEC_H
+
+/*
+ * Copyright (c) 2018 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <dali/public-api/common/dali-common.h>
+#include <dali-toolkit/devel-api/layouting/layout-length.h>
+
+#include <sstream>
+
+namespace Dali
+{
+namespace Toolkit
+{
+
+/**
+ * A MeasureSpec is used during the Measure pass by a LayoutGroup to inform it's children
+ * how to be measured. For instance, it may measure a child with an exact width and an unspecified
+ * height in order to determine height for width.
+ */
+class DALI_IMPORT_API MeasureSpec
+{
+public:
+  using IntType = LayoutLength::IntType;
+
+  enum class Mode
+  {
+    UNSPECIFIED, ///< This is used by a parent to determine the desired dimension of a child layout.
+    EXACTLY, /** This is used by a parent to impose an exact size on the child. The child must use
+                 this size, and guarantee that all of its descendants will fit within this size */
+    AT_MOST /** This is used by the parent to impose a maximum size on the child. The child must guarantee
+             * that it and all of it's descendants will fit within this size. */
+  };
+
+  MeasureSpec( LayoutLength measureSpec, MeasureSpec::Mode mode )
+  : mSize( measureSpec.mValue ),
+    mMode( mode )
+  {
+  }
+
+  MeasureSpec( IntType measureSpec )
+  : mSize( measureSpec ),
+    mMode( Mode::UNSPECIFIED )
+  {
+  }
+
+  ~MeasureSpec() = default;
+
+  MeasureSpec& operator=( const MeasureSpec& rhs )
+  {
+    this->mSize = rhs.mSize;
+    this->mMode = rhs.mMode;
+    return *this;
+  }
+
+  bool operator==( MeasureSpec value )
+  {
+    return mSize == value.mSize;
+  }
+
+  bool operator!=( MeasureSpec value )
+  {
+    return mSize != value.mSize;
+  }
+
+  /**
+   * @brief Get the mode of the measure spec.
+   *
+   * @return The mode of the measure spec
+   */
+  MeasureSpec::Mode GetMode() const
+  {
+    return mMode;
+  }
+
+  /**
+   * @brief Get the size of the measure spec
+   *
+   * @return the size of the measure spec
+   */
+  IntType GetSize() const
+  {
+    return mSize;
+  }
+
+  /**
+   * @brief Adjust the measure size by the given delta.
+   *
+   * Used only for EXACT and AT_MOST modes.
+   * @param[in] measureSpec the measure spec to adjust
+   * @param[in] delta A positive or negative value to adjust the measure spec by.
+   *
+   * @note if the adjusted size is negative, it is zeroed.
+   * @return A new measure spec with the adjusted values.
+   */
+  static MeasureSpec Adjust( MeasureSpec measureSpec, int delta )
+  {
+    auto mode = measureSpec.GetMode();
+    auto size = measureSpec.GetSize();
+
+    if( mode == MeasureSpec::Mode::UNSPECIFIED )
+    {
+      return MeasureSpec( size, MeasureSpec::Mode::UNSPECIFIED );
+    }
+
+    if( delta < 0 && measureSpec.mSize < static_cast<IntType>(abs(delta)) )
+    {
+      size = 0;
+    }
+    else
+    {
+      size += delta;
+    }
+    return MeasureSpec( size, mode );
+  }
+
+public:
+  IntType  mSize; ///< The specified size
+  Mode     mMode; ///< The measure mode
+};
+
+inline std::ostream& operator<< (std::ostream& o, const MeasureSpec& measureSpec )
+{
+  return o << ( (measureSpec.GetMode() == MeasureSpec::Mode::UNSPECIFIED ? "Unspecified"
+                 : (measureSpec.GetMode() == MeasureSpec::Mode::EXACTLY ? "Exactly":"At most" ) ) )
+           << " " << measureSpec.GetSize();
+}
+
+} //namespace Toolkit
+} //namespace Dali
+
+
+#endif // DALI_TOOLKIT_LAYOUTING_MEASURE_SPEC_H
diff --git a/dali-toolkit/devel-api/layouting/measured-size.h b/dali-toolkit/devel-api/layouting/measured-size.h
new file mode 100644 (file)
index 0000000..ff937cf
--- /dev/null
@@ -0,0 +1,117 @@
+#ifndef DALI_TOOLKIT_LAYOUTING_MEASURED_SIZE_H
+#define DALI_TOOLKIT_LAYOUTING_MEASURED_SIZE_H
+
+/*
+ * Copyright (c) 2018 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <dali/public-api/common/dali-common.h>
+#include <dali-toolkit/devel-api/layouting/layout-length.h>
+
+namespace Dali
+{
+namespace Toolkit
+{
+
+/**
+ * Class that encodes a measurement and a measure state, which is set if the measured size is too small.
+ */
+class DALI_IMPORT_API MeasuredSize
+{
+public:
+
+  enum State
+  {
+    MEASURED_SIZE_OK, ///< The measured size is good
+    MEASURED_SIZE_TOO_SMALL ///< The measured size is too small
+  };
+
+  MeasuredSize()
+  : mMeasuredSize( 0u )
+  {
+  }
+
+  MeasuredSize( LayoutLength measuredSize )
+  : mMeasuredSize( measuredSize ),
+    mState ( MeasuredSize::State::MEASURED_SIZE_OK )
+  {
+  }
+
+  MeasuredSize( LayoutLength measuredSize, MeasuredSize::State state )
+  : mMeasuredSize( measuredSize ),
+    mState( state )
+  {
+  }
+
+  ~MeasuredSize() = default;
+
+  MeasuredSize& operator=( const MeasuredSize& rhs )
+  {
+    this->mMeasuredSize = rhs.mMeasuredSize;
+    this->mState = rhs.mState;
+    return *this;
+  }
+
+  MeasuredSize& operator=( LayoutLength::IntType rhs )
+  {
+    this->mMeasuredSize = rhs;
+    this->mState = State::MEASURED_SIZE_OK;
+    return *this;
+  }
+
+  inline bool operator==( MeasuredSize value )
+  {
+    return mMeasuredSize == value.mMeasuredSize;
+  }
+
+  inline bool operator!=( MeasuredSize value )
+  {
+    return mMeasuredSize != value.mMeasuredSize;
+  }
+
+  inline operator LayoutLength::IntType()
+  {
+    return mMeasuredSize.mValue;
+  }
+
+  inline void SetState( MeasuredSize::State state )
+  {
+    mState = state;
+  }
+
+  inline MeasuredSize::State GetState()
+  {
+    return mState;
+  }
+
+  inline void SetSize( LayoutLength size )
+  {
+    mMeasuredSize = size;
+  }
+  inline LayoutLength GetSize()
+  {
+    return mMeasuredSize;
+  }
+
+private:
+  LayoutLength mMeasuredSize; ///< The measured size
+  State mState; ///< The measured state
+};
+
+} //namespace Toolkit
+} //namespace Dali
+
+
+#endif // DALI_TOOLKIT_LAYOUTING_MEASURED_SIZE_H
diff --git a/dali-toolkit/devel-api/layouting/vbox-layout.cpp b/dali-toolkit/devel-api/layouting/vbox-layout.cpp
new file mode 100644 (file)
index 0000000..b82166b
--- /dev/null
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2018 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//CLASS HEADER
+#include <dali-toolkit/devel-api/layouting/vbox-layout.h>
+
+//EXTERNAL HEADERS
+//INTERNAL HEADERS
+#include <dali-toolkit/internal/layouting/vbox-layout-impl.h>
+
+namespace Dali
+{
+namespace Toolkit
+{
+
+VboxLayout::VboxLayout()
+{
+}
+
+VboxLayout VboxLayout::New()
+{
+  Internal::VboxLayoutPtr internal = Internal::VboxLayout::New();
+  return VboxLayout( internal.Get() );
+}
+
+VboxLayout VboxLayout::DownCast( BaseHandle handle )
+{
+  return VboxLayout( dynamic_cast< Dali::Toolkit::Internal::VboxLayout*>( handle.GetObjectPtr() ) );
+}
+
+VboxLayout::VboxLayout( const VboxLayout& other )
+: LayoutGroup( other )
+{
+}
+
+VboxLayout& VboxLayout::operator=( const VboxLayout& other )
+{
+  if( &other != this )
+  {
+    LayoutGroup::operator=( other );
+  }
+  return *this;
+}
+
+void VboxLayout::SetCellPadding( LayoutSize size )
+{
+  GetImplementation(*this).SetCellPadding( size );
+}
+
+LayoutSize VboxLayout::GetCellPadding()
+{
+  return GetImplementation(*this).GetCellPadding();
+}
+
+VboxLayout::VboxLayout( Dali::Toolkit::Internal::VboxLayout* object )
+: LayoutGroup( object )
+{
+}
+
+} // namespace Toolkit
+} // namespace Dali
diff --git a/dali-toolkit/devel-api/layouting/vbox-layout.h b/dali-toolkit/devel-api/layouting/vbox-layout.h
new file mode 100644 (file)
index 0000000..78e5bc2
--- /dev/null
@@ -0,0 +1,127 @@
+#ifndef DALI_TOOLKIT_LAYOUTING_VBOX_LAYOUT_H
+#define DALI_TOOLKIT_LAYOUTING_VBOX_LAYOUT_H
+
+/*
+ * Copyright (c) 2018 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <dali/public-api/common/dali-common.h>
+#include <dali/public-api/object/base-handle.h>
+#include <dali-toolkit/devel-api/layouting/layout-group.h>
+#include <dali-toolkit/devel-api/layouting/layout-size.h>
+
+namespace Dali
+{
+namespace Toolkit
+{
+
+namespace Internal DALI_INTERNAL
+{
+class VboxLayout;
+}
+
+/**
+ * This class implements a vertical box layout, automatically handling
+ * right to left or left to right direction change.
+ */
+class DALI_IMPORT_API VboxLayout : public LayoutGroup
+{
+public:
+
+  enum PropertyRange
+  {
+    CHILD_PROPERTY_START_INDEX = LayoutGroup::CHILD_PROPERTY_START_INDEX+100,
+    CHILD_PROPERTY_END_INDEX   = CHILD_PROPERTY_START_INDEX+1000
+  };
+
+  struct ChildProperty
+  {
+    enum
+    {
+      WEIGHT = CHILD_PROPERTY_START_INDEX,
+    };
+  };
+
+  /**
+   * @brief Creates an uninitialized VboxLayout handle.
+   *
+   * Initialize it using VboxLayout::New().
+   * Calling member functions with an uninitialized handle is not allowed.
+   */
+  VboxLayout();
+
+  /**
+   * @brief Creates a VboxLayout object.
+   */
+  static VboxLayout New();
+
+  /**
+   * @brief Downcasts a handle to a VboxLayout handle.
+   *
+   * If handle points to a VboxLayout, the downcast produces a valid handle.
+   * If not, the returned handle is left uninitialized.
+
+   * @param[in] handle to an object
+   * @return Handle to a VboxLayout or an uninitialized handle
+   */
+  static VboxLayout DownCast( BaseHandle handle );
+
+  /**
+   * @brief Copy constructor
+   */
+  VboxLayout( const VboxLayout& other );
+
+  /**
+   * @brief Assigment operator
+   */
+  VboxLayout& operator=( const VboxLayout& other );
+
+  /**
+   * @brief Default destructor.
+   *
+   * This is non-virtual, since derived Handle types must not contain data or virtual methods
+   */
+  ~VboxLayout()=default;
+
+  /**
+   * @brief Set the padding between cells in the layout
+   *
+   * @param[in] size The padding between cells.
+   */
+  void SetCellPadding( LayoutSize size );
+
+  /**
+   * @brief Get the padding between cells in the layout
+   *
+   * @return The padding between cells.
+   */
+  LayoutSize GetCellPadding();
+
+public: // Not intended for application developers
+
+  /// @cond internal
+  /**
+   * @brief This constructor is used by VboxLayout::New() methods.
+   *
+   * @param[in] actor A pointer to a newly allocated Dali resource
+   */
+  explicit DALI_INTERNAL VboxLayout( Internal::VboxLayout* body );
+  /// @endcond
+};
+
+} // namespace Toolkit
+} // namespace Dali
+
+#endif // DALI_TOOLKIT_LAYOUTING_VBOX_LAYOUT_H
index f3e049b..837a5e3 100644 (file)
@@ -2,7 +2,7 @@
 #define __DALI_SCRIPT_PLUGIN_H__
 
 /*
- * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2018 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -18,7 +18,7 @@
  *
  */
 
-#include <dali/public-api/common/dali-common.h>
+#include <dali-toolkit/public-api/dali-toolkit-common.h>
 #include <string>
 
 namespace Dali
@@ -34,7 +34,7 @@ namespace Toolkit
  * CreateScriptPlugin()  // returns a pointer to a ScriptPlugin object
  * DestroyScriptPlugin() // destroys the plugin
  */
-class DALI_IMPORT_API ScriptPlugin
+class DALI_TOOLKIT_API ScriptPlugin
 {
 public:
 
index 8eed33b..86e2678 100644 (file)
@@ -2,7 +2,7 @@
 #define __DALI_TOOLKIT_SCRIPT_H__
 
 /*
- * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2018 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -19,7 +19,7 @@
  */
 
 // EXTERNAL INCLUDES
-#include <dali/public-api/common/dali-common.h>
+#include <dali-toolkit/public-api/dali-toolkit-common.h>
 #include <dali/public-api/object/base-handle.h>
 
 namespace Dali
@@ -49,7 +49,7 @@ class Script;
  * @endcode
  *
  */
-class DALI_IMPORT_API Script : public BaseHandle
+class DALI_TOOLKIT_API Script : public BaseHandle
 {
 
 public:
index faf3c57..ab00ee3 100644 (file)
@@ -2,7 +2,7 @@
 #define DALI_TOOLKIT_STYLE_MANAGER_DEVEL_H
 
 /*
- * Copyright (c) 2017 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2018 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -38,7 +38,7 @@ namespace DevelStyleManager
  * @param[in] styleManager The instance of StyleManager
  * @return A property map to the currently defined configurations
 **/
-DALI_IMPORT_API const Property::Map GetConfigurations( StyleManager styleManager );
+DALI_TOOLKIT_API const Property::Map GetConfigurations( StyleManager styleManager );
 
 } // namespace DevelStyleManager
 
index 11bcc2e..7de6dc6 100644 (file)
@@ -2,7 +2,7 @@
 #define __DALI_TOOLKIT_CUBE_TRANSITION_CROSS_EFFECT_H__
 
 /*
- * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2018 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -39,7 +39,7 @@ namespace Internal DALI_INTERNAL
  * SubClass of CubeTransitionEffect
  * Rotate the neighboring cubes in perpendicular directions to transition from one image to another
  */
-class DALI_IMPORT_API CubeTransitionCrossEffect : public CubeTransitionEffect
+class DALI_TOOLKIT_API CubeTransitionCrossEffect : public CubeTransitionEffect
 {
 
 public:
old mode 100644 (file)
new mode 100755 (executable)
index df51440..9f9efc0
@@ -2,7 +2,7 @@
 #define DALI_TOOLKIT_CUBE_TRANSITION_EFFECT_H
 
 /*
- * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2018 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -20,6 +20,7 @@
 
 // INTERNAL INCLUDES
 #include <dali-toolkit/public-api/controls/control.h>
+#include <dali-toolkit/public-api/dali-toolkit-common.h>
 
 // EXTERNAL INCLUDES
 #include <dali/public-api/rendering/texture.h>
@@ -81,7 +82,7 @@ class CubeTransitionEffect;
  * |---------------------|----------------------------------|
  * | transitionCompleted | @ref TransitionCompletedSignal() |
  */
-class DALI_IMPORT_API CubeTransitionEffect : public Control
+class DALI_TOOLKIT_API CubeTransitionEffect : public Control
 {
 public:
 
index 0543d27..04a375e 100644 (file)
@@ -2,7 +2,7 @@
 #define __DALI_TOOLKIT_CUBE_TRANSITION_FOLD_EFFECT_H__
 
 /*
- * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2018 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -39,7 +39,7 @@ namespace Internal DALI_INTERNAL
  * SubClass of CubeTransitionEffect
  * Rotate the neighboring cubes in opposite directions to transition from one image to another
  */
-class DALI_IMPORT_API CubeTransitionFoldEffect : public CubeTransitionEffect
+class DALI_TOOLKIT_API CubeTransitionFoldEffect : public CubeTransitionEffect
 {
 
 public:
index b8a5c4f..89abc2c 100644 (file)
@@ -2,7 +2,7 @@
 #define __DALI_TOOLKIT_CUBE_TRANSITION_WAVE_EFFECT_H__
 
 /*
- * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2018 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -39,7 +39,7 @@ namespace Internal DALI_INTERNAL
  * SubClass of CubeTransitionEffect
  * Rotate the cubes successively according to the finger movement to achieve wave-like transition effect
  */
-class DALI_IMPORT_API CubeTransitionWaveEffect : public CubeTransitionEffect
+class DALI_TOOLKIT_API CubeTransitionWaveEffect : public CubeTransitionEffect
 {
 
 public:
old mode 100644 (file)
new mode 100755 (executable)
index 23dfb2c..8d662cf
@@ -2,7 +2,7 @@
 #define __DALI_TOOLKIT_TRANSITION_DATA_H__
 
 /*
- * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2018 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -24,6 +24,9 @@
 #include <dali/public-api/object/property-array.h>
 #include <dali/public-api/object/property-map.h>
 
+// INTERNAL INCLUDES
+#include <dali-toolkit/public-api/dali-toolkit-common.h>
+
 namespace Dali
 {
 
@@ -67,7 +70,7 @@ class TransitionData;
  * ]
  *
  */
-class DALI_IMPORT_API TransitionData : public BaseHandle
+class DALI_TOOLKIT_API TransitionData : public BaseHandle
 {
 public:
   /**
old mode 100644 (file)
new mode 100755 (executable)
index 74af0cb..94db5c4
@@ -21,6 +21,9 @@
 #include <dali/public-api/object/base-handle.h>
 #include <dali/public-api/actors/actor.h>
 
+// INTERNAL INCLUDES
+#include <dali-toolkit/public-api/dali-toolkit-common.h>
+
 namespace Dali
 {
 
@@ -77,7 +80,7 @@ namespace Visual
  * Absolute means that the component describes world units (equivalent to pixels)
  *
  */
-class DALI_IMPORT_API Base : public BaseHandle
+class DALI_TOOLKIT_API Base : public BaseHandle
 {
 public:
 
index 856360b..454919a 100644 (file)
@@ -2,7 +2,7 @@
 #define DALI_TOOLKIT_VISUAL_FACTORY_H
 
 /*
- * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2018 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -51,7 +51,7 @@ class VisualFactory;
  * | visualType               | INTEGER or STRING |
  * | shader                   | MAP               |
  */
-class DALI_IMPORT_API VisualFactory : public BaseHandle
+class DALI_TOOLKIT_API VisualFactory : public BaseHandle
 {
 public:
 
old mode 100644 (file)
new mode 100755 (executable)
index 8a90b03..692e0d8
@@ -2,7 +2,7 @@
 #define __DALI_TOOLKIT_INTERNAL_BUILDER_H__
 
 /*
- * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2018 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
index 76b1ecd..2a7badc 100644 (file)
@@ -2,7 +2,7 @@
 #define __DALI_JSON_PARSE_STATE_H__
 
 /*
- * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2018 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -19,7 +19,7 @@
  */
 
 // EXTERNAL INCLUDES
-#include <dali/public-api/common/dali-common.h>
+#include <dali-toolkit/public-api/dali-toolkit-common.h>
 
 // INTERNAL INCLUDES
 #include <dali-toolkit/devel-api/builder/tree-node.h>
index f900350..ea37e62 100644 (file)
@@ -2,7 +2,7 @@
 #define __DALI_SCRIPT_TREE_NODE_MANIPULATOR_H__
 
 /*
- * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2018 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -23,7 +23,7 @@
 #include <iterator>
 #include <cstring>
 
-#include <dali/public-api/common/dali-common.h>
+#include <dali-toolkit/public-api/dali-toolkit-common.h>
 #include <dali/public-api/common/vector-wrapper.h>
 
 // INTERNAL INCLUDES
index af3aac4..e916a0e 100755 (executable)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2018 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -19,7 +19,7 @@
 #include "control-data-impl.h"
 
 // EXTERNAL INCLUDES
-#include <dali/public-api/common/dali-common.h>
+#include <dali-toolkit/public-api/dali-toolkit-common.h>
 #include <dali/integration-api/debug.h>
 #include <dali/devel-api/object/handle-devel.h>
 #include <dali/devel-api/scripting/enum-helper.h>
 
 // INTERNAL INCLUDES
 #include <dali-toolkit/internal/visuals/visual-base-impl.h>
-#include <dali-toolkit/devel-api/controls/control-depth-index-ranges.h>
-#include <dali-toolkit/internal/styling/style-manager-impl.h>
 #include <dali-toolkit/public-api/visuals/image-visual-properties.h>
 #include <dali-toolkit/public-api/visuals/visual-properties.h>
-#include <dali-toolkit/internal/visuals/visual-string-constants.h>
+#include <dali-toolkit/devel-api/controls/control-depth-index-ranges.h>
 #include <dali-toolkit/devel-api/controls/control-devel.h>
 #include <dali-toolkit/devel-api/controls/control-wrapper-impl.h>
+#include <dali-toolkit/internal/styling/style-manager-impl.h>
+#include <dali-toolkit/internal/visuals/visual-string-constants.h>
 
 namespace Dali
 {
@@ -317,6 +317,7 @@ Control::Impl::Impl( Control& controlImpl )
 : mControlImpl( controlImpl ),
   mState( Toolkit::DevelControl::NORMAL ),
   mSubStateName(""),
+  mLayout( NULL ),
   mLeftFocusableActorId( -1 ),
   mRightFocusableActorId( -1 ),
   mUpFocusableActorId( -1 ),
@@ -577,7 +578,7 @@ Toolkit::Visual::Base Control::Impl::GetVisual( Property::Index index ) const
 
 void Control::Impl::EnableVisual( Property::Index index, bool enable )
 {
-  DALI_LOG_INFO( gLogFilter, Debug::Verbose, "Control::EnableVisual Visual (%d)\n", index);
+  DALI_LOG_INFO( gLogFilter, Debug::General, "Control::EnableVisual(%d, %s)\n", index, enable?"T":"F");
 
   RegisteredVisualContainer::Iterator iter;
   if ( FindVisual( index, mVisuals, iter ) )
@@ -604,6 +605,10 @@ void Control::Impl::EnableVisual( Property::Index index, bool enable )
       }
     }
   }
+  else
+  {
+    DALI_LOG_WARNING( "Control::EnableVisual(%d, %s) FAILED - NO SUCH VISUAL\n", index, enable?"T":"F" );
+  }
 }
 
 bool Control::Impl::IsVisualEnabled( Property::Index index ) const
@@ -635,7 +640,7 @@ void Control::Impl::StartObservingVisual( Toolkit::Visual::Base& visual)
 // Called by a Visual when it's resource is ready
 void Control::Impl::ResourceReady( Visual::Base& object)
 {
-  DALI_LOG_INFO( gLogFilter, Debug::Verbose, "ResourceReady replacements pending[%d]\n", mRemoveVisuals.Count() );
+  DALI_LOG_INFO( gLogFilter, Debug::Verbose, "Control::Impl::ResourceReady() replacements pending[%d]\n", mRemoveVisuals.Count() );
 
   Actor self = mControlImpl.Self();
 
@@ -706,82 +711,92 @@ Toolkit::Visual::ResourceStatus Control::Impl::GetVisualResourceStatus( Property
   return Toolkit::Visual::ResourceStatus::PREPARING;
 }
 
-Dali::Animation Control::Impl::CreateTransition( const Toolkit::TransitionData& handle )
+
+
+void Control::Impl::AddTransitions( Dali::Animation& animation,
+                                    const Toolkit::TransitionData& handle,
+                                    bool createAnimation )
 {
-  Dali::Animation transition;
+  // Setup a Transition from TransitionData.
   const Internal::TransitionData& transitionData = Toolkit::GetImplementation( handle );
-
-  if( transitionData.Count() > 0 )
+  TransitionData::Iterator end = transitionData.End();
+  for( TransitionData::Iterator iter = transitionData.Begin() ;
+       iter != end; ++iter )
   {
-    // Setup a Transition from TransitionData.
-    TransitionData::Iterator end = transitionData.End();
-    for( TransitionData::Iterator iter = transitionData.Begin() ;
-         iter != end; ++iter )
-    {
-      TransitionData::Animator* animator = (*iter);
+    TransitionData::Animator* animator = (*iter);
 
-      Toolkit::Visual::Base visual = GetVisualByName( mVisuals, animator->objectName );
+    Toolkit::Visual::Base visual = GetVisualByName( mVisuals, animator->objectName );
 
-      if( visual )
-      {
+    if( visual )
+    {
 #if defined(DEBUG_ENABLED)
-        Dali::TypeInfo typeInfo;
-        ControlWrapper* controlWrapperImpl = dynamic_cast<ControlWrapper*>(&mControlImpl);
-        if( controlWrapperImpl )
-        {
-          typeInfo = controlWrapperImpl->GetTypeInfo();
-        }
+      Dali::TypeInfo typeInfo;
+      ControlWrapper* controlWrapperImpl = dynamic_cast<ControlWrapper*>(&mControlImpl);
+      if( controlWrapperImpl )
+      {
+        typeInfo = controlWrapperImpl->GetTypeInfo();
+      }
 
-        DALI_LOG_INFO( gLogFilter, Debug::Concise, "CreateTransition: Found %s visual for %s\n",
-                       visual.GetName().c_str(), typeInfo?typeInfo.GetName().c_str():"Unknown" );
+      DALI_LOG_INFO( gLogFilter, Debug::Concise, "CreateTransition: Found %s visual for %s\n",
+                     visual.GetName().c_str(), typeInfo?typeInfo.GetName().c_str():"Unknown" );
 #endif
-        Internal::Visual::Base& visualImpl = Toolkit::GetImplementation( visual );
-        visualImpl.AnimateProperty( transition, *animator );
-      }
-      else
+      Internal::Visual::Base& visualImpl = Toolkit::GetImplementation( visual );
+      visualImpl.AnimateProperty( animation, *animator );
+    }
+    else
+    {
+      DALI_LOG_INFO( gLogFilter, Debug::Concise, "CreateTransition: Could not find visual. Trying actors");
+      // Otherwise, try any actor children of control (Including the control)
+      Actor child = mControlImpl.Self().FindChildByName( animator->objectName );
+      if( child )
       {
-        DALI_LOG_INFO( gLogFilter, Debug::Concise, "CreateTransition: Could not find visual. Trying actors");
-        // Otherwise, try any actor children of control (Including the control)
-        Actor child = mControlImpl.Self().FindChildByName( animator->objectName );
-        if( child )
+        Property::Index propertyIndex = DevelHandle::GetPropertyIndex( child, animator->propertyKey );
+        if( propertyIndex != Property::INVALID_INDEX )
         {
-          Property::Index propertyIndex = DevelHandle::GetPropertyIndex( child, animator->propertyKey );
-          if( propertyIndex != Property::INVALID_INDEX )
+          if( animator->animate == false )
           {
-            if( animator->animate == false )
+            if( animator->targetValue.GetType() != Property::NONE )
             {
-              if( animator->targetValue.GetType() != Property::NONE )
-              {
-                child.SetProperty( propertyIndex, animator->targetValue );
-              }
+              child.SetProperty( propertyIndex, animator->targetValue );
             }
-            else // animate the property
+          }
+          else // animate the property
+          {
+            if( animator->initialValue.GetType() != Property::NONE )
+            {
+              child.SetProperty( propertyIndex, animator->initialValue );
+            }
+
+            if( createAnimation && !animation )
             {
-              if( animator->initialValue.GetType() != Property::NONE )
-              {
-                child.SetProperty( propertyIndex, animator->initialValue );
-              }
-
-              if( ! transition )
-              {
-                transition = Dali::Animation::New( 0.1f );
-              }
-
-              transition.AnimateTo( Property( child, propertyIndex ),
-                                    animator->targetValue,
-                                    animator->alphaFunction,
-                                    TimePeriod( animator->timePeriodDelay,
-                                                animator->timePeriodDuration ) );
+              animation = Dali::Animation::New( 0.1f );
             }
+
+            animation.AnimateTo( Property( child, propertyIndex ),
+                                 animator->targetValue,
+                                 animator->alphaFunction,
+                                 TimePeriod( animator->timePeriodDelay,
+                                             animator->timePeriodDuration ) );
           }
         }
       }
     }
   }
+}
+
+Dali::Animation Control::Impl::CreateTransition( const Toolkit::TransitionData& transitionData )
+{
+  Dali::Animation transition;
 
+  if( transitionData.Count() > 0 )
+  {
+    AddTransitions( transition, transitionData, true );
+  }
   return transition;
 }
 
+
+
 void Control::Impl::DoAction( Dali::Property::Index visualIndex, Dali::Property::Index actionId, const Dali::Property::Value attributes )
 {
   RegisteredVisualContainer::Iterator iter;
@@ -1407,6 +1422,24 @@ bool Control::Impl::FilterKeyEvent( const KeyEvent& event )
   return consumed;
 }
 
+Toolkit::Internal::LayoutItemPtr Control::Impl::GetLayout() const
+{
+  return mLayout;
+}
+
+void Control::Impl::SetLayout( Toolkit::Internal::LayoutItem& layout )
+{
+  if( mLayout )
+  {
+    mLayout->Unparent();
+    mLayout.Reset();
+  }
+  mLayout = &layout;
+
+  auto controlHandle = Toolkit::Control::DownCast( mControlImpl.Self() ); // Get a handle of this control implementation without copying internals.
+  mLayout->Initialize( controlHandle, controlHandle.GetTypeName() ); // LayoutGroup takes ownership of existing children
+}
+
 } // namespace Internal
 
 } // namespace Toolkit
index a0ff3d1..2a06d4c 100755 (executable)
@@ -2,7 +2,7 @@
 #define DALI_TOOLKIT_CONTROL_DATA_IMPL_H
 
 /*
- * Copyright (c) 2017 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2018 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -27,6 +27,7 @@
 #include <dali-toolkit/internal/visuals/visual-resource-observer.h>
 #include <dali-toolkit/public-api/controls/control-impl.h>
 #include <dali/devel-api/common/owner-container.h>
+#include <dali-toolkit/devel-api/layouting/layout-item-impl.h>
 #include <dali-toolkit/devel-api/visual-factory/visual-base.h>
 #include <dali-toolkit/internal/controls/tooltip/tooltip.h>
 #include <dali-toolkit/internal/builder/style.h>
@@ -83,7 +84,7 @@ public:
 
   /**
    * @brief Constructor.
-   * @param[in] controlImpl The control which own this implementation
+   * @param[in] controlImpl The control which owns this implementation
    */
   Impl( Control& controlImpl );
 
@@ -185,6 +186,16 @@ public:
   Toolkit::Visual::ResourceStatus GetVisualResourceStatus( Property::Index index ) const;
 
   /**
+   * @param[in,out] animation Handle to existing animation, or an empty handle that
+   * can be set to a New animation if createAnimation is true
+   * @param[in] transitionData The transition data describing the animation
+   * @param[in] createAnimation True if the animation should be created
+   */
+  void AddTransitions( Dali::Animation& animation,
+                       const Toolkit::TransitionData& transitionData,
+                       bool createAnimation = false );
+
+  /**
    * @copydoc Dali::Toolkit::DevelControl::CreateTransition()
    */
   Dali::Animation CreateTransition( const Toolkit::TransitionData& transitionData );
@@ -313,6 +324,19 @@ public:
    */
   bool FilterKeyEvent( const KeyEvent& event );
 
+  /**
+   * @brief Get the layout associated with this control, if any.
+   *
+   * @return A pointer to the layout, or NULL.
+   */
+  Toolkit::Internal::LayoutItemPtr GetLayout() const;
+
+  /**
+   * @brief Set the layout on this control.
+   * @param[in] layout Pointer to the layout
+   */
+  void SetLayout( Toolkit::Internal::LayoutItem& layout );
+
 private:
 
   /**
@@ -358,6 +382,9 @@ public:
   DevelControl::State mState;
   std::string mSubStateName;
 
+  // Layout
+  Toolkit::Internal::LayoutItemPtr mLayout;
+
   int mLeftFocusableActorId;       ///< Actor ID of Left focusable control.
   int mRightFocusableActorId;      ///< Actor ID of Right focusable control.
   int mUpFocusableActorId;         ///< Actor ID of Up focusable control.
@@ -391,6 +418,7 @@ public:
 
   RegisteredVisualContainer mRemoveVisuals;         ///< List of visuals that are being replaced by another visual once ready
 
+
   // Properties - these need to be members of Internal::Control::Impl as they access private methods/data of Internal::Control and Internal::Control::Impl.
   static const PropertyRegistration PROPERTY_1;
   static const PropertyRegistration PROPERTY_2;
index fec5df5..485cd59 100755 (executable)
@@ -39,18 +39,19 @@ namespace
 
 #define FLEX_CONTAINER_TAG "DALI Toolkit::FlexContainer "
 #define FC_LOG(fmt, args...) Debug::LogMessage(Debug::DebugInfo, FLEX_CONTAINER_TAG fmt, ## args)
-//#define FLEX_CONTAINER_DEBUG 1
+// #define FLEX_CONTAINER_DEBUG 1
 
 #if defined(FLEX_CONTAINER_DEBUG)
-void PrintNode( Toolkit::Internal::FlexContainer::FlexItemNodeContainer itemNodes )
+void PrintNodes( Toolkit::Internal::FlexContainer::FlexItemNodeContainer itemNodes )
 {
   // Print the style property and layout of all the children
   for( unsigned int i = 0; i < itemNodes.size(); ++i )
   {
     FC_LOG( "Item %d style: \n", i );
-    print_css_node( itemNodes[i].node, (css_print_options_t)( CSS_PRINT_STYLE | CSS_PRINT_CHILDREN ) );
+    YGNodePrint( itemNodes[i].node, (YGPrintOptions)( YGPrintOptionsStyle | YGPrintOptionsChildren ) );
+    FC_LOG( "\n" );
     FC_LOG( "Item %d layout: \n", i );
-    print_css_node( itemNodes[i].node, (css_print_options_t)( CSS_PRINT_LAYOUT | CSS_PRINT_CHILDREN ) );
+    YGNodePrint( itemNodes[i].node, (YGPrintOptions)( YGPrintOptionsLayout | YGPrintOptionsChildren ) );
     FC_LOG( "\n" );
   }
 }
@@ -156,26 +157,6 @@ const Scripting::StringEnum ALIGN_CONTENT_STRING_TABLE[] =
 };
 const unsigned int ALIGN_CONTENT_STRING_TABLE_COUNT = sizeof( ALIGN_CONTENT_STRING_TABLE ) / sizeof( ALIGN_CONTENT_STRING_TABLE[0] );
 
-/**
- * The function used by the layout algorithm to be get the style properties
- * and layout information of the child at the given index.
- */
-css_node_t* GetChildNodeAtIndex( void *childrenNodes, int i )
-{
-  FlexContainer::FlexItemNodeContainer childrenNodeContainer = *( static_cast<FlexContainer::FlexItemNodeContainer*>( childrenNodes ) );
-  return childrenNodeContainer[i].node;
-}
-
-/**
- * The function used by the layout algorithm to check whether the node is dirty
- * for relayout.
- */
-bool IsNodeDirty( void *itemNodes )
-{
-  // We only calculate the layout when the child is added or removed, or when
-  // style properties are changed. So should always return true here.
-  return true;
-}
 } // Unnamed namespace
 
 Toolkit::FlexContainer FlexContainer::New()
@@ -195,11 +176,11 @@ Toolkit::FlexContainer FlexContainer::New()
 
 FlexContainer::~FlexContainer()
 {
-  free_css_node( mRootNode.node );
+  YGNodeFree( mRootNode.node );
 
   for( unsigned int i = 0; i < mChildrenNodes.size(); i++ )
   {
-    free_css_node( mChildrenNodes[i].node );
+    YGNodeFree( mChildrenNodes[i].node );
   }
 
   mChildrenNodes.clear();
@@ -256,7 +237,7 @@ void FlexContainer::SetFlexDirection( Toolkit::FlexContainer::FlexDirection flex
   if( mFlexDirection != flexDirection )
   {
     mFlexDirection = flexDirection;
-    mRootNode.node->style.flex_direction = static_cast<css_flex_direction_t>( mFlexDirection );
+    YGNodeStyleSetFlexDirection( mRootNode.node, static_cast<YGFlexDirection>( flexDirection ) );
 
     RelayoutRequest();
   }
@@ -272,7 +253,7 @@ void FlexContainer::SetFlexWrap( Toolkit::FlexContainer::WrapType flexWrap )
   if( mFlexWrap != flexWrap )
   {
     mFlexWrap = flexWrap;
-    mRootNode.node->style.flex_wrap = static_cast<css_wrap_type_t>( mFlexWrap );
+    YGNodeStyleSetFlexWrap( mRootNode.node, static_cast<YGWrap>( flexWrap ) );
 
     RelayoutRequest();
   }
@@ -288,7 +269,7 @@ void FlexContainer::SetJustifyContent( Toolkit::FlexContainer::Justification jus
   if( mJustifyContent != justifyContent )
   {
     mJustifyContent = justifyContent;
-    mRootNode.node->style.justify_content = static_cast<css_justify_t>( mJustifyContent );
+    YGNodeStyleSetJustifyContent( mRootNode.node, static_cast<YGJustify>( justifyContent ) );
 
     RelayoutRequest();
   }
@@ -304,7 +285,7 @@ void FlexContainer::SetAlignItems( Toolkit::FlexContainer::Alignment alignItems
   if( mAlignItems != alignItems )
   {
     mAlignItems = alignItems;
-    mRootNode.node->style.align_items = static_cast<css_align_t>( mAlignItems );
+    YGNodeStyleSetAlignItems( mRootNode.node, static_cast<YGAlign>( alignItems ) );
 
     RelayoutRequest();
   }
@@ -320,7 +301,7 @@ void FlexContainer::SetAlignContent( Toolkit::FlexContainer::Alignment alignCont
   if( mAlignContent != alignContent )
   {
     mAlignContent = alignContent;
-    mRootNode.node->style.align_content = static_cast<css_align_t>( mAlignContent );
+    YGNodeStyleSetAlignContent( mRootNode.node, static_cast<YGAlign>( alignContent ) );
 
     RelayoutRequest();
   }
@@ -498,10 +479,10 @@ void FlexContainer::OnChildAdd( Actor& child )
   // Create a new node for the child.
   FlexItemNode childNode;
   childNode.actor = child;
-  childNode.node = new_css_node();
-  childNode.node->get_child = GetChildNodeAtIndex;
-  childNode.node->is_dirty = IsNodeDirty;
-  mChildrenNodes.push_back(childNode);
+  childNode.node = YGNodeNew();
+
+  mChildrenNodes.push_back( childNode );
+  YGNodeInsertChild( mRootNode.node, childNode.node, mChildrenNodes.size() - 1 );
 
   Control::OnChildAdd( child );
 }
@@ -512,7 +493,9 @@ void FlexContainer::OnChildRemove( Actor& child )
   {
     if( mChildrenNodes[i].actor.GetHandle() == child )
     {
-      free_css_node( mChildrenNodes[i].node );
+      YGNodeRemoveChild( mRootNode.node, mChildrenNodes[i].node );
+      YGNodeFree( mChildrenNodes[i].node );
+
       mChildrenNodes.erase( mChildrenNodes.begin() + i );
 
       // Relayout the container only if instances were found
@@ -543,17 +526,20 @@ void FlexContainer::OnRelayout( const Vector2& size, RelayoutContainer& containe
 
       if( negotiatedWidth > 0 )
       {
-        mChildrenNodes[i].node->style.dimensions[CSS_WIDTH] = negotiatedWidth;
+        YGNodeStyleSetWidth( mChildrenNodes[i].node, negotiatedWidth );
       }
       if( negotiatedHeight > 0 )
       {
-        mChildrenNodes[i].node->style.dimensions[CSS_HEIGHT] = negotiatedHeight;
+        YGNodeStyleSetHeight( mChildrenNodes[i].node, negotiatedHeight );
       }
     }
   }
 
   // Relayout the container
   RelayoutChildren();
+#if defined(FLEX_CONTAINER_DEBUG)
+  PrintNodes( mChildrenNodes );
+#endif
 
   for( unsigned int i = 0; i < mChildrenNodes.size(); i++ )
   {
@@ -573,8 +559,7 @@ void FlexContainer::OnRelayout( const Vector2& size, RelayoutContainer& containe
           child.SetResizePolicy( ResizePolicy::USE_ASSIGNED_SIZE, Dimension::HEIGHT );
         }
       }
-
-      container.Add( child, Vector2(mChildrenNodes[i].node->layout.dimensions[CSS_WIDTH], mChildrenNodes[i].node->layout.dimensions[CSS_HEIGHT] ) );
+      container.Add( child, Vector2(YGNodeLayoutGetWidth(mChildrenNodes[i].node), YGNodeLayoutGetHeight(mChildrenNodes[i].node) ) );
     }
   }
 }
@@ -589,9 +574,8 @@ void FlexContainer::OnSizeSet( const Vector3& size )
   if( mRootNode.node )
   {
     Actor self = Self();
-
-    mRootNode.node->style.dimensions[CSS_WIDTH] = size.x;
-    mRootNode.node->style.dimensions[CSS_HEIGHT] = size.y;
+    YGNodeStyleSetWidth( mRootNode.node, size.x );
+    YGNodeStyleSetHeight( mRootNode.node, size.y );
 
     RelayoutRequest();
   }
@@ -628,33 +612,16 @@ void FlexContainer::ComputeLayout()
 {
   if( mRootNode.node )
   {
-    mRootNode.node->children_count = mChildrenNodes.size();
-
-    // Intialize the layout.
-    mRootNode.node->layout.position[CSS_LEFT] = 0;
-    mRootNode.node->layout.position[CSS_TOP] = 0;
-    mRootNode.node->layout.position[CSS_BOTTOM] = 0;
-    mRootNode.node->layout.position[CSS_RIGHT] = 0;
-    mRootNode.node->layout.dimensions[CSS_WIDTH] = CSS_UNDEFINED;
-    mRootNode.node->layout.dimensions[CSS_HEIGHT] = CSS_UNDEFINED;
-
     for( unsigned int i = 0; i < mChildrenNodes.size(); i++ )
     {
-      css_node_t* childNode = mChildrenNodes[i].node;
+      YGNodeRef childNode = mChildrenNodes[i].node;
       Actor childActor = mChildrenNodes[i].actor.GetHandle();
 
-      childNode->layout.position[CSS_LEFT] = 0;
-      childNode->layout.position[CSS_TOP] = 0;
-      childNode->layout.position[CSS_BOTTOM] = 0;
-      childNode->layout.position[CSS_RIGHT] = 0;
-      childNode->layout.dimensions[CSS_WIDTH] = CSS_UNDEFINED;
-      childNode->layout.dimensions[CSS_HEIGHT] = CSS_UNDEFINED;
-
       // Intialize the style of the child.
-      childNode->style.minDimensions[CSS_WIDTH] = childActor.GetMinimumSize().x;
-      childNode->style.minDimensions[CSS_HEIGHT] = childActor.GetMinimumSize().y;
-      childNode->style.maxDimensions[CSS_WIDTH] = childActor.GetMaximumSize().x;
-      childNode->style.maxDimensions[CSS_HEIGHT] = childActor.GetMaximumSize().y;
+      YGNodeStyleSetMinWidth( childNode, childActor.GetMinimumSize().x );
+      YGNodeStyleSetMinHeight( childNode, childActor.GetMinimumSize().y );
+      YGNodeStyleSetMaxWidth( childNode, childActor.GetMaximumSize().x );
+      YGNodeStyleSetMaxHeight( childNode, childActor.GetMaximumSize().y );
 
       // Check child properties on the child for how to layout it.
       // These properties should be dynamically registered to the child which
@@ -662,7 +629,7 @@ void FlexContainer::ComputeLayout()
 
       if( childActor.GetPropertyType( Toolkit::FlexContainer::ChildProperty::FLEX ) != Property::NONE )
       {
-        childNode->style.flex = childActor.GetProperty( Toolkit::FlexContainer::ChildProperty::FLEX ).Get<float>();
+        YGNodeStyleSetFlex( childNode, childActor.GetProperty( Toolkit::FlexContainer::ChildProperty::FLEX ).Get<float>() );
       }
 
       Toolkit::FlexContainer::Alignment alignSelf( Toolkit::FlexContainer::ALIGN_AUTO );
@@ -681,43 +648,49 @@ void FlexContainer::ComputeLayout()
                                                                           ALIGN_SELF_STRING_TABLE_COUNT,
                                                                           alignSelf );
         }
+        YGNodeStyleSetAlignSelf( childNode, static_cast<YGAlign>(alignSelf) );
       }
-      childNode->style.align_self = static_cast<css_align_t>(alignSelf);
 
       if( childActor.GetPropertyType( Toolkit::FlexContainer::ChildProperty::FLEX_MARGIN ) != Property::NONE )
       {
         Vector4 flexMargin = childActor.GetProperty( Toolkit::FlexContainer::ChildProperty::FLEX_MARGIN ).Get<Vector4>();
-        childNode->style.margin[CSS_LEFT] = flexMargin.x;
-        childNode->style.margin[CSS_TOP] = flexMargin.y;
-        childNode->style.margin[CSS_RIGHT] = flexMargin.z;
-        childNode->style.margin[CSS_BOTTOM] = flexMargin.w;
+        YGNodeStyleSetMargin( childNode, YGEdgeLeft, flexMargin.x );
+        YGNodeStyleSetMargin( childNode, YGEdgeTop, flexMargin.y );
+        YGNodeStyleSetMargin( childNode, YGEdgeRight, flexMargin.z );
+        YGNodeStyleSetMargin( childNode, YGEdgeBottom, flexMargin.w );
       }
     }
 
     // Calculate the layout
-    css_direction_t nodeLayoutDirection = CSS_DIRECTION_INHERIT;
+    YGDirection nodeLayoutDirection = YGDirectionInherit;
     switch( mContentDirection )
     {
     case Dali::Toolkit::FlexContainer::LTR:
     {
-      nodeLayoutDirection = CSS_DIRECTION_LTR;
+      nodeLayoutDirection = YGDirectionLTR;
       break;
     }
 
     case Dali::Toolkit::FlexContainer::RTL:
     {
-      nodeLayoutDirection = CSS_DIRECTION_RTL;
+      nodeLayoutDirection = YGDirectionRTL;
       break;
     }
 
     case Dali::Toolkit::FlexContainer::INHERIT:
     {
-      nodeLayoutDirection = CSS_DIRECTION_INHERIT;
+      nodeLayoutDirection = YGDirectionInherit;
       break;
     }
     }
 
-    layoutNode( mRootNode.node, Self().GetMaximumSize().x, Self().GetMaximumSize().y, nodeLayoutDirection);
+#if defined(FLEX_CONTAINER_DEBUG)
+    YGNodePrint( mRootNode.node, (YGPrintOptions)( YGPrintOptionsLayout | YGPrintOptionsStyle | YGPrintOptionsChildren ) );
+#endif
+    YGNodeCalculateLayout( mRootNode.node, Self().GetMaximumSize().x, Self().GetMaximumSize().y, nodeLayoutDirection );
+#if defined(FLEX_CONTAINER_DEBUG)
+    YGNodePrint( mRootNode.node, (YGPrintOptions)( YGPrintOptionsLayout | YGPrintOptionsStyle | YGPrintOptionsChildren ) );
+#endif
   }
 }
 
@@ -731,8 +704,8 @@ void FlexContainer::RelayoutChildren()
     Dali::Actor child = mChildrenNodes[i].actor.GetHandle();
     if( child )
     {
-      child.SetX( mChildrenNodes[i].node->layout.position[CSS_LEFT] );
-      child.SetY( mChildrenNodes[i].node->layout.position[CSS_TOP] );
+      child.SetX( YGNodeLayoutGetLeft( mChildrenNodes[i].node ) );
+      child.SetY( YGNodeLayoutGetTop( mChildrenNodes[i].node ) );
     }
   }
 }
@@ -858,20 +831,15 @@ void FlexContainer::OnInitialize()
   self.LayoutDirectionChangedSignal().Connect( this, &FlexContainer::OnLayoutDirectionChanged );
 
   mRootNode.actor = self;
-  mRootNode.node = new_css_node();
-  mRootNode.node->context = &mChildrenNodes;
+  mRootNode.node = YGNodeNew();
+  YGNodeSetContext( mRootNode.node, &mChildrenNodes );
 
   // Set default style
-  mRootNode.node->style.direction = static_cast<css_direction_t>( mContentDirection );
-  mRootNode.node->style.flex_direction = static_cast<css_flex_direction_t>( mFlexDirection );
-  mRootNode.node->style.flex_wrap = static_cast<css_wrap_type_t>( mFlexWrap );
-  mRootNode.node->style.justify_content = static_cast<css_justify_t>( mJustifyContent );
-  mRootNode.node->style.align_items = static_cast<css_align_t>( mAlignItems );
-  mRootNode.node->style.align_content = static_cast<css_align_t>( mAlignContent );
-
-  // Set callbacks.
-  mRootNode.node->get_child = GetChildNodeAtIndex;
-  mRootNode.node->is_dirty = IsNodeDirty;
+  YGNodeStyleSetFlexDirection( mRootNode.node, static_cast<YGFlexDirection>( mFlexDirection ) );
+  YGNodeStyleSetFlexWrap( mRootNode.node, static_cast<YGWrap>( mFlexWrap ) );
+  YGNodeStyleSetJustifyContent( mRootNode.node, static_cast<YGJustify>( mJustifyContent ) );
+  YGNodeStyleSetAlignItems( mRootNode.node, static_cast<YGAlign>( mAlignItems ) );
+  YGNodeStyleSetAlignContent( mRootNode.node, static_cast<YGAlign>( mAlignContent ) );
 
   // Make self as keyboard focusable and focus group
   self.SetKeyboardFocusable( true );
index 71fec8e..9b8b9e9 100755 (executable)
 // INTERNAL INCLUDES
 #include <dali-toolkit/public-api/controls/control-impl.h>
 #include <dali-toolkit/public-api/controls/flex-container/flex-container.h>
-extern "C"
-{
-#include <dali-toolkit/third-party/facebook-flexbox/layout.h>
-}
+#include <dali-toolkit/third-party/yoga/Yoga.h>
 
 namespace Dali
 {
@@ -52,7 +49,7 @@ public:
   struct FlexItemNode
   {
     WeakHandle< Dali::Actor > actor;      ///< Actor handle of the flex item
-    css_node_t* node;                     ///< The style properties and layout information
+    YGNodeRef node;                     ///< The style properties and layout information
   };
 
   typedef std::vector< FlexItemNode > FlexItemNodeContainer;
index 13e68bc..58476a8 100755 (executable)
@@ -2,7 +2,7 @@
 #define __DALI_TOOLKIT_GRID_LAYOUT_H__
 
 /*
- * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2018 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -22,7 +22,7 @@
 
 #include <dali-toolkit/public-api/controls/scrollable/item-view/item-layout.h>
 
-#include <dali/public-api/common/dali-common.h>
+#include <dali-toolkit/public-api/dali-toolkit-common.h>
 
 
 namespace Dali
index f32296b..00121b8 100755 (executable)
@@ -11,6 +11,12 @@ toolkit_src_files = \
    $(toolkit_src_dir)/builder/style.cpp \
    $(toolkit_src_dir)/builder/tree-node-manipulator.cpp \
    $(toolkit_src_dir)/builder/replacement.cpp \
+   $(toolkit_src_dir)/layouting/hbox-layout-impl.cpp \
+   $(toolkit_src_dir)/layouting/vbox-layout-impl.cpp \
+   $(toolkit_src_dir)/layouting/layout-item-data-impl.cpp \
+   $(toolkit_src_dir)/layouting/layout-group-data-impl.cpp \
+   $(toolkit_src_dir)/layouting/layout-controller-debug.cpp \
+   $(toolkit_src_dir)/layouting/layout-controller-impl.cpp \
    $(toolkit_src_dir)/visuals/animated-image/animated-image-visual.cpp \
    $(toolkit_src_dir)/visuals/animated-image/image-cache.cpp \
    $(toolkit_src_dir)/visuals/animated-image/fixed-image-cache.cpp \
diff --git a/dali-toolkit/internal/layouting/hbox-layout-impl.cpp b/dali-toolkit/internal/layouting/hbox-layout-impl.cpp
new file mode 100644 (file)
index 0000000..ca86db6
--- /dev/null
@@ -0,0 +1,282 @@
+/*
+ * Copyright (c) 2018 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//CLASS HEADER
+#include <dali-toolkit/internal/layouting/hbox-layout-impl.h>
+
+//EXTERNAL HEADERS
+//INTERNAL HEADERS
+#include <dali/integration-api/debug.h>
+#include <dali/public-api/common/extents.h>
+#include <dali/public-api/actors/actor.h>
+#include <dali-toolkit/devel-api/layouting/layout-item.h>
+#include <dali-toolkit/public-api/controls/control-impl.h>
+#include <dali-toolkit/internal/controls/control/control-data-impl.h>
+
+
+#if defined(DEBUG_ENABLED)
+static Debug::Filter* gLogFilter = Debug::Filter::New( Debug::Concise, false, "LOG_LAYOUT" );
+#endif
+
+namespace Dali
+{
+namespace Toolkit
+{
+namespace Internal
+{
+
+HboxLayoutPtr HboxLayout::New()
+{
+  HboxLayoutPtr layout( new HboxLayout() );
+  return layout;
+}
+
+HboxLayout::HboxLayout()
+: LayoutGroup(),
+  mCellPadding( 0, 0 ),
+  mTotalLength( 0 )
+{
+}
+
+HboxLayout::~HboxLayout()
+{
+}
+
+void HboxLayout::DoInitialize()
+{
+}
+
+void HboxLayout::DoRegisterChildProperties( const std::string& containerType )
+{
+  auto typeInfo = Dali::TypeRegistry::Get().GetTypeInfo( containerType );
+  if( typeInfo )
+  {
+    Property::IndexContainer indices;
+    typeInfo.GetChildPropertyIndices( indices );
+
+    if( std::find( indices.Begin(), indices.End(), Toolkit::HboxLayout::ChildProperty::WEIGHT ) == indices.End() )
+    {
+      ChildPropertyRegistration( typeInfo.GetName(), "weight",
+                                 Toolkit::HboxLayout::ChildProperty::WEIGHT, Property::FLOAT );
+    }
+  }
+}
+
+void HboxLayout::OnChildAdd( LayoutItem& child )
+{
+  auto owner = child.GetOwner();
+  owner.SetProperty( Toolkit::HboxLayout::ChildProperty::WEIGHT, 1.0f );
+}
+
+void HboxLayout::SetCellPadding( LayoutSize size )
+{
+  mCellPadding = size;
+}
+
+LayoutSize HboxLayout::GetCellPadding()
+{
+  return mCellPadding;
+}
+
+void HboxLayout::OnMeasure( MeasureSpec widthMeasureSpec, MeasureSpec heightMeasureSpec )
+{
+#if defined(DEBUG_ENABLED)
+  auto actor = Actor::DownCast(GetOwner());
+
+  std::ostringstream oss;
+  oss << "HBoxLayout::OnMeasure  ";
+  if( actor )
+  {
+    oss << "Actor Id:" << actor.GetId() << " Name:" << actor.GetName() << "  ";
+  }
+  oss << "widthMeasureSpec:" << widthMeasureSpec << " heightMeasureSpec:" << heightMeasureSpec << std::endl;
+  DALI_LOG_INFO( gLogFilter, Debug::Concise, oss.str().c_str() );
+#endif
+
+  auto widthMode = widthMeasureSpec.GetMode();
+  auto heightMode = heightMeasureSpec.GetMode();
+  bool isExactly = (widthMode == MeasureSpec::Mode::EXACTLY);
+  bool matchHeight = false;
+  bool allFillParent = true;
+  LayoutLength maxHeight = 0;
+  LayoutLength alternativeMaxHeight = 0;
+  struct
+  {
+    MeasuredSize::State widthState;
+    MeasuredSize::State heightState;
+  } childState = { MeasuredSize::State::MEASURED_SIZE_OK, MeasuredSize::State::MEASURED_SIZE_OK };
+
+  // measure children, and determine if further resolution is required
+  for( unsigned int i=0; i<GetChildCount(); ++i )
+  {
+    auto childLayout = GetChildAt( i );
+    if( childLayout )
+    {
+      auto childOwner = childLayout->GetOwner();
+      auto desiredHeight = childOwner.GetProperty<int>( Toolkit::LayoutItem::ChildProperty::HEIGHT_SPECIFICATION );
+
+      MeasureChildWithMargins( childLayout, widthMeasureSpec, 0, heightMeasureSpec, 0 );
+      auto childWidth = childLayout->GetMeasuredWidth();
+      auto childMargin = childOwner.GetProperty<Extents>( Toolkit::LayoutGroup::ChildProperty::MARGIN_SPECIFICATION );
+      auto length = childWidth + LayoutLength::IntType(childMargin.start + childMargin.end);
+
+      auto cellPadding = i<GetChildCount()-1 ? mCellPadding.width: 0;
+
+      if( isExactly )
+      {
+        mTotalLength += length;
+      }
+      else
+      {
+        auto totalLength = mTotalLength;
+        mTotalLength = std::max( totalLength, totalLength + length + cellPadding );
+      }
+
+      bool matchHeightLocally = false;
+      if( heightMode != MeasureSpec::Mode::EXACTLY && desiredHeight == Toolkit::ChildLayoutData::MATCH_PARENT )
+      {
+        // Will have to re-measure at least this child when we know exact height.
+        matchHeight = true;
+        matchHeightLocally = true;
+      }
+
+      auto marginHeight = LayoutLength( childMargin.top + childMargin.bottom );
+      auto childHeight = childLayout->GetMeasuredHeight() + marginHeight;
+
+      if( childLayout->GetMeasuredWidthAndState().GetState() == MeasuredSize::State::MEASURED_SIZE_TOO_SMALL )
+      {
+        childState.widthState = MeasuredSize::State::MEASURED_SIZE_TOO_SMALL;
+      }
+      if( childLayout->GetMeasuredHeightAndState().GetState() == MeasuredSize::State::MEASURED_SIZE_TOO_SMALL )
+      {
+        childState.heightState = MeasuredSize::State::MEASURED_SIZE_TOO_SMALL;
+      }
+
+      maxHeight = std::max( maxHeight, childHeight );
+      allFillParent = ( allFillParent && desiredHeight == Toolkit::ChildLayoutData::MATCH_PARENT );
+      alternativeMaxHeight = std::max( alternativeMaxHeight, matchHeightLocally ? marginHeight : childHeight );
+    }
+  }
+
+  Extents padding = GetPadding();
+  mTotalLength += padding.start + padding.end;
+  auto widthSize = mTotalLength;
+  widthSize = std::max( widthSize, GetSuggestedMinimumWidth() );
+  MeasuredSize widthSizeAndState = ResolveSizeAndState( widthSize, widthMeasureSpec, MeasuredSize::State::MEASURED_SIZE_OK);
+  widthSize = widthSizeAndState.GetSize();
+
+  if( !allFillParent && heightMode != MeasureSpec::Mode::EXACTLY )
+  {
+    maxHeight = alternativeMaxHeight;
+  }
+  maxHeight += padding.top + padding.bottom;
+  maxHeight = std::max( maxHeight, GetSuggestedMinimumHeight() );
+
+  widthSizeAndState.SetState( childState.widthState );
+
+  SetMeasuredDimensions( widthSizeAndState,
+                         ResolveSizeAndState( maxHeight, heightMeasureSpec, childState.heightState ) );
+
+  if( matchHeight )
+  {
+    ForceUniformHeight( GetChildCount(), widthMeasureSpec );
+  }
+}
+
+void HboxLayout::ForceUniformHeight( int count, MeasureSpec widthMeasureSpec )
+{
+  // Pretend that the linear layout has an exact size. This is the measured height of
+  // ourselves. The measured height should be the max height of the children, changed
+  // to accommodate the heightMeasureSpec from the parent
+  auto uniformMeasureSpec = MeasureSpec( GetMeasuredHeight(), MeasureSpec::Mode::EXACTLY );
+  for (int i = 0; i < count; ++i)
+  {
+    LayoutItemPtr childLayout = GetChildAt(i);
+    if( childLayout != nullptr )
+    {
+      auto childOwner = childLayout->GetOwner();
+      auto desiredWidth = childOwner.GetProperty<int>( Toolkit::LayoutItem::ChildProperty::WIDTH_SPECIFICATION );
+      auto desiredHeight = childOwner.GetProperty<int>( Toolkit::LayoutItem::ChildProperty::HEIGHT_SPECIFICATION );
+
+      if( desiredHeight == Toolkit::ChildLayoutData::MATCH_PARENT )
+      {
+        // Temporarily force children to reuse their old measured width
+        int oldWidth = desiredWidth;
+        childOwner.SetProperty( Toolkit::LayoutItem::ChildProperty::WIDTH_SPECIFICATION, childLayout->GetMeasuredWidth().mValue );
+
+        // Remeasure with new dimensions
+        MeasureChildWithMargins( childLayout, widthMeasureSpec, 0, uniformMeasureSpec, 0);
+
+        childOwner.SetProperty( Toolkit::LayoutItem::ChildProperty::WIDTH_SPECIFICATION, oldWidth );
+      }
+    }
+  }
+}
+
+void HboxLayout::OnLayout( bool changed, LayoutLength left, LayoutLength top, LayoutLength right, LayoutLength bottom )
+{
+  auto owner = GetOwner();
+  auto actor = Actor::DownCast(owner);
+  bool isLayoutRtl = actor ? actor.GetProperty<bool>( Actor::Property::LAYOUT_DIRECTION ) : false;
+
+  Extents padding = GetPadding();
+
+  LayoutLength childTop( 0 );
+  LayoutLength childLeft( padding.start );
+
+  // Where bottom of child should go
+  auto height = bottom - top;
+
+  // Space available for child
+  auto childSpace = height - padding.top - padding.bottom;
+
+  auto count = GetChildCount();
+
+  int start = 0;
+  int dir = 1;
+
+  // In case of RTL, start drawing from the last child.
+  // @todo re-work to draw the first child from the right edge, and move leftwards.
+  // (Should have an alignment also)
+  if( isLayoutRtl ) {
+    start = count - 1;
+    dir = -1;
+  }
+
+  for( unsigned int i = 0; i < count; i++)
+  {
+    int childIndex = start + dir * i;
+    LayoutItemPtr childLayout = GetChildAt( childIndex );
+    if( childLayout != nullptr )
+    {
+      auto childWidth = childLayout->GetMeasuredWidth();
+      auto childHeight = childLayout->GetMeasuredHeight();
+
+      auto childOwner = childLayout->GetOwner();
+      auto childMargin = childOwner.GetProperty<Extents>( Toolkit::LayoutGroup::ChildProperty::MARGIN_SPECIFICATION );
+
+      childTop = LayoutLength(padding.top) + ((childSpace - childHeight) / 2) + childMargin.top - childMargin.bottom;
+
+      childLeft += childMargin.start;
+      childLayout->Layout( childLeft, childTop, childLeft + childWidth, childTop + childHeight );
+      childLeft += childWidth + childMargin.end + mCellPadding.width;
+    }
+  }
+}
+
+} // namespace Internal
+} // namespace Toolkit
+} // namespace Dali
diff --git a/dali-toolkit/internal/layouting/hbox-layout-impl.h b/dali-toolkit/internal/layouting/hbox-layout-impl.h
new file mode 100644 (file)
index 0000000..2057376
--- /dev/null
@@ -0,0 +1,103 @@
+#ifndef DALI_TOOLKIT_INTERNAL_LAYOUTING_HBOX_LAYOUT_H
+#define DALI_TOOLKIT_INTERNAL_LAYOUTING_HBOX_LAYOUT_H
+
+/*
+ * Copyright (c) 2018 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <dali/public-api/common/intrusive-ptr.h>
+#include <dali/public-api/object/base-object.h>
+#include <dali-toolkit/devel-api/layouting/layout-group-impl.h>
+#include <dali-toolkit/devel-api/layouting/hbox-layout.h>
+
+namespace Dali
+{
+namespace Toolkit
+{
+namespace Internal
+{
+
+class HboxLayout;
+using HboxLayoutPtr = IntrusivePtr<HboxLayout>;
+
+class HboxLayout final : public LayoutGroup
+{
+public:
+  static HboxLayoutPtr New();
+
+public:
+  void SetCellPadding( LayoutSize size );
+  LayoutSize GetCellPadding();
+
+protected:
+  HboxLayout();
+  virtual ~HboxLayout();
+
+  /**
+   * @copydoc LayoutItem::DoInitialize
+   */
+  virtual void DoInitialize() override;
+
+  /**
+   * @copydoc LayoutItem::DoRegisterChildProperties()
+   */
+  virtual void DoRegisterChildProperties( const std::string& containerType ) override;
+
+  /**
+   * @copydoc LayoutItem::OnChildAdd
+   */
+  virtual void OnChildAdd( LayoutItem& child ) override;
+
+  /**
+   * @copydoc LayoutItem::OnMeasure
+   */
+  virtual void OnMeasure( MeasureSpec widthMeasureSpec, MeasureSpec heightMeasureSpec ) override;
+
+  /**
+   * @copydoc LayoutItem::OnLayout
+   */
+  virtual void OnLayout( bool changed, LayoutLength l, LayoutLength t, LayoutLength r, LayoutLength b ) override;
+
+private:
+  HboxLayout( const HboxLayout& other ) = delete;
+  HboxLayout& operator=( const HboxLayout& other ) = delete;
+
+  void ForceUniformHeight( int count, MeasureSpec widthMeasureSpec );
+
+private:
+  LayoutSize mCellPadding;
+  LayoutLength mTotalLength;
+};
+
+} // namespace Internal
+
+inline Internal::HboxLayout& GetImplementation( Dali::Toolkit::HboxLayout& handle )
+{
+  DALI_ASSERT_ALWAYS( handle && "HboxLayout handle is empty" );
+  BaseObject& object = handle.GetBaseObject();
+  return static_cast<Internal::HboxLayout&>( object );
+}
+
+inline const Internal::HboxLayout& GetImplementation( const Dali::Toolkit::HboxLayout& handle )
+{
+  DALI_ASSERT_ALWAYS( handle && "HboxLayout handle is empty" );
+  const BaseObject& object = handle.GetBaseObject();
+  return static_cast<const Internal::HboxLayout&>( object );
+}
+
+} // namespace Toolkit
+} // namespace Dali
+
+#endif // DALI_TOOLKIT_INTERNAL_LAYOUTING_HBOX_LAYOUT_H
diff --git a/dali-toolkit/internal/layouting/layout-controller-debug.cpp b/dali-toolkit/internal/layouting/layout-controller-debug.cpp
new file mode 100644 (file)
index 0000000..85057c1
--- /dev/null
@@ -0,0 +1,193 @@
+/*
+ * Copyright (c) 2018 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <dali-toolkit/dali-toolkit.h>
+#include <dali-toolkit/internal/controls/control/control-data-impl.h>
+#include <dali-toolkit/internal/layouting/layout-controller-debug.h>
+#include <dali-toolkit/devel-api/layouting/layout-group-impl.h>
+
+namespace Dali
+{
+namespace Toolkit
+{
+namespace Internal
+{
+
+#if defined( DEBUG_ENABLED )
+Debug::Filter* gLogFilter = Debug::Filter::New( Debug::Verbose, false, "LOG_LAYOUT_TREE" );
+
+
+void GetLayoutMeasureStateString( std::ostringstream& oss, LayoutItemPtr layout )
+{
+  if( layout )
+  {
+    auto widthSizeAndState = layout->GetMeasuredWidthAndState();
+    auto heightSizeAndState = layout->GetMeasuredHeightAndState();
+
+    oss << "LayoutMeasureState:" <<
+      "  w:" << widthSizeAndState.GetSize() << (widthSizeAndState.GetState()==MeasuredSize::MEASURED_SIZE_TOO_SMALL?"/TooSmall":"") <<
+      "  h:" << heightSizeAndState.GetSize() << (heightSizeAndState.GetState()==MeasuredSize::MEASURED_SIZE_TOO_SMALL?"/TooSmall":"");
+  }
+}
+
+void LayoutDebugMeasureStateRecurseLayout( LayoutItemPtr layout, int depth );
+
+void LayoutDebugMeasureStateRecurseActor( Actor root, int depth )
+{
+  std::ostringstream oss;
+  for(int i=0;i<depth;++i) { oss << "  "; };
+  oss << "Actor " << root.GetId() << ":" << root.GetName() << " ";
+
+  bool descendActor = true;
+  Toolkit::Control control = Toolkit::Control::DownCast( root );
+  if( control )
+  {
+    Internal::Control& controlImpl = GetImplementation( control );
+    Internal::Control::Impl& controlDataImpl = Internal::Control::Impl::Get( controlImpl );
+    LayoutItemPtr layout = controlDataImpl.GetLayout();
+
+    if( layout != nullptr )
+    {
+      GetLayoutMeasureStateString( oss, layout );
+      oss << std::endl;
+      DALI_LOG_INFO( gLogFilter, Debug::Verbose, oss.str().c_str() );
+
+      auto layoutGroup = LayoutGroupPtr( dynamic_cast< LayoutGroup* >( layout.Get() ) );
+      if( layoutGroup )
+      {
+        for( unsigned int i=0; i<layoutGroup->GetChildCount(); ++i )
+        {
+          auto layoutChild = layoutGroup->GetChildAt( i );
+          LayoutDebugMeasureStateRecurseLayout( layoutChild, depth+1 );
+        }
+      }
+      descendActor = false;
+    }
+  }
+
+  if( descendActor == true )
+  {
+    oss << std::endl;
+    DALI_LOG_INFO( gLogFilter, Debug::Verbose, oss.str().c_str() );
+
+    // Depth first descent through actor children
+    for( unsigned int i = 0, count = root.GetChildCount(); i < count; ++i )
+    {
+      Actor child = root.GetChildAt( i );
+      LayoutDebugMeasureStateRecurseActor( child, depth+1 );
+    }
+  }
+}
+
+void LayoutDebugMeasureStateRecurseLayout( LayoutItemPtr layout, int depth )
+{
+  std::ostringstream oss;
+  for(int i=0;i<depth;++i) { oss << "  "; }; // indent
+
+  Actor actor = Actor::DownCast( layout->GetOwner() );
+  if( actor )
+  {
+    oss << "Actor " << actor.GetId() << ":" << actor.GetName() << " ";
+  }
+  else
+  {
+    oss << "Owner: " << layout->GetOwner().GetObjectPtr() << " ";
+  }
+
+  GetLayoutMeasureStateString( oss, layout );
+  oss << std::endl;
+  DALI_LOG_INFO( gLogFilter, Debug::Verbose, oss.str().c_str() );
+
+  auto layoutGroup = LayoutGroupPtr( dynamic_cast< LayoutGroup* >( layout.Get() ) );
+  if( layoutGroup )
+  {
+    for( unsigned int i=0; i<layoutGroup->GetChildCount(); ++i )
+    {
+      auto layoutChild = layoutGroup->GetChildAt( i );
+      LayoutDebugMeasureStateRecurseLayout( layoutChild, depth+1 );
+    }
+  }
+  else if( actor )
+  {
+    for( unsigned int i = 0, count = actor.GetChildCount(); i < count; ++i )
+    {
+      LayoutDebugMeasureStateRecurseActor( actor.GetChildAt( i ), depth + 1 );
+    }
+  }
+}
+
+
+void LayoutDebugMeasureState( Actor root )
+{
+  DALI_LOG_INFO( gLogFilter, Debug::Verbose, "Layout tree after measure:\n\n" );
+  LayoutDebugMeasureStateRecurseActor( root, 0 );
+}
+
+
+void LayoutDebugAfterLayoutRecurse( Actor root, int depth )
+{
+  std::ostringstream oss;
+  for(int i=0;i<depth;++i) { oss << "  "; };
+  oss << "Actor " << root.GetId() << ":" << root.GetName() << " ";
+  Toolkit::Control control = Toolkit::Control::DownCast( root );
+  if( control )
+  {
+    Internal::Control& controlImpl = GetImplementation( control );
+    Internal::Control::Impl& controlDataImpl = Internal::Control::Impl::Get( controlImpl );
+    LayoutItemPtr layout = controlDataImpl.GetLayout();
+
+    if( layout )
+    {
+      auto childOwner = layout->GetOwner();
+      auto widthMeasureSpec = childOwner.GetProperty<int>( Toolkit::LayoutItem::ChildProperty::WIDTH_SPECIFICATION );
+      auto heightMeasureSpec = childOwner.GetProperty<int>( Toolkit::LayoutItem::ChildProperty::HEIGHT_SPECIFICATION );
+
+      oss << "LayoutData:" << "( " << widthMeasureSpec << ", " << heightMeasureSpec << ") ";
+
+      auto actorPos  = root.GetProperty<Vector3>( Actor::Property::POSITION );
+      auto actorSize = root.GetProperty<Vector3>( Actor::Property::SIZE );
+      oss << "  ActorPos: (" << actorPos.x << ", " << actorPos.y << ")";
+      oss << "  ActorSize: (" << actorSize.width << ", " << actorSize.height << ")";
+    }
+    else
+    {
+      // Try getting layout data from parent control
+    }
+  }
+  oss << std::endl;
+
+  DALI_LOG_INFO( gLogFilter, Debug::Verbose, oss.str().c_str() );
+
+  // Depth first descent through actor children
+  for( unsigned int i = 0, count = root.GetChildCount(); i < count; ++i )
+  {
+    Actor child = root.GetChildAt( i );
+    LayoutDebugAfterLayoutRecurse( child, depth+1 );
+  }
+}
+
+void LayoutDebugAfterLayout( Actor root )
+{
+  DALI_LOG_INFO( gLogFilter, Debug::Verbose, "Layout tree after layout:\n\n" );
+  LayoutDebugAfterLayoutRecurse( root, 0 );
+}
+
+
+#endif
+
+} // namespace Internal
+} // namespace Toolkit
+} // namespace Dali
diff --git a/dali-toolkit/internal/layouting/layout-controller-debug.h b/dali-toolkit/internal/layouting/layout-controller-debug.h
new file mode 100644 (file)
index 0000000..9a2323f
--- /dev/null
@@ -0,0 +1,55 @@
+#ifndef DALI_TOOLKIT_INTERNAL_LAYOUTING_DEBUG_H
+#define DALI_TOOLKIT_INTERNAL_LAYOUTING_DEBUG_H
+
+/*
+ * Copyright (c) 2018 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <dali/public-api/actors/actor.h>
+#include <dali/integration-api/debug.h>
+#include <dali-toolkit/devel-api/layouting/measure-spec.h>
+
+namespace Dali
+{
+namespace Toolkit
+{
+namespace Internal
+{
+
+#if defined(DEBUG_ENABLED)
+
+extern void LayoutDebugMeasureState( Actor root );
+extern void LayoutDebugAfterLayout( Actor root );
+
+
+#define LAYOUT_DEBUG_MEASURE_STATES( root ) \
+  LayoutDebugMeasureState( root )
+
+#define LAYOUT_DEBUG_AFTER_LAYOUT( root ) \
+  LayoutDebugAfterLayout( root )
+
+#else
+
+
+#define LAYOUT_DEBUG_MEASURE_STATES( root )
+#define LAYOUT_DEBUG_AFTER_LAYOUT( root )
+
+#endif
+
+} // namespace Internal
+} // namespace Toolkit
+} // namespace Dali
+
+#endif //DALI_TOOLKIT_INTERNAL_LAYOUTING_DEBUG_H
diff --git a/dali-toolkit/internal/layouting/layout-controller-impl.cpp b/dali-toolkit/internal/layouting/layout-controller-impl.cpp
new file mode 100644 (file)
index 0000000..90f125b
--- /dev/null
@@ -0,0 +1,156 @@
+/*
+ * Copyright (c) 2018 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <dali/public-api/common/stage.h>
+#include <dali/public-api/actors/layer.h>
+#include <dali-toolkit/internal/layouting/layout-controller-impl.h>
+#include <dali-toolkit/devel-api/layouting/layout-group-impl.h>
+#include <dali-toolkit/public-api/controls/control.h>
+#include <dali-toolkit/public-api/controls/control-impl.h>
+#include <dali-toolkit/internal/controls/control/control-data-impl.h>
+#include <dali-toolkit/internal/layouting/layout-controller-debug.h>
+
+using namespace Dali;
+
+#if defined(DEBUG_ENABLED)
+static Debug::Filter* gLogFilter = Debug::Filter::New( Debug::Concise, false, "LOG_LAYOUT" );
+#endif
+
+namespace Dali
+{
+namespace Toolkit
+{
+namespace Internal
+{
+
+LayoutController::LayoutController()
+: mLayoutRequested(false)
+{
+}
+
+LayoutController::~LayoutController()
+{
+}
+
+void LayoutController::Initialize()
+{
+}
+
+void LayoutController::RequestLayout( LayoutItem& LayoutItem )
+{
+  DALI_LOG_INFO( gLogFilter, Debug::Concise, "LayoutController::RequestLayout\n" );
+  mLayoutRequested = true;
+
+  // Go up the tree and mark all parents to relayout
+  LayoutParent* layoutParent = LayoutItem.GetParent();
+  if( layoutParent )
+  {
+    LayoutGroup& layoutGroup = static_cast< LayoutGroup& >( *layoutParent );
+    if( ! layoutGroup.IsLayoutRequested() )
+    {
+      layoutGroup.RequestLayout();
+    }
+  }
+}
+
+void LayoutController::Process()
+{
+  // Perform the full process.
+
+  if( mLayoutRequested )
+  {
+    mLayoutRequested = false;
+
+    // If window size has changed, expect stage to have already been updated
+    Stage stage = Stage::GetCurrent();
+    auto stageWidth  = stage.GetSize().width;
+    auto stageHeight = stage.GetSize().height;
+
+    auto widthSpec = MeasureSpec( stageWidth, MeasureSpec::Mode::EXACTLY );
+    auto heightSpec = MeasureSpec( stageHeight, MeasureSpec::Mode::EXACTLY );
+
+    // Test how to perform a measure on each control.
+    MeasureHierarchy( stage.GetRootLayer(), widthSpec, heightSpec );
+
+    LAYOUT_DEBUG_MEASURE_STATES( stage.GetRootLayer() );
+    PerformLayout( stage.GetRootLayer(), 0, 0, stageWidth, stageHeight );
+
+    LAYOUT_DEBUG_AFTER_LAYOUT( stage.GetRootLayer() );
+  }
+}
+
+void LayoutController::MeasureHierarchy( Actor root, MeasureSpec widthSpec, MeasureSpec heightSpec )
+{
+  // Does this actor have a layout?
+  // Yes - measure the layout. It will call this method again for each of it's children.
+  // No - recurse through actor children.
+  //
+  // If in a leaf actor with no layout, it's natural size is bubbled back up.
+  //
+  // What happens if nothing in the tree has a layout?
+
+  Toolkit::Control control = Toolkit::Control::DownCast( root );
+  if( control )
+  {
+    Internal::Control& controlImpl = GetImplementation( control );
+    Internal::Control::Impl& controlDataImpl = Internal::Control::Impl::Get( controlImpl );
+    LayoutItemPtr layout = controlDataImpl.GetLayout();
+
+    if( layout )
+    {
+      layout->Measure( widthSpec, heightSpec );
+    }
+  }
+  else
+  {
+    // Depth first descent through actor children
+    for( unsigned int i = 0, count = root.GetChildCount(); i < count; ++i )
+    {
+      Actor child = root.GetChildAt( i );
+      MeasureHierarchy( child, widthSpec, heightSpec );
+    }
+  }
+}
+
+void LayoutController::PerformLayout( Actor root, int left, int top, int right, int bottom )
+{
+  Toolkit::Control control = Toolkit::Control::DownCast( root );
+  if( control )
+  {
+    Internal::Control& controlImpl = GetImplementation( control );
+    Internal::Control::Impl& controlDataImpl = Internal::Control::Impl::Get( controlImpl );
+    LayoutItemPtr layout = controlDataImpl.GetLayout();
+
+    if( layout )
+    {
+      layout->Layout( left, top, right, bottom );
+    }
+  }
+  else
+  {
+    // Depth first descent through actor children
+    for( unsigned int i = 0, count = root.GetChildCount(); i < count; ++i )
+    {
+      Actor child = root.GetChildAt( i );
+      PerformLayout( child, left, top, right, bottom );
+    }
+  }
+}
+
+
+} // namespace Internal
+} // namespace Toolkit
+} // namespace Dali
diff --git a/dali-toolkit/internal/layouting/layout-controller-impl.h b/dali-toolkit/internal/layouting/layout-controller-impl.h
new file mode 100644 (file)
index 0000000..08db259
--- /dev/null
@@ -0,0 +1,101 @@
+#ifndef DALI_TOOLKIT_INTERNAL_LAYOUT_CONTROLLER_H
+#define DALI_TOOLKIT_INTERNAL_LAYOUT_CONTROLLER_H
+
+/*
+ * Copyright (c) 2018 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <dali/public-api/object/base-object.h>
+#include <dali/integration-api/core.h>
+#include <dali-toolkit/public-api/controls/control.h>
+#include <dali-toolkit/devel-api/layouting/layout-controller.h>
+#include <dali-toolkit/devel-api/layouting/layout-item-impl.h>
+#include <dali-toolkit/devel-api/layouting/layout-group-impl.h>
+
+namespace Dali
+{
+namespace Toolkit
+{
+namespace Internal
+{
+
+/**
+ * @brief Layout controller handles measurement and layout of all
+ * controls that utilize Layouts.
+ */
+class LayoutController : public Dali::BaseObject, public Integration::Processor
+{
+public:
+  /**
+   * Constructor
+   */
+  LayoutController();
+
+  /**
+   * Destructor
+   */
+  ~LayoutController();
+
+  /**
+   * Second stage initialization
+   */
+  void Initialize();
+
+  /**
+   * This marks the given layout and all its parents as dirty.
+   */
+  void RequestLayout( LayoutItem& layout );
+
+  /**
+   * Measures next level of layouts in the actor hierarchy.
+   */
+  void MeasureHierarchy( Actor root, MeasureSpec widthSpec, MeasureSpec heightSpec );
+
+  /**
+   * Perform layout of the hierarchy
+   */
+  void PerformLayout( Actor root, int left, int top, int right, int bottom );
+
+protected: // Implementation of Processor
+
+  /**
+   * @copydoc Dali::Integration::Processor::Process()
+   */
+  virtual void Process();
+
+private:
+  bool mLayoutRequested;
+};
+
+} // namespace Internal
+
+inline Internal::LayoutController& GetImpl( Dali::Toolkit::LayoutController& handle )
+{
+  DALI_ASSERT_ALWAYS(handle);
+  Dali::BaseObject& object = handle.GetBaseObject();
+  return static_cast<Internal::LayoutController&>(object);
+}
+
+inline const Internal::LayoutController& GetImpl( const Dali::Toolkit::LayoutController& handle )
+{
+  DALI_ASSERT_ALWAYS(handle);
+  const Dali::BaseObject& object = handle.GetBaseObject();
+  return static_cast<const Internal::LayoutController&>(object);
+}
+
+} // namespace Toolkit
+} // namespace Dali
+
+#endif // DALI_TOOLKIT_INTERNAL_LAYOUT_CONTROLLER_H
diff --git a/dali-toolkit/internal/layouting/layout-group-data-impl.cpp b/dali-toolkit/internal/layouting/layout-group-data-impl.cpp
new file mode 100644 (file)
index 0000000..f1d7fea
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2018 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <dali-toolkit/devel-api/layouting/layout-group-impl.h>
+#include <dali-toolkit/internal/layouting/layout-group-data-impl.h>
+
+namespace Dali
+{
+namespace Toolkit
+{
+namespace Internal
+{
+
+LayoutGroup::Impl::Impl()
+: mChildren(),
+  mNextLayoutId(1)
+{
+}
+
+} // namespace Internal
+
+} // namespace Toolkit
+
+} // namespace Dali
diff --git a/dali-toolkit/internal/layouting/layout-group-data-impl.h b/dali-toolkit/internal/layouting/layout-group-data-impl.h
new file mode 100644 (file)
index 0000000..231cc09
--- /dev/null
@@ -0,0 +1,54 @@
+#ifndef DALI_TOOLKIT_INTERNAL_LAYOUT_GROUP_DATA_IMPL_H_H
+#define DALI_TOOLKIT_INTERNAL_LAYOUT_GROUP_DATA_IMPL_H_H
+
+/*
+ * Copyright (c) 2018 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <vector>
+
+#include <dali-toolkit/devel-api/layouting/layout-item-impl.h>
+#include <dali-toolkit/internal/layouting/layout-item-data-impl.h>
+#include <dali-toolkit/devel-api/layouting/layout-group-impl.h>
+
+namespace Dali
+{
+namespace Toolkit
+{
+namespace Internal
+{
+
+class LayoutGroup::Impl
+{
+public:
+  Impl();
+
+public:
+  struct ChildLayout
+  {
+    LayoutItemPtr child;
+    Toolkit::LayoutGroup::LayoutId layoutId;
+  };
+
+  std::vector<ChildLayout> mChildren;
+  Toolkit::LayoutGroup::LayoutId mNextLayoutId;
+};
+
+
+} // namespace Internal
+} // namespace Toolkit
+} // namespace Dali
+
+#endif //DALI_TOOLKIT_INTERNAL_LAYOUT_GROUP_DATA_IMPL_H_H
diff --git a/dali-toolkit/internal/layouting/layout-item-data-impl.cpp b/dali-toolkit/internal/layouting/layout-item-data-impl.cpp
new file mode 100644 (file)
index 0000000..d3b394d
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2018 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <dali-toolkit/internal/layouting/layout-item-data-impl.h>
+#include <dali-toolkit/devel-api/layouting/measured-size.h>
+
+namespace Dali
+{
+namespace Toolkit
+{
+namespace Internal
+{
+
+bool LayoutItem::Impl::sUseZeroUnspecifiedMeasureSpec = false;
+
+
+LayoutItem::Impl::Impl()
+: mOwner( nullptr ),
+  mLayoutParent( nullptr ),
+  mOldWidthMeasureSpec( 0u ),
+  mOldHeightMeasureSpec( 0u ),
+  mMinimumSize(),
+  mMeasuredWidth(0u),
+  mMeasuredHeight(0u),
+  mLeft( 0 ),
+  mRight( 0 ),
+  mTop( 0 ),
+  mBottom( 0 ),
+  mViewFlags( 0 ),
+  mPrivateFlags( 0 ),
+  mAnimated(false)
+{
+}
+
+} // namespace Internal
+} // namespace Toolkit
+} // namespace Dali
diff --git a/dali-toolkit/internal/layouting/layout-item-data-impl.h b/dali-toolkit/internal/layouting/layout-item-data-impl.h
new file mode 100644 (file)
index 0000000..3758460
--- /dev/null
@@ -0,0 +1,119 @@
+#ifndef DALI_TOOLKIT_INTERNAL_LAYOUTING_LAYOUT_BASE_DATA_IMPL_H_H
+#define DALI_TOOLKIT_INTERNAL_LAYOUTING_LAYOUT_BASE_DATA_IMPL_H_H
+
+/*
+ * Copyright (c) 2018 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <dali-toolkit/devel-api/layouting/layout-item-impl.h>
+#include <dali-toolkit/devel-api/layouting/layout-controller.h>
+#include <dali-toolkit/devel-api/layouting/layout-size.h>
+
+namespace Dali
+{
+namespace Toolkit
+{
+namespace Internal
+{
+class LayoutParent;
+
+
+class LayoutItem::Impl
+{
+public:
+  Impl();
+
+public:
+  BaseObject* mOwner; ///< Control or Visual that owns this layout. Raw pointer to prevent cyclic references
+  LayoutParent* mLayoutParent; ///< The containing layout parent.
+
+  MeasureSpec mOldWidthMeasureSpec;
+  MeasureSpec mOldHeightMeasureSpec;
+  LayoutSize mMinimumSize;
+
+  MeasuredSize mMeasuredWidth;
+  MeasuredSize mMeasuredHeight;
+
+  Extents mMargin; ///< Distances in pixels from the edges of this view to this view's parent.
+  Extents mPadding; ///< Distances in pixels from the edges of this view to this view's content.
+
+  LayoutLength mLeft;
+  LayoutLength mRight;
+  LayoutLength mTop;
+  LayoutLength mBottom;
+
+  /**
+   * This view is visible.
+   * Use with {@link #setVisibility} and <a href="#attr_android:visibility">{@code
+   * android:visibility}.
+   */
+  static const int VISIBLE = 0x00000000;
+
+  /**
+   * This view is invisible, but it still takes up space for layout purposes.
+   * Use with {@link #setVisibility} and <a href="#attr_android:visibility">{@code
+   * android:visibility}.
+   */
+  static const int INVISIBLE = 0x00000004;
+
+  /**
+   * This view is invisible, and it doesn't take any space for layout
+   * purposes. Use with {@link #setVisibility} and <a href="#attr_android:visibility">{@code
+   * android:visibility}.
+   */
+  static const int GONE = 0x00000008;
+
+  /**
+   * Mask for use with setFlags indicating bits used for visibility.
+   * {@hide}
+   */
+  static const int VISIBILITY_MASK = 0x0000000C;
+
+  static const int PRIVATE_FLAG_MEASURED_DIMENSION_SET        = 0x00000001;
+  static const int PRIVATE_FLAG_FORCE_LAYOUT                  = 0x00000002;
+  static const int PRIVATE_FLAG_LAYOUT_REQUIRED               = 0x00000004;
+  static const int PRIVATE_FLAG_IS_LAID_OUT                   = 0x00000008;
+  static const int PRIVATE_FLAG_MEASURE_NEEDED_BEFORE_LAYOUT  = 0x00000010; ///< Flag indicating that a call to measure() was skipped and should be done instead when layout() is invoked.
+  static const int PRIVATE_FLAG_HAS_BOUNDS                    = 0x00000020;
+
+  int mViewFlags;
+  int mPrivateFlags;
+
+  bool mAnimated;
+
+  inline void ClearPrivateFlag( int flag )
+  {
+    mPrivateFlags &= ~flag;
+  }
+
+  inline void SetPrivateFlag( int flag )
+  {
+    mPrivateFlags |= flag;
+  }
+
+  inline bool GetPrivateFlag( int flag )
+  {
+    return ( mPrivateFlags & flag ) != 0;
+  }
+
+  static bool sUseZeroUnspecifiedMeasureSpec;
+
+};
+
+} // namespace Internal
+} // namespace Toolkit
+} // namespace Dali
+
+#endif //DALI_TOOLKIT_INTERNAL_LAYOUTING_LAYOUT_BASE_DATA_IMPL_H_H
diff --git a/dali-toolkit/internal/layouting/vbox-layout-impl.cpp b/dali-toolkit/internal/layouting/vbox-layout-impl.cpp
new file mode 100644 (file)
index 0000000..56fb230
--- /dev/null
@@ -0,0 +1,261 @@
+/*
+ * Copyright (c) 2018 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//CLASS HEADER
+#include <dali-toolkit/internal/layouting/vbox-layout-impl.h>
+
+//EXTERNAL HEADERS
+//INTERNAL HEADERS
+#include <dali/integration-api/debug.h>
+#include <dali/public-api/common/extents.h>
+#include <dali/devel-api/actors/actor-devel.h>
+#include <dali/devel-api/object/handle-devel.h>
+#include <dali-toolkit/devel-api/layouting/layout-item.h>
+#include <dali-toolkit/public-api/controls/control-impl.h>
+#include <dali-toolkit/internal/controls/control/control-data-impl.h>
+
+
+#if defined(DEBUG_ENABLED)
+static Debug::Filter* gLogFilter = Debug::Filter::New( Debug::Concise, false, "LOG_LAYOUT" );
+#endif
+
+namespace Dali
+{
+namespace Toolkit
+{
+namespace Internal
+{
+
+VboxLayoutPtr VboxLayout::New()
+{
+  VboxLayoutPtr layout( new VboxLayout() );
+  return layout;
+}
+
+VboxLayout::VboxLayout()
+: LayoutGroup(),
+  mCellPadding( 0, 0 ),
+  mTotalLength( 0 )
+{
+}
+
+VboxLayout::~VboxLayout()
+{
+}
+
+void VboxLayout::DoInitialize()
+{
+}
+
+void VboxLayout::DoRegisterChildProperties( const std::string& containerType )
+{
+  auto typeInfo = Dali::TypeRegistry::Get().GetTypeInfo( containerType );
+  if( typeInfo )
+  {
+    Property::IndexContainer indices;
+    typeInfo.GetChildPropertyIndices( indices );
+
+    if( std::find( indices.Begin(), indices.End(), Toolkit::VboxLayout::ChildProperty::WEIGHT ) ==
+        indices.End() )
+    {
+      ChildPropertyRegistration( typeInfo.GetName(), "weight", Toolkit::VboxLayout::ChildProperty::WEIGHT, Property::FLOAT );
+    }
+  }
+}
+
+void VboxLayout::OnChildAdd( LayoutItem& child )
+{
+  auto owner = child.GetOwner();
+  owner.SetProperty( Toolkit::VboxLayout::ChildProperty::WEIGHT, 1.0f );
+}
+
+void VboxLayout::SetCellPadding( LayoutSize size )
+{
+  mCellPadding = size;
+}
+
+LayoutSize VboxLayout::GetCellPadding()
+{
+  return mCellPadding;
+}
+
+
+void VboxLayout::OnMeasure( MeasureSpec widthMeasureSpec, MeasureSpec heightMeasureSpec )
+{
+#if defined(DEBUG_ENABLED)
+  auto actor = Actor::DownCast(GetOwner());
+
+  std::ostringstream oss;
+  oss << "VboxLayout::OnMeasure  ";
+  if( actor )
+  {
+    oss << "Actor Id:" << actor.GetId() << " Name:" << actor.GetName() << "  ";
+  }
+  oss << "widthMeasureSpec:" << widthMeasureSpec << " heightMeasureSpec:" << heightMeasureSpec << std::endl;
+  DALI_LOG_INFO( gLogFilter, Debug::Concise, oss.str().c_str() );
+#endif
+
+  auto widthMode = widthMeasureSpec.GetMode();
+
+  bool matchWidth = false;
+  bool allFillParent = true;
+  LayoutLength maxWidth = 0;
+  LayoutLength alternativeMaxWidth = 0;
+
+  struct
+  {
+    MeasuredSize::State widthState;
+    MeasuredSize::State heightState;
+  } childState = { MeasuredSize::State::MEASURED_SIZE_OK, MeasuredSize::State::MEASURED_SIZE_OK };
+
+  // measure children, and determine if further resolution is required
+  for( unsigned int i=0; i<GetChildCount(); ++i )
+  {
+    auto childLayout = GetChildAt( i );
+    if( childLayout )
+    {
+      auto childOwner = childLayout->GetOwner();
+      auto desiredWidth = childOwner.GetProperty<int>( Toolkit::LayoutItem::ChildProperty::WIDTH_SPECIFICATION );
+
+      MeasureChildWithMargins( childLayout, widthMeasureSpec, 0, heightMeasureSpec, 0 );
+      auto childHeight = childLayout->GetMeasuredHeight();
+      auto childMargin = childOwner.GetProperty<Extents>( Toolkit::LayoutGroup::ChildProperty::MARGIN_SPECIFICATION );
+      auto length = childHeight + LayoutLength::IntType(childMargin.top + childMargin.bottom );
+
+      auto cellPadding = i<GetChildCount()-1 ? mCellPadding.height : 0;
+      auto totalLength = mTotalLength;
+      mTotalLength = std::max( totalLength, totalLength + length + cellPadding);
+
+      bool matchWidthLocally = false;
+      if( widthMode != MeasureSpec::Mode::EXACTLY && desiredWidth == Toolkit::ChildLayoutData::MATCH_PARENT )
+      {
+        // Will have to re-measure at least this child when we know exact height.
+        matchWidth = true;
+        matchWidthLocally = true;
+      }
+
+      auto marginWidth = LayoutLength( childMargin.start + childMargin.end );
+      auto childWidth = childLayout->GetMeasuredWidth() + marginWidth;
+
+      // was combineMeasuredStates()
+      if( childLayout->GetMeasuredWidthAndState().GetState() == MeasuredSize::State::MEASURED_SIZE_TOO_SMALL )
+      {
+        childState.widthState = MeasuredSize::State::MEASURED_SIZE_TOO_SMALL;
+      }
+      if( childLayout->GetMeasuredHeightAndState().GetState() == MeasuredSize::State::MEASURED_SIZE_TOO_SMALL )
+      {
+        childState.heightState = MeasuredSize::State::MEASURED_SIZE_TOO_SMALL;
+      }
+
+      maxWidth = std::max( maxWidth, childWidth );
+      allFillParent = ( allFillParent && desiredWidth == Toolkit::ChildLayoutData::MATCH_PARENT );
+      alternativeMaxWidth = std::max( alternativeMaxWidth, matchWidthLocally ? marginWidth : childWidth );
+    }
+  }
+
+  Extents padding = GetPadding();
+  mTotalLength += padding.top + padding.bottom;
+  auto heightSize = mTotalLength;
+  heightSize = std::max( heightSize, GetSuggestedMinimumHeight() );
+  MeasuredSize heightSizeAndState = ResolveSizeAndState( heightSize, heightMeasureSpec, MeasuredSize::State::MEASURED_SIZE_OK);
+  heightSize = heightSizeAndState.GetSize();
+
+  if( !allFillParent && widthMode != MeasureSpec::Mode::EXACTLY )
+  {
+    maxWidth = alternativeMaxWidth;
+  }
+  maxWidth += padding.start + padding.end;
+  maxWidth = std::max( maxWidth, GetSuggestedMinimumWidth() );
+
+  heightSizeAndState.SetState( childState.heightState );
+
+  SetMeasuredDimensions( ResolveSizeAndState( maxWidth, widthMeasureSpec, childState.widthState ),
+                         heightSizeAndState );
+
+  if( matchWidth )
+  {
+    ForceUniformWidth( GetChildCount(), heightMeasureSpec );
+  }
+}
+
+void VboxLayout::ForceUniformWidth( int count, MeasureSpec heightMeasureSpec )
+{
+  // Pretend that the linear layout has an exact size. This is the measured height of
+  // ourselves. The measured height should be the max height of the children, changed
+  // to accommodate the heightMeasureSpec from the parent
+  auto uniformMeasureSpec = MeasureSpec( GetMeasuredWidth(), MeasureSpec::Mode::EXACTLY );
+  for (int i = 0; i < count; ++i)
+  {
+    LayoutItemPtr childLayout = GetChildAt(i);
+    if( childLayout != nullptr )
+    {
+      auto childOwner = childLayout->GetOwner();
+      auto desiredWidth = childOwner.GetProperty<int>( Toolkit::LayoutItem::ChildProperty::WIDTH_SPECIFICATION );
+      auto desiredHeight = childOwner.GetProperty<int>( Toolkit::LayoutItem::ChildProperty::HEIGHT_SPECIFICATION );
+
+      if( desiredWidth == Toolkit::ChildLayoutData::MATCH_PARENT )
+      {
+        // Temporarily force children to reuse their old measured height
+        int oldHeight = desiredHeight;
+        childOwner.SetProperty( Toolkit::LayoutItem::ChildProperty::HEIGHT_SPECIFICATION, childLayout->GetMeasuredHeight().mValue );
+
+        // Remeasure with new dimensions
+        MeasureChildWithMargins( childLayout, uniformMeasureSpec, 0, heightMeasureSpec, 0 );
+
+        childOwner.SetProperty( Toolkit::LayoutItem::ChildProperty::HEIGHT_SPECIFICATION, oldHeight );
+      }
+    }
+  }
+}
+
+void VboxLayout::OnLayout( bool changed, LayoutLength left, LayoutLength top, LayoutLength right, LayoutLength bottom )
+{
+  auto owner = GetOwner();
+  Extents padding = GetPadding();
+
+  LayoutLength childTop( 0 );
+  LayoutLength childLeft( padding.start );
+
+  // Where bottom of child should go
+  auto width = right - left;
+
+  // Space available for child
+  auto childSpace = width - padding.start - padding.end;
+  auto count = GetChildCount();
+
+  for( unsigned int childIndex = 0; childIndex < count; childIndex++)
+  {
+    LayoutItemPtr childLayout = GetChildAt( childIndex );
+    if( childLayout != nullptr )
+    {
+      auto childWidth = childLayout->GetMeasuredWidth();
+      auto childHeight = childLayout->GetMeasuredHeight();
+
+      auto childOwner = childLayout->GetOwner();
+      auto childMargin = childOwner.GetProperty<Extents>( Toolkit::LayoutGroup::ChildProperty::MARGIN_SPECIFICATION );
+
+      childTop += childMargin.top;
+      childLeft = ( childSpace - childWidth ) / 2 + childMargin.start - childMargin.end;
+
+      childLayout->Layout( childLeft, childTop, childLeft + childWidth, childTop + childHeight );
+      childTop += childHeight + childMargin.bottom + mCellPadding.height;
+    }
+  }
+}
+
+} // namespace Internal
+} // namespace Toolkit
+} // namespace Dali
diff --git a/dali-toolkit/internal/layouting/vbox-layout-impl.h b/dali-toolkit/internal/layouting/vbox-layout-impl.h
new file mode 100644 (file)
index 0000000..fb88095
--- /dev/null
@@ -0,0 +1,123 @@
+#ifndef DALI_TOOLKIT_INTERNAL_LAYOUTING_VBOX_LAYOUT_H
+#define DALI_TOOLKIT_INTERNAL_LAYOUTING_VBOX_LAYOUT_H
+
+/*
+ * Copyright (c) 2018 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <dali/public-api/common/intrusive-ptr.h>
+#include <dali/public-api/object/base-object.h>
+#include <dali-toolkit/devel-api/layouting/layout-group-impl.h>
+#include <dali-toolkit/devel-api/layouting/vbox-layout.h>
+
+namespace Dali
+{
+namespace Toolkit
+{
+namespace Internal
+{
+
+class VboxLayout;
+using VboxLayoutPtr = IntrusivePtr<VboxLayout>;
+
+class VboxLayout final : public LayoutGroup
+{
+public:
+  static VboxLayoutPtr New();
+
+public:
+
+  /**
+   * Set the inter-cell padding
+   * @param[in] size The size of the inter-cell padding
+   */
+  void SetCellPadding( LayoutSize size );
+
+  /**
+   * Get the inter-cell padding
+   * @return The size of the inter-cell padding
+   */
+  LayoutSize GetCellPadding();
+
+protected:
+  /**
+   * Constructor
+   */
+  VboxLayout();
+
+  /**
+   * Virtual destructor
+   */
+  virtual ~VboxLayout();
+
+  /**
+   * @copydoc LayoutItem::DoInitialize
+   */
+  virtual void DoInitialize() override;
+
+  /**
+   * @copydoc LayoutItem::DoRegisterChildProperties()
+   */
+  virtual void DoRegisterChildProperties( const std::string& containerType ) override;
+
+  /**
+   * @copydoc LayoutItem::OnChildAdd
+   */
+  virtual void OnChildAdd( LayoutItem& child ) override;
+
+  /**
+   * @copydoc LayoutItem::OnMeasure
+   */
+  virtual void OnMeasure( MeasureSpec widthMeasureSpec, MeasureSpec heightMeasureSpec ) override;
+
+  /**
+   * @copydoc LayoutItem::OnLayout
+   */
+  virtual void OnLayout( bool changed, LayoutLength l, LayoutLength t, LayoutLength r, LayoutLength b ) override;
+
+private:
+  VboxLayout( const VboxLayout& other ) = delete;
+  VboxLayout& operator=( const VboxLayout& other ) = delete;
+
+  /**
+   * Apply a uniform width to the children
+   */
+  void ForceUniformWidth( int count, MeasureSpec heightMeasureSpec );
+
+private:
+  LayoutSize mCellPadding;
+  LayoutLength mTotalLength;
+};
+
+} // namespace Internal
+
+inline Internal::VboxLayout& GetImplementation( Dali::Toolkit::VboxLayout& handle )
+{
+  DALI_ASSERT_ALWAYS( handle && "VboxLayout handle is empty" );
+  BaseObject& object = handle.GetBaseObject();
+  return static_cast<Internal::VboxLayout&>( object );
+}
+
+inline const Internal::VboxLayout& GetImplementation( const Dali::Toolkit::VboxLayout& handle )
+{
+  DALI_ASSERT_ALWAYS( handle && "VboxLayout handle is empty" );
+  const BaseObject& object = handle.GetBaseObject();
+  return static_cast<const Internal::VboxLayout&>( object );
+}
+
+} // namespace Toolkit
+} // namespace Dali
+
+#endif // DALI_TOOLKIT_INTERNAL_LAYOUTING_VBOX_LAYOUT_H
index a8623f0..1bf9944 100644 (file)
@@ -2,7 +2,7 @@
 #define DALI_TOOLKIT_INTERNAL_TEXTURE_UPLOAD_OBSERVER_H
 
 /*
- * Copyright (c) 2017 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2018 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -18,7 +18,7 @@
  *
  */
 
-#include <dali/public-api/common/dali-common.h>
+#include <dali-toolkit/public-api/dali-toolkit-common.h>
 #include <dali/public-api/signals/dali-signal.h>
 
 namespace Dali
index 90dcd32..0e7f396 100644 (file)
@@ -19,7 +19,7 @@
 #include <dali-toolkit/internal/visuals/visual-base-data-impl.h>
 
 // EXTERNAL INCLUDES
-#include <dali/public-api/common/dali-common.h>
+#include <dali-toolkit/public-api/dali-toolkit-common.h>
 #include <dali/devel-api/scripting/enum-helper.h>
 #include <dali/devel-api/scripting/scripting.h>
 #include <dali/integration-api/debug.h>
index 064b13d..8d2158f 100755 (executable)
@@ -19,7 +19,7 @@
 #include "visual-base-impl.h"
 
 // EXTERNAL HEADER
-#include <dali/public-api/common/dali-common.h>
+#include <dali-toolkit/public-api/dali-toolkit-common.h>
 #include <dali/devel-api/object/handle-devel.h>
 #include <dali/devel-api/scripting/enum-helper.h>
 #include <dali/devel-api/rendering/renderer-devel.h>
@@ -699,17 +699,20 @@ void Visual::Base::SetupBlendMode( Animation& transition, bool isInitialOpaque,
   // turned off after the animation ends if the final value is opaque
   if( ! isInitialOpaque || mImpl->mMixColor.a < 1.0f )
   {
-    mImpl->mRenderer.SetProperty( Renderer::Property::BLEND_MODE, BlendMode::ON );
-
-    if( animating == true && mImpl->mMixColor.a >= 1.0f )
+    if( mImpl->mRenderer )
     {
-      // When it becomes opaque, set the blend mode back to automatically
-      if( ! mImpl->mBlendSlotDelegate )
+      mImpl->mRenderer.SetProperty( Renderer::Property::BLEND_MODE, BlendMode::ON );
+
+      if( animating == true && mImpl->mMixColor.a >= 1.0f )
       {
-        mImpl->mBlendSlotDelegate = new SlotDelegate<Visual::Base>(this);
+        // When it becomes opaque, set the blend mode back to automatically
+        if( ! mImpl->mBlendSlotDelegate )
+        {
+          mImpl->mBlendSlotDelegate = new SlotDelegate<Visual::Base>(this);
+        }
+        transition.FinishedSignal().Connect( *(mImpl->mBlendSlotDelegate),
+                                             &Visual::Base::OnMixColorFinished );
       }
-      transition.FinishedSignal().Connect( *(mImpl->mBlendSlotDelegate),
-                                           &Visual::Base::OnMixColorFinished );
     }
   }
 }
index 00c397d..4839551 100644 (file)
@@ -217,6 +217,9 @@ public:
    * If the visual isn't staged (i.e. it doesn't have a renderer),
    * then this will not add an animation.
    *
+   * If the animator is valid and the transition handle is empty - it will
+   * be created.
+   *
    * @param[in] transition The animation to create or attach to
    * @param[in] animator The animation parameters of the property.
    */
old mode 100644 (file)
new mode 100755 (executable)
index fe9b11e..e3903e3
@@ -2,7 +2,7 @@
 #define __DALI_TOOLKIT_ACCESSIBILITY_MANAGER_H__
 
 /*
- * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2018 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -21,6 +21,9 @@
 // EXTERNAL INCLUDES
 #include <dali/public-api/actors/actor.h>
 
+// INTERNAL INCLUDES
+#include <dali-toolkit/public-api/dali-toolkit-common.h>
+
 namespace Dali
 {
 
@@ -55,7 +58,7 @@ class AccessibilityManager;
  * | focusedActorActivated | @ref FocusedActorActivatedSignal() |
  * @SINCE_1_0.0
  */
-class DALI_IMPORT_API AccessibilityManager : public BaseHandle
+class DALI_TOOLKIT_API AccessibilityManager : public BaseHandle
 {
 public:
 
index 48e2c8e..039e6c6 100644 (file)
@@ -2,7 +2,7 @@
 #define __DALI_ALIGNMENT_H__
 
 /*
- * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2018 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -46,7 +46,7 @@ class Alignment;
  * All actors added to an alignment are going to be set with the same anchor point and parent origin. And if the scaling property is set to a value
  * different than ScaleNone, constraints as well.
  */
-class DALI_IMPORT_API Alignment : public Control
+class DALI_TOOLKIT_API Alignment : public Control
 {
 public:
   /**
index d9fc769..848644f 100644 (file)
@@ -2,7 +2,7 @@
 #define __DALI_TOOLKIT_BUTTON_H__
 
 /*
- * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2018 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -85,7 +85,7 @@ class Button;
  * | buttonClick      | Doesn't have attributes | Simulates a button click. See @ref DoAction() |
  * @SINCE_1_0.0
  */
-class DALI_IMPORT_API Button : public Control
+class DALI_TOOLKIT_API Button : public Control
 {
 public:
 
index 301a810..7e83432 100644 (file)
@@ -2,7 +2,7 @@
 #define __DALI_TOOLKIT_CHECK_BOX_BUTTON_H__
 
 /*
- * Copyright (c) 2017 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2018 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -78,7 +78,7 @@ class CheckBoxButton;
  * @endcode
  * @SINCE_1_0.0
  */
-class DALI_IMPORT_API CheckBoxButton : public Button
+class DALI_TOOLKIT_API CheckBoxButton : public Button
 {
 public:
 
index f3cbea8..13784dd 100644 (file)
@@ -2,7 +2,7 @@
 #define __DALI_TOOLKIT_PUSH_BUTTON_H__
 
 /*
- * Copyright (c) 2017 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2018 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -85,7 +85,7 @@ class PushButton;
  * See Button for more details on signals and modifying appearance via properties.
  * @SINCE_1_0.0
  */
-class DALI_IMPORT_API PushButton : public Button
+class DALI_TOOLKIT_API PushButton : public Button
 {
 public:
 
index 58b8604..8d4b4cb 100644 (file)
@@ -2,7 +2,7 @@
 #define __DALI_TOOLKIT_RADIO_BUTTON_H__
 
 /*
- * Copyright (c) 2017 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2018 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -84,7 +84,7 @@ class RadioButton;
  * @endcode
  * @SINCE_1_0.0
  */
-class DALI_IMPORT_API RadioButton: public Button
+class DALI_TOOLKIT_API RadioButton: public Button
 {
  public:
   /**
index 9a1e560..b7b2bd4 100644 (file)
@@ -2,7 +2,7 @@
 #define DALI_TOOLKIT_CONTROL_IMPL_H
 
 /*
- * Copyright (c) 2017 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2018 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -53,7 +53,7 @@ namespace Internal
  * be disconnected automatically when the control is destroyed.
  * @SINCE_1_0.0
  */
-class DALI_IMPORT_API Control : public CustomActorImpl, public ConnectionTrackerInterface
+class DALI_TOOLKIT_API Control : public CustomActorImpl, public ConnectionTrackerInterface
 {
 public:
 
@@ -701,7 +701,7 @@ private:
  * @return Implementation
  * @pre handle is initialized and points to a control
  */
-DALI_IMPORT_API Internal::Control& GetImplementation( Dali::Toolkit::Control& handle );
+DALI_TOOLKIT_API Internal::Control& GetImplementation( Dali::Toolkit::Control& handle );
 
 /**
  * @brief Gets implementation from the handle.
@@ -711,7 +711,7 @@ DALI_IMPORT_API Internal::Control& GetImplementation( Dali::Toolkit::Control& ha
  * @return Implementation
  * @pre Handle is initialized and points to a control.
  */
-DALI_IMPORT_API const Internal::Control& GetImplementation( const Dali::Toolkit::Control& handle );
+DALI_TOOLKIT_API const Internal::Control& GetImplementation( const Dali::Toolkit::Control& handle );
 
 } // namespace Internal
 
index 8e522a2..f418372 100644 (file)
@@ -2,7 +2,7 @@
 #define __DALI_TOOLKIT_CONTROL_H__
 
 /*
- * Copyright (c) 2017 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2018 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -20,7 +20,7 @@
 
 // EXTERNAL INCLUDES
 #include <dali/public-api/actors/custom-actor.h>
-#include <dali/public-api/common/dali-common.h>
+#include <dali-toolkit/public-api/dali-toolkit-common.h>
 #include <dali/public-api/events/long-press-gesture-detector.h>
 #include <dali/public-api/events/pan-gesture-detector.h>
 #include <dali/public-api/events/pinch-gesture-detector.h>
@@ -72,7 +72,7 @@ class Control;
  * |------------------------|----------------------------------------------------|
  * | accessibilityActivated | %OnAccessibilityActivated()                        |
  */
-class DALI_IMPORT_API Control : public CustomActor
+class DALI_TOOLKIT_API Control : public CustomActor
 {
 public:
 
index 94ef744..ac564b9 100644 (file)
@@ -2,7 +2,7 @@
 #define __DALI_TOOLKIT_FLEX_CONTAINER_H__
 
 /*
- * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2018 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -101,7 +101,7 @@ class FlexContainer;
  * @SINCE_1_1.35
  */
 
-class DALI_IMPORT_API FlexContainer : public Control
+class DALI_TOOLKIT_API FlexContainer : public Control
 {
 public:
 
index 7c99a5f..7a8fc9e 100644 (file)
@@ -2,7 +2,7 @@
 #define __DALI_TOOLKIT_IMAGE_VIEW_H__
 
 /*
- * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2018 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -73,7 +73,7 @@ class ImageView;
  * @SINCE_1_0.0
  *
  */
-class DALI_IMPORT_API ImageView : public Control
+class DALI_TOOLKIT_API ImageView : public Control
 {
 public:
 
index 9ef0d46..60d6d4b 100755 (executable)
@@ -2,7 +2,7 @@
 #define __DALI_TOOLKIT_MODEL3D_VIEW_H__
 
 /*
- * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2018 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -45,7 +45,7 @@ class Model3dView;
  *
  * @SINCE_1_1.4
  */
-class DALI_IMPORT_API Model3dView : public Control
+class DALI_TOOLKIT_API Model3dView : public Control
 {
 public:
 
index ed4ceb2..a7b87c2 100644 (file)
@@ -2,7 +2,7 @@
 #define DALI_TOOLKIT_PROGRESS_BAR_H
 
 /*
- * Copyright (c) 2017 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2018 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -47,7 +47,7 @@ class ProgressBar;
  * @SINCE_1_2.60
  */
 
-class DALI_IMPORT_API ProgressBar : public Control
+class DALI_TOOLKIT_API ProgressBar : public Control
 {
 public:
 
index 2a9df0d..2285e68 100755 (executable)
@@ -2,7 +2,7 @@
 #define __DALI_TOOLKIT_SCROLL_BAR_H__
 
 /*
- * Copyright (c) 2017 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2018 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -49,7 +49,7 @@ class ScrollBar;
  * | scrollPositionIntervalReached | @ref ScrollPositionIntervalReachedSignal() |
  * @SINCE_1_0.0
  */
-class DALI_IMPORT_API ScrollBar : public Control
+class DALI_TOOLKIT_API ScrollBar : public Control
 {
 public:
 
index 8a880ac..04bc8e6 100644 (file)
@@ -2,7 +2,7 @@
 #define __DALI_TOOLKIT_DEFAULT_ITEM_LAYOUT_H__
 
 /*
- * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2018 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -57,7 +57,7 @@ enum Type
  * @param[in] type The type of layout required
  * @return An ItemLayoutPtr to the newly created layout
  */
-DALI_IMPORT_API ItemLayoutPtr New( Type type );
+DALI_TOOLKIT_API ItemLayoutPtr New( Type type );
 
 } // namespace DefaultItemLayout
 
index db4825a..69fe4aa 100644 (file)
@@ -2,7 +2,7 @@
 #define __DALI_TOOLKIT_ITEM_FACTORY_H__
 
 /*
- * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2018 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -21,6 +21,9 @@
 // EXTERNAL INCLUDES
 #include <dali/public-api/actors/actor.h>
 
+// INTERNAL INCLUDES
+#include <dali-toolkit/public-api/dali-toolkit-common.h>
+
 namespace Dali
 {
 
@@ -47,7 +50,7 @@ public:
    * @brief Virtual destructor.
    * @SINCE_1_0.0
    */
-  DALI_EXPORT_API virtual ~ItemFactory() {};
+  DALI_TOOLKIT_API virtual ~ItemFactory() {};
 
   /**
    * @brief Queries the number of items available from the factory.
index e81c787..2ffcdcc 100755 (executable)
@@ -2,7 +2,7 @@
 #define __DALI_TOOLKIT_ITEM_LAYOUT_H__
 
 /*
- * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2018 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -138,7 +138,7 @@ struct ItemRange
  * Whilst scrolling, the layout provides a range of items that are within a layout-area (3D bounding volume).
  * @SINCE_1_0.0
  */
-class DALI_IMPORT_API ItemLayout : public RefObject
+class DALI_TOOLKIT_API ItemLayout : public RefObject
 {
 public:
 
@@ -148,7 +148,7 @@ public:
    * @brief Virtual destructor.
    * @SINCE_1_0.0
    */
-  DALI_IMPORT_API virtual ~ItemLayout();
+  virtual ~ItemLayout();
 
   /**
    * @brief Set the orientation of the layout.
@@ -156,7 +156,7 @@ public:
    * @SINCE_1_0.0
    * @param[in] orientation The orientation of the layout.
    */
-  DALI_IMPORT_API void SetOrientation(ControlOrientation::Type orientation);
+  void SetOrientation(ControlOrientation::Type orientation);
 
   /**
    * @brief Query the orientation of the layout.
@@ -164,7 +164,7 @@ public:
    * @SINCE_1_0.0
    * @return the orientation of the layout.
    */
-  DALI_IMPORT_API ControlOrientation::Type GetOrientation() const;
+  ControlOrientation::Type GetOrientation() const;
 
   /**
    * @brief Apply the layout Properties.
@@ -192,7 +192,7 @@ public:
    * @note layout-position is not provided as a parameter, since applying size constraints is not recommended.
    * Animating to target-sizes is preferable, since this allows controls to perform layouting without constraints.
    */
-  DALI_IMPORT_API void GetItemSize( unsigned int itemId, const Vector3& layoutSize, Vector3& itemSize ) const;
+  void GetItemSize( unsigned int itemId, const Vector3& layoutSize, Vector3& itemSize ) const;
 
   /**
    * @brief Overrides the default size for the layout.
@@ -200,7 +200,7 @@ public:
    * @SINCE_1_0.0
    * @param[in] itemSize The size of each item.
    */
-  DALI_IMPORT_API void SetItemSize( const Vector3& itemSize );
+  void SetItemSize( const Vector3& itemSize );
 
   /**
    * @brief Query the minimum valid layout position; this is a negative value.
@@ -261,7 +261,7 @@ public:
    * @param[in] layoutSize the current size of the item view instance
    * @return The layout position
    */
-  DALI_IMPORT_API virtual float GetClosestOnScreenLayoutPosition(int itemID, float currentLayoutPosition, const Vector3& layoutSize);
+  virtual float GetClosestOnScreenLayoutPosition(int itemID, float currentLayoutPosition, const Vector3& layoutSize);
 
   /**
    * @brief Query the number of items that should be reserved, for scrolling purposes.
@@ -340,7 +340,7 @@ public:
    * @param[in] loopEnabled Whether the KeyboardFocusManager is set to wrap around between first and last item
    * @return The next item ID.
    */
-  DALI_IMPORT_API virtual int GetNextFocusItemID(int itemID, int maxItems, Dali::Toolkit::Control::KeyboardFocus::Direction direction, bool loopEnabled);
+  virtual int GetNextFocusItemID(int itemID, int maxItems, Dali::Toolkit::Control::KeyboardFocus::Direction direction, bool loopEnabled);
 
   /**
    * @brief Query the flick speed factor of the layout while swipping.
@@ -355,7 +355,7 @@ public:
    * @SINCE_1_0.0
    * @return The scroll speed factor of the layout.
    */
-  DALI_IMPORT_API virtual float GetFlickSpeedFactor() const;
+  virtual float GetFlickSpeedFactor() const;
 
   /**
    * @brief Applies constraints defined by the layout to an actor.
@@ -365,7 +365,7 @@ public:
    * @param[in] layoutSize The current size of the item view instance.
    * @param[in] itemViewActor The item view instance which requests the application of constraints.
    */
-  DALI_IMPORT_API virtual void ApplyConstraints( Actor& actor, const int itemId, const Vector3& layoutSize, const Actor& itemViewActor ) = 0;
+  virtual void ApplyConstraints( Actor& actor, const int itemId, const Vector3& layoutSize, const Actor& itemViewActor ) = 0;
 
   /**
    * @brief Gets the position of a given item
@@ -376,7 +376,7 @@ public:
    * @param[in] layoutSize The current size of the item view instance
    * @return The item position (x,y,z)
    */
-  DALI_IMPORT_API virtual Vector3 GetItemPosition(int itemID, float currentLayoutPosition, const Vector3& layoutSize) const = 0;
+  virtual Vector3 GetItemPosition(int itemID, float currentLayoutPosition, const Vector3& layoutSize) const = 0;
 
   /**
    * @brief Retrieve the extension for this layout.
@@ -395,7 +395,7 @@ protected:
    * @brief Create a new ItemLayout; Only derived versions are instantiatable.
    * @SINCE_1_0.0
    */
-  DALI_IMPORT_API ItemLayout();
+  ItemLayout();
 
 private:
 
index 191ef46..b2e99f5 100755 (executable)
@@ -2,7 +2,7 @@
 #define __DALI_TOOLKIT_ITEM_VIEW_H__
 
 /*
- * Copyright (c) 2017 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2018 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -64,7 +64,7 @@ typedef IntrusivePtr<ItemLayout> ItemLayoutPtr;
  * @SINCE_1_1.33
  */
 
-class DALI_IMPORT_API ItemView : public Scrollable
+class DALI_TOOLKIT_API ItemView : public Scrollable
 {
 public:
 
old mode 100644 (file)
new mode 100755 (executable)
index 2e2c2b2..0805ba6
@@ -2,7 +2,7 @@
 #define __DALI_TOOLKIT_SCROLL_VIEW_CONSTRAINTS_H__
 
 /*
- * Copyright (c) 2017 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2018 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -21,6 +21,9 @@
 // EXTERNAL INCLUDES
 #include <dali/public-api/animation/constraint.h>
 
+// INTERNAL INCLUDES
+#include <dali-toolkit/public-api/dali-toolkit-common.h>
+
 namespace Dali
 {
 
@@ -49,7 +52,7 @@ namespace Toolkit
  * @param[in] current Current position
  * @param[in] inputs The position input that Actor will move
  */
-DALI_IMPORT_API void MoveActorConstraint( Vector3& current, const PropertyInputContainer& inputs );
+DALI_TOOLKIT_API void MoveActorConstraint( Vector3& current, const PropertyInputContainer& inputs );
 
 /**
  * @brief Wraps an Actor's position in accordance with the min/max bounds of domain.
@@ -58,7 +61,7 @@ DALI_IMPORT_API void MoveActorConstraint( Vector3& current, const PropertyInputC
  * @param[in] position Position to be wrapped
  * @param[in] inputs The input that Actor's position will be wrapped
  */
-DALI_IMPORT_API void WrapActorConstraint( Vector3& position, const PropertyInputContainer& inputs );
+DALI_TOOLKIT_API void WrapActorConstraint( Vector3& position, const PropertyInputContainer& inputs );
 
 /**
  * @}
old mode 100644 (file)
new mode 100755 (executable)
index 049e2ab..639ae75
@@ -2,7 +2,7 @@
 #define __DALI_TOOLKIT_SCROLL_VIEW_EFFECT_H__
 
 /*
- * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2018 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -21,6 +21,9 @@
 // EXTERNAL INCLUDES
 #include <dali/public-api/object/base-handle.h>
 
+// INTERNAL INCLUDES
+#include <dali-toolkit/public-api/dali-toolkit-common.h>
+
 namespace Dali
 {
 
@@ -55,7 +58,7 @@ class ScrollViewEffect;
  * properties as inputs.
  * @SINCE_1_0.0
  */
-class DALI_IMPORT_API ScrollViewEffect : public Dali::BaseHandle
+class DALI_TOOLKIT_API ScrollViewEffect : public Dali::BaseHandle
 {
 
 public:
old mode 100644 (file)
new mode 100755 (executable)
index dc23694..e18eff4
@@ -2,7 +2,7 @@
 #define __DALI_TOOLKIT_SCROLL_VIEW_PAGE_PATH_EFFECT_H__
 
 /*
- * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2018 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -21,6 +21,9 @@
 // INTERNAL INCLUDES
 #include <dali-toolkit/public-api/controls/scrollable/scroll-view/scroll-view-effect.h>
 
+// INTERNAL INCLUDES
+#include <dali-toolkit/public-api/dali-toolkit-common.h>
+
 namespace Dali
 {
 
@@ -62,7 +65,7 @@ class ScrollViewPagePathEffect;
  * not implemented.
  * @SINCE_1_0.0
  */
-class DALI_IMPORT_API ScrollViewPagePathEffect : public ScrollViewEffect
+class DALI_TOOLKIT_API ScrollViewPagePathEffect : public ScrollViewEffect
 {
 
 public:
index 594e6da..4bed510 100755 (executable)
@@ -2,7 +2,7 @@
 #define __DALI_TOOLKIT_SCROLL_VIEW_H__
 
 /*
- * Copyright (c) 2017 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2018 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -85,7 +85,7 @@ enum DirectionBias
  * @brief Used for specifying minimum/maximum extents of a ruler.
  * @SINCE_1_0.0
  */
-class DALI_IMPORT_API RulerDomain
+class DALI_TOOLKIT_API RulerDomain
 {
 public:
 
@@ -154,7 +154,7 @@ class RulerExtension;
  * where their snap points are and their domain.
  * @SINCE_1_0.0
  */
-class DALI_IMPORT_API Ruler : public RefObject
+class DALI_TOOLKIT_API Ruler : public RefObject
 {
 public:
   /**
@@ -372,7 +372,7 @@ typedef IntrusivePtr<Ruler> RulerPtr; ///< Pointer to Dali::Toolkit::Ruler objec
  * @brief Concrete implementation of Ruler that has no snapping and has one single page.
  * @SINCE_1_0.0
  */
-class DALI_IMPORT_API DefaultRuler : public Ruler
+class DALI_TOOLKIT_API DefaultRuler : public Ruler
 {
 public:
   /**
@@ -406,7 +406,7 @@ public:
  * @brief Concrete implementation of Ruler that has fixed snapping.
  * @SINCE_1_0.0
  */
-class DALI_IMPORT_API FixedRuler : public Ruler
+class DALI_TOOLKIT_API FixedRuler : public Ruler
 {
 public:
   /**
@@ -454,7 +454,7 @@ class ScrollView;
  * | snap-started      | @ref SnapStartedSignal()   |
  * @SINCE_1_0.0
  */
-class DALI_IMPORT_API ScrollView : public Scrollable
+class DALI_TOOLKIT_API ScrollView : public Scrollable
 {
 
 public:
index 44f1b26..b369321 100644 (file)
@@ -2,7 +2,7 @@
 #define __DALI_TOOLKIT_SCROLLABLE_H__
 
 /*
- * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2018 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -50,7 +50,7 @@ class Scrollable;
  * | scrollUpdated    | @ref ScrollUpdatedSignal()   |
  * @SINCE_1_0.0
  */
-class DALI_IMPORT_API Scrollable : public Control
+class DALI_TOOLKIT_API Scrollable : public Control
 {
 public:
 
index 83e2b5c..e2c529e 100644 (file)
@@ -2,7 +2,7 @@
 #define __DALI_TOOLKIT_SLIDER_H__
 
 /*
- * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2018 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -47,7 +47,7 @@ class Slider;
  * | slidingFinished   | @ref SlidingFinishedSignal()  |
  * @SINCE_1_1.39
  */
-class DALI_IMPORT_API Slider : public Control
+class DALI_TOOLKIT_API Slider : public Control
 {
 public:
 
index 9674dc9..61da392 100644 (file)
@@ -2,7 +2,7 @@
 #define __DALI_TOOLKIT_TABLE_VIEW_H__
 
 /*
- * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2018 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -83,7 +83,7 @@ class TableView;
  * @endcode
  * @SINCE_1_0.0
  */
-class DALI_IMPORT_API TableView : public Control
+class DALI_TOOLKIT_API TableView : public Control
 {
 public:
 
index f633f45..5260ffe 100644 (file)
@@ -2,7 +2,7 @@
 #define __DALI_TOOLKIT_TEXT_EDITOR_H__
 
 /*
- * Copyright (c) 2017 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2018 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -46,7 +46,7 @@ class TextEditor;
  * | inputStyleChanged    | @ref InputStyleChangedSignal() | @SINCE_1_2_2       |
  *
  */
-class DALI_IMPORT_API TextEditor : public Control
+class DALI_TOOLKIT_API TextEditor : public Control
 {
 public:
 
index 7f7fd86..8940fe8 100644 (file)
@@ -2,7 +2,7 @@
 #define __DALI_TOOLKIT_TEXT_FIELD_H__
 
 /*
- * Copyright (c) 2017 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2018 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -46,7 +46,7 @@ class TextField;
  * | maxLengthReached     | @ref MaxLengthReachedSignal()  | @SINCE_1_0.0       |
  * | inputStyleChanged    | @ref InputStyleChangedSignal() | @SINCE_1_2_2       |
  */
-class DALI_IMPORT_API TextField : public Control
+class DALI_TOOLKIT_API TextField : public Control
 {
 public:
 
index 13a9738..be95d30 100644 (file)
@@ -2,7 +2,7 @@
 #define __DALI_TOOLKIT_TEXT_LABEL_H__
 
 /*
- * Copyright (c) 2017 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2018 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -63,7 +63,7 @@ class TextLabel;
  *
  * @SINCE_1_0.0
  */
-class DALI_IMPORT_API TextLabel : public Control
+class DALI_TOOLKIT_API TextLabel : public Control
 {
 public:
 
index 85fbd8d..87ade91 100755 (executable)
@@ -2,7 +2,7 @@
 #define __DALI_TOOLKIT_VIDEO_VIEW_H__
 
 /*
- * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2018 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -59,7 +59,7 @@ namespace Internal DALI_INTERNAL
  * @SINCE_1_1.38
  *
  */
-class DALI_IMPORT_API VideoView: public Control
+class DALI_TOOLKIT_API VideoView: public Control
 {
 public:
 
diff --git a/dali-toolkit/public-api/dali-toolkit-common.h b/dali-toolkit/public-api/dali-toolkit-common.h
new file mode 100755 (executable)
index 0000000..56f3927
--- /dev/null
@@ -0,0 +1,45 @@
+#ifndef DALI_TOOLKIT_COMMON_H
+#define DALI_TOOLKIT_COMMON_H
+
+/*
+ * Copyright (c) 2018 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// EXTERNAL INCLUDES
+#include <dali/public-api/dali-adaptor-common.h>
+
+/*
+ * Definitions for shared library support.
+ *
+ * If a library is configured with --enable-exportall or --enable-debug
+ * then HIDE_DALI_INTERNALS is not defined, and nothing is hidden.
+ * If it is configured without these options (the default), then HIDE_INTERNALS
+ * is defined when building the library, visibility is automatically hidden, and the explicit
+ * defines below come into use.
+ * When building a library that uses DALI, HIDE_DALI_INTERNALS.
+ */
+#if __GNUC__ >= 4
+#  ifndef HIDE_DALI_INTERNALS
+#    define DALI_TOOLKIT_API
+#  else
+#    define DALI_TOOLKIT_API __attribute__ ((visibility ("default")))
+#  endif
+#else
+/** Visibility attribute to show declarations */
+#  define DALI_TOOLKIT_API
+#endif
+
+#endif // DALI_TOOLKIT_COMMON_H
index 43ab645..f3ab911 100644 (file)
@@ -31,7 +31,7 @@ namespace Toolkit
 
 const unsigned int TOOLKIT_MAJOR_VERSION = 1;
 const unsigned int TOOLKIT_MINOR_VERSION = 3;
-const unsigned int TOOLKIT_MICRO_VERSION = 24;
+const unsigned int TOOLKIT_MICRO_VERSION = 25;
 const char * const TOOLKIT_BUILD_DATE    = __DATE__ " " __TIME__;
 
 #ifdef DEBUG_ENABLED
old mode 100644 (file)
new mode 100755 (executable)
index 9c59162..617fdcb
@@ -2,7 +2,7 @@
 #define __DALI_TOOLKIT_VERSION_H__
 
 /*
- * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2018 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  */
 
 // EXTERNAL INCLUDES
-#include <dali/public-api/common/dali-common.h>
+#include <dali-toolkit/public-api/dali-toolkit-common.h>
 
 namespace Dali
 {
 namespace Toolkit
 {
-DALI_IMPORT_API extern const unsigned int TOOLKIT_MAJOR_VERSION; ///< The major version number of the Toolkit.
-DALI_IMPORT_API extern const unsigned int TOOLKIT_MINOR_VERSION; ///< The minor version number of the Toolkit.
-DALI_IMPORT_API extern const unsigned int TOOLKIT_MICRO_VERSION; ///< The micro version number of the Toolkit.
-DALI_IMPORT_API extern const char * const TOOLKIT_BUILD_DATE;    ///< The date/time the Toolkit library was built.
+DALI_TOOLKIT_API extern const unsigned int TOOLKIT_MAJOR_VERSION; ///< The major version number of the Toolkit.
+DALI_TOOLKIT_API extern const unsigned int TOOLKIT_MINOR_VERSION; ///< The minor version number of the Toolkit.
+DALI_TOOLKIT_API extern const unsigned int TOOLKIT_MICRO_VERSION; ///< The micro version number of the Toolkit.
+DALI_TOOLKIT_API extern const char * const TOOLKIT_BUILD_DATE;    ///< The date/time the Toolkit library was built.
 } // namespace Toolkit
 } // namespace Dali
 
index 84b1176..08c922f 100644 (file)
@@ -2,7 +2,7 @@
 #define __DALI_TOOLKIT_ENUMS_H__
 
 /*
- * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2018 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -19,7 +19,7 @@
  */
 
 // INTERNAL INCLUDES
-#include <dali/public-api/common/dali-common.h>
+#include <dali-toolkit/public-api/dali-toolkit-common.h>
 
 namespace Dali
 {
@@ -61,7 +61,7 @@ enum Type
  * @param[in] orientation The orientation
  * @return true if the orientation is vertical
  */
-DALI_IMPORT_API bool IsVertical(ControlOrientation::Type orientation);
+DALI_TOOLKIT_API bool IsVertical(ControlOrientation::Type orientation);
 
 /**
  * @brief Queries whether an orientation is horizontal.
@@ -70,7 +70,7 @@ DALI_IMPORT_API bool IsVertical(ControlOrientation::Type orientation);
  * @param[in] orientation The orientation
  * @return true if the orientation is horizontal
  */
-DALI_IMPORT_API bool IsHorizontal(ControlOrientation::Type orientation);
+DALI_TOOLKIT_API bool IsHorizontal(ControlOrientation::Type orientation);
 
 /**
  * @}
index e490f79..7cce0ee 100755 (executable)
@@ -39,6 +39,7 @@ public_api_src_files = \
 
 public_api_header_files = \
   $(public_api_src_dir)/dali-toolkit-version.h \
+  $(public_api_src_dir)/dali-toolkit-common.h \
   $(public_api_src_dir)/enums.h \
   $(public_api_src_dir)/align-enumerations.h \
   $(public_api_src_dir)/toolkit-property-index-ranges.h
index e5a6409..caed557 100644 (file)
@@ -2,7 +2,7 @@
 #define __DALI_TOOLKIT_KEYBOARD_FOCUS_MANAGER_H__
 
 /*
- * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2018 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -54,7 +54,7 @@ class KeyboardFocusManager;
  * | keyboardFocusedActorEnterKey | @ref FocusedActorEnterKeySignal()  |
  * @SINCE_1_0.0
  */
-class DALI_IMPORT_API KeyboardFocusManager : public BaseHandle
+class DALI_TOOLKIT_API KeyboardFocusManager : public BaseHandle
 {
 
 public:
old mode 100644 (file)
new mode 100755 (executable)
index 9c021b5..8d4c629
@@ -2,7 +2,7 @@
 #define DALI_TOOLKIT_ASYNC_IMAGE_LOADER_H
 
 /*
- * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2018 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -23,6 +23,9 @@
 #include <dali/public-api/images/image-operations.h>
 #include <dali/public-api/signals/dali-signal.h>
 
+// INTERNAL INCLUDES
+#include <dali-toolkit/public-api/dali-toolkit-common.h>
+
 namespace Dali
 {
 class PixelData;
@@ -87,7 +90,7 @@ class AsyncImageLoader;
  *
  * @endcode
  */
-class DALI_IMPORT_API AsyncImageLoader : public BaseHandle
+class DALI_TOOLKIT_API AsyncImageLoader : public BaseHandle
 {
 public:
 
old mode 100644 (file)
new mode 100755 (executable)
index 9d0a820..732c937
@@ -2,7 +2,7 @@
 #define DALI_TOOLKIT_SYNC_IMAGE_LOADER_H
 
 /*
- * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2018 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -22,6 +22,9 @@
 #include <dali/public-api/images/image-operations.h>
 #include <dali/public-api/images/pixel-data.h>
 
+// INTERNAL INCLUDES
+#include <dali-toolkit/public-api/dali-toolkit-common.h>
+
 namespace Dali
 {
 
@@ -61,7 +64,7 @@ namespace SyncImageLoader
  * @param[in] url The URL of the image file to load
  * @return A PixelData object containing the image, or an invalid object on failure
  */
-DALI_IMPORT_API PixelData Load( const std::string& url );
+DALI_TOOLKIT_API PixelData Load( const std::string& url );
 
 /**
  * @brief Loads an image synchronously by specifying the target dimensions.
@@ -77,7 +80,7 @@ DALI_IMPORT_API PixelData Load( const std::string& url );
  * @param[in] dimensions The width and height to fit the loaded image to
  * @return A PixelData object containing the image, or an invalid object on failure
  */
-DALI_IMPORT_API PixelData Load( const std::string& url, ImageDimensions dimensions );
+DALI_TOOLKIT_API PixelData Load( const std::string& url, ImageDimensions dimensions );
 
 /**
  * @brief Loads an image synchronously by specifying the target dimensions and options.
@@ -91,7 +94,7 @@ DALI_IMPORT_API PixelData Load( const std::string& url, ImageDimensions dimensio
  * @param[in] orientationCorrection Reorient the image to respect any orientation metadata in its header
  * @return A PixelData object containing the image, or an invalid object on failure
  */
-DALI_IMPORT_API PixelData Load( const std::string& url,
+DALI_TOOLKIT_API PixelData Load( const std::string& url,
                 ImageDimensions dimensions,
                 FittingMode::Type fittingMode,
                 SamplingMode::Type samplingMode,
index 7f52d85..de6bfb1 100644 (file)
@@ -2,7 +2,7 @@
 #define __DALI_TOOLKIT_STYLE_MANAGER_H__
 
 /*
- * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2018 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -65,7 +65,7 @@ class StyleManager;
  * | styleChanged            | @ref StyleChangedSignal()        |
  * @SINCE_1_1.32
  */
-class DALI_IMPORT_API StyleManager : public BaseHandle
+class DALI_TOOLKIT_API StyleManager : public BaseHandle
 {
 public:
 
diff --git a/dali-toolkit/third-party/facebook-flexbox/layout.c b/dali-toolkit/third-party/facebook-flexbox/layout.c
deleted file mode 100644 (file)
index 618d01b..0000000
+++ /dev/null
@@ -1,1371 +0,0 @@
-/**
- * Copyright (c) 2014, 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 <math.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-// in concatenated header, don't include Layout.h it's already at the top
-#ifndef CSS_LAYOUT_IMPLEMENTATION
-#include "layout.h"
-#endif
-
-#ifdef _MSC_VER
-#include <float.h>
-#define isnan _isnan
-
-/* 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
-
-bool isUndefined(float value) {
-  return isnan(value);
-}
-
-static bool eq(float a, float b) {
-  if (isUndefined(a)) {
-    return isUndefined(b);
-  }
-  return fabs(a - b) < 0.0001;
-}
-
-void init_css_node(css_node_t *node) {
-  node->style.align_items = CSS_ALIGN_STRETCH;
-  node->style.align_content = CSS_ALIGN_FLEX_START;
-
-  node->style.direction = CSS_DIRECTION_INHERIT;
-  node->style.flex_direction = CSS_FLEX_DIRECTION_COLUMN;
-
-  // Some of the fields default to undefined and not 0
-  node->style.dimensions[CSS_WIDTH] = CSS_UNDEFINED;
-  node->style.dimensions[CSS_HEIGHT] = CSS_UNDEFINED;
-
-  node->style.minDimensions[CSS_WIDTH] = CSS_UNDEFINED;
-  node->style.minDimensions[CSS_HEIGHT] = CSS_UNDEFINED;
-
-  node->style.maxDimensions[CSS_WIDTH] = CSS_UNDEFINED;
-  node->style.maxDimensions[CSS_HEIGHT] = CSS_UNDEFINED;
-
-  node->style.position[CSS_LEFT] = CSS_UNDEFINED;
-  node->style.position[CSS_TOP] = CSS_UNDEFINED;
-  node->style.position[CSS_RIGHT] = CSS_UNDEFINED;
-  node->style.position[CSS_BOTTOM] = CSS_UNDEFINED;
-
-  node->style.margin[CSS_START] = CSS_UNDEFINED;
-  node->style.margin[CSS_END] = CSS_UNDEFINED;
-  node->style.padding[CSS_START] = CSS_UNDEFINED;
-  node->style.padding[CSS_END] = CSS_UNDEFINED;
-  node->style.border[CSS_START] = CSS_UNDEFINED;
-  node->style.border[CSS_END] = CSS_UNDEFINED;
-
-  node->layout.dimensions[CSS_WIDTH] = CSS_UNDEFINED;
-  node->layout.dimensions[CSS_HEIGHT] = CSS_UNDEFINED;
-
-  // Such that the comparison is always going to be false
-  node->layout.last_requested_dimensions[CSS_WIDTH] = -1;
-  node->layout.last_requested_dimensions[CSS_HEIGHT] = -1;
-  node->layout.last_parent_max_width = -1;
-  node->layout.last_parent_max_height = -1;
-  node->layout.last_direction = (css_direction_t)-1;
-  node->layout.should_update = true;
-}
-
-css_node_t *new_css_node() {
-  css_node_t *node = (css_node_t *)calloc(1, sizeof(*node));
-  init_css_node(node);
-  return node;
-}
-
-void free_css_node(css_node_t *node) {
-  free(node);
-}
-
-static void indent(int n) {
-  int i;
-  for (i = 0; i < n; ++i) {
-    printf("  ");
-  }
-}
-
-static void print_number_0(const char *str, float number) {
-  if (!eq(number, 0)) {
-    printf("%s: %g, ", str, number);
-  }
-}
-
-static void print_number_nan(const char *str, float number) {
-  if (!isnan(number)) {
-    printf("%s: %g, ", str, number);
-  }
-}
-
-static bool four_equal(float four[4]) {
-  return
-    eq(four[0], four[1]) &&
-    eq(four[0], four[2]) &&
-    eq(four[0], four[3]);
-}
-
-
-static void print_css_node_rec(
-  css_node_t *node,
-  css_print_options_t options,
-  int level
-) {
-  indent(level);
-  printf("{");
-
-  if (node->print) {
-    node->print(node->context);
-  }
-
-  if (options & CSS_PRINT_LAYOUT) {
-    printf("layout: {");
-    printf("width: %g, ", node->layout.dimensions[CSS_WIDTH]);
-    printf("height: %g, ", node->layout.dimensions[CSS_HEIGHT]);
-    printf("top: %g, ", node->layout.position[CSS_TOP]);
-    printf("left: %g", node->layout.position[CSS_LEFT]);
-    printf("}, ");
-  }
-
-  if (options & CSS_PRINT_STYLE) {
-    if (node->style.direction == CSS_DIRECTION_INHERIT) {
-      printf("direction: 'inherit', ");
-    } else if (node->style.direction == CSS_DIRECTION_LTR) {
-      printf("direction: 'LTR', ");
-    } else if (node->style.direction == CSS_DIRECTION_RTL) {
-      printf("direction: 'RTL', ");
-    }
-
-    if (node->style.flex_direction == CSS_FLEX_DIRECTION_COLUMN) {
-      printf("flexDirection: 'column', ");
-    } else if (node->style.flex_direction == CSS_FLEX_DIRECTION_COLUMN_REVERSE) {
-      printf("flexDirection: 'columnReverse', ");
-    } else if (node->style.flex_direction == CSS_FLEX_DIRECTION_ROW) {
-      printf("flexDirection: 'row', ");
-    } else if (node->style.flex_direction == CSS_FLEX_DIRECTION_ROW_REVERSE) {
-      printf("flexDirection: 'rowReverse', ");
-    }
-
-    if (node->style.justify_content == CSS_JUSTIFY_FLEX_START) {
-      printf("justifyContent: 'flex-start', ");
-    } else if (node->style.justify_content == CSS_JUSTIFY_CENTER) {
-      printf("justifyContent: 'center', ");
-    } else if (node->style.justify_content == CSS_JUSTIFY_FLEX_END) {
-      printf("justifyContent: 'flex-end', ");
-    } else if (node->style.justify_content == CSS_JUSTIFY_SPACE_AROUND) {
-      printf("justifyContent: 'space-around', ");
-    } else if (node->style.justify_content == CSS_JUSTIFY_SPACE_BETWEEN) {
-      printf("justifyContent: 'space-between', ");
-    }
-
-    if (node->style.align_items == CSS_ALIGN_FLEX_START) {
-      printf("alignItems: 'flex-start', ");
-    } else if (node->style.align_items == CSS_ALIGN_CENTER) {
-      printf("alignItems: 'center', ");
-    } else if (node->style.align_items == CSS_ALIGN_FLEX_END) {
-      printf("alignItems: 'flex-end', ");
-    } else if (node->style.align_items == CSS_ALIGN_STRETCH) {
-      printf("alignItems: 'stretch', ");
-    }
-
-    if (node->style.align_content == CSS_ALIGN_FLEX_START) {
-      printf("alignContent: 'flex-start', ");
-    } else if (node->style.align_content == CSS_ALIGN_CENTER) {
-      printf("alignContent: 'center', ");
-    } else if (node->style.align_content == CSS_ALIGN_FLEX_END) {
-      printf("alignContent: 'flex-end', ");
-    } else if (node->style.align_content == CSS_ALIGN_STRETCH) {
-      printf("alignContent: 'stretch', ");
-    }
-
-    if (node->style.align_self == CSS_ALIGN_FLEX_START) {
-      printf("alignSelf: 'flex-start', ");
-    } else if (node->style.align_self == CSS_ALIGN_CENTER) {
-      printf("alignSelf: 'center', ");
-    } else if (node->style.align_self == CSS_ALIGN_FLEX_END) {
-      printf("alignSelf: 'flex-end', ");
-    } else if (node->style.align_self == CSS_ALIGN_STRETCH) {
-      printf("alignSelf: 'stretch', ");
-    } else if (node->style.align_self == CSS_ALIGN_AUTO) {
-      printf("alignSelf: 'auto', ");
-    }
-
-    if (node->style.flex_wrap == CSS_NOWRAP) {
-      printf("flexWrap: 'no-wrap', ");
-    } else if (node->style.flex_wrap == CSS_WRAP) {
-      printf("flexWrap: 'wrap', ");
-    }
-
-    print_number_nan("flex", node->style.flex);
-
-    if (four_equal(node->style.margin)) {
-      print_number_0("margin", node->style.margin[CSS_LEFT]);
-    } else {
-      print_number_0("marginLeft", node->style.margin[CSS_LEFT]);
-      print_number_0("marginRight", node->style.margin[CSS_RIGHT]);
-      print_number_0("marginTop", node->style.margin[CSS_TOP]);
-      print_number_0("marginBottom", node->style.margin[CSS_BOTTOM]);
-      print_number_0("marginStart", node->style.margin[CSS_START]);
-      print_number_0("marginEnd", node->style.margin[CSS_END]);
-    }
-
-    if (four_equal(node->style.padding)) {
-      print_number_0("padding", node->style.margin[CSS_LEFT]);
-    } else {
-      print_number_0("paddingLeft", node->style.padding[CSS_LEFT]);
-      print_number_0("paddingRight", node->style.padding[CSS_RIGHT]);
-      print_number_0("paddingTop", node->style.padding[CSS_TOP]);
-      print_number_0("paddingBottom", node->style.padding[CSS_BOTTOM]);
-      print_number_0("paddingStart", node->style.padding[CSS_START]);
-      print_number_0("paddingEnd", node->style.padding[CSS_END]);
-    }
-
-    if (four_equal(node->style.border)) {
-      print_number_0("borderWidth", node->style.border[CSS_LEFT]);
-    } else {
-      print_number_0("borderLeftWidth", node->style.border[CSS_LEFT]);
-      print_number_0("borderRightWidth", node->style.border[CSS_RIGHT]);
-      print_number_0("borderTopWidth", node->style.border[CSS_TOP]);
-      print_number_0("borderBottomWidth", node->style.border[CSS_BOTTOM]);
-      print_number_0("borderStartWidth", node->style.border[CSS_START]);
-      print_number_0("borderEndWidth", node->style.border[CSS_END]);
-    }
-
-    print_number_nan("width", node->style.dimensions[CSS_WIDTH]);
-    print_number_nan("height", node->style.dimensions[CSS_HEIGHT]);
-
-    if(node->style.minDimensions[CSS_WIDTH] != CSS_UNDEFINED) {
-      print_number_nan("minWidth", node->style.minDimensions[CSS_WIDTH]);
-    }
-    if(node->style.minDimensions[CSS_HEIGHT] != CSS_UNDEFINED) {
-      print_number_nan("minHeight", node->style.minDimensions[CSS_HEIGHT]);
-    }
-    if(node->style.maxDimensions[CSS_WIDTH] != CSS_UNDEFINED) {
-      print_number_nan("maxWidth", node->style.maxDimensions[CSS_WIDTH]);
-    }
-    if(node->style.maxDimensions[CSS_HEIGHT] != CSS_UNDEFINED) {
-      print_number_nan("maxHeight", node->style.maxDimensions[CSS_HEIGHT]);
-    }
-
-    if (node->style.position_type == CSS_POSITION_ABSOLUTE) {
-      printf("position: 'absolute', ");
-    }
-    else if (node->style.position_type == CSS_POSITION_RELATIVE) {
-      printf("position: 'relative', ");
-    }
-
-    print_number_nan("position-left", node->style.position[CSS_LEFT]);
-    print_number_nan("position-right", node->style.position[CSS_RIGHT]);
-    print_number_nan("position-top", node->style.position[CSS_TOP]);
-    print_number_nan("position-bottom", node->style.position[CSS_BOTTOM]);
-  }
-
-  if (options & CSS_PRINT_CHILDREN && node->children_count > 0) {
-    printf("children: [\n");
-    int i;
-    for (i = 0; i < node->children_count; ++i) {
-      print_css_node_rec(node->get_child(node->context, i), options, level + 1);
-    }
-    indent(level);
-    printf("]},\n");
-  } else {
-    printf("},\n");
-  }
-}
-
-void print_css_node(css_node_t *node, css_print_options_t options) {
-  print_css_node_rec(node, options, 0);
-}
-
-
-static css_position_t leading[4] = {
-  /* CSS_FLEX_DIRECTION_COLUMN = */ CSS_TOP,
-  /* CSS_FLEX_DIRECTION_COLUMN_REVERSE = */ CSS_BOTTOM,
-  /* CSS_FLEX_DIRECTION_ROW = */ CSS_LEFT,
-  /* CSS_FLEX_DIRECTION_ROW_REVERSE = */ CSS_RIGHT
-};
-static css_position_t trailing[4] = {
-  /* CSS_FLEX_DIRECTION_COLUMN = */ CSS_BOTTOM,
-  /* CSS_FLEX_DIRECTION_COLUMN_REVERSE = */ CSS_TOP,
-  /* CSS_FLEX_DIRECTION_ROW = */ CSS_RIGHT,
-  /* CSS_FLEX_DIRECTION_ROW_REVERSE = */ CSS_LEFT
-};
-static css_position_t pos[4] = {
-  /* CSS_FLEX_DIRECTION_COLUMN = */ CSS_TOP,
-  /* CSS_FLEX_DIRECTION_COLUMN_REVERSE = */ CSS_BOTTOM,
-  /* CSS_FLEX_DIRECTION_ROW = */ CSS_LEFT,
-  /* CSS_FLEX_DIRECTION_ROW_REVERSE = */ CSS_RIGHT
-};
-static css_dimension_t dim[4] = {
-  /* CSS_FLEX_DIRECTION_COLUMN = */ CSS_HEIGHT,
-  /* CSS_FLEX_DIRECTION_COLUMN_REVERSE = */ CSS_HEIGHT,
-  /* CSS_FLEX_DIRECTION_ROW = */ CSS_WIDTH,
-  /* CSS_FLEX_DIRECTION_ROW_REVERSE = */ CSS_WIDTH
-};
-
-static bool isRowDirection(css_flex_direction_t flex_direction) {
-  return flex_direction == CSS_FLEX_DIRECTION_ROW ||
-         flex_direction == CSS_FLEX_DIRECTION_ROW_REVERSE;
-}
-
-static bool isColumnDirection(css_flex_direction_t flex_direction) {
-  return flex_direction == CSS_FLEX_DIRECTION_COLUMN ||
-         flex_direction == CSS_FLEX_DIRECTION_COLUMN_REVERSE;
-}
-
-static float getLeadingMargin(css_node_t *node, css_flex_direction_t axis) {
-  if (isRowDirection(axis) && !isUndefined(node->style.margin[CSS_START])) {
-    return node->style.margin[CSS_START];
-  }
-
-  return node->style.margin[leading[axis]];
-}
-
-static float getTrailingMargin(css_node_t *node, css_flex_direction_t axis) {
-  if (isRowDirection(axis) && !isUndefined(node->style.margin[CSS_END])) {
-    return node->style.margin[CSS_END];
-  }
-
-  return node->style.margin[trailing[axis]];
-}
-
-static float getLeadingPadding(css_node_t *node, css_flex_direction_t axis) {
-  if (isRowDirection(axis) &&
-      !isUndefined(node->style.padding[CSS_START]) &&
-      node->style.padding[CSS_START] >= 0) {
-    return node->style.padding[CSS_START];
-  }
-
-  if (node->style.padding[leading[axis]] >= 0) {
-    return node->style.padding[leading[axis]];
-  }
-
-  return 0;
-}
-
-static float getTrailingPadding(css_node_t *node, css_flex_direction_t axis) {
-  if (isRowDirection(axis) &&
-      !isUndefined(node->style.padding[CSS_END]) &&
-      node->style.padding[CSS_END] >= 0) {
-    return node->style.padding[CSS_END];
-  }
-
-  if (node->style.padding[trailing[axis]] >= 0) {
-    return node->style.padding[trailing[axis]];
-  }
-
-  return 0;
-}
-
-static float getLeadingBorder(css_node_t *node, css_flex_direction_t axis) {
-  if (isRowDirection(axis) &&
-      !isUndefined(node->style.border[CSS_START]) &&
-      node->style.border[CSS_START] >= 0) {
-    return node->style.border[CSS_START];
-  }
-
-  if (node->style.border[leading[axis]] >= 0) {
-    return node->style.border[leading[axis]];
-  }
-
-  return 0;
-}
-
-static float getTrailingBorder(css_node_t *node, css_flex_direction_t axis) {
-  if (isRowDirection(axis) &&
-      !isUndefined(node->style.border[CSS_END]) &&
-      node->style.border[CSS_END] >= 0) {
-    return node->style.border[CSS_END];
-  }
-
-  if (node->style.border[trailing[axis]] >= 0) {
-    return node->style.border[trailing[axis]];
-  }
-
-  return 0;
-}
-
-static float getLeadingPaddingAndBorder(css_node_t *node, css_flex_direction_t axis) {
-  return getLeadingPadding(node, axis) + getLeadingBorder(node, axis);
-}
-
-static float getTrailingPaddingAndBorder(css_node_t *node, css_flex_direction_t axis) {
-  return getTrailingPadding(node, axis) + getTrailingBorder(node, axis);
-}
-
-static float getBorderAxis(css_node_t *node, css_flex_direction_t axis) {
-  return getLeadingBorder(node, axis) + getTrailingBorder(node, axis);
-}
-
-static float getMarginAxis(css_node_t *node, css_flex_direction_t axis) {
-  return getLeadingMargin(node, axis) + getTrailingMargin(node, axis);
-}
-
-static float getPaddingAndBorderAxis(css_node_t *node, css_flex_direction_t axis) {
-  return getLeadingPaddingAndBorder(node, axis) + getTrailingPaddingAndBorder(node, axis);
-}
-
-static css_align_t getAlignItem(css_node_t *node, css_node_t *child) {
-  if (child->style.align_self != CSS_ALIGN_AUTO) {
-    return child->style.align_self;
-  }
-  return node->style.align_items;
-}
-
-static css_direction_t resolveDirection(css_node_t *node, css_direction_t parentDirection) {
-  css_direction_t direction = node->style.direction;
-
-  if (direction == CSS_DIRECTION_INHERIT) {
-    direction = parentDirection > CSS_DIRECTION_INHERIT ? parentDirection : CSS_DIRECTION_LTR;
-  }
-
-  return direction;
-}
-
-static css_flex_direction_t getFlexDirection(css_node_t *node) {
-  return node->style.flex_direction;
-}
-
-static css_flex_direction_t resolveAxis(css_flex_direction_t flex_direction, css_direction_t direction) {
-  if (direction == CSS_DIRECTION_RTL) {
-    if (flex_direction == CSS_FLEX_DIRECTION_ROW) {
-      return CSS_FLEX_DIRECTION_ROW_REVERSE;
-    } else if (flex_direction == CSS_FLEX_DIRECTION_ROW_REVERSE) {
-      return CSS_FLEX_DIRECTION_ROW;
-    }
-  }
-
-  return flex_direction;
-}
-
-static css_flex_direction_t getCrossFlexDirection(css_flex_direction_t flex_direction, css_direction_t direction) {
-  if (isColumnDirection(flex_direction)) {
-    return resolveAxis(CSS_FLEX_DIRECTION_ROW, direction);
-  } else {
-    return CSS_FLEX_DIRECTION_COLUMN;
-  }
-}
-
-static float getFlex(css_node_t *node) {
-  return node->style.flex;
-}
-
-static bool isFlex(css_node_t *node) {
-  return (
-    node->style.position_type == CSS_POSITION_RELATIVE &&
-    getFlex(node) > 0
-  );
-}
-
-static bool isFlexWrap(css_node_t *node) {
-  return node->style.flex_wrap == CSS_WRAP;
-}
-
-static float getDimWithMargin(css_node_t *node, css_flex_direction_t axis) {
-  return node->layout.dimensions[dim[axis]] +
-    getLeadingMargin(node, axis) +
-    getTrailingMargin(node, axis);
-}
-
-static bool isStyleDimDefined(css_node_t *node, css_flex_direction_t axis) {
-  float value = node->style.dimensions[dim[axis]];
-  return !isUndefined(value) && value >= 0.0;
-}
-
-static bool isLayoutDimDefined(css_node_t *node, css_flex_direction_t axis) {
-  float value = node->layout.dimensions[dim[axis]];
-  return !isUndefined(value) && value >= 0.0;
-}
-
-static bool isPosDefined(css_node_t *node, css_position_t position) {
-  return !isUndefined(node->style.position[position]);
-}
-
-static bool isMeasureDefined(css_node_t *node) {
-  return node->measure;
-}
-
-static float getPosition(css_node_t *node, css_position_t position) {
-  float result = node->style.position[position];
-  if (!isUndefined(result)) {
-    return result;
-  }
-  return 0;
-}
-
-static float boundAxis(css_node_t *node, css_flex_direction_t axis, float value) {
-  float min = CSS_UNDEFINED;
-  float max = CSS_UNDEFINED;
-
-  if (isColumnDirection(axis)) {
-    min = node->style.minDimensions[CSS_HEIGHT];
-    max = node->style.maxDimensions[CSS_HEIGHT];
-  } else if (isRowDirection(axis)) {
-    min = node->style.minDimensions[CSS_WIDTH];
-    max = node->style.maxDimensions[CSS_WIDTH];
-  }
-
-  float boundValue = value;
-
-  if (!isUndefined(max) && max >= 0.0 && boundValue > max) {
-    boundValue = max;
-  }
-  if (!isUndefined(min) && min >= 0.0 && boundValue < min) {
-    boundValue = min;
-  }
-
-  return boundValue;
-}
-
-// When the user specifically sets a value for width or height
-static void setDimensionFromStyle(css_node_t *node, css_flex_direction_t axis) {
-  // The parent already computed us a width or height. We just skip it
-  if (isLayoutDimDefined(node, axis)) {
-    return;
-  }
-  // We only run if there's a width or height defined
-  if (!isStyleDimDefined(node, axis)) {
-    return;
-  }
-
-  // The dimensions can never be smaller than the padding and border
-  node->layout.dimensions[dim[axis]] = fmaxf(
-    boundAxis(node, axis, node->style.dimensions[dim[axis]]),
-    getPaddingAndBorderAxis(node, axis)
-  );
-}
-
-static void setTrailingPosition(css_node_t *node, css_node_t *child, css_flex_direction_t axis) {
-    child->layout.position[trailing[axis]] = node->layout.dimensions[dim[axis]] -
-      child->layout.dimensions[dim[axis]] - 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 getRelativePosition(css_node_t *node, css_flex_direction_t axis) {
-  float lead = node->style.position[leading[axis]];
-  if (!isUndefined(lead)) {
-    return lead;
-  }
-  return -getPosition(node, trailing[axis]);
-}
-
-static void layoutNodeImpl(css_node_t *node, float parentMaxWidth, float parentMaxHeight, css_direction_t parentDirection) {
-  /** START_GENERATED **/
-  css_direction_t direction = resolveDirection(node, parentDirection);
-  css_flex_direction_t mainAxis = resolveAxis(getFlexDirection(node), direction);
-  css_flex_direction_t crossAxis = getCrossFlexDirection(mainAxis, direction);
-  css_flex_direction_t resolvedRowAxis = resolveAxis(CSS_FLEX_DIRECTION_ROW, direction);
-
-  // Handle width and height style attributes
-  setDimensionFromStyle(node, mainAxis);
-  setDimensionFromStyle(node, crossAxis);
-
-  // Set the resolved resolution in the node's layout
-  node->layout.direction = direction;
-
-  // The position is set by the parent, but we need to complete it with a
-  // delta composed of the margin and left/top/right/bottom
-  node->layout.position[leading[mainAxis]] += getLeadingMargin(node, mainAxis) +
-    getRelativePosition(node, mainAxis);
-  node->layout.position[trailing[mainAxis]] += getTrailingMargin(node, mainAxis) +
-    getRelativePosition(node, mainAxis);
-  node->layout.position[leading[crossAxis]] += getLeadingMargin(node, crossAxis) +
-    getRelativePosition(node, crossAxis);
-  node->layout.position[trailing[crossAxis]] += getTrailingMargin(node, crossAxis) +
-    getRelativePosition(node, crossAxis);
-
-  // Inline immutable values from the target node to avoid excessive method
-  // invocations during the layout calculation.
-  int childCount = node->children_count;
-  float paddingAndBorderAxisResolvedRow = getPaddingAndBorderAxis(node, resolvedRowAxis);
-  float paddingAndBorderAxisColumn = getPaddingAndBorderAxis(node, CSS_FLEX_DIRECTION_COLUMN);
-
-  if (isMeasureDefined(node)) {
-    bool isResolvedRowDimDefined = isLayoutDimDefined(node, resolvedRowAxis);
-
-    float width = CSS_UNDEFINED;
-    css_measure_mode_t widthMode = CSS_MEASURE_MODE_UNDEFINED;
-    if (isStyleDimDefined(node, resolvedRowAxis)) {
-      width = node->style.dimensions[CSS_WIDTH];
-      widthMode = CSS_MEASURE_MODE_EXACTLY;
-    } else if (isResolvedRowDimDefined) {
-      width = node->layout.dimensions[dim[resolvedRowAxis]];
-      widthMode = CSS_MEASURE_MODE_EXACTLY;
-    } else {
-      width = parentMaxWidth -
-        getMarginAxis(node, resolvedRowAxis);
-      widthMode = CSS_MEASURE_MODE_AT_MOST;
-    }
-    width -= paddingAndBorderAxisResolvedRow;
-    if (isUndefined(width)) {
-      widthMode = CSS_MEASURE_MODE_UNDEFINED;
-    }
-
-    float height = CSS_UNDEFINED;
-    css_measure_mode_t heightMode = CSS_MEASURE_MODE_UNDEFINED;
-    if (isStyleDimDefined(node, CSS_FLEX_DIRECTION_COLUMN)) {
-      height = node->style.dimensions[CSS_HEIGHT];
-      heightMode = CSS_MEASURE_MODE_EXACTLY;
-    } else if (isLayoutDimDefined(node, CSS_FLEX_DIRECTION_COLUMN)) {
-      height = node->layout.dimensions[dim[CSS_FLEX_DIRECTION_COLUMN]];
-      heightMode = CSS_MEASURE_MODE_EXACTLY;
-    } else {
-      height = parentMaxHeight -
-        getMarginAxis(node, resolvedRowAxis);
-      heightMode = CSS_MEASURE_MODE_AT_MOST;
-    }
-    height -= getPaddingAndBorderAxis(node, CSS_FLEX_DIRECTION_COLUMN);
-    if (isUndefined(height)) {
-      heightMode = CSS_MEASURE_MODE_UNDEFINED;
-    }
-
-    // We only need to give a dimension for the text if we haven't got any
-    // for it computed yet. It can either be from the style attribute or because
-    // the element is flexible.
-    bool isRowUndefined = !isStyleDimDefined(node, resolvedRowAxis) && !isResolvedRowDimDefined;
-    bool isColumnUndefined = !isStyleDimDefined(node, CSS_FLEX_DIRECTION_COLUMN) &&
-      isUndefined(node->layout.dimensions[dim[CSS_FLEX_DIRECTION_COLUMN]]);
-
-    // Let's not measure the text if we already know both dimensions
-    if (isRowUndefined || isColumnUndefined) {
-      css_dim_t measureDim = node->measure(
-        node->context,
-        width,
-        widthMode,
-        height,
-        heightMode
-      );
-      if (isRowUndefined) {
-        node->layout.dimensions[CSS_WIDTH] = measureDim.dimensions[CSS_WIDTH] +
-          paddingAndBorderAxisResolvedRow;
-      }
-      if (isColumnUndefined) {
-        node->layout.dimensions[CSS_HEIGHT] = measureDim.dimensions[CSS_HEIGHT] +
-          paddingAndBorderAxisColumn;
-      }
-    }
-    if (childCount == 0) {
-      return;
-    }
-  }
-
-  bool isNodeFlexWrap = isFlexWrap(node);
-
-  css_justify_t justifyContent = node->style.justify_content;
-
-  float leadingPaddingAndBorderMain = getLeadingPaddingAndBorder(node, mainAxis);
-  float leadingPaddingAndBorderCross = getLeadingPaddingAndBorder(node, crossAxis);
-  float paddingAndBorderAxisMain = getPaddingAndBorderAxis(node, mainAxis);
-  float paddingAndBorderAxisCross = getPaddingAndBorderAxis(node, crossAxis);
-
-  bool isMainDimDefined = isLayoutDimDefined(node, mainAxis);
-  bool isCrossDimDefined = isLayoutDimDefined(node, crossAxis);
-  bool isMainRowDirection = isRowDirection(mainAxis);
-
-  int i;
-  int ii;
-  css_node_t* child;
-  css_flex_direction_t axis;
-
-  css_node_t* firstAbsoluteChild = NULL;
-  css_node_t* currentAbsoluteChild = NULL;
-
-  float definedMainDim = CSS_UNDEFINED;
-  if (isMainDimDefined) {
-    definedMainDim = node->layout.dimensions[dim[mainAxis]] - paddingAndBorderAxisMain;
-  }
-
-  // We want to execute the next two loops one per line with flex-wrap
-  int startLine = 0;
-  int endLine = 0;
-  // int nextOffset = 0;
-  int alreadyComputedNextLayout = 0;
-  // We aggregate the total dimensions of the container in those two variables
-  float linesCrossDim = 0;
-  float linesMainDim = 0;
-  int linesCount = 0;
-  while (endLine < childCount) {
-    // <Loop A> Layout non flexible children and count children by type
-
-    // mainContentDim is accumulation of the dimensions and margin of all the
-    // non flexible children. 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 mainContentDim = 0;
-
-    // There are three kind of children, non flexible, flexible and absolute.
-    // We need to know how many there are in order to distribute the space.
-    int flexibleChildrenCount = 0;
-    float totalFlexible = 0;
-    int nonFlexibleChildrenCount = 0;
-
-    // Use the line loop to position children in the main axis for as long
-    // as they are using a simple stacking behaviour. Children that are
-    // immediately stacked in the initial loop will not be touched again
-    // in <Loop C>.
-    bool isSimpleStackMain =
-        (isMainDimDefined && justifyContent == CSS_JUSTIFY_FLEX_START) ||
-        (!isMainDimDefined && justifyContent != CSS_JUSTIFY_CENTER);
-    int firstComplexMain = (isSimpleStackMain ? childCount : startLine);
-
-    // Use the initial line loop to position children in the cross axis for
-    // as long as they are relatively positioned with alignment STRETCH or
-    // FLEX_START. Children that are immediately stacked in the initial loop
-    // will not be touched again in <Loop D>.
-    bool isSimpleStackCross = true;
-    int firstComplexCross = childCount;
-
-    css_node_t* firstFlexChild = NULL;
-    css_node_t* currentFlexChild = NULL;
-
-    float mainDim = leadingPaddingAndBorderMain;
-    float crossDim = 0;
-
-    float maxWidth = CSS_UNDEFINED;
-    float maxHeight = CSS_UNDEFINED;
-    for (i = startLine; i < childCount; ++i) {
-      child = node->get_child(node->context, i);
-      child->line_index = linesCount;
-
-      child->next_absolute_child = NULL;
-      child->next_flex_child = NULL;
-
-      css_align_t alignItem = getAlignItem(node, child);
-
-      // Pre-fill cross axis dimensions when the child is using stretch before
-      // we call the recursive layout pass
-      if (alignItem == CSS_ALIGN_STRETCH &&
-          child->style.position_type == CSS_POSITION_RELATIVE &&
-          isCrossDimDefined &&
-          !isStyleDimDefined(child, crossAxis)) {
-        child->layout.dimensions[dim[crossAxis]] = fmaxf(
-          boundAxis(child, crossAxis, node->layout.dimensions[dim[crossAxis]] -
-            paddingAndBorderAxisCross - getMarginAxis(child, crossAxis)),
-          // You never want to go smaller than padding
-          getPaddingAndBorderAxis(child, crossAxis)
-        );
-      } else if (child->style.position_type == CSS_POSITION_ABSOLUTE) {
-        // Store a private linked list of absolutely positioned children
-        // so that we can efficiently traverse them later.
-        if (firstAbsoluteChild == NULL) {
-          firstAbsoluteChild = child;
-        }
-        if (currentAbsoluteChild != NULL) {
-          currentAbsoluteChild->next_absolute_child = child;
-        }
-        currentAbsoluteChild = child;
-
-        // Pre-fill dimensions when using absolute position and both offsets for the axis are defined (either both
-        // left and right or top and bottom).
-        for (ii = 0; ii < 2; ii++) {
-          axis = (ii != 0) ? CSS_FLEX_DIRECTION_ROW : CSS_FLEX_DIRECTION_COLUMN;
-          if (isLayoutDimDefined(node, axis) &&
-              !isStyleDimDefined(child, axis) &&
-              isPosDefined(child, leading[axis]) &&
-              isPosDefined(child, trailing[axis])) {
-            child->layout.dimensions[dim[axis]] = fmaxf(
-              boundAxis(child, axis, node->layout.dimensions[dim[axis]] -
-                getPaddingAndBorderAxis(node, axis) -
-                getMarginAxis(child, axis) -
-                getPosition(child, leading[axis]) -
-                getPosition(child, trailing[axis])),
-              // You never want to go smaller than padding
-              getPaddingAndBorderAxis(child, axis)
-            );
-          }
-        }
-      }
-
-      float nextContentDim = 0;
-
-      // It only makes sense to consider a child flexible if we have a computed
-      // dimension for the node->
-      if (isMainDimDefined && isFlex(child)) {
-        flexibleChildrenCount++;
-        totalFlexible += child->style.flex;
-
-        // Store a private linked list of flexible children so that we can
-        // efficiently traverse them later.
-        if (firstFlexChild == NULL) {
-          firstFlexChild = child;
-        }
-        if (currentFlexChild != NULL) {
-          currentFlexChild->next_flex_child = child;
-        }
-        currentFlexChild = child;
-
-        // Even if we don't know its exact size yet, we already know the padding,
-        // border and margin. We'll use this partial information, which represents
-        // the smallest possible size for the child, to compute the remaining
-        // available space.
-        nextContentDim = getPaddingAndBorderAxis(child, mainAxis) +
-          getMarginAxis(child, mainAxis);
-
-      } else {
-        maxWidth = CSS_UNDEFINED;
-        maxHeight = CSS_UNDEFINED;
-
-        if (!isMainRowDirection) {
-          if (isLayoutDimDefined(node, resolvedRowAxis)) {
-            maxWidth = node->layout.dimensions[dim[resolvedRowAxis]] -
-              paddingAndBorderAxisResolvedRow;
-          } else {
-            maxWidth = parentMaxWidth -
-              getMarginAxis(node, resolvedRowAxis) -
-              paddingAndBorderAxisResolvedRow;
-          }
-        } else {
-          if (isLayoutDimDefined(node, CSS_FLEX_DIRECTION_COLUMN)) {
-            maxHeight = node->layout.dimensions[dim[CSS_FLEX_DIRECTION_COLUMN]] -
-                paddingAndBorderAxisColumn;
-          } else {
-            maxHeight = parentMaxHeight -
-              getMarginAxis(node, CSS_FLEX_DIRECTION_COLUMN) -
-              paddingAndBorderAxisColumn;
-          }
-        }
-
-        // This is the main recursive call. We layout non flexible children.
-        if (alreadyComputedNextLayout == 0) {
-          layoutNode(child, maxWidth, maxHeight, direction);
-        }
-
-        // Absolute positioned elements do not take part of the layout, so we
-        // don't use them to compute mainContentDim
-        if (child->style.position_type == CSS_POSITION_RELATIVE) {
-          nonFlexibleChildrenCount++;
-          // At this point we know the final size and margin of the element.
-          nextContentDim = getDimWithMargin(child, mainAxis);
-        }
-      }
-
-      // The element we are about to add would make us go to the next line
-      if (isNodeFlexWrap &&
-          isMainDimDefined &&
-          mainContentDim + nextContentDim > definedMainDim &&
-          // If there's only one element, then it's bigger than the content
-          // and needs its own line
-          i != startLine) {
-        nonFlexibleChildrenCount--;
-        alreadyComputedNextLayout = 1;
-        break;
-      }
-
-      // Disable simple stacking in the main axis for the current line as
-      // we found a non-trivial child-> The remaining children will be laid out
-      // in <Loop C>.
-      if (isSimpleStackMain &&
-          (child->style.position_type != CSS_POSITION_RELATIVE || isFlex(child))) {
-        isSimpleStackMain = false;
-        firstComplexMain = i;
-      }
-
-      // Disable simple stacking in the cross axis for the current line as
-      // we found a non-trivial child-> The remaining children will be laid out
-      // in <Loop D>.
-      if (isSimpleStackCross &&
-          (child->style.position_type != CSS_POSITION_RELATIVE ||
-              (alignItem != CSS_ALIGN_STRETCH && alignItem != CSS_ALIGN_FLEX_START) ||
-              (alignItem == CSS_ALIGN_STRETCH && !isCrossDimDefined))) {
-        isSimpleStackCross = false;
-        firstComplexCross = i;
-      }
-
-      if (isSimpleStackMain) {
-        child->layout.position[pos[mainAxis]] += mainDim;
-        if (isMainDimDefined) {
-          setTrailingPosition(node, child, mainAxis);
-        }
-
-        mainDim += getDimWithMargin(child, mainAxis);
-        crossDim = fmaxf(crossDim, boundAxis(child, crossAxis, getDimWithMargin(child, crossAxis)));
-      }
-
-      if (isSimpleStackCross) {
-        child->layout.position[pos[crossAxis]] += linesCrossDim + leadingPaddingAndBorderCross;
-        if (isCrossDimDefined) {
-          setTrailingPosition(node, child, crossAxis);
-        }
-      }
-
-      alreadyComputedNextLayout = 0;
-      mainContentDim += nextContentDim;
-      endLine = i + 1;
-    }
-
-    // <Loop B> Layout flexible children and allocate empty space
-
-    // 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;
-
-    // The remaining available space that needs to be allocated
-    float remainingMainDim = 0;
-    if (isMainDimDefined) {
-      remainingMainDim = definedMainDim - mainContentDim;
-    } else {
-      remainingMainDim = fmaxf(mainContentDim, 0) - mainContentDim;
-    }
-
-    // If there are flexible children in the mix, they are going to fill the
-    // remaining space
-    if (flexibleChildrenCount != 0) {
-      float flexibleMainDim = remainingMainDim / totalFlexible;
-      float baseMainDim;
-      float boundMainDim;
-
-      // If the flex share of remaining space doesn't meet min/max bounds,
-      // remove this child from flex calculations.
-      currentFlexChild = firstFlexChild;
-      while (currentFlexChild != NULL) {
-        baseMainDim = flexibleMainDim * currentFlexChild->style.flex +
-            getPaddingAndBorderAxis(currentFlexChild, mainAxis);
-        boundMainDim = boundAxis(currentFlexChild, mainAxis, baseMainDim);
-
-        if (baseMainDim != boundMainDim) {
-          remainingMainDim -= boundMainDim;
-          totalFlexible -= currentFlexChild->style.flex;
-        }
-
-        currentFlexChild = currentFlexChild->next_flex_child;
-      }
-      flexibleMainDim = remainingMainDim / totalFlexible;
-
-      // The non flexible children can overflow the container, in this case
-      // we should just assume that there is no space available.
-      if (flexibleMainDim < 0) {
-        flexibleMainDim = 0;
-      }
-
-      currentFlexChild = firstFlexChild;
-      while (currentFlexChild != NULL) {
-        // At this point we know the final size of the element in the main
-        // dimension
-        currentFlexChild->layout.dimensions[dim[mainAxis]] = boundAxis(currentFlexChild, mainAxis,
-          flexibleMainDim * currentFlexChild->style.flex +
-              getPaddingAndBorderAxis(currentFlexChild, mainAxis)
-        );
-
-        maxWidth = CSS_UNDEFINED;
-        if (isLayoutDimDefined(node, resolvedRowAxis)) {
-          maxWidth = node->layout.dimensions[dim[resolvedRowAxis]] -
-            paddingAndBorderAxisResolvedRow;
-        } else if (!isMainRowDirection) {
-          maxWidth = parentMaxWidth -
-            getMarginAxis(node, resolvedRowAxis) -
-            paddingAndBorderAxisResolvedRow;
-        }
-        maxHeight = CSS_UNDEFINED;
-        if (isLayoutDimDefined(node, CSS_FLEX_DIRECTION_COLUMN)) {
-          maxHeight = node->layout.dimensions[dim[CSS_FLEX_DIRECTION_COLUMN]] -
-            paddingAndBorderAxisColumn;
-        } else if (isMainRowDirection) {
-          maxHeight = parentMaxHeight -
-            getMarginAxis(node, CSS_FLEX_DIRECTION_COLUMN) -
-            paddingAndBorderAxisColumn;
-        }
-
-        // And we recursively call the layout algorithm for this child
-        layoutNode(currentFlexChild, maxWidth, maxHeight, direction);
-
-        child = currentFlexChild;
-        currentFlexChild = currentFlexChild->next_flex_child;
-        child->next_flex_child = NULL;
-      }
-
-    // We use justifyContent to figure out how to allocate the remaining
-    // space available
-    } else if (justifyContent != CSS_JUSTIFY_FLEX_START) {
-      if (justifyContent == CSS_JUSTIFY_CENTER) {
-        leadingMainDim = remainingMainDim / 2;
-      } else if (justifyContent == CSS_JUSTIFY_FLEX_END) {
-        leadingMainDim = remainingMainDim;
-      } else if (justifyContent == CSS_JUSTIFY_SPACE_BETWEEN) {
-        remainingMainDim = fmaxf(remainingMainDim, 0);
-        if (flexibleChildrenCount + nonFlexibleChildrenCount - 1 != 0) {
-          betweenMainDim = remainingMainDim /
-            (flexibleChildrenCount + nonFlexibleChildrenCount - 1);
-        } else {
-          betweenMainDim = 0;
-        }
-      } else if (justifyContent == CSS_JUSTIFY_SPACE_AROUND) {
-        // Space on the edges is half of the space between elements
-        betweenMainDim = remainingMainDim /
-          (flexibleChildrenCount + nonFlexibleChildrenCount);
-        leadingMainDim = betweenMainDim / 2;
-      }
-    }
-
-    // <Loop C> Position elements in the main axis and compute dimensions
-
-    // At this point, all the children have their dimensions set. We need to
-    // find their position. In order to do that, we accumulate data in
-    // variables that are also useful to compute the total dimensions of the
-    // container!
-    mainDim += leadingMainDim;
-
-    for (i = firstComplexMain; i < endLine; ++i) {
-      child = node->get_child(node->context, i);
-
-      if (child->style.position_type == CSS_POSITION_ABSOLUTE &&
-          isPosDefined(child, leading[mainAxis])) {
-        // 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]] = getPosition(child, leading[mainAxis]) +
-          getLeadingBorder(node, mainAxis) +
-          getLeadingMargin(child, mainAxis);
-      } else {
-        // If the child is position absolute (without top/left) or relative,
-        // we put it at the current accumulated offset.
-        child->layout.position[pos[mainAxis]] += mainDim;
-
-        // Define the trailing position accordingly.
-        if (isMainDimDefined) {
-          setTrailingPosition(node, child, mainAxis);
-        }
-
-        // Now that we placed the element, we need to update the variables
-        // We only need to do that for relative elements. Absolute elements
-        // do not take part in that phase.
-        if (child->style.position_type == CSS_POSITION_RELATIVE) {
-          // The main dimension is the sum of all the elements dimension plus
-          // the spacing.
-          mainDim += betweenMainDim + getDimWithMargin(child, mainAxis);
-          // The cross dimension is the max of the elements dimension since there
-          // can only be one element in that cross dimension.
-          crossDim = fmaxf(crossDim, boundAxis(child, crossAxis, getDimWithMargin(child, crossAxis)));
-        }
-      }
-    }
-
-    float containerCrossAxis = node->layout.dimensions[dim[crossAxis]];
-    if (!isCrossDimDefined) {
-      containerCrossAxis = fmaxf(
-        // For the cross dim, we add both sides at the end because the value
-        // is aggregate via a max function. Intermediate negative values
-        // can mess this computation otherwise
-        boundAxis(node, crossAxis, crossDim + paddingAndBorderAxisCross),
-        paddingAndBorderAxisCross
-      );
-    }
-
-    // <Loop D> Position elements in the cross axis
-    for (i = firstComplexCross; i < endLine; ++i) {
-      child = node->get_child(node->context, i);
-
-      if (child->style.position_type == CSS_POSITION_ABSOLUTE &&
-          isPosDefined(child, leading[crossAxis])) {
-        // In case the child is absolutely positionned and has a
-        // top/left/bottom/right being set, we override all the previously
-        // computed positions to set it correctly.
-        child->layout.position[pos[crossAxis]] = getPosition(child, leading[crossAxis]) +
-          getLeadingBorder(node, crossAxis) +
-          getLeadingMargin(child, crossAxis);
-
-      } 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
-        if (child->style.position_type == CSS_POSITION_RELATIVE) {
-          /*eslint-disable */
-          // This variable is intentionally re-defined as the code is transpiled to a block scope language
-          css_align_t alignItem = getAlignItem(node, child);
-          /*eslint-enable */
-          if (alignItem == CSS_ALIGN_STRETCH) {
-            // You can only stretch if the dimension has not already been defined
-            // previously.
-            if (!isStyleDimDefined(child, crossAxis)) {
-              float dimCrossAxis = child->layout.dimensions[dim[crossAxis]];
-              child->layout.dimensions[dim[crossAxis]] = fmaxf(
-                boundAxis(child, crossAxis, containerCrossAxis -
-                  paddingAndBorderAxisCross - getMarginAxis(child, crossAxis)),
-                // You never want to go smaller than padding
-                getPaddingAndBorderAxis(child, crossAxis)
-              );
-
-              // If the size has changed, and this child has children we need to re-layout this child
-              if (dimCrossAxis != child->layout.dimensions[dim[crossAxis]] && child->children_count > 0) {
-                // Reset child margins before re-layout as they are added back in layoutNode and would be doubled
-                child->layout.position[leading[mainAxis]] -= getLeadingMargin(child, mainAxis) +
-                  getRelativePosition(child, mainAxis);
-                child->layout.position[trailing[mainAxis]] -= getTrailingMargin(child, mainAxis) +
-                  getRelativePosition(child, mainAxis);
-                child->layout.position[leading[crossAxis]] -= getLeadingMargin(child, crossAxis) +
-                  getRelativePosition(child, crossAxis);
-                child->layout.position[trailing[crossAxis]] -= getTrailingMargin(child, crossAxis) +
-                  getRelativePosition(child, crossAxis);
-
-                layoutNode(child, maxWidth, maxHeight, direction);
-              }
-            }
-          } else if (alignItem != CSS_ALIGN_FLEX_START) {
-            // The remaining space between the parent dimensions+padding and child
-            // dimensions+margin.
-            float remainingCrossDim = containerCrossAxis -
-              paddingAndBorderAxisCross - getDimWithMargin(child, crossAxis);
-
-            if (alignItem == CSS_ALIGN_CENTER) {
-              leadingCrossDim += remainingCrossDim / 2;
-            } else { // CSS_ALIGN_FLEX_END
-              leadingCrossDim += remainingCrossDim;
-            }
-          }
-        }
-
-        // And we apply the position
-        child->layout.position[pos[crossAxis]] += linesCrossDim + leadingCrossDim;
-
-        // Define the trailing position accordingly.
-        if (isCrossDimDefined) {
-          setTrailingPosition(node, child, crossAxis);
-        }
-      }
-    }
-
-    linesCrossDim += crossDim;
-    linesMainDim = fmaxf(linesMainDim, mainDim);
-    linesCount += 1;
-    startLine = endLine;
-  }
-
-  // <Loop E>
-  //
-  // Note(prenaux): More than one line, we need to layout the crossAxis
-  // according to alignContent.
-  //
-  // Note that we could probably remove <Loop D> and handle the one line case
-  // here too, but for the moment this is safer since it won't interfere with
-  // previously working code.
-  //
-  // See specs:
-  // http://www.w3.org/TR/2012/CR-css3-flexbox-20120918/#layout-algorithm
-  // section 9.4
-  //
-  if (linesCount > 1 && isCrossDimDefined) {
-    float nodeCrossAxisInnerSize = node->layout.dimensions[dim[crossAxis]] -
-        paddingAndBorderAxisCross;
-    float remainingAlignContentDim = nodeCrossAxisInnerSize - linesCrossDim;
-
-    float crossDimLead = 0;
-    float currentLead = leadingPaddingAndBorderCross;
-
-    css_align_t alignContent = node->style.align_content;
-    if (alignContent == CSS_ALIGN_FLEX_END) {
-      currentLead += remainingAlignContentDim;
-    } else if (alignContent == CSS_ALIGN_CENTER) {
-      currentLead += remainingAlignContentDim / 2;
-    } else if (alignContent == CSS_ALIGN_STRETCH) {
-      if (nodeCrossAxisInnerSize > linesCrossDim) {
-        crossDimLead = (remainingAlignContentDim / linesCount);
-      }
-    }
-
-    int endIndex = 0;
-    for (i = 0; i < linesCount; ++i) {
-      int startIndex = endIndex;
-
-      // compute the line's height and find the endIndex
-      float lineHeight = 0;
-      for (ii = startIndex; ii < childCount; ++ii) {
-        child = node->get_child(node->context, ii);
-        if (child->style.position_type != CSS_POSITION_RELATIVE) {
-          continue;
-        }
-        if (child->line_index != i) {
-          break;
-        }
-        if (isLayoutDimDefined(child, crossAxis)) {
-          lineHeight = fmaxf(
-            lineHeight,
-            child->layout.dimensions[dim[crossAxis]] + getMarginAxis(child, crossAxis)
-          );
-        }
-      }
-      endIndex = ii;
-      lineHeight += crossDimLead;
-
-      for (ii = startIndex; ii < endIndex; ++ii) {
-        child = node->get_child(node->context, ii);
-        if (child->style.position_type != CSS_POSITION_RELATIVE) {
-          continue;
-        }
-
-        css_align_t alignContentAlignItem = getAlignItem(node, child);
-        if (alignContentAlignItem == CSS_ALIGN_FLEX_START) {
-          child->layout.position[pos[crossAxis]] = currentLead + getLeadingMargin(child, crossAxis);
-        } else if (alignContentAlignItem == CSS_ALIGN_FLEX_END) {
-          child->layout.position[pos[crossAxis]] = currentLead + lineHeight - getTrailingMargin(child, crossAxis) - child->layout.dimensions[dim[crossAxis]];
-        } else if (alignContentAlignItem == CSS_ALIGN_CENTER) {
-          float childHeight = child->layout.dimensions[dim[crossAxis]];
-          child->layout.position[pos[crossAxis]] = currentLead + (lineHeight - childHeight) / 2;
-        } else if (alignContentAlignItem == CSS_ALIGN_STRETCH) {
-          child->layout.position[pos[crossAxis]] = currentLead + getLeadingMargin(child, crossAxis);
-          // TODO(prenaux): Correctly set the height of items with undefined
-          //                (auto) crossAxis dimension.
-        }
-      }
-
-      currentLead += lineHeight;
-    }
-  }
-
-  bool needsMainTrailingPos = false;
-  bool needsCrossTrailingPos = false;
-
-  // If the user didn't specify a width or height, and it has not been set
-  // by the container, then we set it via the children.
-  if (!isMainDimDefined) {
-    node->layout.dimensions[dim[mainAxis]] = fmaxf(
-      // We're missing the last padding at this point to get the final
-      // dimension
-      boundAxis(node, mainAxis, linesMainDim + getTrailingPaddingAndBorder(node, mainAxis)),
-      // We can never assign a width smaller than the padding and borders
-      paddingAndBorderAxisMain
-    );
-
-    if (mainAxis == CSS_FLEX_DIRECTION_ROW_REVERSE ||
-        mainAxis == CSS_FLEX_DIRECTION_COLUMN_REVERSE) {
-      needsMainTrailingPos = true;
-    }
-  }
-
-  if (!isCrossDimDefined) {
-    node->layout.dimensions[dim[crossAxis]] = fmaxf(
-      // For the cross dim, we add both sides at the end because the value
-      // is aggregate via a max function. Intermediate negative values
-      // can mess this computation otherwise
-      boundAxis(node, crossAxis, linesCrossDim + paddingAndBorderAxisCross),
-      paddingAndBorderAxisCross
-    );
-
-    if (crossAxis == CSS_FLEX_DIRECTION_ROW_REVERSE ||
-        crossAxis == CSS_FLEX_DIRECTION_COLUMN_REVERSE) {
-      needsCrossTrailingPos = true;
-    }
-  }
-
-  // <Loop F> Set trailing position if necessary
-  if (needsMainTrailingPos || needsCrossTrailingPos) {
-    for (i = 0; i < childCount; ++i) {
-      child = node->get_child(node->context, i);
-
-      if (needsMainTrailingPos) {
-        setTrailingPosition(node, child, mainAxis);
-      }
-
-      if (needsCrossTrailingPos) {
-        setTrailingPosition(node, child, crossAxis);
-      }
-    }
-  }
-
-  // <Loop G> Calculate dimensions for absolutely positioned elements
-  currentAbsoluteChild = firstAbsoluteChild;
-  while (currentAbsoluteChild != NULL) {
-    // Pre-fill dimensions when using absolute position and both offsets for
-    // the axis are defined (either both left and right or top and bottom).
-    for (ii = 0; ii < 2; ii++) {
-      axis = (ii != 0) ? CSS_FLEX_DIRECTION_ROW : CSS_FLEX_DIRECTION_COLUMN;
-
-      if (isLayoutDimDefined(node, axis) &&
-          !isStyleDimDefined(currentAbsoluteChild, axis) &&
-          isPosDefined(currentAbsoluteChild, leading[axis]) &&
-          isPosDefined(currentAbsoluteChild, trailing[axis])) {
-        currentAbsoluteChild->layout.dimensions[dim[axis]] = fmaxf(
-          boundAxis(currentAbsoluteChild, axis, node->layout.dimensions[dim[axis]] -
-            getBorderAxis(node, axis) -
-            getMarginAxis(currentAbsoluteChild, axis) -
-            getPosition(currentAbsoluteChild, leading[axis]) -
-            getPosition(currentAbsoluteChild, trailing[axis])
-          ),
-          // You never want to go smaller than padding
-          getPaddingAndBorderAxis(currentAbsoluteChild, axis)
-        );
-      }
-
-      if (isPosDefined(currentAbsoluteChild, trailing[axis]) &&
-          !isPosDefined(currentAbsoluteChild, leading[axis])) {
-        currentAbsoluteChild->layout.position[leading[axis]] =
-          node->layout.dimensions[dim[axis]] -
-          currentAbsoluteChild->layout.dimensions[dim[axis]] -
-          getPosition(currentAbsoluteChild, trailing[axis]);
-      }
-    }
-
-    child = currentAbsoluteChild;
-    currentAbsoluteChild = currentAbsoluteChild->next_absolute_child;
-    child->next_absolute_child = NULL;
-  }
-  /** END_GENERATED **/
-}
-
-void layoutNode(css_node_t *node, float parentMaxWidth, float parentMaxHeight, css_direction_t parentDirection) {
-  css_layout_t *layout = &node->layout;
-  css_direction_t direction = node->style.direction;
-  layout->should_update = true;
-
-  bool skipLayout =
-    !node->is_dirty(node->context) &&
-    eq(layout->last_requested_dimensions[CSS_WIDTH], layout->dimensions[CSS_WIDTH]) &&
-    eq(layout->last_requested_dimensions[CSS_HEIGHT], layout->dimensions[CSS_HEIGHT]) &&
-    eq(layout->last_parent_max_width, parentMaxWidth) &&
-    eq(layout->last_parent_max_height, parentMaxHeight) &&
-    eq(layout->last_direction, direction);
-
-  if (skipLayout) {
-    layout->dimensions[CSS_WIDTH] = layout->last_dimensions[CSS_WIDTH];
-    layout->dimensions[CSS_HEIGHT] = layout->last_dimensions[CSS_HEIGHT];
-    layout->position[CSS_TOP] = layout->last_position[CSS_TOP];
-    layout->position[CSS_LEFT] = layout->last_position[CSS_LEFT];
-  } else {
-    layout->last_requested_dimensions[CSS_WIDTH] = layout->dimensions[CSS_WIDTH];
-    layout->last_requested_dimensions[CSS_HEIGHT] = layout->dimensions[CSS_HEIGHT];
-    layout->last_parent_max_width = parentMaxWidth;
-    layout->last_parent_max_height = parentMaxHeight;
-    layout->last_direction = direction;
-
-    int i, childCount;
-    for (i = 0, childCount = node->children_count; i < childCount; i++) {
-      resetNodeLayout(node->get_child(node->context, i));
-    }
-
-    layoutNodeImpl(node, parentMaxWidth, parentMaxHeight, parentDirection);
-
-    layout->last_dimensions[CSS_WIDTH] = layout->dimensions[CSS_WIDTH];
-    layout->last_dimensions[CSS_HEIGHT] = layout->dimensions[CSS_HEIGHT];
-    layout->last_position[CSS_TOP] = layout->position[CSS_TOP];
-    layout->last_position[CSS_LEFT] = layout->position[CSS_LEFT];
-  }
-
-#if defined(FLEXBOX_LAYOUT_NODE_DEBUG)
-  printf("Input:    ");
-  print_css_node(node, (css_print_options_t)(CSS_PRINT_STYLE | CSS_PRINT_CHILDREN));
-  printf("Output:   ");
-  print_css_node(node, (css_print_options_t)(CSS_PRINT_LAYOUT | CSS_PRINT_CHILDREN));
-  printf("\n");
-#endif // defined(FLEXBOX_LAYOUT_NODE_DEBUG)
-}
-
-void resetNodeLayout(css_node_t *node) {
-  node->layout.dimensions[CSS_WIDTH] = CSS_UNDEFINED;
-  node->layout.dimensions[CSS_HEIGHT] = CSS_UNDEFINED;
-  node->layout.position[CSS_LEFT] = 0;
-  node->layout.position[CSS_TOP] = 0;
-}
diff --git a/dali-toolkit/third-party/facebook-flexbox/layout.h b/dali-toolkit/third-party/facebook-flexbox/layout.h
deleted file mode 100644 (file)
index d6ad495..0000000
+++ /dev/null
@@ -1,177 +0,0 @@
-/**
- * Copyright (c) 2014, 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.
- */
-
-#ifndef __LAYOUT_H
-#define __LAYOUT_H
-
-#include <math.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 CSS_UNDEFINED NAN
-
-typedef enum {
-  CSS_DIRECTION_INHERIT = 0,
-  CSS_DIRECTION_LTR,
-  CSS_DIRECTION_RTL
-} css_direction_t;
-
-typedef enum {
-  CSS_FLEX_DIRECTION_COLUMN = 0,
-  CSS_FLEX_DIRECTION_COLUMN_REVERSE,
-  CSS_FLEX_DIRECTION_ROW,
-  CSS_FLEX_DIRECTION_ROW_REVERSE
-} css_flex_direction_t;
-
-typedef enum {
-  CSS_JUSTIFY_FLEX_START = 0,
-  CSS_JUSTIFY_CENTER,
-  CSS_JUSTIFY_FLEX_END,
-  CSS_JUSTIFY_SPACE_BETWEEN,
-  CSS_JUSTIFY_SPACE_AROUND
-} css_justify_t;
-
-// Note: auto is only a valid value for alignSelf. It is NOT a valid value for
-// alignItems.
-typedef enum {
-  CSS_ALIGN_AUTO = 0,
-  CSS_ALIGN_FLEX_START,
-  CSS_ALIGN_CENTER,
-  CSS_ALIGN_FLEX_END,
-  CSS_ALIGN_STRETCH
-} css_align_t;
-
-typedef enum {
-  CSS_POSITION_RELATIVE = 0,
-  CSS_POSITION_ABSOLUTE
-} css_position_type_t;
-
-typedef enum {
-  CSS_NOWRAP = 0,
-  CSS_WRAP
-} css_wrap_type_t;
-
-// Note: left and top are shared between position[2] and position[4], so
-// they have to be before right and bottom.
-typedef enum {
-  CSS_LEFT = 0,
-  CSS_TOP,
-  CSS_RIGHT,
-  CSS_BOTTOM,
-  CSS_START,
-  CSS_END,
-  CSS_POSITION_COUNT
-} css_position_t;
-
-typedef enum {
-  CSS_MEASURE_MODE_UNDEFINED = 0,
-  CSS_MEASURE_MODE_EXACTLY,
-  CSS_MEASURE_MODE_AT_MOST
-} css_measure_mode_t;
-
-typedef enum {
-  CSS_WIDTH = 0,
-  CSS_HEIGHT
-} css_dimension_t;
-
-typedef struct {
-  float position[4];
-  float dimensions[2];
-  css_direction_t direction;
-
-  // Instead of recomputing the entire layout every single time, we
-  // cache some information to break early when nothing changed
-  bool should_update;
-  float last_requested_dimensions[2];
-  float last_parent_max_width;
-  float last_parent_max_height;
-  float last_dimensions[2];
-  float last_position[2];
-  css_direction_t last_direction;
-} css_layout_t;
-
-typedef struct {
-  float dimensions[2];
-} css_dim_t;
-
-typedef struct {
-  css_direction_t direction;
-  css_flex_direction_t flex_direction;
-  css_justify_t justify_content;
-  css_align_t align_content;
-  css_align_t align_items;
-  css_align_t align_self;
-  css_position_type_t position_type;
-  css_wrap_type_t flex_wrap;
-  float flex;
-  float margin[6];
-  float position[4];
-  /**
-   * You should skip all the rules that contain negative values for the
-   * following attributes. For example:
-   *   {padding: 10, paddingLeft: -5}
-   * should output:
-   *   {left: 10 ...}
-   * the following two are incorrect:
-   *   {left: -5 ...}
-   *   {left: 0 ...}
-   */
-  float padding[6];
-  float border[6];
-  float dimensions[2];
-  float minDimensions[2];
-  float maxDimensions[2];
-} css_style_t;
-
-typedef struct css_node css_node_t;
-struct css_node {
-  css_style_t style;
-  css_layout_t layout;
-  int children_count;
-  int line_index;
-
-  css_node_t *next_absolute_child;
-  css_node_t *next_flex_child;
-
-  css_dim_t (*measure)(void *context, float width, css_measure_mode_t widthMode, float height, css_measure_mode_t heightMode);
-  void (*print)(void *context);
-  struct css_node* (*get_child)(void *context, int i);
-  bool (*is_dirty)(void *context);
-  void *context;
-};
-
-// Lifecycle of nodes and children
-css_node_t *new_css_node(void);
-void init_css_node(css_node_t *node);
-void free_css_node(css_node_t *node);
-
-// Print utilities
-typedef enum {
-  CSS_PRINT_LAYOUT = 1,
-  CSS_PRINT_STYLE = 2,
-  CSS_PRINT_CHILDREN = 4,
-} css_print_options_t;
-void print_css_node(css_node_t *node, css_print_options_t options);
-
-bool isUndefined(float value);
-
-// Function that computes the layout!
-void layoutNode(css_node_t *node, float maxWidth, float maxHeight, css_direction_t parentDirection);
-
-// Reset the calculated layout values for a given node. You should call this before `layoutNode`.
-void resetNodeLayout(css_node_t *node);
-
-#endif // __LAYOUT_H
index 53e027f..54dd713 100644 (file)
@@ -1,4 +1,13 @@
 third_party_src_files = \
    $(third_party_src_dir)/nanosvg/nanosvg.cc \
    $(third_party_src_dir)/nanosvg/nanosvgrast.cc \
-   $(third_party_src_dir)/facebook-flexbox/layout.c
+   $(third_party_src_dir)/yoga/Utils.cpp \
+   $(third_party_src_dir)/yoga/YGConfig.cpp \  
+   $(third_party_src_dir)/yoga/YGEnums.cpp \
+   $(third_party_src_dir)/yoga/YGFloatOptional.cpp \
+   $(third_party_src_dir)/yoga/YGLayout.cpp \
+   $(third_party_src_dir)/yoga/YGNode.cpp \
+   $(third_party_src_dir)/yoga/YGNodePrint.cpp \
+   $(third_party_src_dir)/yoga/YGStyle.cpp \
+   $(third_party_src_dir)/yoga/Yoga.cpp
+
diff --git a/dali-toolkit/third-party/yoga/Utils.cpp b/dali-toolkit/third-party/yoga/Utils.cpp
new file mode 100644 (file)
index 0000000..6fa8df8
--- /dev/null
@@ -0,0 +1,68 @@
+/**
+ * Copyright (c) 2014-present, Facebook, Inc.
+ *
+ * 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"
+
+YGFlexDirection YGFlexDirectionCross(
+    const YGFlexDirection flexDirection,
+    const YGDirection direction) {
+  return YGFlexDirectionIsColumn(flexDirection)
+      ? YGResolveFlexDirection(YGFlexDirectionRow, direction)
+      : YGFlexDirectionColumn;
+}
+
+float YGFloatMax(const float a, const float b) {
+  if (!YGFloatIsUndefined(a) && !YGFloatIsUndefined(b)) {
+    return fmaxf(a, b);
+  }
+  return YGFloatIsUndefined(a) ? b : a;
+}
+
+float YGFloatMin(const float a, const float b) {
+  if (!YGFloatIsUndefined(a) && !YGFloatIsUndefined(b)) {
+    return fminf(a, b);
+  }
+
+  return YGFloatIsUndefined(a) ? b : a;
+}
+
+bool YGValueEqual(const YGValue a, const YGValue b) {
+  if (a.unit != b.unit) {
+    return false;
+  }
+
+  if (a.unit == YGUnitUndefined ||
+      (YGFloatIsUndefined(a.value) && YGFloatIsUndefined(b.value))) {
+    return true;
+  }
+
+  return fabs(a.value - b.value) < 0.0001f;
+}
+
+bool YGFloatsEqual(const float a, const float b) {
+  if (!YGFloatIsUndefined(a) && !YGFloatIsUndefined(b)) {
+    return fabs(a - b) < 0.0001f;
+  }
+  return YGFloatIsUndefined(a) && YGFloatIsUndefined(b);
+}
+
+float YGFloatSanitize(const float& val) {
+  return YGFloatIsUndefined(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;
+}
diff --git a/dali-toolkit/third-party/yoga/Utils.h b/dali-toolkit/third-party/yoga/Utils.h
new file mode 100644 (file)
index 0000000..6c95b1e
--- /dev/null
@@ -0,0 +1,148 @@
+/**
+ * Copyright (c) 2014-present, Facebook, Inc.
+ *
+ * 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);
+}
diff --git a/dali-toolkit/third-party/yoga/YGConfig.cpp b/dali-toolkit/third-party/yoga/YGConfig.cpp
new file mode 100644 (file)
index 0000000..5cee527
--- /dev/null
@@ -0,0 +1,19 @@
+/**
+ * Copyright (c) 2014-present, Facebook, Inc.
+ *
+ * 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) {}
diff --git a/dali-toolkit/third-party/yoga/YGConfig.h b/dali-toolkit/third-party/yoga/YGConfig.h
new file mode 100644 (file)
index 0000000..0f655d1
--- /dev/null
@@ -0,0 +1,23 @@
+/**
+ * Copyright (c) 2014-present, Facebook, Inc.
+ *
+ * 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;
+
+  YGConfig(YGLogger logger);
+};
diff --git a/dali-toolkit/third-party/yoga/YGEnums.cpp b/dali-toolkit/third-party/yoga/YGEnums.cpp
new file mode 100644 (file)
index 0000000..7f16628
--- /dev/null
@@ -0,0 +1,226 @@
+/**
+ * Copyright (c) 2014-present, Facebook, Inc.
+ *
+ * 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";
+}
diff --git a/dali-toolkit/third-party/yoga/YGEnums.h b/dali-toolkit/third-party/yoga/YGEnums.h
new file mode 100644 (file)
index 0000000..0976d78
--- /dev/null
@@ -0,0 +1,155 @@
+/**
+ * Copyright (c) 2014-present, Facebook, Inc.
+ *
+ * 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
diff --git a/dali-toolkit/third-party/yoga/YGFloatOptional.cpp b/dali-toolkit/third-party/yoga/YGFloatOptional.cpp
new file mode 100644 (file)
index 0000000..00bfc71
--- /dev/null
@@ -0,0 +1,92 @@
+/**
+ * Copyright (c) 2014-present, Facebook, Inc.
+ *
+ * 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"
+
+YGFloatOptional::YGFloatOptional(const float& value) {
+  if (YGFloatIsUndefined(value)) {
+    isUndefined_ = true;
+    value_ = 0;
+  } else {
+    value_ = value;
+    isUndefined_ = false;
+  }
+}
+
+YGFloatOptional::YGFloatOptional() : value_(0), isUndefined_(true) {}
+
+const 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_;
+}
+
+void YGFloatOptional::setValue(const float& val) {
+  value_ = val;
+  isUndefined_ = false;
+}
+
+const bool& YGFloatOptional::isUndefined() const {
+  return isUndefined_;
+}
+
+bool YGFloatOptional::operator==(const YGFloatOptional& op) const {
+  if (isUndefined_ == op.isUndefined()) {
+    return isUndefined_ ? true : value_ == op.getValue();
+  }
+  return false;
+}
+
+bool YGFloatOptional::operator!=(const YGFloatOptional& op) const {
+  return !(*this == op);
+}
+
+bool YGFloatOptional::operator==(const float& val) const {
+  if (YGFloatIsUndefined(val) == isUndefined_) {
+    return isUndefined_ ? true : val == value_;
+  }
+  return false;
+}
+
+bool YGFloatOptional::operator!=(const 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 ? true : *this > op;
+}
+
+bool YGFloatOptional::operator<=(const YGFloatOptional& op) const {
+  return *this == op ? true : *this < op;
+}
diff --git a/dali-toolkit/third-party/yoga/YGFloatOptional.h b/dali-toolkit/third-party/yoga/YGFloatOptional.h
new file mode 100644 (file)
index 0000000..21af2a8
--- /dev/null
@@ -0,0 +1,39 @@
+/**
+ * Copyright (c) 2014-present, Facebook, Inc.
+ *
+ * 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(const float& value);
+  explicit YGFloatOptional();
+
+  // 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()`.
+  const float& getValue() const;
+
+  // Sets the value of float optional, and thus isUndefined is assigned false.
+  void setValue(const float& val);
+
+  const bool& isUndefined() const;
+
+  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==(const float& val) const;
+  bool operator!=(const float& val) const;
+};
diff --git a/dali-toolkit/third-party/yoga/YGLayout.cpp b/dali-toolkit/third-party/yoga/YGLayout.cpp
new file mode 100644 (file)
index 0000000..6e367bd
--- /dev/null
@@ -0,0 +1,65 @@
+/**
+ * Copyright (c) 2014-present, Facebook, Inc.
+ *
+ * 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"
+
+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 (!YGFloatIsUndefined(measuredDimensions[0]) ||
+      !YGFloatIsUndefined(layout.measuredDimensions[0])) {
+    isEqual =
+        isEqual && (measuredDimensions[0] == layout.measuredDimensions[0]);
+  }
+  if (!YGFloatIsUndefined(measuredDimensions[1]) ||
+      !YGFloatIsUndefined(layout.measuredDimensions[1])) {
+    isEqual =
+        isEqual && (measuredDimensions[1] == layout.measuredDimensions[1]);
+  }
+
+  return isEqual;
+}
+
+bool YGLayout::operator!=(YGLayout layout) const {
+  return !(*this == layout);
+}
diff --git a/dali-toolkit/third-party/yoga/YGLayout.h b/dali-toolkit/third-party/yoga/YGLayout.h
new file mode 100644 (file)
index 0000000..46ca130
--- /dev/null
@@ -0,0 +1,42 @@
+/**
+ * Copyright (c) 2014-present, Facebook, Inc.
+ *
+ * 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;
+};
diff --git a/dali-toolkit/third-party/yoga/YGMacros.h b/dali-toolkit/third-party/yoga/YGMacros.h
new file mode 100644 (file)
index 0000000..15ed81d
--- /dev/null
@@ -0,0 +1,41 @@
+/**
+ * Copyright (c) 2014-present, Facebook, Inc.
+ *
+ * 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
diff --git a/dali-toolkit/third-party/yoga/YGNode.cpp b/dali-toolkit/third-party/yoga/YGNode.cpp
new file mode 100644 (file)
index 0000000..64a47d3
--- /dev/null
@@ -0,0 +1,768 @@
+/**
+ * Copyright (c) 2014-present, Facebook, Inc.
+ *
+ * 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"
+
+void* YGNode::getContext() const {
+  return context_;
+}
+
+YGPrintFunc YGNode::getPrintFunc() const {
+  return print_;
+}
+
+bool YGNode::getHasNewLayout() const {
+  return hasNewLayout_;
+}
+
+YGNodeType YGNode::getNodeType() const {
+  return nodeType_;
+}
+
+YGMeasureFunc YGNode::getMeasure() const {
+  return measure_;
+}
+
+YGBaselineFunc YGNode::getBaseline() const {
+  return baseline_;
+}
+
+YGDirtiedFunc YGNode::getDirtied() const {
+  return dirtied_;
+}
+
+YGStyle& YGNode::getStyle() {
+  return style_;
+}
+
+YGLayout& YGNode::getLayout() {
+  return layout_;
+}
+
+uint32_t YGNode::getLineIndex() const {
+  return lineIndex_;
+}
+
+YGNodeRef YGNode::getOwner() const {
+  return owner_;
+}
+
+YGVector YGNode::getChildren() const {
+  return children_;
+}
+
+uint32_t YGNode::getChildrenCount() const {
+  return static_cast<uint32_t>(children_.size());
+}
+
+YGNodeRef YGNode::getChild(uint32_t index) const {
+  return children_.at(index);
+}
+
+YGNodeRef YGNode::getNextChild() const {
+  return nextChild_;
+}
+
+YGConfigRef YGNode::getConfig() const {
+  return config_;
+}
+
+bool YGNode::isDirty() const {
+  return isDirty_;
+}
+
+YGValue YGNode::getResolvedDimension(int index) {
+  return resolvedDimensions_[index];
+}
+
+std::array<YGValue, 2> YGNode::getResolvedDimensions() const {
+  return resolvedDimensions_;
+}
+
+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::setContext(void* context) {
+  context_ = context;
+}
+
+void YGNode::setPrintFunc(YGPrintFunc printFunc) {
+  print_ = printFunc;
+}
+
+void YGNode::setHasNewLayout(bool hasNewLayout) {
+  hasNewLayout_ = hasNewLayout;
+}
+
+void YGNode::setNodeType(YGNodeType nodeType) {
+  nodeType_ = nodeType;
+}
+
+void YGNode::setStyleFlexDirection(YGFlexDirection direction) {
+  style_.flexDirection = direction;
+}
+
+void YGNode::setStyleAlignContent(YGAlign alignContent) {
+  style_.alignContent = alignContent;
+}
+
+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::setBaseLineFunc(YGBaselineFunc baseLineFunc) {
+  baseline_ = baseLineFunc;
+}
+
+void YGNode::setDirtiedFunc(YGDirtiedFunc dirtiedFunc) {
+  dirtied_ = dirtiedFunc;
+}
+
+void YGNode::setStyle(const YGStyle& style) {
+  style_ = style;
+}
+
+void YGNode::setLayout(const YGLayout& layout) {
+  layout_ = layout;
+}
+
+void YGNode::setLineIndex(uint32_t lineIndex) {
+  lineIndex_ = lineIndex;
+}
+
+void YGNode::setOwner(YGNodeRef owner) {
+  owner_ = owner;
+}
+
+void YGNode::setChildren(const YGVector& children) {
+  children_ = children;
+}
+
+void YGNode::setNextChild(YGNodeRef nextChild) {
+  nextChild_ = nextChild;
+}
+
+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::setConfig(YGConfigRef config) {
+  config_ = config;
+}
+
+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()
+    : context_(nullptr),
+      print_(nullptr),
+      hasNewLayout_(true),
+      nodeType_(YGNodeTypeDefault),
+      measure_(nullptr),
+      baseline_(nullptr),
+      dirtied_(nullptr),
+      style_(YGStyle()),
+      layout_(YGLayout()),
+      lineIndex_(0),
+      owner_(nullptr),
+      children_(YGVector()),
+      nextChild_(nullptr),
+      config_(nullptr),
+      isDirty_(false),
+      resolvedDimensions_({{YGValueUndefined, YGValueUndefined}}) {}
+
+YGNode::YGNode(const YGNode& node)
+    : context_(node.context_),
+      print_(node.print_),
+      hasNewLayout_(node.hasNewLayout_),
+      nodeType_(node.nodeType_),
+      measure_(node.measure_),
+      baseline_(node.baseline_),
+      dirtied_(node.dirtied_),
+      style_(node.style_),
+      layout_(node.layout_),
+      lineIndex_(node.lineIndex_),
+      owner_(node.owner_),
+      children_(node.children_),
+      nextChild_(node.nextChild_),
+      config_(node.config_),
+      isDirty_(node.isDirty_),
+      resolvedDimensions_(node.resolvedDimensions_) {}
+
+YGNode::YGNode(const YGConfigRef newConfig) : YGNode() {
+  config_ = newConfig;
+}
+
+YGNode::YGNode(
+    void* context,
+    YGPrintFunc print,
+    bool hasNewLayout,
+    YGNodeType nodeType,
+    YGMeasureFunc measure,
+    YGBaselineFunc baseline,
+    YGDirtiedFunc dirtied,
+    YGStyle style,
+    const YGLayout& layout,
+    uint32_t lineIndex,
+    YGNodeRef owner,
+    const YGVector& children,
+    YGNodeRef nextChild,
+    YGConfigRef config,
+    bool isDirty,
+    std::array<YGValue, 2> resolvedDimensions)
+    : context_(context),
+      print_(print),
+      hasNewLayout_(hasNewLayout),
+      nodeType_(nodeType),
+      measure_(measure),
+      baseline_(baseline),
+      dirtied_(dirtied),
+      style_(style),
+      layout_(layout),
+      lineIndex_(lineIndex),
+      owner_(owner),
+      children_(children),
+      nextChild_(nextChild),
+      config_(config),
+      isDirty_(isDirty),
+      resolvedDimensions_(resolvedDimensions) {}
+
+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();
+  nextChild_ = node.getNextChild();
+  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();
+}
+
+YGNode::~YGNode() {
+  // All the member variables are deallocated externally, so no need to
+  // deallocate here
+}
+
+// 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 &&
+      !YGFloatIsUndefined(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 &&
+      !YGFloatIsUndefined(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;
+}
diff --git a/dali-toolkit/third-party/yoga/YGNode.h b/dali-toolkit/third-party/yoga/YGNode.h
new file mode 100644 (file)
index 0000000..96541a5
--- /dev/null
@@ -0,0 +1,184 @@
+/**
+ * Copyright (c) 2014-present, Facebook, Inc.
+ *
+ * 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_;
+  YGPrintFunc print_;
+  bool hasNewLayout_;
+  YGNodeType nodeType_;
+  YGMeasureFunc measure_;
+  YGBaselineFunc baseline_;
+  YGDirtiedFunc dirtied_;
+  YGStyle style_;
+  YGLayout layout_;
+  uint32_t lineIndex_;
+  YGNodeRef owner_;
+  YGVector children_;
+  YGNodeRef nextChild_;
+  YGConfigRef config_;
+  bool isDirty_;
+  std::array<YGValue, 2> resolvedDimensions_;
+
+  YGFloatOptional relativePosition(
+      const YGFlexDirection& axis,
+      const float& axisSize) const;
+
+ public:
+  YGNode();
+  ~YGNode();
+  explicit YGNode(const YGConfigRef newConfig);
+  YGNode(const YGNode& node);
+  YGNode& operator=(const YGNode& node);
+  YGNode(
+      void* context,
+      YGPrintFunc print,
+      bool hasNewLayout,
+      YGNodeType nodeType,
+      YGMeasureFunc measure,
+      YGBaselineFunc baseline,
+      YGDirtiedFunc dirtied,
+      YGStyle style,
+      const YGLayout& layout,
+      uint32_t lineIndex,
+      YGNodeRef owner,
+      const YGVector& children,
+      YGNodeRef nextChild,
+      YGConfigRef config,
+      bool isDirty,
+      std::array<YGValue, 2> resolvedDimensions);
+
+  // Getters
+  void* getContext() const;
+  YGPrintFunc getPrintFunc() const;
+  bool getHasNewLayout() const;
+  YGNodeType getNodeType() const;
+  YGMeasureFunc getMeasure() const;
+  YGBaselineFunc getBaseline() const;
+  YGDirtiedFunc getDirtied() const;
+  // For Performance reasons passing as reference.
+  YGStyle& getStyle();
+  // For Performance reasons passing as reference.
+  YGLayout& getLayout();
+  uint32_t getLineIndex() const;
+  // 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;
+  YGVector getChildren() const;
+  uint32_t getChildrenCount() const;
+  YGNodeRef getChild(uint32_t index) const;
+  YGNodeRef getNextChild() const;
+  YGConfigRef getConfig() const;
+  bool isDirty() const;
+  std::array<YGValue, 2> getResolvedDimensions() const;
+  YGValue getResolvedDimension(int 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);
+  void setPrintFunc(YGPrintFunc printFunc);
+  void setHasNewLayout(bool hasNewLayout);
+  void setNodeType(YGNodeType nodeTye);
+  void setMeasureFunc(YGMeasureFunc measureFunc);
+  void setBaseLineFunc(YGBaselineFunc baseLineFunc);
+  void setDirtiedFunc(YGDirtiedFunc dirtiedFunc);
+  void setStyle(const YGStyle& style);
+  void setStyleFlexDirection(YGFlexDirection direction);
+  void setStyleAlignContent(YGAlign alignContent);
+  void setLayout(const YGLayout& layout);
+  void setLineIndex(uint32_t lineIndex);
+  void setOwner(YGNodeRef owner);
+  void setChildren(const YGVector& children);
+  void setNextChild(YGNodeRef nextChild);
+  void setConfig(YGConfigRef 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;
+};
diff --git a/dali-toolkit/third-party/yoga/YGNodePrint.cpp b/dali-toolkit/third-party/yoga/YGNodePrint.cpp
new file mode 100644 (file)
index 0000000..ab3aa7c
--- /dev/null
@@ -0,0 +1,231 @@
+/*
+ * Copyright (c) 2017-present, Facebook, Inc.
+ *
+ * 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
diff --git a/dali-toolkit/third-party/yoga/YGNodePrint.h b/dali-toolkit/third-party/yoga/YGNodePrint.h
new file mode 100644 (file)
index 0000000..16259fc
--- /dev/null
@@ -0,0 +1,22 @@
+/**
+ * Copyright (c) 2014-present, Facebook, Inc.
+ *
+ * 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
diff --git a/dali-toolkit/third-party/yoga/YGStyle.cpp b/dali-toolkit/third-party/yoga/YGStyle.cpp
new file mode 100644 (file)
index 0000000..7664dcf
--- /dev/null
@@ -0,0 +1,106 @@
+/**
+ * Copyright (c) 2014-present, Facebook, Inc.
+ *
+ * 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;
+}
+
+bool YGStyle::operator!=(YGStyle style) {
+  return !(*this == style);
+}
+
+YGStyle::~YGStyle() {}
diff --git a/dali-toolkit/third-party/yoga/YGStyle.h b/dali-toolkit/third-party/yoga/YGStyle.h
new file mode 100644 (file)
index 0000000..f0f97bd
--- /dev/null
@@ -0,0 +1,43 @@
+/**
+ * Copyright (c) 2014-present, Facebook, Inc.
+ *
+ * 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"
+#include "Yoga.h"
+
+struct YGStyle {
+  YGDirection direction;
+  YGFlexDirection flexDirection;
+  YGJustify justifyContent;
+  YGAlign alignContent;
+  YGAlign alignItems;
+  YGAlign alignSelf;
+  YGPositionType positionType;
+  YGWrap flexWrap;
+  YGOverflow overflow;
+  YGDisplay display;
+  YGFloatOptional flex;
+  YGFloatOptional flexGrow;
+  YGFloatOptional flexShrink;
+  YGValue flexBasis;
+  std::array<YGValue, YGEdgeCount> margin;
+  std::array<YGValue, YGEdgeCount> position;
+  std::array<YGValue, YGEdgeCount> padding;
+  std::array<YGValue, YGEdgeCount> border;
+  std::array<YGValue, 2> dimensions;
+  std::array<YGValue, 2> minDimensions;
+  std::array<YGValue, 2> maxDimensions;
+  YGFloatOptional aspectRatio;
+
+  YGStyle();
+  // Yoga specific properties, not compatible with flexbox specification
+  bool operator==(const YGStyle& style);
+
+  bool operator!=(YGStyle style);
+  ~YGStyle();
+};
diff --git a/dali-toolkit/third-party/yoga/Yoga-internal.h b/dali-toolkit/third-party/yoga/Yoga-internal.h
new file mode 100644 (file)
index 0000000..be1d963
--- /dev/null
@@ -0,0 +1,100 @@
+/**
+ * Copyright (c) 2014-present, Facebook, Inc.
+ *
+ * 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
+
+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 (!YGFloatIsUndefined(availableWidth) ||
+        !YGFloatIsUndefined(measurement.availableWidth)) {
+      isEqual = isEqual && availableWidth == measurement.availableWidth;
+    }
+    if (!YGFloatIsUndefined(availableHeight) ||
+        !YGFloatIsUndefined(measurement.availableHeight)) {
+      isEqual = isEqual && availableHeight == measurement.availableHeight;
+    }
+    if (!YGFloatIsUndefined(computedWidth) ||
+        !YGFloatIsUndefined(measurement.computedWidth)) {
+      isEqual = isEqual && computedWidth == measurement.computedWidth;
+    }
+    if (!YGFloatIsUndefined(computedHeight) ||
+        !YGFloatIsUndefined(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);
diff --git a/dali-toolkit/third-party/yoga/Yoga.cpp b/dali-toolkit/third-party/yoga/Yoga.cpp
new file mode 100644 (file)
index 0000000..a927ef5
--- /dev/null
@@ -0,0 +1,4054 @@
+/**
+ * Copyright (c) 2014-present, Facebook, Inc.
+ *
+ * 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};
+
+#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) {
+  // 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;
+}
+
+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 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())));
+  }
+
+  if (oldNode->getNextChild() != nullptr) {
+    node->setNextChild(YGNodeDeepClone(oldNode->getNextChild()));
+  }
+
+  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 (uint32_t i = 0; i < root->getChildrenCount(); ++i) {
+    YGConfigFreeRecursive(root->getChild(i));
+  }
+}
+
+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) {
+  free(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();
+}
+
+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();
+}
+
+#define YG_NODE_STYLE_PROPERTY_SETTER_IMPL(                               \
+    type, name, paramName, instanceName)                                  \
+  void YGNodeStyleSet##name(const YGNodeRef node, const type paramName) { \
+    if (node->getStyle().instanceName != paramName) {                     \
+      YGStyle style = node->getStyle();                                   \
+      style.instanceName = paramName;                                     \
+      node->setStyle(style);                                              \
+      node->markDirtyAndPropogate();                                      \
+    }                                                                     \
+  }
+
+#define YG_NODE_STYLE_PROPERTY_SETTER_UNIT_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) {               \
+      YGStyle style = node->getStyle();                                   \
+      style.instanceName = value;                                         \
+      node->setStyle(style);                                              \
+      node->markDirtyAndPropogate();                                      \
+    }                                                                     \
+  }                                                                       \
+                                                                          \
+  void YGNodeStyleSet##name##Percent(                                     \
+      const YGNodeRef node, const type paramName) {                       \
+    YGValue value = {                                                     \
+        YGFloatSanitize(paramName),                                       \
+        YGFloatIsUndefined(paramName) ? YGUnitUndefined : YGUnitPercent,  \
+    };                                                                    \
+    if ((node->getStyle().instanceName.value != value.value &&            \
+         value.unit != YGUnitUndefined) ||                                \
+        node->getStyle().instanceName.unit != value.unit) {               \
+      YGStyle style = node->getStyle();                                   \
+                                                                          \
+      style.instanceName = value;                                         \
+      node->setStyle(style);                                              \
+      node->markDirtyAndPropogate();                                      \
+    }                                                                     \
+  }
+
+#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) {                  \
+      YGStyle style = node->getStyle();                                      \
+      style.instanceName = value;                                            \
+      node->setStyle(style);                                                 \
+      node->markDirtyAndPropogate();                                         \
+    }                                                                        \
+  }                                                                          \
+                                                                             \
+  void YGNodeStyleSet##name##Percent(                                        \
+      const YGNodeRef node, const type paramName) {                          \
+    if (node->getStyle().instanceName.value != YGFloatSanitize(paramName) || \
+        node->getStyle().instanceName.unit != YGUnitPercent) {               \
+      YGStyle style = node->getStyle();                                      \
+      style.instanceName.value = YGFloatSanitize(paramName);                 \
+      style.instanceName.unit =                                              \
+          YGFloatIsUndefined(paramName) ? YGUnitAuto : YGUnitPercent;        \
+      node->setStyle(style);                                                 \
+      node->markDirtyAndPropogate();                                         \
+    }                                                                        \
+  }                                                                          \
+                                                                             \
+  void YGNodeStyleSet##name##Auto(const YGNodeRef node) {                    \
+    if (node->getStyle().instanceName.unit != YGUnitAuto) {                  \
+      YGStyle style = node->getStyle();                                      \
+      style.instanceName.value = 0;                                          \
+      style.instanceName.unit = YGUnitAuto;                                  \
+      node->setStyle(style);                                                 \
+      node->markDirtyAndPropogate();                                         \
+    }                                                                        \
+  }
+
+#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->getStyle().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) {                           \
+    YGValue value = node->getStyle().instanceName;                            \
+    if (value.unit == YGUnitUndefined || value.unit == YGUnitAuto) {          \
+      value.value = YGUndefined;                                              \
+    }                                                                         \
+    return value;                                                             \
+  }
+
+#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) {            \
+      YGStyle style = node->getStyle();                                      \
+      style.instanceName[edge].value = 0;                                    \
+      style.instanceName[edge].unit = YGUnitAuto;                            \
+      node->setStyle(style);                                                 \
+      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) {        \
+      YGStyle style = node->getStyle();                                  \
+      style.instanceName[edge] = value;                                  \
+      node->setStyle(style);                                             \
+      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) {        \
+      YGStyle style = node->getStyle();                                  \
+      style.instanceName[edge] = value;                                  \
+      node->setStyle(style);                                             \
+      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];                        \
+  }
+
+// 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);
+
+// TODO(T26792433): Change the API to accept YGFloatOptional.
+void YGNodeStyleSetFlex(const YGNodeRef node, const float flex) {
+  if (node->getStyle().flex != flex) {
+    YGStyle style = node->getStyle();
+    if (YGFloatIsUndefined(flex)) {
+      style.flex = YGFloatOptional();
+    } else {
+      style.flex = YGFloatOptional(flex);
+    }
+    node->setStyle(style);
+    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) {
+    YGStyle style = node->getStyle();
+    if (YGFloatIsUndefined(flexGrow)) {
+      style.flexGrow = YGFloatOptional();
+    } else {
+      style.flexGrow = YGFloatOptional(flexGrow);
+    }
+    node->setStyle(style);
+    node->markDirtyAndPropogate();
+  }
+}
+
+// TODO(T26792433): Change the API to accept YGFloatOptional.
+void YGNodeStyleSetFlexShrink(const YGNodeRef node, const float flexShrink) {
+  if (node->getStyle().flexShrink != flexShrink) {
+    YGStyle style = node->getStyle();
+    if (YGFloatIsUndefined(flexShrink)) {
+      style.flexShrink = YGFloatOptional();
+    } else {
+      style.flexShrink = YGFloatOptional(flexShrink);
+    }
+    node->setStyle(style);
+    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) {
+    YGStyle style = node->getStyle();
+    style.flexBasis = value;
+    node->setStyle(style);
+    node->markDirtyAndPropogate();
+  }
+}
+
+void YGNodeStyleSetFlexBasisPercent(
+    const YGNodeRef node,
+    const float flexBasisPercent) {
+  if (node->getStyle().flexBasis.value != flexBasisPercent ||
+      node->getStyle().flexBasis.unit != YGUnitPercent) {
+    YGStyle style = node->getStyle();
+    style.flexBasis.value = YGFloatSanitize(flexBasisPercent);
+    style.flexBasis.unit =
+        YGFloatIsUndefined(flexBasisPercent) ? YGUnitAuto : YGUnitPercent;
+    node->setStyle(style);
+    node->markDirtyAndPropogate();
+  }
+}
+
+void YGNodeStyleSetFlexBasisAuto(const YGNodeRef node) {
+  if (node->getStyle().flexBasis.unit != YGUnitAuto) {
+    YGStyle style = node->getStyle();
+    style.flexBasis.value = 0;
+    style.flexBasis.unit = YGUnitAuto;
+    node->setStyle(style);
+    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) {
+    YGStyle style = node->getStyle();
+    style.border[edge] = value;
+    node->setStyle(style);
+    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) {
+    YGStyle style = node->getStyle();
+    style.aspectRatio = YGFloatOptional(aspectRatio);
+    node->setStyle(style);
+    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]);
+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]);
+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;
+
+    const float& marginRow = YGUnwrapFloatOptional(
+        child->getMarginForAxis(YGFlexDirectionRow, ownerWidth));
+    const float& 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;
+
+  const float& marginRow =
+      YGUnwrapFloatOptional(child->getMarginForAxis(YGFlexDirectionRow, width));
+  const float& 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)) {
+    const float& marginAxisColumn = YGUnwrapFloatOptional(
+        node->getMarginForAxis(YGFlexDirectionColumn, ownerWidth));
+    const float& 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 (singleFlexChild != nullptr) {
+        if (child->isNodeFlexible()) {
+          // There is already a flexible child, abort
+          singleFlexChild = nullptr;
+          break;
+        }
+      } else if (
+          child->resolveFlexGrow() > 0.0f &&
+          child->resolveFlexShrink() > 0.0f) {
+        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->getChildrenCount(); 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();
+
+  // 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 &&
+      collectedFlexItemsValues.remainingFreeSpace > 0) {
+    if (style.minDimensions[dim[mainAxis]].unit != YGUnitUndefined &&
+        !YGResolveValue(style.minDimensions[dim[mainAxis]], mainAxisownerSize)
+             .isUndefined()) {
+      collectedFlexItemsValues.remainingFreeSpace = YGFloatMax(
+          0,
+          YGUnwrapFloatOptional(YGResolveValue(
+              style.minDimensions[dim[mainAxis]], mainAxisownerSize)) -
+              (availableInnerMainDim -
+               collectedFlexItemsValues.remainingFreeSpace));
+    } 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;
+    }
+  }
+
+  const float leadingPaddingAndBorderMain = YGUnwrapFloatOptional(
+      node->getLeadingPaddingAndBorder(mainAxis, ownerWidth));
+  collectedFlexItemsValues.mainDim =
+      leadingPaddingAndBorderMain + leadingMainDim;
+  collectedFlexItemsValues.crossDim = 0;
+
+  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);
+
+          // The cross dimension is the max of the elements dimension since
+          // there can only be one element in that cross dimension.
+          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 += YGUnwrapFloatOptional(
+      node->getTrailingPaddingAndBorder(mainAxis, ownerWidth));
+}
+
+//
+// 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
+  if (performLayout && (lineCount > 1 || YGIsBaselineLayout(node)) &&
+      !YGFloatIsUndefined(availableInnerCrossDim)) {
+    const float remainingAlignContentDim = availableInnerCrossDim - totalLineCrossDim;
+
+    float crossDimLead = 0;
+    float currentLead = leadingPaddingAndBorderCross;
+
+    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 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 && !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 (gPrintTree) {
+      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 (gPrintTree) {
+        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);
+}
diff --git a/dali-toolkit/third-party/yoga/Yoga.h b/dali-toolkit/third-party/yoga/Yoga.h
new file mode 100644 (file)
index 0000000..25eb0eb
--- /dev/null
@@ -0,0 +1,327 @@
+/**
+ * Copyright (c) 2014-present, Facebook, Inc.
+ *
+ * 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;
+
+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 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);
+
+#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);
+
+void* YGNodeGetContext(YGNodeRef node);
+void YGNodeSetContext(YGNodeRef node, void* context);
+YGMeasureFunc YGNodeGetMeasureFunc(YGNodeRef node);
+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);
+
+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);
+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.
+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);
+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
index cf899ef..9203cc9 100644 (file)
@@ -1,6 +1,6 @@
 Name:       dali-toolkit
 Summary:    Dali 3D engine Toolkit
-Version:    1.3.24
+Version:    1.3.25
 Release:    1
 Group:      System/Libraries
 License:    Apache-2.0 and BSD-3-Clause and MIT
index dc7641b..b93b605 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2018 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
 #include <utils/v8-utils.h>
 
 // The plugin factories
-extern "C" DALI_EXPORT_API Dali::Toolkit::ScriptPlugin* CreateScriptPlugin(void)
+extern "C" DALI_TOOLKIT_API Dali::Toolkit::ScriptPlugin* CreateScriptPlugin(void)
 {
   return new Dali::V8Plugin::DaliScriptV8;
 }
 
-extern "C" DALI_EXPORT_API void DestroyScriptPlugin(Dali::Toolkit::ScriptPlugin* plugin)
+extern "C" DALI_TOOLKIT_API void DestroyScriptPlugin(Dali::Toolkit::ScriptPlugin* plugin)
 {
   delete plugin;
 }
index 61d265b..8177f3b 100644 (file)
@@ -2,7 +2,7 @@
 #define __DALI_V8PLUGIN_SCRIPT_H__
 
 /*
- * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2018 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -20,9 +20,9 @@
 
 // EXTERNAL INCLUDES
 #include <dali-toolkit/devel-api/scripting/script-plugin.h>
-#include <dali/public-api/common/dali-common.h>
+#include <dali-toolkit/public-api/dali-toolkit-common.h>
 
-namespace Dali DALI_IMPORT_API
+namespace Dali DALI_TOOLKIT_API
 {
 
 namespace V8Plugin
index f1767e4..c1013fe 100644 (file)
@@ -2,7 +2,7 @@
 #define __DALI_V8PLUGIN_DALI_WRAP_H__
 
 /*
- * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2018 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -20,9 +20,9 @@
 
 // EXTERNAL INCLUDES
 #include <v8.h>
-#include <dali/public-api/common/dali-common.h>
 
 // INTERNAL INCLUDES
+#include <dali-toolkit/public-api/dali-toolkit-common.h>
 #include <garbage-collector/garbage-collector.h>
 
 #include <module-loader/module-loader.h>