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/pattern/text/text_pattern.h"
24 #include "core/components_ng/property/measure_property.h"
25 #include "core/pipeline_ng/pipeline_context.h"
26 #ifdef ENABLE_ROSEN_BACKEND
27 #include "core/components/custom_paint/rosen_render_custom_paint.h"
28 #endif
29
30 namespace OHOS::Ace::NG {
Init(RefPtr<SecurityComponentLayoutProperty> & property,RefPtr<LayoutWrapper> & iconWrap)31 void IconLayoutElement::Init(RefPtr<SecurityComponentLayoutProperty>& property,
32 RefPtr<LayoutWrapper>& iconWrap)
33 {
34 CHECK_NULL_VOID(property);
35 CHECK_NULL_VOID(iconWrap);
36 secCompProperty_ = property;
37 iconWrap_ = iconWrap;
38 if (property->GetIconStyle().value_or(-1) ==
39 static_cast<int32_t>(SecurityComponentIconStyle::ICON_NULL)) {
40 return;
41 }
42 isExist_ = true;
43
44 auto pipeline = PipelineContext::GetCurrentContextSafely();
45 CHECK_NULL_VOID(pipeline);
46 auto theme = pipeline->GetTheme<SecurityComponentTheme>();
47 CHECK_NULL_VOID(theme);
48 minIconSize_ = theme->GetMinIconSize().ConvertToPx();
49
50 if (property->GetIconSize().has_value()) {
51 isSetSize_ = true;
52 width_ = height_ = property->GetIconSize().value().ConvertToPx();
53 } else {
54 width_ = height_ = theme->GetIconSize().ConvertToPx();
55 }
56 }
57
DoMeasure()58 void IconLayoutElement::DoMeasure()
59 {
60 if (!isExist_) {
61 return;
62 }
63 auto iconConstraint = secCompProperty_->CreateChildConstraint();
64 iconConstraint.selfIdealSize.SetWidth(width_);
65 iconConstraint.selfIdealSize.SetHeight(height_);
66 iconWrap_->Measure(iconConstraint);
67 }
68
ShrinkWidth(double reduceSize)69 double IconLayoutElement::ShrinkWidth(double reduceSize)
70 {
71 if (!isExist_ || isSetSize_) {
72 return reduceSize;
73 }
74 if (GreatNotEqual(minIconSize_, (width_ - reduceSize))) {
75 int remain = reduceSize - (width_ - minIconSize_);
76 height_ = width_ = minIconSize_;
77 return remain;
78 }
79
80 width_ -= reduceSize;
81 height_ = width_;
82 return 0.0;
83 }
84
ShrinkHeight(double reduceSize)85 double IconLayoutElement::ShrinkHeight(double reduceSize)
86 {
87 if (!isExist_ || isSetSize_) {
88 return reduceSize;
89 }
90 if (GreatNotEqual(minIconSize_, (height_ - reduceSize))) {
91 double remain = reduceSize - (height_ - minIconSize_);
92 width_ = height_ = minIconSize_;
93 return remain;
94 }
95 height_ -= reduceSize;
96 width_ = height_;
97 return 0.0;
98 }
99
Init(RefPtr<SecurityComponentLayoutProperty> & property,RefPtr<LayoutWrapper> & textWrap)100 void TextLayoutElement::Init(RefPtr<SecurityComponentLayoutProperty>& property,
101 RefPtr<LayoutWrapper>& textWrap)
102 {
103 secCompProperty_ = property;
104 textWrap_ = textWrap;
105 CHECK_NULL_VOID(property);
106 CHECK_NULL_VOID(textWrap);
107 if (property->GetSecurityComponentDescription().value_or(-1) ==
108 static_cast<int32_t>(SecurityComponentDescription::TEXT_NULL)) {
109 return;
110 }
111 isExist_ = true;
112
113 auto textProp = AceType::DynamicCast<TextLayoutProperty>(textWrap_->GetLayoutProperty());
114 CHECK_NULL_VOID(textProp);
115 auto context = PipelineContext::GetCurrentContextSafely();
116 CHECK_NULL_VOID(context);
117 auto theme = context->GetTheme<SecurityComponentTheme>();
118 CHECK_NULL_VOID(theme);
119 minFontSize_ = theme->GetMinFontSize();
120 if (property->GetFontSize().has_value()) {
121 isSetSize_ = true;
122 } else {
123 defaultFontSize_ = theme->GetFontSize();
124 textProp->UpdateFontSize(defaultFontSize_);
125 }
126
127 auto textConstraint = property->CreateChildConstraint();
128 SizeT<float> maxSize { textConstraint.maxSize.Width(), Infinity<float>() };
129 textConstraint.maxSize = maxSize;
130 textWrap_->Measure(std::optional<LayoutConstraintF>(textConstraint));
131 auto geometryNode = textWrap->GetGeometryNode();
132 CHECK_NULL_VOID(geometryNode);
133 auto textSizeF = geometryNode->GetFrameSize();
134 width_ = textSizeF.Width();
135 height_ = textSizeF.Height();
136 }
137
MeasureForWidth(float width)138 void TextLayoutElement::MeasureForWidth(float width)
139 {
140 auto textProp = AceType::DynamicCast<TextLayoutProperty>(textWrap_->GetLayoutProperty());
141 CHECK_NULL_VOID(textProp);
142 auto textConstraint = textProp->GetContentLayoutConstraint();
143 CHECK_NULL_VOID(textConstraint);
144 textConstraint->selfIdealSize.SetWidth(width);
145 textWrap_->Measure(textConstraint);
146 auto textSizeF = textWrap_->GetGeometryNode()->GetFrameSize();
147 width_ = textSizeF.Width();
148 height_ = textSizeF.Height();
149 }
150
DoMeasure(bool isVertical,float minWidth,float leftSpace)151 void TextLayoutElement::DoMeasure(bool isVertical, float minWidth, float leftSpace)
152 {
153 if (!isExist_) {
154 return;
155 }
156
157 float textMaxWidth;
158 if (isVertical) {
159 textMaxWidth = minWidth > leftSpace ? minWidth : leftSpace;
160 } else {
161 textMaxWidth = minWidth > leftSpace ? minWidth - leftSpace : 0.0;
162 }
163 auto textNode = textWrap_->GetHostNode();
164 CHECK_NULL_VOID(textNode);
165 auto textPattern = textNode->GetPattern<TextPattern>();
166 CHECK_NULL_VOID(textPattern);
167
168 if (GreatNotEqual(width_, textMaxWidth)) {
169 MeasureForWidth(textMaxWidth);
170 auto realWidth = textPattern->GetLineMetrics(0).width;
171 if (LessNotEqual(width_, realWidth)) {
172 MeasureForWidth(realWidth);
173 }
174 }
175 }
176
ChooseExactFontSize(RefPtr<TextLayoutProperty> & property,bool isWidth)177 void TextLayoutElement::ChooseExactFontSize(RefPtr<TextLayoutProperty>& property, bool isWidth)
178 {
179 if (!minTextSize_.has_value()) {
180 property->UpdateFontSize(minFontSize_);
181 return;
182 }
183 constexpr Dimension ADAPT_UNIT = 1.0_fp;
184 Dimension step = ADAPT_UNIT;
185 Dimension fontSize = (property->GetFontSize().has_value()) ? property->GetFontSize().value() : defaultFontSize_;
186 while (fontSize > minFontSize_) {
187 auto tempSize = GetMeasureTextSize(property->GetContent().value_or(""),
188 fontSize,
189 property->GetFontWeight().value_or(FontWeight::NORMAL), 0.0);
190 if (!tempSize.has_value()) {
191 fontSize = minFontSize_;
192 break;
193 }
194 if (isWidth) {
195 if (GreatOrEqual(width_, tempSize.value().Width())) {
196 break;
197 }
198 } else {
199 if (GreatOrEqual(height_, tempSize.value().Height())) {
200 break;
201 }
202 }
203 fontSize -= step;
204 }
205 property->UpdateFontSize(fontSize);
206 }
207
UpdateSize(bool isWidth)208 void TextLayoutElement::UpdateSize(bool isWidth)
209 {
210 auto textProp = AceType::DynamicCast<TextLayoutProperty>(textWrap_->GetLayoutProperty());
211 CHECK_NULL_VOID(textProp);
212 ChooseExactFontSize(textProp, isWidth);
213 auto textConstraint = textProp->GetContentLayoutConstraint();
214 CHECK_NULL_VOID(textConstraint);
215 if (isWidth) {
216 textConstraint->selfIdealSize.SetWidth(width_);
217 } else {
218 textConstraint->selfIdealSize.SetHeight(height_);
219 }
220
221 textWrap_->Measure(textConstraint);
222 auto geometryNode = textWrap_->GetGeometryNode();
223 CHECK_NULL_VOID(geometryNode);
224 auto textSizeF = geometryNode->GetFrameSize();
225 width_ = textSizeF.Width();
226 height_ = textSizeF.Height();
227 }
228
GetCurrentTextSize(std::optional<SizeF> & currentTextSize,Dimension & currentFontSize)229 bool TextLayoutElement::GetCurrentTextSize(std::optional<SizeF>& currentTextSize, Dimension& currentFontSize)
230 {
231 if (!isExist_) {
232 return false;
233 }
234
235 auto textProp = AceType::DynamicCast<TextLayoutProperty>(textWrap_->GetLayoutProperty());
236 CHECK_NULL_RETURN(textProp, false);
237 if (!textProp->GetFontSize().has_value()) {
238 return false;
239 }
240 if (!textProp->GetContent().has_value()) {
241 return false;
242 }
243 currentTextSize = GetMeasureTextSize(textProp->GetContent().value(), textProp->GetFontSize().value(),
244 textProp->GetFontWeight().value_or(FontWeight::NORMAL), width_);
245 if (!currentTextSize.has_value()) {
246 return false;
247 }
248 currentFontSize = textProp->GetFontSize().value();
249 return true;
250 }
251
TryShrinkTextWidth(SizeF & point,SizeF & circlePoint,bool maxSpaceToShrink,float maxDistance,float threshold)252 bool TextLayoutElement::TryShrinkTextWidth(SizeF& point, SizeF& circlePoint, bool maxSpaceToShrink, float maxDistance,
253 float threshold)
254 {
255 auto textProp = AceType::DynamicCast<TextLayoutProperty>(textWrap_->GetLayoutProperty());
256 CHECK_NULL_RETURN(textProp, false);
257
258 auto stepPx = Dimension(1.0, DimensionUnit::VP).ConvertToPx();
259 auto tempHeight = height_;
260 auto tempWidth = width_;
261 auto currentRectWidth = point.Width();
262 while (NearEqual(tempHeight, height_)) {
263 if (LessOrEqual(tempWidth, threshold)) {
264 return false;
265 }
266 tempWidth -= stepPx;
267 currentRectWidth -= stepPx;
268 auto tempSize = GetMeasureTextSize(textProp->GetContent().value(), textProp->GetFontSize().value(),
269 textProp->GetFontWeight().value_or(FontWeight::NORMAL), tempWidth);
270 if (!tempSize.has_value()) {
271 return false;
272 }
273 tempHeight = tempSize.value().Height();
274 if (!NearEqual(tempHeight, height_)) {
275 return false;
276 }
277 auto distance = pow(currentRectWidth - circlePoint.Width()) + pow(point.Height() - circlePoint.Height());
278 if (!GreatNotEqual(distance, maxDistance)) {
279 break;
280 }
281 }
282
283 MeasureForWidth(tempWidth);
284 return true;
285 }
286
GetMeasureTextSize(const std::string & data,const Dimension & fontSize,FontWeight fontWeight,float constraintWidth)287 std::optional<SizeF> TextLayoutElement::GetMeasureTextSize(const std::string& data,
288 const Dimension& fontSize, FontWeight fontWeight, float constraintWidth)
289 {
290 #ifdef ENABLE_ROSEN_BACKEND
291 MeasureContext content;
292 if (!NearEqual(constraintWidth, 0.0)) {
293 content.constraintWidth = Dimension(constraintWidth);
294 }
295 content.textContent = data;
296 content.fontSize = fontSize;
297 auto fontweight = StringUtils::FontWeightToString(fontWeight);
298 content.fontWeight = fontweight;
299 auto size = RosenRenderCustomPaint::MeasureTextSizeInner(content);
300 return SizeF(size.Width(), size.Height());
301 #else
302 return std::nullopt;
303 #endif
304 }
305
MeasureMinTextSize()306 void TextLayoutElement::MeasureMinTextSize()
307 {
308 auto textProp = AceType::DynamicCast<TextLayoutProperty>(textWrap_->GetLayoutProperty());
309 CHECK_NULL_VOID(textProp);
310 minTextSize_ = GetMeasureTextSize(textProp->GetContent().value_or(""),
311 minFontSize_,
312 textProp->GetFontWeight().value_or(FontWeight::NORMAL), 0.0);
313 }
314
ShrinkWidth(double reduceSize)315 double TextLayoutElement::ShrinkWidth(double reduceSize)
316 {
317 if (!isExist_ || isSetSize_) {
318 return reduceSize;
319 }
320 if (!minTextSize_.has_value()) {
321 MeasureMinTextSize();
322 }
323 double minTextWidth = minTextSize_.value_or(SizeT(0.0F, 0.0F)).Width();
324 if (GreatNotEqual(minTextWidth, (width_ - reduceSize))) {
325 int remain = reduceSize - (width_ - minTextWidth);
326 width_ = minTextWidth;
327 UpdateSize(true);
328 return remain;
329 }
330
331 width_ -= reduceSize;
332 UpdateSize(true);
333 return 0.0;
334 }
335
ShrinkHeight(double reduceSize)336 double TextLayoutElement::ShrinkHeight(double reduceSize)
337 {
338 if (!isExist_ || isSetSize_) {
339 return reduceSize;
340 }
341 if (!minTextSize_.has_value()) {
342 MeasureMinTextSize();
343 }
344
345 double minTextHeight = minTextSize_.value_or(SizeT(0.0F, 0.0F)).Height();
346 if (GreatNotEqual(minTextHeight, (height_ - reduceSize))) {
347 double remain = reduceSize - (height_ - minTextHeight);
348 height_ = minTextHeight;
349 UpdateSize(false);
350 return remain;
351 }
352 height_ -= reduceSize;
353 UpdateSize(false);
354 return 0.0;
355 }
356 };
357