From eb7909124ee6c56a3f6b117ca4d4590d35047008 Mon Sep 17 00:00:00 2001 From: Gabor Kiss-Vamosi Date: Thu, 2 Apr 2020 11:54:33 +0200 Subject: [PATCH] add LV_LINEMETER_PRECISE to balance performance and quality --- lv_conf_template.h | 9 +++++++ src/lv_conf_internal.h | 11 ++++++++ src/lv_misc/lv_math.c | 4 --- src/lv_themes/lv_theme_material.c | 1 - src/lv_widgets/lv_linemeter.c | 42 ++++++++++++++++++++++++++++--- 5 files changed, 59 insertions(+), 8 deletions(-) diff --git a/lv_conf_template.h b/lv_conf_template.h index ff63282b6..920e390e0 100644 --- a/lv_conf_template.h +++ b/lv_conf_template.h @@ -548,6 +548,15 @@ typedef void * lv_obj_user_data_t; /*Line meter (dependencies: *;)*/ #define LV_USE_LINEMETER 1 +#if LV_USE_LINEMETER +/* Draw line more precisely at cost of performance. + * Useful if there are lot of lines any minor are visible + * 0: No extra precision + * 1: Some extra precision + * 2: Best precision + */ +# define LV_LINEMETER_PRECISE 0 +#endif /*Mask (dependencies: -)*/ #define LV_USE_OBJMASK 0 diff --git a/src/lv_conf_internal.h b/src/lv_conf_internal.h index e5c9accc9..4f152147f 100644 --- a/src/lv_conf_internal.h +++ b/src/lv_conf_internal.h @@ -810,6 +810,17 @@ #ifndef LV_USE_LINEMETER #define LV_USE_LINEMETER 1 #endif +#if LV_USE_LINEMETER +/* Draw line more precisely at cost of performance. + * Useful if there are lot of lines any minor are visible + * 0: No extra precision + * 1: Some extra precision + * 2: Best precision + */ +#ifndef LV_LINEMETER_PRECISE +# define LV_LINEMETER_PRECISE 0 +#endif +#endif /*Mask (dependencies: -)*/ #ifndef LV_USE_OBJMASK diff --git a/src/lv_misc/lv_math.c b/src/lv_misc/lv_math.c index 9a21be35f..039e41e84 100644 --- a/src/lv_misc/lv_math.c +++ b/src/lv_misc/lv_math.c @@ -122,10 +122,6 @@ void lv_sqrt(uint32_t x, lv_sqrt_res_t * q, uint32_t mask) trial = root + mask; if ((uint32_t)trial * trial <= x) root = trial; mask = mask >> 1; - - trial = root + mask; - if ((uint32_t)trial * trial <= x) root = trial; - mask = mask >> 1; } while(mask); q->i = (uint32_t) root >> 4; diff --git a/src/lv_themes/lv_theme_material.c b/src/lv_themes/lv_theme_material.c index acd1476d7..2fe6d1c5d 100644 --- a/src/lv_themes/lv_theme_material.c +++ b/src/lv_themes/lv_theme_material.c @@ -416,7 +416,6 @@ static void linemeter_init(void) lv_style_set_line_color(&lmeter, LV_STATE_DEFAULT, theme.color_primary); lv_style_set_scale_grad_color(&lmeter, LV_STATE_DEFAULT, theme.color_primary); lv_style_set_scale_end_color(&lmeter, LV_STATE_DEFAULT, lv_color_hex3(0x666)); - lv_style_set_line_rounded(&lmeter, LV_STATE_DEFAULT, true); lv_style_set_line_width(&lmeter, LV_STATE_DEFAULT, LV_DPI / 20); lv_style_set_scale_end_line_width(&lmeter, LV_STATE_DEFAULT, LV_DPI / 30); #endif diff --git a/src/lv_widgets/lv_linemeter.c b/src/lv_widgets/lv_linemeter.c index ba0cd116a..75a03a724 100644 --- a/src/lv_widgets/lv_linemeter.c +++ b/src/lv_widgets/lv_linemeter.c @@ -19,6 +19,7 @@ * DEFINES *********************/ #define LV_OBJX_NAME "lv_linemeter" +#define LV_LINEMETER_PRECISE 0 /*Draw line more precisely at cost of performance*/ /********************** * TYPEDEFS @@ -293,19 +294,26 @@ void lv_linemeter_draw_scale(lv_obj_t * lmeter, const lv_area_t * clip_area, uin lv_draw_line_dsc_t line_dsc; lv_draw_line_dsc_init(&line_dsc); lv_obj_init_draw_line_dsc(lmeter, part, &line_dsc); +#if LV_LINEMETER_PRECISE == 2 line_dsc.raw_end = 1; +#endif lv_style_int_t end_line_width = lv_obj_get_style_scale_end_line_width(lmeter, part); +#if LV_LINEMETER_PRECISE > 0 lv_area_t mask_area; mask_area.x1 = x_ofs - r_in; mask_area.x2 = x_ofs + r_in - 1; mask_area.y1 = y_ofs - r_in; mask_area.y2 = y_ofs + r_in - 1; + lv_draw_mask_radius_param_t mask_in_param; lv_draw_mask_radius_init(&mask_in_param, &mask_area, LV_RADIUS_CIRCLE, true); int16_t mask_in_id = lv_draw_mask_add(&mask_in_param, 0); +#endif + +#if LV_LINEMETER_PRECISE > 1 mask_area.x1 = x_ofs - r_out; mask_area.x2 = x_ofs + r_out - 1; mask_area.y1 = y_ofs - r_out; @@ -313,9 +321,12 @@ void lv_linemeter_draw_scale(lv_obj_t * lmeter, const lv_area_t * clip_area, uin lv_draw_mask_radius_param_t mask_out_param; lv_draw_mask_radius_init(&mask_out_param, &mask_area, LV_RADIUS_CIRCLE, false); int16_t mask_out_id = lv_draw_mask_add(&mask_out_param, 0); - /*In calculation use a larger radius to avoid rounding errors */ lv_coord_t r_out_extra = r_out + LV_DPI; +#else + lv_coord_t r_out_extra = r_out; +#endif + for(i = 0; i < ext->line_cnt; i++) { /* `* 256` for extra precision*/ int32_t angle_upscale = (i * ext->scale_angle * 256) / (ext->line_cnt - 1); @@ -348,6 +359,26 @@ void lv_linemeter_draw_scale(lv_obj_t * lmeter, const lv_area_t * clip_area, uin x_out_extra += x_ofs; y_out_extra += y_ofs; + /*With no extra precision use the coordinates on the inner radius*/ +#if LV_LINEMETER_PRECISE == 0 + /*Use the interpolated values to get x and y coordinates*/ + int32_t y_in_extra = (int32_t)((int32_t)sin_mid * r_in) >> (LV_TRIGO_SHIFT - 8); + int32_t x_in_extra = (int32_t)((int32_t)cos_mid * r_in) >> (LV_TRIGO_SHIFT - 8); + + /*Rounding*/ + if(x_in_extra > 0) x_in_extra = (x_in_extra + 127) >> 8; + else x_in_extra = (x_in_extra - 127) >> 8; + + if(y_in_extra > 0) y_in_extra = (y_in_extra + 127) >> 8; + else y_in_extra = (y_in_extra - 127) >> 8; + + x_in_extra += x_ofs; + y_in_extra += y_ofs; +#else + int32_t x_in_extra = x_ofs; + int32_t y_in_extra = y_ofs; +#endif + /*Use smaller clip area only around the visible line*/ int32_t y_in = (int32_t)((int32_t)lv_trigo_sin(angle_normal + angle_ofs) * r_in) >> LV_TRIGO_SHIFT; int32_t x_in = (int32_t)((int32_t)lv_trigo_sin(angle_normal + 90 + angle_ofs) * r_in) >> LV_TRIGO_SHIFT; @@ -372,8 +403,8 @@ void lv_linemeter_draw_scale(lv_obj_t * lmeter, const lv_area_t * clip_area, uin lv_point_t p1; lv_point_t p2; - p2.x = x_ofs; - p2.y = y_ofs; + p2.x = x_in_extra; + p2.y = y_in_extra; p1.x = x_out_extra; p1.y = y_out_extra; @@ -389,8 +420,13 @@ void lv_linemeter_draw_scale(lv_obj_t * lmeter, const lv_area_t * clip_area, uin lv_draw_line(&p1, &p2, &clip_sub, &line_dsc); } +#if LV_LINEMETER_PRECISE > 0 lv_draw_mask_remove_id(mask_in_id); +#endif + +#if LV_LINEMETER_PRECISE > 1 lv_draw_mask_remove_id(mask_out_id); +#endif if(part == LV_LINEMETER_PART_MAIN) { lv_style_int_t border_width = lv_obj_get_style_scale_border_width(lmeter, part);