Skip to content

Commit 919e983

Browse files
committed
feat(android): layout insets calculation from YogaStylableProps
1 parent c4efd73 commit 919e983

File tree

4 files changed

+140
-50
lines changed

4 files changed

+140
-50
lines changed

packages/react-native/ReactAndroid/src/main/jni/react/fabric/FabricMountingManager.cpp

Lines changed: 41 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,13 @@ void FabricMountingManager::setComputedBoxModelRegistry(
6565
namespace {
6666

6767
inline bool needsComputedBoxModel(const ShadowView& shadowView) {
68-
return shadowView.traits.check(ShadowNodeTraits::Trait::NeedsComputedBoxModel);
68+
return shadowView.traits.check(
69+
ShadowNodeTraits::Trait::NeedsComputedBoxModel);
70+
}
71+
72+
inline std::shared_ptr<const YogaStylableProps> getYogaStylableProps(
73+
const ShadowView& shadowView) {
74+
return std::static_pointer_cast<const YogaStylableProps>(shadowView.props);
6975
}
7076

7177
#ifdef REACT_NATIVE_DEBUG
@@ -719,21 +725,35 @@ void FabricMountingManager::executeMount(
719725
// information has changed and NeedsComputedBoxModel trait is set.
720726
// This information is needed for proper calculation of the clipPath
721727
// geometry box.
722-
auto oldNeedsComputedBoxModel = needsComputedBoxModel(oldChildShadowView);
723-
auto newNeedsComputedBoxModel = needsComputedBoxModel(newChildShadowView);
728+
auto oldNeedsComputedBoxModel =
729+
needsComputedBoxModel(oldChildShadowView);
730+
auto newNeedsComputedBoxModel =
731+
needsComputedBoxModel(newChildShadowView);
724732

725733
if (computedBoxModelRegistry_) {
726-
if (newNeedsComputedBoxModel &&
727-
(oldChildShadowView.layoutMetrics.marginInsets !=
728-
newChildShadowView.layoutMetrics.marginInsets ||
729-
oldChildShadowView.layoutMetrics.paddingInsets !=
730-
newChildShadowView.layoutMetrics.paddingInsets)) {
731-
computedBoxModelRegistry_->store(
732-
surfaceId,
733-
newChildShadowView.tag,
734-
newChildShadowView.layoutMetrics.marginInsets,
735-
newChildShadowView.layoutMetrics.paddingInsets);
736-
} else if (oldNeedsComputedBoxModel && !newNeedsComputedBoxModel) {
734+
if (newNeedsComputedBoxModel) {
735+
auto oldProps = getYogaStylableProps(oldChildShadowView);
736+
auto newProps = getYogaStylableProps(newChildShadowView);
737+
if (oldProps && newProps) {
738+
auto newMarginInsets =
739+
marginInsetsFromYogaStylableProps(*newProps.get());
740+
auto oldMarginInsets =
741+
marginInsetsFromYogaStylableProps(*oldProps.get());
742+
auto newPaddingInsets =
743+
paddingInsetsFromYogaStylableProps(*newProps.get());
744+
auto oldPaddingInsets =
745+
paddingInsetsFromYogaStylableProps(*oldProps.get());
746+
if (oldMarginInsets != newMarginInsets ||
747+
oldPaddingInsets != newPaddingInsets) {
748+
computedBoxModelRegistry_->store(
749+
surfaceId,
750+
newChildShadowView.tag,
751+
newMarginInsets,
752+
newPaddingInsets);
753+
}
754+
}
755+
} else if (
756+
oldNeedsComputedBoxModel && !newNeedsComputedBoxModel) {
737757
computedBoxModelRegistry_->remove(
738758
surfaceId, newChildShadowView.tag);
739759
}
@@ -828,11 +848,13 @@ void FabricMountingManager::executeMount(
828848
// geometry box.
829849
if (needsComputedBoxModel(newChildShadowView)) {
830850
if (computedBoxModelRegistry_) {
831-
computedBoxModelRegistry_->store(
832-
surfaceId,
833-
newChildShadowView.tag,
834-
newChildShadowView.layoutMetrics.marginInsets,
835-
newChildShadowView.layoutMetrics.paddingInsets);
851+
if (auto newProps = getYogaStylableProps(newChildShadowView)) {
852+
computedBoxModelRegistry_->store(
853+
surfaceId,
854+
newChildShadowView.tag,
855+
marginInsetsFromYogaStylableProps(*newProps.get()),
856+
paddingInsetsFromYogaStylableProps(*newProps.get()));
857+
}
836858
}
837859
}
838860
}

packages/react-native/ReactCommon/react/renderer/components/view/conversions.h

Lines changed: 98 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#include <glog/logging.h>
1111
#include <react/debug/react_native_expect.h>
1212
#include <react/renderer/components/view/primitives.h>
13+
#include <react/renderer/components/view/YogaStylableProps.h>
1314
#include <react/renderer/core/LayoutMetrics.h>
1415
#include <react/renderer/core/PropsParserContext.h>
1516
#include <react/renderer/core/RawProps.h>
@@ -164,22 +165,106 @@ inline LayoutMetrics layoutMetricsFromYogaNode(yoga::Node &yogaNode)
164165
layoutMetrics.layoutDirection = YGNodeLayoutGetDirection(&yogaNode) == YGDirectionRTL ? LayoutDirection::RightToLeft
165166
: LayoutDirection::LeftToRight;
166167

167-
layoutMetrics.marginInsets = EdgeInsets{
168-
floatFromYogaFloat(YGNodeLayoutGetMargin(&yogaNode, YGEdgeLeft)),
169-
floatFromYogaFloat(YGNodeLayoutGetMargin(&yogaNode, YGEdgeTop)),
170-
floatFromYogaFloat(YGNodeLayoutGetMargin(&yogaNode, YGEdgeRight)),
171-
floatFromYogaFloat(YGNodeLayoutGetMargin(&yogaNode, YGEdgeBottom))
172-
};
173-
layoutMetrics.paddingInsets = EdgeInsets{
174-
floatFromYogaFloat(YGNodeLayoutGetPadding(&yogaNode, YGEdgeLeft)),
175-
floatFromYogaFloat(YGNodeLayoutGetPadding(&yogaNode, YGEdgeTop)),
176-
floatFromYogaFloat(YGNodeLayoutGetPadding(&yogaNode, YGEdgeRight)),
177-
floatFromYogaFloat(YGNodeLayoutGetPadding(&yogaNode, YGEdgeBottom))
178-
};
179-
180168
return layoutMetrics;
181169
}
182170

171+
template <auto LayoutMember, typename... Args>
172+
float getLayoutEdgeValue(const YogaStylableProps& props, Args&&... args) {
173+
std::optional<float> result;
174+
auto tryResolve = [&](const auto &arg) -> bool {
175+
if (result.has_value()) {
176+
return false;
177+
}
178+
179+
using T = std::decay_t<decltype(arg)>;
180+
if constexpr (std::is_same_v<T, yoga::Style::Length YogaStylableProps::*>) {
181+
if (const auto& length = props.*arg; length.isDefined()) {
182+
result = length.value().unwrap();
183+
}
184+
} else if constexpr (std::is_same_v<T, facebook::yoga::Edge>) {
185+
if (auto edgeValue = (props.yogaStyle.*LayoutMember)(arg); edgeValue.isDefined()) {
186+
result = edgeValue.value().unwrap();
187+
}
188+
}
189+
return result.has_value();
190+
};
191+
192+
(tryResolve(std::forward<decltype(args)>(args)) || ...);
193+
return result.value_or(0.0f);
194+
}
195+
196+
inline EdgeInsets marginInsetsFromYogaStylableProps(const YogaStylableProps &props)
197+
{
198+
return {
199+
.left = getLayoutEdgeValue<&yoga::Style::margin>(
200+
props,
201+
&YogaStylableProps::marginInlineStart,
202+
facebook::yoga::Edge::Start,
203+
facebook::yoga::Edge::Left,
204+
&YogaStylableProps::marginInline,
205+
facebook::yoga::Edge::Horizontal,
206+
facebook::yoga::Edge::All),
207+
.top = getLayoutEdgeValue<&yoga::Style::margin>(
208+
props,
209+
facebook::yoga::Edge::Top,
210+
&YogaStylableProps::marginBlockStart,
211+
&YogaStylableProps::marginBlock,
212+
facebook::yoga::Edge::Vertical,
213+
facebook::yoga::Edge::All),
214+
.right = getLayoutEdgeValue<&yoga::Style::margin>(
215+
props,
216+
&YogaStylableProps::marginInlineEnd,
217+
facebook::yoga::Edge::End,
218+
facebook::yoga::Edge::Right,
219+
&YogaStylableProps::marginInline,
220+
facebook::yoga::Edge::Horizontal,
221+
facebook::yoga::Edge::All),
222+
.bottom = getLayoutEdgeValue<&yoga::Style::margin>(
223+
props,
224+
facebook::yoga::Edge::Bottom,
225+
&YogaStylableProps::marginBlockEnd,
226+
&YogaStylableProps::marginBlock,
227+
facebook::yoga::Edge::Vertical,
228+
facebook::yoga::Edge::All)
229+
};
230+
}
231+
232+
inline EdgeInsets paddingInsetsFromYogaStylableProps(const YogaStylableProps &props)
233+
{
234+
return {
235+
.left = getLayoutEdgeValue<&yoga::Style::padding>(
236+
props,
237+
&YogaStylableProps::paddingInlineStart,
238+
facebook::yoga::Edge::Start,
239+
facebook::yoga::Edge::Left,
240+
&YogaStylableProps::paddingInline,
241+
facebook::yoga::Edge::Horizontal,
242+
facebook::yoga::Edge::All),
243+
.top = getLayoutEdgeValue<&yoga::Style::padding>(
244+
props,
245+
facebook::yoga::Edge::Top,
246+
&YogaStylableProps::paddingBlockStart,
247+
&YogaStylableProps::paddingBlock,
248+
facebook::yoga::Edge::Vertical,
249+
facebook::yoga::Edge::All),
250+
.right = getLayoutEdgeValue<&yoga::Style::padding>(
251+
props,
252+
&YogaStylableProps::paddingInlineEnd,
253+
facebook::yoga::Edge::End,
254+
facebook::yoga::Edge::Right,
255+
&YogaStylableProps::paddingInline,
256+
facebook::yoga::Edge::Horizontal,
257+
facebook::yoga::Edge::All),
258+
.bottom = getLayoutEdgeValue<&yoga::Style::padding>(
259+
props,
260+
facebook::yoga::Edge::Bottom,
261+
&YogaStylableProps::paddingBlockEnd,
262+
&YogaStylableProps::paddingBlock,
263+
facebook::yoga::Edge::Vertical,
264+
facebook::yoga::Edge::All)
265+
};
266+
}
267+
183268
inline YGDirection yogaDirectionFromLayoutDirection(LayoutDirection direction)
184269
{
185270
switch (direction) {

packages/react-native/ReactCommon/react/renderer/core/LayoutMetrics.cpp

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -43,16 +43,6 @@ std::vector<DebugStringConvertibleObject> getDebugProps(
4343
",right:" + getDebugDescription(object.overflowInset.right, {}) +
4444
",bottom:" + getDebugDescription(object.overflowInset.bottom, {}) +
4545
",left:" + getDebugDescription(object.overflowInset.left, {}) + "}"},
46-
{.name = "marginInsets",
47-
.value = "{top:" + getDebugDescription(object.marginInsets.top, {}) +
48-
",right:" + getDebugDescription(object.marginInsets.right, {}) +
49-
",bottom:" + getDebugDescription(object.marginInsets.bottom, {}) +
50-
",left:" + getDebugDescription(object.marginInsets.left, {}) + "}"},
51-
{.name = "paddingInsets",
52-
.value = "{top:" + getDebugDescription(object.paddingInsets.top, {}) +
53-
",right:" + getDebugDescription(object.paddingInsets.right, {}) +
54-
",bottom:" + getDebugDescription(object.paddingInsets.bottom, {}) +
55-
",left:" + getDebugDescription(object.paddingInsets.left, {}) + "}"},
5646
{.name = "displayType",
5747
.value = object.displayType == DisplayType::None
5848
? "None"

packages/react-native/ReactCommon/react/renderer/core/LayoutMetrics.h

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -46,11 +46,6 @@ struct LayoutMetrics {
4646
// (like when using `overflow: clip` on Web).
4747
EdgeInsets overflowInset{};
4848

49-
// Width of the margins in each direction.
50-
EdgeInsets marginInsets{};
51-
// Width of the paddings in each direction.
52-
EdgeInsets paddingInsets{};
53-
5449
// Origin: the outer border of the node.
5550
// Size: includes content only.
5651
Rect getContentFrame() const
@@ -127,9 +122,7 @@ struct hash<facebook::react::LayoutMetrics> {
127122
layoutMetrics.displayType,
128123
layoutMetrics.layoutDirection,
129124
layoutMetrics.pointScaleFactor,
130-
layoutMetrics.overflowInset,
131-
layoutMetrics.marginInsets,
132-
layoutMetrics.paddingInsets);
125+
layoutMetrics.overflowInset);
133126
}
134127
};
135128

0 commit comments

Comments
 (0)