mirror of
https://github.com/lvgl/lvgl.git
synced 2024-11-27 11:43:43 +08:00
fix(qrcode): remove global variables and lv_qrcode_delete (#3771)
Signed-off-by: pengyiqiang <pengyiqiang@xiaomi.com> Co-authored-by: pengyiqiang <pengyiqiang@xiaomi.com>
This commit is contained in:
parent
0738d1ac36
commit
be1e1fca3a
@ -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.
|
||||
|
@ -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
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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*/
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user