• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022-2025 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 <algorithm>
17 #include <hitrace_meter.h>
18 #include <surface.h>
19 #include "surface_draw.h"
20 #include <transaction/rs_interfaces.h>
21 #include <ui/rs_surface_extractor.h>
22 
23 #include "image/bitmap.h"
24 #include "image_source.h"
25 #include "image_type.h"
26 #include "image_utils.h"
27 #include "render/rs_pixel_map_util.h"
28 #include "surface_capture_future.h"
29 #include "window_manager_hilog.h"
30 
31 namespace OHOS {
32 namespace Rosen {
33 namespace {
34 constexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, HILOG_DOMAIN_WINDOW, "SurfaceDraw"};
35 constexpr uint32_t IMAGE_BYTES_STRIDE = 4;
36 constexpr float CENTER_IN_RECT = 0.5;                     // Multiply by 0.5 to obtain the coordinates in center
37 constexpr float FIXED_BOTTOM_SAFE_AREA_HEIGHT_VP = 28.0;  // 28.0 indicates fixed bottom safe area height of windowRect
38 constexpr float FIXED_TOP_SAFE_AREA_HEIGHT_VP = 36.0;     // 36.0 indicates fixed top safe srea height off windowRect
39 constexpr float MAX_BRAND_CONTENT_WIDTH_VP = 400.0;       // 400.0 indicates max brand content width of windowRect
40 constexpr float MIN_BRAND_CONTENT_HEIGHT_VP = 80.0;       // 80.0 indicates min brand content height of windowRect
41 constexpr float MIN_RECT_HEIGHT_VP = 100.0;               // 100.0 indicates min rect height of windowRect
42 constexpr float SIDE_DISTANCE_VP = 16.0;                  // 16.0 indicates side distance of windowRect
43 constexpr float WIDTH_THRESHOLD_SMALL_VP = 320.0;         // Small threshold, use it when windowWidth <=320
44 constexpr float WIDTH_THRESHOLD_MEDIUM_VP = 600.0;        // Medium threshold, use it when windowWidth <=600
45 constexpr float WIDTH_THRESHOLD_LARGE_VP = 840.0;         // Large threshold, use it when windowWidth <=840
46 constexpr float ICON_SIZE_SMALL_VP = 128.0;               // 128.0 indicates small app icon sideLength
47 constexpr float ICON_SIZE_MEDIUM_VP = 192.0;              // 192.0 indicates medium app icon sideLength
48 constexpr float ICON_SIZE_LARGE_VP = 256.0;               // 256.0 indicates large app icon sideLength
49 constexpr float ASPECT_RATIO_1 = 9.0f / 7.2f;             // windowRect Aspect ratio threshold 9 : 7.2
50 constexpr float ASPECT_RATIO_2 = 9.0f / 10.8f;            // windwoRect Aspect ratio threshold 9 : 10.8
51 constexpr float EIGHTY_PERCENT = 0.8;                     // 0.8 indicates eighty percent
52 constexpr float FORTY_PERCENT = 0.4;                      // 0.4 indicates forty percent
53 constexpr float SEVENTY_PERCENT = 0.7;                    // 0.7 indicates seventy percent
54 constexpr float THIRTY_PERCENT = 0.3;                     // 0.3 indicates thirty percent
55 } // namespace
56 
IsValidPixelMap(const std::shared_ptr<Media::PixelMap> & pixelMap)57 bool IsValidPixelMap(const std::shared_ptr<Media::PixelMap>& pixelMap)
58 {
59     if (pixelMap == nullptr) {
60         TLOGD(WmsLogTag::WMS_PATTERN, "pixelMap is nullptr.");
61         return false;
62     }
63     return pixelMap->GetHeight() > 0 && pixelMap->GetWidth() > 0;
64 }
65 
66 template <typename T>
TryDrawResource(const std::shared_ptr<Rosen::ResourceInfo> & resource,uint32_t frameIdx,T && drawFunc,const char * resourceName)67 void TryDrawResource(const std::shared_ptr<Rosen::ResourceInfo>& resource, uint32_t frameIdx, T&& drawFunc,
68     const char* resourceName)
69 {
70     if (!resource || resource->pixelMaps.empty()) {
71         TLOGD(WmsLogTag::WMS_PATTERN, "draw failed, null resource.");
72         return;
73     }
74     uint32_t idx = (resource->pixelMaps.size() > 1) ? frameIdx : 0;
75     const auto& map = resource->pixelMaps[idx];
76     if (IsValidPixelMap(map)) {
77         if (!drawFunc(map)) {
78             TLOGD(WmsLogTag::WMS_PATTERN, "draw StartingWindow %{public}s failed.", resourceName);
79         }
80     }
81 }
82 
IsValidRect(const Rect & targetRect,const Rect & winRect)83 bool IsValidRect(const Rect& targetRect, const Rect& winRect)
84 {
85     bool valid = targetRect.posX_ > 0
86               && targetRect.posY_ > 0
87               && targetRect.width_ > 0
88               && targetRect.height_ > 0
89               && (targetRect.posX_ + targetRect.width_) < winRect.width_
90               && (targetRect.posY_ + targetRect.height_) < winRect.height_;
91     return valid;
92 }
93 
GetAppIconRect(const Rect & winRect,const float ratio)94 Rect GetAppIconRect(const Rect& winRect, const float ratio)
95 {
96     float width  = static_cast<float>(winRect.width_);
97     float height = static_cast<float>(winRect.height_);
98     float aspectRatio = width / height;
99     float sideLen = ICON_SIZE_LARGE_VP * ratio;
100     if (width <= WIDTH_THRESHOLD_SMALL_VP * ratio) {
101         sideLen = ICON_SIZE_SMALL_VP * ratio;
102     } else if (width <= WIDTH_THRESHOLD_MEDIUM_VP * ratio) {
103         sideLen = MathHelper::GreatNotEqual(aspectRatio, ASPECT_RATIO_2) ?
104             ICON_SIZE_SMALL_VP * ratio : ICON_SIZE_MEDIUM_VP * ratio;
105     } else if (width <= WIDTH_THRESHOLD_LARGE_VP * ratio) {
106         sideLen = MathHelper::GreatNotEqual(aspectRatio, ASPECT_RATIO_1) ?
107             ICON_SIZE_MEDIUM_VP * ratio : ICON_SIZE_LARGE_VP * ratio;
108     }
109     float posX = (width - sideLen) * CENTER_IN_RECT;
110     float posY = (SEVENTY_PERCENT * height - FIXED_TOP_SAFE_AREA_HEIGHT_VP * ratio - sideLen) *
111         CENTER_IN_RECT + FIXED_TOP_SAFE_AREA_HEIGHT_VP * ratio;
112 
113     Rosen::Rect appIconRect {
114         static_cast<int32_t>(posX),
115         static_cast<int32_t>(posY),
116         static_cast<uint32_t>(sideLen),
117         static_cast<uint32_t>(sideLen)
118     };
119     return appIconRect;
120 }
121 
GetAboveRect(const Rect & winRect,const float ratio)122 Rect GetAboveRect(const Rect& winRect, const float ratio)
123 {
124     float width  = static_cast<float>(winRect.width_);
125     float height = static_cast<float>(winRect.height_);
126 
127     float axis = (height * CENTER_IN_RECT) / width;
128     float sideLen = MathHelper::GreatNotEqual(axis, 1.0f) ?
129         width * EIGHTY_PERCENT : (height * CENTER_IN_RECT) * EIGHTY_PERCENT;
130 
131     float posX = (width - sideLen) * CENTER_IN_RECT;
132     float posY = (SEVENTY_PERCENT * height - FIXED_TOP_SAFE_AREA_HEIGHT_VP * ratio - sideLen) *
133         CENTER_IN_RECT + FIXED_TOP_SAFE_AREA_HEIGHT_VP * ratio;
134     Rosen::Rect aboveRect {
135         static_cast<int32_t>(posX),
136         static_cast<int32_t>(posY),
137         static_cast<uint32_t>(sideLen),
138         static_cast<uint32_t>(sideLen)
139     };
140     return aboveRect;
141 }
142 
GetBelowRect(const Rect & winRect,const float ratio)143 Rect GetBelowRect(const Rect& winRect, const float ratio)
144 {
145     float width  = static_cast<float>(winRect.width_);
146     float height = static_cast<float>(winRect.height_);
147 
148     float rectWidth = width - 2 * SIDE_DISTANCE_VP * ratio; // 2 indicates double
149     float rectHeight = (height * THIRTY_PERCENT) * FORTY_PERCENT; // 40% height based on 30% of winRect height
150 
151     Rosen::Rect belowRect { 0, 0,
152         static_cast<uint32_t>(MathHelper::Min(rectWidth, MAX_BRAND_CONTENT_WIDTH_VP * ratio)),
153         static_cast<uint32_t>(MathHelper::Max(rectHeight, MIN_BRAND_CONTENT_HEIGHT_VP * ratio))
154     };
155     belowRect.posX_ = static_cast<int32_t>((width - belowRect.width_) * CENTER_IN_RECT);
156     belowRect.posY_ = static_cast<int32_t>((height * THIRTY_PERCENT - FIXED_BOTTOM_SAFE_AREA_HEIGHT_VP * ratio -
157         belowRect.height_) * CENTER_IN_RECT + height * SEVENTY_PERCENT);
158     return belowRect;
159 }
160 
FitAndDraw(const std::shared_ptr<Media::PixelMap> & pixelMap,const Rect & targetRect,Drawing::Canvas & canvas,ImageFit fit)161 void FitAndDraw(const std::shared_ptr<Media::PixelMap>& pixelMap, const Rect& targetRect,
162     Drawing::Canvas& canvas, ImageFit fit)
163 {
164     auto rsImage = std::make_shared<Rosen::RSImage>();
165     if (rsImage == nullptr) {
166         TLOGD(WmsLogTag::WMS_PATTERN, "rsImage is nullptr.");
167         return;
168     }
169     rsImage->SetPixelMap(pixelMap);
170     rsImage->SetImageFit(int(fit));
171     canvas.Save();
172     canvas.Translate(targetRect.posX_, targetRect.posY_);
173     rsImage->CanvasDrawImage(
174         canvas,
175         Drawing::Rect(
176             targetRect.posX_,
177             targetRect.posY_,
178             targetRect.posX_ + targetRect.width_,
179             targetRect.posY_ + targetRect.height_),
180         Drawing::SamplingOptions());
181     canvas.Restore();
182 }
183 
DoDrawIllustration(const std::shared_ptr<Media::PixelMap> & pixelMap,const Rect & winRect,Drawing::Canvas & canvas,const float ratio,ImageFit fit)184 bool DoDrawIllustration(const std::shared_ptr<Media::PixelMap>& pixelMap, const Rect& winRect,
185     Drawing::Canvas& canvas, const float ratio, ImageFit fit)
186 {
187     auto aboveRect = GetAboveRect(winRect, ratio);
188     if (!IsValidRect(aboveRect, winRect)) {
189         TLOGD(WmsLogTag::WMS_PATTERN, "aboveRect is invalid.");
190         return false;
191     }
192     FitAndDraw(pixelMap, aboveRect, canvas, fit);
193     return true;
194 }
195 
DoDrawAppIcon(const std::shared_ptr<Media::PixelMap> & pixelMap,const Rect & winRect,Drawing::Canvas & canvas,const float ratio,ImageFit fit)196 bool DoDrawAppIcon(const std::shared_ptr<Media::PixelMap>& pixelMap, const Rect& winRect,
197     Drawing::Canvas& canvas, const float ratio, ImageFit fit)
198 {
199     auto appRect = GetAppIconRect(winRect, ratio);
200     if (!IsValidRect(appRect, winRect)) {
201         TLOGD(WmsLogTag::WMS_PATTERN, "appRect is invalid.");
202         return false;
203     }
204     FitAndDraw(pixelMap, appRect, canvas, fit);
205     return true;
206 }
207 
DoDrawBranding(const std::shared_ptr<Media::PixelMap> & pixelMap,const Rect & winRect,Drawing::Canvas & canvas,const float ratio,ImageFit fit)208 bool DoDrawBranding(const std::shared_ptr<Media::PixelMap>& pixelMap, const Rect& winRect,
209     Drawing::Canvas& canvas, const float ratio, ImageFit fit)
210 {
211     if ((winRect.height_ * THIRTY_PERCENT) < MIN_RECT_HEIGHT_VP * ratio) {
212         TLOGD(WmsLogTag::WMS_PATTERN, "rect is invalid.");
213         return false;
214     }
215     auto belowRect = GetBelowRect(winRect, ratio);
216     if (!IsValidRect(belowRect, winRect)) {
217         TLOGD(WmsLogTag::WMS_PATTERN, "belowRect is invalid.");
218         return false;
219     }
220     FitAndDraw(pixelMap, belowRect, canvas, fit);
221     return true;
222 }
223 
DoDrawBackgroundImage(const std::shared_ptr<Media::PixelMap> & pixelMap,const Rect & winRect,Drawing::Canvas & canvas,const std::string & fit)224 bool DoDrawBackgroundImage(const std::shared_ptr<Media::PixelMap>& pixelMap, const Rect& winRect,
225     Drawing::Canvas& canvas, const std::string &fit)
226 {
227     const std::unordered_map<std::string, ImageFit> drawStrategies = {
228         { "Fill", ImageFit::FILL },
229         { "None", ImageFit::NONE },
230         { "Cover", ImageFit::COVER },
231         { "Auto", ImageFit::FIT_WIDTH },
232         { "Contain", ImageFit::CONTAIN },
233         { "ScaleDown", ImageFit::SCALE_DOWN },
234     };
235     std::string effectiveFit = fit.empty() ? "Cover" : fit;
236     auto it = drawStrategies.find(effectiveFit);
237     if (it == drawStrategies.end()) {
238         TLOGD(WmsLogTag::WMS_PATTERN, "Unsupported fit type: %{public}s", effectiveFit.c_str());
239         return false;
240     }
241     FitAndDraw(pixelMap, winRect, canvas, it->second);
242     return true;
243 }
244 
DrawImage(std::shared_ptr<RSSurfaceNode> surfaceNode,int32_t bufferWidth,int32_t bufferHeight,const std::string & imagePath)245 bool SurfaceDraw::DrawImage(std::shared_ptr<RSSurfaceNode> surfaceNode, int32_t bufferWidth,
246     int32_t bufferHeight, const std::string& imagePath)
247 {
248     sptr<OHOS::Surface> layer = GetLayer(surfaceNode);
249     if (layer == nullptr) {
250         WLOGFE("layer is nullptr");
251         return false;
252     }
253     sptr<OHOS::SurfaceBuffer> buffer = GetSurfaceBuffer(layer, bufferWidth, bufferHeight);
254     if (buffer == nullptr || buffer->GetVirAddr() == nullptr) {
255         return false;
256     }
257     auto addr = static_cast<uint8_t *>(buffer->GetVirAddr());
258     if (!DoDraw(addr, buffer->GetWidth(), buffer->GetHeight(), imagePath)) {
259         WLOGE("draw window pixel failed");
260         return false;
261     }
262     OHOS::BufferFlushConfig flushConfig = {
263         .damage = {
264             .w = buffer->GetWidth(),
265             .h = buffer->GetHeight(),
266         },
267     };
268     OHOS::SurfaceError ret = layer->FlushBuffer(buffer, -1, flushConfig);
269     if (ret != OHOS::SurfaceError::SURFACE_ERROR_OK) {
270         WLOGFE("draw pointer FlushBuffer ret:%{public}s", SurfaceErrorStr(ret).c_str());
271         return false;
272     }
273     return true;
274 }
275 
DrawImage(std::shared_ptr<RSSurfaceNode> surfaceNode,int32_t bufferWidth,int32_t bufferHeight,std::shared_ptr<Media::PixelMap> pixelMap)276 bool SurfaceDraw::DrawImage(std::shared_ptr<RSSurfaceNode> surfaceNode, int32_t bufferWidth,
277     int32_t bufferHeight, std::shared_ptr<Media::PixelMap> pixelMap)
278 {
279     sptr<OHOS::Surface> layer = GetLayer(surfaceNode);
280     if (layer == nullptr) {
281         WLOGFE("layer is nullptr");
282         return false;
283     }
284     sptr<OHOS::SurfaceBuffer> buffer = GetSurfaceBuffer(layer, bufferWidth, bufferHeight);
285     if (buffer == nullptr || buffer->GetVirAddr() == nullptr) {
286         return false;
287     }
288     auto addr = static_cast<uint8_t *>(buffer->GetVirAddr());
289     if (!DoDraw(addr, buffer->GetWidth(), buffer->GetHeight(), pixelMap)) {
290         WLOGE("draw window pixel failed");
291         return false;
292     }
293     OHOS::BufferFlushConfig flushConfig = {
294         .damage = {
295             .w = buffer->GetWidth(),
296             .h = buffer->GetHeight(),
297         },
298     };
299     OHOS::SurfaceError ret = layer->FlushBuffer(buffer, -1, flushConfig);
300     if (ret != OHOS::SurfaceError::SURFACE_ERROR_OK) {
301         WLOGFE("draw pointer FlushBuffer ret:%{public}s", SurfaceErrorStr(ret).c_str());
302         return false;
303     }
304     return true;
305 }
306 
DrawColor(std::shared_ptr<RSSurfaceNode> surfaceNode,int32_t bufferWidth,int32_t bufferHeight,uint32_t color)307 bool SurfaceDraw::DrawColor(std::shared_ptr<RSSurfaceNode> surfaceNode, int32_t bufferWidth,
308     int32_t bufferHeight, uint32_t color)
309 {
310     sptr<OHOS::Surface> layer = GetLayer(surfaceNode);
311     if (layer == nullptr) {
312         WLOGFE("layer is nullptr");
313         return false;
314     }
315     sptr<OHOS::SurfaceBuffer> buffer = GetSurfaceBuffer(layer, bufferWidth, bufferHeight);
316     if (buffer == nullptr || buffer->GetVirAddr() == nullptr) {
317         return false;
318     }
319     auto addr = static_cast<uint8_t *>(buffer->GetVirAddr());
320     if (!DoDraw(addr, buffer->GetWidth(), buffer->GetHeight(), color)) {
321         WLOGE("draw window color failed");
322         return false;
323     }
324     OHOS::BufferFlushConfig flushConfig = {
325         .damage = {
326             .w = buffer->GetWidth(),
327             .h = buffer->GetHeight(),
328         },
329     };
330     OHOS::SurfaceError ret = layer->FlushBuffer(buffer, -1, flushConfig);
331     if (ret != OHOS::SurfaceError::SURFACE_ERROR_OK) {
332         WLOGFE("draw pointer FlushBuffer ret:%{public}s", SurfaceErrorStr(ret).c_str());
333         return false;
334     }
335     return true;
336 }
337 
GetLayer(std::shared_ptr<RSSurfaceNode> surfaceNode)338 sptr<OHOS::Surface> SurfaceDraw::GetLayer(std::shared_ptr<RSSurfaceNode> surfaceNode)
339 {
340     if (surfaceNode == nullptr) {
341         return nullptr;
342     }
343     return surfaceNode->GetSurface();
344 }
345 
GetSurfaceBuffer(sptr<OHOS::Surface> layer,int32_t bufferWidth,int32_t bufferHeight)346 sptr<OHOS::SurfaceBuffer> SurfaceDraw::GetSurfaceBuffer(sptr<OHOS::Surface> layer,
347     int32_t bufferWidth, int32_t bufferHeight)
348 {
349     sptr<OHOS::SurfaceBuffer> buffer;
350     int32_t releaseFence = 0;
351     OHOS::BufferRequestConfig config = {
352         .width = bufferWidth,
353         .height = bufferHeight,
354         .strideAlignment = 0x8,
355         .format = GRAPHIC_PIXEL_FMT_RGBA_8888,
356         .usage = BUFFER_USAGE_CPU_READ | BUFFER_USAGE_CPU_WRITE | BUFFER_USAGE_MEM_DMA,
357     };
358 
359     OHOS::SurfaceError ret = layer->RequestBuffer(buffer, releaseFence, config);
360     if (ret != OHOS::SURFACE_ERROR_OK) {
361         WLOGFE("request buffer ret:%{public}s", SurfaceErrorStr(ret).c_str());
362         return nullptr;
363     }
364     return buffer;
365 }
366 
DecodeImageToPixelMap(const std::string & imagePath)367 std::unique_ptr<OHOS::Media::PixelMap> SurfaceDraw::DecodeImageToPixelMap(const std::string& imagePath)
368 {
369     OHOS::Media::SourceOptions opts;
370     opts.formatHint = "image/png";
371     uint32_t ret = 0;
372     auto imageSource = OHOS::Media::ImageSource::CreateImageSource(imagePath, opts, ret);
373     if (imageSource == nullptr) {
374         WLOGFE("invalid image path.");
375         return nullptr;
376     }
377     std::set<std::string> formats;
378     ret = imageSource->GetSupportedFormats(formats);
379     WLOGFD("get supported format ret:%{public}u", ret);
380 
381     OHOS::Media::DecodeOptions decodeOpts;
382     std::unique_ptr<OHOS::Media::PixelMap> pixelMap = imageSource->CreatePixelMap(decodeOpts, ret);
383     if (pixelMap == nullptr) {
384         WLOGFE("pixelMap is nullptr");
385     }
386     return pixelMap;
387 }
388 
DrawPixelmap(Drawing::Canvas & canvas,const std::string & imagePath)389 void SurfaceDraw::DrawPixelmap(Drawing::Canvas& canvas, const std::string& imagePath)
390 {
391     std::unique_ptr<OHOS::Media::PixelMap> pixelmap = DecodeImageToPixelMap(imagePath);
392     if (pixelmap == nullptr) {
393         WLOGFE("drawing pixel map is nullptr");
394         return;
395     }
396     Drawing::Pen pen;
397     pen.SetAntiAlias(true);
398     pen.SetColor(Drawing::Color::COLOR_BLUE);
399     Drawing::scalar penWidth = 1;
400     pen.SetWidth(penWidth);
401     canvas.AttachPen(pen);
402     RSPixelMapUtil::DrawPixelMap(canvas, *pixelmap, 0, 0);
403 }
404 
DoDraw(uint8_t * addr,uint32_t width,uint32_t height,const std::string & imagePath)405 bool SurfaceDraw::DoDraw(uint8_t* addr, uint32_t width, uint32_t height, const std::string& imagePath)
406 {
407     Drawing::Bitmap bitmap;
408     Drawing::BitmapFormat format { Drawing::ColorType::COLORTYPE_RGBA_8888,
409         Drawing::AlphaType::ALPHATYPE_OPAQUE };
410     bitmap.Build(width, height, format);
411     Drawing::Canvas canvas;
412     canvas.Bind(bitmap);
413     canvas.Clear(Drawing::Color::COLOR_TRANSPARENT);
414     DrawPixelmap(canvas, imagePath);
415     uint32_t addrSize = width * height * IMAGE_BYTES_STRIDE;
416     errno_t ret = memcpy_s(addr, addrSize, bitmap.GetPixels(), addrSize);
417     if (ret != EOK) {
418         WLOGFE("draw failed");
419         return false;
420     }
421     return true;
422 }
423 
DoDraw(uint8_t * addr,uint32_t width,uint32_t height,std::shared_ptr<Media::PixelMap> pixelMap)424 bool SurfaceDraw::DoDraw(uint8_t* addr, uint32_t width, uint32_t height, std::shared_ptr<Media::PixelMap> pixelMap)
425 {
426     Drawing::Bitmap bitmap;
427     Drawing::Canvas canvas;
428     Drawing::BitmapFormat format { Drawing::ColorType::COLORTYPE_RGBA_8888, Drawing::AlphaType::ALPHATYPE_OPAQUE };
429     bitmap.Build(width, height, format);
430     canvas.Bind(bitmap);
431     canvas.Clear(Drawing::Color::COLOR_TRANSPARENT);
432 
433     Drawing::Image image;
434     Drawing::Bitmap imageBitmap;
435     Drawing::SamplingOptions sampling = Drawing::SamplingOptions(Drawing::FilterMode::NEAREST,
436         Drawing::MipmapMode::NEAREST);
437     imageBitmap.Build(pixelMap->GetWidth(), pixelMap->GetHeight(), format);
438     imageBitmap.SetPixels(const_cast<uint8_t*>(pixelMap->GetPixels()));
439     image.BuildFromBitmap(imageBitmap);
440 
441     Drawing::Rect dst(0, 0, width, height);
442     Drawing::Rect src(0, 0, pixelMap->GetWidth(), pixelMap->GetHeight());
443     canvas.DrawImageRect(image, src, dst, sampling);
444 
445     uint32_t addrSize = width * height * IMAGE_BYTES_STRIDE;
446     errno_t ret = memcpy_s(addr, addrSize, bitmap.GetPixels(), addrSize);
447     if (ret != EOK) {
448         WLOGFE("draw failed");
449         return false;
450     }
451     return true;
452 }
453 
DoDraw(uint8_t * addr,uint32_t width,uint32_t height,uint32_t color)454 bool SurfaceDraw::DoDraw(uint8_t* addr, uint32_t width, uint32_t height, uint32_t color)
455 {
456     Drawing::Bitmap bitmap;
457     Drawing::BitmapFormat format { Drawing::ColorType::COLORTYPE_RGBA_8888,
458         Drawing::AlphaType::ALPHATYPE_OPAQUE };
459     bitmap.Build(width, height, format);
460     Drawing::Canvas canvas;
461     canvas.Bind(bitmap);
462     canvas.Clear(color);
463 
464     uint32_t addrSize = width * height * IMAGE_BYTES_STRIDE;
465     errno_t ret = memcpy_s(addr, addrSize, bitmap.GetPixels(), addrSize);
466     if (ret != EOK) {
467         WLOGFE("draw failed");
468         return false;
469     }
470     return true;
471 }
472 
DrawImageRect(std::shared_ptr<RSSurfaceNode> surfaceNode,Rect rect,std::shared_ptr<Media::PixelMap> pixelMap,uint32_t color,bool fillWindow)473 bool SurfaceDraw::DrawImageRect(std::shared_ptr<RSSurfaceNode> surfaceNode, Rect rect,
474     std::shared_ptr<Media::PixelMap> pixelMap, uint32_t color, bool fillWindow)
475 {
476     int32_t winHeight = static_cast<int32_t>(rect.height_);
477     int32_t winWidth = static_cast<int32_t>(rect.width_);
478     sptr<OHOS::Surface> layer = GetLayer(surfaceNode);
479     if (layer == nullptr) {
480         WLOGFE("layer is nullptr");
481         return false;
482     }
483     sptr<OHOS::SurfaceBuffer> buffer = GetSurfaceBuffer(layer, winWidth, winHeight);
484     if (buffer == nullptr || buffer->GetVirAddr() == nullptr) {
485         return false;
486     }
487     if (!DoDrawImageRect(buffer, rect, pixelMap, color, fillWindow)) {
488         WLOGE("draw image rect failed.");
489         return false;
490     }
491     OHOS::BufferFlushConfig flushConfig = {
492         .damage = {
493             .w = buffer->GetWidth(),
494             .h = buffer->GetHeight(),
495         },
496     };
497     OHOS::SurfaceError surfaceRet = layer->FlushBuffer(buffer, -1, flushConfig);
498     if (surfaceRet != OHOS::SurfaceError::SURFACE_ERROR_OK) {
499         WLOGFE("draw pointer FlushBuffer ret:%{public}s", SurfaceErrorStr(surfaceRet).c_str());
500         return false;
501     }
502     return true;
503 }
504 
DoDrawImageRect(sptr<OHOS::SurfaceBuffer> buffer,const Rect & rect,std::shared_ptr<Media::PixelMap> pixelMap,uint32_t color,bool fillWindow)505 bool SurfaceDraw::DoDrawImageRect(sptr<OHOS::SurfaceBuffer> buffer, const Rect& rect,
506     std::shared_ptr<Media::PixelMap> pixelMap, uint32_t color, bool fillWindow)
507 {
508     int32_t winWidth = static_cast<int32_t>(rect.width_);
509     int32_t winHeight = static_cast<int32_t>(rect.height_);
510     // actual width of the surface buffer after alignment
511     auto bufferStride = buffer->GetStride();
512     int32_t alignWidth = bufferStride / static_cast<int32_t>(IMAGE_BYTES_STRIDE);
513     if (pixelMap == nullptr) {
514         WLOGFE("drawing pixel map failed, because pixel map is nullptr.");
515         return false;
516     }
517     if (pixelMap->GetHeight() <= 0 || pixelMap->GetWidth() <= 0 || winWidth <= 0 || winHeight <= 0) {
518         WLOGFE("drawing pixel map failed, because width or height is invalid.");
519         return false;
520     }
521     Drawing::Bitmap bitmap;
522     Drawing::BitmapFormat format { Drawing::ColorType::COLORTYPE_RGBA_8888,
523         Drawing::AlphaType::ALPHATYPE_OPAQUE };
524     bitmap.Build(alignWidth, winHeight, format);
525     Drawing::Canvas canvas;
526     canvas.Bind(bitmap);
527     canvas.Clear(color);
528     float xAxis = static_cast<float>(winWidth) / pixelMap->GetWidth();
529     float yAxis = static_cast<float>(winHeight) / pixelMap->GetHeight();
530     float axis = std::min(xAxis, yAxis);
531     int scaledPixelMapW = pixelMap->GetWidth();
532     int scaledPixelMapH = pixelMap->GetHeight();
533     if (axis < 1.0) {
534         canvas.Scale(axis, axis);
535         scaledPixelMapW = scaledPixelMapW * axis;
536         scaledPixelMapH = scaledPixelMapH * axis;
537     } else if (fillWindow) {
538         // scale snapshot to whole window
539         canvas.Scale(xAxis, yAxis);
540         scaledPixelMapW = winWidth;
541         scaledPixelMapH = winHeight;
542     }
543     int left = (winWidth - scaledPixelMapW) / 2; // 2 is the left and right boundaries of the win
544     int top = (winHeight - scaledPixelMapH) / 2; // 2 is the top and bottom boundaries of the win
545     WLOGFD("pixelMap width: %{public}d win height: %{public}d left:%{public}d top:%{public}d.",
546         pixelMap->GetWidth(), pixelMap->GetHeight(), left, top);
547     RSPixelMapUtil::DrawPixelMap(canvas, *pixelMap, left, top);
548     // bufferSize is actual size of the surface buffer after alignment
549     int32_t bufferSize = bufferStride * winHeight;
550     uint8_t* bitmapAddr = static_cast<uint8_t*>(bitmap.GetPixels());
551     auto addr = static_cast<uint8_t *>(buffer->GetVirAddr());
552     errno_t ret = memcpy_s(addr, bufferSize, bitmapAddr, bufferSize);
553     if (ret != EOK) {
554         WLOGFE("draw image rect failed, because copy bitmap to buffer failed.");
555         return false;
556     }
557     return true;
558 }
559 
GetSurfaceSnapshot(const std::shared_ptr<RSSurfaceNode> surfaceNode,std::shared_ptr<Media::PixelMap> & pixelMap,int32_t timeoutMs,float scaleW,float scaleH)560 bool SurfaceDraw::GetSurfaceSnapshot(const std::shared_ptr<RSSurfaceNode> surfaceNode,
561     std::shared_ptr<Media::PixelMap>&pixelMap, int32_t timeoutMs, float scaleW, float scaleH)
562 {
563     if (surfaceNode == nullptr) {
564         WLOGFE("surfaceNode is null");
565         return false;
566     }
567     HITRACE_METER_FMT(HITRACE_TAG_WINDOW_MANAGER, "SurfaceDraw:GetSurfaceSnapshot(%llu)", surfaceNode->GetId());
568     std::shared_ptr<SurfaceCaptureFuture> callback = std::make_shared<SurfaceCaptureFuture>();
569     RSSurfaceCaptureConfig config = {
570         .scaleX = scaleW,
571         .scaleY = scaleH,
572     };
573     if (RSInterfaces::GetInstance().TakeSurfaceCapture(surfaceNode, callback, config)) {
574         pixelMap = callback->GetResult(timeoutMs); // get pixelmap time out ms
575     }
576     if (pixelMap == nullptr) {
577         WLOGE("get surface snapshot timeout.");
578         return false;
579     }
580     return true;
581 }
582 
DrawMasking(std::shared_ptr<RSSurfaceNode> surfaceNode,Rect screenRect,Rect transparentRect)583 bool SurfaceDraw::DrawMasking(std::shared_ptr<RSSurfaceNode> surfaceNode, Rect screenRect,
584     Rect transparentRect)
585 {
586     int32_t screenHeight = static_cast<int32_t>(screenRect.height_);
587     int32_t screenWidth = static_cast<int32_t>(screenRect.width_);
588     int32_t transparentHeight = static_cast<int32_t>(transparentRect.height_);
589     int32_t transparentWidth = static_cast<int32_t>(transparentRect.width_);
590     sptr<OHOS::Surface> layer = GetLayer(surfaceNode);
591     if (layer == nullptr) {
592         WLOGFE("layer is nullptr");
593         return false;
594     }
595     sptr<OHOS::SurfaceBuffer> buffer = GetSurfaceBuffer(layer, screenWidth, screenHeight);
596     if (buffer == nullptr || buffer->GetVirAddr() == nullptr) {
597         return false;
598     }
599     auto addr = static_cast<uint8_t *>(buffer->GetVirAddr());
600     Drawing::Bitmap fullbitmap;
601     Drawing::BitmapFormat fullBitmapFormat { Drawing::ColorType::COLORTYPE_RGBA_8888,
602         Drawing::AlphaType::ALPHATYPE_OPAQUE };
603     fullbitmap.Build(screenWidth, screenHeight, fullBitmapFormat);
604     Drawing::Canvas canvas;
605     canvas.Bind(fullbitmap);
606     canvas.Clear(0xFF000000);
607     Drawing::Bitmap transBitmap;
608     Drawing::BitmapFormat transBitmapFormat { Drawing::ColorType::COLORTYPE_RGBA_8888,
609         Drawing::AlphaType::ALPHATYPE_OPAQUE };
610     transBitmap.Build(transparentWidth, transparentHeight, transBitmapFormat);
611     transBitmap.ClearWithColor(0);
612     canvas.DrawBitmap(transBitmap, static_cast<Drawing::scalar>(transparentRect.posX_),
613         static_cast<Drawing::scalar>(transparentRect.posY_));
614 
615     uint32_t addrSize = static_cast<uint32_t>(screenWidth * screenHeight * IMAGE_BYTES_STRIDE);
616     errno_t ret = memcpy_s(addr, addrSize, fullbitmap.GetPixels(), addrSize);
617     if (ret != EOK) {
618         WLOGFE("draw failed");
619         return false;
620     }
621     OHOS::BufferFlushConfig flushConfig = {
622         .damage = {
623             .w = buffer->GetWidth(),
624             .h = buffer->GetHeight(),
625         },
626     };
627     OHOS::SurfaceError surfaceRet = layer->FlushBuffer(buffer, -1, flushConfig);
628     if (surfaceRet != OHOS::SurfaceError::SURFACE_ERROR_OK) {
629         WLOGFE("draw masking FlushBuffer ret:%{public}s", SurfaceErrorStr(surfaceRet).c_str());
630         return false;
631     }
632     return true;
633 }
634 
DrawCustomStartingWindow(const std::shared_ptr<RSSurfaceNode> & surfaceNode,const Rect & rect,const std::shared_ptr<Rosen::StartingWindowPageDrawInfo> & info,float ratio,const std::array<uint32_t,size_t (StartWindowResType::Count)> & frameIndex)635 bool SurfaceDraw::DrawCustomStartingWindow(const std::shared_ptr<RSSurfaceNode>& surfaceNode,
636     const Rect& rect, const std::shared_ptr<Rosen::StartingWindowPageDrawInfo>& info,
637     float ratio, const std::array<uint32_t, size_t(StartWindowResType::Count)>& frameIndex)
638 {
639     int32_t winHeight = static_cast<int32_t>(rect.height_);
640     int32_t winWidth = static_cast<int32_t>(rect.width_);
641     sptr<OHOS::Surface> layer = GetLayer(surfaceNode);
642     if (layer == nullptr) {
643         TLOGD(WmsLogTag::WMS_PATTERN, "layer is nullptr");
644         return false;
645     }
646     sptr<OHOS::SurfaceBuffer> buffer = GetSurfaceBuffer(layer, winWidth, winHeight);
647     if (buffer == nullptr || buffer->GetVirAddr() == nullptr) {
648         TLOGD(WmsLogTag::WMS_PATTERN, "buffer or virAddr is nullptr");
649         return false;
650     }
651     if (!DoDrawCustomStartingWindow(buffer, rect, info, ratio, frameIndex)) {
652         TLOGD(WmsLogTag::WMS_PATTERN, "draw Custom startingwindow page failed");
653         return false;
654     }
655     OHOS::BufferFlushConfig flushConfig = {
656         .damage = {
657             .w = buffer->GetWidth(),
658             .h = buffer->GetHeight(),
659         },
660     };
661     OHOS::SurfaceError surfaceRet = layer->FlushBuffer(buffer, -1, flushConfig);
662     if (surfaceRet != OHOS::SurfaceError::SURFACE_ERROR_OK) {
663         TLOGD(WmsLogTag::WMS_PATTERN, "draw pointer FlushBuffer ret:%{public}s", SurfaceErrorStr(surfaceRet).c_str());
664         return false;
665     }
666     return true;
667 }
668 
DoDrawCustomStartingWindow(const sptr<OHOS::SurfaceBuffer> & buffer,const Rect & rect,const std::shared_ptr<Rosen::StartingWindowPageDrawInfo> & info,const float ratio,const std::array<uint32_t,size_t (StartWindowResType::Count)> & frameIndex)669 bool SurfaceDraw::DoDrawCustomStartingWindow(const sptr<OHOS::SurfaceBuffer>& buffer, const Rect& rect,
670     const std::shared_ptr<Rosen::StartingWindowPageDrawInfo>& info, const float ratio,
671     const std::array<uint32_t, size_t(StartWindowResType::Count)>& frameIndex)
672 {
673     if (info == nullptr || rect.width_ <= 0 || rect.height_ <= 0 || ratio  <= 0) {
674         TLOGD(WmsLogTag::WMS_PATTERN, "info is nullptr or invalid rect and ratio");
675         return false;
676     }
677     auto bufferStride = buffer->GetStride();
678     int32_t alignWidth = bufferStride / static_cast<int32_t>(IMAGE_BYTES_STRIDE);
679     Drawing::Bitmap customDrawBitmap;
680     Drawing::BitmapFormat format { Drawing::ColorType::COLORTYPE_RGBA_8888, Drawing::AlphaType::ALPHATYPE_OPAQUE };
681     customDrawBitmap.Build(alignWidth, rect.height_, format);
682     Drawing::Canvas canvas;
683     canvas.Bind(customDrawBitmap);
684     canvas.Clear(info->bgColor);
685     TryDrawResource(info->bgImage, frameIndex[(size_t)StartWindowResType::BgImage],
686         [&](const auto& map) { return DoDrawBackgroundImage(map, rect, canvas, info->startWindowBackgroundImageFit); },
687         "background image");
688 
689     TryDrawResource(info->branding, frameIndex[(size_t)StartWindowResType::Branding],
690         [&](const auto& map) { return DoDrawBranding(map, rect, canvas, ratio, ImageFit::SCALE_DOWN); },
691         "branding image");
692 
693     TryDrawResource(info->illustration, frameIndex[(size_t)StartWindowResType::Illustration],
694         [&](const auto& map) { return DoDrawIllustration(map, rect, canvas, ratio, ImageFit::SCALE_DOWN); },
695         "illustration image");
696 
697     TryDrawResource(info->appIcon, frameIndex[(size_t)StartWindowResType::AppIcon],
698         [&](const auto& map) { return DoDrawAppIcon(map, rect, canvas, ratio, ImageFit::CONTAIN); },
699         "app icon image");
700     int32_t bufferSize = bufferStride * rect.height_;
701     uint8_t* bitmapAddr = static_cast<uint8_t*>(customDrawBitmap.GetPixels());
702     auto addr = static_cast<uint8_t *>(buffer->GetVirAddr());
703     errno_t ret = memcpy_s(addr, bufferSize, bitmapAddr, bufferSize);
704     if (ret != EOK) {
705         TLOGD(WmsLogTag::WMS_PATTERN, "draw image failed, because copy customDrawBitmap to buffer failed.");
706         return false;
707     }
708     return true;
709 }
710 } // Rosen
711 } // OHOS