• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022 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 "drag_window_ohos.h"
17 
18 #include "rosen_text/typography.h"
19 
20 #include "include/core/SkCanvas.h"
21 #include "include/core/SkSamplingOptions.h"
22 
23 #include "adapter/ohos/entrance/rs_adapter.h"
24 #include "base/geometry/ng/rect_t.h"
25 #include "base/geometry/offset.h"
26 #include "base/image/pixel_map.h"
27 #include "base/log/log_wrapper.h"
28 #include "base/utils/utils.h"
29 #include "core/components/text/render_text.h"
30 #include "core/components_ng/base/frame_node.h"
31 #include "core/components_ng/pattern/text/text_pattern.h"
32 #include "core/components_ng/render/adapter/rosen_render_context.h"
33 #include "core/components_ng/render/adapter/drawing_image.h"
34 #include "core/components_ng/render/drawing.h"
35 #include "core/pipeline_ng/pipeline_context.h"
36 
37 #include "render_service_client/core/ui/rs_root_node.h"
38 #include "render_service_client/core/ui/rs_surface_node.h"
39 
40 using namespace OHOS::Rosen;
41 
42 namespace OHOS::Ace {
43 #ifdef ENABLE_ROSEN_BACKEND
44 namespace {
45 // Adapt text dragging background shadows to expand the width of dargwindow
46 const Dimension Window_EXTERN = 10.0_vp;
47 
AlphaTypeToAlphaType(const RefPtr<PixelMap> & pixmap)48 RSAlphaType AlphaTypeToAlphaType(const RefPtr<PixelMap>& pixmap)
49 {
50     switch (pixmap->GetAlphaType()) {
51         case AlphaType::IMAGE_ALPHA_TYPE_UNKNOWN:
52             return RSAlphaType::ALPHATYPE_UNKNOWN;
53         case AlphaType::IMAGE_ALPHA_TYPE_OPAQUE:
54             return RSAlphaType::ALPHATYPE_OPAQUE;
55         case AlphaType::IMAGE_ALPHA_TYPE_PREMUL:
56             return RSAlphaType::ALPHATYPE_PREMUL;
57         case AlphaType::IMAGE_ALPHA_TYPE_UNPREMUL:
58             return RSAlphaType::ALPHATYPE_UNPREMUL;
59         default:
60             return RSAlphaType::ALPHATYPE_UNKNOWN;
61     }
62 }
63 
PixelFormatToColorType(const RefPtr<PixelMap> & pixmap)64 RSColorType PixelFormatToColorType(const RefPtr<PixelMap>& pixmap)
65 {
66     switch (pixmap->GetPixelFormat()) {
67         case PixelFormat::RGB_565:
68             return RSColorType::COLORTYPE_RGB_565;
69         case PixelFormat::RGBA_8888:
70             return RSColorType::COLORTYPE_RGBA_8888;
71         case PixelFormat::BGRA_8888:
72             return RSColorType::COLORTYPE_BGRA_8888;
73         case PixelFormat::ALPHA_8:
74             return RSColorType::COLORTYPE_ALPHA_8;
75         case PixelFormat::RGBA_F16:
76             return RSColorType::COLORTYPE_RGBA_F16;
77         case PixelFormat::UNKNOWN:
78         case PixelFormat::ARGB_8888:
79         case PixelFormat::RGB_888:
80         case PixelFormat::NV21:
81         case PixelFormat::NV12:
82         case PixelFormat::CMYK:
83         default:
84             return RSColorType::COLORTYPE_UNKNOWN;
85     }
86 }
87 
MakeBitmapFormatFromPixelMap(const RefPtr<PixelMap> & pixmap)88 RSBitmapFormat MakeBitmapFormatFromPixelMap(const RefPtr<PixelMap>& pixmap)
89 {
90     RSBitmapFormat format;
91     format.colorType = PixelFormatToColorType(pixmap);
92     format.alphaType = AlphaTypeToAlphaType(pixmap);
93     return format;
94 }
95 
DrawDrawingImage(RSCanvas * canvas,const std::shared_ptr<RSImage> & drawingImage,int32_t width,int32_t height)96 void DrawDrawingImage(RSCanvas* canvas, const std::shared_ptr<RSImage>& drawingImage, int32_t width, int32_t height)
97 {
98     CHECK_NULL_VOID(drawingImage);
99     RSBrush brush;
100     auto colorSpace = RSRecordingColorSpace::CreateRefImage(*drawingImage);
101     brush.SetColor(brush.GetColor4f(), colorSpace);
102     auto srcRect = RSRect(0, 0, drawingImage->GetWidth(), drawingImage->GetHeight());
103     auto dstRect = RSRect(0, 0, width, height);
104     RSSamplingOptions sampling;
105     canvas->AttachBrush(brush);
106     canvas->DrawImageRect(
107         *drawingImage, srcRect, dstRect, sampling, Drawing::SrcRectConstraint::FAST_SRC_RECT_CONSTRAINT);
108     canvas->DetachBrush();
109 }
110 
DrawPixelMapInner(RSCanvas * canvas,const RefPtr<PixelMap> & pixmap,int32_t width,int32_t height)111 void DrawPixelMapInner(RSCanvas* canvas, const RefPtr<PixelMap>& pixmap, int32_t width, int32_t height)
112 {
113     // Step1: Create Bitmap
114     auto bitmapFormat = MakeBitmapFormatFromPixelMap(pixmap);
115     auto bitmap = std::make_shared<RSBitmap>();
116     bitmap->Build(pixmap->GetWidth(), pixmap->GetHeight(), bitmapFormat);
117     bitmap->SetPixels(const_cast<void*>(reinterpret_cast<const void*>(pixmap->GetPixels())));
118 
119     // Step2: Create Image and draw it
120     auto image = std::make_shared<RSImage>();
121     image->BuildFromBitmap(*bitmap);
122     DrawDrawingImage(canvas, image, width, height);
123 }
124 } // namespace
125 #endif
126 
CreateDragWindow(const std::string & windowName,int32_t x,int32_t y,uint32_t width,uint32_t height)127 RefPtr<DragWindow> DragWindow::CreateDragWindow(
128     const std::string& windowName, int32_t x, int32_t y, uint32_t width, uint32_t height)
129 {
130     return CreateDragWindow({ windowName, x, y, width, height });
131 }
132 
CreateDragWindow(const DragWindowParams & params)133 RefPtr<DragWindow> DragWindow::CreateDragWindow(const DragWindowParams& params)
134 {
135     int32_t halfWidth = static_cast<int32_t>(params.width) / 2;
136     int32_t halfHeight = static_cast<int32_t>(params.height) / 2;
137 
138     OHOS::sptr<OHOS::Rosen::WindowOption> option = new OHOS::Rosen::WindowOption();
139     option->SetWindowRect({ params.x - halfWidth, params.y - halfHeight, params.width, params.height });
140     option->SetHitOffset(halfWidth, halfHeight);
141     if (params.parentWindowId == -1) {
142         option->SetWindowType(OHOS::Rosen::WindowType::WINDOW_TYPE_DRAGGING_EFFECT);
143     } else {
144         option->SetParentId(params.parentWindowId);
145         option->SetWindowType(OHOS::Rosen::WindowType::WINDOW_TYPE_APP_SUB_WINDOW);
146     }
147     option->SetWindowMode(OHOS::Rosen::WindowMode::WINDOW_MODE_FLOATING);
148     option->SetFocusable(false);
149     OHOS::sptr<OHOS::Rosen::Window> dragWindow = OHOS::Rosen::Window::Create(params.windowName, option);
150     CHECK_NULL_RETURN(dragWindow, nullptr);
151 
152     OHOS::Rosen::WMError ret = dragWindow->MoveTo(params.x - halfWidth, params.y - halfHeight, true);
153     if (ret != OHOS::Rosen::WMError::WM_OK) {
154         TAG_LOGE(AceLogTag::ACE_DRAG, "DragWindow MoveTo, drag window move failed, ret: %d", ret);
155         return nullptr;
156     }
157 
158     ret = dragWindow->Show();
159     if (ret != OHOS::Rosen::WMError::WM_OK) {
160         TAG_LOGE(AceLogTag::ACE_DRAG, "DragWindow CreateDragWindow, drag window Show() failed, ret: %d", ret);
161         return nullptr;
162     }
163 
164     auto window = AceType::MakeRefPtr<DragWindowOhos>(dragWindow);
165     window->SetSize(params.width, params.height);
166     return window;
167 }
168 
CreateTextDragWindow(const std::string & windowName,int32_t x,int32_t y,uint32_t width,uint32_t height)169 RefPtr<DragWindow> DragWindow::CreateTextDragWindow(
170     const std::string& windowName, int32_t x, int32_t y, uint32_t width, uint32_t height)
171 {
172     int32_t halfWidth = static_cast<int32_t>(width + Window_EXTERN.ConvertToPx() * 2) / 2;
173     int32_t halfHeight = static_cast<int32_t>(height + Window_EXTERN.ConvertToPx() * 2) / 2;
174 
175     OHOS::sptr<OHOS::Rosen::WindowOption> option = new OHOS::Rosen::WindowOption();
176     option->SetWindowRect({ static_cast<int32_t>(x - Window_EXTERN.ConvertToPx()),
177         static_cast<int32_t>(y - Window_EXTERN.ConvertToPx()),
178         static_cast<int32_t>(width + Window_EXTERN.ConvertToPx() * 2),
179         static_cast<int32_t>(height + Window_EXTERN.ConvertToPx() * 2) });
180     option->SetHitOffset(halfWidth, halfHeight);
181     option->SetWindowType(OHOS::Rosen::WindowType::WINDOW_TYPE_DRAGGING_EFFECT);
182     option->SetWindowMode(OHOS::Rosen::WindowMode::WINDOW_MODE_FLOATING);
183     option->SetFocusable(false);
184     OHOS::sptr<OHOS::Rosen::Window> dragWindow = OHOS::Rosen::Window::Create(windowName, option);
185     CHECK_NULL_RETURN(dragWindow, nullptr);
186 
187     OHOS::Rosen::WMError ret = dragWindow->Show();
188     if (ret != OHOS::Rosen::WMError::WM_OK) {
189         TAG_LOGE(AceLogTag::ACE_DRAG, "DragWindow CreateTextDragWindow, drag window Show() failed, ret: %d", ret);
190     }
191 
192     auto window = AceType::MakeRefPtr<DragWindowOhos>(dragWindow);
193     window->SetSize(width + Window_EXTERN.ConvertToPx() * 2, height + Window_EXTERN.ConvertToPx() * 2);
194     return window;
195 }
196 
MoveTo(int32_t x,int32_t y) const197 void DragWindowOhos::MoveTo(int32_t x, int32_t y) const
198 {
199     CHECK_NULL_VOID(dragWindow_);
200 
201     OHOS::Rosen::WMError ret = dragWindow_->MoveTo(x + offsetX_ - width_ / 2, y + offsetY_ - height_ / 2, true);
202     if (ret != OHOS::Rosen::WMError::WM_OK) {
203         TAG_LOGE(AceLogTag::ACE_DRAG, "DragWindow MoveTo, drag window move failed, ret: %d", ret);
204         return;
205     }
206 
207     ret = dragWindow_->Show();
208     if (ret != OHOS::Rosen::WMError::WM_OK) {
209         TAG_LOGE(AceLogTag::ACE_DRAG, "DragWindow CreateDragWindow, drag window Show() failed, ret: %d", ret);
210     }
211 }
212 
TextDragWindowMove(double x,double y) const213 void DragWindowOhos::TextDragWindowMove(double x, double y) const
214 {
215     CHECK_NULL_VOID(dragWindow_);
216     OHOS::Rosen::WMError ret =
217         dragWindow_->MoveTo(x - Window_EXTERN.ConvertToPx() + offsetX_, y + offsetY_ - Window_EXTERN.ConvertToPx());
218     if (ret != OHOS::Rosen::WMError::WM_OK) {
219         TAG_LOGE(AceLogTag::ACE_DRAG, "DragWindow TextDragWindowMove, drag window move failed, ret: %d", ret);
220         return;
221     }
222 
223     ret = dragWindow_->Show();
224     if (ret != OHOS::Rosen::WMError::WM_OK) {
225         TAG_LOGE(AceLogTag::ACE_DRAG, "DragWindow TextDragWindowMove, drag window Show() failed, ret: %d", ret);
226     }
227 }
228 
Destroy() const229 void DragWindowOhos::Destroy() const
230 {
231     CHECK_NULL_VOID(dragWindow_);
232 
233     OHOS::Rosen::WMError ret = dragWindow_->Destroy();
234     if (ret != OHOS::Rosen::WMError::WM_OK) {
235         TAG_LOGE(AceLogTag::ACE_DRAG, "DragWindow Destroy, drag window destroy failed, ret: %d", ret);
236     }
237 }
238 
FlushImplicitTransaction()239 void DragWindowOhos::FlushImplicitTransaction()
240 {
241     auto transactionProxy = Rosen::RSTransactionProxy::GetInstance();
242     if (transactionProxy != nullptr) {
243         transactionProxy->FlushImplicitTransaction();
244     }
245 }
246 
DrawFrameNode(const RefPtr<NG::FrameNode> & rootNode)247 void DragWindowOhos::DrawFrameNode(const RefPtr<NG::FrameNode>& rootNode)
248 {
249 #ifdef ENABLE_ROSEN_BACKEND
250     CHECK_NULL_VOID(rootNode);
251     auto surfaceNode = dragWindow_->GetSurfaceNode();
252     RsAdapter::RsFlushImplicitTransaction(rsUiDirector_, dragWindow_, surfaceNode);
253     auto renderContext = AceType::DynamicCast<NG::RosenRenderContext>(rootNode->GetRenderContext());
254     CHECK_NULL_VOID(renderContext);
255     auto rsNode = renderContext->GetRSNode();
256     CHECK_NULL_VOID(rsNode);
257     rsUiDirector_->SetRSRootNode(Rosen::RSNode::ReinterpretCast<Rosen::RSRootNode>(rsNode));
258     rsUiDirector_->SendMessages();
259 #endif
260 }
261 
DrawPixelMap(const RefPtr<PixelMap> & pixelmap)262 void DragWindowOhos::DrawPixelMap(const RefPtr<PixelMap>& pixelmap)
263 {
264 #ifdef ENABLE_ROSEN_BACKEND
265     CHECK_NULL_VOID(pixelmap);
266     auto surfaceNode = dragWindow_->GetSurfaceNode();
267     RsAdapter::RsFlushImplicitTransactionWithRoot(rsUiDirector_, dragWindow_, surfaceNode, rootNode_);
268     CHECK_NULL_VOID(rootNode_);
269     rootNode_->SetBounds(0, 0, static_cast<float>(width_), static_cast<float>(height_));
270     rootNode_->SetFrame(0, 0, static_cast<float>(width_), static_cast<float>(height_));
271     rsUiDirector_->SetRSRootNode(Rosen::RSNode::ReinterpretCast<Rosen::RSRootNode>(rootNode_));
272     auto canvasNode = std::static_pointer_cast<Rosen::RSCanvasNode>(rootNode_);
273     auto drawing = canvasNode->BeginRecording(width_, height_);
274     DrawPixelMapInner(drawing, pixelmap, width_, height_);
275     canvasNode->FinishRecording();
276     rsUiDirector_->SendMessages();
277 #endif
278 }
279 
DrawImage(void * drawingImage)280 void DragWindowOhos::DrawImage(void* drawingImage)
281 {
282 #ifdef ENABLE_ROSEN_BACKEND
283     CHECK_NULL_VOID(drawingImage);
284     auto* canvasImagePtr = reinterpret_cast<RefPtr<NG::CanvasImage>*>(drawingImage);
285     CHECK_NULL_VOID(canvasImagePtr);
286     RefPtr<NG::DrawingImage> canvasImage = AceType::DynamicCast<NG::DrawingImage>(*canvasImagePtr);
287     CHECK_NULL_VOID(canvasImage);
288     auto surfaceNode = dragWindow_->GetSurfaceNode();
289     RsAdapter::RsFlushImplicitTransactionWithRoot(rsUiDirector_, dragWindow_, surfaceNode, rootNode_);
290     CHECK_NULL_VOID(rootNode_);
291     rootNode_->SetBounds(0, 0, static_cast<float>(width_), static_cast<float>(height_));
292     rootNode_->SetFrame(0, 0, static_cast<float>(width_), static_cast<float>(height_));
293     rsUiDirector_->SetRSRootNode(Rosen::RSNode::ReinterpretCast<Rosen::RSRootNode>(rootNode_));
294     auto canvasNode = std::static_pointer_cast<Rosen::RSCanvasNode>(rootNode_);
295     auto drawing = canvasNode->BeginRecording(width_, height_);
296     auto rsImage = canvasImage->GetImage();
297     DrawDrawingImage(drawing, rsImage, width_, height_);
298     canvasNode->FinishRecording();
299     rsUiDirector_->SendMessages();
300 #endif
301 }
302 
DrawText(std::shared_ptr<Rosen::Typography> paragraph,const Offset & offset,const RefPtr<RenderText> & renderText)303 void DragWindowOhos::DrawText(
304     std::shared_ptr<Rosen::Typography> paragraph, const Offset& offset, const RefPtr<RenderText>& renderText)
305 {
306 #ifndef NG_BUILD
307 #ifdef ENABLE_ROSEN_BACKEND
308     CHECK_NULL_VOID(paragraph);
309     auto surfaceNode = dragWindow_->GetSurfaceNode();
310     RsAdapter::RsFlushImplicitTransactionWithRoot(rsUiDirector_, dragWindow_, surfaceNode, rootNode_);
311     CHECK_NULL_VOID(rootNode_);
312     rootNode_->SetBounds(0, 0, static_cast<float>(width_), static_cast<float>(height_));
313     rootNode_->SetFrame(0, 0, static_cast<float>(width_), static_cast<float>(height_));
314     rsUiDirector_->SetRSRootNode(Rosen::RSNode::ReinterpretCast<Rosen::RSRootNode>(rootNode_));
315     auto canvasNode = std::static_pointer_cast<Rosen::RSCanvasNode>(rootNode_);
316     RSRecordingPath path;
317     if (renderText->GetStartOffset().GetY() == renderText->GetEndOffset().GetY()) {
318         path.MoveTo(renderText->GetStartOffset().GetX() - renderText->GetGlobalOffset().GetX(),
319             renderText->GetStartOffset().GetY() - renderText->GetGlobalOffset().GetY());
320         path.LineTo(renderText->GetEndOffset().GetX() - renderText->GetGlobalOffset().GetX(),
321             renderText->GetEndOffset().GetY() - renderText->GetGlobalOffset().GetY());
322         path.LineTo(renderText->GetEndOffset().GetX() - renderText->GetGlobalOffset().GetX(),
323             renderText->GetEndOffset().GetY() - renderText->GetSelectHeight() - renderText->GetGlobalOffset().GetY());
324         path.LineTo(renderText->GetStartOffset().GetX() - renderText->GetGlobalOffset().GetX(),
325             renderText->GetStartOffset().GetY() - renderText->GetSelectHeight() - renderText->GetGlobalOffset().GetY());
326         path.LineTo(renderText->GetStartOffset().GetX() - renderText->GetGlobalOffset().GetX(),
327             renderText->GetStartOffset().GetY() - renderText->GetGlobalOffset().GetY());
328     } else {
329         path.MoveTo(renderText->GetStartOffset().GetX() - renderText->GetGlobalOffset().GetX(),
330             renderText->GetStartOffset().GetY() - renderText->GetGlobalOffset().GetY());
331         path.LineTo(renderText->GetStartOffset().GetX() - renderText->GetGlobalOffset().GetX(),
332             renderText->GetStartOffset().GetY() - renderText->GetSelectHeight() - renderText->GetGlobalOffset().GetY());
333         path.LineTo(renderText->GetPaintRect().Right() - renderText->GetGlobalOffset().GetX(),
334             renderText->GetStartOffset().GetY() - renderText->GetSelectHeight() - renderText->GetGlobalOffset().GetY());
335         path.LineTo(renderText->GetPaintRect().Right() - renderText->GetGlobalOffset().GetX(),
336             renderText->GetEndOffset().GetY() - renderText->GetSelectHeight() - renderText->GetGlobalOffset().GetY());
337         path.LineTo(renderText->GetEndOffset().GetX() - renderText->GetGlobalOffset().GetX(),
338             renderText->GetEndOffset().GetY() - renderText->GetSelectHeight() - renderText->GetGlobalOffset().GetY());
339         path.LineTo(renderText->GetEndOffset().GetX() - renderText->GetGlobalOffset().GetX(),
340             renderText->GetEndOffset().GetY() - renderText->GetGlobalOffset().GetY());
341         path.LineTo(renderText->GetPaintRect().Left() - renderText->GetGlobalOffset().GetX(),
342             renderText->GetEndOffset().GetY() - renderText->GetGlobalOffset().GetY());
343         path.LineTo(renderText->GetPaintRect().Left() - renderText->GetGlobalOffset().GetX(),
344             renderText->GetStartOffset().GetY() - renderText->GetGlobalOffset().GetY());
345         path.LineTo(renderText->GetStartOffset().GetX() - renderText->GetGlobalOffset().GetX(),
346             renderText->GetStartOffset().GetY() - renderText->GetGlobalOffset().GetY());
347     }
348     rootNode_->SetClipToBounds(true);
349     rootNode_->SetClipBounds(Rosen::RSPath::CreateRSPath(path));
350     auto recordingCanvas = canvasNode->BeginRecording(width_, height_);
351     paragraph->Paint(recordingCanvas, 0, 0);
352     canvasNode->FinishRecording();
353     rsUiDirector_->SendMessages();
354 #endif
355 #endif
356 }
357 
DrawTextNG(const RefPtr<NG::Paragraph> & paragraph,const RefPtr<NG::TextPattern> & textPattern)358 void DragWindowOhos::DrawTextNG(const RefPtr<NG::Paragraph>& paragraph, const RefPtr<NG::TextPattern>& textPattern)
359 {
360 #ifdef ENABLE_ROSEN_BACKEND
361     CHECK_NULL_VOID(paragraph);
362     auto surfaceNode = dragWindow_->GetSurfaceNode();
363     RsAdapter::RsFlushImplicitTransactionWithRoot(rsUiDirector_, dragWindow_, surfaceNode, rootNode_);
364     CHECK_NULL_VOID(rootNode_);
365     rootNode_->SetBounds(Window_EXTERN.ConvertToPx(), Window_EXTERN.ConvertToPx(), static_cast<float>(width_),
366         static_cast<float>(height_));
367     rootNode_->SetFrame(Window_EXTERN.ConvertToPx(), Window_EXTERN.ConvertToPx(), static_cast<float>(width_),
368         static_cast<float>(height_));
369     rsUiDirector_->SetRSRootNode(Rosen::RSNode::ReinterpretCast<Rosen::RSRootNode>(rootNode_));
370     auto canvasNode = std::static_pointer_cast<Rosen::RSCanvasNode>(rootNode_);
371     CHECK_NULL_VOID(canvasNode);
372     Offset globalOffset;
373     textPattern->GetGlobalOffset(globalOffset);
374     RSRecordingPath path;
375     if (textPattern->GetStartOffset().GetY() == textPattern->GetEndOffset().GetY()) {
376         path.MoveTo(textPattern->GetStartOffset().GetX() - globalOffset.GetX(),
377             textPattern->GetStartOffset().GetY() - globalOffset.GetY());
378         path.LineTo(textPattern->GetEndOffset().GetX() - globalOffset.GetX(),
379             textPattern->GetEndOffset().GetY() - globalOffset.GetY());
380         path.LineTo(textPattern->GetEndOffset().GetX() - globalOffset.GetX(),
381             textPattern->GetEndOffset().GetY() + textPattern->GetSelectHeight() - globalOffset.GetY());
382         path.LineTo(textPattern->GetStartOffset().GetX() - globalOffset.GetX(),
383             textPattern->GetStartOffset().GetY() + textPattern->GetSelectHeight() - globalOffset.GetY());
384         path.LineTo(textPattern->GetStartOffset().GetX() - globalOffset.GetX(),
385             textPattern->GetStartOffset().GetY() - globalOffset.GetY());
386     } else {
387         path.MoveTo(textPattern->GetStartOffset().GetX() - globalOffset.GetX(),
388             textPattern->GetStartOffset().GetY() - globalOffset.GetY());
389         path.LineTo(
390             textPattern->GetTextContentRect().Width(), textPattern->GetStartOffset().GetY() - globalOffset.GetY());
391         path.LineTo(
392             textPattern->GetTextContentRect().Width(), textPattern->GetEndOffset().GetY() - globalOffset.GetY());
393         path.LineTo(textPattern->GetEndOffset().GetX() - globalOffset.GetX(),
394             textPattern->GetEndOffset().GetY() - globalOffset.GetY());
395         path.LineTo(textPattern->GetEndOffset().GetX() - globalOffset.GetX(),
396             textPattern->GetEndOffset().GetY() + textPattern->GetSelectHeight() - globalOffset.GetY());
397         path.LineTo(textPattern->GetTextContentRect().GetX(),
398             textPattern->GetEndOffset().GetY() + textPattern->GetSelectHeight() - globalOffset.GetY());
399         path.LineTo(textPattern->GetTextContentRect().GetX(),
400             textPattern->GetStartOffset().GetY() + textPattern->GetSelectHeight() - globalOffset.GetY());
401         path.LineTo(textPattern->GetStartOffset().GetX() - globalOffset.GetX(),
402             textPattern->GetStartOffset().GetY() + textPattern->GetSelectHeight() - globalOffset.GetY());
403         path.LineTo(textPattern->GetStartOffset().GetX() - globalOffset.GetX(),
404             textPattern->GetStartOffset().GetY() - globalOffset.GetY());
405     }
406     rootNode_->SetClipToBounds(true);
407     rootNode_->SetClipBounds(Rosen::RSPath::CreateRSPath(path));
408     auto recordingCanvas = canvasNode->BeginRecording(width_, height_);
409     paragraph->Paint(*recordingCanvas, textPattern->GetTextContentRect().GetX(),
410         textPattern->GetTextContentRect().GetY() - std::min(textPattern->GetBaselineOffset(), 0.0f));
411     canvasNode->FinishRecording();
412     rsUiDirector_->SendMessages();
413 
414     auto context = NG::PipelineContext::GetCurrentContext();
415     CHECK_NULL_VOID(context);
416     context->RequestFrame();
417 #endif
418 }
419 } // namespace OHOS::Ace
420