mirror of
https://github.com/lvgl/lvgl.git
synced 2025-01-21 06:53:01 +08:00
suppor blend modes on images
This commit is contained in:
parent
2acbc59a46
commit
d0bc387c14
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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)
|
||||
{
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user