diff --git a/src/lv_core/lv_debug.c b/src/lv_core/lv_debug.c index 83071af53..5da0a67b3 100644 --- a/src/lv_core/lv_debug.c +++ b/src/lv_core/lv_debug.c @@ -87,10 +87,10 @@ bool lv_debug_check_style(const lv_style_t * style) if(style == NULL) return true; /*NULL style is still valid*/ #if LV_USE_ASSERT_STYLE - if(style->debug_sentinel != LV_STYLE_DEGUG_SENTINEL_VALUE) { - LV_LOG_WARN("Invalid style (local variable or not initialized?)"); - return false; - } +// if(style->debug_sentinel != LV_STYLE_DEGUG_SENTINEL_VALUE) { +// LV_LOG_WARN("Invalid style (local variable or not initialized?)"); +// return false; +// } #endif return true; diff --git a/src/lv_core/lv_group.c b/src/lv_core/lv_group.c index fc8bfda49..7c7f9cbc8 100644 --- a/src/lv_core/lv_group.c +++ b/src/lv_core/lv_group.c @@ -550,24 +550,24 @@ static void style_mod_def(lv_group_t * group, lv_style_t * style) (void)group; /*Unused*/ #if LV_COLOR_DEPTH != 1 - /*Make the style to be a little bit orange*/ - style->body.border.opa = LV_OPA_COVER; - style->body.border.color = LV_COLOR_ORANGE; - - /*If not transparent or has border then emphasis the border*/ - if(style->body.opa != LV_OPA_TRANSP || style->body.border.width != 0) style->body.border.width = LV_DPI / 20; - - style->body.main_color = lv_color_mix(style->body.main_color, LV_COLOR_ORANGE, LV_OPA_70); - style->body.grad_color = lv_color_mix(style->body.grad_color, LV_COLOR_ORANGE, LV_OPA_70); - style->body.shadow.color = lv_color_mix(style->body.shadow.color, LV_COLOR_ORANGE, LV_OPA_60); - - style->text.color = lv_color_mix(style->text.color, LV_COLOR_ORANGE, LV_OPA_70); - - /*Add some recolor to the images*/ - if(style->image.intense < LV_OPA_MIN) { - style->image.color = LV_COLOR_ORANGE; - style->image.intense = LV_OPA_40; - } +// /*Make the style to be a little bit orange*/ +// style->body.border.opa = LV_OPA_COVER; +// style->body.border.color = LV_COLOR_ORANGE; +// +// /*If not transparent or has border then emphasis the border*/ +// if(style->body.opa != LV_OPA_TRANSP || style->body.border.width != 0) style->body.border.width = LV_DPI / 20; +// +// style->body.main_color = lv_color_mix(style->body.main_color, LV_COLOR_ORANGE, LV_OPA_70); +// style->body.grad_color = lv_color_mix(style->body.grad_color, LV_COLOR_ORANGE, LV_OPA_70); +// style->body.shadow.color = lv_color_mix(style->body.shadow.color, LV_COLOR_ORANGE, LV_OPA_60); +// +// style->text.color = lv_color_mix(style->text.color, LV_COLOR_ORANGE, LV_OPA_70); +// +// /*Add some recolor to the images*/ +// if(style->image.intense < LV_OPA_MIN) { +// style->image.color = LV_COLOR_ORANGE; +// style->image.intense = LV_OPA_40; +// } #else style->body.border.opa = LV_OPA_COVER; style->body.border.color = LV_COLOR_BLACK; @@ -586,24 +586,24 @@ static void style_mod_edit_def(lv_group_t * group, lv_style_t * style) (void)group; /*Unused*/ #if LV_COLOR_DEPTH != 1 - /*Make the style to be a little bit orange*/ - style->body.border.opa = LV_OPA_COVER; - style->body.border.color = LV_COLOR_GREEN; - - /*If not empty or has border then emphasis the border*/ - if(style->body.opa != LV_OPA_TRANSP || style->body.border.width != 0) style->body.border.width = LV_DPI / 20; - - style->body.main_color = lv_color_mix(style->body.main_color, LV_COLOR_GREEN, LV_OPA_70); - style->body.grad_color = lv_color_mix(style->body.grad_color, LV_COLOR_GREEN, LV_OPA_70); - style->body.shadow.color = lv_color_mix(style->body.shadow.color, LV_COLOR_GREEN, LV_OPA_60); - - style->text.color = lv_color_mix(style->text.color, LV_COLOR_GREEN, LV_OPA_70); - - /*Add some recolor to the images*/ - if(style->image.intense < LV_OPA_MIN) { - style->image.color = LV_COLOR_GREEN; - style->image.intense = LV_OPA_40; - } +// /*Make the style to be a little bit orange*/ +// style->body.border.opa = LV_OPA_COVER; +// style->body.border.color = LV_COLOR_GREEN; +// +// /*If not empty or has border then emphasis the border*/ +// if(style->body.opa != LV_OPA_TRANSP || style->body.border.width != 0) style->body.border.width = LV_DPI / 20; +// +// style->body.main_color = lv_color_mix(style->body.main_color, LV_COLOR_GREEN, LV_OPA_70); +// style->body.grad_color = lv_color_mix(style->body.grad_color, LV_COLOR_GREEN, LV_OPA_70); +// style->body.shadow.color = lv_color_mix(style->body.shadow.color, LV_COLOR_GREEN, LV_OPA_60); +// +// style->text.color = lv_color_mix(style->text.color, LV_COLOR_GREEN, LV_OPA_70); +// +// /*Add some recolor to the images*/ +// if(style->image.intense < LV_OPA_MIN) { +// style->image.color = LV_COLOR_GREEN; +// style->image.intense = LV_OPA_40; +// } #else style->body.border.opa = LV_OPA_COVER; diff --git a/src/lv_core/lv_obj.c b/src/lv_core/lv_obj.c index 1d690e78f..c34e30ef7 100644 --- a/src/lv_core/lv_obj.c +++ b/src/lv_core/lv_obj.c @@ -105,7 +105,7 @@ void lv_init(void) #endif /*Init. the sstyles*/ - lv_style_init(); + lv_style_built_in_init(); /*Initialize the screen refresh system*/ lv_refr_init(); @@ -187,9 +187,11 @@ lv_obj_t * lv_obj_create(lv_obj_t * parent, const lv_obj_t * copy) /*Set the default styles*/ lv_theme_t * th = lv_theme_get_current(); if(th) { - new_obj->style_p = th->style.scr; +// new_obj->style_p = th->style.scr; } else { - new_obj->style_p = &lv_style_scr; + lv_style_init(&new_obj->style_local); + new_obj->style_chain.style = &new_obj->style_local; + new_obj->style_chain.next = NULL; } /*Init. user date*/ @@ -279,9 +281,11 @@ lv_obj_t * lv_obj_create(lv_obj_t * parent, const lv_obj_t * copy) /*Set appearance*/ lv_theme_t * th = lv_theme_get_current(); if(th) { - new_obj->style_p = th->style.panel; +// new_obj->style_p = th->style.panel; } else { - new_obj->style_p = &lv_style_plain_color; + lv_style_init(&new_obj->style_local); + new_obj->style_chain.style = &new_obj->style_local; + new_obj->style_chain.next = NULL; } #if LV_USE_EXT_CLICK_AREA == LV_EXT_CLICK_AREA_FULL @@ -365,8 +369,6 @@ lv_obj_t * lv_obj_create(lv_obj_t * parent, const lv_obj_t * copy) new_obj->protect = copy->protect; new_obj->opa_scale = copy->opa_scale; - new_obj->style_p = copy->style_p; - #if LV_USE_GROUP /*Add to the same group*/ if(copy->group_p != NULL) { @@ -1198,20 +1200,47 @@ void lv_obj_set_ext_click_area(lv_obj_t * obj, lv_coord_t left, lv_coord_t right * @param obj pointer to an object * @param style_p pointer to the new style */ -void lv_obj_set_style(lv_obj_t * obj, const lv_style_t * style) +//void lv_obj_set_style(lv_obj_t * obj, const lv_style_t * style) +//{ +// LV_ASSERT_OBJ(obj, LV_OBJX_NAME); +// if(style) { +// LV_ASSERT_STYLE(style); +// } +// +// obj->style_p = style; +// +// /*Send a signal about style change to every children with NULL style*/ +// refresh_children_style(obj); +// +// /*Notify the object about the style change too*/ +// lv_obj_refresh_style(obj); +//} + + +void lv_obj_set_style_color(lv_obj_t * obj, lv_style_property_t prop, lv_color_t color) { - LV_ASSERT_OBJ(obj, LV_OBJX_NAME); - if(style) { - LV_ASSERT_STYLE(style); - } + lv_style_set_color(&obj->style_local, prop, color); +} - obj->style_p = style; +void lv_obj_set_style_value(lv_obj_t * obj, lv_style_property_t prop, lv_style_value_t value) +{ + lv_style_set_value(&obj->style_local, prop, value); +} - /*Send a signal about style change to every children with NULL style*/ - refresh_children_style(obj); +void lv_obj_set_style_opa(lv_obj_t * obj, lv_style_property_t prop, lv_opa_t opa) +{ + lv_style_set_opa(&obj->style_local, prop, opa); +} - /*Notify the object about the style change too*/ - lv_obj_refresh_style(obj); +void lv_obj_add_style_class(lv_obj_t * obj, lv_style_t * style) +{ + lv_obj_style_chian_t * s = lv_mem_alloc(sizeof(lv_obj_style_chian_t)); + s->style = style; + + /* Insert the class after the first item. + * (The first style is the local style, and the newest class should came after it.)*/ + s->next = obj->style_chain.next; + obj->style_chain.next = s; } /** @@ -1234,22 +1263,22 @@ void lv_obj_refresh_style(lv_obj_t * obj) */ void lv_obj_report_style_mod(lv_style_t * style) { - LV_ASSERT_STYLE(style); - - lv_disp_t * d = lv_disp_get_next(NULL); - - while(d) { - lv_obj_t * i; - LV_LL_READ(d->scr_ll, i) - { - if(i->style_p == style || style == NULL) { - lv_obj_refresh_style(i); - } - - report_style_mod_core(style, i); - } - d = lv_disp_get_next(d); - } +// LV_ASSERT_STYLE(style); +// +// lv_disp_t * d = lv_disp_get_next(NULL); +// +// while(d) { +// lv_obj_t * i; +// LV_LL_READ(d->scr_ll, i) +// { +// if(i->style_p == style || style == NULL) { +// lv_obj_refresh_style(i); +// } +// +// report_style_mod_core(style, i); +// } +// d = lv_disp_get_next(d); +// } } /*----------------- @@ -1272,7 +1301,7 @@ void lv_obj_set_hidden(lv_obj_t * obj, bool en) if(!obj->hidden) lv_obj_invalidate(obj); /*Invalidate when not hidden (hidden objects are ignored) */ lv_obj_t * par = lv_obj_get_parent(obj); - par->signal_cb(par, LV_SIGNAL_CHILD_CHG, obj); + if(par) par->signal_cb(par, LV_SIGNAL_CHILD_CHG, obj); } /** @@ -1782,14 +1811,16 @@ void lv_obj_get_inner_coords(const lv_obj_t * obj, lv_area_t * coords_p) { LV_ASSERT_OBJ(obj, LV_OBJX_NAME); - const lv_style_t * style = lv_obj_get_style(obj); - if(style->body.border.part & LV_BORDER_PART_LEFT) coords_p->x1 += style->body.border.width; + lv_border_part_t part = lv_obj_get_style_value(obj, LV_STYLE_BORDER_PART); + lv_coord_t w = lv_obj_get_style_value(obj, LV_STYLE_BORDER_WIDTH); - if(style->body.border.part & LV_BORDER_PART_RIGHT) coords_p->x2 -= style->body.border.width; + if(part & LV_BORDER_PART_LEFT) coords_p->x1 += w; - if(style->body.border.part & LV_BORDER_PART_TOP) coords_p->y1 += style->body.border.width; + if(part & LV_BORDER_PART_RIGHT) coords_p->x2 -= w; - if(style->body.border.part & LV_BORDER_PART_BOTTOM) coords_p->y2 -= style->body.border.width; + if(part & LV_BORDER_PART_TOP) coords_p->y1 += w; + + if(part & LV_BORDER_PART_BOTTOM) coords_p->y2 -= w; } /** @@ -1863,9 +1894,10 @@ lv_coord_t lv_obj_get_width_fit(const lv_obj_t * obj) { LV_ASSERT_OBJ(obj, LV_OBJX_NAME); - const lv_style_t * style = lv_obj_get_style(obj); + lv_style_value_t left = lv_obj_get_style_value(obj, LV_STYLE_PAD_LEFT); + lv_style_value_t right = lv_obj_get_style_value(obj, LV_STYLE_PAD_RIGHT); - return lv_obj_get_width(obj) - style->body.padding.left - style->body.padding.right; + return lv_obj_get_width(obj) - left - right; } /** @@ -1877,9 +1909,10 @@ lv_coord_t lv_obj_get_height_fit(const lv_obj_t * obj) { LV_ASSERT_OBJ(obj, LV_OBJX_NAME); - const lv_style_t * style = lv_obj_get_style(obj); + lv_style_value_t top = lv_obj_get_style_value(obj, LV_STYLE_PAD_TOP); + lv_style_value_t bottom = lv_obj_get_style_value(obj, LV_STYLE_PAD_BOTTOM); - return lv_obj_get_height(obj) - style->body.padding.top - style->body.padding.bottom; + return lv_obj_get_height(obj) - top - bottom; } /** @@ -1991,52 +2024,137 @@ lv_coord_t lv_obj_get_ext_draw_pad(const lv_obj_t * obj) * Appearance get *---------------*/ -/** - * Get the style pointer of an object (if NULL get style of the parent) - * @param obj pointer to an object - * @return pointer to a style - */ -const lv_style_t * lv_obj_get_style(const lv_obj_t * obj) + +lv_style_value_t lv_obj_get_style_value(const lv_obj_t * obj, lv_style_property_t prop) { - LV_ASSERT_OBJ(obj, LV_OBJX_NAME); + lv_res_t found = LV_RES_INV; + lv_style_value_t res; - const lv_style_t * style_act = obj->style_p; - if(style_act == NULL) { - lv_obj_t * par = obj->par; + lv_style_attr_t attr; + attr.full= prop >> 8; - while(par) { - if(par->style_p) { - if(par->style_p->glass == 0) { -#if LV_USE_GROUP == 0 - style_act = par->style_p; -#else - /*If a parent is focused then use then focused style*/ - lv_group_t * g = lv_obj_get_group(par); - if(lv_group_get_focused(g) == par) { - style_act = lv_group_mod_style(g, par->style_p); - } else { - style_act = par->style_p; - } -#endif - break; - } - } - par = par->par; - } + const lv_obj_t * parent = obj; + while(parent) { + const lv_obj_style_chian_t * chain = &obj->style_chain; + while(chain) { + found = lv_style_get_value(chain->style, prop, &res); + if(found == LV_RES_OK) { + return res; + } + chain = chain->next; + } + + if(attr.bits.inherit == 0) break; + parent = lv_obj_get_parent(parent); } -#if LV_USE_GROUP - if(obj->group_p) { - if(lv_group_get_focused(obj->group_p) == obj) { - style_act = lv_group_mod_style(obj->group_p, style_act); - } + + switch(prop) { + case LV_STYLE_BORDER_PART: + return LV_BORDER_PART_FULL; } -#endif - if(style_act == NULL) style_act = &lv_style_plain; - - return style_act; + return 0; } +lv_color_t lv_obj_get_style_color(const lv_obj_t * obj, lv_style_property_t prop) +{ + lv_res_t found = LV_RES_INV; + lv_color_t res; + + lv_style_attr_t attr; + attr.full= prop >> 8; + + const lv_obj_t * parent = obj; + while(parent) { + const lv_obj_style_chian_t * chain = &obj->style_chain; + while(chain) { + found = lv_style_get_color(chain->style, prop, &res); + if(found == LV_RES_OK) { + return res; + } + chain = chain->next; + } + + if(attr.bits.inherit == 0) break; + parent = lv_obj_get_parent(parent); + } + + return LV_COLOR_WHITE; +} + +lv_opa_t lv_obj_get_style_opa(const lv_obj_t * obj, lv_style_property_t prop) +{ + lv_res_t found = LV_RES_INV; + lv_opa_t res; + + lv_style_attr_t attr; + attr.full= prop >> 8; + + const lv_obj_t * parent = obj; + while(parent) { + const lv_obj_style_chian_t * chain = &obj->style_chain; + while(chain) { + found = lv_style_get_opa(chain->style, prop, &res); + if(found == LV_RES_OK) { + return res; + } + chain = chain->next; + } + + if(attr.bits.inherit == 0) break; + parent = lv_obj_get_parent(parent); + } + + return LV_OPA_COVER; +} + +// +///** +// * Get the style pointer of an object (if NULL get style of the parent) +// * @param obj pointer to an object +// * @return pointer to a style +// */ +//const lv_style_t * lv_obj_get_style(const lv_obj_t * obj) +//{ +// LV_ASSERT_OBJ(obj, LV_OBJX_NAME); +// +// const lv_style_t * style_act = obj->style_p; +// if(style_act == NULL) { +// lv_obj_t * par = obj->par; +// +// while(par) { +// if(par->style_p) { +// if(par->style_p->glass == 0) { +//#if LV_USE_GROUP == 0 +// style_act = par->style_p; +//#else +// /*If a parent is focused then use then focused style*/ +// lv_group_t * g = lv_obj_get_group(par); +// if(lv_group_get_focused(g) == par) { +// style_act = lv_group_mod_style(g, par->style_p); +// } else { +// style_act = par->style_p; +// } +//#endif +// break; +// } +// } +// par = par->par; +// } +// } +//#if LV_USE_GROUP +// if(obj->group_p) { +// if(lv_group_get_focused(obj->group_p) == obj) { +// style_act = lv_group_mod_style(obj->group_p, style_act); +// } +// } +//#endif +// +// if(style_act == NULL) style_act = &lv_style_plain; +// +// return style_act; +//} + /*----------------- * Attribute get *----------------*/ @@ -2397,6 +2515,31 @@ static void lv_obj_del_async_cb(void * obj) lv_obj_del(obj); } +/** + * Initialize a rectangle descriptor from an object's styles + * @param obj pointer to an object + * @param chain an extra style chain to evaluate before processing the object's styles + * @param dsc the descriptor the initialize + * @note Only the relevant fields will be set. + * E.g. if `border width == 0` the other border properties won't be evaluated. + */ +void lv_obj_init_draw_rect_dsc(lv_obj_t * obj, lv_obj_style_chian_t * chain, lv_draw_rect_dsc_t * dsc) +{ + lv_draw_rect_dsc_init(dsc); + dsc->radius = lv_obj_get_style_value(obj, LV_STYLE_RADIUS); + + dsc->bg_color = lv_obj_get_style_color(obj, LV_STYLE_BG_COLOR); + + dsc->border_width = lv_obj_get_style_value(obj, LV_STYLE_BORDER_WIDTH); + if(dsc->border_width) { + dsc->border_opa = lv_obj_get_style_opa(obj, LV_STYLE_BORDER_OPA); + if(dsc->border_opa >= LV_OPA_MIN) { + dsc->border_part = lv_obj_get_style_value(obj, LV_STYLE_BORDER_PART); + dsc->border_color = lv_obj_get_style_color(obj, LV_STYLE_BORDER_COLOR); + } + } +} + /** * Handle the drawing related tasks of the base objects. * @param obj pointer to an object @@ -2412,15 +2555,17 @@ static lv_design_res_t lv_obj_design(lv_obj_t * obj, const lv_area_t * clip_area /*Most trivial test. Is the mask fully IN the object? If no it surely doesn't cover it*/ if(lv_area_is_in(clip_area, &obj->coords) == false) return LV_DESIGN_RES_NOT_COVER; - const lv_style_t * style = lv_obj_get_style(obj); - if(style->body.corner_mask) return LV_DESIGN_RES_MASKED; + if(lv_obj_get_style_value(obj, LV_STYLE_BG_BLEND_MODE) != LV_BLEND_MODE_NORMAL) return LV_DESIGN_RES_NOT_COVER; + if(lv_obj_get_style_value(obj, LV_STYLE_BORDER_BLEND_MODE) != LV_BLEND_MODE_NORMAL) return LV_DESIGN_RES_NOT_COVER; + + if(lv_obj_get_style_value(obj, LV_STYLE_BG_CLIP_CORNER)) return LV_DESIGN_RES_MASKED; /*Can cover the area only if fully solid (no opacity)*/ - if(style->body.opa < LV_OPA_MAX) return LV_DESIGN_RES_NOT_COVER; + if(lv_obj_get_style_opa(obj, LV_STYLE_BG_OPA) < LV_OPA_MAX) return LV_DESIGN_RES_NOT_COVER; /* Because of the radius it is not sure the area is covered * Check the areas where there is no radius*/ - lv_coord_t r = style->body.radius; + lv_coord_t r = lv_obj_get_style_value(obj, LV_STYLE_RADIUS); if(r == LV_RADIUS_CIRCLE) return LV_DESIGN_RES_NOT_COVER; @@ -2442,20 +2587,23 @@ static lv_design_res_t lv_obj_design(lv_obj_t * obj, const lv_area_t * clip_area } else if(mode == LV_DESIGN_DRAW_MAIN) { - const lv_style_t * style = lv_obj_get_style(obj); - lv_draw_rect(&obj->coords, clip_area, style, lv_obj_get_opa_scale(obj)); + lv_draw_rect_dsc_t draw_dsc; + lv_obj_init_draw_rect_dsc(obj, NULL, &draw_dsc); + lv_draw_rect(&obj->coords, clip_area, &draw_dsc, lv_obj_get_opa_scale(obj)); - if(style->body.corner_mask) { + if(lv_obj_get_style_value(obj, LV_STYLE_BG_CLIP_CORNER)) { lv_draw_mask_radius_param_t * mp = lv_mem_buf_get(sizeof(lv_draw_mask_radius_param_t)); - lv_draw_mask_radius_init(mp, &obj->coords, style->body.radius, false); + lv_coord_t r = lv_obj_get_style_value(obj, LV_STYLE_RADIUS); + + lv_draw_mask_radius_init(mp, &obj->coords, r, false); /*Add the mask and use `obj+8` as custom id. Don't use `obj` directly because it might be used by the user*/ lv_draw_mask_add(mp, obj + 8); } } else if(mode == LV_DESIGN_DRAW_POST) { - const lv_style_t * style = lv_obj_get_style(obj); - if(style->body.corner_mask) { +// const lv_style_t * style = lv_obj_get_style(obj); + if(lv_obj_get_style_value(obj, LV_STYLE_BG_CLIP_CORNER)) { lv_draw_mask_radius_param_t * param = lv_draw_mask_remove_custom(obj + 8); lv_mem_buf_release(param); } @@ -2481,10 +2629,9 @@ static lv_res_t lv_obj_signal(lv_obj_t * obj, lv_signal_t sign, void * param) /*Return 'invalid' if the child change signal is not enabled*/ if(lv_obj_is_protected(obj, LV_PROTECT_CHILD_CHG) != false) res = LV_RES_INV; } else if(sign == LV_SIGNAL_REFR_EXT_DRAW_PAD) { - const lv_style_t * style = lv_obj_get_style(obj); - lv_coord_t shadow = (style->body.shadow.width >> 1) + 1; - shadow += style->body.shadow.spread; - shadow += LV_MATH_MAX(LV_MATH_ABS(style->body.shadow.offset.x), LV_MATH_ABS(style->body.shadow.offset.y)); + lv_coord_t shadow = (lv_obj_get_style_value(obj, LV_STYLE_SHADOW_WIDTH) >> 1) + 1; + shadow += lv_obj_get_style_value(obj, LV_STYLE_SHADOW_SPREAD); + shadow += LV_MATH_MAX(LV_MATH_ABS(lv_obj_get_style_value(obj, LV_STYLE_SHADOW_OFFSET_X)), LV_MATH_ABS(lv_obj_get_style_value(obj, LV_STYLE_SHADOW_OFFSET_Y))); if(shadow > obj->ext_draw_pad) obj->ext_draw_pad = shadow; } else if(sign == LV_SIGNAL_STYLE_CHG) { @@ -2520,16 +2667,16 @@ static void refresh_children_position(lv_obj_t * obj, lv_coord_t x_diff, lv_coor */ static void report_style_mod_core(void * style_p, lv_obj_t * obj) { - lv_obj_t * i; - LV_LL_READ(obj->child_ll, i) - { - if(i->style_p == style_p || style_p == NULL) { - refresh_children_style(i); - lv_obj_refresh_style(i); - } - - report_style_mod_core(style_p, i); - } +// lv_obj_t * i; +// LV_LL_READ(obj->child_ll, i) +// { +// if(i->style.local == style_p || style_p == NULL) { +// refresh_children_style(i); +// lv_obj_refresh_style(i); +// } +// +// report_style_mod_core(style_p, i); +// } } /** @@ -2539,17 +2686,17 @@ static void report_style_mod_core(void * style_p, lv_obj_t * obj) */ static void refresh_children_style(lv_obj_t * obj) { - lv_obj_t * child = lv_obj_get_child(obj, NULL); - while(child != NULL) { - if(child->style_p == NULL) { - refresh_children_style(child); /*Check children too*/ - lv_obj_refresh_style(child); /*Notify the child about the style change*/ - } else if(child->style_p->glass) { - /*Children with 'glass' parent might be effected if their style == NULL*/ - refresh_children_style(child); - } - child = lv_obj_get_child(obj, child); - } +// lv_obj_t * child = lv_obj_get_child(obj, NULL); +// while(child != NULL) { +// if(child->style_p == NULL) { +// refresh_children_style(child); /*Check children too*/ +// lv_obj_refresh_style(child); /*Notify the child about the style change*/ +// } else if(child->style_p->glass) { +// /*Children with 'glass' parent might be effected if their style == NULL*/ +// refresh_children_style(child); +// } +// child = lv_obj_get_child(obj, child); +// } } /** diff --git a/src/lv_core/lv_obj.h b/src/lv_core/lv_obj.h index c976cad6c..d626f3aae 100644 --- a/src/lv_core/lv_obj.h +++ b/src/lv_core/lv_obj.h @@ -187,6 +187,11 @@ typedef struct } lv_reailgn_t; #endif +typedef struct _lv_obj_style_chian_t { + lv_style_t * style; + struct _lv_obj_style_chian_t * next; +}lv_obj_style_chian_t; + typedef struct _lv_obj_t { struct _lv_obj_t * par; /**< Pointer to the parent object*/ @@ -199,7 +204,8 @@ typedef struct _lv_obj_t lv_design_cb_t design_cb; /**< Object type specific design function*/ void * ext_attr; /**< Object type specific extended data*/ - const lv_style_t * style_p; /**< Pointer to the object's style*/ + lv_style_t style_local; + lv_obj_style_chian_t style_chain; #if LV_USE_GROUP != 0 void * group_p; /**< Pointer to the group of the object*/ @@ -442,6 +448,12 @@ void lv_obj_set_ext_click_area(lv_obj_t * obj, lv_coord_t left, lv_coord_t right */ void lv_obj_set_style(lv_obj_t * obj, const lv_style_t * style); +void lv_obj_set_style_color(lv_obj_t * obj, lv_style_property_t prop, lv_color_t color); + +void lv_obj_set_style_value(lv_obj_t * obj, lv_style_property_t prop, lv_style_value_t value); + +void lv_obj_set_style_opa(lv_obj_t * obj, lv_style_property_t prop, lv_opa_t opa); + /** * Notify an object about its style is modified * @param obj pointer to an object @@ -790,12 +802,18 @@ lv_coord_t lv_obj_get_ext_draw_pad(const lv_obj_t * obj); * Appearance get *---------------*/ -/** - * Get the style pointer of an object (if NULL get style of the parent) - * @param obj pointer to an object - * @return pointer to a style - */ -const lv_style_t * lv_obj_get_style(const lv_obj_t * obj); +lv_style_value_t lv_obj_get_style_value(const lv_obj_t * obj, lv_style_property_t prop); + +lv_color_t lv_obj_get_style_color(const lv_obj_t * obj, lv_style_property_t prop); + +lv_opa_t lv_obj_get_style_opa(const lv_obj_t * obj, lv_style_property_t prop); + +///** +// * Get the style pointer of an object (if NULL get style of the parent) +// * @param obj pointer to an object +// * @return pointer to a style +// */ +//const lv_style_t * lv_obj_get_style(const lv_obj_t * obj); /*----------------- * Attribute get diff --git a/src/lv_core/lv_refr.c b/src/lv_core/lv_refr.c index d8d4ce6c0..e37b825d8 100644 --- a/src/lv_core/lv_refr.c +++ b/src/lv_core/lv_refr.c @@ -435,12 +435,8 @@ static lv_obj_t * lv_refr_get_top_obj(const lv_area_t * area_p, lv_obj_t * obj) /*If no better children check this object*/ if(found_p == NULL) { - const lv_style_t * style = lv_obj_get_style(obj); - if(style->body.opa == LV_OPA_COVER && design_res == LV_DESIGN_RES_COVER && - lv_obj_get_opa_scale(obj) == LV_OPA_COVER && - style->body.blend_mode == LV_BLEND_MODE_NORMAL && - style->body.border.blend_mode == LV_BLEND_MODE_NORMAL && - style->image.blend_mode == LV_BLEND_MODE_NORMAL) { + if(lv_obj_get_style_value(obj, LV_STYLE_BG_OPA) == LV_OPA_COVER && design_res == LV_DESIGN_RES_COVER && + lv_obj_get_opa_scale(obj) == LV_OPA_COVER) { found_p = obj; } } diff --git a/src/lv_core/lv_style.c b/src/lv_core/lv_style.c index a2f69ecf5..7ce5bb0ab 100644 --- a/src/lv_core/lv_style.c +++ b/src/lv_core/lv_style.c @@ -25,6 +25,9 @@ res->attr = start->attr; \ } +#define LV_STYLE_PROP_TO_ID(prop) (prop & 0xFF); +#define LV_STYLE_PROP_GET_TYPE(prop) ((prop >> 8) & 0xFF); + /********************** * TYPEDEFS **********************/ @@ -32,6 +35,7 @@ /********************** * STATIC PROTOTYPES **********************/ +static inline int32_t get_property_index(const lv_style_t * style, lv_style_property_t prop); #if LV_USE_ANIMATION static void style_animator(lv_style_anim_dsc_t * dsc, lv_anim_value_t val); static void style_animation_common_end_cb(lv_anim_t * a); @@ -40,19 +44,19 @@ static void style_animation_common_end_cb(lv_anim_t * a); /********************** * STATIC VARIABLES **********************/ -lv_style_t lv_style_scr; -lv_style_t lv_style_transp; -lv_style_t lv_style_transp_fit; -lv_style_t lv_style_transp_tight; -lv_style_t lv_style_plain; -lv_style_t lv_style_plain_color; -lv_style_t lv_style_pretty; -lv_style_t lv_style_pretty_color; -lv_style_t lv_style_btn_rel; -lv_style_t lv_style_btn_pr; -lv_style_t lv_style_btn_tgl_rel; -lv_style_t lv_style_btn_tgl_pr; -lv_style_t lv_style_btn_ina; +//lv_style_t lv_style_scr; +//lv_style_t lv_style_transp; +//lv_style_t lv_style_transp_fit; +//lv_style_t lv_style_transp_tight; +//lv_style_t lv_style_plain; +//lv_style_t lv_style_plain_color; +//lv_style_t lv_style_pretty; +//lv_style_t lv_style_pretty_color; +//lv_style_t lv_style_btn_rel; +//lv_style_t lv_style_btn_pr; +//lv_style_t lv_style_btn_tgl_rel; +//lv_style_t lv_style_btn_tgl_pr; +//lv_style_t lv_style_btn_ina; /********************** * MACROS @@ -63,182 +67,18 @@ lv_style_t lv_style_btn_ina; **********************/ /** - * Init the basic styles + * Init. the built-in styles */ -void lv_style_init(void) +void lv_style_built_in_init(void) { - /* Not White/Black/Gray colors are created by HSV model with - * HUE = 210*/ - /*Screen style*/ - lv_style_scr.glass = 0; - lv_style_scr.body.opa = LV_OPA_COVER; - lv_style_scr.body.main_color = LV_COLOR_WHITE; - lv_style_scr.body.grad_color = LV_COLOR_WHITE; - lv_style_scr.body.main_color_stop = 0; - lv_style_scr.body.grad_color_stop = 255; - lv_style_scr.body.grad_dir = LV_GRAD_DIR_VER; - lv_style_scr.body.radius = 0; - lv_style_scr.body.blend_mode = LV_BLEND_MODE_NORMAL; - lv_style_scr.body.padding.left = 0; - lv_style_scr.body.padding.right = 0; - lv_style_scr.body.padding.top = 0; - lv_style_scr.body.padding.bottom = 0; - lv_style_scr.body.padding.inner = LV_DPI / 20; +} - lv_style_scr.body.border.color = LV_COLOR_BLACK; - lv_style_scr.body.border.opa = LV_OPA_COVER; - lv_style_scr.body.border.width = 0; - lv_style_scr.body.border.part = LV_BORDER_PART_FULL; - lv_style_scr.body.border.blend_mode = LV_BLEND_MODE_NORMAL; - - lv_style_scr.body.shadow.color = LV_COLOR_GRAY; - lv_style_scr.body.shadow.width = 0; - lv_style_scr.body.shadow.opa = LV_OPA_COVER; - lv_style_scr.body.shadow.offset.x = 0; - lv_style_scr.body.shadow.offset.y = 0; - lv_style_scr.body.shadow.spread = 0; - lv_style_scr.body.shadow.blend_mode = LV_BLEND_MODE_NORMAL; - - lv_style_scr.text.opa = LV_OPA_COVER; - lv_style_scr.text.color = lv_color_make(0x30, 0x30, 0x30); - lv_style_scr.text.sel_color = lv_color_make(0x55, 0x96, 0xd8); - lv_style_scr.text.font = LV_FONT_DEFAULT; - lv_style_scr.text.letter_space = 0; - lv_style_scr.text.line_space = 2; - lv_style_scr.text.blend_mode = LV_BLEND_MODE_NORMAL; - lv_style_scr.text.underline = 0; - lv_style_scr.text.strikethrough = 0; - - lv_style_scr.image.opa = LV_OPA_COVER; - lv_style_scr.image.color = lv_color_make(0x20, 0x20, 0x20); - lv_style_scr.image.intense = LV_OPA_TRANSP; - lv_style_scr.image.blend_mode = LV_BLEND_MODE_NORMAL; - - lv_style_scr.line.opa = LV_OPA_COVER; - lv_style_scr.line.color = lv_color_make(0x20, 0x20, 0x20); - lv_style_scr.line.width = 2; - lv_style_scr.line.rounded = 0; - lv_style_scr.line.blend_mode = LV_BLEND_MODE_NORMAL; - -#if LV_USE_DEBUG -#if LV_USE_ASSERT_STYLE - lv_style_scr.debug_sentinel = LV_STYLE_DEGUG_SENTINEL_VALUE; -#endif -#endif - - /*Plain style (by default near the same as the screen style)*/ - lv_style_copy(&lv_style_plain, &lv_style_scr); - lv_style_plain.body.opa = LV_OPA_COVER; - lv_style_plain.body.padding.left = LV_DPI / 20; - lv_style_plain.body.padding.right = LV_DPI / 20; - lv_style_plain.body.padding.top = LV_DPI / 20; - lv_style_plain.body.padding.bottom = LV_DPI / 20; - - /*Plain color style*/ - lv_style_copy(&lv_style_plain_color, &lv_style_plain); - lv_style_plain_color.text.color = lv_color_make(0xf0, 0xf0, 0xf0); - lv_style_plain_color.image.color = lv_color_make(0xf0, 0xf0, 0xf0); - lv_style_plain_color.line.color = lv_color_make(0xf0, 0xf0, 0xf0); - lv_style_plain_color.body.main_color = lv_color_make(0x55, 0x96, 0xd8); - lv_style_plain_color.body.grad_color = lv_style_plain_color.body.main_color; - - /*Pretty style */ - lv_style_copy(&lv_style_pretty, &lv_style_plain); - lv_style_pretty.text.color = lv_color_make(0x20, 0x20, 0x20); - lv_style_pretty.image.color = lv_color_make(0x20, 0x20, 0x20); - lv_style_pretty.line.color = lv_color_make(0x20, 0x20, 0x20); - lv_style_pretty.body.main_color = LV_COLOR_WHITE; - lv_style_pretty.body.grad_color = LV_COLOR_SILVER; - lv_style_pretty.body.radius = LV_DPI / 15; - lv_style_pretty.body.border.color = lv_color_make(0x40, 0x40, 0x40); - lv_style_pretty.body.border.width = LV_DPI / 50 >= 1 ? LV_DPI / 50 : 1; - lv_style_pretty.body.border.opa = LV_OPA_30; - - /*Pretty color style*/ - lv_style_copy(&lv_style_pretty_color, &lv_style_pretty); - lv_style_pretty_color.text.color = lv_color_make(0xe0, 0xe0, 0xe0); - lv_style_pretty_color.image.color = lv_color_make(0xe0, 0xe0, 0xe0); - lv_style_pretty_color.line.color = lv_color_make(0xc0, 0xc0, 0xc0); - lv_style_pretty_color.body.main_color = lv_color_make(0x6b, 0x9a, 0xc7); - lv_style_pretty_color.body.grad_color = lv_color_make(0x2b, 0x59, 0x8b); - lv_style_pretty_color.body.border.color = lv_color_make(0x15, 0x2c, 0x42); - - /*Transparent style*/ - lv_style_copy(&lv_style_transp, &lv_style_plain); - lv_style_transp.glass = 1; - lv_style_transp.body.border.width = 0; - lv_style_transp.body.opa = LV_OPA_TRANSP; - - /*Transparent fitting size*/ - lv_style_copy(&lv_style_transp_fit, &lv_style_transp); - lv_style_transp_fit.body.padding.left = 0; - lv_style_transp_fit.body.padding.right = 0; - lv_style_transp_fit.body.padding.top = 0; - lv_style_transp_fit.body.padding.bottom = 0; - - /*Transparent tight style*/ - lv_style_copy(&lv_style_transp_tight, &lv_style_transp_fit); - lv_style_transp_tight.body.padding.inner = 0; - - /*Button released style*/ - lv_style_copy(&lv_style_btn_rel, &lv_style_plain); - lv_style_btn_rel.body.main_color = lv_color_make(0x76, 0xa2, 0xd0); - lv_style_btn_rel.body.grad_color = lv_color_make(0x19, 0x3a, 0x5d); - lv_style_btn_rel.body.main_color_stop = 0x00; - lv_style_btn_rel.body.grad_color_stop = 0xff;; - lv_style_btn_rel.body.grad_dir = LV_GRAD_DIR_VER; - lv_style_btn_rel.body.radius = LV_DPI / 15; - lv_style_btn_rel.body.opa = LV_OPA_COVER; - lv_style_btn_rel.body.padding.left = LV_DPI / 4; - lv_style_btn_rel.body.padding.right = LV_DPI / 4; - lv_style_btn_rel.body.padding.top = LV_DPI / 6; - lv_style_btn_rel.body.padding.bottom = LV_DPI / 6; - lv_style_btn_rel.body.padding.inner = LV_DPI / 10; - lv_style_btn_rel.body.border.color = lv_color_make(0x0b, 0x19, 0x28); - lv_style_btn_rel.body.border.width = LV_DPI / 50 >= 1 ? LV_DPI / 50 : 1; - lv_style_btn_rel.body.border.opa = LV_OPA_70; - lv_style_btn_rel.body.shadow.color = LV_COLOR_BLACK; - lv_style_btn_rel.body.shadow.width = 0; - lv_style_btn_rel.body.shadow.opa = LV_OPA_COVER; - lv_style_btn_rel.body.shadow.offset.x = 0; - lv_style_btn_rel.body.shadow.offset.y = 0; - lv_style_btn_rel.text.color = lv_color_make(0xff, 0xff, 0xff); - lv_style_btn_rel.image.color = lv_color_make(0xff, 0xff, 0xff); - - /*Button pressed style*/ - lv_style_copy(&lv_style_btn_pr, &lv_style_btn_rel); - lv_style_btn_pr.body.main_color = lv_color_make(0x33, 0x62, 0x94); - lv_style_btn_pr.body.grad_color = lv_color_make(0x10, 0x26, 0x3c); - lv_style_btn_pr.text.color = lv_color_make(0xa4, 0xb5, 0xc6); - lv_style_btn_pr.image.color = lv_color_make(0xa4, 0xb5, 0xc6); - lv_style_btn_pr.line.color = lv_color_make(0xa4, 0xb5, 0xc6); - - /*Button toggle released style*/ - lv_style_copy(&lv_style_btn_tgl_rel, &lv_style_btn_rel); - lv_style_btn_tgl_rel.body.main_color = lv_color_make(0x0a, 0x11, 0x22); - lv_style_btn_tgl_rel.body.grad_color = lv_color_make(0x37, 0x62, 0x90); - lv_style_btn_tgl_rel.body.border.color = lv_color_make(0x01, 0x07, 0x0d); - lv_style_btn_tgl_rel.text.color = lv_color_make(0xc8, 0xdd, 0xf4); - lv_style_btn_tgl_rel.image.color = lv_color_make(0xc8, 0xdd, 0xf4); - lv_style_btn_tgl_rel.line.color = lv_color_make(0xc8, 0xdd, 0xf4); - - /*Button toggle pressed style*/ - lv_style_copy(&lv_style_btn_tgl_pr, &lv_style_btn_tgl_rel); - lv_style_btn_tgl_pr.body.main_color = lv_color_make(0x02, 0x14, 0x27); - lv_style_btn_tgl_pr.body.grad_color = lv_color_make(0x2b, 0x4c, 0x70); - lv_style_btn_tgl_pr.text.color = lv_color_make(0xa4, 0xb5, 0xc6); - lv_style_btn_tgl_pr.image.color = lv_color_make(0xa4, 0xb5, 0xc6); - lv_style_btn_tgl_pr.line.color = lv_color_make(0xa4, 0xb5, 0xc6); - - /*Button inactive style*/ - lv_style_copy(&lv_style_btn_ina, &lv_style_btn_rel); - lv_style_btn_ina.body.main_color = lv_color_make(0xd8, 0xd8, 0xd8); - lv_style_btn_ina.body.grad_color = lv_color_make(0xd8, 0xd8, 0xd8); - lv_style_btn_ina.body.border.color = lv_color_make(0x90, 0x90, 0x90); - lv_style_btn_ina.text.color = lv_color_make(0x70, 0x70, 0x70); - lv_style_btn_ina.image.color = lv_color_make(0x70, 0x70, 0x70); - lv_style_btn_ina.line.color = lv_color_make(0x70, 0x70, 0x70); +void lv_style_init(lv_style_t * style) +{ + style->map = NULL; + style->size = 0; + style->used_groups = 0; } /** @@ -251,6 +91,102 @@ void lv_style_copy(lv_style_t * dest, const lv_style_t * src) memcpy(dest, src, sizeof(lv_style_t)); } +void lv_style_set_value(lv_style_t * style, lv_style_property_t prop, lv_style_value_t value) +{ + int32_t id = get_property_index(style, prop); + /*If exists update the property*/ + if(id >= 0) { + memcpy(style->map + id + sizeof(lv_style_property_t), &value, sizeof(lv_style_value_t)); + } + /*Add new property if not exists yet*/ + else { + style->size += sizeof(lv_style_property_t) + sizeof(lv_style_value_t); + style->map = lv_mem_realloc(style->map, style->size); + LV_ASSERT_MEM(style->map); + if(style->map == NULL) return; + + memcpy(style->map + style->size - (sizeof(lv_style_property_t) + sizeof(lv_style_value_t)), &prop, sizeof(lv_style_property_t)); + memcpy(style->map + style->size - sizeof(lv_style_value_t), &value, sizeof(lv_style_value_t)); + } +} + +void lv_style_set_color(lv_style_t * style, lv_style_property_t prop, lv_color_t color) +{ + int32_t id = get_property_index(style, prop); + /*If exists update the property*/ + if(id >= 0) { + memcpy(style->map + id + sizeof(lv_style_property_t), &color, sizeof(lv_color_t)); + } + /*Add new property if not exists yet*/ + else { + style->size += sizeof(lv_style_property_t) + sizeof(lv_color_t); + style->map = lv_mem_realloc(style->map, style->size); + LV_ASSERT_MEM(style->map); + if(style == NULL) return; + + memcpy(style->map + style->size - (sizeof(lv_style_property_t) + sizeof(lv_color_t)), &prop, sizeof(lv_style_property_t)); + memcpy(style->map + style->size - sizeof(lv_color_t), &color, sizeof(lv_color_t)); + } +} + +void lv_style_set_opa(lv_style_t * style, lv_style_property_t prop, lv_opa_t opa) +{ + int32_t id = get_property_index(style, prop); + /*If exists update the property*/ + if(id >= 0) { + memcpy(style->map + id + sizeof(lv_style_property_t), &opa, sizeof(lv_opa_t)); + } + /*Add new property if not exists yet*/ + else { + style->size += sizeof(lv_style_property_t) + sizeof(lv_opa_t); + style->map = lv_mem_realloc(style->map, style->size); + LV_ASSERT_MEM(style->map); + if(style == NULL) return; + + memcpy(style->map + style->size - (sizeof(lv_style_property_t) + sizeof(lv_opa_t)), &prop, sizeof(lv_style_property_t)); + memcpy(style->map + style->size - sizeof(lv_opa_t), &opa, sizeof(lv_opa_t)); + } +} + + +lv_res_t lv_style_get_value(const lv_style_t * style, lv_style_property_t prop, lv_style_value_t * res) +{ + int32_t id = get_property_index(style, prop); + if(id < 0) { + res = 0; + return LV_RES_INV; + } else { + memcpy(res, &style->map[id + sizeof(lv_style_property_t)], sizeof(lv_style_value_t)); + return LV_RES_OK; + } +} + + +lv_res_t lv_style_get_opa(const lv_style_t * style, lv_style_property_t prop, lv_opa_t * res) +{ + + int32_t id = get_property_index(style, prop); + if(id < 0) { + res = 0; + return LV_RES_INV; + } else { + memcpy(res, &style->map[id + sizeof(lv_style_property_t)], sizeof(lv_opa_t)); + return LV_RES_OK; + } +} + +lv_res_t lv_style_get_color(const lv_style_t * style, lv_style_property_t prop, lv_color_t * res) +{ + int32_t id = get_property_index(style, prop); + if(id < 0) { + res = 0; + return LV_RES_INV; + } else { + memcpy(res, &style->map[id + sizeof(lv_style_property_t)], sizeof(lv_color_t)); + return LV_RES_OK; + } +} + /** * Mix two styles according to a given ratio * @param start start style @@ -260,48 +196,48 @@ void lv_style_copy(lv_style_t * dest, const lv_style_t * src) */ void lv_style_mix(const lv_style_t * start, const lv_style_t * end, lv_style_t * res, uint16_t ratio) { - STYLE_ATTR_MIX(body.opa, ratio); - STYLE_ATTR_MIX(body.radius, ratio); - STYLE_ATTR_MIX(body.border.width, ratio); - STYLE_ATTR_MIX(body.border.opa, ratio); - STYLE_ATTR_MIX(body.shadow.width, ratio); - STYLE_ATTR_MIX(body.shadow.offset.x, ratio); - STYLE_ATTR_MIX(body.shadow.offset.y, ratio); - STYLE_ATTR_MIX(body.shadow.spread, ratio); - STYLE_ATTR_MIX(body.padding.left, ratio); - STYLE_ATTR_MIX(body.padding.right, ratio); - STYLE_ATTR_MIX(body.padding.top, ratio); - STYLE_ATTR_MIX(body.padding.bottom, ratio); - STYLE_ATTR_MIX(body.padding.inner, ratio); - STYLE_ATTR_MIX(text.line_space, ratio); - STYLE_ATTR_MIX(text.letter_space, ratio); - STYLE_ATTR_MIX(text.opa, ratio); - STYLE_ATTR_MIX(line.width, ratio); - STYLE_ATTR_MIX(line.opa, ratio); - STYLE_ATTR_MIX(image.intense, ratio); - STYLE_ATTR_MIX(image.opa, ratio); - - lv_opa_t opa = ratio == STYLE_MIX_MAX ? LV_OPA_COVER : ratio; - - res->body.main_color = lv_color_mix(end->body.main_color, start->body.main_color, opa); - res->body.grad_color = lv_color_mix(end->body.grad_color, start->body.grad_color, opa); - res->body.border.color = lv_color_mix(end->body.border.color, start->body.border.color, opa); - res->body.shadow.color = lv_color_mix(end->body.shadow.color, start->body.shadow.color, opa); - res->text.color = lv_color_mix(end->text.color, start->text.color, opa); - res->image.color = lv_color_mix(end->image.color, start->image.color, opa); - res->line.color = lv_color_mix(end->line.color, start->line.color, opa); - - if(ratio < (STYLE_MIX_MAX >> 1)) { - res->body.border.part = start->body.border.part; - res->glass = start->glass; - res->text.font = start->text.font; - res->line.rounded = start->line.rounded; - } else { - res->body.border.part = end->body.border.part; - res->glass = end->glass; - res->text.font = end->text.font; - res->line.rounded = end->line.rounded; - } +// STYLE_ATTR_MIX(body.opa, ratio); +// STYLE_ATTR_MIX(body.radius, ratio); +// STYLE_ATTR_MIX(body.border.width, ratio); +// STYLE_ATTR_MIX(body.border.opa, ratio); +// STYLE_ATTR_MIX(body.shadow.width, ratio); +// STYLE_ATTR_MIX(body.shadow.offset.x, ratio); +// STYLE_ATTR_MIX(body.shadow.offset.y, ratio); +// STYLE_ATTR_MIX(body.shadow.spread, ratio); +// STYLE_ATTR_MIX(body.padding.left, ratio); +// STYLE_ATTR_MIX(body.padding.right, ratio); +// STYLE_ATTR_MIX(body.padding.top, ratio); +// STYLE_ATTR_MIX(body.padding.bottom, ratio); +// STYLE_ATTR_MIX(body.padding.inner, ratio); +// STYLE_ATTR_MIX(text.line_space, ratio); +// STYLE_ATTR_MIX(text.letter_space, ratio); +// STYLE_ATTR_MIX(text.opa, ratio); +// STYLE_ATTR_MIX(line.width, ratio); +// STYLE_ATTR_MIX(line.opa, ratio); +// STYLE_ATTR_MIX(image.intense, ratio); +// STYLE_ATTR_MIX(image.opa, ratio); +// +// lv_opa_t opa = ratio == STYLE_MIX_MAX ? LV_OPA_COVER : ratio; +// +// res->body.main_color = lv_color_mix(end->body.main_color, start->body.main_color, opa); +// res->body.grad_color = lv_color_mix(end->body.grad_color, start->body.grad_color, opa); +// res->body.border.color = lv_color_mix(end->body.border.color, start->body.border.color, opa); +// res->body.shadow.color = lv_color_mix(end->body.shadow.color, start->body.shadow.color, opa); +// res->text.color = lv_color_mix(end->text.color, start->text.color, opa); +// res->image.color = lv_color_mix(end->image.color, start->image.color, opa); +// res->line.color = lv_color_mix(end->line.color, start->line.color, opa); +// +// if(ratio < (STYLE_MIX_MAX >> 1)) { +// res->body.border.part = start->body.border.part; +// res->glass = start->glass; +// res->text.font = start->text.font; +// res->line.rounded = start->line.rounded; +// } else { +// res->body.border.part = end->body.border.part; +// res->glass = end->glass; +// res->text.font = end->text.font; +// res->line.rounded = end->line.rounded; +// } } #if LV_USE_ANIMATION @@ -340,6 +276,41 @@ void lv_style_anim_set_styles(lv_anim_t * a, lv_style_t * to_anim, const lv_styl /********************** * STATIC FUNCTIONS **********************/ + +static inline int32_t get_property_index(const lv_style_t * style, lv_style_property_t prop) +{ + uint8_t id_to_find = prop & 0xFF; + + size_t i = 0; + while(i < style->size) { + + if(style->map[i] == id_to_find) { + return i; + } else { + lv_style_attr_t attr; + attr.full = style->map[i + 1]; + switch(attr.bits.type) { + case LV_STYLE_ATTR_TYPE_VALUE: + i+= sizeof(lv_style_value_t); + break; + case LV_STYLE_ATTR_TYPE_OPA: + i+= sizeof(lv_opa_t); + break; + case LV_STYLE_ATTR_TYPE_COLOR: + i+= sizeof(lv_color_t); + break; + case LV_STYLE_ATTR_TYPE_PTR: + i+= sizeof(void*); + break; + } + + i += sizeof(lv_style_property_t); + } + } + + return -1; +} + #if LV_USE_ANIMATION /** * Used by the style animations to set the values of a style according to start and end style. diff --git a/src/lv_core/lv_style.h b/src/lv_core/lv_style.h index 58bccb0d1..f96483dae 100644 --- a/src/lv_core/lv_style.h +++ b/src/lv_core/lv_style.h @@ -18,6 +18,7 @@ extern "C" { #include "../lv_misc/lv_color.h" #include "../lv_misc/lv_area.h" #include "../lv_misc/lv_anim.h" +#include "../lv_misc/lv_types.h" #include "../lv_draw/lv_draw_blend.h" /********************* @@ -44,8 +45,6 @@ enum { }; typedef uint8_t lv_border_part_t; - - enum { LV_GRAD_DIR_NONE, LV_GRAD_DIR_VER, @@ -54,100 +53,63 @@ enum { typedef uint8_t lv_grad_dir_t; -/** - * Styles can be assigned to objects - which holds information about - * how the object should be drawn. - * - * This allows for easy customization without having to modify the object's design - * function. - */ -typedef struct -{ - uint8_t glass : 1; /**< 1: Do not inherit this style*/ +#define LV_STYLE_PROP_INIT(name, id, attr) name = (id | ((attr) << 8)) - /** Object background. */ - struct - { - lv_color_t main_color; /**< Object's main background color. */ - lv_color_t grad_color; /**< Second color. If not equal to `main_color` a gradient will be drawn for the background. */ - lv_coord_t radius; /**< Object's corner radius. You can use #LV_RADIUS_CIRCLE if you want to draw a circle. */ - lv_opa_t opa; /**< Object's opacity (0-255). */ - uint8_t main_color_stop; /**< 0..255 proportionally where should the gradient start (the main color stop)*/ - uint8_t grad_color_stop; /**< 0..255 proportionally where should the gradient stop (the grad_color start) */ - lv_blend_mode_t blend_mode :3; - lv_grad_dir_t grad_dir :2; /**< LV_GRAD_DIR_NONE/VER/HOR*/ - uint8_t corner_mask :1; /**< Crop the overflowing content from the rounded corners */ +#define LV_STYLE_ID_MASK 0x00FF - struct - { - lv_color_t color; /**< Border color */ - lv_coord_t width; /**< Border width */ - lv_border_part_t part; /**< Which borders to draw */ - lv_opa_t opa; /**< Border opacity. */ - lv_blend_mode_t blend_mode :3; - } border; +#define LV_STYLE_ATTR_TYPE_OPA (0 << 0) +#define LV_STYLE_ATTR_TYPE_VALUE (1 << 0) +#define LV_STYLE_ATTR_TYPE_COLOR (2 << 0) +#define LV_STYLE_ATTR_TYPE_PTR (3 << 0) +#define LV_STYLE_ATTR_INHERIT (1 << 3) - - struct - { - lv_color_t color; - lv_coord_t width; - lv_coord_t spread; - lv_point_t offset; - lv_opa_t opa; - lv_blend_mode_t blend_mode :3; - } shadow; +#define LV_STYLE_ATTR_FLAGS_MASK (0x7 << 5) - struct - { - lv_coord_t top; - lv_coord_t bottom; - lv_coord_t left; - lv_coord_t right; - lv_coord_t inner; - } padding; - } body; +typedef union { + struct { + uint8_t type :3; + uint8_t inherit :1; /*1: The property can be inherited*/ + uint8_t cached :1; /*1: Not a real property of this style just cached from an other style*/ + uint8_t reserved :3; + }bits; + uint8_t full; +}lv_style_attr_t; - /** Style for text drawn by this object. */ - struct - { - lv_color_t color; /**< Text color */ - lv_color_t sel_color; /**< Text selection background color. */ - const lv_font_t * font; - lv_coord_t letter_space; /**< Space between letters */ - lv_coord_t line_space; /**< Space between lines (vertical) */ - lv_opa_t opa; /**< Text opacity */ - lv_blend_mode_t blend_mode :3; - uint8_t underline :1; - uint8_t strikethrough :1; - } text; +enum { + LV_STYLE_PROP_INIT(LV_STYLE_RADIUS, 0x01, LV_STYLE_ATTR_TYPE_VALUE), + LV_STYLE_PROP_INIT(LV_STYLE_PAD_TOP, 0x04, LV_STYLE_ATTR_TYPE_VALUE), + LV_STYLE_PROP_INIT(LV_STYLE_PAD_BOTTOM, 0x05, LV_STYLE_ATTR_TYPE_VALUE), + LV_STYLE_PROP_INIT(LV_STYLE_PAD_LEFT, 0x06, LV_STYLE_ATTR_TYPE_VALUE), + LV_STYLE_PROP_INIT(LV_STYLE_PAD_RIGHT, 0x07, LV_STYLE_ATTR_TYPE_VALUE), + LV_STYLE_PROP_INIT(LV_STYLE_BG_COLOR, 0x10, LV_STYLE_ATTR_TYPE_COLOR), + LV_STYLE_PROP_INIT(LV_STYLE_BG_OPA, 0x11, LV_STYLE_ATTR_TYPE_OPA), + LV_STYLE_PROP_INIT(LV_STYLE_BG_CLIP_CORNER, 0x12, LV_STYLE_ATTR_TYPE_VALUE), + LV_STYLE_PROP_INIT(LV_STYLE_BG_BLEND_MODE, 0x13, LV_STYLE_ATTR_TYPE_VALUE), + LV_STYLE_PROP_INIT(LV_STYLE_BORDER_COLOR, 0x20, LV_STYLE_ATTR_TYPE_COLOR), + LV_STYLE_PROP_INIT(LV_STYLE_BORDER_OPA, 0x21, LV_STYLE_ATTR_TYPE_OPA), + LV_STYLE_PROP_INIT(LV_STYLE_BORDER_WIDTH, 0x22, LV_STYLE_ATTR_TYPE_VALUE), + LV_STYLE_PROP_INIT(LV_STYLE_BORDER_PART, 0x23, LV_STYLE_ATTR_TYPE_VALUE), + LV_STYLE_PROP_INIT(LV_STYLE_BORDER_BLEND_MODE, 0x24, LV_STYLE_ATTR_TYPE_VALUE), + LV_STYLE_PROP_INIT(LV_STYLE_SHADOW_WIDTH, 0x30, LV_STYLE_ATTR_TYPE_VALUE), + LV_STYLE_PROP_INIT(LV_STYLE_SHADOW_COLOR, 0x31, LV_STYLE_ATTR_TYPE_COLOR), + LV_STYLE_PROP_INIT(LV_STYLE_SHADOW_OFFSET_X, 0x32, LV_STYLE_ATTR_TYPE_VALUE), + LV_STYLE_PROP_INIT(LV_STYLE_SHADOW_OFFSET_Y, 0x33, LV_STYLE_ATTR_TYPE_VALUE), + LV_STYLE_PROP_INIT(LV_STYLE_SHADOW_SPREAD, 0x34, LV_STYLE_ATTR_TYPE_VALUE), + LV_STYLE_PROP_INIT(LV_STYLE_SHADOW_OPA, 0x35, LV_STYLE_ATTR_TYPE_OPA), + LV_STYLE_PROP_INIT(LV_STYLE_TEXT_COLOR, 0x40, LV_STYLE_ATTR_TYPE_COLOR), + LV_STYLE_PROP_INIT(LV_STYLE_LINE_COLOR, 0x50, LV_STYLE_ATTR_TYPE_COLOR), + LV_STYLE_PROP_INIT(LV_STYLE_IMG_COLOR, 0x60, LV_STYLE_ATTR_TYPE_COLOR), +}; - /**< Style of images. */ - struct - { - lv_color_t color; /**< Color to recolor the image with */ - lv_opa_t intense; /**< Opacity of recoloring (0 means no recoloring) */ - lv_opa_t opa; /**< Opacity of whole image */ - lv_blend_mode_t blend_mode :3; - } image; +typedef uint16_t lv_style_property_t; - /**< Style of lines (not borders). */ - struct - { - lv_color_t color; - lv_coord_t width; - lv_opa_t opa; - uint8_t rounded : 1; /**< 1: rounded line endings*/ - lv_blend_mode_t blend_mode :3; - } line; +typedef struct { + uint8_t * map; + uint16_t used_groups; + uint16_t size; +}lv_style_t; -#if LV_USE_DEBUG -#if LV_USE_ASSERT_STYLE - uint32_t debug_sentinel; /**line.width; - circle_style.body.border.color = style->line.color; - circle_style.body.border.opa = style->line.opa; - - lv_draw_mask_angle_param_t mask_angle_param; - lv_draw_mask_angle_init(&mask_angle_param, center_x, center_y, start_angle, end_angle); - - int16_t mask_angle_id = lv_draw_mask_add(&mask_angle_param, NULL); - - lv_area_t area; - area.x1 = center_x - radius; - area.y1 = center_y - radius; - area.x2 = center_x + radius - 1; /*-1 because the center already belongs to the left/bottom part*/ - area.y2 = center_y + radius - 1; - - lv_draw_rect(&area, clip_area, &circle_style, LV_OPA_COVER); - - lv_draw_mask_remove_id(mask_angle_id); - - if(style->line.rounded) { - circle_style.body.main_color = style->line.color; - circle_style.body.grad_color = style->line.color; - circle_style.body.opa = LV_OPA_COVER; - circle_style.body.border.width = 0; - - lv_area_t round_area; - get_rounded_area(start_angle, radius, style->line.width, &round_area); - round_area.x1 += center_x; - round_area.x2 += center_x; - round_area.y1 += center_y; - round_area.y2 += center_y; - - lv_draw_rect(&round_area, clip_area, &circle_style, opa_scale); - - get_rounded_area(end_angle, radius, style->line.width, &round_area); - round_area.x1 += center_x; - round_area.x2 += center_x; - round_area.y1 += center_y; - round_area.y2 += center_y; - - lv_draw_rect(&round_area, clip_area, &circle_style, opa_scale); - } -} - - -/********************** - * STATIC FUNCTIONS - **********************/ - -static void get_rounded_area(int16_t angle, lv_coord_t radius, uint8_t tickness, lv_area_t * res_area) -{ - const uint8_t ps = 8; - const uint8_t pa = 127; - - lv_coord_t thick_half = tickness / 2; - lv_coord_t thick_corr = tickness & 0x01 ? 0 : 1; - - lv_coord_t rx_corr; - lv_coord_t ry_corr; - - if(angle > 90 && angle < 270) rx_corr = 0; - else rx_corr = 0; - - if(angle > 0 && angle < 180) ry_corr = 0; - else ry_corr = 0; - - lv_coord_t cir_x; - lv_coord_t cir_y; - - cir_x = ((radius - rx_corr - thick_half) * lv_trigo_sin(90 - angle)) >> (LV_TRIGO_SHIFT - ps); - cir_y = ((radius - ry_corr - thick_half) * lv_trigo_sin(angle)) >> (LV_TRIGO_SHIFT - ps); - - /* Actually the center of the pixel need to be calculated so apply 1/2 px offset*/ - if(cir_x > 0) { - cir_x = (cir_x - pa) >> ps; - res_area->x1 = cir_x - thick_half + thick_corr; - res_area->x2 = cir_x + thick_half; - } - else { - cir_x = (cir_x + pa) >> ps; - res_area->x1 = cir_x - thick_half; - res_area->x2 = cir_x + thick_half - thick_corr; - } - - if(cir_y > 0) { - cir_y = (cir_y - pa) >> ps; - res_area->y1 = cir_y - thick_half + thick_corr; - res_area->y2 = cir_y + thick_half; - } - else { - cir_y = (cir_y + pa) >> ps; - res_area->y1 = cir_y - thick_half; - res_area->y2 = cir_y + thick_half - thick_corr; - } -} +///** +// * @file lv_draw_arc.c +// * +// */ +// +///********************* +// * INCLUDES +// *********************/ +//#include "lv_draw_arc.h" +//#include "lv_draw_mask.h" +//#include "../lv_misc/lv_math.h" +// +///********************* +// * DEFINES +// *********************/ +// +///********************** +// * TYPEDEFS +// **********************/ +// +///********************** +// * STATIC PROTOTYPES +// **********************/ +//static void get_rounded_area(int16_t angle, lv_coord_t radius, uint8_t tickness, lv_area_t * res_area); +// +///********************** +// * STATIC VARIABLES +// **********************/ +// +///********************** +// * MACROS +// **********************/ +// +///********************** +// * GLOBAL FUNCTIONS +// **********************/ +// +///** +// * Draw an arc. (Can draw pie too with great thickness.) +// * @param center_x the x coordinate of the center of the arc +// * @param center_y the y coordinate of the center of the arc +// * @param radius the radius of the arc +// * @param mask the arc will be drawn only in this mask +// * @param start_angle the start angle of the arc (0 deg on the bottom, 90 deg on the right) +// * @param end_angle the end angle of the arc +// * @param style style of the arc (`body.thickness`, `body.main_color`, `body.opa` is used) +// * @param opa_scale scale down all opacities by the factor +// */ +//void lv_draw_arc(lv_coord_t center_x, lv_coord_t center_y, uint16_t radius, const lv_area_t * clip_area, +// uint16_t start_angle, uint16_t end_angle, const lv_style_t * style, lv_opa_t opa_scale) +//{ +// lv_style_t circle_style; +// lv_style_copy(&circle_style, style); +// circle_style.body.radius = LV_RADIUS_CIRCLE; +// circle_style.body.opa = LV_OPA_TRANSP; +// circle_style.body.border.width = style->line.width; +// circle_style.body.border.color = style->line.color; +// circle_style.body.border.opa = style->line.opa; +// +// lv_draw_mask_angle_param_t mask_angle_param; +// lv_draw_mask_angle_init(&mask_angle_param, center_x, center_y, start_angle, end_angle); +// +// int16_t mask_angle_id = lv_draw_mask_add(&mask_angle_param, NULL); +// +// lv_area_t area; +// area.x1 = center_x - radius; +// area.y1 = center_y - radius; +// area.x2 = center_x + radius - 1; /*-1 because the center already belongs to the left/bottom part*/ +// area.y2 = center_y + radius - 1; +// +// lv_draw_rect(&area, clip_area, &circle_style, LV_OPA_COVER); +// +// lv_draw_mask_remove_id(mask_angle_id); +// +// if(style->line.rounded) { +// circle_style.body.main_color = style->line.color; +// circle_style.body.grad_color = style->line.color; +// circle_style.body.opa = LV_OPA_COVER; +// circle_style.body.border.width = 0; +// +// lv_area_t round_area; +// get_rounded_area(start_angle, radius, style->line.width, &round_area); +// round_area.x1 += center_x; +// round_area.x2 += center_x; +// round_area.y1 += center_y; +// round_area.y2 += center_y; +// +// lv_draw_rect(&round_area, clip_area, &circle_style, opa_scale); +// +// get_rounded_area(end_angle, radius, style->line.width, &round_area); +// round_area.x1 += center_x; +// round_area.x2 += center_x; +// round_area.y1 += center_y; +// round_area.y2 += center_y; +// +// lv_draw_rect(&round_area, clip_area, &circle_style, opa_scale); +// } +//} +// +// +///********************** +// * STATIC FUNCTIONS +// **********************/ +// +//static void get_rounded_area(int16_t angle, lv_coord_t radius, uint8_t tickness, lv_area_t * res_area) +//{ +// const uint8_t ps = 8; +// const uint8_t pa = 127; +// +// lv_coord_t thick_half = tickness / 2; +// lv_coord_t thick_corr = tickness & 0x01 ? 0 : 1; +// +// lv_coord_t rx_corr; +// lv_coord_t ry_corr; +// +// if(angle > 90 && angle < 270) rx_corr = 0; +// else rx_corr = 0; +// +// if(angle > 0 && angle < 180) ry_corr = 0; +// else ry_corr = 0; +// +// lv_coord_t cir_x; +// lv_coord_t cir_y; +// +// cir_x = ((radius - rx_corr - thick_half) * lv_trigo_sin(90 - angle)) >> (LV_TRIGO_SHIFT - ps); +// cir_y = ((radius - ry_corr - thick_half) * lv_trigo_sin(angle)) >> (LV_TRIGO_SHIFT - ps); +// +// /* Actually the center of the pixel need to be calculated so apply 1/2 px offset*/ +// if(cir_x > 0) { +// cir_x = (cir_x - pa) >> ps; +// res_area->x1 = cir_x - thick_half + thick_corr; +// res_area->x2 = cir_x + thick_half; +// } +// else { +// cir_x = (cir_x + pa) >> ps; +// res_area->x1 = cir_x - thick_half; +// res_area->x2 = cir_x + thick_half - thick_corr; +// } +// +// if(cir_y > 0) { +// cir_y = (cir_y - pa) >> ps; +// res_area->y1 = cir_y - thick_half + thick_corr; +// res_area->y2 = cir_y + thick_half; +// } +// else { +// cir_y = (cir_y + pa) >> ps; +// res_area->y1 = cir_y - thick_half; +// res_area->y2 = cir_y + thick_half - thick_corr; +// } +//} diff --git a/src/lv_draw/lv_draw_img.c b/src/lv_draw/lv_draw_img.c index a52537bdb..ea54acd8f 100644 --- a/src/lv_draw/lv_draw_img.c +++ b/src/lv_draw/lv_draw_img.c @@ -57,22 +57,22 @@ static void lv_draw_map(const lv_area_t * map_area, const lv_area_t * clip_area, void lv_draw_img(const lv_area_t * coords, const lv_area_t * mask, const void * src, const lv_style_t * style, uint16_t angle, lv_point_t * center, uint16_t zoom, bool antialias, lv_opa_t opa_scale) { - if(src == NULL) { - LV_LOG_WARN("Image draw: src is NULL"); - lv_draw_rect(coords, mask, &lv_style_plain, LV_OPA_COVER); - lv_draw_label(coords, mask, &lv_style_plain, LV_OPA_COVER, "No\ndata", LV_TXT_FLAG_NONE, NULL, NULL, NULL, LV_BIDI_DIR_LTR); - return; - } - - lv_res_t res; - res = lv_img_draw_core(coords, mask, src, style, angle, center, zoom, antialias, opa_scale); - - if(res == LV_RES_INV) { - LV_LOG_WARN("Image draw error"); - lv_draw_rect(coords, mask, &lv_style_plain, LV_OPA_COVER); - lv_draw_label(coords, mask, &lv_style_plain, LV_OPA_COVER, "No\ndata", LV_TXT_FLAG_NONE, NULL, NULL, NULL, LV_BIDI_DIR_LTR); - return; - } +// if(src == NULL) { +// LV_LOG_WARN("Image draw: src is NULL"); +// lv_draw_rect(coords, mask, &lv_style_plain, LV_OPA_COVER); +// lv_draw_label(coords, mask, &lv_style_plain, LV_OPA_COVER, "No\ndata", LV_TXT_FLAG_NONE, NULL, NULL, NULL, LV_BIDI_DIR_LTR); +// return; +// } +// +// lv_res_t res; +// res = lv_img_draw_core(coords, mask, src, style, angle, center, zoom, antialias, opa_scale); +// +// if(res == LV_RES_INV) { +// LV_LOG_WARN("Image draw error"); +// lv_draw_rect(coords, mask, &lv_style_plain, LV_OPA_COVER); +// lv_draw_label(coords, mask, &lv_style_plain, LV_OPA_COVER, "No\ndata", LV_TXT_FLAG_NONE, NULL, NULL, NULL, LV_BIDI_DIR_LTR); +// return; +// } } /** @@ -194,124 +194,124 @@ lv_img_src_t lv_img_src_get_type(const void * src) static lv_res_t lv_img_draw_core(const lv_area_t * coords, const lv_area_t * mask, const void * src, const lv_style_t * style, uint16_t angle, lv_point_t * pivot, uint16_t zoom, bool antialias, lv_opa_t opa_scale) { - lv_opa_t opa = - opa_scale == LV_OPA_COVER ? style->image.opa : (uint16_t)((uint16_t)style->image.opa * opa_scale) >> 8; - - lv_img_cache_entry_t * cdsc = lv_img_cache_open(src, style); - - if(cdsc == NULL) return LV_RES_INV; - - bool chroma_keyed = lv_img_cf_is_chroma_keyed(cdsc->dec_dsc.header.cf); - bool alpha_byte = lv_img_cf_has_alpha(cdsc->dec_dsc.header.cf); - - if(cdsc->dec_dsc.error_msg != NULL) { - LV_LOG_WARN("Image draw error"); - lv_draw_rect(coords, mask, &lv_style_plain, LV_OPA_COVER); - lv_draw_label(coords, mask, &lv_style_plain, LV_OPA_COVER, cdsc->dec_dsc.error_msg, LV_TXT_FLAG_NONE, NULL, NULL, NULL, LV_BIDI_DIR_LTR); - } - /* The decoder open could open the image and gave the entire uncompressed image. - * Just draw it!*/ - else if(cdsc->dec_dsc.img_data) { - lv_area_t map_area_rot; - lv_area_copy(&map_area_rot, coords); - if(angle || zoom != LV_IMG_ZOOM_NONE) { - /*Get the exact area which is required to show the rotated image*/ - lv_coord_t pivot_x = lv_area_get_width(coords) / 2 + coords->x1; - lv_coord_t pivot_y = lv_area_get_height(coords) / 2 + coords->y1; - - if (pivot){ - pivot_x = pivot->x + coords->x1; - pivot_y = pivot->y + coords->y1; - } - lv_coord_t w = lv_area_get_width(coords); - lv_coord_t w_zoom = (((w * zoom) >> 8) - w) / 2; - lv_coord_t h = lv_area_get_height(coords); - lv_coord_t h_zoom = (((h * zoom) >> 8) - h) / 2; - - lv_area_t norm; - norm.x1 = coords->x1 - pivot_x - w_zoom; - norm.y1 = coords->y1 - pivot_y - h_zoom; - norm.x2 = coords->x2 - pivot_x + w_zoom; - norm.y2 = coords->y2 - pivot_y + h_zoom; - - int16_t sinma = lv_trigo_sin(angle); - int16_t cosma = lv_trigo_sin(angle + 90); - - lv_point_t lt; - lv_point_t rt; - lv_point_t lb; - lv_point_t rb; - lt.x = ((cosma * norm.x1 - sinma * norm.y1) >> (LV_TRIGO_SHIFT)) + pivot_x; - lt.y = ((sinma * norm.x1 + cosma * norm.y1) >> (LV_TRIGO_SHIFT)) + pivot_y; - - rt.x = ((cosma * norm.x2 - sinma * norm.y1) >> (LV_TRIGO_SHIFT)) + pivot_x; - rt.y = ((sinma * norm.x2 + cosma * norm.y1) >> (LV_TRIGO_SHIFT)) + pivot_y; - - lb.x = ((cosma * norm.x1 - sinma * norm.y2) >> (LV_TRIGO_SHIFT)) + pivot_x; - lb.y = ((sinma * norm.x1 + cosma * norm.y2) >> (LV_TRIGO_SHIFT)) + pivot_y; - - rb.x = ((cosma * norm.x2 - sinma * norm.y2) >> (LV_TRIGO_SHIFT)) + pivot_x; - rb.y = ((sinma * norm.x2 + cosma * norm.y2) >> (LV_TRIGO_SHIFT)) + pivot_y; - - map_area_rot.x1 = LV_MATH_MIN(LV_MATH_MIN(LV_MATH_MIN(lb.x, lt.x), rb.x), rt.x); - map_area_rot.x2 = LV_MATH_MAX(LV_MATH_MAX(LV_MATH_MAX(lb.x, lt.x), rb.x), rt.x); - map_area_rot.y1 = LV_MATH_MIN(LV_MATH_MIN(LV_MATH_MIN(lb.y, lt.y), rb.y), rt.y); - map_area_rot.y2 = LV_MATH_MAX(LV_MATH_MAX(LV_MATH_MAX(lb.y, lt.y), rb.y), rt.y); - } - - lv_area_t mask_com; /*Common area of mask and coords*/ - bool union_ok; - union_ok = lv_area_intersect(&mask_com, mask, &map_area_rot); - if(union_ok == false) { - return LV_RES_OK; /*Out of mask. There is nothing to draw so the image is drawn - successfully.*/ - } - - lv_draw_map(coords, &mask_com, cdsc->dec_dsc.img_data, opa, chroma_keyed, alpha_byte, style, angle, pivot, zoom, antialias); - } - /* The whole uncompressed image is not available. Try to read it line-by-line*/ - else { - lv_area_t mask_com; /*Common area of mask and coords*/ - bool union_ok; - union_ok = lv_area_intersect(&mask_com, mask, coords); - if(union_ok == false) { - return LV_RES_OK; /*Out of mask. There is nothing to draw so the image is drawn - successfully.*/ - } - - lv_coord_t width = lv_area_get_width(&mask_com); - - uint8_t * buf = lv_mem_buf_get(lv_area_get_width(&mask_com) * LV_IMG_PX_SIZE_ALPHA_BYTE); /*+1 because of the possible alpha byte*/ - - lv_area_t line; - lv_area_copy(&line, &mask_com); - lv_area_set_height(&line, 1); - lv_coord_t x = mask_com.x1 - coords->x1; - lv_coord_t y = mask_com.y1 - coords->y1; - lv_coord_t row; - lv_res_t read_res; - for(row = mask_com.y1; row <= mask_com.y2; row++) { - lv_area_t mask_line; - union_ok = lv_area_intersect(&mask_line, mask, &line); - if(union_ok == false) continue; - - read_res = lv_img_decoder_read_line(&cdsc->dec_dsc, x, y, width, buf); - if(read_res != LV_RES_OK) { - lv_img_decoder_close(&cdsc->dec_dsc); - LV_LOG_WARN("Image draw can't read the line"); - lv_mem_buf_release(buf); - return LV_RES_INV; - } - - - lv_draw_map(&line, &mask_line, buf, opa, chroma_keyed, alpha_byte, style, 0, NULL, LV_IMG_ZOOM_NONE, false); - line.y1++; - line.y2++; - y++; - } - lv_mem_buf_release(buf); - } - +// lv_opa_t opa = +// opa_scale == LV_OPA_COVER ? style->image.opa : (uint16_t)((uint16_t)style->image.opa * opa_scale) >> 8; +// +// lv_img_cache_entry_t * cdsc = lv_img_cache_open(src, style); +// +// if(cdsc == NULL) return LV_RES_INV; +// +// bool chroma_keyed = lv_img_cf_is_chroma_keyed(cdsc->dec_dsc.header.cf); +// bool alpha_byte = lv_img_cf_has_alpha(cdsc->dec_dsc.header.cf); +// +// if(cdsc->dec_dsc.error_msg != NULL) { +// LV_LOG_WARN("Image draw error"); +// lv_draw_rect(coords, mask, &lv_style_plain, LV_OPA_COVER); +// lv_draw_label(coords, mask, &lv_style_plain, LV_OPA_COVER, cdsc->dec_dsc.error_msg, LV_TXT_FLAG_NONE, NULL, NULL, NULL, LV_BIDI_DIR_LTR); +// } +// /* The decoder open could open the image and gave the entire uncompressed image. +// * Just draw it!*/ +// else if(cdsc->dec_dsc.img_data) { +// lv_area_t map_area_rot; +// lv_area_copy(&map_area_rot, coords); +// if(angle || zoom != LV_IMG_ZOOM_NONE) { +// /*Get the exact area which is required to show the rotated image*/ +// lv_coord_t pivot_x = lv_area_get_width(coords) / 2 + coords->x1; +// lv_coord_t pivot_y = lv_area_get_height(coords) / 2 + coords->y1; +// +// if (pivot){ +// pivot_x = pivot->x + coords->x1; +// pivot_y = pivot->y + coords->y1; +// } +// lv_coord_t w = lv_area_get_width(coords); +// lv_coord_t w_zoom = (((w * zoom) >> 8) - w) / 2; +// lv_coord_t h = lv_area_get_height(coords); +// lv_coord_t h_zoom = (((h * zoom) >> 8) - h) / 2; +// +// lv_area_t norm; +// norm.x1 = coords->x1 - pivot_x - w_zoom; +// norm.y1 = coords->y1 - pivot_y - h_zoom; +// norm.x2 = coords->x2 - pivot_x + w_zoom; +// norm.y2 = coords->y2 - pivot_y + h_zoom; +// +// int16_t sinma = lv_trigo_sin(angle); +// int16_t cosma = lv_trigo_sin(angle + 90); +// +// lv_point_t lt; +// lv_point_t rt; +// lv_point_t lb; +// lv_point_t rb; +// lt.x = ((cosma * norm.x1 - sinma * norm.y1) >> (LV_TRIGO_SHIFT)) + pivot_x; +// lt.y = ((sinma * norm.x1 + cosma * norm.y1) >> (LV_TRIGO_SHIFT)) + pivot_y; +// +// rt.x = ((cosma * norm.x2 - sinma * norm.y1) >> (LV_TRIGO_SHIFT)) + pivot_x; +// rt.y = ((sinma * norm.x2 + cosma * norm.y1) >> (LV_TRIGO_SHIFT)) + pivot_y; +// +// lb.x = ((cosma * norm.x1 - sinma * norm.y2) >> (LV_TRIGO_SHIFT)) + pivot_x; +// lb.y = ((sinma * norm.x1 + cosma * norm.y2) >> (LV_TRIGO_SHIFT)) + pivot_y; +// +// rb.x = ((cosma * norm.x2 - sinma * norm.y2) >> (LV_TRIGO_SHIFT)) + pivot_x; +// rb.y = ((sinma * norm.x2 + cosma * norm.y2) >> (LV_TRIGO_SHIFT)) + pivot_y; +// +// map_area_rot.x1 = LV_MATH_MIN(LV_MATH_MIN(LV_MATH_MIN(lb.x, lt.x), rb.x), rt.x); +// map_area_rot.x2 = LV_MATH_MAX(LV_MATH_MAX(LV_MATH_MAX(lb.x, lt.x), rb.x), rt.x); +// map_area_rot.y1 = LV_MATH_MIN(LV_MATH_MIN(LV_MATH_MIN(lb.y, lt.y), rb.y), rt.y); +// map_area_rot.y2 = LV_MATH_MAX(LV_MATH_MAX(LV_MATH_MAX(lb.y, lt.y), rb.y), rt.y); +// } +// +// lv_area_t mask_com; /*Common area of mask and coords*/ +// bool union_ok; +// union_ok = lv_area_intersect(&mask_com, mask, &map_area_rot); +// if(union_ok == false) { +// return LV_RES_OK; /*Out of mask. There is nothing to draw so the image is drawn +// successfully.*/ +// } +// +// lv_draw_map(coords, &mask_com, cdsc->dec_dsc.img_data, opa, chroma_keyed, alpha_byte, style, angle, pivot, zoom, antialias); +// } +// /* The whole uncompressed image is not available. Try to read it line-by-line*/ +// else { +// lv_area_t mask_com; /*Common area of mask and coords*/ +// bool union_ok; +// union_ok = lv_area_intersect(&mask_com, mask, coords); +// if(union_ok == false) { +// return LV_RES_OK; /*Out of mask. There is nothing to draw so the image is drawn +// successfully.*/ +// } +// +// lv_coord_t width = lv_area_get_width(&mask_com); +// +// uint8_t * buf = lv_mem_buf_get(lv_area_get_width(&mask_com) * LV_IMG_PX_SIZE_ALPHA_BYTE); /*+1 because of the possible alpha byte*/ +// +// lv_area_t line; +// lv_area_copy(&line, &mask_com); +// lv_area_set_height(&line, 1); +// lv_coord_t x = mask_com.x1 - coords->x1; +// lv_coord_t y = mask_com.y1 - coords->y1; +// lv_coord_t row; +// lv_res_t read_res; +// for(row = mask_com.y1; row <= mask_com.y2; row++) { +// lv_area_t mask_line; +// union_ok = lv_area_intersect(&mask_line, mask, &line); +// if(union_ok == false) continue; +// +// read_res = lv_img_decoder_read_line(&cdsc->dec_dsc, x, y, width, buf); +// if(read_res != LV_RES_OK) { +// lv_img_decoder_close(&cdsc->dec_dsc); +// LV_LOG_WARN("Image draw can't read the line"); +// lv_mem_buf_release(buf); +// return LV_RES_INV; +// } +// +// +// lv_draw_map(&line, &mask_line, buf, opa, chroma_keyed, alpha_byte, style, 0, NULL, LV_IMG_ZOOM_NONE, false); +// line.y1++; +// line.y2++; +// y++; +// } +// lv_mem_buf_release(buf); +// } +// return LV_RES_OK; } @@ -332,187 +332,187 @@ static lv_res_t lv_img_draw_core(const lv_area_t * coords, const lv_area_t * mas static void lv_draw_map(const lv_area_t * map_area, const lv_area_t * clip_area, const uint8_t * map_p, lv_opa_t opa, bool chroma_key, bool alpha_byte, const lv_style_t * style, uint16_t angle, lv_point_t * pivot, uint16_t zoom, bool antialaias) { - - if(opa < LV_OPA_MIN) return; - if(opa > LV_OPA_MAX) opa = LV_OPA_COVER; - - /* Use the clip area as draw area*/ - lv_area_t draw_area; - lv_area_copy(&draw_area, clip_area); - - lv_disp_t * disp = lv_refr_get_disp_refreshing(); - lv_disp_buf_t * vdb = lv_disp_get_buf(disp); - const lv_area_t * disp_area = &vdb->area; - - /* Now `draw_area` has absolute coordinates. - * Make it relative to `disp_area` to simplify draw to `disp_buf`*/ - draw_area.x1 -= disp_area->x1; - draw_area.y1 -= disp_area->y1; - draw_area.x2 -= disp_area->x1; - draw_area.y2 -= disp_area->y1; - - uint8_t other_mask_cnt = lv_draw_mask_get_cnt(); - - /*The simplest case just copy the pixels into the VDB*/ - if(other_mask_cnt == 0 && angle == 0 && zoom == LV_IMG_ZOOM_NONE && - chroma_key == false && alpha_byte == false && - opa == LV_OPA_COVER && style->image.intense == LV_OPA_TRANSP) { - lv_blend_map(clip_area, map_area, (lv_color_t *)map_p, NULL, LV_DRAW_MASK_RES_FULL_COVER, LV_OPA_COVER, style->image.blend_mode); - } - /*In the other cases every pixel need to be checked one-by-one*/ - else { - /*The pixel size in byte is different if an alpha byte is added too*/ - uint8_t px_size_byte = alpha_byte ? LV_IMG_PX_SIZE_ALPHA_BYTE : sizeof(lv_color_t); - - /*Build the image and a mask line-by-line*/ - uint32_t mask_buf_size = lv_area_get_size(&draw_area) > LV_HOR_RES_MAX ? LV_HOR_RES_MAX : lv_area_get_size(&draw_area); - lv_color_t * map2 = lv_mem_buf_get(mask_buf_size * sizeof(lv_color_t)); - lv_opa_t * mask_buf = lv_mem_buf_get(mask_buf_size); - - /*Go to the first displayed pixel of the map*/ - lv_coord_t map_w = lv_area_get_width(map_area); - lv_coord_t map_h = lv_area_get_height(map_area); - const uint8_t * map_buf_tmp = map_p; - map_buf_tmp += map_w * (draw_area.y1 - (map_area->y1 - disp_area->y1)) * px_size_byte; - map_buf_tmp += (draw_area.x1 - (map_area->x1 - disp_area->x1)) * px_size_byte; - - lv_color_t c; - lv_color_t chroma_keyed_color = LV_COLOR_TRANSP; - uint32_t px_i = 0; - uint32_t px_i_start; - - const uint8_t * map_px; - - lv_area_t blend_area; - blend_area.x1 = draw_area.x1 + disp_area->x1; - blend_area.x2 = blend_area.x1 + lv_area_get_width(&draw_area) - 1; - blend_area.y1 = disp_area->y1 + draw_area.y1; - blend_area.y2 = blend_area.y1; - - /*Prepare the `mask_buf`if there are other masks*/ - if(other_mask_cnt) { - memset(mask_buf, 0xFF, mask_buf_size); - } - - - bool transform = angle != 0 || zoom != LV_IMG_ZOOM_NONE ? true : false; - lv_img_transform_dsc_t trans_dsc; - memset(&trans_dsc, 0, sizeof(lv_img_transform_dsc_t)); - if(transform) { - lv_img_cf_t cf = LV_IMG_CF_TRUE_COLOR; - if(alpha_byte) cf = LV_IMG_CF_TRUE_COLOR_ALPHA; - else if(chroma_key) cf = LV_IMG_CF_TRUE_COLOR_CHROMA_KEYED; - - - trans_dsc.cfg.angle = angle; - trans_dsc.cfg.zoom = zoom; - trans_dsc.cfg.src = map_p; - trans_dsc.cfg.src_w = map_w; - trans_dsc.cfg.src_h = map_h; - trans_dsc.cfg.cf = cf; - trans_dsc.cfg.pivot_x = map_w / 2; - trans_dsc.cfg.pivot_y = map_h / 2; - if (pivot){ - trans_dsc.cfg.pivot_x = pivot->x; - trans_dsc.cfg.pivot_y = pivot->y; - } - trans_dsc.cfg.color = style->image.color; - trans_dsc.cfg.antialias = antialaias; - - lv_img_buf_transform_init(&trans_dsc); - } - - lv_draw_mask_res_t mask_res; - mask_res = (alpha_byte || chroma_key || angle) ? LV_DRAW_MASK_RES_CHANGED : LV_DRAW_MASK_RES_FULL_COVER; - lv_coord_t x; - lv_coord_t y; - for(y = 0; y < lv_area_get_height(&draw_area); y++) { - map_px = map_buf_tmp; - px_i_start = px_i; - - for(x = 0; x < lv_area_get_width(&draw_area); x++, map_px += px_size_byte, px_i++) { - - if(transform == false) { - if(alpha_byte) { - lv_opa_t px_opa = map_px[LV_IMG_PX_SIZE_ALPHA_BYTE - 1]; - mask_buf[px_i] = px_opa; - if(px_opa < LV_OPA_MIN) continue; - } else { - mask_buf[px_i] = LV_OPA_COVER; - } - -#if LV_COLOR_DEPTH == 8 - c.full = map_px[0]; -#elif LV_COLOR_DEPTH == 16 - c.full = map_px[0] + (map_px[1] << 8); -#elif LV_COLOR_DEPTH == 32 - c.full = *((uint32_t*)map_px); -#endif - if (chroma_key) { - if(c.full == chroma_keyed_color.full) { - mask_buf[px_i] = LV_OPA_TRANSP; - continue; - } - } - } else { - /*Rotate*/ - bool ret; - lv_coord_t rot_x = x + (disp_area->x1 + draw_area.x1) - map_area->x1; - lv_coord_t rot_y = y + (disp_area->y1 + draw_area.y1) - map_area->y1; - ret = lv_img_buf_transform(&trans_dsc, rot_x, rot_y); - if(ret == false) { - mask_buf[px_i] = LV_OPA_TRANSP; - continue; - } else { - mask_buf[px_i] = trans_dsc.res.opa; - c.full = trans_dsc.res.color.full; - } - } - - if(style->image.intense != 0) { - c = lv_color_mix(style->image.color, c, style->image.intense); - } - - map2[px_i].full = c.full; - } - - /*Apply the masks if any*/ - if(other_mask_cnt) { - lv_draw_mask_res_t mask_res_sub; - mask_res_sub = lv_draw_mask_apply(mask_buf + px_i_start, draw_area.x1 + vdb->area.x1, y + draw_area.y1 + vdb->area.y1, lv_area_get_width(&draw_area)); - if(mask_res_sub == LV_DRAW_MASK_RES_FULL_TRANSP) { - memset(mask_buf + px_i_start, 0x00, lv_area_get_width(&draw_area)); - mask_res = LV_DRAW_MASK_RES_CHANGED; - } else if(mask_res_sub == LV_DRAW_MASK_RES_CHANGED) { - mask_res = LV_DRAW_MASK_RES_CHANGED; - } - } - - map_buf_tmp += map_w * px_size_byte; - if(px_i + lv_area_get_width(&draw_area) < mask_buf_size) { - blend_area.y2 ++; - } else { - lv_blend_map(clip_area, &blend_area, map2, mask_buf, mask_res, opa, style->image.blend_mode); - - blend_area.y1 = blend_area.y2 + 1; - blend_area.y2 = blend_area.y1; - - px_i = 0; - mask_res = (alpha_byte || chroma_key || angle) ? LV_DRAW_MASK_RES_CHANGED : LV_DRAW_MASK_RES_FULL_COVER; - - /*Prepare the `mask_buf`if there are other masks*/ - if(other_mask_cnt) { - memset(mask_buf, 0xFF, mask_buf_size); - } - } - } - /*Flush the last part*/ - if(blend_area.y1 != blend_area.y2) { - blend_area.y2--; - lv_blend_map(clip_area, &blend_area, map2, mask_buf, mask_res, opa, style->image.blend_mode); - } - - lv_mem_buf_release(mask_buf); - lv_mem_buf_release(map2); - } +// +// if(opa < LV_OPA_MIN) return; +// if(opa > LV_OPA_MAX) opa = LV_OPA_COVER; +// +// /* Use the clip area as draw area*/ +// lv_area_t draw_area; +// lv_area_copy(&draw_area, clip_area); +// +// lv_disp_t * disp = lv_refr_get_disp_refreshing(); +// lv_disp_buf_t * vdb = lv_disp_get_buf(disp); +// const lv_area_t * disp_area = &vdb->area; +// +// /* Now `draw_area` has absolute coordinates. +// * Make it relative to `disp_area` to simplify draw to `disp_buf`*/ +// draw_area.x1 -= disp_area->x1; +// draw_area.y1 -= disp_area->y1; +// draw_area.x2 -= disp_area->x1; +// draw_area.y2 -= disp_area->y1; +// +// uint8_t other_mask_cnt = lv_draw_mask_get_cnt(); +// +// /*The simplest case just copy the pixels into the VDB*/ +// if(other_mask_cnt == 0 && angle == 0 && zoom == LV_IMG_ZOOM_NONE && +// chroma_key == false && alpha_byte == false && +// opa == LV_OPA_COVER && style->image.intense == LV_OPA_TRANSP) { +// lv_blend_map(clip_area, map_area, (lv_color_t *)map_p, NULL, LV_DRAW_MASK_RES_FULL_COVER, LV_OPA_COVER, style->image.blend_mode); +// } +// /*In the other cases every pixel need to be checked one-by-one*/ +// else { +// /*The pixel size in byte is different if an alpha byte is added too*/ +// uint8_t px_size_byte = alpha_byte ? LV_IMG_PX_SIZE_ALPHA_BYTE : sizeof(lv_color_t); +// +// /*Build the image and a mask line-by-line*/ +// uint32_t mask_buf_size = lv_area_get_size(&draw_area) > LV_HOR_RES_MAX ? LV_HOR_RES_MAX : lv_area_get_size(&draw_area); +// lv_color_t * map2 = lv_mem_buf_get(mask_buf_size * sizeof(lv_color_t)); +// lv_opa_t * mask_buf = lv_mem_buf_get(mask_buf_size); +// +// /*Go to the first displayed pixel of the map*/ +// lv_coord_t map_w = lv_area_get_width(map_area); +// lv_coord_t map_h = lv_area_get_height(map_area); +// const uint8_t * map_buf_tmp = map_p; +// map_buf_tmp += map_w * (draw_area.y1 - (map_area->y1 - disp_area->y1)) * px_size_byte; +// map_buf_tmp += (draw_area.x1 - (map_area->x1 - disp_area->x1)) * px_size_byte; +// +// lv_color_t c; +// lv_color_t chroma_keyed_color = LV_COLOR_TRANSP; +// uint32_t px_i = 0; +// uint32_t px_i_start; +// +// const uint8_t * map_px; +// +// lv_area_t blend_area; +// blend_area.x1 = draw_area.x1 + disp_area->x1; +// blend_area.x2 = blend_area.x1 + lv_area_get_width(&draw_area) - 1; +// blend_area.y1 = disp_area->y1 + draw_area.y1; +// blend_area.y2 = blend_area.y1; +// +// /*Prepare the `mask_buf`if there are other masks*/ +// if(other_mask_cnt) { +// memset(mask_buf, 0xFF, mask_buf_size); +// } +// +// +// bool transform = angle != 0 || zoom != LV_IMG_ZOOM_NONE ? true : false; +// lv_img_transform_dsc_t trans_dsc; +// memset(&trans_dsc, 0, sizeof(lv_img_transform_dsc_t)); +// if(transform) { +// lv_img_cf_t cf = LV_IMG_CF_TRUE_COLOR; +// if(alpha_byte) cf = LV_IMG_CF_TRUE_COLOR_ALPHA; +// else if(chroma_key) cf = LV_IMG_CF_TRUE_COLOR_CHROMA_KEYED; +// +// +// trans_dsc.cfg.angle = angle; +// trans_dsc.cfg.zoom = zoom; +// trans_dsc.cfg.src = map_p; +// trans_dsc.cfg.src_w = map_w; +// trans_dsc.cfg.src_h = map_h; +// trans_dsc.cfg.cf = cf; +// trans_dsc.cfg.pivot_x = map_w / 2; +// trans_dsc.cfg.pivot_y = map_h / 2; +// if (pivot){ +// trans_dsc.cfg.pivot_x = pivot->x; +// trans_dsc.cfg.pivot_y = pivot->y; +// } +// trans_dsc.cfg.color = style->image.color; +// trans_dsc.cfg.antialias = antialaias; +// +// lv_img_buf_transform_init(&trans_dsc); +// } +// +// lv_draw_mask_res_t mask_res; +// mask_res = (alpha_byte || chroma_key || angle) ? LV_DRAW_MASK_RES_CHANGED : LV_DRAW_MASK_RES_FULL_COVER; +// lv_coord_t x; +// lv_coord_t y; +// for(y = 0; y < lv_area_get_height(&draw_area); y++) { +// map_px = map_buf_tmp; +// px_i_start = px_i; +// +// for(x = 0; x < lv_area_get_width(&draw_area); x++, map_px += px_size_byte, px_i++) { +// +// if(transform == false) { +// if(alpha_byte) { +// lv_opa_t px_opa = map_px[LV_IMG_PX_SIZE_ALPHA_BYTE - 1]; +// mask_buf[px_i] = px_opa; +// if(px_opa < LV_OPA_MIN) continue; +// } else { +// mask_buf[px_i] = LV_OPA_COVER; +// } +// +//#if LV_COLOR_DEPTH == 8 +// c.full = map_px[0]; +//#elif LV_COLOR_DEPTH == 16 +// c.full = map_px[0] + (map_px[1] << 8); +//#elif LV_COLOR_DEPTH == 32 +// c.full = *((uint32_t*)map_px); +//#endif +// if (chroma_key) { +// if(c.full == chroma_keyed_color.full) { +// mask_buf[px_i] = LV_OPA_TRANSP; +// continue; +// } +// } +// } else { +// /*Rotate*/ +// bool ret; +// lv_coord_t rot_x = x + (disp_area->x1 + draw_area.x1) - map_area->x1; +// lv_coord_t rot_y = y + (disp_area->y1 + draw_area.y1) - map_area->y1; +// ret = lv_img_buf_transform(&trans_dsc, rot_x, rot_y); +// if(ret == false) { +// mask_buf[px_i] = LV_OPA_TRANSP; +// continue; +// } else { +// mask_buf[px_i] = trans_dsc.res.opa; +// c.full = trans_dsc.res.color.full; +// } +// } +// +// if(style->image.intense != 0) { +// c = lv_color_mix(style->image.color, c, style->image.intense); +// } +// +// map2[px_i].full = c.full; +// } +// +// /*Apply the masks if any*/ +// if(other_mask_cnt) { +// lv_draw_mask_res_t mask_res_sub; +// mask_res_sub = lv_draw_mask_apply(mask_buf + px_i_start, draw_area.x1 + vdb->area.x1, y + draw_area.y1 + vdb->area.y1, lv_area_get_width(&draw_area)); +// if(mask_res_sub == LV_DRAW_MASK_RES_FULL_TRANSP) { +// memset(mask_buf + px_i_start, 0x00, lv_area_get_width(&draw_area)); +// mask_res = LV_DRAW_MASK_RES_CHANGED; +// } else if(mask_res_sub == LV_DRAW_MASK_RES_CHANGED) { +// mask_res = LV_DRAW_MASK_RES_CHANGED; +// } +// } +// +// map_buf_tmp += map_w * px_size_byte; +// if(px_i + lv_area_get_width(&draw_area) < mask_buf_size) { +// blend_area.y2 ++; +// } else { +// lv_blend_map(clip_area, &blend_area, map2, mask_buf, mask_res, opa, style->image.blend_mode); +// +// blend_area.y1 = blend_area.y2 + 1; +// blend_area.y2 = blend_area.y1; +// +// px_i = 0; +// mask_res = (alpha_byte || chroma_key || angle) ? LV_DRAW_MASK_RES_CHANGED : LV_DRAW_MASK_RES_FULL_COVER; +// +// /*Prepare the `mask_buf`if there are other masks*/ +// if(other_mask_cnt) { +// memset(mask_buf, 0xFF, mask_buf_size); +// } +// } +// } +// /*Flush the last part*/ +// if(blend_area.y1 != blend_area.y2) { +// blend_area.y2--; +// lv_blend_map(clip_area, &blend_area, map2, mask_buf, mask_res, opa, style->image.blend_mode); +// } +// +// lv_mem_buf_release(mask_buf); +// lv_mem_buf_release(map2); +// } } diff --git a/src/lv_draw/lv_draw_label.c b/src/lv_draw/lv_draw_label.c index 65a9ccaf1..69ef7a327 100644 --- a/src/lv_draw/lv_draw_label.c +++ b/src/lv_draw/lv_draw_label.c @@ -1,757 +1,757 @@ -/** - * @file lv_draw_label.c - * - */ - -/********************* - * INCLUDES - *********************/ -#include "lv_draw_label.h" -#include "../lv_misc/lv_math.h" -#include "../lv_hal/lv_hal_disp.h" -#include "../lv_core/lv_refr.h" -#include "../lv_misc/lv_bidi.h" - -/********************* - * DEFINES - *********************/ -#define LABEL_RECOLOR_PAR_LENGTH 6 -#define LV_LABEL_HINT_UPDATE_TH 1024 /*Update the "hint" if the label's y coordinates have changed more then this*/ - -/********************** - * TYPEDEFS - **********************/ -enum { - CMD_STATE_WAIT, - CMD_STATE_PAR, - CMD_STATE_IN, -}; -typedef uint8_t cmd_state_t; - -/********************** - * STATIC PROTOTYPES - **********************/ -static void lv_draw_letter(const lv_point_t * pos_p, const lv_area_t * clip_area, const lv_font_t * font_p, uint32_t letter, - lv_color_t color, lv_opa_t opa); -static void draw_letter_normal(lv_coord_t pos_x, lv_coord_t pos_y, lv_font_glyph_dsc_t * g, const lv_area_t * clip_area, const uint8_t * map_p, lv_color_t color, lv_opa_t opa); -static void draw_letter_subpx(lv_coord_t pos_x, lv_coord_t pos_y, lv_font_glyph_dsc_t * g, const lv_area_t * clip_area, const uint8_t * map_p, lv_color_t color, lv_opa_t opa); - - -static uint8_t hex_char_to_num(char hex); - -/********************** - * STATIC VARIABLES - **********************/ -/*clang-format off*/ -static const uint8_t bpp1_opa_table[2] = {0, 255}; /*Opacity mapping with bpp = 1 (Just for compatibility)*/ -static const uint8_t bpp2_opa_table[4] = {0, 85, 170, 255}; /*Opacity mapping with bpp = 2*/ -static const uint8_t bpp4_opa_table[16] = {0, 17, 34, 51, /*Opacity mapping with bpp = 4*/ - 68, 85, 102, 119, - 136, 153, 170, 187, - 204, 221, 238, 255}; - /*clang-format on*/ - -/********************** - * MACROS - **********************/ - -/********************** - * GLOBAL FUNCTIONS - **********************/ - -/** - * Write a text - * @param coords coordinates of the label - * @param mask the label will be drawn only in this area - * @param style pointer to a style - * @param opa_scale scale down all opacities by the factor - * @param txt 0 terminated text to write - * @param flag settings for the text from 'txt_flag_t' enum - * @param offset text offset in x and y direction (NULL if unused) - * @param sel make the text selected in the range by drawing a background there - */ -void lv_draw_label(const lv_area_t * coords, const lv_area_t * mask, const lv_style_t * style, lv_opa_t opa_scale, - const char * txt, lv_txt_flag_t flag, lv_point_t * offset, lv_draw_label_txt_sel_t * sel, - lv_draw_label_hint_t * hint, lv_bidi_dir_t bidi_dir) -{ - const lv_font_t * font = style->text.font; - lv_coord_t w; - - /*No need to waste processor time if string is empty*/ - if (txt[0] == '\0') return; - - if((flag & LV_TXT_FLAG_EXPAND) == 0) { - /*Normally use the label's width as width*/ - w = lv_area_get_width(coords); - } else { - /*If EXAPND is enabled then not limit the text's width to the object's width*/ - lv_point_t p; - lv_txt_get_size(&p, txt, style->text.font, style->text.letter_space, style->text.line_space, LV_COORD_MAX, - flag); - w = p.x; - } - - lv_coord_t line_height = lv_font_get_line_height(font) + style->text.line_space; - - /*Init variables for the first line*/ - lv_coord_t line_width = 0; - lv_point_t pos; - pos.x = coords->x1; - pos.y = coords->y1; - - lv_coord_t x_ofs = 0; - lv_coord_t y_ofs = 0; - if(offset != NULL) { - x_ofs = offset->x; - y_ofs = offset->y; - pos.y += y_ofs; - } - - uint32_t line_start = 0; - int32_t last_line_start = -1; - - /*Check the hint to use the cached info*/ - if(hint && y_ofs == 0 && coords->y1 < 0) { - /*If the label changed too much recalculate the hint.*/ - if(LV_MATH_ABS(hint->coord_y - coords->y1) > LV_LABEL_HINT_UPDATE_TH - 2 * line_height) { - hint->line_start = -1; - } - last_line_start = hint->line_start; - } - - /*Use the hint if it's valid*/ - if(hint && last_line_start >= 0) { - line_start = last_line_start; - pos.y += hint->y; - } - - - uint32_t line_end = line_start + lv_txt_get_next_line(&txt[line_start], font, style->text.letter_space, w, flag); - - /*Go the first visible line*/ - while(pos.y + line_height < mask->y1) { - /*Go to next line*/ - line_start = line_end; - line_end += lv_txt_get_next_line(&txt[line_start], font, style->text.letter_space, w, flag); - pos.y += line_height; - - /*Save at the threshold coordinate*/ - if(hint && pos.y >= -LV_LABEL_HINT_UPDATE_TH && hint->line_start < 0) { - hint->line_start = line_start; - hint->y = pos.y - coords->y1; - hint->coord_y = coords->y1; - } - - if(txt[line_start] == '\0') return; - } - - /*Align to middle*/ - if(flag & LV_TXT_FLAG_CENTER) { - line_width = lv_txt_get_width(&txt[line_start], line_end - line_start, font, style->text.letter_space, flag); - - pos.x += (lv_area_get_width(coords) - line_width) / 2; - - } - /*Align to the right*/ - else if(flag & LV_TXT_FLAG_RIGHT) { - line_width = lv_txt_get_width(&txt[line_start], line_end - line_start, font, style->text.letter_space, flag); - pos.x += lv_area_get_width(coords) - line_width; - } - - lv_opa_t opa = opa_scale == LV_OPA_COVER ? style->text.opa : (uint16_t)((uint16_t)style->text.opa * opa_scale) >> 8; - - uint16_t sel_start = 0xFFFF; - uint16_t sel_end = 0xFFFF; - if(sel) { - sel_start = sel->start; - sel_end = sel->end; - if(sel_start > sel_end) { - uint16_t tmp = sel_start; - sel_start = sel_end; - sel_end = tmp; - } - } - - lv_style_t line_style; - if(style->text.underline || style->text.strikethrough) { - lv_style_copy(&line_style, style); - line_style.line.color = style->text.color; - line_style.line.width = (style->text.font->line_height + 5) / 10; /*+5 for rounding*/ - line_style.line.opa = style->text.opa; - line_style.line.blend_mode = style->text.blend_mode; - } - - cmd_state_t cmd_state = CMD_STATE_WAIT; - uint32_t i; - uint16_t par_start = 0; - lv_color_t recolor; - lv_coord_t letter_w; - lv_style_t sel_style; - lv_style_copy(&sel_style, &lv_style_plain_color); - sel_style.body.main_color = sel_style.body.grad_color = style->text.sel_color; - lv_coord_t pos_x_start = pos.x; - /*Write out all lines*/ - while(txt[line_start] != '\0') { - if(offset != NULL) pos.x += x_ofs; - - /*Write all letter of a line*/ - cmd_state = CMD_STATE_WAIT; - i = 0; - uint32_t letter; - uint32_t letter_next; -#if LV_USE_BIDI - char *bidi_txt = lv_mem_buf_get(line_end - line_start + 1); - lv_bidi_process_paragraph(txt + line_start, bidi_txt, line_end - line_start, bidi_dir, NULL, 0); -#else - const char *bidi_txt = txt + line_start; -#endif - - while(i < line_end - line_start) { - uint16_t logical_char_pos = 0; - if(sel_start != 0xFFFF && sel_end != 0xFFFF) { -#if LV_USE_BIDI - logical_char_pos = lv_txt_encoded_get_char_id(txt, line_start); - uint16_t t = lv_txt_encoded_get_char_id(bidi_txt, i); - logical_char_pos += lv_bidi_get_logical_pos(bidi_txt, NULL, line_end - line_start, bidi_dir, t, NULL); -#else - logical_char_pos = lv_txt_encoded_get_char_id(txt, line_start + i); -#endif - } - - letter = lv_txt_encoded_next(bidi_txt, &i); - letter_next = lv_txt_encoded_next(&bidi_txt[i], NULL); - - - /*Handle the re-color command*/ - if((flag & LV_TXT_FLAG_RECOLOR) != 0) { - if(letter == (uint32_t)LV_TXT_COLOR_CMD[0]) { - if(cmd_state == CMD_STATE_WAIT) { /*Start char*/ - par_start = i; - cmd_state = CMD_STATE_PAR; - continue; - } else if(cmd_state == CMD_STATE_PAR) { /*Other start char in parameter escaped cmd. char */ - cmd_state = CMD_STATE_WAIT; - } else if(cmd_state == CMD_STATE_IN) { /*Command end */ - cmd_state = CMD_STATE_WAIT; - continue; - } - } - - /*Skip the color parameter and wait the space after it*/ - if(cmd_state == CMD_STATE_PAR) { - if(letter == ' ') { - /*Get the parameter*/ - if(i - par_start == LABEL_RECOLOR_PAR_LENGTH + 1) { - char buf[LABEL_RECOLOR_PAR_LENGTH + 1]; - memcpy(buf, &bidi_txt[par_start], LABEL_RECOLOR_PAR_LENGTH); - buf[LABEL_RECOLOR_PAR_LENGTH] = '\0'; - int r, g, b; - r = (hex_char_to_num(buf[0]) << 4) + hex_char_to_num(buf[1]); - g = (hex_char_to_num(buf[2]) << 4) + hex_char_to_num(buf[3]); - b = (hex_char_to_num(buf[4]) << 4) + hex_char_to_num(buf[5]); - recolor = lv_color_make(r, g, b); - } else { - recolor.full = style->text.color.full; - } - cmd_state = CMD_STATE_IN; /*After the parameter the text is in the command*/ - } - continue; - } - } - - lv_color_t color = style->text.color; - - if(cmd_state == CMD_STATE_IN) color = recolor; - - letter_w = lv_font_get_glyph_width(font, letter, letter_next); - - if(sel_start != 0xFFFF && sel_end != 0xFFFF) { - if(logical_char_pos >= sel_start && logical_char_pos < sel_end) { - lv_area_t sel_coords; - sel_coords.x1 = pos.x; - sel_coords.y1 = pos.y; - sel_coords.x2 = pos.x + letter_w + style->text.letter_space - 1; - sel_coords.y2 = pos.y + line_height - 1; - lv_draw_rect(&sel_coords, mask, &sel_style, opa); - } - } - - lv_draw_letter(&pos, mask, font, letter, color, opa); - - if(letter_w > 0) { - pos.x += letter_w + style->text.letter_space; - } - } - - if(style->text.strikethrough) { - lv_point_t p1; - lv_point_t p2; - p1.x = pos_x_start; - p1.y = pos.y + (style->text.font->line_height / 2) + style->line.width / 2; - p2.x = pos.x; - p2.y = p1.y; - lv_draw_line(&p1, &p2, mask, &line_style, opa_scale); - } - - if(style->text.underline) { - lv_point_t p1; - lv_point_t p2; - p1.x = pos_x_start; - p1.y = pos.y + style->text.font->line_height - style->text.font->base_line + style->line.width / 2 + 1; - p2.x = pos.x; - p2.y = p1.y; - lv_draw_line(&p1, &p2, mask, &line_style, opa_scale); - } - -#if LV_USE_BIDI - lv_mem_buf_release(bidi_txt); - bidi_txt = NULL; -#endif - /*Go to next line*/ - line_start = line_end; - line_end += lv_txt_get_next_line(&txt[line_start], font, style->text.letter_space, w, flag); - - pos.x = coords->x1; - /*Align to middle*/ - if(flag & LV_TXT_FLAG_CENTER) { - line_width = - lv_txt_get_width(&txt[line_start], line_end - line_start, font, style->text.letter_space, flag); - - pos.x += (lv_area_get_width(coords) - line_width) / 2; - - } - /*Align to the right*/ - else if(flag & LV_TXT_FLAG_RIGHT) { - line_width = - lv_txt_get_width(&txt[line_start], line_end - line_start, font, style->text.letter_space, flag); - pos.x += lv_area_get_width(coords) - line_width; - } - - /*Go the next line position*/ - pos.y += line_height; - - if(pos.y > mask->y2) return; - } -} - -/********************** - * STATIC FUNCTIONS - **********************/ - - -/** - * Draw a letter in the Virtual Display Buffer - * @param pos_p left-top coordinate of the latter - * @param mask_p the letter will be drawn only on this area (truncated to VDB area) - * @param font_p pointer to font - * @param letter a letter to draw - * @param color color of letter - * @param opa opacity of letter (0..255) - */ -static void lv_draw_letter(const lv_point_t * pos_p, const lv_area_t * clip_area, const lv_font_t * font_p, uint32_t letter, - lv_color_t color, lv_opa_t opa) -{ - if(opa < LV_OPA_MIN) return; - if(opa > LV_OPA_MAX) opa = LV_OPA_COVER; - - if(font_p == NULL) { - LV_LOG_WARN("lv_draw_letter: font is NULL"); - return; - } - - lv_font_glyph_dsc_t g; - bool g_ret = lv_font_get_glyph_dsc(font_p, &g, letter, '\0'); - if(g_ret == false) { - /* Add waring if the dsc is not found - * but do not print warning for non printable ASCII chars (e.g. '\n')*/ - if(letter >= 0x20) { - LV_LOG_WARN("lv_draw_letter: glyph dsc. not found"); - } - return; - } - - lv_coord_t pos_x = pos_p->x + g.ofs_x; - lv_coord_t pos_y = pos_p->y + (font_p->line_height - font_p->base_line) - g.box_h - g.ofs_y; - - /*If the letter is completely out of mask don't draw it */ - if(pos_x + g.box_w < clip_area->x1 || - pos_x > clip_area->x2 || - pos_y + g.box_h < clip_area->y1 || - pos_y > clip_area->y2) return; - - - const uint8_t * map_p = lv_font_get_glyph_bitmap(font_p, letter); - if(map_p == NULL) { - LV_LOG_WARN("lv_draw_letter: character's bitmap not found"); - return; - } - - if(font_p->subpx) { - draw_letter_subpx(pos_x, pos_y, &g, clip_area, map_p, color, opa); - } else { - draw_letter_normal(pos_x, pos_y, &g, clip_area, map_p, color, opa); - } -} - - -static void draw_letter_normal(lv_coord_t pos_x, lv_coord_t pos_y, lv_font_glyph_dsc_t * g, const lv_area_t * clip_area, const uint8_t * map_p, lv_color_t color, lv_opa_t opa) -{ - - const uint8_t * bpp_opa_table; - uint8_t bitmask_init; - uint8_t bitmask; - - if(g->bpp == 3) g->bpp = 4; - - switch(g->bpp) { - case 1: - bpp_opa_table = bpp1_opa_table; - bitmask_init = 0x80; - break; - case 2: - bpp_opa_table = bpp2_opa_table; - bitmask_init = 0xC0; - break; - case 4: - bpp_opa_table = bpp4_opa_table; - bitmask_init = 0xF0; - break; - case 8: - bpp_opa_table = NULL; - bitmask_init = 0xFF; - break; /*No opa table, pixel value will be used directly*/ - default: - LV_LOG_WARN("lv_draw_letter: invalid bpp not found"); - return; /*Invalid bpp. Can't render the letter*/ - } - - - - lv_coord_t col, row; - - uint8_t width_byte_scr = g->box_w >> 3; /*Width in bytes (on the screen finally) (e.g. w = 11 -> 2 bytes wide)*/ - if(g->box_w & 0x7) width_byte_scr++; - uint16_t width_bit = g->box_w * g->bpp; /*Letter width in bits*/ - - - /* Calculate the col/row start/end on the map*/ - lv_coord_t col_start = pos_x >= clip_area->x1 ? 0 : clip_area->x1 - pos_x; - lv_coord_t col_end = pos_x + g->box_w <= clip_area->x2 ? g->box_w : clip_area->x2 - pos_x + 1; - lv_coord_t row_start = pos_y >= clip_area->y1 ? 0 : clip_area->y1 - pos_y; - lv_coord_t row_end = pos_y + g->box_h <= clip_area->y2 ? g->box_h : clip_area->y2 - pos_y + 1; - - /*Move on the map too*/ - uint32_t bit_ofs = (row_start * width_bit) + (col_start * g->bpp); - map_p += bit_ofs >> 3; - - uint8_t letter_px; - lv_opa_t px_opa; - uint16_t col_bit; - col_bit = bit_ofs & 0x7; /* "& 0x7" equals to "% 8" just faster */ - - uint32_t mask_buf_size = g->box_w * g->box_h > LV_HOR_RES_MAX ? g->box_w * g->box_h : LV_HOR_RES_MAX; - lv_opa_t * mask_buf = lv_mem_buf_get(mask_buf_size); - lv_coord_t mask_p = 0; - lv_coord_t mask_p_start; - - lv_area_t fill_area; - fill_area.x1 = col_start + pos_x; - fill_area.x2 = col_end + pos_x - 1; - fill_area.y1 = row_start + pos_y; - fill_area.y2 = fill_area.y1; - - uint8_t other_mask_cnt = lv_draw_mask_get_cnt(); - - for(row = row_start ; row < row_end; row++) { - bitmask = bitmask_init >> col_bit; - mask_p_start = mask_p; - for(col = col_start; col < col_end; col++) { - - /*Load the pixel's opacity into the mask*/ - letter_px = (*map_p & bitmask) >> (8 - col_bit - g->bpp); - if(letter_px != 0) { - if(opa == LV_OPA_COVER) { - px_opa = g->bpp == 8 ? letter_px : bpp_opa_table[letter_px]; - } else { - px_opa = g->bpp == 8 ? (uint16_t)((uint16_t)letter_px * opa) >> 8 - : (uint16_t)((uint16_t)bpp_opa_table[letter_px] * opa) >> 8; - } - - mask_buf[mask_p] = px_opa; - - } else { - mask_buf[mask_p] = 0; - } - - /*Go to the next column*/ - if(col_bit < 8 - g->bpp) { - col_bit += g->bpp; - bitmask = bitmask >> g->bpp; - } else { - col_bit = 0; - bitmask = bitmask_init; - map_p++; - } - - /*Next mask byte*/ - mask_p++; - } - - /*Apply masks if any*/ - if(other_mask_cnt) { - lv_draw_mask_res_t mask_res = lv_draw_mask_apply(mask_buf + mask_p_start, fill_area.x1, fill_area.y2, lv_area_get_width(&fill_area)); - if(mask_res == LV_DRAW_MASK_RES_FULL_TRANSP) { - memset(mask_buf + mask_p_start, 0x00, lv_area_get_width(&fill_area)); - } - } - - if((uint32_t) mask_p + (row_end - row_start) < mask_buf_size) { - fill_area.y2 ++; - } else { - lv_blend_fill(clip_area, &fill_area, - color, mask_buf, LV_DRAW_MASK_RES_CHANGED, opa, - LV_BLEND_MODE_NORMAL); - - fill_area.y1 = fill_area.y2 + 1; - fill_area.y2 = fill_area.y1; - mask_p = 0; - } - - col_bit += ((g->box_w - col_end) + col_start) * g->bpp; - - map_p += (col_bit >> 3); - col_bit = col_bit & 0x7; - } - - /*Flush the last part*/ - if(fill_area.y1 != fill_area.y2) { - fill_area.y2--; - lv_blend_fill(clip_area, &fill_area, - color, mask_buf, LV_DRAW_MASK_RES_CHANGED, opa, - LV_BLEND_MODE_NORMAL); - mask_p = 0; - } - - lv_mem_buf_release(mask_buf); -} - -static void draw_letter_subpx(lv_coord_t pos_x, lv_coord_t pos_y, lv_font_glyph_dsc_t * g, const lv_area_t * clip_area, const uint8_t * map_p, lv_color_t color, lv_opa_t opa) -{ - const uint8_t * bpp_opa_table; - uint8_t bitmask_init; - uint8_t bitmask; - - if(g->bpp == 3) g->bpp = 4; - - switch(g->bpp) { - case 1: - bpp_opa_table = bpp1_opa_table; - bitmask_init = 0x80; - break; - case 2: - bpp_opa_table = bpp2_opa_table; - bitmask_init = 0xC0; - break; - case 4: - bpp_opa_table = bpp4_opa_table; - bitmask_init = 0xF0; - break; - case 8: - bpp_opa_table = NULL; - bitmask_init = 0xFF; - break; /*No opa table, pixel value will be used directly*/ - default: - LV_LOG_WARN("lv_draw_letter: invalid bpp not found"); - return; /*Invalid bpp. Can't render the letter*/ - } - - lv_coord_t col, row; - - uint8_t width_byte_scr = g->box_w >> 3; /*Width in bytes (on the screen finally) (e.g. w = 11 -> 2 bytes wide)*/ - if(g->box_w & 0x7) width_byte_scr++; - uint16_t width_bit = g->box_w * g->bpp; /*Letter width in bits*/ - - - /* Calculate the col/row start/end on the map*/ - lv_coord_t col_start = pos_x >= clip_area->x1 ? 0 : (clip_area->x1 - pos_x) * 3; - lv_coord_t col_end = pos_x + g->box_w / 3 <= clip_area->x2 ? g->box_w : (clip_area->x2 - pos_x + 1) * 3; - lv_coord_t row_start = pos_y >= clip_area->y1 ? 0 : clip_area->y1 - pos_y; - lv_coord_t row_end = pos_y + g->box_h <= clip_area->y2 ? g->box_h : clip_area->y2 - pos_y + 1; - - /*Move on the map too*/ - uint32_t bit_ofs = (row_start * width_bit) + (col_start * g->bpp); - map_p += bit_ofs >> 3; - - uint8_t letter_px; - lv_opa_t px_opa; - uint16_t col_bit; - col_bit = bit_ofs & 0x7; /* "& 0x7" equals to "% 8" just faster */ - - uint32_t mask_buf_size = g->box_w * g->box_h > LV_HOR_RES_MAX ? g->box_w * g->box_h : LV_HOR_RES_MAX; - lv_opa_t * mask_buf = lv_mem_buf_get(mask_buf_size); - lv_coord_t mask_p = 0; - lv_coord_t mask_p_start; - lv_color_t * color_buf = lv_mem_buf_get(mask_buf_size * sizeof(lv_color_t)); - - lv_disp_t * disp = lv_refr_get_disp_refreshing(); - lv_disp_buf_t * vdb = lv_disp_get_buf(disp); - - lv_coord_t vdb_width = lv_area_get_width(&vdb->area); - lv_color_t * vdb_buf_tmp = vdb->buf_act; - - /*Set a pointer on VDB to the first pixel of the letter*/ - vdb_buf_tmp += ((pos_y - vdb->area.y1) * vdb_width) + pos_x - vdb->area.x1; - - /*If the letter is partially out of mask the move there on VDB*/ - vdb_buf_tmp += (row_start * vdb_width) + col_start / 3; - - lv_area_t map_area; - map_area.x1 = col_start / 3 + pos_x; - map_area.x2 = col_end / 3 + pos_x - 1; - map_area.y1 = row_start + pos_y; - map_area.y2 = map_area.y1; - - uint8_t other_mask_cnt = lv_draw_mask_get_cnt(); - - uint8_t font_rgb[3]; - -#if LV_COLOR_16_SWAP == 0 - uint8_t txt_rgb[3] = {color.ch.red, color.ch.green, color.ch.blue}; -#else - uint8_t txt_rgb[3] = {color.ch.red, (color.ch.green_h << 3) + color.ch.green_l, color.ch.blue}; -#endif - - for(row = row_start ; row < row_end; row++) { - uint8_t subpx_cnt = 0; - bitmask = bitmask_init >> col_bit; - mask_p_start = mask_p; - for(col = col_start; col < col_end; col++) { - /*Load the pixel's opacity into the mask*/ - letter_px = (*map_p & bitmask) >> (8 - col_bit - g->bpp); - if(letter_px != 0) { - if(opa == LV_OPA_COVER) { - px_opa = g->bpp == 8 ? letter_px : bpp_opa_table[letter_px]; - } else { - px_opa = g->bpp == 8 ? (uint16_t)((uint16_t)letter_px * opa) >> 8 - : (uint16_t)((uint16_t)bpp_opa_table[letter_px] * opa) >> 8; - } - } else { - px_opa = 0; - } - - font_rgb[subpx_cnt] = px_opa; - - subpx_cnt ++; - if(subpx_cnt == 3) { - subpx_cnt = 0; - - lv_color_t res_color; -#if LV_COLOR_16_SWAP == 0 - uint8_t bg_rgb[3] = {vdb_buf_tmp->ch.red, vdb_buf_tmp->ch.green, vdb_buf_tmp->ch.blue}; -#else - uint8_t bg_rgb[3] = {vdb_buf_tmp->ch.red, - (vdb_buf_tmp->ch.green_h << 3) + vdb_buf_tmp->ch.green_l, - vdb_buf_tmp->ch.blue}; -#endif - -#if LV_SUBPX_BGR - res_color.ch.blue = (uint16_t)((uint16_t)txt_rgb[0] * font_rgb[0] + (bg_rgb[0] * (255 - font_rgb[0]))) >> 8; - res_color.ch.red = (uint16_t)((uint16_t)txt_rgb[2] * font_rgb[2] + (bg_rgb[2] * (255 - font_rgb[2]))) >> 8; -#else - res_color.ch.red = (uint16_t)((uint16_t)txt_rgb[0] * font_rgb[0] + (bg_rgb[0] * (255 - font_rgb[0]))) >> 8; - res_color.ch.blue = (uint16_t)((uint16_t)txt_rgb[2] * font_rgb[2] + (bg_rgb[2] * (255 - font_rgb[2]))) >> 8; -#endif - -#if LV_COLOR_16_SWAP == 0 - res_color.ch.green = (uint16_t)((uint16_t)txt_rgb[1] * font_rgb[1] + (bg_rgb[1] * (255 - font_rgb[1]))) >> 8; -#else - uint8_t green = (uint16_t)((uint16_t)txt_rgb[1] * font_rgb[1] + (bg_rgb[1] * (255 - font_rgb[1]))) >> 8; - res_color.ch.green_h = green >> 3; - res_color.ch.green_l = green & 0x7; -#endif - - if(font_rgb[0] == 0 && font_rgb[1] == 0 && font_rgb[2] == 0) mask_buf[mask_p] = LV_OPA_TRANSP; - else mask_buf[mask_p] = LV_OPA_COVER; - color_buf[mask_p] = res_color; - - /*Next mask byte*/ - mask_p++; - vdb_buf_tmp++; - } - - /*Go to the next column*/ - if(col_bit < 8 - g->bpp) { - col_bit += g->bpp; - bitmask = bitmask >> g->bpp; - } else { - col_bit = 0; - bitmask = bitmask_init; - map_p++; - } - } - - /*Apply masks if any*/ - if(other_mask_cnt) { - lv_draw_mask_res_t mask_res = lv_draw_mask_apply(mask_buf + mask_p_start, map_area.x1, map_area.y2, lv_area_get_width(&map_area)); - if(mask_res == LV_DRAW_MASK_RES_FULL_TRANSP) { - memset(mask_buf + mask_p_start, 0x00, lv_area_get_width(&map_area)); - } - } - - if((uint32_t) mask_p + (row_end - row_start) < mask_buf_size) { - map_area.y2 ++; - } else { - lv_blend_map(clip_area, &map_area, color_buf, mask_buf, LV_DRAW_MASK_RES_CHANGED, opa, LV_BLEND_MODE_NORMAL); - - map_area.y1 = map_area.y2 + 1; - map_area.y2 = map_area.y1; - mask_p = 0; - } - - col_bit += ((g->box_w - col_end) + col_start) * g->bpp; - - map_p += (col_bit >> 3); - col_bit = col_bit & 0x7; - - /*Next row in VDB*/ - vdb_buf_tmp += vdb_width - (col_end - col_start) / 3; - } - - /*Flush the last part*/ - if(map_area.y1 != map_area.y2) { - map_area.y2--; - lv_blend_map(clip_area, &map_area, color_buf, mask_buf, LV_DRAW_MASK_RES_CHANGED, opa, LV_BLEND_MODE_NORMAL); - } - - lv_mem_buf_release(mask_buf); - lv_mem_buf_release(color_buf); -} - - -/** - * Convert a hexadecimal characters to a number (0..15) - * @param hex Pointer to a hexadecimal character (0..9, A..F) - * @return the numerical value of `hex` or 0 on error - */ -static uint8_t hex_char_to_num(char hex) -{ - uint8_t result = 0; - - if(hex >= '0' && hex <= '9') { - result = hex - '0'; - } else { - if(hex >= 'a') hex -= 'a' - 'A'; /*Convert to upper case*/ - - switch(hex) { - case 'A': result = 10; break; - case 'B': result = 11; break; - case 'C': result = 12; break; - case 'D': result = 13; break; - case 'E': result = 14; break; - case 'F': result = 15; break; - default: result = 0; break; - } - } - - return result; -} +///** +// * @file lv_draw_label.c +// * +// */ +// +///********************* +// * INCLUDES +// *********************/ +//#include "lv_draw_label.h" +//#include "../lv_misc/lv_math.h" +//#include "../lv_hal/lv_hal_disp.h" +//#include "../lv_core/lv_refr.h" +//#include "../lv_misc/lv_bidi.h" +// +///********************* +// * DEFINES +// *********************/ +//#define LABEL_RECOLOR_PAR_LENGTH 6 +//#define LV_LABEL_HINT_UPDATE_TH 1024 /*Update the "hint" if the label's y coordinates have changed more then this*/ +// +///********************** +// * TYPEDEFS +// **********************/ +//enum { +// CMD_STATE_WAIT, +// CMD_STATE_PAR, +// CMD_STATE_IN, +//}; +//typedef uint8_t cmd_state_t; +// +///********************** +// * STATIC PROTOTYPES +// **********************/ +//static void lv_draw_letter(const lv_point_t * pos_p, const lv_area_t * clip_area, const lv_font_t * font_p, uint32_t letter, +// lv_color_t color, lv_opa_t opa); +//static void draw_letter_normal(lv_coord_t pos_x, lv_coord_t pos_y, lv_font_glyph_dsc_t * g, const lv_area_t * clip_area, const uint8_t * map_p, lv_color_t color, lv_opa_t opa); +//static void draw_letter_subpx(lv_coord_t pos_x, lv_coord_t pos_y, lv_font_glyph_dsc_t * g, const lv_area_t * clip_area, const uint8_t * map_p, lv_color_t color, lv_opa_t opa); +// +// +//static uint8_t hex_char_to_num(char hex); +// +///********************** +// * STATIC VARIABLES +// **********************/ +///*clang-format off*/ +//static const uint8_t bpp1_opa_table[2] = {0, 255}; /*Opacity mapping with bpp = 1 (Just for compatibility)*/ +//static const uint8_t bpp2_opa_table[4] = {0, 85, 170, 255}; /*Opacity mapping with bpp = 2*/ +//static const uint8_t bpp4_opa_table[16] = {0, 17, 34, 51, /*Opacity mapping with bpp = 4*/ +// 68, 85, 102, 119, +// 136, 153, 170, 187, +// 204, 221, 238, 255}; +// /*clang-format on*/ +// +///********************** +// * MACROS +// **********************/ +// +///********************** +// * GLOBAL FUNCTIONS +// **********************/ +// +///** +// * Write a text +// * @param coords coordinates of the label +// * @param mask the label will be drawn only in this area +// * @param style pointer to a style +// * @param opa_scale scale down all opacities by the factor +// * @param txt 0 terminated text to write +// * @param flag settings for the text from 'txt_flag_t' enum +// * @param offset text offset in x and y direction (NULL if unused) +// * @param sel make the text selected in the range by drawing a background there +// */ +//void lv_draw_label(const lv_area_t * coords, const lv_area_t * mask, const lv_style_t * style, lv_opa_t opa_scale, +// const char * txt, lv_txt_flag_t flag, lv_point_t * offset, lv_draw_label_txt_sel_t * sel, +// lv_draw_label_hint_t * hint, lv_bidi_dir_t bidi_dir) +//{ +// const lv_font_t * font = style->text.font; +// lv_coord_t w; +// +// /*No need to waste processor time if string is empty*/ +// if (txt[0] == '\0') return; +// +// if((flag & LV_TXT_FLAG_EXPAND) == 0) { +// /*Normally use the label's width as width*/ +// w = lv_area_get_width(coords); +// } else { +// /*If EXAPND is enabled then not limit the text's width to the object's width*/ +// lv_point_t p; +// lv_txt_get_size(&p, txt, style->text.font, style->text.letter_space, style->text.line_space, LV_COORD_MAX, +// flag); +// w = p.x; +// } +// +// lv_coord_t line_height = lv_font_get_line_height(font) + style->text.line_space; +// +// /*Init variables for the first line*/ +// lv_coord_t line_width = 0; +// lv_point_t pos; +// pos.x = coords->x1; +// pos.y = coords->y1; +// +// lv_coord_t x_ofs = 0; +// lv_coord_t y_ofs = 0; +// if(offset != NULL) { +// x_ofs = offset->x; +// y_ofs = offset->y; +// pos.y += y_ofs; +// } +// +// uint32_t line_start = 0; +// int32_t last_line_start = -1; +// +// /*Check the hint to use the cached info*/ +// if(hint && y_ofs == 0 && coords->y1 < 0) { +// /*If the label changed too much recalculate the hint.*/ +// if(LV_MATH_ABS(hint->coord_y - coords->y1) > LV_LABEL_HINT_UPDATE_TH - 2 * line_height) { +// hint->line_start = -1; +// } +// last_line_start = hint->line_start; +// } +// +// /*Use the hint if it's valid*/ +// if(hint && last_line_start >= 0) { +// line_start = last_line_start; +// pos.y += hint->y; +// } +// +// +// uint32_t line_end = line_start + lv_txt_get_next_line(&txt[line_start], font, style->text.letter_space, w, flag); +// +// /*Go the first visible line*/ +// while(pos.y + line_height < mask->y1) { +// /*Go to next line*/ +// line_start = line_end; +// line_end += lv_txt_get_next_line(&txt[line_start], font, style->text.letter_space, w, flag); +// pos.y += line_height; +// +// /*Save at the threshold coordinate*/ +// if(hint && pos.y >= -LV_LABEL_HINT_UPDATE_TH && hint->line_start < 0) { +// hint->line_start = line_start; +// hint->y = pos.y - coords->y1; +// hint->coord_y = coords->y1; +// } +// +// if(txt[line_start] == '\0') return; +// } +// +// /*Align to middle*/ +// if(flag & LV_TXT_FLAG_CENTER) { +// line_width = lv_txt_get_width(&txt[line_start], line_end - line_start, font, style->text.letter_space, flag); +// +// pos.x += (lv_area_get_width(coords) - line_width) / 2; +// +// } +// /*Align to the right*/ +// else if(flag & LV_TXT_FLAG_RIGHT) { +// line_width = lv_txt_get_width(&txt[line_start], line_end - line_start, font, style->text.letter_space, flag); +// pos.x += lv_area_get_width(coords) - line_width; +// } +// +// lv_opa_t opa = opa_scale == LV_OPA_COVER ? style->text.opa : (uint16_t)((uint16_t)style->text.opa * opa_scale) >> 8; +// +// uint16_t sel_start = 0xFFFF; +// uint16_t sel_end = 0xFFFF; +// if(sel) { +// sel_start = sel->start; +// sel_end = sel->end; +// if(sel_start > sel_end) { +// uint16_t tmp = sel_start; +// sel_start = sel_end; +// sel_end = tmp; +// } +// } +// +// lv_style_t line_style; +// if(style->text.underline || style->text.strikethrough) { +// lv_style_copy(&line_style, style); +// line_style.line.color = style->text.color; +// line_style.line.width = (style->text.font->line_height + 5) / 10; /*+5 for rounding*/ +// line_style.line.opa = style->text.opa; +// line_style.line.blend_mode = style->text.blend_mode; +// } +// +// cmd_state_t cmd_state = CMD_STATE_WAIT; +// uint32_t i; +// uint16_t par_start = 0; +// lv_color_t recolor; +// lv_coord_t letter_w; +// lv_style_t sel_style; +// lv_style_copy(&sel_style, &lv_style_plain_color); +// sel_style.body.main_color = sel_style.body.grad_color = style->text.sel_color; +// lv_coord_t pos_x_start = pos.x; +// /*Write out all lines*/ +// while(txt[line_start] != '\0') { +// if(offset != NULL) pos.x += x_ofs; +// +// /*Write all letter of a line*/ +// cmd_state = CMD_STATE_WAIT; +// i = 0; +// uint32_t letter; +// uint32_t letter_next; +//#if LV_USE_BIDI +// char *bidi_txt = lv_mem_buf_get(line_end - line_start + 1); +// lv_bidi_process_paragraph(txt + line_start, bidi_txt, line_end - line_start, bidi_dir, NULL, 0); +//#else +// const char *bidi_txt = txt + line_start; +//#endif +// +// while(i < line_end - line_start) { +// uint16_t logical_char_pos = 0; +// if(sel_start != 0xFFFF && sel_end != 0xFFFF) { +//#if LV_USE_BIDI +// logical_char_pos = lv_txt_encoded_get_char_id(txt, line_start); +// uint16_t t = lv_txt_encoded_get_char_id(bidi_txt, i); +// logical_char_pos += lv_bidi_get_logical_pos(bidi_txt, NULL, line_end - line_start, bidi_dir, t, NULL); +//#else +// logical_char_pos = lv_txt_encoded_get_char_id(txt, line_start + i); +//#endif +// } +// +// letter = lv_txt_encoded_next(bidi_txt, &i); +// letter_next = lv_txt_encoded_next(&bidi_txt[i], NULL); +// +// +// /*Handle the re-color command*/ +// if((flag & LV_TXT_FLAG_RECOLOR) != 0) { +// if(letter == (uint32_t)LV_TXT_COLOR_CMD[0]) { +// if(cmd_state == CMD_STATE_WAIT) { /*Start char*/ +// par_start = i; +// cmd_state = CMD_STATE_PAR; +// continue; +// } else if(cmd_state == CMD_STATE_PAR) { /*Other start char in parameter escaped cmd. char */ +// cmd_state = CMD_STATE_WAIT; +// } else if(cmd_state == CMD_STATE_IN) { /*Command end */ +// cmd_state = CMD_STATE_WAIT; +// continue; +// } +// } +// +// /*Skip the color parameter and wait the space after it*/ +// if(cmd_state == CMD_STATE_PAR) { +// if(letter == ' ') { +// /*Get the parameter*/ +// if(i - par_start == LABEL_RECOLOR_PAR_LENGTH + 1) { +// char buf[LABEL_RECOLOR_PAR_LENGTH + 1]; +// memcpy(buf, &bidi_txt[par_start], LABEL_RECOLOR_PAR_LENGTH); +// buf[LABEL_RECOLOR_PAR_LENGTH] = '\0'; +// int r, g, b; +// r = (hex_char_to_num(buf[0]) << 4) + hex_char_to_num(buf[1]); +// g = (hex_char_to_num(buf[2]) << 4) + hex_char_to_num(buf[3]); +// b = (hex_char_to_num(buf[4]) << 4) + hex_char_to_num(buf[5]); +// recolor = lv_color_make(r, g, b); +// } else { +// recolor.full = style->text.color.full; +// } +// cmd_state = CMD_STATE_IN; /*After the parameter the text is in the command*/ +// } +// continue; +// } +// } +// +// lv_color_t color = style->text.color; +// +// if(cmd_state == CMD_STATE_IN) color = recolor; +// +// letter_w = lv_font_get_glyph_width(font, letter, letter_next); +// +// if(sel_start != 0xFFFF && sel_end != 0xFFFF) { +// if(logical_char_pos >= sel_start && logical_char_pos < sel_end) { +// lv_area_t sel_coords; +// sel_coords.x1 = pos.x; +// sel_coords.y1 = pos.y; +// sel_coords.x2 = pos.x + letter_w + style->text.letter_space - 1; +// sel_coords.y2 = pos.y + line_height - 1; +// lv_draw_rect(&sel_coords, mask, &sel_style, opa); +// } +// } +// +// lv_draw_letter(&pos, mask, font, letter, color, opa); +// +// if(letter_w > 0) { +// pos.x += letter_w + style->text.letter_space; +// } +// } +// +// if(style->text.strikethrough) { +// lv_point_t p1; +// lv_point_t p2; +// p1.x = pos_x_start; +// p1.y = pos.y + (style->text.font->line_height / 2) + style->line.width / 2; +// p2.x = pos.x; +// p2.y = p1.y; +// lv_draw_line(&p1, &p2, mask, &line_style, opa_scale); +// } +// +// if(style->text.underline) { +// lv_point_t p1; +// lv_point_t p2; +// p1.x = pos_x_start; +// p1.y = pos.y + style->text.font->line_height - style->text.font->base_line + style->line.width / 2 + 1; +// p2.x = pos.x; +// p2.y = p1.y; +// lv_draw_line(&p1, &p2, mask, &line_style, opa_scale); +// } +// +//#if LV_USE_BIDI +// lv_mem_buf_release(bidi_txt); +// bidi_txt = NULL; +//#endif +// /*Go to next line*/ +// line_start = line_end; +// line_end += lv_txt_get_next_line(&txt[line_start], font, style->text.letter_space, w, flag); +// +// pos.x = coords->x1; +// /*Align to middle*/ +// if(flag & LV_TXT_FLAG_CENTER) { +// line_width = +// lv_txt_get_width(&txt[line_start], line_end - line_start, font, style->text.letter_space, flag); +// +// pos.x += (lv_area_get_width(coords) - line_width) / 2; +// +// } +// /*Align to the right*/ +// else if(flag & LV_TXT_FLAG_RIGHT) { +// line_width = +// lv_txt_get_width(&txt[line_start], line_end - line_start, font, style->text.letter_space, flag); +// pos.x += lv_area_get_width(coords) - line_width; +// } +// +// /*Go the next line position*/ +// pos.y += line_height; +// +// if(pos.y > mask->y2) return; +// } +//} +// +///********************** +// * STATIC FUNCTIONS +// **********************/ +// +// +///** +// * Draw a letter in the Virtual Display Buffer +// * @param pos_p left-top coordinate of the latter +// * @param mask_p the letter will be drawn only on this area (truncated to VDB area) +// * @param font_p pointer to font +// * @param letter a letter to draw +// * @param color color of letter +// * @param opa opacity of letter (0..255) +// */ +//static void lv_draw_letter(const lv_point_t * pos_p, const lv_area_t * clip_area, const lv_font_t * font_p, uint32_t letter, +// lv_color_t color, lv_opa_t opa) +//{ +// if(opa < LV_OPA_MIN) return; +// if(opa > LV_OPA_MAX) opa = LV_OPA_COVER; +// +// if(font_p == NULL) { +// LV_LOG_WARN("lv_draw_letter: font is NULL"); +// return; +// } +// +// lv_font_glyph_dsc_t g; +// bool g_ret = lv_font_get_glyph_dsc(font_p, &g, letter, '\0'); +// if(g_ret == false) { +// /* Add waring if the dsc is not found +// * but do not print warning for non printable ASCII chars (e.g. '\n')*/ +// if(letter >= 0x20) { +// LV_LOG_WARN("lv_draw_letter: glyph dsc. not found"); +// } +// return; +// } +// +// lv_coord_t pos_x = pos_p->x + g.ofs_x; +// lv_coord_t pos_y = pos_p->y + (font_p->line_height - font_p->base_line) - g.box_h - g.ofs_y; +// +// /*If the letter is completely out of mask don't draw it */ +// if(pos_x + g.box_w < clip_area->x1 || +// pos_x > clip_area->x2 || +// pos_y + g.box_h < clip_area->y1 || +// pos_y > clip_area->y2) return; +// +// +// const uint8_t * map_p = lv_font_get_glyph_bitmap(font_p, letter); +// if(map_p == NULL) { +// LV_LOG_WARN("lv_draw_letter: character's bitmap not found"); +// return; +// } +// +// if(font_p->subpx) { +// draw_letter_subpx(pos_x, pos_y, &g, clip_area, map_p, color, opa); +// } else { +// draw_letter_normal(pos_x, pos_y, &g, clip_area, map_p, color, opa); +// } +//} +// +// +//static void draw_letter_normal(lv_coord_t pos_x, lv_coord_t pos_y, lv_font_glyph_dsc_t * g, const lv_area_t * clip_area, const uint8_t * map_p, lv_color_t color, lv_opa_t opa) +//{ +// +// const uint8_t * bpp_opa_table; +// uint8_t bitmask_init; +// uint8_t bitmask; +// +// if(g->bpp == 3) g->bpp = 4; +// +// switch(g->bpp) { +// case 1: +// bpp_opa_table = bpp1_opa_table; +// bitmask_init = 0x80; +// break; +// case 2: +// bpp_opa_table = bpp2_opa_table; +// bitmask_init = 0xC0; +// break; +// case 4: +// bpp_opa_table = bpp4_opa_table; +// bitmask_init = 0xF0; +// break; +// case 8: +// bpp_opa_table = NULL; +// bitmask_init = 0xFF; +// break; /*No opa table, pixel value will be used directly*/ +// default: +// LV_LOG_WARN("lv_draw_letter: invalid bpp not found"); +// return; /*Invalid bpp. Can't render the letter*/ +// } +// +// +// +// lv_coord_t col, row; +// +// uint8_t width_byte_scr = g->box_w >> 3; /*Width in bytes (on the screen finally) (e.g. w = 11 -> 2 bytes wide)*/ +// if(g->box_w & 0x7) width_byte_scr++; +// uint16_t width_bit = g->box_w * g->bpp; /*Letter width in bits*/ +// +// +// /* Calculate the col/row start/end on the map*/ +// lv_coord_t col_start = pos_x >= clip_area->x1 ? 0 : clip_area->x1 - pos_x; +// lv_coord_t col_end = pos_x + g->box_w <= clip_area->x2 ? g->box_w : clip_area->x2 - pos_x + 1; +// lv_coord_t row_start = pos_y >= clip_area->y1 ? 0 : clip_area->y1 - pos_y; +// lv_coord_t row_end = pos_y + g->box_h <= clip_area->y2 ? g->box_h : clip_area->y2 - pos_y + 1; +// +// /*Move on the map too*/ +// uint32_t bit_ofs = (row_start * width_bit) + (col_start * g->bpp); +// map_p += bit_ofs >> 3; +// +// uint8_t letter_px; +// lv_opa_t px_opa; +// uint16_t col_bit; +// col_bit = bit_ofs & 0x7; /* "& 0x7" equals to "% 8" just faster */ +// +// uint32_t mask_buf_size = g->box_w * g->box_h > LV_HOR_RES_MAX ? g->box_w * g->box_h : LV_HOR_RES_MAX; +// lv_opa_t * mask_buf = lv_mem_buf_get(mask_buf_size); +// lv_coord_t mask_p = 0; +// lv_coord_t mask_p_start; +// +// lv_area_t fill_area; +// fill_area.x1 = col_start + pos_x; +// fill_area.x2 = col_end + pos_x - 1; +// fill_area.y1 = row_start + pos_y; +// fill_area.y2 = fill_area.y1; +// +// uint8_t other_mask_cnt = lv_draw_mask_get_cnt(); +// +// for(row = row_start ; row < row_end; row++) { +// bitmask = bitmask_init >> col_bit; +// mask_p_start = mask_p; +// for(col = col_start; col < col_end; col++) { +// +// /*Load the pixel's opacity into the mask*/ +// letter_px = (*map_p & bitmask) >> (8 - col_bit - g->bpp); +// if(letter_px != 0) { +// if(opa == LV_OPA_COVER) { +// px_opa = g->bpp == 8 ? letter_px : bpp_opa_table[letter_px]; +// } else { +// px_opa = g->bpp == 8 ? (uint16_t)((uint16_t)letter_px * opa) >> 8 +// : (uint16_t)((uint16_t)bpp_opa_table[letter_px] * opa) >> 8; +// } +// +// mask_buf[mask_p] = px_opa; +// +// } else { +// mask_buf[mask_p] = 0; +// } +// +// /*Go to the next column*/ +// if(col_bit < 8 - g->bpp) { +// col_bit += g->bpp; +// bitmask = bitmask >> g->bpp; +// } else { +// col_bit = 0; +// bitmask = bitmask_init; +// map_p++; +// } +// +// /*Next mask byte*/ +// mask_p++; +// } +// +// /*Apply masks if any*/ +// if(other_mask_cnt) { +// lv_draw_mask_res_t mask_res = lv_draw_mask_apply(mask_buf + mask_p_start, fill_area.x1, fill_area.y2, lv_area_get_width(&fill_area)); +// if(mask_res == LV_DRAW_MASK_RES_FULL_TRANSP) { +// memset(mask_buf + mask_p_start, 0x00, lv_area_get_width(&fill_area)); +// } +// } +// +// if((uint32_t) mask_p + (row_end - row_start) < mask_buf_size) { +// fill_area.y2 ++; +// } else { +// lv_blend_fill(clip_area, &fill_area, +// color, mask_buf, LV_DRAW_MASK_RES_CHANGED, opa, +// LV_BLEND_MODE_NORMAL); +// +// fill_area.y1 = fill_area.y2 + 1; +// fill_area.y2 = fill_area.y1; +// mask_p = 0; +// } +// +// col_bit += ((g->box_w - col_end) + col_start) * g->bpp; +// +// map_p += (col_bit >> 3); +// col_bit = col_bit & 0x7; +// } +// +// /*Flush the last part*/ +// if(fill_area.y1 != fill_area.y2) { +// fill_area.y2--; +// lv_blend_fill(clip_area, &fill_area, +// color, mask_buf, LV_DRAW_MASK_RES_CHANGED, opa, +// LV_BLEND_MODE_NORMAL); +// mask_p = 0; +// } +// +// lv_mem_buf_release(mask_buf); +//} +// +//static void draw_letter_subpx(lv_coord_t pos_x, lv_coord_t pos_y, lv_font_glyph_dsc_t * g, const lv_area_t * clip_area, const uint8_t * map_p, lv_color_t color, lv_opa_t opa) +//{ +// const uint8_t * bpp_opa_table; +// uint8_t bitmask_init; +// uint8_t bitmask; +// +// if(g->bpp == 3) g->bpp = 4; +// +// switch(g->bpp) { +// case 1: +// bpp_opa_table = bpp1_opa_table; +// bitmask_init = 0x80; +// break; +// case 2: +// bpp_opa_table = bpp2_opa_table; +// bitmask_init = 0xC0; +// break; +// case 4: +// bpp_opa_table = bpp4_opa_table; +// bitmask_init = 0xF0; +// break; +// case 8: +// bpp_opa_table = NULL; +// bitmask_init = 0xFF; +// break; /*No opa table, pixel value will be used directly*/ +// default: +// LV_LOG_WARN("lv_draw_letter: invalid bpp not found"); +// return; /*Invalid bpp. Can't render the letter*/ +// } +// +// lv_coord_t col, row; +// +// uint8_t width_byte_scr = g->box_w >> 3; /*Width in bytes (on the screen finally) (e.g. w = 11 -> 2 bytes wide)*/ +// if(g->box_w & 0x7) width_byte_scr++; +// uint16_t width_bit = g->box_w * g->bpp; /*Letter width in bits*/ +// +// +// /* Calculate the col/row start/end on the map*/ +// lv_coord_t col_start = pos_x >= clip_area->x1 ? 0 : (clip_area->x1 - pos_x) * 3; +// lv_coord_t col_end = pos_x + g->box_w / 3 <= clip_area->x2 ? g->box_w : (clip_area->x2 - pos_x + 1) * 3; +// lv_coord_t row_start = pos_y >= clip_area->y1 ? 0 : clip_area->y1 - pos_y; +// lv_coord_t row_end = pos_y + g->box_h <= clip_area->y2 ? g->box_h : clip_area->y2 - pos_y + 1; +// +// /*Move on the map too*/ +// uint32_t bit_ofs = (row_start * width_bit) + (col_start * g->bpp); +// map_p += bit_ofs >> 3; +// +// uint8_t letter_px; +// lv_opa_t px_opa; +// uint16_t col_bit; +// col_bit = bit_ofs & 0x7; /* "& 0x7" equals to "% 8" just faster */ +// +// uint32_t mask_buf_size = g->box_w * g->box_h > LV_HOR_RES_MAX ? g->box_w * g->box_h : LV_HOR_RES_MAX; +// lv_opa_t * mask_buf = lv_mem_buf_get(mask_buf_size); +// lv_coord_t mask_p = 0; +// lv_coord_t mask_p_start; +// lv_color_t * color_buf = lv_mem_buf_get(mask_buf_size * sizeof(lv_color_t)); +// +// lv_disp_t * disp = lv_refr_get_disp_refreshing(); +// lv_disp_buf_t * vdb = lv_disp_get_buf(disp); +// +// lv_coord_t vdb_width = lv_area_get_width(&vdb->area); +// lv_color_t * vdb_buf_tmp = vdb->buf_act; +// +// /*Set a pointer on VDB to the first pixel of the letter*/ +// vdb_buf_tmp += ((pos_y - vdb->area.y1) * vdb_width) + pos_x - vdb->area.x1; +// +// /*If the letter is partially out of mask the move there on VDB*/ +// vdb_buf_tmp += (row_start * vdb_width) + col_start / 3; +// +// lv_area_t map_area; +// map_area.x1 = col_start / 3 + pos_x; +// map_area.x2 = col_end / 3 + pos_x - 1; +// map_area.y1 = row_start + pos_y; +// map_area.y2 = map_area.y1; +// +// uint8_t other_mask_cnt = lv_draw_mask_get_cnt(); +// +// uint8_t font_rgb[3]; +// +//#if LV_COLOR_16_SWAP == 0 +// uint8_t txt_rgb[3] = {color.ch.red, color.ch.green, color.ch.blue}; +//#else +// uint8_t txt_rgb[3] = {color.ch.red, (color.ch.green_h << 3) + color.ch.green_l, color.ch.blue}; +//#endif +// +// for(row = row_start ; row < row_end; row++) { +// uint8_t subpx_cnt = 0; +// bitmask = bitmask_init >> col_bit; +// mask_p_start = mask_p; +// for(col = col_start; col < col_end; col++) { +// /*Load the pixel's opacity into the mask*/ +// letter_px = (*map_p & bitmask) >> (8 - col_bit - g->bpp); +// if(letter_px != 0) { +// if(opa == LV_OPA_COVER) { +// px_opa = g->bpp == 8 ? letter_px : bpp_opa_table[letter_px]; +// } else { +// px_opa = g->bpp == 8 ? (uint16_t)((uint16_t)letter_px * opa) >> 8 +// : (uint16_t)((uint16_t)bpp_opa_table[letter_px] * opa) >> 8; +// } +// } else { +// px_opa = 0; +// } +// +// font_rgb[subpx_cnt] = px_opa; +// +// subpx_cnt ++; +// if(subpx_cnt == 3) { +// subpx_cnt = 0; +// +// lv_color_t res_color; +//#if LV_COLOR_16_SWAP == 0 +// uint8_t bg_rgb[3] = {vdb_buf_tmp->ch.red, vdb_buf_tmp->ch.green, vdb_buf_tmp->ch.blue}; +//#else +// uint8_t bg_rgb[3] = {vdb_buf_tmp->ch.red, +// (vdb_buf_tmp->ch.green_h << 3) + vdb_buf_tmp->ch.green_l, +// vdb_buf_tmp->ch.blue}; +//#endif +// +//#if LV_SUBPX_BGR +// res_color.ch.blue = (uint16_t)((uint16_t)txt_rgb[0] * font_rgb[0] + (bg_rgb[0] * (255 - font_rgb[0]))) >> 8; +// res_color.ch.red = (uint16_t)((uint16_t)txt_rgb[2] * font_rgb[2] + (bg_rgb[2] * (255 - font_rgb[2]))) >> 8; +//#else +// res_color.ch.red = (uint16_t)((uint16_t)txt_rgb[0] * font_rgb[0] + (bg_rgb[0] * (255 - font_rgb[0]))) >> 8; +// res_color.ch.blue = (uint16_t)((uint16_t)txt_rgb[2] * font_rgb[2] + (bg_rgb[2] * (255 - font_rgb[2]))) >> 8; +//#endif +// +//#if LV_COLOR_16_SWAP == 0 +// res_color.ch.green = (uint16_t)((uint16_t)txt_rgb[1] * font_rgb[1] + (bg_rgb[1] * (255 - font_rgb[1]))) >> 8; +//#else +// uint8_t green = (uint16_t)((uint16_t)txt_rgb[1] * font_rgb[1] + (bg_rgb[1] * (255 - font_rgb[1]))) >> 8; +// res_color.ch.green_h = green >> 3; +// res_color.ch.green_l = green & 0x7; +//#endif +// +// if(font_rgb[0] == 0 && font_rgb[1] == 0 && font_rgb[2] == 0) mask_buf[mask_p] = LV_OPA_TRANSP; +// else mask_buf[mask_p] = LV_OPA_COVER; +// color_buf[mask_p] = res_color; +// +// /*Next mask byte*/ +// mask_p++; +// vdb_buf_tmp++; +// } +// +// /*Go to the next column*/ +// if(col_bit < 8 - g->bpp) { +// col_bit += g->bpp; +// bitmask = bitmask >> g->bpp; +// } else { +// col_bit = 0; +// bitmask = bitmask_init; +// map_p++; +// } +// } +// +// /*Apply masks if any*/ +// if(other_mask_cnt) { +// lv_draw_mask_res_t mask_res = lv_draw_mask_apply(mask_buf + mask_p_start, map_area.x1, map_area.y2, lv_area_get_width(&map_area)); +// if(mask_res == LV_DRAW_MASK_RES_FULL_TRANSP) { +// memset(mask_buf + mask_p_start, 0x00, lv_area_get_width(&map_area)); +// } +// } +// +// if((uint32_t) mask_p + (row_end - row_start) < mask_buf_size) { +// map_area.y2 ++; +// } else { +// lv_blend_map(clip_area, &map_area, color_buf, mask_buf, LV_DRAW_MASK_RES_CHANGED, opa, LV_BLEND_MODE_NORMAL); +// +// map_area.y1 = map_area.y2 + 1; +// map_area.y2 = map_area.y1; +// mask_p = 0; +// } +// +// col_bit += ((g->box_w - col_end) + col_start) * g->bpp; +// +// map_p += (col_bit >> 3); +// col_bit = col_bit & 0x7; +// +// /*Next row in VDB*/ +// vdb_buf_tmp += vdb_width - (col_end - col_start) / 3; +// } +// +// /*Flush the last part*/ +// if(map_area.y1 != map_area.y2) { +// map_area.y2--; +// lv_blend_map(clip_area, &map_area, color_buf, mask_buf, LV_DRAW_MASK_RES_CHANGED, opa, LV_BLEND_MODE_NORMAL); +// } +// +// lv_mem_buf_release(mask_buf); +// lv_mem_buf_release(color_buf); +//} +// +// +///** +// * Convert a hexadecimal characters to a number (0..15) +// * @param hex Pointer to a hexadecimal character (0..9, A..F) +// * @return the numerical value of `hex` or 0 on error +// */ +//static uint8_t hex_char_to_num(char hex) +//{ +// uint8_t result = 0; +// +// if(hex >= '0' && hex <= '9') { +// result = hex - '0'; +// } else { +// if(hex >= 'a') hex -= 'a' - 'A'; /*Convert to upper case*/ +// +// switch(hex) { +// case 'A': result = 10; break; +// case 'B': result = 11; break; +// case 'C': result = 12; break; +// case 'D': result = 13; break; +// case 'E': result = 14; break; +// case 'F': result = 15; break; +// default: result = 0; break; +// } +// } +// +// return result; +//} diff --git a/src/lv_draw/lv_draw_line.c b/src/lv_draw/lv_draw_line.c index 949860b9d..27b63412e 100644 --- a/src/lv_draw/lv_draw_line.c +++ b/src/lv_draw/lv_draw_line.c @@ -1,349 +1,349 @@ -/**lip - * @file lv_draw_line.c - * - */ - -/********************* - * INCLUDES - *********************/ -#include -#include -#include "lv_draw.h" -#include "lv_draw_mask.h" -#include "lv_draw_blend.h" -#include "../lv_core/lv_refr.h" -#include "../lv_misc/lv_math.h" - -/********************* - * DEFINES - *********************/ - -/********************** - * TYPEDEFS - **********************/ - -/********************** - * STATIC PROTOTYPES - **********************/ -static void draw_line_skew(const lv_point_t * point1, const lv_point_t * point2, const lv_area_t * clip, - const lv_style_t * style, lv_opa_t opa_scale); -static void draw_line_hor(const lv_point_t * point1, const lv_point_t * point2, const lv_area_t * clip, - const lv_style_t * style, lv_opa_t opa_scale); -static void draw_line_ver(const lv_point_t * point1, const lv_point_t * point2, const lv_area_t * clip, - const lv_style_t * style, lv_opa_t opa_scale); - - -/********************** - * STATIC VARIABLES - **********************/ - -/********************** - * MACROS - **********************/ - -/********************** - * GLOBAL FUNCTIONS - **********************/ - -/** - * Draw a line - * @param point1 first point of the line - * @param point2 second point of the line - * @param mask the line will be drawn only on this area - * @param style pointer to a line's style - * @param opa_scale scale down all opacities by the factor - */ -void lv_draw_line(const lv_point_t * point1, const lv_point_t * point2, const lv_area_t * clip, - const lv_style_t * style, lv_opa_t opa_scale) -{ - if(style->line.width == 0) return; - if(point1->x == point2->x && point1->y == point2->y) return; - - lv_area_t clip_line; - clip_line.x1 = LV_MATH_MIN(point1->x, point2->x) - style->line.width/2; - clip_line.x2 = LV_MATH_MAX(point1->x, point2->x) + style->line.width/2; - clip_line.y1 = LV_MATH_MIN(point1->y, point2->y) - style->line.width/2; - clip_line.y2 = LV_MATH_MAX(point1->y, point2->y) + style->line.width/2; - - bool is_common; - is_common = lv_area_intersect(&clip_line, &clip_line, clip); - if(!is_common) return; - - if(point1->y == point2->y) draw_line_hor(point1, point2, &clip_line, style, opa_scale); - else if(point1->x == point2->x) draw_line_ver(point1, point2, &clip_line, style, opa_scale); - else draw_line_skew(point1, point2, &clip_line, style, opa_scale); -} - -/********************** - * STATIC FUNCTIONS - **********************/ - -static void draw_line_hor(const lv_point_t * point1, const lv_point_t * point2, const lv_area_t * clip, - const lv_style_t * style, lv_opa_t opa_scale) -{ - lv_opa_t opa = style->line.opa; - if(opa_scale != LV_OPA_COVER) opa = (opa * opa_scale) >> 8; - - lv_disp_t * disp = lv_refr_get_disp_refreshing(); - lv_disp_buf_t * vdb = lv_disp_get_buf(disp); - - const lv_area_t * disp_area = &vdb->area; - - lv_coord_t w = style->line.width - 1; - lv_coord_t w_half0 = w >> 1; - lv_coord_t w_half1 = w_half0 + (w & 0x1); /*Compensate rounding error*/ - - - int16_t other_mask_cnt = lv_draw_mask_get_cnt(); - - lv_area_t draw_area; - draw_area.x1 = LV_MATH_MIN(point1->x, point2->x); - draw_area.x2 = LV_MATH_MAX(point1->x, point2->x) - 1; - draw_area.y1 = point1->y - w_half1; - draw_area.y2 = point1->y + w_half0; - - /*If there is no mask then simply draw a rectangle*/ - if(other_mask_cnt == 0) { - lv_blend_fill(clip, &draw_area, - style->line.color, NULL, LV_DRAW_MASK_RES_FULL_COVER,opa, - LV_BLEND_MODE_NORMAL); - } - /*If there other mask apply it*/ - else { - /* Get clipped fill area which is the real draw area. - * It is always the same or inside `fill_area` */ - bool is_common; - is_common = lv_area_intersect(&draw_area, clip, &draw_area); - if(!is_common) return; - - /* Now `draw_area` has absolute coordinates. - * Make it relative to `disp_area` to simplify draw to `disp_buf`*/ - draw_area.x1 -= vdb->area.x1; - draw_area.y1 -= vdb->area.y1; - draw_area.x2 -= vdb->area.x1; - draw_area.y2 -= vdb->area.y1; - - lv_coord_t draw_area_w = lv_area_get_width(&draw_area); - - lv_area_t fill_area; - fill_area.x1 = draw_area.x1 + disp_area->x1; - fill_area.x2 = draw_area.x2 + disp_area->x1; - fill_area.y1 = draw_area.y1 + disp_area->y1; - fill_area.y2 = fill_area.y1; - - lv_opa_t * mask_buf = lv_mem_buf_get(draw_area_w); - lv_coord_t h; - lv_draw_mask_res_t mask_res; - for(h = draw_area.y1; h <= draw_area.y2; h++) { - memset(mask_buf, LV_OPA_COVER, draw_area_w); - mask_res = lv_draw_mask_apply(mask_buf, vdb->area.x1 + draw_area.x1, vdb->area.y1 + h, draw_area_w); - - lv_blend_fill(clip, &fill_area, - style->line.color, mask_buf, mask_res, style->line.opa, - style->line.blend_mode); - - fill_area.y1++; - fill_area.y2++; - } - lv_mem_buf_release(mask_buf); - } -} - - -static void draw_line_ver(const lv_point_t * point1, const lv_point_t * point2, const lv_area_t * clip, - const lv_style_t * style, lv_opa_t opa_scale) -{ - lv_opa_t opa = style->line.opa; - if(opa_scale != LV_OPA_COVER) opa = (opa * opa_scale) >> 8; - - lv_disp_t * disp = lv_refr_get_disp_refreshing(); - lv_disp_buf_t * vdb = lv_disp_get_buf(disp); - - const lv_area_t * disp_area = &vdb->area; - - lv_coord_t w = style->line.width - 1; - lv_coord_t w_half0 = w >> 1; - lv_coord_t w_half1 = w_half0 + (w & 0x1); /*Compensate rounding error*/ - - - int16_t other_mask_cnt = lv_draw_mask_get_cnt(); - - lv_area_t draw_area; - draw_area.x1 = point1->x - w_half1; - draw_area.x2 = point1->x + w_half0; - draw_area.y1 = LV_MATH_MIN(point1->y, point2->y); - draw_area.y2 = LV_MATH_MAX(point1->y, point2->y) - 1; - - /*If there is no mask then simply draw a rectangle*/ - if(other_mask_cnt == 0) { - - lv_blend_fill(clip, &draw_area, - style->line.color, NULL, LV_DRAW_MASK_RES_FULL_COVER, opa, - style->line.blend_mode); - } - /*If there other mask apply it*/ - else { - /* Get clipped fill area which is the real draw area. - * It is always the same or inside `fill_area` */ - bool is_common; - is_common = lv_area_intersect(&draw_area, clip, &draw_area); - if(!is_common) return; - - /* Now `draw_area` has absolute coordinates. - * Make it relative to `disp_area` to simplify draw to `disp_buf`*/ - draw_area.x1 -= vdb->area.x1; - draw_area.y1 -= vdb->area.y1; - draw_area.x2 -= vdb->area.x1; - draw_area.y2 -= vdb->area.y1; - - lv_coord_t draw_area_w = lv_area_get_width(&draw_area); - - lv_area_t fill_area; - fill_area.x1 = draw_area.x1 + disp_area->x1; - fill_area.x2 = draw_area.x2 + disp_area->x1; - fill_area.y1 = draw_area.y1 + disp_area->y1; - fill_area.y2 = fill_area.y1; - - lv_opa_t * mask_buf = lv_mem_buf_get(draw_area_w); - lv_coord_t h; - lv_draw_mask_res_t mask_res; - for(h = draw_area.y1; h <= draw_area.y2; h++) { - memset(mask_buf, LV_OPA_COVER, draw_area_w); - mask_res = lv_draw_mask_apply(mask_buf, vdb->area.x1 + draw_area.x1, vdb->area.y1 + h, draw_area_w); - - lv_blend_fill(clip, &fill_area, - style->line.color, mask_buf, mask_res, style->line.opa, - LV_BLEND_MODE_NORMAL); - - fill_area.y1++; - fill_area.y2++; - } - lv_mem_buf_release(mask_buf); - } -} - - -static void draw_line_skew(const lv_point_t * point1, const lv_point_t * point2, const lv_area_t * clip, - const lv_style_t * style, lv_opa_t opa_scale) -{ - lv_opa_t opa = style->line.opa; - if(opa_scale != LV_OPA_COVER) opa = (opa * opa_scale) >> 8; - - /*Keep the great y in p1*/ - lv_point_t p1; - lv_point_t p2; - if(point1->y < point2->y) { - p1.y = point1->y; - p2.y = point2->y; - p1.x = point1->x; - p2.x = point2->x; - } else { - p1.y = point2->y; - p2.y = point1->y; - p1.x = point2->x; - p2.x = point1->x; - } - - lv_coord_t xdiff = p2.x - p1.x; - lv_coord_t ydiff = p2.y - p1.y; - bool flat = LV_MATH_ABS(xdiff) > LV_MATH_ABS(ydiff) ? true : false; - - static const uint8_t wcorr[] = { - 128, 128, 128, 129, 129, 130, 130, 131, - 132, 133, 134, 135, 137, 138, 140, 141, - 143, 145, 147, 149, 151, 153, 155, 158, - 160, 162, 165, 167, 170, 173, 175, 178, - 181, - }; - - lv_coord_t w = style->line.width; - lv_coord_t wcorr_i = 0; - if(flat) wcorr_i = (LV_MATH_ABS(ydiff) << 5) / LV_MATH_ABS(xdiff); - else wcorr_i = (LV_MATH_ABS(xdiff) << 5) / LV_MATH_ABS(ydiff); - - w = (w * wcorr[wcorr_i]) >> 7; - lv_coord_t w_half0 = w >> 1; - lv_coord_t w_half1 = w_half0 + (w & 0x1); /*Compensate rounding error*/ - - lv_area_t draw_area; - draw_area.x1 = LV_MATH_MIN(p1.x, p2.x) - w; - draw_area.x2 = LV_MATH_MAX(p1.x, p2.x) + w; - draw_area.y1 = LV_MATH_MIN(p1.y, p2.y) - w; - draw_area.y2 = LV_MATH_MAX(p1.y, p2.y) + w; - - /* Get the union of `coords` and `clip`*/ - /* `clip` is already truncated to the `vdb` size - * in 'lv_refr_area' function */ - bool is_common = lv_area_intersect(&draw_area, &draw_area, clip); - if(is_common == false) return; - - lv_draw_mask_line_param_t mask_left_param; - lv_draw_mask_line_param_t mask_right_param; - lv_draw_mask_line_param_t mask_top_param; - lv_draw_mask_line_param_t mask_bottom_param; - - if(flat) { - if(xdiff > 0) { - lv_draw_mask_line_points_init(&mask_left_param, p1.x, p1.y - w_half0, p2.x, p2.y - w_half0, LV_DRAW_MASK_LINE_SIDE_LEFT); - lv_draw_mask_line_points_init(&mask_right_param, p1.x, p1.y + w_half1, p2.x, p2.y + w_half1, LV_DRAW_MASK_LINE_SIDE_RIGHT); - } else { - lv_draw_mask_line_points_init(&mask_left_param, p1.x, p1.y + w_half1, p2.x, p2.y + w_half1, LV_DRAW_MASK_LINE_SIDE_LEFT); - lv_draw_mask_line_points_init(&mask_right_param, p1.x, p1.y - w_half0, p2.x, p2.y - w_half0, LV_DRAW_MASK_LINE_SIDE_RIGHT); - } - } else { - lv_draw_mask_line_points_init(&mask_left_param, p1.x + w_half1, p1.y, p2.x + w_half1, p2.y, LV_DRAW_MASK_LINE_SIDE_LEFT); - lv_draw_mask_line_points_init(&mask_right_param, p1.x - w_half0, p1.y, p2.x - w_half0, p2.y, LV_DRAW_MASK_LINE_SIDE_RIGHT); - } - - /*Use the normal vector for the endings*/ - lv_draw_mask_line_points_init(&mask_top_param, p1.x, p1.y, p1.x - ydiff, p1.y + xdiff, LV_DRAW_MASK_LINE_SIDE_BOTTOM); - lv_draw_mask_line_points_init(&mask_bottom_param, p2.x, p2.y,p2.x - ydiff, p2.y + xdiff, LV_DRAW_MASK_LINE_SIDE_TOP); - - int16_t mask_left_id = lv_draw_mask_add(&mask_left_param, NULL); - int16_t mask_right_id = lv_draw_mask_add(&mask_right_param, NULL); - int16_t mask_top_id = lv_draw_mask_add(&mask_top_param, NULL); - int16_t mask_bottom_id = lv_draw_mask_add(&mask_bottom_param, NULL); - - lv_disp_t * disp = lv_refr_get_disp_refreshing(); - lv_disp_buf_t * vdb = lv_disp_get_buf(disp); - - const lv_area_t * disp_area = &vdb->area; - - /*Store the coordinates of the `draw_a` relative to the VDB */ - draw_area.x1 -= disp_area->x1; - draw_area.y1 -= disp_area->y1; - draw_area.x2 -= disp_area->x1; - draw_area.y2 -= disp_area->y1; - - lv_coord_t draw_area_w = lv_area_get_width(&draw_area); - - /*Draw the background line by line*/ - lv_coord_t h; - lv_draw_mask_res_t mask_res; - lv_opa_t * mask_buf = lv_mem_buf_get(draw_area_w); - lv_area_t fill_area; - fill_area.x1 = draw_area.x1 + disp_area->x1; - fill_area.x2 = draw_area.x2 + disp_area->x1; - fill_area.y1 = draw_area.y1 + disp_area->y1; - fill_area.y2 = fill_area.y1; - - /*Fill the first row with 'color'*/ - for(h = draw_area.y1; h <= draw_area.y2; h++) { - memset(mask_buf, LV_OPA_COVER, draw_area_w); - mask_res = lv_draw_mask_apply(mask_buf, vdb->area.x1 + draw_area.x1, vdb->area.y1 + h, draw_area_w); - - lv_blend_fill(clip, &fill_area, - style->line.color, mask_buf, mask_res, opa, - style->line.blend_mode); - - fill_area.y1++; - fill_area.y2++; - } - - lv_mem_buf_release(mask_buf); - - lv_draw_mask_remove_id(mask_left_id); - lv_draw_mask_remove_id(mask_right_id); - lv_draw_mask_remove_id(mask_top_id); - lv_draw_mask_remove_id(mask_bottom_id); -} +///**lip +// * @file lv_draw_line.c +// * +// */ +// +///********************* +// * INCLUDES +// *********************/ +//#include +//#include +//#include "lv_draw.h" +//#include "lv_draw_mask.h" +//#include "lv_draw_blend.h" +//#include "../lv_core/lv_refr.h" +//#include "../lv_misc/lv_math.h" +// +///********************* +// * DEFINES +// *********************/ +// +///********************** +// * TYPEDEFS +// **********************/ +// +///********************** +// * STATIC PROTOTYPES +// **********************/ +//static void draw_line_skew(const lv_point_t * point1, const lv_point_t * point2, const lv_area_t * clip, +// const lv_style_t * style, lv_opa_t opa_scale); +//static void draw_line_hor(const lv_point_t * point1, const lv_point_t * point2, const lv_area_t * clip, +// const lv_style_t * style, lv_opa_t opa_scale); +//static void draw_line_ver(const lv_point_t * point1, const lv_point_t * point2, const lv_area_t * clip, +// const lv_style_t * style, lv_opa_t opa_scale); +// +// +///********************** +// * STATIC VARIABLES +// **********************/ +// +///********************** +// * MACROS +// **********************/ +// +///********************** +// * GLOBAL FUNCTIONS +// **********************/ +// +///** +// * Draw a line +// * @param point1 first point of the line +// * @param point2 second point of the line +// * @param mask the line will be drawn only on this area +// * @param style pointer to a line's style +// * @param opa_scale scale down all opacities by the factor +// */ +//void lv_draw_line(const lv_point_t * point1, const lv_point_t * point2, const lv_area_t * clip, +// const lv_style_t * style, lv_opa_t opa_scale) +//{ +// if(style->line.width == 0) return; +// if(point1->x == point2->x && point1->y == point2->y) return; +// +// lv_area_t clip_line; +// clip_line.x1 = LV_MATH_MIN(point1->x, point2->x) - style->line.width/2; +// clip_line.x2 = LV_MATH_MAX(point1->x, point2->x) + style->line.width/2; +// clip_line.y1 = LV_MATH_MIN(point1->y, point2->y) - style->line.width/2; +// clip_line.y2 = LV_MATH_MAX(point1->y, point2->y) + style->line.width/2; +// +// bool is_common; +// is_common = lv_area_intersect(&clip_line, &clip_line, clip); +// if(!is_common) return; +// +// if(point1->y == point2->y) draw_line_hor(point1, point2, &clip_line, style, opa_scale); +// else if(point1->x == point2->x) draw_line_ver(point1, point2, &clip_line, style, opa_scale); +// else draw_line_skew(point1, point2, &clip_line, style, opa_scale); +//} +// +///********************** +// * STATIC FUNCTIONS +// **********************/ +// +//static void draw_line_hor(const lv_point_t * point1, const lv_point_t * point2, const lv_area_t * clip, +// const lv_style_t * style, lv_opa_t opa_scale) +//{ +// lv_opa_t opa = style->line.opa; +// if(opa_scale != LV_OPA_COVER) opa = (opa * opa_scale) >> 8; +// +// lv_disp_t * disp = lv_refr_get_disp_refreshing(); +// lv_disp_buf_t * vdb = lv_disp_get_buf(disp); +// +// const lv_area_t * disp_area = &vdb->area; +// +// lv_coord_t w = style->line.width - 1; +// lv_coord_t w_half0 = w >> 1; +// lv_coord_t w_half1 = w_half0 + (w & 0x1); /*Compensate rounding error*/ +// +// +// int16_t other_mask_cnt = lv_draw_mask_get_cnt(); +// +// lv_area_t draw_area; +// draw_area.x1 = LV_MATH_MIN(point1->x, point2->x); +// draw_area.x2 = LV_MATH_MAX(point1->x, point2->x) - 1; +// draw_area.y1 = point1->y - w_half1; +// draw_area.y2 = point1->y + w_half0; +// +// /*If there is no mask then simply draw a rectangle*/ +// if(other_mask_cnt == 0) { +// lv_blend_fill(clip, &draw_area, +// style->line.color, NULL, LV_DRAW_MASK_RES_FULL_COVER,opa, +// LV_BLEND_MODE_NORMAL); +// } +// /*If there other mask apply it*/ +// else { +// /* Get clipped fill area which is the real draw area. +// * It is always the same or inside `fill_area` */ +// bool is_common; +// is_common = lv_area_intersect(&draw_area, clip, &draw_area); +// if(!is_common) return; +// +// /* Now `draw_area` has absolute coordinates. +// * Make it relative to `disp_area` to simplify draw to `disp_buf`*/ +// draw_area.x1 -= vdb->area.x1; +// draw_area.y1 -= vdb->area.y1; +// draw_area.x2 -= vdb->area.x1; +// draw_area.y2 -= vdb->area.y1; +// +// lv_coord_t draw_area_w = lv_area_get_width(&draw_area); +// +// lv_area_t fill_area; +// fill_area.x1 = draw_area.x1 + disp_area->x1; +// fill_area.x2 = draw_area.x2 + disp_area->x1; +// fill_area.y1 = draw_area.y1 + disp_area->y1; +// fill_area.y2 = fill_area.y1; +// +// lv_opa_t * mask_buf = lv_mem_buf_get(draw_area_w); +// lv_coord_t h; +// lv_draw_mask_res_t mask_res; +// for(h = draw_area.y1; h <= draw_area.y2; h++) { +// memset(mask_buf, LV_OPA_COVER, draw_area_w); +// mask_res = lv_draw_mask_apply(mask_buf, vdb->area.x1 + draw_area.x1, vdb->area.y1 + h, draw_area_w); +// +// lv_blend_fill(clip, &fill_area, +// style->line.color, mask_buf, mask_res, style->line.opa, +// style->line.blend_mode); +// +// fill_area.y1++; +// fill_area.y2++; +// } +// lv_mem_buf_release(mask_buf); +// } +//} +// +// +//static void draw_line_ver(const lv_point_t * point1, const lv_point_t * point2, const lv_area_t * clip, +// const lv_style_t * style, lv_opa_t opa_scale) +//{ +// lv_opa_t opa = style->line.opa; +// if(opa_scale != LV_OPA_COVER) opa = (opa * opa_scale) >> 8; +// +// lv_disp_t * disp = lv_refr_get_disp_refreshing(); +// lv_disp_buf_t * vdb = lv_disp_get_buf(disp); +// +// const lv_area_t * disp_area = &vdb->area; +// +// lv_coord_t w = style->line.width - 1; +// lv_coord_t w_half0 = w >> 1; +// lv_coord_t w_half1 = w_half0 + (w & 0x1); /*Compensate rounding error*/ +// +// +// int16_t other_mask_cnt = lv_draw_mask_get_cnt(); +// +// lv_area_t draw_area; +// draw_area.x1 = point1->x - w_half1; +// draw_area.x2 = point1->x + w_half0; +// draw_area.y1 = LV_MATH_MIN(point1->y, point2->y); +// draw_area.y2 = LV_MATH_MAX(point1->y, point2->y) - 1; +// +// /*If there is no mask then simply draw a rectangle*/ +// if(other_mask_cnt == 0) { +// +// lv_blend_fill(clip, &draw_area, +// style->line.color, NULL, LV_DRAW_MASK_RES_FULL_COVER, opa, +// style->line.blend_mode); +// } +// /*If there other mask apply it*/ +// else { +// /* Get clipped fill area which is the real draw area. +// * It is always the same or inside `fill_area` */ +// bool is_common; +// is_common = lv_area_intersect(&draw_area, clip, &draw_area); +// if(!is_common) return; +// +// /* Now `draw_area` has absolute coordinates. +// * Make it relative to `disp_area` to simplify draw to `disp_buf`*/ +// draw_area.x1 -= vdb->area.x1; +// draw_area.y1 -= vdb->area.y1; +// draw_area.x2 -= vdb->area.x1; +// draw_area.y2 -= vdb->area.y1; +// +// lv_coord_t draw_area_w = lv_area_get_width(&draw_area); +// +// lv_area_t fill_area; +// fill_area.x1 = draw_area.x1 + disp_area->x1; +// fill_area.x2 = draw_area.x2 + disp_area->x1; +// fill_area.y1 = draw_area.y1 + disp_area->y1; +// fill_area.y2 = fill_area.y1; +// +// lv_opa_t * mask_buf = lv_mem_buf_get(draw_area_w); +// lv_coord_t h; +// lv_draw_mask_res_t mask_res; +// for(h = draw_area.y1; h <= draw_area.y2; h++) { +// memset(mask_buf, LV_OPA_COVER, draw_area_w); +// mask_res = lv_draw_mask_apply(mask_buf, vdb->area.x1 + draw_area.x1, vdb->area.y1 + h, draw_area_w); +// +// lv_blend_fill(clip, &fill_area, +// style->line.color, mask_buf, mask_res, style->line.opa, +// LV_BLEND_MODE_NORMAL); +// +// fill_area.y1++; +// fill_area.y2++; +// } +// lv_mem_buf_release(mask_buf); +// } +//} +// +// +//static void draw_line_skew(const lv_point_t * point1, const lv_point_t * point2, const lv_area_t * clip, +// const lv_style_t * style, lv_opa_t opa_scale) +//{ +// lv_opa_t opa = style->line.opa; +// if(opa_scale != LV_OPA_COVER) opa = (opa * opa_scale) >> 8; +// +// /*Keep the great y in p1*/ +// lv_point_t p1; +// lv_point_t p2; +// if(point1->y < point2->y) { +// p1.y = point1->y; +// p2.y = point2->y; +// p1.x = point1->x; +// p2.x = point2->x; +// } else { +// p1.y = point2->y; +// p2.y = point1->y; +// p1.x = point2->x; +// p2.x = point1->x; +// } +// +// lv_coord_t xdiff = p2.x - p1.x; +// lv_coord_t ydiff = p2.y - p1.y; +// bool flat = LV_MATH_ABS(xdiff) > LV_MATH_ABS(ydiff) ? true : false; +// +// static const uint8_t wcorr[] = { +// 128, 128, 128, 129, 129, 130, 130, 131, +// 132, 133, 134, 135, 137, 138, 140, 141, +// 143, 145, 147, 149, 151, 153, 155, 158, +// 160, 162, 165, 167, 170, 173, 175, 178, +// 181, +// }; +// +// lv_coord_t w = style->line.width; +// lv_coord_t wcorr_i = 0; +// if(flat) wcorr_i = (LV_MATH_ABS(ydiff) << 5) / LV_MATH_ABS(xdiff); +// else wcorr_i = (LV_MATH_ABS(xdiff) << 5) / LV_MATH_ABS(ydiff); +// +// w = (w * wcorr[wcorr_i]) >> 7; +// lv_coord_t w_half0 = w >> 1; +// lv_coord_t w_half1 = w_half0 + (w & 0x1); /*Compensate rounding error*/ +// +// lv_area_t draw_area; +// draw_area.x1 = LV_MATH_MIN(p1.x, p2.x) - w; +// draw_area.x2 = LV_MATH_MAX(p1.x, p2.x) + w; +// draw_area.y1 = LV_MATH_MIN(p1.y, p2.y) - w; +// draw_area.y2 = LV_MATH_MAX(p1.y, p2.y) + w; +// +// /* Get the union of `coords` and `clip`*/ +// /* `clip` is already truncated to the `vdb` size +// * in 'lv_refr_area' function */ +// bool is_common = lv_area_intersect(&draw_area, &draw_area, clip); +// if(is_common == false) return; +// +// lv_draw_mask_line_param_t mask_left_param; +// lv_draw_mask_line_param_t mask_right_param; +// lv_draw_mask_line_param_t mask_top_param; +// lv_draw_mask_line_param_t mask_bottom_param; +// +// if(flat) { +// if(xdiff > 0) { +// lv_draw_mask_line_points_init(&mask_left_param, p1.x, p1.y - w_half0, p2.x, p2.y - w_half0, LV_DRAW_MASK_LINE_SIDE_LEFT); +// lv_draw_mask_line_points_init(&mask_right_param, p1.x, p1.y + w_half1, p2.x, p2.y + w_half1, LV_DRAW_MASK_LINE_SIDE_RIGHT); +// } else { +// lv_draw_mask_line_points_init(&mask_left_param, p1.x, p1.y + w_half1, p2.x, p2.y + w_half1, LV_DRAW_MASK_LINE_SIDE_LEFT); +// lv_draw_mask_line_points_init(&mask_right_param, p1.x, p1.y - w_half0, p2.x, p2.y - w_half0, LV_DRAW_MASK_LINE_SIDE_RIGHT); +// } +// } else { +// lv_draw_mask_line_points_init(&mask_left_param, p1.x + w_half1, p1.y, p2.x + w_half1, p2.y, LV_DRAW_MASK_LINE_SIDE_LEFT); +// lv_draw_mask_line_points_init(&mask_right_param, p1.x - w_half0, p1.y, p2.x - w_half0, p2.y, LV_DRAW_MASK_LINE_SIDE_RIGHT); +// } +// +// /*Use the normal vector for the endings*/ +// lv_draw_mask_line_points_init(&mask_top_param, p1.x, p1.y, p1.x - ydiff, p1.y + xdiff, LV_DRAW_MASK_LINE_SIDE_BOTTOM); +// lv_draw_mask_line_points_init(&mask_bottom_param, p2.x, p2.y,p2.x - ydiff, p2.y + xdiff, LV_DRAW_MASK_LINE_SIDE_TOP); +// +// int16_t mask_left_id = lv_draw_mask_add(&mask_left_param, NULL); +// int16_t mask_right_id = lv_draw_mask_add(&mask_right_param, NULL); +// int16_t mask_top_id = lv_draw_mask_add(&mask_top_param, NULL); +// int16_t mask_bottom_id = lv_draw_mask_add(&mask_bottom_param, NULL); +// +// lv_disp_t * disp = lv_refr_get_disp_refreshing(); +// lv_disp_buf_t * vdb = lv_disp_get_buf(disp); +// +// const lv_area_t * disp_area = &vdb->area; +// +// /*Store the coordinates of the `draw_a` relative to the VDB */ +// draw_area.x1 -= disp_area->x1; +// draw_area.y1 -= disp_area->y1; +// draw_area.x2 -= disp_area->x1; +// draw_area.y2 -= disp_area->y1; +// +// lv_coord_t draw_area_w = lv_area_get_width(&draw_area); +// +// /*Draw the background line by line*/ +// lv_coord_t h; +// lv_draw_mask_res_t mask_res; +// lv_opa_t * mask_buf = lv_mem_buf_get(draw_area_w); +// lv_area_t fill_area; +// fill_area.x1 = draw_area.x1 + disp_area->x1; +// fill_area.x2 = draw_area.x2 + disp_area->x1; +// fill_area.y1 = draw_area.y1 + disp_area->y1; +// fill_area.y2 = fill_area.y1; +// +// /*Fill the first row with 'color'*/ +// for(h = draw_area.y1; h <= draw_area.y2; h++) { +// memset(mask_buf, LV_OPA_COVER, draw_area_w); +// mask_res = lv_draw_mask_apply(mask_buf, vdb->area.x1 + draw_area.x1, vdb->area.y1 + h, draw_area_w); +// +// lv_blend_fill(clip, &fill_area, +// style->line.color, mask_buf, mask_res, opa, +// style->line.blend_mode); +// +// fill_area.y1++; +// fill_area.y2++; +// } +// +// lv_mem_buf_release(mask_buf); +// +// lv_draw_mask_remove_id(mask_left_id); +// lv_draw_mask_remove_id(mask_right_id); +// lv_draw_mask_remove_id(mask_top_id); +// lv_draw_mask_remove_id(mask_bottom_id); +//} diff --git a/src/lv_draw/lv_draw_rect.c b/src/lv_draw/lv_draw_rect.c index aa8f04cdf..ee3a04080 100644 --- a/src/lv_draw/lv_draw_rect.c +++ b/src/lv_draw/lv_draw_rect.c @@ -26,10 +26,10 @@ /********************** * STATIC PROTOTYPES **********************/ -static void draw_bg(const lv_area_t * coords, const lv_area_t * clip, const lv_style_t * style, lv_opa_t opa_scale); -static void draw_border(const lv_area_t * coords, const lv_area_t * clip, const lv_style_t * style, lv_opa_t opa_scale); -static void draw_shadow(const lv_area_t * coords, const lv_area_t * clip, const lv_style_t * style, lv_opa_t opa_scale); -static lv_color_t grad_get(const lv_style_t * style, lv_coord_t s, lv_coord_t i); +static void draw_bg(const lv_area_t * coords, const lv_area_t * clip, lv_draw_rect_dsc_t * dsc, lv_opa_t opa_scale); +static void draw_border(const lv_area_t * coords, const lv_area_t * clip, lv_draw_rect_dsc_t * dsc, lv_opa_t opa_scale); +static void draw_shadow(const lv_area_t * coords, const lv_area_t * clip, lv_draw_rect_dsc_t * dsc, lv_opa_t opa_scale); +static lv_color_t grad_get(lv_draw_rect_dsc_t * dsc, lv_coord_t s, lv_coord_t i); static void shadow_draw_corner_buf(const lv_area_t * coords, lv_opa_t * sh_buf, lv_coord_t s, lv_coord_t r); static void shadow_blur_corner(lv_coord_t size, lv_coord_t sw, lv_opa_t * res_buf, uint16_t * sh_ups_buf); @@ -45,6 +45,13 @@ static void shadow_blur_corner(lv_coord_t size, lv_coord_t sw, lv_opa_t * res_bu * GLOBAL FUNCTIONS **********************/ +void lv_draw_rect_dsc_init(lv_draw_rect_dsc_t * dsc) +{ + memset(dsc, 0x00, sizeof(lv_draw_rect_dsc_t)); + dsc->bg_opa = LV_OPA_COVER; + dsc->border_opa = LV_OPA_COVER; +} + /** * Draw a rectangle * @param coords the coordinates of the rectangle @@ -52,13 +59,13 @@ static void shadow_blur_corner(lv_coord_t size, lv_coord_t sw, lv_opa_t * res_bu * @param style pointer to a style * @param opa_scale scale down all opacities by the factor */ -void lv_draw_rect(const lv_area_t * coords, const lv_area_t * clip, const lv_style_t * style, lv_opa_t opa_scale) +void lv_draw_rect(const lv_area_t * coords, const lv_area_t * clip, lv_draw_rect_dsc_t * dsc, lv_opa_t opa_scale) { if(lv_area_get_height(coords) < 1 || lv_area_get_width(coords) < 1) return; - draw_shadow(coords, clip, style, opa_scale); - draw_bg(coords, clip, style, opa_scale); - draw_border(coords, clip, style, opa_scale); + draw_shadow(coords, clip, dsc, opa_scale); + draw_bg(coords, clip, dsc, opa_scale); + draw_border(coords, clip, dsc, opa_scale); } /** @@ -70,47 +77,47 @@ void lv_draw_rect(const lv_area_t * coords, const lv_area_t * clip, const lv_sty */ void lv_draw_px(const lv_point_t * point, const lv_area_t * clip_area, const lv_style_t * style, lv_opa_t opa_scale) { - lv_opa_t opa = style->body.opa; - if(opa_scale != LV_OPA_COVER) opa = (opa * opa_scale) >> 8; - - if(opa > LV_OPA_MAX) opa = LV_OPA_COVER; - - lv_area_t fill_area; - fill_area.x1 = point->x; - fill_area.y1 = point->y; - fill_area.x2 = point->x; - fill_area.y2 = point->y; - - uint8_t mask_cnt = lv_draw_mask_get_cnt(); - - if(mask_cnt == 0) { - lv_blend_fill(clip_area, &fill_area, style->body.main_color, NULL, LV_DRAW_MASK_RES_FULL_COVER, opa, style->body.blend_mode); - } else { - uint8_t mask_buf; - lv_draw_mask_res_t mask_res; - mask_res = lv_draw_mask_apply(&mask_buf, point->x, point->y, 1); - lv_blend_fill(clip_area, &fill_area, style->body.main_color, &mask_buf, mask_res, opa, style->body.blend_mode); - } +// lv_opa_t opa = style->body.opa; +// if(opa_scale != LV_OPA_COVER) opa = (opa * opa_scale) >> 8; +// +// if(opa > LV_OPA_MAX) opa = LV_OPA_COVER; +// +// lv_area_t fill_area; +// fill_area.x1 = point->x; +// fill_area.y1 = point->y; +// fill_area.x2 = point->x; +// fill_area.y2 = point->y; +// +// uint8_t mask_cnt = lv_draw_mask_get_cnt(); +// +// if(mask_cnt == 0) { +// lv_blend_fill(clip_area, &fill_area, style->body.main_color, NULL, LV_DRAW_MASK_RES_FULL_COVER, opa, style->body.blend_mode); +// } else { +// uint8_t mask_buf; +// lv_draw_mask_res_t mask_res; +// mask_res = lv_draw_mask_apply(&mask_buf, point->x, point->y, 1); +// lv_blend_fill(clip_area, &fill_area, style->body.main_color, &mask_buf, mask_res, opa, style->body.blend_mode); +// } } /********************** * STATIC FUNCTIONS **********************/ -static void draw_bg(const lv_area_t * coords, const lv_area_t * clip, const lv_style_t * style, lv_opa_t opa_scale) +static void draw_bg(const lv_area_t * coords, const lv_area_t * clip, lv_draw_rect_dsc_t * dsc, lv_opa_t opa_scale) { lv_area_t coords_bg; lv_area_copy(&coords_bg, coords); /*If the border fully covers make the bg area 1px smaller to avoid artifacts on the corners*/ - if(style->body.border.width > 1 && style->body.border.opa >= LV_OPA_MAX && style->body.radius != 0) { + if(dsc->border_width > 1 && dsc->border_opa >= LV_OPA_MAX && dsc->radius != 0) { coords_bg.x1++; coords_bg.y1++; coords_bg.x2--; coords_bg.y2--; } - lv_opa_t opa = style->body.opa; + lv_opa_t opa = dsc->bg_opa; if(opa_scale != LV_OPA_COVER) opa = (opa * opa_scale) >> 8; if(opa > LV_OPA_MAX) opa = LV_OPA_COVER; @@ -141,8 +148,8 @@ static void draw_bg(const lv_area_t * coords, const lv_area_t * clip, const lv_s bool simple_mode = true; if(lv_draw_mask_get_cnt()!= 0) simple_mode = false; - else if(style->body.border.part != LV_BORDER_PART_FULL) simple_mode = false; - else if(style->body.grad_dir == LV_GRAD_DIR_HOR) simple_mode = false; + else if(dsc->border_part != LV_BORDER_PART_FULL) simple_mode = false; + else if(dsc->bg_grad_dir == LV_GRAD_DIR_HOR) simple_mode = false; int16_t mask_rout_id = LV_MASK_ID_INV; @@ -150,15 +157,15 @@ static void draw_bg(const lv_area_t * coords, const lv_area_t * clip, const lv_s lv_coord_t coords_h = lv_area_get_height(&coords_bg); /*Get the real radius*/ - lv_coord_t rout = style->body.radius; + lv_coord_t rout = dsc->radius; lv_coord_t short_side = LV_MATH_MIN(coords_w, coords_h); if(rout > short_side >> 1) rout = short_side >> 1; /*Most simple case: just a plain rectangle*/ - if(simple_mode && rout == 0 && style->body.main_color.full == style->body.grad_color.full) { + if(simple_mode && rout == 0 && dsc->bg_color.full == dsc->bg_grad_color.full) { lv_blend_fill(clip, &coords_bg, - style->body.main_color, NULL, LV_DRAW_MASK_RES_FULL_COVER, opa, - style->body.blend_mode); + dsc->bg_color, NULL, LV_DRAW_MASK_RES_FULL_COVER, opa, + dsc->bg_blend_mode); } /*More complex case: there is a radius, gradient or mask.*/ else { @@ -172,17 +179,17 @@ static void draw_bg(const lv_area_t * coords, const lv_area_t * clip, const lv_s /*Draw the background line by line*/ lv_coord_t h; lv_draw_mask_res_t mask_res = LV_DRAW_MASK_RES_FULL_COVER; - lv_color_t grad_color = style->body.main_color; + lv_color_t grad_color = dsc->bg_color; lv_color_t * grad_map = NULL; /*In case of horizontal gradient pre-compute a line with a gradient*/ - if(style->body.grad_dir == LV_GRAD_DIR_HOR && style->body.main_color.full != style->body.grad_color.full) { + if(dsc->bg_grad_dir == LV_GRAD_DIR_HOR && dsc->bg_color.full != dsc->bg_grad_color.full) { grad_map = lv_mem_buf_get(coords_w * sizeof(lv_color_t)); lv_coord_t i; for(i = 0; i < coords_w; i++) { - grad_map[i] = grad_get(style, coords_w, i); + grad_map[i] = grad_get(dsc, coords_w, i); } } @@ -210,8 +217,8 @@ static void draw_bg(const lv_area_t * coords, const lv_area_t * clip, const lv_s } /*Get the current line color*/ - if(style->body.grad_dir == LV_GRAD_DIR_VER && style->body.main_color.full != style->body.grad_color.full) { - grad_color = grad_get(style, lv_area_get_height(&coords_bg), y - coords_bg.y1); + if(dsc->bg_grad_dir == LV_GRAD_DIR_VER && dsc->bg_color.full != dsc->bg_grad_color.full) { + grad_color = grad_get(dsc, lv_area_get_height(&coords_bg), y - coords_bg.y1); } /* If there is not other mask and drawing the corner area split the drawing to corner and middle areas @@ -228,7 +235,7 @@ static void draw_bg(const lv_area_t * coords, const lv_area_t * clip, const lv_s fill_area2.y2 = fill_area.y2; lv_blend_fill(clip, &fill_area2, - grad_color, mask_buf, mask_res, opa, style->body.blend_mode); + grad_color, mask_buf, mask_res, opa, dsc->bg_blend_mode); /*Central part*/ @@ -236,7 +243,7 @@ static void draw_bg(const lv_area_t * coords, const lv_area_t * clip, const lv_s fill_area2.x2 = coords_bg.x2 - rout; lv_blend_fill(clip, &fill_area2, - grad_color, NULL, LV_DRAW_MASK_RES_FULL_COVER, opa, style->body.blend_mode); + grad_color, NULL, LV_DRAW_MASK_RES_FULL_COVER, opa, dsc->bg_blend_mode); fill_area2.x1 = coords_bg.x2 - rout + 1; fill_area2.x2 = coords_bg.x2; @@ -244,13 +251,13 @@ static void draw_bg(const lv_area_t * coords, const lv_area_t * clip, const lv_s lv_coord_t mask_ofs = (coords_bg.x2 - rout + 1) - (vdb->area.x1 + draw_area.x1); if(mask_ofs < 0) mask_ofs = 0; lv_blend_fill(clip, &fill_area2, - grad_color, mask_buf + mask_ofs, mask_res, opa, style->body.blend_mode); + grad_color, mask_buf + mask_ofs, mask_res, opa, dsc->bg_blend_mode); } else { if(grad_map == NULL) { lv_blend_fill(clip, &fill_area, - grad_color,mask_buf, mask_res, opa, style->body.blend_mode); + grad_color,mask_buf, mask_res, opa, dsc->bg_blend_mode); } else { - lv_blend_map(clip, &fill_area, grad_map, mask_buf, mask_res, opa, style->body.blend_mode); + lv_blend_map(clip, &fill_area, grad_map, mask_buf, mask_res, opa, dsc->bg_blend_mode); } } @@ -268,12 +275,12 @@ static void draw_bg(const lv_area_t * coords, const lv_area_t * clip, const lv_s } -static void draw_border(const lv_area_t * coords, const lv_area_t * clip, const lv_style_t * style, lv_opa_t opa_scale) +static void draw_border(const lv_area_t * coords, const lv_area_t * clip, lv_draw_rect_dsc_t * dsc, lv_opa_t opa_scale) { - lv_coord_t border_width = style->body.border.width; + lv_coord_t border_width = dsc->border_width; if(border_width == 0) return; - lv_opa_t opa = style->body.border.opa; + lv_opa_t opa = dsc->border_opa; if(opa_scale != LV_OPA_COVER) opa = (opa * opa_scale) >> 8; if(opa > LV_OPA_MAX) opa = LV_OPA_COVER; @@ -304,8 +311,8 @@ static void draw_border(const lv_area_t * coords, const lv_area_t * clip, const bool simple_mode = true; if(lv_draw_mask_get_cnt()!= 0) simple_mode = false; - else if(style->body.border.part != LV_BORDER_PART_FULL) simple_mode = false; - else if(style->body.grad_dir == LV_GRAD_DIR_HOR) simple_mode = false; + else if(dsc->border_part != LV_BORDER_PART_FULL) simple_mode = false; + else if(dsc->bg_grad_dir == LV_GRAD_DIR_HOR) simple_mode = false; int16_t mask_rout_id = LV_MASK_ID_INV; @@ -313,7 +320,7 @@ static void draw_border(const lv_area_t * coords, const lv_area_t * clip, const lv_coord_t coords_h = lv_area_get_height(coords); /*Get the real radius*/ - lv_coord_t rout = style->body.radius; + lv_coord_t rout = dsc->radius; lv_coord_t short_side = LV_MATH_MIN(coords_w, coords_h); if(rout > short_side >> 1) rout = short_side >> 1; @@ -332,10 +339,10 @@ static void draw_border(const lv_area_t * coords, const lv_area_t * clip, const /*Get the inner area*/ lv_area_t area_small; lv_area_copy(&area_small, coords); - area_small.x1 += ((style->body.border.part & LV_BORDER_PART_LEFT) ? border_width : - (border_width + rout)); - area_small.x2 -= ((style->body.border.part & LV_BORDER_PART_RIGHT) ? border_width : - (border_width + rout)); - area_small.y1 += ((style->body.border.part & LV_BORDER_PART_TOP) ? border_width : - (border_width + rout)); - area_small.y2 -= ((style->body.border.part & LV_BORDER_PART_BOTTOM) ? border_width : - (border_width + rout)); + area_small.x1 += ((dsc->border_part & LV_BORDER_PART_LEFT) ? border_width : - (border_width + rout)); + area_small.x2 -= ((dsc->border_part & LV_BORDER_PART_RIGHT) ? border_width : - (border_width + rout)); + area_small.y1 += ((dsc->border_part & LV_BORDER_PART_TOP) ? border_width : - (border_width + rout)); + area_small.y2 -= ((dsc->border_part & LV_BORDER_PART_BOTTOM) ? border_width : - (border_width + rout)); /*Create inner the mask*/ lv_draw_mask_radius_param_t mask_rin_param; @@ -348,6 +355,9 @@ static void draw_border(const lv_area_t * coords, const lv_area_t * clip, const lv_draw_mask_res_t mask_res; lv_area_t fill_area; + lv_color_t color = dsc->border_color; + lv_blend_mode_t blend_mode = dsc->border_blend_mode; + /*Apply some optimization if there is no other mask*/ if(simple_mode) { /*Draw the upper corner area*/ @@ -368,15 +378,13 @@ static void draw_border(const lv_area_t * coords, const lv_area_t * clip, const fill_area2.x1 = coords->x1; fill_area2.x2 = coords->x1 + rout - 1; - lv_blend_fill(clip, &fill_area2, - style->body.border.color, mask_buf, mask_res, opa, style->body.border.blend_mode); + lv_blend_fill(clip, &fill_area2, color, mask_buf, mask_res, opa, blend_mode); - if(fill_area2.y2 < coords->y1 + style->body.border.width) { + if(fill_area2.y2 < coords->y1 + border_width) { fill_area2.x1 = coords->x1 + rout; fill_area2.x2 = coords->x2 - rout; - lv_blend_fill(clip, &fill_area2, - style->body.border.color, NULL, LV_DRAW_MASK_RES_FULL_COVER, opa, style->body.border.blend_mode); + lv_blend_fill(clip, &fill_area2, color, NULL, LV_DRAW_MASK_RES_FULL_COVER, opa, blend_mode); } fill_area2.x1 = coords->x2 - rout + 1; @@ -384,15 +392,14 @@ static void draw_border(const lv_area_t * coords, const lv_area_t * clip, const lv_coord_t mask_ofs = (coords->x2 - rout + 1) - (vdb->area.x1 + draw_area.x1); if(mask_ofs < 0) mask_ofs = 0; - lv_blend_fill(clip, &fill_area2, - style->body.border.color, mask_buf + mask_ofs, mask_res, opa, style->body.border.blend_mode); + lv_blend_fill(clip, &fill_area2, color, mask_buf + mask_ofs, mask_res, opa, blend_mode); fill_area.y1++; fill_area.y2++; } /*Draw the lower corner area corner area*/ - if(style->body.border.part & LV_BORDER_PART_BOTTOM) { + if(dsc->border_part & LV_BORDER_PART_BOTTOM) { lv_coord_t lower_corner_end = coords->y2 - disp_area->y1 - corner_size; if(lower_corner_end <= upper_corner_end) lower_corner_end = upper_corner_end + 1; fill_area.y1 = disp_area->y1 + lower_corner_end; @@ -407,24 +414,21 @@ static void draw_border(const lv_area_t * coords, const lv_area_t * clip, const fill_area2.y1 = fill_area.y1; fill_area2.y2 = fill_area.y2; - lv_blend_fill(clip, &fill_area2, - style->body.border.color, mask_buf, mask_res, opa, style->body.border.blend_mode); + lv_blend_fill(clip, &fill_area2, color, mask_buf, mask_res, opa, blend_mode); - if(fill_area2.y2 > coords->y2 - style->body.border.width ) { + if(fill_area2.y2 > coords->y2 - border_width ) { fill_area2.x1 = coords->x1 + rout; fill_area2.x2 = coords->x2 - rout; - lv_blend_fill(clip, &fill_area2, - style->body.border.color, NULL, LV_DRAW_MASK_RES_FULL_COVER, opa, style->body.border.blend_mode); + lv_blend_fill(clip, &fill_area2, color, NULL, LV_DRAW_MASK_RES_FULL_COVER, opa, blend_mode); } fill_area2.x1 = coords->x2 - rout + 1; fill_area2.x2 = coords->x2; lv_coord_t mask_ofs = (coords->x2 - rout + 1) - (vdb->area.x1 + draw_area.x1); if(mask_ofs < 0) mask_ofs = 0; - lv_blend_fill(clip, &fill_area2, - style->body.border.color, mask_buf + mask_ofs, mask_res, opa, style->body.border.blend_mode); + lv_blend_fill(clip, &fill_area2, color, mask_buf + mask_ofs, mask_res, opa, blend_mode); fill_area.y1++; @@ -438,15 +442,13 @@ static void draw_border(const lv_area_t * coords, const lv_area_t * clip, const fill_area.x1 = coords->x1; fill_area.x2 = coords->x1 + border_width - 1; - lv_blend_fill(clip, &fill_area, - style->body.border.color, NULL, LV_DRAW_MASK_RES_FULL_COVER, opa, style->body.border.blend_mode); + lv_blend_fill(clip, &fill_area, color, NULL, LV_DRAW_MASK_RES_FULL_COVER, opa, blend_mode); /*Draw the right vertical border*/ fill_area.x1 = coords->x2 - border_width + 1; fill_area.x2 = coords->x2; - lv_blend_fill(clip, &fill_area, - style->body.border.color, NULL, LV_DRAW_MASK_RES_FULL_COVER, opa, style->body.border.blend_mode); + lv_blend_fill(clip, &fill_area, color, NULL, LV_DRAW_MASK_RES_FULL_COVER, opa, blend_mode); } /*Process line by line if there is other mask too*/ else { @@ -458,8 +460,7 @@ static void draw_border(const lv_area_t * coords, const lv_area_t * clip, const memset(mask_buf, LV_OPA_COVER, draw_area_w); mask_res = lv_draw_mask_apply(mask_buf, vdb->area.x1 + draw_area.x1, vdb->area.y1 + h, draw_area_w); - lv_blend_fill( clip, &fill_area, - style->body.border.color, mask_buf, mask_res, opa, style->body.border.blend_mode); + lv_blend_fill( clip, &fill_area, color, mask_buf, mask_res, opa, blend_mode); fill_area.y1++; fill_area.y2++; @@ -471,399 +472,399 @@ static void draw_border(const lv_area_t * coords, const lv_area_t * clip, const lv_mem_buf_release(mask_buf); } -static lv_color_t grad_get(const lv_style_t * style, lv_coord_t s, lv_coord_t i) +static lv_color_t grad_get(lv_draw_rect_dsc_t * dsc, lv_coord_t s, lv_coord_t i) { - lv_coord_t min = (style->body.main_color_stop * s) >> 8; - if(i <= min) return style->body.main_color; - - lv_coord_t max = (style->body.grad_color_stop * s) >> 8; - if(i >= max) return style->body.grad_color; - - lv_coord_t d = style->body.grad_color_stop - style->body.main_color_stop; - d = (s * d) >> 8; - i -= min; - lv_opa_t mix = (i * 255) / d; - return lv_color_mix(style->body.grad_color, style->body.main_color, mix); +// lv_coord_t min = (style->body.main_color_stop * s) >> 8; +// if(i <= min) return style->body.main_color; +// +// lv_coord_t max = (style->body.grad_color_stop * s) >> 8; +// if(i >= max) return style->body.grad_color; +// +// lv_coord_t d = style->body.grad_color_stop - style->body.main_color_stop; +// d = (s * d) >> 8; +// i -= min; +// lv_opa_t mix = (i * 255) / d; +// return lv_color_mix(style->body.grad_color, style->body.main_color, mix); } -static void draw_shadow(const lv_area_t * coords, const lv_area_t * clip, const lv_style_t * style, lv_opa_t opa_scale) +static void draw_shadow(const lv_area_t * coords, const lv_area_t * clip, lv_draw_rect_dsc_t * dsc, lv_opa_t opa_scale) { - /*Check whether the shadow is visible*/ - if(style->body.shadow.width == 0) return; - - if(style->body.shadow.width == 1 && style->body.shadow.offset.x == 0 && - style->body.shadow.offset.y == 0 && style->body.shadow.spread <= 0) { - return; - } - - lv_coord_t sw = style->body.shadow.width; - - lv_area_t sh_rect_area; - sh_rect_area.x1 = coords->x1 + style->body.shadow.offset.x - style->body.shadow.spread; - sh_rect_area.x2 = coords->x2 + style->body.shadow.offset.x + style->body.shadow.spread; - sh_rect_area.y1 = coords->y1 + style->body.shadow.offset.y - style->body.shadow.spread; - sh_rect_area.y2 = coords->y2 + style->body.shadow.offset.y + style->body.shadow.spread; - - lv_area_t sh_area; - sh_area.x1 = sh_rect_area.x1 - sw / 2 - 1; - sh_area.x2 = sh_rect_area.x2 + sw / 2 + 1; - sh_area.y1 = sh_rect_area.y1 - sw / 2 - 1; - sh_area.y2 = sh_rect_area.y2 + sw / 2 + 1; - - lv_opa_t opa = style->body.shadow.opa; - - if(opa_scale != LV_OPA_COVER) opa = (opa * opa_scale) >> 8; - - if(opa > LV_OPA_MAX) opa = LV_OPA_COVER; - - lv_disp_t * disp = lv_refr_get_disp_refreshing(); - lv_disp_buf_t * vdb = lv_disp_get_buf(disp); - - /* Get clipped fill area which is the real draw area. - * It is always the same or inside `fill_area` */ - lv_area_t draw_area; - bool is_common; - is_common = lv_area_intersect(&draw_area, &sh_area, clip); - if(is_common == false) return; - - const lv_area_t * disp_area = &vdb->area; - - /* Now `draw_area` has absolute coordinates. - * Make it relative to `disp_area` to simplify draw to `disp_buf`*/ - draw_area.x1 -= disp_area->x1; - draw_area.y1 -= disp_area->y1; - draw_area.x2 -= disp_area->x1; - draw_area.y2 -= disp_area->y1; - - /*Consider 1 px smaller bg to be sure the edge will be covered by the shadow*/ - lv_area_t bg_coords; - lv_area_copy(&bg_coords, coords); - bg_coords.x1 += 1; - bg_coords.y1 += 1; - bg_coords.x2 -= 1; - bg_coords.y2 -= 1; - - /*Get the real radius*/ - lv_coord_t r_bg = style->body.radius; - lv_coord_t short_side = LV_MATH_MIN(lv_area_get_width(&bg_coords), lv_area_get_height(&bg_coords)); - if(r_bg > short_side >> 1) r_bg = short_side >> 1; - - lv_coord_t r_sh = style->body.radius; - short_side = LV_MATH_MIN(lv_area_get_width(&sh_rect_area), lv_area_get_height(&sh_rect_area)); - if(r_sh > short_side >> 1) r_sh = short_side >> 1; - - - lv_coord_t corner_size = sw + r_sh; - - lv_opa_t * sh_buf = lv_mem_buf_get(corner_size * corner_size); - shadow_draw_corner_buf(&sh_rect_area, sh_buf, style->body.shadow.width, r_sh); - - bool simple_mode = true; - if(lv_draw_mask_get_cnt() > 0) simple_mode = false; - else if(style->body.shadow.offset.x != 0 || style->body.shadow.offset.y != 0) simple_mode = false; - else if(style->body.shadow.spread != 0) simple_mode = false; - - lv_coord_t y_max; - - /*Create a mask*/ - lv_draw_mask_res_t mask_res; - lv_opa_t * mask_buf = lv_mem_buf_get(lv_area_get_width(&sh_rect_area)); - - lv_draw_mask_radius_param_t mask_rout_param; - lv_draw_mask_radius_init(&mask_rout_param, &bg_coords, r_bg, true); - - int16_t mask_rout_id = LV_MASK_ID_INV; - mask_rout_id = lv_draw_mask_add(&mask_rout_param, NULL); - - lv_area_t a; - - /*Draw the top right corner*/ - a.x2 = sh_area.x2; - a.x1 = a.x2 - corner_size + 1; - a.y1 = sh_area.y1; - a.y2 = a.y1; - - lv_coord_t first_px; - first_px = 0; - if(disp_area->x1 > a.x1) { - first_px = disp_area->x1 - a.x1; - } - - lv_coord_t hor_mid_dist = (sh_area.x1 + lv_area_get_width(&sh_area) / 2) - (a.x1 + first_px); - if(hor_mid_dist > 0) { - first_px += hor_mid_dist; - } - a.x1 += first_px; - - lv_coord_t ver_mid_dist = (a.y1 + corner_size) - (sh_area.y1 + lv_area_get_height(&sh_area) / 2); - lv_coord_t ver_mid_corr = 0; - if(ver_mid_dist <= 0) ver_mid_dist = 0; - else { - if(lv_area_get_height(&sh_area) & 0x1) ver_mid_corr = 1; - } - lv_opa_t * sh_buf_tmp = sh_buf; - - lv_coord_t y; - for(y = 0; y < corner_size - ver_mid_dist + ver_mid_corr; y++) { - memcpy(mask_buf, sh_buf_tmp, corner_size); - mask_res = lv_draw_mask_apply(mask_buf + first_px, a.x1, a.y1, lv_area_get_width(&a)); - if(mask_res == LV_DRAW_MASK_RES_FULL_COVER) mask_res = LV_DRAW_MASK_RES_CHANGED; - - lv_blend_fill(clip, &a, - style->body.shadow.color, mask_buf + first_px, mask_res, opa, style->body.shadow.blend_mode); - a.y1++; - a.y2++; - sh_buf_tmp += corner_size; - } - - /*Draw the bottom right corner*/ - a.y1 = sh_area.y2; - a.y2 = a.y1; - - sh_buf_tmp = sh_buf ; - - for(y = 0; y < corner_size - ver_mid_dist; y++) { - memcpy(mask_buf, sh_buf_tmp, corner_size); - mask_res = lv_draw_mask_apply(mask_buf + first_px, a.x1, a.y1, lv_area_get_width(&a)); - if(mask_res == LV_DRAW_MASK_RES_FULL_COVER) mask_res = LV_DRAW_MASK_RES_CHANGED; - - lv_blend_fill(clip, &a, - style->body.shadow.color, mask_buf + first_px, mask_res, opa, style->body.shadow.blend_mode); - a.y1--; - a.y2--; - sh_buf_tmp += corner_size; - } - - /*Fill the right side*/ - a.y1 = sh_area.y1 + corner_size; - a.y2 = a.y1; - sh_buf_tmp = sh_buf + corner_size * (corner_size - 1); - - lv_coord_t x; - - if(simple_mode) { - /*Draw vertical lines*/ - lv_area_t va; - va.x1 = a.x1; - va.x2 = a.x1; - va.y1 = sh_area.y1 + corner_size; - va.y2 = sh_area.y2 - corner_size; - - if(va.y1 <= va.y2) { - for(x = a.x1; x < a.x2; x++) { - if(x > coords->x2) { - lv_opa_t opa_tmp = sh_buf_tmp[x - a.x1 + first_px]; - if(opa_tmp != LV_OPA_COVER || opa != LV_OPA_COVER) opa_tmp = (opa * opa_tmp) >> 8; - lv_blend_fill(clip, &va, - style->body.shadow.color, NULL, LV_DRAW_MASK_RES_FULL_COVER, opa_tmp, style->body.shadow.blend_mode); - } - va.x1++; - va.x2++; - } - } - } - else { - for(y = corner_size; y < lv_area_get_height(&sh_area) - corner_size; y++) { - memcpy(mask_buf, sh_buf_tmp, corner_size); - mask_res = lv_draw_mask_apply(mask_buf + first_px, a.x1, a.y1, lv_area_get_width(&a)); - if(mask_res == LV_DRAW_MASK_RES_FULL_COVER) mask_res = LV_DRAW_MASK_RES_CHANGED; - - lv_blend_fill(clip, &a, - style->body.shadow.color, mask_buf+first_px, mask_res, opa, style->body.shadow.blend_mode); - a.y1++; - a.y2++; - } - } - - /*Invert the shadow corner buffer and draw the corners on the left*/ - sh_buf_tmp = sh_buf ; - for(y = 0; y < corner_size; y++) { - for(x = 0; x < corner_size / 2; x++) { - lv_opa_t tmp = sh_buf_tmp[x]; - sh_buf_tmp[x] = sh_buf_tmp[corner_size - x - 1]; - sh_buf_tmp[corner_size - x - 1] = tmp; - } - sh_buf_tmp += corner_size; - } - - /*Draw the top left corner*/ - a.x1 = sh_area.x1; - a.x2 = a.x1 + corner_size - 1; - a.y1 = sh_area.y1; - a.y2 = a.y1; - - if(a.x2 > sh_area.x1 + lv_area_get_width(&sh_area)/2 - 1) { - a.x2 = sh_area.x1 + lv_area_get_width(&sh_area)/2 -1 ; - } - - first_px = 0; - if(disp_area->x1 >= a.x1) { - first_px = disp_area->x1 - a.x1; - a.x1 += first_px; - } - - sh_buf_tmp = sh_buf ; - for(y = 0; y < corner_size - ver_mid_dist + ver_mid_corr; y++) { - memcpy(mask_buf, sh_buf_tmp, corner_size); - mask_res = lv_draw_mask_apply(mask_buf + first_px, a.x1, a.y1, lv_area_get_width(&a)); - if(mask_res == LV_DRAW_MASK_RES_FULL_COVER) mask_res = LV_DRAW_MASK_RES_CHANGED; - - lv_blend_fill(clip, &a, - style->body.shadow.color, mask_buf + first_px, mask_res, opa, style->body.shadow.blend_mode); - a.y1++; - a.y2++; - sh_buf_tmp += corner_size; - } - - /*Draw the bottom left corner*/ - a.y1 = sh_area.y2; - a.y2 = a.y1; - - sh_buf_tmp = sh_buf ; - - for(y = 0; y < corner_size - ver_mid_dist; y++) { - memcpy(mask_buf, sh_buf_tmp, corner_size); - mask_res = lv_draw_mask_apply(mask_buf + first_px, a.x1, a.y1, lv_area_get_width(&a)); - if(mask_res == LV_DRAW_MASK_RES_FULL_COVER) mask_res = LV_DRAW_MASK_RES_CHANGED; - - lv_blend_fill(clip, &a, - style->body.shadow.color, mask_buf + first_px, mask_res, opa, style->body.shadow.blend_mode); - a.y1--; - a.y2--; - sh_buf_tmp += corner_size; - } - - /*Fill the left side*/ - a.y1 = sh_area.y1+corner_size; - a.y2 = a.y1; - - sh_buf_tmp = sh_buf + corner_size * (corner_size - 1); - - if(simple_mode) { - /*Draw vertical lines*/ - lv_area_t va; - va.x1 = a.x1; - va.x2 = a.x1; - va.y1 = sh_area.y1 + corner_size; - va.y2 = sh_area.y2 - corner_size; - - if(va.y1 <= va.y2) { - for(x = a.x1; x < coords->x1; x++) { - lv_opa_t opa_tmp = sh_buf_tmp[x - a.x1 + first_px]; - if(opa_tmp != LV_OPA_COVER || opa != LV_OPA_COVER) opa_tmp = (opa * opa_tmp) >> 8; - lv_blend_fill(clip, &va, - style->body.shadow.color, NULL, LV_DRAW_MASK_RES_FULL_COVER, opa_tmp, style->body.shadow.blend_mode); - va.x1++; - va.x2++; - } - } - } - else { - for(y = corner_size; y < lv_area_get_height(&sh_area) - corner_size; y++) { - memcpy(mask_buf, sh_buf_tmp, corner_size); - mask_res = lv_draw_mask_apply(mask_buf + first_px, a.x1, a.y1, lv_area_get_width(&a)); - if(mask_res == LV_DRAW_MASK_RES_FULL_COVER) mask_res = LV_DRAW_MASK_RES_CHANGED; - - lv_blend_fill(clip, &a, - style->body.shadow.color, mask_buf + first_px, mask_res, opa, style->body.shadow.blend_mode); - a.y1++; - a.y2++; - } - } - - /*Fill the top side*/ - - a.x1 = sh_area.x1 + corner_size; - a.x2 = sh_area.x2 - corner_size; - a.y1 = sh_area.y1; - a.y2 = a.y1; - - - first_px = 0; - if(disp_area->x1 > a.x1) { - first_px = disp_area->x1 - a.x1; - a.x1 += first_px; - } - - if(a.x1 <= a.x2) { - - sh_buf_tmp = sh_buf + corner_size - 1; - - y_max = corner_size - ver_mid_dist; - if(simple_mode) { - y_max = sw / 2 + 1; - if(y_max > corner_size - ver_mid_dist) y_max = corner_size - ver_mid_dist; - } - - for(y = 0; y < y_max; y++) { - if(simple_mode == false) { - memset(mask_buf, sh_buf_tmp[0], lv_area_get_width(&a)); - mask_res = lv_draw_mask_apply(mask_buf, a.x1, a.y1, lv_area_get_width(&a)); - if(mask_res == LV_DRAW_MASK_RES_FULL_COVER) mask_res = LV_DRAW_MASK_RES_CHANGED; - - lv_blend_fill(clip, &a, - style->body.shadow.color, mask_buf, mask_res, opa, style->body.shadow.blend_mode); - } else { - - lv_opa_t opa_tmp = sh_buf_tmp[0]; - if(opa_tmp != LV_OPA_COVER || opa != LV_OPA_COVER) opa_tmp = (opa * opa_tmp) >> 8; - lv_blend_fill(clip, &a, - style->body.shadow.color, NULL, LV_DRAW_MASK_RES_FULL_COVER, opa_tmp, style->body.shadow.blend_mode); - } - - a.y1++; - a.y2++; - sh_buf_tmp += corner_size; - } - - /*Fill the bottom side*/ - lv_coord_t y_min = simple_mode ? (corner_size - (sh_area.y2 - coords->y2)) : ver_mid_dist; - if(y_min < 0) y_min = 0; - sh_buf_tmp = sh_buf + corner_size * (corner_size - y_min - 1 ) + corner_size - 1; - - a.y1 = sh_area.y2 - corner_size + 1 + y_min; - a.y2 = a.y1; - - for(y = y_min; y < corner_size; y++) { - if(simple_mode == false) { - memset(mask_buf, sh_buf_tmp[0], lv_area_get_width(&a)); - mask_res = lv_draw_mask_apply(mask_buf, a.x1, a.y1, lv_area_get_width(&a)); - if(mask_res == LV_DRAW_MASK_RES_FULL_COVER) mask_res = LV_DRAW_MASK_RES_CHANGED; - lv_blend_fill(clip, &a, - style->body.shadow.color, mask_buf, mask_res, opa, style->body.shadow.blend_mode); - } else { - lv_opa_t opa_tmp = sh_buf_tmp[0]; - if(opa_tmp != LV_OPA_COVER || opa != LV_OPA_COVER) opa_tmp = (opa * opa_tmp) >> 8; - lv_blend_fill(clip, &a, - style->body.shadow.color, NULL, LV_DRAW_MASK_RES_FULL_COVER, opa_tmp, style->body.shadow.blend_mode); - } - - a.y1++; - a.y2++; - sh_buf_tmp -= corner_size; - } - } - - /*Finally fill the middle area*/ - if(simple_mode == false) { - a.y1 = sh_area.y1 + corner_size; - a.y2 = a.y1; - if(a.x1 <= a.x2) { - for(y = 0; y < lv_area_get_height(&sh_area) - corner_size * 2; y++) { - memset(mask_buf, 0xFF, lv_area_get_width(&a)); - mask_res = lv_draw_mask_apply(mask_buf, a.x1, a.y1, lv_area_get_width(&a)); - lv_blend_fill(clip, &a, - style->body.shadow.color, mask_buf, mask_res, opa, style->body.shadow.blend_mode); - - a.y1++; - a.y2++; - } - } - } - - lv_draw_mask_remove_id(mask_rout_id); - lv_mem_buf_release(mask_buf); - lv_mem_buf_release(sh_buf); +// /*Check whether the shadow is visible*/ +// if(style->body.shadow.width == 0) return; +// +// if(style->body.shadow.width == 1 && style->body.shadow.offset.x == 0 && +// style->body.shadow.offset.y == 0 && style->body.shadow.spread <= 0) { +// return; +// } +// +// lv_coord_t sw = style->body.shadow.width; +// +// lv_area_t sh_rect_area; +// sh_rect_area.x1 = coords->x1 + style->body.shadow.offset.x - style->body.shadow.spread; +// sh_rect_area.x2 = coords->x2 + style->body.shadow.offset.x + style->body.shadow.spread; +// sh_rect_area.y1 = coords->y1 + style->body.shadow.offset.y - style->body.shadow.spread; +// sh_rect_area.y2 = coords->y2 + style->body.shadow.offset.y + style->body.shadow.spread; +// +// lv_area_t sh_area; +// sh_area.x1 = sh_rect_area.x1 - sw / 2 - 1; +// sh_area.x2 = sh_rect_area.x2 + sw / 2 + 1; +// sh_area.y1 = sh_rect_area.y1 - sw / 2 - 1; +// sh_area.y2 = sh_rect_area.y2 + sw / 2 + 1; +// +// lv_opa_t opa = style->body.shadow.opa; +// +// if(opa_scale != LV_OPA_COVER) opa = (opa * opa_scale) >> 8; +// +// if(opa > LV_OPA_MAX) opa = LV_OPA_COVER; +// +// lv_disp_t * disp = lv_refr_get_disp_refreshing(); +// lv_disp_buf_t * vdb = lv_disp_get_buf(disp); +// +// /* Get clipped fill area which is the real draw area. +// * It is always the same or inside `fill_area` */ +// lv_area_t draw_area; +// bool is_common; +// is_common = lv_area_intersect(&draw_area, &sh_area, clip); +// if(is_common == false) return; +// +// const lv_area_t * disp_area = &vdb->area; +// +// /* Now `draw_area` has absolute coordinates. +// * Make it relative to `disp_area` to simplify draw to `disp_buf`*/ +// draw_area.x1 -= disp_area->x1; +// draw_area.y1 -= disp_area->y1; +// draw_area.x2 -= disp_area->x1; +// draw_area.y2 -= disp_area->y1; +// +// /*Consider 1 px smaller bg to be sure the edge will be covered by the shadow*/ +// lv_area_t bg_coords; +// lv_area_copy(&bg_coords, coords); +// bg_coords.x1 += 1; +// bg_coords.y1 += 1; +// bg_coords.x2 -= 1; +// bg_coords.y2 -= 1; +// +// /*Get the real radius*/ +// lv_coord_t r_bg = style->body.radius; +// lv_coord_t short_side = LV_MATH_MIN(lv_area_get_width(&bg_coords), lv_area_get_height(&bg_coords)); +// if(r_bg > short_side >> 1) r_bg = short_side >> 1; +// +// lv_coord_t r_sh = style->body.radius; +// short_side = LV_MATH_MIN(lv_area_get_width(&sh_rect_area), lv_area_get_height(&sh_rect_area)); +// if(r_sh > short_side >> 1) r_sh = short_side >> 1; +// +// +// lv_coord_t corner_size = sw + r_sh; +// +// lv_opa_t * sh_buf = lv_mem_buf_get(corner_size * corner_size); +// shadow_draw_corner_buf(&sh_rect_area, sh_buf, style->body.shadow.width, r_sh); +// +// bool simple_mode = true; +// if(lv_draw_mask_get_cnt() > 0) simple_mode = false; +// else if(style->body.shadow.offset.x != 0 || style->body.shadow.offset.y != 0) simple_mode = false; +// else if(style->body.shadow.spread != 0) simple_mode = false; +// +// lv_coord_t y_max; +// +// /*Create a mask*/ +// lv_draw_mask_res_t mask_res; +// lv_opa_t * mask_buf = lv_mem_buf_get(lv_area_get_width(&sh_rect_area)); +// +// lv_draw_mask_radius_param_t mask_rout_param; +// lv_draw_mask_radius_init(&mask_rout_param, &bg_coords, r_bg, true); +// +// int16_t mask_rout_id = LV_MASK_ID_INV; +// mask_rout_id = lv_draw_mask_add(&mask_rout_param, NULL); +// +// lv_area_t a; +// +// /*Draw the top right corner*/ +// a.x2 = sh_area.x2; +// a.x1 = a.x2 - corner_size + 1; +// a.y1 = sh_area.y1; +// a.y2 = a.y1; +// +// lv_coord_t first_px; +// first_px = 0; +// if(disp_area->x1 > a.x1) { +// first_px = disp_area->x1 - a.x1; +// } +// +// lv_coord_t hor_mid_dist = (sh_area.x1 + lv_area_get_width(&sh_area) / 2) - (a.x1 + first_px); +// if(hor_mid_dist > 0) { +// first_px += hor_mid_dist; +// } +// a.x1 += first_px; +// +// lv_coord_t ver_mid_dist = (a.y1 + corner_size) - (sh_area.y1 + lv_area_get_height(&sh_area) / 2); +// lv_coord_t ver_mid_corr = 0; +// if(ver_mid_dist <= 0) ver_mid_dist = 0; +// else { +// if(lv_area_get_height(&sh_area) & 0x1) ver_mid_corr = 1; +// } +// lv_opa_t * sh_buf_tmp = sh_buf; +// +// lv_coord_t y; +// for(y = 0; y < corner_size - ver_mid_dist + ver_mid_corr; y++) { +// memcpy(mask_buf, sh_buf_tmp, corner_size); +// mask_res = lv_draw_mask_apply(mask_buf + first_px, a.x1, a.y1, lv_area_get_width(&a)); +// if(mask_res == LV_DRAW_MASK_RES_FULL_COVER) mask_res = LV_DRAW_MASK_RES_CHANGED; +// +// lv_blend_fill(clip, &a, +// style->body.shadow.color, mask_buf + first_px, mask_res, opa, style->body.shadow.blend_mode); +// a.y1++; +// a.y2++; +// sh_buf_tmp += corner_size; +// } +// +// /*Draw the bottom right corner*/ +// a.y1 = sh_area.y2; +// a.y2 = a.y1; +// +// sh_buf_tmp = sh_buf ; +// +// for(y = 0; y < corner_size - ver_mid_dist; y++) { +// memcpy(mask_buf, sh_buf_tmp, corner_size); +// mask_res = lv_draw_mask_apply(mask_buf + first_px, a.x1, a.y1, lv_area_get_width(&a)); +// if(mask_res == LV_DRAW_MASK_RES_FULL_COVER) mask_res = LV_DRAW_MASK_RES_CHANGED; +// +// lv_blend_fill(clip, &a, +// style->body.shadow.color, mask_buf + first_px, mask_res, opa, style->body.shadow.blend_mode); +// a.y1--; +// a.y2--; +// sh_buf_tmp += corner_size; +// } +// +// /*Fill the right side*/ +// a.y1 = sh_area.y1 + corner_size; +// a.y2 = a.y1; +// sh_buf_tmp = sh_buf + corner_size * (corner_size - 1); +// +// lv_coord_t x; +// +// if(simple_mode) { +// /*Draw vertical lines*/ +// lv_area_t va; +// va.x1 = a.x1; +// va.x2 = a.x1; +// va.y1 = sh_area.y1 + corner_size; +// va.y2 = sh_area.y2 - corner_size; +// +// if(va.y1 <= va.y2) { +// for(x = a.x1; x < a.x2; x++) { +// if(x > coords->x2) { +// lv_opa_t opa_tmp = sh_buf_tmp[x - a.x1 + first_px]; +// if(opa_tmp != LV_OPA_COVER || opa != LV_OPA_COVER) opa_tmp = (opa * opa_tmp) >> 8; +// lv_blend_fill(clip, &va, +// style->body.shadow.color, NULL, LV_DRAW_MASK_RES_FULL_COVER, opa_tmp, style->body.shadow.blend_mode); +// } +// va.x1++; +// va.x2++; +// } +// } +// } +// else { +// for(y = corner_size; y < lv_area_get_height(&sh_area) - corner_size; y++) { +// memcpy(mask_buf, sh_buf_tmp, corner_size); +// mask_res = lv_draw_mask_apply(mask_buf + first_px, a.x1, a.y1, lv_area_get_width(&a)); +// if(mask_res == LV_DRAW_MASK_RES_FULL_COVER) mask_res = LV_DRAW_MASK_RES_CHANGED; +// +// lv_blend_fill(clip, &a, +// style->body.shadow.color, mask_buf+first_px, mask_res, opa, style->body.shadow.blend_mode); +// a.y1++; +// a.y2++; +// } +// } +// +// /*Invert the shadow corner buffer and draw the corners on the left*/ +// sh_buf_tmp = sh_buf ; +// for(y = 0; y < corner_size; y++) { +// for(x = 0; x < corner_size / 2; x++) { +// lv_opa_t tmp = sh_buf_tmp[x]; +// sh_buf_tmp[x] = sh_buf_tmp[corner_size - x - 1]; +// sh_buf_tmp[corner_size - x - 1] = tmp; +// } +// sh_buf_tmp += corner_size; +// } +// +// /*Draw the top left corner*/ +// a.x1 = sh_area.x1; +// a.x2 = a.x1 + corner_size - 1; +// a.y1 = sh_area.y1; +// a.y2 = a.y1; +// +// if(a.x2 > sh_area.x1 + lv_area_get_width(&sh_area)/2 - 1) { +// a.x2 = sh_area.x1 + lv_area_get_width(&sh_area)/2 -1 ; +// } +// +// first_px = 0; +// if(disp_area->x1 >= a.x1) { +// first_px = disp_area->x1 - a.x1; +// a.x1 += first_px; +// } +// +// sh_buf_tmp = sh_buf ; +// for(y = 0; y < corner_size - ver_mid_dist + ver_mid_corr; y++) { +// memcpy(mask_buf, sh_buf_tmp, corner_size); +// mask_res = lv_draw_mask_apply(mask_buf + first_px, a.x1, a.y1, lv_area_get_width(&a)); +// if(mask_res == LV_DRAW_MASK_RES_FULL_COVER) mask_res = LV_DRAW_MASK_RES_CHANGED; +// +// lv_blend_fill(clip, &a, +// style->body.shadow.color, mask_buf + first_px, mask_res, opa, style->body.shadow.blend_mode); +// a.y1++; +// a.y2++; +// sh_buf_tmp += corner_size; +// } +// +// /*Draw the bottom left corner*/ +// a.y1 = sh_area.y2; +// a.y2 = a.y1; +// +// sh_buf_tmp = sh_buf ; +// +// for(y = 0; y < corner_size - ver_mid_dist; y++) { +// memcpy(mask_buf, sh_buf_tmp, corner_size); +// mask_res = lv_draw_mask_apply(mask_buf + first_px, a.x1, a.y1, lv_area_get_width(&a)); +// if(mask_res == LV_DRAW_MASK_RES_FULL_COVER) mask_res = LV_DRAW_MASK_RES_CHANGED; +// +// lv_blend_fill(clip, &a, +// style->body.shadow.color, mask_buf + first_px, mask_res, opa, style->body.shadow.blend_mode); +// a.y1--; +// a.y2--; +// sh_buf_tmp += corner_size; +// } +// +// /*Fill the left side*/ +// a.y1 = sh_area.y1+corner_size; +// a.y2 = a.y1; +// +// sh_buf_tmp = sh_buf + corner_size * (corner_size - 1); +// +// if(simple_mode) { +// /*Draw vertical lines*/ +// lv_area_t va; +// va.x1 = a.x1; +// va.x2 = a.x1; +// va.y1 = sh_area.y1 + corner_size; +// va.y2 = sh_area.y2 - corner_size; +// +// if(va.y1 <= va.y2) { +// for(x = a.x1; x < coords->x1; x++) { +// lv_opa_t opa_tmp = sh_buf_tmp[x - a.x1 + first_px]; +// if(opa_tmp != LV_OPA_COVER || opa != LV_OPA_COVER) opa_tmp = (opa * opa_tmp) >> 8; +// lv_blend_fill(clip, &va, +// style->body.shadow.color, NULL, LV_DRAW_MASK_RES_FULL_COVER, opa_tmp, style->body.shadow.blend_mode); +// va.x1++; +// va.x2++; +// } +// } +// } +// else { +// for(y = corner_size; y < lv_area_get_height(&sh_area) - corner_size; y++) { +// memcpy(mask_buf, sh_buf_tmp, corner_size); +// mask_res = lv_draw_mask_apply(mask_buf + first_px, a.x1, a.y1, lv_area_get_width(&a)); +// if(mask_res == LV_DRAW_MASK_RES_FULL_COVER) mask_res = LV_DRAW_MASK_RES_CHANGED; +// +// lv_blend_fill(clip, &a, +// style->body.shadow.color, mask_buf + first_px, mask_res, opa, style->body.shadow.blend_mode); +// a.y1++; +// a.y2++; +// } +// } +// +// /*Fill the top side*/ +// +// a.x1 = sh_area.x1 + corner_size; +// a.x2 = sh_area.x2 - corner_size; +// a.y1 = sh_area.y1; +// a.y2 = a.y1; +// +// +// first_px = 0; +// if(disp_area->x1 > a.x1) { +// first_px = disp_area->x1 - a.x1; +// a.x1 += first_px; +// } +// +// if(a.x1 <= a.x2) { +// +// sh_buf_tmp = sh_buf + corner_size - 1; +// +// y_max = corner_size - ver_mid_dist; +// if(simple_mode) { +// y_max = sw / 2 + 1; +// if(y_max > corner_size - ver_mid_dist) y_max = corner_size - ver_mid_dist; +// } +// +// for(y = 0; y < y_max; y++) { +// if(simple_mode == false) { +// memset(mask_buf, sh_buf_tmp[0], lv_area_get_width(&a)); +// mask_res = lv_draw_mask_apply(mask_buf, a.x1, a.y1, lv_area_get_width(&a)); +// if(mask_res == LV_DRAW_MASK_RES_FULL_COVER) mask_res = LV_DRAW_MASK_RES_CHANGED; +// +// lv_blend_fill(clip, &a, +// style->body.shadow.color, mask_buf, mask_res, opa, style->body.shadow.blend_mode); +// } else { +// +// lv_opa_t opa_tmp = sh_buf_tmp[0]; +// if(opa_tmp != LV_OPA_COVER || opa != LV_OPA_COVER) opa_tmp = (opa * opa_tmp) >> 8; +// lv_blend_fill(clip, &a, +// style->body.shadow.color, NULL, LV_DRAW_MASK_RES_FULL_COVER, opa_tmp, style->body.shadow.blend_mode); +// } +// +// a.y1++; +// a.y2++; +// sh_buf_tmp += corner_size; +// } +// +// /*Fill the bottom side*/ +// lv_coord_t y_min = simple_mode ? (corner_size - (sh_area.y2 - coords->y2)) : ver_mid_dist; +// if(y_min < 0) y_min = 0; +// sh_buf_tmp = sh_buf + corner_size * (corner_size - y_min - 1 ) + corner_size - 1; +// +// a.y1 = sh_area.y2 - corner_size + 1 + y_min; +// a.y2 = a.y1; +// +// for(y = y_min; y < corner_size; y++) { +// if(simple_mode == false) { +// memset(mask_buf, sh_buf_tmp[0], lv_area_get_width(&a)); +// mask_res = lv_draw_mask_apply(mask_buf, a.x1, a.y1, lv_area_get_width(&a)); +// if(mask_res == LV_DRAW_MASK_RES_FULL_COVER) mask_res = LV_DRAW_MASK_RES_CHANGED; +// lv_blend_fill(clip, &a, +// style->body.shadow.color, mask_buf, mask_res, opa, style->body.shadow.blend_mode); +// } else { +// lv_opa_t opa_tmp = sh_buf_tmp[0]; +// if(opa_tmp != LV_OPA_COVER || opa != LV_OPA_COVER) opa_tmp = (opa * opa_tmp) >> 8; +// lv_blend_fill(clip, &a, +// style->body.shadow.color, NULL, LV_DRAW_MASK_RES_FULL_COVER, opa_tmp, style->body.shadow.blend_mode); +// } +// +// a.y1++; +// a.y2++; +// sh_buf_tmp -= corner_size; +// } +// } +// +// /*Finally fill the middle area*/ +// if(simple_mode == false) { +// a.y1 = sh_area.y1 + corner_size; +// a.y2 = a.y1; +// if(a.x1 <= a.x2) { +// for(y = 0; y < lv_area_get_height(&sh_area) - corner_size * 2; y++) { +// memset(mask_buf, 0xFF, lv_area_get_width(&a)); +// mask_res = lv_draw_mask_apply(mask_buf, a.x1, a.y1, lv_area_get_width(&a)); +// lv_blend_fill(clip, &a, +// style->body.shadow.color, mask_buf, mask_res, opa, style->body.shadow.blend_mode); +// +// a.y1++; +// a.y2++; +// } +// } +// } +// +// lv_draw_mask_remove_id(mask_rout_id); +// lv_mem_buf_release(mask_buf); +// lv_mem_buf_release(sh_buf); } static void shadow_draw_corner_buf(const lv_area_t * coords, lv_opa_t * sh_buf, lv_coord_t sw, lv_coord_t r) diff --git a/src/lv_draw/lv_draw_rect.h b/src/lv_draw/lv_draw_rect.h index e3007addf..9fd58a796 100644 --- a/src/lv_draw/lv_draw_rect.h +++ b/src/lv_draw/lv_draw_rect.h @@ -14,6 +14,7 @@ extern "C" { * INCLUDES *********************/ #include "lv_draw.h" +#include "../lv_core/lv_style.h" /********************* * DEFINES @@ -23,10 +24,26 @@ extern "C" { * TYPEDEFS **********************/ +typedef struct { + lv_color_t bg_color; + lv_color_t bg_grad_color; + lv_style_value_t border_width; + lv_color_t border_color; + lv_blend_mode_t border_blend_mode; + lv_opa_t bg_opa; + lv_opa_t border_opa; + lv_style_value_t radius; + lv_style_value_t border_part; + lv_style_value_t bg_grad_dir; + lv_style_value_t bg_blend_mode; +}lv_draw_rect_dsc_t; + /********************** * GLOBAL PROTOTYPES **********************/ +void lv_draw_rect_dsc_init(lv_draw_rect_dsc_t * dsc); + /** * Draw a rectangle * @param coords the coordinates of the rectangle @@ -34,7 +51,7 @@ extern "C" { * @param style pointer to a style * @param opa_scale scale down all opacities by the factor */ -void lv_draw_rect(const lv_area_t * coords, const lv_area_t * mask, const lv_style_t * style, lv_opa_t opa_scale); +void lv_draw_rect(const lv_area_t * coords, const lv_area_t * mask, lv_draw_rect_dsc_t * dsc, lv_opa_t opa_scale); /** * Draw a pixel diff --git a/src/lv_draw/lv_img_cache.c b/src/lv_draw/lv_img_cache.c index 5ca48e438..36bb524e6 100644 --- a/src/lv_draw/lv_img_cache.c +++ b/src/lv_draw/lv_img_cache.c @@ -62,7 +62,7 @@ static uint16_t entry_cnt; * @param style style of the image * @return pointer to the cache entry or NULL if can open the image */ -lv_img_cache_entry_t * lv_img_cache_open(const void * src, const lv_style_t * style) +lv_img_cache_entry_t * lv_img_cache_open(const void * src, lv_color_t color) { if(entry_cnt == 0) { LV_LOG_WARN("lv_img_cache_open: the cache size is 0"); @@ -124,7 +124,7 @@ lv_img_cache_entry_t * lv_img_cache_open(const void * src, const lv_style_t * st uint32_t t_start; t_start = lv_tick_get(); cached_src->dec_dsc.time_to_open = 0; - lv_res_t open_res = lv_img_decoder_open(&cached_src->dec_dsc, src, style); + lv_res_t open_res = lv_img_decoder_open(&cached_src->dec_dsc, src, color); if(open_res == LV_RES_INV) { LV_LOG_WARN("Image draw cannot open the image resource"); lv_img_decoder_close(&cached_src->dec_dsc); diff --git a/src/lv_draw/lv_img_cache.h b/src/lv_draw/lv_img_cache.h index 859b4b8db..ba757b40f 100644 --- a/src/lv_draw/lv_img_cache.h +++ b/src/lv_draw/lv_img_cache.h @@ -50,7 +50,7 @@ typedef struct * @param style style of the image * @return pointer to the cache entry or NULL if can open the image */ -lv_img_cache_entry_t * lv_img_cache_open(const void * src, const lv_style_t * style); +lv_img_cache_entry_t * lv_img_cache_open(const void * src, lv_color_t color); /** * Set the number of images to be cached. diff --git a/src/lv_draw/lv_img_decoder.c b/src/lv_draw/lv_img_decoder.c index 6c130b2f3..84cbea57b 100644 --- a/src/lv_draw/lv_img_decoder.c +++ b/src/lv_draw/lv_img_decoder.c @@ -117,9 +117,9 @@ lv_res_t lv_img_decoder_get_info(const char * src, lv_img_header_t * header) * @return LV_RES_OK: opened the image. `dsc->img_data` and `dsc->header` are set. * LV_RES_INV: none of the registered image decoders were able to open the image. */ -lv_res_t lv_img_decoder_open(lv_img_decoder_dsc_t * dsc, const void * src, const lv_style_t * style) +lv_res_t lv_img_decoder_open(lv_img_decoder_dsc_t * dsc, const void * src, lv_color_t color) { - dsc->style = style; + dsc->color = color; dsc->src_type = lv_img_src_get_type(src); dsc->user_data = NULL; @@ -569,7 +569,7 @@ static lv_res_t lv_img_decoder_built_in_line_alpha(lv_img_decoder_dsc_t * dsc, l 68, 85, 102, 119, 136, 153, 170, 187, 204, 221, 238, 255}; /*Simply fill the buffer with the color. Later only the alpha value will be modified.*/ - lv_color_t bg_color = dsc->style->image.color; + lv_color_t bg_color = dsc->color; lv_coord_t i; for(i = 0; i < len; i++) { #if LV_COLOR_DEPTH == 8 || LV_COLOR_DEPTH == 1 diff --git a/src/lv_draw/lv_img_decoder.h b/src/lv_draw/lv_img_decoder.h index a1713e0c0..4d04df0f8 100644 --- a/src/lv_draw/lv_img_decoder.h +++ b/src/lv_draw/lv_img_decoder.h @@ -110,7 +110,7 @@ typedef struct _lv_img_decoder_dsc const void * src; /**Style to draw the image.*/ - const lv_style_t * style; + lv_color_t color; /**Type of the source: file or variable. Can be set in `open` function if required*/ lv_img_src_t src_type; @@ -167,7 +167,7 @@ lv_res_t lv_img_decoder_get_info(const char * src, lv_img_header_t * header); * @return LV_RES_OK: opened the image. `dsc->img_data` and `dsc->header` are set. * LV_RES_INV: none of the registered image decoders were able to open the image. */ -lv_res_t lv_img_decoder_open(lv_img_decoder_dsc_t * dsc, const void * src, const lv_style_t * style); +lv_res_t lv_img_decoder_open(lv_img_decoder_dsc_t * dsc, const void * src, lv_color_t color); /** * Read a line from an opened image diff --git a/src/lv_hal/lv_hal_disp.c b/src/lv_hal/lv_hal_disp.c index 11a3bbcb2..016d6c90e 100644 --- a/src/lv_hal/lv_hal_disp.c +++ b/src/lv_hal/lv_hal_disp.c @@ -139,8 +139,10 @@ lv_disp_t * lv_disp_drv_register(lv_disp_drv_t * driver) disp->act_scr = lv_obj_create(NULL, NULL); /*Create a default screen on the display*/ disp->top_layer = lv_obj_create(NULL, NULL); /*Create top layer on the display*/ disp->sys_layer = lv_obj_create(NULL, NULL); /*Create sys layer on the display*/ - lv_obj_set_style(disp->top_layer, &lv_style_transp); - lv_obj_set_style(disp->sys_layer, &lv_style_transp); +// lv_obj_set_style(disp->top_layer, &lv_style_transp); +// lv_obj_set_style(disp->sys_layer, &lv_style_transp); + lv_obj_set_hidden(disp->top_layer, true); + lv_obj_set_hidden(disp->sys_layer, true); lv_obj_invalidate(disp->act_scr);