diff --git a/Kconfig b/Kconfig index 2c61dfebaa..954b1cb518 100644 --- a/Kconfig +++ b/Kconfig @@ -177,6 +177,13 @@ menu "LVGL configuration" help Align the start address of draw_buf addresses to this bytes. + config LV_DRAW_TRANSFORM_USE_MATRIX + bool "Using matrix for transformations" + default n + depends on LV_USE_MATRIX + help + Requirements: The rendering engine needs to support 3x3 matrix transformations. + config LV_DRAW_LAYER_SIMPLE_BUF_SIZE int "Optimal size to buffer the widget with opacity" default 24576 @@ -372,6 +379,8 @@ menu "LVGL configuration" config LV_USE_DRAW_VG_LITE bool "Use VG-Lite GPU" + default n + select LV_USE_MATRIX config LV_VG_LITE_USE_GPU_INIT bool "Enable VG-Lite custom external 'gpu_init()' function" @@ -415,6 +424,7 @@ menu "LVGL configuration" config LV_USE_VECTOR_GRAPHIC bool "Use Vector Graphic APIs" default n + select LV_USE_MATRIX help Enable drawing support vector graphic APIs. endmenu @@ -696,6 +706,11 @@ menu "LVGL configuration" config LV_USE_FLOAT bool "Use float as lv_value_precise_t" default n + + config LV_USE_MATRIX + bool "Enable matrix support" + default n + select LV_USE_FLOAT endmenu menu "Font Usage" diff --git a/lv_conf_template.h b/lv_conf_template.h index 5339df8114..956e764fc0 100644 --- a/lv_conf_template.h +++ b/lv_conf_template.h @@ -106,6 +106,12 @@ /*Align the start address of draw_buf addresses to this bytes*/ #define LV_DRAW_BUF_ALIGN 4 +/*Using matrix for transformations. + *Requirements: + `LV_USE_MATRIX = 1`. + The rendering engine needs to support 3x3 matrix transformations.*/ +#define LV_DRAW_TRANSFORM_USE_MATRIX 0 + /* If a widget has `style_opa < 255` (not `bg_opa`, `text_opa` etc) or not NORMAL blend mode * it is buffered into a "simple" layer before rendering. The widget can be buffered in smaller chunks. * "Transformed layers" (if `transform_angle/zoom` are set) use larger buffers @@ -438,6 +444,10 @@ /* Use `float` as `lv_value_precise_t` */ #define LV_USE_FLOAT 0 +/*Enable matrix support + *Requires `LV_USE_FLOAT = 1`*/ +#define LV_USE_MATRIX 0 + /*================== * FONT USAGE *===================*/ @@ -791,7 +801,8 @@ /*Rlottie library*/ #define LV_USE_RLOTTIE 0 -/*Enable Vector Graphic APIs*/ +/*Enable Vector Graphic APIs + *Requires `LV_USE_MATRIX = 1`*/ #define LV_USE_VECTOR_GRAPHIC 0 /* Enable ThorVG (vector graphics library) from the src/libs folder */ diff --git a/src/core/lv_refr.c b/src/core/lv_refr.c index 8430f70b0a..a5cafe4e6b 100644 --- a/src/core/lv_refr.c +++ b/src/core/lv_refr.c @@ -604,6 +604,10 @@ static void refr_area(const lv_area_t * area_p) lv_layer_t * layer = disp_refr->layer_head; layer->draw_buf = disp_refr->buf_act; +#if LV_DRAW_TRANSFORM_USE_MATRIX + lv_matrix_identity(&layer->matrix); +#endif + /*With full refresh just redraw directly into the buffer*/ /*In direct mode draw directly on the absolute coordinates of the buffer*/ if(disp_refr->render_mode != LV_DISPLAY_RENDER_MODE_PARTIAL) { @@ -891,18 +895,120 @@ static bool alpha_test_area_on_obj(lv_obj_t * obj, const lv_area_t * area) else return true; } -void refr_obj(lv_layer_t * layer, lv_obj_t * obj) +#if LV_DRAW_TRANSFORM_USE_MATRIX + +static void refr_obj_matrix(lv_layer_t * layer, lv_obj_t * obj) +{ + lv_matrix_t ori_matrix = layer->matrix; + lv_matrix_t obj_matrix; + lv_matrix_identity(&obj_matrix); + + lv_point_t pivot = { + .x = lv_obj_get_style_transform_pivot_x(obj, 0), + .y = lv_obj_get_style_transform_pivot_y(obj, 0) + }; + + pivot.x = obj->coords.x1 + lv_pct_to_px(pivot.x, lv_area_get_width(&obj->coords)); + pivot.y = obj->coords.y1 + lv_pct_to_px(pivot.y, lv_area_get_height(&obj->coords)); + + int32_t rotation = lv_obj_get_style_transform_rotation(obj, 0); + int32_t scale_x = lv_obj_get_style_transform_scale_x(obj, 0); + int32_t scale_y = lv_obj_get_style_transform_scale_y(obj, 0); + int32_t skew_x = lv_obj_get_style_transform_skew_x(obj, 0); + int32_t skew_y = lv_obj_get_style_transform_skew_y(obj, 0); + + /* generate the obj matrix */ + lv_matrix_translate(&obj_matrix, pivot.x, pivot.y); + if(rotation != 0) { + lv_matrix_rotate(&obj_matrix, rotation * 0.1f); + } + + if(scale_x != LV_SCALE_NONE || scale_y != LV_SCALE_NONE) { + lv_matrix_scale( + &obj_matrix, + (float)scale_x / LV_SCALE_NONE, + (float)scale_y / LV_SCALE_NONE + ); + } + + if(skew_x != 0 || skew_y != 0) { + lv_matrix_skew(&obj_matrix, skew_x, skew_y); + } + + lv_matrix_translate(&obj_matrix, -pivot.x, -pivot.y); + + /* apply the obj matrix */ + lv_matrix_multiply(&layer->matrix, &obj_matrix); + + /* calculate clip area without transform */ + lv_matrix_t matrix_reverse; + lv_matrix_inverse(&matrix_reverse, &obj_matrix); + + lv_area_t clip_area = layer->_clip_area; + lv_area_t clip_area_ori = layer->_clip_area; + clip_area = lv_matrix_transform_area(&matrix_reverse, &clip_area); + + /* increase the clip area by 1 pixel to avoid rounding errors */ + if(!lv_matrix_is_identity_or_translation(&obj_matrix)) { + lv_area_increase(&clip_area, 1, 1); + } + + layer->_clip_area = clip_area; + + /* redraw obj */ + lv_obj_redraw(layer, obj); + + /* restore original matrix */ + layer->matrix = ori_matrix; + /* restore clip area */ + layer->_clip_area = clip_area_ori; +} + +static bool refr_check_obj_clip_overflow(lv_layer_t * layer, lv_obj_t * obj) +{ + if(lv_obj_get_style_transform_rotation(obj, 0) == 0) { + return false; + } + + /*Truncate the area to the object*/ + lv_area_t obj_coords; + int32_t ext_size = _lv_obj_get_ext_draw_size(obj); + lv_area_copy(&obj_coords, &obj->coords); + lv_area_increase(&obj_coords, ext_size, ext_size); + + lv_obj_get_transformed_area(obj, &obj_coords, LV_OBJ_POINT_TRANSFORM_FLAG_RECURSIVE); + + lv_area_t clip_coords_for_obj; + if(!_lv_area_intersect(&clip_coords_for_obj, &layer->_clip_area, &obj_coords)) { + return false; + } + + bool has_clip = lv_memcmp(&clip_coords_for_obj, &obj_coords, sizeof(lv_area_t)) != 0; + return has_clip; +} + +#endif /* LV_DRAW_TRANSFORM_USE_MATRIX */ + +static void refr_obj(lv_layer_t * layer, lv_obj_t * obj) { if(lv_obj_has_flag(obj, LV_OBJ_FLAG_HIDDEN)) return; + lv_opa_t opa = lv_obj_get_style_opa_layered(obj, 0); + if(opa < LV_OPA_MIN) return; + +#if LV_DRAW_TRANSFORM_USE_MATRIX + /*If the layer opa is full then use the matrix transform*/ + if(opa >= LV_OPA_MAX && !refr_check_obj_clip_overflow(layer, obj)) { + refr_obj_matrix(layer, obj); + return; + } +#endif /* LV_DRAW_TRANSFORM_USE_MATRIX */ + lv_layer_type_t layer_type = _lv_obj_get_layer_type(obj); if(layer_type == LV_LAYER_TYPE_NONE) { lv_obj_redraw(layer, obj); } else { - lv_opa_t opa = lv_obj_get_style_opa_layered(obj, 0); - if(opa < LV_OPA_MIN) return; - lv_area_t layer_area_full; lv_area_t obj_draw_size; lv_result_t res = layer_get_area(layer, obj, layer_type, &layer_area_full, &obj_draw_size); diff --git a/src/draw/lv_draw.c b/src/draw/lv_draw.c index b4cb7cc8a0..1a72f04dde 100644 --- a/src/draw/lv_draw.c +++ b/src/draw/lv_draw.c @@ -89,6 +89,9 @@ lv_draw_task_t * lv_draw_add_task(lv_layer_t * layer, const lv_area_t * coords) new_task->area = *coords; new_task->_real_area = *coords; new_task->clip_area = layer->_clip_area; +#if LV_DRAW_TRANSFORM_USE_MATRIX + new_task->matrix = layer->matrix; +#endif new_task->state = LV_DRAW_TASK_STATE_QUEUED; /*Find the tail*/ @@ -346,6 +349,10 @@ lv_layer_t * lv_draw_layer_create(lv_layer_t * parent_layer, lv_color_format_t c new_layer->buf_area = *area; new_layer->color_format = color_format; +#if LV_DRAW_TRANSFORM_USE_MATRIX + lv_matrix_identity(&new_layer->matrix); +#endif + if(disp->layer_head) { lv_layer_t * tail = disp->layer_head; while(tail->next) tail = tail->next; diff --git a/src/draw/lv_draw.h b/src/draw/lv_draw.h index 14a3af2d0d..6056058d6c 100644 --- a/src/draw/lv_draw.h +++ b/src/draw/lv_draw.h @@ -19,6 +19,7 @@ extern "C" { #include "../misc/lv_style.h" #include "../misc/lv_text.h" #include "../misc/lv_profiler.h" +#include "../misc/lv_matrix.h" #include "lv_image_decoder.h" #include "../osal/lv_os.h" #include "lv_draw_buf.h" @@ -29,6 +30,12 @@ extern "C" { #define LV_DRAW_UNIT_NONE 0 #define LV_DRAW_UNIT_IDLE -1 /*The draw unit is idle, new dispatching might be requested to try again*/ +#if LV_DRAW_TRANSFORM_USE_MATRIX +#if !LV_USE_MATRIX +#error "LV_DRAW_TRANSFORM_USE_MATRIX requires LV_USE_MATRIX = 1" +#endif +#endif + /********************** * TYPEDEFS **********************/ @@ -80,6 +87,11 @@ struct _lv_draw_task_t { */ lv_area_t clip_area; +#if LV_DRAW_TRANSFORM_USE_MATRIX + /** Transform matrix to be applied when rendering the layer */ + lv_matrix_t matrix; +#endif + volatile int state; /*int instead of lv_draw_task_state_t to be sure its atomic*/ void * draw_dsc; @@ -166,6 +178,11 @@ struct _lv_layer_t { */ lv_area_t _clip_area; +#if LV_DRAW_TRANSFORM_USE_MATRIX + /** Transform matrix to be applied when rendering the layer */ + lv_matrix_t matrix; +#endif + /** Linked list of draw tasks */ lv_draw_task_t * draw_task_head; diff --git a/src/draw/lv_draw_vector.c b/src/draw/lv_draw_vector.c index b03f6e8c1e..bcf3ced7e9 100644 --- a/src/draw/lv_draw_vector.c +++ b/src/draw/lv_draw_vector.c @@ -56,33 +56,6 @@ typedef struct { * STATIC PROTOTYPES **********************/ -static bool _is_identity_or_translation(const lv_matrix_t * matrix) -{ - return (matrix->m[0][0] == 1.0f && - matrix->m[0][1] == 0.0f && - matrix->m[1][0] == 0.0f && - matrix->m[1][1] == 1.0f && - matrix->m[2][0] == 0.0f && - matrix->m[2][1] == 0.0f && - matrix->m[2][2] == 1.0f); -} - -static void _multiply_matrix(lv_matrix_t * matrix, const lv_matrix_t * mul) -{ - /*TODO: use NEON to optimize this function on ARM architecture.*/ - lv_matrix_t tmp; - - for(int y = 0; y < 3; y++) { - for(int x = 0; x < 3; x++) { - tmp.m[y][x] = (matrix->m[y][0] * mul->m[0][x]) - + (matrix->m[y][1] * mul->m[1][x]) - + (matrix->m[y][2] * mul->m[2][x]); - } - } - - lv_memcpy(matrix, &tmp, sizeof(lv_matrix_t)); -} - static void _copy_draw_dsc(lv_vector_draw_dsc_t * dst, const lv_vector_draw_dsc_t * src) { lv_memcpy(&(dst->fill_dsc), &(src->fill_dsc), sizeof(lv_vector_fill_dsc_t)); @@ -111,89 +84,6 @@ static void _copy_draw_dsc(lv_vector_draw_dsc_t * dst, const lv_vector_draw_dsc_ * GLOBAL FUNCTIONS **********************/ -/* matrix functions */ -void lv_matrix_identity(lv_matrix_t * matrix) -{ - matrix->m[0][0] = 1.0f; - matrix->m[0][1] = 0.0f; - matrix->m[0][2] = 0.0f; - matrix->m[1][0] = 0.0f; - matrix->m[1][1] = 1.0f; - matrix->m[1][2] = 0.0f; - matrix->m[2][0] = 0.0f; - matrix->m[2][1] = 0.0f; - matrix->m[2][2] = 1.0f; -} - -void lv_matrix_translate(lv_matrix_t * matrix, float dx, float dy) -{ - if(_is_identity_or_translation(matrix)) { - /*optimization for matrix translation.*/ - matrix->m[0][2] += dx; - matrix->m[1][2] += dy; - return; - } - - lv_matrix_t tlm = {{ - {1.0f, 0.0f, dx}, - {0.0f, 1.0f, dy}, - {0.0f, 0.0f, 1.0f}, - } - }; - - _multiply_matrix(matrix, &tlm); -} - -void lv_matrix_scale(lv_matrix_t * matrix, float scale_x, float scale_y) -{ - lv_matrix_t scm = {{ - {scale_x, 0.0f, 0.0f}, - {0.0f, scale_y, 0.0f}, - {0.0f, 0.0f, 1.0f}, - } - }; - - _multiply_matrix(matrix, &scm); -} - -void lv_matrix_rotate(lv_matrix_t * matrix, float degree) -{ - float radian = degree / 180.0f * (float)M_PI; - float cos_r = cosf(radian); - float sin_r = sinf(radian); - - lv_matrix_t rtm = {{ - {cos_r, -sin_r, 0.0f}, - {sin_r, cos_r, 0.0f}, - {0.0f, 0.0f, 1.0f}, - } - }; - - _multiply_matrix(matrix, &rtm); -} - -void lv_matrix_skew(lv_matrix_t * matrix, float skew_x, float skew_y) -{ - float rskew_x = skew_x / 180.0f * (float)M_PI; - float rskew_y = skew_y / 180.0f * (float)M_PI; - float tan_x = tanf(rskew_x); - float tan_y = tanf(rskew_y); - - lv_matrix_t skm = {{ - {1.0f, tan_x, 0.0f}, - {tan_y, 1.0f, 0.0f}, - {0.0f, 0.0f, 1.0f}, - } - }; - - _multiply_matrix(matrix, &skm); -} - -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; diff --git a/src/draw/lv_draw_vector.h b/src/draw/lv_draw_vector.h index c5366df720..83c66b4f70 100644 --- a/src/draw/lv_draw_vector.h +++ b/src/draw/lv_draw_vector.h @@ -15,9 +15,14 @@ extern "C" { *********************/ #include "lv_draw.h" #include "../misc/lv_array.h" +#include "../misc/lv_matrix.h" #if LV_USE_VECTOR_GRAPHIC +#if !LV_USE_MATRIX +#error "lv_draw_vector needs LV_USE_MATRIX = 1" +#endif + /********************** * TYPEDEFS **********************/ @@ -95,10 +100,6 @@ typedef struct { float y; } lv_fpoint_t; -typedef struct { - float m[3][3]; -} lv_matrix_t; - typedef struct { lv_vector_path_quality_t quality; lv_array_t ops; @@ -166,50 +167,6 @@ typedef struct { * GLOBAL PROTOTYPES **********************/ -/** - * Set matrix to identity matrix - * @param matrix pointer to a matrix - */ -void lv_matrix_identity(lv_matrix_t * matrix); - -/** - * Translate the matrix to new position - * @param matrix pointer to a matrix - * @param tx the amount of translate in x direction - * @param tx the amount of translate in y direction - */ -void lv_matrix_translate(lv_matrix_t * matrix, float tx, float ty); - -/** - * Change the scale factor of the matrix - * @param matrix pointer to a matrix - * @param scale_x the scale factor for the X direction - * @param scale_y the scale factor for the Y direction - */ -void lv_matrix_scale(lv_matrix_t * matrix, float scale_x, float scale_y); - -/** - * Rotate the matrix with origin - * @param matrix pointer to a matrix - * @param degree angle to rotate - */ -void lv_matrix_rotate(lv_matrix_t * matrix, float degree); - -/** - * Change the skew factor of the matrix - * @param matrix pointer to a matrix - * @param skew_x the skew factor for x direction - * @param skew_y the skew factor for y direction - */ -void lv_matrix_skew(lv_matrix_t * matrix, float skew_x, float skew_y); - -/** - * Multiply two matrix and store the result to the first one - * @param matrix pointer to a matrix - * @param matrix2 pointer to another matrix - */ -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 diff --git a/src/draw/vg_lite/lv_draw_vg_lite.c b/src/draw/vg_lite/lv_draw_vg_lite.c index 9057f31c76..6c39a31c70 100644 --- a/src/draw/vg_lite/lv_draw_vg_lite.c +++ b/src/draw/vg_lite/lv_draw_vg_lite.c @@ -116,6 +116,12 @@ static void draw_execute(lv_draw_vg_lite_unit_t * u) vg_lite_identity(&u->global_matrix); vg_lite_translate(-layer->buf_area.x1, -layer->buf_area.y1, &u->global_matrix); +#if LV_DRAW_TRANSFORM_USE_MATRIX + vg_lite_matrix_t layer_matrix; + lv_vg_lite_matrix(&layer_matrix, &t->matrix); + lv_vg_lite_matrix_multiply(&u->global_matrix, &layer_matrix); +#endif + switch(t->type) { case LV_DRAW_TASK_TYPE_LABEL: lv_draw_vg_lite_label(draw_unit, t->draw_dsc, &t->area); diff --git a/src/draw/vg_lite/lv_draw_vg_lite_label.c b/src/draw/vg_lite/lv_draw_vg_lite_label.c index ae409abf6d..9f241f6428 100644 --- a/src/draw/vg_lite/lv_draw_vg_lite_label.c +++ b/src/draw/vg_lite/lv_draw_vg_lite_label.c @@ -198,6 +198,7 @@ static void draw_letter_bitmap(lv_draw_vg_lite_unit_t * u, const lv_draw_glyph_d vg_lite_matrix_t path_matrix; vg_lite_identity(&path_matrix); lv_vg_lite_matrix_multiply(&path_matrix, &u->global_matrix); + LV_VG_LITE_ASSERT_MATRIX(&path_matrix); LV_PROFILER_BEGIN_TAG("vg_lite_draw_pattern"); LV_VG_LITE_CHECK_ERROR(vg_lite_draw_pattern( @@ -243,16 +244,24 @@ static void draw_letter_outline(lv_draw_vg_lite_unit_t * u, const lv_draw_glyph_ lv_vg_lite_path_t * outline = (lv_vg_lite_path_t *)dsc->glyph_data; lv_point_t pos = {dsc->letter_coords->x1, dsc->letter_coords->y1}; + /* scale size */ + float scale = FT_F26DOT6_TO_PATH_SCALE(lv_freetype_outline_get_scale(dsc->g->resolved_font)); /* calc convert matrix */ - float scale = FT_F26DOT6_TO_PATH_SCALE(lv_freetype_outline_get_scale(dsc->g->resolved_font)); vg_lite_matrix_t matrix; vg_lite_identity(&matrix); + /* matrix for drawing, different from matrix for calculating the bonding box */ + vg_lite_matrix_t draw_matrix; + vg_lite_identity(&draw_matrix); + + lv_vg_lite_matrix_multiply(&draw_matrix, &u->global_matrix); + /* convert to vg-lite coordinate */ + vg_lite_translate(pos.x - dsc->g->ofs_x, pos.y + dsc->g->box_h + dsc->g->ofs_y, &draw_matrix); vg_lite_translate(pos.x - dsc->g->ofs_x, pos.y + dsc->g->box_h + dsc->g->ofs_y, &matrix); - /* scale size */ + vg_lite_scale(scale, scale, &draw_matrix); vg_lite_scale(scale, scale, &matrix); /* calc inverse matrix */ @@ -272,20 +281,16 @@ static void draw_letter_outline(lv_draw_vg_lite_unit_t * u, const lv_draw_glyph_ /* Since the font uses Cartesian coordinates, the y coordinates need to be reversed */ lv_vg_lite_path_set_bonding_box(outline, p1_res.x, p2_res.y, p2_res.x, p1_res.y); - /* Move to the position relative to the first address of the buffer */ - lv_layer_t * layer = u->base_unit.target_layer; - vg_lite_translate(-layer->buf_area.x1 / scale, layer->buf_area.y1 / scale, &matrix); - vg_lite_path_t * vg_lite_path = lv_vg_lite_path_get_path(outline); LV_VG_LITE_ASSERT_DEST_BUFFER(&u->target_buffer); LV_VG_LITE_ASSERT_PATH(vg_lite_path); - LV_VG_LITE_ASSERT_MATRIX(&matrix); + LV_VG_LITE_ASSERT_MATRIX(&draw_matrix); LV_PROFILER_BEGIN_TAG("vg_lite_draw"); LV_VG_LITE_CHECK_ERROR(vg_lite_draw( &u->target_buffer, vg_lite_path, VG_LITE_FILL_NON_ZERO, - &matrix, VG_LITE_BLEND_SRC_OVER, lv_vg_lite_color(dsc->color, dsc->opa, true))); + &draw_matrix, VG_LITE_BLEND_SRC_OVER, lv_vg_lite_color(dsc->color, dsc->opa, true))); LV_PROFILER_END_TAG("vg_lite_draw"); /* Flush in time to avoid accumulation of drawing commands */ 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 cbf96badc0..80d637e672 100644 --- a/src/draw/vg_lite/lv_draw_vg_lite_vector.c +++ b/src/draw/vg_lite/lv_draw_vg_lite_vector.c @@ -35,7 +35,6 @@ typedef void (*path_drop_func_t)(struct _lv_draw_vg_lite_unit_t *, path_drop_dat **********************/ static void task_draw_cb(void * ctx, const lv_vector_path_t * path, const lv_vector_draw_dsc_t * dsc); -static void lv_matrix_to_vg(vg_lite_matrix_t * desy, const lv_matrix_t * src); static void lv_path_to_vg(lv_vg_lite_path_t * dest, const lv_vector_path_t * src); static vg_lite_path_type_t lv_path_opa_to_path_type(const lv_vector_draw_dsc_t * dsc); static vg_lite_blend_t lv_blend_to_vg(lv_vector_blend_t blend); @@ -106,7 +105,7 @@ static void task_draw_cb(void * ctx, const lv_vector_path_t * path, const lv_vec /* transform matrix */ vg_lite_matrix_t matrix; - lv_matrix_to_vg(&matrix, &dsc->matrix); + lv_vg_lite_matrix(&matrix, &dsc->matrix); LV_VG_LITE_ASSERT_MATRIX(&matrix); /* convert path */ @@ -223,7 +222,7 @@ static void task_draw_cb(void * ctx, const lv_vector_path_t * path, const lv_vec lv_matrix_multiply(&m, &dsc->fill_dsc.matrix); vg_lite_matrix_t pattern_matrix; - lv_matrix_to_vg(&pattern_matrix, &m); + lv_vg_lite_matrix(&pattern_matrix, &m); vg_lite_color_t recolor = lv_vg_lite_color(dsc->fill_dsc.img_dsc.recolor, dsc->fill_dsc.img_dsc.recolor_opa, true); @@ -250,7 +249,7 @@ static void task_draw_cb(void * ctx, const lv_vector_path_t * path, const lv_vec break; case LV_VECTOR_DRAW_STYLE_GRADIENT: { vg_lite_matrix_t grad_matrix; - lv_matrix_to_vg(&grad_matrix, &dsc->fill_dsc.matrix); + lv_vg_lite_matrix(&grad_matrix, &dsc->fill_dsc.matrix); lv_vg_lite_draw_grad( u, @@ -282,11 +281,6 @@ static void task_draw_cb(void * ctx, const lv_vector_path_t * path, const lv_vec LV_PROFILER_END; } -static void lv_matrix_to_vg(vg_lite_matrix_t * dest, const lv_matrix_t * src) -{ - lv_memcpy(dest, src, sizeof(lv_matrix_t)); -} - static vg_lite_quality_t lv_quality_to_vg(lv_vector_path_quality_t quality) { switch(quality) { diff --git a/src/draw/vg_lite/lv_vg_lite_grad.c b/src/draw/vg_lite/lv_vg_lite_grad.c index d01edba1b1..4276aedc93 100644 --- a/src/draw/vg_lite/lv_vg_lite_grad.c +++ b/src/draw/vg_lite/lv_vg_lite_grad.c @@ -153,9 +153,9 @@ 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); - - grad_point_to_matrix(grad_mat_p, grad->x1, grad->y1, grad->x2, grad->y2); + vg_lite_identity(grad_mat_p); lv_vg_lite_matrix_multiply(grad_mat_p, grad_matrix); + grad_point_to_matrix(grad_mat_p, grad->x1, grad->y1, grad->x2, grad->y2); LV_VG_LITE_ASSERT_SRC_BUFFER(&linear_grad->image); @@ -314,10 +314,7 @@ bool lv_vg_lite_draw_grad_helper( return false; } - vg_lite_matrix_t grad_matrix; - vg_lite_identity(&grad_matrix); - - return lv_vg_lite_draw_grad(u, buffer, path, &grad, &grad_matrix, matrix, fill, blend); + return lv_vg_lite_draw_grad(u, buffer, path, &grad, matrix, matrix, fill, blend); } /********************** @@ -548,7 +545,6 @@ static grad_type_t lv_grad_style_to_type(lv_vector_gradient_style_t style) static void grad_point_to_matrix(vg_lite_matrix_t * grad_matrix, float x1, float y1, float x2, float y2) { - vg_lite_identity(grad_matrix); vg_lite_translate(x1, y1, grad_matrix); float angle = atan2f(y2 - y1, x2 - x1) * 180.0f / (float)M_PI; diff --git a/src/draw/vg_lite/lv_vg_lite_utils.c b/src/draw/vg_lite/lv_vg_lite_utils.c index 16fb295310..87c68658f2 100644 --- a/src/draw/vg_lite/lv_vg_lite_utils.c +++ b/src/draw/vg_lite/lv_vg_lite_utils.c @@ -776,6 +776,15 @@ void lv_vg_lite_rect(vg_lite_rectangle_t * rect, const lv_area_t * area) rect->height = lv_area_get_height(area); } +#if LV_USE_MATRIX + +void lv_vg_lite_matrix(vg_lite_matrix_t * dest, const lv_matrix_t * src) +{ + lv_memcpy(dest, src, sizeof(lv_matrix_t)); +} + +#endif + uint32_t lv_vg_lite_get_palette_size(vg_lite_buffer_format_t format) { uint32_t size = 0; diff --git a/src/draw/vg_lite/lv_vg_lite_utils.h b/src/draw/vg_lite/lv_vg_lite_utils.h index 9e62ae448e..d107840d72 100644 --- a/src/draw/vg_lite/lv_vg_lite_utils.h +++ b/src/draw/vg_lite/lv_vg_lite_utils.h @@ -145,6 +145,12 @@ vg_lite_color_t lv_vg_lite_color(lv_color_t color, lv_opa_t opa, bool pre_mul); void lv_vg_lite_rect(vg_lite_rectangle_t * rect, const lv_area_t * area); +#if LV_USE_MATRIX + +void lv_vg_lite_matrix(vg_lite_matrix_t * dest, const lv_matrix_t * src); + +#endif + /* Param checker */ bool lv_vg_lite_buffer_check(const vg_lite_buffer_t * buffer, bool is_src); diff --git a/src/libs/thorvg/tvgSwRasterTexmap.h b/src/libs/thorvg/tvgSwRasterTexmap.h index 1a19e38b46..6ef2e32047 100644 --- a/src/libs/thorvg/tvgSwRasterTexmap.h +++ b/src/libs/thorvg/tvgSwRasterTexmap.h @@ -836,11 +836,13 @@ static AASpans* _AASpans(float ymin, float ymax, const SwImage* image, const SwB //Initialize X range auto height = yEnd - yStart; - aaSpans->lines = static_cast(calloc(height, sizeof(AALine))); + aaSpans->lines = static_cast(malloc(height * sizeof(AALine))); for (int32_t i = 0; i < height; i++) { aaSpans->lines[i].x[0] = INT32_MAX; - aaSpans->lines[i].x[1] = INT32_MIN; + aaSpans->lines[i].x[1] = 0; + aaSpans->lines[i].length[0] = 0; + aaSpans->lines[i].length[1] = 0; } return aaSpans; } diff --git a/src/lv_conf_internal.h b/src/lv_conf_internal.h index aa8cfc4a9d..d2f839ad51 100644 --- a/src/lv_conf_internal.h +++ b/src/lv_conf_internal.h @@ -293,6 +293,18 @@ #endif #endif +/*Using matrix for transformations. + *Requirements: + `LV_USE_MATRIX = 1`. + The rendering engine needs to support 3x3 matrix transformations.*/ +#ifndef LV_DRAW_TRANSFORM_USE_MATRIX + #ifdef CONFIG_LV_DRAW_TRANSFORM_USE_MATRIX + #define LV_DRAW_TRANSFORM_USE_MATRIX CONFIG_LV_DRAW_TRANSFORM_USE_MATRIX + #else + #define LV_DRAW_TRANSFORM_USE_MATRIX 0 + #endif +#endif + /* If a widget has `style_opa < 255` (not `bg_opa`, `text_opa` etc) or not NORMAL blend mode * it is buffered into a "simple" layer before rendering. The widget can be buffered in smaller chunks. * "Transformed layers" (if `transform_angle/zoom` are set) use larger buffers @@ -1291,6 +1303,16 @@ #endif #endif +/*Enable matrix support + *Requires `LV_USE_FLOAT = 1`*/ +#ifndef LV_USE_MATRIX + #ifdef CONFIG_LV_USE_MATRIX + #define LV_USE_MATRIX CONFIG_LV_USE_MATRIX + #else + #define LV_USE_MATRIX 0 + #endif +#endif + /*================== * FONT USAGE *===================*/ @@ -2636,7 +2658,8 @@ #endif #endif -/*Enable Vector Graphic APIs*/ +/*Enable Vector Graphic APIs + *Requires `LV_USE_MATRIX = 1`*/ #ifndef LV_USE_VECTOR_GRAPHIC #ifdef CONFIG_LV_USE_VECTOR_GRAPHIC #define LV_USE_VECTOR_GRAPHIC CONFIG_LV_USE_VECTOR_GRAPHIC diff --git a/src/misc/lv_matrix.c b/src/misc/lv_matrix.c new file mode 100644 index 0000000000..d6bc117f5b --- /dev/null +++ b/src/misc/lv_matrix.c @@ -0,0 +1,227 @@ +/** + * @file lv_matrix.c + * + */ + +/********************* + * INCLUDES + *********************/ + +#include "lv_matrix.h" + +#if LV_USE_MATRIX + +#include "../stdlib/lv_string.h" +#include "lv_math.h" + +#include + +/********************* + * DEFINES + *********************/ +#ifndef M_PI + #define M_PI 3.1415926f +#endif + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * STATIC PROTOTYPES + **********************/ + +/********************** + * STATIC VARIABLES + **********************/ + +/********************** + * MACROS + **********************/ + +/********************** + * GLOBAL FUNCTIONS + **********************/ + +void lv_matrix_identity(lv_matrix_t * matrix) +{ + matrix->m[0][0] = 1.0f; + matrix->m[0][1] = 0.0f; + matrix->m[0][2] = 0.0f; + matrix->m[1][0] = 0.0f; + matrix->m[1][1] = 1.0f; + matrix->m[1][2] = 0.0f; + matrix->m[2][0] = 0.0f; + matrix->m[2][1] = 0.0f; + matrix->m[2][2] = 1.0f; +} + +void lv_matrix_translate(lv_matrix_t * matrix, float dx, float dy) +{ + if(lv_matrix_is_identity_or_translation(matrix)) { + /*optimization for matrix translation.*/ + matrix->m[0][2] += dx; + matrix->m[1][2] += dy; + return; + } + + lv_matrix_t tlm = {{ + {1.0f, 0.0f, dx}, + {0.0f, 1.0f, dy}, + {0.0f, 0.0f, 1.0f}, + } + }; + + lv_matrix_multiply(matrix, &tlm); +} + +void lv_matrix_scale(lv_matrix_t * matrix, float scale_x, float scale_y) +{ + lv_matrix_t scm = {{ + {scale_x, 0.0f, 0.0f}, + {0.0f, scale_y, 0.0f}, + {0.0f, 0.0f, 1.0f}, + } + }; + + lv_matrix_multiply(matrix, &scm); +} + +void lv_matrix_rotate(lv_matrix_t * matrix, float degree) +{ + float radian = degree / 180.0f * (float)M_PI; + float cos_r = cosf(radian); + float sin_r = sinf(radian); + + lv_matrix_t rtm = {{ + {cos_r, -sin_r, 0.0f}, + {sin_r, cos_r, 0.0f}, + {0.0f, 0.0f, 1.0f}, + } + }; + + lv_matrix_multiply(matrix, &rtm); +} + +void lv_matrix_skew(lv_matrix_t * matrix, float skew_x, float skew_y) +{ + float rskew_x = skew_x / 180.0f * (float)M_PI; + float rskew_y = skew_y / 180.0f * (float)M_PI; + float tan_x = tanf(rskew_x); + float tan_y = tanf(rskew_y); + + lv_matrix_t skm = {{ + {1.0f, tan_x, 0.0f}, + {tan_y, 1.0f, 0.0f}, + {0.0f, 0.0f, 1.0f}, + } + }; + + lv_matrix_multiply(matrix, &skm); +} + +void lv_matrix_multiply(lv_matrix_t * matrix, const lv_matrix_t * mul) +{ + /*TODO: use NEON to optimize this function on ARM architecture.*/ + lv_matrix_t tmp; + + for(int y = 0; y < 3; y++) { + for(int x = 0; x < 3; x++) { + tmp.m[y][x] = (matrix->m[y][0] * mul->m[0][x]) + + (matrix->m[y][1] * mul->m[1][x]) + + (matrix->m[y][2] * mul->m[2][x]); + } + } + + lv_memcpy(matrix, &tmp, sizeof(lv_matrix_t)); +} + +bool lv_matrix_inverse(lv_matrix_t * matrix, const lv_matrix_t * m) +{ + float det00, det01, det02; + float d; + bool is_affine; + + /* Test for identity matrix. */ + if(m == NULL) { + lv_matrix_identity(matrix); + return true; + } + + det00 = (m->m[1][1] * m->m[2][2]) - (m->m[2][1] * m->m[1][2]); + det01 = (m->m[2][0] * m->m[1][2]) - (m->m[1][0] * m->m[2][2]); + det02 = (m->m[1][0] * m->m[2][1]) - (m->m[2][0] * m->m[1][1]); + + /* Compute determinant. */ + d = (m->m[0][0] * det00) + (m->m[0][1] * det01) + (m->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 = (m->m[2][0] == 0.0f) && (m->m[2][1] == 0.0f) && (m->m[2][2] == 1.0f); + + matrix->m[0][0] = d * det00; + matrix->m[0][1] = d * ((m->m[2][1] * m->m[0][2]) - (m->m[0][1] * m->m[2][2])); + matrix->m[0][2] = d * ((m->m[0][1] * m->m[1][2]) - (m->m[1][1] * m->m[0][2])); + matrix->m[1][0] = d * det01; + matrix->m[1][1] = d * ((m->m[0][0] * m->m[2][2]) - (m->m[2][0] * m->m[0][2])); + matrix->m[1][2] = d * ((m->m[1][0] * m->m[0][2]) - (m->m[0][0] * m->m[1][2])); + matrix->m[2][0] = is_affine ? 0.0f : d * det02; + matrix->m[2][1] = is_affine ? 0.0f : d * ((m->m[2][0] * m->m[0][1]) - (m->m[0][0] * m->m[2][1])); + matrix->m[2][2] = is_affine ? 1.0f : d * ((m->m[0][0] * m->m[1][1]) - (m->m[1][0] * m->m[0][1])); + + /* Success. */ + return true; +} + +lv_point_precise_t lv_matrix_transform_precise_point(const lv_matrix_t * matrix, const lv_point_precise_t * point) +{ + lv_point_precise_t p; + p.x = (lv_value_precise_t)(point->x * matrix->m[0][0] + point->y * matrix->m[0][1] + matrix->m[0][2]); + p.y = (lv_value_precise_t)(point->x * matrix->m[1][0] + point->y * matrix->m[1][1] + matrix->m[1][2]); + return p; +} + +lv_area_t lv_matrix_transform_area(const lv_matrix_t * matrix, const lv_area_t * area) +{ + lv_area_t res; + lv_point_precise_t p[4] = { + {area->x1, area->y1}, + {area->x1, area->y2}, + {area->x2, area->y1}, + {area->x2, area->y2}, + }; + p[0] = lv_matrix_transform_precise_point(matrix, &p[0]); + p[1] = lv_matrix_transform_precise_point(matrix, &p[1]); + p[2] = lv_matrix_transform_precise_point(matrix, &p[2]); + p[3] = lv_matrix_transform_precise_point(matrix, &p[3]); + + res.x1 = (int32_t)(LV_MIN4(p[0].x, p[1].x, p[2].x, p[3].x)); + res.x2 = (int32_t)(LV_MAX4(p[0].x, p[1].x, p[2].x, p[3].x)); + res.y1 = (int32_t)(LV_MIN4(p[0].y, p[1].y, p[2].y, p[3].y)); + res.y2 = (int32_t)(LV_MAX4(p[0].y, p[1].y, p[2].y, p[3].y)); + + return res; +} + +bool lv_matrix_is_identity_or_translation(const lv_matrix_t * matrix) +{ + return (matrix->m[0][0] == 1.0f && + matrix->m[0][1] == 0.0f && + matrix->m[1][0] == 0.0f && + matrix->m[1][1] == 1.0f && + matrix->m[2][0] == 0.0f && + matrix->m[2][1] == 0.0f && + matrix->m[2][2] == 1.0f); +} + +/********************** + * STATIC FUNCTIONS + **********************/ + +#endif /*LV_USE_MATRIX*/ diff --git a/src/misc/lv_matrix.h b/src/misc/lv_matrix.h new file mode 100644 index 0000000000..394ae18190 --- /dev/null +++ b/src/misc/lv_matrix.h @@ -0,0 +1,130 @@ +/** + * @file lv_matrix.h + * + */ + +#ifndef LV_MATRIX_H +#define LV_MATRIX_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ + +#include "../lv_conf_internal.h" + +#if LV_USE_MATRIX + +#include "lv_types.h" +#include "lv_area.h" + + +/********************* + * DEFINES + *********************/ + +#if !LV_USE_FLOAT +#error "LV_USE_FLOAT is required for lv_matrix" +#endif + +/********************** + * TYPEDEFS + **********************/ + +typedef struct { + float m[3][3]; +} lv_matrix_t; + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +/** + * Set matrix to identity matrix + * @param matrix pointer to a matrix + */ +void lv_matrix_identity(lv_matrix_t * matrix); + +/** + * Translate the matrix to new position + * @param matrix pointer to a matrix + * @param tx the amount of translate in x direction + * @param tx the amount of translate in y direction + */ +void lv_matrix_translate(lv_matrix_t * matrix, float tx, float ty); + +/** + * Change the scale factor of the matrix + * @param matrix pointer to a matrix + * @param scale_x the scale factor for the X direction + * @param scale_y the scale factor for the Y direction + */ +void lv_matrix_scale(lv_matrix_t * matrix, float scale_x, float scale_y); + +/** + * Rotate the matrix with origin + * @param matrix pointer to a matrix + * @param degree angle to rotate + */ +void lv_matrix_rotate(lv_matrix_t * matrix, float degree); + +/** + * Change the skew factor of the matrix + * @param matrix pointer to a matrix + * @param skew_x the skew factor for x direction + * @param skew_y the skew factor for y direction + */ +void lv_matrix_skew(lv_matrix_t * matrix, float skew_x, float skew_y); + +/** + * Multiply two matrix and store the result to the first one + * @param matrix pointer to a matrix + * @param matrix2 pointer to another matrix + */ +void lv_matrix_multiply(lv_matrix_t * matrix, const lv_matrix_t * mul); + +/** + * Invert the matrix + * @param matrix pointer to a matrix + * @param m pointer to another matrix (optional) + * @return true: the matrix is invertible, false: the matrix is singular and cannot be inverted + */ +bool lv_matrix_inverse(lv_matrix_t * matrix, const lv_matrix_t * m); + +/** + * Transform a point by a matrix + * @param matrix pointer to a matrix + * @param point pointer to a point + * @return the transformed point + */ +lv_point_precise_t lv_matrix_transform_precise_point(const lv_matrix_t * matrix, const lv_point_precise_t * point); + +/** + * Transform an area by a matrix + * @param matrix pointer to a matrix + * @param area pointer to an area + * @return the transformed area + */ +lv_area_t lv_matrix_transform_area(const lv_matrix_t * matrix, const lv_area_t * area); + +/** + * Check if the matrix is identity or translation matrix + * @param matrix pointer to a matrix + * @return true: the matrix is identity or translation matrix, false: the matrix is not identity or translation matrix + */ +bool lv_matrix_is_identity_or_translation(const lv_matrix_t * matrix); + +/********************** + * MACROS + **********************/ + +#endif /*LV_USE_MATRIX*/ + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif /*LV_MATRIX_H*/ diff --git a/src/others/snapshot/lv_snapshot.c b/src/others/snapshot/lv_snapshot.c index 07d0950b07..74609aa370 100644 --- a/src/others/snapshot/lv_snapshot.c +++ b/src/others/snapshot/lv_snapshot.c @@ -111,6 +111,9 @@ lv_result_t lv_snapshot_take_to_draw_buf(lv_obj_t * obj, lv_color_format_t cf, l layer.buf_area.y2 = snapshot_area.y1 + h - 1; layer.color_format = cf; layer._clip_area = snapshot_area; +#if LV_DRAW_TRANSFORM_USE_MATRIX + lv_matrix_identity(&layer.matrix); +#endif lv_display_t * disp_old = _lv_refr_get_disp_refreshing(); lv_display_t * disp_new = lv_obj_get_display(obj); diff --git a/src/widgets/canvas/lv_canvas.c b/src/widgets/canvas/lv_canvas.c index 836e81cbf4..b3823fc718 100644 --- a/src/widgets/canvas/lv_canvas.c +++ b/src/widgets/canvas/lv_canvas.c @@ -377,6 +377,9 @@ void lv_canvas_init_layer(lv_obj_t * obj, lv_layer_t * layer) layer->color_format = header->cf; layer->buf_area = canvas_area; layer->_clip_area = canvas_area; +#if LV_DRAW_TRANSFORM_USE_MATRIX + lv_matrix_identity(&layer->matrix); +#endif } void lv_canvas_finish_layer(lv_obj_t * canvas, lv_layer_t * layer) diff --git a/tests/ref_imgs_vg_lite/draw/draw_layer_bitmap_mask.png b/tests/ref_imgs_vg_lite/draw/draw_layer_bitmap_mask.png index 8a4b6fac81..9c44eecba4 100644 Binary files a/tests/ref_imgs_vg_lite/draw/draw_layer_bitmap_mask.png and b/tests/ref_imgs_vg_lite/draw/draw_layer_bitmap_mask.png differ diff --git a/tests/ref_imgs_vg_lite/draw/draw_layer_bitmap_mask_not_masked.png b/tests/ref_imgs_vg_lite/draw/draw_layer_bitmap_mask_not_masked.png index 8a4b6fac81..9c44eecba4 100644 Binary files a/tests/ref_imgs_vg_lite/draw/draw_layer_bitmap_mask_not_masked.png and b/tests/ref_imgs_vg_lite/draw/draw_layer_bitmap_mask_not_masked.png differ diff --git a/tests/ref_imgs_vg_lite/draw/layer_transform_2.png b/tests/ref_imgs_vg_lite/draw/layer_transform_2.png index 5518b701d9..5d5711ec98 100644 Binary files a/tests/ref_imgs_vg_lite/draw/layer_transform_2.png and b/tests/ref_imgs_vg_lite/draw/layer_transform_2.png differ diff --git a/tests/ref_imgs_vg_lite/draw/render/argb8888/demo_render_layer_normal_opa_128.png b/tests/ref_imgs_vg_lite/draw/render/argb8888/demo_render_layer_normal_opa_128.png index d74b98619c..34e766e458 100644 Binary files a/tests/ref_imgs_vg_lite/draw/render/argb8888/demo_render_layer_normal_opa_128.png and b/tests/ref_imgs_vg_lite/draw/render/argb8888/demo_render_layer_normal_opa_128.png differ diff --git a/tests/ref_imgs_vg_lite/draw/render/argb8888/demo_render_layer_normal_opa_255.png b/tests/ref_imgs_vg_lite/draw/render/argb8888/demo_render_layer_normal_opa_255.png index 97ed7855a5..f20c381178 100644 Binary files a/tests/ref_imgs_vg_lite/draw/render/argb8888/demo_render_layer_normal_opa_255.png and b/tests/ref_imgs_vg_lite/draw/render/argb8888/demo_render_layer_normal_opa_255.png differ diff --git a/tests/ref_imgs_vg_lite/draw/render/l8/demo_render_layer_normal_opa_128.png b/tests/ref_imgs_vg_lite/draw/render/l8/demo_render_layer_normal_opa_128.png index e454c8e4ee..7fbc1b2e36 100644 Binary files a/tests/ref_imgs_vg_lite/draw/render/l8/demo_render_layer_normal_opa_128.png and b/tests/ref_imgs_vg_lite/draw/render/l8/demo_render_layer_normal_opa_128.png differ diff --git a/tests/ref_imgs_vg_lite/draw/render/l8/demo_render_layer_normal_opa_255.png b/tests/ref_imgs_vg_lite/draw/render/l8/demo_render_layer_normal_opa_255.png index 48fdf0a508..239ebd531c 100644 Binary files a/tests/ref_imgs_vg_lite/draw/render/l8/demo_render_layer_normal_opa_255.png and b/tests/ref_imgs_vg_lite/draw/render/l8/demo_render_layer_normal_opa_255.png differ diff --git a/tests/ref_imgs_vg_lite/draw/render/rgb565/demo_render_blend_mode_opa_128.png b/tests/ref_imgs_vg_lite/draw/render/rgb565/demo_render_blend_mode_opa_128.png index 1a37a6a4c2..2be528e265 100644 Binary files a/tests/ref_imgs_vg_lite/draw/render/rgb565/demo_render_blend_mode_opa_128.png and b/tests/ref_imgs_vg_lite/draw/render/rgb565/demo_render_blend_mode_opa_128.png differ diff --git a/tests/ref_imgs_vg_lite/draw/render/rgb565/demo_render_blend_mode_opa_255.png b/tests/ref_imgs_vg_lite/draw/render/rgb565/demo_render_blend_mode_opa_255.png index b39303b786..0cd8b6c1e8 100644 Binary files a/tests/ref_imgs_vg_lite/draw/render/rgb565/demo_render_blend_mode_opa_255.png and b/tests/ref_imgs_vg_lite/draw/render/rgb565/demo_render_blend_mode_opa_255.png differ diff --git a/tests/ref_imgs_vg_lite/draw/render/rgb565/demo_render_layer_normal_opa_128.png b/tests/ref_imgs_vg_lite/draw/render/rgb565/demo_render_layer_normal_opa_128.png index 15a4dcfce0..1478062197 100644 Binary files a/tests/ref_imgs_vg_lite/draw/render/rgb565/demo_render_layer_normal_opa_128.png and b/tests/ref_imgs_vg_lite/draw/render/rgb565/demo_render_layer_normal_opa_128.png differ diff --git a/tests/ref_imgs_vg_lite/draw/render/rgb565/demo_render_layer_normal_opa_255.png b/tests/ref_imgs_vg_lite/draw/render/rgb565/demo_render_layer_normal_opa_255.png index a40e13f6eb..967ddb576c 100644 Binary files a/tests/ref_imgs_vg_lite/draw/render/rgb565/demo_render_layer_normal_opa_255.png and b/tests/ref_imgs_vg_lite/draw/render/rgb565/demo_render_layer_normal_opa_255.png differ diff --git a/tests/ref_imgs_vg_lite/draw/render/rgb888/demo_render_blend_mode_opa_128.png b/tests/ref_imgs_vg_lite/draw/render/rgb888/demo_render_blend_mode_opa_128.png index ec363e5a54..c791794ed2 100644 Binary files a/tests/ref_imgs_vg_lite/draw/render/rgb888/demo_render_blend_mode_opa_128.png and b/tests/ref_imgs_vg_lite/draw/render/rgb888/demo_render_blend_mode_opa_128.png differ diff --git a/tests/ref_imgs_vg_lite/draw/render/rgb888/demo_render_blend_mode_opa_255.png b/tests/ref_imgs_vg_lite/draw/render/rgb888/demo_render_blend_mode_opa_255.png index ea6c1d5f9e..ff9f92c689 100644 Binary files a/tests/ref_imgs_vg_lite/draw/render/rgb888/demo_render_blend_mode_opa_255.png and b/tests/ref_imgs_vg_lite/draw/render/rgb888/demo_render_blend_mode_opa_255.png differ diff --git a/tests/ref_imgs_vg_lite/draw/render/rgb888/demo_render_layer_normal_opa_128.png b/tests/ref_imgs_vg_lite/draw/render/rgb888/demo_render_layer_normal_opa_128.png index d74b98619c..34e766e458 100644 Binary files a/tests/ref_imgs_vg_lite/draw/render/rgb888/demo_render_layer_normal_opa_128.png and b/tests/ref_imgs_vg_lite/draw/render/rgb888/demo_render_layer_normal_opa_128.png differ diff --git a/tests/ref_imgs_vg_lite/draw/render/rgb888/demo_render_layer_normal_opa_255.png b/tests/ref_imgs_vg_lite/draw/render/rgb888/demo_render_layer_normal_opa_255.png index 97ed7855a5..f20c381178 100644 Binary files a/tests/ref_imgs_vg_lite/draw/render/rgb888/demo_render_layer_normal_opa_255.png and b/tests/ref_imgs_vg_lite/draw/render/rgb888/demo_render_layer_normal_opa_255.png differ diff --git a/tests/ref_imgs_vg_lite/draw/render/xrgb8888/demo_render_layer_normal_opa_128.png b/tests/ref_imgs_vg_lite/draw/render/xrgb8888/demo_render_layer_normal_opa_128.png index d74b98619c..34e766e458 100644 Binary files a/tests/ref_imgs_vg_lite/draw/render/xrgb8888/demo_render_layer_normal_opa_128.png and b/tests/ref_imgs_vg_lite/draw/render/xrgb8888/demo_render_layer_normal_opa_128.png differ diff --git a/tests/ref_imgs_vg_lite/draw/render/xrgb8888/demo_render_layer_normal_opa_255.png b/tests/ref_imgs_vg_lite/draw/render/xrgb8888/demo_render_layer_normal_opa_255.png index 97ed7855a5..f20c381178 100644 Binary files a/tests/ref_imgs_vg_lite/draw/render/xrgb8888/demo_render_layer_normal_opa_255.png and b/tests/ref_imgs_vg_lite/draw/render/xrgb8888/demo_render_layer_normal_opa_255.png differ diff --git a/tests/ref_imgs_vg_lite/widgets/bar_corner_2.png b/tests/ref_imgs_vg_lite/widgets/bar_corner_2.png index 018ae44dff..518a5b9134 100644 Binary files a/tests/ref_imgs_vg_lite/widgets/bar_corner_2.png and b/tests/ref_imgs_vg_lite/widgets/bar_corner_2.png differ diff --git a/tests/ref_imgs_vg_lite/widgets/bar_corner_3.png b/tests/ref_imgs_vg_lite/widgets/bar_corner_3.png index ddf83887dd..34392b2931 100644 Binary files a/tests/ref_imgs_vg_lite/widgets/bar_corner_3.png and b/tests/ref_imgs_vg_lite/widgets/bar_corner_3.png differ diff --git a/tests/ref_imgs_vg_lite/widgets/bar_corner_5.png b/tests/ref_imgs_vg_lite/widgets/bar_corner_5.png index 09d3d3feee..3cb878761a 100644 Binary files a/tests/ref_imgs_vg_lite/widgets/bar_corner_5.png and b/tests/ref_imgs_vg_lite/widgets/bar_corner_5.png differ diff --git a/tests/ref_imgs_vg_lite/widgets/bar_corner_6.png b/tests/ref_imgs_vg_lite/widgets/bar_corner_6.png index abfcf33080..dbc2ede580 100644 Binary files a/tests/ref_imgs_vg_lite/widgets/bar_corner_6.png and b/tests/ref_imgs_vg_lite/widgets/bar_corner_6.png differ diff --git a/tests/ref_imgs_vg_lite/widgets/obj_flag_overflow_visible_1_4.png b/tests/ref_imgs_vg_lite/widgets/obj_flag_overflow_visible_1_4.png index a20d5a7b1e..ecdd8f62e0 100644 Binary files a/tests/ref_imgs_vg_lite/widgets/obj_flag_overflow_visible_1_4.png and b/tests/ref_imgs_vg_lite/widgets/obj_flag_overflow_visible_1_4.png differ diff --git a/tests/src/lv_test_conf.h b/tests/src/lv_test_conf.h index 6ff7f50503..bc2809b231 100644 --- a/tests/src/lv_test_conf.h +++ b/tests/src/lv_test_conf.h @@ -110,10 +110,6 @@ typedef void * lv_user_data_t; #define LV_DPI_DEF 130 #endif -#if defined(LVGL_CI_USING_SYS_HEAP) -#undef LV_USE_FLOAT -#endif - #ifdef __cplusplus } /*extern "C"*/ #endif diff --git a/tests/src/lv_test_conf_full.h b/tests/src/lv_test_conf_full.h index 3d30b5db61..2c7e6c18df 100644 --- a/tests/src/lv_test_conf_full.h +++ b/tests/src/lv_test_conf_full.h @@ -10,6 +10,7 @@ #define LV_USE_ASSERT_OBJ 1 #define LV_USE_ASSERT_STYLE 1 #define LV_USE_FLOAT 1 +#define LV_USE_MATRIX 1 #define LV_FONT_MONTSERRAT_8 1 #define LV_FONT_MONTSERRAT_10 1 diff --git a/tests/src/lv_test_conf_vg_lite.h b/tests/src/lv_test_conf_vg_lite.h index 62a000e4a5..9adc7d20f9 100644 --- a/tests/src/lv_test_conf_vg_lite.h +++ b/tests/src/lv_test_conf_vg_lite.h @@ -31,3 +31,9 @@ /* Enable performance monitor log mode for build test */ #define LV_USE_PERF_MONITOR_LOG_MODE 1 + +/*Using matrix for transformations. + *Requirements: + `LV_USE_MATRIX = 1`. + The rendering engine needs to support 3x3 matrix transformations.*/ +#define LV_DRAW_TRANSFORM_USE_MATRIX 1