From 2a9c2ede4373047cb21bb3f00fefaefa50602288 Mon Sep 17 00:00:00 2001 From: Carlos Diaz Date: Fri, 22 Sep 2023 00:42:36 -0600 Subject: [PATCH] feat(scale): remove float and adding padding handling(#4552) --- src/widgets/scale/lv_scale.c | 315 +++++++++++++++++++++-------------- src/widgets/scale/lv_scale.h | 1 + 2 files changed, 189 insertions(+), 127 deletions(-) diff --git a/src/widgets/scale/lv_scale.c b/src/widgets/scale/lv_scale.c index 0d616d825..7719e043f 100644 --- a/src/widgets/scale/lv_scale.c +++ b/src/widgets/scale/lv_scale.c @@ -52,6 +52,11 @@ static void scale_set_arc_properties(lv_obj_t * obj, lv_draw_arc_dsc_t * arc_dsc static void scale_find_section_tick_idx(lv_obj_t * obj); static void scale_store_main_line_tick_width_compensation(lv_obj_t * obj, const uint32_t tick_idx, const bool is_major_tick, const lv_coord_t major_tick_width, const lv_coord_t minor_tick_width); +static void scale_store_section_line_tick_width_compensation(lv_obj_t * obj, const bool is_major_tick, + lv_draw_label_dsc_t * label_dsc, lv_draw_line_dsc_t * major_tick_dsc, lv_draw_line_dsc_t * minor_tick_dsc, + const int32_t tick_value, const uint8_t tick_idx, lv_point_t * tick_point_a); +static void scale_build_custom_label_text(lv_obj_t * obj, lv_draw_label_dsc_t * label_dsc, + const uint16_t major_tick_idx); /********************** * STATIC VARIABLES @@ -182,6 +187,12 @@ void lv_scale_set_text_src(lv_obj_t * obj, char * txt_src[]) scale->txt_src = txt_src; + scale->custom_label_cnt = 0; + lv_coord_t idx; + for(idx = 0; txt_src[idx]; ++idx) { + scale->custom_label_cnt++; + } + lv_obj_invalidate(obj); } @@ -282,6 +293,9 @@ static void lv_scale_constructor(const lv_obj_class_t * class_p, lv_obj_t * obj) scale->minor_len = 5u; scale->last_tick_width = 0U; scale->first_tick_width = 0U; + scale->post_draw = false; + scale->custom_label_cnt = 0U; + scale->txt_src = NULL; LV_TRACE_OBJ_CREATE("finished"); } @@ -392,6 +406,12 @@ static void scale_draw_indicator(lv_obj_t * obj, lv_event_t * event) scale_set_line_properties(obj, &minor_tick_dsc, section->items_style, LV_PART_ITEMS); } } + else { + /* Tick is not in section, get the proper styles */ + lv_obj_init_draw_label_dsc(obj, LV_PART_INDICATOR, &label_dsc); + lv_obj_init_draw_line_dsc(obj, LV_PART_INDICATOR, &major_tick_dsc); + lv_obj_init_draw_line_dsc(obj, LV_PART_ITEMS, &minor_tick_dsc); + } } /* The tick is represented by a line. We need two points to draw it */ @@ -407,13 +427,7 @@ static void scale_draw_indicator(lv_obj_t * obj, lv_event_t * event) /* Check if the custom text array has element for this major tick index */ if(scale->txt_src) { - if(scale->txt_src[major_tick_idx - 1U]) { - label_dsc.text = scale->txt_src[major_tick_idx - 1U]; - label_dsc.text_local = 0; - } - else { - label_dsc.text = NULL; - } + scale_build_custom_label_text(obj, &label_dsc, major_tick_idx); } else { /* Add label with mapped values */ lv_snprintf(text_buffer, sizeof(text_buffer), "%" LV_PRId32, tick_value); @@ -429,72 +443,8 @@ static void scale_draw_indicator(lv_obj_t * obj, lv_event_t * event) scale_store_main_line_tick_width_compensation(obj, tick_idx, is_major_tick, major_tick_dsc.width, minor_tick_dsc.width); /* Store the first and last section tick vertical/horizontal position */ - _LV_LL_READ_BACK(&scale->section_ll, section) { - if(section->minor_range <= tick_value && section->major_range >= tick_value) { - if(is_major_tick) { - scale_set_indicator_label_properties(obj, &label_dsc, section->indicator_style); - scale_set_line_properties(obj, &major_tick_dsc, section->indicator_style, LV_PART_INDICATOR); - } - else { - scale_set_line_properties(obj, &minor_tick_dsc, section->items_style, LV_PART_ITEMS); - } - } - - if(LV_SCALE_MODE_VERTICAL_LEFT == scale->mode || LV_SCALE_MODE_VERTICAL_RIGHT == scale->mode) { - lv_coord_t tmp_width = 0; - - if(tick_idx == section->first_tick_idx_in_section) { - if(section->first_tick_idx_is_major) { - tmp_width = major_tick_dsc.width; - } - else { - tmp_width = minor_tick_dsc.width; - } - - section->first_tick_in_section.y = tick_point_a.y; - section->first_tick_in_section_width = tmp_width; - } - else if(tick_idx == section->last_tick_idx_in_section) { - if(section->last_tick_idx_is_major) { - tmp_width = major_tick_dsc.width; - } - else { - tmp_width = minor_tick_dsc.width; - } - - section->last_tick_in_section.y = tick_point_a.y; - section->last_tick_in_section_width = tmp_width; - } - else { /* Nothing to do */ } - } - else { - lv_coord_t tmp_width = 0; - - if(tick_idx == section->first_tick_idx_in_section) { - if(section->first_tick_idx_is_major) { - tmp_width = major_tick_dsc.width; - } - else { - tmp_width = minor_tick_dsc.width; - } - - section->first_tick_in_section.x = tick_point_a.x; - section->first_tick_in_section_width = tmp_width; - } - else if(tick_idx == section->last_tick_idx_in_section) { - if(section->last_tick_idx_is_major) { - tmp_width = major_tick_dsc.width; - } - else { - tmp_width = minor_tick_dsc.width; - } - - section->last_tick_in_section.x = tick_point_a.x; - section->last_tick_in_section_width = tmp_width; - } - else { /* Nothing to do */ } - } - } + scale_store_section_line_tick_width_compensation(obj, is_major_tick, &label_dsc, &major_tick_dsc, &minor_tick_dsc, + tick_value, tick_idx, &tick_point_a); if(is_major_tick) { major_tick_dsc.p1 = tick_point_a; @@ -544,6 +494,12 @@ static void scale_draw_indicator(lv_obj_t * obj, lv_event_t * event) scale_set_line_properties(obj, &minor_tick_dsc, section->items_style, LV_PART_ITEMS); } } + else { + /* Tick is not in section, get the proper styles */ + lv_obj_init_draw_label_dsc(obj, LV_PART_INDICATOR, &label_dsc); + lv_obj_init_draw_line_dsc(obj, LV_PART_INDICATOR, &major_tick_dsc); + lv_obj_init_draw_line_dsc(obj, LV_PART_ITEMS, &minor_tick_dsc); + } } /* The tick is represented by a line. We need two points to draw it */ @@ -559,13 +515,7 @@ static void scale_draw_indicator(lv_obj_t * obj, lv_event_t * event) /* Check if the custom text array has element for this major tick index */ if(scale->txt_src) { - if(scale->txt_src[major_tick_idx - 1U]) { - label_dsc.text = scale->txt_src[major_tick_idx - 1U]; - label_dsc.text_local = 0; - } - else { - label_dsc.text = NULL; - } + scale_build_custom_label_text(obj, &label_dsc, major_tick_idx); } else { /* Add label with mapped values */ lv_snprintf(text_buffer, sizeof(text_buffer), "%" LV_PRId32, tick_value); @@ -630,31 +580,29 @@ static void scale_draw_main(lv_obj_t * obj, lv_event_t * event) /* Get style properties so they can be used in the main line drawing */ const lv_coord_t border_width = lv_obj_get_style_border_width(obj, LV_PART_MAIN); - const lv_coord_t pad_top = lv_obj_get_style_pad_top(obj, LV_PART_MAIN) + lv_obj_get_style_border_width(obj, - LV_PART_MAIN); - const lv_coord_t pad_left = lv_obj_get_style_pad_left(obj, LV_PART_MAIN) + lv_obj_get_style_border_width(obj, - LV_PART_MAIN); - const lv_coord_t scroll_top = lv_obj_get_scroll_top(obj); - const lv_coord_t scroll_left = lv_obj_get_scroll_left(obj); + const lv_coord_t pad_top = lv_obj_get_style_pad_top(obj, LV_PART_MAIN) + border_width; + const lv_coord_t pad_bottom = lv_obj_get_style_pad_bottom(obj, LV_PART_MAIN) + border_width; + const lv_coord_t pad_left = lv_obj_get_style_pad_left(obj, LV_PART_MAIN) + border_width; + const lv_coord_t pad_right = lv_obj_get_style_pad_right(obj, LV_PART_MAIN) + border_width; lv_coord_t x_ofs = 0U; lv_coord_t y_ofs = 0U; if(LV_SCALE_MODE_VERTICAL_LEFT == scale->mode) { - x_ofs = obj->coords.x2 + (line_dsc.width / 2U); - y_ofs = obj->coords.y1 + pad_top + border_width - scroll_top; + x_ofs = obj->coords.x2 + (line_dsc.width / 2U) - pad_right; + y_ofs = obj->coords.y1 + pad_top; } else if(LV_SCALE_MODE_VERTICAL_RIGHT == scale->mode) { - x_ofs = obj->coords.x1 + (line_dsc.width / 2U); - y_ofs = obj->coords.y1 + pad_top + border_width - scroll_top; + x_ofs = obj->coords.x1 + (line_dsc.width / 2U) + pad_left; + y_ofs = obj->coords.y1 + pad_top; } if(LV_SCALE_MODE_HORIZONTAL_BOTTOM == scale->mode) { - x_ofs = obj->coords.x1 + pad_left - scroll_left; - y_ofs = obj->coords.y1 + (line_dsc.width / 2U); + x_ofs = obj->coords.x1 + pad_right; + y_ofs = obj->coords.y1 + (line_dsc.width / 2U) + pad_top; } else if(LV_SCALE_MODE_HORIZONTAL_TOP == scale->mode) { - x_ofs = obj->coords.x1 + pad_left - scroll_left; - y_ofs = obj->coords.y2 + (line_dsc.width / 2U); + x_ofs = obj->coords.x1 + pad_left; + y_ofs = obj->coords.y2 + (line_dsc.width / 2U) - pad_bottom; } else { /* Nothing to do */ } @@ -666,7 +614,7 @@ static void scale_draw_main(lv_obj_t * obj, lv_event_t * event) main_line_point_a.x = x_ofs - 1U; main_line_point_a.y = y_ofs; main_line_point_b.x = x_ofs - 1U; - main_line_point_b.y = obj->coords.y2 + pad_left - scroll_top; + main_line_point_b.y = obj->coords.y2 - pad_left; /* Adjust main line with initial and last tick width */ main_line_point_a.y -= scale->last_tick_width / 2U; @@ -675,7 +623,8 @@ static void scale_draw_main(lv_obj_t * obj, lv_event_t * event) else { main_line_point_a.x = x_ofs; main_line_point_a.y = y_ofs; - main_line_point_b.x = obj->coords.x2 + (pad_left - scroll_left); + /* X of second point starts at the edge of the object minus the left pad */ + main_line_point_b.x = obj->coords.x2 - (pad_left); main_line_point_b.y = y_ofs; /* Adjust main line with initial and last tick width */ @@ -701,23 +650,23 @@ static void scale_draw_main(lv_obj_t * obj, lv_event_t * event) if(LV_SCALE_MODE_VERTICAL_LEFT == scale->mode || LV_SCALE_MODE_VERTICAL_RIGHT == scale->mode) { /* Calculate position of the first tick in the section */ main_point_a.x = main_line_point_a.x; - float tmp = (float) section->first_tick_in_section.y + (float)(section->first_tick_in_section_width / 2U); - main_point_a.y = (lv_coord_t) tmp; + lv_coord_t tmp = (lv_coord_t)(section->first_tick_in_section_width / 2U); + main_point_a.y = section->first_tick_in_section.y + tmp; /* Calculate position of the last tick in the section */ main_point_b.x = main_line_point_a.x; - tmp = (float) section->last_tick_in_section.y - (float)(section->last_tick_in_section_width / 2U); - main_point_b.y = (lv_coord_t) tmp; + tmp = (lv_coord_t)(section->last_tick_in_section_width / 2U); + main_point_b.y = section->last_tick_in_section.y - tmp; } else { /* Calculate position of the first tick in the section */ - float tmp = (float) section->first_tick_in_section.x - (float)(section->first_tick_in_section_width / 2U); - main_point_a.x = (lv_coord_t) tmp; + lv_coord_t tmp = (lv_coord_t)(section->first_tick_in_section_width / 2U); + main_point_a.x = section->first_tick_in_section.x - tmp; main_point_a.y = main_line_point_a.y; /* Calculate position of the last tick in the section */ - tmp = (float) section->last_tick_in_section.x + (float)(section->last_tick_in_section_width / 2U); - main_point_b.x = (lv_coord_t) tmp; + tmp = (lv_coord_t)(section->last_tick_in_section_width / 2U); + main_point_b.x = section->last_tick_in_section.x + tmp; main_point_b.y = main_line_point_a.y; } @@ -837,28 +786,33 @@ static void scale_get_tick_points(lv_obj_t * obj, const uint32_t tick_idx, bool /* Get style properties so they can be used in the tick and label drawing */ const lv_coord_t border_width = lv_obj_get_style_border_width(obj, LV_PART_MAIN); - const lv_coord_t pad_top = lv_obj_get_style_pad_top(obj, LV_PART_MAIN) + lv_obj_get_style_border_width(obj, - LV_PART_MAIN); - const lv_coord_t pad_left = lv_obj_get_style_pad_left(obj, LV_PART_MAIN) + lv_obj_get_style_border_width(obj, - LV_PART_MAIN); + const lv_coord_t pad_top = lv_obj_get_style_pad_top(obj, LV_PART_MAIN) + border_width; + const lv_coord_t pad_bottom = lv_obj_get_style_pad_bottom(obj, LV_PART_MAIN) + border_width; + const lv_coord_t pad_right = lv_obj_get_style_pad_right(obj, LV_PART_MAIN) + border_width; + const lv_coord_t pad_left = lv_obj_get_style_pad_left(obj, LV_PART_MAIN) + border_width; + const lv_coord_t tick_pad_right = lv_obj_get_style_pad_right(obj, LV_PART_TICKS); + const lv_coord_t tick_pad_left = lv_obj_get_style_pad_left(obj, LV_PART_TICKS); + const lv_coord_t tick_pad_top = lv_obj_get_style_pad_top(obj, LV_PART_TICKS); + const lv_coord_t tick_pad_bottom = lv_obj_get_style_pad_bottom(obj, LV_PART_TICKS); + lv_coord_t x_ofs = 0U; lv_coord_t y_ofs = 0U; if(LV_SCALE_MODE_VERTICAL_LEFT == scale->mode) { - x_ofs = obj->coords.x2 + (main_line_dsc.width / 2U); - y_ofs = obj->coords.y1 + pad_top + border_width - lv_obj_get_scroll_top(obj); + x_ofs = obj->coords.x2 + (main_line_dsc.width / 2U) - pad_right; + y_ofs = obj->coords.y1 + (pad_top + tick_pad_top); } else if(LV_SCALE_MODE_VERTICAL_RIGHT == scale->mode) { - x_ofs = obj->coords.x1 + (main_line_dsc.width / 2U); - y_ofs = obj->coords.y1 + pad_top + border_width - lv_obj_get_scroll_top(obj); + x_ofs = obj->coords.x1 + (main_line_dsc.width / 2U) + pad_left; + y_ofs = obj->coords.y1 + (pad_top + tick_pad_top); } else if(LV_SCALE_MODE_HORIZONTAL_BOTTOM == scale->mode) { - x_ofs = obj->coords.x1 + pad_left - lv_obj_get_scroll_left(obj); - y_ofs = obj->coords.y1 + (main_line_dsc.width / 2U); + x_ofs = obj->coords.x1 + (pad_right + tick_pad_right); + y_ofs = obj->coords.y1 + (main_line_dsc.width / 2U) + pad_top; } else if(LV_SCALE_MODE_HORIZONTAL_TOP == scale->mode) { - x_ofs = obj->coords.x1 + pad_left - lv_obj_get_scroll_left(obj); - y_ofs = obj->coords.y2 + (main_line_dsc.width / 2U); + x_ofs = obj->coords.x1 + (pad_left + tick_pad_left); + y_ofs = obj->coords.y2 + (main_line_dsc.width / 2U) - pad_bottom; } else { /* Nothing to do */ } @@ -877,16 +831,17 @@ static void scale_get_tick_points(lv_obj_t * obj, const uint32_t tick_idx, bool /* Setup the tick points */ if(LV_SCALE_MODE_VERTICAL_LEFT == scale->mode || LV_SCALE_MODE_VERTICAL_RIGHT == scale->mode) { - /* Vertical position starts at y2 of the scale main line */ - lv_coord_t vertical_position = obj->coords.y2; + /* Vertical position starts at y2 of the scale main line, we start at y2 because the ticks are drawn from bottom to top */ + lv_coord_t vertical_position = obj->coords.y2 - (pad_bottom + tick_pad_bottom); + if(scale->total_tick_count == tick_idx) { - vertical_position = obj->coords.y1; + vertical_position = y_ofs; } /* Increment the tick offset depending of its index */ else if(0 != tick_idx) { - float section = (float) lv_obj_get_height(obj) / (float) scale->total_tick_count; - float offset = section * tick_idx; - vertical_position -= (lv_coord_t) offset; + const lv_coord_t scale_total_height = lv_obj_get_height(obj) - (pad_top + pad_bottom + tick_pad_top + tick_pad_bottom); + lv_coord_t offset = ((lv_coord_t) tick_idx * (lv_coord_t) scale_total_height) / (lv_coord_t) scale->total_tick_count; + vertical_position -= offset; } else { /* Nothing to do */ } @@ -897,16 +852,16 @@ static void scale_get_tick_points(lv_obj_t * obj, const uint32_t tick_idx, bool } else { /* Horizontal position starts at x1 of the scale main line */ - lv_coord_t horizontal_position = obj->coords.x1; + lv_coord_t horizontal_position = x_ofs; /* Position the last tick at the x2 scale coordinate */ if(scale->total_tick_count == tick_idx) { - horizontal_position = obj->coords.x2; + horizontal_position = obj->coords.x2 - (pad_left + tick_pad_left); } /* Increment the tick offset depending of its index */ else if(0U != tick_idx) { - float section = (float) lv_obj_get_width(obj) / (float) scale->total_tick_count; - float offset = section * tick_idx; - horizontal_position += (lv_coord_t) offset; + const lv_coord_t scale_total_width = lv_obj_get_width(obj) - (pad_right + pad_left + tick_pad_right + tick_pad_left); + lv_coord_t offset = ((lv_coord_t) tick_idx * (lv_coord_t) scale_total_width) / (lv_coord_t) scale->total_tick_count; + horizontal_position += offset; } else { /* Nothing to do */ } @@ -1246,4 +1201,110 @@ static void scale_store_main_line_tick_width_compensation(lv_obj_t * obj, const else { /* Nothing to do */ } } +/** + * Sets the text of the tick label descriptor when using custom labels + * + * Sets the text pointer when valid custom label is available, otherwise set it to NULL. + * + * @param obj pointer to a scale object + * @param label_dsc pointer to the label descriptor + * @param major_tick_idx index of the current major tick + */ +static void scale_build_custom_label_text(lv_obj_t * obj, lv_draw_label_dsc_t * label_dsc, + const uint16_t major_tick_idx) +{ + lv_scale_t * scale = (lv_scale_t *) obj; + + /* Check if the scale has valid custom labels available, + * this avoids reading past txt_src array when the scale requires more tick labels than available */ + if(major_tick_idx <= scale->custom_label_cnt) { + if(scale->txt_src[major_tick_idx - 1U]) { + label_dsc->text = scale->txt_src[major_tick_idx - 1U]; + label_dsc->text_local = 0; + } + else { + label_dsc->text = NULL; + } + } + else { + label_dsc->text = NULL; + } +} + +/** + * Stores tick width compensation information for main line sections + * + * @param obj pointer to a scale object + * @param is_major_tick Indicates if tick is major or not + * @param label_dsc pointer to the label descriptor + * @param major_tick_dsc pointer to the major_tick_dsc + * @param minor_tick_dsc pointer to the minor_tick_dsc + * @param tick_value Current tick value, used to know if tick_idx belongs to a section or not + * @param tick_idx Current tick index + * @param tick_point_a Pointer to tick point a + */ +static void scale_store_section_line_tick_width_compensation(lv_obj_t * obj, const bool is_major_tick, + lv_draw_label_dsc_t * label_dsc, lv_draw_line_dsc_t * major_tick_dsc, lv_draw_line_dsc_t * minor_tick_dsc, + const int32_t tick_value, const uint8_t tick_idx, lv_point_t * tick_point_a) +{ + lv_scale_t * scale = (lv_scale_t *) obj; + lv_scale_section_t * section; + + _LV_LL_READ_BACK(&scale->section_ll, section) { + if(section->minor_range <= tick_value && section->major_range >= tick_value) { + if(is_major_tick) { + scale_set_indicator_label_properties(obj, label_dsc, section->indicator_style); + scale_set_line_properties(obj, major_tick_dsc, section->indicator_style, LV_PART_INDICATOR); + } + else { + scale_set_line_properties(obj, minor_tick_dsc, section->items_style, LV_PART_ITEMS); + } + } + + lv_coord_t tmp_width = 0; + + if(tick_idx == section->first_tick_idx_in_section) { + if(section->first_tick_idx_is_major) { + tmp_width = major_tick_dsc->width; + } + else { + tmp_width = minor_tick_dsc->width; + } + + section->first_tick_in_section.y = tick_point_a->y; + /* Add 1px as adjustment if tmp_width is odd */ + if(tmp_width & 0x01U) { + if(LV_SCALE_MODE_VERTICAL_LEFT == scale->mode || LV_SCALE_MODE_VERTICAL_RIGHT == scale->mode) { + tmp_width += 1U; + } + else { + tmp_width -= 1U; + } + } + section->first_tick_in_section_width = tmp_width; + } + else if(tick_idx == section->last_tick_idx_in_section) { + if(section->last_tick_idx_is_major) { + tmp_width = major_tick_dsc->width; + } + else { + tmp_width = minor_tick_dsc->width; + } + + section->last_tick_in_section.y = tick_point_a->y; + /* Add 1px as adjustment if tmp_width is odd */ + if(tmp_width & 0x01U) { + if(LV_SCALE_MODE_VERTICAL_LEFT == scale->mode || LV_SCALE_MODE_VERTICAL_RIGHT == scale->mode) { + tmp_width -= 1U; + } + else { + tmp_width += 1U; + } + } + section->last_tick_in_section_width = tmp_width; + } + else { /* Nothing to do */ } + } +} + #endif diff --git a/src/widgets/scale/lv_scale.h b/src/widgets/scale/lv_scale.h index 38eadf67d..cefc1a6f1 100644 --- a/src/widgets/scale/lv_scale.h +++ b/src/widgets/scale/lv_scale.h @@ -73,6 +73,7 @@ typedef struct { lv_obj_t obj; lv_ll_t section_ll; /**< Linked list for the sections (stores lv_scale_section_t)*/ char ** txt_src; + lv_coord_t custom_label_cnt; lv_coord_t major_len; lv_coord_t minor_len; lv_coord_t range_min;