Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
CTCaer
GitHub Repository: CTCaer/hekate
Path: blob/master/bdk/libs/lvgl/lv_draw/lv_draw_label.c
1476 views
1
/**
2
* @file lv_draw_label.c
3
*
4
*/
5
6
/*********************
7
* INCLUDES
8
*********************/
9
#include "lv_draw_label.h"
10
#include "lv_draw_rbasic.h"
11
#include "../lv_misc/lv_math.h"
12
13
/*********************
14
* DEFINES
15
*********************/
16
#define LABEL_RECOLOR_PAR_LENGTH 6
17
18
/**********************
19
* TYPEDEFS
20
**********************/
21
enum {
22
CMD_STATE_WAIT,
23
CMD_STATE_PAR,
24
CMD_STATE_IN,
25
};
26
typedef uint8_t cmd_state_t;
27
28
/**********************
29
* STATIC PROTOTYPES
30
**********************/
31
static uint8_t hex_char_to_num(char hex);
32
33
/**********************
34
* STATIC VARIABLES
35
**********************/
36
37
38
/**********************
39
* MACROS
40
**********************/
41
42
/**********************
43
* GLOBAL FUNCTIONS
44
**********************/
45
46
/**
47
* Write a text
48
* @param coords coordinates of the label
49
* @param mask the label will be drawn only in this area
50
* @param style pointer to a style
51
* @param opa_scale scale down all opacities by the factor
52
* @param txt 0 terminated text to write
53
* @param flag settings for the text from 'txt_flag_t' enum
54
* @param offset text offset in x and y direction (NULL if unused)
55
*
56
*/
57
void lv_draw_label(const lv_area_t * coords, const lv_area_t * mask, const lv_style_t * style, lv_opa_t opa_scale,
58
const char * txt, lv_txt_flag_t flag, lv_point_t * offset)
59
{
60
const lv_font_t * font = style->text.font;
61
lv_coord_t w;
62
if((flag & LV_TXT_FLAG_EXPAND) == 0) {
63
/*Normally use the label's width as width*/
64
w = lv_area_get_width(coords);
65
} else {
66
/*If EXAPND is enabled then not limit the text's width to the object's width*/
67
lv_point_t p;
68
lv_txt_get_size(&p, txt, style->text.font, style->text.letter_space, style->text.line_space, LV_COORD_MAX, flag);
69
w = p.x;
70
}
71
72
lv_coord_t line_height = lv_font_get_height(font) + style->text.line_space;
73
74
75
/*Init variables for the first line*/
76
lv_coord_t line_width = 0;
77
lv_point_t pos;
78
pos.x = coords->x1;
79
pos.y = coords->y1;
80
81
lv_coord_t x_ofs = 0;
82
lv_coord_t y_ofs = 0;
83
if(offset != NULL) {
84
x_ofs = offset->x;
85
y_ofs = offset->y;
86
pos.y += y_ofs;
87
}
88
89
uint32_t line_start = 0;
90
uint32_t line_end = lv_txt_get_next_line(txt, font, style->text.letter_space, w, flag);
91
92
/*Go the first visible line*/
93
while(pos.y + line_height < mask->y1) {
94
/*Go to next line*/
95
line_start = line_end;
96
line_end += lv_txt_get_next_line(&txt[line_start], font, style->text.letter_space, w, flag);
97
pos.y += line_height;
98
99
if(txt[line_start] == '\0') return;
100
}
101
102
/*Align to middle*/
103
if(flag & LV_TXT_FLAG_CENTER) {
104
line_width = lv_txt_get_width(&txt[line_start], line_end - line_start,
105
font, style->text.letter_space, flag);
106
107
pos.x += (lv_area_get_width(coords) - line_width) / 2;
108
109
}
110
/*Align to the right*/
111
else if(flag & LV_TXT_FLAG_RIGHT) {
112
line_width = lv_txt_get_width(&txt[line_start], line_end - line_start,
113
font, style->text.letter_space, flag);
114
pos.x += lv_area_get_width(coords) - line_width;
115
}
116
117
118
lv_opa_t opa = opa_scale == LV_OPA_COVER ? style->text.opa : (uint16_t)((uint16_t) style->text.opa * opa_scale) >> 8;
119
120
cmd_state_t cmd_state = CMD_STATE_WAIT;
121
uint32_t i;
122
uint16_t par_start = 0;
123
lv_color_t recolor;
124
lv_coord_t letter_w;
125
126
/*Real draw need a background color for higher bpp letter*/
127
#if LV_VDB_SIZE == 0
128
lv_rletter_set_background(style->body.main_color);
129
#endif
130
131
132
/*Write out all lines*/
133
while(txt[line_start] != '\0') {
134
if(offset != NULL) {
135
pos.x += x_ofs;
136
}
137
/*Write all letter of a line*/
138
cmd_state = CMD_STATE_WAIT;
139
i = line_start;
140
uint32_t letter;
141
while(i < line_end) {
142
letter = lv_txt_encoded_next(txt, &i);
143
144
/*Handle the re-color command*/
145
if((flag & LV_TXT_FLAG_RECOLOR) != 0) {
146
if(letter == (uint32_t)LV_TXT_COLOR_CMD[0]) {
147
if(cmd_state == CMD_STATE_WAIT) { /*Start char*/
148
par_start = i;
149
cmd_state = CMD_STATE_PAR;
150
continue;
151
} else if(cmd_state == CMD_STATE_PAR) { /*Other start char in parameter escaped cmd. char */
152
cmd_state = CMD_STATE_WAIT;
153
} else if(cmd_state == CMD_STATE_IN) { /*Command end */
154
cmd_state = CMD_STATE_WAIT;
155
continue;
156
}
157
}
158
159
/*Skip the color parameter and wait the space after it*/
160
if(cmd_state == CMD_STATE_PAR) {
161
if(letter == ' ') {
162
/*Get the parameter*/
163
if(i - par_start == LABEL_RECOLOR_PAR_LENGTH + 1) {
164
char buf[LABEL_RECOLOR_PAR_LENGTH + 1];
165
memcpy(buf, &txt[par_start], LABEL_RECOLOR_PAR_LENGTH);
166
buf[LABEL_RECOLOR_PAR_LENGTH] = '\0';
167
int r, g, b;
168
r = (hex_char_to_num(buf[0]) << 4) + hex_char_to_num(buf[1]);
169
g = (hex_char_to_num(buf[2]) << 4) + hex_char_to_num(buf[3]);
170
b = (hex_char_to_num(buf[4]) << 4) + hex_char_to_num(buf[5]);
171
recolor = LV_COLOR_MAKE(r, g, b);
172
} else {
173
recolor.full = style->text.color.full;
174
}
175
cmd_state = CMD_STATE_IN; /*After the parameter the text is in the command*/
176
}
177
continue;
178
}
179
}
180
181
lv_color_t color = style->text.color;
182
183
if(cmd_state == CMD_STATE_IN) color = recolor;
184
185
letter_fp(&pos, mask, font, letter, color, opa);
186
letter_w = lv_font_get_width(font, letter);
187
188
if(letter_w > 0){
189
pos.x += letter_w + style->text.letter_space;
190
}
191
}
192
/*Go to next line*/
193
line_start = line_end;
194
line_end += lv_txt_get_next_line(&txt[line_start], font, style->text.letter_space, w, flag);
195
196
pos.x = coords->x1;
197
/*Align to middle*/
198
if(flag & LV_TXT_FLAG_CENTER) {
199
line_width = lv_txt_get_width(&txt[line_start], line_end - line_start,
200
font, style->text.letter_space, flag);
201
202
pos.x += (lv_area_get_width(coords) - line_width) / 2;
203
204
}
205
/*Align to the right*/
206
else if(flag & LV_TXT_FLAG_RIGHT) {
207
line_width = lv_txt_get_width(&txt[line_start], line_end - line_start,
208
font, style->text.letter_space, flag);
209
pos.x += lv_area_get_width(coords) - line_width;
210
}
211
212
/*Go the next line position*/
213
pos.y += line_height;
214
215
if(pos.y > mask->y2) return;
216
}
217
}
218
219
/**********************
220
* STATIC FUNCTIONS
221
**********************/
222
223
/**
224
* Convert a hexadecimal characters to a number (0..15)
225
* @param hex Pointer to a hexadecimal character (0..9, A..F)
226
* @return the numerical value of `hex` or 0 on error
227
*/
228
static uint8_t hex_char_to_num(char hex)
229
{
230
uint8_t result = 0;
231
232
if(hex >= '0' && hex <= '9') {
233
result = hex - '0';
234
}
235
else {
236
if(hex >= 'a') hex -= 'a' - 'A'; /*Convert to upper case*/
237
238
switch(hex) {
239
case 'A':
240
result = 10;
241
break;
242
case 'B':
243
result = 11;
244
break;
245
case 'C':
246
result = 12;
247
break;
248
case 'D':
249
result = 13;
250
break;
251
case 'E':
252
result = 14;
253
break;
254
case 'F':
255
result = 15;
256
break;
257
default:
258
result = 0;
259
break;
260
}
261
}
262
263
return result;
264
}
265
266