1717namespace facebook {
1818namespace 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+
2074LayoutableShadowNode::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