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