• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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_overlay_modifier.h"
17 
18 #include "base/utils/utils.h"
19 #include "core/components_ng/pattern/text_field/text_field_model.h"
20 #include "core/components_ng/pattern/text_field/text_field_pattern.h"
21 #include "core/components_ng/render/drawing_prop_convertor.h"
22 
23 namespace OHOS::Ace::NG {
24 namespace {
25 constexpr int32_t LAND_DURATION = 100;
26 const RefPtr<CubicCurve> LAND_CURVE = AceType::MakeRefPtr<CubicCurve>(0.2, 0, 0.2, 1.0f);
27 constexpr int32_t HALF_RECT = 2;
28 } // namespace
29 
TextFieldOverlayModifier(const WeakPtr<OHOS::Ace::NG::Pattern> & pattern,WeakPtr<ScrollEdgeEffect> && edgeEffect)30 TextFieldOverlayModifier::TextFieldOverlayModifier(
31     const WeakPtr<OHOS::Ace::NG::Pattern>& pattern, WeakPtr<ScrollEdgeEffect>&& edgeEffect)
32     : pattern_(pattern), edgeEffect_(edgeEffect)
33 {
34     auto textFieldPattern = DynamicCast<TextFieldPattern>(pattern_.Upgrade());
35     CHECK_NULL_VOID(textFieldPattern);
36     auto theme = textFieldPattern->GetTheme();
37     CHECK_NULL_VOID(theme);
38     cursorColor_ = AceType::MakeRefPtr<AnimatablePropertyColor>(LinearColor(Color()));
39     cursorWidth_ =
40         AceType::MakeRefPtr<AnimatablePropertyFloat>(static_cast<float>(theme->GetCursorWidth().ConvertToPx()));
41     selectedColor_ = AceType::MakeRefPtr<AnimatablePropertyColor>(LinearColor(Color()));
42     cursorVisible_ = AceType::MakeRefPtr<PropertyBool>(false);
43     showSelect_ = AceType::MakeRefPtr<PropertyBool>(false);
44     contentSize_ = AceType::MakeRefPtr<PropertySizeF>(SizeF());
45     contentOffset_ = AceType::MakeRefPtr<PropertyOffsetF>(OffsetF());
46     cursorOffset_ = AceType::MakeRefPtr<PropertyOffsetF>(textFieldPattern->GetCaretOffset());
47     floatingCursorOffset_ = AceType::MakeRefPtr<AnimatablePropertyOffsetF>(textFieldPattern->GetCaretOffset());
48     floatingCursorVisible_ = AceType::MakeRefPtr<PropertyBool>(false);
49     showOriginCursor_ = AceType::MakeRefPtr<PropertyBool>(false);
50     frameSize_ = AceType::MakeRefPtr<PropertySizeF>(SizeF());
51     currentOffset_ = AceType::MakeRefPtr<PropertyFloat>(0.0f);
52     underlineWidth_ = AceType::MakeRefPtr<PropertyFloat>(0.0f);
53     underlineColor_ = AceType::MakeRefPtr<PropertyColor>(Color());
54     changeSelectedRects_ = AceType::MakeRefPtr<PropertyBool>(false);
55     firstHandleOffset_ = AceType::MakeRefPtr<PropertyOffsetF>(OffsetF());
56     secondHandleOffset_ = AceType::MakeRefPtr<PropertyOffsetF>(OffsetF());
57     showPreviewText_ = AceType::MakeRefPtr<PropertyBool>(false);
58     changePreviewTextRects_ = AceType::MakeRefPtr<PropertyBool>(false);
59     previewTextDecorationColor_ = AceType::MakeRefPtr<PropertyColor>(Color());
60     previewTextStyle_ = PreviewTextStyle::NORMAL;
61     contentChange_ = AceType::MakeRefPtr<PropertyBool>(false);
62     hoverColor_ = AceType::MakeRefPtr<PropertyInt>(0);
63     ModifierAttachProperty();
64 }
65 
ModifierAttachProperty()66 void TextFieldOverlayModifier::ModifierAttachProperty()
67 {
68     AttachProperty(cursorColor_);
69     AttachProperty(cursorWidth_);
70     AttachProperty(selectedColor_);
71     AttachProperty(cursorVisible_);
72     AttachProperty(showSelect_);
73     AttachProperty(contentSize_);
74     AttachProperty(contentOffset_);
75     AttachProperty(cursorOffset_);
76     AttachProperty(floatingCursorOffset_);
77     AttachProperty(floatingCursorVisible_);
78     AttachProperty(showOriginCursor_);
79     AttachProperty(frameSize_);
80     AttachProperty(currentOffset_);
81     AttachProperty(underlineWidth_);
82     AttachProperty(underlineColor_);
83     AttachProperty(changeSelectedRects_);
84     AttachProperty(firstHandleOffset_);
85     AttachProperty(secondHandleOffset_);
86     AttachProperty(showPreviewText_);
87     AttachProperty(changePreviewTextRects_);
88     AttachProperty(previewTextDecorationColor_);
89     AttachProperty(contentChange_);
90 }
91 
ContentChange()92 void TextFieldOverlayModifier::ContentChange()
93 {
94     CHECK_NULL_VOID(contentChange_);
95     contentChange_->Set(!contentChange_->Get());
96 }
97 
SetFirstHandleOffset(const OffsetF & offset)98 void TextFieldOverlayModifier::SetFirstHandleOffset(const OffsetF& offset)
99 {
100     firstHandleOffset_->Set(offset);
101 }
102 
SetSecondHandleOffset(const OffsetF & offset)103 void TextFieldOverlayModifier::SetSecondHandleOffset(const OffsetF& offset)
104 {
105     secondHandleOffset_->Set(offset);
106 }
107 
onDraw(DrawingContext & context)108 void TextFieldOverlayModifier::onDraw(DrawingContext& context)
109 {
110     auto& canvas = context.canvas;
111     if (Container::GreatOrEqualAPIVersion(PlatformVersion::VERSION_ELEVEN)) {
112         canvas.Save();
113         RSRect clipRect;
114         std::vector<RSPoint> clipRadius;
115         GetFrameRectClip(clipRect, clipRadius);
116         canvas.ClipRoundRect(clipRect, clipRadius, true);
117     }
118     PaintCursor(context);
119     PaintFloatingCursor(context);
120     PaintSelection(context);
121     if (Container::GreatOrEqualAPIVersion(PlatformVersion::VERSION_ELEVEN)) {
122         canvas.Restore();
123     }
124     PaintScrollBar(context);
125     PaintEdgeEffect(frameSize_->Get(), context.canvas);
126     PaintUnderline(context.canvas);
127     PaintPreviewTextDecoration(context);
128     if (Container::GreatOrEqualAPITargetVersion(PlatformVersion::VERSION_EIGHTEEN)) {
129         RSBrush brush;
130         brush.SetAntiAlias(true);
131         brush.SetColor(hoverColor_->Get());
132         canvas.AttachBrush(brush);
133         for (const auto& hoverRects : hoverRects_) {
134             auto rect = hoverRects.GetRect();
135             RSRect rsRect(rect.Left(), rect.Top(), rect.Right(), rect.Bottom());
136             canvas.DrawRoundRect(RSRoundRect(rsRect, rect.Width() / HALF_RECT, rect.Height() / HALF_RECT));
137         }
138         canvas.DetachBrush();
139         canvas.Restore();
140     }
141 }
142 
SetHoverColorAndRects(const std::vector<RoundRect> & hoverRects,uint32_t hoverColor)143 void TextFieldOverlayModifier::SetHoverColorAndRects(
144     const std::vector<RoundRect>& hoverRects, uint32_t hoverColor)
145 {
146     CHECK_NULL_VOID(hoverColor);
147     hoverRects_ = hoverRects;
148     hoverColor_->Set(static_cast<int32_t>(hoverColor));
149 }
150 
ClearHoverColorAndRects()151 void TextFieldOverlayModifier::ClearHoverColorAndRects()
152 {
153     hoverRects_.clear();
154 }
155 
GetFrameRectClip(RSRect & clipRect,std::vector<RSPoint> & clipRadius)156 void TextFieldOverlayModifier::GetFrameRectClip(RSRect& clipRect, std::vector<RSPoint>& clipRadius)
157 {
158     auto textFieldPattern = DynamicCast<TextFieldPattern>(pattern_.Upgrade());
159     CHECK_NULL_VOID(textFieldPattern);
160     auto host = textFieldPattern->GetHost();
161     CHECK_NULL_VOID(host);
162     auto renderContext = host->GetRenderContext();
163     CHECK_NULL_VOID(renderContext);
164     auto textFrameRect = textFieldPattern->GetFrameRect();
165     clipRect = RSRect(0.0f, 0.0f, textFrameRect.Width(), textFrameRect.Height());
166     auto radius = renderContext->GetBorderRadius().value_or(BorderRadiusProperty());
167     auto radiusTopLeft = RSPoint(static_cast<float>(radius.radiusTopLeft.value_or(0.0_vp).ConvertToPx()),
168         static_cast<float>(radius.radiusTopLeft.value_or(0.0_vp).ConvertToPx()));
169     clipRadius.emplace_back(radiusTopLeft);
170     auto radiusTopRight = RSPoint(static_cast<float>(radius.radiusTopRight.value_or(0.0_vp).ConvertToPx()),
171         static_cast<float>(radius.radiusTopRight.value_or(0.0_vp).ConvertToPx()));
172     clipRadius.emplace_back(radiusTopRight);
173     auto radiusBottomRight = RSPoint(static_cast<float>(radius.radiusBottomRight.value_or(0.0_vp).ConvertToPx()),
174         static_cast<float>(radius.radiusBottomRight.value_or(0.0_vp).ConvertToPx()));
175     clipRadius.emplace_back(radiusBottomRight);
176     auto radiusBottomLeft = RSPoint(static_cast<float>(radius.radiusBottomLeft.value_or(0.0_vp).ConvertToPx()),
177         static_cast<float>(radius.radiusBottomLeft.value_or(0.0_vp).ConvertToPx()));
178     clipRadius.emplace_back(radiusBottomLeft);
179 }
180 
PaintUnderline(RSCanvas & canvas) const181 void TextFieldOverlayModifier::PaintUnderline(RSCanvas& canvas) const
182 {
183     auto textFieldPattern = DynamicCast<TextFieldPattern>(pattern_.Upgrade());
184     CHECK_NULL_VOID(textFieldPattern);
185     auto layoutProperty = textFieldPattern->GetLayoutProperty<TextFieldLayoutProperty>();
186     CHECK_NULL_VOID(layoutProperty);
187     if (!(layoutProperty->GetShowUnderlineValue(false) && textFieldPattern->IsUnspecifiedOrTextType())) {
188         return;
189     }
190     if (textFieldPattern->IsNormalInlineState() && textFieldPattern->HasFocus()) {
191         return;
192     }
193     auto contentRect = textFieldPattern->GetContentRect();
194     auto textFrameRect = textFieldPattern->GetFrameRect();
195     auto responseArea = textFieldPattern->GetResponseArea();
196     auto responseAreaWidth = responseArea ? responseArea->GetAreaRect().Width() : 0.0f;
197     auto clearNodeResponseArea = textFieldPattern->GetCleanNodeResponseArea();
198     responseAreaWidth += clearNodeResponseArea ? clearNodeResponseArea->GetAreaRect().Width() : 0.0f;
199     auto hasResponseArea = GreatNotEqual(responseAreaWidth, 0.0f);
200     auto isRTL = layoutProperty->GetNonAutoLayoutDirection() == TextDirection::RTL;
201     Point leftPoint, rightPoint;
202     if (isRTL) {
203         leftPoint.SetX(hasResponseArea ? 0.0 : contentRect.Left());
204         rightPoint.SetX(contentRect.Right());
205     } else {
206         leftPoint.SetX(contentRect.Left());
207         rightPoint.SetX(hasResponseArea ? textFrameRect.Width() : contentRect.Right());
208     }
209 
210     leftPoint.SetY(textFrameRect.Height());
211     rightPoint.SetY(textFrameRect.Height());
212 
213     RSPen pen;
214     pen.SetColor(ToRSColor(underlineColor_->Get()));
215     pen.SetWidth(underlineWidth_->Get());
216     pen.SetAntiAlias(true);
217     canvas.AttachPen(pen);
218     canvas.DrawLine(ToRSPoint(PointF(leftPoint.GetX(), leftPoint.GetY())),
219         ToRSPoint(PointF(rightPoint.GetX(), rightPoint.GetY())));
220     canvas.DetachPen();
221 }
222 
PaintSelection(DrawingContext & context) const223 void TextFieldOverlayModifier::PaintSelection(DrawingContext& context) const
224 {
225     if (!showSelect_->Get() && !needPaintSelect_) {
226         return;
227     }
228     auto& canvas = context.canvas;
229     canvas.Save();
230     auto textFieldPattern = DynamicCast<TextFieldPattern>(pattern_.Upgrade());
231     CHECK_NULL_VOID(textFieldPattern);
232     auto host = textFieldPattern->GetHost();
233     CHECK_NULL_VOID(host);
234     auto pipelineContext = host->GetContext();
235     CHECK_NULL_VOID(pipelineContext);
236     auto themeManager = pipelineContext->GetThemeManager();
237     CHECK_NULL_VOID(themeManager);
238     auto theme = themeManager->GetTheme<TextFieldTheme>();
239     RSBrush brush;
240     brush.SetAntiAlias(true);
241     brush.SetColor(ToRSColor(selectedColor_->Get()));
242     canvas.AttachBrush(brush);
243     auto paintOffset = textFieldPattern->GetContentRect().GetOffset();
244     auto textBoxes = textFieldPattern->GetTextBoxesForSelect();
245     auto textRect = textFieldPattern->GetTextRect();
246     bool isTextArea = textFieldPattern->IsTextArea();
247     float clipRectHeight = 0.0f;
248     clipRectHeight = paintOffset.GetY() + contentSize_->Get().Height();
249     RSRect clipInnerRect;
250     auto defaultStyle = !textFieldPattern->IsNormalInlineState() || isTextArea;
251     if (defaultStyle) {
252         clipInnerRect = RSRect(paintOffset.GetX(), paintOffset.GetY(),
253             paintOffset.GetX() + contentSize_->Get().Width() + textFieldPattern->GetInlinePadding(), clipRectHeight);
254         canvas.ClipRect(clipInnerRect, RSClipOp::INTERSECT);
255     } else {
256         clipInnerRect = RSRect(paintOffset.GetX(), 0.0f, paintOffset.GetX() + contentSize_->Get().Width(),
257             textFieldPattern->GetFrameRect().Height());
258         canvas.ClipRect(clipInnerRect, RSClipOp::INTERSECT);
259     }
260     // for default style, selection height is equal to the content height
261     for (const auto& textBox : textBoxes) {
262         canvas.DrawRect(RSRect(textBox.Left() + (isTextArea ? contentOffset_->Get().GetX() : textRect.GetX()),
263             defaultStyle
264                 ? (textBox.Top() + (isTextArea ? textRect.GetY() : contentOffset_->Get().GetY()))
265                 : 0.0f,
266             textBox.Right() + (isTextArea ? contentOffset_->Get().GetX() : textRect.GetX()),
267             defaultStyle
268                 ? (textBox.Bottom() + (isTextArea ? textRect.GetY() : contentOffset_->Get().GetY()))
269                          : textFieldPattern->GetFrameRect().Height()));
270     }
271     canvas.DetachBrush();
272     canvas.Restore();
273 }
274 
PaintCursor(DrawingContext & context) const275 void TextFieldOverlayModifier::PaintCursor(DrawingContext& context) const
276 {
277     float cursorWidth = static_cast<float>(cursorWidth_->Get());
278     if (NearZero(cursorWidth)) {
279         return; // will not draw cursor
280     }
281 
282     auto& canvas = context.canvas;
283     auto textFieldPattern = DynamicCast<TextFieldPattern>(pattern_.Upgrade());
284     CHECK_NULL_VOID(textFieldPattern);
285     auto magnifierController = textFieldPattern->GetMagnifierController();
286     CHECK_NULL_VOID(magnifierController);
287 
288     auto showOriginCursor = floatingCursorVisible_->Get() && showOriginCursor_->Get();
289     auto cursorVisible = floatingCursorVisible_->Get() ? showOriginCursor_->Get() : cursorVisible_->Get();
290     if (!cursorVisible || textFieldPattern->IsSelected()) {
291         return;
292     }
293     canvas.Save();
294 
295     RSPen pen;
296     pen.SetAntiAlias(true);
297     pen.SetWidth(cursorWidth);
298     pen.SetCapStyle(RSPen::CapStyle::ROUND_CAP);
299 
300     if (showOriginCursor) {
301         pen.SetColor(ToRSColor(LinearColor(textFieldPattern->GetOriginCursorColor())));
302     } else {
303         pen.SetColor(ToRSColor(cursorColor_->Get()));
304     }
305     canvas.AttachPen(pen);
306     auto paintOffset = contentOffset_->Get();
307     ACE_LAYOUT_SCOPED_TRACE("PaintCursor[offset:%f, %f]", paintOffset.GetX(), paintOffset.GetY());
308     float clipRectHeight = 0.0f;
309     clipRectHeight = paintOffset.GetY() + contentSize_->Get().Height();
310     RSRect clipInnerRect(paintOffset.GetX(), paintOffset.GetY(),
311         // add extra clip space for cases such as auto width
312         paintOffset.GetX() + contentSize_->Get().Width() +
313             (LessOrEqual(contentSize_->Get().Width(), 0.0) ? cursorWidth_->Get() : 0.0f),
314         clipRectHeight);
315     canvas.ClipRect(clipInnerRect, RSClipOp::INTERSECT);
316 
317     auto caretRect = textFieldPattern->GetCaretRect();
318     float midPosX = caretRect.GetX() + cursorWidth / 2;
319     float startPosY = caretRect.GetY();
320     float endPosY = caretRect.GetY() + caretRect.Height();
321     float roundCapRadius = static_cast<float>(cursorWidth_->Get()) / 2;
322     canvas.DrawLine(RSPoint(midPosX, startPosY + roundCapRadius),
323         RSPoint(midPosX, endPosY - roundCapRadius));
324     canvas.DetachPen();
325     canvas.Restore();
326 }
327 
PaintFloatingCursor(DrawingContext & context) const328 void TextFieldOverlayModifier::PaintFloatingCursor(DrawingContext& context) const
329 {
330     float cursorWidth = static_cast<float>(cursorWidth_->Get());
331     if (NearZero(cursorWidth)) {
332         return; // will not draw cursor
333     }
334 
335     auto& canvas = context.canvas;
336     auto textFieldPattern = DynamicCast<TextFieldPattern>(pattern_.Upgrade());
337     CHECK_NULL_VOID(textFieldPattern);
338     if (!floatingCursorVisible_->Get() || textFieldPattern->IsSelected()) {
339         return;
340     }
341     canvas.Save();
342 
343     RSPen pen;
344     pen.SetAntiAlias(true);
345     pen.SetWidth(cursorWidth);
346     pen.SetCapStyle(RSPen::CapStyle::ROUND_CAP);
347     pen.SetColor(ToRSColor(cursorColor_->Get()));
348     canvas.AttachPen(pen);
349     auto paintOffset = contentOffset_->Get();
350     ACE_LAYOUT_SCOPED_TRACE("PaintCursor[offset:%f, %f]", paintOffset.GetX(), paintOffset.GetY());
351     float clipRectHeight = 0.0f;
352     clipRectHeight = paintOffset.GetY() + contentSize_->Get().Height();
353     RSRect clipInnerRect(paintOffset.GetX(), paintOffset.GetY(),
354         // add extra clip space for cases such as auto width
355         paintOffset.GetX() + contentSize_->Get().Width() +
356             (LessOrEqual(contentSize_->Get().Width(), 0.0) ? cursorWidth_->Get() : 0.0f),
357         clipRectHeight);
358     canvas.ClipRect(clipInnerRect, RSClipOp::INTERSECT);
359 
360     auto caretRect = textFieldPattern->GetFloatingCaretRect();
361     auto floatingOffset = floatingCursorOffset_->Get();
362     float midPosX = floatingOffset.GetX() + cursorWidth / 2;
363     float startPosY = floatingOffset.GetY();
364     float endPosY = floatingOffset.GetY() + caretRect.Height();
365     float roundCapRadius = static_cast<float>(cursorWidth_->Get()) / 2;
366     canvas.DrawLine(RSPoint(midPosX, startPosY + roundCapRadius),
367         RSPoint(midPosX, endPosY - roundCapRadius));
368     canvas.DetachPen();
369     canvas.Restore();
370 }
371 
StartFloatingCaretLand(const OffsetF & originCaretOffset)372 void TextFieldOverlayModifier::StartFloatingCaretLand(const OffsetF& originCaretOffset)
373 {
374     AnimationOption option = AnimationOption();
375     option.SetDuration(LAND_DURATION);
376     option.SetCurve(LAND_CURVE);
377     caretLanding_ = true;
378     AnimationUtils::Animate(
379         option,
380         [weak = WeakClaim(this), originCaretOffset]() {
381             auto modifier = weak.Upgrade();
382             CHECK_NULL_VOID(modifier);
383             modifier->SetFloatingCursorOffset(originCaretOffset);
384         },
385         [weak = WeakClaim(this), pattern = pattern_]() {
386             auto textField = DynamicCast<TextFieldPattern>(pattern.Upgrade());
387             CHECK_NULL_VOID(textField);
388             auto modifier = weak.Upgrade();
389             CHECK_NULL_VOID(modifier);
390             modifier->SetFloatCaretLanding(false);
391             textField->ResetFloatingCursorState();
392             auto textFieldHost = textField->GetHost();
393             CHECK_NULL_VOID(textFieldHost);
394             textFieldHost->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
395         });
396 }
397 
PaintEdgeEffect(const SizeF & frameSize,RSCanvas & canvas)398 void TextFieldOverlayModifier::PaintEdgeEffect(const SizeF& frameSize, RSCanvas& canvas)
399 {
400     auto edgeEffect = edgeEffect_.Upgrade();
401     CHECK_NULL_VOID(edgeEffect);
402     edgeEffect->Paint(canvas, frameSize, { 0.0f, 0.0f });
403 }
404 
PaintScrollBar(DrawingContext & context)405 void TextFieldOverlayModifier::PaintScrollBar(DrawingContext& context)
406 {
407     auto textFieldPattern = DynamicCast<TextFieldPattern>(pattern_.Upgrade());
408     CHECK_NULL_VOID(textFieldPattern);
409     if (textFieldPattern->GetScrollBarVisible() && textFieldPattern->IsTextArea()) {
410         ScrollBarOverlayModifier::onDraw(context);
411     }
412 }
413 
PaintPreviewTextDecoration(DrawingContext & context) const414 void TextFieldOverlayModifier::PaintPreviewTextDecoration(DrawingContext& context) const
415 {
416     if (previewTextStyle_ != PreviewTextStyle::UNDERLINE ||
417         (!showPreviewText_->Get() && !needPaintPreviewText)) {
418         return;
419     }
420 
421     auto& canvas = context.canvas;
422     canvas.Save();
423     auto textFieldPattern = DynamicCast<TextFieldPattern>(pattern_.Upgrade());
424     CHECK_NULL_VOID(textFieldPattern);
425     auto host = textFieldPattern->GetHost();
426     CHECK_NULL_VOID(host);
427     auto pipelineContext = host->GetContext();
428     CHECK_NULL_VOID(pipelineContext);
429     auto themeManager = pipelineContext->GetThemeManager();
430     CHECK_NULL_VOID(themeManager);
431     auto theme = themeManager->GetTheme<TextFieldTheme>();
432 
433     auto textRect = textFieldPattern->GetTextRect();
434     bool isTextArea = textFieldPattern->IsTextArea();
435 
436     float offsetX = isTextArea ? contentOffset_->Get().GetX() : textRect.GetX();
437     float offsetY = isTextArea ? textRect.GetY() : contentOffset_->Get().GetY();
438     auto previewTextRect = textFieldPattern->GetPreviewTextRects();
439     if (previewTextRect.empty()) {
440         return;
441     }
442 
443     auto paintOffset = contentOffset_->Get();
444     float clipRectHeight = paintOffset.GetY() + contentSize_->Get().Height();
445     RSRect clipInnerRect;
446     auto defaultStyle = !textFieldPattern->IsNormalInlineState() || isTextArea;
447     if (defaultStyle) {
448         clipInnerRect = RSRect(paintOffset.GetX(), paintOffset.GetY(),
449             paintOffset.GetX() + contentSize_->Get().Width() + textFieldPattern->GetInlinePadding(), clipRectHeight);
450         canvas.ClipRect(clipInnerRect, RSClipOp::INTERSECT);
451     } else {
452         clipInnerRect = RSRect(paintOffset.GetX(), 0.0f, paintOffset.GetX() + contentSize_->Get().Width(),
453             textFieldPattern->GetFrameRect().Height());
454         canvas.ClipRect(clipInnerRect, RSClipOp::INTERSECT);
455     }
456 
457     auto underlineWidth = textFieldPattern->GetPreviewUnderlineWidth();
458     RSBrush brush;
459     brush.SetAntiAlias(true);
460     brush.SetColor(ToRSColor(previewTextDecorationColor_->Get()));
461     canvas.AttachBrush(brush);
462     for (const auto& drawRect : previewTextRect) {
463         RSRect rect(drawRect.Left() + offsetX, drawRect.Bottom() + offsetY - underlineWidth,
464                 drawRect.Right() + offsetX, drawRect.Bottom() + offsetY);
465         canvas.DrawRoundRect(RSRoundRect(rect, underlineWidth / 2, underlineWidth / 2));
466     }
467     canvas.DetachBrush();
468     canvas.Restore();
469 }
470 
SetCursorColor(Color & value)471 void TextFieldOverlayModifier::SetCursorColor(Color& value)
472 {
473     cursorColor_->Set(LinearColor(value));
474 }
475 
SetCursorWidth(float value)476 void TextFieldOverlayModifier::SetCursorWidth(float value)
477 {
478     cursorWidth_->Set(value);
479 }
480 
SetSelectedBackGroundColor(Color & value)481 void TextFieldOverlayModifier::SetSelectedBackGroundColor(Color& value)
482 {
483     selectedColor_->Set(LinearColor(value));
484 }
485 
SetCursorVisible(bool value)486 void TextFieldOverlayModifier::SetCursorVisible(bool value)
487 {
488     cursorVisible_->Set(value);
489 }
490 
SetContentSize(SizeF & value)491 void TextFieldOverlayModifier::SetContentSize(SizeF& value)
492 {
493     contentSize_->Set(value);
494 }
495 
SetContentOffset(OffsetF & value)496 void TextFieldOverlayModifier::SetContentOffset(OffsetF& value)
497 {
498     contentOffset_->Set(value);
499 }
500 
SetCursorOffset(const OffsetF & value)501 void TextFieldOverlayModifier::SetCursorOffset(const OffsetF& value)
502 {
503     cursorOffset_->Set(value);
504 }
505 
SetFloatingCursorOffset(const OffsetF & value)506 void TextFieldOverlayModifier::SetFloatingCursorOffset(const OffsetF& value)
507 {
508     floatingCursorOffset_->Set(value);
509 }
510 
SetFloatingCursorVisible(bool value)511 void TextFieldOverlayModifier::SetFloatingCursorVisible(bool value)
512 {
513     floatingCursorVisible_->Set(value);
514 }
515 
SetShowOriginCursor(bool value)516 void TextFieldOverlayModifier::SetShowOriginCursor(bool value)
517 {
518     showOriginCursor_->Set(value);
519 }
520 
521 
SetInputStyle(InputStyle & value)522 void TextFieldOverlayModifier::SetInputStyle(InputStyle& value)
523 {
524     inputStyle_ = value;
525 }
526 
SetFrameSize(const SizeF & value)527 void TextFieldOverlayModifier::SetFrameSize(const SizeF& value)
528 {
529     frameSize_->Set(value);
530 }
531 
SetCurrentOffset(float value)532 void TextFieldOverlayModifier::SetCurrentOffset(float value)
533 {
534     currentOffset_->Set(value);
535 }
536 
SetUnderlineWidth(float value)537 void TextFieldOverlayModifier::SetUnderlineWidth(float value)
538 {
539     underlineWidth_->Set(value);
540 }
541 
SetUnderlineColor(const Color & value)542 void TextFieldOverlayModifier::SetUnderlineColor(const Color& value)
543 {
544     underlineColor_->Set(value);
545 }
546 
SetScrollBar(const RefPtr<ScrollBar> & scrollBar)547 void TextFieldOverlayModifier::SetScrollBar(const RefPtr<ScrollBar>& scrollBar)
548 {
549     scrollBar_ = scrollBar;
550 }
551 
SetChangeSelectedRects(bool value)552 void TextFieldOverlayModifier::SetChangeSelectedRects(bool value)
553 {
554     if (value) {
555         changeSelectedRects_->Set(!changeSelectedRects_->Get());
556     }
557     needPaintSelect_ = value;
558 }
559 
SetShowSelect(bool value)560 void TextFieldOverlayModifier::SetShowSelect(bool value)
561 {
562     showSelect_->Set(value);
563 }
SetShowPreviewTextDecoration(bool value)564 void TextFieldOverlayModifier::SetShowPreviewTextDecoration(bool value)
565 {
566     showPreviewText_->Set(value);
567 }
SetPreviewTextRects(bool value)568 void TextFieldOverlayModifier::SetPreviewTextRects(bool value)
569 {
570     if (value) {
571         changePreviewTextRects_->Set(!changePreviewTextRects_->Get());
572     }
573     needPaintPreviewText = value;
574 }
SetPreviewTextDecorationColor(const Color & value)575 void TextFieldOverlayModifier::SetPreviewTextDecorationColor(const Color& value)
576 {
577     previewTextDecorationColor_->Set(value);
578 }
SetPreviewTextStyle(PreviewTextStyle style)579 void TextFieldOverlayModifier::SetPreviewTextStyle(PreviewTextStyle style)
580 {
581     previewTextStyle_ = style;
582 }
583 } // namespace OHOS::Ace::NG
584