diff --git a/src/draw/lv_draw_vector.c b/src/draw/lv_draw_vector.c index 3bbca3c6a3..41637c2f26 100644 --- a/src/draw/lv_draw_vector.c +++ b/src/draw/lv_draw_vector.c @@ -541,6 +541,11 @@ void lv_vector_dsc_set_fill_rule(lv_vector_dsc_t * dsc, lv_vector_fill_t rule) dsc->current_dsc.fill_dsc.fill_rule = rule; } +void lv_vector_dsc_set_fill_units(lv_vector_dsc_t * dsc, const lv_vector_fill_units_t units) +{ + dsc->current_dsc.fill_dsc.fill_units = units; +} + void lv_vector_dsc_set_fill_image(lv_vector_dsc_t * dsc, const lv_draw_image_dsc_t * img_dsc) { dsc->current_dsc.fill_dsc.style = LV_VECTOR_DRAW_STYLE_PATTERN; diff --git a/src/draw/lv_draw_vector.h b/src/draw/lv_draw_vector.h index 02ba6cb4da..ccb03df73a 100644 --- a/src/draw/lv_draw_vector.h +++ b/src/draw/lv_draw_vector.h @@ -86,6 +86,11 @@ typedef enum { LV_VECTOR_GRADIENT_STYLE_RADIAL, } lv_vector_gradient_style_t; +typedef enum { + LV_VECTOR_FILL_UNITS_OBJECT_BOUNDING_BOX = 0, /** Relative coordinates relative to the object bounding box. */ + LV_VECTOR_FILL_UNITS_USER_SPACE_ON_USE, /** Absolute coordinates relative to the layer's coordinate system */ +} lv_vector_fill_units_t; + struct _lv_fpoint_t { float x; float y; @@ -272,6 +277,15 @@ void lv_vector_dsc_set_fill_opa(lv_vector_dsc_t * dsc, lv_opa_t opa); */ void lv_vector_dsc_set_fill_rule(lv_vector_dsc_t * dsc, lv_vector_fill_t rule); +/** + * Set the fill units for descriptor. + * @param dsc pointer to a vector graphic descriptor + * @param units the units to be set in lv_vector_fill_units_t format + * @note The units can be either relative to the object bounding box or absolute in user space. + * This API specifically affects the drawing position of the fill image and does not impact other elements. + */ +void lv_vector_dsc_set_fill_units(lv_vector_dsc_t * dsc, const lv_vector_fill_units_t units); + /** * Set fill image for descriptor * @param dsc pointer to a vector graphic descriptor diff --git a/src/draw/lv_draw_vector_private.h b/src/draw/lv_draw_vector_private.h index 3b644ae032..7b2d4e04a8 100644 --- a/src/draw/lv_draw_vector_private.h +++ b/src/draw/lv_draw_vector_private.h @@ -51,6 +51,7 @@ struct _lv_vector_fill_dsc_t { lv_color32_t color; lv_opa_t opa; lv_vector_fill_t fill_rule; + lv_vector_fill_units_t fill_units; lv_draw_image_dsc_t img_dsc; lv_vector_gradient_t gradient; lv_matrix_t matrix; diff --git a/src/draw/sw/lv_draw_sw_vector.c b/src/draw/sw/lv_draw_sw_vector.c index 38f5d99077..3d12c4d1bc 100644 --- a/src/draw/sw/lv_draw_sw_vector.c +++ b/src/draw/sw/lv_draw_sw_vector.c @@ -330,13 +330,22 @@ static void _set_paint_fill(Tvg_Paint * obj, Tvg_Canvas * canvas, const lv_vecto tvg_shape_set_fill_color(obj, c.r, c.g, c.b, c.a); } else if(dsc->style == LV_VECTOR_DRAW_STYLE_PATTERN) { - float x, y, w, h; - tvg_paint_get_bounds(obj, &x, &y, &w, &h, false); - lv_matrix_t imx; - lv_memcpy(&imx, matrix, sizeof(lv_matrix_t)); - lv_matrix_translate(&imx, x, y); - lv_matrix_multiply(&imx, &dsc->matrix); + + if(dsc->fill_units == LV_VECTOR_FILL_UNITS_OBJECT_BOUNDING_BOX) { + /* Convert to object bounding box coordinates */ + imx = *matrix; + + float x, y, w, h; + tvg_paint_get_bounds(obj, &x, &y, &w, &h, false); + lv_matrix_translate(&imx, x, y); + lv_matrix_multiply(&imx, &dsc->matrix); + } + else { + /* Copy fill matrix directly, no need to convert */ + imx = dsc->matrix; + } + _set_paint_fill_pattern(obj, canvas, &dsc->img_dsc, &imx); } else if(dsc->style == LV_VECTOR_DRAW_STYLE_GRADIENT) { 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 623fc8a191..2218b55615 100644 --- a/src/draw/vg_lite/lv_draw_vg_lite_vector.c +++ b/src/draw/vg_lite/lv_draw_vg_lite_vector.c @@ -230,7 +230,12 @@ static void task_draw_cb(void * ctx, const lv_vector_path_t * path, const lv_vec if(lv_vg_lite_buffer_open_image(&image_buffer, &decoder_dsc, dsc->fill_dsc.img_dsc.src, false, true)) { /* Calculate pattern matrix. Should start from path bond box, and also apply fill matrix. */ lv_matrix_t m = dsc->matrix; - lv_matrix_translate(&m, min_x, min_y); + + if(dsc->fill_dsc.fill_units == LV_VECTOR_FILL_UNITS_OBJECT_BOUNDING_BOX) { + /* Convert to object bounding box coordinates */ + lv_matrix_translate(&m, min_x, min_y); + } + lv_matrix_multiply(&m, &dsc->fill_dsc.matrix); vg_lite_matrix_t pattern_matrix; diff --git a/tests/ref_imgs/draw/vector_draw_shapes.lp32.png b/tests/ref_imgs/draw/vector_draw_shapes.lp32.png index 5c16bffff7..c5260f8a50 100644 Binary files a/tests/ref_imgs/draw/vector_draw_shapes.lp32.png and b/tests/ref_imgs/draw/vector_draw_shapes.lp32.png differ diff --git a/tests/ref_imgs/draw/vector_draw_shapes.lp64.png b/tests/ref_imgs/draw/vector_draw_shapes.lp64.png index a14ab9f5d3..1d2d5175df 100644 Binary files a/tests/ref_imgs/draw/vector_draw_shapes.lp64.png and b/tests/ref_imgs/draw/vector_draw_shapes.lp64.png differ diff --git a/tests/ref_imgs_vg_lite/draw/vector_draw_shapes.lp32.png b/tests/ref_imgs_vg_lite/draw/vector_draw_shapes.lp32.png index 6435956c51..8091cc9af1 100644 Binary files a/tests/ref_imgs_vg_lite/draw/vector_draw_shapes.lp32.png and b/tests/ref_imgs_vg_lite/draw/vector_draw_shapes.lp32.png differ diff --git a/tests/ref_imgs_vg_lite/draw/vector_draw_shapes.lp64.png b/tests/ref_imgs_vg_lite/draw/vector_draw_shapes.lp64.png index 990f370741..94fb4ab7c4 100644 Binary files a/tests/ref_imgs_vg_lite/draw/vector_draw_shapes.lp64.png and b/tests/ref_imgs_vg_lite/draw/vector_draw_shapes.lp64.png differ diff --git a/tests/src/test_cases/draw/test_draw_vector.c b/tests/src/test_cases/draw/test_draw_vector.c index ea2fc7a90e..2791585221 100644 --- a/tests/src/test_cases/draw/test_draw_vector.c +++ b/tests/src/test_cases/draw/test_draw_vector.c @@ -128,6 +128,22 @@ static void draw_shapes(lv_layer_t * layer) lv_vector_path_append_arc(path, &p, 50, 45, 45, true); lv_vector_dsc_add_path(ctx, path); // draw a path + /* Test image filling with absolute coordinates */ + lv_vector_dsc_identity(ctx); + lv_vector_dsc_set_fill_units(ctx, LV_VECTOR_FILL_UNITS_USER_SPACE_ON_USE); + lv_vector_dsc_set_fill_image(ctx, &img_dsc); + lv_vector_dsc_set_fill_opa(ctx, LV_OPA_50); + lv_vector_dsc_set_stroke_opa(ctx, LV_OPA_TRANSP); + lv_matrix_identity(&mt); + lv_matrix_translate(&mt, 50, 350); + lv_vector_dsc_set_fill_transform(ctx, &mt); + + lv_vector_path_clear(path); + /* Aligned with translate. Image resolution is 100x100, cropped to 50% of width and height */ + lv_area_t img_area = {50, 350, 50 + 50, 350 + 50}; + lv_vector_path_append_rect(path, &img_area, 0, 0); + lv_vector_dsc_add_path(ctx, path); + lv_draw_vector(ctx); lv_vector_path_delete(path); lv_vector_dsc_delete(ctx);