diff --git a/src/core/lv_obj_scroll.c b/src/core/lv_obj_scroll.c index 322c81b516..d9bef351ac 100644 --- a/src/core/lv_obj_scroll.c +++ b/src/core/lv_obj_scroll.c @@ -35,6 +35,7 @@ /********************** * STATIC PROTOTYPES **********************/ +static inline int32_t mul_div(int32_t v, int32_t factor, int32_t divisor); static void scroll_x_anim(void * obj, int32_t v); static void scroll_y_anim(void * obj, int32_t v); static void scroll_end_cb(lv_anim_t * a); @@ -600,7 +601,7 @@ void lv_obj_get_scrollbar_area(lv_obj_t * obj, lv_area_t * hor_area, lv_area_t * ver_area->x1 = ver_area->x2 - thickness + 1; } - int32_t sb_h = ((obj_h - top_space - bottom_space - hor_req_space) * obj_h) / content_h; + int32_t sb_h = mul_div(obj_h - top_space - bottom_space - hor_req_space, obj_h, content_h); sb_h = LV_MAX(length > 0 ? length : sb_h, SCROLLBAR_MIN_SIZE); /*Style-defined size, calculated size, or minimum size*/ sb_h = LV_MIN(sb_h, obj_h); /*Limit scrollbar length to parent height*/ rem = (obj_h - top_space - bottom_space - hor_req_space) - @@ -611,7 +612,7 @@ void lv_obj_get_scrollbar_area(lv_obj_t * obj, lv_area_t * hor_area, lv_area_t * ver_area->y2 = obj->coords.y2 - bottom_space - hor_req_space - 1; } else { - int32_t sb_y = (rem * sb) / scroll_h; + int32_t sb_y = mul_div(rem, sb, scroll_h); sb_y = rem - sb_y; ver_area->y1 = obj->coords.y1 + sb_y + top_space; @@ -639,7 +640,7 @@ void lv_obj_get_scrollbar_area(lv_obj_t * obj, lv_area_t * hor_area, lv_area_t * hor_area->x1 = obj->coords.x1; hor_area->x2 = obj->coords.x2; - int32_t sb_w = ((obj_w - left_space - right_space - ver_reg_space) * obj_w) / content_w; + int32_t sb_w = mul_div(obj_w - left_space - right_space - ver_reg_space, obj_w, content_w); sb_w = LV_MAX(length > 0 ? length : sb_w, SCROLLBAR_MIN_SIZE); /*Style-defined size, calculated size, or minimum size*/ sb_w = LV_MIN(sb_w, obj_w); /*Limit scrollbar length to parent width*/ rem = (obj_w - left_space - right_space - ver_reg_space) - @@ -656,7 +657,7 @@ void lv_obj_get_scrollbar_area(lv_obj_t * obj, lv_area_t * hor_area, lv_area_t * } } else { - int32_t sb_x = (rem * sr) / scroll_w; + int32_t sb_x = mul_div(rem, sr, scroll_w); sb_x = rem - sb_x; if(rtl) { @@ -748,6 +749,11 @@ void lv_obj_readjust_scroll(lv_obj_t * obj, lv_anim_enable_t anim_en) * STATIC FUNCTIONS **********************/ +static inline int32_t mul_div(int32_t v, int32_t factor, int32_t divisor) +{ + return ((int64_t)v * factor) / divisor; +} + static void scroll_x_anim(void * obj, int32_t v) { lv_obj_scroll_by_raw(obj, v + lv_obj_get_scroll_x(obj), 0); diff --git a/tests/ref_imgs/scrollbar_horizontal.png b/tests/ref_imgs/scrollbar_horizontal.png new file mode 100644 index 0000000000..b024a8da60 Binary files /dev/null and b/tests/ref_imgs/scrollbar_horizontal.png differ diff --git a/tests/ref_imgs/scrollbar_vertical.png b/tests/ref_imgs/scrollbar_vertical.png new file mode 100644 index 0000000000..c283680f4d Binary files /dev/null and b/tests/ref_imgs/scrollbar_vertical.png differ diff --git a/tests/ref_imgs_vg_lite/scrollbar_horizontal.png b/tests/ref_imgs_vg_lite/scrollbar_horizontal.png new file mode 100644 index 0000000000..7896ca213f Binary files /dev/null and b/tests/ref_imgs_vg_lite/scrollbar_horizontal.png differ diff --git a/tests/ref_imgs_vg_lite/scrollbar_vertical.png b/tests/ref_imgs_vg_lite/scrollbar_vertical.png new file mode 100644 index 0000000000..3b7d1bd6a9 Binary files /dev/null and b/tests/ref_imgs_vg_lite/scrollbar_vertical.png differ diff --git a/tests/src/test_cases/test_scrollbar.c b/tests/src/test_cases/test_scrollbar.c new file mode 100644 index 0000000000..3f5553036e --- /dev/null +++ b/tests/src/test_cases/test_scrollbar.c @@ -0,0 +1,52 @@ +#if LV_BUILD_TEST +#include "../lvgl.h" +#include "../../lvgl_private.h" + +#include "unity/unity.h" + +void setUp(void) +{ + /* Function run before every test */ +} + +void tearDown(void) +{ + /* Function run after every test */ + lv_obj_clean(lv_screen_active()); +} + +void test_scrollbar_vertical(void) +{ + lv_obj_set_flex_flow(lv_screen_active(), LV_FLEX_FLOW_ROW); + + const int32_t inner_sizes[] = {100, 500, 1000, 5000, 100000, 500000, 1000000, 4000000}; + for(size_t i = 0; i < sizeof(inner_sizes) / sizeof(inner_sizes[0]); i++) { + lv_obj_t * wrapper = lv_obj_create(lv_screen_active()); + lv_obj_set_flex_grow(wrapper, 1); + lv_obj_set_height(wrapper, LV_PCT(100)); + + lv_obj_t * inner = lv_obj_create(wrapper); + lv_obj_set_size(inner, LV_PCT(100), inner_sizes[i]); + } + + TEST_ASSERT_EQUAL_SCREENSHOT("scrollbar_vertical.png"); +} + +void test_scrollbar_horizontal(void) +{ + lv_obj_set_flex_flow(lv_screen_active(), LV_FLEX_FLOW_COLUMN); + + const int32_t inner_sizes[] = {100, 500, 1000, 5000, 100000, 500000, 1000000, 4000000}; + for(size_t i = 0; i < sizeof(inner_sizes) / sizeof(inner_sizes[0]); i++) { + lv_obj_t * wrapper = lv_obj_create(lv_screen_active()); + lv_obj_set_flex_grow(wrapper, 1); + lv_obj_set_width(wrapper, LV_PCT(100)); + + lv_obj_t * inner = lv_obj_create(wrapper); + lv_obj_set_size(inner, inner_sizes[i], LV_PCT(100)); + } + + TEST_ASSERT_EQUAL_SCREENSHOT("scrollbar_horizontal.png"); +} + +#endif