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