From: Anton Obzhirov Date: Tue, 15 May 2018 08:57:23 +0000 (+0100) Subject: Rebase of facebook flexbox to yoga X-Git-Tag: dali_1.3.25~4 X-Git-Url: http://review.tizen.org/git/?p=platform%2Fcore%2Fuifw%2Fdali-toolkit.git;a=commitdiff_plain;h=334b065ec7bae11e7ac483b2f96e5545ce7363f4 Rebase of facebook flexbox to yoga Change-Id: I5e9298aa22453a79393cc90d5a8e2803d38b51dd --- diff --git a/automated-tests/src/dali-toolkit-third-party/CMakeLists.txt b/automated-tests/src/dali-toolkit-third-party/CMakeLists.txt index 43c4be3..e9ff79a 100644 --- a/automated-tests/src/dali-toolkit-third-party/CMakeLists.txt +++ b/automated-tests/src/dali-toolkit-third-party/CMakeLists.txt @@ -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 index 58c42c4..0000000 --- a/automated-tests/src/dali-toolkit-third-party/facebook-flexbox/layout-test-utils.c +++ /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 - -#ifdef _MSC_VER -#include -#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 index 7513141..0000000 --- a/automated-tests/src/dali-toolkit-third-party/facebook-flexbox/layout-test-utils.h +++ /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 -#include - -#include - -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); diff --git a/automated-tests/src/dali-toolkit-third-party/utc-Dali-Flexbox-Layout.cpp b/automated-tests/src/dali-toolkit-third-party/utc-Dali-Flexbox-Layout.cpp index 83f932e..832d73e 100644 --- a/automated-tests/src/dali-toolkit-third-party/utc-Dali-Flexbox-Layout.cpp +++ b/automated-tests/src/dali-toolkit-third-party/utc-Dali-Flexbox-Layout.cpp @@ -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. @@ -16,11 +16,61 @@ */ #include - -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 +#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(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 index 0000000..a319cf1 --- /dev/null +++ b/automated-tests/src/dali-toolkit-third-party/yoga/YGAbsolutePositionTest.cpp @@ -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 +#include + +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 index 0000000..7cd5c09 --- /dev/null +++ b/automated-tests/src/dali-toolkit-third-party/yoga/YGAlignContentTest.cpp @@ -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 +#include + +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 index 0000000..fd5e424 --- /dev/null +++ b/automated-tests/src/dali-toolkit-third-party/yoga/YGAlignItemsTest.cpp @@ -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 +#include + +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 index 0000000..00bb7b9 --- /dev/null +++ b/automated-tests/src/dali-toolkit-third-party/yoga/YGAlignSelfTest.cpp @@ -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 +#include + +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 index 0000000..fb3f073 --- /dev/null +++ b/automated-tests/src/dali-toolkit-third-party/yoga/YGAndroidNewsFeed.cpp @@ -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 +#include + +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 index 0000000..c49133e --- /dev/null +++ b/automated-tests/src/dali-toolkit-third-party/yoga/YGAspectRatioTest.cpp @@ -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 +#include +#include + +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 index 0000000..c8d1ff1 --- /dev/null +++ b/automated-tests/src/dali-toolkit-third-party/yoga/YGBaselineFuncTest.cpp @@ -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 +#include +#include + +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 index 0000000..d4e6376 --- /dev/null +++ b/automated-tests/src/dali-toolkit-third-party/yoga/YGBorderTest.cpp @@ -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 +#include + +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 index 0000000..9cbbe4e --- /dev/null +++ b/automated-tests/src/dali-toolkit-third-party/yoga/YGComputedMarginTest.cpp @@ -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 +#include + +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 index 0000000..bf31fe7 --- /dev/null +++ b/automated-tests/src/dali-toolkit-third-party/yoga/YGComputedPaddingTest.cpp @@ -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 +#include + +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 index 0000000..ca14386 --- /dev/null +++ b/automated-tests/src/dali-toolkit-third-party/yoga/YGDefaultValuesTest.cpp @@ -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 +#include + +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 index 0000000..42fc123 --- /dev/null +++ b/automated-tests/src/dali-toolkit-third-party/yoga/YGDimensionTest.cpp @@ -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 +#include + +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 index 0000000..bb0c05d --- /dev/null +++ b/automated-tests/src/dali-toolkit-third-party/yoga/YGDirtiedTest.cpp @@ -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 +#include + +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 index 0000000..d951f53 --- /dev/null +++ b/automated-tests/src/dali-toolkit-third-party/yoga/YGDirtyMarkingTest.cpp @@ -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 +#include + +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 index 0000000..45256ac --- /dev/null +++ b/automated-tests/src/dali-toolkit-third-party/yoga/YGDisplayTest.cpp @@ -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 +#include + +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 index 0000000..02de146 --- /dev/null +++ b/automated-tests/src/dali-toolkit-third-party/yoga/YGEdgeTest.cpp @@ -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 +#include + +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 index 0000000..93e0942 --- /dev/null +++ b/automated-tests/src/dali-toolkit-third-party/yoga/YGFlexDirectionTest.cpp @@ -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 +#include + +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 index 0000000..e1a8ba8 --- /dev/null +++ b/automated-tests/src/dali-toolkit-third-party/yoga/YGFlexTest.cpp @@ -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 +#include + +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 index 0000000..e8e5458 --- /dev/null +++ b/automated-tests/src/dali-toolkit-third-party/yoga/YGFlexWrapTest.cpp @@ -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 +#include + +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 index 0000000..39cb20a --- /dev/null +++ b/automated-tests/src/dali-toolkit-third-party/yoga/YGHadOverflowTest.cpp @@ -0,0 +1,127 @@ +// Copyright 2004-present Facebook. All Rights Reserved. + +#include +#include + +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 index 0000000..a557b3d --- /dev/null +++ b/automated-tests/src/dali-toolkit-third-party/yoga/YGInfiniteHeightTest.cpp @@ -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 +#include + +// 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 index 0000000..e5d4216 --- /dev/null +++ b/automated-tests/src/dali-toolkit-third-party/yoga/YGJustifyContentTest.cpp @@ -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 +#include + +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 index 0000000..a04e87d --- /dev/null +++ b/automated-tests/src/dali-toolkit-third-party/yoga/YGLayoutDiffingTest.cpp @@ -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 +#include +#include + +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 index 0000000..1b84ee6 --- /dev/null +++ b/automated-tests/src/dali-toolkit-third-party/yoga/YGLoggerTest.cpp @@ -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 +#include +#include + +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 = "
"; + 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 = "
"; + 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 = "
\n " + "
\n
\n
"; + 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 index 0000000..593cd2f --- /dev/null +++ b/automated-tests/src/dali-toolkit-third-party/yoga/YGMarginTest.cpp @@ -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 +#include + +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 index 0000000..91f1891 --- /dev/null +++ b/automated-tests/src/dali-toolkit-third-party/yoga/YGMeasureCacheTest.cpp @@ -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 +#include +#include + +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 index 0000000..8e52894 --- /dev/null +++ b/automated-tests/src/dali-toolkit-third-party/yoga/YGMeasureModeTest.cpp @@ -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 +#include +#include + +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 index 0000000..aea2cd5 --- /dev/null +++ b/automated-tests/src/dali-toolkit-third-party/yoga/YGMeasureTest.cpp @@ -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 +#include +#include + +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 index 0000000..515bdfd --- /dev/null +++ b/automated-tests/src/dali-toolkit-third-party/yoga/YGMinMaxDimensionTest.cpp @@ -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 +#include + +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 index 0000000..9d6bb48 --- /dev/null +++ b/automated-tests/src/dali-toolkit-third-party/yoga/YGNodeChildTest.cpp @@ -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 +#include + +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 index 0000000..f0d3752 --- /dev/null +++ b/automated-tests/src/dali-toolkit-third-party/yoga/YGPaddingTest.cpp @@ -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 +#include + +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 index 0000000..2be0459 --- /dev/null +++ b/automated-tests/src/dali-toolkit-third-party/yoga/YGPercentageTest.cpp @@ -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 +#include + +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 index 0000000..9df861a --- /dev/null +++ b/automated-tests/src/dali-toolkit-third-party/yoga/YGPersistenceTest.cpp @@ -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 +#include + +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 index 0000000..cbda524 --- /dev/null +++ b/automated-tests/src/dali-toolkit-third-party/yoga/YGRelayoutTest.cpp @@ -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 +#include + +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 index 0000000..82eba44 --- /dev/null +++ b/automated-tests/src/dali-toolkit-third-party/yoga/YGRoundingFunctionTest.cpp @@ -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 +#include +#include + +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 index 0000000..33820c4 --- /dev/null +++ b/automated-tests/src/dali-toolkit-third-party/yoga/YGRoundingMeasureFuncTest.cpp @@ -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 +#include +#include + +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 index 0000000..303e9f0 --- /dev/null +++ b/automated-tests/src/dali-toolkit-third-party/yoga/YGRoundingTest.cpp @@ -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 +#include + +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 index 0000000..3fbcb30 --- /dev/null +++ b/automated-tests/src/dali-toolkit-third-party/yoga/YGSizeOverflowTest.cpp @@ -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 +#include + +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 index 0000000..08b7be2 --- /dev/null +++ b/automated-tests/src/dali-toolkit-third-party/yoga/YGStyleTest.cpp @@ -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 +#include +#include + +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 index 0000000..3c4771d --- /dev/null +++ b/automated-tests/src/dali-toolkit-third-party/yoga/YGTraversalTest.cpp @@ -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 +#include + +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 visited; + YGTraversePreOrder(root, [&visited](YGNodeRef node) { + visited.push_back(node); + }); + + const std::vector 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 index 0000000..273f22a --- /dev/null +++ b/automated-tests/src/dali-toolkit-third-party/yoga/YGTreeMutationTest.cpp @@ -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 +#include + +static std::vector getChildren(YGNodeRef const node) +{ + const uint32_t count = YGNodeGetChildCount(node); + std::vector 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 children = getChildren(root); + const std::vector expectedChildren = {root_child0, root_child1}; + ASSERT_EQ(children, expectedChildren); + + const std::vector owners = {YGNodeGetOwner(root_child0), YGNodeGetOwner(root_child1)}; + const std::vector 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 children = getChildren(root); + const std::vector expectedChildren = {}; + ASSERT_EQ(children, expectedChildren); + + const std::vector owners = {YGNodeGetOwner(root_child0), YGNodeGetOwner(root_child1)}; + const std::vector 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 children = getChildren(root); + const std::vector expectedChildren = {root_child2, root_child3}; + ASSERT_EQ(children, expectedChildren); + + const std::vector owners = {YGNodeGetOwner(root_child0), YGNodeGetOwner(root_child1)}; + const std::vector 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 children = getChildren(root); + const std::vector expectedChildren = {root_child2, root_child1, root_child3}; + ASSERT_EQ(children, expectedChildren); + + const std::vector owners = { + YGNodeGetOwner(root_child0), + YGNodeGetOwner(root_child1), + YGNodeGetOwner(root_child2), + YGNodeGetOwner(root_child3) + }; + const std::vector 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 index 0000000..92e7c8a --- /dev/null +++ b/automated-tests/src/dali-toolkit-third-party/yoga/YGZeroOutLayoutRecursivlyTest.cpp @@ -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 +#include + +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); +} diff --git a/dali-toolkit/internal/controls/flex-container/flex-container-impl.cpp b/dali-toolkit/internal/controls/flex-container/flex-container-impl.cpp index fec5df5..485cd59 100755 --- a/dali-toolkit/internal/controls/flex-container/flex-container-impl.cpp +++ b/dali-toolkit/internal/controls/flex-container/flex-container-impl.cpp @@ -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( 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( mFlexDirection ); + YGNodeStyleSetFlexDirection( mRootNode.node, static_cast( 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( mFlexWrap ); + YGNodeStyleSetFlexWrap( mRootNode.node, static_cast( 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( mJustifyContent ); + YGNodeStyleSetJustifyContent( mRootNode.node, static_cast( 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( mAlignItems ); + YGNodeStyleSetAlignItems( mRootNode.node, static_cast( 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( mAlignContent ); + YGNodeStyleSetAlignContent( mRootNode.node, static_cast( 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(); + YGNodeStyleSetFlex( childNode, childActor.GetProperty( Toolkit::FlexContainer::ChildProperty::FLEX ).Get() ); } 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(alignSelf) ); } - childNode->style.align_self = static_cast(alignSelf); if( childActor.GetPropertyType( Toolkit::FlexContainer::ChildProperty::FLEX_MARGIN ) != Property::NONE ) { Vector4 flexMargin = childActor.GetProperty( Toolkit::FlexContainer::ChildProperty::FLEX_MARGIN ).Get(); - 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( mContentDirection ); - mRootNode.node->style.flex_direction = static_cast( mFlexDirection ); - mRootNode.node->style.flex_wrap = static_cast( mFlexWrap ); - mRootNode.node->style.justify_content = static_cast( mJustifyContent ); - mRootNode.node->style.align_items = static_cast( mAlignItems ); - mRootNode.node->style.align_content = static_cast( mAlignContent ); - - // Set callbacks. - mRootNode.node->get_child = GetChildNodeAtIndex; - mRootNode.node->is_dirty = IsNodeDirty; + YGNodeStyleSetFlexDirection( mRootNode.node, static_cast( mFlexDirection ) ); + YGNodeStyleSetFlexWrap( mRootNode.node, static_cast( mFlexWrap ) ); + YGNodeStyleSetJustifyContent( mRootNode.node, static_cast( mJustifyContent ) ); + YGNodeStyleSetAlignItems( mRootNode.node, static_cast( mAlignItems ) ); + YGNodeStyleSetAlignContent( mRootNode.node, static_cast( mAlignContent ) ); // Make self as keyboard focusable and focus group self.SetKeyboardFocusable( true ); diff --git a/dali-toolkit/internal/controls/flex-container/flex-container-impl.h b/dali-toolkit/internal/controls/flex-container/flex-container-impl.h index 71fec8e..9b8b9e9 100755 --- a/dali-toolkit/internal/controls/flex-container/flex-container-impl.h +++ b/dali-toolkit/internal/controls/flex-container/flex-container-impl.h @@ -24,10 +24,7 @@ // INTERNAL INCLUDES #include #include -extern "C" -{ -#include -} +#include 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; diff --git a/dali-toolkit/third-party/facebook-flexbox/layout.c b/dali-toolkit/third-party/facebook-flexbox/layout.c deleted file mode 100644 index 618d01b..0000000 --- a/dali-toolkit/third-party/facebook-flexbox/layout.c +++ /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 -#include -#include -#include - -// 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 -#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) { - // 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 . - 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 . - 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 . - 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 . - 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; - } - - // 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; - } - } - - // 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 - ); - } - - // 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; - } - - // - // - // Note(prenaux): More than one line, we need to layout the crossAxis - // according to alignContent. - // - // Note that we could probably remove 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; - } - } - - // 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); - } - } - } - - // 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 index d6ad495..0000000 --- a/dali-toolkit/third-party/facebook-flexbox/layout.h +++ /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 -#ifndef __cplusplus -#include -#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 diff --git a/dali-toolkit/third-party/file.list b/dali-toolkit/third-party/file.list index 53e027f..54dd713 100644 --- a/dali-toolkit/third-party/file.list +++ b/dali-toolkit/third-party/file.list @@ -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 index 0000000..6fa8df8 --- /dev/null +++ b/dali-toolkit/third-party/yoga/Utils.cpp @@ -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 index 0000000..6c95b1e --- /dev/null +++ b/dali-toolkit/third-party/yoga/Utils.h @@ -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 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 +bool YGFloatArrayEqual( + const std::array& val1, + const std::array& 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(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 index 0000000..5cee527 --- /dev/null +++ b/dali-toolkit/third-party/yoga/YGConfig.cpp @@ -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 + 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 index 0000000..0f655d1 --- /dev/null +++ b/dali-toolkit/third-party/yoga/YGConfig.h @@ -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 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 index 0000000..7f16628 --- /dev/null +++ b/dali-toolkit/third-party/yoga/YGEnums.cpp @@ -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 index 0000000..0976d78 --- /dev/null +++ b/dali-toolkit/third-party/yoga/YGEnums.h @@ -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 index 0000000..00bfc71 --- /dev/null +++ b/dali-toolkit/third-party/yoga/YGFloatOptional.cpp @@ -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 +#include +#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 index 0000000..21af2a8 --- /dev/null +++ b/dali-toolkit/third-party/yoga/YGFloatOptional.h @@ -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 index 0000000..6e367bd --- /dev/null +++ b/dali-toolkit/third-party/yoga/YGLayout.cpp @@ -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 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 index 0000000..46ca130 --- /dev/null +++ b/dali-toolkit/third-party/yoga/YGLayout.h @@ -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 position; + std::array dimensions; + std::array margin; + std::array border; + std::array 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 + cachedMeasurements; + std::array 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 index 0000000..15ed81d --- /dev/null +++ b/dali-toolkit/third-party/yoga/YGMacros.h @@ -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 index 0000000..64a47d3 --- /dev/null +++ b/dali-toolkit/third-party/yoga/YGNode.cpp @@ -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 +#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(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 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::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 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(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::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 index 0000000..96541a5 --- /dev/null +++ b/dali-toolkit/third-party/yoga/YGNode.h @@ -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 +#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 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 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 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 index 0000000..ab3aa7c --- /dev/null +++ b/dali-toolkit/third-party/yoga/YGNodePrint.cpp @@ -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 +#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& 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 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& edges) { + if (areFourValuesEqual(edges)) { + appendNumberIfNotZero(base, key, edges[YGEdgeLeft]); + } else { + for (int edge = YGEdgeLeft; edge != YGEdgeAll; ++edge) { + string str = key + "-" + YGEdgeToString(static_cast(edge)); + appendNumberIfNotZero(base, str, edges[edge]); + } + } +} + +static void appendEdgeIfNotUndefined( + string* base, + const string& str, + const std::array& 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, "
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(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, "
"); +} +} // 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 index 0000000..16259fc --- /dev/null +++ b/dali-toolkit/third-party/yoga/YGNodePrint.h @@ -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 + +#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 index 0000000..7664dcf --- /dev/null +++ b/dali-toolkit/third-party/yoga/YGStyle.cpp @@ -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 kYGDefaultEdgeValuesUnit = { + {kYGValueUndefined, + kYGValueUndefined, + kYGValueUndefined, + kYGValueUndefined, + kYGValueUndefined, + kYGValueUndefined, + kYGValueUndefined, + kYGValueUndefined, + kYGValueUndefined}}; + +const std::array kYGDefaultDimensionValuesAutoUnit = { + {kYGValueAuto, kYGValueAuto}}; + +const std::array 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 index 0000000..f0f97bd --- /dev/null +++ b/dali-toolkit/third-party/yoga/YGStyle.h @@ -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 margin; + std::array position; + std::array padding; + std::array border; + std::array dimensions; + std::array minDimensions; + std::array 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 index 0000000..be1d9632 --- /dev/null +++ b/dali-toolkit/third-party/yoga/Yoga-internal.h @@ -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 +#include +#include +#include +#include "Yoga.h" + +using YGVector = std::vector; + +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 trailing; +extern const std::array leading; +extern bool YGValueEqual(const YGValue a, const YGValue b); +extern const YGValue YGValueUndefined; +extern const YGValue YGValueAuto; +extern const YGValue YGValueZero; + +template +bool YGValueArrayEqual( + const std::array val1, + const std::array 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& 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 index 0000000..a927ef5 --- /dev/null +++ b/dali-toolkit/third-party/yoga/Yoga.cpp @@ -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 +#include +#include +#include "Utils.h" +#include "YGNode.h" +#include "YGNodePrint.h" +#include "Yoga-internal.h" +#ifdef _MSC_VER +#include + +/* 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 +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& 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 &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 &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(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 leading = { + {YGEdgeTop, YGEdgeBottom, YGEdgeLeft, YGEdgeRight}}; + +const std::array trailing = { + {YGEdgeBottom, YGEdgeTop, YGEdgeRight, YGEdgeLeft}}; +static const std::array pos = {{ + YGEdgeTop, + YGEdgeBottom, + YGEdgeLeft, + YGEdgeRight, +}}; + +static const std::array 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& f) { + for (YGNodeRef node : children) { + f(node); + YGTraverseChildrenPreOrder(node->getChildren(), f); + } +} + +void YGTraversePreOrder(YGNodeRef const node, std::function&& 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 index 0000000..25eb0eb --- /dev/null +++ b/dali-toolkit/third-party/yoga/Yoga.h @@ -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 +#include +#include +#include +#include +#include + +#ifndef __cplusplus +#include +#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 +#include + +// Calls f on each node in the tree including the given node argument. +extern void YGTraversePreOrder(YGNodeRef const node, std::function&& f); + +extern void YGNodeSetChildren( + YGNodeRef const owner, + const std::vector& children); + +#endif