From ca70164c6b409ecfc09b407bd3d85c734fdfe67e Mon Sep 17 00:00:00 2001 From: VIFEX Date: Wed, 10 Jul 2024 01:49:36 +0800 Subject: [PATCH] feat(barcode): add none tiled mode (#6462) Signed-off-by: pengyiqiang Co-authored-by: pengyiqiang --- src/libs/barcode/lv_barcode.c | 114 ++++++++++++++---- src/libs/barcode/lv_barcode.h | 8 ++ tests/ref_imgs/libs/barcode_tiled_1.png | Bin 0 -> 2375 bytes tests/ref_imgs/libs/barcode_tiled_2.png | Bin 0 -> 2763 bytes tests/ref_imgs_vg_lite/libs/barcode_1.png | Bin 2374 -> 2375 bytes tests/ref_imgs_vg_lite/libs/barcode_2.png | Bin 2624 -> 2763 bytes .../ref_imgs_vg_lite/libs/barcode_tiled_1.png | Bin 0 -> 2374 bytes .../ref_imgs_vg_lite/libs/barcode_tiled_2.png | Bin 0 -> 2624 bytes tests/src/test_cases/libs/test_barcode.c | 38 +++--- 9 files changed, 125 insertions(+), 35 deletions(-) create mode 100644 tests/ref_imgs/libs/barcode_tiled_1.png create mode 100644 tests/ref_imgs/libs/barcode_tiled_2.png create mode 100644 tests/ref_imgs_vg_lite/libs/barcode_tiled_1.png create mode 100644 tests/ref_imgs_vg_lite/libs/barcode_tiled_2.png diff --git a/src/libs/barcode/lv_barcode.c b/src/libs/barcode/lv_barcode.c index 16eebcdd6f..1003b2a475 100644 --- a/src/libs/barcode/lv_barcode.c +++ b/src/libs/barcode/lv_barcode.c @@ -28,6 +28,7 @@ static void lv_barcode_constructor(const lv_obj_class_t * class_p, lv_obj_t * obj); static void lv_barcode_destructor(const lv_obj_class_t * class_p, lv_obj_t * obj); static bool lv_barcode_change_buf_size(lv_obj_t * obj, int32_t w, int32_t h); +static void lv_barcode_clear(lv_obj_t * obj); /********************** * STATIC VARIABLES @@ -94,16 +95,23 @@ void lv_barcode_set_direction(lv_obj_t * obj, lv_dir_t direction) barcode->direction = direction; } +void lv_barcode_set_tiled(lv_obj_t * obj, bool tiled) +{ + LV_ASSERT_OBJ(obj, MY_CLASS); + + lv_barcode_t * barcode = (lv_barcode_t *)obj; + barcode->tiled = tiled; + lv_image_set_inner_align(obj, tiled ? LV_IMAGE_ALIGN_TILE : LV_IMAGE_ALIGN_DEFAULT); +} + lv_result_t lv_barcode_update(lv_obj_t * obj, const char * data) { LV_ASSERT_OBJ(obj, MY_CLASS); LV_ASSERT_NULL(data); - lv_result_t res = LV_RESULT_INVALID; - lv_barcode_t * barcode = (lv_barcode_t *)obj; - if(data == NULL || lv_strlen(data) == 0) { LV_LOG_WARN("data is empty"); + lv_barcode_clear(obj); return LV_RESULT_INVALID; } @@ -114,43 +122,92 @@ lv_result_t lv_barcode_update(lv_obj_t * obj, const char * data) LV_ASSERT_MALLOC(out_buf); if(!out_buf) { LV_LOG_ERROR("malloc failed for out_buf"); + lv_barcode_clear(obj); return LV_RESULT_INVALID; } int32_t barcode_w = (int32_t) code128_encode_gs1(data, out_buf, len); - LV_LOG_INFO("barcode width = %d", (int)barcode_w); + LV_LOG_INFO("barcode width = %" LV_PRId32, barcode_w); + lv_barcode_t * barcode = (lv_barcode_t *)obj; LV_ASSERT(barcode->scale > 0); uint16_t scale = barcode->scale; - int32_t buf_w = (barcode->direction == LV_DIR_HOR) ? barcode_w * scale : 1; - int32_t buf_h = (barcode->direction == LV_DIR_VER) ? barcode_w * scale : 1; + int32_t buf_w; + int32_t buf_h; - if(!lv_barcode_change_buf_size(obj, buf_w, buf_h)) { - goto failed; + if(barcode->tiled) { + buf_w = (barcode->direction == LV_DIR_HOR) ? barcode_w * scale : 1; + buf_h = (barcode->direction == LV_DIR_VER) ? barcode_w * scale : 1; + } + else { + lv_obj_update_layout(obj); + buf_w = (barcode->direction == LV_DIR_HOR) ? barcode_w * scale : lv_obj_get_width(obj); + buf_h = (barcode->direction == LV_DIR_VER) ? barcode_w * scale : lv_obj_get_height(obj); } - lv_canvas_set_palette(obj, 0, lv_color_to_32(barcode->dark_color, 0xff)); - lv_canvas_set_palette(obj, 1, lv_color_to_32(barcode->light_color, 0xff)); + if(!lv_barcode_change_buf_size(obj, buf_w, buf_h)) { + lv_barcode_clear(obj); + lv_free(out_buf); + return LV_RESULT_INVALID; + } + + /* Temporarily disable invalidation to improve the efficiency of lv_canvas_set_px */ + lv_display_enable_invalidation(lv_obj_get_display(obj), false); + + lv_draw_buf_t * draw_buf = lv_canvas_get_draw_buf(obj); + uint32_t stride = draw_buf->header.stride; + const lv_color_t color = lv_color_hex(1); + + /* Clear the canvas */ + lv_draw_buf_clear(draw_buf, NULL); + + /* Set the palette */ + lv_canvas_set_palette(obj, 0, lv_color_to_32(barcode->light_color, LV_OPA_COVER)); + lv_canvas_set_palette(obj, 1, lv_color_to_32(barcode->dark_color, LV_OPA_COVER)); for(int32_t x = 0; x < barcode_w; x++) { - lv_color_t color; - color = lv_color_hex(out_buf[x] ? 0 : 1); + /*skip empty data*/ + if(out_buf[x] == 0) { + continue; + } + for(uint16_t i = 0; i < scale; i++) { + int32_t offset = x * scale + i; if(barcode->direction == LV_DIR_HOR) { - lv_canvas_set_px(obj, x * scale + i, 0, color, LV_OPA_COVER); + lv_canvas_set_px(obj, offset, 0, color, LV_OPA_COVER); } - else { - lv_canvas_set_px(obj, 0, x * scale + i, color, LV_OPA_COVER); + else { /*LV_DIR_VER*/ + if(barcode->tiled) { + lv_canvas_set_px(obj, 0, offset, color, LV_OPA_COVER); + } + else { + uint8_t * dest = lv_draw_buf_goto_xy(draw_buf, 0, offset); + lv_memset(dest, 0xFF, stride); + } } } } - res = LV_RESULT_OK; + /* Copy pixels by row */ + if(!barcode->tiled && barcode->direction == LV_DIR_HOR && buf_h > 1) { + /* Skip the first row */ + int32_t h = buf_h - 1; + const uint8_t * src = lv_draw_buf_goto_xy(draw_buf, 0, 0); + uint8_t * dest = lv_draw_buf_goto_xy(draw_buf, 0, 1); + while(h--) { + lv_memcpy(dest, src, stride); + dest += stride; + } + } + + /* invalidate the canvas to refresh it */ + lv_display_enable_invalidation(lv_obj_get_display(obj), true); + lv_obj_invalidate(obj); -failed: lv_free(out_buf); - return res; + + return LV_RESULT_OK; } lv_color_t lv_barcode_get_dark_color(lv_obj_t * obj) @@ -190,7 +247,7 @@ static void lv_barcode_constructor(const lv_obj_class_t * class_p, lv_obj_t * ob barcode->light_color = lv_color_white(); barcode->scale = 1; barcode->direction = LV_DIR_HOR; - lv_image_set_inner_align(obj, LV_IMAGE_ALIGN_TILE); + lv_image_set_inner_align(obj, LV_IMAGE_ALIGN_DEFAULT); } static void lv_barcode_destructor(const lv_obj_class_t * class_p, lv_obj_t * obj) @@ -208,7 +265,10 @@ static void lv_barcode_destructor(const lv_obj_class_t * class_p, lv_obj_t * obj static bool lv_barcode_change_buf_size(lv_obj_t * obj, int32_t w, int32_t h) { LV_ASSERT_NULL(obj); - LV_ASSERT(w > 0); + if(w <= 0 || h <= 0) { + LV_LOG_WARN("invalid size: %" LV_PRId32 " x %" LV_PRId32, w, h); + return false; + } lv_draw_buf_t * old_buf = lv_canvas_get_draw_buf(obj); lv_draw_buf_t * new_buf = lv_draw_buf_create(w, h, LV_COLOR_FORMAT_I1, LV_STRIDE_AUTO); @@ -218,10 +278,22 @@ static bool lv_barcode_change_buf_size(lv_obj_t * obj, int32_t w, int32_t h) } lv_canvas_set_draw_buf(obj, new_buf); - LV_LOG_INFO("set canvas buffer: %p, width = %d", (void *)new_buf, (int)w); + LV_LOG_INFO("set canvas buffer: %p, width = %" LV_PRId32, (void *)new_buf, w); if(old_buf != NULL) lv_draw_buf_destroy(old_buf); return true; } +static void lv_barcode_clear(lv_obj_t * obj) +{ + lv_draw_buf_t * draw_buf = lv_canvas_get_draw_buf(obj); + if(!draw_buf) { + return; + } + + lv_draw_buf_clear(draw_buf, NULL); + lv_image_cache_drop(draw_buf); + lv_obj_invalidate(obj); +} + #endif /*LV_USE_BARCODE*/ diff --git a/src/libs/barcode/lv_barcode.h b/src/libs/barcode/lv_barcode.h index 4f7b446b98..343e18bf86 100644 --- a/src/libs/barcode/lv_barcode.h +++ b/src/libs/barcode/lv_barcode.h @@ -35,6 +35,7 @@ typedef struct { lv_color_t light_color; uint16_t scale; lv_dir_t direction; + bool tiled; } lv_barcode_t; LV_ATTRIBUTE_EXTERN_DATA extern const lv_obj_class_t lv_barcode_class; @@ -78,6 +79,13 @@ void lv_barcode_set_scale(lv_obj_t * obj, uint16_t scale); */ void lv_barcode_set_direction(lv_obj_t * obj, lv_dir_t direction); +/** + * Set the tiled mode of a barcode object + * @param obj pointer to barcode object + * @param tiled true: tiled mode, false: normal mode (default) + */ +void lv_barcode_set_tiled(lv_obj_t * obj, bool tiled); + /** * Set the data of a barcode object * @param obj pointer to barcode object diff --git a/tests/ref_imgs/libs/barcode_tiled_1.png b/tests/ref_imgs/libs/barcode_tiled_1.png new file mode 100644 index 0000000000000000000000000000000000000000..8c2c9a224f20ca31740638b685a8b2ad1f8bcbd9 GIT binary patch literal 2375 zcmeAS@N?(olHy`uVBq!ia0y~yU{+vYV0^&A1QfZHI&TpJ11F!Si(^Q|oVPa)W;F*0 zI9!a{_33~8)ttAB1Xu#+on-a4NEdDLb4z|ODKm1KJ_Cc*{c<4rA(KUn!NDhik>SWF zV>A#(Q^F9-1#h0eWBsxJS!LbNJDIcQt-oGcyYKV&s_HY}=KgK@`|v*vRS6Kb`)We;5}QIZ@M|zLRBOuF%ch literal 0 HcmV?d00001 diff --git a/tests/ref_imgs/libs/barcode_tiled_2.png b/tests/ref_imgs/libs/barcode_tiled_2.png new file mode 100644 index 0000000000000000000000000000000000000000..e86c231d2d87e545c6ccb255756f70e129295c36 GIT binary patch literal 2763 zcmcImZAepL6h6DUrcTX>ZWviwR)4l6`q77yDU*`IB7zhlN0j}MEDLlH+x+;END%($ zgG8a9La_`cf~bpxB6A@95HgiW2jxd7n4-l>sTH2H^xBI#WL6oe2 zTdHY1-G~h!-4!S5^}(kIDrPFWq_dP&2R4IocrGhnE@k_WcKkh?;2V595*loeM8hb) zwM~$lHm{ux@W==qNJT1CS^ArTfo!C~p)5uG>5aoxTZ};%B&54rFx!+OgX3WQ2R3A+ ztfStz+Tg&#tBGVqK{rl=h~+xsxK|G>%oy=NsJhMBvfxSD1c(znmqn=*>a6W?UK#$zH88Xsmn)m1QwImIR*;EuxKt(7BIG~cb?(fMFnQ1`M5)6(Y zqC#WLVuowtK()eer3%`9OH@!Wiu7tjT-vF)0=!kk`3jR62)cq&E zx26>@Vd!}#-MEC8Ti}g1W0El?xd89Q+(jWtRGUBUz9J4;7I}=w5=bc8X3NvW-K3h6 zWgiOCWyNSWF zV>A#(Q^F9-1#h0eWBsxJS!LbNJDIcQt-oGcyYKV&s_HY}=KgK@`|v*vRS6Kb`)We;5}QIZ@M|zLRBOuF%ch literal 2374 zcmeAS@N?(olHy`uVBq!ia0y~yU{+vYV0^&A1QfZHI&TpJ11GPii(^Q|oVPa*W;F*0 zI9!a{_33~8)ttAB1Xu#+on-a4NEdDLb4z~Uv@A7p9|OaSn)`bh7!E8Kj9_3eY-D8+ z5FTZW2Eu4c7+Setztk=< zyXJ7YTFl%slf*wi7W+%u*X{p#V$14qL%YP3Pd_(rEdP32et-CL>pjJy;qPx)OZWXR zI{yB{597+Ol@_<2)U+?&ZTRS8#hx0y`MFWkp1zZ1V6f}j&%wx$#Kg^@ptgZwlrb6z iqbXrD7YwFcuz%5ojr9lrOSJ&oM+}~>elF{r5}E+_tEGPc diff --git a/tests/ref_imgs_vg_lite/libs/barcode_2.png b/tests/ref_imgs_vg_lite/libs/barcode_2.png index 05f2540f958cd5ced4cb7481f2c73a6ca0d2a166..e86c231d2d87e545c6ccb255756f70e129295c36 100644 GIT binary patch literal 2763 zcmcImZAepL6h6DUrcTX>ZWviwR)4l6`q77yDU*`IB7zhlN0j}MEDLlH+x+;END%($ zgG8a9La_`cf~bpxB6A@95HgiW2jxd7n4-l>sTH2H^xBI#WL6oe2 zTdHY1-G~h!-4!S5^}(kIDrPFWq_dP&2R4IocrGhnE@k_WcKkh?;2V595*loeM8hb) zwM~$lHm{ux@W==qNJT1CS^ArTfo!C~p)5uG>5aoxTZ};%B&54rFx!+OgX3WQ2R3A+ ztfStz+Tg&#tBGVqK{rl=h~+xsxK|G>%oy=NsJhMBvfxSD1c(znmqn=*>a6W?UK#$zH88Xsmn)m1QwImIR*;EuxKt(7BIG~cb?(fMFnQ1`M5)6(Y zqC#WLVuowtK()eer3%`9OH@!Wiu7tjT-vF)0=!kk`3jR62)cq&E zx26>@Vd!}#-MEC8Ti}g1W0El?xd89Q+(jWtRGUBUz9J4;7I}=w5=bc8X3NvW-K3h6 zWgiOCWyN4HV!O; z?-Cf<2?xctKdu}yDv+4CQFKz)!UJOPhEz6gY;3sA8&bOkU<%-Zn2Zfi^^rmZ*(b&k zFkivbLxXN~3rrB1ja30$5R=iMTQA52^Zd4$B6dEZ2ynpW%sj{hV}s%gB6w4Y1tyq- z%tlg7P$S$lOh(R6EFpy&E{KG1U>cTGgFjKg{g3MH97GVn^Tal6f(Tipkb-+7XXg_> zcmmmkNG$ODdjqRr5j#@yLHM6wvVy0e4Nv*R3MQasB z%-9MPL~=kXI1qw6u>~u(Gy?Z0viA~BBc~A>lndL=V5uXJ%LrsPyqJJ9w%x%}n!-H~ zXXMzP|BO^QBj;h{6pqZsR^VaH<01>fRGdy08A(x2oR1Ig`_$00fOP{zR z5UW>_O94#(Qz&xa+WYtKx6fzzkV)N^7c{ed<4;pwH~${{@=d^&A%mx@pUXO@geCwA Cy^eVR diff --git a/tests/ref_imgs_vg_lite/libs/barcode_tiled_1.png b/tests/ref_imgs_vg_lite/libs/barcode_tiled_1.png new file mode 100644 index 0000000000000000000000000000000000000000..891942549f4558cdbc37732c99ebeaee565d71ff GIT binary patch literal 2374 zcmeAS@N?(olHy`uVBq!ia0y~yU{+vYV0^&A1QfZHI&TpJ11GPii(^Q|oVPa*W;F*0 zI9!a{_33~8)ttAB1Xu#+on-a4NEdDLb4z~Uv@A7p9|OaSn)`bh7!E8Kj9_3eY-D8+ z5FTZW2Eu4c7+Setztk=< zyXJ7YTFl%slf*wi7W+%u*X{p#V$14qL%YP3Pd_(rEdP32et-CL>pjJy;qPx)OZWXR zI{yB{597+Ol@_<2)U+?&ZTRS8#hx0y`MFWkp1zZ1V6f}j&%wx$#Kg^@ptgZwlrb6z iqbXrD7YwFcuz%5ojr9lrOSJ&oM+}~>elF{r5}E+_tEGPc literal 0 HcmV?d00001 diff --git a/tests/ref_imgs_vg_lite/libs/barcode_tiled_2.png b/tests/ref_imgs_vg_lite/libs/barcode_tiled_2.png new file mode 100644 index 0000000000000000000000000000000000000000..05f2540f958cd5ced4cb7481f2c73a6ca0d2a166 GIT binary patch literal 2624 zcmeAS@N?(olHy`uVBq!ia0y~yU{+vYV0^&A1QfZHI&TpJ0~foei(^Q|oVRy3PK4HV!O; z?-Cf<2?xctKdu}yDv+4CQFKz)!UJOPhEz6gY;3sA8&bOkU<%-Zn2Zfi^^rmZ*(b&k zFkivbLxXN~3rrB1ja30$5R=iMTQA52^Zd4$B6dEZ2ynpW%sj{hV}s%gB6w4Y1tyq- z%tlg7P$S$lOh(R6EFpy&E{KG1U>cTGgFjKg{g3MH97GVn^Tal6f(Tipkb-+7XXg_> zcmmmkNG$ODdjqRr5j#@yLHM6wvVy0e4Nv*R3MQasB z%-9MPL~=kXI1qw6u>~u(Gy?Z0viA~BBc~A>lndL=V5uXJ%LrsPyqJJ9w%x%}n!-H~ zXXMzP|BO^QBj;h{6pqZsR^VaH<01>fRGdy08A(x2oR1Ig`_$00fOP{zR z5UW>_O94#(Qz&xa+WYtKx6fzzkV)N^7c{ed<4;pwH~${{@=d^&A%mx@pUXO@geCwA Cy^eVR literal 0 HcmV?d00001 diff --git a/tests/src/test_cases/libs/test_barcode.c b/tests/src/test_cases/libs/test_barcode.c index 83f8b89edb..5a0e3e5345 100644 --- a/tests/src/test_cases/libs/test_barcode.c +++ b/tests/src/test_cases/libs/test_barcode.c @@ -27,6 +27,7 @@ void test_barcode_normal(void) lv_color_t dark_color = lv_color_black(); lv_color_t light_color = lv_color_white(); uint16_t scale = 2; + lv_result_t res; lv_barcode_set_dark_color(barcode, dark_color); lv_barcode_set_light_color(barcode, light_color); @@ -36,26 +37,35 @@ void test_barcode_normal(void) TEST_ASSERT_EQUAL_COLOR(lv_barcode_get_light_color(barcode), light_color); TEST_ASSERT_EQUAL(lv_barcode_get_scale(barcode), scale); + /* Test horizontal mode */ lv_barcode_set_direction(barcode, LV_DIR_HOR); - lv_result_t res = lv_barcode_update(barcode, "https://lvgl.io"); - TEST_ASSERT_EQUAL(res, LV_RESULT_OK); - - lv_image_dsc_t * image_dsc = lv_canvas_get_image(barcode); - TEST_ASSERT_NOT_NULL(image_dsc); - - lv_obj_set_size(barcode, image_dsc->header.w, 50); - TEST_ASSERT_EQUAL_SCREENSHOT("libs/barcode_1.png"); - - lv_barcode_set_direction(barcode, LV_DIR_VER); + lv_obj_set_height(barcode, 50); res = lv_barcode_update(barcode, "https://lvgl.io"); TEST_ASSERT_EQUAL(res, LV_RESULT_OK); + TEST_ASSERT_EQUAL_SCREENSHOT("libs/barcode_1.png"); - image_dsc = lv_canvas_get_image(barcode); - TEST_ASSERT_NOT_NULL(image_dsc); - - lv_obj_set_size(barcode, 50, image_dsc->header.h); + /* Test vertical mode */ + lv_barcode_set_direction(barcode, LV_DIR_VER); + lv_obj_set_size(barcode, 50, LV_SIZE_CONTENT); + res = lv_barcode_update(barcode, "https://lvgl.io"); + TEST_ASSERT_EQUAL(res, LV_RESULT_OK); TEST_ASSERT_EQUAL_SCREENSHOT("libs/barcode_2.png"); + /* Test tiled + horizontal mode */ + lv_barcode_set_tiled(barcode, true); + lv_barcode_set_direction(barcode, LV_DIR_HOR); + lv_obj_set_size(barcode, LV_SIZE_CONTENT, 50); + + res = lv_barcode_update(barcode, "https://lvgl.io"); + TEST_ASSERT_EQUAL(res, LV_RESULT_OK); + TEST_ASSERT_EQUAL_SCREENSHOT("libs/barcode_tiled_1.png"); + + /* Test tiled + vertical mode */ + lv_barcode_set_direction(barcode, LV_DIR_VER); + lv_obj_set_size(barcode, 50, LV_SIZE_CONTENT); + res = lv_barcode_update(barcode, "https://lvgl.io"); + TEST_ASSERT_EQUAL(res, LV_RESULT_OK); + TEST_ASSERT_EQUAL_SCREENSHOT("libs/barcode_tiled_2.png"); } #else