Skip to content

Commit 64528e5

Browse files
sammy-SCfacebook-github-bot
authored andcommitted
Fix measure when view is inverted
Summary: changelog: [internal] Vertical and horizontal inversion was not taken into account in `computeRelativeLayoutMetrics`. To fix it, we precompute frames to include inversions. Reviewed By: mdvacca Differential Revision: D37994809 fbshipit-source-id: 043e6f19b6fa577f61fa3c739ce2d751ef973cc3
1 parent 143a0f7 commit 64528e5

File tree

5 files changed

+451
-8
lines changed

5 files changed

+451
-8
lines changed

ReactCommon/react/renderer/core/LayoutableShadowNode.cpp

Lines changed: 67 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,60 @@
1717
namespace facebook {
1818
namespace react {
1919

20+
template <class T>
21+
using LayoutableSmallVector = butter::small_vector<T, 16>;
22+
23+
static LayoutableSmallVector<Rect> calculateTransformedFrames(
24+
LayoutableSmallVector<ShadowNode const *> const &shadowNodeList,
25+
LayoutableShadowNode::LayoutInspectingPolicy policy) {
26+
auto size = shadowNodeList.size();
27+
auto transformedFrames = LayoutableSmallVector<Rect>{size};
28+
auto transformation = Transform::Identity();
29+
30+
for (int i = size - 1; i >= 0; --i) {
31+
auto currentShadowNode =
32+
traitCast<LayoutableShadowNode const *>(shadowNodeList.at(i));
33+
auto currentFrame = currentShadowNode->getLayoutMetrics().frame;
34+
35+
if (policy.includeTransform) {
36+
if (Transform::isVerticalInversion(transformation)) {
37+
auto parentShadowNode =
38+
traitCast<LayoutableShadowNode const *>(shadowNodeList.at(i + 1));
39+
currentFrame.origin.y =
40+
parentShadowNode->getLayoutMetrics().frame.size.height -
41+
currentFrame.size.height - currentFrame.origin.y;
42+
}
43+
44+
if (Transform::isHorizontalInversion(transformation)) {
45+
auto parentShadowNode =
46+
traitCast<LayoutableShadowNode const *>(shadowNodeList.at(i + 1));
47+
currentFrame.origin.x =
48+
parentShadowNode->getLayoutMetrics().frame.size.width -
49+
currentFrame.size.width - currentFrame.origin.x;
50+
}
51+
52+
if (i != size - 1) {
53+
auto parentShadowNode =
54+
traitCast<LayoutableShadowNode const *>(shadowNodeList.at(i + 1));
55+
auto contentOritinOffset = parentShadowNode->getContentOriginOffset();
56+
if (Transform::isVerticalInversion(transformation)) {
57+
contentOritinOffset.y = -contentOritinOffset.y;
58+
}
59+
if (Transform::isHorizontalInversion(transformation)) {
60+
contentOritinOffset.x = -contentOritinOffset.x;
61+
}
62+
currentFrame.origin += contentOritinOffset;
63+
}
64+
65+
transformation = transformation * currentShadowNode->getTransform();
66+
}
67+
68+
transformedFrames[i] = currentFrame;
69+
}
70+
71+
return transformedFrames;
72+
}
73+
2074
LayoutableShadowNode::LayoutableShadowNode(
2175
ShadowNodeFragment const &fragment,
2276
ShadowNodeFamily::Shared const &family,
@@ -34,6 +88,8 @@ LayoutMetrics LayoutableShadowNode::computeRelativeLayoutMetrics(
3488
ShadowNodeFamily const &descendantNodeFamily,
3589
LayoutableShadowNode const &ancestorNode,
3690
LayoutInspectingPolicy policy) {
91+
// Prelude.
92+
3793
if (&descendantNodeFamily == &ancestorNode.getFamily()) {
3894
// Layout metrics of a node computed relatively to the same node are equal
3995
// to `transform`-ed layout metrics of the node with zero `origin`.
@@ -53,10 +109,12 @@ LayoutMetrics LayoutableShadowNode::computeRelativeLayoutMetrics(
53109
return EmptyLayoutMetrics;
54110
}
55111

112+
// ------------------------------
113+
56114
// Step 1.
57115
// Creating a list of nodes that form a chain from the descender node to
58116
// ancestor node inclusively.
59-
auto shadowNodeList = butter::small_vector<ShadowNode const *, 16>{};
117+
auto shadowNodeList = LayoutableSmallVector<ShadowNode const *>{};
60118

61119
// Finding the measured node.
62120
// The last element in the `AncestorList` is a pair of a parent of the node
@@ -81,6 +139,8 @@ LayoutMetrics LayoutableShadowNode::computeRelativeLayoutMetrics(
81139
}
82140
}
83141

142+
// ------------------------------
143+
84144
// Step 2.
85145
// Computing the initial size of the measured node.
86146
auto descendantLayoutableNode =
@@ -90,6 +150,9 @@ LayoutMetrics LayoutableShadowNode::computeRelativeLayoutMetrics(
90150
return EmptyLayoutMetrics;
91151
}
92152

153+
// ------------------------------
154+
155+
auto transformedFrames = calculateTransformedFrames(shadowNodeList, policy);
93156
auto layoutMetrics = descendantLayoutableNode->getLayoutMetrics();
94157
auto &resultFrame = layoutMetrics.frame;
95158
resultFrame.origin = {0, 0};
@@ -105,7 +168,7 @@ LayoutMetrics LayoutableShadowNode::computeRelativeLayoutMetrics(
105168
return EmptyLayoutMetrics;
106169
}
107170

108-
auto currentFrame = currentShadowNode->getLayoutMetrics().frame;
171+
auto currentFrame = transformedFrames[i];
109172
if (i == size - 1) {
110173
// If it's the last element, its origin is irrelevant.
111174
currentFrame.origin = {0, 0};
@@ -122,12 +185,10 @@ LayoutMetrics LayoutableShadowNode::computeRelativeLayoutMetrics(
122185
}
123186

124187
resultFrame.origin += currentFrame.origin;
125-
126-
if (i != 0 && policy.includeTransform) {
127-
resultFrame.origin += currentShadowNode->getContentOriginOffset();
128-
}
129188
}
130189

190+
// ------------------------------
191+
131192
return layoutMetrics;
132193
}
133194

0 commit comments

Comments
 (0)