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