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