1 /*
2  * Copyright (c) 2021-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/text_overlay/rosen_render_text_overlay.h"
17 
18 #ifndef USE_ROSEN_DRAWING
19 #include "include/core/SkImage.h"
20 #include "include/core/SkMaskFilter.h"
21 #include "include/core/SkPath.h"
22 #endif
23 
24 #include "core/components/common/painter/rosen_decoration_painter.h"
25 #include "core/components/common/properties/shadow_config.h"
26 #include "core/components/text_field/rosen_render_text_field.h"
27 #include "core/pipeline/base/rosen_render_context.h"
28 
29 namespace OHOS::Ace {
30 namespace {
31 
32 constexpr Dimension CLIP_ORIGIN_X = 4.5754_vp;
33 constexpr Dimension CLIP_ORIGIN_Y = 6.3432_vp;
34 #ifndef USE_ROSEN_DRAWING
35 constexpr Dimension CLIP_LENGTH = 4.0_vp;
36 #endif
37 constexpr Dimension MAGNIFIER_WIDTH = 48.0_vp;
38 constexpr Dimension MAGNIFIER_RADIUS = 24.0_vp;
39 constexpr Dimension MAGNIFIER_OFFSET = 7.0_vp;
40 constexpr Dimension FIRST_DRAG_OFFSET = 19.0_vp;
41 constexpr Dimension HANDLE_LINE_WIDTH = 1.5_vp;
42 constexpr Dimension MORE_BUTTON_SIZE = 40.0_vp;
43 constexpr double MAGNIFIER_GAIN = 1.25;
44 constexpr double FIXED_OFFSET = 18.0;
45 
46 } // namespace
47 
48 class RenderWeb;
Paint(RenderContext & context,const Offset & offset)49 void RosenRenderTextOverlay::Paint(RenderContext& context, const Offset& offset)
50 {
51     if (!showOption_.showStartHandle && !showOption_.showEndHandle && !isUsedByWeb_) {
52         return;
53     }
54 
55     PaintHandles(context);
56 
57     AdjustForAnimation();
58 
59     if ((!isSingleHandle_ || showOption_.showMenu) && !showMagnifier_) {
60         RenderNode::Paint(context, offset);
61     }
62 
63     PaintMore(context);
64 }
65 
PaintHandles(RenderContext & context) const66 void RosenRenderTextOverlay::PaintHandles(RenderContext& context) const
67 {
68     auto renderContext = AceType::DynamicCast<RosenRenderContext>(&context);
69     if (!renderContext) {
70         return;
71     }
72     auto canvas = renderContext->GetCanvas();
73     if (!canvas) {
74         return;
75     }
76     Offset centerOffset = Offset(0.0, NormalizeToPx(handleRadius_));
77 
78     // Paint one handle.
79     if (isSingleHandle_ && clipRect_.IsInRegion(Point(startHandleOffset_.GetX(), startHandleOffset_.GetY()))) {
80         PaintHandle(canvas, startHandleOffset_ + centerOffset);
81         return;
82     }
83 
84     // Paint start handle of textOverlay.
85     if (showOption_.showStartHandle &&
86         clipRect_.IsInRegion(Point(startHandleOffset_.GetX(), startHandleOffset_.GetY()))) {
87         PaintHandle(canvas,
88             startHandleOffset_ + Offset(0.0, -startHandleHeight_.value_or(lineHeight_) - NormalizeToPx(handleRadius_)),
89             true);
90     }
91 
92     // Paint end handle of textOverlay.
93     if (showOption_.showEndHandle && clipRect_.IsInRegion(Point(endHandleOffset_.GetX(), endHandleOffset_.GetY()))) {
94         PaintHandle(canvas, endHandleOffset_ + centerOffset);
95     }
96 }
97 
98 #ifndef USE_ROSEN_DRAWING
PaintHandle(SkCanvas * skCanvas,Offset centerOffset,bool isLeftHandle) const99 void RosenRenderTextOverlay::PaintHandle(SkCanvas* skCanvas, Offset centerOffset, bool isLeftHandle) const
100 {
101     if (!skCanvas) {
102         return;
103     }
104 
105     SkPaint paint;
106     paint.setAntiAlias(true);
107     skCanvas->save();
108     skCanvas->translate(centerOffset.GetX(), centerOffset.GetY());
109     // Paint outer circle.
110     paint.setColor(handleColor_.GetValue());
111     skCanvas->drawCircle(0.0, 0.0, NormalizeToPx(handleRadius_), paint);
112     // Paint inner circle.
113     paint.setColor(handleColorInner_.GetValue());
114     skCanvas->drawCircle(0.0, 0.0, NormalizeToPx(handleRadiusInner_), paint);
115     // Paint line of handle.
116     paint.setAntiAlias(true);
117     paint.setColor(handleColor_.GetValue());
118     paint.setStrokeWidth(NormalizeToPx(HANDLE_LINE_WIDTH));
119     paint.setStrokeCap(SkPaint::Cap::kRound_Cap);
120     // 1.0 is avoid separation of handle circle and handle line.
121     Offset startPoint(Offset(0.0, NormalizeToPx(-handleRadius_) + 1.0));
122     // 1.0_dp is designed by UX, handle line is higher than height of select region.
123     Offset endPoint(
124         Offset(0.0, NormalizeToPx(-handleRadius_) - endHandleHeight_.value_or(lineHeight_) - NormalizeToPx(1.0_vp)));
125     if (isLeftHandle) {
126         startPoint.SetY(NormalizeToPx(handleRadius_) - 1.0);
127         endPoint.SetY(NormalizeToPx(handleRadius_) + startHandleHeight_.value_or(lineHeight_) + NormalizeToPx(1.0_vp));
128     }
129     skCanvas->drawLine(startPoint.GetX(), startPoint.GetY(), endPoint.GetX(), endPoint.GetY(), paint);
130     skCanvas->restore();
131 }
132 #else
PaintHandle(RSCanvas * canvas,Offset centerOffset,bool isLeftHandle) const133 void RosenRenderTextOverlay::PaintHandle(RSCanvas* canvas, Offset centerOffset, bool isLeftHandle) const
134 {
135     if (!canvas) {
136         return;
137     }
138 
139     RSBrush brush;
140     brush.SetAntiAlias(true);
141     canvas->Save();
142     canvas->Translate(centerOffset.GetX(), centerOffset.GetY());
143     // Paint outer circle.
144     brush.SetColor(handleColor_.GetValue());
145     canvas->AttachBrush(brush);
146     canvas->DrawCircle(RSPoint(0.0, 0.0), NormalizeToPx(handleRadius_));
147     canvas->DetachBrush();
148     // Paint inner circle.
149     brush.SetColor(handleColorInner_.GetValue());
150     canvas->AttachBrush(brush);
151     canvas->DrawCircle(RSPoint(0.0, 0.0), NormalizeToPx(handleRadiusInner_));
152     canvas->DetachBrush();
153     // Paint line of handle.
154     RSPen pen;
155     pen.SetAntiAlias(true);
156     pen.SetColor(handleColor_.GetValue());
157     pen.SetWidth(NormalizeToPx(HANDLE_LINE_WIDTH));
158     pen.SetCapStyle(RSPen::CapStyle::ROUND_CAP);
159     // 1.0 is avoid separation of handle circle and handle line.
160     Offset startPoint(Offset(0.0, NormalizeToPx(-handleRadius_) + 1.0));
161     // 1.0_dp is designed by UX, handle line is higher than height of select region.
162     Offset endPoint(
163         Offset(0.0, NormalizeToPx(-handleRadius_) - endHandleHeight_.value_or(lineHeight_) - NormalizeToPx(1.0_vp)));
164     if (isLeftHandle) {
165         startPoint.SetY(NormalizeToPx(handleRadius_) - 1.0);
166         endPoint.SetY(NormalizeToPx(handleRadius_) + startHandleHeight_.value_or(lineHeight_) + NormalizeToPx(1.0_vp));
167     }
168     canvas->AttachPen(pen);
169     canvas->DrawLine(RSPoint(startPoint.GetX(), startPoint.GetY()), RSPoint(endPoint.GetX(), endPoint.GetY()));
170     canvas->DetachPen();
171     canvas->Restore();
172 }
173 #endif
174 
PaintMagnifier(RenderContext & context)175 void RosenRenderTextOverlay::PaintMagnifier(RenderContext& context)
176 {
177     auto textField = weakTextField_.Upgrade();
178     auto rosenTextField = AceType::DynamicCast<RosenRenderTextField>(textField);
179     auto canvas = static_cast<RosenRenderContext*>(&context)->GetCanvas();
180     auto pipelineContext = context_.Upgrade();
181     if (!canvas || !rosenTextField || !pipelineContext) {
182         return;
183     }
184     auto bitmap = rosenTextField->GetBitmap();
185     double viewScale = pipelineContext->GetViewScale();
186     double globalX = 0.0;
187     double globalY = 0.0;
188     double x = 0.0;
189     double y = 0.0;
190     if (isTouchEndDrag_ || isSingleHandle_) {
191         auto caretRect = rosenTextField->GetCaretRect();
192         auto textFieldGlobalOffset = rosenTextField->GetGlobalOffset();
193         globalX = textFieldGlobalOffset.GetX() + caretRect.GetOffset().GetX() + caretRect.Width() / 2 -
194                   NormalizeToPx(MAGNIFIER_RADIUS);
195         globalY = textFieldGlobalOffset.GetY() + caretRect.GetOffset().GetY() - NormalizeToPx(MAGNIFIER_WIDTH) -
196                   NormalizeToPx(MAGNIFIER_OFFSET);
197         if (!isSingleHandle_ && NeedAdjustEndHandle()) {
198             globalY -= NormalizeToPx(FIRST_DRAG_OFFSET - MAGNIFIER_OFFSET);
199         }
200         x = caretRect.GetOffset().GetX() + caretRect.Width() / 2 - NormalizeToPx(MAGNIFIER_RADIUS);
201         y = caretRect.GetOffset().GetY() + caretRect.Height() / 2 - NormalizeToPx(MAGNIFIER_RADIUS);
202     } else if (isTouchStartDrag_) {
203         auto caretRect = rosenTextField->GetStartRect();
204         auto textFieldGlobalOffset = rosenTextField->GetGlobalOffset();
205         globalX = textFieldGlobalOffset.GetX() + caretRect.GetOffset().GetX() + caretRect.Width() / 2 -
206                   NormalizeToPx(MAGNIFIER_RADIUS);
207         globalY = textFieldGlobalOffset.GetY() + caretRect.GetOffset().GetY() - NormalizeToPx(MAGNIFIER_WIDTH) -
208                   NormalizeToPx(FIRST_DRAG_OFFSET);
209 
210         if (!isSingleHandle_ && NeedAdjustStartHandle()) {
211             globalY += NormalizeToPx(FIRST_DRAG_OFFSET - MAGNIFIER_OFFSET);
212         }
213         x = caretRect.GetOffset().GetX() + caretRect.Width() / 2 - NormalizeToPx(MAGNIFIER_RADIUS);
214         y = caretRect.GetOffset().GetY() + caretRect.Height() / 2 - NormalizeToPx(MAGNIFIER_RADIUS);
215     } else {
216         return;
217     }
218 
219     globalX = LessOrEqual(globalX, 0.0) ? 0.0 : globalX;
220     globalY = LessOrEqual(globalY, 0.0) ? 0.0 : globalY;
221 
222 #ifndef USE_ROSEN_DRAWING
223     SkRRect rrect = SkRRect::MakeRectXY(
224         SkRect::MakeXYWH(globalX, globalY, NormalizeToPx(MAGNIFIER_WIDTH), NormalizeToPx(MAGNIFIER_WIDTH)),
225         NormalizeToPx(MAGNIFIER_WIDTH), NormalizeToPx(MAGNIFIER_WIDTH));
226 
227     RosenDecorationPainter::PaintShadow(SkPath().addRRect(rrect), ShadowConfig::DefaultShadowM,
228         static_cast<RosenRenderContext*>(&context)->GetRSNode());
229 
230     SkRRect ScaleRrect =
231         SkRRect::MakeRectXY(SkRect::MakeXYWH(globalX * viewScale, globalY * viewScale,
232             NormalizeToPx(MAGNIFIER_WIDTH) * viewScale, NormalizeToPx(MAGNIFIER_WIDTH) * viewScale),
233             NormalizeToPx(MAGNIFIER_WIDTH) * viewScale, NormalizeToPx(MAGNIFIER_WIDTH) * viewScale);
234 
235     canvas->save();
236     canvas->scale(1.0 / viewScale, 1.0 / viewScale);
237     SkPaint paint;
238     canvas->clipRRect(ScaleRrect, true);
239 
240     paint.setColor(SK_ColorWHITE);
241     paint.setAntiAlias(true);
242     canvas->drawRRect(ScaleRrect, paint);
243 
244     canvas->drawImageRect(bitmap.asImage(),
245         SkRect::MakeXYWH(x * viewScale * MAGNIFIER_GAIN + FIXED_OFFSET, y * viewScale * MAGNIFIER_GAIN + FIXED_OFFSET,
246             NormalizeToPx(MAGNIFIER_WIDTH) * viewScale, NormalizeToPx(MAGNIFIER_WIDTH) * viewScale),
247         SkRect::MakeXYWH(globalX * viewScale, globalY * viewScale, NormalizeToPx(MAGNIFIER_WIDTH) * viewScale,
248             NormalizeToPx(MAGNIFIER_WIDTH) * viewScale),
249         SkSamplingOptions(), nullptr, SkCanvas::kStrict_SrcRectConstraint);
250     canvas->restore();
251 #else
252     RSRoundRect rrect(
253         RSRect(globalX, globalY, NormalizeToPx(MAGNIFIER_WIDTH) + globalX, NormalizeToPx(MAGNIFIER_WIDTH) + globalY),
254         NormalizeToPx(MAGNIFIER_WIDTH), NormalizeToPx(MAGNIFIER_WIDTH));
255     RSRecordingPath path;
256     path.AddRoundRect(rrect);
257 
258     RosenDecorationPainter::PaintShadow(
259         path, ShadowConfig::DefaultShadowM, static_cast<RosenRenderContext*>(&context)->GetRSNode());
260 
261     RSRoundRect ScaleRrect(RSRect(globalX * viewScale, globalY * viewScale,
262                                NormalizeToPx(MAGNIFIER_WIDTH) * viewScale + globalX * viewScale,
263                                NormalizeToPx(MAGNIFIER_WIDTH) * viewScale + globalY * viewScale),
264         NormalizeToPx(MAGNIFIER_WIDTH) * viewScale, NormalizeToPx(MAGNIFIER_WIDTH) * viewScale);
265 
266     canvas->Save();
267     canvas->Scale(1.0 / viewScale, 1.0 / viewScale);
268     RSBrush brush;
269     canvas->ClipRoundRect(ScaleRrect, RSClipOp::INTERSECT, true);
270 
271     brush.SetColor(RSColor::COLOR_WHITE);
272     brush.SetAntiAlias(true);
273     canvas->AttachBrush(brush);
274     canvas->DrawRoundRect(ScaleRrect);
275     canvas->DetachBrush();
276 
277     RSImage image;
278     image.BuildFromBitmap(bitmap);
279     canvas->DrawImageRect(image,
280         RSRect(x * viewScale * MAGNIFIER_GAIN + FIXED_OFFSET, y * viewScale * MAGNIFIER_GAIN + FIXED_OFFSET,
281             NormalizeToPx(MAGNIFIER_WIDTH) * viewScale + (x * viewScale * MAGNIFIER_GAIN + FIXED_OFFSET),
282             NormalizeToPx(MAGNIFIER_WIDTH) * viewScale + (y * viewScale * MAGNIFIER_GAIN + FIXED_OFFSET)),
283         RSRect(globalX * viewScale, globalY * viewScale,
284             NormalizeToPx(MAGNIFIER_WIDTH) * viewScale + globalX * viewScale,
285             NormalizeToPx(MAGNIFIER_WIDTH) * viewScale + globalY * viewScale),
286         RSSamplingOptions());
287     canvas->Restore();
288 #endif
289 }
290 
291 #ifndef USE_ROSEN_DRAWING
PaintClipLine(SkCanvas * skCanvas,SkPaint paint)292 void RosenRenderTextOverlay::PaintClipLine(SkCanvas* skCanvas, SkPaint paint)
293 {
294     if (!skCanvas) {
295         LOGE("Paint skCanvas is null");
296         return;
297     }
298 
299     if (LessOrEqual(clipWidth_, 0.0)) {
300         return;
301     }
302 
303     paint.setStrokeWidth(NormalizeToPx(Dimension(clipWidth_, DimensionUnit::VP)));
304     paint.setColor(clipColor_.GetValue());
305     SkPath linePath;
306     linePath.moveTo(SkDoubleToScalar(NormalizeToPx(CLIP_ORIGIN_X)), SkDoubleToScalar(NormalizeToPx(CLIP_ORIGIN_Y)));
307     linePath.rLineTo(SkDoubleToScalar(NormalizeToPx(CLIP_LENGTH)), SkDoubleToScalar(NormalizeToPx(CLIP_LENGTH)));
308     skCanvas->drawPath(linePath, paint);
309 }
310 #else
PaintClipLine(RSCanvas * canvas,RSPen pen)311 void RosenRenderTextOverlay::PaintClipLine(RSCanvas* canvas, RSPen pen)
312 {
313     if (!canvas) {
314         LOGE("Paint canvas is null");
315         return;
316     }
317 
318     if (LessOrEqual(clipWidth_, 0.0)) {
319         return;
320     }
321 
322     pen.SetWidth(NormalizeToPx(Dimension(clipWidth_, DimensionUnit::VP)));
323     pen.SetColor(clipColor_.GetValue());
324     RSRecordingPath linePath;
325     linePath.MoveTo(static_cast<float>(NormalizeToPx(CLIP_ORIGIN_X)), static_cast<float>(NormalizeToPx(CLIP_ORIGIN_Y)));
326     // Drawing is not supported
327     canvas->AttachPen(pen);
328     canvas->DrawPath(linePath);
329     canvas->DetachPen();
330 }
331 #endif
332 
InitMoreButtonPaintColor()333 void RosenRenderTextOverlay::InitMoreButtonPaintColor()
334 {
335     RefPtr<TextOverlayTheme> theme = GetTheme<TextOverlayTheme>();
336     if (theme) {
337         clipColor_ = theme->GetMenuBackgroundColor();
338         arrowColor_ = theme->GetMenuButtonTextStyle().GetTextColor();
339     }
340 }
341 
CalculateMoreButtonCenter()342 Offset RosenRenderTextOverlay::CalculateMoreButtonCenter()
343 {
344     Offset offset = moreButtonPosition_;
345     if (textDirection_ == TextDirection::RTL) {
346         offset += Offset(NormalizeToPx(ICON_PADDING), NormalizeToPx(ICON_PADDING));
347     } else {
348         offset += Offset(-NormalizeToPx(ICON_SIZE + ICON_PADDING), NormalizeToPx(ICON_PADDING));
349     }
350     RefPtr<TextOverlayTheme> theme = GetTheme<TextOverlayTheme>();
351     if (theme) {
352         auto padding = theme->GetMenuPadding();
353         if (textDirection_ == TextDirection::RTL) {
354             offset += Offset(NormalizeToPx(padding.Left()), NormalizeToPx(padding.Top()));
355         } else {
356             offset += Offset(-NormalizeToPx(padding.Right()), NormalizeToPx(padding.Top()));
357         }
358     }
359     return offset;
360 }
361 
CheckNeedPaintMore()362 bool RosenRenderTextOverlay::CheckNeedPaintMore()
363 {
364     auto overlay = overlayComponent_.Upgrade();
365     if (overlay && !overlay->HasMoreButton()) {
366         return false;
367     }
368 
369     if (isDragging_) {
370         return false;
371     }
372 
373     if (hasPoped_ || GetChildren().empty()) {
374         RestoreMoreButtonStyle();
375         return false;
376     }
377 
378     if (HasToolBarOnly()) {
379         RestoreMoreButtonStyle();
380     }
381 
382     return true;
383 }
384 
PaintMore(RenderContext & context)385 void RosenRenderTextOverlay::PaintMore(RenderContext& context)
386 {
387     if (!CheckNeedPaintMore()) {
388         return;
389     }
390 
391     const auto renderContext = static_cast<RosenRenderContext*>(&context);
392     auto canvas = renderContext->GetCanvas();
393     if (canvas == nullptr) {
394         LOGE("Paint canvas is null");
395         return;
396     }
397 
398     auto pipelineContext = context_.Upgrade();
399     double dipScale = 1.0;
400     if (pipelineContext) {
401         dipScale = pipelineContext->GetDipScale();
402     }
403     InitMoreButtonPaintColor();
404     Offset moreOffset = CalculateMoreButtonCenter();
405     Offset center = (DOT1_POSITION + DOT4_POSITION) * dipScale * HALF;
406 #ifndef USE_ROSEN_DRAWING
407     canvas->save();
408     canvas->translate(moreOffset.GetX() + center.GetX(), moreOffset.GetY() + center.GetY());
409     if (textDirection_ == TextDirection::RTL) {
410         // mirror effect
411         canvas->scale(-1.0, 1.0);
412     }
413     canvas->rotate(rotateDegree_);
414     canvas->translate(-center.GetX(), -center.GetY());
415 
416     Offset topLeft = (DOT1_POSITION + dot1StartOffset_) * dipScale;
417     Offset topRight = (DOT2_POSITION + dot2StartOffset_) * dipScale;
418     Offset bottomLeft = (DOT3_POSITION + dot3StartOffset_) * dipScale;
419     Offset bottomRight = (DOT4_POSITION + dot4StartOffset_) * dipScale;
420 
421     SkPaint skPaint;
422     skPaint.setAntiAlias(true);
423     skPaint.setColor(arrowColor_.GetValue());
424     skPaint.setStyle(SkPaint::Style::kStroke_Style);
425     skPaint.setStrokeWidth(NormalizeToPx(strokeWidth_));
426     skPaint.setStrokeCap(SkPaint::Cap::kRound_Cap);
427 
428     SkPath path;
429     path.moveTo(SkDoubleToScalar(topLeft.GetX()), SkDoubleToScalar(topLeft.GetY()));
430     path.lineTo(SkDoubleToScalar(topLeft.GetX()), SkDoubleToScalar(topLeft.GetY()));
431     path.moveTo(SkDoubleToScalar(topRight.GetX()), SkDoubleToScalar(topRight.GetY()));
432     path.rLineTo(SkDoubleToScalar(dot2Offset_.GetX() * dipScale), SkDoubleToScalar(0.0));
433     path.moveTo(SkDoubleToScalar(bottomLeft.GetX()), SkDoubleToScalar(bottomLeft.GetY()));
434     path.rLineTo(SkDoubleToScalar(0.0), SkDoubleToScalar(dot3Offset_.GetY() * dipScale));
435     path.moveTo(SkDoubleToScalar(bottomRight.GetX()), SkDoubleToScalar(bottomRight.GetY()));
436     path.rLineTo(SkDoubleToScalar(dot4Offset_.GetX() * dipScale), SkDoubleToScalar(dot4Offset_.GetY() * dipScale));
437     canvas->drawPath(path, skPaint);
438 
439     PaintClipLine(canvas, skPaint);
440     canvas->restore();
441 #else
442     canvas->Save();
443     canvas->Translate(moreOffset.GetX() + center.GetX(), moreOffset.GetY() + center.GetY());
444     if (textDirection_ == TextDirection::RTL) {
445         // mirror effect
446         canvas->Scale(-1.0, 1.0);
447     }
448     canvas->Rotate(rotateDegree_);
449     canvas->Translate(-center.GetX(), -center.GetY());
450 
451     Offset topLeft = (DOT1_POSITION + dot1StartOffset_) * dipScale;
452     Offset topRight = (DOT2_POSITION + dot2StartOffset_) * dipScale;
453     Offset bottomLeft = (DOT3_POSITION + dot3StartOffset_) * dipScale;
454     Offset bottomRight = (DOT4_POSITION + dot4StartOffset_) * dipScale;
455 
456     RSPen pen;
457     pen.SetAntiAlias(true);
458     pen.SetColor(arrowColor_.GetValue());
459     pen.SetWidth(NormalizeToPx(strokeWidth_));
460     pen.SetCapStyle(RSPen::CapStyle::ROUND_CAP);
461 
462     RSRecordingPath path;
463     path.MoveTo(static_cast<float>(topLeft.GetX()), static_cast<float>(topLeft.GetY()));
464     path.LineTo(static_cast<float>(topLeft.GetX()), static_cast<float>(topLeft.GetY()));
465     path.MoveTo(static_cast<float>(topRight.GetX()), static_cast<float>(topRight.GetY()));
466     // Drawing is not supported
467     path.MoveTo(static_cast<float>(bottomLeft.GetX()), static_cast<float>(bottomLeft.GetY()));
468     // Drawing is not supported
469     path.MoveTo(static_cast<float>(bottomRight.GetX()), static_cast<float>(bottomRight.GetY()));
470     // Drawing is not supported
471     canvas->AttachPen(pen);
472     canvas->DrawPath(path);
473     canvas->DetachPen();
474 
475     PaintClipLine(canvas, pen);
476     canvas->Restore();
477 #endif
478 }
479 
AdjustForAnimation()480 void RosenRenderTextOverlay::AdjustForAnimation()
481 {
482     ResetRenderChild();
483     InitRenderChild(AceType::Claim(this));
484     if (!renderBox_ || !renderClip_) {
485         return;
486     }
487     double moreButtonSize = NormalizeToPx(MORE_BUTTON_SIZE);
488 
489     // Adjust box and menu for painting before animation.
490     if (!isAnimationStarted_ && GetChildren().front()) {
491         if (hasMenu_) {
492             if (renderMenu_) {
493                 renderMenu_->SetIsWattingForAnimationStart(true);
494             }
495         } else {
496             renderBox_->SetPaintSize(Size(moreButtonSize, moreButtonSize));
497             renderBox_->SetPosition(Offset(GetChildren().front()->GetLayoutSize().Width() - moreButtonSize, 0.0));
498         }
499     } else {
500         if (renderMenu_) {
501             renderMenu_->SetIsWattingForAnimationStart(false);
502         }
503     }
504 
505     // Adjust box for painting after animation.
506     if (isAnimationStopped_ && hasMenu_ && GetChildren().front()) {
507         renderBox_->SetPaintSize(Size(moreButtonSize, moreButtonSize));
508         renderBox_->SetPosition(Offset(GetChildren().front()->GetLayoutSize().Width() - moreButtonSize, 0.0));
509     }
510 }
511 
NeedAdjustEndHandle()512 bool RosenRenderTextOverlay::NeedAdjustEndHandle()
513 {
514     auto textField = weakTextField_.Upgrade();
515     auto rosenTextField = AceType::DynamicCast<RosenRenderTextField>(textField);
516     if (!rosenTextField) {
517         LOGE("RosenTextField is nullptr");
518         return false;
519     }
520     return rosenTextField->GetEditingValue().selection.GetEnd() <= startIndex_;
521 }
522 
NeedAdjustStartHandle()523 bool RosenRenderTextOverlay::NeedAdjustStartHandle()
524 {
525     auto textField = weakTextField_.Upgrade();
526     auto rosenTextField = AceType::DynamicCast<RosenRenderTextField>(textField);
527     if (!rosenTextField) {
528         LOGE("RosenTextField is nullptr");
529         return false;
530     }
531     return rosenTextField->GetEditingValue().selection.GetEnd() > endIndex_;
532 }
533 
534 } // namespace OHOS::Ace
535