• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021 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 "core/components/wrap/render_wrap.h"
17 
18 #include <algorithm>
19 
20 #include "core/components/wrap/wrap_component.h"
21 
22 namespace OHOS::Ace {
23 namespace {
24 
25 constexpr int32_t MIN_COMPATIBLE_VERSION = 6;
26 
27 }
28 
Create()29 RefPtr<RenderNode> RenderWrap::Create()
30 {
31     return AceType::MakeRefPtr<RenderWrap>();
32 }
33 
Update(const RefPtr<Component> & component)34 void RenderWrap::Update(const RefPtr<Component>& component)
35 {
36     const RefPtr<WrapComponent> wrap = AceType::DynamicCast<WrapComponent>(component);
37     if (!wrap) {
38         LOGE("Wrap::RenderWrap update dynamicCast to nullptr error");
39         return;
40     }
41     direction_ = wrap->GetDirection();
42     // Whole alignment
43     alignment_ = wrap->GetAlignment();
44     // content main alignment
45     mainAlignment_ = wrap->GetMainAlignment();
46     // content cross alignment
47     crossAlignment_ = wrap->GetCrossAlignment();
48     spacing_ = wrap->GetSpacing();
49     contentSpace_ = wrap->GetContentSpacing();
50     dialogStretch_ = wrap->GetDialogStretch();
51     horizontalMeasure_ = wrap->GetHorizontalMeasure();
52     verticalMeasure_ = wrap->GetVerticalMeasure();
53     SetTextDirection(wrap->GetTextDirection());
54     isLeftToRight_ = (wrap->GetTextDirection() == TextDirection::LTR);
55     contentList_.clear();
56     MarkNeedLayout();
57 }
58 
PerformLayout()59 void RenderWrap::PerformLayout()
60 {
61     if (GetChildren().empty()) {
62         // no child will set current to empty and return
63         SetLayoutSize(Size(0.0, 0.0));
64         return;
65     }
66 
67     PerformLayoutInitialize();
68 
69     // overall size including space
70     totalMainLength_ = 0.0;
71     totalCrossLength_ = 0.0;
72 
73     LayoutParam layoutParam;
74     layoutParam.SetMinSize(Size(0.0, 0.0));
75     layoutParam.SetMaxSize(GetLeftSize(0.0, mainLengthLimit_, crossLengthLimit_));
76     if (dialogStretch_) {
77         HandleDialogStretch(layoutParam);
78     } else {
79         auto spacing = NormalizeToPx(spacing_);
80         auto contentSpace = NormalizeToPx(contentSpace_);
81         // content size
82         double currentMainLength = 0.0;
83         // the cross length is without space
84         double currentCrossLength = 0.0;
85         // number of item in content
86         int32_t count = 0;
87         // max baseline of each line
88         double baselineDistance = 0.0;
89         std::list<RefPtr<RenderNode>> itemsList;
90         for (auto& item : GetChildren()) {
91             item->Layout(layoutParam);
92 
93             if (mainLengthLimit_ >= currentMainLength + GetMainItemLength(item)) {
94                 currentMainLength += GetMainItemLength(item);
95                 currentMainLength += spacing;
96                 currentCrossLength = std::max(currentCrossLength, GetCrossItemLength(item));
97                 if (crossAlignment_ == WrapAlignment::BASELINE) {
98                     baselineDistance = std::max(baselineDistance, item->GetBaselineDistance(TextBaseline::ALPHABETIC));
99                 }
100                 itemsList.push_back(item);
101                 count += 1;
102             } else {
103                 currentMainLength -= spacing;
104                 if ((direction_ == WrapDirection::HORIZONTAL && !isLeftToRight_) ||
105                     (direction_ == WrapDirection::HORIZONTAL_REVERSE && isLeftToRight_) ||
106                     direction_ == WrapDirection::VERTICAL_REVERSE) {
107                     itemsList.reverse();
108                 }
109                 auto contentInfo = ContentInfo(currentMainLength, currentCrossLength, count, itemsList);
110                 contentInfo.maxBaselineDistance = baselineDistance;
111                 contentList_.emplace_back(contentInfo);
112                 itemsList.clear();
113                 totalMainLength_ = std::max(currentMainLength, totalMainLength_);
114                 totalCrossLength_ += currentCrossLength + contentSpace;
115                 currentMainLength = GetMainItemLength(item) + spacing;
116                 currentCrossLength = GetCrossItemLength(item);
117                 if (crossAlignment_ == WrapAlignment::BASELINE) {
118                     baselineDistance = item->GetBaselineDistance(TextBaseline::ALPHABETIC);
119                 }
120                 itemsList.push_back(item);
121                 count = 1;
122             }
123         }
124         // Add last content into list
125         currentMainLength -= spacing;
126         if ((direction_ == WrapDirection::HORIZONTAL && !isLeftToRight_) ||
127             (direction_ == WrapDirection::HORIZONTAL_REVERSE && isLeftToRight_) ||
128             (direction_ == WrapDirection::VERTICAL_REVERSE)) {
129             itemsList.reverse();
130         }
131         auto contentInfo = ContentInfo(currentMainLength, currentCrossLength, count, itemsList);
132         contentInfo.maxBaselineDistance = baselineDistance;
133         contentList_.emplace_back(contentInfo);
134         if ((direction_ == WrapDirection::VERTICAL || direction_ == WrapDirection::VERTICAL_REVERSE) &&
135             !isLeftToRight_) {
136             contentList_.reverse();
137         }
138         totalMainLength_ = std::max(currentMainLength, totalMainLength_);
139         // n contents has n - 1 space
140         totalCrossLength_ += currentCrossLength;
141     }
142     LayoutWholeWrap();
143     SetWrapLayoutSize(mainLengthLimit_, totalCrossLength_);
144     contentList_.clear();
145 }
146 
HandleDialogStretch(const LayoutParam & layoutParam)147 void RenderWrap::HandleDialogStretch(const LayoutParam& layoutParam)
148 {
149     int32_t dialogButtonNum = 0;
150     double totalLength = 0.0;
151     auto spacing = NormalizeToPx(spacing_);
152     auto contentSpace = NormalizeToPx(contentSpace_);
153     // whether the btn in the wrap needs wrap
154     for (const auto& item : GetChildren()) {
155         dialogButtonNum += 1;
156         item->Layout(layoutParam);
157         totalLength += GetMainItemLength(item) + spacing;
158         if (totalLength - spacing > mainLengthLimit_) {
159             dialogDirection_ = WrapDirection::VERTICAL;
160         }
161     }
162     if (dialogButtonNum == 0) {
163         LOGW("dialog button number is 0");
164         return;
165     }
166 
167     double buttonSize = (mainLengthLimit_ - spacing * (dialogButtonNum - 1)) / dialogButtonNum;
168     std::list<RefPtr<RenderNode>> itemsList;
169     for (const auto& item : GetChildren()) {
170         LayoutParam newParam;
171         // if dialog is vertical, stretch each button equally to fill max length, otherwise stretch equally in same line
172         double stretchSize = dialogDirection_ == WrapDirection::VERTICAL ? mainLengthLimit_ : buttonSize;
173         newParam.SetFixedSize(
174             (direction_ == WrapDirection::HORIZONTAL ? Size(stretchSize, item->GetLayoutSize().Height())
175                                                      : Size(item->GetLayoutSize().Width(), stretchSize)));
176         item->Layout(newParam);
177         itemsList.push_back(item);
178         totalMainLength_ = mainLengthLimit_;
179 
180         if (dialogDirection_ == WrapDirection::VERTICAL) {
181             // stretch each button equally to fill max length
182 
183             totalCrossLength_ += direction_ == WrapDirection::HORIZONTAL ? item->GetLayoutSize().Height()
184                                                                          : item->GetLayoutSize().Width();
185             totalCrossLength_ += contentSpace;
186             contentList_.emplace_back(
187                 ContentInfo(newParam.GetMaxSize().Width(), newParam.GetMaxSize().Height(), 1, itemsList));
188             itemsList.clear();
189         } else {
190             // stretch each button equally in same line
191             totalCrossLength_ = std::max(direction_ == WrapDirection::HORIZONTAL ? item->GetLayoutSize().Height()
192                                                                                  : item->GetLayoutSize().Width(),
193                 totalCrossLength_);
194         }
195     }
196     // if wrap direction is vertical, item has already added into content list
197     if (dialogDirection_ == WrapDirection::VERTICAL) {
198         totalCrossLength_ -= contentSpace;
199         return;
200     }
201     if (!isLeftToRight_) {
202         itemsList.reverse();
203     }
204     if (direction_ == WrapDirection::HORIZONTAL) {
205         contentList_.emplace_back(ContentInfo(mainLengthLimit_, totalCrossLength_, dialogButtonNum, itemsList));
206     } else {
207         contentList_.emplace_back(ContentInfo(totalCrossLength_, mainLengthLimit_, dialogButtonNum, itemsList));
208     }
209 }
210 
GetMainItemLength(const RefPtr<RenderNode> & item) const211 double RenderWrap::GetMainItemLength(const RefPtr<RenderNode>& item) const
212 {
213     return direction_ == WrapDirection::HORIZONTAL || direction_ == WrapDirection::HORIZONTAL_REVERSE
214                ? item->GetLayoutSize().Width()
215                : item->GetLayoutSize().Height();
216 }
217 
GetCrossItemLength(const RefPtr<RenderNode> & item) const218 double RenderWrap::GetCrossItemLength(const RefPtr<RenderNode>& item) const
219 {
220     return direction_ == WrapDirection::VERTICAL || direction_ == WrapDirection::VERTICAL_REVERSE
221                ? item->GetLayoutSize().Width()
222                : item->GetLayoutSize().Height();
223 }
224 
PerformLayoutInitialize()225 void RenderWrap::PerformLayoutInitialize()
226 {
227     if (direction_ == WrapDirection::HORIZONTAL || direction_ == WrapDirection::HORIZONTAL_REVERSE) {
228         mainLengthLimit_ = GetLayoutParam().GetMaxSize().Width();
229         crossLengthLimit_ = GetLayoutParam().GetMaxSize().Height();
230     } else {
231         mainLengthLimit_ =
232             GetLayoutParam().GetMaxSize().IsInfinite() ? viewPort_.Height() : GetLayoutParam().GetMaxSize().Height();
233         crossLengthLimit_ = GetLayoutParam().GetMaxSize().Width();
234     }
235 }
236 
GetLeftSize(double crossLength,double mainLeftLength,double crossLeftLength) const237 Size RenderWrap::GetLeftSize(double crossLength, double mainLeftLength, double crossLeftLength) const
238 {
239     if (direction_ == WrapDirection::HORIZONTAL || direction_ == WrapDirection::HORIZONTAL_REVERSE) {
240         return Size(mainLeftLength, crossLeftLength - crossLength);
241     } else {
242         return Size(crossLeftLength - crossLength, mainLeftLength);
243     }
244 }
245 
LayoutWholeWrap()246 void RenderWrap::LayoutWholeWrap()
247 {
248     int32_t contentNum = static_cast<int32_t>(contentList_.size());
249     if (contentNum == 0) {
250         LOGW("no content in wrap");
251         return;
252     }
253     Offset startPosition;
254     Offset betweenPosition;
255     bool isHorizontal = direction_ == WrapDirection::HORIZONTAL || direction_ == WrapDirection::HORIZONTAL_REVERSE;
256 
257     switch (alignment_) {
258         case WrapAlignment::START: {
259             startPosition = Offset(0.0, 0.0);
260             betweenPosition = Offset();
261             break;
262         }
263         case WrapAlignment::END: {
264             startPosition = GetContentOffset(totalCrossLength_);
265             betweenPosition = Offset();
266             break;
267         }
268         case WrapAlignment::CENTER: {
269             // divided the space by two
270             startPosition = GetContentOffset(totalCrossLength_) / 2;
271             betweenPosition = Offset();
272             break;
273         }
274         case WrapAlignment::SPACE_BETWEEN: {
275             startPosition = Offset(0.0, 0.0);
276             double crossSpace =
277                 contentNum > 1 ? (crossLengthLimit_ - totalCrossLength_) / static_cast<double>(contentNum - 1) : 0.0;
278             betweenPosition = isHorizontal ? Offset(0.0, crossSpace) : Offset(crossSpace, 0.0);
279             break;
280         }
281         case WrapAlignment::SPACE_EVENLY: {
282             double leftSpace = crossLengthLimit_ - totalCrossLength_;
283             double crossSpace = leftSpace / static_cast<double>(contentNum + 1);
284             startPosition = isHorizontal ? Offset(0.0, crossSpace) : Offset(crossSpace, 0.0);
285             betweenPosition = isHorizontal ? Offset(0.0, crossSpace) : Offset(crossSpace, 0.0);
286             break;
287         }
288         case WrapAlignment::SPACE_AROUND: {
289             double leftSpace = crossLengthLimit_ - totalCrossLength_;
290             double crossSpace = leftSpace / static_cast<double>(contentNum);
291             startPosition = isHorizontal ? Offset(0.0, crossSpace / 2) : Offset(crossSpace / 2, 0.0);
292             betweenPosition = isHorizontal ? Offset(0.0, crossSpace) : Offset(crossSpace, 0.0);
293             break;
294         }
295         default: {
296             LOGE("Wrap::alignment setting error.");
297             startPosition = Offset(0.0, 0.0);
298             betweenPosition = Offset();
299             break;
300         }
301     }
302     auto context = context_.Upgrade();
303     bool applyNewOffset = context ? context->GetMinPlatformVersion() >= MIN_COMPATIBLE_VERSION : false;
304     if (applyNewOffset) {
305         // In content type, wrap is as large as children, no need to set alignment_.
306         if ((!isHorizontal && horizontalMeasure_ == MeasureType::CONTENT) ||
307             (isHorizontal && verticalMeasure_ == MeasureType::CONTENT)) {
308             startPosition = Offset();
309             betweenPosition = Offset();
310         }
311     }
312     TraverseContent(startPosition, betweenPosition);
313 }
314 
GetContentOffset(double totalCrossLength) const315 Offset RenderWrap::GetContentOffset(double totalCrossLength) const
316 {
317     if (direction_ == WrapDirection::HORIZONTAL || direction_ == WrapDirection::HORIZONTAL_REVERSE) {
318         return Offset(0.0, crossLengthLimit_ - totalCrossLength);
319     } else {
320         return Offset(crossLengthLimit_ - totalCrossLength, 0.0);
321     }
322 }
323 
TraverseContent(const Offset & startPosition,const Offset & betweenPosition) const324 void RenderWrap::TraverseContent(const Offset& startPosition, const Offset& betweenPosition) const
325 {
326     // determine the content start position by main axis
327     Offset accumulateOffset = startPosition;
328     int32_t startItemIndex = 0;
329     double currentMainSpaceLength = 0.0;
330     for (const auto& content : contentList_) {
331         // dfs positioned item in each content
332         currentMainSpaceLength = mainLengthLimit_ - content.mainLength_;
333         int32_t itemNum = content.count_;
334         if (itemNum == 0) {
335             LOGE("fail to TraverseContent due to item num is zero");
336             return;
337         }
338 
339         switch (mainAlignment_) {
340             case WrapAlignment::START: {
341                 if ((direction_ == WrapDirection::HORIZONTAL && !isLeftToRight_) ||
342                     (direction_ == WrapDirection::HORIZONTAL_REVERSE && isLeftToRight_) ||
343                     (direction_ == WrapDirection::VERTICAL_REVERSE)) {
344                     PositionedItem(0.0, content, accumulateOffset + GetItemMainOffset(currentMainSpaceLength),
345                         content.crossLength_);
346                 } else {
347                     PositionedItem(0.0, content, accumulateOffset, content.crossLength_);
348                 }
349                 break;
350             }
351             case WrapAlignment::END: {
352                 if ((direction_ == WrapDirection::HORIZONTAL && !isLeftToRight_) ||
353                     (direction_ == WrapDirection::HORIZONTAL_REVERSE && isLeftToRight_) ||
354                     direction_ == WrapDirection::VERTICAL_REVERSE) {
355                     PositionedItem(0.0, content, accumulateOffset, content.crossLength_);
356                 } else {
357                     PositionedItem(0.0, content, accumulateOffset + GetItemMainOffset(currentMainSpaceLength),
358                         content.crossLength_);
359                 }
360                 break;
361             }
362             case WrapAlignment::CENTER: {
363                 // divided the space by two
364                 PositionedItem(0.0, content, accumulateOffset + GetItemMainOffset(currentMainSpaceLength / 2),
365                     content.crossLength_);
366                 break;
367             }
368             case WrapAlignment::SPACE_BETWEEN: {
369                 double betweenSpace = (itemNum - 1 == 0) ? 0.0 : currentMainSpaceLength / (itemNum - 1);
370                 PositionedItem(betweenSpace, content, accumulateOffset, content.crossLength_);
371                 break;
372             }
373             case WrapAlignment::SPACE_AROUND: {
374                 double itemMainSpace = currentMainSpaceLength / itemNum;
375                 PositionedItem(itemMainSpace, content, accumulateOffset + GetItemMainOffset(itemMainSpace / 2),
376                     content.crossLength_);
377                 break;
378             }
379             case WrapAlignment::SPACE_EVENLY: {
380                 double itemMainSpace = currentMainSpaceLength / (itemNum + 1);
381                 PositionedItem(
382                     itemMainSpace, content, accumulateOffset + GetItemMainOffset(itemMainSpace), content.crossLength_);
383                 break;
384             }
385             default: {
386                 LOGE("Wrap::mainAlignment setting error. Now using START");
387                 PositionedItem(0.0, content, accumulateOffset, content.crossLength_);
388                 break;
389             }
390         }
391         auto contentSpace = NormalizeToPx(contentSpace_);
392         startItemIndex += itemNum;
393         accumulateOffset += betweenPosition;
394         accumulateOffset += (direction_ == WrapDirection::HORIZONTAL || direction_ == WrapDirection::HORIZONTAL_REVERSE)
395                                 ? Offset(0.0, content.crossLength_ + contentSpace)
396                                 : Offset(content.crossLength_ + contentSpace, 0.0);
397     }
398 }
399 
GetItemMainOffset(double mainSpace) const400 Offset RenderWrap::GetItemMainOffset(double mainSpace) const
401 {
402     // calculate the offset of each item in content
403     if (direction_ == WrapDirection::HORIZONTAL || direction_ == WrapDirection::HORIZONTAL_REVERSE) {
404         return Offset(mainSpace, 0.0);
405     } else {
406         return Offset(0.0, mainSpace);
407     }
408 }
409 
PositionedItem(double betweenSpace,const ContentInfo & content,const Offset & position,double totalCrossSpace) const410 void RenderWrap::PositionedItem(
411     double betweenSpace, const ContentInfo& content, const Offset& position, double totalCrossSpace) const
412 {
413     Offset itemPositionOffset;
414     // iterate every item in content
415     for (const auto& item : content.itemList_) {
416         switch (crossAlignment_) {
417             case WrapAlignment::START: {
418                 if ((direction_ == WrapDirection::VERTICAL && !isLeftToRight_) ||
419                     (direction_ == WrapDirection::VERTICAL_REVERSE && !isLeftToRight_)) {
420                     HandleEndAlignment(totalCrossSpace, item, position, betweenSpace, itemPositionOffset);
421                 } else {
422                     HandleStartAlignment(item, position, betweenSpace, itemPositionOffset);
423                 }
424                 break;
425             }
426             case WrapAlignment::STRETCH: {
427                 PlaceItemAndLog(item, position + itemPositionOffset, "STRETCH");
428                 // stretch the component in wrap
429                 LayoutParam layoutParam;
430                 auto spacing = NormalizeToPx(spacing_);
431                 if (direction_ == WrapDirection::HORIZONTAL || direction_ == WrapDirection::HORIZONTAL_REVERSE) {
432                     itemPositionOffset += Offset(item->GetLayoutSize().Width() + betweenSpace + spacing, 0.0);
433                     layoutParam.SetFixedSize(Size(item->GetLayoutSize().Width(), totalCrossSpace));
434                 } else {
435                     itemPositionOffset += Offset(0.0, item->GetLayoutSize().Height() + betweenSpace + spacing);
436                     layoutParam.SetFixedSize(Size(totalCrossSpace, item->GetLayoutSize().Height()));
437                 }
438                 item->Layout(layoutParam);
439                 break;
440             }
441             case WrapAlignment::END: {
442                 if ((direction_ == WrapDirection::VERTICAL && !isLeftToRight_) ||
443                     (direction_ == WrapDirection::VERTICAL_REVERSE && !isLeftToRight_)) {
444                     HandleStartAlignment(item, position, betweenSpace, itemPositionOffset);
445                 } else {
446                     HandleEndAlignment(totalCrossSpace, item, position, betweenSpace, itemPositionOffset);
447                 }
448                 break;
449             }
450             case WrapAlignment::CENTER: {
451                 // divide the space by two
452                 HandleCenterAlignment(totalCrossSpace, item, position, betweenSpace, itemPositionOffset);
453                 break;
454             }
455             case WrapAlignment::BASELINE: {
456                 if (direction_ == WrapDirection::VERTICAL || direction_ == WrapDirection::VERTICAL_REVERSE) {
457                     if (isLeftToRight_) {
458                         HandleStartAlignment(item, position, betweenSpace, itemPositionOffset);
459                     } else {
460                         HandleEndAlignment(totalCrossSpace, item, position, betweenSpace, itemPositionOffset);
461                     }
462                 } else {
463                     HandleBaselineAlignment(
464                         content.maxBaselineDistance, item, position, betweenSpace, itemPositionOffset);
465                 }
466                 break;
467             }
468             default: {
469                 LOGW("Wrap::crossAlignment setting error. Now using START");
470                 if ((direction_ == WrapDirection::VERTICAL && !isLeftToRight_) ||
471                     (direction_ == WrapDirection::VERTICAL_REVERSE && !isLeftToRight_)) {
472                     HandleEndAlignment(totalCrossSpace, item, position, betweenSpace, itemPositionOffset);
473                 } else {
474                     HandleStartAlignment(item, position, betweenSpace, itemPositionOffset);
475                 }
476                 break;
477             }
478         }
479     }
480 }
481 
PlaceItemAndLog(const RefPtr<RenderNode> & node,const Offset & position,const std::string & align) const482 void RenderWrap::PlaceItemAndLog(const RefPtr<RenderNode>& node, const Offset& position, const std::string& align) const
483 {
484     node->SetPosition(position);
485     LOGD("Wrap::PositionedItem %s item position x:%lf, y:%lf", align.c_str(), position.GetX(), position.GetY());
486 }
487 
HandleCenterAlignment(double totalCrossSpace,const RefPtr<RenderNode> & item,const Offset & position,double betweenSpace,Offset & itemPositionOffset) const488 void RenderWrap::HandleCenterAlignment(double totalCrossSpace, const RefPtr<RenderNode>& item, const Offset& position,
489     double betweenSpace, Offset& itemPositionOffset) const
490 {
491     // itemPositionOffset will change in this function
492     Offset crossOffset;
493     auto spacing = NormalizeToPx(spacing_);
494     if (direction_ == WrapDirection::HORIZONTAL || direction_ == WrapDirection::HORIZONTAL_REVERSE) {
495         crossOffset = Offset(0.0, (totalCrossSpace - item->GetLayoutSize().Height()) / 2.0);
496         PlaceItemAndLog(item, position + itemPositionOffset + crossOffset, "CENTER");
497         itemPositionOffset += Offset(item->GetLayoutSize().Width() + betweenSpace + spacing, 0.0);
498     } else {
499         crossOffset = Offset((totalCrossSpace - item->GetLayoutSize().Width()) / 2, 0.0);
500         PlaceItemAndLog(item, position + itemPositionOffset + crossOffset, "CENTER");
501         itemPositionOffset += Offset(0.0, item->GetLayoutSize().Height() + betweenSpace + spacing);
502     }
503 }
504 
HandleEndAlignment(double totalCrossSpace,const RefPtr<RenderNode> & item,const Offset & position,double betweenSpace,Offset & itemPositionOffset) const505 void RenderWrap::HandleEndAlignment(double totalCrossSpace, const RefPtr<RenderNode>& item, const Offset& position,
506     double betweenSpace, Offset& itemPositionOffset) const
507 {
508     // itemPositionOffset will change in this function
509     Offset crossOffset;
510     auto spacing = NormalizeToPx(spacing_);
511     if (direction_ == WrapDirection::HORIZONTAL || direction_ == WrapDirection::HORIZONTAL_REVERSE) {
512         crossOffset = Offset(0.0, totalCrossSpace - item->GetLayoutSize().Height());
513         PlaceItemAndLog(item, position + itemPositionOffset + crossOffset, "END");
514         itemPositionOffset += Offset(item->GetLayoutSize().Width() + betweenSpace + spacing, 0.0);
515     } else {
516         crossOffset = Offset(totalCrossSpace - item->GetLayoutSize().Width(), 0.0);
517         PlaceItemAndLog(item, position + itemPositionOffset + crossOffset, "END");
518         itemPositionOffset += Offset(0.0, item->GetLayoutSize().Height() + betweenSpace + spacing);
519     }
520 }
521 
HandleBaselineAlignment(double totalCrossSpace,const RefPtr<RenderNode> & item,const Offset & position,double betweenSpace,Offset & itemPositionOffset) const522 void RenderWrap::HandleBaselineAlignment(double totalCrossSpace, const RefPtr<RenderNode>& item, const Offset& position,
523     double betweenSpace, Offset& itemPositionOffset) const
524 {
525     Offset crossOffset;
526     auto spacing = NormalizeToPx(spacing_);
527     crossOffset = Offset(0.0, totalCrossSpace - item->GetBaselineDistance(TextBaseline::ALPHABETIC));
528     PlaceItemAndLog(item, position + itemPositionOffset + crossOffset, "Baseline");
529     itemPositionOffset += Offset(item->GetLayoutSize().Width() + betweenSpace + spacing, 0.0);
530 }
531 
HandleStartAlignment(const RefPtr<RenderNode> & item,const Offset & position,double betweenSpace,Offset & itemPositionOffset) const532 void RenderWrap::HandleStartAlignment(
533     const RefPtr<RenderNode>& item, const Offset& position, double betweenSpace, Offset& itemPositionOffset) const
534 {
535     PlaceItemAndLog(item, position + itemPositionOffset, "START");
536     // Decide content offset position
537     auto spacing = NormalizeToPx(spacing_);
538     bool isHorizontal = direction_ == WrapDirection::HORIZONTAL || direction_ == WrapDirection::HORIZONTAL_REVERSE;
539     itemPositionOffset += Offset(isHorizontal ? item->GetLayoutSize().Width() + betweenSpace + spacing : 0.0,
540         isHorizontal ? 0.0 : item->GetLayoutSize().Height() + betweenSpace + spacing);
541 }
542 
ClearRenderObject()543 void RenderWrap::ClearRenderObject()
544 {
545     RenderNode::ClearRenderObject();
546     direction_ = WrapDirection::VERTICAL;
547     alignment_ = WrapAlignment::START;
548     mainAlignment_ = WrapAlignment::START;
549     crossAlignment_ = WrapAlignment::START;
550     spacing_ = Dimension();
551     contentSpace_ = Dimension();
552     mainLengthLimit_ = 0.0;
553     crossLengthLimit_ = 0.0;
554     totalMainLength_ = 0.0;
555     totalCrossLength_ = 0.0;
556 
557     dialogDirection_ = WrapDirection::HORIZONTAL;
558     dialogStretch_ = false;
559     isLeftToRight_ = true;
560 }
561 
MaybeRelease()562 bool RenderWrap::MaybeRelease()
563 {
564     auto context = GetContext().Upgrade();
565     if (context && context->GetRenderFactory() && context->GetRenderFactory()->GetRenderWrapFactory()->Recycle(this)) {
566         ClearRenderObject();
567         return false;
568     }
569     return true;
570 }
571 
572 } // namespace OHOS::Ace