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 #ifndef FOUNDATION_ACE_INTERFACE_INNERAPI_DRAWABLE_DESCRIPTOR_H
17 #define FOUNDATION_ACE_INTERFACE_INNERAPI_DRAWABLE_DESCRIPTOR_H
18 
19 #define ACE_FORCE_EXPORT __attribute__((visibility("default")))
20 
21 #ifndef ACE_EXPORT
22 #ifndef HIDDEN_SYMBOL
23 #define ACE_EXPORT ACE_FORCE_EXPORT
24 #else
25 #define ACE_EXPORT
26 #endif
27 #endif
28 
29 #include <optional>
30 #include <string>
31 #include <tuple>
32 #include <utility>
33 
34 #include "image_converter.h"
35 #ifndef USE_ROSEN_DRAWING
36 #include "include/core/SkBlendMode.h"
37 #include "include/core/SkCanvas.h"
38 #include "include/core/SkPaint.h"
39 #else
40 #include "draw/canvas.h"
41 #include "image/bitmap.h"
42 #include "image/image_info.h"
43 #endif
44 #include "resource_manager.h"
45 
46 #include "drawable_descriptor_log.h"
47 
48 namespace OHOS::Ace::Napi {
49 using OptionalPixelMap = std::optional<std::shared_ptr<Media::PixelMap>>;
50 struct DrawableItem {
51     using RState = Global::Resource::RState;
52     std::unique_ptr<uint8_t[]> data_;
53     size_t len_ = 0;
54     RState state_ = Global::Resource::ERROR;
55 };
56 
57 class ACE_EXPORT DrawableDescriptor {
58 public:
59     enum class DrawableType {
60         BASE,
61         LAYERED,
62         ANIMATED,
63         PIXELMAP,
64     };
65     DrawableDescriptor() = default;
DrawableDescriptor(std::shared_ptr<Media::PixelMap> pixelMap)66     explicit DrawableDescriptor(std::shared_ptr<Media::PixelMap> pixelMap) : pixelMap_(std::move(pixelMap)) {};
DrawableDescriptor(std::unique_ptr<uint8_t[]> mediaData,size_t len)67     DrawableDescriptor(std::unique_ptr<uint8_t[]> mediaData, size_t len)
68         : mediaData_(std::move(mediaData)), len_(len) {};
69     virtual ~DrawableDescriptor() = default;
70     virtual std::shared_ptr<Media::PixelMap> GetPixelMap();
71     virtual DrawableType GetDrawableType();
SetPixelMap(std::shared_ptr<Media::PixelMap> pixelMap)72     void SetPixelMap(std::shared_ptr<Media::PixelMap> pixelMap)
73     {
74         pixelMap_ = pixelMap;
75     }
HasPixelMap()76     bool HasPixelMap()
77     {
78         return pixelMap_.has_value();
79     }
ResetPixelMap()80     void ResetPixelMap()
81     {
82         pixelMap_.reset();
83     }
84 
85 private:
86     bool GetPixelMapFromBuffer();
87 
88     std::unique_ptr<uint8_t[]> mediaData_;
89     size_t len_ = 0;
90     OptionalPixelMap pixelMap_;
91 };
92 
93 class ACE_EXPORT LayeredDrawableDescriptor : public DrawableDescriptor {
94 public:
95     LayeredDrawableDescriptor() = default;
LayeredDrawableDescriptor(std::unique_ptr<uint8_t[]> jsonBuf,size_t len,const std::shared_ptr<Global::Resource::ResourceManager> & resourceMgr)96     LayeredDrawableDescriptor(std::unique_ptr<uint8_t[]> jsonBuf, size_t len,
97         const std::shared_ptr<Global::Resource::ResourceManager>& resourceMgr)
98         : jsonBuf_(std::move(jsonBuf)), len_(len)
99     {
100         InitialResource(resourceMgr);
101         jsonBuf_.reset();
102     };
LayeredDrawableDescriptor(std::unique_ptr<uint8_t[]> jsonBuf,size_t len,const std::shared_ptr<Global::Resource::ResourceManager> & resourceMgr,std::string path,uint32_t iconType,uint32_t density)103     LayeredDrawableDescriptor(std::unique_ptr<uint8_t[]> jsonBuf, size_t len,
104         const std::shared_ptr<Global::Resource::ResourceManager>& resourceMgr, std::string path, uint32_t iconType,
105         uint32_t density)
106         : jsonBuf_(std::move(jsonBuf)), len_(len), maskPath_(std::move(path)), iconType_(iconType), density_(density)
107     {
108         InitialResource(resourceMgr);
109         jsonBuf_.reset();
110     };
LayeredDrawableDescriptor(std::unique_ptr<uint8_t[]> jsonBuf,size_t len,const std::shared_ptr<Global::Resource::ResourceManager> & resourceMgr,std::string path,uint32_t iconType,std::pair<std::unique_ptr<uint8_t[]>,size_t> & foregroundInfo,std::pair<std::unique_ptr<uint8_t[]>,size_t> & backgroundInfo)111     LayeredDrawableDescriptor(std::unique_ptr<uint8_t[]> jsonBuf, size_t len,
112         const std::shared_ptr<Global::Resource::ResourceManager>& resourceMgr, std::string path, uint32_t iconType,
113         std::pair<std::unique_ptr<uint8_t[]>, size_t>& foregroundInfo,
114         std::pair<std::unique_ptr<uint8_t[]>, size_t>& backgroundInfo)
115         : jsonBuf_(std::move(jsonBuf)), len_(len), maskPath_(std::move(path)), iconType_(iconType)
116     {
117         InitLayeredParam(foregroundInfo, backgroundInfo);
118         InitialResource(resourceMgr);
119         jsonBuf_.reset();
120     };
121 
122     ~LayeredDrawableDescriptor() override = default;
123     std::unique_ptr<DrawableDescriptor> GetForeground();
124     std::unique_ptr<DrawableDescriptor> GetBackground();
125     std::unique_ptr<DrawableDescriptor> GetMask();
126     std::shared_ptr<Media::PixelMap> GetPixelMap() override;
127     DrawableType GetDrawableType() override;
128     static std::string GetStaticMaskClipPath();
129     void InitLayeredParam(std::pair<std::unique_ptr<uint8_t[]>, size_t> &foregroundInfo,
130         std::pair<std::unique_ptr<uint8_t[]>, size_t> &backgroundInfo);
SetForeground(std::shared_ptr<Media::PixelMap> foreground)131     void SetForeground(std::shared_ptr<Media::PixelMap> foreground)
132     {
133         foreground_ = foreground;
134         customized_ = true;
135     }
136 
SetBackground(std::shared_ptr<Media::PixelMap> background)137     void SetBackground(std::shared_ptr<Media::PixelMap> background)
138     {
139         background_ = background;
140         customized_ = true;
141     }
142 
SetMask(std::shared_ptr<Media::PixelMap> mask)143     void SetMask(std::shared_ptr<Media::PixelMap> mask)
144     {
145         mask_ = mask;
146         customized_ = true;
147     }
148 
Customized()149     bool Customized()
150     {
151         return customized_;
152     }
153 
154     void InitialMask(const std::shared_ptr<Global::Resource::ResourceManager>& resourceMgr);
155     bool GetDefaultMask();
156 
157     bool GetCompositePixelMapWithBadge(
158         const std::shared_ptr<Media::PixelMap> layeredPixelMap,
159         const std::shared_ptr<Media::PixelMap> badgedPixelMap,
160         std::shared_ptr<Media::PixelMap> &compositePixelMap);
161 
162 private:
163     friend class ImageConverter;
164     void InitialResource(const std::shared_ptr<Global::Resource::ResourceManager>& resourceMgr);
165     bool PreGetPixelMapFromJsonBuf(
166         const std::shared_ptr<Global::Resource::ResourceManager>& resourceMgr, bool isBackground);
167     DrawableItem PreGetDrawableItem(
168         const std::shared_ptr<Global::Resource::ResourceManager>& resourceMgr, const char* item);
169     std::unique_ptr<Media::ImageSource> CreateImageSource(DrawableItem& drawableItem, uint32_t& errorCode);
170     bool GetPixelMapFromJsonBuf(bool isBackground);
171     bool GetMaskByName(std::shared_ptr<Global::Resource::ResourceManager>& resourceMgr, const std::string& name);
172     bool CreatePixelMap();
173     bool GetMaskByPath();
174 #ifndef USE_ROSEN_DRAWING
175     void DrawOntoCanvas(
176         const std::shared_ptr<SkBitmap>& bitMap, float width, float height, SkCanvas& canvas, const SkPaint& paint);
177 #else
178     bool GetLayeredIconParm(std::shared_ptr<Rosen::Drawing::Bitmap>& foreground,
179         std::shared_ptr<Rosen::Drawing::Bitmap>& background, std::shared_ptr<Rosen::Drawing::Bitmap>& mask);
180     Rosen::Drawing::ImageInfo ImageInfo();
181     void CompositeIconNotAdaptive(std::shared_ptr<Rosen::Drawing::Bitmap>& foreground,
182         std::shared_ptr<Rosen::Drawing::Bitmap>& background, std::shared_ptr<Rosen::Drawing::Bitmap>& mask);
183     void CompositeIconAdaptive(std::shared_ptr<Rosen::Drawing::Bitmap>& foreground,
184         std::shared_ptr<Rosen::Drawing::Bitmap>& background, std::shared_ptr<Rosen::Drawing::Bitmap>& mask);
185     Rosen::Drawing::ImageInfo CreateRSImageInfo(OptionalPixelMap pixelmap, int32_t width, int32_t height);
186     void TransformToPixelMap(const Rosen::Drawing::Bitmap& bitmap, const Rosen::Drawing::ImageInfo& imageInfo);
187     void DrawOntoCanvas(const std::shared_ptr<Rosen::Drawing::Bitmap>& bitMap, float width, float height,
188         Rosen::Drawing::Canvas& canvas);
189     void BlendForeground(Rosen::Drawing::Canvas& bitmapCanvas, Rosen::Drawing::Brush& brush,
190         Rosen::Drawing::Image& image, const std::shared_ptr<Rosen::Drawing::Bitmap>& background,
191         const std::shared_ptr<Rosen::Drawing::Bitmap>& foreground);
192 #endif
193 
194     std::unique_ptr<uint8_t[]> defaultMaskData_;
195     size_t defaultMaskDataLength_ = 0;
196     DrawableItem backgroundItem_;
197     DrawableItem foregroundItem_;
198     std::unique_ptr<uint8_t[]> jsonBuf_;
199     size_t len_ = 0;
200     std::string maskPath_;
201     uint32_t iconType_ = 0;
202     uint32_t density_ = 0;
203     OptionalPixelMap foreground_;
204     OptionalPixelMap background_;
205     OptionalPixelMap mask_;
206     OptionalPixelMap layeredPixelMap_;
207     bool customized_ = false;
208 };
209 
210 class ACE_EXPORT AnimatedDrawableDescriptor : public DrawableDescriptor {
211 public:
AnimatedDrawableDescriptor(std::vector<std::shared_ptr<Media::PixelMap>> pixelMaps,int32_t duration,int32_t iterations)212     AnimatedDrawableDescriptor(std::vector<std::shared_ptr<Media::PixelMap>> pixelMaps, int32_t duration,
213         int32_t iterations): pixelMapList_(std::move(pixelMaps)), duration_(duration), iterations_(iterations) {};
214     ~AnimatedDrawableDescriptor() override = default;
215     std::shared_ptr<Media::PixelMap> GetPixelMap() override;
216     DrawableType GetDrawableType() override;
217     std::vector<std::shared_ptr<Media::PixelMap>> GetPixelMapList();
218     int32_t GetDuration();
219     int32_t GetIterations();
220     void SetDuration(int32_t duration);
221     void SetIterations(int32_t iterations);
222 private:
223     std::vector<std::shared_ptr<Media::PixelMap>> pixelMapList_;
224     int32_t duration_ = -1;
225     int32_t iterations_ = 1;
226 };
227 
228 class DrawableDescriptorFactory {
229 public:
230     using DrawableType = DrawableDescriptor::DrawableType;
231     using ResourceManager = Global::Resource::ResourceManager;
232     using RState = Global::Resource::RState;
Create(int32_t id,const std::shared_ptr<ResourceManager> & resourceMgr,RState & state,DrawableType & drawableType,uint32_t density)233     static std::unique_ptr<DrawableDescriptor> Create(int32_t id, const std::shared_ptr<ResourceManager>& resourceMgr,
234         RState& state, DrawableType& drawableType, uint32_t density)
235     {
236         std::string type;
237         size_t len;
238         std::unique_ptr<uint8_t[]> jsonBuf;
239         state = resourceMgr->GetDrawableInfoById(id, type, len, jsonBuf, density);
240         if (state != Global::Resource::SUCCESS) {
241             HILOGE("Failed to get drawable info from resmgr");
242             return nullptr;
243         }
244         transform(type.begin(), type.end(), type.begin(), ::tolower);
245         if (type == "json") {
246             HILOGD("Create LayeredDrawableDescriptor object");
247             drawableType = DrawableDescriptor::DrawableType::LAYERED;
248             state = Global::Resource::SUCCESS;
249             return std::make_unique<LayeredDrawableDescriptor>(std::move(jsonBuf), len, resourceMgr);
250         }
251         if (type == "png" || type == "jpg" || type == "bmp" || type == "svg" || type == "gif" || type == "webp" ||
252             type == "astc" || type == "sut") {
253             HILOGD("Create DrawableDescriptor object");
254             drawableType = DrawableDescriptor::DrawableType::BASE;
255             state = Global::Resource::SUCCESS;
256             return std::make_unique<DrawableDescriptor>(std::move(jsonBuf), len);
257         }
258         HILOGE("unknow resource type: %{public}s", type.c_str());
259         state = Global::Resource::INVALID_FORMAT;
260         return nullptr;
261     }
262 
Create(const char * name,const std::shared_ptr<ResourceManager> & resourceMgr,RState & state,DrawableType & drawableType,uint32_t density)263     static std::unique_ptr<DrawableDescriptor> Create(const char* name,
264         const std::shared_ptr<ResourceManager>& resourceMgr, RState& state, DrawableType& drawableType,
265         uint32_t density)
266     {
267         std::string type;
268         size_t len;
269         std::unique_ptr<uint8_t[]> jsonBuf;
270         state = resourceMgr->GetDrawableInfoByName(name, type, len, jsonBuf, density);
271         if (state != Global::Resource::SUCCESS) {
272             HILOGE("Failed to get drawable info from resmgr");
273             return nullptr;
274         }
275         transform(type.begin(), type.end(), type.begin(), ::tolower);
276         if (type == "json") {
277             HILOGD("Create LayeredDrawableDescriptor object");
278             drawableType = DrawableDescriptor::DrawableType::LAYERED;
279             state = Global::Resource::SUCCESS;
280             return std::make_unique<LayeredDrawableDescriptor>(std::move(jsonBuf), len, resourceMgr);
281         }
282         if (type == "png" || type == "jpg" || type == "bmp" || type == "svg" || type == "gif" || type == "webp" ||
283             type == "astc" || type == "sut") {
284             HILOGD("Create DrawableDescriptor object");
285             drawableType = DrawableDescriptor::DrawableType::BASE;
286             state = Global::Resource::SUCCESS;
287             return std::make_unique<DrawableDescriptor>(std::move(jsonBuf), len);
288         }
289         HILOGE("unknow resource type: %{public}s", type.c_str());
290         state = Global::Resource::INVALID_FORMAT;
291         return nullptr;
292     }
293 
Create(std::tuple<int32_t,uint32_t,uint32_t> & drawableInfo,const std::shared_ptr<ResourceManager> & resourceMgr,RState & state,DrawableType & drawableType)294     static std::unique_ptr<DrawableDescriptor> Create(std::tuple<int32_t, uint32_t, uint32_t>& drawableInfo,
295         const std::shared_ptr<ResourceManager>& resourceMgr, RState& state, DrawableType& drawableType)
296     {
297         int32_t resId = std::get<0>(drawableInfo);
298         uint32_t iconType = std::get<1>(drawableInfo);
299         uint32_t density = std::get<2>(drawableInfo);
300         std::unique_ptr<uint8_t[]> jsonBuf;
301         std::tuple<std::string, size_t, std::string> info;
302         state = resourceMgr->GetDrawableInfoById(resId, info, jsonBuf, iconType, density);
303         if (state != Global::Resource::SUCCESS) {
304             HILOGW("Failed to get drawable info from resmgr");
305             return nullptr;
306         }
307         std::string type = std::get<0>(info);
308         size_t len = std::get<1>(info);
309         std::string path = std::get<2>(info);
310         transform(type.begin(), type.end(), type.begin(), ::tolower);
311         if (type == "json") {
312             HILOGD("Create LayeredDrawableDescriptor object");
313             drawableType = DrawableDescriptor::DrawableType::LAYERED;
314             auto layeredDrawableDescriptor =
315                 std::make_unique<LayeredDrawableDescriptor>(std::move(jsonBuf), len, resourceMgr,
316                     path, iconType, density);
317             return layeredDrawableDescriptor;
318         }
319         if (type == "png" || type == "jpg" || type == "bmp" || type == "svg" || type == "gif" || type == "webp" ||
320             type == "astc" || type == "sut") {
321             HILOGD("Create DrawableDescriptor object");
322             drawableType = DrawableDescriptor::DrawableType::BASE;
323             return std::make_unique<DrawableDescriptor>(std::move(jsonBuf), len);
324         }
325         HILOGE("unknow resource type: %{public}s", type.c_str());
326         state = Global::Resource::INVALID_FORMAT;
327         return nullptr;
328     }
329 
Create(std::tuple<const char *,uint32_t,uint32_t> & drawableInfo,const std::shared_ptr<ResourceManager> & resourceMgr,RState & state,DrawableType & drawableType)330     static std::unique_ptr<DrawableDescriptor> Create(std::tuple<const char*, uint32_t, uint32_t>& drawableInfo,
331         const std::shared_ptr<ResourceManager>& resourceMgr, RState& state, DrawableType& drawableType)
332     {
333         const char* name = std::get<0>(drawableInfo);
334         uint32_t iconType = std::get<1>(drawableInfo);
335         uint32_t density = std::get<2>(drawableInfo);
336         std::unique_ptr<uint8_t[]> jsonBuf;
337         std::tuple<std::string, size_t, std::string> info;
338         state = resourceMgr->GetDrawableInfoByName(name, info, jsonBuf, iconType, density);
339         if (state != Global::Resource::SUCCESS) {
340             HILOGW("Failed to get drawable info from resmgr");
341             return nullptr;
342         }
343         std::string type = std::get<0>(info);
344         size_t len = std::get<1>(info);
345         std::string path = std::get<2>(info);
346         transform(type.begin(), type.end(), type.begin(), ::tolower);
347         if (type == "json") {
348             HILOGD("Create LayeredDrawableDescriptor object");
349             drawableType = DrawableDescriptor::DrawableType::LAYERED;
350             auto layeredDrawableDescriptor = std::make_unique<LayeredDrawableDescriptor>(
351                 std::move(jsonBuf), len, resourceMgr, path, iconType, density);
352             return layeredDrawableDescriptor;
353         }
354         if (type == "png" || type == "jpg" || type == "bmp" || type == "svg" || type == "gif" || type == "webp" ||
355             type == "astc" || type == "sut") {
356             HILOGD("Create DrawableDescriptor object");
357             drawableType = DrawableDescriptor::DrawableType::BASE;
358             return std::make_unique<DrawableDescriptor>(std::move(jsonBuf), len);
359         }
360         HILOGE("unknow resource type: %{public}s", type.c_str());
361         state = Global::Resource::INVALID_FORMAT;
362         return nullptr;
363     }
364 
Create(std::pair<std::unique_ptr<uint8_t[]>,size_t> & foregroundInfo,std::pair<std::unique_ptr<uint8_t[]>,size_t> & backgroundInfo,std::string & path,DrawableType & drawableType,const std::shared_ptr<ResourceManager> & resourceMgr)365     static std::unique_ptr<DrawableDescriptor> Create(std::pair<std::unique_ptr<uint8_t[]>, size_t> &foregroundInfo,
366         std::pair<std::unique_ptr<uint8_t[]>, size_t> &backgroundInfo, std::string &path, DrawableType& drawableType,
367         const std::shared_ptr<ResourceManager>& resourceMgr)
368     {
369         std::unique_ptr<uint8_t[]> jsonBuf;
370         drawableType = DrawableDescriptor::DrawableType::LAYERED;
371         auto layeredDrawableDescriptor = std::make_unique<LayeredDrawableDescriptor>(
372             std::move(jsonBuf), 0, resourceMgr, path, 1, foregroundInfo, backgroundInfo);
373         return layeredDrawableDescriptor;
374     }
375 };
376 } // namespace OHOS::Ace::Napi
377 #endif // FOUNDATION_ACE_INTERFACE_INNERAPI_DRAWABLE_DESCRIPTOR_H
378