• 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/base/modifier.h"
20 #include "core/components_ng/pattern/text_field/text_field_pattern.h"
21 #include "core/components_ng/render/adapter/pixelmap_image.h"
22 #include "core/components_ng/render/drawing.h"
23 #include "core/components_ng/render/drawing_prop_convertor.h"
24 #include "core/components_ng/render/image_painter.h"
25 
26 namespace OHOS::Ace::NG {
27 namespace {
28 constexpr float MAGNIFIER_GAIN = 1.25f;
29 constexpr Dimension MAGNIFIER_WIDTH = 140.0_vp;
30 constexpr Dimension MAGNIFIER_HEIGHT = 48.0_vp;
31 constexpr Dimension MAGNIFIER_OFFSET_Y = 4.0_vp;
32 constexpr Dimension PIXEL_MAP_IMAGE_OFFSET = 4.0_vp;
33 constexpr Dimension MAGNIFIER_BOUNDRY_WIDTH = 1.0_vp;
34 constexpr Dimension DEFAULT_STATUS_BAR_HEIGHT = 48.0_vp;
35 } // namespace
36 
TextFieldOverlayModifier(const WeakPtr<OHOS::Ace::NG::Pattern> & pattern,WeakPtr<ScrollEdgeEffect> && edgeEffect)37 TextFieldOverlayModifier::TextFieldOverlayModifier(
38     const WeakPtr<OHOS::Ace::NG::Pattern>& pattern, WeakPtr<ScrollEdgeEffect>&& edgeEffect)
39     : pattern_(pattern), edgeEffect_(edgeEffect)
40 {
41     auto textFieldPattern = DynamicCast<TextFieldPattern>(pattern_.Upgrade());
42     CHECK_NULL_VOID(textFieldPattern);
43     auto theme = textFieldPattern->GetTheme();
44     CHECK_NULL_VOID(theme);
45     cursorColor_ = AceType::MakeRefPtr<AnimatablePropertyColor>(LinearColor(Color()));
46     cursorWidth_ =
47         AceType::MakeRefPtr<AnimatablePropertyFloat>(static_cast<float>(theme->GetCursorWidth().ConvertToPx()));
48     selectedColor_ = AceType::MakeRefPtr<AnimatablePropertyColor>(LinearColor(Color()));
49     cursorVisible_ = AceType::MakeRefPtr<PropertyBool>(false);
50     showSelect_ = AceType::MakeRefPtr<PropertyBool>(false);
51     contentSize_ = AceType::MakeRefPtr<PropertySizeF>(SizeF());
52     contentOffset_ = AceType::MakeRefPtr<PropertyOffsetF>(OffsetF());
53     cursorOffset_ = AceType::MakeRefPtr<PropertyOffsetF>(textFieldPattern->GetCaretOffset());
54     frameSize_ = AceType::MakeRefPtr<PropertySizeF>(SizeF());
55     currentOffset_ = AceType::MakeRefPtr<PropertyFloat>(0.0f);
56     underlineWidth_ = AceType::MakeRefPtr<PropertyFloat>(0.0f);
57     underlineColor_ = AceType::MakeRefPtr<PropertyColor>(Color());
58     changeSelectedRects_ = AceType::MakeRefPtr<PropertyBool>(false);
59     firstHandleOffset_ = AceType::MakeRefPtr<PropertyOffsetF>(OffsetF());
60     secondHandleOffset_ = AceType::MakeRefPtr<PropertyOffsetF>(OffsetF());
61 
62     AttachProperty(cursorColor_);
63     AttachProperty(cursorWidth_);
64     AttachProperty(selectedColor_);
65     AttachProperty(cursorVisible_);
66     AttachProperty(showSelect_);
67     AttachProperty(contentSize_);
68     AttachProperty(contentOffset_);
69     AttachProperty(cursorOffset_);
70     AttachProperty(frameSize_);
71     AttachProperty(currentOffset_);
72     AttachProperty(underlineWidth_);
73     AttachProperty(underlineColor_);
74     AttachProperty(changeSelectedRects_);
75     AttachProperty(firstHandleOffset_);
76     AttachProperty(secondHandleOffset_);
77 }
78 
SetFirstHandleOffset(const OffsetF & offset)79 void TextFieldOverlayModifier::SetFirstHandleOffset(const OffsetF& offset)
80 {
81     firstHandleOffset_->Set(offset);
82 }
83 
SetSecondHandleOffset(const OffsetF & offset)84 void TextFieldOverlayModifier::SetSecondHandleOffset(const OffsetF& offset)
85 {
86     secondHandleOffset_->Set(offset);
87 }
88 
onDraw(DrawingContext & context)89 void TextFieldOverlayModifier::onDraw(DrawingContext& context)
90 {
91     auto& canvas = context.canvas;
92     if (Container::GreatOrEqualAPIVersion(PlatformVersion::VERSION_ELEVEN)) {
93         canvas.Save();
94         RSRect clipRect;
95         std::vector<RSPoint> clipRadius;
96         GetFrameRectClip(clipRect, clipRadius);
97         canvas.ClipRoundRect(clipRect, clipRadius, true);
98     }
99     PaintCursor(context);
100     PaintSelection(context);
101     if (Container::GreatOrEqualAPIVersion(PlatformVersion::VERSION_ELEVEN)) {
102         canvas.Restore();
103     }
104     PaintScrollBar(context);
105     PaintEdgeEffect(frameSize_->Get(), context.canvas);
106     PaintUnderline(context.canvas);
107     PaintMagnifier(context);
108 }
109 
GetFrameRectClip(RSRect & clipRect,std::vector<RSPoint> & clipRadius)110 void TextFieldOverlayModifier::GetFrameRectClip(RSRect& clipRect, std::vector<RSPoint>& clipRadius)
111 {
112     auto textFieldPattern = DynamicCast<TextFieldPattern>(pattern_.Upgrade());
113     CHECK_NULL_VOID(textFieldPattern);
114     auto host = textFieldPattern->GetHost();
115     CHECK_NULL_VOID(host);
116     auto renderContext = host->GetRenderContext();
117     CHECK_NULL_VOID(renderContext);
118     auto textFrameRect = textFieldPattern->GetFrameRect();
119     clipRect = RSRect(0.0f, 0.0f, textFrameRect.Width(), textFrameRect.Height());
120     auto radius = renderContext->GetBorderRadius().value_or(BorderRadiusProperty());
121     auto radiusTopLeft = RSPoint(static_cast<float>(radius.radiusTopLeft.value_or(0.0_vp).ConvertToPx()),
122         static_cast<float>(radius.radiusTopLeft.value_or(0.0_vp).ConvertToPx()));
123     clipRadius.emplace_back(radiusTopLeft);
124     auto radiusTopRight = RSPoint(static_cast<float>(radius.radiusTopRight.value_or(0.0_vp).ConvertToPx()),
125         static_cast<float>(radius.radiusTopRight.value_or(0.0_vp).ConvertToPx()));
126     clipRadius.emplace_back(radiusTopRight);
127     auto radiusBottomRight = RSPoint(static_cast<float>(radius.radiusBottomRight.value_or(0.0_vp).ConvertToPx()),
128         static_cast<float>(radius.radiusBottomRight.value_or(0.0_vp).ConvertToPx()));
129     clipRadius.emplace_back(radiusBottomRight);
130     auto radiusBottomLeft = RSPoint(static_cast<float>(radius.radiusBottomLeft.value_or(0.0_vp).ConvertToPx()),
131         static_cast<float>(radius.radiusBottomLeft.value_or(0.0_vp).ConvertToPx()));
132     clipRadius.emplace_back(radiusBottomLeft);
133 }
134 
PaintUnderline(RSCanvas & canvas) const135 void TextFieldOverlayModifier::PaintUnderline(RSCanvas& canvas) const
136 {
137     auto textFieldPattern = DynamicCast<TextFieldPattern>(pattern_.Upgrade());
138     CHECK_NULL_VOID(textFieldPattern);
139     auto layoutProperty = textFieldPattern->GetLayoutProperty<TextFieldLayoutProperty>();
140     CHECK_NULL_VOID(layoutProperty);
141     if (!(layoutProperty->GetShowUnderlineValue(false) && textFieldPattern->IsUnspecifiedOrTextType())) {
142         return;
143     }
144     if (textFieldPattern->IsNormalInlineState() && textFieldPattern->HasFocus()) {
145         return;
146     }
147     auto contentRect = textFieldPattern->GetContentRect();
148     auto textFrameRect = textFieldPattern->GetFrameRect();
149     auto responseArea = textFieldPattern->GetResponseArea();
150     Point leftPoint, rightPoint;
151     if (layoutProperty->GetShowCounterValue(false)) {
152         leftPoint.SetX(contentRect.Left());
153         leftPoint.SetY(textFrameRect.Height());
154         rightPoint.SetX(contentRect.Right());
155         rightPoint.SetY(textFrameRect.Height());
156     } else {
157         auto responseAreaWidth = responseArea ? responseArea->GetAreaRect().Width() : 0.0f;
158         leftPoint.SetX(contentRect.Left());
159         leftPoint.SetY(textFrameRect.Height());
160         rightPoint.SetX(contentRect.Right() + responseAreaWidth);
161         rightPoint.SetY(textFrameRect.Height());
162     }
163     RSPen pen;
164     pen.SetColor(ToRSColor(underlineColor_->Get()));
165     pen.SetWidth(underlineWidth_->Get());
166     pen.SetAntiAlias(true);
167     canvas.AttachPen(pen);
168     canvas.DrawLine(
169         ToRSPoint(PointF(leftPoint.GetX(), leftPoint.GetY())), ToRSPoint(PointF(rightPoint.GetX(), rightPoint.GetY())));
170     canvas.DetachPen();
171 }
172 
PaintSelection(DrawingContext & context) const173 void TextFieldOverlayModifier::PaintSelection(DrawingContext& context) const
174 {
175     if (!showSelect_->Get() && !needPaintSelect_) {
176         return;
177     }
178     auto& canvas = context.canvas;
179     canvas.Save();
180     auto textFieldPattern = DynamicCast<TextFieldPattern>(pattern_.Upgrade());
181     CHECK_NULL_VOID(textFieldPattern);
182     auto pipelineContext = PipelineContext::GetCurrentContext();
183     CHECK_NULL_VOID(pipelineContext);
184     auto themeManager = pipelineContext->GetThemeManager();
185     CHECK_NULL_VOID(themeManager);
186     auto theme = themeManager->GetTheme<TextFieldTheme>();
187     RSBrush brush;
188     brush.SetAntiAlias(true);
189     brush.SetColor(ToRSColor(selectedColor_->Get()));
190     canvas.AttachBrush(brush);
191     auto paintOffset = textFieldPattern->GetContentRect().GetOffset();
192     auto textBoxes = textFieldPattern->GetTextBoxes();
193     auto textRect = textFieldPattern->GetTextRect();
194     bool isTextArea = textFieldPattern->IsTextArea();
195     float clipRectHeight = 0.0f;
196     clipRectHeight = paintOffset.GetY() + contentSize_->Get().Height();
197     RSRect clipInnerRect;
198     auto defaultStyle = !textFieldPattern->IsNormalInlineState() || isTextArea;
199     if (defaultStyle) {
200         clipInnerRect = RSRect(paintOffset.GetX(), paintOffset.GetY(),
201             paintOffset.GetX() + contentSize_->Get().Width() + textFieldPattern->GetInlinePadding(), clipRectHeight);
202         canvas.ClipRect(clipInnerRect, RSClipOp::INTERSECT);
203     } else {
204         clipInnerRect = RSRect(paintOffset.GetX(), 0.0f, paintOffset.GetX() + contentSize_->Get().Width(),
205             textFieldPattern->GetFrameRect().Height());
206         canvas.ClipRect(clipInnerRect, RSClipOp::INTERSECT);
207     }
208     // for default style, selection height is equal to the content height
209     for (const auto& textBox : textBoxes) {
210         canvas.DrawRect(RSRect(textBox.Left() + (isTextArea ? contentOffset_->Get().GetX() : textRect.GetX()),
211             defaultStyle
212                 ? (textBox.Top() + (isTextArea ? textRect.GetY() : contentOffset_->Get().GetY()))
213                 : 0.0f,
214             textBox.Right() + (isTextArea ? contentOffset_->Get().GetX() : textRect.GetX()),
215             defaultStyle
216                 ? (textBox.Bottom() + (isTextArea ? textRect.GetY() : contentOffset_->Get().GetY()))
217                          : textFieldPattern->GetFrameRect().Height()));
218     }
219     canvas.DetachBrush();
220     canvas.Restore();
221 }
222 
PaintCursor(DrawingContext & context) const223 void TextFieldOverlayModifier::PaintCursor(DrawingContext& context) const
224 {
225     auto& canvas = context.canvas;
226     auto textFieldPattern = DynamicCast<TextFieldPattern>(pattern_.Upgrade());
227     CHECK_NULL_VOID(textFieldPattern);
228     if (textFieldPattern->GetShowMagnifier()) {
229         cursorVisible_->Set(true);
230     }
231     if (!cursorVisible_->Get() || textFieldPattern->IsSelected()) {
232         return;
233     }
234     canvas.Save();
235     RSBrush brush;
236     brush.SetAntiAlias(true);
237     brush.SetColor(ToRSColor(cursorColor_->Get()));
238     canvas.AttachBrush(brush);
239     auto paintOffset = contentOffset_->Get();
240     float clipRectHeight = 0.0f;
241     clipRectHeight = paintOffset.GetY() + contentSize_->Get().Height();
242     RSRect clipInnerRect(paintOffset.GetX(), paintOffset.GetY(),
243         // add extra clip space for cases such as auto width
244         paintOffset.GetX() + contentSize_->Get().Width() +
245             (LessOrEqual(contentSize_->Get().Width(), 0.0) ? cursorWidth_->Get() : 0.0f),
246         clipRectHeight);
247     canvas.ClipRect(clipInnerRect, RSClipOp::INTERSECT);
248     auto caretRect = textFieldPattern->GetCaretRect();
249     canvas.DrawRect(RSRect(caretRect.GetX(), caretRect.GetY(),
250         caretRect.GetX() + (static_cast<float>(cursorWidth_->Get())), caretRect.GetY() + caretRect.Height()));
251     canvas.DetachBrush();
252     canvas.Restore();
253 }
254 
PaintEdgeEffect(const SizeF & frameSize,RSCanvas & canvas)255 void TextFieldOverlayModifier::PaintEdgeEffect(const SizeF& frameSize, RSCanvas& canvas)
256 {
257     auto edgeEffect = edgeEffect_.Upgrade();
258     CHECK_NULL_VOID(edgeEffect);
259     edgeEffect->Paint(canvas, frameSize, { 0.0f, 0.0f });
260 }
261 
PaintScrollBar(DrawingContext & context)262 void TextFieldOverlayModifier::PaintScrollBar(DrawingContext& context)
263 {
264     auto textFieldPattern = DynamicCast<TextFieldPattern>(pattern_.Upgrade());
265     CHECK_NULL_VOID(textFieldPattern);
266     if (textFieldPattern->GetScrollBarVisible() && textFieldPattern->IsTextArea()) {
267         ScrollBarOverlayModifier::onDraw(context);
268     }
269 }
270 
PaintMagnifier(DrawingContext & context)271 void TextFieldOverlayModifier::PaintMagnifier(DrawingContext& context)
272 {
273     auto pattern = DynamicCast<TextFieldPattern>(pattern_.Upgrade());
274     CHECK_NULL_VOID(pattern);
275     magnifierRect_ = pattern->GetMagnifierRect();
276     auto textFieldpattern = DynamicCast<TextFieldPattern>(magnifierRect_.parent.Upgrade());
277     CHECK_NULL_VOID(textFieldpattern);
278     if (!magnifierRect_.isChildNode || !textFieldpattern->GetShowMagnifier()) {
279         return;
280     }
281     auto pixelMap = textFieldpattern->GetPixelMap();
282     CHECK_NULL_VOID(pixelMap);
283     auto& canvas = context.canvas;
284     canvas.Save();
285 
286     auto cursorOffsetY = magnifierRect_.cursorOffset.GetY();
287     auto localOffsetX = magnifierRect_.localOffset.GetX();
288     if (!GetMagnifierRect(magnifierRect_.startX, magnifierRect_.startY, magnifierRect_.endX, magnifierRect_.endY,
289         localOffsetX, cursorOffsetY)) {
290         return;
291     }
292 
293     RSBrush brush;
294     brush.SetColor(RSColor::COLOR_WHITE);
295     brush.SetAntiAlias(true);
296     canvas.AttachBrush(brush);
297 
298     std::vector<TextPoint> drawPathPoints =
299         GetTextPoints(magnifierRect_.startX, magnifierRect_.startY, magnifierRect_.endX, magnifierRect_.endY, false);
300     auto drawPath = GetPathByPoints(drawPathPoints);
301     PaintShadow(*drawPath, ShadowConfig::DefaultShadowM, canvas);
302     canvas.DrawPath(*drawPath);
303     std::vector<TextPoint> clipPathPoints =
304         GetTextPoints(magnifierRect_.startX, magnifierRect_.startY, magnifierRect_.endX, magnifierRect_.endY, false);
305     auto clipPath = GetPathByPoints(clipPathPoints);
306     canvas.ClipPath(*clipPath, RSClipOp::INTERSECT, true);
307 
308     auto magnifierGain = MAGNIFIER_GAIN;
309     auto pixelMapImageOffset = PIXEL_MAP_IMAGE_OFFSET.ConvertToPx();
310 
311     PixelMapImage pixelMapImage(pixelMap);
312     auto magnifierPaintConfig = pixelMapImage.GetPaintConfig();
313     magnifierPaintConfig.scaleX_ = magnifierGain;
314     magnifierPaintConfig.scaleY_ = magnifierGain;
315     pixelMapImage.SetPaintConfig(magnifierPaintConfig);
316 
317     RectF dstRect;
318     dstRect.SetRect(localOffsetX - localOffsetX * magnifierGain - pattern->GetTextPaintOffset().GetX() * magnifierGain,
319         magnifierRect_.startY - pattern->GetTextPaintOffset().GetY() * magnifierGain - cursorOffsetY * magnifierGain +
320             pixelMapImageOffset,
321         pixelMap->GetWidth() * magnifierGain, pixelMap->GetHeight() * magnifierGain);
322     pixelMapImage.DrawRect(canvas, ToRSRect(dstRect));
323 
324     canvas.DetachBrush();
325     canvas.Restore();
326 }
327 
GetMagnifierRect(float & startX,float & startY,float & endX,float & endY,float & localOffsetX,float & cursorOffsetY)328 bool TextFieldOverlayModifier::GetMagnifierRect(
329     float& startX, float& startY, float& endX, float& endY, float& localOffsetX, float& cursorOffsetY)
330 {
331     auto pattern = DynamicCast<TextFieldPattern>(magnifierRect_.parent.Upgrade());
332     CHECK_NULL_RETURN(pattern, false);
333     auto cursorOffsetX = magnifierRect_.cursorOffset.GetX();
334     auto magnifierWidth = MAGNIFIER_WIDTH.ConvertToPx();
335     auto magnifierHeight = MAGNIFIER_HEIGHT.ConvertToPx();
336     auto magnifierOffsetY = MAGNIFIER_OFFSET_Y.ConvertToPx();
337     auto localOffsetY = magnifierRect_.localOffset.GetY();
338     localOffsetX = std::max(localOffsetX, magnifierRect_.contentOffset.GetX());
339     localOffsetX = std::min(localOffsetX, magnifierRect_.contentSize.Width() + magnifierRect_.contentOffset.GetX());
340     auto textBoxesLeft = 0.0f;
341     if (!pattern->GetTextBoxes().empty()) {
342         textBoxesLeft = pattern->GetTextBoxes()[0].Left();
343     }
344     startX = localOffsetX - magnifierWidth / 2.0f;
345     if ((pattern->GetCaretIndex() == pattern->GetContentWideTextLength() && localOffsetX >= cursorOffsetX) ||
346         (pattern->GetCaretIndex() == 0 && localOffsetX <= cursorOffsetX)) {
347         startX = cursorOffsetX - magnifierWidth / 2.0f;
348         localOffsetX = cursorOffsetX;
349     }
350     auto firstHandleOffsetY = pattern->GetTextSelectController()->GetFirstHandleOffset().GetY();
351     auto secondHandleOffsetY = pattern->GetTextSelectController()->GetSecondHandleOffset().GetY();
352     if (pattern->IsSelected() && firstHandleOffsetY != secondHandleOffsetY &&
353         localOffsetY < firstHandleOffsetY + pattern->GetLineHeight() &&
354         localOffsetY < secondHandleOffsetY + pattern->GetLineHeight()) {
355         if (firstHandleOffsetY < secondHandleOffsetY) {
356             cursorOffsetY = firstHandleOffsetY;
357         } else if (secondHandleOffsetY < firstHandleOffsetY) {
358             cursorOffsetY = secondHandleOffsetY;
359         }
360     }
361     startY = cursorOffsetY - magnifierHeight - magnifierOffsetY;
362     if ((pattern->GetParentGlobalOffset().GetY() + startY) < DEFAULT_STATUS_BAR_HEIGHT.ConvertToPx()) {
363         startY = cursorOffsetY + pattern->GetLineHeight() + magnifierHeight + magnifierOffsetY;
364     }
365     startX = std::max(startX, 0.0f);
366     endX = startX + magnifierWidth;
367     endY = startY;
368     if (endX > magnifierRect_.contentSize.Width() + magnifierRect_.contentOffset.GetX() * 2.0f) {
369         endX = magnifierRect_.contentSize.Width() + magnifierRect_.contentOffset.GetX() * 2.0f;
370         startX = endX - magnifierWidth;
371     }
372     return true;
373 }
374 
GetTextPoints(float startX,float startY,float endX,float endY,bool haveOffset)375 std::vector<TextPoint> TextFieldOverlayModifier::GetTextPoints(
376     float startX, float startY, float endX, float endY, bool haveOffset)
377 {
378     std::vector<TextPoint> textPoints;
379     auto lineHeight = MAGNIFIER_HEIGHT.ConvertToPx();
380     auto offset = MAGNIFIER_BOUNDRY_WIDTH.ConvertToPx();
381     if (haveOffset) {
382         textPoints.emplace_back(TextPoint(startX - offset, startY - offset));
383         textPoints.emplace_back(TextPoint(endX + offset, endY - offset));
384         textPoints.emplace_back(TextPoint(endX + offset, endY + lineHeight + offset));
385         textPoints.emplace_back(TextPoint(startX - offset, endY + lineHeight + offset));
386         textPoints.emplace_back(TextPoint(startX - offset, endY - offset));
387         textPoints.emplace_back(TextPoint(endX + offset, endY - offset));
388         return textPoints;
389     }
390     textPoints.emplace_back(TextPoint(startX, startY));
391     textPoints.emplace_back(TextPoint(endX, endY));
392     textPoints.emplace_back(TextPoint(endX, endY + lineHeight));
393     textPoints.emplace_back(TextPoint(startX, endY + lineHeight));
394     textPoints.emplace_back(TextPoint(startX, endY));
395     textPoints.emplace_back(TextPoint(endX, endY));
396     return textPoints;
397 }
398 
GetPathByPoints(std::vector<TextPoint> points)399 std::shared_ptr<RSPath> TextFieldOverlayModifier::GetPathByPoints(std::vector<TextPoint> points)
400 {
401     std::shared_ptr<RSPath> path = std::make_shared<RSPath>();
402     auto radius = MAGNIFIER_HEIGHT.ConvertToPx() / 2.0f;
403     path->MoveTo(points[0].x + radius, points[0].y);
404     size_t step = 2;
405     for (size_t i = 0; i + step < points.size(); i++) {
406         auto firstPoint = points[i];
407         auto crossPoint = points[i + 1];
408         auto secondPoint = points[i + step];
409 
410         if (crossPoint.y == firstPoint.y) {
411             int32_t directionX = (crossPoint.x - firstPoint.x) > 0 ? 1 : -1;
412             int32_t directionY = (secondPoint.y - crossPoint.y) > 0 ? 1 : -1;
413             auto direction =
414                 (directionX * directionY > 0) ? RSPathDirection::CW_DIRECTION : RSPathDirection::CCW_DIRECTION;
415             path->LineTo(crossPoint.x - radius * directionX, crossPoint.y);
416             path->ArcTo(radius, radius, 0.0f, direction, crossPoint.x, crossPoint.y + radius * directionY);
417         } else {
418             int32_t directionX = (secondPoint.x - crossPoint.x) > 0 ? 1 : -1;
419             int32_t directionY = (crossPoint.y - firstPoint.y) > 0 ? 1 : -1;
420             auto direction =
421                 (directionX * directionY < 0) ? RSPathDirection::CW_DIRECTION : RSPathDirection::CCW_DIRECTION;
422             path->LineTo(crossPoint.x, crossPoint.y - radius * directionY);
423             path->ArcTo(radius, radius, 0.0f, direction, crossPoint.x + radius * directionX, secondPoint.y);
424         }
425     }
426     return path;
427 }
PaintShadow(const RSPath & path,const Shadow & shadow,RSCanvas & canvas)428 void TextFieldOverlayModifier::PaintShadow(const RSPath& path, const Shadow& shadow, RSCanvas& canvas)
429 {
430     canvas.Save();
431 #ifndef USE_ROSEN_DRAWING
432     RSPath rsPath = path;
433 #else
434     RSRecordingPath rsPath;
435     rsPath.AddPath(path);
436 #endif
437     rsPath.Offset(shadow.GetOffset().GetX(), shadow.GetOffset().GetY());
438     RSColor spotColor = ToRSColor(shadow.GetColor());
439     RSPoint3 planeParams = { 0.0f, 0.0f, shadow.GetElevation() };
440 #ifndef USE_ROSEN_DRAWING
441     RSPoint3 lightPos = { rsPath.GetBounds().GetLeft() / 2 + rsPath.GetBounds().GetRight(),
442         rsPath.GetBounds().GetTop() / 2.0 + rsPath.GetBounds().GetBottom() / 2.0, shadow.GetLightHeight() };
443 #else
444     auto bounds = rsPath.GetBounds();
445     RSPoint3 lightPos = { bounds.GetLeft() / 2.0 + bounds.GetRight() / 2.0,
446         bounds.GetTop() / 2.0 + bounds.GetBottom() / 2.0, shadow.GetLightHeight() };
447 #endif
448     RSColor ambientColor = RSColor(0, 0, 0, 0);
449     canvas.DrawShadow(rsPath, planeParams, lightPos, shadow.GetLightRadius(), ambientColor, spotColor,
450         RSShadowFlags::TRANSPARENT_OCCLUDER);
451     canvas.Restore();
452 }
453 
SetCursorColor(Color & value)454 void TextFieldOverlayModifier::SetCursorColor(Color& value)
455 {
456     cursorColor_->Set(LinearColor(value));
457 }
458 
SetCursorWidth(float value)459 void TextFieldOverlayModifier::SetCursorWidth(float value)
460 {
461     cursorWidth_->Set(value);
462 }
463 
SetSelectedBackGroundColor(Color & value)464 void TextFieldOverlayModifier::SetSelectedBackGroundColor(Color& value)
465 {
466     selectedColor_->Set(LinearColor(value));
467 }
468 
SetCursorVisible(bool value)469 void TextFieldOverlayModifier::SetCursorVisible(bool value)
470 {
471     cursorVisible_->Set(value);
472 }
473 
SetContentSize(SizeF & value)474 void TextFieldOverlayModifier::SetContentSize(SizeF& value)
475 {
476     contentSize_->Set(value);
477 }
478 
SetContentOffset(OffsetF & value)479 void TextFieldOverlayModifier::SetContentOffset(OffsetF& value)
480 {
481     contentOffset_->Set(value);
482 }
483 
SetCursorOffset(const OffsetF & value)484 void TextFieldOverlayModifier::SetCursorOffset(const OffsetF& value)
485 {
486     cursorOffset_->Set(value);
487 }
488 
SetInputStyle(InputStyle & value)489 void TextFieldOverlayModifier::SetInputStyle(InputStyle& value)
490 {
491     inputStyle_ = value;
492 }
493 
SetFrameSize(const SizeF & value)494 void TextFieldOverlayModifier::SetFrameSize(const SizeF& value)
495 {
496     frameSize_->Set(value);
497 }
498 
SetCurrentOffset(float value)499 void TextFieldOverlayModifier::SetCurrentOffset(float value)
500 {
501     currentOffset_->Set(value);
502 }
503 
SetUnderlineWidth(float value)504 void TextFieldOverlayModifier::SetUnderlineWidth(float value)
505 {
506     underlineWidth_->Set(value);
507 }
508 
SetUnderlineColor(const Color & value)509 void TextFieldOverlayModifier::SetUnderlineColor(const Color& value)
510 {
511     underlineColor_->Set(value);
512 }
513 
SetScrollBar(const RefPtr<ScrollBar> & scrollBar)514 void TextFieldOverlayModifier::SetScrollBar(const RefPtr<ScrollBar>& scrollBar)
515 {
516     scrollBar_ = scrollBar;
517 }
518 
SetChangeSelectedRects(bool value)519 void TextFieldOverlayModifier::SetChangeSelectedRects(bool value)
520 {
521     if (value) {
522         changeSelectedRects_->Set(!changeSelectedRects_->Get());
523     }
524     needPaintSelect_ = value;
525 }
526 
SetShowSelect(bool value)527 void TextFieldOverlayModifier::SetShowSelect(bool value)
528 {
529     showSelect_->Set(value);
530 }
531 } // namespace OHOS::Ace::NG
532