diff --git a/demos/render/lv_demo_render.c b/demos/render/lv_demo_render.c index 68fb4f744..044d988f7 100644 --- a/demos/render/lv_demo_render.c +++ b/demos/render/lv_demo_render.c @@ -115,7 +115,6 @@ static void fill_cb(lv_obj_t * parent) static lv_obj_t * border_obj_create(lv_obj_t * parent, int32_t col, int32_t row) { - lv_obj_t * obj = lv_obj_create(parent); lv_obj_remove_style_all(obj); lv_obj_set_style_border_color(obj, lv_color_hex3(0x000), 0); diff --git a/src/core/lv_obj.c b/src/core/lv_obj.c index 605044e85..f0b211248 100644 --- a/src/core/lv_obj.c +++ b/src/core/lv_obj.c @@ -422,6 +422,22 @@ static void lv_obj_draw(lv_event_t * e) return; } + if(lv_obj_get_style_bg_grad_dir(obj, 0) != LV_GRAD_DIR_NONE) { + if(lv_obj_get_style_bg_grad_opa(obj, 0) < LV_OPA_MAX) { + info->res = LV_COVER_RES_NOT_COVER; + return; + } + const lv_grad_dsc_t * grad_dsc = lv_obj_get_style_bg_grad(obj, 0); + if(grad_dsc) { + uint32_t i; + for(i = 0; i < grad_dsc->stops_count; i++) { + if(grad_dsc->stops[i].opa < LV_OPA_MAX) { + info->res = LV_COVER_RES_NOT_COVER; + return; + } + } + } + } info->res = LV_COVER_RES_COVER; } diff --git a/src/draw/lv_draw_label.c b/src/draw/lv_draw_label.c index 74071438f..7ad6ed65c 100644 --- a/src/draw/lv_draw_label.c +++ b/src/draw/lv_draw_label.c @@ -278,7 +278,7 @@ void lv_draw_label_iterate_letters(lv_draw_unit_t * draw_unit, const lv_draw_lab /*Always set the bg_coordinates for placeholder drawing*/ bg_coords.x1 = pos.x; bg_coords.y1 = pos.y; - bg_coords.x2 = pos.x + letter_w + dsc->letter_space - 1; + bg_coords.x2 = pos.x + letter_w - 1; bg_coords.y2 = pos.y + line_height - 1; if(i >= line_end - line_start) { @@ -387,7 +387,8 @@ static void draw_letter(lv_draw_unit_t * draw_unit, lv_draw_glyph_dsc_t * dsc, letter_coords.y2 = letter_coords.y1 + g.box_h - 1; /*If the letter is completely out of mask don't draw it*/ - if(_lv_area_is_out(&letter_coords, draw_unit->clip_area, 0)) { + if(_lv_area_is_out(&letter_coords, draw_unit->clip_area, 0) && + _lv_area_is_out(dsc->bg_coords, draw_unit->clip_area, 0)) { LV_PROFILER_END; return; } diff --git a/src/draw/sw/lv_draw_sw_fill.c b/src/draw/sw/lv_draw_sw_fill.c index 9274f25c1..bb83bc6a6 100644 --- a/src/draw/sw/lv_draw_sw_fill.c +++ b/src/draw/sw/lv_draw_sw_fill.c @@ -132,7 +132,9 @@ void lv_draw_sw_fill(lv_draw_unit_t * draw_unit, const lv_draw_fill_dsc_t * dsc, blend_dsc.mask_res = lv_draw_sw_mask_apply(mask_list, mask_buf, blend_area.x1, top_y, clipped_w); if(blend_dsc.mask_res == LV_DRAW_SW_MASK_RES_FULL_COVER) blend_dsc.mask_res = LV_DRAW_SW_MASK_RES_CHANGED; + bool hor_grad_processed; if(top_y >= clipped_coords.y1) { + hor_grad_processed = false; blend_area.y1 = top_y; blend_area.y2 = top_y; @@ -141,6 +143,7 @@ void lv_draw_sw_fill(lv_draw_unit_t * draw_unit, const lv_draw_fill_dsc_t * dsc, blend_dsc.opa = grad->opa_map[top_y - bg_coords.y1]; } else if(grad_dir == LV_GRAD_DIR_HOR) { + hor_grad_processed = true; if(grad_opa_map) { int32_t i; for(i = 0; i < clipped_w; i++) { @@ -160,6 +163,15 @@ void lv_draw_sw_fill(lv_draw_unit_t * draw_unit, const lv_draw_fill_dsc_t * dsc, blend_dsc.color = grad->color_map[bottom_y - bg_coords.y1]; blend_dsc.opa = grad->opa_map[bottom_y - bg_coords.y1]; } + else if(hor_grad_processed == false && grad_dir == LV_GRAD_DIR_HOR) { + if(grad_opa_map) { + int32_t i; + for(i = 0; i < clipped_w; i++) { + if(grad_opa_map[i] < LV_OPA_MAX) mask_buf[i] = (mask_buf[i] * grad_opa_map[i]) >> 8; + } + blend_dsc.mask_res = LV_DRAW_SW_MASK_RES_CHANGED; + } + } lv_draw_sw_blend(draw_unit, &blend_dsc); } } diff --git a/tests/ref_imgs/widgets/obj_flag_overflow_visible_1_4.png b/tests/ref_imgs/widgets/obj_flag_overflow_visible_1_4.png index b5c2f7b3e..d2a59684d 100644 Binary files a/tests/ref_imgs/widgets/obj_flag_overflow_visible_1_4.png and b/tests/ref_imgs/widgets/obj_flag_overflow_visible_1_4.png differ diff --git a/tests/unity/unity_support.c b/tests/unity/unity_support.c index 935e14a25..c1382fd47 100644 --- a/tests/unity/unity_support.c +++ b/tests/unity/unity_support.c @@ -11,7 +11,7 @@ /********************* * INCLUDES *********************/ -#if LV_BUILD_TEST +#if LV_BUILD_TEST || 1 #include "../lvgl.h" #include #include @@ -47,6 +47,7 @@ typedef struct { /********************** * STATIC PROTOTYPES **********************/ +static bool screenhot_compare(const char * fn_ref, const char * mode, uint8_t tolerance); static int read_png_file(png_image_t * p, const char * file_name); static int write_png_file(void * raw_img, uint32_t width, uint32_t height, char * file_name); static void png_release(png_image_t * p); @@ -65,11 +66,69 @@ static void png_release(png_image_t * p); bool lv_test_assert_image_eq(const char * fn_ref) { + bool pass; + + lv_obj_t * scr = lv_screen_active(); + lv_obj_invalidate(scr); + + pass = screenhot_compare(fn_ref, "full refresh", 0); + if(!pass) return false; + + //Software has minor rounding errors when not the whole image is updated + //so ignore stripe invalidation for now + // uint32_t i; + // for(i = 0; i < 800; i += 50 ) { + // lv_area_t a; + // a.y1 = 0; + // a.y2 = 479; + // a.x1 = i; + // a.x2 = i + 12; + // lv_obj_invalidate_area(scr, &a); + // + // a.x1 = i + 25; + // a.x2 = i + 32; + // lv_obj_invalidate_area(scr, &a); + // } + // + // pass = screenhot_compare(fn_ref, "vertical stripes", 32); + // if(!pass) return false; + // + // + // for(i = 0; i < 480; i += 40) { + // lv_area_t a; + // a.x1 = 0; + // a.x2 = 799; + // a.y1 = i; + // a.y2 = i + 9; + // lv_obj_invalidate_area(scr, &a); + // + // a.y1 = i + 25; + // a.y2 = i + 32; + // lv_obj_invalidate_area(scr, &a); + // } + // + // pass = screenhot_compare(fn_ref, "horizontal stripes", 32); + // if(!pass) return false; + + return true; +} + +/********************** + * STATIC FUNCTIONS + **********************/ + +/** + * Compare the content of the frame buffer with a reference image + * @param fn_ref reference image name + * @param mode arbitrary string to tell more about the compare + * @return true: test passed; false: test failed + */ +static bool screenhot_compare(const char * fn_ref, const char * mode, uint8_t tolerance) +{ + char fn_ref_full[512]; sprintf(fn_ref_full, "%s%s", REF_IMGS_PATH, fn_ref); - - //lv_obj_invalidate(lv_screen_active()); lv_refr_now(NULL); extern uint8_t * last_flushed_buf; @@ -91,13 +150,14 @@ bool lv_test_assert_image_eq(const char * fn_ref) const png_byte * ptr_ref = NULL; bool err = false; - int x, y, i_buf = 0; + uint32_t stride = lv_draw_buf_width_to_stride(800, LV_COLOR_FORMAT_ARGB8888); + int x, y; for(y = 0; y < p.height; y++) { + uint8_t * screen_buf_tmp = screen_buf + stride * y; png_byte * row = p.row_pointers[y]; - for(x = 0; x < p.width; x++) { ptr_ref = &(row[x * 3]); - ptr_act = &(screen_buf[i_buf * 4]); + ptr_act = screen_buf_tmp; uint32_t ref_px = 0; uint32_t act_px = 0; @@ -106,13 +166,16 @@ bool lv_test_assert_image_eq(const char * fn_ref) uint8_t act_swap[3] = {ptr_act[2], ptr_act[1], ptr_act[0]}; - if(memcmp(act_swap, ptr_ref, 3) != 0) { - TEST_PRINTF("Error on x:%d, y:%d. Expected %X, Actual %X", x, y, ref_px, act_px); + if(LV_ABS((int32_t) act_swap[0] - ptr_ref[0]) > tolerance || + LV_ABS((int32_t) act_swap[1] - ptr_ref[1]) > tolerance || + LV_ABS((int32_t) act_swap[2] - ptr_ref[2]) > tolerance) { + uint32_t act_swap_32 = (act_swap[2] << 16) + (act_swap[1] << 8) + (act_swap[0] << 0); + TEST_PRINTF("Error %s on x:%d, y:%d.\nExpected: %X\nActual: %X", mode, x, y, ref_px, act_swap_32); fflush(stderr); err = true; break; } - i_buf++; + screen_buf_tmp += 4; } if(err) break; } @@ -128,7 +191,6 @@ bool lv_test_assert_image_eq(const char * fn_ref) write_png_file(screen_buf, 800, 480, fn_err_full); } - png_release(&p); fflush(stdout); @@ -136,10 +198,6 @@ bool lv_test_assert_image_eq(const char * fn_ref) } -/********************** - * STATIC FUNCTIONS - **********************/ - static int read_png_file(png_image_t * p, const char * file_name) { char header[8]; // 8 is the maximum size that can be checked @@ -204,7 +262,6 @@ static int read_png_file(png_image_t * p, const char * file_name) return 0; } - static int write_png_file(void * raw_img, uint32_t width, uint32_t height, char * file_name) { png_structp png_ptr; @@ -253,7 +310,6 @@ static int write_png_file(void * raw_img, uint32_t width, uint32_t height, char png_write_info(png_ptr, info_ptr); - /* write bytes */ if(setjmp(png_jmpbuf(png_ptr))) { TEST_PRINTF("[write_png_file %s] Error during writing bytes", file_name); @@ -273,7 +329,6 @@ static int write_png_file(void * raw_img, uint32_t width, uint32_t height, char } png_write_image(png_ptr, row_pointers); - /* end write */ if(setjmp(png_jmpbuf(png_ptr))) { TEST_PRINTF("[write_png_file %s] Error during end of write", file_name); @@ -291,7 +346,6 @@ static int write_png_file(void * raw_img, uint32_t width, uint32_t height, char return 0; } - static void png_release(png_image_t * p) { int y; @@ -302,5 +356,4 @@ static void png_release(png_image_t * p) png_destroy_read_struct(&p->png_ptr, &p->info_ptr, NULL); } - #endif