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