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 #include "core/components_ng/pattern/security_component/security_component_layout_element.h"
16
17 #include "base/log/ace_scoring_log.h"
18 #include "base/memory/ace_type.h"
19 #include "core/components_ng/pattern/image/image_layout_property.h"
20 #include "core/components_ng/pattern/security_component/security_component_layout_property.h"
21 #include "core/components_ng/pattern/security_component/security_component_theme.h"
22 #include "core/components_ng/pattern/text/text_layout_property.h"
23 #include "core/components_ng/property/measure_property.h"
24 #include "core/pipeline_ng/pipeline_context.h"
25 #ifdef ENABLE_ROSEN_BACKEND
26 #include "core/components/custom_paint/rosen_render_custom_paint.h"
27 #endif
28
29 namespace OHOS::Ace::NG {
Init(RefPtr<SecurityComponentLayoutProperty> & property,RefPtr<LayoutWrapper> & iconWrap)30 void IconLayoutElement::Init(RefPtr<SecurityComponentLayoutProperty>& property,
31 RefPtr<LayoutWrapper>& iconWrap)
32 {
33 secCompProperty_ = property;
34 iconWrap_ = iconWrap;
35 CHECK_NULL_VOID(property);
36 CHECK_NULL_VOID(iconWrap);
37 if (property->GetIconStyle().value_or(-1) ==
38 static_cast<int32_t>(SecurityComponentIconStyle::ICON_NULL)) {
39 return;
40 }
41 isExist_ = true;
42
43 auto pipeline = PipelineContext::GetCurrentContext();
44 CHECK_NULL_VOID(pipeline);
45 auto theme = pipeline->GetTheme<SecurityComponentTheme>();
46 CHECK_NULL_VOID(theme);
47 minIconSize_ = theme->GetMinIconSize().ConvertToPx();
48
49 if (property->GetIconSize().has_value()) {
50 isSetSize_ = true;
51 width_ = height_ = property->GetIconSize().value().ConvertToPx();
52 } else {
53 width_ = height_ = theme->GetIconSize().ConvertToPx();
54 }
55 }
56
DoMeasure()57 void IconLayoutElement::DoMeasure()
58 {
59 if (!isExist_) {
60 return;
61 }
62 auto iconConstraint = secCompProperty_->CreateChildConstraint();
63 iconConstraint.selfIdealSize.SetWidth(width_);
64 iconConstraint.selfIdealSize.SetHeight(height_);
65 iconWrap_->Measure(iconConstraint);
66 }
67
ShrinkWidth(double reduceSize)68 double IconLayoutElement::ShrinkWidth(double reduceSize)
69 {
70 if (!isExist_ || isSetSize_) {
71 return reduceSize;
72 }
73 if (GreatNotEqual(minIconSize_, (width_ - reduceSize))) {
74 int remain = reduceSize - (width_ - minIconSize_);
75 height_ = width_ = minIconSize_;
76 return remain;
77 }
78
79 width_ -= reduceSize;
80 height_ = width_;
81 return 0.0;
82 }
83
ShrinkHeight(double reduceSize)84 double IconLayoutElement::ShrinkHeight(double reduceSize)
85 {
86 if (!isExist_ || isSetSize_) {
87 return reduceSize;
88 }
89 if (GreatNotEqual(minIconSize_, (height_ - reduceSize))) {
90 double remain = reduceSize - (height_ - minIconSize_);
91 width_ = height_ = minIconSize_;
92 return remain;
93 }
94 height_ -= reduceSize;
95 width_ = height_;
96 return 0.0;
97 }
98
Init(RefPtr<SecurityComponentLayoutProperty> & property,RefPtr<LayoutWrapper> & textWrap)99 void TextLayoutElement::Init(RefPtr<SecurityComponentLayoutProperty>& property,
100 RefPtr<LayoutWrapper>& textWrap)
101 {
102 secCompProperty_ = property;
103 textWrap_ = textWrap;
104 CHECK_NULL_VOID(property);
105 CHECK_NULL_VOID(textWrap);
106 if (property->GetSecurityComponentDescription().value_or(-1) ==
107 static_cast<int32_t>(SecurityComponentDescription::TEXT_NULL)) {
108 return;
109 }
110 isExist_ = true;
111
112 auto textProp = AceType::DynamicCast<TextLayoutProperty>(textWrap_->GetLayoutProperty());
113 CHECK_NULL_VOID(textProp);
114 auto theme = PipelineContext::GetCurrentContext()->GetTheme<SecurityComponentTheme>();
115 CHECK_NULL_VOID(theme);
116 minFontSize_ = theme->GetMinFontSize();
117 if (property->GetFontSize().has_value()) {
118 isSetSize_ = true;
119 } else {
120 defaultFontSize_ = theme->GetFontSize();
121 textProp->UpdateFontSize(defaultFontSize_);
122 }
123
124 auto textConstraint = property->CreateChildConstraint();
125 SizeT<float> maxSize { Infinity<float>(), Infinity<float>() };
126 textConstraint.maxSize = maxSize;
127 textWrap_->Measure(std::optional<LayoutConstraintF>(textConstraint));
128 auto textSizeF = textWrap->GetGeometryNode()->GetFrameSize();
129 width_ = textSizeF.Width();
130 height_ = textSizeF.Height();
131 }
132
ChooseExactFontSize(RefPtr<TextLayoutProperty> & property,bool isWidth)133 void TextLayoutElement::ChooseExactFontSize(RefPtr<TextLayoutProperty>& property, bool isWidth)
134 {
135 if (!minTextSize_.has_value()) {
136 property->UpdateFontSize(minFontSize_);
137 return;
138 }
139 constexpr Dimension ADAPT_UNIT = 1.0_fp;
140 Dimension step = ADAPT_UNIT;
141 Dimension fontSize = (property->GetFontSize().has_value()) ? property->GetFontSize().value() : defaultFontSize_;
142 while (fontSize > minFontSize_) {
143 auto tempSize = GetMeasureTextSize(property->GetContent().value_or(""),
144 fontSize,
145 property->GetFontWeight().value_or(FontWeight::NORMAL));
146 if (!tempSize.has_value()) {
147 fontSize = minFontSize_;
148 break;
149 }
150 if (isWidth) {
151 if (GreatOrEqual(width_, tempSize.value().Width())) {
152 break;
153 }
154 } else {
155 if (GreatOrEqual(height_, tempSize.value().Height())) {
156 break;
157 }
158 }
159 fontSize -= step;
160 }
161 property->UpdateFontSize(fontSize);
162 }
163
UpdateSize(bool isWidth)164 void TextLayoutElement::UpdateSize(bool isWidth)
165 {
166 auto textProp = AceType::DynamicCast<TextLayoutProperty>(textWrap_->GetLayoutProperty());
167 CHECK_NULL_VOID(textProp);
168 ChooseExactFontSize(textProp, isWidth);
169 auto textConstraint = textProp->GetContentLayoutConstraint();
170 CHECK_NULL_VOID(textConstraint);
171 if (isWidth) {
172 textConstraint->selfIdealSize.SetWidth(width_);
173 } else {
174 textConstraint->selfIdealSize.SetHeight(height_);
175 }
176
177 textWrap_->Measure(textConstraint);
178 auto textSizeF = textWrap_->GetGeometryNode()->GetFrameSize();
179 width_ = textSizeF.Width();
180 height_ = textSizeF.Height();
181 }
182
GetMeasureTextSize(const std::string & data,const Dimension & fontSize,FontWeight fontWeight)183 std::optional<SizeF> TextLayoutElement::GetMeasureTextSize(const std::string& data,
184 const Dimension& fontSize, FontWeight fontWeight)
185 {
186 #ifdef ENABLE_ROSEN_BACKEND
187 MeasureContext content;
188 content.textContent = data;
189 content.fontSize = fontSize;
190 auto fontweight = StringUtils::FontWeightToString(fontWeight);
191 content.fontWeight = fontweight;
192 auto size = RosenRenderCustomPaint::MeasureTextSizeInner(content);
193 return SizeF(size.Width(), size.Height());
194 #else
195 return std::nullopt;
196 #endif
197 }
198
MeasureMinTextSize()199 void TextLayoutElement::MeasureMinTextSize()
200 {
201 auto textProp = AceType::DynamicCast<TextLayoutProperty>(textWrap_->GetLayoutProperty());
202 CHECK_NULL_VOID(textProp);
203 minTextSize_ = GetMeasureTextSize(textProp->GetContent().value_or(""),
204 minFontSize_,
205 textProp->GetFontWeight().value_or(FontWeight::NORMAL));
206 }
207
ShrinkWidth(double reduceSize)208 double TextLayoutElement::ShrinkWidth(double reduceSize)
209 {
210 if (!isExist_ || isSetSize_) {
211 return reduceSize;
212 }
213 if (!minTextSize_.has_value()) {
214 MeasureMinTextSize();
215 }
216 double minTextWidth = minTextSize_.value_or(SizeT(0.0F, 0.0F)).Width();
217 if (GreatNotEqual(minTextWidth, (width_ - reduceSize))) {
218 int remain = reduceSize - (width_ - minTextWidth);
219 width_ = minTextWidth;
220 UpdateSize(true);
221 return remain;
222 }
223
224 width_ -= reduceSize;
225 UpdateSize(true);
226 return 0.0;
227 }
228
ShrinkHeight(double reduceSize)229 double TextLayoutElement::ShrinkHeight(double reduceSize)
230 {
231 if (!isExist_ || isSetSize_) {
232 return reduceSize;
233 }
234 if (!minTextSize_.has_value()) {
235 MeasureMinTextSize();
236 }
237
238 double minTextHeight = minTextSize_.value_or(SizeT(0.0F, 0.0F)).Height();
239 if (GreatNotEqual(minTextHeight, (height_ - reduceSize))) {
240 double remain = reduceSize - (height_ - minTextHeight);
241 height_ = minTextHeight;
242 UpdateSize(false);
243 return remain;
244 }
245 height_ -= reduceSize;
246 UpdateSize(false);
247 return 0.0;
248 }
249 };
250