1 /*
2 * Copyright (c) 2021 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 #include "animation_label.h"
16 #include <cerrno>
17 #include <cstdio>
18 #include <string>
19 #include "frame.h"
20 #include "log/log.h"
21 #include "png.h"
22 #include "securec.h"
23 #include "view.h"
24
25 namespace updater {
AnimationLable(int startX,int startY,int w,int h,Frame * mParent)26 AnimationLable::AnimationLable(int startX, int startY, int w, int h, Frame *mParent)
27 {
28 startX_ = startX;
29 startY_ = startY;
30 this->CreateBuffer(w, h, View::PixelFormat::BGRA888);
31 parent_ = mParent;
32 SetFocusAble(false);
33 needStop_ = false;
34 parent_->ViewRegister(this);
35 startFlag_ = false;
36 #ifndef UPDATER_UT
37 updateThread = std::thread(&AnimationLable::UpdateLoop, this);
38 updateThread.detach();
39 #endif
40 }
41
~AnimationLable()42 AnimationLable::~AnimationLable()
43 {
44 startFlag_ = false;
45 needStop_ = true;
46 for (std::vector<void *>::iterator it = imgList_.begin(); it != imgList_.end(); it++) {
47 if (*it != nullptr) {
48 free(*it);
49 *it = nullptr;
50 }
51 }
52 imgList_.clear();
53 }
54
Start()55 void AnimationLable::Start()
56 {
57 startFlag_ = true;
58 }
59
Stop()60 void AnimationLable::Stop()
61 {
62 startFlag_ = false;
63 }
64
SetStaticImg(int picId)65 void AnimationLable::SetStaticImg(int picId)
66 {
67 staticShowId_ = picId;
68 }
69
SetPlayMode(AnimationLable::PlayMode mode)70 void AnimationLable::SetPlayMode(AnimationLable::PlayMode mode)
71 {
72 if (mode == AnimationLable::PlayMode::ANIMATION_MODE) {
73 showStatic_ = false;
74 } else if (mode == AnimationLable::PlayMode::STATIC_MODE) {
75 showStatic_ = true;
76 }
77 }
78
UpdateLoop()79 void AnimationLable::UpdateLoop()
80 {
81 unsigned int index = 0;
82 while (!needStop_) {
83 if (showStatic_) {
84 usleep(SECOND_PER_MS * SECOND_PER_MS);
85 } else {
86 usleep(intervalMs_ * SECOND_PER_MS);
87 }
88 if (imgList_.size() <= 0) {
89 return;
90 }
91 if (!startFlag_ && IsVisiable()) {
92 continue;
93 }
94
95 if (imgList_.size() <= index) {
96 index = 0;
97 }
98 SyncBuffer();
99 mutex_.lock();
100
101 if (showStatic_) {
102 if (staticShowId_ < staticImgSize_) {
103 DrawSubView(0, 0, viewWidth_, viewHeight_, staticImgList_[staticShowId_]);
104 }
105 } else {
106 DrawSubView(0, 0, viewWidth_, viewHeight_, imgList_[index]);
107 }
108 mutex_.unlock();
109 if (parent_ != nullptr) {
110 parent_->OnDraw();
111 }
112 index++;
113 }
114 LOG(DEBUG) << "anim loop end";
115 }
116
AddImg(const std::string & imgFileName)117 void AnimationLable::AddImg(const std::string &imgFileName)
118 {
119 mutex_.lock();
120 void *buf = LoadPng(imgFileName);
121 if (buf != nullptr) {
122 imgList_.push_back(buf);
123 }
124 mutex_.unlock();
125 }
126
AddStaticImg(const std::string & imgFileName)127 int AnimationLable::AddStaticImg(const std::string &imgFileName)
128 {
129 int id = staticImgSize_;
130 mutex_.lock();
131 staticImgList_[id] = LoadPng(imgFileName);
132 staticImgSize_++;
133 mutex_.unlock();
134 return id;
135 }
136
LoadPngInternalWithFile(FILE * fp,png_structpp pngPtr,png_infopp pngInfoPtr,struct PictureAttr & attr)137 int AnimationLable::LoadPngInternalWithFile(FILE *fp, png_structpp pngPtr, png_infopp pngInfoPtr,
138 struct PictureAttr &attr)
139 {
140 if (fp == nullptr) {
141 return -1;
142 }
143 uint8_t header[PNG_HEADER_SIZE];
144 size_t bytesRead = fread(header, 1, sizeof(header), fp);
145 if (bytesRead != sizeof(header)) {
146 LOG(ERROR) << "read header from file failed: " << errno;
147 return -1;
148 }
149 if (png_sig_cmp(header, 0, sizeof(header))) {
150 LOG(ERROR) << "png file header is not valid";
151 return -1;
152 }
153
154 *pngPtr = png_create_read_struct(PNG_LIBPNG_VER_STRING, nullptr, nullptr, nullptr);
155 if (*pngPtr == nullptr) {
156 LOG(ERROR) << "creat png struct failed";
157 return -1;
158 }
159
160 *pngInfoPtr = png_create_info_struct(*pngPtr);
161 if (*pngInfoPtr == nullptr) {
162 LOG(ERROR) << "Create png info failed";
163 return -1;
164 }
165 png_init_io(*pngPtr, fp);
166 png_set_sig_bytes(*pngPtr, sizeof(header));
167 png_read_info(*pngPtr, *pngInfoPtr);
168 png_get_IHDR(*pngPtr, *pngInfoPtr, &attr.pictureWidth, &attr.pictureHeight, &attr.bitDepth, &attr.colorType,
169 nullptr, nullptr, nullptr);
170 attr.pictureChannels = png_get_channels(*pngPtr, *pngInfoPtr);
171 if (attr.bitDepth <= MAX_BIT_DEPTH && attr.pictureChannels == 1 && attr.colorType == PNG_COLOR_TYPE_PALETTE) {
172 // paletted images: expand to 8-bit RGB. Note that we DON'T
173 // currently expand the tRNS chunk (if any) to an alpha
174 // channel, because minui doesn't support alpha channels in
175 // general.
176 png_set_palette_to_rgb(*pngPtr);
177 attr.pictureChannels = MAX_PICTURE_CHANNELS;
178 }
179
180 if (attr.pictureChannels < MAX_PICTURE_CHANNELS) {
181 LOG(ERROR) << "need rgb format pic";
182 return -1;
183 }
184 return 0;
185 }
186
CopyPictureBuffer(struct PictureAttr & attr,char * pictureBufferTmp,BRGA888Pixel * pictureBuffer) const187 void AnimationLable::CopyPictureBuffer(struct PictureAttr &attr, char *pictureBufferTmp,
188 BRGA888Pixel *pictureBuffer) const
189 {
190 int copyHeight = (viewHeight_ < static_cast<int>(attr.pictureHeight)) ? viewHeight_ :
191 static_cast<int>(attr.pictureHeight);
192 int copyWidth = (viewWidth_ < static_cast<int>(attr.pictureWidth)) ? viewWidth_ :
193 static_cast<int>(attr.pictureWidth);
194 auto *rgb = reinterpret_cast<RGB888Pixel*>(pictureBufferTmp);
195 for (int y = 0; y < copyHeight; y++) {
196 for (int x = 0; x < copyWidth; x++) {
197 unsigned int colorValue = rgb[x + y * attr.pictureWidth].r +
198 rgb[x + y * attr.pictureWidth].g + rgb[x + y * attr.pictureWidth].b;
199 if (colorValue > 0) {
200 pictureBuffer[x + y * viewWidth_].r = rgb[x + y * attr.pictureWidth].r;
201 pictureBuffer[x + y * viewWidth_].g = rgb[x + y * attr.pictureWidth].g;
202 pictureBuffer[x + y * viewWidth_].b = rgb[x + y * attr.pictureWidth].b;
203 pictureBuffer[x + y * viewWidth_].a = 0xff;
204 }
205 }
206 }
207 }
208
LoadPng(const std::string & imgFileName)209 void *AnimationLable::LoadPng(const std::string &imgFileName)
210 {
211 png_structp pngPtr = nullptr;
212 png_infop pngInfoPtr = nullptr;
213 struct PictureAttr attr {};
214 char *pictureBufferTmp = nullptr;
215 BRGA888Pixel *pictureBuffer = nullptr;
216 char *backgroundBuffer = static_cast<char*>(GetRawBuffer());
217 int pictureBufferSize = viewHeight_ * viewWidth_ * sizeof(BRGA888Pixel);
218 uint8_t *pictureRow = nullptr;
219
220 FILE *fp = fopen(imgFileName.c_str(), "rb");
221 UPDATER_FILE_CHECK(fp != nullptr, "open font file failed", return nullptr);
222 if (LoadPngInternalWithFile(fp, &pngPtr, &pngInfoPtr, attr) < 0) {
223 png_destroy_read_struct(&pngPtr, &pngInfoPtr, 0);
224 fclose(fp);
225 fp = nullptr;
226 return nullptr;
227 }
228 unsigned int pictureRowSize = attr.pictureWidth * attr.pictureChannels;
229 pictureBufferTmp = static_cast<char *>(malloc(pictureRowSize * attr.pictureHeight));
230 UPDATER_ERROR_CHECK(pictureBufferTmp != nullptr, "Allocate memory failed", goto err);
231
232 for (unsigned int y = 0; y < attr.pictureHeight; y++) {
233 pictureRow = reinterpret_cast<uint8_t *>((pictureBufferTmp) + y * pictureRowSize);
234 png_read_row(pngPtr, pictureRow, nullptr);
235 }
236
237 pictureBuffer = static_cast<BRGA888Pixel*>(malloc(pictureBufferSize));
238 UPDATER_ERROR_CHECK(pictureBuffer != nullptr, "Allocate memory failed", goto err);
239 if (memcpy_s(reinterpret_cast<char *>(pictureBuffer), pictureBufferSize,
240 backgroundBuffer, pictureBufferSize) != EOK) {
241 goto err;
242 }
243 CopyPictureBuffer(attr, pictureBufferTmp, pictureBuffer);
244 free(pictureBufferTmp);
245 pictureBufferTmp = nullptr;
246 fclose(fp);
247 fp = nullptr;
248 return static_cast<void *>(pictureBuffer);
249 err:
250 if (pictureBuffer != nullptr) {
251 free(pictureBuffer);
252 pictureBuffer = nullptr;
253 }
254 if (pictureBufferTmp != nullptr) {
255 free(pictureBufferTmp);
256 pictureBufferTmp = nullptr;
257 }
258 if (fp != nullptr) {
259 fclose(fp);
260 fp = nullptr;
261 }
262 return nullptr;
263 }
264
SetInterval(int ms)265 void AnimationLable::SetInterval(int ms)
266 {
267 intervalMs_ = ms;
268 }
269 } // namespace updater
270