feat(draw): add vg-lite draw unit (#5010)
Signed-off-by: pengyiqiang <pengyiqiang@xiaomi.com> Co-authored-by: pengyiqiang <pengyiqiang@xiaomi.com>
This commit is contained in:
13
Kconfig
13
Kconfig
@@ -357,6 +357,19 @@ menu "LVGL configuration"
|
|||||||
config LV_USE_DRAW_PXP
|
config LV_USE_DRAW_PXP
|
||||||
bool "Use NXP's PXP on iMX RTxxx platforms."
|
bool "Use NXP's PXP on iMX RTxxx platforms."
|
||||||
|
|
||||||
|
config LV_USE_DRAW_VG_LITE
|
||||||
|
bool "Use VG-Lite GPU."
|
||||||
|
|
||||||
|
config LV_VG_LITE_USE_GPU_INIT
|
||||||
|
bool "Enbale VG-Lite custom external 'gpu_init()' function."
|
||||||
|
default n
|
||||||
|
depends on LV_USE_DRAW_VG_LITE
|
||||||
|
|
||||||
|
config LV_VG_LITE_USE_ASSERT
|
||||||
|
bool "Enable VG-Lite assert."
|
||||||
|
default n
|
||||||
|
depends on LV_USE_DRAW_VG_LITE
|
||||||
|
|
||||||
config LV_USE_GPU_SDL
|
config LV_USE_GPU_SDL
|
||||||
bool "Use SDL renderer API"
|
bool "Use SDL renderer API"
|
||||||
default n
|
default n
|
||||||
|
|||||||
@@ -128,6 +128,17 @@
|
|||||||
/* Draw using cached SDL textures*/
|
/* Draw using cached SDL textures*/
|
||||||
#define LV_USE_DRAW_SDL 0
|
#define LV_USE_DRAW_SDL 0
|
||||||
|
|
||||||
|
/* Use VG-Lite GPU. */
|
||||||
|
#define LV_USE_DRAW_VG_LITE 0
|
||||||
|
|
||||||
|
#if LV_USE_DRAW_VG_LITE
|
||||||
|
/* Enbale VG-Lite custom external 'gpu_init()' function */
|
||||||
|
#define LV_VG_LITE_USE_GPU_INIT 0
|
||||||
|
|
||||||
|
/* Enable VG-Lite assert. */
|
||||||
|
#define LV_VG_LITE_USE_ASSERT 0
|
||||||
|
#endif
|
||||||
|
|
||||||
/*=================
|
/*=================
|
||||||
* OPERATING SYSTEM
|
* OPERATING SYSTEM
|
||||||
*=================*/
|
*=================*/
|
||||||
|
|||||||
@@ -419,6 +419,8 @@ static void draw_letter(lv_draw_unit_t * draw_unit, lv_draw_glyph_dsc_t * dsc,
|
|||||||
if(g.bpp == LV_IMGFONT_BPP) dsc->format = LV_DRAW_LETTER_BITMAP_FORMAT_IMAGE;
|
if(g.bpp == LV_IMGFONT_BPP) dsc->format = LV_DRAW_LETTER_BITMAP_FORMAT_IMAGE;
|
||||||
else dsc->format = LV_DRAW_LETTER_BITMAP_FORMAT_A8;
|
else dsc->format = LV_DRAW_LETTER_BITMAP_FORMAT_A8;
|
||||||
|
|
||||||
|
dsc->g = &g;
|
||||||
|
|
||||||
cb(draw_unit, dsc, NULL, NULL);
|
cb(draw_unit, dsc, NULL, NULL);
|
||||||
LV_PROFILER_END;
|
LV_PROFILER_END;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -87,6 +87,7 @@ typedef struct {
|
|||||||
lv_draw_glyph_bitmap_format_t format;
|
lv_draw_glyph_bitmap_format_t format;
|
||||||
const lv_area_t * letter_coords;
|
const lv_area_t * letter_coords;
|
||||||
const lv_area_t * bg_coords;
|
const lv_area_t * bg_coords;
|
||||||
|
const lv_font_glyph_dsc_t * g;
|
||||||
lv_color_t color;
|
lv_color_t color;
|
||||||
lv_opa_t opa;
|
lv_opa_t opa;
|
||||||
} lv_draw_glyph_dsc_t;
|
} lv_draw_glyph_dsc_t;
|
||||||
|
|||||||
197
src/draw/vg_lite/lv_draw_buf_vg_lite.c
Normal file
197
src/draw/vg_lite/lv_draw_buf_vg_lite.c
Normal file
@@ -0,0 +1,197 @@
|
|||||||
|
/**
|
||||||
|
* @file lv_draw_buf_vg_lite.c
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*********************
|
||||||
|
* INCLUDES
|
||||||
|
*********************/
|
||||||
|
|
||||||
|
#include "lv_draw_vg_lite.h"
|
||||||
|
|
||||||
|
#if LV_USE_DRAW_VG_LITE
|
||||||
|
|
||||||
|
#include "lv_vg_lite_utils.h"
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
/*********************
|
||||||
|
* DEFINES
|
||||||
|
*********************/
|
||||||
|
|
||||||
|
/**********************
|
||||||
|
* TYPEDEFS
|
||||||
|
**********************/
|
||||||
|
|
||||||
|
/**********************
|
||||||
|
* STATIC PROTOTYPES
|
||||||
|
**********************/
|
||||||
|
|
||||||
|
static void * buf_malloc(size_t size, lv_color_format_t color_format);
|
||||||
|
static void buf_free(void * buf);
|
||||||
|
static void * buf_align(void * buf, lv_color_format_t color_format);
|
||||||
|
static void invalidate_cache(void * buf, uint32_t stride, lv_color_format_t color_format, const lv_area_t * area);
|
||||||
|
static uint32_t width_to_stride(uint32_t w, lv_color_format_t color_format);
|
||||||
|
static void * buf_go_to_xy(const void * buf, uint32_t stride, lv_color_format_t color_format, int32_t x,
|
||||||
|
int32_t y);
|
||||||
|
static void buf_clear(void * buf, uint32_t w, uint32_t h, lv_color_format_t color_format, const lv_area_t * a);
|
||||||
|
static void buf_copy(void * dest_buf, uint32_t dest_w, uint32_t dest_h, const lv_area_t * dest_area_to_copy,
|
||||||
|
void * src_buf, uint32_t src_w, uint32_t src_h, const lv_area_t * src_area_to_copy,
|
||||||
|
lv_color_format_t color_format);
|
||||||
|
|
||||||
|
/**********************
|
||||||
|
* STATIC VARIABLES
|
||||||
|
**********************/
|
||||||
|
|
||||||
|
/**********************
|
||||||
|
* MACROS
|
||||||
|
**********************/
|
||||||
|
|
||||||
|
/**********************
|
||||||
|
* GLOBAL FUNCTIONS
|
||||||
|
**********************/
|
||||||
|
|
||||||
|
void lv_draw_buf_vg_lite_init_handlers(void)
|
||||||
|
{
|
||||||
|
lv_draw_buf_handlers_t * handlers = lv_draw_buf_get_handlers();
|
||||||
|
|
||||||
|
handlers->buf_malloc_cb = buf_malloc;
|
||||||
|
handlers->buf_free_cb = buf_free;
|
||||||
|
handlers->align_pointer_cb = buf_align;
|
||||||
|
handlers->invalidate_cache_cb = invalidate_cache;
|
||||||
|
handlers->width_to_stride_cb = width_to_stride;
|
||||||
|
handlers->go_to_xy_cb = buf_go_to_xy;
|
||||||
|
handlers->buf_clear_cb = buf_clear;
|
||||||
|
handlers->buf_copy_cb = buf_copy;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**********************
|
||||||
|
* STATIC FUNCTIONS
|
||||||
|
**********************/
|
||||||
|
|
||||||
|
static void * buf_malloc(size_t size_bytes, lv_color_format_t color_format)
|
||||||
|
{
|
||||||
|
LV_UNUSED(color_format);
|
||||||
|
size_bytes = LV_VG_LITE_ALIGN(size_bytes, LV_VG_LITE_BUF_ALIGN);
|
||||||
|
return aligned_alloc(LV_VG_LITE_BUF_ALIGN, size_bytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void buf_free(void * buf)
|
||||||
|
{
|
||||||
|
free(buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void * buf_align(void * buf, lv_color_format_t color_format)
|
||||||
|
{
|
||||||
|
LV_UNUSED(color_format);
|
||||||
|
return (void *)LV_VG_LITE_ALIGN((lv_uintptr_t)buf, LV_VG_LITE_BUF_ALIGN);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void invalidate_cache(void * buf, uint32_t stride, lv_color_format_t color_format, const lv_area_t * area)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint32_t width_to_stride(uint32_t w, lv_color_format_t color_format)
|
||||||
|
{
|
||||||
|
return lv_vg_lite_width_to_stride(w, lv_vg_lite_vg_fmt(color_format));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void * buf_go_to_xy(const void * buf, uint32_t stride, lv_color_format_t color_format, int32_t x,
|
||||||
|
int32_t y)
|
||||||
|
{
|
||||||
|
const uint8_t * buf_tmp = buf;
|
||||||
|
buf_tmp += stride * y;
|
||||||
|
buf_tmp += x * lv_color_format_get_size(color_format);
|
||||||
|
|
||||||
|
return (void *)buf_tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void buf_clear(void * buf, uint32_t w, uint32_t h, lv_color_format_t color_format, const lv_area_t * a)
|
||||||
|
{
|
||||||
|
#if 0
|
||||||
|
if(LV_VG_LITE_IS_ALIGNED(buf, LV_VG_LITE_BUF_ALIGN)) {
|
||||||
|
/* finish outstanding buffers */
|
||||||
|
LV_VG_LITE_CHECK_ERROR(vg_lite_finish());
|
||||||
|
|
||||||
|
vg_lite_buffer_t dest_buf;
|
||||||
|
LV_ASSERT(lv_vg_lite_buffer_init(&dest_buf, buf, w, h, lv_vg_lite_vg_fmt(color_format), false));
|
||||||
|
LV_VG_LITE_ASSERT_DEST_BUFFER(&dest_buf);
|
||||||
|
|
||||||
|
vg_lite_rectangle_t rect;
|
||||||
|
lv_vg_lite_rect(&rect, a);
|
||||||
|
LV_VG_LITE_CHECK_ERROR(vg_lite_clear(&dest_buf, &rect, 0));
|
||||||
|
LV_VG_LITE_CHECK_ERROR(vg_lite_finish());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
uint8_t px_size = lv_color_format_get_size(color_format);
|
||||||
|
uint32_t stride = lv_draw_buf_width_to_stride(w, color_format);
|
||||||
|
uint8_t * bufc = buf;
|
||||||
|
|
||||||
|
/*Got the first pixel of each buffer*/
|
||||||
|
bufc += stride * a->y1;
|
||||||
|
bufc += a->x1 * px_size;
|
||||||
|
|
||||||
|
uint32_t line_length = lv_area_get_width(a) * px_size;
|
||||||
|
int32_t y;
|
||||||
|
for(y = a->y1; y <= a->y2; y++) {
|
||||||
|
lv_memzero(bufc, line_length);
|
||||||
|
bufc += stride;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void buf_copy(void * dest_buf, uint32_t dest_w, uint32_t dest_h, const lv_area_t * dest_area_to_copy,
|
||||||
|
void * src_buf, uint32_t src_w, uint32_t src_h, const lv_area_t * src_area_to_copy,
|
||||||
|
lv_color_format_t color_format)
|
||||||
|
{
|
||||||
|
#if 0
|
||||||
|
if(LV_VG_LITE_IS_ALIGNED(dest_buf, LV_VG_LITE_BUF_ALIGN)
|
||||||
|
&& LV_VG_LITE_IS_ALIGNED(src_buf, LV_VG_LITE_BUF_ALIGN)) {
|
||||||
|
vg_lite_buffer_t dest;
|
||||||
|
LV_ASSERT(lv_vg_lite_buffer_init(&dest, dest_buf, dest_w, dest_h, lv_vg_lite_vg_fmt(color_format), false));
|
||||||
|
LV_VG_LITE_ASSERT_DEST_BUFFER(&dest);
|
||||||
|
|
||||||
|
vg_lite_buffer_t src;
|
||||||
|
LV_ASSERT(lv_vg_lite_buffer_init(&src, src_buf, src_w, src_h, lv_vg_lite_vg_fmt(color_format), false));
|
||||||
|
LV_VG_LITE_ASSERT_SRC_BUFFER(&src);
|
||||||
|
|
||||||
|
vg_lite_rectangle_t src_rect;
|
||||||
|
lv_vg_lite_rect(&src_rect, src_area_to_copy);
|
||||||
|
|
||||||
|
vg_lite_matrix_t matrix;
|
||||||
|
vg_lite_identity(&matrix);
|
||||||
|
|
||||||
|
LV_VG_LITE_CHECK_ERROR(vg_lite_blit_rect(&dest, &src,
|
||||||
|
&src_rect,
|
||||||
|
&matrix,
|
||||||
|
VG_LITE_BLEND_NONE, 0,
|
||||||
|
VG_LITE_FILTER_POINT));
|
||||||
|
LV_VG_LITE_CHECK_ERROR(vg_lite_finish());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
uint8_t px_size = lv_color_format_get_size(color_format);
|
||||||
|
uint8_t * dest_bufc = dest_buf;
|
||||||
|
uint8_t * src_bufc = src_buf;
|
||||||
|
|
||||||
|
uint32_t dest_stride = lv_draw_buf_width_to_stride(dest_w, color_format);
|
||||||
|
uint32_t src_stride = lv_draw_buf_width_to_stride(src_w, color_format);
|
||||||
|
|
||||||
|
/*Got the first pixel of each buffer*/
|
||||||
|
dest_bufc += dest_stride * dest_area_to_copy->y1;
|
||||||
|
dest_bufc += dest_area_to_copy->x1 * px_size;
|
||||||
|
|
||||||
|
src_bufc += src_stride * src_area_to_copy->y1;
|
||||||
|
src_bufc += src_area_to_copy->x1 * px_size;
|
||||||
|
|
||||||
|
uint32_t line_length = lv_area_get_width(dest_area_to_copy) * px_size;
|
||||||
|
int32_t y;
|
||||||
|
for(y = dest_area_to_copy->y1; y <= dest_area_to_copy->y2; y++) {
|
||||||
|
lv_memcpy(dest_bufc, src_bufc, line_length);
|
||||||
|
dest_bufc += dest_stride;
|
||||||
|
src_bufc += src_stride;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /*LV_USE_DRAW_VG_LITE*/
|
||||||
241
src/draw/vg_lite/lv_draw_vg_lite.c
Normal file
241
src/draw/vg_lite/lv_draw_vg_lite.c
Normal file
@@ -0,0 +1,241 @@
|
|||||||
|
/**
|
||||||
|
* @file lv_vg_lite_draw.c
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*********************
|
||||||
|
* INCLUDES
|
||||||
|
*********************/
|
||||||
|
|
||||||
|
#include "lv_draw_vg_lite.h"
|
||||||
|
|
||||||
|
#if LV_USE_DRAW_VG_LITE
|
||||||
|
|
||||||
|
#include "../lv_draw.h"
|
||||||
|
#include "lv_draw_vg_lite_type.h"
|
||||||
|
#include "lv_vg_lite_path.h"
|
||||||
|
#include "lv_vg_lite_utils.h"
|
||||||
|
#include "lv_vg_lite_decoder.h"
|
||||||
|
|
||||||
|
/*********************
|
||||||
|
* DEFINES
|
||||||
|
*********************/
|
||||||
|
|
||||||
|
#define VG_LITE_DRAW_UNIT_ID 2
|
||||||
|
|
||||||
|
/**********************
|
||||||
|
* TYPEDEFS
|
||||||
|
**********************/
|
||||||
|
|
||||||
|
/**********************
|
||||||
|
* STATIC PROTOTYPES
|
||||||
|
**********************/
|
||||||
|
|
||||||
|
static int32_t draw_dispatch(lv_draw_unit_t * draw_unit, lv_layer_t * layer);
|
||||||
|
|
||||||
|
static int32_t draw_evaluate(lv_draw_unit_t * draw_unit, lv_draw_task_t * task);
|
||||||
|
|
||||||
|
static int32_t draw_delete(lv_draw_unit_t * draw_unit);
|
||||||
|
|
||||||
|
/**********************
|
||||||
|
* STATIC VARIABLES
|
||||||
|
**********************/
|
||||||
|
|
||||||
|
/**********************
|
||||||
|
* MACROS
|
||||||
|
**********************/
|
||||||
|
|
||||||
|
/**********************
|
||||||
|
* GLOBAL FUNCTIONS
|
||||||
|
**********************/
|
||||||
|
|
||||||
|
void lv_draw_vg_lite_init(void)
|
||||||
|
{
|
||||||
|
#if LV_VG_LITE_USE_GPU_INIT
|
||||||
|
extern void gpu_init(void);
|
||||||
|
static bool inited = false;
|
||||||
|
if(!inited) {
|
||||||
|
gpu_init();
|
||||||
|
inited = true;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
lv_vg_lite_dump_info();
|
||||||
|
|
||||||
|
lv_draw_buf_vg_lite_init_handlers();
|
||||||
|
|
||||||
|
lv_draw_vg_lite_unit_t * unit = lv_draw_create_unit(sizeof(lv_draw_vg_lite_unit_t));
|
||||||
|
unit->base_unit.dispatch_cb = draw_dispatch;
|
||||||
|
unit->base_unit.evaluate_cb = draw_evaluate;
|
||||||
|
unit->base_unit.delete_cb = draw_delete;
|
||||||
|
|
||||||
|
lv_vg_lite_path_init(unit);
|
||||||
|
|
||||||
|
lv_vg_lite_decoder_init();
|
||||||
|
}
|
||||||
|
|
||||||
|
void lv_draw_vg_lite_deinit(void)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/**********************
|
||||||
|
* STATIC FUNCTIONS
|
||||||
|
**********************/
|
||||||
|
|
||||||
|
static void draw_execute(lv_draw_vg_lite_unit_t * u)
|
||||||
|
{
|
||||||
|
lv_draw_task_t * t = u->task_act;
|
||||||
|
lv_draw_unit_t * draw_unit = (lv_draw_unit_t *)u;
|
||||||
|
|
||||||
|
lv_layer_t * layer = u->base_unit.target_layer;
|
||||||
|
|
||||||
|
lv_vg_lite_buffer_init(
|
||||||
|
&u->target_buffer,
|
||||||
|
layer->buf,
|
||||||
|
lv_area_get_width(&layer->buf_area),
|
||||||
|
lv_area_get_height(&layer->buf_area),
|
||||||
|
lv_vg_lite_vg_fmt(layer->color_format),
|
||||||
|
false);
|
||||||
|
|
||||||
|
vg_lite_identity(&u->global_matrix);
|
||||||
|
vg_lite_translate(-layer->buf_area.x1, -layer->buf_area.y1, &u->global_matrix);
|
||||||
|
|
||||||
|
switch(t->type) {
|
||||||
|
case LV_DRAW_TASK_TYPE_LABEL:
|
||||||
|
lv_draw_vg_lite_label(draw_unit, t->draw_dsc, &t->area);
|
||||||
|
break;
|
||||||
|
case LV_DRAW_TASK_TYPE_FILL:
|
||||||
|
lv_draw_vg_lite_fill(draw_unit, t->draw_dsc, &t->area);
|
||||||
|
break;
|
||||||
|
case LV_DRAW_TASK_TYPE_BORDER:
|
||||||
|
lv_draw_vg_lite_border(draw_unit, t->draw_dsc, &t->area);
|
||||||
|
break;
|
||||||
|
case LV_DRAW_TASK_TYPE_BOX_SHADOW:
|
||||||
|
lv_draw_vg_lite_box_shadow(draw_unit, t->draw_dsc, &t->area);
|
||||||
|
break;
|
||||||
|
case LV_DRAW_TASK_TYPE_IMAGE:
|
||||||
|
lv_draw_vg_lite_img(draw_unit, t->draw_dsc, &t->area);
|
||||||
|
break;
|
||||||
|
case LV_DRAW_TASK_TYPE_ARC:
|
||||||
|
lv_draw_vg_lite_arc(draw_unit, t->draw_dsc, &t->area);
|
||||||
|
break;
|
||||||
|
case LV_DRAW_TASK_TYPE_LINE:
|
||||||
|
lv_draw_vg_lite_line(draw_unit, t->draw_dsc);
|
||||||
|
break;
|
||||||
|
case LV_DRAW_TASK_TYPE_LAYER:
|
||||||
|
lv_draw_vg_lite_layer(draw_unit, t->draw_dsc, &t->area);
|
||||||
|
break;
|
||||||
|
case LV_DRAW_TASK_TYPE_TRIANGLE:
|
||||||
|
lv_draw_vg_lite_triangle(draw_unit, t->draw_dsc);
|
||||||
|
break;
|
||||||
|
case LV_DRAW_TASK_TYPE_MASK_RECTANGLE:
|
||||||
|
lv_draw_vg_lite_mask_rect(draw_unit, t->draw_dsc, &t->area);
|
||||||
|
break;
|
||||||
|
#if LV_USE_VECTOR_GRAPHIC
|
||||||
|
case LV_DRAW_TASK_TYPE_VECTOR:
|
||||||
|
lv_draw_vg_lite_vector(draw_unit, t->draw_dsc);
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if LV_USE_PARALLEL_DRAW_DEBUG
|
||||||
|
/* Layers manage it for themselves. */
|
||||||
|
if(t->type != LV_DRAW_TASK_TYPE_LAYER) {
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
LV_VG_LITE_CHECK_ERROR(vg_lite_finish());
|
||||||
|
}
|
||||||
|
|
||||||
|
static int32_t draw_dispatch(lv_draw_unit_t * draw_unit, lv_layer_t * layer)
|
||||||
|
{
|
||||||
|
lv_draw_vg_lite_unit_t * draw_vg_lite_unit = (lv_draw_vg_lite_unit_t *)draw_unit;
|
||||||
|
|
||||||
|
/* Return immediately if it's busy with draw task. */
|
||||||
|
if(draw_vg_lite_unit->task_act) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Return if target buffer format is not supported. */
|
||||||
|
if(!lv_vg_lite_is_dest_cf_supported(layer->color_format)) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Try to get an ready to draw. */
|
||||||
|
lv_draw_task_t * t = lv_draw_get_next_available_task(layer, NULL, VG_LITE_DRAW_UNIT_ID);
|
||||||
|
|
||||||
|
/* Return 0 is no selection, some tasks can be supported by other units. */
|
||||||
|
if(!t || t->preferred_draw_unit_id != VG_LITE_DRAW_UNIT_ID) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void * buf = lv_draw_layer_alloc_buf(layer);
|
||||||
|
if(!buf) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
t->state = LV_DRAW_TASK_STATE_IN_PROGRESS;
|
||||||
|
draw_vg_lite_unit->base_unit.target_layer = layer;
|
||||||
|
draw_vg_lite_unit->base_unit.clip_area = &t->clip_area;
|
||||||
|
draw_vg_lite_unit->task_act = t;
|
||||||
|
|
||||||
|
draw_execute(draw_vg_lite_unit);
|
||||||
|
|
||||||
|
draw_vg_lite_unit->task_act->state = LV_DRAW_TASK_STATE_READY;
|
||||||
|
draw_vg_lite_unit->task_act = NULL;
|
||||||
|
|
||||||
|
/* The draw unit is free now. Request a new dispatching as it can get a new task. */
|
||||||
|
lv_draw_dispatch_request();
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int32_t draw_evaluate(lv_draw_unit_t * draw_unit, lv_draw_task_t * task)
|
||||||
|
{
|
||||||
|
LV_UNUSED(draw_unit);
|
||||||
|
|
||||||
|
switch(task->type) {
|
||||||
|
#if LV_USE_FREETYPE && LV_FREETYPE_CACHE_TYPE == LV_FREETYPE_CACHE_TYPE_OUTLINE
|
||||||
|
case LV_DRAW_TASK_TYPE_LABEL: {
|
||||||
|
const lv_draw_label_dsc_t * label_dsc = task->draw_dsc;
|
||||||
|
if(lv_freetype_is_outline_font(label_dsc->font)) {
|
||||||
|
task->preference_score = 0;
|
||||||
|
task->preferred_draw_unit_id = VG_LITE_DRAW_UNIT_ID;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
case LV_DRAW_TASK_TYPE_FILL:
|
||||||
|
case LV_DRAW_TASK_TYPE_BORDER:
|
||||||
|
case LV_DRAW_TASK_TYPE_BOX_SHADOW:
|
||||||
|
case LV_DRAW_TASK_TYPE_IMAGE:
|
||||||
|
case LV_DRAW_TASK_TYPE_LAYER:
|
||||||
|
case LV_DRAW_TASK_TYPE_LINE:
|
||||||
|
case LV_DRAW_TASK_TYPE_ARC:
|
||||||
|
case LV_DRAW_TASK_TYPE_TRIANGLE:
|
||||||
|
// case LV_DRAW_TASK_TYPE_MASK_RECTANGLE:
|
||||||
|
// case LV_DRAW_TASK_TYPE_MASK_BITMAP:
|
||||||
|
#if LV_USE_VECTOR_GRAPHIC
|
||||||
|
case LV_DRAW_TASK_TYPE_VECTOR:
|
||||||
|
#endif
|
||||||
|
task->preference_score = 80;
|
||||||
|
task->preferred_draw_unit_id = VG_LITE_DRAW_UNIT_ID;
|
||||||
|
return 1;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int32_t draw_delete(lv_draw_unit_t * draw_unit)
|
||||||
|
{
|
||||||
|
lv_draw_vg_lite_unit_t * unit = (lv_draw_vg_lite_unit_t *)draw_unit;
|
||||||
|
lv_vg_lite_path_deinit(unit);
|
||||||
|
lv_vg_lite_decoder_deinit();
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /*LV_USE_DRAW_VG_LITE*/
|
||||||
84
src/draw/vg_lite/lv_draw_vg_lite.h
Normal file
84
src/draw/vg_lite/lv_draw_vg_lite.h
Normal file
@@ -0,0 +1,84 @@
|
|||||||
|
/**
|
||||||
|
* @file lv_vg_lite_draw.h
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef LV_VG_LITE_DRAW_H
|
||||||
|
#define LV_VG_LITE_DRAW_H
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*********************
|
||||||
|
* INCLUDES
|
||||||
|
*********************/
|
||||||
|
|
||||||
|
#include "../../lv_conf_internal.h"
|
||||||
|
|
||||||
|
#if LV_USE_DRAW_VG_LITE
|
||||||
|
|
||||||
|
#include "../lv_draw.h"
|
||||||
|
#include "../../draw/lv_draw_vector.h"
|
||||||
|
|
||||||
|
/*********************
|
||||||
|
* DEFINES
|
||||||
|
*********************/
|
||||||
|
|
||||||
|
/**********************
|
||||||
|
* TYPEDEFS
|
||||||
|
**********************/
|
||||||
|
|
||||||
|
/**********************
|
||||||
|
* GLOBAL PROTOTYPES
|
||||||
|
**********************/
|
||||||
|
|
||||||
|
void lv_draw_buf_vg_lite_init_handlers(void);
|
||||||
|
|
||||||
|
void lv_draw_vg_lite_init(void);
|
||||||
|
|
||||||
|
void lv_draw_vg_lite_deinit(void);
|
||||||
|
|
||||||
|
void lv_draw_vg_lite_arc(lv_draw_unit_t * draw_unit, const lv_draw_arc_dsc_t * dsc,
|
||||||
|
const lv_area_t * coords);
|
||||||
|
|
||||||
|
void lv_draw_vg_lite_box_shadow(lv_draw_unit_t * draw_unit, const lv_draw_box_shadow_dsc_t * dsc,
|
||||||
|
const lv_area_t * coords);
|
||||||
|
|
||||||
|
void lv_draw_vg_lite_border(lv_draw_unit_t * draw_unit, const lv_draw_border_dsc_t * dsc,
|
||||||
|
const lv_area_t * coords);
|
||||||
|
|
||||||
|
void lv_draw_vg_lite_fill(lv_draw_unit_t * draw_unit, const lv_draw_fill_dsc_t * dsc,
|
||||||
|
const lv_area_t * coords);
|
||||||
|
|
||||||
|
void lv_draw_vg_lite_img(lv_draw_unit_t * draw_unit, const lv_draw_image_dsc_t * dsc,
|
||||||
|
const lv_area_t * coords);
|
||||||
|
|
||||||
|
void lv_draw_vg_lite_label(lv_draw_unit_t * draw_unit, const lv_draw_label_dsc_t * dsc,
|
||||||
|
const lv_area_t * coords);
|
||||||
|
|
||||||
|
void lv_draw_vg_lite_layer(lv_draw_unit_t * draw_unit, const lv_draw_image_dsc_t * draw_dsc,
|
||||||
|
const lv_area_t * coords);
|
||||||
|
|
||||||
|
void lv_draw_vg_lite_line(lv_draw_unit_t * draw_unit, const lv_draw_line_dsc_t * dsc);
|
||||||
|
|
||||||
|
void lv_draw_vg_lite_triangle(lv_draw_unit_t * draw_unit, const lv_draw_triangle_dsc_t * dsc);
|
||||||
|
|
||||||
|
void lv_draw_vg_lite_mask_rect(lv_draw_unit_t * draw_unit, const lv_draw_mask_rect_dsc_t * dsc,
|
||||||
|
const lv_area_t * coords);
|
||||||
|
|
||||||
|
#if LV_USE_VECTOR_GRAPHIC
|
||||||
|
void lv_draw_vg_lite_vector(lv_draw_unit_t * draw_unit, const lv_draw_vector_task_dsc_t * dsc);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**********************
|
||||||
|
* MACROS
|
||||||
|
**********************/
|
||||||
|
|
||||||
|
#endif /*LV_USE_DRAW_VG_LITE*/
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
} /*extern "C"*/
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /*LV_VG_LITE_DRAW_H*/
|
||||||
200
src/draw/vg_lite/lv_draw_vg_lite_arc.c
Normal file
200
src/draw/vg_lite/lv_draw_vg_lite_arc.c
Normal file
@@ -0,0 +1,200 @@
|
|||||||
|
/**
|
||||||
|
* @file lv_draw_vg_lite_arc.c
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*********************
|
||||||
|
* INCLUDES
|
||||||
|
*********************/
|
||||||
|
|
||||||
|
#include "lv_draw_vg_lite.h"
|
||||||
|
|
||||||
|
#if LV_USE_DRAW_VG_LITE
|
||||||
|
|
||||||
|
#include "lv_draw_vg_lite_type.h"
|
||||||
|
#include "lv_vg_lite_math.h"
|
||||||
|
#include "lv_vg_lite_path.h"
|
||||||
|
#include "lv_vg_lite_utils.h"
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
|
/*********************
|
||||||
|
* DEFINES
|
||||||
|
*********************/
|
||||||
|
|
||||||
|
#define PI 3.1415926535897932384626433832795
|
||||||
|
#define TWO_PI 6.283185307179586476925286766559
|
||||||
|
#define DEG_TO_RAD 0.017453292519943295769236907684886
|
||||||
|
#define RAD_TO_DEG 57.295779513082320876798154814105
|
||||||
|
#define radians(deg) ((deg) * DEG_TO_RAD)
|
||||||
|
#define degrees(rad) ((rad) * RAD_TO_DEG)
|
||||||
|
|
||||||
|
/**********************
|
||||||
|
* TYPEDEFS
|
||||||
|
**********************/
|
||||||
|
|
||||||
|
/**********************
|
||||||
|
* STATIC PROTOTYPES
|
||||||
|
**********************/
|
||||||
|
|
||||||
|
/**********************
|
||||||
|
* STATIC VARIABLES
|
||||||
|
**********************/
|
||||||
|
|
||||||
|
/**********************
|
||||||
|
* MACROS
|
||||||
|
**********************/
|
||||||
|
|
||||||
|
/**********************
|
||||||
|
* GLOBAL FUNCTIONS
|
||||||
|
**********************/
|
||||||
|
|
||||||
|
void lv_draw_vg_lite_arc(lv_draw_unit_t * draw_unit, const lv_draw_arc_dsc_t * dsc,
|
||||||
|
const lv_area_t * coords)
|
||||||
|
{
|
||||||
|
if(dsc->opa <= LV_OPA_MIN)
|
||||||
|
return;
|
||||||
|
if(dsc->width <= 0)
|
||||||
|
return;
|
||||||
|
if(dsc->start_angle == dsc->end_angle)
|
||||||
|
return;
|
||||||
|
|
||||||
|
lv_draw_vg_lite_unit_t * u = (lv_draw_vg_lite_unit_t *)draw_unit;
|
||||||
|
|
||||||
|
lv_area_t clip_area;
|
||||||
|
if(!_lv_area_intersect(&clip_area, coords, draw_unit->clip_area)) {
|
||||||
|
/*Fully clipped, nothing to do*/
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
float start_angle = dsc->start_angle;
|
||||||
|
float end_angle = dsc->end_angle;
|
||||||
|
float sweep_angle = end_angle - start_angle;
|
||||||
|
|
||||||
|
while(sweep_angle < 0) {
|
||||||
|
sweep_angle += 360;
|
||||||
|
}
|
||||||
|
|
||||||
|
while(sweep_angle > 360) {
|
||||||
|
sweep_angle -= 360;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*If the angles are the same then there is nothing to draw*/
|
||||||
|
if(math_zero(sweep_angle)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
lv_vg_lite_path_t * path = lv_vg_lite_path_get(u, VG_LITE_FP32);
|
||||||
|
lv_vg_lite_path_set_quality(path, VG_LITE_HIGH);
|
||||||
|
lv_vg_lite_path_set_bonding_box_area(path, &clip_area);
|
||||||
|
|
||||||
|
float radius_out = dsc->radius;
|
||||||
|
float radius_in = dsc->radius - dsc->width;
|
||||||
|
float half_width = dsc->width * 0.5f;
|
||||||
|
float radius_center = radius_out - half_width;
|
||||||
|
float cx = dsc->center.x;
|
||||||
|
float cy = dsc->center.y;
|
||||||
|
|
||||||
|
vg_lite_fill_t fill = VG_LITE_FILL_NON_ZERO;
|
||||||
|
|
||||||
|
if(math_equal(sweep_angle, 360)) {
|
||||||
|
lv_vg_lite_path_append_circle(path, cx, cy, radius_out, radius_out);
|
||||||
|
lv_vg_lite_path_append_circle(path, cx, cy, radius_in, radius_in);
|
||||||
|
fill = VG_LITE_FILL_EVEN_ODD;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
/* radius_out start point */
|
||||||
|
float start_angle_rad = MATH_RADIANS(start_angle);
|
||||||
|
float start_x = radius_out * MATH_COSF(start_angle_rad) + cx;
|
||||||
|
float start_y = radius_out * MATH_SINF(start_angle_rad) + cy;
|
||||||
|
|
||||||
|
/* radius_in start point */
|
||||||
|
float end_angle_rad = MATH_RADIANS(end_angle);
|
||||||
|
float end_x = radius_in * MATH_COSF(end_angle_rad) + cx;
|
||||||
|
float end_y = radius_in * MATH_SINF(end_angle_rad) + cy;
|
||||||
|
|
||||||
|
/* radius_out arc */
|
||||||
|
lv_vg_lite_path_append_arc(path,
|
||||||
|
cx, cy,
|
||||||
|
radius_out,
|
||||||
|
start_angle,
|
||||||
|
sweep_angle,
|
||||||
|
false);
|
||||||
|
|
||||||
|
/* line to radius_in */
|
||||||
|
lv_vg_lite_path_line_to(path, end_x, end_y);
|
||||||
|
|
||||||
|
/* radius_in arc */
|
||||||
|
lv_vg_lite_path_append_arc(path,
|
||||||
|
cx, cy,
|
||||||
|
radius_in,
|
||||||
|
end_angle,
|
||||||
|
-sweep_angle,
|
||||||
|
false);
|
||||||
|
|
||||||
|
/* close arc */
|
||||||
|
lv_vg_lite_path_line_to(path, start_x, start_y);
|
||||||
|
lv_vg_lite_path_close(path);
|
||||||
|
|
||||||
|
/* draw round */
|
||||||
|
if(dsc->rounded && half_width > 0) {
|
||||||
|
float rcx1 = cx + radius_center * MATH_COSF(end_angle_rad);
|
||||||
|
float rcy1 = cy + radius_center * MATH_SINF(end_angle_rad);
|
||||||
|
lv_vg_lite_path_append_circle(path, rcx1, rcy1, half_width, half_width);
|
||||||
|
|
||||||
|
float rcx2 = cx + radius_center * MATH_COSF(start_angle_rad);
|
||||||
|
float rcy2 = cy + radius_center * MATH_SINF(start_angle_rad);
|
||||||
|
lv_vg_lite_path_append_circle(path, rcx2, rcy2, half_width, half_width);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
lv_vg_lite_path_end(path);
|
||||||
|
|
||||||
|
vg_lite_matrix_t matrix;
|
||||||
|
vg_lite_identity(&matrix);
|
||||||
|
lv_vg_lite_matrix_multiply(&matrix, &u->global_matrix);
|
||||||
|
|
||||||
|
vg_lite_color_t color = lv_vg_lite_color(dsc->color, dsc->opa, true);
|
||||||
|
|
||||||
|
vg_lite_path_t * vg_lite_path = lv_vg_lite_path_get_path(path);
|
||||||
|
|
||||||
|
LV_VG_LITE_ASSERT_DEST_BUFFER(&u->target_buffer);
|
||||||
|
LV_VG_LITE_ASSERT_PATH(vg_lite_path);
|
||||||
|
|
||||||
|
LV_VG_LITE_CHECK_ERROR(vg_lite_draw(
|
||||||
|
&u->target_buffer,
|
||||||
|
vg_lite_path,
|
||||||
|
fill,
|
||||||
|
&matrix,
|
||||||
|
VG_LITE_BLEND_SRC_OVER,
|
||||||
|
color));
|
||||||
|
|
||||||
|
if(dsc->img_src) {
|
||||||
|
vg_lite_buffer_t src_buf;
|
||||||
|
lv_image_decoder_dsc_t decoder_dsc;
|
||||||
|
if(lv_vg_lite_buffer_open_image(&src_buf, &decoder_dsc, dsc->img_src)) {
|
||||||
|
vg_lite_matrix_t path_matrix;
|
||||||
|
vg_lite_identity(&path_matrix);
|
||||||
|
LV_VG_LITE_CHECK_ERROR(vg_lite_draw_pattern(
|
||||||
|
&u->target_buffer,
|
||||||
|
vg_lite_path,
|
||||||
|
fill,
|
||||||
|
&path_matrix,
|
||||||
|
&src_buf,
|
||||||
|
&matrix,
|
||||||
|
VG_LITE_BLEND_SRC_OVER,
|
||||||
|
VG_LITE_PATTERN_COLOR,
|
||||||
|
0,
|
||||||
|
color,
|
||||||
|
VG_LITE_FILTER_BI_LINEAR));
|
||||||
|
lv_image_decoder_close(&decoder_dsc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
lv_vg_lite_path_drop(u, path);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**********************
|
||||||
|
* STATIC FUNCTIONS
|
||||||
|
**********************/
|
||||||
|
|
||||||
|
#endif /*LV_USE_DRAW_VG_LITE*/
|
||||||
115
src/draw/vg_lite/lv_draw_vg_lite_border.c
Normal file
115
src/draw/vg_lite/lv_draw_vg_lite_border.c
Normal file
@@ -0,0 +1,115 @@
|
|||||||
|
/**
|
||||||
|
* @file lv_draw_vg_lite_border.c
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*********************
|
||||||
|
* INCLUDES
|
||||||
|
*********************/
|
||||||
|
|
||||||
|
#include "lv_draw_vg_lite.h"
|
||||||
|
|
||||||
|
#if LV_USE_DRAW_VG_LITE
|
||||||
|
|
||||||
|
#include "lv_draw_vg_lite_type.h"
|
||||||
|
#include "lv_vg_lite_utils.h"
|
||||||
|
#include "lv_vg_lite_path.h"
|
||||||
|
|
||||||
|
/*********************
|
||||||
|
* DEFINES
|
||||||
|
*********************/
|
||||||
|
|
||||||
|
/**********************
|
||||||
|
* TYPEDEFS
|
||||||
|
**********************/
|
||||||
|
|
||||||
|
/**********************
|
||||||
|
* STATIC PROTOTYPES
|
||||||
|
**********************/
|
||||||
|
|
||||||
|
/**********************
|
||||||
|
* STATIC VARIABLES
|
||||||
|
**********************/
|
||||||
|
|
||||||
|
/**********************
|
||||||
|
* MACROS
|
||||||
|
**********************/
|
||||||
|
|
||||||
|
/**********************
|
||||||
|
* GLOBAL FUNCTIONS
|
||||||
|
**********************/
|
||||||
|
|
||||||
|
void lv_draw_vg_lite_border(lv_draw_unit_t * draw_unit, const lv_draw_border_dsc_t * dsc,
|
||||||
|
const lv_area_t * coords)
|
||||||
|
{
|
||||||
|
if(dsc->opa <= LV_OPA_MIN)
|
||||||
|
return;
|
||||||
|
if(dsc->width == 0)
|
||||||
|
return;
|
||||||
|
if(dsc->side == LV_BORDER_SIDE_NONE)
|
||||||
|
return;
|
||||||
|
|
||||||
|
lv_draw_vg_lite_unit_t * u = (lv_draw_vg_lite_unit_t *)draw_unit;
|
||||||
|
|
||||||
|
lv_area_t clip_area;
|
||||||
|
if(!_lv_area_intersect(&clip_area, coords, draw_unit->clip_area)) {
|
||||||
|
/*Fully clipped, nothing to do*/
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t w = lv_area_get_width(coords);
|
||||||
|
int32_t h = lv_area_get_height(coords);
|
||||||
|
int32_t r_out = dsc->radius;
|
||||||
|
if(r_out) {
|
||||||
|
int32_t r_short = LV_MIN(w, h) / 2;
|
||||||
|
r_out = LV_MIN(r_out, r_short);
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t border_w = dsc->width;
|
||||||
|
int32_t r_in = LV_MAX(0, r_out - border_w);
|
||||||
|
|
||||||
|
lv_vg_lite_path_t * path = lv_vg_lite_path_get(u, VG_LITE_S16);
|
||||||
|
lv_vg_lite_path_set_quality(path, dsc->radius == 0 ? VG_LITE_LOW : VG_LITE_HIGH);
|
||||||
|
lv_vg_lite_path_set_bonding_box_area(path, &clip_area);
|
||||||
|
|
||||||
|
/* outer rect */
|
||||||
|
lv_vg_lite_path_append_rect(path,
|
||||||
|
coords->x1, coords->y1,
|
||||||
|
w, h,
|
||||||
|
r_out, r_out);
|
||||||
|
|
||||||
|
/* inner rect */
|
||||||
|
lv_vg_lite_path_append_rect(path,
|
||||||
|
coords->x1 + border_w, coords->y1 + border_w,
|
||||||
|
w - border_w * 2, h - border_w * 2,
|
||||||
|
r_in, r_in);
|
||||||
|
|
||||||
|
lv_vg_lite_path_end(path);
|
||||||
|
|
||||||
|
vg_lite_matrix_t matrix;
|
||||||
|
vg_lite_identity(&matrix);
|
||||||
|
lv_vg_lite_matrix_multiply(&matrix, &u->global_matrix);
|
||||||
|
|
||||||
|
vg_lite_color_t color = lv_vg_lite_color(dsc->color, dsc->opa, true);
|
||||||
|
|
||||||
|
vg_lite_path_t * vg_lite_path = lv_vg_lite_path_get_path(path);
|
||||||
|
|
||||||
|
LV_VG_LITE_ASSERT_DEST_BUFFER(&u->target_buffer);
|
||||||
|
LV_VG_LITE_ASSERT_PATH(vg_lite_path);
|
||||||
|
|
||||||
|
LV_VG_LITE_CHECK_ERROR(vg_lite_draw(
|
||||||
|
&u->target_buffer,
|
||||||
|
vg_lite_path,
|
||||||
|
VG_LITE_FILL_EVEN_ODD,
|
||||||
|
&matrix,
|
||||||
|
VG_LITE_BLEND_SRC_OVER,
|
||||||
|
color));
|
||||||
|
|
||||||
|
lv_vg_lite_path_drop(u, path);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**********************
|
||||||
|
* STATIC FUNCTIONS
|
||||||
|
**********************/
|
||||||
|
|
||||||
|
#endif /*LV_USE_DRAW_VG_LITE*/
|
||||||
97
src/draw/vg_lite/lv_draw_vg_lite_box_shadow.c
Normal file
97
src/draw/vg_lite/lv_draw_vg_lite_box_shadow.c
Normal file
@@ -0,0 +1,97 @@
|
|||||||
|
/**
|
||||||
|
* @file lv_draw_vg_lite_box_shadow.c
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*********************
|
||||||
|
* INCLUDES
|
||||||
|
*********************/
|
||||||
|
|
||||||
|
#include "lv_draw_vg_lite.h"
|
||||||
|
|
||||||
|
#if LV_USE_DRAW_VG_LITE
|
||||||
|
|
||||||
|
#include "lv_draw_vg_lite_type.h"
|
||||||
|
|
||||||
|
/*********************
|
||||||
|
* DEFINES
|
||||||
|
*********************/
|
||||||
|
|
||||||
|
/**********************
|
||||||
|
* TYPEDEFS
|
||||||
|
**********************/
|
||||||
|
|
||||||
|
/**********************
|
||||||
|
* STATIC PROTOTYPES
|
||||||
|
**********************/
|
||||||
|
|
||||||
|
/**********************
|
||||||
|
* STATIC VARIABLES
|
||||||
|
**********************/
|
||||||
|
|
||||||
|
/**********************
|
||||||
|
* MACROS
|
||||||
|
**********************/
|
||||||
|
|
||||||
|
/**********************
|
||||||
|
* GLOBAL FUNCTIONS
|
||||||
|
**********************/
|
||||||
|
|
||||||
|
void lv_draw_vg_lite_box_shadow(lv_draw_unit_t * draw_unit, const lv_draw_box_shadow_dsc_t * dsc,
|
||||||
|
const lv_area_t * coords)
|
||||||
|
{
|
||||||
|
/*Calculate the rectangle which is blurred to get the shadow in `shadow_area`*/
|
||||||
|
lv_area_t core_area;
|
||||||
|
core_area.x1 = coords->x1 + dsc->ofs_x - dsc->spread;
|
||||||
|
core_area.x2 = coords->x2 + dsc->ofs_x + dsc->spread;
|
||||||
|
core_area.y1 = coords->y1 + dsc->ofs_y - dsc->spread;
|
||||||
|
core_area.y2 = coords->y2 + dsc->ofs_y + dsc->spread;
|
||||||
|
|
||||||
|
/*Calculate the bounding box of the shadow*/
|
||||||
|
lv_area_t shadow_area;
|
||||||
|
shadow_area.x1 = core_area.x1 - dsc->width / 2 - 1;
|
||||||
|
shadow_area.x2 = core_area.x2 + dsc->width / 2 + 1;
|
||||||
|
shadow_area.y1 = core_area.y1 - dsc->width / 2 - 1;
|
||||||
|
shadow_area.y2 = core_area.y2 + dsc->width / 2 + 1;
|
||||||
|
|
||||||
|
lv_opa_t opa = dsc->opa;
|
||||||
|
if(opa > LV_OPA_MAX) opa = LV_OPA_COVER;
|
||||||
|
|
||||||
|
/*Get clipped draw area which is the real draw area.
|
||||||
|
*It is always the same or inside `shadow_area`*/
|
||||||
|
lv_area_t draw_area;
|
||||||
|
if(!_lv_area_intersect(&draw_area, &shadow_area, draw_unit->clip_area)) return;
|
||||||
|
|
||||||
|
lv_draw_border_dsc_t border_dsc;
|
||||||
|
lv_draw_border_dsc_init(&border_dsc);
|
||||||
|
border_dsc.width = 3;
|
||||||
|
border_dsc.color = dsc->color;
|
||||||
|
border_dsc.radius = dsc->radius;
|
||||||
|
|
||||||
|
lv_area_move(&draw_area, dsc->ofs_x, dsc->ofs_y);
|
||||||
|
draw_area = core_area;
|
||||||
|
int32_t half_w = dsc->width / 2;
|
||||||
|
|
||||||
|
for(int32_t w = 0; w < half_w; w++) {
|
||||||
|
border_dsc.opa = lv_map(w, 0, half_w, dsc->opa / 4, LV_OPA_0);
|
||||||
|
border_dsc.radius++;
|
||||||
|
lv_area_increase(&draw_area, 1, 1);
|
||||||
|
lv_draw_vg_lite_border(draw_unit, &border_dsc, &draw_area);
|
||||||
|
|
||||||
|
/* fill center */
|
||||||
|
if(dsc->ofs_x || dsc->ofs_y) {
|
||||||
|
lv_draw_fill_dsc_t fill_dsc;
|
||||||
|
lv_draw_fill_dsc_init(&fill_dsc);
|
||||||
|
fill_dsc.radius = dsc->radius;
|
||||||
|
fill_dsc.opa = dsc->opa;
|
||||||
|
fill_dsc.color = dsc->color;
|
||||||
|
lv_draw_vg_lite_fill(draw_unit, &fill_dsc, &core_area);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**********************
|
||||||
|
* STATIC FUNCTIONS
|
||||||
|
**********************/
|
||||||
|
|
||||||
|
#endif /*LV_USE_DRAW_VG_LITE*/
|
||||||
111
src/draw/vg_lite/lv_draw_vg_lite_fill.c
Normal file
111
src/draw/vg_lite/lv_draw_vg_lite_fill.c
Normal file
@@ -0,0 +1,111 @@
|
|||||||
|
/**
|
||||||
|
* @file lv_draw_vg_lite_fill.c
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*********************
|
||||||
|
* INCLUDES
|
||||||
|
*********************/
|
||||||
|
|
||||||
|
#include "lv_draw_vg_lite.h"
|
||||||
|
|
||||||
|
#if LV_USE_DRAW_VG_LITE
|
||||||
|
|
||||||
|
#include "lv_draw_vg_lite_type.h"
|
||||||
|
#include "lv_vg_lite_path.h"
|
||||||
|
#include "lv_vg_lite_utils.h"
|
||||||
|
|
||||||
|
/*********************
|
||||||
|
* DEFINES
|
||||||
|
*********************/
|
||||||
|
|
||||||
|
#if LV_GRADIENT_MAX_STOPS > VLC_MAX_GRADIENT_STOPS
|
||||||
|
#error "LV_GRADIENT_MAX_STOPS must be equal or less than VLC_MAX_GRADIENT_STOPS"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**********************
|
||||||
|
* TYPEDEFS
|
||||||
|
**********************/
|
||||||
|
|
||||||
|
/**********************
|
||||||
|
* STATIC PROTOTYPES
|
||||||
|
**********************/
|
||||||
|
|
||||||
|
/**********************
|
||||||
|
* STATIC VARIABLES
|
||||||
|
**********************/
|
||||||
|
|
||||||
|
/**********************
|
||||||
|
* MACROS
|
||||||
|
**********************/
|
||||||
|
|
||||||
|
/**********************
|
||||||
|
* GLOBAL FUNCTIONS
|
||||||
|
**********************/
|
||||||
|
|
||||||
|
void lv_draw_vg_lite_fill(lv_draw_unit_t * draw_unit, const lv_draw_fill_dsc_t * dsc, const lv_area_t * coords)
|
||||||
|
{
|
||||||
|
if(dsc->opa <= LV_OPA_MIN) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
lv_draw_vg_lite_unit_t * u = (lv_draw_vg_lite_unit_t *)draw_unit;
|
||||||
|
|
||||||
|
lv_area_t clip_area;
|
||||||
|
if(!_lv_area_intersect(&clip_area, coords, draw_unit->clip_area)) {
|
||||||
|
/*Fully clipped, nothing to do*/
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
vg_lite_matrix_t matrix;
|
||||||
|
vg_lite_identity(&matrix);
|
||||||
|
lv_vg_lite_matrix_multiply(&matrix, &u->global_matrix);
|
||||||
|
|
||||||
|
int32_t w = lv_area_get_width(coords);
|
||||||
|
int32_t h = lv_area_get_height(coords);
|
||||||
|
int32_t r = dsc->radius;
|
||||||
|
if(r) {
|
||||||
|
int32_t r_short = LV_MIN(w, h) / 2;
|
||||||
|
r = LV_MIN(r, r_short);
|
||||||
|
}
|
||||||
|
|
||||||
|
lv_vg_lite_path_t * path = lv_vg_lite_path_get(u, VG_LITE_S16);
|
||||||
|
lv_vg_lite_path_set_quality(path, dsc->radius == 0 ? VG_LITE_LOW : VG_LITE_HIGH);
|
||||||
|
lv_vg_lite_path_set_bonding_box_area(path, &clip_area);
|
||||||
|
lv_vg_lite_path_append_rect(path, coords->x1, coords->y1, w, h, r, r);
|
||||||
|
lv_vg_lite_path_end(path);
|
||||||
|
|
||||||
|
vg_lite_path_t * vg_lite_path = lv_vg_lite_path_get_path(path);
|
||||||
|
|
||||||
|
LV_VG_LITE_ASSERT_DEST_BUFFER(&u->target_buffer);
|
||||||
|
LV_VG_LITE_ASSERT_PATH(vg_lite_path);
|
||||||
|
|
||||||
|
if(dsc->grad.dir != LV_GRAD_DIR_NONE) {
|
||||||
|
lv_vg_lite_draw_linear_grad(
|
||||||
|
&u->target_buffer,
|
||||||
|
vg_lite_path,
|
||||||
|
coords,
|
||||||
|
&dsc->grad,
|
||||||
|
&matrix,
|
||||||
|
VG_LITE_FILL_EVEN_ODD,
|
||||||
|
VG_LITE_BLEND_SRC_OVER);
|
||||||
|
}
|
||||||
|
else { /* normal fill */
|
||||||
|
vg_lite_color_t color = lv_vg_lite_color(dsc->color, dsc->opa, true);
|
||||||
|
LV_VG_LITE_CHECK_ERROR(vg_lite_draw(
|
||||||
|
&u->target_buffer,
|
||||||
|
vg_lite_path,
|
||||||
|
VG_LITE_FILL_EVEN_ODD,
|
||||||
|
&matrix,
|
||||||
|
VG_LITE_BLEND_SRC_OVER,
|
||||||
|
color));
|
||||||
|
}
|
||||||
|
|
||||||
|
lv_vg_lite_path_drop(u, path);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**********************
|
||||||
|
* STATIC FUNCTIONS
|
||||||
|
**********************/
|
||||||
|
|
||||||
|
#endif /*LV_USE_DRAW_VG_LITE*/
|
||||||
155
src/draw/vg_lite/lv_draw_vg_lite_img.c
Normal file
155
src/draw/vg_lite/lv_draw_vg_lite_img.c
Normal file
@@ -0,0 +1,155 @@
|
|||||||
|
/**
|
||||||
|
* @file lv_draw_vg_lite_img.c
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*********************
|
||||||
|
* INCLUDES
|
||||||
|
*********************/
|
||||||
|
|
||||||
|
#include "lv_draw_vg_lite.h"
|
||||||
|
|
||||||
|
#if LV_USE_DRAW_VG_LITE
|
||||||
|
|
||||||
|
#include "lv_draw_vg_lite_type.h"
|
||||||
|
#include "lv_vg_lite_decoder.h"
|
||||||
|
#include "lv_vg_lite_path.h"
|
||||||
|
#include "lv_vg_lite_utils.h"
|
||||||
|
|
||||||
|
/*********************
|
||||||
|
* DEFINES
|
||||||
|
*********************/
|
||||||
|
|
||||||
|
/**********************
|
||||||
|
* TYPEDEFS
|
||||||
|
**********************/
|
||||||
|
|
||||||
|
/**********************
|
||||||
|
* STATIC PROTOTYPES
|
||||||
|
**********************/
|
||||||
|
|
||||||
|
/**********************
|
||||||
|
* STATIC VARIABLES
|
||||||
|
**********************/
|
||||||
|
|
||||||
|
/**********************
|
||||||
|
* MACROS
|
||||||
|
**********************/
|
||||||
|
|
||||||
|
/**********************
|
||||||
|
* GLOBAL FUNCTIONS
|
||||||
|
**********************/
|
||||||
|
|
||||||
|
void lv_draw_vg_lite_img(lv_draw_unit_t * draw_unit, const lv_draw_image_dsc_t * dsc,
|
||||||
|
const lv_area_t * coords)
|
||||||
|
{
|
||||||
|
if(dsc->opa <= LV_OPA_MIN) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
lv_draw_vg_lite_unit_t * u = (lv_draw_vg_lite_unit_t *)draw_unit;
|
||||||
|
|
||||||
|
/* The coordinates passed in by coords are not transformed,
|
||||||
|
* so the transformed area needs to be calculated once.
|
||||||
|
*/
|
||||||
|
lv_area_t image_tf_area;
|
||||||
|
_lv_image_buf_get_transformed_area(
|
||||||
|
&image_tf_area,
|
||||||
|
lv_area_get_width(coords),
|
||||||
|
lv_area_get_height(coords),
|
||||||
|
dsc->rotation,
|
||||||
|
dsc->scale_x,
|
||||||
|
dsc->scale_y,
|
||||||
|
&dsc->pivot);
|
||||||
|
lv_area_move(&image_tf_area, coords->x1, coords->y1);
|
||||||
|
|
||||||
|
lv_area_t clip_area;
|
||||||
|
if(!_lv_area_intersect(&clip_area, &image_tf_area, draw_unit->clip_area)) {
|
||||||
|
/*Fully clipped, nothing to do*/
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
vg_lite_buffer_t src_buf;
|
||||||
|
lv_image_decoder_dsc_t decoder_dsc;
|
||||||
|
if(!lv_vg_lite_buffer_open_image(&src_buf, &decoder_dsc, dsc->src)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* image opa */
|
||||||
|
lv_opa_t opa = dsc->opa;
|
||||||
|
vg_lite_color_t color = 0;
|
||||||
|
if(opa < LV_OPA_MAX) {
|
||||||
|
lv_memset(&color, opa, sizeof(color));
|
||||||
|
src_buf.image_mode = VG_LITE_MULTIPLY_IMAGE_MODE;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool has_recolor = dsc->recolor_opa >= LV_OPA_MIN;
|
||||||
|
bool has_trasform = (dsc->rotation != 0 || dsc->scale_x != LV_SCALE_NONE || dsc->scale_y != LV_SCALE_NONE);
|
||||||
|
vg_lite_filter_t filter = has_trasform ? VG_LITE_FILTER_BI_LINEAR : VG_LITE_FILTER_POINT;
|
||||||
|
|
||||||
|
vg_lite_matrix_t matrix;
|
||||||
|
vg_lite_identity(&matrix);
|
||||||
|
lv_vg_lite_matrix_multiply(&matrix, &u->global_matrix);
|
||||||
|
lv_vg_lite_image_matrix(&matrix, coords->x1, coords->y1, dsc);
|
||||||
|
|
||||||
|
LV_VG_LITE_ASSERT_SRC_BUFFER(&src_buf);
|
||||||
|
LV_VG_LITE_ASSERT_DEST_BUFFER(&u->target_buffer);
|
||||||
|
|
||||||
|
/* If clipping is not required, blit directly */
|
||||||
|
if(_lv_area_is_in(&image_tf_area, draw_unit->clip_area, false) && !has_recolor) {
|
||||||
|
/* The image area is the coordinates relative to the image itself */
|
||||||
|
lv_area_t src_area = *coords;
|
||||||
|
lv_area_move(&src_area, -coords->x1, -coords->y1);
|
||||||
|
|
||||||
|
/* rect is used to crop the pixel-aligned padding area */
|
||||||
|
vg_lite_rectangle_t rect;
|
||||||
|
lv_vg_lite_rect(&rect, &src_area);
|
||||||
|
LV_VG_LITE_CHECK_ERROR(vg_lite_blit_rect(
|
||||||
|
&u->target_buffer,
|
||||||
|
&src_buf,
|
||||||
|
&rect,
|
||||||
|
&matrix,
|
||||||
|
lv_vg_lite_blend_mode(dsc->blend_mode),
|
||||||
|
color,
|
||||||
|
filter));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
lv_vg_lite_path_t * path = lv_vg_lite_path_get(u, VG_LITE_S16);
|
||||||
|
lv_vg_lite_path_append_rect(
|
||||||
|
path,
|
||||||
|
clip_area.x1, clip_area.y1,
|
||||||
|
lv_area_get_width(&clip_area), lv_area_get_height(&clip_area),
|
||||||
|
0, 0);
|
||||||
|
lv_vg_lite_path_set_bonding_box_area(path, &clip_area);
|
||||||
|
lv_vg_lite_path_end(path);
|
||||||
|
|
||||||
|
vg_lite_path_t * vg_lite_path = lv_vg_lite_path_get_path(path);
|
||||||
|
LV_VG_LITE_ASSERT_PATH(vg_lite_path);
|
||||||
|
|
||||||
|
vg_lite_matrix_t path_matrix;
|
||||||
|
vg_lite_identity(&path_matrix);
|
||||||
|
|
||||||
|
LV_VG_LITE_CHECK_ERROR(vg_lite_draw_pattern(
|
||||||
|
&u->target_buffer,
|
||||||
|
vg_lite_path,
|
||||||
|
VG_LITE_FILL_EVEN_ODD,
|
||||||
|
&path_matrix,
|
||||||
|
&src_buf,
|
||||||
|
&matrix,
|
||||||
|
lv_vg_lite_blend_mode(dsc->blend_mode),
|
||||||
|
VG_LITE_PATTERN_COLOR,
|
||||||
|
lv_vg_lite_color(dsc->recolor, dsc->recolor_opa, true),
|
||||||
|
color,
|
||||||
|
filter));
|
||||||
|
|
||||||
|
lv_vg_lite_path_drop(u, path);
|
||||||
|
}
|
||||||
|
|
||||||
|
lv_image_decoder_close(&decoder_dsc);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**********************
|
||||||
|
* STATIC FUNCTIONS
|
||||||
|
**********************/
|
||||||
|
|
||||||
|
#endif /*LV_USE_DRAW_VG_LITE*/
|
||||||
313
src/draw/vg_lite/lv_draw_vg_lite_label.c
Normal file
313
src/draw/vg_lite/lv_draw_vg_lite_label.c
Normal file
@@ -0,0 +1,313 @@
|
|||||||
|
/**
|
||||||
|
* @file lv_draw_vg_lite_label.c
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*********************
|
||||||
|
* INCLUDES
|
||||||
|
*********************/
|
||||||
|
|
||||||
|
#include "lv_draw_vg_lite.h"
|
||||||
|
|
||||||
|
#include "../../libs/freetype/lv_freetype.h"
|
||||||
|
|
||||||
|
#if LV_USE_DRAW_VG_LITE
|
||||||
|
|
||||||
|
#include "lv_vg_lite_utils.h"
|
||||||
|
#include "lv_vg_lite_path.h"
|
||||||
|
#include "lv_draw_vg_lite_type.h"
|
||||||
|
|
||||||
|
/*********************
|
||||||
|
* DEFINES
|
||||||
|
*********************/
|
||||||
|
|
||||||
|
#define PATH_QUALITY VG_LITE_MEDIUM
|
||||||
|
#define PATH_DATA_COORD_FORMAT VG_LITE_S16
|
||||||
|
#define PATH_REF_SIZE 128
|
||||||
|
#define FT_F26DOT6_SHIFT 6
|
||||||
|
|
||||||
|
/** After converting the font reference size, it is also necessary to scale the 26dot6 data
|
||||||
|
* in the path to the real physical size
|
||||||
|
*/
|
||||||
|
#define FT_F26DOT6_TO_PATH_SCALE(x) (LV_FREETYPE_F26DOT6_TO_FLOAT(x) / (1 << FT_F26DOT6_SHIFT))
|
||||||
|
|
||||||
|
#define SUPPORT_OUTLINE_FONT (LV_USE_FREETYPE && LV_FREETYPE_CACHE_TYPE == LV_FREETYPE_CACHE_TYPE_OUTLINE)
|
||||||
|
|
||||||
|
/**********************
|
||||||
|
* TYPEDEFS
|
||||||
|
**********************/
|
||||||
|
|
||||||
|
/**********************
|
||||||
|
* STATIC PROTOTYPES
|
||||||
|
**********************/
|
||||||
|
|
||||||
|
static void draw_letter_cb(lv_draw_unit_t * draw_unit, lv_draw_glyph_dsc_t * glyph_draw_dsc,
|
||||||
|
lv_draw_fill_dsc_t * fill_draw_dsc, const lv_area_t * fill_area);
|
||||||
|
|
||||||
|
static void draw_letter_bitmap(lv_draw_vg_lite_unit_t * u, const lv_draw_glyph_dsc_t * dsc);
|
||||||
|
|
||||||
|
#if SUPPORT_OUTLINE_FONT
|
||||||
|
static void freetype_outline_event_cb(lv_event_t * e);
|
||||||
|
static void draw_letter_outline(lv_draw_vg_lite_unit_t * u, const lv_draw_glyph_dsc_t * dsc);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**********************
|
||||||
|
* STATIC VARIABLES
|
||||||
|
**********************/
|
||||||
|
|
||||||
|
/**********************
|
||||||
|
* MACROS
|
||||||
|
**********************/
|
||||||
|
|
||||||
|
/**********************
|
||||||
|
* GLOBAL FUNCTIONS
|
||||||
|
**********************/
|
||||||
|
|
||||||
|
void lv_draw_vg_lite_label(lv_draw_unit_t * draw_unit, const lv_draw_label_dsc_t * dsc,
|
||||||
|
const lv_area_t * coords)
|
||||||
|
{
|
||||||
|
if(dsc->opa <= LV_OPA_MIN) return;
|
||||||
|
|
||||||
|
#if SUPPORT_OUTLINE_FONT
|
||||||
|
static bool is_init = false;
|
||||||
|
if(!is_init) {
|
||||||
|
lv_freetype_outline_set_ref_size(PATH_REF_SIZE);
|
||||||
|
lv_freetype_outline_add_event(freetype_outline_event_cb, LV_EVENT_ALL, draw_unit);
|
||||||
|
is_init = true;
|
||||||
|
}
|
||||||
|
#endif /*SUPPORT_OUTLINE_FONT*/
|
||||||
|
|
||||||
|
lv_draw_label_iterate_letters(draw_unit, dsc, coords, draw_letter_cb);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**********************
|
||||||
|
* STATIC FUNCTIONS
|
||||||
|
**********************/
|
||||||
|
|
||||||
|
static void draw_letter_cb(lv_draw_unit_t * draw_unit, lv_draw_glyph_dsc_t * glyph_draw_dsc,
|
||||||
|
lv_draw_fill_dsc_t * fill_draw_dsc, const lv_area_t * fill_area)
|
||||||
|
{
|
||||||
|
lv_draw_vg_lite_unit_t * u = (lv_draw_vg_lite_unit_t *)draw_unit;
|
||||||
|
if(glyph_draw_dsc) {
|
||||||
|
if(glyph_draw_dsc->bitmap == NULL) {
|
||||||
|
#if LV_USE_FONT_PLACEHOLDER
|
||||||
|
/* Draw a placeholder rectangle*/
|
||||||
|
lv_draw_border_dsc_t border_draw_dsc;
|
||||||
|
lv_draw_border_dsc_init(&border_draw_dsc);
|
||||||
|
border_draw_dsc.opa = glyph_draw_dsc->opa;
|
||||||
|
border_draw_dsc.color = glyph_draw_dsc->color;
|
||||||
|
border_draw_dsc.width = 1;
|
||||||
|
lv_draw_vg_lite_border(draw_unit, &border_draw_dsc, glyph_draw_dsc->bg_coords);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
else if(glyph_draw_dsc->format == LV_DRAW_LETTER_BITMAP_FORMAT_A8
|
||||||
|
|| glyph_draw_dsc->format == LV_DRAW_LETTER_BITMAP_FORMAT_IMAGE) {
|
||||||
|
#if SUPPORT_OUTLINE_FONT
|
||||||
|
if(lv_freetype_is_outline_font(glyph_draw_dsc->g->resolved_font)) {
|
||||||
|
draw_letter_outline(u, glyph_draw_dsc);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
#endif /*SUPPORT_OUTLINE_FONT*/
|
||||||
|
{
|
||||||
|
draw_letter_bitmap(u, glyph_draw_dsc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(fill_draw_dsc && fill_area) {
|
||||||
|
lv_draw_vg_lite_fill(draw_unit, fill_draw_dsc, fill_area);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void draw_letter_bitmap(lv_draw_vg_lite_unit_t * u, const lv_draw_glyph_dsc_t * dsc)
|
||||||
|
{
|
||||||
|
lv_area_t clip_area;
|
||||||
|
if(!_lv_area_intersect(&clip_area, u->base_unit.clip_area, dsc->letter_coords)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
lv_area_t image_area = *dsc->letter_coords;
|
||||||
|
|
||||||
|
vg_lite_matrix_t matrix;
|
||||||
|
vg_lite_identity(&matrix);
|
||||||
|
lv_vg_lite_matrix_multiply(&matrix, &u->global_matrix);
|
||||||
|
vg_lite_translate(image_area.x1, image_area.y1, &matrix);
|
||||||
|
|
||||||
|
vg_lite_buffer_t src_buf;
|
||||||
|
lv_vg_lite_buffer_init(
|
||||||
|
&src_buf,
|
||||||
|
dsc->bitmap,
|
||||||
|
lv_area_get_width(&image_area),
|
||||||
|
lv_area_get_height(&image_area),
|
||||||
|
VG_LITE_A8,
|
||||||
|
false);
|
||||||
|
|
||||||
|
vg_lite_color_t color;
|
||||||
|
color = lv_vg_lite_color(dsc->color, dsc->opa, true);
|
||||||
|
|
||||||
|
LV_VG_LITE_ASSERT_SRC_BUFFER(&src_buf);
|
||||||
|
LV_VG_LITE_ASSERT_DEST_BUFFER(&u->target_buffer);
|
||||||
|
|
||||||
|
/* If clipping is not required, blit directly */
|
||||||
|
if(_lv_area_is_in(&image_area, u->base_unit.clip_area, false)) {
|
||||||
|
/* The image area is the coordinates relative to the image itself */
|
||||||
|
lv_area_t src_area = image_area;
|
||||||
|
lv_area_move(&src_area, -image_area.x1, -image_area.y1);
|
||||||
|
|
||||||
|
/* rect is used to crop the pixel-aligned padding area */
|
||||||
|
vg_lite_rectangle_t rect;
|
||||||
|
lv_vg_lite_rect(&rect, &src_area);
|
||||||
|
LV_VG_LITE_CHECK_ERROR(vg_lite_blit_rect(
|
||||||
|
&u->target_buffer,
|
||||||
|
&src_buf,
|
||||||
|
&rect,
|
||||||
|
&matrix,
|
||||||
|
VG_LITE_BLEND_SRC_OVER,
|
||||||
|
color,
|
||||||
|
VG_LITE_FILTER_LINEAR));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
lv_vg_lite_path_t * path = lv_vg_lite_path_get(u, VG_LITE_S16);
|
||||||
|
lv_vg_lite_path_append_rect(
|
||||||
|
path,
|
||||||
|
clip_area.x1, clip_area.y1,
|
||||||
|
lv_area_get_width(&clip_area), lv_area_get_height(&clip_area),
|
||||||
|
0, 0);
|
||||||
|
lv_vg_lite_path_set_bonding_box_area(path, &clip_area);
|
||||||
|
lv_vg_lite_path_end(path);
|
||||||
|
|
||||||
|
vg_lite_path_t * vg_lite_path = lv_vg_lite_path_get_path(path);
|
||||||
|
LV_VG_LITE_ASSERT_PATH(vg_lite_path);
|
||||||
|
|
||||||
|
vg_lite_matrix_t path_matrix;
|
||||||
|
vg_lite_identity(&path_matrix);
|
||||||
|
|
||||||
|
LV_VG_LITE_CHECK_ERROR(vg_lite_draw_pattern(
|
||||||
|
&u->target_buffer,
|
||||||
|
vg_lite_path,
|
||||||
|
VG_LITE_FILL_EVEN_ODD,
|
||||||
|
&path_matrix,
|
||||||
|
&src_buf,
|
||||||
|
&matrix,
|
||||||
|
VG_LITE_BLEND_SRC_OVER,
|
||||||
|
VG_LITE_PATTERN_COLOR,
|
||||||
|
color,
|
||||||
|
color,
|
||||||
|
VG_LITE_FILTER_LINEAR));
|
||||||
|
|
||||||
|
lv_vg_lite_path_drop(u, path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#if SUPPORT_OUTLINE_FONT
|
||||||
|
|
||||||
|
static void draw_letter_outline(lv_draw_vg_lite_unit_t * u, const lv_draw_glyph_dsc_t * dsc)
|
||||||
|
{
|
||||||
|
/* get clip area */
|
||||||
|
lv_area_t path_clip_area;
|
||||||
|
if(!_lv_area_intersect(&path_clip_area, u->base_unit.clip_area, dsc->letter_coords)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* vg-lite bounding_box will crop the pixels on the edge, so +1px is needed here */
|
||||||
|
path_clip_area.x2++;
|
||||||
|
path_clip_area.y2++;
|
||||||
|
|
||||||
|
lv_vg_lite_path_t * outline = (lv_vg_lite_path_t *)dsc->bitmap;
|
||||||
|
lv_point_t pos = {dsc->letter_coords->x1, dsc->letter_coords->y1};
|
||||||
|
|
||||||
|
/* calc convert matrix */
|
||||||
|
float scale = FT_F26DOT6_TO_PATH_SCALE(lv_freetype_outline_get_scale(dsc->g->resolved_font));
|
||||||
|
vg_lite_matrix_t matrix;
|
||||||
|
vg_lite_identity(&matrix);
|
||||||
|
lv_vg_lite_matrix_multiply(&matrix, &u->global_matrix);
|
||||||
|
|
||||||
|
/* convert to vg-lite coordinate */
|
||||||
|
vg_lite_translate(pos.x - dsc->g->ofs_x, pos.y + dsc->g->box_h + dsc->g->ofs_y, &matrix);
|
||||||
|
|
||||||
|
/* scale size */
|
||||||
|
vg_lite_scale(scale, scale, &matrix);
|
||||||
|
|
||||||
|
/* Cartesian coordinates to LCD coordinates */
|
||||||
|
lv_vg_lite_matrix_flip_y(&matrix);
|
||||||
|
|
||||||
|
/* calc inverse matrix */
|
||||||
|
vg_lite_matrix_t result;
|
||||||
|
if(!lv_vg_lite_matrix_inverse(&result, &matrix)) {
|
||||||
|
LV_LOG_ERROR("no inverse matrix");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
lv_point_precise_t p1 = { path_clip_area.x1, path_clip_area.y1 };
|
||||||
|
lv_point_precise_t p1_res = lv_vg_lite_matrix_transform_point(&result, &p1);
|
||||||
|
|
||||||
|
lv_point_precise_t p2 = { path_clip_area.x2, path_clip_area.y2 };
|
||||||
|
lv_point_precise_t p2_res = lv_vg_lite_matrix_transform_point(&result, &p2);
|
||||||
|
|
||||||
|
/* Since the font uses Cartesian coordinates, the y coordinates need to be reversed */
|
||||||
|
lv_vg_lite_path_set_bonding_box(outline, p1_res.x, p2_res.y, p2_res.x, p1_res.y);
|
||||||
|
|
||||||
|
vg_lite_path_t * vg_lite_path = lv_vg_lite_path_get_path(outline);
|
||||||
|
|
||||||
|
LV_VG_LITE_ASSERT_DEST_BUFFER(&u->target_buffer);
|
||||||
|
LV_VG_LITE_ASSERT_PATH(vg_lite_path);
|
||||||
|
LV_VG_LITE_CHECK_ERROR(vg_lite_draw(
|
||||||
|
&u->target_buffer, vg_lite_path, VG_LITE_FILL_NON_ZERO,
|
||||||
|
&matrix, VG_LITE_BLEND_SRC_OVER, lv_vg_lite_color(dsc->color, dsc->opa, true)));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void vg_lite_outline_push(const lv_freetype_outline_event_param_t * param)
|
||||||
|
{
|
||||||
|
lv_vg_lite_path_t * outline = param->outline;
|
||||||
|
LV_ASSERT_NULL(outline);
|
||||||
|
|
||||||
|
lv_freetype_outline_type_t type = param->type;
|
||||||
|
switch(type) {
|
||||||
|
case LV_FREETYPE_OUTLINE_END:
|
||||||
|
lv_vg_lite_path_end(outline);
|
||||||
|
break;
|
||||||
|
case LV_FREETYPE_OUTLINE_MOVE_TO:
|
||||||
|
lv_vg_lite_path_move_to(outline, param->to.x, param->to.y);
|
||||||
|
break;
|
||||||
|
case LV_FREETYPE_OUTLINE_LINE_TO:
|
||||||
|
lv_vg_lite_path_line_to(outline, param->to.x, param->to.y);
|
||||||
|
break;
|
||||||
|
case LV_FREETYPE_OUTLINE_CUBIC_TO:
|
||||||
|
lv_vg_lite_path_cubic_to(outline, param->control1.x, param->control1.y,
|
||||||
|
param->control2.x, param->control2.y,
|
||||||
|
param->to.x, param->to.y);
|
||||||
|
break;
|
||||||
|
case LV_FREETYPE_OUTLINE_CONIC_TO:
|
||||||
|
lv_vg_lite_path_quad_to(outline, param->control1.x, param->control1.y,
|
||||||
|
param->to.x, param->to.y);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
LV_LOG_ERROR("unknown point type: %d", type);
|
||||||
|
LV_ASSERT(false);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void freetype_outline_event_cb(lv_event_t * e)
|
||||||
|
{
|
||||||
|
lv_event_code_t code = lv_event_get_code(e);
|
||||||
|
lv_freetype_outline_event_param_t * param = lv_event_get_param(e);
|
||||||
|
switch(code) {
|
||||||
|
case LV_EVENT_CREATE:
|
||||||
|
param->outline = lv_vg_lite_path_create(PATH_DATA_COORD_FORMAT);
|
||||||
|
break;
|
||||||
|
case LV_EVENT_DELETE:
|
||||||
|
lv_vg_lite_path_destroy(param->outline);
|
||||||
|
break;
|
||||||
|
case LV_EVENT_INSERT:
|
||||||
|
vg_lite_outline_push(param);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
LV_LOG_WARN("unknown event code: %d", code);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /*SUPPORT_OUTLINE_FONT*/
|
||||||
|
|
||||||
|
#endif /*LV_USE_DRAW_VG_LITE*/
|
||||||
72
src/draw/vg_lite/lv_draw_vg_lite_layer.c
Normal file
72
src/draw/vg_lite/lv_draw_vg_lite_layer.c
Normal file
@@ -0,0 +1,72 @@
|
|||||||
|
/**
|
||||||
|
* @file lv_draw_vg_lite_layer.c
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*********************
|
||||||
|
* INCLUDES
|
||||||
|
*********************/
|
||||||
|
|
||||||
|
#include "lv_draw_vg_lite.h"
|
||||||
|
|
||||||
|
#if LV_USE_DRAW_VG_LITE
|
||||||
|
|
||||||
|
#include "lv_vg_lite_utils.h"
|
||||||
|
#include "lv_draw_vg_lite_type.h"
|
||||||
|
|
||||||
|
/*********************
|
||||||
|
* DEFINES
|
||||||
|
*********************/
|
||||||
|
|
||||||
|
/**********************
|
||||||
|
* TYPEDEFS
|
||||||
|
**********************/
|
||||||
|
|
||||||
|
/**********************
|
||||||
|
* STATIC PROTOTYPES
|
||||||
|
**********************/
|
||||||
|
|
||||||
|
/**********************
|
||||||
|
* STATIC VARIABLES
|
||||||
|
**********************/
|
||||||
|
|
||||||
|
/**********************
|
||||||
|
* MACROS
|
||||||
|
**********************/
|
||||||
|
|
||||||
|
/**********************
|
||||||
|
* GLOBAL FUNCTIONS
|
||||||
|
**********************/
|
||||||
|
|
||||||
|
void lv_draw_vg_lite_layer(lv_draw_unit_t * draw_unit, const lv_draw_image_dsc_t * draw_dsc,
|
||||||
|
const lv_area_t * coords)
|
||||||
|
{
|
||||||
|
lv_layer_t * layer = (lv_layer_t *)draw_dsc->src;
|
||||||
|
|
||||||
|
/*It can happen that nothing was draw on a layer and therefore its buffer is not allocated.
|
||||||
|
*In this case just return. */
|
||||||
|
if(layer->buf == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
lv_image_dsc_t img_dsc;
|
||||||
|
lv_memzero(&img_dsc, sizeof(lv_image_dsc_t));
|
||||||
|
img_dsc.header.w = lv_area_get_width(&layer->buf_area);
|
||||||
|
img_dsc.header.h = lv_area_get_height(&layer->buf_area);
|
||||||
|
img_dsc.header.cf = layer->color_format;
|
||||||
|
img_dsc.header.always_zero = 0;
|
||||||
|
img_dsc.data = layer->buf;
|
||||||
|
|
||||||
|
lv_draw_image_dsc_t new_draw_dsc = *draw_dsc;
|
||||||
|
new_draw_dsc.src = &img_dsc;
|
||||||
|
|
||||||
|
lv_draw_vg_lite_img(draw_unit, &new_draw_dsc, coords);
|
||||||
|
lv_cache_lock();
|
||||||
|
lv_cache_invalidate_by_src(&img_dsc, LV_CACHE_SRC_TYPE_POINTER);
|
||||||
|
lv_cache_unlock();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**********************
|
||||||
|
* STATIC FUNCTIONS
|
||||||
|
**********************/
|
||||||
|
|
||||||
|
#endif /*LV_USE_DRAW_VG_LITE*/
|
||||||
211
src/draw/vg_lite/lv_draw_vg_lite_line.c
Normal file
211
src/draw/vg_lite/lv_draw_vg_lite_line.c
Normal file
@@ -0,0 +1,211 @@
|
|||||||
|
/**
|
||||||
|
* @file lv_draw_vg_lite_line.c
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*********************
|
||||||
|
* INCLUDES
|
||||||
|
*********************/
|
||||||
|
|
||||||
|
#include "lv_draw_vg_lite.h"
|
||||||
|
|
||||||
|
#if LV_USE_DRAW_VG_LITE
|
||||||
|
|
||||||
|
#include "lv_draw_vg_lite_type.h"
|
||||||
|
#include "lv_vg_lite_math.h"
|
||||||
|
#include "lv_vg_lite_path.h"
|
||||||
|
#include "lv_vg_lite_utils.h"
|
||||||
|
|
||||||
|
/*********************
|
||||||
|
* DEFINES
|
||||||
|
*********************/
|
||||||
|
|
||||||
|
#define SQ(x) ((x) * (x))
|
||||||
|
|
||||||
|
/**********************
|
||||||
|
* TYPEDEFS
|
||||||
|
**********************/
|
||||||
|
|
||||||
|
/**********************
|
||||||
|
* STATIC PROTOTYPES
|
||||||
|
**********************/
|
||||||
|
|
||||||
|
/**********************
|
||||||
|
* STATIC VARIABLES
|
||||||
|
**********************/
|
||||||
|
|
||||||
|
/**********************
|
||||||
|
* MACROS
|
||||||
|
**********************/
|
||||||
|
|
||||||
|
/**********************
|
||||||
|
* GLOBAL FUNCTIONS
|
||||||
|
**********************/
|
||||||
|
|
||||||
|
void lv_draw_vg_lite_line(lv_draw_unit_t * draw_unit, const lv_draw_line_dsc_t * dsc)
|
||||||
|
{
|
||||||
|
if(dsc->opa <= LV_OPA_MIN)
|
||||||
|
return;
|
||||||
|
if(dsc->width == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
float p1_x = dsc->p1.x;
|
||||||
|
float p1_y = dsc->p1.y;
|
||||||
|
float p2_x = dsc->p2.x;
|
||||||
|
float p2_y = dsc->p2.y;
|
||||||
|
|
||||||
|
if(p1_x == p2_x && p1_y == p2_y)
|
||||||
|
return;
|
||||||
|
|
||||||
|
float half_w = dsc->width * 0.5f;
|
||||||
|
|
||||||
|
lv_area_t rel_clip_area;
|
||||||
|
rel_clip_area.x1 = LV_MIN(p1_x, p2_x) - half_w;
|
||||||
|
rel_clip_area.x2 = LV_MAX(p1_x, p2_x) + half_w;
|
||||||
|
rel_clip_area.y1 = LV_MIN(p1_y, p2_y) - half_w;
|
||||||
|
rel_clip_area.y2 = LV_MAX(p1_y, p2_y) + half_w;
|
||||||
|
|
||||||
|
if(!_lv_area_intersect(&rel_clip_area, &rel_clip_area, draw_unit->clip_area)) {
|
||||||
|
return; /*Fully clipped, nothing to do*/
|
||||||
|
}
|
||||||
|
|
||||||
|
lv_draw_vg_lite_unit_t * u = (lv_draw_vg_lite_unit_t *)draw_unit;
|
||||||
|
|
||||||
|
int32_t dash_width = dsc->dash_width;
|
||||||
|
int32_t dash_gap = dsc->dash_gap;
|
||||||
|
int32_t dash_l = dash_width + dash_gap;
|
||||||
|
|
||||||
|
float dx = p2_x - p1_x;
|
||||||
|
float dy = p2_y - p1_y;
|
||||||
|
float inv_dl = math_fast_inv_sqrtf(SQ(dx) + SQ(dy));
|
||||||
|
float w_dx = dsc->width * dy * inv_dl;
|
||||||
|
float w_dy = dsc->width * dx * inv_dl;
|
||||||
|
float w2_dx = w_dx / 2;
|
||||||
|
float w2_dy = w_dy / 2;
|
||||||
|
|
||||||
|
int32_t ndash = 0;
|
||||||
|
if(dash_width && dash_l * inv_dl < 1.0f) {
|
||||||
|
ndash = (1.0f / inv_dl + dash_l - 1) / dash_l;
|
||||||
|
}
|
||||||
|
|
||||||
|
lv_vg_lite_path_t * path = lv_vg_lite_path_get(u, VG_LITE_FP32);
|
||||||
|
lv_vg_lite_path_set_quality(path, VG_LITE_MEDIUM);
|
||||||
|
lv_vg_lite_path_set_bonding_box_area(path, &rel_clip_area);
|
||||||
|
|
||||||
|
/* head point */
|
||||||
|
float head_start_x = p1_x + w2_dx;
|
||||||
|
float head_start_y = p1_y - w2_dy;
|
||||||
|
float head_end_x = p1_x - w2_dx;
|
||||||
|
float head_end_y = p1_y + w2_dy;
|
||||||
|
|
||||||
|
/* tali point */
|
||||||
|
float tali_start_x = p2_x - w2_dx;
|
||||||
|
float tali_start_y = p2_y + w2_dy;
|
||||||
|
float tali_end_x = p2_x + w2_dx;
|
||||||
|
float tali_end_y = p2_y - w2_dy;
|
||||||
|
|
||||||
|
/*
|
||||||
|
head_start tali_end
|
||||||
|
*-----------------*
|
||||||
|
/| |\
|
||||||
|
/ | | \
|
||||||
|
arc_c *( *p1 p2* )* arc_c
|
||||||
|
\ | | /
|
||||||
|
\| |/
|
||||||
|
*-----------------*
|
||||||
|
head_end tali_start
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* move to start point */
|
||||||
|
lv_vg_lite_path_move_to(path, head_start_x, head_start_y);
|
||||||
|
|
||||||
|
/* draw line head */
|
||||||
|
if(dsc->round_start) {
|
||||||
|
float arc_cx = p1_x - w2_dy;
|
||||||
|
float arc_cy = p1_y - w2_dx;
|
||||||
|
|
||||||
|
/* start 90deg arc */
|
||||||
|
lv_vg_lite_path_append_arc_right_angle(path,
|
||||||
|
head_start_x, head_start_y,
|
||||||
|
p1_x, p1_y,
|
||||||
|
arc_cx, arc_cy);
|
||||||
|
|
||||||
|
/* end 90deg arc */
|
||||||
|
lv_vg_lite_path_append_arc_right_angle(path,
|
||||||
|
arc_cx, arc_cy,
|
||||||
|
p1_x, p1_y,
|
||||||
|
head_end_x, head_end_y);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
lv_vg_lite_path_line_to(path, head_end_x, head_end_y);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* draw line body */
|
||||||
|
lv_vg_lite_path_line_to(path, tali_start_x, tali_start_y);
|
||||||
|
|
||||||
|
/* draw line tail */
|
||||||
|
if(dsc->round_end) {
|
||||||
|
float arc_cx = p2_x + w2_dy;
|
||||||
|
float arc_cy = p2_y + w2_dx;
|
||||||
|
lv_vg_lite_path_append_arc_right_angle(path,
|
||||||
|
tali_start_x, tali_start_y,
|
||||||
|
p2_x, p2_y,
|
||||||
|
arc_cx, arc_cy);
|
||||||
|
lv_vg_lite_path_append_arc_right_angle(path,
|
||||||
|
arc_cx, arc_cy,
|
||||||
|
p2_x, p2_y,
|
||||||
|
tali_end_x, tali_end_y);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
lv_vg_lite_path_line_to(path, tali_end_x, tali_end_y);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* close draw line body */
|
||||||
|
lv_vg_lite_path_line_to(path, head_start_x, head_start_y);
|
||||||
|
|
||||||
|
for(int32_t i = 0; i < ndash; i++) {
|
||||||
|
float start_x = p1_x - w2_dx + dx * (i * dash_l + dash_width) * inv_dl;
|
||||||
|
float start_y = p1_y + w2_dy + dy * (i * dash_l + dash_width) * inv_dl;
|
||||||
|
|
||||||
|
lv_vg_lite_path_move_to(path, start_x, start_y);
|
||||||
|
lv_vg_lite_path_line_to(path,
|
||||||
|
p1_x + w2_dx + dx * (i * dash_l + dash_width) * inv_dl,
|
||||||
|
p1_y - w2_dy + dy * (i * dash_l + dash_width) * inv_dl);
|
||||||
|
lv_vg_lite_path_line_to(path,
|
||||||
|
p1_x + w2_dx + dx * (i + 1) * dash_l * inv_dl,
|
||||||
|
p1_y - w2_dy + dy * (i + 1) * dash_l * inv_dl);
|
||||||
|
lv_vg_lite_path_line_to(path,
|
||||||
|
p1_x - w2_dx + dx * (i + 1) * dash_l * inv_dl,
|
||||||
|
p1_y + w2_dy + dy * (i + 1) * dash_l * inv_dl);
|
||||||
|
lv_vg_lite_path_line_to(path, start_x, start_y);
|
||||||
|
}
|
||||||
|
|
||||||
|
lv_vg_lite_path_end(path);
|
||||||
|
|
||||||
|
vg_lite_matrix_t matrix;
|
||||||
|
vg_lite_identity(&matrix);
|
||||||
|
lv_vg_lite_matrix_multiply(&matrix, &u->global_matrix);
|
||||||
|
|
||||||
|
vg_lite_color_t color = lv_vg_lite_color(dsc->color, dsc->opa, true);
|
||||||
|
|
||||||
|
vg_lite_path_t * vg_lite_path = lv_vg_lite_path_get_path(path);
|
||||||
|
|
||||||
|
LV_VG_LITE_ASSERT_DEST_BUFFER(&u->target_buffer);
|
||||||
|
LV_VG_LITE_ASSERT_PATH(vg_lite_path);
|
||||||
|
|
||||||
|
LV_VG_LITE_CHECK_ERROR(vg_lite_draw(
|
||||||
|
&u->target_buffer,
|
||||||
|
vg_lite_path,
|
||||||
|
VG_LITE_FILL_EVEN_ODD,
|
||||||
|
&matrix,
|
||||||
|
VG_LITE_BLEND_SRC_OVER,
|
||||||
|
color));
|
||||||
|
|
||||||
|
lv_vg_lite_path_drop(u, path);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**********************
|
||||||
|
* STATIC FUNCTIONS
|
||||||
|
**********************/
|
||||||
|
|
||||||
|
#endif /*LV_USE_DRAW_VG_LITE*/
|
||||||
94
src/draw/vg_lite/lv_draw_vg_lite_mask_rect.c
Normal file
94
src/draw/vg_lite/lv_draw_vg_lite_mask_rect.c
Normal file
@@ -0,0 +1,94 @@
|
|||||||
|
/**
|
||||||
|
* @file lv_draw_vg_lite_rect.c
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*********************
|
||||||
|
* INCLUDES
|
||||||
|
*********************/
|
||||||
|
|
||||||
|
#include "lv_draw_vg_lite.h"
|
||||||
|
|
||||||
|
#if LV_USE_DRAW_VG_LITE
|
||||||
|
|
||||||
|
#include "lv_vg_lite_utils.h"
|
||||||
|
#include "lv_draw_vg_lite_type.h"
|
||||||
|
|
||||||
|
/*********************
|
||||||
|
* DEFINES
|
||||||
|
*********************/
|
||||||
|
|
||||||
|
/**********************
|
||||||
|
* TYPEDEFS
|
||||||
|
**********************/
|
||||||
|
|
||||||
|
/**********************
|
||||||
|
* STATIC PROTOTYPES
|
||||||
|
**********************/
|
||||||
|
|
||||||
|
/**********************
|
||||||
|
* STATIC VARIABLES
|
||||||
|
**********************/
|
||||||
|
|
||||||
|
/**********************
|
||||||
|
* MACROS
|
||||||
|
**********************/
|
||||||
|
|
||||||
|
/**********************
|
||||||
|
* GLOBAL FUNCTIONS
|
||||||
|
**********************/
|
||||||
|
|
||||||
|
void lv_draw_vg_lite_mask_rect(lv_draw_unit_t * draw_unit, const lv_draw_mask_rect_dsc_t * dsc,
|
||||||
|
const lv_area_t * coords)
|
||||||
|
{
|
||||||
|
LV_UNUSED(coords);
|
||||||
|
|
||||||
|
lv_area_t draw_area;
|
||||||
|
if(!_lv_area_intersect(&draw_area, &dsc->area, draw_unit->clip_area)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
lv_draw_sw_mask_radius_param_t param;
|
||||||
|
lv_draw_sw_mask_radius_init(¶m, &dsc->area, dsc->radius, false);
|
||||||
|
|
||||||
|
void * masks[2] = {0};
|
||||||
|
masks[0] = ¶m;
|
||||||
|
|
||||||
|
uint32_t area_w = lv_area_get_width(&draw_area);
|
||||||
|
lv_opa_t * mask_buf = lv_malloc(area_w);
|
||||||
|
|
||||||
|
int32_t y;
|
||||||
|
for(y = draw_area.y1; y <= draw_area.y2; y++) {
|
||||||
|
lv_memset(mask_buf, 0xff, area_w);
|
||||||
|
lv_draw_sw_mask_res_t res = lv_draw_sw_mask_apply(masks, mask_buf, draw_area.x1, y, area_w);
|
||||||
|
if(res == LV_DRAW_SW_MASK_RES_FULL_COVER) continue;
|
||||||
|
|
||||||
|
lv_layer_t * target_layer = draw_unit->target_layer;
|
||||||
|
lv_color32_t * c32_buf = lv_draw_layer_go_to_xy(target_layer, draw_area.x1 - target_layer->buf_area.x1,
|
||||||
|
y - target_layer->buf_area.y1);
|
||||||
|
|
||||||
|
if(res == LV_DRAW_SW_MASK_RES_TRANSP) {
|
||||||
|
uint32_t i;
|
||||||
|
for(i = 0; i < area_w; i++) {
|
||||||
|
c32_buf[i].alpha = 0x00;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
uint32_t i;
|
||||||
|
for(i = 0; i < area_w; i++) {
|
||||||
|
if(mask_buf[i] != LV_OPA_COVER) {
|
||||||
|
c32_buf[i].alpha = LV_OPA_MIX2(c32_buf[i].alpha, mask_buf[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
lv_free(mask_buf);
|
||||||
|
lv_draw_sw_mask_free_param(¶m);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**********************
|
||||||
|
* STATIC FUNCTIONS
|
||||||
|
**********************/
|
||||||
|
|
||||||
|
#endif /*LV_USE_DRAW_VG_LITE*/
|
||||||
104
src/draw/vg_lite/lv_draw_vg_lite_triangle.c
Normal file
104
src/draw/vg_lite/lv_draw_vg_lite_triangle.c
Normal file
@@ -0,0 +1,104 @@
|
|||||||
|
/**
|
||||||
|
* @file lv_draw_vg_lite_triangle.c
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*********************
|
||||||
|
* INCLUDES
|
||||||
|
*********************/
|
||||||
|
|
||||||
|
#include "lv_draw_vg_lite.h"
|
||||||
|
|
||||||
|
#if LV_USE_DRAW_VG_LITE
|
||||||
|
|
||||||
|
#include "lv_vg_lite_utils.h"
|
||||||
|
#include "lv_vg_lite_path.h"
|
||||||
|
#include "lv_draw_vg_lite_type.h"
|
||||||
|
|
||||||
|
/*********************
|
||||||
|
* DEFINES
|
||||||
|
*********************/
|
||||||
|
|
||||||
|
/**********************
|
||||||
|
* TYPEDEFS
|
||||||
|
**********************/
|
||||||
|
|
||||||
|
/**********************
|
||||||
|
* STATIC PROTOTYPES
|
||||||
|
**********************/
|
||||||
|
|
||||||
|
/**********************
|
||||||
|
* STATIC VARIABLES
|
||||||
|
**********************/
|
||||||
|
|
||||||
|
/**********************
|
||||||
|
* MACROS
|
||||||
|
**********************/
|
||||||
|
|
||||||
|
/**********************
|
||||||
|
* GLOBAL FUNCTIONS
|
||||||
|
**********************/
|
||||||
|
|
||||||
|
void lv_draw_vg_lite_triangle(lv_draw_unit_t * draw_unit, const lv_draw_triangle_dsc_t * dsc)
|
||||||
|
{
|
||||||
|
if(dsc->bg_opa <= LV_OPA_MIN) return;
|
||||||
|
|
||||||
|
lv_area_t tri_area;
|
||||||
|
tri_area.x1 = (int32_t)LV_MIN3(dsc->p[0].x, dsc->p[1].x, dsc->p[2].x);
|
||||||
|
tri_area.y1 = (int32_t)LV_MIN3(dsc->p[0].y, dsc->p[1].y, dsc->p[2].y);
|
||||||
|
tri_area.x2 = (int32_t)LV_MAX3(dsc->p[0].x, dsc->p[1].x, dsc->p[2].x);
|
||||||
|
tri_area.y2 = (int32_t)LV_MAX3(dsc->p[0].y, dsc->p[1].y, dsc->p[2].y);
|
||||||
|
|
||||||
|
bool is_common;
|
||||||
|
lv_area_t clip_area;
|
||||||
|
is_common = _lv_area_intersect(&clip_area, &tri_area, draw_unit->clip_area);
|
||||||
|
if(!is_common) return;
|
||||||
|
|
||||||
|
lv_draw_vg_lite_unit_t * u = (lv_draw_vg_lite_unit_t *)draw_unit;
|
||||||
|
|
||||||
|
lv_vg_lite_path_t * path = lv_vg_lite_path_get(u, VG_LITE_FP32);
|
||||||
|
lv_vg_lite_path_set_bonding_box_area(path, &clip_area);
|
||||||
|
lv_vg_lite_path_move_to(path, dsc->p[0].x, dsc->p[0].y);
|
||||||
|
lv_vg_lite_path_line_to(path, dsc->p[1].x, dsc->p[1].y);
|
||||||
|
lv_vg_lite_path_line_to(path, dsc->p[2].x, dsc->p[2].y);
|
||||||
|
lv_vg_lite_path_close(path);
|
||||||
|
lv_vg_lite_path_end(path);
|
||||||
|
|
||||||
|
vg_lite_path_t * vg_lite_path = lv_vg_lite_path_get_path(path);
|
||||||
|
|
||||||
|
LV_VG_LITE_ASSERT_DEST_BUFFER(&u->target_buffer);
|
||||||
|
LV_VG_LITE_ASSERT_PATH(vg_lite_path);
|
||||||
|
|
||||||
|
vg_lite_matrix_t matrix;
|
||||||
|
vg_lite_identity(&matrix);
|
||||||
|
lv_vg_lite_matrix_multiply(&matrix, &u->global_matrix);
|
||||||
|
|
||||||
|
if(dsc->bg_grad.dir != LV_GRAD_DIR_NONE) {
|
||||||
|
lv_vg_lite_draw_linear_grad(
|
||||||
|
&u->target_buffer,
|
||||||
|
vg_lite_path,
|
||||||
|
&tri_area,
|
||||||
|
&dsc->bg_grad,
|
||||||
|
&matrix,
|
||||||
|
VG_LITE_FILL_EVEN_ODD,
|
||||||
|
VG_LITE_BLEND_SRC_OVER);
|
||||||
|
}
|
||||||
|
else { /* normal fill */
|
||||||
|
vg_lite_color_t color = lv_vg_lite_color(dsc->bg_color, dsc->bg_opa, true);
|
||||||
|
LV_VG_LITE_CHECK_ERROR(vg_lite_draw(
|
||||||
|
&u->target_buffer,
|
||||||
|
vg_lite_path,
|
||||||
|
VG_LITE_FILL_EVEN_ODD,
|
||||||
|
&matrix,
|
||||||
|
VG_LITE_BLEND_SRC_OVER,
|
||||||
|
color));
|
||||||
|
}
|
||||||
|
|
||||||
|
lv_vg_lite_path_drop(u, path);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**********************
|
||||||
|
* STATIC FUNCTIONS
|
||||||
|
**********************/
|
||||||
|
|
||||||
|
#endif
|
||||||
55
src/draw/vg_lite/lv_draw_vg_lite_type.h
Normal file
55
src/draw/vg_lite/lv_draw_vg_lite_type.h
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
/**
|
||||||
|
* @file lv_draw_vg_lite_type.h
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef LV_DRAW_VG_LITE_TYPE_H
|
||||||
|
#define LV_DRAW_VG_LITE_TYPE_H
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*********************
|
||||||
|
* INCLUDES
|
||||||
|
*********************/
|
||||||
|
|
||||||
|
#include "../../lv_conf_internal.h"
|
||||||
|
|
||||||
|
#if LV_USE_DRAW_VG_LITE
|
||||||
|
|
||||||
|
#include "../lv_draw.h"
|
||||||
|
#include <vg_lite.h>
|
||||||
|
|
||||||
|
/*********************
|
||||||
|
* DEFINES
|
||||||
|
*********************/
|
||||||
|
|
||||||
|
/**********************
|
||||||
|
* TYPEDEFS
|
||||||
|
**********************/
|
||||||
|
|
||||||
|
typedef struct _lv_draw_vg_lite_unit_t {
|
||||||
|
lv_draw_unit_t base_unit;
|
||||||
|
struct _lv_draw_task_t * task_act;
|
||||||
|
vg_lite_buffer_t target_buffer;
|
||||||
|
vg_lite_matrix_t global_matrix;
|
||||||
|
lv_ll_t path_free_ll;
|
||||||
|
int path_max_cnt;
|
||||||
|
} lv_draw_vg_lite_unit_t;
|
||||||
|
|
||||||
|
/**********************
|
||||||
|
* GLOBAL PROTOTYPES
|
||||||
|
**********************/
|
||||||
|
|
||||||
|
/**********************
|
||||||
|
* MACROS
|
||||||
|
**********************/
|
||||||
|
|
||||||
|
#endif /*LV_USE_DRAW_VG_LITE*/
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
} /*extern "C"*/
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /*LV_VG_LITE_DRAW_H*/
|
||||||
317
src/draw/vg_lite/lv_draw_vg_lite_vector.c
Normal file
317
src/draw/vg_lite/lv_draw_vg_lite_vector.c
Normal file
@@ -0,0 +1,317 @@
|
|||||||
|
/**
|
||||||
|
* @file lv_draw_vg_lite_vector.c
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*********************
|
||||||
|
* INCLUDES
|
||||||
|
*********************/
|
||||||
|
|
||||||
|
#include "lv_draw_vg_lite.h"
|
||||||
|
|
||||||
|
#if LV_USE_DRAW_VG_LITE && LV_USE_VECTOR_GRAPHIC
|
||||||
|
|
||||||
|
#include "lv_draw_vg_lite_type.h"
|
||||||
|
#include "lv_vg_lite_path.h"
|
||||||
|
#include "lv_vg_lite_utils.h"
|
||||||
|
|
||||||
|
/*********************
|
||||||
|
* DEFINES
|
||||||
|
*********************/
|
||||||
|
|
||||||
|
/**********************
|
||||||
|
* TYPEDEFS
|
||||||
|
**********************/
|
||||||
|
|
||||||
|
/**********************
|
||||||
|
* STATIC PROTOTYPES
|
||||||
|
**********************/
|
||||||
|
|
||||||
|
static void task_draw_cb(void * ctx, const lv_vector_path_t * path, const lv_vector_draw_dsc_t * dsc);
|
||||||
|
static void lv_matrix_to_vg(vg_lite_matrix_t * desy, const lv_matrix_t * src);
|
||||||
|
static void lv_path_to_vg(lv_vg_lite_path_t * dest, const lv_vector_path_t * src);
|
||||||
|
static vg_lite_blend_t lv_blend_to_vg(lv_vector_blend_t blend);
|
||||||
|
static vg_lite_fill_t lv_fill_to_vg(lv_vector_fill_t fill_rule);
|
||||||
|
static vg_lite_gradient_spreadmode_t lv_spread_to_vg(lv_vector_gradient_spread_t spread);
|
||||||
|
|
||||||
|
/**********************
|
||||||
|
* STATIC VARIABLES
|
||||||
|
**********************/
|
||||||
|
|
||||||
|
/**********************
|
||||||
|
* MACROS
|
||||||
|
**********************/
|
||||||
|
|
||||||
|
/**********************
|
||||||
|
* GLOBAL FUNCTIONS
|
||||||
|
**********************/
|
||||||
|
|
||||||
|
void lv_draw_vg_lite_vector(lv_draw_unit_t * draw_unit, const lv_draw_vector_task_dsc_t * dsc)
|
||||||
|
{
|
||||||
|
if(dsc->task_list == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
lv_layer_t * layer = dsc->base.layer;
|
||||||
|
if(layer->buf == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
_lv_vector_for_each_destroy_tasks(dsc->task_list, task_draw_cb, draw_unit);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**********************
|
||||||
|
* STATIC FUNCTIONS
|
||||||
|
**********************/
|
||||||
|
|
||||||
|
static vg_lite_color_t lv_color32_to_vg(lv_color32_t color, lv_opa_t opa)
|
||||||
|
{
|
||||||
|
uint8_t a = LV_OPA_MIX2(color.alpha, opa);
|
||||||
|
if(a < LV_OPA_MAX) {
|
||||||
|
color.red = LV_UDIV255(color.red * opa);
|
||||||
|
color.green = LV_UDIV255(color.green * opa);
|
||||||
|
color.blue = LV_UDIV255(color.blue * opa);
|
||||||
|
}
|
||||||
|
return (uint32_t)a << 24 | (uint32_t)color.blue << 16 | (uint32_t)color.green << 8 | color.red;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void task_draw_cb(void * ctx, const lv_vector_path_t * path, const lv_vector_draw_dsc_t * dsc)
|
||||||
|
{
|
||||||
|
lv_draw_vg_lite_unit_t * u = ctx;
|
||||||
|
LV_VG_LITE_ASSERT_DEST_BUFFER(&u->target_buffer);
|
||||||
|
|
||||||
|
/* clear area */
|
||||||
|
if(!path) {
|
||||||
|
/* clear color needs to ignore fill_dsc.opa */
|
||||||
|
vg_lite_color_t c = lv_color32_to_vg(dsc->fill_dsc.color, LV_OPA_COVER);
|
||||||
|
vg_lite_rectangle_t rect;
|
||||||
|
lv_vg_lite_rect(&rect, &dsc->scissor_area);
|
||||||
|
LV_VG_LITE_CHECK_ERROR(vg_lite_clear(&u->target_buffer, &rect, c));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* set scissor area */
|
||||||
|
lv_vg_lite_set_scissor_area(&dsc->scissor_area);
|
||||||
|
|
||||||
|
/* convert color */
|
||||||
|
vg_lite_color_t vg_color = lv_color32_to_vg(dsc->fill_dsc.color, dsc->fill_dsc.opa);
|
||||||
|
|
||||||
|
/* transform matrix */
|
||||||
|
vg_lite_matrix_t matrix;
|
||||||
|
lv_matrix_to_vg(&matrix, &dsc->matrix);
|
||||||
|
|
||||||
|
/* convert path */
|
||||||
|
lv_vg_lite_path_t * lv_vg_path = lv_vg_lite_path_get(u, VG_LITE_FP32);
|
||||||
|
lv_path_to_vg(lv_vg_path, path);
|
||||||
|
vg_lite_path_t * vg_path = lv_vg_lite_path_get_path(lv_vg_path);
|
||||||
|
LV_VG_LITE_ASSERT_PATH(vg_path);
|
||||||
|
|
||||||
|
/* convert blend mode and fill rule */
|
||||||
|
vg_lite_blend_t blend = lv_blend_to_vg(dsc->blend_mode);
|
||||||
|
vg_lite_fill_t fill = lv_fill_to_vg(dsc->fill_dsc.fill_rule);
|
||||||
|
|
||||||
|
/* get path bounds */
|
||||||
|
float min_x, min_y, max_x, max_y;
|
||||||
|
lv_vg_lite_path_get_bonding_box(lv_vg_path, &min_x, &min_y, &max_x, &max_y);
|
||||||
|
|
||||||
|
switch(dsc->fill_dsc.style) {
|
||||||
|
case LV_VECTOR_DRAW_STYLE_SOLID: {
|
||||||
|
/* normal draw shape */
|
||||||
|
LV_VG_LITE_CHECK_ERROR(vg_lite_draw(
|
||||||
|
&u->target_buffer,
|
||||||
|
vg_path,
|
||||||
|
fill,
|
||||||
|
&matrix,
|
||||||
|
blend,
|
||||||
|
vg_color));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case LV_VECTOR_DRAW_STYLE_PATTERN: {
|
||||||
|
/* draw image */
|
||||||
|
vg_lite_buffer_t image_buffer;
|
||||||
|
lv_image_decoder_dsc_t decoder_dsc;
|
||||||
|
if(lv_vg_lite_buffer_open_image(&image_buffer, &decoder_dsc, dsc->fill_dsc.img_dsc.src)) {
|
||||||
|
lv_matrix_t m = dsc->matrix;
|
||||||
|
lv_matrix_translate(&m, min_x, min_y);
|
||||||
|
lv_matrix_multiply(&m, &dsc->fill_dsc.matrix);
|
||||||
|
|
||||||
|
vg_lite_matrix_t src_matrix;
|
||||||
|
lv_matrix_to_vg(&src_matrix, &m);
|
||||||
|
|
||||||
|
vg_lite_matrix_t path_matrix;
|
||||||
|
vg_lite_identity(&path_matrix);
|
||||||
|
|
||||||
|
vg_lite_color_t recolor = lv_vg_lite_color(dsc->fill_dsc.img_dsc.recolor, dsc->fill_dsc.img_dsc.recolor_opa, true);
|
||||||
|
|
||||||
|
LV_VG_LITE_CHECK_ERROR(vg_lite_draw_pattern(
|
||||||
|
&u->target_buffer,
|
||||||
|
vg_path,
|
||||||
|
fill,
|
||||||
|
&path_matrix,
|
||||||
|
&image_buffer,
|
||||||
|
&src_matrix,
|
||||||
|
blend,
|
||||||
|
VG_LITE_PATTERN_COLOR,
|
||||||
|
recolor,
|
||||||
|
vg_color,
|
||||||
|
VG_LITE_FILTER_BI_LINEAR));
|
||||||
|
lv_image_decoder_close(&decoder_dsc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case LV_VECTOR_DRAW_STYLE_GRADIENT: {
|
||||||
|
/* draw gradient */
|
||||||
|
lv_area_t grad_area;
|
||||||
|
lv_area_set(&grad_area, min_x, min_y, max_x, max_y);
|
||||||
|
lv_vector_gradient_style_t style = dsc->fill_dsc.gradient.style;
|
||||||
|
vg_lite_gradient_spreadmode_t spreadmode = lv_spread_to_vg(dsc->fill_dsc.gradient.spread);
|
||||||
|
LV_UNUSED(spreadmode);
|
||||||
|
|
||||||
|
if(style == LV_VECTOR_GRADIENT_STYLE_LINEAR) {
|
||||||
|
lv_vg_lite_draw_linear_grad(
|
||||||
|
&u->target_buffer,
|
||||||
|
vg_path,
|
||||||
|
&grad_area,
|
||||||
|
&dsc->fill_dsc.gradient.grad,
|
||||||
|
&matrix,
|
||||||
|
fill,
|
||||||
|
blend);
|
||||||
|
}
|
||||||
|
else if(style == LV_VECTOR_GRADIENT_STYLE_RADIAL) {
|
||||||
|
if(vg_lite_query_feature(gcFEATURE_BIT_VG_RADIAL_GRADIENT)) {
|
||||||
|
/* TODO: radial gradient */
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
LV_LOG_WARN("radial gradient is not supported");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
LV_LOG_WARN("unknown style: %d", dsc->fill_dsc.style);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* drop path */
|
||||||
|
lv_vg_lite_path_drop(u, lv_vg_path);
|
||||||
|
|
||||||
|
/* disable scissor */
|
||||||
|
lv_vg_lite_disable_scissor();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void lv_matrix_to_vg(vg_lite_matrix_t * dest, const lv_matrix_t * src)
|
||||||
|
{
|
||||||
|
lv_memcpy(dest, src, sizeof(lv_matrix_t));
|
||||||
|
}
|
||||||
|
|
||||||
|
static vg_lite_quality_t lv_quality_to_vg(lv_vector_path_quality_t quality)
|
||||||
|
{
|
||||||
|
switch(quality) {
|
||||||
|
case LV_VECTOR_PATH_QUALITY_LOW:
|
||||||
|
return VG_LITE_LOW;
|
||||||
|
case LV_VECTOR_PATH_QUALITY_MEDIUM:
|
||||||
|
return VG_LITE_MEDIUM;
|
||||||
|
case LV_VECTOR_PATH_QUALITY_HIGH:
|
||||||
|
return VG_LITE_HIGH;
|
||||||
|
default:
|
||||||
|
return VG_LITE_MEDIUM;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void lv_path_to_vg(lv_vg_lite_path_t * dest, const lv_vector_path_t * src)
|
||||||
|
{
|
||||||
|
lv_vg_lite_path_set_quality(dest, lv_quality_to_vg(src->quality));
|
||||||
|
|
||||||
|
uint32_t pidx = 0;
|
||||||
|
for(uint32_t i = 0; i < src->ops.size; i++) {
|
||||||
|
lv_vector_path_op_t * op = LV_ARRAY_GET(&src->ops, i, uint8_t);
|
||||||
|
switch(*op) {
|
||||||
|
case LV_VECTOR_PATH_OP_MOVE_TO: {
|
||||||
|
lv_fpoint_t * pt = LV_ARRAY_GET(&src->points, pidx, lv_fpoint_t);
|
||||||
|
lv_vg_lite_path_move_to(dest, pt->x, pt->y);
|
||||||
|
pidx += 1;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case LV_VECTOR_PATH_OP_LINE_TO: {
|
||||||
|
lv_fpoint_t * pt = LV_ARRAY_GET(&src->points, pidx, lv_fpoint_t);
|
||||||
|
lv_vg_lite_path_line_to(dest, pt->x, pt->y);
|
||||||
|
pidx += 1;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case LV_VECTOR_PATH_OP_QUAD_TO: {
|
||||||
|
lv_fpoint_t * pt1 = LV_ARRAY_GET(&src->points, pidx, lv_fpoint_t);
|
||||||
|
lv_fpoint_t * pt2 = LV_ARRAY_GET(&src->points, pidx + 1, lv_fpoint_t);
|
||||||
|
lv_vg_lite_path_quad_to(dest, pt1->x, pt1->y, pt2->x, pt2->y);
|
||||||
|
pidx += 2;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case LV_VECTOR_PATH_OP_CUBIC_TO: {
|
||||||
|
lv_fpoint_t * pt1 = LV_ARRAY_GET(&src->points, pidx, lv_fpoint_t);
|
||||||
|
lv_fpoint_t * pt2 = LV_ARRAY_GET(&src->points, pidx + 1, lv_fpoint_t);
|
||||||
|
lv_fpoint_t * pt3 = LV_ARRAY_GET(&src->points, pidx + 2, lv_fpoint_t);
|
||||||
|
lv_vg_lite_path_cubic_to(dest, pt1->x, pt1->y, pt2->x, pt2->y, pt3->x, pt3->y);
|
||||||
|
pidx += 3;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case LV_VECTOR_PATH_OP_CLOSE: {
|
||||||
|
lv_vg_lite_path_close(dest);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
lv_vg_lite_path_end(dest);
|
||||||
|
lv_vg_lite_path_update_bonding_box(dest);
|
||||||
|
}
|
||||||
|
|
||||||
|
static vg_lite_blend_t lv_blend_to_vg(lv_vector_blend_t blend)
|
||||||
|
{
|
||||||
|
switch(blend) {
|
||||||
|
case LV_VECTOR_BLEND_SRC_OVER:
|
||||||
|
return VG_LITE_BLEND_SRC_OVER;
|
||||||
|
case LV_VECTOR_BLEND_SCREEN:
|
||||||
|
return VG_LITE_BLEND_SCREEN;
|
||||||
|
case LV_VECTOR_BLEND_MULTIPLY:
|
||||||
|
return VG_LITE_BLEND_MULTIPLY;
|
||||||
|
case LV_VECTOR_BLEND_NONE:
|
||||||
|
return VG_LITE_BLEND_NONE;
|
||||||
|
case LV_VECTOR_BLEND_ADDITIVE:
|
||||||
|
return VG_LITE_BLEND_ADDITIVE;
|
||||||
|
case LV_VECTOR_BLEND_SRC_IN:
|
||||||
|
return VG_LITE_BLEND_SRC_IN;
|
||||||
|
case LV_VECTOR_BLEND_DST_OVER:
|
||||||
|
return VG_LITE_BLEND_DST_OVER;
|
||||||
|
case LV_VECTOR_BLEND_DST_IN:
|
||||||
|
return VG_LITE_BLEND_DST_IN;
|
||||||
|
case LV_VECTOR_BLEND_SUBTRACTIVE:
|
||||||
|
return VG_LITE_BLEND_SUBTRACT;
|
||||||
|
default:
|
||||||
|
return VG_LITE_BLEND_SRC_OVER;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static vg_lite_fill_t lv_fill_to_vg(lv_vector_fill_t fill_rule)
|
||||||
|
{
|
||||||
|
switch(fill_rule) {
|
||||||
|
case LV_VECTOR_FILL_NONZERO:
|
||||||
|
return VG_LITE_FILL_NON_ZERO;
|
||||||
|
case LV_VECTOR_FILL_EVENODD:
|
||||||
|
return VG_LITE_FILL_EVEN_ODD;
|
||||||
|
default:
|
||||||
|
return VG_LITE_FILL_NON_ZERO;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static vg_lite_gradient_spreadmode_t lv_spread_to_vg(lv_vector_gradient_spread_t spread)
|
||||||
|
{
|
||||||
|
switch(spread) {
|
||||||
|
case LV_VECTOR_GRADIENT_SPREAD_PAD:
|
||||||
|
return VG_LITE_GRADIENT_SPREAD_PAD;
|
||||||
|
case LV_VECTOR_GRADIENT_SPREAD_REPEAT:
|
||||||
|
return VG_LITE_GRADIENT_SPREAD_REPEAT;
|
||||||
|
case LV_VECTOR_GRADIENT_SPREAD_REFLECT:
|
||||||
|
return VG_LITE_GRADIENT_SPREAD_REFLECT;
|
||||||
|
default:
|
||||||
|
return VG_LITE_GRADIENT_SPREAD_FILL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /*LV_USE_DRAW_VG_LITE && LV_USE_VECTOR_GRAPHIC*/
|
||||||
550
src/draw/vg_lite/lv_vg_lite_decoder.c
Normal file
550
src/draw/vg_lite/lv_vg_lite_decoder.c
Normal file
@@ -0,0 +1,550 @@
|
|||||||
|
/**
|
||||||
|
* @file lv_vg_lite_decoder.c
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*********************
|
||||||
|
* INCLUDES
|
||||||
|
*********************/
|
||||||
|
|
||||||
|
#include "lv_vg_lite_decoder.h"
|
||||||
|
|
||||||
|
#if LV_USE_DRAW_VG_LITE
|
||||||
|
|
||||||
|
#include "lv_vg_lite_utils.h"
|
||||||
|
|
||||||
|
/*********************
|
||||||
|
* DEFINES
|
||||||
|
*********************/
|
||||||
|
|
||||||
|
/**********************
|
||||||
|
* TYPEDEFS
|
||||||
|
**********************/
|
||||||
|
|
||||||
|
#pragma pack(1)
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
lv_color16_t c;
|
||||||
|
uint8_t alpha;
|
||||||
|
} lv_color16_alpha_t;
|
||||||
|
|
||||||
|
#pragma pack()
|
||||||
|
|
||||||
|
/**********************
|
||||||
|
* STATIC PROTOTYPES
|
||||||
|
**********************/
|
||||||
|
|
||||||
|
static lv_result_t decoder_info(lv_image_decoder_t * decoder, const void * src, lv_image_header_t * header);
|
||||||
|
static lv_result_t decoder_open(lv_image_decoder_t * decoder, lv_image_decoder_dsc_t * dsc,
|
||||||
|
const lv_image_decoder_args_t * args);
|
||||||
|
static void decode_close(lv_image_decoder_t * decoder, lv_image_decoder_dsc_t * dsc);
|
||||||
|
static void image_try_self_pre_mul(lv_image_decoder_dsc_t * dsc);
|
||||||
|
static void image_color32_pre_mul(lv_color32_t * img_data, uint32_t px_size);
|
||||||
|
static void image_color16_pre_mul(lv_color16_alpha_t * img_data, uint32_t px_size);
|
||||||
|
static void image_copy(uint8_t * dest, const uint8_t * src,
|
||||||
|
size_t dest_stride, size_t src_stride,
|
||||||
|
uint32_t height);
|
||||||
|
static void image_invalidate_cache(void * buf, uint32_t stride,
|
||||||
|
uint32_t width, uint32_t height,
|
||||||
|
lv_color_format_t cf);
|
||||||
|
static void cache_invalidate_cb(lv_cache_entry_t * entry);
|
||||||
|
|
||||||
|
/**********************
|
||||||
|
* STATIC VARIABLES
|
||||||
|
**********************/
|
||||||
|
|
||||||
|
/**********************
|
||||||
|
* MACROS
|
||||||
|
**********************/
|
||||||
|
|
||||||
|
/**********************
|
||||||
|
* GLOBAL FUNCTIONS
|
||||||
|
**********************/
|
||||||
|
|
||||||
|
void lv_vg_lite_decoder_init(void)
|
||||||
|
{
|
||||||
|
lv_image_decoder_t * decoder = lv_image_decoder_create();
|
||||||
|
lv_image_decoder_set_info_cb(decoder, decoder_info);
|
||||||
|
lv_image_decoder_set_open_cb(decoder, decoder_open);
|
||||||
|
lv_image_decoder_set_close_cb(decoder, decode_close);
|
||||||
|
decoder->cache_data_type = lv_cache_register_data_type();
|
||||||
|
}
|
||||||
|
|
||||||
|
void lv_vg_lite_decoder_deinit(void)
|
||||||
|
{
|
||||||
|
lv_image_decoder_t * dec = NULL;
|
||||||
|
while((dec = lv_image_decoder_get_next(dec)) != NULL) {
|
||||||
|
if(dec->info_cb == decoder_info) {
|
||||||
|
lv_image_decoder_delete(dec);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
lv_result_t lv_vg_lite_decoder_post_process(lv_image_decoder_dsc_t * dsc)
|
||||||
|
{
|
||||||
|
lv_color_format_t color_format = dsc->header.cf;
|
||||||
|
lv_result_t res = LV_RESULT_OK;
|
||||||
|
|
||||||
|
/* Only support this color format */
|
||||||
|
switch(color_format) {
|
||||||
|
case LV_COLOR_FORMAT_ARGB8888:
|
||||||
|
case LV_COLOR_FORMAT_XRGB8888:
|
||||||
|
case LV_COLOR_FORMAT_RGB565A8:
|
||||||
|
case LV_COLOR_FORMAT_RGB888:
|
||||||
|
case LV_COLOR_FORMAT_RGB565:
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return LV_RESULT_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
lv_cache_entry_t * entry = dsc->cache_entry;
|
||||||
|
if(!entry) {
|
||||||
|
LV_LOG_WARN("No detected cache entry, src_type: %d, src: %p",
|
||||||
|
dsc->src_type, dsc->src);
|
||||||
|
return LV_RESULT_INVALID;
|
||||||
|
}
|
||||||
|
|
||||||
|
lv_cache_lock();
|
||||||
|
|
||||||
|
/* Check if the image is aligned */
|
||||||
|
if(!(entry->process_state & LV_VG_LITE_IMAGE_FLAG_ALIGNED)) {
|
||||||
|
int32_t image_w = dsc->header.w;
|
||||||
|
int32_t image_h = dsc->header.h;
|
||||||
|
uint32_t width_byte = image_w * lv_color_format_get_size(color_format);
|
||||||
|
uint32_t stride = lv_draw_buf_width_to_stride(image_w, color_format);
|
||||||
|
|
||||||
|
const uint8_t * ori_image = lv_cache_get_data(entry);
|
||||||
|
|
||||||
|
/* Check stride alignment requirements */
|
||||||
|
bool is_aligned = (stride == width_byte)
|
||||||
|
&& (ori_image == lv_draw_buf_align((void *)ori_image, color_format));
|
||||||
|
|
||||||
|
if(!is_aligned) {
|
||||||
|
/* alloc new image */
|
||||||
|
size_t size_bytes = stride * dsc->header.h;
|
||||||
|
uint8_t * new_image = lv_draw_buf_malloc(size_bytes, color_format);
|
||||||
|
if(!new_image) {
|
||||||
|
LV_LOG_ERROR("alloc %zu failed, cf = %d", size_bytes, color_format);
|
||||||
|
res = LV_RESULT_INVALID;
|
||||||
|
goto alloc_failed;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Replace the image data pointer */
|
||||||
|
entry->data = new_image;
|
||||||
|
dsc->img_data = new_image;
|
||||||
|
|
||||||
|
/* Copy image data */
|
||||||
|
image_copy(new_image, ori_image, stride, width_byte, image_h);
|
||||||
|
|
||||||
|
/* invalidate D-Cache */
|
||||||
|
image_invalidate_cache(new_image, stride, image_w, image_h, color_format);
|
||||||
|
|
||||||
|
/* free memory for old image */
|
||||||
|
lv_draw_buf_free((void *)ori_image);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
LV_LOG_INFO("no need to realign stride: %" LV_PRIu32, stride);
|
||||||
|
}
|
||||||
|
|
||||||
|
entry->process_state |= LV_VG_LITE_IMAGE_FLAG_ALIGNED;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Since image_try_self_pre_mul requires width alignment,
|
||||||
|
* premul alpha is placed after the image width alignment process.
|
||||||
|
*/
|
||||||
|
image_try_self_pre_mul(dsc);
|
||||||
|
|
||||||
|
alloc_failed:
|
||||||
|
lv_cache_unlock();
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**********************
|
||||||
|
* STATIC FUNCTIONS
|
||||||
|
**********************/
|
||||||
|
|
||||||
|
static lv_result_t try_cache(lv_image_decoder_dsc_t * dsc)
|
||||||
|
{
|
||||||
|
lv_cache_lock();
|
||||||
|
if(dsc->src_type == LV_IMAGE_SRC_FILE) {
|
||||||
|
const char * fn = dsc->src;
|
||||||
|
|
||||||
|
lv_cache_entry_t * cache = lv_cache_find_by_src(NULL, fn, LV_CACHE_SRC_TYPE_PATH);
|
||||||
|
if(cache) {
|
||||||
|
dsc->img_data = lv_cache_get_data(cache);
|
||||||
|
dsc->cache_entry = cache; /*Save the cache to release it in decoder_close*/
|
||||||
|
lv_cache_unlock();
|
||||||
|
return LV_RESULT_OK;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(dsc->src_type == LV_IMAGE_SRC_VARIABLE) {
|
||||||
|
lv_cache_entry_t * cache = lv_cache_find_by_src(NULL, dsc->src, LV_CACHE_SRC_TYPE_POINTER);
|
||||||
|
if(cache) {
|
||||||
|
dsc->img_data = lv_cache_get_data(cache);
|
||||||
|
dsc->cache_entry = cache;
|
||||||
|
lv_cache_unlock();
|
||||||
|
return LV_RESULT_OK;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
lv_cache_unlock();
|
||||||
|
return LV_RESULT_INVALID;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void image_color32_pre_mul(lv_color32_t * img_data, uint32_t px_size)
|
||||||
|
{
|
||||||
|
while(px_size--) {
|
||||||
|
img_data->red = LV_UDIV255(img_data->red * img_data->alpha);
|
||||||
|
img_data->green = LV_UDIV255(img_data->green * img_data->alpha);
|
||||||
|
img_data->blue = LV_UDIV255(img_data->blue * img_data->alpha);
|
||||||
|
img_data++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void image_color16_pre_mul(lv_color16_alpha_t * img_data, uint32_t px_size)
|
||||||
|
{
|
||||||
|
while(px_size--) {
|
||||||
|
img_data->c.red = LV_UDIV255(img_data->c.red * img_data->alpha);
|
||||||
|
img_data->c.green = LV_UDIV255(img_data->c.green * img_data->alpha);
|
||||||
|
img_data->c.blue = LV_UDIV255(img_data->c.blue * img_data->alpha);
|
||||||
|
img_data++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void image_try_self_pre_mul(lv_image_decoder_dsc_t * dsc)
|
||||||
|
{
|
||||||
|
/* !!! WARNING !!!
|
||||||
|
* self-premultiplied images
|
||||||
|
* should be width-aligned and in modifiable RAM
|
||||||
|
*/
|
||||||
|
if(lv_vg_lite_support_blend_normal()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(dsc->cache_entry->process_state & LV_VG_LITE_IMAGE_FLAG_PRE_MUL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
lv_color_format_t cf = dsc->header.cf;
|
||||||
|
if(!lv_color_format_has_alpha(cf)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t image_w = dsc->header.w;
|
||||||
|
int32_t image_h = dsc->header.h;
|
||||||
|
uint32_t stride = lv_draw_buf_width_to_stride(image_w, cf);
|
||||||
|
uint32_t aligned_w = lv_vg_lite_width_align(image_w);
|
||||||
|
size_t px_size = aligned_w * image_h;
|
||||||
|
|
||||||
|
if(cf == LV_COLOR_FORMAT_ARGB8888) {
|
||||||
|
image_color32_pre_mul((lv_color32_t *)dsc->img_data, px_size);
|
||||||
|
}
|
||||||
|
else if(cf == LV_COLOR_FORMAT_RGB565A8) {
|
||||||
|
image_color16_pre_mul((lv_color16_alpha_t *)dsc->img_data, px_size);
|
||||||
|
}
|
||||||
|
else if(LV_COLOR_FORMAT_IS_INDEXED(cf)) {
|
||||||
|
lv_color32_t * palette = (lv_color32_t *)dsc->img_data;
|
||||||
|
uint32_t palette_size = LV_COLOR_INDEXED_PALETTE_SIZE(cf);
|
||||||
|
image_color32_pre_mul(palette, palette_size);
|
||||||
|
}
|
||||||
|
else if(LV_COLOR_FORMAT_IS_ALPHA_ONLY(cf)) {
|
||||||
|
/* do nothing */
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
LV_LOG_WARN("unsupported cf: %d", cf);
|
||||||
|
}
|
||||||
|
|
||||||
|
image_invalidate_cache((void *)dsc->img_data, stride, image_w, image_h, cf);
|
||||||
|
|
||||||
|
dsc->cache_entry->process_state |= LV_VG_LITE_IMAGE_FLAG_PRE_MUL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void image_copy(uint8_t * dest, const uint8_t * src,
|
||||||
|
size_t dest_stride, size_t src_stride,
|
||||||
|
uint32_t height)
|
||||||
|
{
|
||||||
|
for(uint32_t y = 0; y < height; y++) {
|
||||||
|
lv_memcpy(dest, src, src_stride);
|
||||||
|
src += src_stride;
|
||||||
|
dest += dest_stride;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void image_invalidate_cache(void * buf, uint32_t stride,
|
||||||
|
uint32_t width, uint32_t height,
|
||||||
|
lv_color_format_t cf)
|
||||||
|
{
|
||||||
|
width = lv_vg_lite_width_align(width);
|
||||||
|
lv_area_t image_area;
|
||||||
|
lv_area_set(&image_area, 0, 0, width - 1, height - 1);
|
||||||
|
lv_draw_buf_invalidate_cache(buf, stride, cf, &image_area);
|
||||||
|
}
|
||||||
|
|
||||||
|
static lv_result_t decoder_info(lv_image_decoder_t * decoder, const void * src, lv_image_header_t * header)
|
||||||
|
{
|
||||||
|
return lv_bin_decoder_info(decoder, src, header);
|
||||||
|
}
|
||||||
|
|
||||||
|
static lv_result_t decoder_open_variable(lv_image_decoder_t * decoder, lv_image_decoder_dsc_t * dsc)
|
||||||
|
{
|
||||||
|
LV_UNUSED(decoder); /*Unused*/
|
||||||
|
|
||||||
|
lv_color_format_t cf = dsc->header.cf;
|
||||||
|
int32_t width = dsc->header.w;
|
||||||
|
int32_t height = dsc->header.h;
|
||||||
|
|
||||||
|
/* native stride */
|
||||||
|
uint32_t width_byte;
|
||||||
|
width_byte = width * lv_color_format_get_bpp(cf);
|
||||||
|
width_byte = (width_byte + 7) >> 3; /*Round up*/
|
||||||
|
|
||||||
|
bool support_blend_normal = lv_vg_lite_support_blend_normal();
|
||||||
|
|
||||||
|
uint32_t start = lv_tick_get();
|
||||||
|
|
||||||
|
/*In case of uncompressed formats the image stored in the ROM/RAM.
|
||||||
|
*So simply give its pointer*/
|
||||||
|
const uint8_t * image_data = ((lv_image_dsc_t *)dsc->src)->data;
|
||||||
|
|
||||||
|
bool has_alpha = lv_color_format_has_alpha(cf);
|
||||||
|
bool is_indexed = LV_COLOR_FORMAT_IS_INDEXED(cf);
|
||||||
|
bool is_addr_aligned = (image_data == lv_draw_buf_align((void *)image_data, cf)) ? true : false;
|
||||||
|
|
||||||
|
uint32_t stride = lv_draw_buf_width_to_stride(width, cf);
|
||||||
|
bool is_stride_aligned = (stride == width_byte) ? true : false;
|
||||||
|
|
||||||
|
/* When the following conditions are met,
|
||||||
|
* there is no need to copy image resource preprocessing.
|
||||||
|
*/
|
||||||
|
if(is_addr_aligned
|
||||||
|
&& is_stride_aligned
|
||||||
|
&& !is_indexed
|
||||||
|
&& (!has_alpha || (has_alpha && support_blend_normal))) {
|
||||||
|
|
||||||
|
/*add cache*/
|
||||||
|
lv_cache_lock();
|
||||||
|
lv_cache_entry_t * cache = lv_cache_add(image_data, 0, decoder->cache_data_type, 1);
|
||||||
|
cache->process_state = LV_VG_LITE_IMAGE_FLAG_ALIGNED;
|
||||||
|
cache->weight = lv_tick_elaps(start);
|
||||||
|
cache->src_type = LV_CACHE_SRC_TYPE_POINTER;
|
||||||
|
cache->src = dsc->src;
|
||||||
|
|
||||||
|
dsc->cache_entry = cache;
|
||||||
|
dsc->img_data = lv_cache_get_data(cache);
|
||||||
|
lv_cache_unlock();
|
||||||
|
return LV_RESULT_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t palette_size = LV_COLOR_INDEXED_PALETTE_SIZE(cf);
|
||||||
|
uint32_t palette_size_bytes = palette_size * sizeof(lv_color32_t);
|
||||||
|
|
||||||
|
/* Since the palette and index image are next to each other,
|
||||||
|
* the palette size needs to be aligned to ensure that the image is aligned.
|
||||||
|
*/
|
||||||
|
uint32_t palette_size_bytes_aligned = LV_VG_LITE_ALIGN(palette_size_bytes, LV_VG_LITE_BUF_ALIGN);
|
||||||
|
|
||||||
|
size_t image_size = height * stride + palette_size_bytes_aligned;
|
||||||
|
|
||||||
|
void * image_buf = lv_draw_buf_malloc(image_size, cf);
|
||||||
|
if(image_buf == NULL) {
|
||||||
|
LV_LOG_ERROR("alloc %zu failed, cf = %d", image_size, cf);
|
||||||
|
return LV_RESULT_INVALID;
|
||||||
|
}
|
||||||
|
|
||||||
|
const uint8_t * src = image_data;
|
||||||
|
uint8_t * dest = image_buf;
|
||||||
|
|
||||||
|
/* copy palette */
|
||||||
|
if(palette_size_bytes) {
|
||||||
|
lv_memcpy(dest, src, palette_size_bytes);
|
||||||
|
src += palette_size_bytes;
|
||||||
|
|
||||||
|
/* move to align size */
|
||||||
|
dest += palette_size_bytes_aligned;
|
||||||
|
}
|
||||||
|
|
||||||
|
image_copy(dest, src, stride, width_byte, height);
|
||||||
|
|
||||||
|
lv_cache_lock();
|
||||||
|
lv_cache_entry_t * cache = lv_cache_add(image_buf, 0, decoder->cache_data_type, image_size);
|
||||||
|
|
||||||
|
dsc->img_data = lv_cache_get_data(cache);
|
||||||
|
dsc->cache_entry = cache;
|
||||||
|
|
||||||
|
/* premul alpha */
|
||||||
|
image_try_self_pre_mul(dsc);
|
||||||
|
|
||||||
|
/* invalidate D-Cache */
|
||||||
|
image_invalidate_cache(image_buf, stride, width, height, cf);
|
||||||
|
|
||||||
|
cache->process_state |= LV_VG_LITE_IMAGE_FLAG_ALLOCED | LV_VG_LITE_IMAGE_FLAG_ALIGNED;
|
||||||
|
cache->weight = lv_tick_elaps(start);
|
||||||
|
cache->src_type = LV_CACHE_SRC_TYPE_POINTER;
|
||||||
|
cache->src = dsc->src;
|
||||||
|
lv_cache_unlock();
|
||||||
|
|
||||||
|
LV_LOG_INFO("image %p (W%" LV_PRId32 " x H%" LV_PRId32 ", buffer: %p, cf: %d) decode finish %" LV_PRIu32 "ms",
|
||||||
|
image_data, width, height, image_buf, cf, cache->weight);
|
||||||
|
return LV_RESULT_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static lv_result_t decoder_open_file(lv_image_decoder_t * decoder, lv_image_decoder_dsc_t * dsc)
|
||||||
|
{
|
||||||
|
LV_UNUSED(decoder); /*Unused*/
|
||||||
|
|
||||||
|
lv_color_format_t cf = dsc->header.cf;
|
||||||
|
int32_t width = dsc->header.w;
|
||||||
|
int32_t height = dsc->header.h;
|
||||||
|
const char * path = dsc->src;
|
||||||
|
|
||||||
|
uint32_t start = lv_tick_get();
|
||||||
|
|
||||||
|
lv_fs_file_t file;
|
||||||
|
lv_fs_res_t res = lv_fs_open(&file, path, LV_FS_MODE_RD);
|
||||||
|
if(res != LV_FS_RES_OK) {
|
||||||
|
LV_LOG_ERROR("open %s failed", path);
|
||||||
|
return LV_RESULT_INVALID;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* skip image header bytes */
|
||||||
|
res = lv_fs_seek(&file, sizeof(lv_image_header_t), LV_FS_SEEK_SET);
|
||||||
|
if(res != LV_FS_RES_OK) {
|
||||||
|
LV_LOG_ERROR("seek %s lv_image_header_t failed", path);
|
||||||
|
lv_fs_close(&file);
|
||||||
|
return LV_RESULT_INVALID;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* native stride */
|
||||||
|
uint32_t width_byte;
|
||||||
|
width_byte = width * lv_color_format_get_bpp(cf);
|
||||||
|
width_byte = (width_byte + 7) >> 3; /*Round up*/
|
||||||
|
|
||||||
|
bool support_blend_normal = lv_vg_lite_support_blend_normal();
|
||||||
|
|
||||||
|
uint32_t stride = lv_draw_buf_width_to_stride(width, cf);
|
||||||
|
|
||||||
|
uint32_t palette_size = LV_COLOR_INDEXED_PALETTE_SIZE(cf);
|
||||||
|
uint32_t palette_size_bytes = palette_size * sizeof(lv_color32_t);
|
||||||
|
|
||||||
|
/* Since the palette and index image are next to each other,
|
||||||
|
* the palette size needs to be aligned to ensure that the image is aligned.
|
||||||
|
*/
|
||||||
|
uint32_t palette_size_bytes_aligned = LV_VG_LITE_ALIGN(palette_size_bytes, LV_VG_LITE_BUF_ALIGN);
|
||||||
|
|
||||||
|
size_t image_size = height * stride + palette_size_bytes_aligned;
|
||||||
|
|
||||||
|
void * image_buf = lv_draw_buf_malloc(image_size, cf);
|
||||||
|
if(image_buf == NULL) {
|
||||||
|
LV_LOG_ERROR("alloc %zu failed, cf = %d", image_size, cf);
|
||||||
|
goto failed;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t * dest = image_buf;
|
||||||
|
|
||||||
|
/* copy palette */
|
||||||
|
if(palette_size_bytes) {
|
||||||
|
uint32_t br;
|
||||||
|
/* read palette */
|
||||||
|
res = lv_fs_read(&file, dest, palette_size_bytes, &br);
|
||||||
|
if(res != LV_FS_RES_OK || br != palette_size_bytes) {
|
||||||
|
LV_LOG_ERROR("read %s (palette: %" LV_PRIu32 ", br: %" LV_PRIu32 ") failed",
|
||||||
|
path, palette_size_bytes, br);
|
||||||
|
goto failed;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!support_blend_normal) {
|
||||||
|
image_color32_pre_mul((lv_color32_t *)image_buf, palette_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* move to index image map */
|
||||||
|
dest += palette_size_bytes_aligned;
|
||||||
|
}
|
||||||
|
|
||||||
|
for(uint32_t y = 0; y < height; y++) {
|
||||||
|
uint32_t br;
|
||||||
|
res = lv_fs_read(&file, dest, width_byte, &br);
|
||||||
|
if(res != LV_FS_RES_OK || br != width_byte) {
|
||||||
|
LV_LOG_ERROR("read %s (y: %" LV_PRIu32 ", width_byte: %" LV_PRIu32 ", br: %" LV_PRIu32 ") failed",
|
||||||
|
path, y, width_byte, br);
|
||||||
|
goto failed;
|
||||||
|
}
|
||||||
|
|
||||||
|
dest += stride;
|
||||||
|
}
|
||||||
|
|
||||||
|
lv_fs_close(&file);
|
||||||
|
|
||||||
|
lv_cache_lock();
|
||||||
|
lv_cache_entry_t * cache = lv_cache_add(image_buf, 0, decoder->cache_data_type, image_size);
|
||||||
|
|
||||||
|
dsc->cache_entry = cache;
|
||||||
|
dsc->img_data = lv_cache_get_data(cache);
|
||||||
|
|
||||||
|
/* premul alpha */
|
||||||
|
image_try_self_pre_mul(dsc);
|
||||||
|
|
||||||
|
/* invalidate D-Cache */
|
||||||
|
image_invalidate_cache(image_buf, stride, width, height, cf);
|
||||||
|
|
||||||
|
cache->process_state |= LV_VG_LITE_IMAGE_FLAG_ALLOCED | LV_VG_LITE_IMAGE_FLAG_ALIGNED;
|
||||||
|
cache->weight = lv_tick_elaps(start);
|
||||||
|
cache->invalidate_cb = cache_invalidate_cb;
|
||||||
|
cache->src = lv_strdup(dsc->src);
|
||||||
|
cache->src_type = LV_CACHE_SRC_TYPE_PATH;
|
||||||
|
lv_cache_unlock();
|
||||||
|
|
||||||
|
LV_LOG_INFO("image %s (W%" LV_PRId32 " x H%" LV_PRId32 ", buffer: %p cf: %d) decode finish %" LV_PRIu32 "ms",
|
||||||
|
path, width, height, image_buf, cf, cache->weight);
|
||||||
|
return LV_RESULT_OK;
|
||||||
|
|
||||||
|
failed:
|
||||||
|
lv_fs_close(&file);
|
||||||
|
|
||||||
|
if(image_buf) {
|
||||||
|
LV_LOG_INFO("free image_buf: %p", image_buf);
|
||||||
|
lv_draw_buf_free(image_buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
return LV_RESULT_INVALID;
|
||||||
|
}
|
||||||
|
|
||||||
|
static lv_result_t decoder_open(lv_image_decoder_t * decoder, lv_image_decoder_dsc_t * dsc,
|
||||||
|
const lv_image_decoder_args_t * args)
|
||||||
|
{
|
||||||
|
LV_UNUSED(args); /*Unused*/
|
||||||
|
|
||||||
|
/*Check the cache first*/
|
||||||
|
if(try_cache(dsc) == LV_RESULT_OK) {
|
||||||
|
return LV_RESULT_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch(dsc->src_type) {
|
||||||
|
case LV_IMAGE_SRC_VARIABLE:
|
||||||
|
return decoder_open_variable(decoder, dsc);
|
||||||
|
case LV_IMAGE_SRC_FILE:
|
||||||
|
return decoder_open_file(decoder, dsc);
|
||||||
|
}
|
||||||
|
|
||||||
|
return LV_RESULT_INVALID;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void decode_close(lv_image_decoder_t * decoder, lv_image_decoder_dsc_t * dsc)
|
||||||
|
{
|
||||||
|
LV_UNUSED(decoder); /*Unused*/
|
||||||
|
|
||||||
|
lv_cache_lock();
|
||||||
|
lv_cache_release(dsc->cache_entry);
|
||||||
|
lv_cache_unlock();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void cache_invalidate_cb(lv_cache_entry_t * entry)
|
||||||
|
{
|
||||||
|
if(entry->src_type == LV_CACHE_SRC_TYPE_PATH) lv_free((void *)entry->src);
|
||||||
|
lv_draw_buf_free((void *)entry->data);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /*LV_USE_DRAW_VG_LITE*/
|
||||||
49
src/draw/vg_lite/lv_vg_lite_decoder.h
Normal file
49
src/draw/vg_lite/lv_vg_lite_decoder.h
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
/**
|
||||||
|
* @file lv_vg_lite_decoder.h
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef LV_VG_LITE_DECODER_H
|
||||||
|
#define LV_VG_LITE_DECODER_H
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*********************
|
||||||
|
* INCLUDES
|
||||||
|
*********************/
|
||||||
|
|
||||||
|
#include "../lv_image_decoder.h"
|
||||||
|
|
||||||
|
#if LV_USE_DRAW_VG_LITE
|
||||||
|
|
||||||
|
/*********************
|
||||||
|
* DEFINES
|
||||||
|
*********************/
|
||||||
|
|
||||||
|
/**********************
|
||||||
|
* TYPEDEFS
|
||||||
|
**********************/
|
||||||
|
|
||||||
|
/**********************
|
||||||
|
* GLOBAL PROTOTYPES
|
||||||
|
**********************/
|
||||||
|
|
||||||
|
void lv_vg_lite_decoder_init(void);
|
||||||
|
|
||||||
|
void lv_vg_lite_decoder_deinit(void);
|
||||||
|
|
||||||
|
lv_result_t lv_vg_lite_decoder_post_process(lv_image_decoder_dsc_t * dsc);
|
||||||
|
|
||||||
|
/**********************
|
||||||
|
* MACROS
|
||||||
|
**********************/
|
||||||
|
|
||||||
|
#endif /*LV_USE_DRAW_VG_LITE*/
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
} /*extern "C"*/
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /*LV_VG_LITE_DECODER_H*/
|
||||||
60
src/draw/vg_lite/lv_vg_lite_math.c
Normal file
60
src/draw/vg_lite/lv_vg_lite_math.c
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
/**
|
||||||
|
* @file lv_vg_lite_math.h
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*********************
|
||||||
|
* INCLUDES
|
||||||
|
*********************/
|
||||||
|
|
||||||
|
#include "lv_vg_lite_math.h"
|
||||||
|
|
||||||
|
#if LV_USE_DRAW_VG_LITE
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
/*********************
|
||||||
|
* DEFINES
|
||||||
|
*********************/
|
||||||
|
|
||||||
|
/**********************
|
||||||
|
* TYPEDEFS
|
||||||
|
**********************/
|
||||||
|
|
||||||
|
/**********************
|
||||||
|
* STATIC PROTOTYPES
|
||||||
|
**********************/
|
||||||
|
|
||||||
|
/**********************
|
||||||
|
* STATIC VARIABLES
|
||||||
|
**********************/
|
||||||
|
|
||||||
|
/**********************
|
||||||
|
* MACROS
|
||||||
|
**********************/
|
||||||
|
|
||||||
|
/**********************
|
||||||
|
* GLOBAL FUNCTIONS
|
||||||
|
**********************/
|
||||||
|
|
||||||
|
float math_fast_inv_sqrtf(float number)
|
||||||
|
{
|
||||||
|
int32_t i;
|
||||||
|
float x2, y;
|
||||||
|
const float threehalfs = 1.5f;
|
||||||
|
|
||||||
|
x2 = number * 0.5f;
|
||||||
|
y = number;
|
||||||
|
i = *(int32_t *)&y; /* evil floating point bit level hacking */
|
||||||
|
i = 0x5f3759df - (i >> 1); /* what the fuck? */
|
||||||
|
y = *(float *)&i;
|
||||||
|
y = y * (threehalfs - (x2 * y * y)); /* 1st iteration */
|
||||||
|
|
||||||
|
return y;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**********************
|
||||||
|
* STATIC FUNCTIONS
|
||||||
|
**********************/
|
||||||
|
|
||||||
|
#endif /*LV_USE_DRAW_VG_LITE*/
|
||||||
75
src/draw/vg_lite/lv_vg_lite_math.h
Normal file
75
src/draw/vg_lite/lv_vg_lite_math.h
Normal file
@@ -0,0 +1,75 @@
|
|||||||
|
/**
|
||||||
|
* @file lv_vg_lite_math.h
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef LV_VG_LITE_MATH_H
|
||||||
|
#define LV_VG_LITE_MATH_H
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*********************
|
||||||
|
* INCLUDES
|
||||||
|
*********************/
|
||||||
|
|
||||||
|
#include "../../lv_conf_internal.h"
|
||||||
|
|
||||||
|
#if LV_USE_DRAW_VG_LITE
|
||||||
|
|
||||||
|
#include <math.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <float.h>
|
||||||
|
|
||||||
|
/*********************
|
||||||
|
* DEFINES
|
||||||
|
*********************/
|
||||||
|
|
||||||
|
#define MATH_PI 3.14159265358979323846f
|
||||||
|
#define MATH_HALF_PI 1.57079632679489661923f
|
||||||
|
#define MATH_TWO_PI 6.28318530717958647692f
|
||||||
|
#define DEG_TO_RAD 0.017453292519943295769236907684886
|
||||||
|
#define RAD_TO_DEG 57.295779513082320876798154814105
|
||||||
|
|
||||||
|
#define MATH_TANF(x) tanf(x)
|
||||||
|
#define MATH_SINF(x) sinf(x)
|
||||||
|
#define MATH_COSF(x) cosf(x)
|
||||||
|
#define MATH_ASINF(x) asinf(x)
|
||||||
|
#define MATH_FABSF(x) fabsf(x)
|
||||||
|
#define MATH_SQRTF(x) sqrtf(x)
|
||||||
|
|
||||||
|
#define MATH_RADIANS(deg) ((deg) * DEG_TO_RAD)
|
||||||
|
#define MATD_DEGRESS(rad) ((rad) * RAD_TO_DEG)
|
||||||
|
|
||||||
|
/**********************
|
||||||
|
* TYPEDEFS
|
||||||
|
**********************/
|
||||||
|
|
||||||
|
/**********************
|
||||||
|
* GLOBAL PROTOTYPES
|
||||||
|
**********************/
|
||||||
|
|
||||||
|
static inline bool math_zero(float a)
|
||||||
|
{
|
||||||
|
return (MATH_FABSF(a) < FLT_EPSILON);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline bool math_equal(float a, float b)
|
||||||
|
{
|
||||||
|
return math_zero(a - b);
|
||||||
|
}
|
||||||
|
|
||||||
|
float math_fast_inv_sqrtf(float number);
|
||||||
|
|
||||||
|
/**********************
|
||||||
|
* MACROS
|
||||||
|
**********************/
|
||||||
|
|
||||||
|
#endif /*LV_USE_DRAW_VG_LITE*/
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
} /*extern "C"*/
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /*LV_VG_LITE_MATH_H*/
|
||||||
606
src/draw/vg_lite/lv_vg_lite_path.c
Normal file
606
src/draw/vg_lite/lv_vg_lite_path.c
Normal file
@@ -0,0 +1,606 @@
|
|||||||
|
/**
|
||||||
|
* @file lv_vg_lite_path.c
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*********************
|
||||||
|
* INCLUDES
|
||||||
|
*********************/
|
||||||
|
|
||||||
|
#include "lv_vg_lite_path.h"
|
||||||
|
|
||||||
|
#if LV_USE_DRAW_VG_LITE
|
||||||
|
|
||||||
|
#include "lv_draw_vg_lite_type.h"
|
||||||
|
#include "lv_vg_lite_math.h"
|
||||||
|
#include <float.h>
|
||||||
|
|
||||||
|
/*********************
|
||||||
|
* DEFINES
|
||||||
|
*********************/
|
||||||
|
|
||||||
|
#define PATH_KAPPA 0.552284f
|
||||||
|
#define PATH_MAX_CNT 32
|
||||||
|
|
||||||
|
/* Magic number from https://spencermortensen.com/articles/bezier-circle/ */
|
||||||
|
#define PATH_ARC_MAGIC 0.55191502449351f
|
||||||
|
|
||||||
|
#define SIGN(x) (math_zero(x) ? 0 : ((x) > 0 ? 1 : -1))
|
||||||
|
|
||||||
|
#define VLC_OP_ARG_LEN(OP, LEN) \
|
||||||
|
case VLC_OP_##OP: \
|
||||||
|
return (LEN)
|
||||||
|
|
||||||
|
/**********************
|
||||||
|
* TYPEDEFS
|
||||||
|
**********************/
|
||||||
|
|
||||||
|
struct _lv_vg_lite_path_t {
|
||||||
|
vg_lite_path_t base;
|
||||||
|
size_t mem_size;
|
||||||
|
uint8_t format_len;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct _lv_vg_lite_path_t * lv_vg_lite_path_ref_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
float min_x;
|
||||||
|
float min_y;
|
||||||
|
float max_x;
|
||||||
|
float max_y;
|
||||||
|
} lv_vg_lite_path_bounds_t;
|
||||||
|
|
||||||
|
/**********************
|
||||||
|
* STATIC PROTOTYPES
|
||||||
|
**********************/
|
||||||
|
|
||||||
|
/**********************
|
||||||
|
* STATIC VARIABLES
|
||||||
|
**********************/
|
||||||
|
|
||||||
|
/**********************
|
||||||
|
* MACROS
|
||||||
|
**********************/
|
||||||
|
|
||||||
|
/**********************
|
||||||
|
* GLOBAL FUNCTIONS
|
||||||
|
**********************/
|
||||||
|
|
||||||
|
void lv_vg_lite_path_init(struct _lv_draw_vg_lite_unit_t * unit)
|
||||||
|
{
|
||||||
|
LV_ASSERT_NULL(unit);
|
||||||
|
_lv_ll_init(&unit->path_free_ll, sizeof(lv_vg_lite_path_ref_t));
|
||||||
|
}
|
||||||
|
|
||||||
|
void lv_vg_lite_path_deinit(struct _lv_draw_vg_lite_unit_t * unit)
|
||||||
|
{
|
||||||
|
LV_ASSERT_NULL(unit);
|
||||||
|
|
||||||
|
lv_ll_t * ll_p = &unit->path_free_ll;
|
||||||
|
lv_vg_lite_path_ref_t * path_ref;
|
||||||
|
|
||||||
|
_LV_LL_READ(ll_p, path_ref) {
|
||||||
|
lv_vg_lite_path_destroy(*path_ref);
|
||||||
|
}
|
||||||
|
|
||||||
|
_lv_ll_clear(ll_p);
|
||||||
|
}
|
||||||
|
|
||||||
|
lv_vg_lite_path_t * lv_vg_lite_path_create(vg_lite_format_t data_format)
|
||||||
|
{
|
||||||
|
lv_vg_lite_path_t * path = lv_malloc_zeroed(sizeof(lv_vg_lite_path_t));
|
||||||
|
LV_ASSERT_MALLOC(path);
|
||||||
|
path->format_len = lv_vg_lite_path_format_len(data_format);
|
||||||
|
LV_ASSERT(vg_lite_init_path(
|
||||||
|
&path->base,
|
||||||
|
data_format,
|
||||||
|
VG_LITE_MEDIUM,
|
||||||
|
0,
|
||||||
|
NULL,
|
||||||
|
0, 0, 0, 0)
|
||||||
|
== VG_LITE_SUCCESS);
|
||||||
|
return path;
|
||||||
|
}
|
||||||
|
|
||||||
|
void lv_vg_lite_path_destroy(lv_vg_lite_path_t * path)
|
||||||
|
{
|
||||||
|
LV_ASSERT_NULL(path);
|
||||||
|
if(path->base.path != NULL) {
|
||||||
|
lv_free(path->base.path);
|
||||||
|
path->base.path = NULL;
|
||||||
|
}
|
||||||
|
lv_free(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
lv_vg_lite_path_t * lv_vg_lite_path_get(struct _lv_draw_vg_lite_unit_t * unit, vg_lite_format_t data_format)
|
||||||
|
{
|
||||||
|
LV_ASSERT_NULL(unit);
|
||||||
|
|
||||||
|
unit->path_max_cnt++;
|
||||||
|
LV_ASSERT(unit->path_max_cnt < PATH_MAX_CNT);
|
||||||
|
|
||||||
|
lv_ll_t * ll_p = &unit->path_free_ll;
|
||||||
|
|
||||||
|
lv_vg_lite_path_ref_t * path_ref = _lv_ll_get_head(ll_p);
|
||||||
|
if(path_ref) {
|
||||||
|
lv_vg_lite_path_t * path = *path_ref;
|
||||||
|
lv_vg_lite_path_reset(path, data_format);
|
||||||
|
_lv_ll_remove(ll_p, path_ref);
|
||||||
|
lv_free(path_ref);
|
||||||
|
|
||||||
|
return path;
|
||||||
|
}
|
||||||
|
|
||||||
|
return lv_vg_lite_path_create(data_format);
|
||||||
|
}
|
||||||
|
|
||||||
|
void lv_vg_lite_path_drop(struct _lv_draw_vg_lite_unit_t * unit, lv_vg_lite_path_t * path)
|
||||||
|
{
|
||||||
|
LV_ASSERT_NULL(unit);
|
||||||
|
LV_ASSERT_NULL(path);
|
||||||
|
|
||||||
|
unit->path_max_cnt--;
|
||||||
|
LV_ASSERT(unit->path_max_cnt >= 0);
|
||||||
|
|
||||||
|
lv_ll_t * ll_p = &unit->path_free_ll;
|
||||||
|
|
||||||
|
uint32_t len = _lv_ll_get_len(ll_p);
|
||||||
|
if(len >= PATH_MAX_CNT) {
|
||||||
|
lv_vg_lite_path_ref_t * tail = _lv_ll_get_tail(ll_p);
|
||||||
|
lv_vg_lite_path_destroy(*tail);
|
||||||
|
_lv_ll_remove(ll_p, tail);
|
||||||
|
lv_free(tail);
|
||||||
|
}
|
||||||
|
|
||||||
|
lv_vg_lite_path_ref_t * head = _lv_ll_ins_head(ll_p);
|
||||||
|
LV_ASSERT_MALLOC(head);
|
||||||
|
*head = path;
|
||||||
|
}
|
||||||
|
|
||||||
|
void lv_vg_lite_path_reset(lv_vg_lite_path_t * path, vg_lite_format_t data_format)
|
||||||
|
{
|
||||||
|
LV_ASSERT_NULL(path);
|
||||||
|
lv_memzero(path->base.path, path->mem_size);
|
||||||
|
path->base.path_length = 0;
|
||||||
|
path->base.format = data_format;
|
||||||
|
path->base.quality = VG_LITE_MEDIUM;
|
||||||
|
path->format_len = lv_vg_lite_path_format_len(data_format);
|
||||||
|
}
|
||||||
|
|
||||||
|
vg_lite_path_t * lv_vg_lite_path_get_path(lv_vg_lite_path_t * path)
|
||||||
|
{
|
||||||
|
LV_ASSERT_NULL(path);
|
||||||
|
return &path->base;
|
||||||
|
}
|
||||||
|
|
||||||
|
void lv_vg_lite_path_set_bonding_box(lv_vg_lite_path_t * path,
|
||||||
|
float min_x, float min_y,
|
||||||
|
float max_x, float max_y)
|
||||||
|
{
|
||||||
|
LV_ASSERT_NULL(path);
|
||||||
|
path->base.bounding_box[0] = min_x;
|
||||||
|
path->base.bounding_box[1] = min_y;
|
||||||
|
path->base.bounding_box[2] = max_x;
|
||||||
|
path->base.bounding_box[3] = max_y;
|
||||||
|
}
|
||||||
|
|
||||||
|
void lv_vg_lite_path_set_bonding_box_area(lv_vg_lite_path_t * path, const lv_area_t * area)
|
||||||
|
{
|
||||||
|
LV_ASSERT_NULL(path);
|
||||||
|
LV_ASSERT_NULL(area);
|
||||||
|
lv_vg_lite_path_set_bonding_box(path, area->x1, area->y1, area->x2 + 1, area->y2 + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void lv_vg_lite_path_get_bonding_box(lv_vg_lite_path_t * path,
|
||||||
|
float * min_x, float * min_y,
|
||||||
|
float * max_x, float * max_y)
|
||||||
|
{
|
||||||
|
LV_ASSERT_NULL(path);
|
||||||
|
if(min_x) *min_x = path->base.bounding_box[0];
|
||||||
|
if(min_y) *min_y = path->base.bounding_box[1];
|
||||||
|
if(max_x) *max_x = path->base.bounding_box[2];
|
||||||
|
if(max_y) *max_y = path->base.bounding_box[3];
|
||||||
|
}
|
||||||
|
|
||||||
|
static void path_bounds_iter_cb(void * user_data, uint8_t op_code, const float * data, uint32_t len)
|
||||||
|
{
|
||||||
|
if(len == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
float x;
|
||||||
|
float y;
|
||||||
|
} point_t;
|
||||||
|
|
||||||
|
const int pt_len = sizeof(point_t) / sizeof(float);
|
||||||
|
|
||||||
|
LV_ASSERT(len % pt_len == 0);
|
||||||
|
|
||||||
|
const point_t * pt = (point_t *)data;
|
||||||
|
len /= pt_len;
|
||||||
|
|
||||||
|
lv_vg_lite_path_bounds_t * bounds = user_data;
|
||||||
|
|
||||||
|
for(uint32_t i = 0; i < len; i++) {
|
||||||
|
if(pt[i].x < bounds->min_x) bounds->min_x = pt[i].x;
|
||||||
|
if(pt[i].y < bounds->min_y) bounds->min_y = pt[i].y;
|
||||||
|
if(pt[i].x > bounds->max_x) bounds->max_x = pt[i].x;
|
||||||
|
if(pt[i].y > bounds->max_y) bounds->max_y = pt[i].y;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool lv_vg_lite_path_update_bonding_box(lv_vg_lite_path_t * path)
|
||||||
|
{
|
||||||
|
LV_ASSERT_NULL(path);
|
||||||
|
|
||||||
|
if(!path->format_len) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
lv_vg_lite_path_bounds_t bounds;
|
||||||
|
|
||||||
|
/* init bounds */
|
||||||
|
bounds.min_x = __FLT_MAX__;
|
||||||
|
bounds.min_y = __FLT_MAX__;
|
||||||
|
bounds.max_x = __FLT_MIN__;
|
||||||
|
bounds.max_y = __FLT_MIN__;
|
||||||
|
|
||||||
|
/* calc bounds */
|
||||||
|
lv_vg_lite_path_for_each_data(lv_vg_lite_path_get_path(path), path_bounds_iter_cb, &bounds);
|
||||||
|
|
||||||
|
/* set bounds */
|
||||||
|
lv_vg_lite_path_set_bonding_box(path, bounds.min_x, bounds.min_y, bounds.max_x, bounds.max_y);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void lv_vg_lite_path_set_quality(lv_vg_lite_path_t * path, vg_lite_quality_t quality)
|
||||||
|
{
|
||||||
|
LV_ASSERT_NULL(path);
|
||||||
|
path->base.quality = quality;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void lv_vg_lite_path_append_data(lv_vg_lite_path_t * path, const void * data, size_t len)
|
||||||
|
{
|
||||||
|
LV_ASSERT_NULL(path);
|
||||||
|
LV_ASSERT_NULL(data);
|
||||||
|
|
||||||
|
if(path->base.path_length + len > path->mem_size) {
|
||||||
|
if(path->mem_size == 0) {
|
||||||
|
path->mem_size = len;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
path->mem_size *= 2;
|
||||||
|
}
|
||||||
|
path->base.path = lv_realloc(path->base.path, path->mem_size);
|
||||||
|
LV_ASSERT_MALLOC(path->base.path);
|
||||||
|
}
|
||||||
|
|
||||||
|
lv_memcpy((uint8_t *)path->base.path + path->base.path_length, data, len);
|
||||||
|
path->base.path_length += len;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void lv_vg_lite_path_append_op(lv_vg_lite_path_t * path, uint32_t op)
|
||||||
|
{
|
||||||
|
lv_vg_lite_path_append_data(path, &op, path->format_len);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void lv_vg_lite_path_append_point(lv_vg_lite_path_t * path, float x, float y)
|
||||||
|
{
|
||||||
|
if(path->base.format == VG_LITE_FP32) {
|
||||||
|
lv_vg_lite_path_append_data(path, &x, sizeof(x));
|
||||||
|
lv_vg_lite_path_append_data(path, &y, sizeof(y));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t ix = (int32_t)(x);
|
||||||
|
int32_t iy = (int32_t)(y);
|
||||||
|
lv_vg_lite_path_append_data(path, &ix, path->format_len);
|
||||||
|
lv_vg_lite_path_append_data(path, &iy, path->format_len);
|
||||||
|
}
|
||||||
|
|
||||||
|
void lv_vg_lite_path_move_to(lv_vg_lite_path_t * path,
|
||||||
|
float x, float y)
|
||||||
|
{
|
||||||
|
LV_ASSERT_NULL(path);
|
||||||
|
lv_vg_lite_path_append_op(path, VLC_OP_MOVE);
|
||||||
|
lv_vg_lite_path_append_point(path, x, y);
|
||||||
|
}
|
||||||
|
|
||||||
|
void lv_vg_lite_path_line_to(lv_vg_lite_path_t * path,
|
||||||
|
float x, float y)
|
||||||
|
{
|
||||||
|
LV_ASSERT_NULL(path);
|
||||||
|
lv_vg_lite_path_append_op(path, VLC_OP_LINE);
|
||||||
|
lv_vg_lite_path_append_point(path, x, y);
|
||||||
|
}
|
||||||
|
|
||||||
|
void lv_vg_lite_path_quad_to(lv_vg_lite_path_t * path,
|
||||||
|
float cx, float cy,
|
||||||
|
float x, float y)
|
||||||
|
{
|
||||||
|
LV_ASSERT_NULL(path);
|
||||||
|
lv_vg_lite_path_append_op(path, VLC_OP_QUAD);
|
||||||
|
lv_vg_lite_path_append_point(path, cx, cy);
|
||||||
|
lv_vg_lite_path_append_point(path, x, y);
|
||||||
|
}
|
||||||
|
|
||||||
|
void lv_vg_lite_path_cubic_to(lv_vg_lite_path_t * path,
|
||||||
|
float cx1, float cy1,
|
||||||
|
float cx2, float cy2,
|
||||||
|
float x, float y)
|
||||||
|
{
|
||||||
|
LV_ASSERT_NULL(path);
|
||||||
|
lv_vg_lite_path_append_op(path, VLC_OP_CUBIC);
|
||||||
|
lv_vg_lite_path_append_point(path, cx1, cy1);
|
||||||
|
lv_vg_lite_path_append_point(path, cx2, cy2);
|
||||||
|
lv_vg_lite_path_append_point(path, x, y);
|
||||||
|
}
|
||||||
|
|
||||||
|
void lv_vg_lite_path_close(lv_vg_lite_path_t * path)
|
||||||
|
{
|
||||||
|
LV_ASSERT_NULL(path);
|
||||||
|
lv_vg_lite_path_append_op(path, VLC_OP_CLOSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
void lv_vg_lite_path_end(lv_vg_lite_path_t * path)
|
||||||
|
{
|
||||||
|
LV_ASSERT_NULL(path);
|
||||||
|
lv_vg_lite_path_append_op(path, VLC_OP_END);
|
||||||
|
}
|
||||||
|
|
||||||
|
void lv_vg_lite_path_append_rect(
|
||||||
|
lv_vg_lite_path_t * path,
|
||||||
|
float x, float y,
|
||||||
|
float w, float h,
|
||||||
|
float rx, float ry)
|
||||||
|
{
|
||||||
|
const float half_w = w * 0.5f;
|
||||||
|
const float half_h = h * 0.5f;
|
||||||
|
|
||||||
|
/*clamping cornerRadius by minimum size*/
|
||||||
|
if(rx > half_w)
|
||||||
|
rx = half_w;
|
||||||
|
if(ry > half_h)
|
||||||
|
ry = half_h;
|
||||||
|
|
||||||
|
/*rectangle*/
|
||||||
|
if(rx == 0 && ry == 0) {
|
||||||
|
lv_vg_lite_path_move_to(path, x, y);
|
||||||
|
lv_vg_lite_path_line_to(path, x + w, y);
|
||||||
|
lv_vg_lite_path_line_to(path, x + w, y + h);
|
||||||
|
lv_vg_lite_path_line_to(path, x, y + h);
|
||||||
|
lv_vg_lite_path_close(path);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*circle*/
|
||||||
|
if(math_equal(rx, half_w) && math_equal(ry, half_h)) {
|
||||||
|
return lv_vg_lite_path_append_circle(path, x + (w * 0.5f), y + (h * 0.5f), rx, ry);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*rounded rectangle*/
|
||||||
|
float hrx = rx * 0.5f;
|
||||||
|
float hry = ry * 0.5f;
|
||||||
|
lv_vg_lite_path_move_to(path, x + rx, y);
|
||||||
|
lv_vg_lite_path_line_to(path, x + w - rx, y);
|
||||||
|
lv_vg_lite_path_cubic_to(path, x + w - rx + hrx, y, x + w, y + ry - hry, x + w, y + ry);
|
||||||
|
lv_vg_lite_path_line_to(path, x + w, y + h - ry);
|
||||||
|
lv_vg_lite_path_cubic_to(path, x + w, y + h - ry + hry, x + w - rx + hrx, y + h, x + w - rx, y + h);
|
||||||
|
lv_vg_lite_path_line_to(path, x + rx, y + h);
|
||||||
|
lv_vg_lite_path_cubic_to(path, x + rx - hrx, y + h, x, y + h - ry + hry, x, y + h - ry);
|
||||||
|
lv_vg_lite_path_line_to(path, x, y + ry);
|
||||||
|
lv_vg_lite_path_cubic_to(path, x, y + ry - hry, x + rx - hrx, y, x + rx, y);
|
||||||
|
lv_vg_lite_path_close(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
void lv_vg_lite_path_append_circle(
|
||||||
|
lv_vg_lite_path_t * path,
|
||||||
|
float cx, float cy,
|
||||||
|
float rx, float ry)
|
||||||
|
{
|
||||||
|
/* https://learn.microsoft.com/zh-cn/xamarin/xamarin-forms/user-interface/graphics/skiasharp/curves/beziers */
|
||||||
|
float rx_kappa = rx * PATH_KAPPA;
|
||||||
|
float ry_kappa = ry * PATH_KAPPA;
|
||||||
|
|
||||||
|
lv_vg_lite_path_move_to(path, cx, cy - ry);
|
||||||
|
lv_vg_lite_path_cubic_to(path, cx + rx_kappa, cy - ry, cx + rx, cy - ry_kappa, cx + rx, cy);
|
||||||
|
lv_vg_lite_path_cubic_to(path, cx + rx, cy + ry_kappa, cx + rx_kappa, cy + ry, cx, cy + ry);
|
||||||
|
lv_vg_lite_path_cubic_to(path, cx - rx_kappa, cy + ry, cx - rx, cy + ry_kappa, cx - rx, cy);
|
||||||
|
lv_vg_lite_path_cubic_to(path, cx - rx, cy - ry_kappa, cx - rx_kappa, cy - ry, cx, cy - ry);
|
||||||
|
lv_vg_lite_path_close(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
void lv_vg_lite_path_append_arc_right_angle(lv_vg_lite_path_t * path,
|
||||||
|
float start_x, float start_y,
|
||||||
|
float center_x, float center_y,
|
||||||
|
float end_x, float end_y)
|
||||||
|
{
|
||||||
|
float dx1 = center_x - start_x;
|
||||||
|
float dy1 = center_y - start_y;
|
||||||
|
float dx2 = end_x - center_x;
|
||||||
|
float dy2 = end_y - center_y;
|
||||||
|
|
||||||
|
float c = SIGN(dx1 * dy2 - dx2 * dy1) * PATH_ARC_MAGIC;
|
||||||
|
|
||||||
|
lv_vg_lite_path_cubic_to(path,
|
||||||
|
start_x - c * dy1, start_y + c * dx1,
|
||||||
|
end_x - c * dy2, end_y + c * dx2,
|
||||||
|
end_x, end_y);
|
||||||
|
}
|
||||||
|
|
||||||
|
void lv_vg_lite_path_append_arc(lv_vg_lite_path_t * path,
|
||||||
|
float cx, float cy,
|
||||||
|
float radius,
|
||||||
|
float start_angle,
|
||||||
|
float sweep,
|
||||||
|
bool pie)
|
||||||
|
{
|
||||||
|
/* just circle */
|
||||||
|
if(sweep >= 360.0f || sweep <= -360.0f) {
|
||||||
|
return lv_vg_lite_path_append_circle(path, cx, cy, radius, radius);
|
||||||
|
}
|
||||||
|
|
||||||
|
start_angle = (start_angle * MATH_PI) / 180.0f;
|
||||||
|
sweep = sweep * MATH_PI / 180.0f;
|
||||||
|
|
||||||
|
int n_curves = ceil(MATH_FABSF(sweep / MATH_HALF_PI));
|
||||||
|
int sweep_sign = (sweep < 0 ? -1 : 1);
|
||||||
|
float fract = fmodf(sweep, MATH_HALF_PI);
|
||||||
|
fract = (math_zero(fract)) ? MATH_HALF_PI * sweep_sign : fract;
|
||||||
|
|
||||||
|
/* Start from here */
|
||||||
|
float start_x = radius * MATH_COSF(start_angle);
|
||||||
|
float start_y = radius * MATH_SINF(start_angle);
|
||||||
|
|
||||||
|
if(pie) {
|
||||||
|
lv_vg_lite_path_move_to(path, cx, cy);
|
||||||
|
lv_vg_lite_path_line_to(path, start_x + cx, start_y + cy);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
lv_vg_lite_path_move_to(path, start_x + cx, start_y + cy);
|
||||||
|
}
|
||||||
|
|
||||||
|
for(int i = 0; i < n_curves; ++i) {
|
||||||
|
float end_angle = start_angle + ((i != n_curves - 1) ? MATH_HALF_PI * sweep_sign : fract);
|
||||||
|
float end_x = radius * MATH_COSF(end_angle);
|
||||||
|
float end_y = radius * MATH_SINF(end_angle);
|
||||||
|
|
||||||
|
/* variables needed to calculate bezier control points */
|
||||||
|
|
||||||
|
/** get bezier control points using article:
|
||||||
|
* (http://itc.ktu.lt/index.php/ITC/article/view/11812/6479)
|
||||||
|
*/
|
||||||
|
float ax = start_x;
|
||||||
|
float ay = start_y;
|
||||||
|
float bx = end_x;
|
||||||
|
float by = end_y;
|
||||||
|
float q1 = ax * ax + ay * ay;
|
||||||
|
float q2 = ax * bx + ay * by + q1;
|
||||||
|
float k2 = (4.0f / 3.0f) * ((MATH_SQRTF(2 * q1 * q2) - q2) / (ax * by - ay * bx));
|
||||||
|
|
||||||
|
/* Next start point is the current end point */
|
||||||
|
start_x = end_x;
|
||||||
|
start_y = end_y;
|
||||||
|
|
||||||
|
end_x += cx;
|
||||||
|
end_y += cy;
|
||||||
|
|
||||||
|
float ctrl1_x = ax - k2 * ay + cx;
|
||||||
|
float ctrl1_y = ay + k2 * ax + cy;
|
||||||
|
float ctrl2_x = bx + k2 * by + cx;
|
||||||
|
float ctrl2_y = by - k2 * bx + cy;
|
||||||
|
|
||||||
|
lv_vg_lite_path_cubic_to(path, ctrl1_x, ctrl1_y, ctrl2_x, ctrl2_y, end_x, end_y);
|
||||||
|
start_angle = end_angle;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(pie) {
|
||||||
|
lv_vg_lite_path_close(path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t lv_vg_lite_vlc_op_arg_len(uint8_t vlc_op)
|
||||||
|
{
|
||||||
|
switch(vlc_op) {
|
||||||
|
VLC_OP_ARG_LEN(END, 0);
|
||||||
|
VLC_OP_ARG_LEN(CLOSE, 0);
|
||||||
|
VLC_OP_ARG_LEN(MOVE, 2);
|
||||||
|
VLC_OP_ARG_LEN(MOVE_REL, 2);
|
||||||
|
VLC_OP_ARG_LEN(LINE, 2);
|
||||||
|
VLC_OP_ARG_LEN(LINE_REL, 2);
|
||||||
|
VLC_OP_ARG_LEN(QUAD, 4);
|
||||||
|
VLC_OP_ARG_LEN(QUAD_REL, 4);
|
||||||
|
VLC_OP_ARG_LEN(CUBIC, 6);
|
||||||
|
VLC_OP_ARG_LEN(CUBIC_REL, 6);
|
||||||
|
VLC_OP_ARG_LEN(SCCWARC, 5);
|
||||||
|
VLC_OP_ARG_LEN(SCCWARC_REL, 5);
|
||||||
|
VLC_OP_ARG_LEN(SCWARC, 5);
|
||||||
|
VLC_OP_ARG_LEN(SCWARC_REL, 5);
|
||||||
|
VLC_OP_ARG_LEN(LCCWARC, 5);
|
||||||
|
VLC_OP_ARG_LEN(LCCWARC_REL, 5);
|
||||||
|
VLC_OP_ARG_LEN(LCWARC, 5);
|
||||||
|
VLC_OP_ARG_LEN(LCWARC_REL, 5);
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
LV_LOG_ERROR("UNKNOW_VLC_OP: 0x%x", vlc_op);
|
||||||
|
LV_ASSERT(false);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t lv_vg_lite_path_format_len(vg_lite_format_t format)
|
||||||
|
{
|
||||||
|
switch(format) {
|
||||||
|
case VG_LITE_S8:
|
||||||
|
return 1;
|
||||||
|
case VG_LITE_S16:
|
||||||
|
return 2;
|
||||||
|
case VG_LITE_S32:
|
||||||
|
return 4;
|
||||||
|
case VG_LITE_FP32:
|
||||||
|
return 4;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
LV_LOG_ERROR("UNKNOW_FORMAT: %d", format);
|
||||||
|
LV_ASSERT(false);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void lv_vg_lite_path_for_each_data(const vg_lite_path_t * path, lv_vg_lite_path_iter_cb_t cb, void * user_data)
|
||||||
|
{
|
||||||
|
LV_ASSERT_NULL(path);
|
||||||
|
LV_ASSERT_NULL(cb);
|
||||||
|
|
||||||
|
uint8_t fmt_len = lv_vg_lite_path_format_len(path->format);
|
||||||
|
uint8_t * cur = path->path;
|
||||||
|
uint8_t * end = cur + path->path_length;
|
||||||
|
float tmp_data[8];
|
||||||
|
|
||||||
|
while(cur < end) {
|
||||||
|
/* get op code */
|
||||||
|
uint8_t op_code = VLC_GET_OP_CODE(cur);
|
||||||
|
|
||||||
|
/* get arguments length */
|
||||||
|
uint8_t arg_len = lv_vg_lite_vlc_op_arg_len(op_code);
|
||||||
|
|
||||||
|
/* skip op code */
|
||||||
|
cur += fmt_len;
|
||||||
|
|
||||||
|
/* print arguments */
|
||||||
|
for(uint8_t i = 0; i < arg_len; i++) {
|
||||||
|
switch(path->format) {
|
||||||
|
case VG_LITE_S8:
|
||||||
|
tmp_data[i] = *((int8_t *)cur);
|
||||||
|
break;
|
||||||
|
case VG_LITE_S16:
|
||||||
|
tmp_data[i] = *((int16_t *)cur);
|
||||||
|
break;
|
||||||
|
case VG_LITE_S32:
|
||||||
|
tmp_data[i] = *((int32_t *)cur);
|
||||||
|
break;
|
||||||
|
case VG_LITE_FP32:
|
||||||
|
tmp_data[i] = *((float *)cur);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
LV_LOG_ERROR("UNKNOW_FORMAT(%d)", path->format);
|
||||||
|
LV_ASSERT(false);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
cur += fmt_len;
|
||||||
|
}
|
||||||
|
|
||||||
|
cb(user_data, op_code, tmp_data, arg_len);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**********************
|
||||||
|
* STATIC FUNCTIONS
|
||||||
|
**********************/
|
||||||
|
|
||||||
|
#endif /*LV_USE_DRAW_VG_LITE*/
|
||||||
124
src/draw/vg_lite/lv_vg_lite_path.h
Normal file
124
src/draw/vg_lite/lv_vg_lite_path.h
Normal file
@@ -0,0 +1,124 @@
|
|||||||
|
/**
|
||||||
|
* @file lv_vg_lite_path.h
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef LV_VG_LITE_PATH_H
|
||||||
|
#define LV_VG_LITE_PATH_H
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*********************
|
||||||
|
* INCLUDES
|
||||||
|
*********************/
|
||||||
|
|
||||||
|
#include "lv_vg_lite_utils.h"
|
||||||
|
|
||||||
|
#if LV_USE_DRAW_VG_LITE
|
||||||
|
|
||||||
|
/*********************
|
||||||
|
* DEFINES
|
||||||
|
*********************/
|
||||||
|
|
||||||
|
typedef struct _lv_vg_lite_path_t lv_vg_lite_path_t;
|
||||||
|
struct _lv_draw_vg_lite_unit_t;
|
||||||
|
|
||||||
|
typedef void (*lv_vg_lite_path_iter_cb_t)(void * user_data, uint8_t op_code, const float * data, uint32_t len);
|
||||||
|
|
||||||
|
/**********************
|
||||||
|
* TYPEDEFS
|
||||||
|
**********************/
|
||||||
|
|
||||||
|
/**********************
|
||||||
|
* GLOBAL PROTOTYPES
|
||||||
|
**********************/
|
||||||
|
|
||||||
|
void lv_vg_lite_path_init(struct _lv_draw_vg_lite_unit_t * unit);
|
||||||
|
|
||||||
|
void lv_vg_lite_path_deinit(struct _lv_draw_vg_lite_unit_t * unit);
|
||||||
|
|
||||||
|
lv_vg_lite_path_t * lv_vg_lite_path_create(vg_lite_format_t data_format);
|
||||||
|
|
||||||
|
void lv_vg_lite_path_destroy(lv_vg_lite_path_t * path);
|
||||||
|
|
||||||
|
lv_vg_lite_path_t * lv_vg_lite_path_get(struct _lv_draw_vg_lite_unit_t * unit, vg_lite_format_t data_format);
|
||||||
|
|
||||||
|
void lv_vg_lite_path_drop(struct _lv_draw_vg_lite_unit_t * unit, lv_vg_lite_path_t * path);
|
||||||
|
|
||||||
|
void lv_vg_lite_path_reset(lv_vg_lite_path_t * path, vg_lite_format_t data_format);
|
||||||
|
|
||||||
|
void lv_vg_lite_path_set_bonding_box_area(lv_vg_lite_path_t * path, const lv_area_t * area);
|
||||||
|
|
||||||
|
void lv_vg_lite_path_set_bonding_box(lv_vg_lite_path_t * path,
|
||||||
|
float min_x, float min_y,
|
||||||
|
float max_x, float max_y);
|
||||||
|
|
||||||
|
void lv_vg_lite_path_get_bonding_box(lv_vg_lite_path_t * path,
|
||||||
|
float * min_x, float * min_y,
|
||||||
|
float * max_x, float * max_y);
|
||||||
|
|
||||||
|
bool lv_vg_lite_path_update_bonding_box(lv_vg_lite_path_t * path);
|
||||||
|
|
||||||
|
void lv_vg_lite_path_set_quality(lv_vg_lite_path_t * path, vg_lite_quality_t quality);
|
||||||
|
|
||||||
|
vg_lite_path_t * lv_vg_lite_path_get_path(lv_vg_lite_path_t * path);
|
||||||
|
|
||||||
|
void lv_vg_lite_path_move_to(lv_vg_lite_path_t * path,
|
||||||
|
float x, float y);
|
||||||
|
|
||||||
|
void lv_vg_lite_path_line_to(lv_vg_lite_path_t * path,
|
||||||
|
float x, float y);
|
||||||
|
|
||||||
|
void lv_vg_lite_path_quad_to(lv_vg_lite_path_t * path,
|
||||||
|
float cx, float cy,
|
||||||
|
float x, float y);
|
||||||
|
|
||||||
|
void lv_vg_lite_path_cubic_to(lv_vg_lite_path_t * path,
|
||||||
|
float cx1, float cy1,
|
||||||
|
float cx2, float cy2,
|
||||||
|
float x, float y);
|
||||||
|
|
||||||
|
void lv_vg_lite_path_close(lv_vg_lite_path_t * path);
|
||||||
|
|
||||||
|
void lv_vg_lite_path_end(lv_vg_lite_path_t * path);
|
||||||
|
|
||||||
|
void lv_vg_lite_path_append_rect(lv_vg_lite_path_t * path,
|
||||||
|
float x, float y,
|
||||||
|
float w, float h,
|
||||||
|
float rx, float ry);
|
||||||
|
|
||||||
|
void lv_vg_lite_path_append_circle(lv_vg_lite_path_t * path,
|
||||||
|
float cx, float cy,
|
||||||
|
float rx, float ry);
|
||||||
|
|
||||||
|
void lv_vg_lite_path_append_arc_right_angle(lv_vg_lite_path_t * path,
|
||||||
|
float start_x, float start_y,
|
||||||
|
float center_x, float center_y,
|
||||||
|
float end_x, float end_y);
|
||||||
|
|
||||||
|
void lv_vg_lite_path_append_arc(lv_vg_lite_path_t * path,
|
||||||
|
float cx, float cy,
|
||||||
|
float radius,
|
||||||
|
float start_angle,
|
||||||
|
float sweep,
|
||||||
|
bool pie);
|
||||||
|
|
||||||
|
uint8_t lv_vg_lite_vlc_op_arg_len(uint8_t vlc_op);
|
||||||
|
|
||||||
|
uint8_t lv_vg_lite_path_format_len(vg_lite_format_t format);
|
||||||
|
|
||||||
|
void lv_vg_lite_path_for_each_data(const vg_lite_path_t * path, lv_vg_lite_path_iter_cb_t cb, void * user_data);
|
||||||
|
|
||||||
|
/**********************
|
||||||
|
* MACROS
|
||||||
|
**********************/
|
||||||
|
|
||||||
|
#endif /*LV_USE_DRAW_VG_LITE*/
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
} /*extern "C"*/
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /*LV_VG_LITE_PATH_H*/
|
||||||
1070
src/draw/vg_lite/lv_vg_lite_utils.c
Normal file
1070
src/draw/vg_lite/lv_vg_lite_utils.c
Normal file
File diff suppressed because it is too large
Load Diff
188
src/draw/vg_lite/lv_vg_lite_utils.h
Normal file
188
src/draw/vg_lite/lv_vg_lite_utils.h
Normal file
@@ -0,0 +1,188 @@
|
|||||||
|
/**
|
||||||
|
* @file lv_vg_lite_utils.h
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef LV_VG_LITE_UTILS_H
|
||||||
|
#define LV_VG_LITE_UTILS_H
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*********************
|
||||||
|
* INCLUDES
|
||||||
|
*********************/
|
||||||
|
|
||||||
|
#include "../../lvgl.h"
|
||||||
|
|
||||||
|
#if LV_USE_DRAW_VG_LITE
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <vg_lite.h>
|
||||||
|
|
||||||
|
/*********************
|
||||||
|
* DEFINES
|
||||||
|
*********************/
|
||||||
|
|
||||||
|
#define LV_VG_LITE_BUF_ALIGN 64
|
||||||
|
|
||||||
|
#define LV_VG_LITE_IS_ERROR(err) (err > 0)
|
||||||
|
|
||||||
|
#define VLC_GET_OP_CODE(ptr) (*((uint8_t*)ptr))
|
||||||
|
|
||||||
|
#if LV_VG_LITE_USE_ASSERT
|
||||||
|
#define LV_VG_LITE_ASSERT(expr) LV_ASSERT(expr)
|
||||||
|
#else
|
||||||
|
#define LV_VG_LITE_ASSERT(expr)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define LV_VG_LITE_CHECK_ERROR(expr) \
|
||||||
|
do { \
|
||||||
|
vg_lite_error_t error = expr; \
|
||||||
|
if (LV_VG_LITE_IS_ERROR(error)) { \
|
||||||
|
LV_LOG_ERROR("Execute '" #expr "' error(%d): %s", \
|
||||||
|
(int)error, lv_vg_lite_error_string(error)); \
|
||||||
|
LV_VG_LITE_ASSERT(false); \
|
||||||
|
} \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define LV_VG_LITE_ASSERT_PATH(path) LV_VG_LITE_ASSERT(lv_vg_lite_path_check(path))
|
||||||
|
#define LV_VG_LITE_ASSERT_SRC_BUFFER(buffer) LV_VG_LITE_ASSERT(lv_vg_lite_buffer_check(buffer, true))
|
||||||
|
#define LV_VG_LITE_ASSERT_DEST_BUFFER(buffer) LV_VG_LITE_ASSERT(lv_vg_lite_buffer_check(buffer, false))
|
||||||
|
|
||||||
|
#define LV_VG_LITE_ALIGN(number, align_bytes) \
|
||||||
|
(((number) + ((align_bytes)-1)) & ~((align_bytes)-1))
|
||||||
|
|
||||||
|
#define LV_VG_LITE_IS_ALIGNED(num, align) (((uintptr_t)(num) & ((align)-1)) == 0)
|
||||||
|
|
||||||
|
#define LV_VG_LITE_IS_INDEX_FMT(fmt) \
|
||||||
|
((fmt) == VG_LITE_INDEX_1 \
|
||||||
|
|| (fmt) == VG_LITE_INDEX_2 \
|
||||||
|
|| (fmt) == VG_LITE_INDEX_4 \
|
||||||
|
|| (fmt) == VG_LITE_INDEX_8)
|
||||||
|
|
||||||
|
/**********************
|
||||||
|
* TYPEDEFS
|
||||||
|
**********************/
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
LV_VG_LITE_IMAGE_FLAG_ALLOCED = 1 << 0,
|
||||||
|
LV_VG_LITE_IMAGE_FLAG_ALIGNED = 1 << 1,
|
||||||
|
LV_VG_LITE_IMAGE_FLAG_PRE_MUL = 1 << 2,
|
||||||
|
} lv_vg_lite_image_flag_t;
|
||||||
|
|
||||||
|
/**********************
|
||||||
|
* GLOBAL PROTOTYPES
|
||||||
|
**********************/
|
||||||
|
|
||||||
|
/* Print info */
|
||||||
|
|
||||||
|
void lv_vg_lite_dump_info(void);
|
||||||
|
|
||||||
|
const char * lv_vg_lite_error_string(vg_lite_error_t error);
|
||||||
|
|
||||||
|
const char * lv_vg_lite_feature_string(vg_lite_feature_t feature);
|
||||||
|
|
||||||
|
const char * lv_vg_lite_buffer_format_string(vg_lite_buffer_format_t format);
|
||||||
|
|
||||||
|
const char * lv_vg_lite_filter_string(vg_lite_filter_t filter);
|
||||||
|
|
||||||
|
const char * lv_vg_lite_blend_string(vg_lite_blend_t blend);
|
||||||
|
|
||||||
|
const char * lv_vg_lite_global_alpha_string(vg_lite_global_alpha_t global_alpha);
|
||||||
|
|
||||||
|
const char * lv_vg_lite_fill_rule_string(vg_lite_fill_t fill_rule);
|
||||||
|
|
||||||
|
const char * lv_vg_lite_image_mode_string(vg_lite_buffer_image_mode_t image_mode);
|
||||||
|
|
||||||
|
const char * lv_vg_lite_vlc_op_string(uint8_t vlc_op);
|
||||||
|
|
||||||
|
void lv_vg_lite_path_dump_info(const vg_lite_path_t * path);
|
||||||
|
|
||||||
|
void lv_vg_lite_buffer_dump_info(const vg_lite_buffer_t * buffer);
|
||||||
|
|
||||||
|
void lv_vg_lite_matrix_dump_info(const vg_lite_matrix_t * matrix);
|
||||||
|
|
||||||
|
bool lv_vg_lite_is_dest_cf_supported(lv_color_format_t cf);
|
||||||
|
|
||||||
|
bool lv_vg_lite_is_src_cf_supported(lv_color_format_t cf);
|
||||||
|
|
||||||
|
/* Converter */
|
||||||
|
|
||||||
|
vg_lite_buffer_format_t lv_vg_lite_vg_fmt(lv_color_format_t cf);
|
||||||
|
|
||||||
|
void lv_vg_lite_buffer_format_bytes(
|
||||||
|
vg_lite_buffer_format_t format,
|
||||||
|
uint32_t * mul,
|
||||||
|
uint32_t * div,
|
||||||
|
uint32_t * bytes_align);
|
||||||
|
|
||||||
|
uint32_t lv_vg_lite_width_to_stride(uint32_t w, vg_lite_buffer_format_t color_format);
|
||||||
|
|
||||||
|
uint32_t lv_vg_lite_width_align(uint32_t w);
|
||||||
|
|
||||||
|
bool lv_vg_lite_buffer_init(
|
||||||
|
vg_lite_buffer_t * buffer,
|
||||||
|
const void * ptr,
|
||||||
|
int32_t width,
|
||||||
|
int32_t height,
|
||||||
|
vg_lite_buffer_format_t format,
|
||||||
|
bool tiled);
|
||||||
|
|
||||||
|
void lv_vg_lite_image_matrix(vg_lite_matrix_t * matrix, int32_t x, int32_t y, const lv_draw_image_dsc_t * dsc);
|
||||||
|
|
||||||
|
bool lv_vg_lite_buffer_open_image(vg_lite_buffer_t * buffer, lv_image_decoder_dsc_t * decoder_dsc, const void * src);
|
||||||
|
|
||||||
|
vg_lite_blend_t lv_vg_lite_blend_mode(lv_blend_mode_t blend_mode);
|
||||||
|
|
||||||
|
uint32_t lv_vg_lite_get_palette_size(vg_lite_buffer_format_t format);
|
||||||
|
|
||||||
|
vg_lite_color_t lv_vg_lite_color(lv_color_t color, lv_opa_t opa, bool pre_mul);
|
||||||
|
|
||||||
|
void lv_vg_lite_rect(vg_lite_rectangle_t * rect, const lv_area_t * area);
|
||||||
|
|
||||||
|
/* Param checker */
|
||||||
|
|
||||||
|
bool lv_vg_lite_buffer_check(const vg_lite_buffer_t * buffer, bool is_src);
|
||||||
|
|
||||||
|
bool lv_vg_lite_path_check(const vg_lite_path_t * path);
|
||||||
|
|
||||||
|
/* Wrapper */
|
||||||
|
|
||||||
|
bool lv_vg_lite_support_blend_normal(void);
|
||||||
|
|
||||||
|
bool lv_vg_lite_16px_align(void);
|
||||||
|
|
||||||
|
void lv_vg_lite_draw_linear_grad(
|
||||||
|
vg_lite_buffer_t * buffer,
|
||||||
|
vg_lite_path_t * path,
|
||||||
|
const lv_area_t * area,
|
||||||
|
const lv_grad_dsc_t * grad,
|
||||||
|
const vg_lite_matrix_t * matrix,
|
||||||
|
vg_lite_fill_t fill,
|
||||||
|
vg_lite_blend_t blend);
|
||||||
|
|
||||||
|
void lv_vg_lite_matrix_multiply(vg_lite_matrix_t * matrix, const vg_lite_matrix_t * mult);
|
||||||
|
|
||||||
|
void lv_vg_lite_matrix_flip_y(vg_lite_matrix_t * matrix);
|
||||||
|
|
||||||
|
bool lv_vg_lite_matrix_inverse(vg_lite_matrix_t * result, const vg_lite_matrix_t * matrix);
|
||||||
|
|
||||||
|
lv_point_precise_t lv_vg_lite_matrix_transform_point(const vg_lite_matrix_t * matrix, const lv_point_precise_t * point);
|
||||||
|
|
||||||
|
void lv_vg_lite_set_scissor_area(const lv_area_t * area);
|
||||||
|
|
||||||
|
void lv_vg_lite_disable_scissor(void);
|
||||||
|
|
||||||
|
/**********************
|
||||||
|
* MACROS
|
||||||
|
**********************/
|
||||||
|
|
||||||
|
#endif /*LV_USE_DRAW_VG_LITE*/
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
} /*extern "C"*/
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /*VG_LITE_UTILS_H*/
|
||||||
@@ -350,6 +350,35 @@
|
|||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* Use VG-Lite GPU. */
|
||||||
|
#ifndef LV_USE_DRAW_VG_LITE
|
||||||
|
#ifdef CONFIG_LV_USE_DRAW_VG_LITE
|
||||||
|
#define LV_USE_DRAW_VG_LITE CONFIG_LV_USE_DRAW_VG_LITE
|
||||||
|
#else
|
||||||
|
#define LV_USE_DRAW_VG_LITE 0
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if LV_USE_DRAW_VG_LITE
|
||||||
|
/* Enbale VG-Lite custom external 'gpu_init()' function */
|
||||||
|
#ifndef LV_VG_LITE_USE_GPU_INIT
|
||||||
|
#ifdef CONFIG_LV_VG_LITE_USE_GPU_INIT
|
||||||
|
#define LV_VG_LITE_USE_GPU_INIT CONFIG_LV_VG_LITE_USE_GPU_INIT
|
||||||
|
#else
|
||||||
|
#define LV_VG_LITE_USE_GPU_INIT 0
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Enable VG-Lite assert. */
|
||||||
|
#ifndef LV_VG_LITE_USE_ASSERT
|
||||||
|
#ifdef CONFIG_LV_VG_LITE_USE_ASSERT
|
||||||
|
#define LV_VG_LITE_USE_ASSERT CONFIG_LV_VG_LITE_USE_ASSERT
|
||||||
|
#else
|
||||||
|
#define LV_VG_LITE_USE_ASSERT 0
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
/*=================
|
/*=================
|
||||||
* OPERATING SYSTEM
|
* OPERATING SYSTEM
|
||||||
*=================*/
|
*=================*/
|
||||||
|
|||||||
@@ -38,6 +38,9 @@
|
|||||||
#if LV_USE_DRAW_SDL
|
#if LV_USE_DRAW_SDL
|
||||||
#include "draw/sdl/lv_draw_sdl.h"
|
#include "draw/sdl/lv_draw_sdl.h"
|
||||||
#endif
|
#endif
|
||||||
|
#if LV_USE_DRAW_VG_LITE
|
||||||
|
#include "draw/vg_lite/lv_draw_vg_lite.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
/*********************
|
/*********************
|
||||||
* DEFINES
|
* DEFINES
|
||||||
@@ -192,6 +195,10 @@ void lv_init(void)
|
|||||||
_lv_image_decoder_init();
|
_lv_image_decoder_init();
|
||||||
lv_bin_decoder_init(); /*LVGL built-in binary image decoder*/
|
lv_bin_decoder_init(); /*LVGL built-in binary image decoder*/
|
||||||
|
|
||||||
|
#if LV_USE_DRAW_VG_LITE
|
||||||
|
lv_draw_vg_lite_init();
|
||||||
|
#endif
|
||||||
|
|
||||||
_lv_cache_init();
|
_lv_cache_init();
|
||||||
_lv_cache_builtin_init();
|
_lv_cache_builtin_init();
|
||||||
lv_cache_lock();
|
lv_cache_lock();
|
||||||
@@ -357,6 +364,10 @@ void lv_deinit(void)
|
|||||||
lv_draw_vglite_deinit();
|
lv_draw_vglite_deinit();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if LV_USE_DRAW_VG_LITE
|
||||||
|
lv_draw_vg_lite_deinit();
|
||||||
|
#endif
|
||||||
|
|
||||||
#if LV_USE_DRAW_SW
|
#if LV_USE_DRAW_SW
|
||||||
lv_draw_sw_deinit();
|
lv_draw_sw_deinit();
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
Reference in New Issue
Block a user