feat(draw): add global matrix drawing modes (#4883)
Signed-off-by: pengyiqiang <pengyiqiang@xiaomi.com> Signed-off-by: wangxuedong <wangxuedong@xiaomi.com> Co-authored-by: pengyiqiang <pengyiqiang@xiaomi.com> Co-authored-by: wangxuedong <wangxuedong@xiaomi.com>
15
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"
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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<AALine*>(calloc(height, sizeof(AALine)));
|
||||
aaSpans->lines = static_cast<AALine*>(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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
227
src/misc/lv_matrix.c
Normal file
@@ -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 <math.h>
|
||||
|
||||
/*********************
|
||||
* 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*/
|
||||
130
src/misc/lv_matrix.h
Normal file
@@ -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*/
|
||||
@@ -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);
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 15 KiB |
|
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 15 KiB |
|
Before Width: | Height: | Size: 3.9 KiB After Width: | Height: | Size: 3.9 KiB |
|
Before Width: | Height: | Size: 54 KiB After Width: | Height: | Size: 52 KiB |
|
Before Width: | Height: | Size: 55 KiB After Width: | Height: | Size: 51 KiB |
|
Before Width: | Height: | Size: 55 KiB After Width: | Height: | Size: 15 KiB |
|
Before Width: | Height: | Size: 58 KiB After Width: | Height: | Size: 16 KiB |
|
Before Width: | Height: | Size: 36 KiB After Width: | Height: | Size: 36 KiB |
|
Before Width: | Height: | Size: 41 KiB After Width: | Height: | Size: 40 KiB |
|
Before Width: | Height: | Size: 47 KiB After Width: | Height: | Size: 46 KiB |
|
Before Width: | Height: | Size: 50 KiB After Width: | Height: | Size: 46 KiB |
|
Before Width: | Height: | Size: 46 KiB After Width: | Height: | Size: 45 KiB |
|
Before Width: | Height: | Size: 48 KiB After Width: | Height: | Size: 47 KiB |
|
Before Width: | Height: | Size: 54 KiB After Width: | Height: | Size: 52 KiB |
|
Before Width: | Height: | Size: 55 KiB After Width: | Height: | Size: 51 KiB |
|
Before Width: | Height: | Size: 54 KiB After Width: | Height: | Size: 52 KiB |
|
Before Width: | Height: | Size: 55 KiB After Width: | Height: | Size: 51 KiB |
|
Before Width: | Height: | Size: 125 KiB After Width: | Height: | Size: 128 KiB |
|
Before Width: | Height: | Size: 128 KiB After Width: | Height: | Size: 129 KiB |
|
Before Width: | Height: | Size: 72 KiB After Width: | Height: | Size: 72 KiB |
|
Before Width: | Height: | Size: 69 KiB After Width: | Height: | Size: 78 KiB |
|
Before Width: | Height: | Size: 55 KiB After Width: | Height: | Size: 56 KiB |
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||