Bootstrap

LVGL 自定义组件(类)之 条形码组件

一、组件分析

const lv_obj_class_t lv_barcode_class = {
    .constructor_cb = lv_barcode_constructor,
    .destructor_cb  = lv_barcode_destructor,
    .width_def      = LV_BARCODE_OBJ_WIDE,
    .height_def     = LV_BARCODE_OBJ_HIDE,
    .instance_size  = sizeof(lv_barcode_t),
    .base_class     = &lv_obj_class
};

lv_barcode_class 就是自定义的条形码组件(类)

里面组成就是类的成员及实现方法

具体可以参考C++中的类和对象

二、源码

lv_barcode.c

/**
 * @file lv_barcode.c
 *
 */

/*********************
 *      INCLUDES
 *********************/
#include "lv_barcode.h"

#if LV_USE_BARCODE != 0

#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>

/*********************
 *      DEFINES
 *********************/
#define MY_CLASS &lv_barcode_class
/**********************
 *      TYPEDEFS
 **********************/

/**********************
 *  STATIC PROTOTYPES
 **********************/
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 VARIABLES
 **********************/
const lv_obj_class_t lv_barcode_class = {
    .constructor_cb = lv_barcode_constructor,
    .destructor_cb  = lv_barcode_destructor,
    .width_def      = LV_BARCODE_OBJ_WIDE,
    .height_def     = LV_BARCODE_OBJ_HIDE,
    .instance_size  = sizeof(lv_barcode_t),
    .base_class     = &lv_obj_class
};


/**********************
 *      MACROS
 **********************/

/**********************
 *   GLOBAL FUNCTIONS
 **********************/
 
/**
 * Create an empty barcode (an `img`) object.
 * @param parent point to an object where to create the barcode
 * @return pointer to the created barcode object
 */
lv_obj_t * lv_barcode_create(lv_obj_t * parent)
{
    LV_LOG_INFO("begin");
    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 barcode object
 * @param barcode pointer to barcode object
 * @param data data to display
 * @param width barcode width
 * @param height barcode height
 */
void lv_barcode_update(lv_obj_t * obj, const char *data, uint32_t width, uint32_t height)
{
	lv_barcode_t * barcode = (lv_barcode_t *)obj;
	lv_img_dsc_t * dsc = lv_barcode_get_imgdsc(obj);
	if(barcode->have_update == true)
	{
		lv_mem_free(dsc->data);
		barcode->have_update = false;
		lv_memset(dsc, 0, sizeof(lv_img_dsc_t));
	}
		
	lv_obj_set_size(barcode->barcode_bg, width * 10 / 9, height * 10 / 8);

	generate_barcode_image(obj, data, width, height);
}

/*=====================
 * Setter functions
 *====================*/
void lv_barcode_set_bg_color(lv_obj_t * obj, lv_color_t new_color)
{
    LV_ASSERT_OBJ(obj, MY_CLASS);
	lv_obj_t * img = lv_barcode_get_img(obj);
    lv_barcode_t * barcode = (lv_barcode_t *)obj;
	lv_img_dsc_t * dsc = lv_barcode_get_imgdsc(obj);
	lv_color_t bg_color = lv_barcode_get_bg_color(obj);
	if(barcode->have_update != true)
	{
    	barcode->bg_color = new_color;
		return ;
	}

	lv_color_t *img_buf = (lv_color_t *)dsc->data;
    for (int i = 0; i < dsc->header.w * dsc->header.h; i++)
	{
		if(memcmp(&img_buf[i], &bg_color, sizeof(lv_color_t)) == false)
        	img_buf[i] = new_color;
    }
	barcode->bg_color = new_color;
	lv_img_set_src(img, dsc);
}

void lv_barcode_set_data_color(lv_obj_t * obj, lv_color_t new_color)
{
    LV_ASSERT_OBJ(obj, MY_CLASS);
	lv_obj_t * img = lv_barcode_get_img(obj);
    lv_barcode_t * barcode = (lv_barcode_t *)obj;
	lv_img_dsc_t * dsc = lv_barcode_get_imgdsc(obj);
	lv_color_t data_color = lv_barcode_get_bg_color(obj);
	if(barcode->have_update != true)
	{
    	barcode->data_color = new_color;
		return ;
	}

	lv_color_t *img_buf = (lv_color_t *)dsc->data;
    for (int i = 0; i < dsc->header.w * dsc->header.h; i++)
	{
		if( memcmp(&img_buf[i], &data_color, sizeof(lv_color_t)) == false)
        	img_buf[i] = new_color;
    }
	barcode->data_color = new_color;
	lv_img_set_src(img, dsc);
}

/*=====================
 * Getter functions
 *====================*/
lv_color_t lv_barcode_get_bg_color(lv_obj_t * obj)
{
    LV_ASSERT_OBJ(obj, MY_CLASS);
    lv_barcode_t * barcode = (lv_barcode_t *)obj;

    return barcode->bg_color;
}

lv_color_t lv_barcode_get_data_color(lv_obj_t * obj)
{
    LV_ASSERT_OBJ(obj, MY_CLASS);
    lv_barcode_t * barcode = (lv_barcode_t *)obj;

    return barcode->data_color;
}

lv_obj_t * lv_barcode_get_img(lv_obj_t * obj)
{
    LV_ASSERT_OBJ(obj, MY_CLASS);
    lv_barcode_t * barcode = (lv_barcode_t *)obj;

    return barcode->barcode_img;
}

lv_img_dsc_t * lv_barcode_get_imgdsc(lv_obj_t * obj)
{
    LV_ASSERT_OBJ(obj, MY_CLASS);
    lv_barcode_t * barcode = (lv_barcode_t *)obj;

    return &barcode->dsc;
}


/*=====================
 * Other functions
 *====================*/

/**********************
 *   STATIC FUNCTIONS
 **********************/
static void generate_barcode_image(lv_obj_t * obj, const char *data, uint32_t width, uint32_t height)
{
	LV_ASSERT_OBJ(obj, MY_CLASS);
	lv_img_dsc_t * img_dsc = lv_barcode_get_imgdsc(obj);
	lv_obj_t * img = lv_barcode_get_img(obj);
	lv_color_t bg_color = lv_barcode_get_bg_color(obj);
	lv_color_t data_color = lv_barcode_get_data_color(obj);

    size_t estimated_length = code128_estimate_len(data);
	LV_LOG_USER("estimated_length :%d\n", estimated_length);
    char *barcode_data = (char *)lv_mem_alloc(estimated_length);
	if(barcode_data == NULL)
	{
		LV_LOG_USER("lv_mem_alloc barcode_data err\n");
		return NULL;
	}

    size_t actual_length = code128_encode_raw(data, barcode_data, estimated_length);
    int min_width = actual_length * 2;
    if (width < min_width) {
        width = min_width;
    }

	LV_LOG_USER("img_buf len :%d\n", width * height * sizeof(lv_color_t));
    lv_color_t *img_buf = (lv_color_t *)lv_mem_alloc(width * height * sizeof(lv_color_t));
	if(img_buf == NULL)
	{
		LV_LOG_USER("lv_mem_alloc img_buf err\n");
		return NULL;
	}

    for (int i = 0; i < width * height; i++) {
        img_buf[i] = bg_color;
    }

    int unit_width = width / actual_length;
    int remaining_width = width % actual_length;
    int left_padding = (width - (actual_length * unit_width + remaining_width)) / 2;

	int x = left_padding;
    for (size_t i = 0; i < actual_length; i++) {
        lv_color_t color = barcode_data[i] ? data_color : bg_color;
        int bar_width = unit_width + (remaining_width > 0 ? 1 : 0);
        if (remaining_width > 0) {
            remaining_width--;
        }

        for (int j = 0; j < bar_width; j++) {
            for (int k = 0; k < height; k++) {
                img_buf[k * width + x + j] = color;
            }
        }
        x += bar_width;
    }

    lv_mem_free(barcode_data);

    img_dsc->header.always_zero = 0;
    img_dsc->header.w = width;
    img_dsc->header.h = height;
    img_dsc->header.cf = LV_IMG_CF_TRUE_COLOR;
    img_dsc->data_size = width * height * sizeof(lv_color_t);
    img_dsc->data = (const uint8_t *)img_buf;

	lv_img_set_src(img, img_dsc);

}

static void lv_barcode_constructor(const lv_obj_class_t * class_p, lv_obj_t * obj)
{
    LV_UNUSED(class_p);
    LV_TRACE_OBJ_CREATE("barcode begin");

    lv_barcode_t * barcode = (lv_barcode_t *)obj;

	/*set barcode bg style*/
	barcode->barcode_bg = lv_obj_create(obj);
	lv_obj_set_scroll_dir(barcode->barcode_bg, LV_DIR_NONE);
	//lv_obj_set_size(barcode->barcode_bg, LV_HOR_RES/2, LV_HOR_RES/6);
	lv_obj_remove_style(barcode->barcode_bg, NULL, LV_PART_SCROLLBAR);
	lv_obj_set_style_bg_color(barcode->barcode_bg, lv_color_white(), LV_PART_MAIN);
	lv_obj_set_style_radius(barcode->barcode_bg, LV_BARCODE_ARDIUS_LEN, LV_PART_MAIN);
	lv_obj_align(barcode->barcode_bg, LV_ALIGN_CENTER, 0, 0);

	/*create a barcode img*/
	barcode->barcode_img = lv_img_create(barcode->barcode_bg);
	//lv_img_set_src(barcode->barcode_img, NULL);
	lv_obj_center(barcode->barcode_img);


    /*set barcode color*/
	barcode->bg_color = lv_color_white();
	barcode->data_color = lv_color_black();

	/*have not alloc data*/
	barcode->have_update = false;

    LV_TRACE_OBJ_CREATE("barcode finished");
}

static void lv_barcode_destructor(const lv_obj_class_t * class_p, lv_obj_t * obj)
{
    LV_UNUSED(class_p);
	lv_barcode_t * barcode = (lv_barcode_t *)obj;
	if(barcode->have_update == true)
	{
		lv_mem_free(barcode->dsc.data);
		barcode->have_update = false;
	}
}


#endif  /*LV_USE_BARCODE*/

lv_barcode.h

/**
 * @file lv_barcode.h
 *
 */

#ifndef LV_BARCODE_H
#define LV_BARCODE_H

#ifdef __cplusplus
extern "C" {
#endif

/*********************
 *      INCLUDES
 *********************/
#include "../lv_demos.h"

#if LV_USE_BARCODE != 0

/*********************
 *      DEFINES
 *********************/

#define LV_BARCODE_ARDIUS_LEN    (10)
#define LV_BARCODE_OBJ_WIDE      (400)
#define LV_BARCODE_OBJ_HIDE      (150)


/**********************
 *      TYPEDEFS
 **********************/


/*Data of canvas*/
typedef struct {
    lv_obj_t obj;
	lv_obj_t * barcode_bg;
    lv_obj_t * barcode_img;
    lv_img_dsc_t dsc;
	lv_color_t bg_color;
	lv_color_t data_color;
	bool have_update;
} lv_barcode_t;

/***********************
 * GLOBAL VARIABLES
 ***********************/

/**********************
 * GLOBAL PROTOTYPES
 **********************/
 /**
 * Create an empty barcode (an `img`) object.
 * @param parent point to an object where to create the barcode
 * @return pointer to the created barcode object
 */
lv_obj_t * lv_barcode_create(lv_obj_t * parent);

/**
 * Set the data of a barcode object
 * @param barcode pointer to barcode object
 * @param data data to display
 * @param width barcode width
 * @param height barcode height
 */
void lv_barcode_update(lv_obj_t * obj, const char *data, uint32_t width, uint32_t height);


/*=====================
 * Setter functions
 *====================*/

/**
 * Get the calc btnmatrix to allow styling or other modifications
 * @param obj   pointer to a calc object
 * @return      pointer to the btnmatrix of the calc
 */

void lv_barcode_set_bg_color(lv_obj_t * obj, lv_color_t new_color);

/**
 * Get the calc textarea(calc history) to allow styling or other modifications
 * @param obj   pointer to a calc object
 * @return      pointer to the textarea(calc history) of the calc
 */
void lv_barcode_set_data_color(lv_obj_t * obj, lv_color_t new_color);

/*=====================
 * Getter functions
 *====================*/

/**
 * Get the barcode bgcolor
 * @param obj   pointer to a barcode object
 * @return      color barcode bgcolor
 */
lv_color_t lv_barcode_get_bg_color(lv_obj_t * obj);

/**
 * Get the barcode data color
 * @param obj   pointer to a barcode object
 * @return      color barcode data color
 */
lv_color_t lv_barcode_get_data_color(lv_obj_t * obj);

/**
 * Get the barcode data color
 * @param obj   pointer to a barcode object
 * @return      pointer to img object in barcode object
 */
lv_obj_t * lv_barcode_get_img(lv_obj_t * obj);

/**
 * Get the barcode data color
 * @param obj   pointer to a barcode object
 * @return      pointer to img data in barcode
 */
lv_img_dsc_t * lv_barcode_get_imgdsc(lv_obj_t * obj);

/*=====================
 * Static functions
 *====================*/

static void generate_barcode_image(lv_obj_t * obj, const char *data, uint32_t width, uint32_t height);
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);

/**********************
 *      MACROS
 **********************/

#endif  /*LV_USE_100ASK_CALC*/

#ifdef __cplusplus
} /*extern "C"*/
#endif

#endif /*LV_USE_BARCODE*/


三、运行demo

void lv_demo_test(void)
{
    lv_obj_t * bg = lv_obj_create(lv_scr_act());
	lv_obj_set_size(bg, 466, 466);
	lv_obj_set_scroll_dir(bg, LV_DIR_NONE);
	lv_obj_remove_style(bg, NULL, LV_PART_SCROLLBAR);
	lv_obj_set_style_bg_color(bg, lv_color_black(), LV_PART_MAIN);
	
	lv_obj_t * barcode = lv_barcode_create(bg);
	lv_barcode_update(barcode, "https://lvgl.io", 300, 100);
}

四、运行效果

;