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