feat(style) add 'inherit' and 'initial' CSS properties (#3390)

Fixes #3086
This commit is contained in:
embeddedt
2022-06-09 20:20:34 -04:00
committed by GitHub
parent 03c43d95ad
commit 9a48de0f8b
10 changed files with 312 additions and 175 deletions

View File

@@ -882,7 +882,7 @@ static void lv_obj_set_state(lv_obj_t * obj, lv_state_t new_state)
if(obj_style->is_trans) continue;
lv_style_value_t v;
if(lv_style_get_prop_inlined(obj_style->style, LV_STYLE_TRANSITION, &v) == false) continue;
if(lv_style_get_prop_inlined(obj_style->style, LV_STYLE_TRANSITION, &v) != LV_STYLE_RES_FOUND) continue;
const lv_style_transition_dsc_t * tr = v.ptr;
/*Add the props to the set if not added yet or added but with smaller weight*/

View File

@@ -44,7 +44,7 @@ typedef enum {
**********************/
static lv_style_t * get_local_style(lv_obj_t * obj, lv_style_selector_t selector);
static _lv_obj_style_t * get_trans_style(lv_obj_t * obj, uint32_t part);
static bool get_prop_core(const lv_obj_t * obj, lv_part_t part, lv_style_prop_t prop, lv_style_value_t * v);
static lv_style_res_t get_prop_core(const lv_obj_t * obj, lv_part_t part, lv_style_prop_t prop, lv_style_value_t * v);
static void report_style_change_core(void * style, lv_obj_t * obj);
static void refresh_children_style(lv_obj_t * obj);
static bool trans_del(lv_obj_t * obj, lv_part_t part, lv_style_prop_t prop, trans_t * tr_limit);
@@ -176,7 +176,7 @@ void lv_obj_refresh_style(lv_obj_t * obj, lv_style_selector_t selector, lv_style
bool is_layout_refr = lv_style_prop_has_flag(prop, LV_STYLE_PROP_LAYOUT_REFR);
bool is_ext_draw = lv_style_prop_has_flag(prop, LV_STYLE_PROP_EXT_DRAW);
bool is_inherit = lv_style_prop_has_flag(prop, LV_STYLE_PROP_INHERIT);
bool is_inheritable = lv_style_prop_has_flag(prop, LV_STYLE_PROP_INHERIT);
bool is_layer_refr = lv_style_prop_has_flag(prop, LV_STYLE_PROP_LAYER_REFR);
if(is_layout_refr) {
@@ -208,7 +208,7 @@ void lv_obj_refresh_style(lv_obj_t * obj, lv_style_selector_t selector, lv_style
}
lv_obj_invalidate(obj);
if(prop == LV_STYLE_PROP_ANY || (is_inherit && (is_ext_draw || is_layout_refr))) {
if(prop == LV_STYLE_PROP_ANY || (is_inheritable && (is_ext_draw || is_layout_refr))) {
if(part != LV_PART_SCROLLBAR) {
refresh_children_style(obj);
}
@@ -223,15 +223,15 @@ void lv_obj_enable_style_refresh(bool en)
lv_style_value_t lv_obj_get_style_prop(const lv_obj_t * obj, lv_part_t part, lv_style_prop_t prop)
{
lv_style_value_t value_act;
bool inherit = lv_style_prop_has_flag(prop, LV_STYLE_PROP_INHERIT);
bool found = false;
bool inheritable = lv_style_prop_has_flag(prop, LV_STYLE_PROP_INHERIT);
lv_style_res_t found = LV_STYLE_RES_NOT_FOUND;
while(obj) {
found = get_prop_core(obj, part, prop, &value_act);
if(found) break;
if(!inherit) break;
if(found == LV_STYLE_RES_FOUND) break;
if(!inheritable) break;
/*If not found, check the `MAIN` style first*/
if(part != LV_PART_MAIN) {
if(found != LV_STYLE_RES_INHERIT && part != LV_PART_MAIN) {
part = LV_PART_MAIN;
continue;
}
@@ -240,7 +240,7 @@ lv_style_value_t lv_obj_get_style_prop(const lv_obj_t * obj, lv_part_t part, lv_
obj = lv_obj_get_parent(obj);
}
if(!found) {
if(found != LV_STYLE_RES_FOUND) {
if(part == LV_PART_MAIN && (prop == LV_STYLE_WIDTH || prop == LV_STYLE_HEIGHT)) {
const lv_obj_class_t * cls = obj->class_p;
while(cls) {
@@ -275,9 +275,17 @@ void lv_obj_set_local_style_prop(lv_obj_t * obj, lv_style_prop_t prop, lv_style_
lv_obj_refresh_style(obj, selector, prop);
}
void lv_obj_set_local_style_prop_meta(lv_obj_t * obj, lv_style_prop_t prop, uint16_t meta,
lv_style_selector_t selector)
{
lv_style_t * style = get_local_style(obj, selector);
lv_style_set_prop_meta(style, prop, meta);
lv_obj_refresh_style(obj, selector, prop);
}
lv_res_t lv_obj_get_local_style_prop(lv_obj_t * obj, lv_style_prop_t prop, lv_style_value_t * value,
lv_style_selector_t selector)
lv_style_res_t lv_obj_get_local_style_prop(lv_obj_t * obj, lv_style_prop_t prop, lv_style_value_t * value,
lv_style_selector_t selector)
{
uint32_t i;
for(i = 0; i < obj->style_cnt; i++) {
@@ -287,7 +295,7 @@ lv_res_t lv_obj_get_local_style_prop(lv_obj_t * obj, lv_style_prop_t prop, lv_st
}
}
return LV_RES_INV;
return LV_STYLE_RES_NOT_FOUND;
}
bool lv_obj_remove_local_style_prop(lv_obj_t * obj, lv_style_prop_t prop, lv_style_selector_t selector)
@@ -556,7 +564,7 @@ static _lv_obj_style_t * get_trans_style(lv_obj_t * obj, lv_style_selector_t se
}
static bool get_prop_core(const lv_obj_t * obj, lv_part_t part, lv_style_prop_t prop, lv_style_value_t * v)
static lv_style_res_t get_prop_core(const lv_obj_t * obj, lv_part_t part, lv_style_prop_t prop, lv_style_value_t * v)
{
uint8_t group = 1 << _lv_style_get_prop_group(prop);
int32_t weight = -1;
@@ -565,7 +573,7 @@ static bool get_prop_core(const lv_obj_t * obj, lv_part_t part, lv_style_prop_t
lv_style_value_t value_tmp;
bool skip_trans = obj->skip_trans;
uint32_t i;
bool found;
lv_style_res_t found;
for(i = 0; i < obj->style_cnt; i++) {
_lv_obj_style_t * obj_style = &obj->styles[i];
if(obj_style->is_trans == false) break;
@@ -576,9 +584,12 @@ static bool get_prop_core(const lv_obj_t * obj, lv_part_t part, lv_style_prop_t
if(part_act != part) continue;
if((obj_style->style->has_group & group) == 0) continue;
found = lv_style_get_prop(obj_style->style, prop, &value_tmp);
if(found) {
if(found == LV_STYLE_RES_FOUND) {
*v = value_tmp;
return true;
return LV_STYLE_RES_FOUND;
}
else if(found == LV_STYLE_RES_INHERIT) {
return LV_STYLE_RES_INHERIT;
}
}
@@ -598,23 +609,26 @@ static bool get_prop_core(const lv_obj_t * obj, lv_part_t part, lv_style_prop_t
found = lv_style_get_prop(obj_style->style, prop, &value_tmp);
if(found) {
if(found == LV_STYLE_RES_FOUND) {
if(state_act == state) {
*v = value_tmp;
return true;
return LV_STYLE_RES_FOUND;
}
if(weight < state_act) {
weight = state_act;
*v = value_tmp;
}
}
else if(found == LV_STYLE_RES_INHERIT) {
return LV_STYLE_RES_INHERIT;
}
}
if(weight >= 0) {
*v = value_tmp;
return true;
return LV_STYLE_RES_FOUND;
}
else return false;
else return LV_STYLE_RES_NOT_FOUND;
}
/**

View File

@@ -140,8 +140,11 @@ lv_style_value_t lv_obj_get_style_prop(const struct _lv_obj_t * obj, lv_part_t p
void lv_obj_set_local_style_prop(struct _lv_obj_t * obj, lv_style_prop_t prop, lv_style_value_t value,
lv_style_selector_t selector);
lv_res_t lv_obj_get_local_style_prop(struct _lv_obj_t * obj, lv_style_prop_t prop, lv_style_value_t * value,
lv_style_selector_t selector);
void lv_obj_set_local_style_prop_meta(struct _lv_obj_t * obj, lv_style_prop_t prop, uint16_t meta,
lv_style_selector_t selector);
lv_style_res_t lv_obj_get_local_style_prop(struct _lv_obj_t * obj, lv_style_prop_t prop, lv_style_value_t * value,
lv_style_selector_t selector);
/**
* Remove a local style property from a part of an object with a given state.

View File

@@ -600,8 +600,7 @@ void lv_obj_set_style_opa(struct _lv_obj_t * obj, lv_opa_t value, lv_style_selec
lv_obj_set_local_style_prop(obj, LV_STYLE_OPA, v, selector);
}
void lv_obj_set_style_color_filter_dsc(struct _lv_obj_t * obj, const lv_color_filter_dsc_t * value,
lv_style_selector_t selector)
void lv_obj_set_style_color_filter_dsc(struct _lv_obj_t * obj, const lv_color_filter_dsc_t * value, lv_style_selector_t selector)
{
lv_style_value_t v = {
.ptr = value
@@ -641,8 +640,7 @@ void lv_obj_set_style_anim_speed(struct _lv_obj_t * obj, uint32_t value, lv_styl
lv_obj_set_local_style_prop(obj, LV_STYLE_ANIM_SPEED, v, selector);
}
void lv_obj_set_style_transition(struct _lv_obj_t * obj, const lv_style_transition_dsc_t * value,
lv_style_selector_t selector)
void lv_obj_set_style_transition(struct _lv_obj_t * obj, const lv_style_transition_dsc_t * value, lv_style_selector_t selector)
{
lv_style_value_t v = {
.ptr = value

View File

@@ -162,8 +162,7 @@ static inline lv_color_t lv_obj_get_style_bg_grad_color(const struct _lv_obj_t *
static inline lv_color_t lv_obj_get_style_bg_grad_color_filtered(const struct _lv_obj_t * obj, uint32_t part)
{
lv_style_value_t v = _lv_obj_style_apply_color_filter(obj, part, lv_obj_get_style_prop(obj, part,
LV_STYLE_BG_GRAD_COLOR));
lv_style_value_t v = _lv_obj_style_apply_color_filter(obj, part, lv_obj_get_style_prop(obj, part, LV_STYLE_BG_GRAD_COLOR));
return v.color;
}
@@ -217,8 +216,7 @@ static inline lv_color_t lv_obj_get_style_bg_img_recolor(const struct _lv_obj_t
static inline lv_color_t lv_obj_get_style_bg_img_recolor_filtered(const struct _lv_obj_t * obj, uint32_t part)
{
lv_style_value_t v = _lv_obj_style_apply_color_filter(obj, part, lv_obj_get_style_prop(obj, part,
LV_STYLE_BG_IMG_RECOLOR));
lv_style_value_t v = _lv_obj_style_apply_color_filter(obj, part, lv_obj_get_style_prop(obj, part, LV_STYLE_BG_IMG_RECOLOR));
return v.color;
}
@@ -242,8 +240,7 @@ static inline lv_color_t lv_obj_get_style_border_color(const struct _lv_obj_t *
static inline lv_color_t lv_obj_get_style_border_color_filtered(const struct _lv_obj_t * obj, uint32_t part)
{
lv_style_value_t v = _lv_obj_style_apply_color_filter(obj, part, lv_obj_get_style_prop(obj, part,
LV_STYLE_BORDER_COLOR));
lv_style_value_t v = _lv_obj_style_apply_color_filter(obj, part, lv_obj_get_style_prop(obj, part, LV_STYLE_BORDER_COLOR));
return v.color;
}
@@ -285,8 +282,7 @@ static inline lv_color_t lv_obj_get_style_outline_color(const struct _lv_obj_t *
static inline lv_color_t lv_obj_get_style_outline_color_filtered(const struct _lv_obj_t * obj, uint32_t part)
{
lv_style_value_t v = _lv_obj_style_apply_color_filter(obj, part, lv_obj_get_style_prop(obj, part,
LV_STYLE_OUTLINE_COLOR));
lv_style_value_t v = _lv_obj_style_apply_color_filter(obj, part, lv_obj_get_style_prop(obj, part, LV_STYLE_OUTLINE_COLOR));
return v.color;
}
@@ -334,8 +330,7 @@ static inline lv_color_t lv_obj_get_style_shadow_color(const struct _lv_obj_t *
static inline lv_color_t lv_obj_get_style_shadow_color_filtered(const struct _lv_obj_t * obj, uint32_t part)
{
lv_style_value_t v = _lv_obj_style_apply_color_filter(obj, part, lv_obj_get_style_prop(obj, part,
LV_STYLE_SHADOW_COLOR));
lv_style_value_t v = _lv_obj_style_apply_color_filter(obj, part, lv_obj_get_style_prop(obj, part, LV_STYLE_SHADOW_COLOR));
return v.color;
}
@@ -359,8 +354,7 @@ static inline lv_color_t lv_obj_get_style_img_recolor(const struct _lv_obj_t * o
static inline lv_color_t lv_obj_get_style_img_recolor_filtered(const struct _lv_obj_t * obj, uint32_t part)
{
lv_style_value_t v = _lv_obj_style_apply_color_filter(obj, part, lv_obj_get_style_prop(obj, part,
LV_STYLE_IMG_RECOLOR));
lv_style_value_t v = _lv_obj_style_apply_color_filter(obj, part, lv_obj_get_style_prop(obj, part, LV_STYLE_IMG_RECOLOR));
return v.color;
}
@@ -514,8 +508,7 @@ static inline lv_opa_t lv_obj_get_style_opa(const struct _lv_obj_t * obj, uint32
return (lv_opa_t)v.num;
}
static inline const lv_color_filter_dsc_t * lv_obj_get_style_color_filter_dsc(const struct _lv_obj_t * obj,
uint32_t part)
static inline const lv_color_filter_dsc_t * lv_obj_get_style_color_filter_dsc(const struct _lv_obj_t * obj, uint32_t part)
{
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_COLOR_FILTER_DSC);
return (const lv_color_filter_dsc_t *)v.ptr;
@@ -644,14 +637,12 @@ void lv_obj_set_style_text_align(struct _lv_obj_t * obj, lv_text_align_t value,
void lv_obj_set_style_radius(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector);
void lv_obj_set_style_clip_corner(struct _lv_obj_t * obj, bool value, lv_style_selector_t selector);
void lv_obj_set_style_opa(struct _lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector);
void lv_obj_set_style_color_filter_dsc(struct _lv_obj_t * obj, const lv_color_filter_dsc_t * value,
lv_style_selector_t selector);
void lv_obj_set_style_color_filter_dsc(struct _lv_obj_t * obj, const lv_color_filter_dsc_t * value, lv_style_selector_t selector);
void lv_obj_set_style_color_filter_opa(struct _lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector);
void lv_obj_set_style_anim(struct _lv_obj_t * obj, const lv_anim_t * value, lv_style_selector_t selector);
void lv_obj_set_style_anim_time(struct _lv_obj_t * obj, uint32_t value, lv_style_selector_t selector);
void lv_obj_set_style_anim_speed(struct _lv_obj_t * obj, uint32_t value, lv_style_selector_t selector);
void lv_obj_set_style_transition(struct _lv_obj_t * obj, const lv_style_transition_dsc_t * value,
lv_style_selector_t selector);
void lv_obj_set_style_transition(struct _lv_obj_t * obj, const lv_style_transition_dsc_t * value, lv_style_selector_t selector);
void lv_obj_set_style_blend_mode(struct _lv_obj_t * obj, lv_blend_mode_t value, lv_style_selector_t selector);
void lv_obj_set_style_layout(struct _lv_obj_t * obj, uint16_t value, lv_style_selector_t selector);
void lv_obj_set_style_base_dir(struct _lv_obj_t * obj, lv_base_dir_t value, lv_style_selector_t selector);

View File

@@ -9,6 +9,8 @@
#include "lv_style.h"
#include "../misc/lv_gc.h"
#include "../misc/lv_mem.h"
#include "lv_assert.h"
#include "lv_types.h"
/*********************
* DEFINES
@@ -22,6 +24,13 @@
* STATIC PROTOTYPES
**********************/
static void lv_style_set_prop_internal(lv_style_t * style, lv_style_prop_t prop_and_meta, lv_style_value_t value,
void (*value_adjustment_helper)(lv_style_prop_t, lv_style_value_t, uint16_t *, lv_style_value_t *));
static void lv_style_set_prop_helper(lv_style_prop_t prop, lv_style_value_t value, uint16_t * prop_storage,
lv_style_value_t * value_storage);
static void lv_style_set_prop_meta_helper(lv_style_prop_t prop, lv_style_value_t value, uint16_t * prop_storage,
lv_style_value_t * value_storage);
/**********************
* GLOBAL VARIABLES
**********************/
@@ -128,6 +137,7 @@ uint32_t _lv_style_custom_prop_flag_lookup_table_size = 0;
**********************/
static uint16_t last_custom_prop_id = (uint16_t)_LV_STYLE_LAST_BUILT_IN_PROP;
static const lv_style_value_t null_style_value = { .num = 0 };
/**********************
* MACROS
@@ -155,7 +165,7 @@ void lv_style_reset(lv_style_t * style)
{
LV_ASSERT_STYLE(style);
if(style->is_const) {
if(style->prop1 == LV_STYLE_PROP_ANY) {
LV_LOG_ERROR("Cannot reset const style");
return;
}
@@ -171,14 +181,22 @@ lv_style_prop_t lv_style_register_prop(uint8_t flag)
{
if(LV_GC_ROOT(_lv_style_custom_prop_flag_lookup_table) == NULL) {
_lv_style_custom_prop_flag_lookup_table_size = 0;
last_custom_prop_id = (uint16_t)_LV_STYLE_LAST_BUILT_IN_PROP;
}
if(((last_custom_prop_id + 1) & LV_STYLE_PROP_META_MASK) != 0) {
LV_LOG_ERROR("No more custom property IDs available");
return LV_STYLE_PROP_INV;
}
/*
* Allocate the lookup table if it's not yet available.
*/
uint8_t required_size = (last_custom_prop_id + 1 - _LV_STYLE_LAST_BUILT_IN_PROP);
size_t required_size = (last_custom_prop_id + 1 - _LV_STYLE_LAST_BUILT_IN_PROP);
if(_lv_style_custom_prop_flag_lookup_table_size < required_size) {
/* Round required_size up to the nearest 32-byte value */
required_size = (required_size + 31) & ~31;
LV_ASSERT_MSG(required_size > 0, "required size has become 0?");
uint8_t * old_p = LV_GC_ROOT(_lv_style_custom_prop_flag_lookup_table);
uint8_t * new_p = lv_mem_realloc(old_p, required_size * sizeof(uint8_t));
if(new_p == NULL) {
@@ -204,7 +222,7 @@ bool lv_style_remove_prop(lv_style_t * style, lv_style_prop_t prop)
{
LV_ASSERT_STYLE(style);
if(style->is_const) {
if(style->prop1 == LV_STYLE_PROP_ANY) {
LV_LOG_ERROR("Cannot remove prop from const style");
return false;
}
@@ -212,7 +230,7 @@ bool lv_style_remove_prop(lv_style_t * style, lv_style_prop_t prop)
if(style->prop_cnt == 0) return false;
if(style->prop_cnt == 1) {
if(style->prop1 == prop) {
if(LV_STYLE_PROP_ID_MASK(style->prop1) == prop) {
style->prop1 = LV_STYLE_PROP_INV;
style->prop_cnt = 0;
return true;
@@ -224,7 +242,7 @@ bool lv_style_remove_prop(lv_style_t * style, lv_style_prop_t prop)
uint16_t * old_props = (uint16_t *)tmp;
uint32_t i;
for(i = 0; i < style->prop_cnt; i++) {
if(old_props[i] == prop) {
if(LV_STYLE_PROP_ID_MASK(old_props[i]) == prop) {
lv_style_value_t * old_values = (lv_style_value_t *)style->v_p.values_and_props;
if(style->prop_cnt == 2) {
@@ -263,78 +281,15 @@ bool lv_style_remove_prop(lv_style_t * style, lv_style_prop_t prop)
void lv_style_set_prop(lv_style_t * style, lv_style_prop_t prop, lv_style_value_t value)
{
LV_ASSERT_STYLE(style);
if(style->is_const) {
LV_LOG_ERROR("Cannot set property of constant style");
return;
}
if(style->prop_cnt > 1) {
uint8_t * tmp = style->v_p.values_and_props + style->prop_cnt * sizeof(lv_style_value_t);
uint16_t * props = (uint16_t *)tmp;
int32_t i;
for(i = style->prop_cnt - 1; i >= 0; i--) {
if(props[i] == prop) {
lv_style_value_t * values = (lv_style_value_t *)style->v_p.values_and_props;
values[i] = value;
return;
}
}
size_t size = (style->prop_cnt + 1) * (sizeof(lv_style_value_t) + sizeof(uint16_t));
uint8_t * values_and_props = lv_mem_realloc(style->v_p.values_and_props, size);
if(values_and_props == NULL) return;
style->v_p.values_and_props = values_and_props;
tmp = values_and_props + style->prop_cnt * sizeof(lv_style_value_t);
props = (uint16_t *)tmp;
/*Shift all props to make place for the value before them*/
for(i = style->prop_cnt - 1; i >= 0; i--) {
props[i + sizeof(lv_style_value_t) / sizeof(uint16_t)] = props[i];
}
style->prop_cnt++;
/*Go to the new position wit the props*/
tmp = values_and_props + style->prop_cnt * sizeof(lv_style_value_t);
props = (uint16_t *)tmp;
lv_style_value_t * values = (lv_style_value_t *)values_and_props;
/*Set the new property and value*/
props[style->prop_cnt - 1] = prop;
values[style->prop_cnt - 1] = value;
}
else if(style->prop_cnt == 1) {
if(style->prop1 == prop) {
style->v_p.value1 = value;
return;
}
size_t size = (style->prop_cnt + 1) * (sizeof(lv_style_value_t) + sizeof(uint16_t));
uint8_t * values_and_props = lv_mem_alloc(size);
if(values_and_props == NULL) return;
lv_style_value_t value_tmp = style->v_p.value1;
style->v_p.values_and_props = values_and_props;
style->prop_cnt++;
uint8_t * tmp = values_and_props + style->prop_cnt * sizeof(lv_style_value_t);
uint16_t * props = (uint16_t *)tmp;
lv_style_value_t * values = (lv_style_value_t *)values_and_props;
props[0] = style->prop1;
props[1] = prop;
values[0] = value_tmp;
values[1] = value;
}
else {
style->prop_cnt = 1;
style->prop1 = prop;
style->v_p.value1 = value;
}
uint8_t group = _lv_style_get_prop_group(prop);
style->has_group |= 1 << group;
lv_style_set_prop_internal(style, prop, value, lv_style_set_prop_helper);
}
lv_res_t lv_style_get_prop(const lv_style_t * style, lv_style_prop_t prop, lv_style_value_t * value)
void lv_style_set_prop_meta(lv_style_t * style, lv_style_prop_t prop, uint16_t meta)
{
lv_style_set_prop_internal(style, prop | meta, null_style_value, lv_style_set_prop_meta_helper);
}
lv_style_res_t lv_style_get_prop(const lv_style_t * style, lv_style_prop_t prop, lv_style_value_t * value)
{
return lv_style_get_prop_inlined(style, prop, value);
}
@@ -439,3 +394,92 @@ uint8_t _lv_style_prop_lookup_flags(lv_style_prop_t prop)
/**********************
* STATIC FUNCTIONS
**********************/
static void lv_style_set_prop_helper(lv_style_prop_t prop, lv_style_value_t value, uint16_t * prop_storage,
lv_style_value_t * value_storage)
{
*prop_storage = prop;
*value_storage = value;
}
static void lv_style_set_prop_meta_helper(lv_style_prop_t prop, lv_style_value_t value, uint16_t * prop_storage,
lv_style_value_t * value_storage)
{
LV_UNUSED(value);
LV_UNUSED(value_storage);
*prop_storage = prop; /* meta is OR-ed into the prop ID already */
}
static void lv_style_set_prop_internal(lv_style_t * style, lv_style_prop_t prop_and_meta, lv_style_value_t value,
void (*value_adjustment_helper)(lv_style_prop_t, lv_style_value_t, uint16_t *, lv_style_value_t *))
{
LV_ASSERT_STYLE(style);
if(style->prop1 == LV_STYLE_PROP_ANY) {
LV_LOG_ERROR("Cannot set property of constant style");
return;
}
lv_style_prop_t prop_id = LV_STYLE_PROP_ID_MASK(prop_and_meta);
if(style->prop_cnt > 1) {
uint8_t * tmp = style->v_p.values_and_props + style->prop_cnt * sizeof(lv_style_value_t);
uint16_t * props = (uint16_t *)tmp;
int32_t i;
for(i = style->prop_cnt - 1; i >= 0; i--) {
if(LV_STYLE_PROP_ID_MASK(props[i]) == prop_id) {
lv_style_value_t * values = (lv_style_value_t *)style->v_p.values_and_props;
value_adjustment_helper(prop_and_meta, value, &props[i], &values[i]);
return;
}
}
size_t size = (style->prop_cnt + 1) * (sizeof(lv_style_value_t) + sizeof(uint16_t));
uint8_t * values_and_props = lv_mem_realloc(style->v_p.values_and_props, size);
if(values_and_props == NULL) return;
style->v_p.values_and_props = values_and_props;
tmp = values_and_props + style->prop_cnt * sizeof(lv_style_value_t);
props = (uint16_t *)tmp;
/*Shift all props to make place for the value before them*/
for(i = style->prop_cnt - 1; i >= 0; i--) {
props[i + sizeof(lv_style_value_t) / sizeof(uint16_t)] = props[i];
}
style->prop_cnt++;
/*Go to the new position wit the props*/
tmp = values_and_props + style->prop_cnt * sizeof(lv_style_value_t);
props = (uint16_t *)tmp;
lv_style_value_t * values = (lv_style_value_t *)values_and_props;
/*Set the new property and value*/
value_adjustment_helper(prop_and_meta, value, &props[style->prop_cnt - 1], &values[style->prop_cnt - 1]);
}
else if(style->prop_cnt == 1) {
if(LV_STYLE_PROP_ID_MASK(style->prop1) == prop_id) {
value_adjustment_helper(prop_and_meta, value, &style->prop1, &style->v_p.value1);
return;
}
size_t size = (style->prop_cnt + 1) * (sizeof(lv_style_value_t) + sizeof(uint16_t));
uint8_t * values_and_props = lv_mem_alloc(size);
if(values_and_props == NULL) return;
lv_style_value_t value_tmp = style->v_p.value1;
style->v_p.values_and_props = values_and_props;
style->prop_cnt++;
uint8_t * tmp = values_and_props + style->prop_cnt * sizeof(lv_style_value_t);
uint16_t * props = (uint16_t *)tmp;
lv_style_value_t * values = (lv_style_value_t *)values_and_props;
props[0] = style->prop1;
values[0] = value_tmp;
value_adjustment_helper(prop_and_meta, value, &props[1], &values[1]);
}
else {
style->prop_cnt = 1;
value_adjustment_helper(prop_and_meta, value, &style->prop1, &style->v_p.value1);
}
uint8_t group = _lv_style_get_prop_group(prop_id);
style->has_group |= 1 << group;
}

View File

@@ -50,9 +50,9 @@ extern "C" {
LV_EXPORT_CONST_INT(LV_IMG_ZOOM_NONE);
#if LV_USE_ASSERT_STYLE
#define LV_STYLE_CONST_INIT(var_name, prop_array) const lv_style_t var_name = { .sentinel = LV_STYLE_SENTINEL_VALUE, .v_p = { .const_props = prop_array }, .has_group = 0xFF, .is_const = 1 }
#define LV_STYLE_CONST_INIT(var_name, prop_array) const lv_style_t var_name = { .sentinel = LV_STYLE_SENTINEL_VALUE, .v_p = { .const_props = prop_array }, .has_group = 0xFF, .prop1 = LV_STYLE_PROP_ANY }
#else
#define LV_STYLE_CONST_INIT(var_name, prop_array) const lv_style_t var_name = { .v_p = { .const_props = prop_array }, .has_group = 0xFF, .is_const = 1 }
#define LV_STYLE_CONST_INIT(var_name, prop_array) const lv_style_t var_name = { .v_p = { .const_props = prop_array }, .has_group = 0xFF, .prop1 = LV_STYLE_PROP_ANY }
#endif
/** On simple system, don't waste resources on gradients */
@@ -60,6 +60,11 @@ LV_EXPORT_CONST_INT(LV_IMG_ZOOM_NONE);
#define LV_GRADIENT_MAX_STOPS 2
#endif
#define LV_STYLE_PROP_META_INHERIT 0x8000
#define LV_STYLE_PROP_META_INITIAL 0x4000
#define LV_STYLE_PROP_META_MASK (LV_STYLE_PROP_META_INHERIT | LV_STYLE_PROP_META_INITIAL)
#define LV_STYLE_PROP_ID_MASK(prop) ((lv_style_prop_t)((prop) & ~LV_STYLE_PROP_META_MASK))
/**********************
* TYPEDEFS
@@ -264,9 +269,18 @@ typedef enum {
_LV_STYLE_LAST_BUILT_IN_PROP = 111,
_LV_STYLE_NUM_BUILT_IN_PROPS = _LV_STYLE_LAST_BUILT_IN_PROP + 1,
LV_STYLE_PROP_ANY = 0xFFFF
LV_STYLE_PROP_ANY = 0xFFFF,
_LV_STYLE_PROP_CONST = 0xFFFF /* magic value for const styles */
} lv_style_prop_t;
enum {
LV_STYLE_RES_NOT_FOUND,
LV_STYLE_RES_FOUND,
LV_STYLE_RES_INHERIT
};
typedef uint8_t lv_style_res_t;
/**
* Descriptor for style transitions
*/
@@ -305,8 +319,7 @@ typedef struct {
const lv_style_const_prop_t * const_props;
} v_p;
uint16_t prop1 : 15;
uint16_t is_const : 1;
uint16_t prop1;
uint8_t has_group;
uint8_t prop_cnt;
} lv_style_t;
@@ -370,16 +383,13 @@ bool lv_style_remove_prop(lv_style_t * style, lv_style_prop_t prop);
void lv_style_set_prop(lv_style_t * style, lv_style_prop_t prop, lv_style_value_t value);
/**
* Get the value of a property
* @param style pointer to a style
* @param prop the ID of a property
* @param value pointer to a `lv_style_value_t` variable to store the value
* @return LV_RES_INV: the property wasn't found in the style (`value` is unchanged)
* LV_RES_OK: the property was fond, and `value` is set accordingly
* @note For performance reasons there are no sanity check on `style`
* Set a special meta state for a property in a style.
* This function shouldn't be used directly by the user.
* @param style pointer to style
* @param prop the ID of a property (e.g. `LV_STYLE_BG_COLOR`)
* @param meta the meta value to attach to the property in the style
*/
lv_res_t lv_style_get_prop(const lv_style_t * style, lv_style_prop_t prop, lv_style_value_t * value);
void lv_style_set_prop_meta(lv_style_t * style, lv_style_prop_t prop, uint16_t meta);
/**
* Get the value of a property
@@ -389,42 +399,8 @@ lv_res_t lv_style_get_prop(const lv_style_t * style, lv_style_prop_t prop, lv_st
* @return LV_RES_INV: the property wasn't found in the style (`value` is unchanged)
* LV_RES_OK: the property was fond, and `value` is set accordingly
* @note For performance reasons there are no sanity check on `style`
* @note This function is the same as ::lv_style_get_prop but inlined. Use it only on performance critical places
*/
static inline lv_res_t lv_style_get_prop_inlined(const lv_style_t * style, lv_style_prop_t prop,
lv_style_value_t * value)
{
if(style->is_const) {
const lv_style_const_prop_t * const_prop;
for(const_prop = style->v_p.const_props; const_prop->prop != LV_STYLE_PROP_INV; const_prop++) {
if(const_prop->prop == prop) {
*value = const_prop->value;
return LV_RES_OK;
}
}
return LV_RES_INV;
}
if(style->prop_cnt == 0) return LV_RES_INV;
if(style->prop_cnt > 1) {
uint8_t * tmp = style->v_p.values_and_props + style->prop_cnt * sizeof(lv_style_value_t);
uint16_t * props = (uint16_t *)tmp;
uint32_t i;
for(i = 0; i < style->prop_cnt; i++) {
if(props[i] == prop) {
lv_style_value_t * values = (lv_style_value_t *)style->v_p.values_and_props;
*value = values[i];
return LV_RES_OK;
}
}
}
else if(style->prop1 == prop) {
*value = style->v_p.value1;
return LV_RES_OK;
}
return LV_RES_INV;
}
lv_style_res_t lv_style_get_prop(const lv_style_t * style, lv_style_prop_t prop, lv_style_value_t * value);
/**
* Initialize a transition descriptor.
@@ -449,6 +425,64 @@ void lv_style_transition_dsc_init(lv_style_transition_dsc_t * tr, const lv_style
*/
lv_style_value_t lv_style_prop_get_default(lv_style_prop_t prop);
/**
* Get the value of a property
* @param style pointer to a style
* @param prop the ID of a property
* @param value pointer to a `lv_style_value_t` variable to store the value
* @return LV_RES_INV: the property wasn't found in the style (`value` is unchanged)
* LV_RES_OK: the property was fond, and `value` is set accordingly
* @note For performance reasons there are no sanity check on `style`
* @note This function is the same as ::lv_style_get_prop but inlined. Use it only on performance critical places
*/
static inline lv_style_res_t lv_style_get_prop_inlined(const lv_style_t * style, lv_style_prop_t prop,
lv_style_value_t * value)
{
if(style->prop1 == LV_STYLE_PROP_ANY) {
const lv_style_const_prop_t * const_prop;
for(const_prop = style->v_p.const_props; const_prop->prop != LV_STYLE_PROP_INV; const_prop++) {
lv_style_prop_t prop_id = LV_STYLE_PROP_ID_MASK(const_prop->prop);
if(prop_id == prop) {
if(const_prop->prop & LV_STYLE_PROP_META_INHERIT)
return LV_STYLE_RES_INHERIT;
*value = (const_prop->prop & LV_STYLE_PROP_META_INITIAL) ? lv_style_prop_get_default(prop_id) : const_prop->value;
return LV_STYLE_RES_FOUND;
}
}
return LV_STYLE_RES_NOT_FOUND;
}
if(style->prop_cnt == 0) return LV_STYLE_RES_NOT_FOUND;
if(style->prop_cnt > 1) {
uint8_t * tmp = style->v_p.values_and_props + style->prop_cnt * sizeof(lv_style_value_t);
uint16_t * props = (uint16_t *)tmp;
uint32_t i;
for(i = 0; i < style->prop_cnt; i++) {
lv_style_prop_t prop_id = LV_STYLE_PROP_ID_MASK(props[i]);
if(prop_id == prop) {
if(props[i] & LV_STYLE_PROP_META_INHERIT)
return LV_STYLE_RES_INHERIT;
if(props[i] & LV_STYLE_PROP_META_INITIAL)
*value = lv_style_prop_get_default(prop_id);
else {
lv_style_value_t * values = (lv_style_value_t *)style->v_p.values_and_props;
*value = values[i];
}
return LV_STYLE_RES_FOUND;
}
}
}
else if(LV_STYLE_PROP_ID_MASK(style->prop1) == prop) {
if(style->prop1 & LV_STYLE_PROP_META_INHERIT)
return LV_STYLE_RES_INHERIT;
*value = (style->prop1 & LV_STYLE_PROP_META_INITIAL) ? lv_style_prop_get_default(LV_STYLE_PROP_ID_MASK(
style->prop1)) : style->v_p.value1;
return LV_STYLE_RES_FOUND;
}
return LV_STYLE_RES_NOT_FOUND;
}
/**
* Checks if a style is empty (has no properties)
* @param style pointer to a style