From db0904ce81584c39080a4b15b39cca5b48476b7f Mon Sep 17 00:00:00 2001 From: Nick Gerleman Date: Mon, 6 Nov 2023 17:55:33 -0800 Subject: [PATCH] Allow lazy resolution of edge dimension values Summary: This follows the previous patterns used for `Gutters` and `Dimension`, where we hide CompactValue array implementation from `yoga::Style` callers. This allows a single read of a style to only need access to the resolved values of a single edge, vs all edges. This is cheap now because the interface is the representation, but gets expensive if `StyleValuePool` is the actual implementation. This prevents us from needing to resolve nine dimensions, in order to read a single value like `marginLeft`. Doing this, in the new style, also lets us remove `IdxRef` from the API. We unroll the structure dependent parts in the props parsing code, for something more verbose, but also a bit clearer. Changelog: [Internal] Differential Revision: D50998164 fbshipit-source-id: 5f61c68b60782fadf7db4ae40010ae4dd2abc7a1 --- tests/YGStyleAccessorsTest.cpp | 216 --------------------------------- yoga/YGNodeStyle.cpp | 35 +++--- yoga/algorithm/FlexDirection.h | 1 + yoga/debug/AssertFatal.cpp | 2 + yoga/debug/AssertFatal.h | 5 +- yoga/debug/NodeToString.cpp | 47 ++----- yoga/node/Node.cpp | 113 +++++++++-------- yoga/node/Node.h | 15 +-- yoga/style/Style.h | 70 +++-------- 9 files changed, 112 insertions(+), 392 deletions(-) delete mode 100644 tests/YGStyleAccessorsTest.cpp diff --git a/tests/YGStyleAccessorsTest.cpp b/tests/YGStyleAccessorsTest.cpp deleted file mode 100644 index cec5c7e2b4..0000000000 --- a/tests/YGStyleAccessorsTest.cpp +++ /dev/null @@ -1,216 +0,0 @@ -/* - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - * 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 -#include -#include - -#define ACCESSOR_TESTS_1(NAME, X) \ - style.NAME() = X; \ - ASSERT_EQ(style.NAME(), X); -#define ACCESSOR_TESTS_2(NAME, X, ...) \ - ACCESSOR_TESTS_1(NAME, X); \ - ACCESSOR_TESTS_1(NAME, __VA_ARGS__); -#define ACCESSOR_TESTS_3(NAME, X, ...) \ - ACCESSOR_TESTS_1(NAME, X); \ - ACCESSOR_TESTS_2(NAME, __VA_ARGS__); -#define ACCESSOR_TESTS_4(NAME, X, ...) \ - ACCESSOR_TESTS_1(NAME, X); \ - ACCESSOR_TESTS_3(NAME, __VA_ARGS__); -#define ACCESSOR_TESTS_5(NAME, X, ...) \ - ACCESSOR_TESTS_1(NAME, X); \ - ACCESSOR_TESTS_4(NAME, __VA_ARGS__) - -#define ACCESSOR_TESTS_N(a, b, c, d, e, COUNT, ...) ACCESSOR_TESTS_##COUNT -#define ACCESSOR_TESTS(...) ACCESSOR_TESTS_N(__VA_ARGS__, 5, 4, 3, 2, 1) - -#define INDEX_ACCESSOR_TESTS_1(NAME, IDX, X) \ - { \ - auto style = Style{}; \ - style.NAME()[IDX] = X; \ - ASSERT_EQ(style.NAME()[IDX], X); \ - auto asArray = decltype(std::declval().NAME()){X}; \ - style.NAME() = asArray; \ - ASSERT_EQ(static_cast(style.NAME()), asArray); \ - } - -#define INDEX_ACCESSOR_TESTS_2(NAME, IDX, X, Y) \ - INDEX_ACCESSOR_TESTS_1(NAME, IDX, X) \ - INDEX_ACCESSOR_TESTS_1(NAME, IDX, Y) - -#define INDEX_ACCESSOR_TESTS_3(NAME, IDX, X, ...) \ - INDEX_ACCESSOR_TESTS_1(NAME, IDX, X) \ - INDEX_ACCESSOR_TESTS_2(NAME, IDX, __VA_ARGS__) - -#define INDEX_ACCESSOR_TESTS_4(NAME, IDX, X, ...) \ - INDEX_ACCESSOR_TESTS_1(NAME, IDX, X) \ - INDEX_ACCESSOR_TESTS_3(NAME, IDX, __VA_ARGS__) - -#define INDEX_ACCESSOR_TESTS_5(NAME, IDX, X, ...) \ - INDEX_ACCESSOR_TESTS_1(NAME, IDX, X) \ - INDEX_ACCESSOR_TESTS_4(NAME, IDX, __VA_ARGS__) - -#define INDEX_ACCESSOR_TESTS_N(a, b, c, d, e, COUNT, ...) \ - INDEX_ACCESSOR_TESTS_##COUNT -#define INDEX_ACCESSOR_TESTS(...) \ - INDEX_ACCESSOR_TESTS_N(__VA_ARGS__, 5, 4, 3, 2, 1) - -// test macro for up to 5 values. If more are needed, extend the macros above. -#define ACCESSOR_TEST(NAME, DEFAULT_VAL, ...) \ - TEST(Style, style_##NAME##_access) { \ - auto style = Style{}; \ - ASSERT_EQ(style.NAME(), DEFAULT_VAL); \ - ACCESSOR_TESTS(__VA_ARGS__)(NAME, __VA_ARGS__) \ - } - -#define INDEX_ACCESSOR_TEST(NAME, DEFAULT_VAL, IDX, ...) \ - TEST(Style, style_##NAME##_access) { \ - ASSERT_EQ(Style{}.NAME()[IDX], DEFAULT_VAL); \ - INDEX_ACCESSOR_TESTS(__VA_ARGS__)(NAME, IDX, __VA_ARGS__) \ - } - -namespace facebook::yoga { - -// TODO: MSVC doesn't like the macros -#ifndef _MSC_VER - -ACCESSOR_TEST( - direction, - Direction::Inherit, - Direction::LTR, - Direction::RTL, - Direction::Inherit); - -ACCESSOR_TEST( - flexDirection, - FlexDirection::Column, - FlexDirection::ColumnReverse, - FlexDirection::RowReverse, - FlexDirection::Row) - -ACCESSOR_TEST( - justifyContent, - Justify::FlexStart, - Justify::FlexEnd, - Justify::SpaceAround, - Justify::FlexStart, - Justify::SpaceEvenly) - -ACCESSOR_TEST( - alignContent, - Align::FlexStart, - Align::Auto, - Align::FlexStart, - Align::Center, - Align::FlexEnd, - Align::Stretch) - -ACCESSOR_TEST( - alignItems, - Align::Stretch, - Align::FlexStart, - Align::FlexEnd, - Align::Baseline, - Align::SpaceBetween, - Align::SpaceAround) - -ACCESSOR_TEST( - alignSelf, - Align::Auto, - Align::FlexStart, - Align::Center, - Align::Auto, - Align::FlexEnd, - Align::Stretch) - -ACCESSOR_TEST( - positionType, - PositionType::Static, - PositionType::Absolute, - PositionType::Relative) - -ACCESSOR_TEST(flexWrap, Wrap::NoWrap, Wrap::Wrap, Wrap::WrapReverse) - -ACCESSOR_TEST(overflow, Overflow::Visible, Overflow::Hidden, Overflow::Scroll) - -ACCESSOR_TEST(display, Display::Flex, Display::None, Display::Flex) - -ACCESSOR_TEST( - flex, - FloatOptional{}, - FloatOptional{123.45f}, - FloatOptional{-9.87f}, - FloatOptional{}) - -ACCESSOR_TEST( - flexGrow, - FloatOptional{}, - FloatOptional{123.45f}, - FloatOptional{-9.87f}, - FloatOptional{}) - -ACCESSOR_TEST( - flexShrink, - FloatOptional{}, - FloatOptional{123.45f}, - FloatOptional{-9.87f}, - FloatOptional{}) - -ACCESSOR_TEST( - flexBasis, - CompactValue::ofAuto(), - CompactValue::ofUndefined(), - CompactValue::ofAuto(), - CompactValue::of(7777.77f), - CompactValue::of(-100.0f)) - -INDEX_ACCESSOR_TEST( - position, - CompactValue::ofUndefined(), - YGEdgeBottom, - CompactValue::ofAuto(), - CompactValue::ofUndefined(), - CompactValue::of(7777.77f), - CompactValue::of(-100.0f)) - -INDEX_ACCESSOR_TEST( - margin, - CompactValue::ofUndefined(), - YGEdgeTop, - CompactValue::ofAuto(), - CompactValue::ofUndefined(), - CompactValue::of(7777.77f), - CompactValue::of(-100.0f)) - -INDEX_ACCESSOR_TEST( - padding, - CompactValue::ofUndefined(), - YGEdgeAll, - CompactValue::of(7777.77f), - CompactValue::ofUndefined(), - CompactValue::of(-100.0f)) - -INDEX_ACCESSOR_TEST( - border, - CompactValue::ofUndefined(), - YGEdgeHorizontal, - CompactValue::of(-7777.77f), - CompactValue::ofUndefined()) - -ACCESSOR_TEST( - aspectRatio, - FloatOptional{}, - FloatOptional{-123.45f}, - FloatOptional{9876.5f}, - FloatOptional{0.0f}, - FloatOptional{}); - -#endif - -} // namespace facebook::yoga diff --git a/yoga/YGNodeStyle.cpp b/yoga/YGNodeStyle.cpp index 57d352cd01..b2173bbe5e 100644 --- a/yoga/YGNodeStyle.cpp +++ b/yoga/YGNodeStyle.cpp @@ -237,53 +237,52 @@ YGValue YGNodeStyleGetFlexBasis(const YGNodeConstRef node) { void YGNodeStyleSetPosition(YGNodeRef node, YGEdge edge, float points) { auto value = CompactValue::ofMaybe(points); - updateIndexedStyleProp( - node, &Style::position, edge, value); + updateIndexedStyleProp<&Style::position, &Style::setPosition>( + node, edge, value); } void YGNodeStyleSetPositionPercent(YGNodeRef node, YGEdge edge, float percent) { auto value = CompactValue::ofMaybe(percent); - updateIndexedStyleProp( - node, &Style::position, edge, value); + updateIndexedStyleProp<&Style::position, &Style::setPosition>( + node, edge, value); } YGValue YGNodeStyleGetPosition(YGNodeConstRef node, YGEdge edge) { - return resolveRef(node)->getStyle().position()[edge]; + return resolveRef(node)->getStyle().position(edge); } void YGNodeStyleSetMargin(YGNodeRef node, YGEdge edge, float points) { auto value = CompactValue::ofMaybe(points); - updateIndexedStyleProp(node, &Style::margin, edge, value); + updateIndexedStyleProp<&Style::margin, &Style::setMargin>(node, edge, value); } - void YGNodeStyleSetMarginPercent(YGNodeRef node, YGEdge edge, float percent) { auto value = CompactValue::ofMaybe(percent); - updateIndexedStyleProp(node, &Style::margin, edge, value); + updateIndexedStyleProp<&Style::margin, &Style::setMargin>(node, edge, value); } void YGNodeStyleSetMarginAuto(YGNodeRef node, YGEdge edge) { - updateIndexedStyleProp( - node, &Style::margin, edge, CompactValue::ofAuto()); + updateIndexedStyleProp<&Style::margin, &Style::setMargin>( + node, edge, CompactValue::ofAuto()); } YGValue YGNodeStyleGetMargin(YGNodeConstRef node, YGEdge edge) { - return resolveRef(node)->getStyle().margin()[edge]; + return resolveRef(node)->getStyle().margin(edge); } void YGNodeStyleSetPadding(YGNodeRef node, YGEdge edge, float points) { auto value = CompactValue::ofMaybe(points); - updateIndexedStyleProp( - node, &Style::padding, edge, value); + updateIndexedStyleProp<&Style::padding, &Style::setPadding>( + node, edge, value); } void YGNodeStyleSetPaddingPercent(YGNodeRef node, YGEdge edge, float percent) { auto value = CompactValue::ofMaybe(percent); - updateIndexedStyleProp( - node, &Style::padding, edge, value); + updateIndexedStyleProp<&Style::padding, &Style::setPadding>( + node, edge, value); } YGValue YGNodeStyleGetPadding(YGNodeConstRef node, YGEdge edge) { - return resolveRef(node)->getStyle().padding()[edge]; + return resolveRef(node)->getStyle().padding(edge); } void YGNodeStyleSetBorder( @@ -291,11 +290,11 @@ void YGNodeStyleSetBorder( const YGEdge edge, const float border) { auto value = CompactValue::ofMaybe(border); - updateIndexedStyleProp(node, &Style::border, edge, value); + updateIndexedStyleProp<&Style::border, &Style::setBorder>(node, edge, value); } float YGNodeStyleGetBorder(const YGNodeConstRef node, const YGEdge edge) { - auto border = resolveRef(node)->getStyle().border()[edge]; + auto border = resolveRef(node)->getStyle().border(edge); if (border.isUndefined() || border.isAuto()) { return YGUndefined; } diff --git a/yoga/algorithm/FlexDirection.h b/yoga/algorithm/FlexDirection.h index 3770783b7e..a8ee7586ae 100644 --- a/yoga/algorithm/FlexDirection.h +++ b/yoga/algorithm/FlexDirection.h @@ -11,6 +11,7 @@ #include #include +#include #include namespace facebook::yoga { diff --git a/yoga/debug/AssertFatal.cpp b/yoga/debug/AssertFatal.cpp index 2388a74453..e43ce2a254 100644 --- a/yoga/debug/AssertFatal.cpp +++ b/yoga/debug/AssertFatal.cpp @@ -7,8 +7,10 @@ #include +#include #include #include +#include namespace facebook::yoga { diff --git a/yoga/debug/AssertFatal.h b/yoga/debug/AssertFatal.h index 929ff1792d..bbd8ad19ea 100644 --- a/yoga/debug/AssertFatal.h +++ b/yoga/debug/AssertFatal.h @@ -8,11 +8,12 @@ #pragma once #include -#include -#include namespace facebook::yoga { +class Node; +class Config; + [[noreturn]] void fatalWithMessage(const char* message); void assertFatal(bool condition, const char* message); diff --git a/yoga/debug/NodeToString.cpp b/yoga/debug/NodeToString.cpp index a2bf467bed..107c50e4bb 100644 --- a/yoga/debug/NodeToString.cpp +++ b/yoga/debug/NodeToString.cpp @@ -23,12 +23,6 @@ static void indent(std::string& base, uint32_t level) { } } -static bool areFourValuesEqual(const Style::Edges& four) { - return yoga::inexactEquals(four[0], four[1]) && - yoga::inexactEquals(four[0], four[2]) && - yoga::inexactEquals(four[0], four[3]); -} - static void appendFormattedString(std::string& str, const char* fmt, ...) { va_list args; va_start(args, fmt); @@ -86,33 +80,15 @@ static void appendNumberIfNotZero( } } -static void appendEdges( - std::string& base, - const std::string& key, - const Style::Edges& edges) { - if (areFourValuesEqual(edges)) { - auto edgeValue = yoga::Node::computeEdgeValueForColumn(edges, YGEdgeLeft); - appendNumberIfNotUndefined(base, key, edgeValue); - } else { - for (int edge = YGEdgeLeft; edge != YGEdgeAll; ++edge) { - std::string str = key + "-" + YGEdgeToString(static_cast(edge)); - appendNumberIfNotZero(base, str, edges[static_cast(edge)]); - } +template +static void +appendEdges(std::string& base, const std::string& key, const Style& style) { + for (int edge = YGEdgeLeft; edge != YGEdgeAll; ++edge) { + std::string str = key + "-" + YGEdgeToString(static_cast(edge)); + appendNumberIfNotZero(base, str, (style.*Field)(static_cast(edge))); } } -static void appendEdgeIfNotUndefined( - std::string& base, - const std::string& str, - const Style::Edges& edges, - const YGEdge edge) { - // TODO: this doesn't take RTL / YGEdgeStart / YGEdgeEnd into account - auto value = (edge == YGEdgeLeft || edge == YGEdgeRight) - ? yoga::Node::computeEdgeValueForRow(edges, edge, edge) - : yoga::Node::computeEdgeValueForColumn(edges, edge); - appendNumberIfNotUndefined(base, str, value); -} - void nodeToString( std::string& str, const yoga::Node* node, @@ -173,9 +149,9 @@ void nodeToString( if (style.display() != yoga::Node{}.getStyle().display()) { appendFormattedString(str, "display: %s; ", toString(style.display())); } - appendEdges(str, "margin", style.margin()); - appendEdges(str, "padding", style.padding()); - appendEdges(str, "border", style.border()); + appendEdges<&Style::margin>(str, "margin", style); + appendEdges<&Style::padding>(str, "padding", style); + appendEdges<&Style::border>(str, "border", style); if (style.gap(Gutter::All).isDefined()) { appendNumberIfNotUndefined(str, "gap", style.gap(Gutter::All)); @@ -200,10 +176,7 @@ void nodeToString( str, "position: %s; ", toString(style.positionType())); } - appendEdgeIfNotUndefined(str, "left", style.position(), YGEdgeLeft); - appendEdgeIfNotUndefined(str, "right", style.position(), YGEdgeRight); - appendEdgeIfNotUndefined(str, "top", style.position(), YGEdgeTop); - appendEdgeIfNotUndefined(str, "bottom", style.position(), YGEdgeBottom); + appendEdges<&Style::position>(str, "position", style); appendFormattedString(str, "\" "); if (node->hasMeasureFunc()) { diff --git a/yoga/node/Node.cpp b/yoga/node/Node.cpp index 762433f15a..1675cc3605 100644 --- a/yoga/node/Node.cpp +++ b/yoga/node/Node.cpp @@ -56,30 +56,29 @@ void Node::print() { } } -CompactValue Node::computeEdgeValueForRow( - const Style::Edges& edges, - YGEdge rowEdge, - YGEdge edge) { - if (edges[rowEdge].isDefined()) { - return edges[rowEdge]; - } else if (edges[edge].isDefined()) { - return edges[edge]; - } else if (edges[YGEdgeHorizontal].isDefined()) { - return edges[YGEdgeHorizontal]; +// TODO: Edge value resolution should be moved to `yoga::Style` +template +CompactValue Node::computeEdgeValueForRow(YGEdge rowEdge, YGEdge edge) const { + if ((style_.*Field)(rowEdge).isDefined()) { + return (style_.*Field)(rowEdge); + } else if ((style_.*Field)(edge).isDefined()) { + return (style_.*Field)(edge); + } else if ((style_.*Field)(YGEdgeHorizontal).isDefined()) { + return (style_.*Field)(YGEdgeHorizontal); } else { - return edges[YGEdgeAll]; + return (style_.*Field)(YGEdgeAll); } } -CompactValue Node::computeEdgeValueForColumn( - const Style::Edges& edges, - YGEdge edge) { - if (edges[edge].isDefined()) { - return edges[edge]; - } else if (edges[YGEdgeVertical].isDefined()) { - return edges[YGEdgeVertical]; +// TODO: Edge value resolution should be moved to `yoga::Style` +template +CompactValue Node::computeEdgeValueForColumn(YGEdge edge) const { + if ((style_.*Field)(edge).isDefined()) { + return (style_.*Field)(edge); + } else if ((style_.*Field)(YGEdgeVertical).isDefined()) { + return (style_.*Field)(YGEdgeVertical); } else { - return edges[YGEdgeAll]; + return (style_.*Field)(YGEdgeAll); } } @@ -103,8 +102,8 @@ bool Node::isInlineStartPositionDefined(FlexDirection axis, Direction direction) const { const YGEdge startEdge = getInlineStartEdgeUsingErrata(axis, direction); auto leadingPosition = isRow(axis) - ? computeEdgeValueForRow(style_.position(), YGEdgeStart, startEdge) - : computeEdgeValueForColumn(style_.position(), startEdge); + ? computeEdgeValueForRow<&Style::position>(YGEdgeStart, startEdge) + : computeEdgeValueForColumn<&Style::position>(startEdge); return leadingPosition.isDefined(); } @@ -113,8 +112,8 @@ bool Node::isInlineEndPositionDefined(FlexDirection axis, Direction direction) const { const YGEdge endEdge = getInlineEndEdgeUsingErrata(axis, direction); auto trailingPosition = isRow(axis) - ? computeEdgeValueForRow(style_.position(), YGEdgeEnd, endEdge) - : computeEdgeValueForColumn(style_.position(), endEdge); + ? computeEdgeValueForRow<&Style::position>(YGEdgeEnd, endEdge) + : computeEdgeValueForColumn<&Style::position>(endEdge); return trailingPosition.isDefined(); } @@ -125,8 +124,8 @@ float Node::getInlineStartPosition( float axisSize) const { const YGEdge startEdge = getInlineStartEdgeUsingErrata(axis, direction); auto leadingPosition = isRow(axis) - ? computeEdgeValueForRow(style_.position(), YGEdgeStart, startEdge) - : computeEdgeValueForColumn(style_.position(), startEdge); + ? computeEdgeValueForRow<&Style::position>(YGEdgeStart, startEdge) + : computeEdgeValueForColumn<&Style::position>(startEdge); return resolveValue(leadingPosition, axisSize).unwrapOrDefault(0.0f); } @@ -137,8 +136,8 @@ float Node::getInlineEndPosition( float axisSize) const { const YGEdge endEdge = getInlineEndEdgeUsingErrata(axis, direction); auto trailingPosition = isRow(axis) - ? computeEdgeValueForRow(style_.position(), YGEdgeEnd, endEdge) - : computeEdgeValueForColumn(style_.position(), endEdge); + ? computeEdgeValueForRow<&Style::position>(YGEdgeEnd, endEdge) + : computeEdgeValueForColumn<&Style::position>(endEdge); return resolveValue(trailingPosition, axisSize).unwrapOrDefault(0.0f); } @@ -149,8 +148,8 @@ float Node::getInlineStartMargin( float widthSize) const { const YGEdge startEdge = getInlineStartEdgeUsingErrata(axis, direction); auto leadingMargin = isRow(axis) - ? computeEdgeValueForRow(style_.margin(), YGEdgeStart, startEdge) - : computeEdgeValueForColumn(style_.margin(), startEdge); + ? computeEdgeValueForRow<&Style::margin>(YGEdgeStart, startEdge) + : computeEdgeValueForColumn<&Style::margin>(startEdge); return resolveValue(leadingMargin, widthSize).unwrapOrDefault(0.0f); } @@ -161,8 +160,8 @@ float Node::getInlineEndMargin( float widthSize) const { const YGEdge endEdge = getInlineEndEdgeUsingErrata(axis, direction); auto trailingMargin = isRow(axis) - ? computeEdgeValueForRow(style_.margin(), YGEdgeEnd, endEdge) - : computeEdgeValueForColumn(style_.margin(), endEdge); + ? computeEdgeValueForRow<&Style::margin>(YGEdgeEnd, endEdge) + : computeEdgeValueForColumn<&Style::margin>(endEdge); return resolveValue(trailingMargin, widthSize).unwrapOrDefault(0.0f); } @@ -171,8 +170,8 @@ float Node::getInlineStartBorder(FlexDirection axis, Direction direction) const { const YGEdge startEdge = getInlineStartEdgeUsingErrata(axis, direction); YGValue leadingBorder = isRow(axis) - ? computeEdgeValueForRow(style_.border(), YGEdgeStart, startEdge) - : computeEdgeValueForColumn(style_.border(), startEdge); + ? computeEdgeValueForRow<&Style::border>(YGEdgeStart, startEdge) + : computeEdgeValueForColumn<&Style::border>(startEdge); return maxOrDefined(leadingBorder.value, 0.0f); } @@ -181,9 +180,9 @@ float Node::getFlexStartBorder(FlexDirection axis, Direction direction) const { const YGEdge leadRelativeFlexItemEdge = flexStartRelativeEdge(axis, direction); YGValue leadingBorder = isRow(axis) - ? computeEdgeValueForRow( - style_.border(), leadRelativeFlexItemEdge, flexStartEdge(axis)) - : computeEdgeValueForColumn(style_.border(), flexStartEdge(axis)); + ? computeEdgeValueForRow<&Style::border>( + leadRelativeFlexItemEdge, flexStartEdge(axis)) + : computeEdgeValueForColumn<&Style::border>(flexStartEdge(axis)); return maxOrDefined(leadingBorder.value, 0.0f); } @@ -191,8 +190,8 @@ float Node::getFlexStartBorder(FlexDirection axis, Direction direction) const { float Node::getInlineEndBorder(FlexDirection axis, Direction direction) const { const YGEdge endEdge = getInlineEndEdgeUsingErrata(axis, direction); YGValue trailingBorder = isRow(axis) - ? computeEdgeValueForRow(style_.border(), YGEdgeEnd, endEdge) - : computeEdgeValueForColumn(style_.border(), endEdge); + ? computeEdgeValueForRow<&Style::border>(YGEdgeEnd, endEdge) + : computeEdgeValueForColumn<&Style::border>(endEdge); return maxOrDefined(trailingBorder.value, 0.0f); } @@ -200,9 +199,9 @@ float Node::getInlineEndBorder(FlexDirection axis, Direction direction) const { float Node::getFlexEndBorder(FlexDirection axis, Direction direction) const { const YGEdge trailRelativeFlexItemEdge = flexEndRelativeEdge(axis, direction); YGValue trailingBorder = isRow(axis) - ? computeEdgeValueForRow( - style_.border(), trailRelativeFlexItemEdge, flexEndEdge(axis)) - : computeEdgeValueForColumn(style_.border(), flexEndEdge(axis)); + ? computeEdgeValueForRow<&Style::border>( + trailRelativeFlexItemEdge, flexEndEdge(axis)) + : computeEdgeValueForColumn<&Style::border>(flexEndEdge(axis)); return maxOrDefined(trailingBorder.value, 0.0f); } @@ -213,8 +212,8 @@ float Node::getInlineStartPadding( float widthSize) const { const YGEdge startEdge = getInlineStartEdgeUsingErrata(axis, direction); auto leadingPadding = isRow(axis) - ? computeEdgeValueForRow(style_.padding(), YGEdgeStart, startEdge) - : computeEdgeValueForColumn(style_.padding(), startEdge); + ? computeEdgeValueForRow<&Style::padding>(YGEdgeStart, startEdge) + : computeEdgeValueForColumn<&Style::padding>(startEdge); return maxOrDefined(resolveValue(leadingPadding, widthSize).unwrap(), 0.0f); } @@ -226,9 +225,9 @@ float Node::getFlexStartPadding( const YGEdge leadRelativeFlexItemEdge = flexStartRelativeEdge(axis, direction); auto leadingPadding = isRow(axis) - ? computeEdgeValueForRow( - style_.padding(), leadRelativeFlexItemEdge, flexStartEdge(axis)) - : computeEdgeValueForColumn(style_.padding(), flexStartEdge(axis)); + ? computeEdgeValueForRow<&Style::padding>( + leadRelativeFlexItemEdge, flexStartEdge(axis)) + : computeEdgeValueForColumn<&Style::padding>(flexStartEdge(axis)); return maxOrDefined(resolveValue(leadingPadding, widthSize).unwrap(), 0.0f); } @@ -239,8 +238,8 @@ float Node::getInlineEndPadding( float widthSize) const { const YGEdge endEdge = getInlineEndEdgeUsingErrata(axis, direction); auto trailingPadding = isRow(axis) - ? computeEdgeValueForRow(style_.padding(), YGEdgeEnd, endEdge) - : computeEdgeValueForColumn(style_.padding(), endEdge); + ? computeEdgeValueForRow<&Style::padding>(YGEdgeEnd, endEdge) + : computeEdgeValueForColumn<&Style::padding>(endEdge); return maxOrDefined(resolveValue(trailingPadding, widthSize).unwrap(), 0.0f); } @@ -251,9 +250,9 @@ float Node::getFlexEndPadding( float widthSize) const { const YGEdge trailRelativeFlexItemEdge = flexEndRelativeEdge(axis, direction); auto trailingPadding = isRow(axis) - ? computeEdgeValueForRow( - style_.padding(), trailRelativeFlexItemEdge, flexEndEdge(axis)) - : computeEdgeValueForColumn(style_.padding(), flexEndEdge(axis)); + ? computeEdgeValueForRow<&Style::padding>( + trailRelativeFlexItemEdge, flexEndEdge(axis)) + : computeEdgeValueForColumn<&Style::padding>(flexEndEdge(axis)); return maxOrDefined(resolveValue(trailingPadding, widthSize).unwrap(), 0.0f); } @@ -511,18 +510,18 @@ void Node::setPosition( } YGValue Node::getFlexStartMarginValue(FlexDirection axis) const { - if (isRow(axis) && style_.margin()[YGEdgeStart].isDefined()) { - return style_.margin()[YGEdgeStart]; + if (isRow(axis) && style_.margin(YGEdgeStart).isDefined()) { + return style_.margin(YGEdgeStart); } else { - return style_.margin()[flexStartEdge(axis)]; + return style_.margin(flexStartEdge(axis)); } } YGValue Node::marginTrailingValue(FlexDirection axis) const { - if (isRow(axis) && style_.margin()[YGEdgeEnd].isDefined()) { - return style_.margin()[YGEdgeEnd]; + if (isRow(axis) && style_.margin(YGEdgeEnd).isDefined()) { + return style_.margin(YGEdgeEnd); } else { - return style_.margin()[flexEndEdge(axis)]; + return style_.margin(flexEndEdge(axis)); } } diff --git a/yoga/node/Node.h b/yoga/node/Node.h index 0a317c38ab..cd74d4982d 100644 --- a/yoga/node/Node.h +++ b/yoga/node/Node.h @@ -65,6 +65,12 @@ class YG_EXPORT Node : public ::YGNode { style_.alignContent() = Align::Stretch; } + template + CompactValue computeEdgeValueForColumn(YGEdge edge) const; + + template + CompactValue computeEdgeValueForRow(YGEdge rowEdge, YGEdge edge) const; + // DANGER DANGER DANGER! // If the node assigned to has children, we'd either have to deallocate // them (potentially incorrect) or ignore them (danger of leaks). Only ever @@ -189,15 +195,6 @@ class YG_EXPORT Node : public ::YGNode { return resolvedDimensions_[static_cast(dimension)]; } - static CompactValue computeEdgeValueForColumn( - const Style::Edges& edges, - YGEdge edge); - - static CompactValue computeEdgeValueForRow( - const Style::Edges& edges, - YGEdge rowEdge, - YGEdge edge); - // Methods related to positions, margin, padding and border bool isInlineStartPositionDefined(FlexDirection axis, Direction direction) const; diff --git a/yoga/style/Style.h b/yoga/style/Style.h index 3eb5cadd19..06fbe23bb8 100644 --- a/yoga/style/Style.h +++ b/yoga/style/Style.h @@ -34,11 +34,11 @@ class YG_EXPORT Style { template using Values = std::array()>; - public: using Dimensions = Values; using Edges = Values; using Gutters = Values; + public: static constexpr float DefaultFlexGrow = 0.0f; static constexpr float DefaultFlexShrink = 0.0f; static constexpr float WebDefaultFlexShrink = 1.0f; @@ -68,39 +68,6 @@ class YG_EXPORT Style { } }; - template Style::*Prop> - struct IdxRef { - struct Ref { - Style& style; - Idx idx; - operator CompactValue() const { - return (style.*Prop)[idx]; - } - operator YGValue() const { - return (style.*Prop)[idx]; - } - Ref& operator=(CompactValue value) { - (style.*Prop)[idx] = value; - return *this; - } - }; - - Style& style; - IdxRef& operator=(const Values& values) { - style.*Prop = values; - return *this; - } - operator const Values&() const { - return style.*Prop; - } - Ref operator[](Idx idx) { - return {style, idx}; - } - CompactValue operator[](Idx idx) const { - return (style.*Prop)[idx]; - } - }; - Style() { alignContent() = Align::FlexStart; alignItems() = Align::Stretch; @@ -146,9 +113,6 @@ class YG_EXPORT Style { FloatOptional aspectRatio_ = {}; public: - // for library users needing a type - using ValueRepr = std::remove_reference::type; - Direction direction() const { return getEnumData(flags, directionOffset); } @@ -247,32 +211,32 @@ class YG_EXPORT Style { return {*this}; } - const Edges& margin() const { - return margin_; + CompactValue margin(YGEdge edge) const { + return margin_[edge]; } - IdxRef margin() { - return {*this}; + void setMargin(YGEdge edge, CompactValue value) { + margin_[edge] = value; } - const Edges& position() const { - return position_; + CompactValue position(YGEdge edge) const { + return position_[edge]; } - IdxRef position() { - return {*this}; + void setPosition(YGEdge edge, CompactValue value) { + position_[edge] = value; } - const Edges& padding() const { - return padding_; + CompactValue padding(YGEdge edge) const { + return padding_[edge]; } - IdxRef padding() { - return {*this}; + void setPadding(YGEdge edge, CompactValue value) { + padding_[edge] = value; } - const Edges& border() const { - return border_; + CompactValue border(YGEdge edge) const { + return border_[edge]; } - IdxRef border() { - return {*this}; + void setBorder(YGEdge edge, CompactValue value) { + border_[edge] = value; } CompactValue gap(Gutter gutter) const {