• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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