From 533b9495955f04df38a12b75984b5b62a5a30271 Mon Sep 17 00:00:00 2001 From: Gabor Kiss-Vamosi Date: Wed, 15 Jan 2020 00:08:29 +0100 Subject: [PATCH] add dashed line support to horizontal and vertical lines --- src/lv_core/lv_obj.c | 5 +++ src/lv_core/lv_style.h | 2 ++ src/lv_draw/lv_draw_line.c | 62 +++++++++++++++++++++++++++++----- src/lv_draw/lv_draw_line.h | 4 ++- src/lv_themes/lv_theme_alien.c | 1 + 5 files changed, 64 insertions(+), 10 deletions(-) diff --git a/src/lv_core/lv_obj.c b/src/lv_core/lv_obj.c index 258d9be77..5cf55fd74 100644 --- a/src/lv_core/lv_obj.c +++ b/src/lv_core/lv_obj.c @@ -2708,6 +2708,11 @@ void lv_obj_init_draw_line_dsc(lv_obj_t * obj, uint8_t part, lv_draw_line_dsc_t draw_dsc->color = lv_obj_get_style_color(obj, part, LV_STYLE_LINE_COLOR); draw_dsc->blend_mode = lv_obj_get_style_int(obj, part, LV_STYLE_LINE_BLEND_MODE); + + draw_dsc->dash_width = lv_obj_get_style_int(obj, part, LV_STYLE_LINE_DASH_WIDTH); + if(draw_dsc->dash_width) { + draw_dsc->dash_gap = lv_obj_get_style_int(obj, part, LV_STYLE_LINE_DASH_GAP); + } } /** diff --git a/src/lv_core/lv_style.h b/src/lv_core/lv_style.h index 0da1e933d..f444aafde 100644 --- a/src/lv_core/lv_style.h +++ b/src/lv_core/lv_style.h @@ -124,6 +124,8 @@ enum { LV_STYLE_PROP_INIT(LV_STYLE_LINE_WIDTH, 0x7, LV_STYLE_ID_VALUE + 0, LV_STYLE_ATTR_NONE), LV_STYLE_PROP_INIT(LV_STYLE_LINE_BLEND_MODE, 0x7, LV_STYLE_ID_VALUE + 1, LV_STYLE_ATTR_NONE), + LV_STYLE_PROP_INIT(LV_STYLE_LINE_DASH_WIDTH, 0x7, LV_STYLE_ID_VALUE + 2, LV_STYLE_ATTR_NONE), + LV_STYLE_PROP_INIT(LV_STYLE_LINE_DASH_GAP, 0x7, LV_STYLE_ID_VALUE + 3, LV_STYLE_ATTR_NONE), LV_STYLE_PROP_INIT(LV_STYLE_LINE_COLOR, 0x7, LV_STYLE_ID_COLOR + 0, LV_STYLE_ATTR_NONE), LV_STYLE_PROP_INIT(LV_STYLE_LINE_OPA, 0x7, LV_STYLE_ID_OPA + 0, LV_STYLE_ATTR_NONE), diff --git a/src/lv_draw/lv_draw_line.c b/src/lv_draw/lv_draw_line.c index bcb040982..56b992430 100644 --- a/src/lv_draw/lv_draw_line.c +++ b/src/lv_draw/lv_draw_line.c @@ -123,8 +123,11 @@ static void draw_line_hor(const lv_point_t * point1, const lv_point_t * point2, lv_coord_t w_half0 = w >> 1; lv_coord_t w_half1 = w_half0 + (w & 0x1); /*Compensate rounding error*/ + bool dashed = dsc->dash_gap && dsc->dash_width ? true : false; - int16_t other_mask_cnt = lv_draw_mask_get_cnt(); + bool simple_mode = true; + if(lv_draw_mask_get_cnt()) simple_mode = false; + else if(dashed) simple_mode = false; lv_area_t draw_area; draw_area.x1 = LV_MATH_MIN(point1->x, point2->x); @@ -133,7 +136,7 @@ static void draw_line_hor(const lv_point_t * point1, const lv_point_t * point2, draw_area.y2 = point1->y + w_half0; /*If there is no mask then simply draw a rectangle*/ - if(other_mask_cnt == 0) { + if(simple_mode) { lv_blend_fill(clip, &draw_area, dsc->color, NULL, LV_DRAW_MASK_RES_FULL_COVER,opa, LV_BLEND_MODE_NORMAL); @@ -148,10 +151,10 @@ static void draw_line_hor(const lv_point_t * point1, const lv_point_t * point2, /* 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; + 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); @@ -161,6 +164,8 @@ static void draw_line_hor(const lv_point_t * point1, const lv_point_t * point2, fill_area.y1 = draw_area.y1 + disp_area->y1; fill_area.y2 = fill_area.y1; + lv_style_int_t dash_start = (vdb->area.x1 + draw_area.x1) % (dsc->dash_gap + dsc->dash_width); + lv_opa_t * mask_buf = lv_mem_buf_get(draw_area_w); lv_coord_t h; lv_draw_mask_res_t mask_res; @@ -168,6 +173,26 @@ static void draw_line_hor(const lv_point_t * point1, const lv_point_t * point2, 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); + if(dashed) { + if(mask_res != LV_DRAW_MASK_RES_FULL_TRANSP) { + lv_style_int_t dash_cnt = dash_start; + uint32_t i; + for(i = 0; i < draw_area_w; i++, dash_cnt++) { + if(dash_cnt <= dsc->dash_width) { + int16_t diff = dsc->dash_width - dash_cnt; + i += diff; + dash_cnt += diff; + } else if(dash_cnt >= dsc->dash_gap + dsc->dash_width) { + dash_cnt = 0; + } else { + mask_buf[i] = 0x00; + } + } + + mask_res = LV_DRAW_MASK_RES_CHANGED; + } + } + lv_blend_fill(clip, &fill_area, dsc->color, mask_buf, mask_res, dsc->opa, dsc->blend_mode); @@ -193,8 +218,11 @@ static void draw_line_ver(const lv_point_t * point1, const lv_point_t * point2, lv_coord_t w_half0 = w >> 1; lv_coord_t w_half1 = w_half0 + (w & 0x1); /*Compensate rounding error*/ + bool dashed = dsc->dash_gap && dsc->dash_width ? true : false; - int16_t other_mask_cnt = lv_draw_mask_get_cnt(); + bool simple_mode = true; + if(lv_draw_mask_get_cnt()) simple_mode = false; + else if(dashed) simple_mode = false; lv_area_t draw_area; draw_area.x1 = point1->x - w_half1; @@ -203,8 +231,7 @@ static void draw_line_ver(const lv_point_t * point1, const lv_point_t * point2, 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) { - + if(simple_mode) { lv_blend_fill(clip, &draw_area, dsc->color, NULL, LV_DRAW_MASK_RES_FULL_COVER, opa, dsc->blend_mode); @@ -233,12 +260,29 @@ static void draw_line_ver(const lv_point_t * point1, const lv_point_t * point2, fill_area.y2 = fill_area.y1; lv_opa_t * mask_buf = lv_mem_buf_get(draw_area_w); + + lv_style_int_t dash_start = (vdb->area.y1 + draw_area.y1) % (dsc->dash_gap + dsc->dash_width); + lv_style_int_t dash_cnt = dash_start; + 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); + if(dashed) { + if(mask_res != LV_DRAW_MASK_RES_FULL_TRANSP) { + if(dash_cnt > dsc->dash_width) { + mask_res = LV_DRAW_MASK_RES_FULL_TRANSP; + } + + if(dash_cnt >= dsc->dash_gap + dsc->dash_width) { + dash_cnt = 0; + } + } + dash_cnt ++; + } + lv_blend_fill(clip, &fill_area, dsc->color, mask_buf, mask_res, dsc->opa, LV_BLEND_MODE_NORMAL); diff --git a/src/lv_draw/lv_draw_line.h b/src/lv_draw/lv_draw_line.h index 04af73eff..2d5d21131 100644 --- a/src/lv_draw/lv_draw_line.h +++ b/src/lv_draw/lv_draw_line.h @@ -24,8 +24,10 @@ extern "C" { typedef struct { lv_color_t color; lv_style_int_t width; + lv_style_int_t dash_width; + lv_style_int_t dash_gap; lv_opa_t opa; - lv_blend_mode_t blend_mode; + lv_blend_mode_t blend_mode :2; uint8_t round_start :1; uint8_t round_end :1; }lv_draw_line_dsc_t; diff --git a/src/lv_themes/lv_theme_alien.c b/src/lv_themes/lv_theme_alien.c index d9448f9b7..b93e943ca 100644 --- a/src/lv_themes/lv_theme_alien.c +++ b/src/lv_themes/lv_theme_alien.c @@ -91,6 +91,7 @@ static void basic_init(void) lv_style_set_opa(&scr, LV_STYLE_BG_OPA, LV_OPA_COVER); lv_style_set_color(&scr, LV_STYLE_BG_COLOR, LV_COLOR_MAKE(0x20, 0x20, 0x20)); lv_style_set_color(&scr, LV_STYLE_TEXT_COLOR , LV_COLOR_GRAY); + lv_style_set_int(&scr, LV_STYLE_LINE_WIDTH, 2); lv_style_init(&transp); lv_style_set_opa(&transp, LV_STYLE_BG_OPA, LV_OPA_TRANSP);