fix(vg_lite):fix bug for wrong rendering in vertical or horizontal dir (#5789)

Signed-off-by: wangxuedong <wangxuedong@xiaomi.com>
This commit is contained in:
xaowang
2024-03-05 11:34:21 +08:00
committed by GitHub
parent de09007c03
commit c326e31a87
2 changed files with 124 additions and 23 deletions

View File

@@ -194,14 +194,16 @@ static void task_draw_cb(void * ctx, const lv_vector_path_t * path, const lv_vec
vg_lite_gradient_spreadmode_t spreadmode = lv_spread_to_vg(dsc->fill_dsc.gradient.spread);
LV_UNUSED(spreadmode);
lv_matrix_t m = dsc->matrix;
lv_matrix_translate(&m, min_x, min_y);
lv_matrix_multiply(&m, &dsc->fill_dsc.matrix);
vg_lite_matrix_t grad_matrix;
lv_matrix_to_vg(&grad_matrix, &m);
if(style == LV_VECTOR_GRADIENT_STYLE_LINEAR) {
vg_lite_matrix_t grad_matrix, fill_matrix;
lv_area_t grad_area;
lv_area_set(&grad_area, (int32_t)min_x, (int32_t)min_y, (int32_t)max_x, (int32_t)max_y);
lv_vg_lite_grad_area_to_matrix(&grad_matrix, &grad_area, LV_GRAD_DIR_HOR);
lv_matrix_to_vg(&fill_matrix, &dsc->fill_dsc.matrix);
lv_vg_lite_matrix_multiply(&grad_matrix, &matrix);
lv_vg_lite_matrix_multiply(&grad_matrix, &fill_matrix);
lv_vg_lite_draw_linear_grad(
u,
&u->target_buffer,

View File

@@ -119,6 +119,11 @@ typedef struct {
uint8_t alpha;
} vg_color32_t;
typedef struct {
vg_lite_float_t x;
vg_lite_float_t y;
} vg_lite_fpoint_t;
#pragma pack()
class vg_lite_ctx
@@ -288,6 +293,10 @@ static void get_format_bytes(vg_lite_buffer_format_t format,
vg_lite_uint32_t * div,
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 VARIABLES
**********************/
@@ -1608,24 +1617,32 @@ 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)));
float x_min = path->bounding_box[0];
float y_min = path->bounding_box[1];
float x_max = path->bounding_box[2];
float y_max = path->bounding_box[3];
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);
vg_lite_fpoint_t p1 = {0.0f, 0.0f};
vg_lite_fpoint_t p2 = {1.0f, 0};
vg_lite_fpoint_t p1_trans = p1;
vg_lite_fpoint_t p2_trans = p2;
p1_trans = matrix_transform_point(&grad_matrix, &p1);
p2_trans = matrix_transform_point(&grad_matrix, &p2);
float dx = (p2_trans.x - p1_trans.x);
float dy = (p2_trans.y - p1_trans.y);
float scale = sqrtf(dx * dx + dy * dy);
float angle = (float)(atan2f(dy, dx));
float dlen = 256 * scale;
float x_min = grad_matrix.m[0][2];
float y_min = grad_matrix.m[1][2];
float x_max = x_min + dlen * cosf(angle);
float y_max = y_min + dlen * sinf(angle);
LV_LOG_TRACE("linear gradient {%.2f, %.2f} ~ {%.2f, %.2f}", x_min, y_min, x_max, y_max);
auto linearGrad = LinearGradient::gen();
if(matrix->m[0][1] != 0) {
/* vertical */
linearGrad->linear(x_min, y_min, x_min, y_max);
}
else {
/* horizontal */
linearGrad->linear(x_min, y_min, x_max, y_min);
}
linearGrad->transform(matrix_conv(&grad->matrix));
linearGrad->spread(FillSpread::Reflect);
linearGrad->linear(x_min, y_min, x_max, y_max);
linearGrad->spread(FillSpread::Pad);
tvg::Fill::ColorStop colorStops[VLC_MAX_GRADIENT_STOPS];
for(vg_lite_uint32_t i = 0; i < grad->count; i++) {
@@ -2434,4 +2451,86 @@ static void get_format_bytes(vg_lite_buffer_format_t format,
break;
}
}
static vg_lite_fpoint_t matrix_transform_point(const vg_lite_matrix_t * matrix, const vg_lite_fpoint_t * point)
{
vg_lite_fpoint_t p;
p.x = (vg_lite_float_t)(point->x * matrix->m[0][0] + point->y * matrix->m[0][1] + matrix->m[0][2]);
p.y = (vg_lite_float_t)(point->x * matrix->m[1][0] + point->y * matrix->m[1][1] + matrix->m[1][2]);
return p;
}
static bool vg_lite_matrix_inverse(vg_lite_matrix_t * result, const vg_lite_matrix_t * matrix)
{
vg_lite_float_t det00, det01, det02;
vg_lite_float_t d;
bool is_affine;
/* Test for identity matrix. */
if(matrix == NULL) {
result->m[0][0] = 1.0f;
result->m[0][1] = 0.0f;
result->m[0][2] = 0.0f;
result->m[1][0] = 0.0f;
result->m[1][1] = 1.0f;
result->m[1][2] = 0.0f;
result->m[2][0] = 0.0f;
result->m[2][1] = 0.0f;
result->m[2][2] = 1.0f;
/* Success. */
return true;
}
det00 = (matrix->m[1][1] * matrix->m[2][2]) - (matrix->m[2][1] * matrix->m[1][2]);
det01 = (matrix->m[2][0] * matrix->m[1][2]) - (matrix->m[1][0] * matrix->m[2][2]);
det02 = (matrix->m[1][0] * matrix->m[2][1]) - (matrix->m[2][0] * matrix->m[1][1]);
/* Compute determinant. */
d = (matrix->m[0][0] * det00) + (matrix->m[0][1] * det01) + (matrix->m[0][2] * det02);
/* Return 0 if there is no inverse matrix. */
if(d == 0.0f)
return false;
/* Compute reciprocal. */
d = 1.0f / d;
/* Determine if the matrix is affine. */
is_affine = (matrix->m[2][0] == 0.0f) && (matrix->m[2][1] == 0.0f) && (matrix->m[2][2] == 1.0f);
result->m[0][0] = d * det00;
result->m[0][1] = d * ((matrix->m[2][1] * matrix->m[0][2]) - (matrix->m[0][1] * matrix->m[2][2]));
result->m[0][2] = d * ((matrix->m[0][1] * matrix->m[1][2]) - (matrix->m[1][1] * matrix->m[0][2]));
result->m[1][0] = d * det01;
result->m[1][1] = d * ((matrix->m[0][0] * matrix->m[2][2]) - (matrix->m[2][0] * matrix->m[0][2]));
result->m[1][2] = d * ((matrix->m[1][0] * matrix->m[0][2]) - (matrix->m[0][0] * matrix->m[1][2]));
result->m[2][0] = is_affine ? 0.0f : d * det02;
result->m[2][1] = is_affine ? 0.0f : d * ((matrix->m[2][0] * matrix->m[0][1]) - (matrix->m[0][0] * matrix->m[2][1]));
result->m[2][2] = is_affine ? 1.0f : d * ((matrix->m[0][0] * matrix->m[1][1]) - (matrix->m[1][0] * matrix->m[0][1]));
/* Success. */
return true;
}
static void vg_lite_matrix_multiply(vg_lite_matrix_t * matrix, const vg_lite_matrix_t * mult)
{
vg_lite_matrix_t temp;
int row, column;
/* Process all rows. */
for(row = 0; row < 3; row++) {
/* Process all columns. */
for(column = 0; column < 3; column++) {
/* Compute matrix entry. */
temp.m[row][column] = (matrix->m[row][0] * mult->m[0][column])
+ (matrix->m[row][1] * mult->m[1][column])
+ (matrix->m[row][2] * mult->m[2][column]);
}
}
/* Copy temporary matrix into result. */
lv_memcpy(matrix->m, &temp.m, sizeof(temp.m));
}
#endif