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