fix(vg_lite_tvg): fix matrix calculation inconsistency with hardware behavior (#8666)

Signed-off-by: pengyiqiang <pengyiqiang@xiaomi.com>
Co-authored-by: pengyiqiang <pengyiqiang@xiaomi.com>
This commit is contained in:
VIFEX
2025-08-12 19:32:40 +08:00
committed by GitHub
parent 3988c597c9
commit f78be49fba
3 changed files with 42 additions and 18 deletions
@@ -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);
+1 -2
View File
@@ -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");
+41 -7
View File
@@ -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