• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2023 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_ng/pattern/security_component/security_component_layout_algorithm.h"
17 
18 #include "core/components/common/properties/alignment.h"
19 #include "core/components_ng/pattern/button/button_layout_property.h"
20 #include "core/components_ng/pattern/security_component/security_component_log.h"
21 #include "core/components_ng/pattern/text/text_pattern.h"
22 #include "unicode/uchar.h"
23 
24 namespace {
25 constexpr float HALF = 2.0f;
26 constexpr float TEXT_OUT_OF_RANGE_PERCENT = 0.3f; // 30%
27 constexpr float TEXT_OUT_OF_WIDTH_PERCENT = 0.1f; // 10%
28 constexpr float RANGE_RATIO = 1.414f;
29 constexpr float ICON_RANGE_RATIO = 0.7f;
30 }
31 
32 namespace OHOS::Ace::NG {
GetChildWrapper(LayoutWrapper * layoutWrapper,const std::string & tag)33 RefPtr<LayoutWrapper> SecurityComponentLayoutAlgorithm::GetChildWrapper(LayoutWrapper* layoutWrapper,
34     const std::string& tag)
35 {
36     int32_t count = layoutWrapper->GetTotalChildCount();
37     for (int32_t i = 0; i < count; i++) {
38         auto childWrapper = layoutWrapper->GetOrCreateChildByIndex(i);
39         if (childWrapper == nullptr) {
40             continue;
41         }
42         if (childWrapper->GetHostTag() == tag) {
43             return childWrapper;
44         }
45     }
46     return nullptr;
47 }
48 
UpdateChildPosition(LayoutWrapper * layoutWrapper,const std::string & tag,OffsetF & offset)49 void SecurityComponentLayoutAlgorithm::UpdateChildPosition(LayoutWrapper* layoutWrapper, const std::string& tag,
50     OffsetF& offset)
51 {
52     auto childWrapper = GetChildWrapper(layoutWrapper, tag);
53     CHECK_NULL_VOID(childWrapper);
54     auto childNode = childWrapper->GetHostNode();
55     CHECK_NULL_VOID(childNode);
56     auto geometryNode = childNode->GetGeometryNode();
57     CHECK_NULL_VOID(geometryNode);
58     geometryNode->SetMarginFrameOffset(
59         OffsetF(std::round(offset.GetX()), std::round(offset.GetY())));
60 }
61 
CreateDefaultChildConstraint(RefPtr<SecurityComponentLayoutProperty> & securityComponentProperty)62 static LayoutConstraintF CreateDefaultChildConstraint(
63     RefPtr<SecurityComponentLayoutProperty>& securityComponentProperty)
64 {
65     auto constraint = securityComponentProperty->CreateChildConstraint();
66     SizeT<float> maxSize { Infinity<float>(), Infinity<float>() };
67     constraint.maxSize = maxSize;
68     return constraint;
69 }
70 
MeasureButton(LayoutWrapper * layoutWrapper,RefPtr<SecurityComponentLayoutProperty> & securityComponentProperty)71 void SecurityComponentLayoutAlgorithm::MeasureButton(LayoutWrapper* layoutWrapper,
72     RefPtr<SecurityComponentLayoutProperty>& securityComponentProperty)
73 {
74     auto buttonWrapper = GetChildWrapper(layoutWrapper, V2::BUTTON_ETS_TAG);
75     CHECK_NULL_VOID(buttonWrapper);
76     auto buttonLayoutProperty = DynamicCast<ButtonLayoutProperty>(buttonWrapper->GetLayoutProperty());
77     CHECK_NULL_VOID(buttonLayoutProperty);
78     auto buttonConstraint = CreateDefaultChildConstraint(securityComponentProperty);
79     if (securityComponentProperty->GetBackgroundType() == static_cast<int32_t>(ButtonType::CIRCLE)) {
80         buttonConstraint.selfIdealSize.SetSize(SizeF(std::min(componentWidth_, componentHeight_),
81             std::min(componentWidth_, componentHeight_)));
82         if (GreatNotEqual(componentWidth_, componentHeight_)) {
83             left_.ShrinkWidth((componentWidth_ / HALF) - (componentHeight_ / HALF));
84         } else if (GreatNotEqual(componentHeight_, componentWidth_)) {
85             top_.ShrinkHeight((componentHeight_ / HALF) - (componentWidth_ / HALF));
86         }
87         componentWidth_ = componentHeight_ = std::min(componentWidth_, componentHeight_);
88     } else {
89         buttonConstraint.selfIdealSize.SetSize(SizeF(componentWidth_, componentHeight_));
90     }
91 
92     buttonWrapper->Measure(std::optional<LayoutConstraintF>(buttonConstraint));
93     auto geometryNode = buttonWrapper->GetGeometryNode();
94     CHECK_NULL_VOID(geometryNode);
95     geometryNode->SetFrameSize(SizeF(componentWidth_, componentHeight_));
96 }
97 
InitPadding(RefPtr<SecurityComponentLayoutProperty> & property)98 void SecurityComponentLayoutAlgorithm::InitPadding(RefPtr<SecurityComponentLayoutProperty>& property)
99 {
100     auto context = PipelineContext::GetCurrentContextSafely();
101     CHECK_NULL_VOID(context);
102     auto theme = context->GetTheme<SecurityComponentTheme>();
103     CHECK_NULL_VOID(theme);
104 
105     double borderWidth = property->GetBackgroundBorderWidth().value_or(Dimension(0.0)).ConvertToPx();
106     double size = property->GetBackgroundLeftPadding().value_or(theme->GetBackgroundLeftPadding()).ConvertToPx() +
107         borderWidth;
108     left_.Init(false,
109         property->GetBackgroundLeftPadding().has_value(), size, borderWidth);
110 
111     size = property->GetBackgroundTopPadding().value_or(theme->GetBackgroundTopPadding()).ConvertToPx() +
112         borderWidth;
113     top_.Init(true,
114         property->GetBackgroundTopPadding().has_value(), size, borderWidth);
115 
116     size = property->GetBackgroundRightPadding().value_or(theme->GetBackgroundRightPadding()).ConvertToPx() +
117         borderWidth;
118     right_.Init(false,
119         property->GetBackgroundRightPadding().has_value(), size, borderWidth);
120 
121     size = property->GetBackgroundBottomPadding().value_or(theme->GetBackgroundBottomPadding()).ConvertToPx() +
122         borderWidth;
123     bottom_.Init(true,
124         property->GetBackgroundBottomPadding().has_value(), size, borderWidth);
125 
126     size = property->GetTextIconSpace().value_or(theme->GetTextIconSpace()).ConvertToPx();
127     middle_.Init(isVertical_, property->GetTextIconSpace().has_value(), size, 0.0);
128 }
129 
UpdateTextSize()130 void SecurityComponentLayoutAlgorithm::UpdateTextSize()
131 {
132     auto minWidth = std::min(maxWidth_, componentWidth_);
133     if (!NearEqual(idealWidth_, 0.0)) {
134         minWidth = std::min(minWidth, idealWidth_);
135     }
136     float leftSpace;
137     if (isVertical_) {
138         leftSpace = left_.width_ + icon_.width_ + right_.width_;
139     } else {
140         leftSpace = left_.width_ + middle_.width_ + icon_.width_ + right_.width_;
141     }
142     text_.DoMeasure(isVertical_, minWidth, leftSpace);
143 }
144 
ShrinkWidth(double diff)145 double SecurityComponentLayoutAlgorithm::ShrinkWidth(double diff)
146 {
147     // first shrink left and right padding
148     double remain = left_.ShrinkWidth(diff / HALF);
149     remain = right_.ShrinkWidth(remain + (diff / HALF));
150     remain = left_.ShrinkWidth(remain);
151     if (NearEqual(remain, 0.0)) {
152         MeasureIntegralSize();
153         return componentWidth_;
154     }
155 
156     // if horizontal shrink IconTextSpace
157     remain = middle_.ShrinkWidth(remain);
158     if (NearEqual(remain, 0.0)) {
159         MeasureIntegralSize();
160         return componentWidth_;
161     }
162 
163     double iconWidth = icon_.width_;
164     double textWidth = text_.width_;
165     if (isVertical_) {
166         // Shrink max width, then shrink another proportionally if vertical
167         if (GreatNotEqual(textWidth, iconWidth)) {
168             double textRemain = text_.ShrinkWidth(remain);
169             double iconRemain = (remain - textRemain) * iconWidth / textWidth;
170             icon_.ShrinkWidth(iconRemain);
171         } else {
172             double iconRemain = icon_.ShrinkWidth(remain);
173             double textRemain = (remain - iconRemain) * textWidth / iconWidth;
174             text_.ShrinkWidth(textRemain);
175         }
176     } else {
177         // Shrink proportional text and icon if horizontal
178         double iconRemain = iconWidth * remain / (iconWidth + textWidth);
179         double textRemain = textWidth * remain / (iconWidth + textWidth);
180         double resIcon = icon_.ShrinkWidth(iconRemain);
181         double resText = text_.ShrinkWidth(textRemain);
182         if (!NearEqual(resIcon, 0.0)) {
183             text_.ShrinkWidth(resIcon);
184         } else if (!NearEqual(resText, 0.0)) {
185             icon_.ShrinkWidth(resText);
186         }
187     }
188     UpdateTextSize();
189     MeasureIntegralSize();
190     return componentWidth_;
191 }
192 
EnlargeWidth(double diff)193 double SecurityComponentLayoutAlgorithm::EnlargeWidth(double diff)
194 {
195     double remain = left_.EnlargeWidth(diff / HALF);
196     remain = right_.EnlargeWidth(remain + (diff / HALF));
197     remain = left_.EnlargeWidth(remain);
198     if (GreatNotEqual(remain, 0.0) && !isVertical_) {
199         middle_.EnlargeWidth(remain);
200     }
201     MeasureIntegralSize();
202     return componentWidth_;
203 }
204 
ShrinkHeight(double diff)205 double SecurityComponentLayoutAlgorithm::ShrinkHeight(double diff)
206 {
207     // first shrink left and right padding
208     double remain = top_.ShrinkHeight(diff / HALF);
209     remain = bottom_.ShrinkHeight(remain + (diff / HALF));
210     remain = top_.ShrinkHeight(remain);
211     if (NearEqual(remain, 0.0)) {
212         MeasureIntegralSize();
213         return componentHeight_;
214     }
215 
216     // if vertical shrink IconTextSpace
217     remain = middle_.ShrinkHeight(remain);
218     if (NearEqual(remain, 0.0)) {
219         MeasureIntegralSize();
220         return componentHeight_;
221     }
222 
223     double iconHeight = icon_.height_;
224     double textHeight = text_.height_;
225     if (!isVertical_) {
226          // Shrink max width, then shrink another proportionally if horizontal
227         if (GreatNotEqual(textHeight, iconHeight)) {
228             double textRemain = text_.ShrinkHeight(remain);
229             double iconRemain = (remain - textRemain) * iconHeight / textHeight;
230             icon_.ShrinkHeight(iconRemain);
231         } else {
232             double iconRemain = icon_.ShrinkHeight(remain);
233             double textRemain = (remain - iconRemain) * textHeight / iconHeight;
234             text_.ShrinkHeight(textRemain);
235         }
236     } else {
237         double iconRemain = iconHeight * remain / (iconHeight + textHeight);
238         double textRemain = textHeight * remain / (iconHeight + textHeight);
239         double resIcon = icon_.ShrinkHeight(iconRemain);
240         double resText = text_.ShrinkHeight(textRemain);
241         if (!NearEqual(resIcon, 0.0)) {
242             text_.ShrinkHeight(resIcon);
243         } else if (!NearEqual(resText, 0.0)) {
244             icon_.ShrinkHeight(resText);
245         }
246     }
247     isNeedReadaptWidth_ = true;
248     MeasureIntegralSize();
249     return componentHeight_;
250 }
251 
EnlargeHeight(double diff)252 double SecurityComponentLayoutAlgorithm::EnlargeHeight(double diff)
253 {
254     double remain = top_.EnlargeHeight(diff / HALF);
255     remain = bottom_.EnlargeHeight(remain + (diff / HALF));
256     remain = top_.EnlargeHeight(remain);
257     if (GreatNotEqual(remain, 0.0) && isVertical_) {
258         middle_.EnlargeHeight(remain);
259     }
260     MeasureIntegralSize();
261     return componentHeight_;
262 }
263 
AdaptWidth()264 void SecurityComponentLayoutAlgorithm::AdaptWidth()
265 {
266     if (idealWidth_ != 0.0) {
267         if (componentWidth_ > idealWidth_) {
268             ShrinkWidth(componentWidth_ - idealWidth_);
269         } else if (componentWidth_ < idealWidth_) {
270             EnlargeWidth(idealWidth_ - componentWidth_);
271         }
272         return;
273     }
274 
275     if (componentWidth_ > maxWidth_) {
276         ShrinkWidth(componentWidth_ - maxWidth_);
277     } else if (componentWidth_ < minWidth_) {
278         EnlargeWidth(minWidth_ - componentWidth_);
279     }
280 }
281 
AdaptHeight()282 void SecurityComponentLayoutAlgorithm::AdaptHeight()
283 {
284     if (idealHeight_ != 0.0) {
285         if (componentHeight_ > idealHeight_) {
286             ShrinkHeight(componentHeight_ - idealHeight_);
287         } else if (componentHeight_ < idealHeight_) {
288             EnlargeHeight(idealHeight_ - componentHeight_);
289         }
290         return;
291     }
292     if (componentHeight_ > maxHeight_) {
293         ShrinkHeight(componentHeight_ - maxHeight_);
294     } else if (componentHeight_ < minHeight_) {
295         EnlargeHeight(minHeight_ - componentHeight_);
296     }
297 }
298 
MeasureIntegralSize()299 void SecurityComponentLayoutAlgorithm::MeasureIntegralSize()
300 {
301     if (isVertical_) {
302         double contextWidth = std::max(text_.width_, icon_.width_);
303         componentHeight_ = top_.height_ + text_.height_ +
304             middle_.height_ + icon_.height_ + bottom_.height_;
305         componentWidth_ = left_.width_ + contextWidth + right_.width_;
306     } else {
307         double contextHeight = std::max(text_.height_, icon_.height_);
308         componentHeight_ = top_.height_ + contextHeight + bottom_.height_;
309         componentWidth_ = left_.width_ + icon_.width_ +
310             middle_.width_ + text_.width_ + right_.width_;
311     }
312 }
313 
UpdateVerticalOffset(OffsetF & offsetIcon,OffsetF & offsetText,SizeF & childSize)314 void SecurityComponentLayoutAlgorithm::UpdateVerticalOffset(OffsetF& offsetIcon,
315     OffsetF& offsetText, SizeF& childSize)
316 {
317     offsetText = offsetIcon + OffsetF(0.0, icon_.height_ + middle_.height_);
318     if (icon_.width_ > text_.width_) {
319         offsetText += OffsetF((icon_.width_ - text_.width_) / HALF, 0.0);
320         childSize += SizeF(icon_.width_, 0.0);
321     } else {
322         offsetIcon += OffsetF((text_.width_ - icon_.width_) / HALF, 0.0);
323         childSize += SizeF(text_.width_, 0.0);
324     }
325     childSize += SizeF(0.0, icon_.height_ + middle_.height_ + text_.height_);
326 }
327 
UpdateHorizontalOffset(LayoutWrapper * layoutWrapper,OffsetF & offsetIcon,OffsetF & offsetText,SizeF & childSize)328 void SecurityComponentLayoutAlgorithm::UpdateHorizontalOffset(LayoutWrapper* layoutWrapper,
329     OffsetF& offsetIcon, OffsetF& offsetText, SizeF& childSize)
330 {
331     if (GetTextDirection(layoutWrapper) == TextDirection::RTL) {
332         offsetIcon = offsetText +
333             OffsetF(text_.width_ + middle_.width_, 0.0);
334     } else {
335         offsetText = offsetIcon +
336             OffsetF(icon_.width_ + middle_.width_, 0.0);
337     }
338     if (icon_.height_ > text_.height_) {
339         offsetText +=
340             OffsetF(0.0, (icon_.height_ - text_.height_) / HALF);
341         childSize += SizeF(0.0, icon_.height_);
342     } else {
343         offsetIcon +=
344             OffsetF(0.0, (text_.height_ - icon_.height_) / HALF);
345         childSize += SizeF(0.0, text_.height_);
346     }
347     childSize += SizeF(icon_.width_ + middle_.width_ + text_.width_, 0.0);
348 }
349 
ParseAlignmentRTL(LayoutWrapper * layoutWrapper,Alignment align)350 Alignment SecurityComponentLayoutAlgorithm::ParseAlignmentRTL(LayoutWrapper* layoutWrapper, Alignment align)
351 {
352     if (GetTextDirection(layoutWrapper) != TextDirection::RTL) {
353         return align;
354     }
355     if (align == Alignment::TOP_LEFT) {
356         return Alignment::TOP_RIGHT;
357     }
358     if (align == Alignment::CENTER_LEFT) {
359         return Alignment::CENTER_RIGHT;
360     }
361     if (align == Alignment::BOTTOM_LEFT) {
362         return Alignment::BOTTOM_RIGHT;
363     }
364     if (align == Alignment::TOP_RIGHT) {
365         return Alignment::TOP_LEFT;
366     }
367     if (align == Alignment::CENTER_RIGHT) {
368         return Alignment::CENTER_LEFT;
369     }
370     if (align == Alignment::BOTTOM_RIGHT) {
371         return Alignment::BOTTOM_LEFT;
372     }
373     return align;
374 }
375 
Layout(LayoutWrapper * layoutWrapper)376 void SecurityComponentLayoutAlgorithm::Layout(LayoutWrapper* layoutWrapper)
377 {
378     CHECK_NULL_VOID(layoutWrapper);
379     OffsetF offsetIcon = OffsetF(0.0, 0.0);
380     OffsetF offsetText = OffsetF(0.0, 0.0);
381     SizeF childSize = SizeF(0.0, 0.0);
382     if (isVertical_) {
383         UpdateVerticalOffset(offsetIcon, offsetText, childSize);
384     } else {
385         UpdateHorizontalOffset(layoutWrapper, offsetIcon, offsetText, childSize);
386     }
387     auto property = AceType::DynamicCast<SecurityComponentLayoutProperty>(layoutWrapper->GetLayoutProperty());
388     CHECK_NULL_VOID(property);
389     if (property->GetAlignment().has_value()) {
390         auto left = LessNotEqual(left_.width_, left_.defaultWidth_) ? left_.width_ : left_.defaultWidth_;
391         auto right = LessNotEqual(right_.width_, right_.defaultWidth_) ? right_.width_ : right_.defaultWidth_;
392         auto top = LessNotEqual(top_.height_, top_.defaultHeight_) ? top_.height_ : top_.defaultHeight_;
393         auto bottom = LessNotEqual(bottom_.height_, bottom_.defaultHeight_) ? bottom_.height_ : bottom_.defaultHeight_;
394         offsetIcon += OffsetF(left, top);
395         offsetText += OffsetF(left, top);
396         auto geometryNode = layoutWrapper->GetGeometryNode();
397         CHECK_NULL_VOID(geometryNode);
398         auto frameSize = geometryNode->GetFrameSize();
399         frameSize -= SizeF(left + right, top + bottom);
400         auto alignment = ParseAlignmentRTL(layoutWrapper, property->GetAlignment().value());
401         auto translate = Alignment::GetAlignPosition(frameSize, childSize, alignment);
402         offsetIcon += translate;
403         offsetText += translate;
404     } else {
405         offsetIcon += OffsetF(left_.width_, top_.height_);
406         offsetText += OffsetF(left_.width_, top_.height_);
407     }
408 
409     UpdateChildPosition(layoutWrapper, V2::IMAGE_ETS_TAG, offsetIcon);
410     UpdateChildPosition(layoutWrapper, V2::SYMBOL_ETS_TAG, offsetIcon);
411     UpdateChildPosition(layoutWrapper, V2::TEXT_ETS_TAG, offsetText);
412 
413     for (auto&& child : layoutWrapper->GetAllChildrenWithBuild()) {
414         child->Layout();
415     }
416 }
417 
UpdateCircleButtonConstraint()418 void SecurityComponentLayoutAlgorithm::UpdateCircleButtonConstraint()
419 {
420     double circleIdealSize = std::max(componentWidth_, componentHeight_);
421     if ((idealWidth_ != 0.0) && (idealHeight_ != 0.0)) {
422         circleIdealSize = std::min(idealWidth_, idealHeight_);
423     } else if (idealWidth_ != 0.0) {
424         circleIdealSize = idealWidth_;
425     } else if (idealHeight_ != 0.0) {
426         circleIdealSize = idealHeight_;
427     } else {
428         if ((componentWidth_ < minWidth_) || (componentHeight_ < minHeight_)) {
429             circleIdealSize = std::max(minWidth_, minHeight_);
430         } else if ((componentWidth_ > maxWidth_) || (componentHeight_ > maxHeight_)) {
431             circleIdealSize = std::min(maxWidth_, maxHeight_);
432         }
433     }
434     idealWidth_ = idealHeight_ = circleIdealSize;
435 }
436 
FillBlank()437 void SecurityComponentLayoutAlgorithm::FillBlank()
438 {
439     if (isNobg_) {
440         return;
441     }
442     if (GreatNotEqual(idealWidth_, componentWidth_)) {
443         left_.width_ += ((idealWidth_ - componentWidth_) / HALF);
444         right_.width_ += ((idealWidth_ - componentWidth_) / HALF);
445     } else if (GreatNotEqual(minWidth_, componentWidth_)) {
446         left_.width_ += ((minWidth_ - componentWidth_) / HALF);
447         right_.width_ += ((minWidth_ - componentWidth_) / HALF);
448     }
449     if (GreatNotEqual(idealHeight_, componentHeight_)) {
450         top_.height_ += ((idealHeight_ - componentHeight_) / HALF);
451         bottom_.height_ += ((idealHeight_ - componentHeight_) / HALF);
452     } else if (GreatNotEqual(minHeight_, componentHeight_)) {
453         top_.height_ += ((minHeight_ - componentHeight_) / HALF);
454         bottom_.height_ += ((minHeight_ - componentHeight_) / HALF);
455     }
456     MeasureIntegralSize();
457 }
458 
GetSecCompChildNode(RefPtr<FrameNode> & parent,const std::string & tag)459 RefPtr<FrameNode> SecurityComponentLayoutAlgorithm::GetSecCompChildNode(RefPtr<FrameNode>& parent,
460     const std::string& tag)
461 {
462     for (const auto& child : parent->GetChildren()) {
463         auto node = AceType::DynamicCast<FrameNode, UINode>(child);
464         CHECK_NULL_RETURN(node, nullptr);
465         if (node->GetTag() == tag) {
466             return node;
467         }
468     }
469     return nullptr;
470 }
471 
UpdateTextRectPoint()472 void SecurityComponentLayoutAlgorithm::UpdateTextRectPoint()
473 {
474     if (isVertical_) {
475         if (icon_.width_ > text_.width_) {
476             textLeftTopPoint_ = SizeF(left_.width_ + icon_.width_ / HALF - text_.width_ / HALF,
477                 top_.height_ + icon_.height_ + middle_.height_);
478             textRightTopPoint_ = SizeF(left_.width_ + icon_.width_ / HALF + text_.width_ / HALF,
479                 top_.height_ + icon_.height_ + middle_.height_);
480             textLeftBottomPoint_ = SizeF(left_.width_ + icon_.width_ / HALF - text_.width_ / HALF,
481                 top_.height_ + icon_.height_ + middle_.height_ + text_.height_);
482             textRightBottomPoint_ = SizeF(left_.width_ + icon_.width_ / HALF + text_.width_ / HALF,
483                 top_.height_ + icon_.height_ + middle_.height_ + text_.height_);
484         } else {
485             textLeftTopPoint_ = SizeF(left_.width_, top_.height_ + icon_.height_ + middle_.height_);
486             textRightTopPoint_ = SizeF(left_.width_ + text_.width_, top_.height_ + icon_.height_ + middle_.height_);
487             textLeftBottomPoint_ = SizeF(left_.width_, top_.height_ + icon_.height_ + middle_.height_ + text_.height_);
488             textRightBottomPoint_ = SizeF(left_.width_ + text_.width_,
489                 top_.height_ + icon_.height_ + middle_.height_ + text_.height_);
490         }
491     } else {
492         if (icon_.height_ > text_.height_) {
493             textLeftTopPoint_ = SizeF(left_.width_ + icon_.width_ + middle_.width_,
494                 top_.height_ + icon_.height_ / HALF - text_.height_ / HALF);
495             textRightTopPoint_ = SizeF(left_.width_ + icon_.width_ + middle_.width_ + text_.width_,
496                 top_.height_ + icon_.height_ / HALF - text_.height_ / HALF);
497             textLeftBottomPoint_ = SizeF(left_.width_ + icon_.width_ + middle_.width_,
498                 top_.height_ + icon_.height_ / HALF + text_.height_ / HALF);
499             textRightBottomPoint_ = SizeF(left_.width_ + icon_.width_ + middle_.width_ + text_.width_,
500                 top_.height_ + icon_.height_ / HALF + text_.height_ / HALF);
501         } else {
502             textLeftTopPoint_ = SizeF(left_.width_ + icon_.width_ + middle_.width_, top_.height_);
503             textRightTopPoint_ = SizeF(left_.width_ + icon_.width_ + middle_.width_ + text_.width_, top_.height_);
504             textLeftBottomPoint_ = SizeF(left_.width_ + icon_.width_ + middle_.width_, top_.height_ + text_.height_);
505             textRightBottomPoint_ = SizeF(left_.width_ + icon_.width_ + middle_.width_ + text_.width_,
506                 top_.height_ + text_.height_);
507         }
508     }
509 }
510 
IsTextAdaptOutOfRange(SizeF & leftPoint,SizeF & rightPoint,SizeF & circlePoint,float maxDistance)511 bool SecurityComponentLayoutAlgorithm::IsTextAdaptOutOfRange(SizeF& leftPoint, SizeF& rightPoint, SizeF& circlePoint,
512     float maxDistance)
513 {
514     if (LessOrEqual(rightPoint.Width(), circlePoint.Width())) {
515         return true;
516     }
517 
518     auto pointDistance = rightPoint.Width() - circlePoint.Width();
519     auto maxSpaceToShrink = rightPoint.Width() - leftPoint.Width();
520     maxSpaceToShrink = GreatNotEqual(maxSpaceToShrink, pointDistance) ? pointDistance : maxSpaceToShrink;
521     auto threshold = currentFontSize_.ConvertToPx() * (1.0 - TEXT_OUT_OF_WIDTH_PERCENT);
522     auto res = text_.TryShrinkTextWidth(rightPoint, circlePoint, maxSpaceToShrink, maxDistance, threshold);
523     if (res) {
524         UpdateTextRectPoint();
525         return false;
526     }
527     return true;
528 }
529 
IsTextOutOfRangeInCircle()530 bool SecurityComponentLayoutAlgorithm::IsTextOutOfRangeInCircle()
531 {
532     auto circlePoint = SizeF(componentWidth_ / HALF, componentHeight_ / HALF);
533     auto threshold = TEXT_OUT_OF_RANGE_PERCENT * RANGE_RATIO * currentFontSize_.ConvertToPx();
534     auto maxDistance = pow(circlePoint.Width() + threshold);
535     auto leftTopDistance = pow(textLeftTopPoint_.Width() - circlePoint.Width()) +
536         pow(textLeftTopPoint_.Height() - circlePoint.Height());
537     if (GreatNotEqual(leftTopDistance, maxDistance)) {
538         return true;
539     }
540     auto leftBottomDistance = pow(textLeftBottomPoint_.Width() - circlePoint.Width()) +
541         pow(textLeftBottomPoint_.Height() - circlePoint.Height());
542     if (GreatNotEqual(leftBottomDistance, maxDistance)) {
543         return true;
544     }
545     auto rightTopDistance = pow(textRightTopPoint_.Width() - circlePoint.Width()) +
546         pow(textRightTopPoint_.Height() - circlePoint.Height());
547     if (GreatNotEqual(rightTopDistance, maxDistance) && IsTextAdaptOutOfRange(textLeftTopPoint_,
548         textRightTopPoint_, circlePoint, maxDistance)) {
549         return true;
550     }
551     auto rightBottomDistance = pow(textRightBottomPoint_.Width() - circlePoint.Width()) +
552         pow(textRightBottomPoint_.Height() - circlePoint.Height());
553     if (GreatNotEqual(rightBottomDistance, maxDistance) && IsTextAdaptOutOfRange(textLeftBottomPoint_,
554         textRightBottomPoint_, circlePoint, maxDistance)) {
555         return true;
556     }
557     return false;
558 }
559 
CompareDistance(SizeF & point,SizeF & circlePoint,float maxDistance)560 bool SecurityComponentLayoutAlgorithm::CompareDistance(SizeF& point, SizeF& circlePoint, float maxDistance)
561 {
562     auto distance = pow(point.Width() - circlePoint.Width()) + pow(point.Height() - circlePoint.Height());
563     if (GreatNotEqual(distance, maxDistance)) {
564         return true;
565     }
566     return false;
567 }
568 
IsOutOfRangeInHoriCapsule(SizeF & leftCirclePoint,SizeF & rightCirclePoint,float maxDistance)569 bool SecurityComponentLayoutAlgorithm::IsOutOfRangeInHoriCapsule(SizeF& leftCirclePoint, SizeF& rightCirclePoint,
570     float maxDistance)
571 {
572     if (GreatNotEqual(textRightTopPoint_.Width(), rightCirclePoint.Width()) &&
573         LessNotEqual(textRightTopPoint_.Height(), rightCirclePoint.Height())) {
574         if (CompareDistance(textRightTopPoint_, rightCirclePoint, maxDistance) &&
575             IsTextAdaptOutOfRange(textLeftTopPoint_, textRightTopPoint_, rightCirclePoint, maxDistance)) {
576             return true;
577         }
578     }
579     if (LessNotEqual(textLeftBottomPoint_.Width(), leftCirclePoint.Width()) &&
580         GreatNotEqual(textLeftBottomPoint_.Height(), leftCirclePoint.Height())) {
581         if (CompareDistance(textLeftBottomPoint_, leftCirclePoint, maxDistance)) {
582             return true;
583         }
584     }
585     return false;
586 }
587 
IsOutOfRangeInVertiCapsule(SizeF & topCirclePoint,SizeF & bottomCirclePoint,float maxDistance)588 bool SecurityComponentLayoutAlgorithm::IsOutOfRangeInVertiCapsule(SizeF& topCirclePoint, SizeF& bottomCirclePoint,
589     float maxDistance)
590 {
591     if (GreatNotEqual(textRightTopPoint_.Width(), topCirclePoint.Width()) &&
592         LessNotEqual(textRightTopPoint_.Height(), topCirclePoint.Height())) {
593         if (CompareDistance(textRightTopPoint_, topCirclePoint, maxDistance) &&
594             IsTextAdaptOutOfRange(textLeftTopPoint_, textRightTopPoint_, topCirclePoint, maxDistance)) {
595             return true;
596         }
597     }
598     if (LessNotEqual(textLeftBottomPoint_.Width(), bottomCirclePoint.Width()) &&
599         GreatNotEqual(textLeftBottomPoint_.Height(), bottomCirclePoint.Height())) {
600         if (CompareDistance(textLeftBottomPoint_, bottomCirclePoint, maxDistance)) {
601             return true;
602         }
603     }
604     return false;
605 }
606 
IsTextOutOfRangeInCapsule()607 bool SecurityComponentLayoutAlgorithm::IsTextOutOfRangeInCapsule()
608 {
609     SizeF rightBottomCirclePoint;
610     auto capsuleRadius = std::min(componentWidth_, componentHeight_) / HALF;
611     auto maxDistance = pow(capsuleRadius + TEXT_OUT_OF_RANGE_PERCENT * RANGE_RATIO * currentFontSize_.ConvertToPx());
612     auto leftTopCirclePoint = SizeF(capsuleRadius, capsuleRadius);
613     if (LessNotEqual(textLeftTopPoint_.Width(), leftTopCirclePoint.Width()) &&
614         LessNotEqual(textLeftTopPoint_.Height(), leftTopCirclePoint.Height())) {
615         if (CompareDistance(textLeftTopPoint_, leftTopCirclePoint, maxDistance)) {
616             return true;
617         }
618     }
619     if (GreatOrEqual(componentWidth_, componentHeight_)) {
620         rightBottomCirclePoint = SizeF(componentWidth_ - capsuleRadius, capsuleRadius);
621         auto res = IsOutOfRangeInHoriCapsule(leftTopCirclePoint, rightBottomCirclePoint, maxDistance);
622         if (res) {
623             return res;
624         }
625     } else {
626         rightBottomCirclePoint = SizeF(capsuleRadius, componentHeight_ - capsuleRadius);
627         auto res = IsOutOfRangeInVertiCapsule(leftTopCirclePoint, rightBottomCirclePoint, maxDistance);
628         if (res) {
629             return res;
630         }
631     }
632     if (GreatNotEqual(textRightBottomPoint_.Width(), rightBottomCirclePoint.Width()) &&
633         GreatNotEqual(textRightBottomPoint_.Height(), rightBottomCirclePoint.Height())) {
634         if (CompareDistance(textRightBottomPoint_, rightBottomCirclePoint, maxDistance) &&
635             IsTextAdaptOutOfRange(textLeftBottomPoint_, textRightBottomPoint_, rightBottomCirclePoint, maxDistance)) {
636             return true;
637         }
638     }
639     return false;
640 }
641 
TopLeftCompDistance(float obtainedRadius,float maxRadius,float threshold)642 bool SecurityComponentLayoutAlgorithm::TopLeftCompDistance(float obtainedRadius, float maxRadius, float threshold)
643 {
644     auto radius = GreatNotEqual(obtainedRadius, maxRadius) ? maxRadius : obtainedRadius;
645     auto circlePoint = SizeF(radius, radius);
646     if (LessNotEqual(textLeftTopPoint_.Width(), circlePoint.Width()) &&
647         LessNotEqual(textLeftTopPoint_.Height(), circlePoint.Height())) {
648         auto distance = pow(textLeftTopPoint_.Width() - circlePoint.Width()) +
649             pow(textLeftTopPoint_.Height() - circlePoint.Height());
650         auto maxDistance = pow(radius + threshold);
651         if (GreatNotEqual(distance, maxDistance)) {
652             return true;
653         }
654     }
655     return false;
656 }
657 
BottomLeftCompDistance(float obtainedRadius,float maxRadius,float threshold)658 bool SecurityComponentLayoutAlgorithm::BottomLeftCompDistance(float obtainedRadius, float maxRadius, float threshold)
659 {
660     auto radius = GreatNotEqual(obtainedRadius, maxRadius) ? maxRadius : obtainedRadius;
661     auto circlePoint = SizeF(radius, componentHeight_ - radius);
662     if (LessNotEqual(textLeftBottomPoint_.Width(), circlePoint.Width()) &&
663         GreatNotEqual(textLeftBottomPoint_.Height(), circlePoint.Height())) {
664         auto distance = pow(textLeftBottomPoint_.Width() - circlePoint.Width()) +
665             pow(textLeftBottomPoint_.Height() - circlePoint.Height());
666         auto maxDistance = pow(radius + threshold);
667         if (GreatNotEqual(distance, maxDistance)) {
668             return true;
669         }
670     }
671     return false;
672 }
673 
TopRightCompDistance(float obtainedRadius,float maxRadius,float threshold)674 bool SecurityComponentLayoutAlgorithm::TopRightCompDistance(float obtainedRadius, float maxRadius, float threshold)
675 {
676     auto radius = GreatNotEqual(obtainedRadius, maxRadius) ? maxRadius : obtainedRadius;
677     auto circlePoint = SizeF(componentWidth_ - radius, radius);
678     if (GreatNotEqual(textRightTopPoint_.Width(), circlePoint.Width()) &&
679         LessNotEqual(textRightTopPoint_.Height(), circlePoint.Height())) {
680         auto distance = pow(textRightTopPoint_.Width() - circlePoint.Width()) +
681             pow(textRightTopPoint_.Height() - circlePoint.Height());
682         auto maxDistance = pow(radius + threshold);
683         if (GreatNotEqual(distance, maxDistance) && IsTextAdaptOutOfRange(textLeftTopPoint_,
684             textRightTopPoint_, circlePoint, maxDistance)) {
685             return true;
686         }
687     }
688     return false;
689 }
690 
BottomRightCompDistance(float obtainedRadius,float maxRadius,float threshold)691 bool SecurityComponentLayoutAlgorithm::BottomRightCompDistance(float obtainedRadius, float maxRadius, float threshold)
692 {
693     auto radius = GreatNotEqual(obtainedRadius, maxRadius) ? maxRadius : obtainedRadius;
694     auto circlePoint = SizeF(componentWidth_ - radius, componentHeight_ - radius);
695     if (GreatNotEqual(textRightBottomPoint_.Width(), circlePoint.Width()) &&
696         GreatNotEqual(textRightBottomPoint_.Height(), circlePoint.Height())) {
697         auto distance = pow(textRightBottomPoint_.Width() - circlePoint.Width()) +
698             pow(textRightBottomPoint_.Height() - circlePoint.Height());
699         auto maxDistance = pow(radius + threshold);
700         if (GreatNotEqual(distance, maxDistance) && IsTextAdaptOutOfRange(textLeftBottomPoint_,
701             textRightBottomPoint_, circlePoint, maxDistance)) {
702             return true;
703         }
704     }
705     return false;
706 }
707 
IsTextOutOfRangeInNormal()708 bool SecurityComponentLayoutAlgorithm::IsTextOutOfRangeInNormal()
709 {
710     auto borderRadius = buttonLayoutProperty_->GetBorderRadius();
711     if (!borderRadius.has_value()) {
712         return false;
713     }
714     auto maxRadius = std::min(componentWidth_, componentHeight_) / HALF;
715     auto threshold = TEXT_OUT_OF_RANGE_PERCENT * RANGE_RATIO * currentFontSize_.ConvertToPx();
716     if (borderRadius->radiusTopLeft.has_value() &&
717         GreatNotEqual(borderRadius->radiusTopLeft.value().ConvertToPx(), currentFontSize_.ConvertToPx())) {
718         if (TopLeftCompDistance(borderRadius->radiusTopLeft.value().ConvertToPx(), maxRadius, threshold)) {
719             return true;
720         }
721     }
722     if (borderRadius->radiusBottomLeft.has_value() &&
723         GreatNotEqual(borderRadius->radiusBottomLeft.value().ConvertToPx(), currentFontSize_.ConvertToPx())) {
724         if (BottomLeftCompDistance(borderRadius->radiusBottomLeft.value().ConvertToPx(), maxRadius, threshold)) {
725             return true;
726         }
727     }
728     if (borderRadius->radiusTopRight.has_value() &&
729         GreatNotEqual(borderRadius->radiusTopRight.value().ConvertToPx(), currentFontSize_.ConvertToPx())) {
730         if (TopRightCompDistance(borderRadius->radiusTopRight.value().ConvertToPx(), maxRadius, threshold)) {
731             return true;
732         }
733     }
734     if (borderRadius->radiusBottomRight.has_value() &&
735         GreatNotEqual(borderRadius->radiusBottomRight.value().ConvertToPx(), currentFontSize_.ConvertToPx())) {
736         if (BottomRightCompDistance(borderRadius->radiusBottomRight.value().ConvertToPx(), maxRadius, threshold)) {
737             return true;
738         }
739     }
740     return false;
741 }
742 
IsTextOutOfOneColumn(RefPtr<FrameNode> & frameNode,float threshold)743 bool SecurityComponentLayoutAlgorithm::IsTextOutOfOneColumn(RefPtr<FrameNode>& frameNode, float threshold)
744 {
745     auto textNode = GetSecCompChildNode(frameNode, V2::TEXT_ETS_TAG);
746     CHECK_NULL_RETURN(textNode, false);
747     auto textPattern = textNode->GetPattern<TextPattern>();
748     CHECK_NULL_RETURN(textPattern, false);
749     auto realWidth = textPattern->GetLineMetrics(0).width;
750     auto allowWidth = text_.width_ + threshold;
751     if (LessNotEqual(allowWidth, realWidth)) {
752         return true;
753     }
754 
755     return false;
756 }
757 
GetMaxLineLimitExceededFlag(std::optional<SizeF> & currentTextSize)758 bool SecurityComponentLayoutAlgorithm::GetMaxLineLimitExceededFlag(std::optional<SizeF>& currentTextSize)
759 {
760     auto res = text_.DidExceedMaxLines(currentTextSize);
761     if (res) {
762         SC_LOG_INFO("MaxLine limit exceeded.");
763         return true;
764     }
765     return false;
766 }
767 
GetTextLimitExceededFlag(RefPtr<SecurityComponentLayoutProperty> & property,RefPtr<FrameNode> & frameNode,std::optional<SizeF> & currentTextSize)768 bool SecurityComponentLayoutAlgorithm::GetTextLimitExceededFlag(RefPtr<SecurityComponentLayoutProperty>& property,
769     RefPtr<FrameNode>& frameNode, std::optional<SizeF>& currentTextSize)
770 {
771     CHECK_NULL_RETURN(frameNode, false);
772     auto buttonNode = GetSecCompChildNode(frameNode, V2::BUTTON_ETS_TAG);
773     CHECK_NULL_RETURN(buttonNode, false);
774     buttonLayoutProperty_ = buttonNode->GetLayoutProperty<ButtonLayoutProperty>();
775     CHECK_NULL_RETURN(buttonLayoutProperty_, false);
776 
777     auto res = text_.GetCurrentTextSize(currentTextSize, currentFontSize_);
778     if (!res) {
779         return false;
780     }
781 
782     UpdateTextRectPoint();
783 
784     auto isCircle = (property->GetBackgroundType() == static_cast<int32_t>(ButtonType::CIRCLE));
785     auto isCapsule = (property->GetBackgroundType() == static_cast<int32_t>(ButtonType::CAPSULE));
786     if (isCircle) {
787         res = IsTextOutOfRangeInCircle();
788     } else if (isCapsule) {
789         res = IsTextOutOfRangeInCapsule();
790     } else {
791         res = IsTextOutOfRangeInNormal();
792     }
793 
794     if (!res) {
795         auto threshold = currentFontSize_.ConvertToPx() * TEXT_OUT_OF_WIDTH_PERCENT;
796         res = IsTextOutOfOneColumn(frameNode, threshold);
797     }
798 
799     return res;
800 }
801 
IsIconOutOfRange(SizeF & iconPoint,SizeF & point,double maxDistance)802 bool SecurityComponentLayoutAlgorithm::IsIconOutOfRange(SizeF& iconPoint, SizeF& point, double maxDistance)
803 {
804     auto iconRadius = icon_.width_ * ICON_RANGE_RATIO / HALF;
805     auto distance = sqrt(pow(iconPoint.Width() - point.Width()) + pow(iconPoint.Height() - point.Height())) +
806         iconRadius;
807     if (GreatNotEqual(distance, maxDistance + 1.0)) {
808         return true;
809     }
810     return false;
811 }
812 
IsIconOutOfBackground(const NG::BorderRadiusProperty & radius)813 bool SecurityComponentLayoutAlgorithm::IsIconOutOfBackground(const NG::BorderRadiusProperty& radius)
814 {
815     auto iconPoint = SizeF(left_.width_ + icon_.width_ / HALF, top_.height_ + icon_.height_ / HALF);
816     auto iconRadius = icon_.width_ * ICON_RANGE_RATIO / HALF;
817     if (GreatNotEqual(iconPoint.Width() + iconRadius, componentWidth_) ||
818         GreatNotEqual(iconPoint.Height() + iconRadius, componentHeight_)) {
819         return true;
820     }
821     if (radius.radiusTopLeft.has_value() &&
822         LessNotEqual(iconPoint.Width(), radius.radiusTopLeft.value().ConvertToPx()) &&
823         LessNotEqual(iconPoint.Height(), radius.radiusTopLeft.value().ConvertToPx())) {
824         auto topLeft = SizeF(radius.radiusTopLeft.value().ConvertToPx(), radius.radiusTopLeft.value().ConvertToPx());
825         return IsIconOutOfRange(iconPoint, topLeft, radius.radiusTopLeft.value().ConvertToPx());
826     }
827     if (radius.radiusTopRight.has_value() &&
828         GreatNotEqual(iconPoint.Width(), componentWidth_ - radius.radiusTopRight.value().ConvertToPx()) &&
829         LessNotEqual(iconPoint.Height(), radius.radiusTopRight.value().ConvertToPx())) {
830         auto topRight = SizeF(componentWidth_ - radius.radiusTopRight.value().ConvertToPx(),
831             radius.radiusTopRight.value().ConvertToPx());
832         return IsIconOutOfRange(iconPoint, topRight, radius.radiusTopRight.value().ConvertToPx());
833     }
834     if (radius.radiusBottomLeft.has_value() &&
835         LessNotEqual(iconPoint.Width(), radius.radiusBottomLeft.value().ConvertToPx()) &&
836         GreatNotEqual(iconPoint.Height(), componentHeight_ - radius.radiusBottomLeft.value().ConvertToPx())) {
837         auto bottomLeft = SizeF(radius.radiusBottomLeft.value().ConvertToPx(),
838             componentHeight_ - radius.radiusBottomLeft.value().ConvertToPx());
839         return IsIconOutOfRange(iconPoint, bottomLeft, radius.radiusBottomLeft.value().ConvertToPx());
840     }
841     if (radius.radiusBottomRight.has_value() &&
842         GreatNotEqual(iconPoint.Width(), componentWidth_ - radius.radiusBottomRight.value().ConvertToPx()) &&
843         GreatNotEqual(iconPoint.Height(), componentHeight_ - radius.radiusBottomRight.value().ConvertToPx())) {
844         auto bottomRight = SizeF(componentWidth_ - radius.radiusBottomRight.value().ConvertToPx(),
845             componentHeight_ - radius.radiusBottomRight.value().ConvertToPx());
846         return IsIconOutOfRange(iconPoint, bottomRight, radius.radiusBottomRight.value().ConvertToPx());
847     }
848 
849     return false;
850 }
851 
GetIconExceededFlag(RefPtr<SecurityComponentLayoutProperty> & property,RefPtr<FrameNode> & frameNode)852 bool SecurityComponentLayoutAlgorithm::GetIconExceededFlag(RefPtr<SecurityComponentLayoutProperty>& property,
853     RefPtr<FrameNode>& frameNode)
854 {
855     if (LessOrEqual(icon_.width_, 0.0) || LessOrEqual(icon_.height_, 0.0)) {
856         return false;
857     }
858 
859     NG::BorderRadiusProperty radius = BorderRadiusProperty(Dimension(0.0));
860     if (property->GetBackgroundType() == static_cast<int32_t>(ButtonType::CIRCLE) ||
861         property->GetBackgroundType() == static_cast<int32_t>(ButtonType::CAPSULE)) {
862         radius = BorderRadiusProperty(Dimension(std::min(componentWidth_, componentHeight_) / HALF));
863     } else if (property->GetBackgroundType() == static_cast<int32_t>(ButtonType::NORMAL) ||
864         property->GetBackgroundType() == static_cast<int32_t>(ButtonType::ROUNDED_RECTANGLE)) {
865         auto buttonNode = GetSecCompChildNode(frameNode, V2::BUTTON_ETS_TAG);
866         CHECK_NULL_RETURN(buttonNode, false);
867         auto bgProp = buttonNode->GetLayoutProperty<ButtonLayoutProperty>();
868         CHECK_NULL_RETURN(bgProp, false);
869         const auto& borderRadius = bgProp->GetBorderRadius();
870         if (borderRadius.has_value()) {
871             radius = borderRadius.value();
872         }
873     } else {
874         return true;
875     }
876     return IsIconOutOfBackground(radius);
877 }
878 
UpdateTextFlags(LayoutWrapper * layoutWrapper)879 void SecurityComponentLayoutAlgorithm::UpdateTextFlags(LayoutWrapper* layoutWrapper)
880 {
881     CHECK_NULL_VOID(layoutWrapper);
882     auto frameNode = layoutWrapper->GetHostNode();
883     CHECK_NULL_VOID(frameNode);
884     auto securityComponentLayoutProperty =
885         AceType::DynamicCast<SecurityComponentLayoutProperty>(layoutWrapper->GetLayoutProperty());
886     CHECK_NULL_VOID(securityComponentLayoutProperty);
887     std::optional<SizeF> currentTextSize;
888     if (frameNode->GetTag() != V2::SAVE_BUTTON_ETS_TAG) {
889         securityComponentLayoutProperty->UpdateIsTextLimitExceeded(GetTextLimitExceededFlag(
890             securityComponentLayoutProperty, frameNode, currentTextSize));
891     }
892     securityComponentLayoutProperty->UpdateIsMaxLineLimitExceeded(GetMaxLineLimitExceededFlag(currentTextSize));
893     securityComponentLayoutProperty->UpdateIsIconExceeded(GetIconExceededFlag(securityComponentLayoutProperty,
894         frameNode));
895 }
896 
InitLayoutWrapper(LayoutWrapper * layoutWrapper,const RefPtr<SecurityComponentLayoutProperty> & securityComponentLayoutProperty)897 void SecurityComponentLayoutAlgorithm::InitLayoutWrapper(LayoutWrapper* layoutWrapper,
898     const RefPtr<SecurityComponentLayoutProperty>& securityComponentLayoutProperty)
899 {
900     CHECK_NULL_VOID(layoutWrapper);
901     auto iconWrapper = GetChildWrapper(layoutWrapper, V2::IMAGE_ETS_TAG);
902     iconWrapper = iconWrapper ? iconWrapper : GetChildWrapper(layoutWrapper, V2::SYMBOL_ETS_TAG);
903     icon_.Init(securityComponentLayoutProperty, iconWrapper);
904 
905     auto textWrapper = GetChildWrapper(layoutWrapper, V2::TEXT_ETS_TAG);
906     text_.Init(securityComponentLayoutProperty, textWrapper);
907 }
908 
Measure(LayoutWrapper * layoutWrapper)909 void SecurityComponentLayoutAlgorithm::Measure(LayoutWrapper* layoutWrapper)
910 {
911     CHECK_NULL_VOID(layoutWrapper);
912     auto securityComponentLayoutProperty =
913         AceType::DynamicCast<SecurityComponentLayoutProperty>(layoutWrapper->GetLayoutProperty());
914     CHECK_NULL_VOID(securityComponentLayoutProperty);
915     InitLayoutWrapper(layoutWrapper, securityComponentLayoutProperty);
916 
917     constraint_ = securityComponentLayoutProperty->GetContentLayoutConstraint();
918     CHECK_NULL_VOID(constraint_);
919 
920     // has value and less equal 0.0
921     if (LessOrEqual(constraint_->selfIdealSize.Width().value_or(1.0), 0.0) &&
922         LessOrEqual(constraint_->selfIdealSize.Height().value_or(1.0), 0.0)) {
923         return;
924     }
925 
926     isVertical_ = (securityComponentLayoutProperty->GetTextIconLayoutDirection().value_or(
927         SecurityComponentLayoutDirection::HORIZONTAL) == SecurityComponentLayoutDirection::VERTICAL);
928     isNobg_ = (securityComponentLayoutProperty->GetBackgroundType().value_or(
929         static_cast<int32_t>(ButtonType::CAPSULE)) == BUTTON_TYPE_NULL);
930     idealWidth_ = constraint_->selfIdealSize.Width().value_or(0.0);
931     idealHeight_ = constraint_->selfIdealSize.Height().value_or(0.0);
932     minWidth_ = constraint_->minSize.Width();
933     minHeight_ = constraint_->minSize.Height();
934     maxWidth_ = constraint_->maxSize.Width();
935     maxHeight_ = constraint_->maxSize.Height();
936     InitPadding(securityComponentLayoutProperty);
937     if (GetTextDirection(layoutWrapper) == TextDirection::RTL) {
938         PaddingLayoutElement temp = left_;
939         left_ = right_;
940         right_ = temp;
941     }
942 
943     MeasureIntegralSize();
944 
945     if (securityComponentLayoutProperty->GetBackgroundType() == static_cast<int32_t>(ButtonType::CIRCLE)) {
946         UpdateCircleButtonConstraint();
947     }
948     AdaptWidth();
949     AdaptHeight();
950     if (isNeedReadaptWidth_) {
951         AdaptWidth();
952     }
953     // fill blank when all paddings can not be enlarged because it has been set
954     FillBlank();
955     icon_.DoMeasure();
956     MeasureButton(layoutWrapper, securityComponentLayoutProperty);
957     auto geometryNode = layoutWrapper->GetGeometryNode();
958     CHECK_NULL_VOID(geometryNode);
959     geometryNode->SetFrameSize(SizeF(componentWidth_, componentHeight_));
960     UpdateTextFlags(layoutWrapper);
961 }
962 
GetTextDirection(LayoutWrapper * layoutWrapper)963 TextDirection SecurityComponentLayoutAlgorithm::GetTextDirection(LayoutWrapper* layoutWrapper)
964 {
965     auto frameNode = layoutWrapper->GetHostNode();
966     // default return LTR
967     CHECK_NULL_RETURN(frameNode, TextDirection::LTR);
968     std::u16string text = u"";
969     // get button string
970     for (const auto& child : frameNode->GetChildren()) {
971         auto node = AceType::DynamicCast<FrameNode, UINode>(child);
972         if (node == nullptr) {
973             continue;
974         }
975         if (node->GetTag() == V2::TEXT_ETS_TAG) {
976             auto textLayoutProperty = node->GetLayoutProperty<TextLayoutProperty>();
977             if (textLayoutProperty == nullptr) {
978                 continue;
979             }
980             text = textLayoutProperty->GetContentValue(text);
981             break;
982         }
983     }
984     if (text.empty()) {
985         return TextDirection::LTR;
986     }
987     for (const auto& charInStr : text) {
988         auto direction = u_charDirection(charInStr);
989         if (direction == UCharDirection::U_LEFT_TO_RIGHT) {
990             return TextDirection::LTR;
991         }
992         if (direction == UCharDirection::U_RIGHT_TO_LEFT || direction == UCharDirection::U_RIGHT_TO_LEFT_ARABIC) {
993             return TextDirection::RTL;
994         }
995     }
996     return TextDirection::LTR;
997 }
998 } // namespace OHOS::Ace::NG
999