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