mirror of https://github.com/arendst/Tasmota.git
LVGL add support for PNG images
This commit is contained in:
parent
80189bf6f8
commit
c642e716ce
|
@ -0,0 +1,50 @@
|
|||
# PNG decoder for LVGL
|
||||
|
||||
Allow the use of PNG images in LVGL. This implementation uses [lodepng](https://github.com/lvandeve/lodepng) library.
|
||||
|
||||
## Get started
|
||||
- Download or clone this repository
|
||||
- [Download from GitHub](https://github.com/littlevgl/lv_lib_lodepng/archive/master.zip)
|
||||
- Clone: `git clone https://github.com/littlevgl/lv_lib_png.git`
|
||||
- Include the library: `#include "lv_lib_png/lv_png.h"`
|
||||
- Initalize the decocer with `lv_png_init()`
|
||||
- Test with the following code:
|
||||
```c
|
||||
LV_IMG_DECLARE(png_decoder_test);
|
||||
lv_obj_t * img = lv_img_create(lv_scr_act(), NULL);
|
||||
lv_img_set_src(img, &png_decoder_test);
|
||||
```
|
||||
|
||||
## Use PNG images from file
|
||||
By deafult `lodepng` uses C file IO API (e.g. `fopen`) and images can be opened like this:
|
||||
```c
|
||||
lv_img_set_src(img, "./lv_lib_lodepng/png_decoder_test.png");
|
||||
```
|
||||
|
||||
If you want to make `lodepng` to use LVGL's file system API add `#define LV_PNG_USE_LV_FILESYSTEM 1` to the end of your`lv_conf.h`.
|
||||
In this case you need to [register a driver](https://docs.lvgl.io/latest/en/html/overview/file-system.html) fo LVGL. The following functions are required:
|
||||
- `open_cb()`
|
||||
- `read_cb()`
|
||||
- `close_cb()`
|
||||
- `size_cb()`
|
||||
|
||||
After that fiels can be opened like this:
|
||||
```c
|
||||
lv_img_set_src(img, "P:lv_lib_lodepng/png_decoder_test.png");
|
||||
```
|
||||
|
||||
|
||||
Note that the path of the file might be different.
|
||||
|
||||
## Use PNG images from flash
|
||||
To store a PNG image in flash it needs to be converted to C array with [Online Image converter](https://lvgl.io/tools/imageconverter). Choose `Raw with alpha` Color format and `C array` Output format. Copy the result C array to your project and use it like this:
|
||||
```c
|
||||
LV_IMG_DECLARE(my_test_img);
|
||||
lv_obj_t * img = lv_img_create(lv_scr_act(), NULL);
|
||||
lv_img_set_src(img, &my_test_img);
|
||||
```
|
||||
|
||||
## Learn more
|
||||
To learn more about the PNG decoder itself read [this blog post](https://blog.littlevgl.com/2018-10-05/png_converter)
|
||||
|
||||
To learn more about the Image decoder interface of LittlevGL read the realevant part of the [documentation](https://docs.littlevgl.com/en/html/overview/image.html#image-decoder).
|
|
@ -0,0 +1,21 @@
|
|||
{
|
||||
"name":"lv_lib_png",
|
||||
"description":"Allow the use of PNG images in LVGL. This implementation uses lodepng library.",
|
||||
"keywords":"lvgl, png",
|
||||
"license": "MIT License",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/lvgl/lv_lib_png"
|
||||
},
|
||||
"frameworks": "arduino",
|
||||
"platforms": "espressif32",
|
||||
"build": {
|
||||
"flags": [ "-DLV_PNG_USE_LV_FILESYSTEM=1",
|
||||
"-DLODEPNG_NO_COMPILE_ALLOCATORS",
|
||||
"-DLODEPNG_NO_COMPILE_ERROR_TEXT",
|
||||
"-DLODEPNG_NO_COMPILE_ANCILLARY_CHUNKS",
|
||||
"-DLV_LVGL_H_INCLUDE_SIMPLE",
|
||||
"-I$PROJECT_DIR/include",
|
||||
"-includetasmota_options.h" ]
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,267 @@
|
|||
/**
|
||||
* @file lv_png.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#ifdef LV_LVGL_H_INCLUDE_SIMPLE
|
||||
#include <lvgl.h>
|
||||
#else
|
||||
#include <lvgl/lvgl.h>
|
||||
#endif
|
||||
|
||||
#include "lv_png.h"
|
||||
#include "lodepng.h"
|
||||
#include <stdlib.h>
|
||||
#if LV_MEM_CUSTOM != 0
|
||||
#include LV_MEM_CUSTOM_INCLUDE
|
||||
#endif
|
||||
#include <stdio.h>
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
static lv_res_t decoder_info(struct _lv_img_decoder * decoder, const void * src, lv_img_header_t * header);
|
||||
static lv_res_t decoder_open(lv_img_decoder_t * dec, lv_img_decoder_dsc_t * dsc);
|
||||
static void decoder_close(lv_img_decoder_t * dec, lv_img_decoder_dsc_t * dsc);
|
||||
static void convert_color_depth(uint8_t * img, uint32_t px_cnt);
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Register the PNG decoder functions in LittlevGL
|
||||
*/
|
||||
void lv_png_init(void)
|
||||
{
|
||||
lv_img_decoder_t * dec = lv_img_decoder_create();
|
||||
lv_img_decoder_set_info_cb(dec, decoder_info);
|
||||
lv_img_decoder_set_open_cb(dec, decoder_open);
|
||||
lv_img_decoder_set_close_cb(dec, decoder_close);
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Get info about a PNG image
|
||||
* @param src can be file name or pointer to a C array
|
||||
* @param header store the info here
|
||||
* @return LV_RES_OK: no error; LV_RES_INV: can't get the info
|
||||
*/
|
||||
static lv_res_t decoder_info(struct _lv_img_decoder * decoder, const void * src, lv_img_header_t * header)
|
||||
{
|
||||
(void) decoder; /*Unused*/
|
||||
lv_img_src_t src_type = lv_img_src_get_type(src); /*Get the source type*/
|
||||
|
||||
/*If it's a PNG file...*/
|
||||
if(src_type == LV_IMG_SRC_FILE) {
|
||||
const char * fn = src;
|
||||
if(!strcmp(&fn[strlen(fn) - 3], "png")) { /*Check the extension*/
|
||||
|
||||
/* Read the width and height from the file. They have a constant location:
|
||||
* [16..23]: width
|
||||
* [24..27]: height
|
||||
*/
|
||||
uint32_t size[2];
|
||||
#if LV_PNG_USE_LV_FILESYSTEM
|
||||
lv_fs_file_t f;
|
||||
lv_fs_res_t res = lv_fs_open(&f, fn, LV_FS_MODE_RD);
|
||||
if(res != LV_FS_RES_OK) return -1;
|
||||
lv_fs_seek(&f, 16);
|
||||
uint32_t rn;
|
||||
lv_fs_read(&f, &size, 8, &rn);
|
||||
if(rn != 8) return LV_RES_INV;
|
||||
lv_fs_close(&f);
|
||||
#else
|
||||
FILE* file;
|
||||
file = fopen(fn, "rb" );
|
||||
if(!file) return LV_RES_INV;
|
||||
fseek(file, 16, SEEK_SET);
|
||||
size_t rn = fread(size, 1 , 8, file);
|
||||
fclose(file);
|
||||
if(rn != 8) return LV_RES_INV;
|
||||
#endif
|
||||
/*Save the data in the header*/
|
||||
header->always_zero = 0;
|
||||
header->cf = LV_IMG_CF_RAW_ALPHA;
|
||||
/*The width and height are stored in Big endian format so convert them to little endian*/
|
||||
header->w = (lv_coord_t) ((size[0] & 0xff000000) >> 24) + ((size[0] & 0x00ff0000) >> 8);
|
||||
header->h = (lv_coord_t) ((size[1] & 0xff000000) >> 24) + ((size[1] & 0x00ff0000) >> 8);
|
||||
|
||||
return LV_RES_OK;
|
||||
}
|
||||
}
|
||||
/*If it's a PNG file in a C array...*/
|
||||
else if(src_type == LV_IMG_SRC_VARIABLE) {
|
||||
const lv_img_dsc_t * img_dsc = src;
|
||||
header->always_zero = 0;
|
||||
header->cf = img_dsc->header.cf; /*Save the color format*/
|
||||
header->w = img_dsc->header.w; /*Save the color width*/
|
||||
header->h = img_dsc->header.h; /*Save the color height*/
|
||||
return LV_RES_OK;
|
||||
}
|
||||
|
||||
return LV_RES_INV; /*If didn't succeeded earlier then it's an error*/
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Open a PNG image and return the decided image
|
||||
* @param src can be file name or pointer to a C array
|
||||
* @param style style of the image object (unused now but certain formats might use it)
|
||||
* @return pointer to the decoded image or `LV_IMG_DECODER_OPEN_FAIL` if failed
|
||||
*/
|
||||
static lv_res_t decoder_open(lv_img_decoder_t * decoder, lv_img_decoder_dsc_t * dsc)
|
||||
{
|
||||
|
||||
(void) decoder; /*Unused*/
|
||||
uint32_t error; /*For the return values of PNG decoder functions*/
|
||||
|
||||
uint8_t * img_data = NULL;
|
||||
|
||||
/*If it's a PNG file...*/
|
||||
if(dsc->src_type == LV_IMG_SRC_FILE) {
|
||||
const char * fn = dsc->src;
|
||||
|
||||
if(!strcmp(&fn[strlen(fn) - 3], "png")) { /*Check the extension*/
|
||||
|
||||
/*Load the PNG file into buffer. It's still compressed (not decoded)*/
|
||||
unsigned char * png_data; /*Pointer to the loaded data. Same as the original file just loaded into the RAM*/
|
||||
size_t png_data_size; /*Size of `png_data` in bytes*/
|
||||
|
||||
error = lodepng_load_file(&png_data, &png_data_size, fn); /*Load the file*/
|
||||
if(error) {
|
||||
#ifdef LODEPNG_COMPILE_ERROR_TEXT
|
||||
LV_LOG_ERROR("lv_png error %u: %s\n", error, lodepng_error_text(error));
|
||||
#else
|
||||
LV_LOG_ERROR("lv_png error %u\n", error);
|
||||
#endif
|
||||
return LV_RES_INV;
|
||||
}
|
||||
|
||||
/*Decode the PNG image*/
|
||||
uint32_t png_width; /*Will be the width of the decoded image*/
|
||||
uint32_t png_height; /*Will be the width of the decoded image*/
|
||||
|
||||
/*Decode the loaded image in ARGB8888 */
|
||||
error = lodepng_decode32(&img_data, &png_width, &png_height, png_data, png_data_size);
|
||||
LV_MEM_CUSTOM_FREE(png_data); /*Free the loaded file*/
|
||||
if(error) {
|
||||
#ifdef LODEPNG_COMPILE_ERROR_TEXT
|
||||
LV_LOG_ERROR("lv_png error %u: %s\n", error, lodepng_error_text(error));
|
||||
#else
|
||||
LV_LOG_ERROR("lv_png error %u\n", error);
|
||||
#endif
|
||||
return LV_RES_INV;
|
||||
}
|
||||
|
||||
/*Convert the image to the system's color depth*/
|
||||
convert_color_depth(img_data, png_width * png_height);
|
||||
dsc->img_data = img_data;
|
||||
return LV_RES_OK; /*The image is fully decoded. Return with its pointer*/
|
||||
}
|
||||
}
|
||||
/*If it's a PNG file in a C array...*/
|
||||
else if(dsc->src_type == LV_IMG_SRC_VARIABLE) {
|
||||
const lv_img_dsc_t * img_dsc = dsc->src;
|
||||
uint32_t png_width; /*No used, just required by he decoder*/
|
||||
uint32_t png_height; /*No used, just required by he decoder*/
|
||||
|
||||
/*Decode the image in ARGB8888 */
|
||||
error = lodepng_decode32(&img_data, &png_width, &png_height, img_dsc->data, img_dsc->data_size);
|
||||
|
||||
if(error) {
|
||||
return LV_RES_INV;
|
||||
}
|
||||
|
||||
/*Convert the image to the system's color depth*/
|
||||
convert_color_depth(img_data, png_width * png_height);
|
||||
|
||||
dsc->img_data = img_data;
|
||||
return LV_RES_OK; /*Return with its pointer*/
|
||||
}
|
||||
|
||||
return LV_RES_INV; /*If not returned earlier then it failed*/
|
||||
}
|
||||
|
||||
/**
|
||||
* Free the allocated resources
|
||||
*/
|
||||
static void decoder_close(lv_img_decoder_t * decoder, lv_img_decoder_dsc_t * dsc)
|
||||
{
|
||||
(void) decoder; /*Unused*/
|
||||
if(dsc->img_data) LV_MEM_CUSTOM_FREE((uint8_t *)dsc->img_data);
|
||||
}
|
||||
|
||||
/**
|
||||
* If the display is not in 32 bit format (ARGB888) then covert the image to the current color depth
|
||||
* @param img the ARGB888 image
|
||||
* @param px_cnt number of pixels in `img`
|
||||
*/
|
||||
static void convert_color_depth(uint8_t * img, uint32_t px_cnt)
|
||||
{
|
||||
#if LV_COLOR_DEPTH == 32
|
||||
lv_color32_t * img_argb = (lv_color32_t*)img;
|
||||
lv_color_t c;
|
||||
lv_color_t * img_c = (lv_color_t *) img;
|
||||
uint32_t i;
|
||||
for(i = 0; i < px_cnt; i++) {
|
||||
c = LV_COLOR_MAKE(img_argb[i].ch.red, img_argb[i].ch.green, img_argb[i].ch.blue);
|
||||
img_c[i].ch.red = c.ch.blue;
|
||||
img_c[i].ch.blue = c.ch.red;
|
||||
}
|
||||
#elif LV_COLOR_DEPTH == 16
|
||||
lv_color32_t * img_argb = (lv_color32_t*)img;
|
||||
lv_color_t c;
|
||||
uint32_t i;
|
||||
for(i = 0; i < px_cnt; i++) {
|
||||
c = LV_COLOR_MAKE(img_argb[i].ch.blue, img_argb[i].ch.green, img_argb[i].ch.red);
|
||||
img[i*3 + 2] = img_argb[i].ch.alpha;
|
||||
img[i*3 + 1] = c.full >> 8;
|
||||
img[i*3 + 0] = c.full & 0xFF;
|
||||
}
|
||||
#ifdef LV_MEM_CUSTOM_REALLOC
|
||||
LV_MEM_CUSTOM_REALLOC(img, px_cnt * 3); /*Shrink the buffer*/
|
||||
#else
|
||||
realloc(img, px_cnt * 3); /*Shrink the buffer*/
|
||||
#endif
|
||||
#elif LV_COLOR_DEPTH == 8
|
||||
lv_color32_t * img_argb = (lv_color32_t*)img;
|
||||
lv_color_t c;
|
||||
uint32_t i;
|
||||
for(i = 0; i < px_cnt; i++) {
|
||||
c = LV_COLOR_MAKE(img_argb[i].red, img_argb[i].green, img_argb[i].blue);
|
||||
img[i*3 + 1] = img_argb[i].alpha;
|
||||
img[i*3 + 0] = c.full
|
||||
}
|
||||
#if LV_MEM_CUSTOM_REALLOC
|
||||
LV_MEM_CUSTOM_REALLOC(img, px_cnt * 2); /*Shrink the buffer*/
|
||||
#else
|
||||
realloc(img, px_cnt * 2); /*Shrink the buffer*/
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
/**
|
||||
* @file lv_png.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LV_PNG_H
|
||||
#define LV_PNG_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Register the PNG decoder functions in LittlevGL
|
||||
*/
|
||||
void lv_png_init(void);
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /*LV_PNG_H*/
|
|
@ -19,7 +19,7 @@ const lvbe_call_c_t lv_img_func[] = {
|
|||
{ "get_offset_x", (void*) &lv_img_get_offset_x, "i", "(lv_obj)" },
|
||||
{ "get_offset_y", (void*) &lv_img_get_offset_y, "i", "(lv_obj)" },
|
||||
{ "get_pivot", (void*) &lv_img_get_pivot, "", "(lv_obj)(lv_point)" },
|
||||
{ "get_src", (void*) &lv_img_get_src, "i", "(lv_obj)" },
|
||||
{ "get_src", (void*) &lv_img_get_src, ".", "(lv_obj)" },
|
||||
{ "get_zoom", (void*) &lv_img_get_zoom, "i", "(lv_obj)" },
|
||||
{ "set_angle", (void*) &lv_img_set_angle, "", "(lv_obj)i" },
|
||||
{ "set_antialias", (void*) &lv_img_set_antialias, "", "(lv_obj)b" },
|
||||
|
@ -27,7 +27,7 @@ const lvbe_call_c_t lv_img_func[] = {
|
|||
{ "set_offset_x", (void*) &lv_img_set_offset_x, "", "(lv_obj)i" },
|
||||
{ "set_offset_y", (void*) &lv_img_set_offset_y, "", "(lv_obj)i" },
|
||||
{ "set_pivot", (void*) &lv_img_set_pivot, "", "(lv_obj)ii" },
|
||||
{ "set_src", (void*) &lv_img_set_src, "", "(lv_obj)i" },
|
||||
{ "set_src", (void*) &lv_img_set_src, "", "(lv_obj)." },
|
||||
{ "set_tasmota_logo", (void*) &lv_img_set_tasmota_logo, "", "(lv_obj)" },
|
||||
{ "set_zoom", (void*) &lv_img_set_zoom, "", "(lv_obj)i" },
|
||||
};
|
||||
|
@ -82,7 +82,7 @@ const lvbe_call_c_t lv_style_func[] = {
|
|||
{ "set_pad_right", (void*) &lv_style_set_pad_right, "", "(lv_style)ii" },
|
||||
{ "set_pad_top", (void*) &lv_style_set_pad_top, "", "(lv_style)ii" },
|
||||
{ "set_pattern_blend_mode", (void*) &lv_style_set_pattern_blend_mode, "", "(lv_style)ii" },
|
||||
{ "set_pattern_image", (void*) &lv_style_set_pattern_image, "", "(lv_style)ii" },
|
||||
{ "set_pattern_image", (void*) &lv_style_set_pattern_image, "", "(lv_style)i." },
|
||||
{ "set_pattern_opa", (void*) &lv_style_set_pattern_opa, "", "(lv_style)ii" },
|
||||
{ "set_pattern_recolor", (void*) &lv_style_set_pattern_recolor, "", "(lv_style)i(lv_color)" },
|
||||
{ "set_pattern_recolor_opa", (void*) &lv_style_set_pattern_recolor_opa, "", "(lv_style)ii" },
|
||||
|
@ -179,7 +179,7 @@ const lvbe_call_c_t lv_obj_func[] = {
|
|||
{ "align_mid_y", (void*) &lv_obj_align_mid_y, "", "(lv_obj)(lv_obj)ii" },
|
||||
{ "align_x", (void*) &lv_obj_align_x, "", "(lv_obj)(lv_obj)ii" },
|
||||
{ "align_y", (void*) &lv_obj_align_y, "", "(lv_obj)(lv_obj)ii" },
|
||||
{ "allocate_ext_attr", (void*) &lv_obj_allocate_ext_attr, "i", "(lv_obj)i" },
|
||||
{ "allocate_ext_attr", (void*) &lv_obj_allocate_ext_attr, ".", "(lv_obj)i" },
|
||||
{ "area_is_visible", (void*) &lv_obj_area_is_visible, "b", "(lv_obj)(lv_area)" },
|
||||
{ "clean", (void*) &lv_obj_clean, "", "(lv_obj)" },
|
||||
{ "clean_style_list", (void*) &lv_obj_clean_style_list, "", "(lv_obj)i" },
|
||||
|
@ -206,7 +206,7 @@ const lvbe_call_c_t lv_obj_func[] = {
|
|||
{ "get_drag_parent", (void*) &lv_obj_get_drag_parent, "b", "(lv_obj)" },
|
||||
{ "get_drag_throw", (void*) &lv_obj_get_drag_throw, "b", "(lv_obj)" },
|
||||
{ "get_draw_rect_ext_pad_size", (void*) &lv_obj_get_draw_rect_ext_pad_size, "i", "(lv_obj)i" },
|
||||
{ "get_ext_attr", (void*) &lv_obj_get_ext_attr, "i", "(lv_obj)" },
|
||||
{ "get_ext_attr", (void*) &lv_obj_get_ext_attr, ".", "(lv_obj)" },
|
||||
{ "get_ext_click_pad_bottom", (void*) &lv_obj_get_ext_click_pad_bottom, "i", "(lv_obj)" },
|
||||
{ "get_ext_click_pad_left", (void*) &lv_obj_get_ext_click_pad_left, "i", "(lv_obj)" },
|
||||
{ "get_ext_click_pad_right", (void*) &lv_obj_get_ext_click_pad_right, "i", "(lv_obj)" },
|
||||
|
@ -215,7 +215,7 @@ const lvbe_call_c_t lv_obj_func[] = {
|
|||
{ "get_focus_parent", (void*) &lv_obj_get_focus_parent, "b", "(lv_obj)" },
|
||||
{ "get_focused_obj", (void*) &lv_obj_get_focused_obj, "lv_obj", "(lv_obj)" },
|
||||
{ "get_gesture_parent", (void*) &lv_obj_get_gesture_parent, "b", "(lv_obj)" },
|
||||
{ "get_group", (void*) &lv_obj_get_group, "i", "(lv_obj)" },
|
||||
{ "get_group", (void*) &lv_obj_get_group, ".", "(lv_obj)" },
|
||||
{ "get_height", (void*) &lv_obj_get_height, "i", "(lv_obj)" },
|
||||
{ "get_height_fit", (void*) &lv_obj_get_height_fit, "i", "(lv_obj)" },
|
||||
{ "get_height_grid", (void*) &lv_obj_get_height_grid, "i", "(lv_obj)ii" },
|
||||
|
@ -269,7 +269,7 @@ const lvbe_call_c_t lv_obj_func[] = {
|
|||
{ "get_style_pad_right", (void*) &lv_obj_get_style_pad_right, "i", "(lv_obj)i" },
|
||||
{ "get_style_pad_top", (void*) &lv_obj_get_style_pad_top, "i", "(lv_obj)i" },
|
||||
{ "get_style_pattern_blend_mode", (void*) &lv_obj_get_style_pattern_blend_mode, "i", "(lv_obj)i" },
|
||||
{ "get_style_pattern_image", (void*) &lv_obj_get_style_pattern_image, "i", "(lv_obj)i" },
|
||||
{ "get_style_pattern_image", (void*) &lv_obj_get_style_pattern_image, ".", "(lv_obj)i" },
|
||||
{ "get_style_pattern_opa", (void*) &lv_obj_get_style_pattern_opa, "i", "(lv_obj)i" },
|
||||
{ "get_style_pattern_recolor", (void*) &lv_obj_get_style_pattern_recolor, "lv_color", "(lv_obj)i" },
|
||||
{ "get_style_pattern_recolor_opa", (void*) &lv_obj_get_style_pattern_recolor_opa, "i", "(lv_obj)i" },
|
||||
|
@ -411,7 +411,7 @@ const lvbe_call_c_t lv_obj_func[] = {
|
|||
{ "set_style_local_pad_right", (void*) &lv_obj_set_style_local_pad_right, "", "(lv_obj)iii" },
|
||||
{ "set_style_local_pad_top", (void*) &lv_obj_set_style_local_pad_top, "", "(lv_obj)iii" },
|
||||
{ "set_style_local_pattern_blend_mode", (void*) &lv_obj_set_style_local_pattern_blend_mode, "", "(lv_obj)iii" },
|
||||
{ "set_style_local_pattern_image", (void*) &lv_obj_set_style_local_pattern_image, "", "(lv_obj)iii" },
|
||||
{ "set_style_local_pattern_image", (void*) &lv_obj_set_style_local_pattern_image, "", "(lv_obj)ii." },
|
||||
{ "set_style_local_pattern_opa", (void*) &lv_obj_set_style_local_pattern_opa, "", "(lv_obj)iii" },
|
||||
{ "set_style_local_pattern_recolor", (void*) &lv_obj_set_style_local_pattern_recolor, "", "(lv_obj)ii(lv_color)" },
|
||||
{ "set_style_local_pattern_recolor_opa", (void*) &lv_obj_set_style_local_pattern_recolor_opa, "", "(lv_obj)iii" },
|
||||
|
@ -574,17 +574,17 @@ const lvbe_call_c_t lv_calendar_func[] = {
|
|||
const lvbe_call_c_t lv_canvas_func[] = {
|
||||
{ "blur_hor", (void*) &lv_canvas_blur_hor, "", "(lv_obj)(lv_area)i" },
|
||||
{ "blur_ver", (void*) &lv_canvas_blur_ver, "", "(lv_obj)(lv_area)i" },
|
||||
{ "copy_buf", (void*) &lv_canvas_copy_buf, "", "(lv_obj)iiiii" },
|
||||
{ "copy_buf", (void*) &lv_canvas_copy_buf, "", "(lv_obj).iiii" },
|
||||
{ "create", (void*) &lv_canvas_create, "+lv_canvas", "(lv_obj)(lv_obj)" },
|
||||
{ "draw_arc", (void*) &lv_canvas_draw_arc, "", "(lv_obj)iiiii(lv_draw_line_dsc)" },
|
||||
{ "draw_img", (void*) &lv_canvas_draw_img, "", "(lv_obj)iii(lv_draw_img_dsc)" },
|
||||
{ "draw_img", (void*) &lv_canvas_draw_img, "", "(lv_obj)ii.(lv_draw_img_dsc)" },
|
||||
{ "draw_line", (void*) &lv_canvas_draw_line, "", "(lv_obj)ii(lv_draw_line_dsc)" },
|
||||
{ "draw_polygon", (void*) &lv_canvas_draw_polygon, "", "(lv_obj)ii(lv_draw_rect_dsc)" },
|
||||
{ "draw_rect", (void*) &lv_canvas_draw_rect, "", "(lv_obj)iiii(lv_draw_rect_dsc)" },
|
||||
{ "draw_text", (void*) &lv_canvas_draw_text, "", "(lv_obj)iii(lv_draw_label_dsc)si" },
|
||||
{ "fill_bg", (void*) &lv_canvas_fill_bg, "", "(lv_obj)(lv_color)i" },
|
||||
{ "get_px", (void*) &lv_canvas_get_px, "lv_color", "(lv_obj)ii" },
|
||||
{ "set_buffer", (void*) &lv_canvas_set_buffer, "", "(lv_obj)iii(lv_img_cf)" },
|
||||
{ "set_buffer", (void*) &lv_canvas_set_buffer, "", "(lv_obj).ii(lv_img_cf)" },
|
||||
{ "set_palette", (void*) &lv_canvas_set_palette, "", "(lv_obj)i(lv_color)" },
|
||||
{ "set_px", (void*) &lv_canvas_set_px, "", "(lv_obj)ii(lv_color)" },
|
||||
{ "transform", (void*) &lv_canvas_transform, "", "(lv_obj)(lv_img_dsc)iiiiiib" },
|
||||
|
@ -714,7 +714,7 @@ const lvbe_call_c_t lv_gauge_func[] = {
|
|||
{ "get_max_value", (void*) &lv_gauge_get_max_value, "i", "(lv_obj)" },
|
||||
{ "get_min_value", (void*) &lv_gauge_get_min_value, "i", "(lv_obj)" },
|
||||
{ "get_needle_count", (void*) &lv_gauge_get_needle_count, "i", "(lv_obj)" },
|
||||
{ "get_needle_img", (void*) &lv_gauge_get_needle_img, "i", "(lv_obj)" },
|
||||
{ "get_needle_img", (void*) &lv_gauge_get_needle_img, ".", "(lv_obj)" },
|
||||
{ "get_needle_img_pivot_x", (void*) &lv_gauge_get_needle_img_pivot_x, "i", "(lv_obj)" },
|
||||
{ "get_needle_img_pivot_y", (void*) &lv_gauge_get_needle_img_pivot_y, "i", "(lv_obj)" },
|
||||
{ "get_scale_angle", (void*) &lv_gauge_get_scale_angle, "i", "(lv_obj)" },
|
||||
|
@ -723,7 +723,7 @@ const lvbe_call_c_t lv_gauge_func[] = {
|
|||
{ "set_critical_value", (void*) &lv_gauge_set_critical_value, "", "(lv_obj)i" },
|
||||
{ "set_formatter_cb", (void*) &lv_gauge_set_formatter_cb, "", "(lv_obj)&4" },
|
||||
{ "set_needle_count", (void*) &lv_gauge_set_needle_count, "", "(lv_obj)i(lv_color)" },
|
||||
{ "set_needle_img", (void*) &lv_gauge_set_needle_img, "", "(lv_obj)iii" },
|
||||
{ "set_needle_img", (void*) &lv_gauge_set_needle_img, "", "(lv_obj).ii" },
|
||||
{ "set_range", (void*) &lv_gauge_set_range, "", "(lv_obj)ii" },
|
||||
{ "set_scale", (void*) &lv_gauge_set_scale, "", "(lv_obj)iii" },
|
||||
{ "set_value", (void*) &lv_gauge_set_value, "", "(lv_obj)ii" },
|
||||
|
@ -732,10 +732,10 @@ const lvbe_call_c_t lv_gauge_func[] = {
|
|||
/* `lv_imgbtn` methods */
|
||||
const lvbe_call_c_t lv_imgbtn_func[] = {
|
||||
{ "create", (void*) &lv_imgbtn_create, "+lv_imgbtn", "(lv_obj)(lv_obj)" },
|
||||
{ "get_src", (void*) &lv_imgbtn_get_src, "i", "(lv_obj)i" },
|
||||
{ "get_src", (void*) &lv_imgbtn_get_src, ".", "(lv_obj)i" },
|
||||
{ "get_state", (void*) &lv_imgbtn_get_state, "i", "(lv_obj)" },
|
||||
{ "set_checkable", (void*) &lv_imgbtn_set_checkable, "", "(lv_obj)b" },
|
||||
{ "set_src", (void*) &lv_imgbtn_set_src, "", "(lv_obj)ii" },
|
||||
{ "set_src", (void*) &lv_imgbtn_set_src, "", "(lv_obj)i." },
|
||||
{ "set_state", (void*) &lv_imgbtn_set_state, "", "(lv_obj)i" },
|
||||
{ "toggle", (void*) &lv_imgbtn_toggle, "", "(lv_obj)" },
|
||||
};
|
||||
|
@ -821,7 +821,7 @@ const lvbe_call_c_t lv_linemeter_func[] = {
|
|||
|
||||
/* `lv_list` methods */
|
||||
const lvbe_call_c_t lv_list_func[] = {
|
||||
{ "add_btn", (void*) &lv_list_add_btn, "lv_obj", "(lv_obj)is" },
|
||||
{ "add_btn", (void*) &lv_list_add_btn, "lv_obj", "(lv_obj).s" },
|
||||
{ "clean", (void*) &lv_list_clean, "", "(lv_obj)" },
|
||||
{ "create", (void*) &lv_list_create, "+lv_list", "(lv_obj)(lv_obj)" },
|
||||
{ "down", (void*) &lv_list_down, "", "(lv_obj)" },
|
||||
|
@ -871,7 +871,7 @@ const lvbe_call_c_t lv_msgbox_func[] = {
|
|||
const lvbe_call_c_t lv_objmask_func[] = {
|
||||
{ "create", (void*) &lv_objmask_create, "+lv_objmask", "(lv_obj)(lv_obj)" },
|
||||
{ "remove_mask", (void*) &lv_objmask_remove_mask, "", "(lv_obj)(lv_objmask_mask)" },
|
||||
{ "update_mask", (void*) &lv_objmask_update_mask, "", "(lv_obj)(lv_objmask_mask)i" },
|
||||
{ "update_mask", (void*) &lv_objmask_update_mask, "", "(lv_obj)(lv_objmask_mask)." },
|
||||
};
|
||||
|
||||
/* `lv_page` methods */
|
||||
|
@ -966,7 +966,7 @@ const lvbe_call_c_t lv_spinbox_func[] = {
|
|||
|
||||
/* `lv_spinner` methods */
|
||||
const lvbe_call_c_t lv_spinner_func[] = {
|
||||
{ "anim_cb", (void*) &lv_spinner_anim_cb, "", "ii" },
|
||||
{ "anim_cb", (void*) &lv_spinner_anim_cb, "", ".i" },
|
||||
{ "create", (void*) &lv_spinner_create, "+lv_spinner", "(lv_obj)(lv_obj)" },
|
||||
{ "get_arc_length", (void*) &lv_spinner_get_arc_length, "i", "(lv_obj)" },
|
||||
{ "get_dir", (void*) &lv_spinner_get_dir, "i", "(lv_obj)" },
|
||||
|
@ -1091,8 +1091,8 @@ const lvbe_call_c_t lv_tileview_func[] = {
|
|||
|
||||
/* `lv_win` methods */
|
||||
const lvbe_call_c_t lv_win_func[] = {
|
||||
{ "add_btn_left", (void*) &lv_win_add_btn_left, "lv_obj", "(lv_obj)i" },
|
||||
{ "add_btn_right", (void*) &lv_win_add_btn_right, "lv_obj", "(lv_obj)i" },
|
||||
{ "add_btn_left", (void*) &lv_win_add_btn_left, "lv_obj", "(lv_obj)." },
|
||||
{ "add_btn_right", (void*) &lv_win_add_btn_right, "lv_obj", "(lv_obj)." },
|
||||
{ "clean", (void*) &lv_win_clean, "", "(lv_obj)" },
|
||||
{ "close_event_cb", (void*) &lv_win_close_event_cb, "", "(lv_obj)(lv_event)" },
|
||||
{ "create", (void*) &lv_win_create, "+lv_win", "(lv_obj)(lv_obj)" },
|
||||
|
|
|
@ -109,6 +109,7 @@ typedef int16_t lv_coord_t;
|
|||
# define LV_MEM_CUSTOM_INCLUDE <tasmota_lv_stdlib.h> /*Header for the dynamic memory function*/
|
||||
# define LV_MEM_CUSTOM_ALLOC lvbe_malloc /*Wrapper to malloc*/ /* PSRAM support */
|
||||
# define LV_MEM_CUSTOM_FREE lvbe_free /*Wrapper to free*/
|
||||
# define LV_MEM_CUSTOM_REALLOC lvbe_realloc /*Wrapper to realloc*/
|
||||
#endif /*LV_MEM_CUSTOM*/
|
||||
|
||||
/* Use the standard memcpy and memset instead of LVGL's own functions.
|
||||
|
@ -328,7 +329,7 @@ typedef void * lv_indev_drv_user_data_t; /*Type of user data in the i
|
|||
*===============*/
|
||||
|
||||
/*1: Enable the log module*/
|
||||
#define LV_USE_LOG 0
|
||||
#define LV_USE_LOG 1
|
||||
#if LV_USE_LOG
|
||||
/* How important log should be added:
|
||||
* LV_LOG_LEVEL_TRACE A lot of logs to give detailed information
|
||||
|
@ -337,7 +338,7 @@ typedef void * lv_indev_drv_user_data_t; /*Type of user data in the i
|
|||
* LV_LOG_LEVEL_ERROR Only critical issue, when the system may fail
|
||||
* LV_LOG_LEVEL_NONE Do not log anything
|
||||
*/
|
||||
# define LV_LOG_LEVEL LV_LOG_LEVEL_WARN
|
||||
# define LV_LOG_LEVEL LV_LOG_LEVEL_ERROR
|
||||
|
||||
/* 1: Print the log with 'printf';
|
||||
* 0: user need to register a callback with `lv_log_register_print_cb`*/
|
||||
|
|
|
@ -20,4 +20,5 @@
|
|||
// replacement for <stdlib.h> used for PSRAM malloc in LVGL
|
||||
|
||||
extern void *lvbe_malloc(size_t size);
|
||||
extern void lvbe_free(void *ptr);
|
||||
extern void lvbe_free(void *ptr);
|
||||
extern void *lvbe_realloc(void *ptr, size_t size);
|
|
@ -931,6 +931,7 @@
|
|||
//#define USE_LVGL // LVGL Engine, requires Berry, takes 440k of Flash
|
||||
#define USE_LVGL_PSRAM // Allocate LVGL memory in PSRAM if PSRAM is connected - this might be slightly slower but leaves main memory intact
|
||||
#define USE_LVGL_MAX_SLEEP 10 // max sleep in ms when LVGL is enabled, more than 10ms will make display less responsive
|
||||
#define USE_LVGL_PNG_DECODER // include a PNG image decoder from file system
|
||||
//#define USE_LVGL_FREETYPE // Use the FreeType renderer to display fonts using native TTF files in file system (+75k flash)
|
||||
// WARNING this feature needs to increase the stack size to 32KB, for which there is no easy way right now
|
||||
#define LV_USE_FT_CACHE_MANAGER 1 // define whether glyphs are cached by FreeType library
|
||||
|
|
|
@ -426,6 +426,7 @@ extern "C" {
|
|||
if ((return_type == nullptr) || (strlen(return_type) == 0)) { be_return_nil(vm); } // does not return
|
||||
else if (strlen(return_type) == 1) {
|
||||
switch (return_type[0]) {
|
||||
case '.': // fallback next
|
||||
case 'i': be_pushint(vm, ret); break;
|
||||
case 'b': be_pushbool(vm, ret); break;
|
||||
case 's': be_pushstring(vm, (const char*) ret); break;
|
||||
|
|
|
@ -32,6 +32,10 @@
|
|||
|
||||
#include "Adafruit_LvGL_Glue.h"
|
||||
|
||||
#ifdef USE_LVGL_PNG_DECODER
|
||||
#include "lv_png.h"
|
||||
#endif // USE_LVGL_PNG_DECODER
|
||||
|
||||
Adafruit_LvGL_Glue * glue;
|
||||
|
||||
// **************************************************
|
||||
|
@ -338,6 +342,14 @@ extern "C" {
|
|||
void lvbe_free(void *ptr) {
|
||||
free(ptr);
|
||||
}
|
||||
|
||||
#ifdef USE_LVGL_PNG_DECODER
|
||||
// for PNG decoder, use same allocators as LVGL
|
||||
void* lodepng_malloc(size_t size) { return lvbe_malloc(size); }
|
||||
void* lodepng_realloc(void* ptr, size_t new_size) { return lvbe_realloc(ptr, new_size); }
|
||||
void lodepng_free(void* ptr) { lvbe_free(ptr); }
|
||||
#endif // USE_LVGL_PNG_DECODER
|
||||
|
||||
}
|
||||
|
||||
/************************************************************
|
||||
|
@ -429,6 +441,9 @@ void start_lvgl(const char * uconfig) {
|
|||
USE_LVGL_FREETYPE_MAX_SIZES,
|
||||
psramFound() ? USE_LVGL_FREETYPE_MAX_BYTES_PSRAM : USE_LVGL_FREETYPE_MAX_BYTES);
|
||||
#endif
|
||||
#ifdef USE_LVGL_PNG_DECODER
|
||||
lv_png_init();
|
||||
#endif // USE_LVGL_PNG_DECODER
|
||||
|
||||
AddLog(LOG_LEVEL_INFO, PSTR(D_LOG_LVGL "LVGL initialized"));
|
||||
}
|
||||
|
|
|
@ -33,8 +33,8 @@ return_types = {
|
|||
"int16_t": "i",
|
||||
"uint32_t": "i",
|
||||
"int32_t": "i",
|
||||
"void *": "i",
|
||||
"const void *": "i",
|
||||
"void *": ".",
|
||||
"const void *": ".",
|
||||
"char *": "s",
|
||||
"const char *": "s",
|
||||
"lv_obj_user_data_t": "i",
|
||||
|
|
Loading…
Reference in New Issue