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