mirror of
https://github.com/lvgl/lvgl.git
synced 2025-01-14 06:42:58 +08:00
feat(vg_lite): add radial gradient support (#5836)
Signed-off-by: pengyiqiang <pengyiqiang@xiaomi.com> Co-authored-by: pengyiqiang <pengyiqiang@xiaomi.com>
This commit is contained in:
parent
3c2a1935c8
commit
4d4bb340c0
14
Kconfig
14
Kconfig
@ -335,6 +335,20 @@ menu "LVGL configuration"
|
||||
which usually improves performance,
|
||||
but does not guarantee the same rendering quality as the software.
|
||||
|
||||
config LV_VG_LITE_LINEAER_GRAD_CACHE_CNT
|
||||
int "VG-Lite linear gradient image maximum cache number."
|
||||
default 32
|
||||
depends on LV_USE_DRAW_VG_LITE
|
||||
help
|
||||
The memory usage of a single gradient image is 4K bytes.
|
||||
|
||||
config LV_VG_LITE_RADIAL_GRAD_CACHE_CNT
|
||||
int "VG-Lite radial gradient image maximum cache number."
|
||||
default 32
|
||||
depends on LV_USE_DRAW_VG_LITE
|
||||
help
|
||||
The memory usage of a single gradient image is radial grad radius * 4 bytes.
|
||||
|
||||
config LV_USE_VECTOR_GRAPHIC
|
||||
bool "Use Vector Graphic APIs"
|
||||
default n
|
||||
|
@ -184,10 +184,15 @@
|
||||
* but does not guarantee the same rendering quality as the software. */
|
||||
#define LV_VG_LITE_USE_BOX_SHADOW 0
|
||||
|
||||
/* VG-Lite gradient image maximum cache number.
|
||||
/* VG-Lite linear gradient image maximum cache number.
|
||||
* NOTE: The memory usage of a single gradient image is 4K bytes.
|
||||
*/
|
||||
#define LV_VG_LITE_GRAD_CACHE_SIZE 32
|
||||
#define LV_VG_LITE_LINEAER_GRAD_CACHE_CNT 32
|
||||
|
||||
/* VG-Lite radial gradient image maximum cache size.
|
||||
* NOTE: The memory usage of a single gradient image is radial grad radius * 4 bytes.
|
||||
*/
|
||||
#define LV_VG_LITE_RADIAL_GRAD_CACHE_CNT 32
|
||||
|
||||
#endif
|
||||
|
||||
|
@ -198,10 +198,15 @@
|
||||
* but does not guarantee the same rendering quality as the software. */
|
||||
#define LV_VG_LITE_USE_BOX_SHADOW 0
|
||||
|
||||
/* VG-Lite gradient image maximum cache number.
|
||||
/* VG-Lite linear gradient image maximum cache number.
|
||||
* NOTE: The memory usage of a single gradient image is 4K bytes.
|
||||
*/
|
||||
#define LV_VG_LITE_GRAD_CACHE_SIZE 32
|
||||
#define LV_VG_LITE_LINEAER_GRAD_CACHE_CNT 32
|
||||
|
||||
/* VG-Lite radial gradient image maximum cache size.
|
||||
* NOTE: The memory usage of a single gradient image is radial grad radius * 4 bytes.
|
||||
*/
|
||||
#define LV_VG_LITE_RADIAL_GRAD_CACHE_CNT 32
|
||||
|
||||
#endif
|
||||
|
||||
|
@ -72,7 +72,7 @@ void lv_draw_vg_lite_init(void)
|
||||
unit->base_unit.delete_cb = draw_delete;
|
||||
|
||||
lv_vg_lite_image_dsc_init(unit);
|
||||
lv_vg_lite_grad_init(unit);
|
||||
lv_vg_lite_grad_init(unit, LV_VG_LITE_LINEAER_GRAD_CACHE_CNT, LV_VG_LITE_RADIAL_GRAD_CACHE_CNT);
|
||||
lv_vg_lite_path_init(unit);
|
||||
lv_vg_lite_decoder_init();
|
||||
}
|
||||
|
@ -40,9 +40,15 @@ struct _lv_vg_lite_pending_t;
|
||||
struct _lv_draw_vg_lite_unit_t {
|
||||
lv_draw_unit_t base_unit;
|
||||
lv_draw_task_t * task_act;
|
||||
|
||||
struct _lv_vg_lite_pending_t * image_dsc_pending;
|
||||
lv_cache_t * grad_cache;
|
||||
struct _lv_vg_lite_pending_t * grad_pending;
|
||||
|
||||
lv_cache_t * linear_grad_cache;
|
||||
struct _lv_vg_lite_pending_t * linear_grad_pending;
|
||||
|
||||
lv_cache_t * radial_grad_cache;
|
||||
struct _lv_vg_lite_pending_t * radial_grad_pending;
|
||||
|
||||
uint16_t flush_count;
|
||||
vg_lite_buffer_t target_buffer;
|
||||
vg_lite_matrix_t global_matrix;
|
||||
|
@ -36,7 +36,6 @@ static void lv_path_opa_to_vg(lv_vg_lite_path_t * dest, const lv_vector_draw_dsc
|
||||
static void lv_stroke_to_vg(lv_vg_lite_path_t * dest, const lv_vector_stroke_dsc_t * dsc);
|
||||
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 vg_lite_cap_style_t lv_stroke_cap_to_vg(lv_vector_stroke_cap_t cap);
|
||||
static vg_lite_join_style_t lv_stroke_join_to_vg(lv_vector_stroke_join_t join);
|
||||
|
||||
@ -205,8 +204,6 @@ static void task_draw_cb(void * ctx, const lv_vector_path_t * path, const lv_vec
|
||||
case LV_VECTOR_DRAW_STYLE_GRADIENT: {
|
||||
/* draw gradient */
|
||||
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) {
|
||||
vg_lite_matrix_t grad_matrix, fill_matrix;
|
||||
@ -229,12 +226,23 @@ static void task_draw_cb(void * ctx, const lv_vector_path_t * path, const lv_vec
|
||||
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");
|
||||
}
|
||||
vg_lite_matrix_t grad_matrix;
|
||||
lv_matrix_to_vg(&grad_matrix, &dsc->fill_dsc.matrix);
|
||||
|
||||
/* add min_x, min_y to gradient center */
|
||||
lv_vector_gradient_t new_grad = dsc->fill_dsc.gradient;
|
||||
new_grad.cx += min_x;
|
||||
new_grad.cy += min_y;
|
||||
|
||||
lv_vg_lite_draw_radial_grad(
|
||||
u,
|
||||
&u->target_buffer,
|
||||
vg_path,
|
||||
&new_grad,
|
||||
&grad_matrix,
|
||||
&matrix,
|
||||
fill,
|
||||
blend);
|
||||
}
|
||||
}
|
||||
break;
|
||||
@ -431,20 +439,6 @@ 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)
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
static vg_lite_cap_style_t lv_stroke_cap_to_vg(lv_vector_stroke_cap_t cap)
|
||||
{
|
||||
switch(cap) {
|
||||
|
@ -13,6 +13,7 @@
|
||||
|
||||
#include "lv_draw_vg_lite_type.h"
|
||||
#include "lv_vg_lite_pending.h"
|
||||
#include "lv_vg_lite_math.h"
|
||||
#include "../../misc/lv_types.h"
|
||||
#include "../../stdlib/lv_string.h"
|
||||
|
||||
@ -25,22 +26,47 @@
|
||||
**********************/
|
||||
|
||||
typedef struct {
|
||||
vg_lite_linear_gradient_t vg_grad;
|
||||
lv_grad_dsc_t lv_grad;
|
||||
} grad_item_t;
|
||||
vg_lite_linear_gradient_t vg_grad;
|
||||
} linear_grad_item_t;
|
||||
|
||||
#if LV_USE_VECTOR_GRAPHIC
|
||||
|
||||
typedef struct {
|
||||
lv_vector_gradient_t lv_grad;
|
||||
vg_lite_radial_gradient_t vg_grad;
|
||||
} radial_grad_item_t;
|
||||
|
||||
#endif /* LV_USE_VECTOR_GRAPHIC */
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
|
||||
static vg_lite_linear_gradient_t * lv_vg_lite_linear_grad_get(struct _lv_draw_vg_lite_unit_t * u,
|
||||
const lv_grad_dsc_t * grad);
|
||||
|
||||
static bool grad_create_cb(grad_item_t * item, void * user_data);
|
||||
static void grad_free_cb(grad_item_t * item, void * user_data);
|
||||
static lv_cache_compare_res_t grad_compare_cb(const grad_item_t * lhs, const grad_item_t * rhs);
|
||||
static void grad_cache_release_cb(void * entry, void * user_data);
|
||||
|
||||
/* Linear gradient */
|
||||
|
||||
static vg_lite_linear_gradient_t * linear_grad_get(struct _lv_draw_vg_lite_unit_t * u,
|
||||
const lv_grad_dsc_t * grad);
|
||||
static bool linear_grad_create_cb(linear_grad_item_t * item, void * user_data);
|
||||
static void linear_grad_free_cb(linear_grad_item_t * item, void * user_data);
|
||||
static lv_cache_compare_res_t linear_grad_compare_cb(const linear_grad_item_t * lhs, const linear_grad_item_t * rhs);
|
||||
|
||||
#if LV_USE_VECTOR_GRAPHIC
|
||||
|
||||
/* Radial gradient */
|
||||
|
||||
static vg_lite_radial_gradient_t * radial_grad_get(struct _lv_draw_vg_lite_unit_t * u,
|
||||
const lv_vector_gradient_t * grad);
|
||||
static bool radial_grad_create_cb(radial_grad_item_t * item, void * user_data);
|
||||
static void radial_grad_free_cb(radial_grad_item_t * item, void * user_data);
|
||||
static lv_cache_compare_res_t radial_grad_compare_cb(const radial_grad_item_t * lhs, const radial_grad_item_t * rhs);
|
||||
|
||||
static vg_lite_gradient_spreadmode_t lv_spread_to_vg(lv_vector_gradient_spread_t spread);
|
||||
|
||||
#endif /* LV_USE_VECTOR_GRAPHIC */
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
@ -53,28 +79,63 @@ static void grad_cache_release_cb(void * entry, void * user_data);
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
void lv_vg_lite_grad_init(struct _lv_draw_vg_lite_unit_t * u)
|
||||
void lv_vg_lite_grad_init(
|
||||
struct _lv_draw_vg_lite_unit_t * u,
|
||||
uint32_t linear_grad_cache_cnt,
|
||||
uint32_t radial_grad_cache_cnt)
|
||||
{
|
||||
LV_ASSERT_NULL(u);
|
||||
LV_UNUSED(radial_grad_cache_cnt);
|
||||
|
||||
lv_cache_ops_t ops = {
|
||||
.compare_cb = (lv_cache_compare_cb_t)grad_compare_cb,
|
||||
.create_cb = (lv_cache_create_cb_t)grad_create_cb,
|
||||
.free_cb = (lv_cache_free_cb_t)grad_free_cb,
|
||||
};
|
||||
/* Create the cache for linear gradients */
|
||||
{
|
||||
lv_cache_ops_t ops = {
|
||||
.compare_cb = (lv_cache_compare_cb_t)linear_grad_compare_cb,
|
||||
.create_cb = (lv_cache_create_cb_t)linear_grad_create_cb,
|
||||
.free_cb = (lv_cache_free_cb_t)linear_grad_free_cb,
|
||||
};
|
||||
|
||||
u->grad_cache = lv_cache_create(&lv_cache_class_lru_rb_count, sizeof(grad_item_t), LV_VG_LITE_GRAD_CACHE_SIZE, ops);
|
||||
LV_ASSERT_NULL(u->grad_cache);
|
||||
u->linear_grad_cache = lv_cache_create(&lv_cache_class_lru_rb_count, sizeof(linear_grad_item_t),
|
||||
linear_grad_cache_cnt,
|
||||
ops);
|
||||
u->linear_grad_pending = lv_vg_lite_pending_create(sizeof(lv_cache_entry_t *), 4);
|
||||
lv_vg_lite_pending_set_free_cb(u->linear_grad_pending, grad_cache_release_cb, u->linear_grad_cache);
|
||||
}
|
||||
|
||||
u->grad_pending = lv_vg_lite_pending_create(sizeof(lv_cache_entry_t *), 4);
|
||||
lv_vg_lite_pending_set_free_cb(u->grad_pending, grad_cache_release_cb, u->grad_cache);
|
||||
#if LV_USE_VECTOR_GRAPHIC
|
||||
|
||||
/* Create the cache for radial gradients */
|
||||
if(vg_lite_query_feature(gcFEATURE_BIT_VG_RADIAL_GRADIENT)) {
|
||||
lv_cache_ops_t ops = {
|
||||
.compare_cb = (lv_cache_compare_cb_t)radial_grad_compare_cb,
|
||||
.create_cb = (lv_cache_create_cb_t)radial_grad_create_cb,
|
||||
.free_cb = (lv_cache_free_cb_t)radial_grad_free_cb,
|
||||
};
|
||||
|
||||
u->radial_grad_cache = lv_cache_create(&lv_cache_class_lru_rb_count, sizeof(radial_grad_item_t),
|
||||
radial_grad_cache_cnt,
|
||||
ops);
|
||||
u->radial_grad_pending = lv_vg_lite_pending_create(sizeof(lv_cache_entry_t *), 4);
|
||||
lv_vg_lite_pending_set_free_cb(u->radial_grad_pending, grad_cache_release_cb, u->radial_grad_cache);
|
||||
}
|
||||
|
||||
#endif /* LV_USE_VECTOR_GRAPHIC */
|
||||
}
|
||||
|
||||
void lv_vg_lite_grad_deinit(struct _lv_draw_vg_lite_unit_t * u)
|
||||
{
|
||||
LV_ASSERT_NULL(u);
|
||||
lv_vg_lite_pending_destroy(u->grad_pending);
|
||||
lv_cache_destroy(u->grad_cache, NULL);
|
||||
lv_vg_lite_pending_destroy(u->linear_grad_pending);
|
||||
u->linear_grad_pending = NULL;
|
||||
lv_cache_destroy(u->linear_grad_cache, NULL);
|
||||
u->linear_grad_cache = NULL;
|
||||
|
||||
if(u->radial_grad_pending) {
|
||||
lv_vg_lite_pending_destroy(u->radial_grad_pending);
|
||||
u->radial_grad_pending = NULL;
|
||||
lv_cache_destroy(u->radial_grad_cache, NULL);
|
||||
u->radial_grad_cache = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void lv_vg_lite_grad_area_to_matrix(vg_lite_matrix_t * grad_matrix, const lv_area_t * area, lv_grad_dir_t dir)
|
||||
@ -119,20 +180,20 @@ void lv_vg_lite_draw_linear_grad(
|
||||
|
||||
LV_PROFILER_BEGIN;
|
||||
|
||||
vg_lite_linear_gradient_t * gradient = lv_vg_lite_linear_grad_get(u, grad);
|
||||
LV_ASSERT_NULL(gradient);
|
||||
if(!gradient) {
|
||||
vg_lite_linear_gradient_t * linear_grad = linear_grad_get(u, grad);
|
||||
LV_ASSERT_NULL(linear_grad);
|
||||
if(!linear_grad) {
|
||||
LV_LOG_ERROR("Failed to get linear gradient");
|
||||
LV_PROFILER_END;
|
||||
return;
|
||||
}
|
||||
|
||||
vg_lite_matrix_t * grad_mat_p = vg_lite_get_grad_matrix(gradient);
|
||||
vg_lite_matrix_t * grad_mat_p = vg_lite_get_grad_matrix(linear_grad);
|
||||
LV_ASSERT_NULL(grad_mat_p);
|
||||
*grad_mat_p = *grad_matrix;
|
||||
|
||||
LV_VG_LITE_ASSERT_DEST_BUFFER(buffer);
|
||||
LV_VG_LITE_ASSERT_SRC_BUFFER(&gradient->image);
|
||||
LV_VG_LITE_ASSERT_SRC_BUFFER(&linear_grad->image);
|
||||
LV_VG_LITE_ASSERT_PATH(path);
|
||||
LV_VG_LITE_ASSERT_MATRIX(grad_mat_p);
|
||||
LV_VG_LITE_ASSERT_MATRIX(matrix);
|
||||
@ -143,37 +204,101 @@ void lv_vg_lite_draw_linear_grad(
|
||||
path,
|
||||
fill,
|
||||
(vg_lite_matrix_t *)matrix,
|
||||
gradient,
|
||||
linear_grad,
|
||||
blend));
|
||||
LV_PROFILER_END_TAG("vg_lite_draw_grad");
|
||||
|
||||
LV_PROFILER_END;
|
||||
}
|
||||
|
||||
#if LV_USE_VECTOR_GRAPHIC
|
||||
|
||||
void lv_vg_lite_draw_radial_grad(
|
||||
struct _lv_draw_vg_lite_unit_t * u,
|
||||
vg_lite_buffer_t * buffer,
|
||||
vg_lite_path_t * path,
|
||||
const lv_vector_gradient_t * grad,
|
||||
const vg_lite_matrix_t * grad_matrix,
|
||||
const vg_lite_matrix_t * matrix,
|
||||
vg_lite_fill_t fill,
|
||||
vg_lite_blend_t blend)
|
||||
{
|
||||
LV_ASSERT_NULL(u);
|
||||
LV_ASSERT_NULL(buffer);
|
||||
LV_ASSERT_NULL(path);
|
||||
LV_ASSERT_NULL(grad);
|
||||
LV_ASSERT_NULL(grad_matrix);
|
||||
LV_ASSERT_NULL(matrix);
|
||||
|
||||
if(!vg_lite_query_feature(gcFEATURE_BIT_VG_RADIAL_GRADIENT)) {
|
||||
LV_LOG_INFO("radial gradient is not supported");
|
||||
return;
|
||||
}
|
||||
|
||||
if(grad->spread == LV_VECTOR_GRADIENT_SPREAD_REPEAT || grad->spread == LV_VECTOR_GRADIENT_SPREAD_REFLECT) {
|
||||
if(!vg_lite_query_feature(gcFEATURE_BIT_VG_IM_REPEAT_REFLECT)) {
|
||||
LV_LOG_INFO("repeat/reflect spread(%d) is not supported", (int)grad->spread);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
LV_PROFILER_BEGIN;
|
||||
|
||||
vg_lite_radial_gradient_t * radial_grad = radial_grad_get(u, grad);
|
||||
|
||||
vg_lite_matrix_t * grad_mat_p = vg_lite_get_radial_grad_matrix(radial_grad);
|
||||
LV_ASSERT_NULL(grad_mat_p);
|
||||
*grad_mat_p = *grad_matrix;
|
||||
|
||||
LV_VG_LITE_ASSERT_DEST_BUFFER(buffer);
|
||||
LV_VG_LITE_ASSERT_SRC_BUFFER(&radial_grad->image);
|
||||
LV_VG_LITE_ASSERT_PATH(path);
|
||||
LV_VG_LITE_ASSERT_MATRIX(grad_mat_p);
|
||||
LV_VG_LITE_ASSERT_MATRIX(matrix);
|
||||
|
||||
LV_PROFILER_BEGIN_TAG("vg_lite_draw_radial_grad");
|
||||
LV_VG_LITE_CHECK_ERROR(
|
||||
vg_lite_draw_radial_grad(
|
||||
buffer,
|
||||
path,
|
||||
fill,
|
||||
(vg_lite_matrix_t *)matrix,
|
||||
radial_grad,
|
||||
0,
|
||||
blend,
|
||||
VG_LITE_FILTER_LINEAR));
|
||||
LV_PROFILER_END_TAG("vg_lite_draw_radial_grad");
|
||||
|
||||
LV_PROFILER_END;
|
||||
}
|
||||
|
||||
#endif /* LV_USE_VECTOR_GRAPHIC */
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
static vg_lite_linear_gradient_t * lv_vg_lite_linear_grad_get(struct _lv_draw_vg_lite_unit_t * u,
|
||||
const lv_grad_dsc_t * grad)
|
||||
static void * grad_get(
|
||||
struct _lv_draw_vg_lite_unit_t * u,
|
||||
lv_cache_t * cache,
|
||||
lv_vg_lite_pending_t * pending,
|
||||
const void * key)
|
||||
{
|
||||
LV_ASSERT_NULL(u);
|
||||
LV_ASSERT_NULL(grad);
|
||||
LV_ASSERT_NULL(cache);
|
||||
LV_ASSERT_NULL(pending);
|
||||
LV_ASSERT_NULL(key);
|
||||
|
||||
grad_item_t search_key;
|
||||
lv_memzero(&search_key, sizeof(grad_item_t));
|
||||
search_key.lv_grad = *grad;
|
||||
|
||||
lv_cache_entry_t * cache_node_entry = lv_cache_acquire(u->grad_cache, &search_key, NULL);
|
||||
lv_cache_entry_t * cache_node_entry = lv_cache_acquire(cache, key, NULL);
|
||||
if(cache_node_entry == NULL) {
|
||||
/* check if the cache is full */
|
||||
size_t free_size = lv_cache_get_free_size(u->grad_cache, NULL);
|
||||
size_t free_size = lv_cache_get_free_size(cache, NULL);
|
||||
if(free_size == 0) {
|
||||
LV_LOG_INFO("grad cache is full, release all pending cache entries");
|
||||
lv_vg_lite_finish(u);
|
||||
}
|
||||
|
||||
cache_node_entry = lv_cache_acquire_or_create(u->grad_cache, &search_key, NULL);
|
||||
cache_node_entry = lv_cache_acquire_or_create(cache, key, NULL);
|
||||
if(cache_node_entry == NULL) {
|
||||
LV_LOG_ERROR("grad cache creating failed");
|
||||
return NULL;
|
||||
@ -181,13 +306,36 @@ static vg_lite_linear_gradient_t * lv_vg_lite_linear_grad_get(struct _lv_draw_vg
|
||||
}
|
||||
|
||||
/* Add the new entry to the pending list */
|
||||
lv_vg_lite_pending_add(u->grad_pending, &cache_node_entry);
|
||||
lv_vg_lite_pending_add(pending, &cache_node_entry);
|
||||
|
||||
return lv_cache_entry_get_data(cache_node_entry);
|
||||
}
|
||||
|
||||
static void grad_cache_release_cb(void * entry, void * user_data)
|
||||
{
|
||||
lv_cache_entry_t ** entry_p = entry;
|
||||
lv_cache_t * cache = user_data;
|
||||
lv_cache_release(cache, *entry_p, NULL);
|
||||
}
|
||||
|
||||
/* Linear gradient */
|
||||
|
||||
static vg_lite_linear_gradient_t * linear_grad_get(struct _lv_draw_vg_lite_unit_t * u,
|
||||
const lv_grad_dsc_t * grad)
|
||||
{
|
||||
linear_grad_item_t search_key;
|
||||
lv_memzero(&search_key, sizeof(search_key));
|
||||
search_key.lv_grad = *grad;
|
||||
|
||||
linear_grad_item_t * item = grad_get(u, u->linear_grad_cache, u->linear_grad_pending, &search_key);
|
||||
if(!item) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
grad_item_t * item = lv_cache_entry_get_data(cache_node_entry);
|
||||
return &item->vg_grad;
|
||||
}
|
||||
|
||||
static bool grad_create_cb(grad_item_t * item, void * user_data)
|
||||
static bool linear_grad_create_cb(linear_grad_item_t * item, void * user_data)
|
||||
{
|
||||
LV_UNUSED(user_data);
|
||||
|
||||
@ -226,13 +374,13 @@ static bool grad_create_cb(grad_item_t * item, void * user_data)
|
||||
return true;
|
||||
}
|
||||
|
||||
static void grad_free_cb(grad_item_t * item, void * user_data)
|
||||
static void linear_grad_free_cb(linear_grad_item_t * item, void * user_data)
|
||||
{
|
||||
LV_UNUSED(user_data);
|
||||
LV_VG_LITE_CHECK_ERROR(vg_lite_clear_grad(&item->vg_grad));
|
||||
}
|
||||
|
||||
static lv_cache_compare_res_t grad_compare_cb(const grad_item_t * lhs, const grad_item_t * rhs)
|
||||
static lv_cache_compare_res_t linear_grad_compare_cb(const linear_grad_item_t * lhs, const linear_grad_item_t * rhs)
|
||||
{
|
||||
if(lhs->lv_grad.stops_count != rhs->lv_grad.stops_count) {
|
||||
return lhs->lv_grad.stops_count > rhs->lv_grad.stops_count ? 1 : -1;
|
||||
@ -247,11 +395,139 @@ static lv_cache_compare_res_t grad_compare_cb(const grad_item_t * lhs, const gra
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void grad_cache_release_cb(void * entry, void * user_data)
|
||||
#if LV_USE_VECTOR_GRAPHIC
|
||||
|
||||
/* Radial gradient */
|
||||
|
||||
static vg_lite_radial_gradient_t * radial_grad_get(struct _lv_draw_vg_lite_unit_t * u,
|
||||
const lv_vector_gradient_t * grad)
|
||||
{
|
||||
lv_cache_entry_t ** entry_p = entry;
|
||||
lv_cache_t * cache = user_data;
|
||||
lv_cache_release(cache, *entry_p, NULL);
|
||||
radial_grad_item_t search_key;
|
||||
lv_memzero(&search_key, sizeof(search_key));
|
||||
search_key.lv_grad = *grad;
|
||||
|
||||
radial_grad_item_t * item = grad_get(u, u->radial_grad_cache, u->radial_grad_pending, &search_key);
|
||||
if(!item) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return &item->vg_grad;
|
||||
}
|
||||
|
||||
static bool radial_grad_create_cb(radial_grad_item_t * item, void * user_data)
|
||||
{
|
||||
LV_UNUSED(user_data);
|
||||
|
||||
LV_PROFILER_BEGIN;
|
||||
|
||||
lv_vector_gradient_t * grad = &item->lv_grad;
|
||||
uint8_t stops_count = grad->grad.stops_count;
|
||||
vg_lite_color_ramp_t * color_ramp = lv_malloc(sizeof(vg_lite_color_ramp_t) * stops_count);
|
||||
LV_ASSERT_MALLOC(color_ramp);
|
||||
if(!color_ramp) {
|
||||
LV_LOG_ERROR("malloc failed for color_ramp");
|
||||
return false;
|
||||
}
|
||||
|
||||
for(uint8_t i = 0; i < stops_count; i++) {
|
||||
color_ramp[i].stop = grad->grad.stops[i].frac / 255.0f;
|
||||
lv_color_t c = grad->grad.stops[i].color;
|
||||
|
||||
color_ramp[i].red = c.red / 255.0f;
|
||||
color_ramp[i].green = c.green / 255.0f;
|
||||
color_ramp[i].blue = c.blue / 255.0f;
|
||||
color_ramp[i].alpha = grad->grad.stops[i].opa / 255.0f;
|
||||
}
|
||||
|
||||
const vg_lite_radial_gradient_parameter_t grad_param = {
|
||||
.cx = grad->cx,
|
||||
.cy = grad->cy,
|
||||
.r = grad->cr,
|
||||
.fx = grad->cx,
|
||||
.fy = grad->cy,
|
||||
};
|
||||
|
||||
vg_lite_radial_gradient_t radial_grad;
|
||||
lv_memzero(&radial_grad, sizeof(radial_grad));
|
||||
|
||||
LV_PROFILER_BEGIN_TAG("vg_lite_set_radial_grad");
|
||||
LV_VG_LITE_CHECK_ERROR(
|
||||
vg_lite_set_radial_grad(
|
||||
&radial_grad,
|
||||
stops_count,
|
||||
color_ramp,
|
||||
grad_param,
|
||||
lv_spread_to_vg(grad->spread),
|
||||
1));
|
||||
LV_PROFILER_END_TAG("vg_lite_set_radial_grad");
|
||||
|
||||
LV_PROFILER_BEGIN_TAG("vg_lite_update_radial_grad");
|
||||
vg_lite_error_t err = vg_lite_update_radial_grad(&radial_grad);
|
||||
LV_PROFILER_END_TAG("vg_lite_update_radial_grad");
|
||||
if(!err) {
|
||||
item->vg_grad = radial_grad;
|
||||
}
|
||||
else {
|
||||
LV_LOG_ERROR("update radial grad error(%d): %s", (int)err, lv_vg_lite_error_string(err));
|
||||
}
|
||||
|
||||
lv_free(color_ramp);
|
||||
|
||||
LV_PROFILER_END;
|
||||
return err == VG_LITE_SUCCESS;
|
||||
}
|
||||
|
||||
static void radial_grad_free_cb(radial_grad_item_t * item, void * user_data)
|
||||
{
|
||||
LV_UNUSED(user_data);
|
||||
LV_VG_LITE_CHECK_ERROR(vg_lite_clear_radial_grad(&item->vg_grad));
|
||||
}
|
||||
|
||||
static lv_cache_compare_res_t radial_grad_compare_cb(const radial_grad_item_t * lhs, const radial_grad_item_t * rhs)
|
||||
{
|
||||
if(!math_equal(lhs->lv_grad.cx, rhs->lv_grad.cx)) {
|
||||
return lhs->lv_grad.cx > rhs->lv_grad.cx ? 1 : -1;
|
||||
}
|
||||
|
||||
if(!math_equal(lhs->lv_grad.cy, rhs->lv_grad.cy)) {
|
||||
return lhs->lv_grad.cy > rhs->lv_grad.cy ? 1 : -1;
|
||||
}
|
||||
|
||||
if(!math_equal(lhs->lv_grad.cr, rhs->lv_grad.cr)) {
|
||||
return lhs->lv_grad.cr > rhs->lv_grad.cr ? 1 : -1;
|
||||
}
|
||||
|
||||
if(lhs->lv_grad.spread != rhs->lv_grad.spread) {
|
||||
return lhs->lv_grad.spread > rhs->lv_grad.spread ? 1 : -1;
|
||||
}
|
||||
|
||||
if(lhs->lv_grad.grad.stops_count != rhs->lv_grad.grad.stops_count) {
|
||||
return lhs->lv_grad.grad.stops_count > rhs->lv_grad.grad.stops_count ? 1 : -1;
|
||||
}
|
||||
|
||||
int cmp_res = lv_memcmp(lhs->lv_grad.grad.stops, rhs->lv_grad.grad.stops,
|
||||
sizeof(lv_gradient_stop_t) * lhs->lv_grad.grad.stops_count);
|
||||
if(cmp_res != 0) {
|
||||
return cmp_res > 0 ? 1 : -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
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_VECTOR_GRAPHIC */
|
||||
|
||||
#endif /*LV_USE_DRAW_VG_LITE*/
|
||||
|
@ -32,7 +32,10 @@ extern "C" {
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
void lv_vg_lite_grad_init(struct _lv_draw_vg_lite_unit_t * u);
|
||||
void lv_vg_lite_grad_init(
|
||||
struct _lv_draw_vg_lite_unit_t * u,
|
||||
uint32_t linear_grad_cache_cnt,
|
||||
uint32_t radial_grad_cache_cnt);
|
||||
|
||||
void lv_vg_lite_grad_deinit(struct _lv_draw_vg_lite_unit_t * u);
|
||||
|
||||
@ -48,7 +51,19 @@ void lv_vg_lite_draw_linear_grad(
|
||||
vg_lite_fill_t fill,
|
||||
vg_lite_blend_t blend);
|
||||
|
||||
void lv_vg_lite_linear_grad_release_all(struct _lv_draw_vg_lite_unit_t * u);
|
||||
#if LV_USE_VECTOR_GRAPHIC
|
||||
|
||||
void lv_vg_lite_draw_radial_grad(
|
||||
struct _lv_draw_vg_lite_unit_t * u,
|
||||
vg_lite_buffer_t * buffer,
|
||||
vg_lite_path_t * path,
|
||||
const lv_vector_gradient_t * grad,
|
||||
const vg_lite_matrix_t * grad_matrix,
|
||||
const vg_lite_matrix_t * matrix,
|
||||
vg_lite_fill_t fill,
|
||||
vg_lite_blend_t blend);
|
||||
|
||||
#endif /* LV_USE_VECTOR_GRAPHIC */
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
|
@ -1064,7 +1064,11 @@ void lv_vg_lite_finish(struct _lv_draw_vg_lite_unit_t * u)
|
||||
LV_VG_LITE_CHECK_ERROR(vg_lite_finish());
|
||||
|
||||
/* Clear all gradient caches reference */
|
||||
lv_vg_lite_pending_remove_all(u->grad_pending);
|
||||
lv_vg_lite_pending_remove_all(u->linear_grad_pending);
|
||||
|
||||
if(u->radial_grad_pending) {
|
||||
lv_vg_lite_pending_remove_all(u->radial_grad_pending);
|
||||
}
|
||||
|
||||
/* Clear image decoder dsc reference */
|
||||
lv_vg_lite_pending_remove_all(u->image_dsc_pending);
|
||||
|
@ -538,14 +538,25 @@
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* VG-Lite gradient image maximum cache number.
|
||||
/* VG-Lite linear gradient image maximum cache number.
|
||||
* NOTE: The memory usage of a single gradient image is 4K bytes.
|
||||
*/
|
||||
#ifndef LV_VG_LITE_GRAD_CACHE_SIZE
|
||||
#ifdef CONFIG_LV_VG_LITE_GRAD_CACHE_SIZE
|
||||
#define LV_VG_LITE_GRAD_CACHE_SIZE CONFIG_LV_VG_LITE_GRAD_CACHE_SIZE
|
||||
#ifndef LV_VG_LITE_LINEAER_GRAD_CACHE_CNT
|
||||
#ifdef CONFIG_LV_VG_LITE_LINEAER_GRAD_CACHE_CNT
|
||||
#define LV_VG_LITE_LINEAER_GRAD_CACHE_CNT CONFIG_LV_VG_LITE_LINEAER_GRAD_CACHE_CNT
|
||||
#else
|
||||
#define LV_VG_LITE_GRAD_CACHE_SIZE 32
|
||||
#define LV_VG_LITE_LINEAER_GRAD_CACHE_CNT 32
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* VG-Lite radial gradient image maximum cache size.
|
||||
* NOTE: The memory usage of a single gradient image is radial grad radius * 4 bytes.
|
||||
*/
|
||||
#ifndef LV_VG_LITE_RADIAL_GRAD_CACHE_CNT
|
||||
#ifdef CONFIG_LV_VG_LITE_RADIAL_GRAD_CACHE_CNT
|
||||
#define LV_VG_LITE_RADIAL_GRAD_CACHE_CNT CONFIG_LV_VG_LITE_RADIAL_GRAD_CACHE_CNT
|
||||
#else
|
||||
#define LV_VG_LITE_RADIAL_GRAD_CACHE_CNT 32
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
@ -271,6 +271,7 @@ static FillRule fill_rule_conv(vg_lite_fill_t fill);
|
||||
static BlendMethod blend_method_conv(vg_lite_blend_t blend);
|
||||
static StrokeCap stroke_cap_conv(vg_lite_cap_style_t cap);
|
||||
static StrokeJoin stroke_join_conv(vg_lite_join_style_t join);
|
||||
static FillSpread fill_spread_conv(vg_lite_gradient_spreadmode_t spread);
|
||||
static Result shape_append_path(std::unique_ptr<Shape> & shape, vg_lite_path_t * path, vg_lite_matrix_t * matrix);
|
||||
static Result shape_append_rect(std::unique_ptr<Shape> & shape, const vg_lite_buffer_t * target,
|
||||
const vg_lite_rectangle_t * rect);
|
||||
@ -808,6 +809,8 @@ extern "C" {
|
||||
case gcFEATURE_BIT_VG_24BIT:
|
||||
case gcFEATURE_BIT_VG_DITHER:
|
||||
case gcFEATURE_BIT_VG_USE_DST:
|
||||
case gcFEATURE_BIT_VG_RADIAL_GRADIENT:
|
||||
case gcFEATURE_BIT_VG_IM_REPEAT_REFLECT:
|
||||
|
||||
#if LV_VG_LITE_THORVG_LVGL_BLEND_SUPPORT
|
||||
case gcFEATURE_BIT_VG_LVGL_SUPPORT:
|
||||
@ -1736,15 +1739,34 @@ Empty_sequence_handler:
|
||||
vg_lite_blend_t blend,
|
||||
vg_lite_filter_t filter)
|
||||
{
|
||||
LV_UNUSED(target);
|
||||
LV_UNUSED(path);
|
||||
LV_UNUSED(fill_rule);
|
||||
LV_UNUSED(path_matrix);
|
||||
LV_UNUSED(grad);
|
||||
LV_UNUSED(paint_color);
|
||||
LV_UNUSED(blend);
|
||||
LV_UNUSED(filter);
|
||||
return VG_LITE_NOT_SUPPORT;
|
||||
auto ctx = vg_lite_ctx::get_instance();
|
||||
TVG_CHECK_RETURN_VG_ERROR(canvas_set_target(ctx, target));
|
||||
|
||||
auto shape = Shape::gen();
|
||||
TVG_CHECK_RETURN_VG_ERROR(shape_append_path(shape, path, path_matrix));
|
||||
TVG_CHECK_RETURN_VG_ERROR(shape->transform(matrix_conv(path_matrix)));
|
||||
TVG_CHECK_RETURN_VG_ERROR(shape->fill(fill_rule_conv(fill_rule)););
|
||||
TVG_CHECK_RETURN_VG_ERROR(shape->blend(blend_method_conv(blend)));
|
||||
|
||||
auto radialGrad = RadialGradient::gen();
|
||||
TVG_CHECK_RETURN_VG_ERROR(radialGrad->transform(matrix_conv(&grad->matrix)));
|
||||
TVG_CHECK_RETURN_VG_ERROR(radialGrad->radial(grad->radial_grad.cx, grad->radial_grad.cy, grad->radial_grad.r));
|
||||
TVG_CHECK_RETURN_VG_ERROR(radialGrad->spread(fill_spread_conv(grad->spread_mode)));
|
||||
|
||||
tvg::Fill::ColorStop colorStops[VLC_MAX_COLOR_RAMP_STOPS];
|
||||
for(vg_lite_uint32_t i = 0; i < grad->ramp_length; i++) {
|
||||
colorStops[i].offset = grad->color_ramp[i].stop;
|
||||
colorStops[i].r = grad->color_ramp[i].red * 255.0f;
|
||||
colorStops[i].g = grad->color_ramp[i].green * 255.0f;
|
||||
colorStops[i].b = grad->color_ramp[i].blue * 255.0f;
|
||||
colorStops[i].a = grad->color_ramp[i].alpha * 255.0f;
|
||||
}
|
||||
TVG_CHECK_RETURN_VG_ERROR(radialGrad->colorStops(colorStops, grad->ramp_length));
|
||||
|
||||
TVG_CHECK_RETURN_VG_ERROR(shape->fill(std::move(radialGrad)));
|
||||
TVG_CHECK_RETURN_VG_ERROR(ctx->canvas->push(std::move(shape)));
|
||||
|
||||
return VG_LITE_SUCCESS;
|
||||
}
|
||||
|
||||
vg_lite_error_t vg_lite_set_command_buffer_size(vg_lite_uint32_t size)
|
||||
@ -1979,6 +2001,20 @@ static StrokeJoin stroke_join_conv(vg_lite_join_style_t join)
|
||||
return StrokeJoin::Bevel;
|
||||
}
|
||||
|
||||
static FillSpread fill_spread_conv(vg_lite_gradient_spreadmode_t spread)
|
||||
{
|
||||
switch(spread) {
|
||||
case VG_LITE_GRADIENT_SPREAD_PAD:
|
||||
return FillSpread::Pad;
|
||||
case VG_LITE_GRADIENT_SPREAD_REPEAT:
|
||||
return FillSpread::Repeat;
|
||||
case VG_LITE_GRADIENT_SPREAD_REFLECT:
|
||||
return FillSpread::Reflect;
|
||||
default:
|
||||
return FillSpread::Pad;
|
||||
}
|
||||
}
|
||||
|
||||
static float vlc_get_arg(const void * data, vg_lite_format_t format)
|
||||
{
|
||||
switch(format) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user