• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-2022 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 #include "animation_label.h"
17 #include <cerrno>
18 #include <cstdio>
19 #include <string>
20 #include <sys/epoll.h>
21 #include "frame.h"
22 #include "png.h"
23 #include "securec.h"
24 #include "view.h"
25 #include "battery_log.h"
26 
27 namespace OHOS {
28 namespace HDI {
29 namespace Battery {
30 namespace V1_1 {
31 constexpr int32_t PNG_HEADER_SIZE = 8;
32 constexpr int32_t MAX_PICTURE_CHANNELS = 3;
33 constexpr int32_t MAX_BIT_DEPTH = 8;
34 constexpr useconds_t SECOND_PER_MS = 1000;
35 bool AnimationLabel::isVisible_ = true;
36 bool AnimationLabel::needStop_ = false;
37 
AnimationLabel(int32_t startX,int32_t startY,int32_t w,int32_t h,Frame * mParent)38 AnimationLabel::AnimationLabel(int32_t startX, int32_t startY, int32_t w, int32_t h, Frame* mParent)
39 {
40     startX_ = startX;
41     startY_ = startY;
42     this->CreateBuffer(w, h, View::PixelFormat::BGRA888);
43     parent_ = mParent;
44     SetFocusAble(false);
45     needStop_ = false;
46     parent_->ViewRegister(this);
47 }
48 
~AnimationLabel()49 AnimationLabel::~AnimationLabel()
50 {
51     needStop_ = true;
52     FreeBuffer();
53     size_t imgSize = imgList_.size();
54 
55     for (size_t i = 0; i < imgSize; i++) {
56         free(imgList_[i]);
57     }
58     imgList_.clear();
59 }
60 
SetStaticImg(int32_t picId)61 void AnimationLabel::SetStaticImg(int32_t picId)
62 {
63     staticShowId_ = picId;
64 }
65 
SetIsVisible(bool visible)66 void AnimationLabel::SetIsVisible(bool visible)
67 {
68     isVisible_ = visible;
69 }
70 
SetPlayMode(AnimationLabel::PlayMode mode)71 void AnimationLabel::SetPlayMode(AnimationLabel::PlayMode mode)
72 {
73     if (mode == AnimationLabel::PlayMode::ANIMATION_MODE) {
74         showStatic_ = false;
75     } else if (mode == AnimationLabel::PlayMode::STATIC_MODE) {
76         showStatic_ = true;
77     }
78 }
79 
UpdateLoop()80 void AnimationLabel::UpdateLoop()
81 {
82     BATTERY_HILOGD(FEATURE_CHARGING, "start update animation loop");
83     uint32_t index = 0;
84 
85     while (!needStop_) {
86         if (showStatic_) {
87             usleep(SECOND_PER_MS * SECOND_PER_MS);
88         } else {
89             usleep(intervalMs_ * SECOND_PER_MS);
90         }
91         if (imgList_.size() <= 0) {
92             continue;
93         }
94 
95         BATTERY_HILOGD(FEATURE_CHARGING, "isVisible_ = %{public}d", isVisible_);
96         if (!isVisible_) {
97             continue;
98         }
99 
100         if (imgList_.size() <= index) {
101             index = 0;
102             needStop_ = true;
103         }
104         SyncBuffer();
105         mutex_.lock();
106 
107         if (showStatic_) {
108             if (staticShowId_ < staticImgSize_) {
109                 DrawSubView(0, 0, viewWidth_, viewHeight_, staticImgList_[staticShowId_]);
110             }
111         } else {
112             DrawSubView(0, 0, viewWidth_, viewHeight_, imgList_[index]);
113         }
114         mutex_.unlock();
115         if (parent_ != nullptr) {
116             parent_->OnDraw();
117         }
118         index++;
119     }
120     BATTERY_HILOGD(FEATURE_CHARGING, "finish update animation loop");
121 }
122 
AddImg(const std::string & imgFileName)123 void AnimationLabel::AddImg(const std::string& imgFileName)
124 {
125     BATTERY_HILOGD(FEATURE_CHARGING, "add img, name=%{public}s", imgFileName.c_str());
126     mutex_.lock();
127     char* buf = static_cast<char*>(LoadPng(imgFileName));
128     imgList_.push_back(buf);
129     mutex_.unlock();
130 }
131 
AddStaticImg(const std::string & imgFileName)132 int32_t AnimationLabel::AddStaticImg(const std::string& imgFileName)
133 {
134     BATTERY_HILOGD(FEATURE_CHARGING, "add static img, name=%{public}s", imgFileName.c_str());
135     int32_t id = staticImgSize_;
136     mutex_.lock();
137     staticImgList_[id] = static_cast<char*>(LoadPng(imgFileName));
138     staticImgSize_++;
139     mutex_.unlock();
140     return id;
141 }
142 
LoadPngInternalWithFile(FILE * fp,png_structpp pngPtr,png_infopp pngInfoPtr,struct PictureAttr & attr)143 int32_t AnimationLabel::LoadPngInternalWithFile(FILE* fp, png_structpp pngPtr, png_infopp pngInfoPtr,
144     struct PictureAttr& attr)
145 {
146     if (fp == nullptr) {
147         return -1;
148     }
149     uint8_t header[PNG_HEADER_SIZE];
150     size_t bytesRead = fread(header, 1, sizeof(header), fp);
151     if (bytesRead != sizeof(header)) {
152         BATTERY_HILOGE(FEATURE_CHARGING, "read header from file failed, errno=%{public}d", errno);
153         return -1;
154     }
155     if (png_sig_cmp(header, 0, sizeof(header))) {
156         BATTERY_HILOGE(FEATURE_CHARGING, "png file header is not valid.");
157         return -1;
158     }
159 
160     *pngPtr = png_create_read_struct(PNG_LIBPNG_VER_STRING, nullptr, nullptr, nullptr);
161     if (*pngPtr == nullptr) {
162         BATTERY_HILOGE(FEATURE_CHARGING, "create png struct failed.");
163         return -1;
164     }
165 
166     *pngInfoPtr = png_create_info_struct(*pngPtr);
167     if (*pngInfoPtr == nullptr) {
168         BATTERY_HILOGE(FEATURE_CHARGING, "create png info failed.");
169         return -1;
170     }
171     png_init_io(*pngPtr, fp);
172     png_set_sig_bytes(*pngPtr, sizeof(header));
173     png_read_info(*pngPtr, *pngInfoPtr);
174     png_get_IHDR(*pngPtr, *pngInfoPtr, &attr.pictureWidth, &attr.pictureHeight, &attr.bitDepth, &attr.colorType,
175         nullptr, nullptr, nullptr);
176     attr.pictureChannels = png_get_channels(*pngPtr, *pngInfoPtr);
177     if (attr.bitDepth <= MAX_BIT_DEPTH && attr.pictureChannels == 1 && attr.colorType == PNG_COLOR_TYPE_PALETTE) {
178         // paletted images: expand to 8-bit RGB.  Note that we DON'T
179         // currently expand the tRNS chunk (if any) to an alpha
180         // channel, because minui doesn't support alpha channels in
181         // general.
182         png_set_palette_to_rgb(*pngPtr);
183         attr.pictureChannels = MAX_PICTURE_CHANNELS;
184     }
185 
186     if (attr.pictureChannels < MAX_PICTURE_CHANNELS) {
187         BATTERY_HILOGE(FEATURE_CHARGING, "need rgb format pic.");
188         return -1;
189     }
190     return 0;
191 }
192 
CopyPictureBuffer(struct PictureAttr & attr,char * pictureBufferTmp,BRGA888Pixel * pictureBuffer) const193 void AnimationLabel::CopyPictureBuffer(struct PictureAttr& attr, char* pictureBufferTmp,
194     BRGA888Pixel* pictureBuffer) const
195 {
196     auto pictureHeight = static_cast<int32_t>(attr.pictureHeight);
197     auto pictureWidth = static_cast<int32_t>(attr.pictureWidth);
198     int32_t copyHeight = (viewHeight_ < pictureHeight) ? viewHeight_ : pictureHeight;
199     int32_t copyWidth = (viewWidth_ < pictureWidth) ? viewWidth_ : pictureWidth;
200     auto* rgb = reinterpret_cast<RGB888Pixel*>(pictureBufferTmp);
201     for (int32_t y = 0; y < copyHeight; y++) {
202         for (int32_t x = 0; x < copyWidth; x++) {
203             uint32_t colorValue = rgb[x + y * pictureWidth].r +
204             rgb[x + y * pictureWidth].g + rgb[x + y * pictureWidth].b;
205             if (colorValue > 0) {
206                 pictureBuffer[x + y * viewWidth_].r = rgb[x + y * pictureWidth].r;
207                 pictureBuffer[x + y * viewWidth_].g = rgb[x + y * pictureWidth].g;
208                 pictureBuffer[x + y * viewWidth_].b = rgb[x + y * pictureWidth].b;
209                 pictureBuffer[x + y * viewWidth_].a = 0xff;
210             }
211         }
212     }
213 }
214 
LoadPng(const std::string & imgFileName)215 void* AnimationLabel::LoadPng(const std::string& imgFileName)
216 {
217     png_structp pngPtr = nullptr;
218     png_infop pngInfoPtr = nullptr;
219     struct PictureAttr attr {};
220     char* pictureBufferTmp = nullptr;
221     uint8_t* pictureRow = nullptr;
222 
223     FILE* fp = fopen(imgFileName.c_str(), "rb");
224     if (fp == nullptr) {
225         BATTERY_HILOGD(FEATURE_CHARGING, "open img file failed.");
226         return nullptr;
227     }
228     if (LoadPngInternalWithFile(fp, &pngPtr, &pngInfoPtr, attr) < 0) {
229         png_destroy_read_struct(&pngPtr, &pngInfoPtr, 0);
230         fclose(fp);
231         fp = nullptr;
232         return nullptr;
233     }
234     uint32_t pictureRowSize = attr.pictureWidth * attr.pictureChannels;
235     pictureBufferTmp = static_cast<char*>(malloc(pictureRowSize * attr.pictureHeight));
236     if (pictureBufferTmp == nullptr) {
237         BATTERY_HILOGD(FEATURE_CHARGING, "malloc memory failed.");
238         if (fp != nullptr) {
239             fclose(fp);
240             fp = nullptr;
241         }
242         return nullptr;
243     }
244 
245     for (uint32_t y = 0; y < attr.pictureHeight; y++) {
246         pictureRow = reinterpret_cast<uint8_t*>((pictureBufferTmp) + y * pictureRowSize);
247         png_read_row(pngPtr, pictureRow, nullptr);
248     }
249 
250     BRGA888Pixel* pictureBuffer = HandleLoadPng(&fp, &pictureBufferTmp, attr);
251     return static_cast<void*>(pictureBuffer);
252 }
253 
HandleLoadPng(FILE ** fp,char ** pictureBufferTmp,struct PictureAttr & attr)254 View::BRGA888Pixel* AnimationLabel::HandleLoadPng(FILE** fp, char** pictureBufferTmp, struct PictureAttr& attr)
255 {
256     int32_t pictureBufferSize = viewHeight_ * viewWidth_ * sizeof(BRGA888Pixel);
257     BRGA888Pixel* pictureBuffer = nullptr;
258     char* backgroundBuffer = static_cast<char*>(GetRawBuffer());
259 
260     pictureBuffer = static_cast<BRGA888Pixel*>(malloc(pictureBufferSize));
261     if (pictureBuffer == nullptr) {
262         BATTERY_HILOGD(FEATURE_CHARGING, "malloc memory failed.");
263         if (*pictureBufferTmp != nullptr) {
264             free(*pictureBufferTmp);
265             *pictureBufferTmp = nullptr;
266         }
267         if (*fp != nullptr) {
268             fclose(*fp);
269             *fp = nullptr;
270         }
271         return nullptr;
272     }
273 
274     if (memcpy_s(reinterpret_cast<char*>(pictureBuffer), pictureBufferSize,
275         backgroundBuffer, pictureBufferSize) != EOK) {
276         if (*pictureBufferTmp != nullptr) {
277             free(*pictureBufferTmp);
278             *pictureBufferTmp = nullptr;
279         }
280         if (pictureBuffer != nullptr) {
281             free(pictureBuffer);
282             pictureBuffer = nullptr;
283         }
284         if (*fp != nullptr) {
285             fclose(*fp);
286             *fp = nullptr;
287         }
288         return nullptr;
289     }
290     CopyPictureBuffer(attr, *pictureBufferTmp, pictureBuffer);
291     free(*pictureBufferTmp);
292     *pictureBufferTmp = nullptr;
293     int32_t ret = fclose(*fp);
294     if (ret < 0) {
295         BATTERY_HILOGD(FEATURE_CHARGING, "fp file close failed.");
296         return nullptr;
297     }
298     *fp = nullptr;
299     return pictureBuffer;
300 }
301 
SetInterval(int32_t ms)302 void AnimationLabel::SetInterval(int32_t ms)
303 {
304     intervalMs_ = static_cast<uint32_t>(ms);
305 }
306 }  // namespace V1_1
307 }  // namespace Battery
308 }  // namespace HDI
309 }  // namespace OHOS
310