From be1e1fca3a30234fdd8bcde44f6ba0b95bb99766 Mon Sep 17 00:00:00 2001 From: _VIFEXTech <1290176185@qq.com> Date: Thu, 3 Nov 2022 01:32:48 +0800 Subject: [PATCH] fix(qrcode): remove global variables and lv_qrcode_delete (#3771) Signed-off-by: pengyiqiang Co-authored-by: pengyiqiang --- docs/libs/qrcode.md | 18 +-- examples/libs/qrcode/lv_example_qrcode_1.c | 13 +-- examples/libs/qrcode/lv_example_qrcode_1.py | 7 +- src/libs/qrcode/lv_qrcode.c | 117 ++++++++++++-------- src/libs/qrcode/lv_qrcode.h | 48 +++++--- 5 files changed, 118 insertions(+), 85 deletions(-) diff --git a/docs/libs/qrcode.md b/docs/libs/qrcode.md index 46e0a47d62..dc25fd7d7a 100644 --- a/docs/libs/qrcode.md +++ b/docs/libs/qrcode.md @@ -3,21 +3,13 @@ QR code generation with LVGL. Uses [QR-Code-generator](https://github.com/nayuki/QR-Code-generator) by [nayuki](https://github.com/nayuki). -## Get started -- Download or clone this repository - - [Download](https://github.com/lvgl/lv_lib_qrcode.git) from GitHub - - Clone: git clone https://github.com/lvgl/lv_lib_qrcode.git -- Include the library: `#include "lv_lib_qrcode/lv_qrcode.h"` -- Test with the following code: -```c -const char * data = "Hello world"; +## Usage -/*Create a 100x100 QR code*/ -lv_obj_t * qr = lv_qrcode_create(lv_scr_act(), 100, lv_color_hex3(0x33f), lv_color_hex3(0xeef)); +Enable `LV_USE_QRCODE` in `lv_conf.h`. -/*Set data*/ -lv_qrcode_update(qr, data, strlen(data)); -``` +Use `lv_qrcode_create()` to create a qrcode object, and use `lv_qrcode_update()` to generate a QR code. + +If you need to re-modify the size and color, use `lv_qrcode_set_size()` and `lv_qrcode_set_dark/light_color()`, and call `lv_qrcode_update()` again to regenerate the QR code. ## Notes - QR codes with less data are smaller, but they scaled by an integer number to best fit to the given size. diff --git a/examples/libs/qrcode/lv_example_qrcode_1.c b/examples/libs/qrcode/lv_example_qrcode_1.c index 7e50fec832..6f1f0593f8 100644 --- a/examples/libs/qrcode/lv_example_qrcode_1.c +++ b/examples/libs/qrcode/lv_example_qrcode_1.c @@ -9,7 +9,10 @@ void lv_example_qrcode_1(void) lv_color_t bg_color = lv_palette_lighten(LV_PALETTE_LIGHT_BLUE, 5); lv_color_t fg_color = lv_palette_darken(LV_PALETTE_BLUE, 4); - lv_obj_t * qr = lv_qrcode_create(lv_scr_act(), 150, fg_color, bg_color); + lv_obj_t * qr = lv_qrcode_create(lv_scr_act()); + lv_qrcode_set_size(qr, 150); + lv_qrcode_set_dark_color(qr, fg_color); + lv_qrcode_set_light_color(qr, bg_color); /*Set data*/ const char * data = "https://lvgl.io"; @@ -22,11 +25,3 @@ void lv_example_qrcode_1(void) } #endif - - - - - - - - diff --git a/examples/libs/qrcode/lv_example_qrcode_1.py b/examples/libs/qrcode/lv_example_qrcode_1.py index 3c6e1ee407..0d702a85c1 100755 --- a/examples/libs/qrcode/lv_example_qrcode_1.py +++ b/examples/libs/qrcode/lv_example_qrcode_1.py @@ -5,11 +5,16 @@ import display_driver bg_color = lv.palette_lighten(lv.PALETTE.LIGHT_BLUE, 5) fg_color = lv.palette_darken(lv.PALETTE.BLUE, 4) -qr = lv.qrcode(lv.scr_act(), 150, fg_color, bg_color) +qr = lv.qrcode(lv.scr_act()) +qr.set_size(150) +qr.set_dark_color(fg_color) +qr.set_light_color(bg_color) + # Set data data = "https://lvgl.io" qr.update(data,len(data)) qr.center() + # Add a border with bg_color qr.set_style_border_color(bg_color, 0) qr.set_style_border_width(5, 0) diff --git a/src/libs/qrcode/lv_qrcode.c b/src/libs/qrcode/lv_qrcode.c index 67747eea51..9a24aad1f0 100644 --- a/src/libs/qrcode/lv_qrcode.c +++ b/src/libs/qrcode/lv_qrcode.c @@ -33,13 +33,10 @@ static void lv_qrcode_destructor(const lv_obj_class_t * class_p, lv_obj_t * obj) const lv_obj_class_t lv_qrcode_class = { .constructor_cb = lv_qrcode_constructor, .destructor_cb = lv_qrcode_destructor, + .instance_size = sizeof(lv_qrcode_t), .base_class = &lv_canvas_class }; -static lv_coord_t size_param; -static lv_color_t dark_color_param; -static lv_color_t light_color_param; - /********************** * MACROS **********************/ @@ -51,48 +48,77 @@ static lv_color_t light_color_param; /** * Create an empty QR code (an `lv_canvas`) object. * @param parent point to an object where to create the QR code - * @param size width and height of the QR code - * @param dark_color dark color of the QR code - * @param light_color light color of the QR code * @return pointer to the created QR code object */ -lv_obj_t * lv_qrcode_create(lv_obj_t * parent, lv_coord_t size, lv_color_t dark_color, lv_color_t light_color) +lv_obj_t * lv_qrcode_create(lv_obj_t * parent) { LV_LOG_INFO("begin"); - size_param = size; - light_color_param = light_color; - dark_color_param = dark_color; - lv_obj_t * obj = lv_obj_class_create_obj(MY_CLASS, parent); lv_obj_class_init_obj(obj); return obj; - } -/** - * Set the data of a QR code object - * @param qrcode pointer to aQ code object - * @param data data to display - * @param data_len length of data in bytes - * @return LV_RES_OK: if no error; LV_RES_INV: on error - */ -lv_res_t lv_qrcode_update(lv_obj_t * qrcode, const void * data, uint32_t data_len) +void lv_qrcode_set_size(lv_obj_t * obj, lv_coord_t size) { + LV_ASSERT_OBJ(obj, MY_CLASS); + + lv_img_dsc_t * img_dsc = lv_canvas_get_img(obj); + void * buf = (void *)img_dsc->data; + + uint32_t buf_size = LV_CANVAS_BUF_SIZE_INDEXED_1BIT(size, size); + buf = lv_realloc(buf, buf_size); + LV_ASSERT_MALLOC(buf); + if(buf == NULL) { + LV_LOG_ERROR("malloc failed for canvas buffer"); + return; + } + + lv_canvas_set_buffer(obj, buf, size, size, LV_IMG_CF_INDEXED_1BIT); + + /*Clear canvas buffer*/ + lv_canvas_fill_bg(obj, lv_color_white(), LV_OPA_COVER); +} + +void lv_qrcode_set_dark_color(lv_obj_t * obj, lv_color_t color) +{ + LV_ASSERT_OBJ(obj, MY_CLASS); + lv_qrcode_t * qrcode = (lv_qrcode_t *)obj; + qrcode->dark_color = color; +} + +void lv_qrcode_set_light_color(lv_obj_t * obj, lv_color_t color) +{ + LV_ASSERT_OBJ(obj, MY_CLASS); + lv_qrcode_t * qrcode = (lv_qrcode_t *)obj; + qrcode->light_color = color; +} + +lv_res_t lv_qrcode_update(lv_obj_t * obj, const void * data, uint32_t data_len) +{ + LV_ASSERT_OBJ(obj, MY_CLASS); + lv_qrcode_t * qrcode = (lv_qrcode_t *)obj; + + lv_img_dsc_t * img_dsc = lv_canvas_get_img(obj); + if(!img_dsc->data) { + LV_LOG_ERROR("canvas buffer is NULL"); + return LV_RES_INV; + } + + lv_canvas_set_palette(obj, 0, qrcode->dark_color); + lv_canvas_set_palette(obj, 1, qrcode->light_color); lv_color_t c; c.full = 1; - lv_canvas_fill_bg(qrcode, c, LV_OPA_COVER); + lv_canvas_fill_bg(obj, c, LV_OPA_COVER); if(data_len > qrcodegen_BUFFER_LEN_MAX) return LV_RES_INV; - lv_img_dsc_t * imgdsc = lv_canvas_get_img(qrcode); - int32_t qr_version = qrcodegen_getMinFitVersion(qrcodegen_Ecc_MEDIUM, data_len); if(qr_version <= 0) return LV_RES_INV; int32_t qr_size = qrcodegen_version2size(qr_version); if(qr_size <= 0) return LV_RES_INV; - int32_t scale = imgdsc->header.w / qr_size; + int32_t scale = img_dsc->header.w / qr_size; if(scale <= 0) return LV_RES_INV; - int32_t remain = imgdsc->header.w % qr_size; + int32_t remain = img_dsc->header.w % qr_size; /* The qr version is incremented by four point */ uint32_t version_extend = remain / (scale << 2); @@ -118,17 +144,17 @@ lv_res_t lv_qrcode_update(lv_obj_t * qrcode, const void * data, uint32_t data_le return LV_RES_INV; } - lv_coord_t obj_w = imgdsc->header.w; + lv_coord_t obj_w = img_dsc->header.w; qr_size = qrcodegen_getSize(qr0); scale = obj_w / qr_size; int scaled = qr_size * scale; int margin = (obj_w - scaled) / 2; - uint8_t * buf_u8 = (uint8_t *)imgdsc->data + 8; /*+8 skip the palette*/ + uint8_t * buf_u8 = (uint8_t *)img_dsc->data + 8; /*+8 skip the palette*/ /* Copy the qr code canvas: * A simple `lv_canvas_set_px` would work but it's slow for so many pixels. * So buffer 1 byte (8 px) from the qr code and set it in the canvas image */ - uint32_t row_byte_cnt = (imgdsc->header.w + 7) >> 3; + uint32_t row_byte_cnt = (img_dsc->header.w + 7) >> 3; int y; for(y = margin; y < scaled + margin; y += scale) { uint8_t b = 0; @@ -142,7 +168,7 @@ lv_res_t lv_qrcode_update(lv_obj_t * qrcode, const void * data, uint32_t data_le if(aligned == false) { c.full = a ? 0 : 1; - lv_canvas_set_px_color(qrcode, x, y, c); + lv_canvas_set_px_color(obj, x, y, c); } else { if(!a) b |= (1 << (7 - p)); @@ -178,12 +204,6 @@ lv_res_t lv_qrcode_update(lv_obj_t * qrcode, const void * data, uint32_t data_le return LV_RES_OK; } - -void lv_qrcode_delete(lv_obj_t * qrcode) -{ - lv_obj_del(qrcode); -} - /********************** * STATIC FUNCTIONS **********************/ @@ -192,24 +212,27 @@ static void lv_qrcode_constructor(const lv_obj_class_t * class_p, lv_obj_t * obj { LV_UNUSED(class_p); - uint32_t buf_size = LV_CANVAS_BUF_SIZE_INDEXED_1BIT(size_param, size_param); - uint8_t * buf = lv_malloc(buf_size); - LV_ASSERT_MALLOC(buf); - if(buf == NULL) return; + /*Set default size*/ + lv_qrcode_set_size(obj, LV_DPI_DEF); - lv_canvas_set_buffer(obj, buf, size_param, size_param, LV_IMG_CF_INDEXED_1BIT); - lv_canvas_set_palette(obj, 0, dark_color_param); - lv_canvas_set_palette(obj, 1, light_color_param); + /*Set default color*/ + lv_qrcode_set_dark_color(obj, lv_color_black()); + lv_qrcode_set_light_color(obj, lv_color_white()); } static void lv_qrcode_destructor(const lv_obj_class_t * class_p, lv_obj_t * obj) { LV_UNUSED(class_p); - lv_img_dsc_t * img = lv_canvas_get_img(obj); - lv_img_cache_invalidate_src(img); - lv_free((void *)img->data); - img->data = NULL; + lv_img_dsc_t * img_dsc = lv_canvas_get_img(obj); + lv_img_cache_invalidate_src(img_dsc); + + if(!img_dsc->data) { + return; + } + + lv_free((void *)img_dsc->data); + img_dsc->data = NULL; } #endif /*LV_USE_QRCODE*/ diff --git a/src/libs/qrcode/lv_qrcode.h b/src/libs/qrcode/lv_qrcode.h index b0752ace9d..e5eef8fd51 100644 --- a/src/libs/qrcode/lv_qrcode.h +++ b/src/libs/qrcode/lv_qrcode.h @@ -20,12 +20,19 @@ extern "C" { * DEFINES *********************/ -extern const lv_obj_class_t lv_qrcode_class; - /********************** * TYPEDEFS **********************/ +/*Data of qrcode*/ +typedef struct { + lv_canvas_t canvas; + lv_color_t dark_color; + lv_color_t light_color; +} lv_qrcode_t; + +extern const lv_obj_class_t lv_qrcode_class; + /********************** * GLOBAL PROTOTYPES **********************/ @@ -33,28 +40,39 @@ extern const lv_obj_class_t lv_qrcode_class; /** * Create an empty QR code (an `lv_canvas`) object. * @param parent point to an object where to create the QR code - * @param size width and height of the QR code - * @param dark_color dark color of the QR code - * @param light_color light color of the QR code * @return pointer to the created QR code object */ -lv_obj_t * lv_qrcode_create(lv_obj_t * parent, lv_coord_t size, lv_color_t dark_color, lv_color_t light_color); +lv_obj_t * lv_qrcode_create(lv_obj_t * parent); + +/** + * Set QR code size. + * @param obj pointer to a QR code object + * @param size width and height of the QR code + */ +void lv_qrcode_set_size(lv_obj_t * obj, lv_coord_t size); + +/** + * Set QR code dark color. + * @param obj pointer to a QR code object + * @param color dark color of the QR code + */ +void lv_qrcode_set_dark_color(lv_obj_t * obj, lv_color_t color); + +/** + * Set QR code light color. + * @param obj pointer to a QR code object + * @param color light color of the QR code + */ +void lv_qrcode_set_light_color(lv_obj_t * obj, lv_color_t color); /** * Set the data of a QR code object - * @param qrcode pointer to aQ code object + * @param obj pointer to a QR code object * @param data data to display * @param data_len length of data in bytes * @return LV_RES_OK: if no error; LV_RES_INV: on error */ -lv_res_t lv_qrcode_update(lv_obj_t * qrcode, const void * data, uint32_t data_len); - -/** - * DEPRECATED: Use normal lv_obj_del instead - * Delete a QR code object - * @param qrcode pointer to a QR code object - */ -void lv_qrcode_delete(lv_obj_t * qrcode); +lv_res_t lv_qrcode_update(lv_obj_t * obj, const void * data, uint32_t data_len); /********************** * MACROS