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/text_field/text_field_content_modifier.h"
17
18 #include "base/utils/utils.h"
19 #include "core/components_ng/base/modifier.h"
20 #include "core/components_ng/pattern/text/text_pattern.h"
21 #include "core/components_ng/pattern/text_field/text_field_pattern.h"
22 #include "core/components_ng/property/calc_length.h"
23 #include "core/components_ng/render/drawing.h"
24 #include "core/components_ng/render/drawing_prop_convertor.h"
25 #include "core/components_ng/render/image_painter.h"
26 #include "core/pipeline_ng/pipeline_context.h"
27
28 namespace OHOS::Ace::NG {
29 namespace {
30 const FontWeight FONT_WEIGHT_CONVERT_MAP[] = {
31 FontWeight::W100,
32 FontWeight::W200,
33 FontWeight::W300,
34 FontWeight::W400,
35 FontWeight::W500,
36 FontWeight::W600,
37 FontWeight::W700,
38 FontWeight::W800,
39 FontWeight::W900,
40 FontWeight::W700,
41 FontWeight::W400,
42 FontWeight::W900,
43 FontWeight::W100,
44 FontWeight::W500,
45 FontWeight::W400,
46 };
47 constexpr float ROUND_VALUE = 0.5f;
48
ConvertFontWeight(FontWeight fontWeight)49 inline FontWeight ConvertFontWeight(FontWeight fontWeight)
50 {
51 return FONT_WEIGHT_CONVERT_MAP[(int)fontWeight];
52 }
53 } // namespace
54
TextFieldContentModifier(const WeakPtr<OHOS::Ace::NG::Pattern> & pattern)55 TextFieldContentModifier::TextFieldContentModifier(const WeakPtr<OHOS::Ace::NG::Pattern>& pattern) : pattern_(pattern)
56 {
57 SetDefaultAnimatablePropertyValue();
58 SetDefaultPropertyValue();
59 }
60
onDraw(DrawingContext & context)61 void TextFieldContentModifier::onDraw(DrawingContext& context)
62 {
63 auto& canvas = context.canvas;
64 auto textFieldPattern = DynamicCast<TextFieldPattern>(pattern_.Upgrade());
65 CHECK_NULL_VOID(textFieldPattern);
66 auto paragraph = textFieldPattern->GetParagraph();
67 CHECK_NULL_VOID(paragraph);
68 auto contentOffset = contentOffset_->Get();
69 auto contentRect = textFieldPattern->GetContentRect();
70 auto clipRectHeight = 0.0f;
71 auto frameNode = textFieldPattern->GetHost();
72 CHECK_NULL_VOID(frameNode);
73 auto layoutProperty = frameNode->GetLayoutProperty<TextFieldLayoutProperty>();
74 CHECK_NULL_VOID(layoutProperty);
75 clipRectHeight = contentRect.GetY() + contentRect.Height();
76 canvas.Save();
77 RSRect clipInnerRect = RSRect(contentRect.GetX(), contentRect.GetY(),
78 contentRect.Width() + contentRect.GetX() + textFieldPattern->GetInlinePadding(), clipRectHeight);
79 canvas.ClipRect(clipInnerRect, RSClipOp::INTERSECT);
80 if (paragraph) {
81 auto textField = textFieldPattern->IsTextArea() ? "TextArea" : "TextInput";
82 ACE_LAYOUT_SCOPED_TRACE("[%s][id:%d] [Rect:%s]", textField, frameNode->GetId(), contentRect.ToString().c_str());
83 if (Container::GreatOrEqualAPIVersion(PlatformVersion::VERSION_ELEVEN)) {
84 canvas.Save();
85 RSRect clipRect;
86 std::vector<RSPoint> clipRadius;
87 GetFrameRectClip(clipRect, clipRadius);
88 canvas.ClipRoundRect(clipRect, clipRadius, true);
89 paragraph->Paint(canvas, textFieldPattern->GetTextRect().GetX(),
90 textFieldPattern->IsTextArea() ? textFieldPattern->GetTextRect().GetY() : contentOffset.GetY());
91 canvas.Restore();
92 } else {
93 paragraph->Paint(canvas, textFieldPattern->GetTextRect().GetX(),
94 textFieldPattern->IsTextArea() ? textFieldPattern->GetTextRect().GetY() : contentOffset.GetY());
95 }
96 }
97 canvas.Restore();
98 }
99
GetFrameRectClip(RSRect & clipRect,std::vector<RSPoint> & clipRadius)100 void TextFieldContentModifier::GetFrameRectClip(RSRect& clipRect, std::vector<RSPoint>& clipRadius)
101 {
102 auto textFieldPattern = DynamicCast<TextFieldPattern>(pattern_.Upgrade());
103 CHECK_NULL_VOID(textFieldPattern);
104 auto host = textFieldPattern->GetHost();
105 CHECK_NULL_VOID(host);
106 auto renderContext = host->GetRenderContext();
107 CHECK_NULL_VOID(renderContext);
108 auto textFrameRect = textFieldPattern->GetFrameRect();
109 clipRect = RSRect(0.0f, 0.0f, textFrameRect.Width(), textFrameRect.Height());
110 auto radius = renderContext->GetBorderRadius().value_or(BorderRadiusProperty());
111 auto radiusTopLeft = RSPoint(static_cast<float>(radius.radiusTopLeft.value_or(0.0_vp).ConvertToPx()),
112 static_cast<float>(radius.radiusTopLeft.value_or(0.0_vp).ConvertToPx()));
113 clipRadius.emplace_back(radiusTopLeft);
114 auto radiusTopRight = RSPoint(static_cast<float>(radius.radiusTopRight.value_or(0.0_vp).ConvertToPx()),
115 static_cast<float>(radius.radiusTopRight.value_or(0.0_vp).ConvertToPx()));
116 clipRadius.emplace_back(radiusTopRight);
117 auto radiusBottomRight = RSPoint(static_cast<float>(radius.radiusBottomRight.value_or(0.0_vp).ConvertToPx()),
118 static_cast<float>(radius.radiusBottomRight.value_or(0.0_vp).ConvertToPx()));
119 clipRadius.emplace_back(radiusBottomRight);
120 auto radiusBottomLeft = RSPoint(static_cast<float>(radius.radiusBottomLeft.value_or(0.0_vp).ConvertToPx()),
121 static_cast<float>(radius.radiusBottomLeft.value_or(0.0_vp).ConvertToPx()));
122 clipRadius.emplace_back(radiusBottomLeft);
123 }
124
SetDefaultAnimatablePropertyValue()125 void TextFieldContentModifier::SetDefaultAnimatablePropertyValue()
126 {
127 RefPtr<TextTheme> theme;
128 RefPtr<TextFieldLayoutProperty> textFieldLayoutProperty;
129 RefPtr<PipelineContext> pipelineContext;
130 auto textPartten = pattern_.Upgrade();
131 CHECK_NULL_VOID(textPartten);
132 auto frameNode = textPartten->GetHost();
133 CHECK_NULL_VOID(frameNode);
134 pipelineContext = frameNode->GetContext();
135 CHECK_NULL_VOID(pipelineContext);
136 theme = pipelineContext->GetTheme<TextTheme>();
137 textFieldLayoutProperty = frameNode->GetLayoutProperty<TextFieldLayoutProperty>();
138 auto textFieldPattern = DynamicCast<TextFieldPattern>(pattern_.Upgrade());
139 CHECK_NULL_VOID(textFieldPattern);
140 TextStyle textStyle;
141 if (!textFieldPattern->GetTextValue().empty()) {
142 textStyle = CreateTextStyleUsingTheme(
143 textFieldLayoutProperty->GetFontStyle(), textFieldLayoutProperty->GetTextLineStyle(), theme);
144 } else {
145 textStyle = CreateTextStyleUsingTheme(textFieldLayoutProperty->GetPlaceholderFontStyle(),
146 textFieldLayoutProperty->GetPlaceholderTextLineStyle(), theme);
147 }
148 SetDefaultFontSize(textStyle);
149 SetDefaultAdaptMinFontSize(textStyle);
150 SetDefaultAdaptMaxFontSize(textStyle);
151 SetDefaultFontWeight(textStyle);
152 SetDefaultTextColor(textStyle);
153 SetDefaultFontStyle(textStyle);
154 SetDefaultTextOverflow(textStyle);
155 SetDefaultTextDecoration(textStyle);
156 }
157
SetDefaultPropertyValue()158 void TextFieldContentModifier::SetDefaultPropertyValue()
159 {
160 RefPtr<TextFieldTheme> theme;
161 RefPtr<PipelineContext> pipelineContext;
162 auto textPattern = pattern_.Upgrade();
163 CHECK_NULL_VOID(textPattern);
164 auto frameNode = textPattern->GetHost();
165 CHECK_NULL_VOID(frameNode);
166 pipelineContext = frameNode->GetContext();
167 CHECK_NULL_VOID(pipelineContext);
168 theme = pipelineContext->GetTheme<TextFieldTheme>();
169 auto textFieldPattern = DynamicCast<TextFieldPattern>(pattern_.Upgrade());
170
171 textObscured_ = AceType::MakeRefPtr<PropertyBool>(textFieldPattern->GetTextObscured());
172 dragStatus_ = AceType::MakeRefPtr<PropertyBool>(false);
173 contentOffset_ = AceType::MakeRefPtr<PropertyOffsetF>(
174 OffsetF(textFieldPattern->GetTextRect().GetX(), textFieldPattern->GetTextRect().GetY()));
175 contentSize_ = AceType::MakeRefPtr<PropertySizeF>(SizeF());
176 textValue_ = AceType::MakeRefPtr<PropertyString>("");
177 errorTextValue_ = AceType::MakeRefPtr<PropertyString>("");
178 placeholderValue_ = AceType::MakeRefPtr<PropertyString>("");
179 textRectY_ = AceType::MakeRefPtr<PropertyFloat>(textFieldPattern->GetTextRect().GetY());
180 textRectX_ = AceType::MakeRefPtr<PropertyFloat>(textFieldPattern->GetTextRect().GetX());
181 textAlign_ = AceType::MakeRefPtr<PropertyInt>(static_cast<int32_t>(TextAlign::START));
182 showErrorState_ = AceType::MakeRefPtr<PropertyBool>(false);
183 fontFamilyString_ = AceType::MakeRefPtr<PropertyString>("");
184 fontReady_ = AceType::MakeRefPtr<PropertyBool>(false);
185 contentChange_ = AceType::MakeRefPtr<PropertyBool>(false);
186 AttachProperty(contentOffset_);
187 AttachProperty(contentSize_);
188 AttachProperty(textValue_);
189 AttachProperty(errorTextValue_);
190 AttachProperty(placeholderValue_);
191 AttachProperty(textRectY_);
192 AttachProperty(textObscured_);
193 AttachProperty(dragStatus_);
194 AttachProperty(textRectX_);
195 AttachProperty(textAlign_);
196 AttachProperty(showErrorState_);
197 AttachProperty(showUnderline_);
198 AttachProperty(fontFamilyString_);
199 AttachProperty(fontReady_);
200 AttachProperty(contentChange_);
201 }
202
SetDefaultFontSize(const TextStyle & textStyle)203 void TextFieldContentModifier::SetDefaultFontSize(const TextStyle& textStyle)
204 {
205 float fontSizeValue;
206 auto pipelineContext = PipelineContext::GetCurrentContext();
207 if (pipelineContext) {
208 fontSizeValue = pipelineContext->NormalizeToPx(textStyle.GetFontSize());
209 if (textStyle.IsAllowScale() && textStyle.GetFontSize().Unit() == DimensionUnit::FP) {
210 fontSizeValue = pipelineContext->NormalizeToPx(textStyle.GetFontSize() * pipelineContext->GetFontScale());
211 }
212 } else {
213 fontSizeValue = textStyle.GetFontSize().ConvertToPx();
214 }
215
216 fontSizeFloat_ = AceType::MakeRefPtr<AnimatablePropertyFloat>(fontSizeValue);
217 AttachProperty(fontSizeFloat_);
218 }
219
SetDefaultAdaptMinFontSize(const TextStyle & textStyle)220 void TextFieldContentModifier::SetDefaultAdaptMinFontSize(const TextStyle& textStyle)
221 {
222 float minFontSizeValue = 0.0f;
223 adaptMinFontSizeFloat_ = AceType::MakeRefPtr<AnimatablePropertyFloat>(minFontSizeValue);
224 AttachProperty(adaptMinFontSizeFloat_);
225 }
226
SetDefaultAdaptMaxFontSize(const TextStyle & textStyle)227 void TextFieldContentModifier::SetDefaultAdaptMaxFontSize(const TextStyle& textStyle)
228 {
229 float maxFontSizeValue = 0.0f;
230 adaptMaxFontSizeFloat_ = AceType::MakeRefPtr<AnimatablePropertyFloat>(maxFontSizeValue);
231 AttachProperty(adaptMaxFontSizeFloat_);
232 }
233
SetDefaultFontWeight(const TextStyle & textStyle)234 void TextFieldContentModifier::SetDefaultFontWeight(const TextStyle& textStyle)
235 {
236 fontWeightFloat_ =
237 AceType::MakeRefPtr<AnimatablePropertyFloat>(static_cast<float>(ConvertFontWeight(textStyle.GetFontWeight())));
238 AttachProperty(fontWeightFloat_);
239 }
240
SetDefaultTextColor(const TextStyle & textStyle)241 void TextFieldContentModifier::SetDefaultTextColor(const TextStyle& textStyle)
242 {
243 animatableTextColor_ = AceType::MakeRefPtr<AnimatablePropertyColor>(LinearColor(textStyle.GetTextColor()));
244 AttachProperty(animatableTextColor_);
245 }
246
SetDefaultFontStyle(const TextStyle & textStyle)247 void TextFieldContentModifier::SetDefaultFontStyle(const TextStyle& textStyle)
248 {
249 fontStyle_ = AceType::MakeRefPtr<PropertyInt>(static_cast<int32_t>(textStyle.GetFontStyle()));
250 AttachProperty(fontStyle_);
251 }
252
SetDefaultTextOverflow(const TextStyle & textStyle)253 void TextFieldContentModifier::SetDefaultTextOverflow(const TextStyle& textStyle)
254 {
255 textOverflow_ = AceType::MakeRefPtr<PropertyInt>(static_cast<int32_t>(textStyle.GetTextOverflow()));
256 AttachProperty(textOverflow_);
257 }
258
SetDefaultTextDecoration(const TextStyle & textStyle)259 void TextFieldContentModifier::SetDefaultTextDecoration(const TextStyle& textStyle)
260 {
261 textDecoration_ = textStyle.GetTextDecoration();
262 textDecorationStyle_ = textStyle.GetTextDecorationStyle();
263 textDecorationColor_ = textStyle.GetTextDecorationColor();
264 textDecorationColorAlpha_ = MakeRefPtr<AnimatablePropertyFloat>(
265 textDecoration_ == TextDecoration::NONE ? 0.0f : textDecorationColor_->GetAlpha());
266 AttachProperty(textDecorationColorAlpha_);
267 }
268
ModifyTextStyle(TextStyle & textStyle)269 void TextFieldContentModifier::ModifyTextStyle(TextStyle& textStyle)
270 {
271 if (fontSize_.has_value() && fontSizeFloat_) {
272 textStyle.SetFontSize(Dimension(fontSizeFloat_->Get(), DimensionUnit::PX));
273 }
274 if (textStyle.GetAdaptTextSize()) {
275 if (adaptMinFontSize_.has_value() && adaptMinFontSizeFloat_) {
276 textStyle.SetAdaptMinFontSize(Dimension(adaptMinFontSizeFloat_->Get(), DimensionUnit::PX));
277 }
278 if (adaptMaxFontSize_.has_value() && adaptMaxFontSizeFloat_) {
279 textStyle.SetAdaptMaxFontSize(Dimension(adaptMaxFontSizeFloat_->Get(), DimensionUnit::PX));
280 }
281 }
282 if (fontWeight_.has_value() && fontWeightFloat_) {
283 textStyle.SetFontWeight(static_cast<FontWeight>(std::floor(fontWeightFloat_->Get() + 0.5f)));
284 }
285 if (textColor_.has_value() && animatableTextColor_) {
286 textStyle.SetTextColor(Color(animatableTextColor_->Get().GetValue()));
287 }
288 ModifyDecorationInTextStyle(textStyle);
289 }
290
SetFontFamilies(const std::vector<std::string> & value)291 void TextFieldContentModifier::SetFontFamilies(const std::vector<std::string>& value)
292 {
293 CHECK_NULL_VOID(fontFamilyString_);
294 fontFamilyString_->Set(V2::ConvertFontFamily(value));
295 }
296
SetFontSize(const Dimension & value)297 void TextFieldContentModifier::SetFontSize(const Dimension& value)
298 {
299 auto textFieldPattern = DynamicCast<TextFieldPattern>(pattern_.Upgrade());
300 CHECK_NULL_VOID(textFieldPattern);
301 auto valPx = static_cast<float>(textFieldPattern->FontSizeConvertToPx(value));
302 fontSize_ = Dimension(valPx);
303 CHECK_NULL_VOID(fontSizeFloat_);
304 fontSizeFloat_->Set(valPx);
305 }
306
SetAdaptMinFontSize(const Dimension & value)307 void TextFieldContentModifier::SetAdaptMinFontSize(const Dimension& value)
308 {
309 auto textFieldPattern = DynamicCast<TextFieldPattern>(pattern_.Upgrade());
310 CHECK_NULL_VOID(textFieldPattern);
311 auto valPx = static_cast<float>(textFieldPattern->FontSizeConvertToPx(value));
312 adaptMinFontSize_ = Dimension(valPx);
313 CHECK_NULL_VOID(adaptMinFontSizeFloat_);
314 adaptMinFontSizeFloat_->Set(valPx);
315 }
316
SetAdaptMaxFontSize(const Dimension & value)317 void TextFieldContentModifier::SetAdaptMaxFontSize(const Dimension& value)
318 {
319 auto textFieldPattern = DynamicCast<TextFieldPattern>(pattern_.Upgrade());
320 CHECK_NULL_VOID(textFieldPattern);
321 auto valPx = static_cast<float>(textFieldPattern->FontSizeConvertToPx(value));
322 adaptMaxFontSize_ = Dimension(valPx);
323 CHECK_NULL_VOID(adaptMaxFontSizeFloat_);
324 adaptMaxFontSizeFloat_->Set(valPx);
325 }
326
SetFontWeight(const FontWeight & value)327 void TextFieldContentModifier::SetFontWeight(const FontWeight& value)
328 {
329 fontWeight_ = ConvertFontWeight(value);
330 CHECK_NULL_VOID(fontWeightFloat_);
331 fontWeightFloat_->Set(static_cast<int>(ConvertFontWeight(value)));
332 }
333
SetTextColor(const Color & value)334 void TextFieldContentModifier::SetTextColor(const Color& value)
335 {
336 textColor_ = value;
337 CHECK_NULL_VOID(animatableTextColor_);
338 animatableTextColor_->Set(LinearColor(value));
339 }
340
SetTextOverflow(const TextOverflow value)341 void TextFieldContentModifier::SetTextOverflow(const TextOverflow value)
342 {
343 if (textOverflow_->Get() != static_cast<int32_t>(value)) {
344 textOverflow_->Set(static_cast<int32_t>(value));
345 }
346 }
347
SetFontStyle(const OHOS::Ace::FontStyle & value)348 void TextFieldContentModifier::SetFontStyle(const OHOS::Ace::FontStyle& value)
349 {
350 if (fontStyle_->Get() != static_cast<int32_t>(value)) {
351 fontStyle_->Set(static_cast<int32_t>(value));
352 }
353 }
354
SetContentOffset(OffsetF & value)355 void TextFieldContentModifier::SetContentOffset(OffsetF& value)
356 {
357 if (contentOffset_) {
358 contentOffset_->Set(value);
359 }
360 }
361
GetContentOffsetY()362 float TextFieldContentModifier::GetContentOffsetY()
363 {
364 return contentOffset_->Get().GetY();
365 }
366
SetContentSize(SizeF & value)367 void TextFieldContentModifier::SetContentSize(SizeF& value)
368 {
369 if (contentSize_) {
370 contentSize_->Set(value);
371 }
372 }
373
SetTextValue(std::string & value)374 void TextFieldContentModifier::SetTextValue(std::string& value)
375 {
376 if (textValue_->Get() != value) {
377 textValue_->Set(value);
378 }
379 }
380
SetErrorTextValue(const std::string & value)381 void TextFieldContentModifier::SetErrorTextValue(const std::string& value)
382 {
383 if (errorTextValue_->Get() != value) {
384 errorTextValue_->Set(value);
385 }
386 }
387
SetPlaceholderValue(std::string && value)388 void TextFieldContentModifier::SetPlaceholderValue(std::string&& value)
389 {
390 if (placeholderValue_->Get() != value) {
391 placeholderValue_->Set(value);
392 }
393 }
394
SetTextRectY(const float value)395 void TextFieldContentModifier::SetTextRectY(const float value)
396 {
397 if (textRectY_->Get() != value) {
398 textRectY_->Set(value);
399 }
400 }
401
GetTextRectY()402 float TextFieldContentModifier::GetTextRectY()
403 {
404 return textRectY_->Get();
405 }
406
SetTextObscured(bool value)407 void TextFieldContentModifier::SetTextObscured(bool value)
408 {
409 if (textObscured_) {
410 textObscured_->Set(value);
411 }
412 }
413
ChangeDragStatus()414 void TextFieldContentModifier::ChangeDragStatus()
415 {
416 dragStatus_->Set(!dragStatus_->Get());
417 }
418
SetTextRectX(const float value)419 void TextFieldContentModifier::SetTextRectX(const float value)
420 {
421 if (textRectX_->Get() != value) {
422 textRectX_->Set(value);
423 }
424 }
425
GetTextRectX()426 float TextFieldContentModifier::GetTextRectX()
427 {
428 return textRectX_->Get();
429 }
430
SetTextAlign(const TextAlign value)431 void TextFieldContentModifier::SetTextAlign(const TextAlign value)
432 {
433 if (textAlign_->Get() != static_cast<int32_t>(value)) {
434 textAlign_->Set(static_cast<int32_t>(value));
435 }
436 }
437
SetShowErrorState(bool value)438 void TextFieldContentModifier::SetShowErrorState(bool value)
439 {
440 if (showErrorState_) {
441 showErrorState_->Set(value);
442 }
443 }
444
SetShowUnderlineState(bool value)445 void TextFieldContentModifier::SetShowUnderlineState(bool value)
446 {
447 if (showUnderline_) {
448 showUnderline_->Set(value);
449 }
450 }
451
SetFontReady(bool value)452 void TextFieldContentModifier::SetFontReady(bool value)
453 {
454 if (fontReady_) {
455 fontReady_->Set(value);
456 }
457 }
458
ContentChange()459 void TextFieldContentModifier::ContentChange()
460 {
461 CHECK_NULL_VOID(contentChange_);
462 contentChange_->Set(!contentChange_->Get());
463 }
464
NeedMeasureUpdate(PropertyChangeFlag & flag)465 bool TextFieldContentModifier::NeedMeasureUpdate(PropertyChangeFlag& flag)
466 {
467 flag = 0;
468 if (fontSize_.has_value() && fontSizeFloat_ && !NearEqual(fontSize_.value().Value(), fontSizeFloat_->Get())) {
469 flag |= PROPERTY_UPDATE_MEASURE;
470 }
471 if (adaptMinFontSize_.has_value() && adaptMinFontSizeFloat_ &&
472 !NearEqual(adaptMinFontSize_.value().Value(), adaptMinFontSizeFloat_->Get())) {
473 flag |= PROPERTY_UPDATE_MEASURE;
474 }
475 if (adaptMaxFontSize_.has_value() && adaptMaxFontSizeFloat_ &&
476 !NearEqual(adaptMaxFontSize_.value().Value(), adaptMaxFontSizeFloat_->Get())) {
477 flag |= PROPERTY_UPDATE_MEASURE;
478 }
479 if (fontWeight_.has_value() && fontWeightFloat_ &&
480 !NearEqual(static_cast<float>(fontWeight_.value()), fontWeightFloat_->Get())) {
481 flag |= PROPERTY_UPDATE_MEASURE;
482 }
483 if (textColor_.has_value() && animatableTextColor_ &&
484 textColor_->GetValue() != animatableTextColor_->Get().GetValue()) {
485 flag |= PROPERTY_UPDATE_MEASURE_SELF;
486 }
487 UpdateTextDecorationMeasureFlag(flag);
488 flag &= (PROPERTY_UPDATE_MEASURE | PROPERTY_UPDATE_MEASURE_SELF | PROPERTY_UPDATE_MEASURE_SELF_AND_PARENT);
489 return flag;
490 }
491
SetTextDecoration(const TextDecoration & value,const Color & color,const TextDecorationStyle & style)492 void TextFieldContentModifier::SetTextDecoration(const TextDecoration& value, const Color& color,
493 const TextDecorationStyle& style)
494 {
495 auto oldTextDecoration = textDecoration_.value_or(TextDecoration::NONE);
496 auto oldTextDecorationColor = textDecorationColor_.value_or(Color::BLACK);
497 auto oldTextDecorationStyle = textDecorationStyle_.value_or(TextDecorationStyle::SOLID);
498 if ((oldTextDecoration == value) && (oldTextDecorationColor == color) && (oldTextDecorationStyle == style)) {
499 return;
500 }
501
502 textDecorationAnimatable_ = (oldTextDecoration == TextDecoration::NONE && value == TextDecoration::UNDERLINE) ||
503 (oldTextDecoration == TextDecoration::UNDERLINE && value == TextDecoration::NONE);
504
505 textDecoration_ = value;
506 textDecorationColor_ = color;
507 textDecorationStyle_ = style;
508 CHECK_NULL_VOID(textDecorationColorAlpha_);
509
510 oldColorAlpha_ = textDecorationColorAlpha_->Get();
511 if (textDecoration_ == TextDecoration::NONE) {
512 textDecorationColorAlpha_->Set(0.0f);
513 } else {
514 textDecorationColorAlpha_->Set(static_cast<float>(textDecorationColor_.value().GetAlpha()));
515 }
516 }
517
ModifyDecorationInTextStyle(TextStyle & textStyle)518 void TextFieldContentModifier::ModifyDecorationInTextStyle(TextStyle& textStyle)
519 {
520 if (textDecoration_.has_value() && textDecorationColor_.has_value() && textDecorationColorAlpha_) {
521 if (textDecorationAnimatable_) {
522 uint8_t alpha = static_cast<uint8_t>(std::floor(textDecorationColorAlpha_->Get() + ROUND_VALUE));
523 if (alpha == 0) {
524 textStyle.SetTextDecoration(TextDecoration::NONE);
525 textStyle.SetTextDecorationColor(textDecorationColor_.value());
526 } else {
527 textStyle.SetTextDecoration(TextDecoration::UNDERLINE);
528 textStyle.SetTextDecorationColor(Color(textDecorationColor_.value()).ChangeAlpha(alpha));
529 }
530 } else {
531 textStyle.SetTextDecoration(textDecoration_.value());
532 textStyle.SetTextDecorationColor(textDecorationColor_.value());
533 }
534 }
535 if (textDecorationStyle_.has_value()) {
536 textStyle.SetTextDecorationStyle(textDecorationStyle_.value());
537 }
538 }
539
UpdateTextDecorationMeasureFlag(PropertyChangeFlag & flag)540 void TextFieldContentModifier::UpdateTextDecorationMeasureFlag(PropertyChangeFlag& flag)
541 {
542 if (textDecoration_.has_value() && textDecorationColor_.has_value() && textDecorationColorAlpha_) {
543 uint8_t alpha = static_cast<uint8_t>(std::floor(textDecorationColorAlpha_->Get() + ROUND_VALUE));
544 if (textDecoration_.value() == TextDecoration::UNDERLINE && alpha != textDecorationColor_.value().GetAlpha()) {
545 flag |= PROPERTY_UPDATE_MEASURE;
546 } else if (textDecoration_.value() == TextDecoration::NONE && alpha != 0.0) {
547 flag |= PROPERTY_UPDATE_MEASURE;
548 }
549 }
550 }
551 } // namespace OHOS::Ace::NG
552