• 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 "flutter/fml/memory/ref_counted.h"
19 #include "flutter/lib/ui/painting/image.h"
20 #include "flutter/third_party/txt/src/txt/paragraph_txt.h"
21 #include "fml/memory/ref_ptr.h"
22 
23 #include "base/geometry/ng/rect_t.h"
24 #include "base/image/pixel_map.h"
25 #include "base/log/log_wrapper.h"
26 #include "base/utils/utils.h"
27 #include "core/components/text/render_text.h"
28 #include "core/components_ng/base/frame_node.h"
29 #include "core/components_ng/render/adapter/rosen_render_context.h"
30 
31 namespace OHOS::Ace {
32 namespace {
ColorSpaceToSkColorSpace(const RefPtr<PixelMap> & pixmap)33 sk_sp<SkColorSpace> ColorSpaceToSkColorSpace(const RefPtr<PixelMap>& pixmap)
34 {
35     return SkColorSpace::MakeSRGB(); // Media::PixelMap has not support wide gamut yet.
36 }
37 
AlphaTypeToSkAlphaType(const RefPtr<PixelMap> & pixmap)38 SkAlphaType AlphaTypeToSkAlphaType(const RefPtr<PixelMap>& pixmap)
39 {
40     switch (pixmap->GetAlphaType()) {
41         case AlphaType::IMAGE_ALPHA_TYPE_UNKNOWN:
42             return SkAlphaType::kUnknown_SkAlphaType;
43         case AlphaType::IMAGE_ALPHA_TYPE_OPAQUE:
44             return SkAlphaType::kOpaque_SkAlphaType;
45         case AlphaType::IMAGE_ALPHA_TYPE_PREMUL:
46             return SkAlphaType::kPremul_SkAlphaType;
47         case AlphaType::IMAGE_ALPHA_TYPE_UNPREMUL:
48             return SkAlphaType::kUnpremul_SkAlphaType;
49         default:
50             return SkAlphaType::kUnknown_SkAlphaType;
51     }
52 }
53 
PixelFormatToSkColorType(const RefPtr<PixelMap> & pixmap)54 SkColorType PixelFormatToSkColorType(const RefPtr<PixelMap>& pixmap)
55 {
56     switch (pixmap->GetPixelFormat()) {
57         case PixelFormat::RGB_565:
58             return SkColorType::kRGB_565_SkColorType;
59         case PixelFormat::RGBA_8888:
60             return SkColorType::kRGBA_8888_SkColorType;
61         case PixelFormat::BGRA_8888:
62             return SkColorType::kBGRA_8888_SkColorType;
63         case PixelFormat::ALPHA_8:
64             return SkColorType::kAlpha_8_SkColorType;
65         case PixelFormat::RGBA_F16:
66             return SkColorType::kRGBA_F16_SkColorType;
67         case PixelFormat::UNKNOWN:
68         case PixelFormat::ARGB_8888:
69         case PixelFormat::RGB_888:
70         case PixelFormat::NV21:
71         case PixelFormat::NV12:
72         case PixelFormat::CMYK:
73         default:
74             return SkColorType::kUnknown_SkColorType;
75     }
76 }
77 
MakeSkImageInfoFromPixelMap(const RefPtr<PixelMap> & pixmap)78 SkImageInfo MakeSkImageInfoFromPixelMap(const RefPtr<PixelMap>& pixmap)
79 {
80     SkColorType colorType = PixelFormatToSkColorType(pixmap);
81     SkAlphaType alphaType = AlphaTypeToSkAlphaType(pixmap);
82     sk_sp<SkColorSpace> colorSpace = ColorSpaceToSkColorSpace(pixmap);
83     return SkImageInfo::Make(pixmap->GetWidth(), pixmap->GetHeight(), colorType, alphaType, colorSpace);
84 }
85 
DrawSkImage(SkCanvas * canvas,const RefPtr<PixelMap> & pixmap,int32_t width,int32_t height)86 void DrawSkImage(SkCanvas* canvas, const RefPtr<PixelMap>& pixmap, int32_t width, int32_t height)
87 {
88     // Step1: Create SkPixmap
89     auto imageInfo = MakeSkImageInfoFromPixelMap(pixmap);
90     SkPixmap imagePixmap(imageInfo, reinterpret_cast<const void*>(pixmap->GetPixels()), pixmap->GetRowBytes());
91 
92     // Step2: Create SkImage and draw it
93     sk_sp<SkImage> skImage =
94         SkImage::MakeFromRaster(imagePixmap, &PixelMap::ReleaseProc, PixelMap::GetReleaseContext(pixmap));
95     CHECK_NULL_VOID(skImage);
96     SkPaint paint;
97     sk_sp<SkColorSpace> colorSpace = skImage->refColorSpace();
98 #ifdef USE_SYSTEM_SKIA
99     paint.setColor4f(paint.getColor4f(), colorSpace.get());
100 #else
101     paint.setColor(paint.getColor4f(), colorSpace.get());
102 #endif
103     auto skSrcRect = SkRect::MakeXYWH(0, 0, pixmap->GetWidth(), pixmap->GetHeight());
104     auto skDstRect = SkRect::MakeXYWH(0, 0, width, height);
105     canvas->drawImageRect(skImage, skSrcRect, skDstRect, &paint);
106 }
107 
DrawSkImage(SkCanvas * canvas,const sk_sp<SkImage> & skImage,int32_t width,int32_t height)108 void DrawSkImage(SkCanvas* canvas, const sk_sp<SkImage>& skImage, int32_t width, int32_t height)
109 {
110     CHECK_NULL_VOID(skImage);
111     SkPaint paint;
112     sk_sp<SkColorSpace> colorSpace = skImage->refColorSpace();
113 #ifdef USE_SYSTEM_SKIA
114     paint.setColor4f(paint.getColor4f(), colorSpace.get());
115 #else
116     paint.setColor(paint.getColor4f(), colorSpace.get());
117 #endif
118     auto skSrcRect = SkRect::MakeXYWH(0, 0, skImage->width(), skImage->height());
119     auto skDstRect = SkRect::MakeXYWH(0, 0, width, height);
120     canvas->drawImageRect(skImage, skSrcRect, skDstRect, &paint);
121 }
122 } // namespace
123 
CreateDragWindow(const std::string & windowName,int32_t x,int32_t y,uint32_t width,uint32_t height)124 RefPtr<DragWindow> DragWindow::CreateDragWindow(
125     const std::string& windowName, int32_t x, int32_t y, uint32_t width, uint32_t height)
126 {
127     int32_t halfWidth = static_cast<int32_t>(width) / 2;
128     int32_t halfHeight = static_cast<int32_t>(height) / 2;
129 
130     OHOS::sptr<OHOS::Rosen::WindowOption> option = new OHOS::Rosen::WindowOption();
131     option->SetWindowRect({ x - halfWidth, y - halfHeight, width, height });
132     option->SetHitOffset(halfWidth, halfHeight);
133     option->SetWindowType(OHOS::Rosen::WindowType::WINDOW_TYPE_DRAGGING_EFFECT);
134     option->SetWindowMode(OHOS::Rosen::WindowMode::WINDOW_MODE_FLOATING);
135     option->SetFocusable(false);
136     OHOS::sptr<OHOS::Rosen::Window> dragWindow = OHOS::Rosen::Window::Create(windowName, option);
137     CHECK_NULL_RETURN(dragWindow, nullptr);
138 
139     OHOS::Rosen::WMError ret = dragWindow->Show();
140     if (ret != OHOS::Rosen::WMError::WM_OK) {
141         LOGE("DragWindow::CreateDragWindow, drag window Show() failed, ret: %d", ret);
142     }
143 
144     auto window = AceType::MakeRefPtr<DragWindowOhos>(dragWindow);
145     window->SetSize(width, height);
146     return window;
147 }
148 
MoveTo(int32_t x,int32_t y) const149 void DragWindowOhos::MoveTo(int32_t x, int32_t y) const
150 {
151     CHECK_NULL_VOID(dragWindow_);
152 
153     OHOS::Rosen::WMError ret = dragWindow_->MoveTo(x + offsetX_ - width_ / 2, y + offsetY_ - height_ / 2);
154     if (ret != OHOS::Rosen::WMError::WM_OK) {
155         LOGE("DragWindow::MoveTo, drag window move failed, ret: %d", ret);
156         return;
157     }
158 
159     ret = dragWindow_->Show();
160     if (ret != OHOS::Rosen::WMError::WM_OK) {
161         LOGE("DragWindow::CreateDragWindow, drag window Show() failed, ret: %d", ret);
162     }
163 }
164 
Destroy() const165 void DragWindowOhos::Destroy() const
166 {
167     CHECK_NULL_VOID(dragWindow_);
168 
169     OHOS::Rosen::WMError ret = dragWindow_->Destroy();
170     if (ret != OHOS::Rosen::WMError::WM_OK) {
171         LOGE("DragWindow::Destroy, drag window destroy failed, ret: %d", ret);
172     }
173 }
174 
DrawFrameNode(const RefPtr<NG::FrameNode> & rootNode)175 void DragWindowOhos::DrawFrameNode(const RefPtr<NG::FrameNode>& rootNode)
176 {
177     CHECK_NULL_VOID(rootNode);
178 
179     auto surfaceNode = dragWindow_->GetSurfaceNode();
180     rsUiDirector_ = Rosen::RSUIDirector::Create();
181     rsUiDirector_->Init();
182     auto transactionProxy = Rosen::RSTransactionProxy::GetInstance();
183     if (transactionProxy != nullptr) {
184         transactionProxy->FlushImplicitTransaction();
185     }
186     rsUiDirector_->SetRSSurfaceNode(surfaceNode);
187 
188     auto renderContext = AceType::DynamicCast<NG::RosenRenderContext>(rootNode->GetRenderContext());
189     CHECK_NULL_VOID(renderContext);
190     auto rsNode = renderContext->GetRSNode();
191     CHECK_NULL_VOID(rsNode);
192 
193     rsUiDirector_->SetRoot(rsNode->GetId());
194     rsUiDirector_->SendMessages();
195 }
196 
DrawPixelMap(const RefPtr<PixelMap> & pixelmap)197 void DragWindowOhos::DrawPixelMap(const RefPtr<PixelMap>& pixelmap)
198 {
199     CHECK_NULL_VOID(pixelmap);
200     auto surfaceNode = dragWindow_->GetSurfaceNode();
201     rsUiDirector_ = Rosen::RSUIDirector::Create();
202     rsUiDirector_->Init();
203     auto transactionProxy = Rosen::RSTransactionProxy::GetInstance();
204     if (transactionProxy != nullptr) {
205         transactionProxy->FlushImplicitTransaction();
206     }
207     rsUiDirector_->SetRSSurfaceNode(surfaceNode);
208     rootNode_ = Rosen::RSRootNode::Create();
209     rootNode_->SetBounds(0, 0, static_cast<float>(width_), static_cast<float>(height_));
210     rootNode_->SetFrame(0, 0, static_cast<float>(width_), static_cast<float>(height_));
211     rsUiDirector_->SetRoot(rootNode_->GetId());
212     auto canvasNode = std::static_pointer_cast<Rosen::RSCanvasNode>(rootNode_);
213     auto skia = canvasNode->BeginRecording(width_, height_);
214     DrawSkImage(skia, pixelmap, width_, height_);
215     canvasNode->FinishRecording();
216     rsUiDirector_->SendMessages();
217 }
218 
DrawImage(void * skImage)219 void DragWindowOhos::DrawImage(void* skImage)
220 {
221     CHECK_NULL_VOID(skImage);
222     fml::RefPtr<flutter::CanvasImage>* canvasImagePtr =
223         reinterpret_cast<fml::RefPtr<flutter::CanvasImage>*>(skImage);
224     CHECK_NULL_VOID(canvasImagePtr);
225     fml::RefPtr<flutter::CanvasImage> canvasImage = *canvasImagePtr;
226     CHECK_NULL_VOID(canvasImage);
227     auto surfaceNode = dragWindow_->GetSurfaceNode();
228     rsUiDirector_ = Rosen::RSUIDirector::Create();
229     rsUiDirector_->Init();
230     auto transactionProxy = Rosen::RSTransactionProxy::GetInstance();
231     if (transactionProxy != nullptr) {
232         transactionProxy->FlushImplicitTransaction();
233     }
234     rsUiDirector_->SetRSSurfaceNode(surfaceNode);
235     rootNode_ = Rosen::RSRootNode::Create();
236     rootNode_->SetBounds(0, 0, static_cast<float>(width_), static_cast<float>(height_));
237     rootNode_->SetFrame(0, 0, static_cast<float>(width_), static_cast<float>(height_));
238     rsUiDirector_->SetRoot(rootNode_->GetId());
239     auto canvasNode = std::static_pointer_cast<Rosen::RSCanvasNode>(rootNode_);
240     auto skia = canvasNode->BeginRecording(width_, height_);
241     DrawSkImage(skia, canvasImage->image(), width_, height_);
242     canvasNode->FinishRecording();
243     rsUiDirector_->SendMessages();
244 }
245 
DrawText(std::shared_ptr<txt::Paragraph> paragraph,const Offset & offset,const RefPtr<RenderText> & renderText)246 void DragWindowOhos::DrawText(std::shared_ptr<txt::Paragraph> paragraph,
247     const Offset& offset, const RefPtr<RenderText>& renderText)
248 {
249     CHECK_NULL_VOID(paragraph);
250     auto surfaceNode = dragWindow_->GetSurfaceNode();
251     rsUiDirector_ = Rosen::RSUIDirector::Create();
252     rsUiDirector_->Init();
253     auto transactionProxy = Rosen::RSTransactionProxy::GetInstance();
254     if (transactionProxy != nullptr) {
255         transactionProxy->FlushImplicitTransaction();
256     }
257     rsUiDirector_->SetRSSurfaceNode(surfaceNode);
258     rootNode_ = Rosen::RSRootNode::Create();
259     rootNode_->SetBounds(0, 0, static_cast<float>(width_), static_cast<float>(height_));
260     rootNode_->SetFrame(0, 0, static_cast<float>(width_), static_cast<float>(height_));
261     rsUiDirector_->SetRoot(rootNode_->GetId());
262     auto canvasNode = std::static_pointer_cast<Rosen::RSCanvasNode>(rootNode_);
263     SkPath path;
264     if (renderText->GetStartOffset().GetY() == renderText->GetEndOffset().GetY()) {
265         path.moveTo(renderText->GetStartOffset().GetX() - renderText->GetGlobalOffset().GetX(),
266             renderText->GetStartOffset().GetY() - renderText->GetGlobalOffset().GetY());
267         path.lineTo(renderText->GetEndOffset().GetX() - renderText->GetGlobalOffset().GetX(),
268             renderText->GetEndOffset().GetY() - renderText->GetGlobalOffset().GetY());
269         path.lineTo(renderText->GetEndOffset().GetX() - renderText->GetGlobalOffset().GetX(),
270             renderText->GetEndOffset().GetY() - renderText->GetSelectHeight() - renderText->GetGlobalOffset().GetY());
271         path.lineTo(renderText->GetStartOffset().GetX() - renderText->GetGlobalOffset().GetX(),
272             renderText->GetStartOffset().GetY() - renderText->GetSelectHeight() - renderText->GetGlobalOffset().GetY());
273         path.lineTo(renderText->GetStartOffset().GetX() - renderText->GetGlobalOffset().GetX(),
274             renderText->GetStartOffset().GetY() - renderText->GetGlobalOffset().GetY());
275     } else {
276         path.moveTo(renderText->GetStartOffset().GetX() - renderText->GetGlobalOffset().GetX(),
277             renderText->GetStartOffset().GetY() - renderText->GetGlobalOffset().GetY());
278         path.lineTo(renderText->GetStartOffset().GetX() - renderText->GetGlobalOffset().GetX(),
279             renderText->GetStartOffset().GetY() - renderText->GetSelectHeight() - renderText->GetGlobalOffset().GetY());
280         path.lineTo(renderText->GetPaintRect().Width(),
281             renderText->GetStartOffset().GetY() - renderText->GetSelectHeight() - renderText->GetGlobalOffset().GetY());
282         path.lineTo(renderText->GetPaintRect().Width(),
283             renderText->GetEndOffset().GetY() - renderText->GetSelectHeight() - renderText->GetGlobalOffset().GetY());
284         path.lineTo(renderText->GetEndOffset().GetX() - renderText->GetGlobalOffset().GetX(),
285             renderText->GetEndOffset().GetY() - renderText->GetSelectHeight() - renderText->GetGlobalOffset().GetY());
286         path.lineTo(renderText->GetEndOffset().GetX() - renderText->GetGlobalOffset().GetX(),
287             renderText->GetEndOffset().GetY() - renderText->GetGlobalOffset().GetY());
288         path.lineTo(renderText->GetPaintRect().Left() - renderText->GetGlobalOffset().GetX(),
289             renderText->GetEndOffset().GetY() - renderText->GetGlobalOffset().GetY());
290         path.lineTo(renderText->GetPaintRect().Left() - renderText->GetGlobalOffset().GetX(),
291             renderText->GetStartOffset().GetY() - renderText->GetGlobalOffset().GetY());
292         path.lineTo(renderText->GetStartOffset().GetX() - renderText->GetGlobalOffset().GetX(),
293             renderText->GetStartOffset().GetY() - renderText->GetGlobalOffset().GetY());
294     }
295     rootNode_->SetClipToBounds(true);
296     rootNode_->SetClipBounds(Rosen::RSPath::CreateRSPath(path));
297     auto skia = canvasNode->BeginRecording(width_, height_);
298     paragraph->Paint(skia, 0, 0);
299     canvasNode->FinishRecording();
300     rsUiDirector_->SendMessages();
301 }
302 } // namespace OHOS::Ace