• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022 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/button/button_layout_algorithm.h"
17 
18 #include "base/utils/utils.h"
19 #include "core/components/button/button_theme.h"
20 #include "core/components/toggle/toggle_theme.h"
21 #include "core/components_ng/base/frame_node.h"
22 #include "core/components_ng/layout/layout_wrapper.h"
23 #include "core/components_ng/pattern/button/button_layout_property.h"
24 #include "core/components_ng/pattern/text/text_layout_property.h"
25 #include "core/components_ng/property/measure_utils.h"
26 #include "core/pipeline_ng/pipeline_context.h"
27 #include "core/components_ng/pattern/button/button_pattern.h"
28 
29 namespace OHOS::Ace::NG {
30 namespace {
checkNegativeBorderRadius(std::optional<Dimension> & radius,const float defaultBorderRadius)31 void checkNegativeBorderRadius(std::optional<Dimension>& radius, const float defaultBorderRadius)
32 {
33     // Change the borderRadius size of a negative number to the default.
34     if (!radius.has_value() || LessNotEqual(radius.value().ConvertToPx(), 0.0)) {
35         radius = Dimension(defaultBorderRadius);
36     }
37 }
38 }
Measure(LayoutWrapper * layoutWrapper)39 void ButtonLayoutAlgorithm::Measure(LayoutWrapper* layoutWrapper)
40 {
41     auto host = layoutWrapper->GetHostNode();
42     CHECK_NULL_VOID(host);
43     auto pattern = host->GetPattern<ButtonPattern>();
44     CHECK_NULL_VOID(pattern);
45     if (pattern->UseContentModifier()) {
46         const auto& childList = layoutWrapper->GetAllChildrenWithBuild();
47         std::list<RefPtr<LayoutWrapper>> builderChildList;
48         for (const auto& child : childList) {
49             if (child->GetHostNode()->GetId() != pattern->GetBuilderId()) {
50                 child->GetGeometryNode()->Reset();
51                 child->GetGeometryNode()->SetContentSize(SizeF());
52             } else {
53                 auto layoutConstraint = layoutWrapper->GetLayoutProperty()->CreateChildConstraint();
54                 child->Measure(layoutConstraint);
55                 builderChildList.push_back(child);
56             }
57         }
58         BoxLayoutAlgorithm::PerformMeasureSelfWithChildList(layoutWrapper, builderChildList);
59         return;
60     }
61     auto layoutConstraint = layoutWrapper->GetLayoutProperty()->CreateChildConstraint();
62     HandleChildLayoutConstraint(layoutWrapper, layoutConstraint);
63     auto buttonLayoutProperty = DynamicCast<ButtonLayoutProperty>(layoutWrapper->GetLayoutProperty());
64     CHECK_NULL_VOID(buttonLayoutProperty);
65     if (buttonLayoutProperty->HasLabel()) {
66         // If the button has label, according to whether the font size is set to do the corresponding expansion button,
67         // font reduction, truncation and other operations.
68         HandleAdaptiveText(layoutWrapper, layoutConstraint);
69     } else {
70         // If the button has not label, measure the child directly.
71         for (auto&& child : layoutWrapper->GetAllChildrenWithBuild()) {
72             child->Measure(layoutConstraint);
73         }
74     }
75     PerformMeasureSelf(layoutWrapper);
76     MarkNeedFlushMouseEvent(layoutWrapper);
77 }
78 
HandleChildLayoutConstraint(LayoutWrapper * layoutWrapper,LayoutConstraintF & layoutConstraint)79 void ButtonLayoutAlgorithm::HandleChildLayoutConstraint(
80     LayoutWrapper* layoutWrapper, LayoutConstraintF& layoutConstraint)
81 {
82     auto buttonLayoutProperty = DynamicCast<ButtonLayoutProperty>(layoutWrapper->GetLayoutProperty());
83     CHECK_NULL_VOID(buttonLayoutProperty);
84     if (!buttonLayoutProperty->HasLabel()) {
85         return;
86     }
87     auto buttonType = buttonLayoutProperty->GetType().value_or(ButtonType::CAPSULE);
88     if (buttonType == ButtonType::CIRCLE) {
89         layoutConstraint.maxSize = HandleLabelCircleButtonConstraint(layoutWrapper).value_or(SizeF());
90         return;
91     }
92     const auto& selfLayoutConstraint = layoutWrapper->GetLayoutProperty()->GetLayoutConstraint();
93     // If height is not set, apply the default height.
94     if (selfLayoutConstraint && !selfLayoutConstraint->selfIdealSize.Height().has_value()) {
95         auto maxHeight = selfLayoutConstraint->maxSize.Height();
96         if (IsAging(layoutWrapper)) {
97             layoutConstraint.maxSize.SetHeight(maxHeight);
98             return;
99         }
100         auto defaultHeight = GetDefaultHeight(layoutWrapper);
101         layoutConstraint.maxSize.SetHeight(maxHeight > defaultHeight ? defaultHeight : maxHeight);
102     }
103 }
104 
105 // If the ButtonType is CIRCLE, then omit text by the smaller edge.
HandleLabelCircleButtonConstraint(LayoutWrapper * layoutWrapper)106 std::optional<SizeF> ButtonLayoutAlgorithm::HandleLabelCircleButtonConstraint(LayoutWrapper* layoutWrapper)
107 {
108     SizeF constraintSize;
109     auto buttonLayoutProperty = DynamicCast<ButtonLayoutProperty>(layoutWrapper->GetLayoutProperty());
110     CHECK_NULL_RETURN(buttonLayoutProperty, constraintSize);
111     const auto& selfLayoutConstraint = layoutWrapper->GetLayoutProperty()->GetLayoutConstraint();
112     CHECK_NULL_RETURN(selfLayoutConstraint, constraintSize);
113     auto host = layoutWrapper->GetHostNode();
114     CHECK_NULL_RETURN(host, constraintSize);
115     auto* context = host->GetContextWithCheck();
116     CHECK_NULL_RETURN(context, constraintSize);
117     auto buttonTheme = context->GetTheme<ButtonTheme>();
118     CHECK_NULL_RETURN(buttonTheme, constraintSize);
119     const auto& padding = buttonLayoutProperty->CreatePaddingAndBorder();
120     auto defaultHeight = GetDefaultHeight(layoutWrapper);
121     float minLength = 0.0f;
122     if (selfLayoutConstraint->selfIdealSize.IsNull()) {
123         // Width and height are not set.
124         minLength = defaultHeight;
125     } else if (selfLayoutConstraint->selfIdealSize.Width().has_value() &&
126                !selfLayoutConstraint->selfIdealSize.Height().has_value()) {
127         // Only width is set.
128         minLength = selfLayoutConstraint->selfIdealSize.Width().value();
129     } else if (selfLayoutConstraint->selfIdealSize.Height().has_value() &&
130                !selfLayoutConstraint->selfIdealSize.Width().has_value()) {
131         // Only height is set.
132         minLength = selfLayoutConstraint->selfIdealSize.Height().value();
133     } else {
134         // Both width and height are set.
135         auto buttonWidth = selfLayoutConstraint->selfIdealSize.Width().value();
136         auto buttonHeight = selfLayoutConstraint->selfIdealSize.Height().value();
137         minLength = std::min(buttonWidth, buttonHeight);
138     }
139     if (buttonLayoutProperty->HasBorderRadius() && selfLayoutConstraint->selfIdealSize.IsNull()) {
140         auto radius =
141             static_cast<float>(GetFirstValidRadius(buttonLayoutProperty->GetBorderRadius().value()).ConvertToPx());
142         minLength = 2 * radius;
143     }
144     constraintSize.SetSizeT(SizeF(minLength, minLength));
145     MinusPaddingToSize(padding, constraintSize);
146     return ConstrainSize(constraintSize, selfLayoutConstraint->minSize, selfLayoutConstraint->maxSize);
147 }
148 
HandleAdaptiveText(LayoutWrapper * layoutWrapper,LayoutConstraintF & layoutConstraint)149 void ButtonLayoutAlgorithm::HandleAdaptiveText(LayoutWrapper* layoutWrapper, LayoutConstraintF& layoutConstraint)
150 {
151     auto buttonLayoutProperty = DynamicCast<ButtonLayoutProperty>(layoutWrapper->GetLayoutProperty());
152     CHECK_NULL_VOID(buttonLayoutProperty);
153     auto host = layoutWrapper->GetHostNode();
154     CHECK_NULL_VOID(host);
155     auto* context = host->GetContextWithCheck();
156     CHECK_NULL_VOID(context);
157     auto buttonTheme = context->GetTheme<ButtonTheme>();
158     CHECK_NULL_VOID(buttonTheme);
159     auto childWrapper = layoutWrapper->GetOrCreateChildByIndex(0);
160     CHECK_NULL_VOID(childWrapper);
161     auto childConstraint = layoutWrapper->GetLayoutProperty()->GetContentLayoutConstraint();
162     childWrapper->Measure(childConstraint);
163     auto textSize = childWrapper->GetGeometryNode()->GetContentSize();
164     if (buttonLayoutProperty->HasFontSize() || buttonLayoutProperty->HasControlSize()) {
165         // Fonsize is set. When the font height is larger than the button height, make the button fit the font
166         // height.
167         if (GreatOrEqual(textSize.Height(), layoutConstraint.maxSize.Height())) {
168             layoutConstraint.maxSize.SetHeight(textSize.Height());
169         }
170     } else {
171         // Fonsize is not set. When the font width is greater than the button width, dynamically change the font
172         // size to no less than 9sp.
173         auto textLayoutProperty = DynamicCast<TextLayoutProperty>(childWrapper->GetLayoutProperty());
174         textLayoutProperty->UpdateAdaptMaxFontSize(
175             buttonLayoutProperty->GetMaxFontSize().value_or(buttonTheme->GetMaxFontSize()));
176         textLayoutProperty->UpdateAdaptMinFontSize(
177             buttonLayoutProperty->GetMinFontSize().value_or(buttonTheme->GetMinFontSize()));
178     }
179     childWrapper->Measure(layoutConstraint);
180     childSize_ = childWrapper->GetGeometryNode()->GetContentSize();
181 }
182 
HandleBorderRadius(LayoutWrapper * layoutWrapper)183 void ButtonLayoutAlgorithm::HandleBorderRadius(LayoutWrapper* layoutWrapper)
184 {
185     auto host = layoutWrapper->GetHostNode();
186     CHECK_NULL_VOID(host);
187     auto buttonLayoutProperty = DynamicCast<ButtonLayoutProperty>(layoutWrapper->GetLayoutProperty());
188     CHECK_NULL_VOID(buttonLayoutProperty);
189     auto frameSize = layoutWrapper->GetGeometryNode()->GetFrameSize();
190     auto renderContext = host->GetRenderContext();
191     CHECK_NULL_VOID(renderContext);
192     auto buttonType = buttonLayoutProperty->GetType().value_or(ButtonType::CAPSULE);
193     if (buttonType == ButtonType::CIRCLE) {
194         auto minSize = std::min(frameSize.Height(), frameSize.Width());
195         auto layoutConstraint = layoutWrapper->GetLayoutProperty()->CreateChildConstraint();
196         if (buttonLayoutProperty->HasBorderRadius() && layoutConstraint.parentIdealSize.IsNull()) {
197             auto borderRadius = buttonLayoutProperty->GetBorderRadius().value_or(NG::BorderRadiusProperty());
198             minSize = static_cast<float>(GetFirstValidRadius(borderRadius).ConvertToPx() * 2);
199         }
200         renderContext->UpdateBorderRadius(BorderRadiusProperty(Dimension(minSize / 2)));
201         MeasureCircleButton(layoutWrapper);
202     } else if (buttonType == ButtonType::CAPSULE) {
203         renderContext->UpdateBorderRadius(BorderRadiusProperty(Dimension(frameSize.Height() / 2)));
204     } else if (buttonType == ButtonType::NORMAL) {
205         auto normalRadius = buttonLayoutProperty->GetBorderRadiusValue(BorderRadiusProperty(Dimension()));
206         renderContext->UpdateBorderRadius(normalRadius);
207     } else if (buttonType == ButtonType::ROUNDED_RECTANGLE) {
208         auto defaultBorderRadius = GetDefaultBorderRadius(layoutWrapper);
209         auto roundedRectRadius =
210             buttonLayoutProperty->GetBorderRadiusValue(BorderRadiusProperty(Dimension(defaultBorderRadius)));
211         checkNegativeBorderRadius(roundedRectRadius.radiusTopLeft, defaultBorderRadius);
212         checkNegativeBorderRadius(roundedRectRadius.radiusTopRight, defaultBorderRadius);
213         checkNegativeBorderRadius(roundedRectRadius.radiusBottomLeft, defaultBorderRadius);
214         checkNegativeBorderRadius(roundedRectRadius.radiusBottomRight, defaultBorderRadius);
215         renderContext->UpdateBorderRadius(roundedRectRadius);
216     }
217 }
218 
219 // Called to perform measure current render node.
PerformMeasureSelf(LayoutWrapper * layoutWrapper)220 void ButtonLayoutAlgorithm::PerformMeasureSelf(LayoutWrapper* layoutWrapper)
221 {
222     auto buttonLayoutProperty = DynamicCast<ButtonLayoutProperty>(layoutWrapper->GetLayoutProperty());
223     CHECK_NULL_VOID(buttonLayoutProperty);
224     BoxLayoutAlgorithm::PerformMeasureSelf(layoutWrapper);
225     if (NeedAgingMeasure(layoutWrapper)) {
226         return;
227     }
228     if (buttonLayoutProperty->HasLabel()) {
229         auto frameSize = layoutWrapper->GetGeometryNode()->GetFrameSize();
230         auto layoutConstraint = layoutWrapper->GetLayoutProperty()->CreateChildConstraint();
231         const auto& selfLayoutConstraint = layoutWrapper->GetLayoutProperty()->GetLayoutConstraint();
232         auto padding = buttonLayoutProperty->CreatePaddingAndBorder();
233         auto topPadding = padding.top.value_or(0.0);
234         auto bottomPadding = padding.bottom.value_or(0.0);
235         auto host = layoutWrapper->GetHostNode();
236         CHECK_NULL_VOID(host);
237         auto* context = host->GetContextWithCheck();
238         CHECK_NULL_VOID(context);
239         auto buttonTheme = context->GetTheme<ButtonTheme>();
240         CHECK_NULL_VOID(buttonTheme);
241         auto defaultHeight = GetDefaultHeight(layoutWrapper);
242         auto buttonType = buttonLayoutProperty->GetType().value_or(ButtonType::CAPSULE);
243         if (buttonType == ButtonType::CIRCLE) {
244             HandleLabelCircleButtonFrameSize(layoutConstraint, frameSize, defaultHeight);
245         } else {
246             if (selfLayoutConstraint && !selfLayoutConstraint->selfIdealSize.Height().has_value()) {
247                 auto layoutContraint = buttonLayoutProperty->GetLayoutConstraint();
248                 CHECK_NULL_VOID(layoutContraint);
249                 auto maxHeight = layoutContraint->maxSize.Height();
250                 auto minHeight = layoutContraint->minSize.Height();
251                 auto actualHeight = static_cast<float>(childSize_.Height() + topPadding + bottomPadding);
252                 actualHeight = std::min(actualHeight, maxHeight);
253                 actualHeight = std::max(actualHeight, minHeight);
254                 frameSize.SetHeight(maxHeight > defaultHeight ? std::max(defaultHeight, actualHeight) : maxHeight);
255             }
256         }
257         // Determine if the button needs to fit the font size.
258         if (buttonLayoutProperty->HasFontSize()) {
259             if (GreatOrEqual(childSize_.Height() + topPadding + bottomPadding, frameSize.Height())) {
260                 frameSize = SizeF(frameSize.Width(), childSize_.Height() + topPadding + bottomPadding);
261             }
262         }
263         layoutWrapper->GetGeometryNode()->SetFrameSize(frameSize);
264     }
265     HandleBorderRadius(layoutWrapper);
266 }
267 
HandleLabelCircleButtonFrameSize(const LayoutConstraintF & layoutConstraint,SizeF & frameSize,const float & defaultHeight)268 void ButtonLayoutAlgorithm::HandleLabelCircleButtonFrameSize(
269     const LayoutConstraintF& layoutConstraint, SizeF& frameSize, const float& defaultHeight)
270 {
271     float minLength = 0.0f;
272     if (layoutConstraint.parentIdealSize.IsNull()) {
273         minLength = static_cast<float>(defaultHeight);
274     } else if (layoutConstraint.parentIdealSize.Width().has_value() &&
275                !layoutConstraint.parentIdealSize.Height().has_value()) {
276         minLength = frameSize.Width();
277     } else if (layoutConstraint.parentIdealSize.Height().has_value() &&
278                !layoutConstraint.parentIdealSize.Width().has_value()) {
279         minLength = frameSize.Height();
280     } else {
281         minLength = std::min(frameSize.Width(), frameSize.Height());
282     }
283     frameSize.SetWidth(minLength);
284     frameSize.SetHeight(minLength);
285 }
286 
MeasureCircleButton(LayoutWrapper * layoutWrapper)287 void ButtonLayoutAlgorithm::MeasureCircleButton(LayoutWrapper* layoutWrapper)
288 {
289     auto frameNode = layoutWrapper->GetHostNode();
290     CHECK_NULL_VOID(frameNode);
291     const auto& radius = frameNode->GetRenderContext()->GetBorderRadius();
292     SizeF frameSize = { -1, -1 };
293     if (radius.has_value()) {
294         auto radiusTopMax = std::max(radius->radiusTopLeft, radius->radiusTopRight);
295         auto radiusBottomMax = std::max(radius->radiusBottomLeft, radius->radiusBottomRight);
296         auto radiusMax = std::max(radiusTopMax, radiusBottomMax);
297         auto rrectRadius = radiusMax.value_or(0.0_vp).ConvertToPx();
298         frameSize.SetSizeT(SizeF { static_cast<float>(rrectRadius * 2), static_cast<float>(rrectRadius * 2) });
299     }
300     frameSize.UpdateIllegalSizeWithCheck(SizeF { 0.0f, 0.0f });
301     layoutWrapper->GetGeometryNode()->SetFrameSize(frameSize);
302 }
303 
GetFirstValidRadius(const BorderRadiusProperty & borderRadius)304 Dimension ButtonLayoutAlgorithm::GetFirstValidRadius(const BorderRadiusProperty& borderRadius)
305 {
306     if (borderRadius.radiusTopLeft.has_value()) {
307         return borderRadius.radiusTopLeft.value();
308     }
309     if (borderRadius.radiusTopRight.has_value()) {
310         return borderRadius.radiusTopRight.value();
311     }
312     if (borderRadius.radiusBottomLeft.has_value()) {
313         return borderRadius.radiusBottomLeft.value();
314     }
315     if (borderRadius.radiusBottomRight.has_value()) {
316         return borderRadius.radiusBottomRight.value();
317     }
318     return 0.0_vp;
319 }
320 
GetDefaultHeight(LayoutWrapper * layoutWrapper)321 float ButtonLayoutAlgorithm::GetDefaultHeight(LayoutWrapper* layoutWrapper)
322 {
323     auto layoutProperty = DynamicCast<ButtonLayoutProperty>(layoutWrapper->GetLayoutProperty());
324     CHECK_NULL_RETURN(layoutProperty, 0.0);
325     auto frameNode = layoutWrapper->GetHostNode();
326     CHECK_NULL_RETURN(frameNode, 0.0);
327     auto* context = frameNode->GetContext();
328     CHECK_NULL_RETURN(context, 0.0);
329     auto buttonTheme = context->GetTheme<ButtonTheme>();
330     CHECK_NULL_RETURN(buttonTheme, 0.0);
331     if (frameNode->GetTag() == V2::TOGGLE_ETS_TAG) {
332         auto toggleTheme = context->GetTheme<ToggleTheme>();
333         CHECK_NULL_RETURN(toggleTheme, 0.0);
334         return static_cast<float>(toggleTheme->GetButtonHeight().ConvertToPx());
335     }
336     ControlSize controlSize = layoutProperty->GetControlSize().value_or(ControlSize::NORMAL);
337     return static_cast<float>(buttonTheme->GetHeight(controlSize).ConvertToPx());
338 }
339 
GetDefaultBorderRadius(LayoutWrapper * layoutWrapper)340 float ButtonLayoutAlgorithm::GetDefaultBorderRadius(LayoutWrapper* layoutWrapper)
341 {
342     auto layoutProperty = DynamicCast<ButtonLayoutProperty>(layoutWrapper->GetLayoutProperty());
343     CHECK_NULL_RETURN(layoutProperty, 0.0f);
344     auto frameNode = layoutWrapper->GetHostNode();
345     CHECK_NULL_RETURN(frameNode, 0.0f);
346     auto* context = frameNode->GetContext();
347     CHECK_NULL_RETURN(context, 0.0f);
348     auto buttonTheme = context->GetTheme<ButtonTheme>();
349     CHECK_NULL_RETURN(buttonTheme, 0.0f);
350     ControlSize controlSize = layoutProperty->GetControlSize().value_or(ControlSize::NORMAL);
351     return static_cast<float>(buttonTheme->GetBorderRadius(controlSize).ConvertToPx());
352 }
353 
MarkNeedFlushMouseEvent(LayoutWrapper * layoutWrapper)354 void ButtonLayoutAlgorithm::MarkNeedFlushMouseEvent(LayoutWrapper* layoutWrapper)
355 {
356     auto host = layoutWrapper->GetHostNode();
357     CHECK_NULL_VOID(host);
358     auto pattern = host->GetPattern<ButtonPattern>();
359     CHECK_NULL_VOID(pattern);
360     auto frameSize = layoutWrapper->GetGeometryNode()->GetFrameSize();
361     if (frameSize != pattern->GetPreFrameSize()) {
362         pattern->SetPreFrameSize(frameSize);
363         auto context = PipelineContext::GetCurrentContext();
364         CHECK_NULL_VOID(context);
365         context->MarkNeedFlushMouseEvent();
366     }
367 }
368 
NeedAgingMeasure(LayoutWrapper * layoutWrapper)369 bool ButtonLayoutAlgorithm::NeedAgingMeasure(LayoutWrapper* layoutWrapper)
370 {
371     if (!IsAging(layoutWrapper)) {
372         return false;
373     }
374     auto buttonLayoutProperty = DynamicCast<ButtonLayoutProperty>(layoutWrapper->GetLayoutProperty());
375     CHECK_NULL_RETURN(buttonLayoutProperty, false);
376     auto pipeline = NG::PipelineContext::GetCurrentContextSafely();
377     CHECK_NULL_RETURN(pipeline, false);
378     auto buttonTheme = pipeline->GetTheme<ButtonTheme>();
379     float agingPadding = buttonTheme->GetAgingNormalPadding().ConvertToPx() * 2.0f;
380     if (buttonLayoutProperty->HasControlSize() && buttonLayoutProperty->GetControlSize() == ControlSize::SMALL) {
381         agingPadding = buttonTheme->GetAgingSmallPadding().ConvertToPx() * 2.0f;
382     }
383     auto host = layoutWrapper->GetHostNode();
384     CHECK_NULL_RETURN(host, false);
385     auto pattern = host->GetPattern<ButtonPattern>();
386     CHECK_NULL_RETURN(pattern, false);
387     if (!pattern->GetHasCustomPadding()) {
388         auto geometryNode = layoutWrapper->GetGeometryNode();
389         CHECK_NULL_RETURN(geometryNode, false);
390         auto frameSize = geometryNode->GetFrameSize();
391         if (buttonLayoutProperty->HasLabel()) {
392             auto childWrapper = layoutWrapper->GetOrCreateChildByIndex(0);
393             CHECK_NULL_RETURN(childWrapper, false);
394             auto childGeometryNode = childWrapper->GetGeometryNode();
395             CHECK_NULL_RETURN(childGeometryNode, false);
396             auto childFrameSize = childGeometryNode->GetContentSize();
397             frameSize.SetHeight(childFrameSize.Height() + agingPadding);
398         } else {
399             frameSize.SetHeight(frameSize.Height() + agingPadding);
400         }
401         geometryNode->SetFrameSize(frameSize);
402     }
403     HandleBorderRadius(layoutWrapper);
404     return true;
405 }
406 
IsAging(LayoutWrapper * layoutWrapper)407 bool ButtonLayoutAlgorithm::IsAging(LayoutWrapper* layoutWrapper)
408 {
409     auto buttonLayoutProperty = DynamicCast<ButtonLayoutProperty>(layoutWrapper->GetLayoutProperty());
410     CHECK_NULL_RETURN(buttonLayoutProperty, false);
411 
412     if (buttonLayoutProperty->HasType() && buttonLayoutProperty->GetType() == ButtonType::CIRCLE) {
413         return false;
414     }
415 
416     if (buttonLayoutProperty->HasLabel() && buttonLayoutProperty->GetLabel()->empty()) {
417         return false;
418     }
419 
420     if (buttonLayoutProperty->HasFontSize() && buttonLayoutProperty->GetFontSize()->Unit() != DimensionUnit::FP) {
421         return false;
422     }
423     const auto& calcConstraint = buttonLayoutProperty->GetCalcLayoutConstraint();
424     if (calcConstraint && calcConstraint->selfIdealSize->Height().has_value() &&
425         calcConstraint->selfIdealSize->Width().has_value()) {
426         return false;
427     }
428     auto pipeline = NG::PipelineContext::GetCurrentContextSafely();
429     CHECK_NULL_RETURN(pipeline, false);
430     auto buttonTheme = pipeline->GetTheme<ButtonTheme>();
431     CHECK_NULL_RETURN(buttonTheme, false);
432     auto fontScale = pipeline->GetFontScale();
433     if (!(NearEqual(fontScale, buttonTheme->GetBigFontSizeScale()) ||
434             NearEqual(fontScale, buttonTheme->GetLargeFontSizeScale()) ||
435             NearEqual(fontScale, buttonTheme->GetMaxFontSizeScale()))) {
436         return false;
437     }
438     return true;
439 }
440 } // namespace OHOS::Ace::NG
441