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