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 "text_label.h"
16 #include <cstdio>
17 #include <iostream>
18 #include <linux/input.h>
19 #include <string>
20 #include "log/log.h"
21 #include "png.h"
22 #include "securec.h"
23 #include "updater_ui_const.h"
24
25 namespace updater {
TextLabel(int mStartX,int mStartY,int w,int h,Frame * mparent)26 TextLabel::TextLabel(int mStartX, int mStartY, int w, int h, Frame *mparent)
27 {
28 startX_ = mStartX;
29 startY_ = mStartY;
30 this->CreateBuffer(w, h, View::PixelFormat::BGRA888);
31 parent_ = mparent;
32 parent_->ViewRegister(this);
33
34 SetFocusAble(true);
35 outlineColor_.r = 0x00;
36 outlineColor_.g = 0x00;
37 outlineColor_.b = 0x00;
38 outlineColor_.a = 0x00;
39 boldTopLine_ = false;
40 boldTopLine_ = false;
41
42 const char midAlpha = 0xAA;
43 actionBgColor_.r = 0x00;
44 actionBgColor_.g = 0x00;
45 actionBgColor_.b = 0x00;
46 actionBgColor_.a = midAlpha;
47
48 const char maxAlpha = 0xff;
49 normalBgColor_.r = 0x00;
50 normalBgColor_.g = 0x00;
51 normalBgColor_.b = 0x00;
52 normalBgColor_.a = maxAlpha;
53
54 const char maxLevel = 0xff;
55 textColor_.r = maxLevel;
56 textColor_.g = maxLevel;
57 textColor_.b = maxLevel;
58 textColor_.a = maxLevel;
59
60 if (memset_s(textBuf_, MAX_TEXT_SIZE + 1, 0, MAX_TEXT_SIZE) != 0) {
61 LOG(WARNING) << "clear buffer failed";
62 }
63 InitFont();
64 }
65
SetFont(FontType fType)66 void TextLabel::SetFont(FontType fType)
67 {
68 fontType_ = fType;
69 InitFont();
70 OnDraw();
71 }
72
PngInitSet(png_structp fontPngPtr,FILE * fp,int size,png_infop fontInfoPtr)73 static void PngInitSet(png_structp fontPngPtr, FILE *fp, int size, png_infop fontInfoPtr)
74 {
75 png_init_io(fontPngPtr, fp);
76 png_set_sig_bytes(fontPngPtr, size);
77 png_read_info(fontPngPtr, fontInfoPtr);
78 return;
79 }
80
CheckInitFont(png_structp fontPngPtr,FILE * fp,png_infop fontInfoPtr)81 static void CheckInitFont(png_structp fontPngPtr, FILE *fp, png_infop fontInfoPtr)
82 {
83 png_destroy_read_struct(&fontPngPtr, &fontInfoPtr, 0);
84 if (fp != nullptr) {
85 fclose(fp);
86 fp = nullptr;
87 }
88 }
89
PNGReadRow(png_uint_32 fontWidth,png_uint_32 fontHeight,png_structp fontPngPtr,char * fontBuf)90 static void PNGReadRow(png_uint_32 fontWidth, png_uint_32 fontHeight, png_structp fontPngPtr, char *fontBuf)
91 {
92 if ((fontWidth > MAX_FONT_BUFFER_SIZE_HW) || (fontHeight > MAX_FONT_BUFFER_SIZE_HW)) {
93 LOG(ERROR) << "font file size is too big!";
94 return;
95 }
96 for (unsigned int y = 0; y < fontHeight; y++) {
97 uint8_t* pRow = reinterpret_cast<uint8_t *>((fontBuf) + y * MAX_FONT_BUFFER_SIZE_HW);
98 png_read_row(fontPngPtr, pRow, nullptr);
99 }
100 return;
101 }
102
InitFont()103 void TextLabel::InitFont()
104 {
105 char resPath[MAX_TEXT_SIZE + 1];
106 png_infop fontInfoPtr = nullptr;
107 png_uint_32 fontWidth = 0;
108 png_uint_32 fontHeight = 0;
109 png_structp fontPngPtr = nullptr;
110 int fontBitDepth = 0;
111 int fontColorType = 0;
112 UPDATER_CHECK_ONLY_RETURN(!memset_s(resPath, MAX_TEXT_SIZE + offset_, 0, MAX_TEXT_SIZE + 1), return);
113 switch (fontType_) {
114 case DEFAULT_FONT:
115 UPDATER_CHECK_ONLY_RETURN(snprintf_s(resPath, sizeof(resPath), sizeof(resPath) -1, "/resources/%s.png",
116 DEFAULT_FONT_NAME.c_str()) != -1, return);
117 break;
118 default:
119 UPDATER_CHECK_ONLY_RETURN(snprintf_s(resPath, sizeof(resPath), sizeof(resPath)-1, "/resources/%s.png",
120 DEFAULT_FONT_NAME.c_str()) != -1, return);
121 break;
122 }
123 FILE* fp = fopen(resPath, "rb");
124 UPDATER_ERROR_CHECK(fp, "open font failed!", return);
125 uint8_t header[headerNumber_];
126 size_t bytesRead = fread(header, 1, sizeof(header), fp);
127 UPDATER_ERROR_CHECK(bytesRead == sizeof(header), "read header failed!", fclose(fp); return);
128 if (png_sig_cmp(header, 0, sizeof(header))) {
129 LOG(ERROR) << "cmp header failed!";
130 fclose(fp);
131 return;
132 }
133 fontPngPtr = png_create_read_struct(PNG_LIBPNG_VER_STRING, nullptr, nullptr, nullptr);
134 UPDATER_ERROR_CHECK(fontPngPtr, "creat font ptr_ failed!", fclose(fp); return);
135 fontInfoPtr = png_create_info_struct(fontPngPtr);
136 if (fontInfoPtr == nullptr) {
137 png_destroy_read_struct(&fontPngPtr, nullptr, nullptr);
138 fclose(fp);
139 return;
140 }
141 PngInitSet(fontPngPtr, fp, sizeof(header), fontInfoPtr);
142 png_get_IHDR(fontPngPtr, fontInfoPtr, &fontWidth, &fontHeight, &fontBitDepth, &fontColorType,
143 nullptr, nullptr, nullptr);
144 png_byte fontChannels = png_get_channels(fontPngPtr, fontInfoPtr);
145 if (fontBitDepth <= defaultFontBitDepth_ && fontChannels == 1 && fontColorType == PNG_COLOR_TYPE_GRAY) {
146 png_set_expand_gray_1_2_4_to_8(fontPngPtr);
147 }
148 fontWidth_ = fontWidth / defaultFontWidth_;
149 fontHeight_ = fontHeight >> 1;
150 PNGReadRow(fontWidth_, fontHeight_, fontPngPtr, fontBuf_);
151 CheckInitFont(fontPngPtr, fp, fontInfoPtr);
152 }
153
SetText(const char * str)154 void TextLabel::SetText(const char *str)
155 {
156 UPDATER_CHECK_ONLY_RETURN(!memset_s(textBuf_, MAX_TEXT_SIZE + 1, 0, MAX_TEXT_SIZE), return);
157 OnDraw();
158 UPDATER_CHECK_ONLY_RETURN(!memcpy_s(textBuf_, MAX_TEXT_SIZE + 1, str, strlen(const_cast<char*>(str))), return);
159 OnDraw();
160 }
161
OnDraw()162 void TextLabel::OnDraw()
163 {
164 std::unique_lock<std::mutex> locker(mutex_);
165 SyncBuffer();
166 if (IsSelected()) {
167 DrawFocus();
168 }
169 DrawOutline();
170 DrawText();
171 if (parent_ != nullptr) {
172 parent_->OnDraw();
173 }
174 }
175
SetOutLineBold(bool topBold,bool bottomBold)176 void TextLabel::SetOutLineBold(bool topBold, bool bottomBold)
177 {
178 boldTopLine_ = topBold;
179 boldBottomLine_ = bottomBold;
180 OnDraw();
181 }
182
DrawOutline()183 void TextLabel::DrawOutline()
184 {
185 void *tmpBuf = GetBuffer();
186 auto *pixelBuf = static_cast<BRGA888Pixel*>(tmpBuf);
187 for (int i = 0; i < viewWidth_; i++) {
188 if (boldTopLine_) {
189 pixelBuf[i].r = outlineColor_.r;
190 pixelBuf[i].g = outlineColor_.g;
191 pixelBuf[i].b = outlineColor_.b;
192 pixelBuf[i].a = outlineColor_.a;
193
194 pixelBuf[viewWidth_ + i].r = outlineColor_.r;
195 pixelBuf[viewWidth_ + i].g = outlineColor_.g;
196 pixelBuf[viewWidth_ + i].b = outlineColor_.b;
197 pixelBuf[viewWidth_ + i].a = outlineColor_.a;
198 }
199
200 const int lines = 2;
201 if (boldBottomLine_) {
202 pixelBuf[(viewHeight_ - lines) * viewWidth_ + i].r = outlineColor_.r;
203 pixelBuf[(viewHeight_ - lines) * viewWidth_ + i].g = outlineColor_.g;
204 pixelBuf[(viewHeight_ - lines) * viewWidth_ + i].b = outlineColor_.b;
205 pixelBuf[(viewHeight_ - lines) * viewWidth_ + i].a = outlineColor_.a;
206 pixelBuf[(viewHeight_ - 1) * viewWidth_ + i].r = outlineColor_.r;
207 pixelBuf[(viewHeight_ - 1) * viewWidth_ + i].g = outlineColor_.g;
208 pixelBuf[(viewHeight_ - 1) * viewWidth_ + i].b = outlineColor_.b;
209 pixelBuf[(viewHeight_ - 1) * viewWidth_ + i].a = outlineColor_.a;
210 }
211 }
212 }
213
SetTextColor(BRGA888Pixel color)214 void TextLabel::SetTextColor(BRGA888Pixel color)
215 {
216 textColor_.r = color.r;
217 textColor_.g = color.g;
218 textColor_.b = color.b;
219 textColor_.a = color.a;
220 }
221
SetTextAlignmentMethod(AlignmentMethod methodH,AlignmentMethod methodV)222 void TextLabel::SetTextAlignmentMethod(AlignmentMethod methodH, AlignmentMethod methodV)
223 {
224 fontAligMethodLevel_ = methodH;
225 fontAligMethodUpright_ = methodV;
226 }
227
SetOnClickCallback(ClickCallback cb)228 void TextLabel::SetOnClickCallback(ClickCallback cb)
229 {
230 callBack_ = cb;
231 }
232
DrawText()233 void TextLabel::DrawText()
234 {
235 void *tmpBuf = GetBuffer();
236 int textSx = 0;
237 int textSy = 0;
238 switch (fontAligMethodUpright_) {
239 case ALIGN_CENTER:
240 textSy = (viewHeight_ - fontHeight_) / MEDIAN_NUMBER;
241 break;
242 case ALIGN_TO_TOP:
243 textSy = 0;
244 break;
245 default:
246 break;
247 }
248
249 const int minPosition = 10;
250 const int average = 2;
251 switch (fontAligMethodLevel_) {
252 case ALIGN_CENTER:
253 textSx = (viewWidth_ - (strlen(textBuf_) * fontWidth_)) / average;
254 UPDATER_CHECK_ONLY_RETURN(textSx >= minPosition, textSx = minPosition);
255 break;
256 case ALIGN_TO_LEFT:
257 textSx = minPosition;
258 break;
259 default:
260 break;
261 }
262 unsigned char ch;
263 char* s = textBuf_;
264 while ((ch = *s++)) {
265 UPDATER_CHECK_ONLY_RETURN(!(ch < ' ' || ch > '~'), ch = '?');
266 auto *srcP = reinterpret_cast<uint8_t*>(static_cast<char*>(fontBuf_) + ((ch - ' ') * fontWidth_));
267 auto *dstP = reinterpret_cast<BRGA888Pixel*>(static_cast<char*>(tmpBuf) + (textSy * viewWidth_ + textSx) *
268 sizeof(BRGA888Pixel));
269 for (unsigned int j = 0; j < fontHeight_; j++) {
270 for (unsigned int i = 0; i < fontWidth_; i++) {
271 uint8_t a = srcP[i];
272 if (a > 0) {
273 dstP[i].r = textColor_.r;
274 dstP[i].g = textColor_.g;
275 dstP[i].b = textColor_.b;
276 dstP[i].a = textColor_.a;
277 }
278 }
279 srcP += MAX_FONT_BUFFER_SIZE_HW;
280 dstP = dstP + viewWidth_;
281 }
282 textSx += fontWidth_;
283 }
284 }
285
DrawFocus()286 void TextLabel::DrawFocus()
287 {
288 BRGA888Pixel pixBuf[viewWidth_];
289 for (int a = 0; a < viewWidth_; a++) {
290 pixBuf[a].r = actionBgColor_.r;
291 pixBuf[a].g = actionBgColor_.g;
292 pixBuf[a].b = actionBgColor_.b;
293 pixBuf[a].a = actionBgColor_.a;
294 }
295 void *viewBgBuf = GetBuffer();
296 for (int i = 0; i < viewHeight_; i++) {
297 UPDATER_CHECK_ONLY_RETURN(!memcpy_s(static_cast<char*>(static_cast<char*>(viewBgBuf) + i * viewWidth_ *
298 sizeof(BRGA888Pixel)), viewWidth_ * sizeof(BRGA888Pixel) + 1, reinterpret_cast<char*>(pixBuf),
299 viewWidth_ * sizeof(BRGA888Pixel)), return);
300 }
301 }
302
OnKeyEvent(int key)303 void TextLabel::OnKeyEvent(int key)
304 {
305 LOG(INFO) << "OnKeyEvent !";
306 switch (key) {
307 case KEY_POWER:
308 if (callBack_ != nullptr) {
309 callBack_(GetViewId());
310 }
311 break;
312 default:
313 break;
314 }
315 }
316 } // namespace updater
317