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