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