1 /**
2 * @file lv_style.c
3 *
4 */
5
6 /*********************
7 * INCLUDES
8 *********************/
9 #include "lv_obj.h"
10 #include "../lv_misc/lv_mem.h"
11 #include "../lv_misc/lv_anim.h"
12
13 /*********************
14 * DEFINES
15 *********************/
16 #define STYLE_MIX_MAX 256
17 #define STYLE_MIX_SHIFT 8 /*log2(STYLE_MIX_MAX)*/
18
19 #define VAL_PROP(v1, v2, r) v1 + (((v2 - v1) * r) >> STYLE_MIX_SHIFT)
20 #define STYLE_ATTR_MIX(attr, r) \
21 if(start->attr != end->attr) { \
22 res->attr = VAL_PROP(start->attr, end->attr, r); \
23 } else { \
24 res->attr = start->attr; \
25 }
26
27 /**********************
28 * TYPEDEFS
29 **********************/
30
31 /**********************
32 * STATIC PROTOTYPES
33 **********************/
34 #if LV_USE_ANIMATION
35 static void style_animator(lv_style_anim_dsc_t * dsc, lv_anim_value_t val);
36 static void style_animation_common_end_cb(lv_anim_t * a);
37 #endif
38
39 /**********************
40 * STATIC VARIABLES
41 **********************/
42 lv_style_t lv_style_scr;
43 lv_style_t lv_style_transp;
44 lv_style_t lv_style_transp_fit;
45 lv_style_t lv_style_transp_tight;
46 lv_style_t lv_style_plain;
47 lv_style_t lv_style_plain_color;
48 lv_style_t lv_style_pretty;
49 lv_style_t lv_style_pretty_color;
50 lv_style_t lv_style_btn_rel;
51 lv_style_t lv_style_btn_pr;
52 lv_style_t lv_style_btn_tgl_rel;
53 lv_style_t lv_style_btn_tgl_pr;
54 lv_style_t lv_style_btn_ina;
55
56 /**********************
57 * MACROS
58 **********************/
59
60 /**********************
61 * GLOBAL FUNCTIONS
62 **********************/
63
64 /**
65 * Init the basic styles
66 */
lv_style_init(void)67 void lv_style_init(void)
68 {
69 /* Not White/Black/Gray colors are created by HSV model with
70 * HUE = 210*/
71
72 /*Screen style*/
73 lv_style_scr.glass = 0;
74 lv_style_scr.body.opa = LV_OPA_COVER;
75 lv_style_scr.body.main_color = LV_COLOR_WHITE;
76 lv_style_scr.body.grad_color = LV_COLOR_WHITE;
77 lv_style_scr.body.radius = 0;
78 lv_style_scr.body.padding.left = 0;
79 lv_style_scr.body.padding.right = 0;
80 lv_style_scr.body.padding.top = 0;
81 lv_style_scr.body.padding.bottom = 0;
82 lv_style_scr.body.padding.inner = LV_DPI / 20;
83
84 lv_style_scr.body.border.color = LV_COLOR_BLACK;
85 lv_style_scr.body.border.opa = LV_OPA_COVER;
86 lv_style_scr.body.border.width = 0;
87 lv_style_scr.body.border.part = LV_BORDER_FULL;
88
89 lv_style_scr.body.shadow.color = LV_COLOR_GRAY;
90 lv_style_scr.body.shadow.type = LV_SHADOW_FULL;
91 lv_style_scr.body.shadow.width = 0;
92
93 lv_style_scr.text.opa = LV_OPA_COVER;
94 lv_style_scr.text.color = lv_color_make(0x30, 0x30, 0x30);
95 lv_style_scr.text.sel_color = lv_color_make(0x55, 0x96, 0xd8);
96 lv_style_scr.text.font = LV_FONT_DEFAULT;
97 lv_style_scr.text.letter_space = 0;
98 lv_style_scr.text.line_space = 2;
99
100 lv_style_scr.image.opa = LV_OPA_COVER;
101 lv_style_scr.image.color = lv_color_make(0x20, 0x20, 0x20);
102 lv_style_scr.image.intense = LV_OPA_TRANSP;
103
104 lv_style_scr.line.opa = LV_OPA_COVER;
105 lv_style_scr.line.color = lv_color_make(0x20, 0x20, 0x20);
106 lv_style_scr.line.width = 2;
107 lv_style_scr.line.rounded = 0;
108
109 /*Plain style (by default near the same as the screen style)*/
110 lv_style_copy(&lv_style_plain, &lv_style_scr);
111 lv_style_plain.body.padding.left = LV_DPI / 20;
112 lv_style_plain.body.padding.right = LV_DPI / 20;
113 lv_style_plain.body.padding.top = LV_DPI / 20;
114 lv_style_plain.body.padding.bottom = LV_DPI / 20;
115
116 /*Plain color style*/
117 lv_style_copy(&lv_style_plain_color, &lv_style_plain);
118 lv_style_plain_color.text.color = lv_color_make(0xf0, 0xf0, 0xf0);
119 lv_style_plain_color.image.color = lv_color_make(0xf0, 0xf0, 0xf0);
120 lv_style_plain_color.line.color = lv_color_make(0xf0, 0xf0, 0xf0);
121 lv_style_plain_color.body.main_color = lv_color_make(0x55, 0x96, 0xd8);
122 lv_style_plain_color.body.grad_color = lv_style_plain_color.body.main_color;
123
124 /*Pretty style */
125 lv_style_copy(&lv_style_pretty, &lv_style_plain);
126 lv_style_pretty.text.color = lv_color_make(0x20, 0x20, 0x20);
127 lv_style_pretty.image.color = lv_color_make(0x20, 0x20, 0x20);
128 lv_style_pretty.line.color = lv_color_make(0x20, 0x20, 0x20);
129 lv_style_pretty.body.main_color = LV_COLOR_WHITE;
130 lv_style_pretty.body.grad_color = LV_COLOR_SILVER;
131 lv_style_pretty.body.radius = LV_DPI / 15;
132 lv_style_pretty.body.border.color = lv_color_make(0x40, 0x40, 0x40);
133 lv_style_pretty.body.border.width = LV_DPI / 50 >= 1 ? LV_DPI / 50 : 1;
134 lv_style_pretty.body.border.opa = LV_OPA_30;
135
136 /*Pretty color style*/
137 lv_style_copy(&lv_style_pretty_color, &lv_style_pretty);
138 lv_style_pretty_color.text.color = lv_color_make(0xe0, 0xe0, 0xe0);
139 lv_style_pretty_color.image.color = lv_color_make(0xe0, 0xe0, 0xe0);
140 lv_style_pretty_color.line.color = lv_color_make(0xc0, 0xc0, 0xc0);
141 lv_style_pretty_color.body.main_color = lv_color_make(0x6b, 0x9a, 0xc7);
142 lv_style_pretty_color.body.grad_color = lv_color_make(0x2b, 0x59, 0x8b);
143 lv_style_pretty_color.body.border.color = lv_color_make(0x15, 0x2c, 0x42);
144
145 /*Transparent style*/
146 lv_style_copy(&lv_style_transp, &lv_style_plain);
147 lv_style_transp.glass = 1;
148 lv_style_transp.body.border.width = 0;
149 lv_style_transp.body.opa = LV_OPA_TRANSP;
150
151 /*Transparent fitting size*/
152 lv_style_copy(&lv_style_transp_fit, &lv_style_transp);
153 lv_style_transp_fit.body.padding.left = 0;
154 lv_style_transp_fit.body.padding.right = 0;
155 lv_style_transp_fit.body.padding.top = 0;
156 lv_style_transp_fit.body.padding.bottom = 0;
157
158 /*Transparent tight style*/
159 lv_style_copy(&lv_style_transp_tight, &lv_style_transp_fit);
160 lv_style_transp_tight.body.padding.inner = 0;
161
162 /*Button released style*/
163 lv_style_copy(&lv_style_btn_rel, &lv_style_plain);
164 lv_style_btn_rel.body.main_color = lv_color_make(0x76, 0xa2, 0xd0);
165 lv_style_btn_rel.body.grad_color = lv_color_make(0x19, 0x3a, 0x5d);
166 lv_style_btn_rel.body.radius = LV_DPI / 15;
167 lv_style_btn_rel.body.padding.left = LV_DPI / 4;
168 lv_style_btn_rel.body.padding.right = LV_DPI / 4;
169 lv_style_btn_rel.body.padding.top = LV_DPI / 6;
170 lv_style_btn_rel.body.padding.bottom = LV_DPI / 6;
171 lv_style_btn_rel.body.padding.inner = LV_DPI / 10;
172 lv_style_btn_rel.body.border.color = lv_color_make(0x0b, 0x19, 0x28);
173 lv_style_btn_rel.body.border.width = LV_DPI / 50 >= 1 ? LV_DPI / 50 : 1;
174 lv_style_btn_rel.body.border.opa = LV_OPA_70;
175 lv_style_btn_rel.body.shadow.color = LV_COLOR_GRAY;
176 lv_style_btn_rel.body.shadow.width = 0;
177 lv_style_btn_rel.text.color = lv_color_make(0xff, 0xff, 0xff);
178 lv_style_btn_rel.image.color = lv_color_make(0xff, 0xff, 0xff);
179
180 /*Button pressed style*/
181 lv_style_copy(&lv_style_btn_pr, &lv_style_btn_rel);
182 lv_style_btn_pr.body.main_color = lv_color_make(0x33, 0x62, 0x94);
183 lv_style_btn_pr.body.grad_color = lv_color_make(0x10, 0x26, 0x3c);
184 lv_style_btn_pr.text.color = lv_color_make(0xa4, 0xb5, 0xc6);
185 lv_style_btn_pr.image.color = lv_color_make(0xa4, 0xb5, 0xc6);
186 lv_style_btn_pr.line.color = lv_color_make(0xa4, 0xb5, 0xc6);
187
188 /*Button toggle released style*/
189 lv_style_copy(&lv_style_btn_tgl_rel, &lv_style_btn_rel);
190 lv_style_btn_tgl_rel.body.main_color = lv_color_make(0x0a, 0x11, 0x22);
191 lv_style_btn_tgl_rel.body.grad_color = lv_color_make(0x37, 0x62, 0x90);
192 lv_style_btn_tgl_rel.body.border.color = lv_color_make(0x01, 0x07, 0x0d);
193 lv_style_btn_tgl_rel.text.color = lv_color_make(0xc8, 0xdd, 0xf4);
194 lv_style_btn_tgl_rel.image.color = lv_color_make(0xc8, 0xdd, 0xf4);
195 lv_style_btn_tgl_rel.line.color = lv_color_make(0xc8, 0xdd, 0xf4);
196
197 /*Button toggle pressed style*/
198 lv_style_copy(&lv_style_btn_tgl_pr, &lv_style_btn_tgl_rel);
199 lv_style_btn_tgl_pr.body.main_color = lv_color_make(0x02, 0x14, 0x27);
200 lv_style_btn_tgl_pr.body.grad_color = lv_color_make(0x2b, 0x4c, 0x70);
201 lv_style_btn_tgl_pr.text.color = lv_color_make(0xa4, 0xb5, 0xc6);
202 lv_style_btn_tgl_pr.image.color = lv_color_make(0xa4, 0xb5, 0xc6);
203 lv_style_btn_tgl_pr.line.color = lv_color_make(0xa4, 0xb5, 0xc6);
204
205 /*Button inactive style*/
206 lv_style_copy(&lv_style_btn_ina, &lv_style_btn_rel);
207 lv_style_btn_ina.body.main_color = lv_color_make(0xd8, 0xd8, 0xd8);
208 lv_style_btn_ina.body.grad_color = lv_color_make(0xd8, 0xd8, 0xd8);
209 lv_style_btn_ina.body.border.color = lv_color_make(0x90, 0x90, 0x90);
210 lv_style_btn_ina.text.color = lv_color_make(0x70, 0x70, 0x70);
211 lv_style_btn_ina.image.color = lv_color_make(0x70, 0x70, 0x70);
212 lv_style_btn_ina.line.color = lv_color_make(0x70, 0x70, 0x70);
213 }
214
215 /**
216 * Copy a style to an other
217 * @param dest pointer to the destination style
218 * @param src pointer to the source style
219 */
lv_style_copy(lv_style_t * dest,const lv_style_t * src)220 void lv_style_copy(lv_style_t * dest, const lv_style_t * src)
221 {
222 memcpy(dest, src, sizeof(lv_style_t));
223 }
224
225 /**
226 * Mix two styles according to a given ratio
227 * @param start start style
228 * @param end end style
229 * @param res store the result style here
230 * @param ratio the ratio of mix [0..256]; 0: `start` style; 256: `end` style
231 */
lv_style_mix(const lv_style_t * start,const lv_style_t * end,lv_style_t * res,uint16_t ratio)232 void lv_style_mix(const lv_style_t * start, const lv_style_t * end, lv_style_t * res, uint16_t ratio)
233 {
234 STYLE_ATTR_MIX(body.opa, ratio);
235 STYLE_ATTR_MIX(body.radius, ratio);
236 STYLE_ATTR_MIX(body.border.width, ratio);
237 STYLE_ATTR_MIX(body.border.opa, ratio);
238 STYLE_ATTR_MIX(body.shadow.width, ratio);
239 STYLE_ATTR_MIX(body.padding.left, ratio);
240 STYLE_ATTR_MIX(body.padding.right, ratio);
241 STYLE_ATTR_MIX(body.padding.top, ratio);
242 STYLE_ATTR_MIX(body.padding.bottom, ratio);
243 STYLE_ATTR_MIX(body.padding.inner, ratio);
244 STYLE_ATTR_MIX(text.line_space, ratio);
245 STYLE_ATTR_MIX(text.letter_space, ratio);
246 STYLE_ATTR_MIX(text.opa, ratio);
247 STYLE_ATTR_MIX(line.width, ratio);
248 STYLE_ATTR_MIX(line.opa, ratio);
249 STYLE_ATTR_MIX(image.intense, ratio);
250 STYLE_ATTR_MIX(image.opa, ratio);
251
252 lv_opa_t opa = ratio == STYLE_MIX_MAX ? LV_OPA_COVER : ratio;
253
254 res->body.main_color = lv_color_mix(end->body.main_color, start->body.main_color, opa);
255 res->body.grad_color = lv_color_mix(end->body.grad_color, start->body.grad_color, opa);
256 res->body.border.color = lv_color_mix(end->body.border.color, start->body.border.color, opa);
257 res->body.shadow.color = lv_color_mix(end->body.shadow.color, start->body.shadow.color, opa);
258 res->text.color = lv_color_mix(end->text.color, start->text.color, opa);
259 res->image.color = lv_color_mix(end->image.color, start->image.color, opa);
260 res->line.color = lv_color_mix(end->line.color, start->line.color, opa);
261
262 if(ratio < (STYLE_MIX_MAX >> 1)) {
263 res->body.border.part = start->body.border.part;
264 res->glass = start->glass;
265 res->text.font = start->text.font;
266 res->body.shadow.type = start->body.shadow.type;
267 res->line.rounded = start->line.rounded;
268 } else {
269 res->body.border.part = end->body.border.part;
270 res->glass = end->glass;
271 res->text.font = end->text.font;
272 res->body.shadow.type = end->body.shadow.type;
273 res->line.rounded = end->line.rounded;
274 }
275 }
276
277 #if LV_USE_ANIMATION
278
lv_style_anim_init(lv_anim_t * a)279 void lv_style_anim_init(lv_anim_t * a)
280 {
281 lv_anim_init(a);
282 a->start = 0;
283 a->end = STYLE_MIX_MAX;
284 a->exec_cb = (lv_anim_exec_xcb_t)style_animator;
285 a->path_cb = lv_anim_path_linear;
286 a->ready_cb = style_animation_common_end_cb;
287
288 lv_style_anim_dsc_t * dsc;
289 dsc = lv_mem_alloc(sizeof(lv_style_anim_dsc_t));
290 lv_mem_assert(dsc);
291 if(dsc == NULL) return;
292 dsc->ready_cb = NULL;
293 dsc->style_anim = NULL;
294 lv_style_copy(&dsc->style_start, &lv_style_plain);
295 lv_style_copy(&dsc->style_end, &lv_style_plain);
296
297 a->var = (void *)dsc;
298 }
299
lv_style_anim_set_styles(lv_anim_t * a,lv_style_t * to_anim,const lv_style_t * start,const lv_style_t * end)300 void lv_style_anim_set_styles(lv_anim_t * a, lv_style_t * to_anim, const lv_style_t * start, const lv_style_t * end)
301 {
302
303 lv_style_anim_dsc_t * dsc = a->var;
304 dsc->style_anim = to_anim;
305 memcpy(&dsc->style_start, start, sizeof(lv_style_t));
306 memcpy(&dsc->style_end, end, sizeof(lv_style_t));
307 memcpy(dsc->style_anim, start, sizeof(lv_style_t));
308 }
309 #endif
310 /**********************
311 * STATIC FUNCTIONS
312 **********************/
313 #if LV_USE_ANIMATION
314 /**
315 * Used by the style animations to set the values of a style according to start and end style.
316 * @param dsc the 'animated variable' set by lv_style_anim_create()
317 * @param val the current state of the animation between 0 and LV_ANIM_RESOLUTION
318 */
style_animator(lv_style_anim_dsc_t * dsc,lv_anim_value_t val)319 static void style_animator(lv_style_anim_dsc_t * dsc, lv_anim_value_t val)
320 {
321 const lv_style_t * start = &dsc->style_start;
322 const lv_style_t * end = &dsc->style_end;
323 lv_style_t * act = dsc->style_anim;
324
325 lv_style_mix(start, end, act, val);
326
327 lv_obj_report_style_mod(dsc->style_anim);
328 }
329
330 /**
331 * Called when a style animation is ready
332 * It called the user defined call back and free the allocated memories
333 * @param a pointer to the animation
334 */
style_animation_common_end_cb(lv_anim_t * a)335 static void style_animation_common_end_cb(lv_anim_t * a)
336 {
337
338 (void)a; /*Unused*/
339 lv_style_anim_dsc_t * dsc = a->var; /*To avoid casting*/
340
341 if(dsc->ready_cb) dsc->ready_cb(a);
342
343 lv_mem_free(dsc);
344 }
345
346 #endif
347