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/pattern/text_field/text_field_pattern.h"
20 #include "core/pipeline_ng/pipeline_context.h"
21
22 namespace OHOS::Ace::NG {
23 namespace {
24 const FontWeight FONT_WEIGHT_CONVERT_MAP[] = {
25 FontWeight::W100,
26 FontWeight::W200,
27 FontWeight::W300,
28 FontWeight::W400,
29 FontWeight::W500,
30 FontWeight::W600,
31 FontWeight::W700,
32 FontWeight::W800,
33 FontWeight::W900,
34 FontWeight::W700,
35 FontWeight::W400,
36 FontWeight::W900,
37 FontWeight::W100,
38 FontWeight::W500,
39 FontWeight::W400,
40 };
41 constexpr float ROUND_VALUE = 0.5f;
42 constexpr Dimension DEFAULT_FADEOUT_VP = 16.0_vp;
43 constexpr double MAX_TEXTFADEOUT_PERCENT = 0.5;
44 constexpr double MIN_TEXTFADEOUT_DELTA = 1.0;
45
ConvertFontWeight(FontWeight fontWeight)46 inline FontWeight ConvertFontWeight(FontWeight fontWeight)
47 {
48 return FONT_WEIGHT_CONVERT_MAP[static_cast<int>(fontWeight)];
49 }
50 } // namespace
51
TextFieldContentModifier(const WeakPtr<OHOS::Ace::NG::Pattern> & pattern)52 TextFieldContentModifier::TextFieldContentModifier(const WeakPtr<OHOS::Ace::NG::Pattern>& pattern) : pattern_(pattern)
53 {
54 SetDefaultAnimatablePropertyValue();
55 SetDefaultPropertyValue();
56 }
57
onDraw(DrawingContext & context)58 void TextFieldContentModifier::onDraw(DrawingContext& context)
59 {
60 auto textFieldPattern = DynamicCast<TextFieldPattern>(pattern_.Upgrade());
61 CHECK_NULL_VOID(textFieldPattern);
62 auto paragraph = textFieldPattern->GetParagraph();
63 CHECK_NULL_VOID(paragraph);
64 if (textFieldPattern->IsInlineMode() || TextOverflow::ELLIPSIS == paragraph->GetParagraphStyle().textOverflow ||
65 !textFadeoutEnabled_) {
66 DoNormalDraw(context);
67 } else {
68 DoTextFadeoutDraw(context);
69 }
70 }
71
GetFrameRectClip(RSRect & clipRect,std::vector<RSPoint> & clipRadius)72 void TextFieldContentModifier::GetFrameRectClip(RSRect& clipRect, std::vector<RSPoint>& clipRadius)
73 {
74 auto textFieldPattern = DynamicCast<TextFieldPattern>(pattern_.Upgrade());
75 CHECK_NULL_VOID(textFieldPattern);
76 auto host = textFieldPattern->GetHost();
77 CHECK_NULL_VOID(host);
78 auto renderContext = host->GetRenderContext();
79 CHECK_NULL_VOID(renderContext);
80 auto textFrameRect = textFieldPattern->GetFrameRect();
81 clipRect = RSRect(0.0f, 0.0f, textFrameRect.Width(), textFrameRect.Height());
82 auto radius = renderContext->GetBorderRadius().value_or(BorderRadiusProperty());
83 auto radiusTopLeft = RSPoint(static_cast<float>(radius.radiusTopLeft.value_or(0.0_vp).ConvertToPx()),
84 static_cast<float>(radius.radiusTopLeft.value_or(0.0_vp).ConvertToPx()));
85 clipRadius.emplace_back(radiusTopLeft);
86 auto radiusTopRight = RSPoint(static_cast<float>(radius.radiusTopRight.value_or(0.0_vp).ConvertToPx()),
87 static_cast<float>(radius.radiusTopRight.value_or(0.0_vp).ConvertToPx()));
88 clipRadius.emplace_back(radiusTopRight);
89 auto radiusBottomRight = RSPoint(static_cast<float>(radius.radiusBottomRight.value_or(0.0_vp).ConvertToPx()),
90 static_cast<float>(radius.radiusBottomRight.value_or(0.0_vp).ConvertToPx()));
91 clipRadius.emplace_back(radiusBottomRight);
92 auto radiusBottomLeft = RSPoint(static_cast<float>(radius.radiusBottomLeft.value_or(0.0_vp).ConvertToPx()),
93 static_cast<float>(radius.radiusBottomLeft.value_or(0.0_vp).ConvertToPx()));
94 clipRadius.emplace_back(radiusBottomLeft);
95 }
96
SetDefaultAnimatablePropertyValue()97 void TextFieldContentModifier::SetDefaultAnimatablePropertyValue()
98 {
99 RefPtr<TextTheme> theme;
100 RefPtr<TextFieldLayoutProperty> textFieldLayoutProperty;
101 RefPtr<PipelineContext> pipelineContext;
102 auto textPartten = pattern_.Upgrade();
103 CHECK_NULL_VOID(textPartten);
104 auto frameNode = textPartten->GetHost();
105 CHECK_NULL_VOID(frameNode);
106 pipelineContext = frameNode->GetContext();
107 CHECK_NULL_VOID(pipelineContext);
108 theme = pipelineContext->GetTheme<TextTheme>();
109 textFieldLayoutProperty = frameNode->GetLayoutProperty<TextFieldLayoutProperty>();
110 auto textFieldPattern = DynamicCast<TextFieldPattern>(pattern_.Upgrade());
111 CHECK_NULL_VOID(textFieldPattern);
112 TextStyle textStyle;
113 if (!textFieldPattern->GetTextUtf16Value().empty()) {
114 textStyle = CreateTextStyleUsingTheme(
115 textFieldLayoutProperty->GetFontStyle(), textFieldLayoutProperty->GetTextLineStyle(), theme);
116 } else {
117 textStyle = CreateTextStyleUsingTheme(textFieldLayoutProperty->GetPlaceholderFontStyle(),
118 textFieldLayoutProperty->GetPlaceholderTextLineStyle(), theme);
119 }
120 SetDefaultFontSize(textStyle);
121 SetDefaultAdaptMinFontSize(textStyle);
122 SetDefaultAdaptMaxFontSize(textStyle);
123 SetDefaultFontWeight(textStyle);
124 SetDefaultTextColor(textStyle);
125 SetDefaultFontStyle(textStyle);
126 SetDefaultTextOverflow(textStyle);
127 SetDefaultTextDecoration(textStyle);
128 }
129
SetDefaultPropertyValue()130 void TextFieldContentModifier::SetDefaultPropertyValue()
131 {
132 RefPtr<TextFieldTheme> theme;
133 RefPtr<PipelineContext> pipelineContext;
134 auto textPattern = pattern_.Upgrade();
135 CHECK_NULL_VOID(textPattern);
136 auto frameNode = textPattern->GetHost();
137 CHECK_NULL_VOID(frameNode);
138 pipelineContext = frameNode->GetContext();
139 CHECK_NULL_VOID(pipelineContext);
140 theme = pipelineContext->GetTheme<TextFieldTheme>();
141 auto textFieldPattern = DynamicCast<TextFieldPattern>(pattern_.Upgrade());
142
143 textObscured_ = AceType::MakeRefPtr<PropertyBool>(textFieldPattern->GetTextObscured());
144 dragStatus_ = AceType::MakeRefPtr<PropertyBool>(false);
145 contentOffset_ = AceType::MakeRefPtr<PropertyOffsetF>(
146 OffsetF(textFieldPattern->GetTextRect().GetX(), textFieldPattern->GetTextRect().GetY()));
147 contentSize_ = AceType::MakeRefPtr<PropertySizeF>(SizeF());
148 textValue_ = AceType::MakeRefPtr<PropertyU16String>(u"");
149 errorTextValue_ = AceType::MakeRefPtr<PropertyU16String>(u"");
150 placeholderValue_ = AceType::MakeRefPtr<PropertyU16String>(u"");
151 textRectY_ = AceType::MakeRefPtr<PropertyFloat>(textFieldPattern->GetTextRect().GetY());
152 textRectX_ = AceType::MakeRefPtr<PropertyFloat>(textFieldPattern->GetTextRect().GetX());
153 textAlign_ = AceType::MakeRefPtr<PropertyInt>(static_cast<int32_t>(TextAlign::START));
154 showErrorState_ = AceType::MakeRefPtr<PropertyBool>(false);
155 fontFamilyString_ = AceType::MakeRefPtr<PropertyString>("");
156 fontReady_ = AceType::MakeRefPtr<PropertyBool>(false);
157 contentChange_ = AceType::MakeRefPtr<PropertyBool>(false);
158 AttachProperty(contentOffset_);
159 AttachProperty(contentSize_);
160 AttachProperty(textValue_);
161 AttachProperty(errorTextValue_);
162 AttachProperty(placeholderValue_);
163 AttachProperty(textRectY_);
164 AttachProperty(textObscured_);
165 AttachProperty(dragStatus_);
166 AttachProperty(textRectX_);
167 AttachProperty(textAlign_);
168 AttachProperty(showErrorState_);
169 AttachProperty(showUnderline_);
170 AttachProperty(fontFamilyString_);
171 AttachProperty(fontReady_);
172 AttachProperty(contentChange_);
173 }
174
SetDefaultFontSize(const TextStyle & textStyle)175 void TextFieldContentModifier::SetDefaultFontSize(const TextStyle& textStyle)
176 {
177 float fontSizeValue;
178 auto pipelineContext = PipelineContext::GetCurrentContextSafelyWithCheck();
179 if (pipelineContext) {
180 fontSizeValue = textStyle.GetFontSize().ConvertToPxDistribute(
181 textStyle.GetMinFontScale(), textStyle.GetMaxFontScale(), textStyle.IsAllowScale());
182 } else {
183 fontSizeValue = textStyle.GetFontSize().ConvertToPx();
184 }
185
186 fontSizeFloat_ = AceType::MakeRefPtr<AnimatablePropertyFloat>(fontSizeValue);
187 AttachProperty(fontSizeFloat_);
188 }
189
SetDefaultAdaptMinFontSize(const TextStyle & textStyle)190 void TextFieldContentModifier::SetDefaultAdaptMinFontSize(const TextStyle& textStyle)
191 {
192 float minFontSizeValue = textStyle.GetFontSize().Value();
193 auto pipelineContext = PipelineContext::GetCurrentContextSafelyWithCheck();
194 if (pipelineContext) {
195 minFontSizeValue = textStyle.GetAdaptMinFontSize().ConvertToPxDistribute(
196 textStyle.GetMinFontScale(), textStyle.GetMaxFontScale(), textStyle.IsAllowScale());
197 }
198 adaptMinFontSizeFloat_ = AceType::MakeRefPtr<AnimatablePropertyFloat>(minFontSizeValue);
199 AttachProperty(adaptMinFontSizeFloat_);
200 }
201
SetDefaultAdaptMaxFontSize(const TextStyle & textStyle)202 void TextFieldContentModifier::SetDefaultAdaptMaxFontSize(const TextStyle& textStyle)
203 {
204 float maxFontSizeValue = textStyle.GetFontSize().Value();
205 auto pipelineContext = PipelineContext::GetCurrentContextSafelyWithCheck();
206 if (pipelineContext) {
207 maxFontSizeValue = textStyle.GetAdaptMaxFontSize().ConvertToPxDistribute(
208 textStyle.GetMinFontScale(), textStyle.GetMaxFontScale(), textStyle.IsAllowScale());
209 }
210 adaptMaxFontSizeFloat_ = AceType::MakeRefPtr<AnimatablePropertyFloat>(maxFontSizeValue);
211 AttachProperty(adaptMaxFontSizeFloat_);
212 }
213
SetDefaultFontWeight(const TextStyle & textStyle)214 void TextFieldContentModifier::SetDefaultFontWeight(const TextStyle& textStyle)
215 {
216 fontWeightFloat_ =
217 AceType::MakeRefPtr<AnimatablePropertyFloat>(static_cast<float>(ConvertFontWeight(textStyle.GetFontWeight())));
218 AttachProperty(fontWeightFloat_);
219 }
220
SetDefaultTextColor(const TextStyle & textStyle)221 void TextFieldContentModifier::SetDefaultTextColor(const TextStyle& textStyle)
222 {
223 animatableTextColor_ = AceType::MakeRefPtr<AnimatablePropertyColor>(LinearColor(textStyle.GetTextColor()));
224 AttachProperty(animatableTextColor_);
225 }
226
SetDefaultFontStyle(const TextStyle & textStyle)227 void TextFieldContentModifier::SetDefaultFontStyle(const TextStyle& textStyle)
228 {
229 fontStyle_ = AceType::MakeRefPtr<PropertyInt>(static_cast<int32_t>(textStyle.GetFontStyle()));
230 AttachProperty(fontStyle_);
231 }
232
SetDefaultTextOverflow(const TextStyle & textStyle)233 void TextFieldContentModifier::SetDefaultTextOverflow(const TextStyle& textStyle)
234 {
235 textOverflow_ = AceType::MakeRefPtr<PropertyInt>(static_cast<int32_t>(textStyle.GetTextOverflow()));
236 AttachProperty(textOverflow_);
237 }
238
SetDefaultTextDecoration(const TextStyle & textStyle)239 void TextFieldContentModifier::SetDefaultTextDecoration(const TextStyle& textStyle)
240 {
241 textDecoration_ = textStyle.GetTextDecoration();
242 textDecorationStyle_ = textStyle.GetTextDecorationStyle();
243 textDecorationColor_ = textStyle.GetTextDecorationColor();
244 textDecorationColorAlpha_ = MakeRefPtr<AnimatablePropertyFloat>(
245 textDecoration_ == TextDecoration::NONE ? 0.0f : textDecorationColor_->GetAlpha());
246 AttachProperty(textDecorationColorAlpha_);
247 }
248
ModifyTextStyle(TextStyle & textStyle)249 void TextFieldContentModifier::ModifyTextStyle(TextStyle& textStyle)
250 {
251 if (fontSize_.has_value() && fontSizeFloat_) {
252 textStyle.SetFontSize(Dimension(fontSizeFloat_->Get(), DimensionUnit::PX));
253 }
254 if (textStyle.GetAdaptTextSize()) {
255 if (adaptMinFontSize_.has_value() && adaptMinFontSizeFloat_) {
256 textStyle.SetAdaptMinFontSize(Dimension(adaptMinFontSizeFloat_->Get(), DimensionUnit::PX));
257 }
258 if (adaptMaxFontSize_.has_value() && adaptMaxFontSizeFloat_) {
259 textStyle.SetAdaptMaxFontSize(Dimension(adaptMaxFontSizeFloat_->Get(), DimensionUnit::PX));
260 }
261 }
262 if (fontWeight_.has_value() && fontWeightFloat_) {
263 textStyle.SetFontWeight(static_cast<FontWeight>(std::floor(fontWeightFloat_->Get() + 0.5f)));
264 }
265 if (textColor_.has_value() && animatableTextColor_) {
266 textStyle.SetTextColor(Color(animatableTextColor_->Get().GetValue()));
267 }
268 ModifyDecorationInTextStyle(textStyle);
269 }
270
SetFontFamilies(const std::vector<std::string> & value)271 void TextFieldContentModifier::SetFontFamilies(const std::vector<std::string>& value)
272 {
273 CHECK_NULL_VOID(fontFamilyString_);
274 fontFamilyString_->Set(V2::ConvertFontFamily(value));
275 }
276
SetFontSize(const Dimension & value,const TextStyle & textStyle)277 void TextFieldContentModifier::SetFontSize(const Dimension& value, const TextStyle& textStyle)
278 {
279 auto valPx = value.ConvertToPxDistribute(textStyle.GetMinFontScale(),
280 textStyle.GetMaxFontScale(), textStyle.IsAllowScale());
281 fontSize_ = Dimension(valPx);
282 CHECK_NULL_VOID(fontSizeFloat_);
283 fontSizeFloat_->Set(valPx);
284 }
285
SetAdaptMinFontSize(const Dimension & value,const TextStyle & textStyle)286 void TextFieldContentModifier::SetAdaptMinFontSize(const Dimension& value, const TextStyle& textStyle)
287 {
288 auto valPx = value.ConvertToPxDistribute(textStyle.GetMinFontScale(),
289 textStyle.GetMaxFontScale(), textStyle.IsAllowScale());
290 adaptMinFontSize_ = Dimension(valPx);
291 CHECK_NULL_VOID(adaptMinFontSizeFloat_);
292 adaptMinFontSizeFloat_->Set(valPx);
293 }
294
SetAdaptMaxFontSize(const Dimension & value,const TextStyle & textStyle)295 void TextFieldContentModifier::SetAdaptMaxFontSize(const Dimension& value, const TextStyle& textStyle)
296 {
297 auto valPx = value.ConvertToPxDistribute(textStyle.GetMinFontScale(),
298 textStyle.GetMaxFontScale(), textStyle.IsAllowScale());
299 adaptMaxFontSize_ = Dimension(valPx);
300 CHECK_NULL_VOID(adaptMaxFontSizeFloat_);
301 adaptMaxFontSizeFloat_->Set(valPx);
302 }
303
SetFontWeight(const FontWeight & value)304 void TextFieldContentModifier::SetFontWeight(const FontWeight& value)
305 {
306 fontWeight_ = ConvertFontWeight(value);
307 CHECK_NULL_VOID(fontWeightFloat_);
308 fontWeightFloat_->Set(static_cast<int>(ConvertFontWeight(value)));
309 }
310
SetTextColor(const Color & value)311 void TextFieldContentModifier::SetTextColor(const Color& value)
312 {
313 textColor_ = value;
314 CHECK_NULL_VOID(animatableTextColor_);
315 animatableTextColor_->Set(LinearColor(value));
316 }
317
SetTextOverflow(const TextOverflow value)318 void TextFieldContentModifier::SetTextOverflow(const TextOverflow value)
319 {
320 if (textOverflow_->Get() != static_cast<int32_t>(value)) {
321 textOverflow_->Set(static_cast<int32_t>(value));
322 }
323 }
324
SetFontStyle(const OHOS::Ace::FontStyle & value)325 void TextFieldContentModifier::SetFontStyle(const OHOS::Ace::FontStyle& value)
326 {
327 if (fontStyle_->Get() != static_cast<int32_t>(value)) {
328 fontStyle_->Set(static_cast<int32_t>(value));
329 }
330 }
331
SetContentOffset(OffsetF & value)332 void TextFieldContentModifier::SetContentOffset(OffsetF& value)
333 {
334 if (contentOffset_) {
335 contentOffset_->Set(value);
336 }
337 }
338
GetContentOffsetY()339 float TextFieldContentModifier::GetContentOffsetY()
340 {
341 return contentOffset_->Get().GetY();
342 }
343
SetContentSize(SizeF & value)344 void TextFieldContentModifier::SetContentSize(SizeF& value)
345 {
346 if (contentSize_) {
347 contentSize_->Set(value);
348 }
349 }
350
SetTextValue(std::u16string & value)351 void TextFieldContentModifier::SetTextValue(std::u16string& value)
352 {
353 if (textValue_->Get() != value) {
354 textValue_->Set(value);
355 }
356 }
357
SetErrorTextValue(const std::u16string & value)358 void TextFieldContentModifier::SetErrorTextValue(const std::u16string& value)
359 {
360 if (errorTextValue_->Get() != value) {
361 errorTextValue_->Set(value);
362 }
363 }
364
SetPlaceholderValue(std::u16string && value)365 void TextFieldContentModifier::SetPlaceholderValue(std::u16string&& value)
366 {
367 if (placeholderValue_->Get() != value) {
368 placeholderValue_->Set(value);
369 }
370 }
371
SetTextRectY(const float value)372 void TextFieldContentModifier::SetTextRectY(const float value)
373 {
374 if (textRectY_->Get() != value) {
375 textRectY_->Set(value);
376 }
377 }
378
GetTextRectY()379 float TextFieldContentModifier::GetTextRectY()
380 {
381 return textRectY_->Get();
382 }
383
SetTextObscured(bool value)384 void TextFieldContentModifier::SetTextObscured(bool value)
385 {
386 if (textObscured_) {
387 textObscured_->Set(value);
388 }
389 }
390
ChangeDragStatus()391 void TextFieldContentModifier::ChangeDragStatus()
392 {
393 dragStatus_->Set(!dragStatus_->Get());
394 }
395
SetTextRectX(const float value)396 void TextFieldContentModifier::SetTextRectX(const float value)
397 {
398 if (textRectX_->Get() != value) {
399 textRectX_->Set(value);
400 }
401 }
402
GetTextRectX()403 float TextFieldContentModifier::GetTextRectX()
404 {
405 return textRectX_->Get();
406 }
407
SetTextAlign(const TextAlign value)408 void TextFieldContentModifier::SetTextAlign(const TextAlign value)
409 {
410 if (textAlign_->Get() != static_cast<int32_t>(value)) {
411 textAlign_->Set(static_cast<int32_t>(value));
412 }
413 }
414
SetShowErrorState(bool value)415 void TextFieldContentModifier::SetShowErrorState(bool value)
416 {
417 if (showErrorState_) {
418 showErrorState_->Set(value);
419 }
420 }
421
SetShowUnderlineState(bool value)422 void TextFieldContentModifier::SetShowUnderlineState(bool value)
423 {
424 if (showUnderline_) {
425 showUnderline_->Set(value);
426 }
427 }
428
SetFontReady(bool value)429 void TextFieldContentModifier::SetFontReady(bool value)
430 {
431 if (fontReady_) {
432 fontReady_->Set(value);
433 }
434 }
435
ContentChange()436 void TextFieldContentModifier::ContentChange()
437 {
438 CHECK_NULL_VOID(contentChange_);
439 contentChange_->Set(!contentChange_->Get());
440 }
441
NeedMeasureUpdate(PropertyChangeFlag & flag)442 bool TextFieldContentModifier::NeedMeasureUpdate(PropertyChangeFlag& flag)
443 {
444 flag = 0;
445 if (fontSize_.has_value() && fontSizeFloat_ && !NearEqual(fontSize_.value().Value(), fontSizeFloat_->Get())) {
446 flag |= PROPERTY_UPDATE_MEASURE;
447 }
448 if (adaptMinFontSize_.has_value() && adaptMinFontSizeFloat_ &&
449 !NearEqual(adaptMinFontSize_.value().Value(), adaptMinFontSizeFloat_->Get())) {
450 flag |= PROPERTY_UPDATE_MEASURE;
451 }
452 if (adaptMaxFontSize_.has_value() && adaptMaxFontSizeFloat_ &&
453 !NearEqual(adaptMaxFontSize_.value().Value(), adaptMaxFontSizeFloat_->Get())) {
454 flag |= PROPERTY_UPDATE_MEASURE;
455 }
456 if (fontWeight_.has_value() && fontWeightFloat_ &&
457 !NearEqual(static_cast<float>(fontWeight_.value()), fontWeightFloat_->Get())) {
458 flag |= PROPERTY_UPDATE_MEASURE;
459 }
460 if (textColor_.has_value() && animatableTextColor_ &&
461 textColor_->GetValue() != animatableTextColor_->Get().GetValue()) {
462 flag |= PROPERTY_UPDATE_MEASURE_SELF;
463 }
464 UpdateTextDecorationMeasureFlag(flag);
465 flag &= (PROPERTY_UPDATE_MEASURE | PROPERTY_UPDATE_MEASURE_SELF | PROPERTY_UPDATE_MEASURE_SELF_AND_PARENT);
466 return flag;
467 }
468
SetTextDecoration(const TextDecoration & value,const Color & color,const TextDecorationStyle & style)469 void TextFieldContentModifier::SetTextDecoration(const TextDecoration& value, const Color& color,
470 const TextDecorationStyle& style)
471 {
472 auto oldTextDecoration = textDecoration_.value_or(TextDecoration::NONE);
473 auto oldTextDecorationColor = textDecorationColor_.value_or(Color::BLACK);
474 auto oldTextDecorationStyle = textDecorationStyle_.value_or(TextDecorationStyle::SOLID);
475 if ((oldTextDecoration == value) && (oldTextDecorationColor == color) && (oldTextDecorationStyle == style)) {
476 return;
477 }
478
479 textDecorationAnimatable_ = (oldTextDecoration == TextDecoration::NONE && value == TextDecoration::UNDERLINE) ||
480 (oldTextDecoration == TextDecoration::UNDERLINE && value == TextDecoration::NONE);
481
482 textDecoration_ = value;
483 textDecorationColor_ = color;
484 textDecorationStyle_ = style;
485 CHECK_NULL_VOID(textDecorationColorAlpha_);
486
487 oldColorAlpha_ = textDecorationColorAlpha_->Get();
488 if (textDecoration_ == TextDecoration::NONE) {
489 textDecorationColorAlpha_->Set(0.0f);
490 } else {
491 textDecorationColorAlpha_->Set(static_cast<float>(textDecorationColor_.value().GetAlpha()));
492 }
493 }
494
ModifyDecorationInTextStyle(TextStyle & textStyle)495 void TextFieldContentModifier::ModifyDecorationInTextStyle(TextStyle& textStyle)
496 {
497 if (textDecoration_.has_value() && textDecorationColor_.has_value() && textDecorationColorAlpha_) {
498 if (textDecorationAnimatable_) {
499 uint8_t alpha = static_cast<uint8_t>(std::floor(textDecorationColorAlpha_->Get() + ROUND_VALUE));
500 if (alpha == 0) {
501 textStyle.SetTextDecoration(TextDecoration::NONE);
502 textStyle.SetTextDecorationColor(textDecorationColor_.value());
503 } else {
504 textStyle.SetTextDecoration(TextDecoration::UNDERLINE);
505 textStyle.SetTextDecorationColor(Color(textDecorationColor_.value()).ChangeAlpha(alpha));
506 }
507 } else {
508 textStyle.SetTextDecoration(textDecoration_.value());
509 textStyle.SetTextDecorationColor(textDecorationColor_.value());
510 }
511 }
512 if (textDecorationStyle_.has_value()) {
513 textStyle.SetTextDecorationStyle(textDecorationStyle_.value());
514 }
515 }
516
UpdateTextDecorationMeasureFlag(PropertyChangeFlag & flag)517 void TextFieldContentModifier::UpdateTextDecorationMeasureFlag(PropertyChangeFlag& flag)
518 {
519 if (textDecoration_.has_value() && textDecorationColor_.has_value() && textDecorationColorAlpha_) {
520 uint8_t alpha = static_cast<uint8_t>(std::floor(textDecorationColorAlpha_->Get() + ROUND_VALUE));
521 if (textDecoration_.value() == TextDecoration::UNDERLINE && alpha != textDecorationColor_.value().GetAlpha()) {
522 flag |= PROPERTY_UPDATE_MEASURE;
523 } else if (textDecoration_.value() == TextDecoration::NONE && alpha != 0.0) {
524 flag |= PROPERTY_UPDATE_MEASURE;
525 }
526 }
527 }
528
SetTextFadeoutEnabled(bool enabled)529 void TextFieldContentModifier::SetTextFadeoutEnabled(bool enabled)
530 {
531 textFadeoutEnabled_ = enabled;
532 }
533
DoNormalDraw(DrawingContext & context)534 void TextFieldContentModifier::DoNormalDraw(DrawingContext& context)
535 {
536 auto& canvas = context.canvas;
537 auto textFieldPattern = DynamicCast<TextFieldPattern>(pattern_.Upgrade());
538 CHECK_NULL_VOID(textFieldPattern);
539 auto paragraph = textFieldPattern->GetParagraph();
540 CHECK_NULL_VOID(paragraph);
541 CHECK_NULL_VOID(contentOffset_);
542 auto contentOffset = contentOffset_->Get();
543 auto contentRect = textFieldPattern->GetContentRect();
544 auto clipRectHeight = 0.0f;
545 auto frameNode = textFieldPattern->GetHost();
546 CHECK_NULL_VOID(frameNode);
547 auto layoutProperty = frameNode->GetLayoutProperty<TextFieldLayoutProperty>();
548 CHECK_NULL_VOID(layoutProperty);
549 clipRectHeight = contentRect.GetY() + contentRect.Height();
550 canvas.Save();
551 RSRect clipInnerRect = RSRect(contentRect.GetX(), contentRect.GetY(),
552 contentRect.Width() + contentRect.GetX() + textFieldPattern->GetInlinePadding(), clipRectHeight);
553 canvas.ClipRect(clipInnerRect, RSClipOp::INTERSECT);
554 if (paragraph) {
555 auto textField = textFieldPattern->IsTextArea() ? "TextArea" : "TextInput";
556 ACE_LAYOUT_SCOPED_TRACE("[%s][id:%d] [Rect:%s]", textField, frameNode->GetId(), contentRect.ToString().c_str());
557 if (Container::GreatOrEqualAPIVersion(PlatformVersion::VERSION_ELEVEN)) {
558 canvas.Save();
559 RSRect clipRect;
560 std::vector<RSPoint> clipRadius;
561 GetFrameRectClip(clipRect, clipRadius);
562 canvas.ClipRoundRect(clipRect, clipRadius, true);
563 paragraph->Paint(canvas, textFieldPattern->GetTextRect().GetX(),
564 textFieldPattern->IsTextArea() ? textFieldPattern->GetTextRect().GetY() : contentOffset.GetY());
565 canvas.Restore();
566 } else {
567 paragraph->Paint(canvas, textFieldPattern->GetTextRect().GetX(),
568 textFieldPattern->IsTextArea() ? textFieldPattern->GetTextRect().GetY() : contentOffset.GetY());
569 }
570 }
571 canvas.Restore();
572 }
573
DoTextFadeoutDraw(DrawingContext & context)574 void TextFieldContentModifier::DoTextFadeoutDraw(DrawingContext& context)
575 {
576 auto& canvas = context.canvas;
577 auto textFieldPattern = DynamicCast<TextFieldPattern>(pattern_.Upgrade());
578 CHECK_NULL_VOID(textFieldPattern);
579 auto paragraph = textFieldPattern->GetParagraph();
580 CHECK_NULL_VOID(paragraph);
581 auto contentRect = textFieldPattern->GetContentRect();
582 auto clipRectHeight = contentRect.GetY() + contentRect.Height();
583 RSRect clipInnerRect = RSRect(contentRect.GetX(), contentRect.GetY(),
584 contentRect.Width() + contentRect.GetX() + textFieldPattern->GetInlinePadding(), clipRectHeight);
585 RSSaveLayerOps slo(&clipInnerRect, nullptr);
586 canvas.SaveLayer(slo);
587
588 DrawTextFadeout(context);
589
590 canvas.Restore();
591 }
592
DrawTextFadeout(DrawingContext & context)593 void TextFieldContentModifier::DrawTextFadeout(DrawingContext& context)
594 {
595 auto& canvas = context.canvas;
596 auto textFieldPattern = DynamicCast<TextFieldPattern>(pattern_.Upgrade());
597 CHECK_NULL_VOID(textFieldPattern);
598 auto frameNode = textFieldPattern->GetHost();
599 CHECK_NULL_VOID(frameNode);
600 auto paragraph = textFieldPattern->GetParagraph();
601 CHECK_NULL_VOID(paragraph);
602 auto contentOffset = contentOffset_->Get();
603 auto contentRect = frameNode->GetGeometryNode()->GetContentRect();
604 auto contentRectX = contentRect.GetX();
605 auto textRect = textFieldPattern->GetTextRect();
606 auto textRectX = textRect.GetX();
607 auto leftFadeOn = false;
608 auto rigthFadeOn = false;
609 auto textFadeoutWidth = DEFAULT_FADEOUT_VP.ConvertToPx();
610 auto gradientPercent = std::min(MAX_TEXTFADEOUT_PERCENT,
611 textFadeoutWidth / std::max(static_cast<double>(contentRect.Width()), textFadeoutWidth));
612 auto textFadeRect = RectF(contentRect.GetX(), contentOffset.GetY(), contentRect.Width(),
613 std::max(textRect.Height(), contentRect.Height()));
614 AdjustTextFadeRect(textFadeRect);
615
616 RSRect clipRect;
617 std::vector<RSPoint> clipRadius;
618 GetFrameRectClip(clipRect, clipRadius);
619 canvas.ClipRoundRect(clipRect, clipRadius, true);
620
621 canvas.Save();
622 RSRect clipTextInnerRect = RSRect(textFadeRect.GetX(), textFadeRect.GetY(),
623 textFadeRect.Width() + textFadeRect.GetX(), textFadeRect.GetY() + textFadeRect.Height());
624 canvas.ClipRect(clipTextInnerRect, RSClipOp::INTERSECT);
625 paragraph->Paint(canvas, textRectX, contentOffset.GetY());
626 canvas.Restore();
627
628 auto textWidth = paragraph->GetTextWidth();
629 auto textIndent = std::max(textFieldPattern->GetTextParagraphIndent(), 0.0f);
630 if (GreatNotEqual(textWidth + textIndent, contentRect.Width())) {
631 leftFadeOn = LessNotEqual(textRectX + MIN_TEXTFADEOUT_DELTA, contentRectX);
632 rigthFadeOn = GreatNotEqual((textRectX + textWidth + textIndent - MIN_TEXTFADEOUT_DELTA), contentRect.Right());
633 }
634 UpdateTextFadeout(canvas, textFadeRect, gradientPercent, leftFadeOn, rigthFadeOn);
635 }
636
AdjustTextFadeRect(RectF & textFadeRect)637 void TextFieldContentModifier::AdjustTextFadeRect(RectF& textFadeRect)
638 {
639 const float TEXT_FADE_ADJUST_PX = 1;
640
641 textFadeRect -= OffsetF(TEXT_FADE_ADJUST_PX, TEXT_FADE_ADJUST_PX);
642 textFadeRect += SizeF((TEXT_FADE_ADJUST_PX + TEXT_FADE_ADJUST_PX), (TEXT_FADE_ADJUST_PX + TEXT_FADE_ADJUST_PX));
643 }
644
UpdateTextFadeout(RSCanvas & canvas,const RectF & textRect,float gradientPercent,bool leftFade,bool rightFade)645 void TextFieldContentModifier::UpdateTextFadeout(
646 RSCanvas& canvas, const RectF& textRect, float gradientPercent, bool leftFade, bool rightFade)
647 {
648 RSBrush brush;
649 std::vector<RSPoint> points = { RSPoint(textRect.Left(), textRect.Top()),
650 RSPoint(textRect.Right(), textRect.Top()) };
651 std::vector<RSColorQuad> colors = { Color::TRANSPARENT.GetValue(), Color::WHITE.GetValue(), Color::WHITE.GetValue(),
652 Color::TRANSPARENT.GetValue() };
653 float leftEndPercent = leftFade ? gradientPercent : 0;
654 float rightStartPercent = 1.0f;
655 if (rightFade && gradientPercent > 0 && gradientPercent < 1.0f) {
656 rightStartPercent = 1.0f - gradientPercent;
657 }
658 std::vector<RSScalar> pos = { 0.0f, leftEndPercent, rightStartPercent, 1.0f };
659 brush.SetShaderEffect(
660 RSShaderEffect::CreateLinearGradient(points.at(0), points.at(1), colors, pos, RSTileMode::CLAMP));
661 brush.SetBlendMode(RSBlendMode::DST_IN);
662 RSRect textFadeoutRect = RSRect(textRect.Left(), textRect.Top(), textRect.Right(), textRect.Bottom());
663 canvas.AttachBrush(brush);
664 canvas.DrawRect(textFadeoutRect);
665 canvas.DetachBrush();
666 }
667 } // namespace OHOS::Ace::NG
668