diff --git a/src/lv_core/lv_refr.c b/src/lv_core/lv_refr.c index 4be13ab2b..07bda2fc9 100644 --- a/src/lv_core/lv_refr.c +++ b/src/lv_core/lv_refr.c @@ -438,7 +438,10 @@ static lv_obj_t * lv_refr_get_top_obj(const lv_area_t * area_p, lv_obj_t * obj) 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) { + 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) { found_p = obj; } } diff --git a/src/lv_core/lv_style.c b/src/lv_core/lv_style.c index 32e7bb3d5..32417e1f0 100644 --- a/src/lv_core/lv_style.c +++ b/src/lv_core/lv_style.c @@ -71,7 +71,7 @@ void lv_style_init(void) /*Screen style*/ lv_style_scr.glass = 0; - lv_style_scr.body.opa = LV_OPA_TRANSP; + 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.radius = 0; @@ -107,7 +107,7 @@ void lv_style_init(void) 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.image.blend_mode = LV_BLEND_MODE_SUBTRACTIVE; lv_style_scr.line.opa = LV_OPA_COVER; lv_style_scr.line.color = lv_color_make(0x20, 0x20, 0x20); @@ -127,19 +127,20 @@ void lv_style_init(void) 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.image.blend_mode = LV_BLEND_MODE_SUBTRACTIVE; 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_BLACK; + lv_style_pretty.body.grad_color = LV_COLOR_SILVER; lv_style_pretty.body.radius = LV_DPI / 5; -// lv_style_pretty.body.opa = LV_OPA_40;//LV_DPI / 5; 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; diff --git a/src/lv_draw/lv_draw_blend.c b/src/lv_draw/lv_draw_blend.c index 57d5d9e75..f86267250 100644 --- a/src/lv_draw/lv_draw_blend.c +++ b/src/lv_draw/lv_draw_blend.c @@ -47,6 +47,10 @@ static void map_normal(const lv_area_t * disp_area, lv_color_t * disp_buf, cons const lv_area_t * map_area, const lv_color_t * map_buf, lv_opa_t opa, const lv_opa_t * mask, lv_draw_mask_res_t mask_res); +static void map_blended(const lv_area_t * disp_area, lv_color_t * disp_buf, const lv_area_t * draw_area, + const lv_area_t * map_area, const lv_color_t * map_buf, lv_opa_t opa, + const lv_opa_t * mask, lv_draw_mask_res_t mask_res, lv_blend_mode_t mode); + static inline lv_color_t color_blend_true_color_additive(lv_color_t bg, lv_color_t fg, lv_opa_t opa); static inline lv_color_t color_blend_true_color_subtractive(lv_color_t fg, lv_color_t bg, lv_opa_t opa); @@ -151,8 +155,9 @@ void lv_blend_map(const lv_area_t * clip_area, const lv_area_t * map_area, const } else if(mode == LV_BLEND_MODE_NORMAL) { map_normal(disp_area, disp_buf, &draw_area, map_area, map_buf, opa, mask, mask_res); + } else { + map_blended(disp_area, disp_buf, &draw_area, map_area, map_buf, opa, mask, mask_res, mode); } - } @@ -419,7 +424,7 @@ static void fill_blended(const lv_area_t * disp_area, lv_color_t * disp_buf, co for(x = draw_area->x1; x <= draw_area->x2; x++) { if(mask_tmp[x] == 0) continue; if(mask_tmp[x] != last_mask || last_dest_color.full != disp_buf_tmp[x].full) { - lv_opa_t opa_tmp = (uint16_t)((uint16_t)mask_tmp[x] * opa) >> 8; + lv_opa_t opa_tmp = mask_tmp[x] >= LV_OPA_MAX ? opa : (uint16_t)((uint16_t)mask_tmp[x] * opa) >> 8; last_res_color = blend_fp(color, disp_buf_tmp[x], opa_tmp); last_mask = mask_tmp[x]; @@ -625,6 +630,80 @@ static void map_normal(const lv_area_t * disp_area, lv_color_t * disp_buf, cons } } +static void map_blended(const lv_area_t * disp_area, lv_color_t * disp_buf, const lv_area_t * draw_area, + const lv_area_t * map_area, const lv_color_t * map_buf, lv_opa_t opa, + const lv_opa_t * mask, lv_draw_mask_res_t mask_res, lv_blend_mode_t mode) +{ + + /*Get the width of the `disp_area` it will be used to go to the next line*/ + lv_coord_t disp_w = lv_area_get_width(disp_area); + + /*Get the width of the `draw_area` it will be used to go to the next line of the mask*/ + lv_coord_t draw_area_w = lv_area_get_width(draw_area); + + /*Get the width of the `mask_area` it will be used to go to the next line*/ + lv_coord_t map_w = lv_area_get_width(map_area); + + /*Create a temp. disp_buf which always point to current line to draw*/ + lv_color_t * disp_buf_tmp = disp_buf + disp_w * draw_area->y1; + + /*Create a temp. map_buf which always point to current line to draw*/ + const lv_color_t * map_buf_tmp = map_buf + map_w * (draw_area->y1 - (map_area->y1 - disp_area->y1)); + + lv_color_t (*blend_fp)(lv_color_t, lv_color_t, lv_opa_t); + switch (mode) { + case LV_BLEND_MODE_ADDITIVE: + blend_fp = color_blend_true_color_additive; + break; + case LV_BLEND_MODE_SUBTRACTIVE: + blend_fp = color_blend_true_color_subtractive; + break; + default: + LV_LOG_WARN("fill_blended: unsupported blend mode"); + return; + break; + } + + lv_coord_t x; + lv_coord_t y; + + /*Simple fill (maybe with opacity), no masking*/ + if(mask_res == LV_DRAW_MASK_RES_FULL_COVER) { + /*Go to the first px of the row*/ + map_buf_tmp += (draw_area->x1 - (map_area->x1 - disp_area->x1)); + + /*The map will be indexed from `draw_area->x1` so compensate it.*/ + map_buf_tmp -= draw_area->x1; + + for(y = draw_area->y1; y <= draw_area->y2; y++) { + for(x = draw_area->x1; x <= draw_area->x2; x++) { + disp_buf_tmp[x] = blend_fp(map_buf_tmp[x], disp_buf_tmp[x], opa); + } + disp_buf_tmp += disp_w; + map_buf_tmp += map_w; + } + } + /*Masked*/ + else { + /* The mask is relative to the clipped area. + * In the cycles below mask will be indexed from `draw_area.x1` + * but it corresponds to zero index. So prepare `mask_tmp` accordingly. */ + const lv_opa_t * mask_tmp = mask - draw_area->x1; + + map_buf_tmp -= draw_area->x1; + for(y = draw_area->y1; y <= draw_area->y2; y++) { + for(x = draw_area->x1; x <= draw_area->x2; x++) { + if(mask_tmp[x] == 0) continue; + lv_opa_t opa_tmp = mask_tmp[x] >= LV_OPA_MAX ? opa : ((opa * mask_tmp[x]) >> 8); + disp_buf_tmp[x] = blend_fp(map_buf_tmp[x], disp_buf_tmp[x], opa_tmp); + } + disp_buf_tmp += disp_w; + mask_tmp += draw_area_w; + map_buf_tmp += map_w; + } + } +} + static inline lv_color_t color_blend_true_color_additive(lv_color_t fg, lv_color_t bg, lv_opa_t opa) { diff --git a/src/lv_draw/lv_draw_img.c b/src/lv_draw/lv_draw_img.c index 999f10a5a..057195fc4 100644 --- a/src/lv_draw/lv_draw_img.c +++ b/src/lv_draw/lv_draw_img.c @@ -27,7 +27,7 @@ static lv_res_t lv_img_draw_core(const lv_area_t * coords, const lv_area_t * mas const lv_style_t * style, lv_opa_t opa_scale); 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, lv_color_t recolor, lv_opa_t recolor_opa); + bool chroma_key, bool alpha_byte, const lv_style_t * style); /********************** * STATIC VARIABLES @@ -504,8 +504,7 @@ static lv_res_t lv_img_draw_core(const lv_area_t * coords, const lv_area_t * mas /* The decoder open could open the image and gave the entire uncompressed image. * Just draw it!*/ else if(cdsc->dec_dsc.img_data) { - lv_draw_map(coords, mask, cdsc->dec_dsc.img_data, opa, chroma_keyed, alpha_byte, style->image.color, - style->image.intense); + lv_draw_map(coords, mask, cdsc->dec_dsc.img_data, opa, chroma_keyed, alpha_byte, style); } /* The whole uncompressed image is not available. Try to read it line-by-line*/ else { @@ -527,7 +526,7 @@ static lv_res_t lv_img_draw_core(const lv_area_t * coords, const lv_area_t * mas LV_LOG_WARN("Image draw can't read the line"); return LV_RES_INV; } - lv_draw_map(&line, mask, buf, opa, chroma_keyed, alpha_byte, style->image.color, style->image.intense); + lv_draw_map(&line, mask, buf, opa, chroma_keyed, alpha_byte, style); line.y1++; line.y2++; y++; @@ -545,11 +544,10 @@ static lv_res_t lv_img_draw_core(const lv_area_t * coords, const lv_area_t * mas * @param opa opacity of the map * @param chroma_keyed true: enable transparency of LV_IMG_LV_COLOR_TRANSP color pixels * @param alpha_byte true: extra alpha byte is inserted for every pixel - * @param recolor mix the pixels with this color - * @param recolor_opa the intense of recoloring + * @param style style of the image */ 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, lv_color_t recolor, lv_opa_t recolor_opa) + bool chroma_key, bool alpha_byte, const lv_style_t * style) { if(opa < LV_OPA_MIN) return; if(opa > LV_OPA_MAX) opa = LV_OPA_COVER; @@ -578,8 +576,8 @@ static void lv_draw_map(const lv_area_t * map_area, const lv_area_t * clip_area, 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 && chroma_key == false && alpha_byte == false && opa == LV_OPA_COVER && recolor_opa == 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, LV_BLEND_MODE_NORMAL); + if(other_mask_cnt == 0 && 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 { @@ -646,8 +644,8 @@ static void lv_draw_map(const lv_area_t * map_area, const lv_area_t * clip_area, } } - if(recolor_opa != 0) { - c = lv_color_mix(recolor, c, recolor_opa); + if(style->image.intense != 0) { + c = lv_color_mix(style->image.color, c, style->image.intense); } map2[px_i].full = c.full; @@ -669,7 +667,7 @@ static void lv_draw_map(const lv_area_t * map_area, const lv_area_t * clip_area, if(px_i + lv_area_get_width(&draw_area) < sizeof(mask_buf)) { blend_area.y2 ++; } else { - lv_blend_map(clip_area, &blend_area, map2, mask_buf, mask_res, opa, LV_BLEND_MODE_NORMAL); + 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; @@ -686,7 +684,7 @@ static void lv_draw_map(const lv_area_t * map_area, const lv_area_t * clip_area, /*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, LV_BLEND_MODE_NORMAL); + lv_blend_map(clip_area, &blend_area, map2, mask_buf, mask_res, opa, style->image.blend_mode); } }