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