1、控件结构体
typedef struct
{
fv_widget_t widget;
fv_color_t dark_color; //暗的颜色,默认值为 黑色
fv_color_t light_color; //亮的颜色,默认值为 白色
uint8_t * map_buf; //二维码解码后的 位图数据缓存(一个方块点 占一个bit)
uint32_t map_width; //二维码解码后的 位图宽度(宽度和高度相等)
uint32_t scale;
} fv_qrcode_t;
2、控件绘制
static int32_t on_paint_self(fv_widget_t* widget, fv_canvas_t* canvas)
{
fv_qrcode_t * qrcode = (fv_qrcode_t*)widget;
uint32_t row_byte_cnt;
int32_t qr_size;
uint8_t * buf_u8;
uint8_t n;
if (qrcode->map_buf == FV_NULL)
{
return 0;
}
if (qrcode->scale == 0)
{
return 0;
}
qr_size = qrcode->map_width;
row_byte_cnt = (qr_size + 7) / 8;
for (int32_t y = 0; y < qr_size; y++)
{
n = 0;
buf_u8 = ((uint8_t*)qrcode->map_buf) + row_byte_cnt * y;
for (int32_t x = 0; x < qr_size; x++)
{
if ((*buf_u8 & (1 << (7 - n))) != 0)
{
canvas->draw_ctx.draw_ctx_brush.brush_fill_color = qrcode->light_color;
}
else
{
canvas->draw_ctx.draw_ctx_brush.brush_fill_color = qrcode->dark_color;
}
fv_rectangle_t rect;
rect.rectangle_left = x * qrcode->scale + (widget->w - qrcode->scale * qr_size) / 2;
rect.rectangle_top = y * qrcode->scale + (widget->h - qrcode->scale * qr_size) / 2;
rect.rectangle_right = rect.rectangle_left + qrcode->scale - 1;
rect.rectangle_bottom = rect.rectangle_top + qrcode->scale - 1;
fv_canvas_rectangle_draw(canvas, &rect);
n++;
if (n == 8)
{
buf_u8++;
n = 0;
}
}
}
return 0;
}
3、更新二维码
int32_t fv_qrcode_update(fv_widget_t* widget, const char* str)
{
fv_qrcode_t * qrcode = (fv_qrcode_t*)widget;
uint32_t data_len;
int32_t width;
width = FV_MIN(widget->w, widget->h);
data_len = strlen(str);
if (data_len > qrcodegen_BUFFER_LEN_MAX)
{
return -1;
}
int32_t qr_version = qrcodegen_getMinFitVersion(qrcodegen_Ecc_MEDIUM, data_len);
if (qr_version <= 0)
{
return -1;
}
int32_t qr_size = qrcodegen_version2size(qr_version);
if (qr_size <= 0)
{
return -1;
}
int32_t scale = width / qr_size;
if (scale <= 0)
{
return -1;
}
int32_t remain = width % qr_size;
uint32_t version_extend = remain / (scale << 2);
if (version_extend && qr_version < qrcodegen_VERSION_MAX)
{
qr_version = qr_version + version_extend > qrcodegen_VERSION_MAX ?
qrcodegen_VERSION_MAX : qr_version + version_extend;
}
uint8_t* qr0 = fv_mem_alloc(qrcodegen_BUFFER_LEN_FOR_VERSION(qr_version));
uint8_t* data_tmp = fv_mem_alloc(qrcodegen_BUFFER_LEN_FOR_VERSION(qr_version));
memcpy(data_tmp, str, data_len);
fv_bool_t ok = qrcodegen_encodeBinary(data_tmp, data_len,
qr0, qrcodegen_Ecc_MEDIUM,
qr_version, qr_version,
qrcodegen_Mask_AUTO, true);
if (!ok)
{
fv_mem_free(qr0);
fv_mem_free(data_tmp);
return -1;
}
qr_size = qrcodegen_getSize(qr0);
uint32_t row_byte_cnt = (qr_size + 7) / 8;
if (qrcode->map_buf != FV_NULL)
{
fv_mem_free(qrcode->map_buf);
qrcode->map_buf = FV_NULL;
}
qrcode->map_buf = fv_mem_alloc(row_byte_cnt * qr_size);
fv_mem_zero(qrcode->map_buf, row_byte_cnt * qr_size);
qrcode->map_width = qr_size;
qrcode->scale = scale;
uint8_t * buf_u8;
uint8_t n;
for (int32_t y = 0; y < qr_size; y++)
{
n = 0;
buf_u8 = ((uint8_t*)qrcode->map_buf) + row_byte_cnt * y;
for (int32_t x = 0; x < qr_size; x++)
{
fv_bool_t a = qrcodegen_getModule(qr0, x, y);
if (!a)
{
*buf_u8 |= (1 << (7 - n));
}
n++;
if (n == 8)
{
buf_u8++;
n = 0;
}
}
}
fv_mem_free(qr0);
fv_mem_free(data_tmp);
return 0;
}