diff --git a/src/draw/lv_draw_vector.c b/src/draw/lv_draw_vector.c index 6873f25d7..dfa3e88cb 100644 --- a/src/draw/lv_draw_vector.c +++ b/src/draw/lv_draw_vector.c @@ -195,6 +195,23 @@ void lv_matrix_multiply(lv_matrix_t * matrix, const lv_matrix_t * m) _multiply_matrix(matrix, m); } +void lv_matrix_transform_point(const lv_matrix_t * matrix, lv_fpoint_t * point) +{ + float x = point->x; + float y = point->y; + + point->x = x * matrix->m[0][0] + y * matrix->m[1][0] + matrix->m[0][2]; + point->y = x * matrix->m[0][1] + y * matrix->m[1][1] + matrix->m[1][2]; +} + +void lv_matrix_transform_path(const lv_matrix_t * matrix, lv_vector_path_t * path) +{ + for(uint32_t i = 0; i < path->points.size; i++) { + lv_fpoint_t * pt = lv_array_at(&path->points, i); + lv_matrix_transform_point(matrix, pt); + } +} + /* path functions */ lv_vector_path_t * lv_vector_path_create(lv_vector_path_quality_t quality) { @@ -295,6 +312,28 @@ void lv_vector_path_close(lv_vector_path_t * path) lv_array_push_back(&path->ops, &op); } +void lv_vector_path_get_bounding(const lv_vector_path_t * path, lv_area_t * area) +{ + uint32_t len = lv_array_size(&path->points); + lv_fpoint_t * p = lv_array_at(&path->points, 0); + float x1 = p[0].x; + float x2 = p[0].x; + float y1 = p[0].y; + float y2 = p[0].y; + + for(uint32_t i = 1; i < len; i++) { + if(p[i].x < x1) x1 = p[i].x; + if(p[i].y < y1) y1 = p[i].y; + if(p[i].x > x2) x2 = p[i].x; + if(p[i].y > y2) y2 = p[i].y; + } + + area->x1 = (int32_t)x1; + area->y1 = (int32_t)y1; + area->x2 = (int32_t)x2; + area->y2 = (int32_t)y2; +} + void lv_vector_path_append_rect(lv_vector_path_t * path, const lv_area_t * rect, float rx, float ry) { float x = rect->x1; @@ -682,6 +721,7 @@ void lv_vector_clear_area(lv_vector_dsc_t * dsc, const lv_area_t * rect) lv_memset(new_task, 0, sizeof(_lv_vector_draw_task)); new_task->dsc.fill_dsc.color = dsc->current_dsc.fill_dsc.color; + new_task->dsc.fill_dsc.opa = dsc->current_dsc.fill_dsc.opa; lv_area_copy(&(new_task->dsc.scissor_area), rect); } diff --git a/src/draw/lv_draw_vector.h b/src/draw/lv_draw_vector.h index a296c5a5c..577ef65e4 100644 --- a/src/draw/lv_draw_vector.h +++ b/src/draw/lv_draw_vector.h @@ -205,6 +205,20 @@ void lv_matrix_skew(lv_matrix_t * matrix, float skew_x, float skew_y); */ void lv_matrix_multiply(lv_matrix_t * matrix, const lv_matrix_t * matrix2); +/** + * Transform the coordinates of a point using given matrix + * @param matrix pointer to a matrix + * @param point pointer to a point + */ +void lv_matrix_transform_point(const lv_matrix_t * matrix, lv_fpoint_t * point); + +/** + * Transform all the coordinates of a path using given matrix + * @param matrix pointer to a matrix + * @param path pointer to a path + */ +void lv_matrix_transform_path(const lv_matrix_t * matrix, lv_vector_path_t * path); + /** * Create a vector graphic path object * @param quality the quality hint of path @@ -269,6 +283,13 @@ void lv_vector_path_cubic_to(lv_vector_path_t * path, const lv_fpoint_t * p1, co */ void lv_vector_path_close(lv_vector_path_t * path); +/** + * Get the bounding box of a path + * @param path pointer to a path + * @param area pointer to a `lv_area_t` variable for bounding box + */ +void lv_vector_path_get_bounding(const lv_vector_path_t * path, lv_area_t * area); + /** * Add a rectangle to the path * @param path pointer to a path diff --git a/src/draw/sw/lv_draw_sw_vector.c b/src/draw/sw/lv_draw_sw_vector.c index bd20df39c..fc6f260d7 100644 --- a/src/draw/sw/lv_draw_sw_vector.c +++ b/src/draw/sw/lv_draw_sw_vector.c @@ -391,7 +391,7 @@ static void _task_draw_cb(void * ctx, const lv_vector_path_t * path, const lv_ve _lv_area_to_tvg(&rc, &dsc->scissor_area); _tvg_color c; - _lv_color_to_tvg(&c, &dsc->fill_dsc.color, LV_OPA_COVER); + _lv_color_to_tvg(&c, &dsc->fill_dsc.color, dsc->fill_dsc.opa); Tvg_Matrix mtx = { 1.0f, 0.0f, 0.0f, diff --git a/tests/src/test_cases/draw/test_draw_vector.c b/tests/src/test_cases/draw/test_draw_vector.c index e4de433ef..75c5292ea 100644 --- a/tests/src/test_cases/draw/test_draw_vector.c +++ b/tests/src/test_cases/draw/test_draw_vector.c @@ -225,6 +225,35 @@ static void canvas_draw(const char * name, void (*draw_cb)(lv_layer_t *)) lv_obj_del(canvas); } +void test_transform(void) +{ + lv_matrix_t matrix; + lv_matrix_identity(&matrix); + lv_matrix_translate(&matrix, 100, 100); + + lv_fpoint_t p = {10, 10}; + lv_matrix_transform_point(&matrix, &p); + + TEST_ASSERT_EQUAL_FLOAT(110.0f, p.x); + TEST_ASSERT_EQUAL_FLOAT(110.0f, p.y); + + lv_vector_path_t * path = lv_vector_path_create(LV_VECTOR_PATH_QUALITY_MEDIUM); + lv_vector_path_move_to(path, &p); + + lv_fpoint_t p2 = {20, 20}; + lv_vector_path_line_to(path, &p2); + lv_matrix_transform_path(&matrix, path); + + lv_fpoint_t * pt = lv_array_at(&path->points, 0); + + TEST_ASSERT_EQUAL_FLOAT(210.0f, pt[0].x); + TEST_ASSERT_EQUAL_FLOAT(210.0f, pt[0].y); + TEST_ASSERT_EQUAL_FLOAT(120.0f, pt[1].x); + TEST_ASSERT_EQUAL_FLOAT(120.0f, pt[1].y); + + lv_vector_path_delete(path); +} + void test_draw_lines(void) { canvas_draw("draw_lines", draw_lines);