• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2023-2024 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 #if defined(ANDROID_PLATFORM) || defined(IOS_PLATFORM)
17 #include "application_context.h"
18 #endif
19 #include <cstdlib>
20 #include <cerrno>
21 #include <limits>
22 
23 #include "drawable_descriptor.h"
24 
25 #include <cstddef>
26 #include <memory>
27 #include <string>
28 
29 #include "include/core/SkSamplingOptions.h"
30 #include "third_party/cJSON/cJSON.h"
31 
32 #ifndef PREVIEW
33 #include "image_source.h"
34 #endif
35 #include "include/core/SkImage.h"
36 #include "include/core/SkRect.h"
37 
38 #ifdef PREVIEW
39 #ifdef WINDOWS_PLATFORM
40 #include <direct.h>
41 #include <windows.h>
42 #elif defined(MAC_PLATFORM)
43 #include <mach-o/dyld.h>
44 #else
45 #include <unistd.h>
46 #endif
47 #endif
48 
49 namespace OHOS::Ace::Napi {
50 namespace {
51 #ifndef PREVIEW
52 const char DRAWABLEDESCRIPTOR_JSON_KEY_BACKGROUND[] = "background";
53 const char DRAWABLEDESCRIPTOR_JSON_KEY_FOREGROUND[] = "foreground";
54 #endif
55 #ifdef USE_ROSEN_DRAWING
56 constexpr float SIDE = 192.0f;
57 constexpr float BADGED_SIDE_X = 21.0f;
58 constexpr float BADGED_SIDE_Y = 7.0f;
59 constexpr float NOT_ADAPTIVE_SIZE = 288.0f;
60 constexpr float HALF = 0.5f;
61 
NearEqual(const double left,const double right,const double epsilon)62 inline bool NearEqual(const double left, const double right, const double epsilon)
63 {
64     return (std::abs(left - right) <= epsilon);
65 }
66 
NearEqual(const double left,const double right)67 inline bool NearEqual(const double left, const double right)
68 {
69     constexpr double epsilon = 0.001f;
70     return NearEqual(left, right, epsilon);
71 }
72 
73 #endif
74 const int DEFAULT_DURATION = 1000;
75 const std::string DEFAULT_MASK = "ohos_icon_mask";
76 constexpr int DECIMAL_BASE = 10;
77 
78 // define for get resource path in preview scenes
79 const static char PREVIEW_LOAD_RESOURCE_ID[] = "ohos_drawable_descriptor_path";
80 #ifdef PREVIEW
81 #ifdef WINDOWS_PLATFORM
82 constexpr static char PREVIEW_LOAD_RESOURCE_PATH[] = "\\resources\\resources.index";
83 #else
84 constexpr static char PREVIEW_LOAD_RESOURCE_PATH[] = "/resources/resources.index";
85 #endif
86 
87 #ifdef LINUX_PLATFORM
88 const static size_t MAX_PATH_LEN = 255;
89 #endif
90 #endif
IsNumber(const std::string & value)91 inline bool IsNumber(const std::string& value)
92 {
93     if (value.empty()) {
94         return false;
95     }
96     return std::all_of(value.begin(), value.end(), [](char i) { return isdigit(i); });
97 }
98 
ConvertStringToUInt32(const std::string & idStr,uint32_t & result)99 bool ConvertStringToUInt32(const std::string& idStr, uint32_t& result)
100 {
101     char* endPtr = nullptr;
102     errno = 0;
103     result = std::strtoul(idStr.c_str(), &endPtr, DECIMAL_BASE);
104     if (errno == ERANGE || result > std::numeric_limits<uint32_t>::max()) {
105         HILOGE("Out of range: string value is too large for uint32_t");
106         return false;
107     }
108     if (endPtr == idStr.c_str() || *endPtr != '\0') {
109         HILOGE("Invalid argument: unable to convert string to uint32_t");
110         return false;
111     }
112 
113     return true;
114 }
115 } // namespace
116 
PreGetDrawableItem(const std::shared_ptr<Global::Resource::ResourceManager> & resourceMgr,const char * item)117 DrawableItem LayeredDrawableDescriptor::PreGetDrawableItem(
118     const std::shared_ptr<Global::Resource::ResourceManager>& resourceMgr, const char* item)
119 {
120     std::string itemStr = item;
121     std::string idStr = itemStr.substr(itemStr.find(':') + 1);
122     DrawableItem resItem;
123     if (!IsNumber(idStr)) {
124         return resItem;
125     }
126 
127     std::tuple<std::string, size_t, std::string> info;
128     uint32_t resourceId = 0;
129     if (ConvertStringToUInt32(idStr, resourceId)) {
130         resItem.state_ = resourceMgr->GetDrawableInfoById(resourceId, info, resItem.data_, iconType_, density_);
131     }
132     resItem.len_ = std::get<1>(info);
133     return resItem;
134 }
135 
PreGetPixelMapFromJsonBuf(const std::shared_ptr<Global::Resource::ResourceManager> & resourceMgr,bool isBackground)136 bool LayeredDrawableDescriptor::PreGetPixelMapFromJsonBuf(
137     const std::shared_ptr<Global::Resource::ResourceManager>& resourceMgr, bool isBackground)
138 {
139 #ifndef PREVIEW
140     cJSON* roots = cJSON_ParseWithLength(reinterpret_cast<const char*>(jsonBuf_.get()), len_);
141 
142     if (roots == nullptr) {
143         return false;
144     }
145 
146     cJSON* item = nullptr;
147     if (isBackground) {
148         item = cJSON_GetObjectItem(roots->child, DRAWABLEDESCRIPTOR_JSON_KEY_BACKGROUND);
149     } else {
150         item = cJSON_GetObjectItem(roots->child, DRAWABLEDESCRIPTOR_JSON_KEY_FOREGROUND);
151     }
152     if (item == nullptr) {
153         cJSON_Delete(roots);
154         HILOGE("GetObjectItem from json buffer failed");
155         return false;
156     }
157     if (cJSON_IsString(item)) {
158         DrawableItem& drawableiItem = isBackground ? backgroundItem_ : foregroundItem_;
159         drawableiItem = PreGetDrawableItem(resourceMgr, item->valuestring);
160     } else {
161         cJSON_Delete(roots);
162         return false;
163     }
164     cJSON_Delete(roots);
165     return true;
166 #else
167     return false;
168 #endif
169 }
170 
InitialResource(const std::shared_ptr<Global::Resource::ResourceManager> & resourceMgr)171 void LayeredDrawableDescriptor::InitialResource(const std::shared_ptr<Global::Resource::ResourceManager>& resourceMgr)
172 {
173     if (!resourceMgr) {
174         HILOGE("Global resource manager is null!");
175         return;
176     }
177     InitialMask(resourceMgr);
178     // preprocess get background and foreground
179     if (!PreGetPixelMapFromJsonBuf(resourceMgr, true)) {
180         HILOGD("Create background Item imageSource from json buffer failed");
181     }
182     if (!PreGetPixelMapFromJsonBuf(resourceMgr, false)) {
183         HILOGD("Create foreground Item imageSource from json buffer failed");
184     }
185 }
186 
InitialMask(const std::shared_ptr<Global::Resource::ResourceManager> & resourceMgr)187 void LayeredDrawableDescriptor::InitialMask(const std::shared_ptr<Global::Resource::ResourceManager>& resourceMgr)
188 {
189     resourceMgr->GetMediaDataByName(DEFAULT_MASK.c_str(), defaultMaskDataLength_, defaultMaskData_);
190 }
191 
GetPixelMapFromBuffer()192 bool DrawableDescriptor::GetPixelMapFromBuffer()
193 {
194     Media::SourceOptions opts;
195     uint32_t errorCode = 0;
196     std::unique_ptr<Media::ImageSource> imageSource =
197         Media::ImageSource::CreateImageSource(mediaData_.get(), len_, opts, errorCode);
198     if (errorCode != 0) {
199         HILOGE("CreateImageSource from buffer failed");
200         return false;
201     }
202     mediaData_.reset();
203     Media::DecodeOptions decodeOpts;
204     decodeOpts.desiredPixelFormat = Media::PixelFormat::BGRA_8888;
205     if (imageSource) {
206         auto pixelMapPtr = imageSource->CreatePixelMap(decodeOpts, errorCode);
207         pixelMap_ = std::shared_ptr<Media::PixelMap>(pixelMapPtr.release());
208     }
209     if (errorCode != 0 || !pixelMap_) {
210         HILOGE("Get PixelMap from buffer failed");
211         return false;
212     }
213     return true;
214 }
215 
GetPixelMap()216 std::shared_ptr<Media::PixelMap> DrawableDescriptor::GetPixelMap()
217 {
218     if (pixelMap_.has_value()) {
219         return pixelMap_.value();
220     }
221     if (GetPixelMapFromBuffer()) {
222         return pixelMap_.value();
223     }
224     HILOGE("Failed to GetPixelMap!");
225     return nullptr;
226 }
227 
GetDrawableType()228 DrawableDescriptor::DrawableType DrawableDescriptor::GetDrawableType()
229 {
230     return DrawableType::BASE;
231 }
232 
CreateImageSource(DrawableItem & drawableItem,uint32_t & errorCode)233 std::unique_ptr<Media::ImageSource> LayeredDrawableDescriptor::CreateImageSource(
234     DrawableItem& drawableItem, uint32_t& errorCode)
235 {
236     if (drawableItem.state_ != Global::Resource::SUCCESS) {
237         HILOGE("GetDrawableInfoById failed");
238         return nullptr;
239     }
240 
241     Media::SourceOptions opts;
242     return Media::ImageSource::CreateImageSource(drawableItem.data_.get(), drawableItem.len_, opts, errorCode);
243 }
244 
GetPixelMapFromJsonBuf(bool isBackground)245 bool LayeredDrawableDescriptor::GetPixelMapFromJsonBuf(bool isBackground)
246 {
247 #ifndef PREVIEW
248     if ((isBackground && background_.has_value()) || (!isBackground && foreground_.has_value())) {
249         return true;
250     }
251     if ((isBackground && backgroundItem_.state_ == Global::Resource::SUCCESS) ||
252         (!isBackground && foregroundItem_.state_ == Global::Resource::SUCCESS)) {
253         uint32_t errorCode = 0;
254         std::unique_ptr<Media::ImageSource> imageSource =
255             LayeredDrawableDescriptor::CreateImageSource(isBackground ? backgroundItem_ : foregroundItem_, errorCode);
256         if (errorCode != 0) {
257             HILOGE("CreateImageSource from json buffer failed");
258             return false;
259         }
260         Media::DecodeOptions decodeOpts;
261         decodeOpts.desiredPixelFormat = Media::PixelFormat::BGRA_8888;
262         if (imageSource) {
263             auto pixelMapPtr = imageSource->CreatePixelMap(decodeOpts, errorCode);
264             if (errorCode != 0) {
265                 HILOGE("Get PixelMap from json buffer failed");
266                 return false;
267             }
268 
269             if (isBackground) {
270                 background_ = std::shared_ptr<Media::PixelMap>(pixelMapPtr.release());
271             } else {
272                 foreground_ = std::shared_ptr<Media::PixelMap>(pixelMapPtr.release());
273             }
274         }
275     } else {
276         HILOGE("Get background from json buffer failed");
277         return false;
278     }
279     if (isBackground) {
280         backgroundItem_.data_.reset();
281     } else {
282         foregroundItem_.data_.reset();
283     }
284     return true;
285 #else
286     return false;
287 #endif
288 }
289 
GetDefaultMask()290 bool LayeredDrawableDescriptor::GetDefaultMask()
291 {
292     Media::SourceOptions opts;
293     uint32_t errorCode = 0;
294     std::unique_ptr<Media::ImageSource> imageSource =
295         Media::ImageSource::CreateImageSource(
296             defaultMaskData_.get(), defaultMaskDataLength_, opts, errorCode);
297     Media::DecodeOptions decodeOpts;
298     decodeOpts.desiredPixelFormat = Media::PixelFormat::BGRA_8888;
299     if (imageSource) {
300         auto pixelMapPtr = imageSource->CreatePixelMap(decodeOpts, errorCode);
301         mask_ = std::shared_ptr<Media::PixelMap>(pixelMapPtr.release());
302     }
303     if (errorCode != 0 || !mask_) {
304         HILOGE("Get mask failed");
305         return false;
306     }
307     return true;
308 }
309 
InitLayeredParam(std::pair<std::unique_ptr<uint8_t[]>,size_t> & foregroundInfo,std::pair<std::unique_ptr<uint8_t[]>,size_t> & backgroundInfo)310 void LayeredDrawableDescriptor::InitLayeredParam(std::pair<std::unique_ptr<uint8_t[]>, size_t> &foregroundInfo,
311     std::pair<std::unique_ptr<uint8_t[]>, size_t> &backgroundInfo)
312 {
313     Media::SourceOptions opts;
314     uint32_t errorCode = 0;
315     auto foreground = Media::ImageSource::CreateImageSource(foregroundInfo.first.get(), foregroundInfo.second, opts,
316         errorCode);
317     if (errorCode == 0 && foreground) {
318         Media::DecodeOptions decodeOpts;
319         decodeOpts.desiredPixelFormat = Media::PixelFormat::BGRA_8888;
320         auto pixelMapPtr = foreground->CreatePixelMap(decodeOpts, errorCode);
321         foreground_ = std::shared_ptr<Media::PixelMap>(pixelMapPtr.release());
322     }
323     auto background = Media::ImageSource::CreateImageSource(backgroundInfo.first.get(), backgroundInfo.second, opts,
324         errorCode);
325     if (errorCode == 0 && background) {
326         Media::DecodeOptions decodeOpts;
327         decodeOpts.desiredPixelFormat = Media::PixelFormat::BGRA_8888;
328         auto pixelMapPtr = background->CreatePixelMap(decodeOpts, errorCode);
329         background_ = std::shared_ptr<Media::PixelMap>(pixelMapPtr.release());
330     }
331 }
332 
GetMaskByPath()333 bool LayeredDrawableDescriptor::GetMaskByPath()
334 {
335     if (maskPath_.empty()) {
336         HILOGD("maskPath is null");
337         return false;
338     }
339     Media::SourceOptions opts;
340     uint32_t errorCode = 0;
341     std::unique_ptr<Media::ImageSource> imageSource =
342         Media::ImageSource::CreateImageSource(maskPath_, opts, errorCode);
343     Media::DecodeOptions decodeOpts;
344     decodeOpts.desiredPixelFormat = Media::PixelFormat::BGRA_8888;
345     if (imageSource) {
346         auto pixelMapPtr = imageSource->CreatePixelMap(decodeOpts, errorCode);
347         mask_ = std::shared_ptr<Media::PixelMap>(pixelMapPtr.release());
348     }
349     if (errorCode != 0 || !mask_) {
350         HILOGE("Get mask failed");
351         return false;
352     }
353     return true;
354 }
355 
GetMaskByName(std::shared_ptr<Global::Resource::ResourceManager> & resourceMgr,const std::string & name)356 bool LayeredDrawableDescriptor::GetMaskByName(
357     std::shared_ptr<Global::Resource::ResourceManager>& resourceMgr, const std::string& name)
358 {
359     size_t len = 0;
360     std::unique_ptr<uint8_t[]> data;
361     resourceMgr->GetMediaDataByName(name.c_str(), len, data);
362     Media::SourceOptions opts;
363     uint32_t errorCode = 0;
364     std::unique_ptr<Media::ImageSource> imageSource =
365         Media::ImageSource::CreateImageSource(data.get(), len, opts, errorCode);
366     Media::DecodeOptions decodeOpts;
367     decodeOpts.desiredPixelFormat = Media::PixelFormat::BGRA_8888;
368     if (imageSource) {
369         auto pixelMapPtr = imageSource->CreatePixelMap(decodeOpts, errorCode);
370         mask_ = std::shared_ptr<Media::PixelMap>(pixelMapPtr.release());
371     }
372     if (errorCode != 0 || !mask_) {
373         HILOGE("Get mask failed");
374         return false;
375     }
376     return true;
377 }
378 
GetForeground()379 std::unique_ptr<DrawableDescriptor> LayeredDrawableDescriptor::GetForeground()
380 {
381     if (foreground_.has_value()) {
382         return std::make_unique<DrawableDescriptor>(foreground_.value());
383     }
384 
385     if (GetPixelMapFromJsonBuf(false)) {
386         return std::make_unique<DrawableDescriptor>(foreground_.value());
387     }
388 
389     HILOGE("GetForeground failed");
390     return nullptr;
391 }
392 
GetBackground()393 std::unique_ptr<DrawableDescriptor> LayeredDrawableDescriptor::GetBackground()
394 {
395     if (background_.has_value()) {
396         return std::make_unique<DrawableDescriptor>(background_.value());
397     }
398 
399     if (GetPixelMapFromJsonBuf(true)) {
400         return std::make_unique<DrawableDescriptor>(background_.value());
401     }
402     HILOGE("GetBackground failed");
403     return nullptr;
404 }
405 
GetMask()406 std::unique_ptr<DrawableDescriptor> LayeredDrawableDescriptor::GetMask()
407 {
408     if (mask_.has_value()) {
409         return std::make_unique<DrawableDescriptor>(mask_.value());
410     }
411 
412     if (GetMaskByPath()) {
413         return std::make_unique<DrawableDescriptor>(mask_.value());
414     }
415 
416     if (GetDefaultMask()) {
417         return std::make_unique<DrawableDescriptor>(mask_.value());
418     }
419 
420     HILOGE("GetMask failed");
421     return nullptr;
422 }
423 
424 #ifndef USE_ROSEN_DRAWING
DrawOntoCanvas(const std::shared_ptr<SkBitmap> & bitMap,float width,float height,SkCanvas & canvas,const SkPaint & paint)425 void LayeredDrawableDescriptor::DrawOntoCanvas(
426     const std::shared_ptr<SkBitmap>& bitMap, float width, float height, SkCanvas& canvas, const SkPaint& paint)
427 {
428     auto x = static_cast<float>((bitMap->width() - static_cast<float>(width)) / 2);
429     auto y = static_cast<float>((bitMap->height() - static_cast<float>(height)) / 2);
430     auto rect1 = SkRect::MakeXYWH(x, y, static_cast<float>(width), static_cast<float>(width));
431     auto rect2 = SkRect::MakeWH(static_cast<float>(width), static_cast<float>(width));
432 
433     canvas.drawImageRect(
434         SkImage::MakeFromBitmap(*bitMap), rect1, rect2, SkSamplingOptions(), &paint, SkCanvas::kFast_SrcRectConstraint);
435 }
436 #else
DrawOntoCanvas(const std::shared_ptr<Rosen::Drawing::Bitmap> & bitMap,float width,float height,Rosen::Drawing::Canvas & canvas)437 void LayeredDrawableDescriptor::DrawOntoCanvas(
438     const std::shared_ptr<Rosen::Drawing::Bitmap>& bitMap, float width, float height, Rosen::Drawing::Canvas& canvas)
439 {
440     auto x = static_cast<float>((bitMap->GetWidth() - static_cast<float>(width)) / 2);
441     auto y = static_cast<float>((bitMap->GetHeight() - static_cast<float>(height)) / 2);
442     Rosen::Drawing::Rect srcRect(x, y, static_cast<float>(width) + x, static_cast<float>(width) + y);
443     Rosen::Drawing::Rect dstRect(0, 0, static_cast<float>(width), static_cast<float>(width));
444     Rosen::Drawing::Image image;
445     image.BuildFromBitmap(*bitMap);
446     canvas.DrawImageRect(image, srcRect, dstRect, Rosen::Drawing::SamplingOptions(),
447         Rosen::Drawing::SrcRectConstraint::FAST_SRC_RECT_CONSTRAINT);
448 }
GetLayeredIconParm(std::shared_ptr<Rosen::Drawing::Bitmap> & foreground,std::shared_ptr<Rosen::Drawing::Bitmap> & background,std::shared_ptr<Rosen::Drawing::Bitmap> & mask)449 bool LayeredDrawableDescriptor::GetLayeredIconParm(std::shared_ptr<Rosen::Drawing::Bitmap>& foreground,
450     std::shared_ptr<Rosen::Drawing::Bitmap>& background, std::shared_ptr<Rosen::Drawing::Bitmap>& mask)
451 {
452     if (foreground_.has_value() || GetPixelMapFromJsonBuf(false)) {
453         foreground = ImageConverter::PixelMapToBitmap(foreground_.value());
454     } else if (!customized_) {
455         HILOGI("Get pixelMap of foreground failed.");
456         return false;
457     }
458     if (background_.has_value() || GetPixelMapFromJsonBuf(true)) {
459         background = ImageConverter::PixelMapToBitmap(background_.value());
460     } else if (!customized_) {
461         HILOGE("Get pixelMap of background failed.");
462         return false;
463     }
464     if (mask_.has_value() || GetMaskByPath() || GetDefaultMask()) {
465         mask = ImageConverter::PixelMapToBitmap(mask_.value());
466     } else if (!customized_) {
467         HILOGE("Get pixelMap of mask failed.");
468         return false;
469     }
470     return true;
471 }
472 
TransformToPixelMap(const Rosen::Drawing::Bitmap & bitmap,const Rosen::Drawing::ImageInfo & imageInfo)473 void LayeredDrawableDescriptor::TransformToPixelMap(
474     const Rosen::Drawing::Bitmap& bitmap, const Rosen::Drawing::ImageInfo& imageInfo)
475 {
476     Media::InitializationOptions opts;
477     if (background_.has_value()) {
478         opts.alphaType = background_.value()->GetAlphaType();
479     } else {
480         opts.alphaType = Media::AlphaType::IMAGE_ALPHA_TYPE_PREMUL;
481     }
482     opts.pixelFormat = Media::PixelFormat::BGRA_8888;
483     layeredPixelMap_ = ImageConverter::BitmapToPixelMap(std::make_shared<Rosen::Drawing::Bitmap>(bitmap), opts);
484 }
485 
CreateRSImageInfo(OptionalPixelMap pixelmap,int32_t width,int32_t height)486 Rosen::Drawing::ImageInfo LayeredDrawableDescriptor::CreateRSImageInfo(
487     OptionalPixelMap pixelmap, int32_t width, int32_t height)
488 {
489     Rosen::Drawing::ColorType colorType =
490         pixelmap.has_value() && pixelmap.value()
491             ? colorType = ImageConverter::PixelFormatToColorType(pixelmap.value()->GetPixelFormat())
492             : colorType = ImageConverter::PixelFormatToColorType(Media::PixelFormat::RGBA_8888);
493     Rosen::Drawing::AlphaType alphaType =
494         pixelmap.has_value() && pixelmap.value()
495             ? alphaType = ImageConverter::AlphaTypeToAlphaType(pixelmap.value()->GetAlphaType())
496             : alphaType = ImageConverter::AlphaTypeToAlphaType(Media::AlphaType::IMAGE_ALPHA_TYPE_PREMUL);
497     return Rosen::Drawing::ImageInfo(width, height, colorType, alphaType);
498 }
499 
CompositeIconAdaptive(std::shared_ptr<Rosen::Drawing::Bitmap> & foreground,std::shared_ptr<Rosen::Drawing::Bitmap> & background,std::shared_ptr<Rosen::Drawing::Bitmap> & mask)500 void LayeredDrawableDescriptor::CompositeIconAdaptive(std::shared_ptr<Rosen::Drawing::Bitmap>& foreground,
501     std::shared_ptr<Rosen::Drawing::Bitmap>& background, std::shared_ptr<Rosen::Drawing::Bitmap>& mask)
502 {
503     if (!background) {
504         HILOGW("The background is null when adaptive composite icons are used.");
505         return;
506     }
507     Rosen::Drawing::Brush brush;
508     brush.SetAntiAlias(true);
509     Rosen::Drawing::ImageInfo imageInfo =
510         CreateRSImageInfo(background_, background->GetWidth(), background->GetHeight());
511     Rosen::Drawing::Bitmap tempCache;
512     tempCache.Build(imageInfo);
513     Rosen::Drawing::Canvas bitmapCanvas;
514     bitmapCanvas.Bind(tempCache);
515 
516     if (background) {
517         brush.SetBlendMode(Rosen::Drawing::BlendMode::SRC);
518         bitmapCanvas.AttachBrush(brush);
519         DrawOntoCanvas(background, background->GetWidth(), background->GetHeight(), bitmapCanvas);
520         bitmapCanvas.DetachBrush();
521     }
522 
523     Rosen::Drawing::Rect dstRect(
524         0.0, 0.0, static_cast<float>(background->GetWidth()), static_cast<float>(background->GetHeight()));
525     Rosen::Drawing::Image image;
526     if (mask) {
527         Rosen::Drawing::Rect srcRect(
528             0.0, 0.0, static_cast<float>(mask->GetWidth()), static_cast<float>(mask->GetHeight()));
529         image.BuildFromBitmap(*mask);
530         brush.SetBlendMode(Rosen::Drawing::BlendMode::DST_IN);
531         bitmapCanvas.AttachBrush(brush);
532         bitmapCanvas.DrawImageRect(image, srcRect, dstRect, Rosen::Drawing::SamplingOptions(),
533             Rosen::Drawing::SrcRectConstraint::FAST_SRC_RECT_CONSTRAINT);
534         bitmapCanvas.DetachBrush();
535     }
536     if (foreground) {
537         BlendForeground(bitmapCanvas, brush, image, background, foreground);
538     }
539     // convert bitmap back to pixelMap
540     bitmapCanvas.ReadPixels(imageInfo, tempCache.GetPixels(), tempCache.GetRowBytes(), 0, 0);
541     TransformToPixelMap(tempCache, imageInfo);
542 }
543 
BlendForeground(Rosen::Drawing::Canvas & bitmapCanvas,Rosen::Drawing::Brush & brush,Rosen::Drawing::Image & image,const std::shared_ptr<Rosen::Drawing::Bitmap> & background,const std::shared_ptr<Rosen::Drawing::Bitmap> & foreground)544 void LayeredDrawableDescriptor::BlendForeground(Rosen::Drawing::Canvas& bitmapCanvas, Rosen::Drawing::Brush& brush,
545     Rosen::Drawing::Image& image, const std::shared_ptr<Rosen::Drawing::Bitmap>& background,
546     const std::shared_ptr<Rosen::Drawing::Bitmap>& foreground)
547 {
548     if (!foreground || !background || NearEqual(foreground->GetWidth(), 0.0) ||
549         NearEqual(foreground->GetHeight(), 0.0)) {
550         return;
551     }
552     auto scale = std::min(background->GetWidth() * 1.0f / foreground->GetWidth(),
553         background->GetHeight() * 1.0f / foreground->GetHeight());
554     if (NearEqual(scale, 0.0)) {
555         return;
556     }
557     auto destWidth = foreground->GetWidth() * scale;
558     auto destHeight = foreground->GetHeight() * scale;
559     auto dstOffsetX = static_cast<float>((background->GetWidth() - destWidth) * HALF);
560     auto dstOffsetY = static_cast<float>((background->GetHeight() - destHeight) * HALF);
561     Rosen::Drawing::Rect rsSrcRect(0.0, 0.0, foreground->GetWidth(), foreground->GetHeight());
562     Rosen::Drawing::Rect rsDstRect(dstOffsetX, dstOffsetY,
563         destWidth + dstOffsetX, destHeight + dstOffsetY);
564     brush.SetBlendMode(Rosen::Drawing::BlendMode::SRC_ATOP);
565     bitmapCanvas.AttachBrush(brush);
566     image.BuildFromBitmap(*foreground);
567     bitmapCanvas.DrawImageRect(image, rsSrcRect, rsDstRect, Rosen::Drawing::SamplingOptions(),
568         Rosen::Drawing::SrcRectConstraint::FAST_SRC_RECT_CONSTRAINT);
569     bitmapCanvas.DetachBrush();
570 }
571 
CompositeIconNotAdaptive(std::shared_ptr<Rosen::Drawing::Bitmap> & foreground,std::shared_ptr<Rosen::Drawing::Bitmap> & background,std::shared_ptr<Rosen::Drawing::Bitmap> & mask)572 void LayeredDrawableDescriptor::CompositeIconNotAdaptive(std::shared_ptr<Rosen::Drawing::Bitmap>& foreground,
573     std::shared_ptr<Rosen::Drawing::Bitmap>& background, std::shared_ptr<Rosen::Drawing::Bitmap>& mask)
574 {
575     Rosen::Drawing::Brush brush;
576     brush.SetAntiAlias(true);
577     Rosen::Drawing::ImageInfo imageInfo = CreateRSImageInfo(background_, SIDE, SIDE);
578     Rosen::Drawing::Bitmap tempCache;
579     tempCache.Build(imageInfo);
580     Rosen::Drawing::Canvas bitmapCanvas;
581     bitmapCanvas.Bind(tempCache);
582 
583     // if developer uses customized param, foreground, background, mask might be null
584     if (background) {
585         brush.SetBlendMode(Rosen::Drawing::BlendMode::SRC);
586         bitmapCanvas.AttachBrush(brush);
587         DrawOntoCanvas(background, SIDE, SIDE, bitmapCanvas);
588         bitmapCanvas.DetachBrush();
589     }
590     if (mask) {
591         brush.SetBlendMode(Rosen::Drawing::BlendMode::DST_IN);
592         bitmapCanvas.AttachBrush(brush);
593         DrawOntoCanvas(mask, SIDE, SIDE, bitmapCanvas);
594         bitmapCanvas.DetachBrush();
595     }
596     if (foreground) {
597         brush.SetBlendMode(Rosen::Drawing::BlendMode::SRC_ATOP);
598         bitmapCanvas.AttachBrush(brush);
599         DrawOntoCanvas(foreground, SIDE, SIDE, bitmapCanvas);
600         bitmapCanvas.DetachBrush();
601     }
602     bitmapCanvas.ReadPixels(imageInfo, tempCache.GetPixels(), tempCache.GetRowBytes(), 0, 0);
603     // convert bitmap back to pixelMap
604     Media::InitializationOptions opts;
605     if (background_.has_value()) {
606         opts.alphaType = background_.value()->GetAlphaType();
607     } else {
608         opts.alphaType = Media::AlphaType::IMAGE_ALPHA_TYPE_PREMUL;
609     }
610     opts.pixelFormat = Media::PixelFormat::BGRA_8888;
611     TransformToPixelMap(tempCache, imageInfo);
612 }
613 #endif
614 
615 #ifndef USE_ROSEN_DRAWING
CreatePixelMap()616 bool LayeredDrawableDescriptor::CreatePixelMap()
617 {
618     HILOGE("not support");
619     return false;
620 }
621 
GetCompositePixelMapWithBadge(const std::shared_ptr<Media::PixelMap> layeredPixelMap,const std::shared_ptr<Media::PixelMap> badgedPixelMap,std::shared_ptr<Media::PixelMap> & compositePixelMap)622 bool LayeredDrawableDescriptor::GetCompositePixelMapWithBadge(
623     const std::shared_ptr<Media::PixelMap> layeredPixelMap,
624     const std::shared_ptr<Media::PixelMap> badgedPixelMap,
625     std::shared_ptr<Media::PixelMap> &compositePixelMap)
626 {
627     HILOGE("not support");
628     return false;
629 }
630 
631 #else
CreatePixelMap()632 bool LayeredDrawableDescriptor::CreatePixelMap()
633 {
634     // if customizedParam_.HasParamCustomized() true,
635     // meaning this descriptor is not created by resource manager,
636     // therefore some params might not be valid.
637     // Otherwise if HasParamCustomized() false,
638     // meaning this descriptor is created by resource manager or
639     // napi directly but has no param passed in, then we should return if any param is missing
640     std::shared_ptr<Rosen::Drawing::Bitmap> foreground;
641     std::shared_ptr<Rosen::Drawing::Bitmap> background;
642     std::shared_ptr<Rosen::Drawing::Bitmap> mask;
643     if (!GetLayeredIconParm(foreground, background, mask)) {
644         return false;
645     }
646     // when the foreground'size is 288 x 288, we don't scale.
647     if (foreground && NearEqual(NOT_ADAPTIVE_SIZE, foreground->GetWidth()) &&
648         NearEqual(NOT_ADAPTIVE_SIZE, foreground->GetHeight())) {
649         HILOGD("foreground size is 288 x 288, we don't scale the foreground.");
650         CompositeIconNotAdaptive(foreground, background, mask);
651     } else {
652         HILOGD("foreground size is not 288 x 288, we'll scale the foreground.");
653         CompositeIconAdaptive(foreground, background, mask);
654     }
655     return true;
656 }
657 
GetCompositePixelMapWithBadge(const std::shared_ptr<Media::PixelMap> layeredPixelMap,const std::shared_ptr<Media::PixelMap> badgedPixelMap,std::shared_ptr<Media::PixelMap> & compositePixelMap)658 bool LayeredDrawableDescriptor::GetCompositePixelMapWithBadge(
659     const std::shared_ptr<Media::PixelMap> layeredPixelMap,
660     const std::shared_ptr<Media::PixelMap> badgedPixelMap,
661     std::shared_ptr<Media::PixelMap> &compositePixelMap)
662 {
663     if ((layeredPixelMap == nullptr) || (badgedPixelMap == nullptr)) {
664         HILOGE("failed due to nullptr");
665         return false;
666     }
667     Rosen::Drawing::Brush brush;
668     brush.SetAntiAlias(true);
669     Rosen::Drawing::ColorType colorType = ImageConverter::PixelFormatToColorType(layeredPixelMap->GetPixelFormat());
670     Rosen::Drawing::AlphaType alphaType = ImageConverter::AlphaTypeToAlphaType(layeredPixelMap->GetAlphaType());
671     Rosen::Drawing::ImageInfo imageInfo(SIDE + BADGED_SIDE_X, SIDE + BADGED_SIDE_Y, colorType, alphaType);
672     Rosen::Drawing::Bitmap tempCache;
673     tempCache.Build(imageInfo);
674     Rosen::Drawing::Canvas bitmapCanvas;
675     bitmapCanvas.Bind(tempCache);
676     std::shared_ptr<Rosen::Drawing::Bitmap> layeredBitmap = ImageConverter::PixelMapToBitmap(layeredPixelMap);
677     if (layeredBitmap) {
678         brush.SetBlendMode(Rosen::Drawing::BlendMode::SRC);
679         bitmapCanvas.AttachBrush(brush);
680         Rosen::Drawing::Rect srcRect(0, 0, layeredBitmap->GetWidth(), layeredBitmap->GetHeight());
681         Rosen::Drawing::Rect dstRect(0, 0, SIDE, SIDE);
682         Rosen::Drawing::Image image;
683         image.BuildFromBitmap(*layeredBitmap);
684         bitmapCanvas.DrawImageRect(image, srcRect, dstRect,
685             Rosen::Drawing::SamplingOptions(), Rosen::Drawing::SrcRectConstraint::FAST_SRC_RECT_CONSTRAINT);
686         bitmapCanvas.DetachBrush();
687     }
688     std::shared_ptr<Rosen::Drawing::Bitmap> badgedBitmap = ImageConverter::PixelMapToBitmap(badgedPixelMap);
689     if (badgedBitmap) {
690         brush.SetBlendMode(Rosen::Drawing::BlendMode::SRC_OVER);
691         bitmapCanvas.AttachBrush(brush);
692         Rosen::Drawing::Rect srcRect(0, 0, badgedBitmap->GetWidth(), badgedBitmap->GetHeight());
693         Rosen::Drawing::Rect dstRect(SIDE + BADGED_SIDE_X - badgedBitmap->GetWidth(),
694             SIDE + BADGED_SIDE_Y - badgedBitmap->GetHeight(), SIDE + BADGED_SIDE_X, SIDE + BADGED_SIDE_Y);
695         Rosen::Drawing::Image image;
696         image.BuildFromBitmap(*badgedBitmap);
697         bitmapCanvas.DrawImageRect(image, srcRect, dstRect,
698             Rosen::Drawing::SamplingOptions(), Rosen::Drawing::SrcRectConstraint::FAST_SRC_RECT_CONSTRAINT);
699         bitmapCanvas.DetachBrush();
700     }
701     bitmapCanvas.ReadPixels(imageInfo, tempCache.GetPixels(), tempCache.GetRowBytes(), 0, 0);
702     Media::InitializationOptions initializationOptions;
703     initializationOptions.alphaType = layeredPixelMap->GetAlphaType();
704     initializationOptions.pixelFormat = Media::PixelFormat::BGRA_8888;
705     compositePixelMap = ImageConverter::BitmapToPixelMap(std::make_shared<Rosen::Drawing::Bitmap>(tempCache),
706         initializationOptions);
707     return true;
708 }
709 #endif
710 
GetPixelMap()711 std::shared_ptr<Media::PixelMap> LayeredDrawableDescriptor::GetPixelMap()
712 {
713     if (layeredPixelMap_.has_value()) {
714         return layeredPixelMap_.value();
715     }
716 
717     if (CreatePixelMap()) {
718         return layeredPixelMap_.value();
719     }
720 
721     HILOGE("Failed to GetPixelMap!");
722     return nullptr;
723 }
724 
GetDrawableType()725 DrawableDescriptor::DrawableType LayeredDrawableDescriptor::GetDrawableType()
726 {
727     return DrawableType::LAYERED;
728 }
729 
GetStaticMaskClipPath()730 std::string LayeredDrawableDescriptor::GetStaticMaskClipPath()
731 {
732     std::string data;
733 #if defined(ANDROID_PLATFORM) || defined(IOS_PLATFORM)
734     std::shared_ptr<AbilityRuntime::Platform::ApplicationContext> applicationContext =
735         AbilityRuntime::Platform::ApplicationContext::GetInstance();
736     if (!applicationContext) {
737         HILOGE("Failed to get applicationContext!");
738         data = "";
739         return data;
740     }
741     auto resMgr = applicationContext->GetResourceManager();
742     if (!resMgr) {
743         HILOGE("Failed to get resource manager!");
744         data = "";
745         return data;
746     }
747 #else
748     std::shared_ptr<Global::Resource::ResourceManager> resMgr(Global::Resource::CreateResourceManager());
749 #endif
750 #ifdef PREVIEW
751     std::string pathTmp = "";
752 #ifdef WINDOWS_PLATFORM
753     char pathBuf[MAX_PATH];
754     _getcwd(pathBuf, MAX_PATH);
755     pathTmp = pathBuf;
756 #elif defined(MAC_PLATFORM)
757     uint32_t size = 0;
758     _NSGetExecutablePath(nullptr, &size);
759 
760     char pathBuf[size + 1];
761     if (_NSGetExecutablePath(pathBuf, &size) != 0) {
762         pathBuf[0] = '\0';
763         HILOGE("Failed, buffer too small!");
764     }
765     pathBuf[size] = '\0';
766 
767     std::string previewFullPath = pathBuf;
768     size_t lastPathIdx = previewFullPath.find_last_of("\\/");
769     pathTmp = (lastPathIdx != std::string::npos) ? previewFullPath.substr(0, lastPathIdx) : "";
770 #else
771     char pathBuf[MAX_PATH_LEN];
772     readlink("/proc/self/exe", pathBuf, MAX_PATH_LEN);
773     pathTmp = pathBuf;
774 #endif
775     size_t lastPathSepLoc = pathTmp.find_last_of("\\/");
776     std::string path = (lastPathSepLoc != std::string::npos) ? pathTmp.substr(0, lastPathSepLoc) : "";
777     path += PREVIEW_LOAD_RESOURCE_PATH;
778     resMgr->AddResource(path.c_str());
779 #endif
780     resMgr->GetStringByName(PREVIEW_LOAD_RESOURCE_ID, data);
781     return data;
782 }
783 
GetPixelMap()784 std::shared_ptr<Media::PixelMap> AnimatedDrawableDescriptor::GetPixelMap()
785 {
786     if (pixelMapList_.empty()) {
787         return nullptr;
788     }
789     return pixelMapList_[0];
790 }
791 
GetDrawableType()792 DrawableDescriptor::DrawableType AnimatedDrawableDescriptor::GetDrawableType()
793 {
794     return DrawableType::ANIMATED;
795 }
796 
GetPixelMapList()797 std::vector<std::shared_ptr<Media::PixelMap>> AnimatedDrawableDescriptor::GetPixelMapList()
798 {
799     return pixelMapList_;
800 }
801 
GetDuration()802 int32_t AnimatedDrawableDescriptor::GetDuration()
803 {
804     if (duration_ <= 0) {
805         duration_ = DEFAULT_DURATION * static_cast<int32_t>(pixelMapList_.size());
806     }
807     return duration_;
808 }
809 
GetIterations()810 int32_t AnimatedDrawableDescriptor::GetIterations()
811 {
812     if (iterations_ < -1) {
813         iterations_ = 1;
814     }
815     return iterations_;
816 }
817 
SetDuration(int32_t duration)818 void AnimatedDrawableDescriptor::SetDuration(int32_t duration)
819 {
820     if (duration <= 0) {
821         duration_ = DEFAULT_DURATION * static_cast<int32_t>(pixelMapList_.size());
822     } else {
823         duration_ = duration;
824     }
825 }
826 
SetIterations(int32_t iterations)827 void AnimatedDrawableDescriptor::SetIterations(int32_t iterations)
828 {
829     if (iterations < -1) {
830         iterations_ = 1;
831     } else {
832         iterations_ = iterations;
833     }
834 }
835 } // namespace OHOS::Ace::Napi
836