Files
yoga/yoga/YGNodeLayout.cpp
Nick Gerleman 8744792f41 Simplify Edge Resolution (#1550)
Summary:
X-link: https://github.com/facebook/react-native/pull/42254

Pull Request resolved: https://github.com/facebook/yoga/pull/1550

This change aims to simplify how we resolve edges. This operation happens many, many times, and has gotten complex and slow when paired with StyleValuePool.

This starts reshaping so that `yoga::Style` can resolve a style prop for a given edge. This is closer to the ideal computed style API to avoid recalcing this so many times, but doesn't address that.

This relies on removing the errata related to row-reverse, and cleans up the removal started in the last change.

This has no measurable perf effect under CompactValue, but has a >10% uplift in perf when using StyleValueHandle, where we can trivially check if a handle points to a defined value without resolving it, but only within `yoga::Style` since we don't expose the handle outside of it.

More quantifiably, we go from 2.35 million StyleValuePool reads to 993k. The rest are checks on the handle.

Reviewed By: joevilches

Differential Revision: D52605596

fbshipit-source-id: 0b366963a899e376f99ce3d75cd5f14a25d60cec
2024-01-19 11:28:06 -08:00

93 lines
2.7 KiB
C++

/*
* 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 <yoga/Yoga.h>
#include <yoga/debug/AssertFatal.h>
#include <yoga/enums/Edge.h>
#include <yoga/node/Node.h>
using namespace facebook;
using namespace facebook::yoga;
namespace {
template <auto LayoutMember>
float getResolvedLayoutProperty(const YGNodeConstRef nodeRef, const Edge edge) {
const auto node = resolveRef(nodeRef);
yoga::assertFatalWithNode(
node,
edge <= Edge::End,
"Cannot get layout properties of multi-edge shorthands");
if (edge == Edge::Start) {
if (node->getLayout().direction() == Direction::RTL) {
return (node->getLayout().*LayoutMember)(PhysicalEdge::Right);
} else {
return (node->getLayout().*LayoutMember)(PhysicalEdge::Left);
}
}
if (edge == Edge::End) {
if (node->getLayout().direction() == Direction::RTL) {
return (node->getLayout().*LayoutMember)(PhysicalEdge::Left);
} else {
return (node->getLayout().*LayoutMember)(PhysicalEdge::Right);
}
}
return (node->getLayout().*LayoutMember)(static_cast<PhysicalEdge>(edge));
}
} // namespace
float YGNodeLayoutGetLeft(const YGNodeConstRef node) {
return resolveRef(node)->getLayout().position(PhysicalEdge::Left);
}
float YGNodeLayoutGetTop(const YGNodeConstRef node) {
return resolveRef(node)->getLayout().position(PhysicalEdge::Top);
}
float YGNodeLayoutGetRight(const YGNodeConstRef node) {
return resolveRef(node)->getLayout().position(PhysicalEdge::Right);
}
float YGNodeLayoutGetBottom(const YGNodeConstRef node) {
return resolveRef(node)->getLayout().position(PhysicalEdge::Bottom);
}
float YGNodeLayoutGetWidth(const YGNodeConstRef node) {
return resolveRef(node)->getLayout().dimension(Dimension::Width);
}
float YGNodeLayoutGetHeight(const YGNodeConstRef node) {
return resolveRef(node)->getLayout().dimension(Dimension::Height);
}
YGDirection YGNodeLayoutGetDirection(const YGNodeConstRef node) {
return unscopedEnum(resolveRef(node)->getLayout().direction());
}
bool YGNodeLayoutGetHadOverflow(const YGNodeConstRef node) {
return resolveRef(node)->getLayout().hadOverflow();
}
float YGNodeLayoutGetMargin(YGNodeConstRef node, YGEdge edge) {
return getResolvedLayoutProperty<&LayoutResults::margin>(
node, scopedEnum(edge));
}
float YGNodeLayoutGetBorder(YGNodeConstRef node, YGEdge edge) {
return getResolvedLayoutProperty<&LayoutResults::border>(
node, scopedEnum(edge));
}
float YGNodeLayoutGetPadding(YGNodeConstRef node, YGEdge edge) {
return getResolvedLayoutProperty<&LayoutResults::padding>(
node, scopedEnum(edge));
}