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