mirror of
https://github.com/lvgl/lvgl.git
synced 2026-06-02 01:18:04 +08:00
fix(barcode): use draw buffer to set canvas to meet align requirement (#5034)
Signed-off-by: Xu Xingliang <xuxingliang@xiaomi.com>
This commit is contained in:
@@ -195,20 +195,10 @@ static void lv_barcode_destructor(const lv_obj_class_t * class_p, lv_obj_t * obj
|
|||||||
{
|
{
|
||||||
LV_UNUSED(class_p);
|
LV_UNUSED(class_p);
|
||||||
|
|
||||||
lv_image_dsc_t * img = lv_canvas_get_image(obj);
|
lv_draw_buf_t * draw_buf = lv_canvas_get_draw_buf(obj);
|
||||||
lv_cache_lock();
|
if(draw_buf == NULL) return;
|
||||||
lv_cache_invalidate_by_src(img, LV_CACHE_SRC_TYPE_POINTER);
|
|
||||||
lv_cache_unlock();
|
|
||||||
|
|
||||||
if(!img->data) {
|
lv_draw_buf_destroy(draw_buf);
|
||||||
LV_LOG_INFO("canvas buffer is NULL");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
LV_LOG_INFO("free canvas buffer: %p", lv_canvas_get_buf(obj));
|
|
||||||
|
|
||||||
lv_draw_buf_free((void *)lv_canvas_get_buf(obj));
|
|
||||||
img->data = NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool lv_barcode_change_buf_size(lv_obj_t * obj, int32_t w, int32_t h)
|
static bool lv_barcode_change_buf_size(lv_obj_t * obj, int32_t w, int32_t h)
|
||||||
@@ -216,22 +206,17 @@ static bool lv_barcode_change_buf_size(lv_obj_t * obj, int32_t w, int32_t h)
|
|||||||
LV_ASSERT_NULL(obj);
|
LV_ASSERT_NULL(obj);
|
||||||
LV_ASSERT(w > 0);
|
LV_ASSERT(w > 0);
|
||||||
|
|
||||||
void * buf = (void *)lv_canvas_get_buf(obj);
|
lv_draw_buf_t * old_buf = lv_canvas_get_draw_buf(obj);
|
||||||
lv_draw_buf_free((void *)buf);
|
lv_draw_buf_t * new_buf = lv_draw_buf_create(w, h, LV_COLOR_FORMAT_I1, 0);
|
||||||
|
if(new_buf == NULL) {
|
||||||
uint32_t stride = lv_draw_buf_width_to_stride(w, LV_COLOR_FORMAT_I1);
|
|
||||||
uint32_t buf_size = stride * h;
|
|
||||||
/*+8 for the 2x4 byte palette*/
|
|
||||||
buf = lv_draw_buf_malloc(buf_size + 8, LV_COLOR_FORMAT_I1);
|
|
||||||
LV_ASSERT_MALLOC(buf);
|
|
||||||
|
|
||||||
if(!buf) {
|
|
||||||
LV_LOG_ERROR("malloc failed for canvas buffer");
|
LV_LOG_ERROR("malloc failed for canvas buffer");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
lv_canvas_set_buffer(obj, buf, w, h, LV_COLOR_FORMAT_I1);
|
lv_canvas_set_draw_buf(obj, new_buf);
|
||||||
LV_LOG_INFO("set canvas buffer: %p, width = %d", buf, (int)w);
|
LV_LOG_INFO("set canvas buffer: %p, width = %d", new_buf, (int)w);
|
||||||
|
|
||||||
|
if(old_buf != NULL) lv_draw_buf_destroy(old_buf);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+18
-27
@@ -58,22 +58,20 @@ void lv_qrcode_set_size(lv_obj_t * obj, int32_t size)
|
|||||||
{
|
{
|
||||||
LV_ASSERT_OBJ(obj, MY_CLASS);
|
LV_ASSERT_OBJ(obj, MY_CLASS);
|
||||||
|
|
||||||
void * buf = (void *)lv_canvas_get_buf(obj);
|
lv_draw_buf_t * old_buf = lv_canvas_get_draw_buf(obj);
|
||||||
if(buf) lv_draw_buf_free(buf);
|
lv_draw_buf_t * new_buf = lv_draw_buf_create(size, size, LV_COLOR_FORMAT_I1, 0);
|
||||||
|
if(new_buf == NULL) {
|
||||||
size_t buf_size = lv_draw_buf_width_to_stride(size, LV_COLOR_FORMAT_I1) * size;
|
|
||||||
buf_size += 8; /*palette*/
|
|
||||||
buf = lv_draw_buf_malloc(buf_size, LV_COLOR_FORMAT_I1);
|
|
||||||
LV_ASSERT_MALLOC(buf);
|
|
||||||
if(buf == NULL) {
|
|
||||||
LV_LOG_ERROR("malloc failed for canvas buffer");
|
LV_LOG_ERROR("malloc failed for canvas buffer");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
lv_canvas_set_buffer(obj, buf, size, size, LV_COLOR_FORMAT_I1);
|
lv_canvas_set_draw_buf(obj, new_buf);
|
||||||
|
LV_LOG_INFO("set canvas buffer: %p, size = %d", new_buf, (int)size);
|
||||||
|
|
||||||
/*Clear canvas buffer*/
|
/*Clear canvas buffer*/
|
||||||
lv_canvas_fill_bg(obj, lv_color_white(), LV_OPA_COVER);
|
lv_canvas_fill_bg(obj, lv_color_white(), LV_OPA_COVER);
|
||||||
|
|
||||||
|
if(old_buf != NULL) lv_draw_buf_destroy(old_buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
void lv_qrcode_set_dark_color(lv_obj_t * obj, lv_color_t color)
|
void lv_qrcode_set_dark_color(lv_obj_t * obj, lv_color_t color)
|
||||||
@@ -95,9 +93,9 @@ lv_result_t lv_qrcode_update(lv_obj_t * obj, const void * data, uint32_t data_le
|
|||||||
LV_ASSERT_OBJ(obj, MY_CLASS);
|
LV_ASSERT_OBJ(obj, MY_CLASS);
|
||||||
lv_qrcode_t * qrcode = (lv_qrcode_t *)obj;
|
lv_qrcode_t * qrcode = (lv_qrcode_t *)obj;
|
||||||
|
|
||||||
lv_image_dsc_t * img_dsc = lv_canvas_get_image(obj);
|
lv_draw_buf_t * draw_buf = lv_canvas_get_draw_buf(obj);
|
||||||
if(!img_dsc->data) {
|
if(draw_buf == NULL) {
|
||||||
LV_LOG_ERROR("canvas buffer is NULL");
|
LV_LOG_ERROR("canvas draw buffer is NULL");
|
||||||
return LV_RESULT_INVALID;
|
return LV_RESULT_INVALID;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -112,12 +110,12 @@ lv_result_t lv_qrcode_update(lv_obj_t * obj, const void * data, uint32_t data_le
|
|||||||
if(qr_version <= 0) return LV_RESULT_INVALID;
|
if(qr_version <= 0) return LV_RESULT_INVALID;
|
||||||
int32_t qr_size = qrcodegen_version2size(qr_version);
|
int32_t qr_size = qrcodegen_version2size(qr_version);
|
||||||
if(qr_size <= 0) return LV_RESULT_INVALID;
|
if(qr_size <= 0) return LV_RESULT_INVALID;
|
||||||
int32_t scale = img_dsc->header.w / qr_size;
|
int32_t scale = draw_buf->header.w / qr_size;
|
||||||
if(scale <= 0) return LV_RESULT_INVALID;
|
if(scale <= 0) return LV_RESULT_INVALID;
|
||||||
|
|
||||||
/* Pick the largest QR code that still maintains scale. */
|
/* Pick the largest QR code that still maintains scale. */
|
||||||
for(int32_t i = qr_version + 1; i < qrcodegen_VERSION_MAX; i++) {
|
for(int32_t i = qr_version + 1; i < qrcodegen_VERSION_MAX; i++) {
|
||||||
if(qrcodegen_version2size(i) * scale > img_dsc->header.w)
|
if(qrcodegen_version2size(i) * scale > draw_buf->header.w)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
qr_version = i;
|
qr_version = i;
|
||||||
@@ -141,17 +139,17 @@ lv_result_t lv_qrcode_update(lv_obj_t * obj, const void * data, uint32_t data_le
|
|||||||
return LV_RESULT_INVALID;
|
return LV_RESULT_INVALID;
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t obj_w = img_dsc->header.w;
|
int32_t obj_w = draw_buf->header.w;
|
||||||
qr_size = qrcodegen_getSize(qr0);
|
qr_size = qrcodegen_getSize(qr0);
|
||||||
scale = obj_w / qr_size;
|
scale = obj_w / qr_size;
|
||||||
int scaled = qr_size * scale;
|
int scaled = qr_size * scale;
|
||||||
int margin = (obj_w - scaled) / 2;
|
int margin = (obj_w - scaled) / 2;
|
||||||
uint8_t * buf_u8 = (uint8_t *)img_dsc->data + 8; /*+8 skip the palette*/
|
uint8_t * buf_u8 = (uint8_t *)draw_buf->data + 8; /*+8 skip the palette*/
|
||||||
|
|
||||||
/* Copy the qr code canvas:
|
/* Copy the qr code canvas:
|
||||||
* A simple `lv_canvas_set_px` would work but it's slow for so many pixels.
|
* 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 */
|
* So buffer 1 byte (8 px) from the qr code and set it in the canvas image */
|
||||||
uint32_t row_byte_cnt = img_dsc->header.stride;
|
uint32_t row_byte_cnt = draw_buf->header.stride;
|
||||||
int y;
|
int y;
|
||||||
for(y = margin; y < scaled + margin; y += scale) {
|
for(y = margin; y < scaled + margin; y += scale) {
|
||||||
uint8_t b = 0;
|
uint8_t b = 0;
|
||||||
@@ -221,17 +219,10 @@ static void lv_qrcode_destructor(const lv_obj_class_t * class_p, lv_obj_t * obj)
|
|||||||
{
|
{
|
||||||
LV_UNUSED(class_p);
|
LV_UNUSED(class_p);
|
||||||
|
|
||||||
lv_image_dsc_t * img_dsc = lv_canvas_get_image(obj);
|
lv_draw_buf_t * draw_buf = lv_canvas_get_draw_buf(obj);
|
||||||
lv_cache_lock();
|
if(draw_buf == NULL) return;
|
||||||
lv_cache_invalidate_by_src(img_dsc, LV_CACHE_SRC_TYPE_POINTER);
|
|
||||||
lv_cache_unlock();
|
|
||||||
|
|
||||||
if(!img_dsc->data) {
|
lv_draw_buf_destroy(draw_buf);
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
lv_draw_buf_free((void *)lv_canvas_get_buf(obj));
|
|
||||||
img_dsc->data = NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /*LV_USE_QRCODE*/
|
#endif /*LV_USE_QRCODE*/
|
||||||
|
|||||||
@@ -53,6 +53,7 @@ lv_obj_t * lv_canvas_create(lv_obj_t * parent);
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Set a buffer for the canvas.
|
* Set a buffer for the canvas.
|
||||||
|
* Use `lv_canvas_set_draw_buf` instead if you need to set a buffer with alignment requirement.
|
||||||
* @param buf a buffer where the content of the canvas will be.
|
* @param buf a buffer where the content of the canvas will be.
|
||||||
* The required size is (lv_image_color_format_get_px_size(cf) * w) / 8 * h)
|
* The required size is (lv_image_color_format_get_px_size(cf) * w) / 8 * h)
|
||||||
* It can be allocated with `lv_malloc()` or
|
* It can be allocated with `lv_malloc()` or
|
||||||
@@ -65,6 +66,13 @@ lv_obj_t * lv_canvas_create(lv_obj_t * parent);
|
|||||||
*/
|
*/
|
||||||
void lv_canvas_set_buffer(lv_obj_t * obj, void * buf, int32_t w, int32_t h, lv_color_format_t cf);
|
void lv_canvas_set_buffer(lv_obj_t * obj, void * buf, int32_t w, int32_t h, lv_color_format_t cf);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set a draw buffer for the canvas. A draw buffer either can be allocated by `lv_draw_buf_create()`
|
||||||
|
* or defined statically by `LV_DRAW_BUF_DEFINE`. When buffer start address and stride has alignment
|
||||||
|
* requirement, it's recommended to use `lv_draw_buf_create`.
|
||||||
|
* @param obj pointer to a canvas object
|
||||||
|
* @param draw_buf pointer to a draw buffer
|
||||||
|
*/
|
||||||
void lv_canvas_set_draw_buf(lv_obj_t * obj, lv_draw_buf_t * draw_buf);
|
void lv_canvas_set_draw_buf(lv_obj_t * obj, lv_draw_buf_t * draw_buf);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
Reference in New Issue
Block a user