1 /*
2 * Copyright (c) 2024 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "movingphoto_layout_algorithm.h"
17 #include "movingphoto_pattern.h"
18
19 namespace OHOS::Ace::NG {
20 namespace {
21 constexpr int32_t ROUND_XMAGE_MODE_VALUE = 0;
22 constexpr int32_t ROUND_XMAGE_PIXEL_GAP = 2;
23 }
24
Layout(LayoutWrapper * layoutWrapper)25 void MovingPhotoLayoutAlgorithm::Layout(LayoutWrapper* layoutWrapper)
26 {
27 BoxLayoutAlgorithm::PerformLayout(layoutWrapper);
28 auto contentOffset = layoutWrapper->GetGeometryNode()->GetContentOffset();
29 auto host = layoutWrapper->GetHostNode();
30 CHECK_NULL_VOID(host);
31 auto pattern = DynamicCast<MovingPhotoPattern>(host->GetPattern());
32 CHECK_NULL_VOID(pattern);
33 SizeF xmageOffset = GetXmageLayoutOffset(layoutWrapper);
34 for (auto&& child : layoutWrapper->GetAllChildrenWithBuild()) {
35 CHECK_NULL_VOID(child);
36 if (child->GetHostTag() == V2::IMAGE_ETS_TAG) {
37 child->GetGeometryNode()->SetMarginFrameOffset({ contentOffset.GetX(), contentOffset.GetY() });
38 } else if (child->GetHostTag() == V2::COLUMN_ETS_TAG) {
39 child->GetGeometryNode()->SetMarginFrameOffset(
40 { contentOffset.GetX() + xmageOffset.Width(), contentOffset.GetY() + xmageOffset.Height() });
41 }
42 child->Layout();
43 if (child->GetHostTag() != V2::COLUMN_ETS_TAG) {
44 continue;
45 }
46 int32_t childCount = host->GetTotalChildCount();
47 CHECK_NULL_VOID(childCount >= 1);
48 auto childLayoutWrapper = host->GetChildByIndex(childCount - 1);
49 for (auto&& videoChild : childLayoutWrapper->GetAllChildrenWithBuild()) {
50 if (videoChild->GetHostTag() == V2::COLUMN_ETS_TAG) {
51 videoChild->GetGeometryNode()->SetMarginFrameOffset({ contentOffset.GetX(), contentOffset.GetY() });
52 }
53 videoChild->Layout();
54 }
55 }
56 }
57
Measure(LayoutWrapper * layoutWrapper)58 void MovingPhotoLayoutAlgorithm::Measure(LayoutWrapper* layoutWrapper)
59 {
60 auto layoutConstraint = layoutWrapper->GetLayoutProperty()->CreateChildConstraint();
61 auto contentSize = layoutWrapper->GetGeometryNode()->GetContentSize();
62 auto host = layoutWrapper->GetHostNode();
63 CHECK_NULL_VOID(host);
64 auto pattern = DynamicCast<MovingPhotoPattern>(host->GetPattern());
65 CHECK_NULL_VOID(pattern);
66 pattern->SetXmagePosition();
67 if (pattern->GetXmageModeStatus() && pattern->GetXmageModeValue() != ROUND_XMAGE_MODE_VALUE) {
68 MeasureInXmageMode(layoutWrapper);
69 return;
70 }
71 for (auto&& child : layoutWrapper->GetAllChildrenWithBuild()) {
72 CHECK_NULL_VOID(child);
73 if (child->GetHostTag() == V2::IMAGE_ETS_TAG) {
74 auto layoutConstraintForImage = layoutConstraint;
75 layoutConstraintForImage.UpdateSelfMarginSizeWithCheck(OptionalSizeF(contentSize));
76 layoutConstraintForImage.UpdateMaxSizeWithCheck(contentSize);
77 layoutConstraintForImage.UpdateMinSizeWithCheck(contentSize);
78 child->Measure(layoutConstraintForImage);
79 } else if (child->GetHostTag() == V2::COLUMN_ETS_TAG) {
80 auto layoutConstraintForColumn = layoutConstraint;
81 layoutConstraintForColumn.UpdateSelfMarginSizeWithCheck(OptionalSizeF(contentSize));
82 layoutConstraintForColumn.UpdateMaxSizeWithCheck(contentSize);
83 layoutConstraintForColumn.UpdateMinSizeWithCheck(contentSize);
84 child->Measure(layoutConstraintForColumn);
85 int32_t childCount = host->GetTotalChildCount();
86 CHECK_NULL_VOID(childCount >= 1);
87 auto childLayoutWrapper = host->GetChildByIndex(childCount - 1);
88 ChildMeasure(childLayoutWrapper, contentSize, layoutConstraint);
89 if (childLayoutWrapper) {
90 PerformMeasureSelf(&*childLayoutWrapper);
91 }
92 }
93 }
94 PerformMeasureSelf(layoutWrapper);
95 }
96
ChildMeasure(RefPtr<LayoutWrapper> childLayoutWrapper,SizeF contentSize,LayoutConstraintF layoutConstraint)97 void MovingPhotoLayoutAlgorithm::ChildMeasure(RefPtr<LayoutWrapper> childLayoutWrapper,
98 SizeF contentSize, LayoutConstraintF layoutConstraint)
99 {
100 for (auto&& columnChild : childLayoutWrapper->GetAllChildrenWithBuild()) {
101 if (columnChild->GetHostTag() == V2::COLUMN_ETS_TAG) {
102 auto layoutConstraintForVideo = layoutConstraint;
103 layoutConstraintForVideo.UpdateSelfMarginSizeWithCheck(OptionalSizeF(contentSize));
104 layoutConstraintForVideo.UpdateMaxSizeWithCheck(contentSize);
105 layoutConstraintForVideo.UpdateMinSizeWithCheck(contentSize);
106 columnChild->Measure(layoutConstraintForVideo);
107 }
108 }
109 }
110
111
MeasureInXmageMode(LayoutWrapper * layoutWrapper)112 void MovingPhotoLayoutAlgorithm::MeasureInXmageMode(LayoutWrapper* layoutWrapper)
113 {
114 auto layoutConstraint = layoutWrapper->GetLayoutProperty()->CreateChildConstraint();
115 auto contentSize = layoutWrapper->GetGeometryNode()->GetContentSize();
116 auto layoutProperty = DynamicCast<MovingPhotoLayoutProperty>(layoutWrapper->GetLayoutProperty());
117 CHECK_NULL_VOID(layoutProperty);
118 auto host = layoutWrapper->GetHostNode();
119 CHECK_NULL_VOID(host);
120 auto pattern = DynamicCast<MovingPhotoPattern>(host->GetPattern());
121 CHECK_NULL_VOID(pattern);
122 for (auto&& child : layoutWrapper->GetAllChildrenWithBuild()) {
123 CHECK_NULL_VOID(child);
124 if (child->GetHostTag() == V2::IMAGE_ETS_TAG) {
125 auto layoutConstraintForImage = layoutConstraint;
126 layoutConstraintForImage.UpdateSelfMarginSizeWithCheck(OptionalSizeF(contentSize));
127 layoutConstraintForImage.UpdateMaxSizeWithCheck(contentSize);
128 layoutConstraintForImage.UpdateMinSizeWithCheck(contentSize);
129 child->Measure(layoutConstraintForImage);
130 } else if (child->GetHostTag() == V2::COLUMN_ETS_TAG) {
131 auto layoutConstraintForColumn = layoutConstraint;
132 auto columnSize = contentSize;
133 SizeF xmageOffsetRatio = pattern->CalculateXmageOffsetRatio(contentSize);
134 SizeF imageSize = layoutProperty->GetImageSize().value();
135 columnSize.SetHeight(imageSize.Height() * xmageOffsetRatio.Height() + ROUND_XMAGE_PIXEL_GAP);
136 columnSize.SetWidth(imageSize.Width() * xmageOffsetRatio.Width() + ROUND_XMAGE_PIXEL_GAP);
137 layoutConstraintForColumn.UpdateSelfMarginSizeWithCheck(OptionalSizeF(columnSize));
138 layoutConstraintForColumn.UpdateMaxSizeWithCheck(columnSize);
139 layoutConstraintForColumn.UpdateMinSizeWithCheck(columnSize);
140 child->Measure(layoutConstraintForColumn);
141 int32_t childCount = host->GetTotalChildCount();
142 CHECK_NULL_VOID(childCount >= 1);
143 auto childLayoutWrapper = host->GetChildByIndex(childCount - 1);
144 ChildMeasureInXmage(childLayoutWrapper, contentSize, imageSize, xmageOffsetRatio, layoutConstraint);
145 if (childLayoutWrapper) {
146 PerformMeasureSelf(&*childLayoutWrapper);
147 }
148 }
149 }
150 PerformMeasureSelf(layoutWrapper);
151 }
152
ChildMeasureInXmage(RefPtr<LayoutWrapper> childLayoutWrapper,SizeF contentSize,SizeF imageSize,SizeF xmageRatio,LayoutConstraintF layoutConstraint)153 void MovingPhotoLayoutAlgorithm::ChildMeasureInXmage(RefPtr<LayoutWrapper> childLayoutWrapper, SizeF contentSize,
154 SizeF imageSize, SizeF xmageRatio, LayoutConstraintF layoutConstraint)
155 {
156 for (auto&& columnChild : childLayoutWrapper->GetAllChildrenWithBuild()) {
157 CHECK_NULL_VOID(columnChild);
158 if (columnChild->GetHostTag() == V2::COLUMN_ETS_TAG) {
159 auto layoutConstraintForVideo = layoutConstraint;
160 auto videoSize = contentSize;
161 videoSize.SetHeight(imageSize.Height() * xmageRatio.Height() + ROUND_XMAGE_PIXEL_GAP);
162 videoSize.SetWidth(imageSize.Width() * xmageRatio.Width() + ROUND_XMAGE_PIXEL_GAP);
163 layoutConstraintForVideo.UpdateSelfMarginSizeWithCheck(OptionalSizeF(videoSize));
164 layoutConstraintForVideo.UpdateMaxSizeWithCheck(videoSize);
165 layoutConstraintForVideo.UpdateMinSizeWithCheck(videoSize);
166 columnChild->Measure(layoutConstraintForVideo);
167 }
168 }
169 }
170
MeasureContent(const LayoutConstraintF & contentConstraint,LayoutWrapper * layoutWrapper)171 std::optional<SizeF> MovingPhotoLayoutAlgorithm::MeasureContent(
172 const LayoutConstraintF& contentConstraint, LayoutWrapper* layoutWrapper)
173 {
174 auto layoutSize = contentConstraint.selfIdealSize.IsValid() ? contentConstraint.selfIdealSize.ConvertToSizeT()
175 : contentConstraint.maxSize;
176 return layoutSize;
177 }
178
GetXmageLayoutOffset(LayoutWrapper * layoutWrapper)179 SizeF MovingPhotoLayoutAlgorithm::GetXmageLayoutOffset(LayoutWrapper* layoutWrapper)
180 {
181 SizeF ret = SizeF(0, 0);
182 auto host = layoutWrapper->GetHostNode();
183 CHECK_NULL_RETURN(host, ret);
184 auto pattern = DynamicCast<MovingPhotoPattern>(host->GetPattern());
185 CHECK_NULL_RETURN(pattern, ret);
186 if (pattern->GetXmageModeStatus() && (pattern->GetXmageModeValue() == ROUND_XMAGE_MODE_VALUE)) {
187 auto contentSize = layoutWrapper->GetGeometryNode()->GetContentSize();
188 auto layoutProperty = DynamicCast<MovingPhotoLayoutProperty>(layoutWrapper->GetLayoutProperty());
189 CHECK_NULL_RETURN(layoutProperty, ret);
190 if (!layoutProperty->HasXmageOffset()) {
191 return ret;
192 }
193 SizeF xmageOffset = layoutProperty->GetXmageOffset().value();
194 SizeF xmageOffsetRatio = pattern->CalculateXmageOffsetRatio(contentSize);
195 ret = SizeF(xmageOffset.Width() * xmageOffsetRatio.Width() - 1,
196 xmageOffset.Height() * xmageOffsetRatio.Height() - 1);
197 }
198 return ret;
199 }
200 } // namespace OHOS::Ace::NG