1 /**
2  * @file lv_style.c
3  *
4  */
5 
6 /*********************
7  *      INCLUDES
8  *********************/
9 #include "lv_style.h"
10 #include "../misc/lv_mem.h"
11 
12 /*********************
13  *      DEFINES
14  *********************/
15 
16 /**********************
17  *      TYPEDEFS
18  **********************/
19 
20 /**********************
21  *  STATIC PROTOTYPES
22  **********************/
23 
24 /**********************
25  *  GLOBAL VARIABLES
26  **********************/
27 
28 /**********************
29  *  STATIC VARIABLES
30  **********************/
31 
32 /**********************
33  *      MACROS
34  **********************/
35 
36 /**********************
37  *   GLOBAL FUNCTIONS
38  **********************/
39 
lv_style_init(lv_style_t * style)40 void lv_style_init(lv_style_t * style)
41 {
42 #if LV_USE_ASSERT_STYLE
43     if(style->sentinel == LV_STYLE_SENTINEL_VALUE && style->prop_cnt > 1) {
44         LV_LOG_WARN("Style might be already inited. (Potential memory leak)");
45     }
46 #endif
47 
48     lv_memset_00(style, sizeof(lv_style_t));
49 #if LV_USE_ASSERT_STYLE
50     style->sentinel = LV_STYLE_SENTINEL_VALUE;
51 #endif
52 }
53 
lv_style_reset(lv_style_t * style)54 void lv_style_reset(lv_style_t * style)
55 {
56     LV_ASSERT_STYLE(style);
57 
58     if(style->is_const) {
59         LV_LOG_ERROR("Cannot reset const style");
60         return;
61     }
62 
63     if(style->prop_cnt > 1) lv_mem_free(style->v_p.values_and_props);
64     lv_memset_00(style, sizeof(lv_style_t));
65 #if LV_USE_ASSERT_STYLE
66     style->sentinel = LV_STYLE_SENTINEL_VALUE;
67 #endif
68 }
69 
lv_style_register_prop(void)70 lv_style_prop_t lv_style_register_prop(void)
71 {
72     static uint16_t act_id = (uint16_t)_LV_STYLE_LAST_BUILT_IN_PROP;
73     act_id++;
74     return act_id;
75 }
76 
lv_style_remove_prop(lv_style_t * style,lv_style_prop_t prop)77 bool lv_style_remove_prop(lv_style_t * style, lv_style_prop_t prop)
78 {
79     LV_ASSERT_STYLE(style);
80 
81     if(style->is_const) {
82         LV_LOG_ERROR("Cannot remove prop from const style");
83         return false;
84     }
85 
86     if(style->prop_cnt == 0)  return false;
87 
88     if(style->prop_cnt == 1) {
89         if(style->prop1 == prop) {
90             style->prop1 = LV_STYLE_PROP_INV;
91             style->prop_cnt = 0;
92             return true;
93         }
94         return false;
95     }
96 
97     uint8_t * tmp = style->v_p.values_and_props + style->prop_cnt * sizeof(lv_style_value_t);
98     uint16_t * old_props = (uint16_t *)tmp;
99     uint32_t i;
100     for(i = 0; i < style->prop_cnt; i++) {
101         if(old_props[i] == prop) {
102             lv_style_value_t * old_values = (lv_style_value_t *)style->v_p.values_and_props;
103 
104             if(style->prop_cnt == 2) {
105                 style->prop_cnt = 1;
106                 style->prop1 = i == 0 ? old_props[1] : old_props[0];
107                 style->v_p.value1 = i == 0 ? old_values[1] : old_values[0];
108             }
109             else {
110                 size_t size = (style->prop_cnt - 1) * (sizeof(lv_style_value_t) + sizeof(uint16_t));
111                 uint8_t * new_values_and_props = lv_mem_alloc(size);
112                 if(new_values_and_props == NULL) return false;
113                 style->v_p.values_and_props = new_values_and_props;
114                 style->prop_cnt--;
115 
116                 tmp = new_values_and_props + style->prop_cnt * sizeof(lv_style_value_t);
117                 uint16_t * new_props = (uint16_t *)tmp;
118                 lv_style_value_t * new_values = (lv_style_value_t *)new_values_and_props;
119 
120                 uint32_t j;
121                 for(i = j = 0; j <= style->prop_cnt;
122                     j++) { /*<=: because prop_cnt already reduced but all the old props. needs to be checked.*/
123                     if(old_props[j] != prop) {
124                         new_values[i] = old_values[j];
125                         new_props[i++] = old_props[j];
126                     }
127                 }
128             }
129 
130             lv_mem_free(old_values);
131             return true;
132         }
133     }
134 
135     return false;
136 }
137 
lv_style_set_prop(lv_style_t * style,lv_style_prop_t prop,lv_style_value_t value)138 void lv_style_set_prop(lv_style_t * style, lv_style_prop_t prop, lv_style_value_t value)
139 {
140     LV_ASSERT_STYLE(style);
141 
142     if(style->is_const) {
143         LV_LOG_ERROR("Cannot set property of constant style");
144         return;
145     }
146 
147     if(style->prop_cnt > 1) {
148         uint8_t * tmp = style->v_p.values_and_props + style->prop_cnt * sizeof(lv_style_value_t);
149         uint16_t * props = (uint16_t *)tmp;
150         int32_t i;
151         for(i = style->prop_cnt - 1; i >= 0; i--) {
152             if(props[i] == prop) {
153                 lv_style_value_t * values = (lv_style_value_t *)style->v_p.values_and_props;
154                 values[i] = value;
155                 return;
156             }
157         }
158 
159         size_t size = (style->prop_cnt + 1) * (sizeof(lv_style_value_t) + sizeof(uint16_t));
160         uint8_t * values_and_props = lv_mem_realloc(style->v_p.values_and_props, size);
161         if(values_and_props == NULL) return;
162         style->v_p.values_and_props = values_and_props;
163 
164         tmp = values_and_props + style->prop_cnt * sizeof(lv_style_value_t);
165         props = (uint16_t *)tmp;
166         /*Shift all props to make place for the value before them*/
167         for(i = style->prop_cnt - 1; i >= 0; i--) {
168             props[i + sizeof(lv_style_value_t) / sizeof(uint16_t)] = props[i];
169         }
170         style->prop_cnt++;
171 
172         /*Go to the new position wit the props*/
173         tmp = values_and_props + style->prop_cnt * sizeof(lv_style_value_t);
174         props = (uint16_t *)tmp;
175         lv_style_value_t * values = (lv_style_value_t *)values_and_props;
176 
177         /*Set the new property and value*/
178         props[style->prop_cnt - 1] = prop;
179         values[style->prop_cnt - 1] = value;
180     }
181     else if(style->prop_cnt == 1) {
182         if(style->prop1 == prop) {
183             style->v_p.value1 = value;
184             return;
185         }
186         size_t size = (style->prop_cnt + 1) * (sizeof(lv_style_value_t) + sizeof(uint16_t));
187         uint8_t * values_and_props = lv_mem_alloc(size);
188         if(values_and_props == NULL) return;
189         lv_style_value_t value_tmp = style->v_p.value1;
190         style->v_p.values_and_props = values_and_props;
191         style->prop_cnt++;
192 
193         uint8_t * tmp = values_and_props + style->prop_cnt * sizeof(lv_style_value_t);
194         uint16_t * props = (uint16_t *)tmp;
195         lv_style_value_t * values = (lv_style_value_t *)values_and_props;
196         props[0] = style->prop1;
197         props[1] = prop;
198         values[0] = value_tmp;
199         values[1] = value;
200     }
201     else {
202         style->prop_cnt = 1;
203         style->prop1 = prop;
204         style->v_p.value1 = value;
205     }
206 
207     uint8_t group = _lv_style_get_prop_group(prop);
208     style->has_group |= 1 << group;
209 }
210 
lv_style_get_prop(const lv_style_t * style,lv_style_prop_t prop,lv_style_value_t * value)211 lv_res_t lv_style_get_prop(const lv_style_t * style, lv_style_prop_t prop, lv_style_value_t * value)
212 {
213     return lv_style_get_prop_inlined(style, prop, value);
214 }
215 
lv_style_transition_dsc_init(lv_style_transition_dsc_t * tr,const lv_style_prop_t props[],lv_anim_path_cb_t path_cb,uint32_t time,uint32_t delay,void * user_data)216 void lv_style_transition_dsc_init(lv_style_transition_dsc_t * tr, const lv_style_prop_t props[],
217                                   lv_anim_path_cb_t path_cb, uint32_t time, uint32_t delay, void * user_data)
218 {
219     lv_memset_00(tr, sizeof(lv_style_transition_dsc_t));
220     tr->props = props;
221     tr->path_xcb = path_cb == NULL ? lv_anim_path_linear : path_cb;
222     tr->time = time;
223     tr->delay = delay;
224 #if LV_USE_USER_DATA
225     tr->user_data = user_data;
226 #else
227     LV_UNUSED(user_data);
228 #endif
229 }
230 
lv_style_prop_get_default(lv_style_prop_t prop)231 lv_style_value_t lv_style_prop_get_default(lv_style_prop_t prop)
232 {
233     lv_style_value_t value;
234     switch(prop) {
235         case LV_STYLE_TRANSFORM_ZOOM:
236             value.num = LV_IMG_ZOOM_NONE;
237             break;
238         case LV_STYLE_BG_COLOR:
239             value.color = lv_color_white();
240             break;
241         case LV_STYLE_BG_GRAD_COLOR:
242         case LV_STYLE_BORDER_COLOR:
243         case LV_STYLE_SHADOW_COLOR:
244         case LV_STYLE_OUTLINE_COLOR:
245         case LV_STYLE_ARC_COLOR:
246         case LV_STYLE_LINE_COLOR:
247         case LV_STYLE_TEXT_COLOR:
248         case LV_STYLE_IMG_RECOLOR:
249             value.color = lv_color_black();
250             break;
251         case LV_STYLE_OPA:
252         case LV_STYLE_BORDER_OPA:
253         case LV_STYLE_TEXT_OPA:
254         case LV_STYLE_IMG_OPA:
255         case LV_STYLE_BG_IMG_OPA:
256         case LV_STYLE_OUTLINE_OPA:
257         case LV_STYLE_SHADOW_OPA:
258         case LV_STYLE_LINE_OPA:
259         case LV_STYLE_ARC_OPA:
260             value.num = LV_OPA_COVER;
261             break;
262         case LV_STYLE_BG_GRAD_STOP:
263             value.num = 255;
264             break;
265         case LV_STYLE_BORDER_SIDE:
266             value.num = LV_BORDER_SIDE_FULL;
267             break;
268         case LV_STYLE_TEXT_FONT:
269             value.ptr = LV_FONT_DEFAULT;
270             break;
271         case LV_STYLE_MAX_WIDTH:
272         case LV_STYLE_MAX_HEIGHT:
273             value.num = LV_COORD_MAX;
274             break;
275         default:
276             value.ptr = NULL;
277             value.num = 0;
278             break;
279     }
280 
281     return value;
282 }
283 
lv_style_is_empty(const lv_style_t * style)284 bool lv_style_is_empty(const lv_style_t * style)
285 {
286     LV_ASSERT_STYLE(style);
287 
288     return style->prop_cnt == 0 ? true : false;
289 }
290 
_lv_style_get_prop_group(lv_style_prop_t prop)291 uint8_t _lv_style_get_prop_group(lv_style_prop_t prop)
292 {
293     uint16_t group = (prop & 0x1FF) >> 4;
294     if(group > 7) group = 7;    /*The MSB marks all the custom properties*/
295     return (uint8_t)group;
296 }
297 
298 /**********************
299  *   STATIC FUNCTIONS
300  **********************/
301