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:
_VIFEXTech
2023-12-18 21:17:42 +08:00
committed by GitHub
parent b172c64a8c
commit 9fc6801860
29 changed files with 5155 additions and 0 deletions
+13
View File
@@ -357,6 +357,19 @@ menu "LVGL configuration"
config LV_USE_DRAW_PXP
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
bool "Use SDL renderer API"
default n
+11
View File
@@ -128,6 +128,17 @@
/* Draw using cached SDL textures*/
#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
*=================*/
+2
View File
@@ -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;
else dsc->format = LV_DRAW_LETTER_BITMAP_FORMAT_A8;
dsc->g = &g;
cb(draw_unit, dsc, NULL, NULL);
LV_PROFILER_END;
}
+1
View File
@@ -87,6 +87,7 @@ typedef struct {
lv_draw_glyph_bitmap_format_t format;
const lv_area_t * letter_coords;
const lv_area_t * bg_coords;
const lv_font_glyph_dsc_t * g;
lv_color_t color;
lv_opa_t opa;
} lv_draw_glyph_dsc_t;
+197
View 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
View 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
View 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
View 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
View 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*/
@@ -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
View 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
View 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
View 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
View 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
View 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*/
@@ -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(&param, &dsc->area, dsc->radius, false);
void * masks[2] = {0};
masks[0] = &param;
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(&param);
}
/**********************
* STATIC FUNCTIONS
**********************/
#endif /*LV_USE_DRAW_VG_LITE*/
+104
View 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
View 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
View 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*/
File diff suppressed because it is too large Load Diff
+49
View 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
View 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
View 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*/
File diff suppressed because it is too large Load Diff
+124
View 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*/
File diff suppressed because it is too large Load Diff
+188
View 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*/
+29
View File
@@ -350,6 +350,35 @@
#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
*=================*/
+11
View File
@@ -38,6 +38,9 @@
#if LV_USE_DRAW_SDL
#include "draw/sdl/lv_draw_sdl.h"
#endif
#if LV_USE_DRAW_VG_LITE
#include "draw/vg_lite/lv_draw_vg_lite.h"
#endif
/*********************
* DEFINES
@@ -192,6 +195,10 @@ void lv_init(void)
_lv_image_decoder_init();
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_builtin_init();
lv_cache_lock();
@@ -357,6 +364,10 @@ void lv_deinit(void)
lv_draw_vglite_deinit();
#endif
#if LV_USE_DRAW_VG_LITE
lv_draw_vg_lite_deinit();
#endif
#if LV_USE_DRAW_SW
lv_draw_sw_deinit();
#endif