From 27af5963593712f76bb38e9aa217b1dae2cd6584 Mon Sep 17 00:00:00 2001 From: Nick Gerleman Date: Wed, 15 Nov 2023 18:34:47 -0800 Subject: [PATCH] Revert D50998164: Allow lazy resolution of edge dimension values Differential Revision: D50998164 Original commit changeset: 248396f9587e Original Phabricator Diff: D50998164 fbshipit-source-id: 4f592158324d758bb9e3731ced36b8e3587c459c --- tests/YGStyleAccessorsTest.cpp | 216 +++++++++++++++++++++++++++++++++ yoga/YGNodeStyle.cpp | 47 ++++--- yoga/algorithm/FlexDirection.h | 1 - yoga/debug/AssertFatal.cpp | 2 - yoga/debug/AssertFatal.h | 5 +- yoga/debug/NodeToString.cpp | 47 +++++-- yoga/node/Node.cpp | 137 ++++++++++----------- yoga/node/Node.h | 15 ++- yoga/style/Style.h | 70 ++++++++--- 9 files changed, 416 insertions(+), 124 deletions(-) create mode 100644 tests/YGStyleAccessorsTest.cpp diff --git a/tests/YGStyleAccessorsTest.cpp b/tests/YGStyleAccessorsTest.cpp new file mode 100644 index 00000000..cec5c7e2 --- /dev/null +++ b/tests/YGStyleAccessorsTest.cpp @@ -0,0 +1,216 @@ +/* + * 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 38a55f2c..57d352cd 100644 --- a/yoga/YGNodeStyle.cpp +++ b/yoga/YGNodeStyle.cpp @@ -35,6 +35,19 @@ void updateStyle(YGNodeRef node, Ref (Style::*prop)(), T value) { [prop](Style& s, T x) { (s.*prop)() = x; }); } +template +void updateIndexedStyleProp( + YGNodeRef node, + Ref (Style::*prop)(), + Idx idx, + CompactValue value) { + updateStyle( + resolveRef(node), + value, + [idx, prop](Style& s, CompactValue x) { return (s.*prop)()[idx] != x; }, + [idx, prop](Style& s, CompactValue x) { (s.*prop)()[idx] = x; }); +} + template void updateIndexedStyleProp(YGNodeRef node, IdxT idx, CompactValue value) { updateStyle( @@ -224,53 +237,53 @@ YGValue YGNodeStyleGetFlexBasis(const YGNodeConstRef node) { void YGNodeStyleSetPosition(YGNodeRef node, YGEdge edge, float points) { auto value = CompactValue::ofMaybe(points); - updateIndexedStyleProp<&Style::position, &Style::setPosition>( - node, edge, value); + updateIndexedStyleProp( + node, &Style::position, edge, value); } void YGNodeStyleSetPositionPercent(YGNodeRef node, YGEdge edge, float percent) { auto value = CompactValue::ofMaybe(percent); - updateIndexedStyleProp<&Style::position, &Style::setPosition>( - node, edge, value); + updateIndexedStyleProp( + node, &Style::position, 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<&Style::margin, &Style::setMargin>(node, edge, value); + updateIndexedStyleProp(node, &Style::margin, edge, value); } void YGNodeStyleSetMarginPercent(YGNodeRef node, YGEdge edge, float percent) { auto value = CompactValue::ofMaybe(percent); - updateIndexedStyleProp<&Style::margin, &Style::setMargin>(node, edge, value); + updateIndexedStyleProp(node, &Style::margin, edge, value); } void YGNodeStyleSetMarginAuto(YGNodeRef node, YGEdge edge) { - updateIndexedStyleProp<&Style::margin, &Style::setMargin>( - node, edge, CompactValue::ofAuto()); + updateIndexedStyleProp( + node, &Style::margin, 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<&Style::padding, &Style::setPadding>( - node, edge, value); + updateIndexedStyleProp( + node, &Style::padding, edge, value); } void YGNodeStyleSetPaddingPercent(YGNodeRef node, YGEdge edge, float percent) { auto value = CompactValue::ofMaybe(percent); - updateIndexedStyleProp<&Style::padding, &Style::setPadding>( - node, edge, value); + updateIndexedStyleProp( + node, &Style::padding, edge, value); } YGValue YGNodeStyleGetPadding(YGNodeConstRef node, YGEdge edge) { - return resolveRef(node)->getStyle().padding(edge); + return resolveRef(node)->getStyle().padding()[edge]; } void YGNodeStyleSetBorder( @@ -278,11 +291,11 @@ void YGNodeStyleSetBorder( const YGEdge edge, const float border) { auto value = CompactValue::ofMaybe(border); - updateIndexedStyleProp<&Style::border, &Style::setBorder>(node, edge, value); + updateIndexedStyleProp(node, &Style::border, 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 a8ee7586..3770783b 100644 --- a/yoga/algorithm/FlexDirection.h +++ b/yoga/algorithm/FlexDirection.h @@ -11,7 +11,6 @@ #include #include -#include #include namespace facebook::yoga { diff --git a/yoga/debug/AssertFatal.cpp b/yoga/debug/AssertFatal.cpp index e43ce2a2..2388a744 100644 --- a/yoga/debug/AssertFatal.cpp +++ b/yoga/debug/AssertFatal.cpp @@ -7,10 +7,8 @@ #include -#include #include #include -#include namespace facebook::yoga { diff --git a/yoga/debug/AssertFatal.h b/yoga/debug/AssertFatal.h index bbd8ad19..929ff179 100644 --- a/yoga/debug/AssertFatal.h +++ b/yoga/debug/AssertFatal.h @@ -8,12 +8,11 @@ #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 107c50e4..a2bf467b 100644 --- a/yoga/debug/NodeToString.cpp +++ b/yoga/debug/NodeToString.cpp @@ -23,6 +23,12 @@ 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); @@ -80,15 +86,33 @@ static void appendNumberIfNotZero( } } -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 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)]); + } } } +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, @@ -149,9 +173,9 @@ void nodeToString( if (style.display() != yoga::Node{}.getStyle().display()) { appendFormattedString(str, "display: %s; ", toString(style.display())); } - appendEdges<&Style::margin>(str, "margin", style); - appendEdges<&Style::padding>(str, "padding", style); - appendEdges<&Style::border>(str, "border", style); + appendEdges(str, "margin", style.margin()); + appendEdges(str, "padding", style.padding()); + appendEdges(str, "border", style.border()); if (style.gap(Gutter::All).isDefined()) { appendNumberIfNotUndefined(str, "gap", style.gap(Gutter::All)); @@ -176,7 +200,10 @@ void nodeToString( str, "position: %s; ", toString(style.positionType())); } - appendEdges<&Style::position>(str, "position", style); + appendEdgeIfNotUndefined(str, "left", style.position(), YGEdgeLeft); + appendEdgeIfNotUndefined(str, "right", style.position(), YGEdgeRight); + appendEdgeIfNotUndefined(str, "top", style.position(), YGEdgeTop); + appendEdgeIfNotUndefined(str, "bottom", style.position(), YGEdgeBottom); appendFormattedString(str, "\" "); if (node->hasMeasureFunc()) { diff --git a/yoga/node/Node.cpp b/yoga/node/Node.cpp index e5100ee2..e69c96f5 100644 --- a/yoga/node/Node.cpp +++ b/yoga/node/Node.cpp @@ -56,29 +56,30 @@ void Node::print() { } } -// 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); +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]; } else { - return (style_.*Field)(YGEdgeAll); + return edges[YGEdgeAll]; } } -// 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); +CompactValue Node::computeEdgeValueForColumn( + const Style::Edges& edges, + YGEdge edge) { + if (edges[edge].isDefined()) { + return edges[edge]; + } else if (edges[YGEdgeVertical].isDefined()) { + return edges[YGEdgeVertical]; } else { - return (style_.*Field)(YGEdgeAll); + return edges[YGEdgeAll]; } } @@ -101,8 +102,8 @@ YGEdge Node::getInlineEndEdgeUsingErrata( bool Node::isFlexStartPositionDefined(FlexDirection axis) const { const YGEdge startEdge = flexStartEdge(axis); 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(); } @@ -111,8 +112,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(); } @@ -120,8 +121,8 @@ bool Node::isInlineStartPositionDefined(FlexDirection axis, Direction direction) bool Node::isFlexEndPositionDefined(FlexDirection axis) const { const YGEdge endEdge = flexEndEdge(axis); auto trailingPosition = isRow(axis) - ? computeEdgeValueForRow<&Style::position>(YGEdgeEnd, endEdge) - : computeEdgeValueForColumn<&Style::position>(endEdge); + ? computeEdgeValueForRow(style_.position(), YGEdgeEnd, endEdge) + : computeEdgeValueForColumn(style_.position(), endEdge); return !trailingPosition.isUndefined(); } @@ -130,8 +131,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(); } @@ -139,8 +140,8 @@ bool Node::isInlineEndPositionDefined(FlexDirection axis, Direction direction) float Node::getFlexStartPosition(FlexDirection axis, float axisSize) const { const YGEdge startEdge = flexStartEdge(axis); 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); } @@ -151,8 +152,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); } @@ -160,8 +161,8 @@ float Node::getInlineStartPosition( float Node::getFlexEndPosition(FlexDirection axis, float axisSize) const { const YGEdge endEdge = flexEndEdge(axis); 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); } @@ -172,8 +173,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); } @@ -181,8 +182,8 @@ float Node::getInlineEndPosition( float Node::getFlexStartMargin(FlexDirection axis, float widthSize) const { const YGEdge startEdge = flexStartEdge(axis); 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); } @@ -193,8 +194,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); } @@ -202,8 +203,8 @@ float Node::getInlineStartMargin( float Node::getFlexEndMargin(FlexDirection axis, float widthSize) const { const YGEdge endEdge = flexEndEdge(axis); 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); } @@ -214,8 +215,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); } @@ -224,8 +225,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); } @@ -234,9 +235,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); } @@ -244,8 +245,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); } @@ -253,9 +254,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); } @@ -266,8 +267,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); } @@ -279,9 +280,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); } @@ -292,8 +293,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); } @@ -304,9 +305,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); } @@ -564,18 +565,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 9fefcf15..601e153f 100644 --- a/yoga/node/Node.h +++ b/yoga/node/Node.h @@ -65,12 +65,6 @@ 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 @@ -195,6 +189,15 @@ 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 isFlexStartPositionDefined(FlexDirection axis) const; bool isInlineStartPositionDefined(FlexDirection axis, Direction direction) diff --git a/yoga/style/Style.h b/yoga/style/Style.h index 06fbe23b..3eb5cadd 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,6 +68,39 @@ 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; @@ -113,6 +146,9 @@ 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); } @@ -211,32 +247,32 @@ class YG_EXPORT Style { return {*this}; } - CompactValue margin(YGEdge edge) const { - return margin_[edge]; + const Edges& margin() const { + return margin_; } - void setMargin(YGEdge edge, CompactValue value) { - margin_[edge] = value; + IdxRef margin() { + return {*this}; } - CompactValue position(YGEdge edge) const { - return position_[edge]; + const Edges& position() const { + return position_; } - void setPosition(YGEdge edge, CompactValue value) { - position_[edge] = value; + IdxRef position() { + return {*this}; } - CompactValue padding(YGEdge edge) const { - return padding_[edge]; + const Edges& padding() const { + return padding_; } - void setPadding(YGEdge edge, CompactValue value) { - padding_[edge] = value; + IdxRef padding() { + return {*this}; } - CompactValue border(YGEdge edge) const { - return border_[edge]; + const Edges& border() const { + return border_; } - void setBorder(YGEdge edge, CompactValue value) { - border_[edge] = value; + IdxRef border() { + return {*this}; } CompactValue gap(Gutter gutter) const {