1
0
mirror of https://github.com/lvgl/lvgl.git synced 2025-01-14 06:42:58 +08:00

feat(vg_lite): add stroke path support (#5831)

Signed-off-by: pengyiqiang <pengyiqiang@xiaomi.com>
Co-authored-by: pengyiqiang <pengyiqiang@xiaomi.com>
This commit is contained in:
VIFEXT 2024-03-14 11:05:16 +08:00 committed by GitHub
parent 1f76eabadd
commit d53b9145a2
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 195 additions and 1 deletions

View File

@ -16,6 +16,7 @@
#include "lv_vg_lite_pending.h"
#include "lv_vg_lite_utils.h"
#include "lv_vg_lite_grad.h"
#include "lv_vg_lite_math.h"
/*********************
* DEFINES
@ -32,9 +33,12 @@
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 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);
/**********************
* STATIC VARIABLES
@ -114,6 +118,9 @@ static void task_draw_cb(void * ctx, const lv_vector_path_t * path, const lv_vec
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);
/* convert stroke style */
lv_stroke_to_vg(lv_vg_path, &dsc->stroke_dsc);
/* 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);
@ -336,6 +343,36 @@ static void lv_path_to_vg(lv_vg_lite_path_t * dest, const lv_vector_path_t * src
LV_PROFILER_END;
}
static void lv_stroke_to_vg(lv_vg_lite_path_t * dest, const lv_vector_stroke_dsc_t * dsc)
{
LV_ASSERT_NULL(dest);
LV_ASSERT_NULL(dsc);
/* if width is 0, no need to set stroke */
if(math_zero(dsc->width)) {
return;
}
vg_lite_path_t * path = lv_vg_lite_path_get_path(dest);
LV_VG_LITE_CHECK_ERROR(vg_lite_set_path_type(path, VG_LITE_DRAW_STROKE_PATH));
LV_VG_LITE_CHECK_ERROR(
vg_lite_set_stroke(
path,
lv_stroke_cap_to_vg(dsc->cap),
lv_stroke_join_to_vg(dsc->join),
dsc->width,
dsc->miter_limit,
lv_array_front(&dsc->dash_pattern),
dsc->dash_pattern.size,
dsc->width / 2,
lv_color32_to_vg(dsc->color, dsc->opa))
);
LV_VG_LITE_CHECK_ERROR(vg_lite_update_stroke(path));
}
static vg_lite_blend_t lv_blend_to_vg(lv_vector_blend_t blend)
{
switch(blend) {
@ -388,4 +425,32 @@ static vg_lite_gradient_spreadmode_t lv_spread_to_vg(lv_vector_gradient_spread_t
}
}
static vg_lite_cap_style_t lv_stroke_cap_to_vg(lv_vector_stroke_cap_t cap)
{
switch(cap) {
case LV_VECTOR_STROKE_CAP_SQUARE:
return VG_LITE_CAP_SQUARE;
case LV_VECTOR_STROKE_CAP_ROUND:
return VG_LITE_CAP_ROUND;
case LV_VECTOR_STROKE_CAP_BUTT:
return VG_LITE_CAP_BUTT;
default:
return VG_LITE_CAP_SQUARE;
}
}
static vg_lite_join_style_t lv_stroke_join_to_vg(lv_vector_stroke_join_t join)
{
switch(join) {
case LV_VECTOR_STROKE_JOIN_BEVEL:
return VG_LITE_JOIN_BEVEL;
case LV_VECTOR_STROKE_JOIN_ROUND:
return VG_LITE_JOIN_ROUND;
case LV_VECTOR_STROKE_JOIN_MITER:
return VG_LITE_JOIN_MITER;
default:
return VG_LITE_JOIN_BEVEL;
}
}
#endif /*LV_USE_DRAW_VG_LITE && LV_USE_VECTOR_GRAPHIC*/

View File

@ -103,6 +103,10 @@ void lv_vg_lite_path_destroy(lv_vg_lite_path_t * path)
if(path->base.path != NULL) {
lv_free(path->base.path);
path->base.path = NULL;
if(path->base.stroke) {
LV_LOG_ERROR("can't free stroke path");
}
}
lv_free(path);
LV_PROFILER_END;
@ -133,6 +137,7 @@ void lv_vg_lite_path_reset(lv_vg_lite_path_t * path, vg_lite_format_t data_forma
path->base.path_length = 0;
path->base.format = data_format;
path->base.quality = VG_LITE_MEDIUM;
path->base.path_type = VG_LITE_DRAW_ZERO;
path->format_len = lv_vg_lite_path_format_len(data_format);
}

View File

@ -269,6 +269,8 @@ static vg_lite_error_t vg_lite_error_conv(Result result);
static Matrix matrix_conv(const vg_lite_matrix_t * matrix);
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 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);
@ -711,6 +713,65 @@ extern "C" {
return VG_LITE_SUCCESS;
}
vg_lite_error_t vg_lite_set_stroke(vg_lite_path_t * path,
vg_lite_cap_style_t cap_style,
vg_lite_join_style_t join_style,
vg_lite_float_t line_width,
vg_lite_float_t miter_limit,
vg_lite_float_t * dash_pattern,
vg_lite_uint32_t pattern_count,
vg_lite_float_t dash_phase,
vg_lite_color_t color)
{
if(!path || line_width <= 0) {
return VG_LITE_INVALID_ARGUMENT;
}
if(miter_limit < 1.0f) {
miter_limit = 1.0f;
}
if(!path->stroke) {
path->stroke = (vg_lite_stroke_t *)lv_malloc_zeroed(sizeof(vg_lite_stroke_t));
if(!path->stroke) {
return VG_LITE_OUT_OF_RESOURCES;
}
}
path->stroke->cap_style = cap_style;
path->stroke->join_style = join_style;
path->stroke->line_width = line_width;
path->stroke->miter_limit = miter_limit;
path->stroke->half_width = line_width / 2.0f;
path->stroke->miter_square = path->stroke->miter_limit * path->stroke->miter_limit;
path->stroke->dash_pattern = dash_pattern;
path->stroke->pattern_count = pattern_count;
path->stroke->dash_phase = dash_phase;
path->stroke_color = color;
return VG_LITE_SUCCESS;
}
vg_lite_error_t vg_lite_update_stroke(vg_lite_path_t * path)
{
LV_UNUSED(path);
return VG_LITE_SUCCESS;
}
vg_lite_error_t vg_lite_set_path_type(vg_lite_path_t * path, vg_lite_path_type_t path_type)
{
if(!path ||
(path_type != VG_LITE_DRAW_FILL_PATH &&
path_type != VG_LITE_DRAW_STROKE_PATH &&
path_type != VG_LITE_DRAW_FILL_STROKE_PATH)
)
return VG_LITE_INVALID_ARGUMENT;
path->path_type = path_type;
return VG_LITE_SUCCESS;
}
vg_lite_error_t vg_lite_get_register(vg_lite_uint32_t address, vg_lite_uint32_t * result)
{
LV_UNUSED(address);
@ -820,7 +881,13 @@ extern "C" {
vg_lite_error_t vg_lite_clear_path(vg_lite_path_t * path)
{
LV_UNUSED(path);
LV_ASSERT_NULL(path);
if(path->stroke) {
lv_free(path->stroke);
path->stroke = NULL;
}
return VG_LITE_NOT_SUPPORT;
}
@ -1880,6 +1947,38 @@ static BlendMethod blend_method_conv(vg_lite_blend_t blend)
return BlendMethod::Normal;
}
static StrokeCap stroke_cap_conv(vg_lite_cap_style_t cap)
{
switch(cap) {
case VG_LITE_CAP_SQUARE:
return StrokeCap::Square;
case VG_LITE_CAP_ROUND:
return StrokeCap::Round;
case VG_LITE_CAP_BUTT:
return StrokeCap::Butt;
default:
break;
}
return StrokeCap::Square;
}
static StrokeJoin stroke_join_conv(vg_lite_join_style_t join)
{
switch(join) {
case VG_LITE_JOIN_BEVEL:
return StrokeJoin::Bevel;
case VG_LITE_JOIN_ROUND:
return StrokeJoin::Round;
case VG_LITE_JOIN_MITER:
return StrokeJoin::Miter;
default:
break;
}
return StrokeJoin::Bevel;
}
static float vlc_get_arg(const void * data, vg_lite_format_t format)
{
switch(format) {
@ -1953,6 +2052,29 @@ static uint8_t vlc_op_arg_len(uint8_t vlc_op)
return 0;
}
static Result shape_set_stroke(std::unique_ptr<Shape> & shape, const vg_lite_path_t * path)
{
/* if path is not a stroke, return */
if(path->path_type == VG_LITE_DRAW_ZERO
|| path->path_type == VG_LITE_DRAW_FILL_PATH) {
return Result::Success;
}
LV_ASSERT_NULL(path->stroke);
TVG_CHECK_RETURN_RESULT(shape->stroke(path->stroke->line_width));
TVG_CHECK_RETURN_RESULT(shape->strokeMiterlimit(path->stroke->miter_limit));
TVG_CHECK_RETURN_RESULT(shape->stroke(stroke_cap_conv(path->stroke->cap_style)));
TVG_CHECK_RETURN_RESULT(shape->stroke(stroke_join_conv(path->stroke->join_style)));
TVG_CHECK_RETURN_RESULT(shape->stroke(TVG_COLOR(path->stroke_color)));
if(path->stroke->pattern_count) {
LV_ASSERT_NULL(path->stroke->dash_pattern);
TVG_CHECK_RETURN_RESULT(shape->stroke(path->stroke->dash_pattern, path->stroke->pattern_count));
}
return Result::Success;
}
static Result shape_append_path(std::unique_ptr<Shape> & shape, vg_lite_path_t * path, vg_lite_matrix_t * matrix)
{
uint8_t fmt_len = vlc_format_len(path->format);
@ -2036,6 +2158,8 @@ static Result shape_append_path(std::unique_ptr<Shape> & shape, vg_lite_path_t *
return Result::Success;
}
TVG_CHECK_RETURN_RESULT(shape_set_stroke(shape, path));
auto cilp = Shape::gen();
TVG_CHECK_RETURN_RESULT(cilp->appendRect(x_min, y_min, x_max - x_min, y_max - y_min, 0, 0));
TVG_CHECK_RETURN_RESULT(cilp->transform(matrix_conv(matrix)));