From d53b9145a23c1227f5958bf4b1948c755904e681 Mon Sep 17 00:00:00 2001 From: VIFEXT Date: Thu, 14 Mar 2024 11:05:16 +0800 Subject: [PATCH] feat(vg_lite): add stroke path support (#5831) Signed-off-by: pengyiqiang Co-authored-by: pengyiqiang --- src/draw/vg_lite/lv_draw_vg_lite_vector.c | 65 +++++++++++ src/draw/vg_lite/lv_vg_lite_path.c | 5 + src/others/vg_lite_tvg/vg_lite_tvg.cpp | 126 +++++++++++++++++++++- 3 files changed, 195 insertions(+), 1 deletion(-) diff --git a/src/draw/vg_lite/lv_draw_vg_lite_vector.c b/src/draw/vg_lite/lv_draw_vg_lite_vector.c index dbb5d23fc..7fa5221fc 100644 --- a/src/draw/vg_lite/lv_draw_vg_lite_vector.c +++ b/src/draw/vg_lite/lv_draw_vg_lite_vector.c @@ -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*/ diff --git a/src/draw/vg_lite/lv_vg_lite_path.c b/src/draw/vg_lite/lv_vg_lite_path.c index 812cc7023..9a840fb43 100644 --- a/src/draw/vg_lite/lv_vg_lite_path.c +++ b/src/draw/vg_lite/lv_vg_lite_path.c @@ -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); } diff --git a/src/others/vg_lite_tvg/vg_lite_tvg.cpp b/src/others/vg_lite_tvg/vg_lite_tvg.cpp index 1161b2aa1..b4e96f6d7 100644 --- a/src/others/vg_lite_tvg/vg_lite_tvg.cpp +++ b/src/others/vg_lite_tvg/vg_lite_tvg.cpp @@ -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, vg_lite_path_t * path, vg_lite_matrix_t * matrix); static Result shape_append_rect(std::unique_ptr & 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, 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, 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, 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)));