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