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