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 3799560ee3..c05600ac26 100644 --- a/src/draw/vg_lite/lv_draw_vg_lite_vector.c +++ b/src/draw/vg_lite/lv_draw_vg_lite_vector.c @@ -165,15 +165,6 @@ static void draw_fill(lv_draw_vg_lite_unit_t * u, break; case LV_VECTOR_DRAW_STYLE_GRADIENT: { vg_lite_matrix_t grad_matrix = *matrix; - -#if LV_USE_VG_LITE_THORVG - /* Workaround inconsistent radial gradient matrix behavior between device and ThorVG */ - if(dsc->fill_dsc.gradient.style == LV_VECTOR_GRADIENT_STYLE_RADIAL) { - /* Restore matrix to identity */ - vg_lite_identity(&grad_matrix); - } -#endif - vg_lite_matrix_t fill_matrix; lv_vg_lite_matrix(&fill_matrix, &dsc->fill_dsc.matrix); lv_vg_lite_matrix_multiply(&grad_matrix, &fill_matrix); diff --git a/src/draw/vg_lite/lv_vg_lite_grad.c b/src/draw/vg_lite/lv_vg_lite_grad.c index 02d7ef735b..88ac0c403d 100644 --- a/src/draw/vg_lite/lv_vg_lite_grad.c +++ b/src/draw/vg_lite/lv_vg_lite_grad.c @@ -191,8 +191,7 @@ bool lv_vg_lite_draw_grad( vg_lite_linear_gradient_t * linear_grad = &grad_item->vg.linear; vg_lite_matrix_t * grad_mat_p = vg_lite_get_grad_matrix(linear_grad); LV_ASSERT_NULL(grad_mat_p); - vg_lite_identity(grad_mat_p); - lv_vg_lite_matrix_multiply(grad_mat_p, grad_matrix); + *grad_mat_p = *grad_matrix; grad_point_to_matrix(grad_mat_p, grad->x1, grad->y1, grad->x2, grad->y2); LV_PROFILER_DRAW_BEGIN_TAG("vg_lite_draw_grad"); diff --git a/src/others/vg_lite_tvg/vg_lite_tvg.cpp b/src/others/vg_lite_tvg/vg_lite_tvg.cpp index 0b54dd645b..bffa955c0e 100644 --- a/src/others/vg_lite_tvg/vg_lite_tvg.cpp +++ b/src/others/vg_lite_tvg/vg_lite_tvg.cpp @@ -324,8 +324,8 @@ static void get_format_bytes(vg_lite_buffer_format_t format, vg_lite_uint32_t * bytes_align); static vg_lite_fpoint_t matrix_transform_point(const vg_lite_matrix_t * matrix, const vg_lite_fpoint_t * point); -static bool vg_lite_matrix_inverse(vg_lite_matrix_t * result, const vg_lite_matrix_t * matrix); -static void vg_lite_matrix_multiply(vg_lite_matrix_t * matrix, const vg_lite_matrix_t * mult); +static Result vg_lite_grad_matrix_conv(vg_lite_matrix_t * result, const vg_lite_matrix_t * grad_matrix, + const vg_lite_matrix_t * path_matrix); /********************** * STATIC VARIABLES @@ -1464,10 +1464,13 @@ Empty_sequence_handler: TVG_CHECK_RETURN_VG_ERROR(shape->fill(fill_rule_conv(fill_rule));); TVG_CHECK_RETURN_VG_ERROR(shape->blend(blend_method_conv(blend))); + vg_lite_matrix_t grad_matrix; + TVG_CHECK_RETURN_VG_ERROR(vg_lite_grad_matrix_conv(&grad_matrix, &grad->matrix, path_matrix)); + auto linearGrad = LinearGradient::gen(); TVG_CHECK_RETURN_VG_ERROR(linearGrad->linear(grad->linear_grad.X0, grad->linear_grad.Y0, grad->linear_grad.X1, grad->linear_grad.Y1)); - TVG_CHECK_RETURN_VG_ERROR(linearGrad->transform(matrix_conv(&grad->matrix))); + TVG_CHECK_RETURN_VG_ERROR(linearGrad->transform(matrix_conv(&grad_matrix))); TVG_CHECK_RETURN_VG_ERROR(linearGrad->spread(fill_spread_conv(grad->spread_mode))); tvg::Fill::ColorStop colorStops[VLC_MAX_COLOR_RAMP_STOPS]; @@ -1919,9 +1922,7 @@ Empty_sequence_handler: TVG_CHECK_RETURN_VG_ERROR(shape->blend(blend_method_conv(blend))); vg_lite_matrix_t grad_matrix; - vg_lite_identity(&grad_matrix); - vg_lite_matrix_inverse(&grad_matrix, matrix); - vg_lite_matrix_multiply(&grad_matrix, &grad->matrix); + TVG_CHECK_RETURN_VG_ERROR(vg_lite_grad_matrix_conv(&grad_matrix, &grad->matrix, matrix)); vg_lite_fpoint_t p1 = {0.0f, 0.0f}; vg_lite_fpoint_t p2 = {1.0f, 0}; @@ -1982,8 +1983,11 @@ Empty_sequence_handler: TVG_CHECK_RETURN_VG_ERROR(shape->fill(fill_rule_conv(fill_rule));); TVG_CHECK_RETURN_VG_ERROR(shape->blend(blend_method_conv(blend))); + vg_lite_matrix_t grad_matrix; + TVG_CHECK_RETURN_VG_ERROR(vg_lite_grad_matrix_conv(&grad_matrix, &grad->matrix, path_matrix)); + auto radialGrad = RadialGradient::gen(); - TVG_CHECK_RETURN_VG_ERROR(radialGrad->transform(matrix_conv(&grad->matrix))); + 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))); @@ -2188,6 +2192,15 @@ static vg_lite_error_t vg_lite_error_conv(Result result) static Matrix matrix_conv(const vg_lite_matrix_t * matrix) { + static const Matrix identity = { + 1, 0, 0, + 0, 1, 0, + 0, 0, 1 + }; + if(!matrix) { + return identity; + } + return *(Matrix *)matrix; } @@ -2990,4 +3003,25 @@ static void vg_lite_matrix_multiply(vg_lite_matrix_t * matrix, const vg_lite_mat lv_memcpy(matrix->m, &temp.m, sizeof(temp.m)); } +static Result vg_lite_grad_matrix_conv(vg_lite_matrix_t * result, const vg_lite_matrix_t * grad_matrix, + const vg_lite_matrix_t * path_matrix) +{ + /** + * Since Thorvg internally multiplies the path (shape) matrix with the gradient matrix to produce + * the rendering result, and VG-Lite's gradient matrix and path matrix are completely independent, + * requiring a previous multiplication to achieve the same rendering result, + * for the VG-Lite emulator, it is necessary to offset the gradient matrix to obtain the user's original gradient matrix + * to simulate hardware behavior: + * matrix_out = path_matrix * gradient_matrix + * => + * gradient_matrix = inv(path_matrix) * matrix_out + */ + if(!vg_lite_matrix_inverse(result, path_matrix)) { + return Result::InvalidArguments; + } + + vg_lite_matrix_multiply(result, grad_matrix); + return Result::Success; +} + #endif