1
0
mirror of https://github.com/lvgl/lvgl.git synced 2025-01-21 06:53:01 +08:00

gird optimization

This commit is contained in:
Gabor Kiss-Vamosi 2020-08-31 09:33:44 +02:00
parent 03fa6b492c
commit 67d268b3ee
12 changed files with 308 additions and 168 deletions

View File

@ -1,3 +1,4 @@
CSRCS += lv_grid.c
CSRCS += lv_group.c CSRCS += lv_group.c
CSRCS += lv_indev.c CSRCS += lv_indev.c
CSRCS += lv_disp.c CSRCS += lv_disp.c

View File

@ -6,12 +6,13 @@
/********************* /*********************
* INCLUDES * INCLUDES
*********************/ *********************/
#include "lv_align.h" #include "lv_grid.h"
#include "lv_obj.h" #include "lv_obj.h"
/********************* /*********************
* DEFINES * DEFINES
*********************/ *********************/
#define CALC_DSC_BUF_SIZE 8
/********************** /**********************
* TYPEDEFS * TYPEDEFS
@ -20,16 +21,18 @@
/********************** /**********************
* STATIC PROTOTYPES * STATIC PROTOTYPES
**********************/ **********************/
static void calc_explicit(lv_obj_t * obj, _lv_grid_calc_t * calc);
static void calc_flow_row(lv_obj_t * obj, _lv_grid_calc_t * calc);
static void calc_explicit_cols(lv_obj_t * cont, _lv_grid_calc_t * calc); static void calc_explicit_cols(lv_obj_t * cont, _lv_grid_calc_t * calc);
static void calc_explicit_rows(lv_obj_t * cont, _lv_grid_calc_t * calc); static void calc_explicit_rows(lv_obj_t * cont, _lv_grid_calc_t * calc);
static void calc_implicit_cols(lv_obj_t * cont, _lv_grid_calc_t * calc);
static void calc_implicit_rows(lv_obj_t * cont, _lv_grid_calc_t * calc); static void calc_implicit_rows(lv_obj_t * cont, _lv_grid_calc_t * calc);
/********************** /**********************
* STATIC VARIABLES * STATIC VARIABLES
**********************/ **********************/
static lv_coord_t col_dsc_calc_buf[CALC_DSC_BUF_SIZE];
static lv_coord_t row_dsc_calc_buf[CALC_DSC_BUF_SIZE];
static bool col_dsc_buf_used;
static bool row_dsc_buf_used;
/********************** /**********************
* MACROS * MACROS
@ -41,14 +44,24 @@ static void calc_implicit_rows(lv_obj_t * cont, _lv_grid_calc_t * calc);
void grid_calc(struct _lv_obj_t * obj, _lv_grid_calc_t * calc) void grid_calc(struct _lv_obj_t * obj, _lv_grid_calc_t * calc)
{ {
static uint32_t cnt = 0;
cnt++;
if(obj->grid == NULL) return; if(obj->grid == NULL) return;
printf("calc: %d (size: %d)\n", cnt, obj->grid->col_dsc_len); // static uint32_t cnt = 0;
// cnt++;
// printf("calc: %d (size: %d)\n", cnt, obj->grid->col_dsc_len);
if(obj->grid->col_dsc && obj->grid->row_dsc) calc_explicit(obj, calc); if(obj->grid->col_dsc && obj->grid->row_dsc) {
else if(obj->grid->col_dsc && !obj->grid->row_dsc) calc_flow_row(obj, calc); calc_explicit_rows(obj, calc);
calc_explicit_cols(obj, calc);
}
else if(obj->grid->col_dsc && !obj->grid->row_dsc) {
calc_explicit_cols(obj, calc);
calc_implicit_rows(obj, calc);
}
else if(!obj->grid->col_dsc && obj->grid->row_dsc) {
calc_implicit_cols(obj, calc);
calc_explicit_rows(obj, calc);
}
} }
@ -89,27 +102,19 @@ bool _lv_grid_has_fr_row(struct _lv_obj_t * obj)
* STATIC FUNCTIONS * STATIC FUNCTIONS
**********************/ **********************/
static void calc_explicit(lv_obj_t * obj, _lv_grid_calc_t * calc)
{
calc_explicit_rows(obj, calc);
calc_explicit_cols(obj, calc);
}
static void calc_flow_row(lv_obj_t * obj, _lv_grid_calc_t * calc)
{
calc_explicit_cols(obj, calc);
calc_implicit_rows(obj, calc);
}
static void calc_explicit_cols(lv_obj_t * cont, _lv_grid_calc_t * calc) static void calc_explicit_cols(lv_obj_t * cont, _lv_grid_calc_t * calc)
{ {
lv_grid_t * grid = cont->grid; lv_grid_t * grid = cont->grid;
uint32_t i; uint32_t i;
lv_coord_t * cols_w = _lv_mem_buf_get(sizeof(lv_coord_t) * grid->col_dsc_len); lv_coord_t * cols_w;
if(!col_dsc_buf_used && grid->col_dsc_len <= CALC_DSC_BUF_SIZE) {
cols_w = col_dsc_calc_buf;
col_dsc_buf_used = true;
} else {
cols_w = _lv_mem_buf_get(sizeof(lv_coord_t) * grid->col_dsc_len);
}
uint32_t col_fr_cnt = 0; uint32_t col_fr_cnt = 0;
lv_coord_t grid_w = 0; lv_coord_t grid_w = 0;
bool auto_w = cont->w_set == LV_SIZE_AUTO ? true : false; bool auto_w = cont->w_set == LV_SIZE_AUTO ? true : false;
@ -144,16 +149,24 @@ static void calc_explicit_cols(lv_obj_t * cont, _lv_grid_calc_t * calc)
for(i = 0; i < grid->col_dsc_len; i++) { for(i = 0; i < grid->col_dsc_len; i++) {
calc->col_dsc[i + 1] = calc->col_dsc[i] + cols_w[i]; calc->col_dsc[i + 1] = calc->col_dsc[i] + cols_w[i];
} }
_lv_mem_buf_release(cols_w);
if(col_dsc_buf_used) col_dsc_buf_used = false ;
else _lv_mem_buf_release(cols_w);
} }
static void calc_explicit_rows(lv_obj_t * cont, _lv_grid_calc_t * calc) static void calc_explicit_rows(lv_obj_t * cont, _lv_grid_calc_t * calc)
{ {
lv_grid_t * grid = cont->grid; lv_grid_t * grid = cont->grid;
uint32_t i; uint32_t i;
calc_explicit_cols(cont, calc);
lv_coord_t * rows_h = _lv_mem_buf_get(sizeof(lv_coord_t) * grid->row_dsc_len); lv_coord_t * rows_h;
if(!row_dsc_buf_used && grid->row_dsc_len <= CALC_DSC_BUF_SIZE) {
rows_h = row_dsc_calc_buf;
row_dsc_buf_used = true;
} else {
rows_h = _lv_mem_buf_get(sizeof(lv_coord_t) * grid->row_dsc_len);
}
uint32_t row_fr_cnt = 0; uint32_t row_fr_cnt = 0;
lv_coord_t grid_h = 0; lv_coord_t grid_h = 0;
@ -192,7 +205,65 @@ static void calc_explicit_rows(lv_obj_t * cont, _lv_grid_calc_t * calc)
calc->row_dsc[i + 1] = calc->row_dsc[i] + rows_h[i]; calc->row_dsc[i + 1] = calc->row_dsc[i] + rows_h[i];
} }
_lv_mem_buf_release(rows_h); if(row_dsc_buf_used) row_dsc_buf_used = false;
else _lv_mem_buf_release(rows_h);
}
static void calc_implicit_cols(lv_obj_t * cont, _lv_grid_calc_t * calc)
{
lv_grid_t * grid = cont->grid;
uint32_t child_cnt = lv_obj_count_children(cont);
uint32_t col_cnt = (child_cnt / grid->row_dsc_len) + 1;
/* If `col_dsc_buf_used`, nested a call of this func. will release `col_dsc_buf_used` because it think it taken it.
* So mark that if the buffer was taken in this call*/
bool col_dsc_buf_mine = false;
/*At worst case all children is gird item prepare place for all of them*/
lv_coord_t * cols_w;
if(!col_dsc_buf_used && col_cnt <= CALC_DSC_BUF_SIZE) {
cols_w = col_dsc_calc_buf;
col_dsc_buf_used = true;
col_dsc_buf_mine = true;
} else {
cols_w = _lv_mem_buf_get(sizeof(lv_coord_t) * col_cnt);
}
uint32_t i;
lv_obj_t * child = lv_obj_get_child_back(cont, NULL);
uint32_t row_i = 0;
uint32_t col_i = 0;
cols_w[0] = 0;
while(child) {
if(_GRID_IS_CELL(child->x_set) && _GRID_IS_CELL(child->y_set)) {
lv_coord_t w;
if(_GRID_GET_CELL_FLAG(child->x_set) == LV_GRID_STRETCH) _lv_obj_calc_auto_size(child, &w, NULL);
else w = lv_obj_get_width(child);
cols_w[col_i] = LV_MATH_MAX(cols_w[col_i], w);
row_i++;
if(row_i == grid->row_dsc_len) {
row_i = 0;
col_i++;
cols_w[col_i] = 0;
}
}
child = lv_obj_get_child_back(cont, child);
}
calc->col_dsc_len = col_cnt + 1;
calc->col_dsc = _lv_mem_buf_get(sizeof(lv_coord_t) * calc->col_dsc_len);
calc->col_dsc[0] = 0;
for(i = 0; i < col_cnt; i++) {
calc->col_dsc[i + 1] = calc->col_dsc[i] + cols_w[i];
}
if(col_dsc_buf_used && col_dsc_buf_mine) col_dsc_buf_used = false;
else _lv_mem_buf_release(cols_w);
} }
@ -200,26 +271,36 @@ static void calc_implicit_rows(lv_obj_t * cont, _lv_grid_calc_t * calc)
{ {
lv_grid_t * grid = cont->grid; lv_grid_t * grid = cont->grid;
uint32_t child_cnt = lv_obj_count_children(cont); uint32_t child_cnt = lv_obj_count_children(cont);
uint32_t row_cnt = (child_cnt / grid->col_dsc_len) + 1; uint32_t row_cnt = (child_cnt / grid->col_dsc_len) + 1;
bool row_dsc_buf_mine = false;
/*At worst case all children is gird item prepare place for all of them*/ /*At worst case all children is gird item prepare place for all of them*/
lv_coord_t * rows_h = _lv_mem_buf_get(sizeof(lv_coord_t) * row_cnt); lv_coord_t * rows_h;
_lv_memset_00(rows_h, sizeof(lv_coord_t) * row_cnt); if(!row_dsc_buf_used && row_cnt <= CALC_DSC_BUF_SIZE) {
rows_h = row_dsc_calc_buf;
row_dsc_buf_used = true;
row_dsc_buf_mine = true;
} else {
rows_h = _lv_mem_buf_get(sizeof(lv_coord_t) * row_cnt);
}
uint32_t i; uint32_t i;
lv_obj_t * child = lv_obj_get_child_back(cont, NULL); lv_obj_t * child = lv_obj_get_child_back(cont, NULL);
uint32_t col_i = 0; uint32_t col_i = 0;
uint32_t row_i = 0; uint32_t row_i = 0;
rows_h[0] = 0;
while(child) { while(child) {
if(_GRID_IS_CELL(child->x_set) && _GRID_IS_CELL(child->y_set)) { if(_GRID_IS_CELL(child->x_set) && _GRID_IS_CELL(child->y_set)) {
rows_h[row_i] = LV_MATH_MAX(rows_h[row_i], lv_obj_get_height(child)); lv_coord_t h;
if(_GRID_GET_CELL_FLAG(child->y_set) == LV_GRID_STRETCH) _lv_obj_calc_auto_size(child, NULL, &h);
else h = lv_obj_get_height(child);
rows_h[row_i] = LV_MATH_MAX(rows_h[row_i], h);
col_i++; col_i++;
if(col_i == grid->col_dsc_len) { if(col_i == grid->col_dsc_len) {
col_i = 0; col_i = 0;
row_i++; row_i++;
rows_h[row_i] = 0;
} }
} }
child = lv_obj_get_child_back(cont, child); child = lv_obj_get_child_back(cont, child);
@ -235,5 +316,6 @@ static void calc_implicit_rows(lv_obj_t * cont, _lv_grid_calc_t * calc)
calc->row_dsc[i + 1] = calc->row_dsc[i] + rows_h[i]; calc->row_dsc[i + 1] = calc->row_dsc[i] + rows_h[i];
} }
_lv_mem_buf_release(rows_h); if(row_dsc_buf_used && row_dsc_buf_mine) row_dsc_buf_used = false;
else _lv_mem_buf_release(rows_h);
} }

View File

@ -3,8 +3,8 @@
* *
*/ */
#ifndef LV_ALIGN_H #ifndef LV_GRID_H
#define LV_ALIGN_H #define LV_GRID_H
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
@ -128,4 +128,4 @@ bool _lv_grid_has_fr_row(struct _lv_obj_t * obj);
} /* extern "C" */ } /* extern "C" */
#endif #endif
#endif /*LV_ALIGN_H*/ #endif /*LV_GRID_H*/

View File

@ -49,6 +49,10 @@
#define LV_OBJ_DEF_WIDTH (LV_DPX(100)) #define LV_OBJ_DEF_WIDTH (LV_DPX(100))
#define LV_OBJ_DEF_HEIGHT (LV_DPX(50)) #define LV_OBJ_DEF_HEIGHT (LV_DPX(50))
#define SCROLLBAR_MIN_SIZE (LV_DPX(10)) #define SCROLLBAR_MIN_SIZE (LV_DPX(10))
#define SCROLL_ANIM_TIME_MIN 100 /*ms*/
#define SCROLL_ANIM_TIME_MAX 300 /*ms*/
#define GRID_DEBUG 1 /*Draw rectangles on grid cells*/
/********************** /**********************
* TYPEDEFS * TYPEDEFS
@ -804,14 +808,14 @@ static bool refr_size(lv_obj_t * obj, lv_coord_t w, lv_coord_t h)
bool lv_obj_is_grid_item(lv_obj_t * obj); bool lv_obj_is_grid_item(lv_obj_t * obj);
static void lv_grid_full_refr(lv_obj_t * cont); static void lv_grid_full_refr(lv_obj_t * cont);
static void _grid_item_repos(lv_obj_t * cont, lv_obj_t * item, _lv_grid_calc_t * calc) static void _grid_item_repos(lv_obj_t * cont, lv_obj_t * item, _lv_grid_calc_t * calc, uint32_t * child_id_ext, lv_point_t * grid_abs)
{ {
if(lv_obj_is_grid_item(item) == false) return; if(lv_obj_is_grid_item(item) == false) return;
uint8_t col_pos; uint32_t col_pos;
uint8_t col_span; uint32_t col_span;
uint8_t row_pos; uint32_t row_pos;
uint8_t row_span; uint32_t row_span;
if(cont->grid->row_dsc && cont->grid->col_dsc) { if(cont->grid->row_dsc && cont->grid->col_dsc) {
col_pos = _GRID_GET_CELL_POS(item->x_set); col_pos = _GRID_GET_CELL_POS(item->x_set);
@ -823,18 +827,26 @@ static void _grid_item_repos(lv_obj_t * cont, lv_obj_t * item, _lv_grid_calc_t *
row_span = 1; row_span = 1;
uint32_t child_id = 0; uint32_t child_id = 0;
lv_obj_t * child = lv_obj_get_child_back(cont, NULL); if(child_id_ext) child_id = *child_id_ext;
else {
lv_obj_t * child = lv_obj_get_child_back(cont, NULL);
while(child) { while(child) {
if(child == item) break; if(child == item) break;
if(_GRID_IS_CELL(child->x_set) && _GRID_IS_CELL(child->y_set)) { if(_GRID_IS_CELL(child->x_set) && _GRID_IS_CELL(child->y_set)) {
child_id++; child_id++;
}
child = lv_obj_get_child_back(cont, child);
} }
child = lv_obj_get_child_back(cont, child);
} }
col_pos = child_id % cont->grid->col_dsc_len; if(cont->grid->row_dsc == NULL) {
row_pos = child_id / cont->grid->col_dsc_len; col_pos = child_id % cont->grid->col_dsc_len;
row_pos = child_id / cont->grid->col_dsc_len;
} else {
col_pos = child_id / cont->grid->row_dsc_len;
row_pos = child_id % cont->grid->row_dsc_len;
}
} }
lv_coord_t col_w = calc->col_dsc[col_pos + col_span] - calc->col_dsc[col_pos]; lv_coord_t col_w = calc->col_dsc[col_pos + col_span] - calc->col_dsc[col_pos];
@ -902,19 +914,12 @@ static void _grid_item_repos(lv_obj_t * cont, lv_obj_t * item, _lv_grid_calc_t *
child = lv_obj_get_child(item, child); child = lv_obj_get_child(item, child);
} }
} }
bool moved = true;
if(grid_abs) {
if(grid_abs->x + x == item->coords.x1 && grid_abs->y + y == item->coords.y1) moved = false;
}
move_obj_to(item, x, y, false); if(moved) move_obj_to(item, x, y, false);
}
bool lv_obj_is_content_sensitive(lv_obj_t * item)
{
if(lv_obj_is_grid_item(item) == false) return false;
lv_obj_t * cont = lv_obj_get_parent(item);
if(cont->grid->col_dsc == NULL && _GRID_GET_CELL_FLAG(item->x_set) == LV_GRID_STRETCH) return true;
if(cont->grid->row_dsc == NULL && _GRID_GET_CELL_FLAG(item->y_set) == LV_GRID_STRETCH) return true;
return false;
} }
static void lv_grid_full_refr(lv_obj_t * cont) static void lv_grid_full_refr(lv_obj_t * cont)
@ -924,9 +929,21 @@ static void lv_grid_full_refr(lv_obj_t * cont)
_lv_grid_calc_t calc; _lv_grid_calc_t calc;
grid_calc(cont, &calc); grid_calc(cont, &calc);
/* Calculate the grids absolute x and y coordinates.
* It will be used as helper during item repositioning to avoid calculating this value for every children*/
lv_point_t grid_abs;
lv_coord_t pad_left = lv_obj_get_style_pad_left(cont, LV_OBJ_PART_MAIN);
lv_coord_t pad_top = lv_obj_get_style_pad_top(cont, LV_OBJ_PART_MAIN);
grid_abs.x = pad_left + cont->coords.x1 - lv_obj_get_scroll_left(cont);
grid_abs.y = pad_top + cont->coords.y1 - lv_obj_get_scroll_top(cont);
uint32_t child_id = 0;
lv_obj_t * item = lv_obj_get_child_back(cont, NULL); lv_obj_t * item = lv_obj_get_child_back(cont, NULL);
while(item) { while(item) {
_grid_item_repos(cont, item, &calc); if(_GRID_IS_CELL(item->x_set) && _GRID_IS_CELL(item->y_set)) {
_grid_item_repos(cont, item, &calc, &child_id, &grid_abs);
child_id++;
}
item = lv_obj_get_child_back(cont, item); item = lv_obj_get_child_back(cont, item);
} }
grid_calc_free(&calc); grid_calc_free(&calc);
@ -944,7 +961,7 @@ static void lv_grid_item_refr_pos(lv_obj_t * item)
_lv_grid_calc_t calc; _lv_grid_calc_t calc;
grid_calc(cont, &calc); grid_calc(cont, &calc);
_grid_item_repos(cont, item, &calc); _grid_item_repos(cont, item, &calc, NULL, NULL);
grid_calc_free(&calc); grid_calc_free(&calc);
} }
@ -993,10 +1010,18 @@ void lv_obj_set_pos(lv_obj_t * obj, lv_coord_t x, lv_coord_t y)
/*If the object is on a grid item let the grid to position it. */ /*If the object is on a grid item let the grid to position it. */
if(gi) { if(gi) {
lv_area_t old_area;
lv_area_copy(&old_area, &obj->coords);
lv_grid_item_refr_pos(obj);
lv_obj_t * cont = lv_obj_get_parent(obj); lv_obj_t * cont = lv_obj_get_parent(obj);
/*If added to a grid with auto flow refresh the whole grid else just this item*/
if(cont->grid->col_dsc == NULL || cont->grid->row_dsc == NULL) lv_grid_full_refr(cont); /*If the item was moved and grid is implicit in the changed direction refresh the whole grid.*/
else lv_grid_item_refr_pos(obj); if((cont->grid->col_dsc == NULL && (old_area.x1 != obj->coords.x1 || old_area.x2 != obj->coords.x2)) ||
(cont->grid->row_dsc == NULL && (old_area.y1 != obj->coords.y1 || old_area.y2 != obj->coords.y2)))
{
lv_grid_full_refr(cont);
}
} else { } else {
move_obj_to(obj, x, y, true); move_obj_to(obj, x, y, true);
} }
@ -1030,9 +1055,10 @@ void _lv_obj_calc_auto_size(lv_obj_t * obj, lv_coord_t * w, lv_coord_t * h)
{ {
if(!w && !h) return; if(!w && !h) return;
static uint32_t cnt = 0; // static uint32_t cnt = 0;
printf("auto_size: %d\n", cnt); // printf("auto_size: %d\n", cnt);
cnt++; // cnt++;
/*If no other effect the auto-size of zero by default*/ /*If no other effect the auto-size of zero by default*/
if(w) *w = 0; if(w) *w = 0;
if(h) *h = 0; if(h) *h = 0;
@ -1043,8 +1069,8 @@ void _lv_obj_calc_auto_size(lv_obj_t * obj, lv_coord_t * w, lv_coord_t * h)
if(obj->grid) { if(obj->grid) {
_lv_grid_calc_t calc; _lv_grid_calc_t calc;
grid_calc(obj, &calc); grid_calc(obj, &calc);
grid_w = calc.col_dsc[calc.col_dsc_len - 1]; grid_w = calc.col_dsc[calc.col_dsc_len - 1] + lv_obj_get_style_pad_top(obj, LV_OBJ_PART_MAIN) + + lv_obj_get_style_pad_bottom(obj, LV_OBJ_PART_MAIN);
grid_h = calc.row_dsc[calc.row_dsc_len - 1]; grid_h = calc.row_dsc[calc.row_dsc_len - 1] + lv_obj_get_style_pad_left(obj, LV_OBJ_PART_MAIN) + lv_obj_get_style_pad_right(obj, LV_OBJ_PART_MAIN);;
grid_calc_free(&calc); grid_calc_free(&calc);
} }
@ -1058,9 +1084,6 @@ void _lv_obj_calc_auto_size(lv_obj_t * obj, lv_coord_t * w, lv_coord_t * h)
} }
if(h) { if(h) {
static uint32_t cnt = 0;
// printf("auto_size_scrl: %d\n", cnt);
cnt++;
lv_obj_scroll_to_y(obj, 0, LV_ANIM_OFF); lv_obj_scroll_to_y(obj, 0, LV_ANIM_OFF);
lv_coord_t scroll_bottom = lv_obj_get_scroll_bottom(obj); lv_coord_t scroll_bottom = lv_obj_get_scroll_bottom(obj);
children_h = lv_obj_get_height(obj) + scroll_bottom; children_h = lv_obj_get_height(obj) + scroll_bottom;
@ -1122,7 +1145,7 @@ void lv_obj_set_size(lv_obj_t * obj, lv_coord_t w, lv_coord_t h)
h = auto_h; h = auto_h;
} }
bool chg = refr_size(obj, w, h); refr_size(obj, w, h);
} }
/** /**
@ -1261,7 +1284,10 @@ void lv_obj_scroll_by(lv_obj_t * obj, lv_coord_t x, lv_coord_t y, lv_anim_enable
lv_anim_path_set_cb(&path, lv_anim_path_ease_out); lv_anim_path_set_cb(&path, lv_anim_path_ease_out);
if(x) { if(x) {
lv_anim_set_time(&a, lv_anim_speed_to_time((lv_disp_get_hor_res(d) * 3) >> 2, 0, x)); uint32_t t = lv_anim_speed_to_time((lv_disp_get_hor_res(d) * 3) >> 2, 0, x);
if(t < SCROLL_ANIM_TIME_MIN) t = SCROLL_ANIM_TIME_MIN;
if(t > SCROLL_ANIM_TIME_MAX) t = SCROLL_ANIM_TIME_MAX;
lv_anim_set_time(&a, t);
lv_anim_set_values(&a, obj->scroll.x, obj->scroll.x + x); lv_anim_set_values(&a, obj->scroll.x, obj->scroll.x + x);
lv_anim_set_exec_cb(&a, (lv_anim_exec_xcb_t) scroll_anim_x_cb); lv_anim_set_exec_cb(&a, (lv_anim_exec_xcb_t) scroll_anim_x_cb);
lv_anim_set_path(&a, &path); lv_anim_set_path(&a, &path);
@ -1269,7 +1295,10 @@ void lv_obj_scroll_by(lv_obj_t * obj, lv_coord_t x, lv_coord_t y, lv_anim_enable
} }
if(y) { if(y) {
lv_anim_set_time(&a, lv_anim_speed_to_time((lv_disp_get_ver_res(d) * 3) >> 2, 0, y)); uint32_t t = lv_anim_speed_to_time((lv_disp_get_ver_res(d) * 3) >> 2, 0, y);
if(t < SCROLL_ANIM_TIME_MIN) t = SCROLL_ANIM_TIME_MIN;
if(t > SCROLL_ANIM_TIME_MAX) t = SCROLL_ANIM_TIME_MAX;
lv_anim_set_time(&a, t);
lv_anim_set_values(&a, obj->scroll.y, obj->scroll.y + y); lv_anim_set_values(&a, obj->scroll.y, obj->scroll.y + y);
lv_anim_set_exec_cb(&a, (lv_anim_exec_xcb_t) scroll_anim_y_cb); lv_anim_set_exec_cb(&a, (lv_anim_exec_xcb_t) scroll_anim_y_cb);
lv_anim_set_path(&a, &path); lv_anim_set_path(&a, &path);
@ -2332,16 +2361,7 @@ lv_obj_t * lv_obj_get_child(const lv_obj_t * obj, const lv_obj_t * child)
{ {
LV_ASSERT_OBJ(obj, LV_OBJX_NAME); LV_ASSERT_OBJ(obj, LV_OBJX_NAME);
lv_obj_t * result = NULL; return child ? _lv_ll_get_next(&obj->child_ll, child) : _lv_ll_get_head(&obj->child_ll);
if(child == NULL) {
result = _lv_ll_get_head(&obj->child_ll);
}
else {
result = _lv_ll_get_next(&obj->child_ll, child);
}
return result;
} }
/** /**
@ -2355,16 +2375,7 @@ lv_obj_t * lv_obj_get_child_back(const lv_obj_t * obj, const lv_obj_t * child)
{ {
LV_ASSERT_OBJ(obj, LV_OBJX_NAME); LV_ASSERT_OBJ(obj, LV_OBJX_NAME);
lv_obj_t * result = NULL; return child ? _lv_ll_get_prev(&obj->child_ll, child) : _lv_ll_get_tail(&obj->child_ll);
if(child == NULL) {
result = _lv_ll_get_tail(&obj->child_ll);
}
else {
result = _lv_ll_get_prev(&obj->child_ll, child);
}
return result;
} }
/** /**
@ -2818,6 +2829,12 @@ lv_style_int_t _lv_obj_get_style_int(const lv_obj_t * obj, uint8_t part, lv_styl
case LV_STYLE_PAD_RIGHT: case LV_STYLE_PAD_RIGHT:
if(list->pad_all_zero) def = true; if(list->pad_all_zero) def = true;
break; break;
case LV_STYLE_MARGIN_TOP:
case LV_STYLE_MARGIN_BOTTOM:
case LV_STYLE_MARGIN_LEFT:
case LV_STYLE_MARGIN_RIGHT:
if(list->margin_all_zero) def = true;
break;
case LV_STYLE_BG_BLEND_MODE: case LV_STYLE_BG_BLEND_MODE:
case LV_STYLE_BORDER_BLEND_MODE: case LV_STYLE_BORDER_BLEND_MODE:
case LV_STYLE_IMAGE_BLEND_MODE: case LV_STYLE_IMAGE_BLEND_MODE:
@ -4086,6 +4103,47 @@ static lv_design_res_t lv_obj_design(lv_obj_t * obj, const lv_area_t * clip_area
coords.y2 += h; coords.y2 += h;
lv_draw_rect(&coords, clip_area, &draw_dsc); lv_draw_rect(&coords, clip_area, &draw_dsc);
} }
#if GRID_DEBUG
/*Draw the grid cells*/
if(obj->grid) {
_lv_grid_calc_t calc;
grid_calc(obj, &calc);
/*Create a color unique to this object. */
lv_color_t c = lv_color_hex(((lv_uintptr_t) obj) & 0xFFFFFF);
lv_draw_rect_dsc_t grid_rect_dsc;
lv_draw_rect_dsc_init(&grid_rect_dsc);
grid_rect_dsc.bg_color = c;
grid_rect_dsc.bg_opa = LV_OPA_20;
grid_rect_dsc.border_width = 2;
grid_rect_dsc.border_color = c;
grid_rect_dsc.border_opa = LV_OPA_70;
lv_point_t grid_abs;
lv_coord_t pad_left = lv_obj_get_style_pad_left(obj, LV_OBJ_PART_MAIN);
lv_coord_t pad_top = lv_obj_get_style_pad_top(obj, LV_OBJ_PART_MAIN);
grid_abs.x = pad_left + obj->coords.x1 - lv_obj_get_scroll_left(obj);
grid_abs.y = pad_top + obj->coords.y1 - lv_obj_get_scroll_top(obj);
uint32_t row;
uint32_t col;
for(row = 0; row < calc.row_dsc_len - 1; row ++) {
for(col = 0; col < calc.col_dsc_len - 1; col ++) {
lv_area_t a;
a.x1 = grid_abs.x + calc.col_dsc[col];
a.x2 = grid_abs.x + calc.col_dsc[col + 1];
a.y1 = grid_abs.y + calc.row_dsc[row];
a.y2 = grid_abs.y + calc.row_dsc[row + 1];
lv_draw_rect(&a, clip_area, &grid_rect_dsc);
}
}
grid_calc_free(&calc);
}
#endif
} }
return LV_DESIGN_RES_OK; return LV_DESIGN_RES_OK;
@ -4194,6 +4252,17 @@ static lv_res_t lv_obj_signal(lv_obj_t * obj, lv_signal_t sign, void * param)
obj->ext_draw_pad = LV_MATH_MAX(obj->ext_draw_pad, d); obj->ext_draw_pad = LV_MATH_MAX(obj->ext_draw_pad, d);
} }
else if(sign == LV_SIGNAL_STYLE_CHG) { else if(sign == LV_SIGNAL_STYLE_CHG) {
lv_obj_t * child = lv_obj_get_child(obj, NULL);
while(child) {
lv_obj_set_pos(child, child->x_set, child->y_set);
child = lv_obj_get_child(obj, child);
}
if(obj->w_set == LV_SIZE_AUTO || obj->h_set == LV_SIZE_AUTO) {
lv_obj_set_size(obj, obj->w_set, obj->h_set);
}
// if(lv_obj_is_grid_item(obj)) lv_grid_full_refr(lv_obj_get_parent(obj));
lv_obj_refresh_ext_draw_pad(obj); lv_obj_refresh_ext_draw_pad(obj);
} }
else if(sign == LV_SIGNAL_PRESSED) { else if(sign == LV_SIGNAL_PRESSED) {
@ -4956,6 +5025,10 @@ static bool style_prop_is_cacheble(lv_style_property_t prop)
case LV_STYLE_PAD_BOTTOM: case LV_STYLE_PAD_BOTTOM:
case LV_STYLE_PAD_LEFT: case LV_STYLE_PAD_LEFT:
case LV_STYLE_PAD_RIGHT: case LV_STYLE_PAD_RIGHT:
case LV_STYLE_MARGIN_TOP:
case LV_STYLE_MARGIN_BOTTOM:
case LV_STYLE_MARGIN_LEFT:
case LV_STYLE_MARGIN_RIGHT:
case LV_STYLE_BG_BLEND_MODE: case LV_STYLE_BG_BLEND_MODE:
case LV_STYLE_BORDER_BLEND_MODE: case LV_STYLE_BORDER_BLEND_MODE:
case LV_STYLE_IMAGE_BLEND_MODE: case LV_STYLE_IMAGE_BLEND_MODE:
@ -5035,6 +5108,14 @@ static void update_style_cache(lv_obj_t * obj, uint8_t part, uint16_t prop)
list->pad_all_zero = 0; list->pad_all_zero = 0;
} }
list->margin_all_zero = 1;
if(lv_obj_get_style_margin_top(obj, part) != 0 ||
lv_obj_get_style_margin_bottom(obj, part) != 0 ||
lv_obj_get_style_margin_left(obj, part) != 0 ||
lv_obj_get_style_margin_right(obj, part) != 0) {
list->margin_all_zero = 0;
}
list->blend_mode_all_normal = 1; list->blend_mode_all_normal = 1;
#if LV_USE_BLEND_MODES #if LV_USE_BLEND_MODES
if(lv_obj_get_style_bg_blend_mode(obj, part) != LV_BLEND_MODE_NORMAL || if(lv_obj_get_style_bg_blend_mode(obj, part) != LV_BLEND_MODE_NORMAL ||

View File

@ -18,7 +18,7 @@ extern "C" {
#include <stddef.h> #include <stddef.h>
#include <stdbool.h> #include <stdbool.h>
#include "lv_style.h" #include "lv_style.h"
#include "lv_align.h" #include "lv_grid.h"
#include "../lv_misc/lv_types.h" #include "../lv_misc/lv_types.h"
#include "../lv_misc/lv_area.h" #include "../lv_misc/lv_area.h"
#include "../lv_misc/lv_color.h" #include "../lv_misc/lv_color.h"

View File

@ -678,7 +678,7 @@ static void lv_refr_obj(lv_obj_t * obj, const lv_area_t * mask_ori_p)
draw_dsc.bg_color.full = debug_color.full; draw_dsc.bg_color.full = debug_color.full;
draw_dsc.bg_opa = LV_OPA_20; draw_dsc.bg_opa = LV_OPA_20;
draw_dsc.border_width = 2; draw_dsc.border_width = 2;
draw_dsc.border_opa = LV_OPA_50; draw_dsc.border_opa = LV_OPA_70;
draw_dsc.border_color.full = (debug_color.full + 0x13) * 9; draw_dsc.border_color.full = (debug_color.full + 0x13) * 9;
lv_draw_rect(&obj_ext_mask, &obj_ext_mask, &draw_dsc); lv_draw_rect(&obj_ext_mask, &obj_ext_mask, &draw_dsc);

View File

@ -1044,6 +1044,7 @@ bool lv_debug_check_style_list(const lv_style_list_t * list)
* STATIC FUNCTIONS * STATIC FUNCTIONS
**********************/ **********************/
static uint32_t stat[256];
/** /**
* Get a property's index (byte index in `style->map`) from a style. * Get a property's index (byte index in `style->map`) from a style.
* Return best matching property's index considering the state of `prop` * Return best matching property's index considering the state of `prop`
@ -1067,6 +1068,12 @@ LV_ATTRIBUTE_FAST_MEM static inline int32_t get_property_index(const lv_style_t
size_t i = 0; size_t i = 0;
stat[prop & 0xFF]++;
//
// if((prop & 0xFF) == LV_STYLE_PAD_TOP) {
// printf("pad top\n");
// }
uint8_t prop_id; uint8_t prop_id;
while((prop_id = get_style_prop_id(style, i)) != _LV_STYLE_CLOSEING_PROP) { while((prop_id = get_style_prop_id(style, i)) != _LV_STYLE_CLOSEING_PROP) {
if(prop_id == id_to_find) { if(prop_id == id_to_find) {

View File

@ -231,7 +231,7 @@ typedef struct {
#if LV_USE_ASSERT_STYLE #if LV_USE_ASSERT_STYLE
uint32_t sentinel; uint32_t sentinel;
#endif #endif
uint32_t style_cnt : 6; uint32_t style_cnt : 5;
uint32_t has_local : 1; uint32_t has_local : 1;
uint32_t has_trans : 1; uint32_t has_trans : 1;
uint32_t skip_trans : 1; /*1: Temporally skip the transition style if any*/ uint32_t skip_trans : 1; /*1: Temporally skip the transition style if any*/
@ -244,6 +244,7 @@ typedef struct {
uint32_t clip_corner_off : 1; uint32_t clip_corner_off : 1;
uint32_t transform_all_zero : 1; uint32_t transform_all_zero : 1;
uint32_t pad_all_zero : 1; uint32_t pad_all_zero : 1;
uint32_t margin_all_zero : 1;
uint32_t blend_mode_all_normal : 1; uint32_t blend_mode_all_normal : 1;
uint32_t bg_opa_transp : 1; uint32_t bg_opa_transp : 1;
uint32_t bg_opa_cover : 1; uint32_t bg_opa_cover : 1;

View File

@ -260,7 +260,7 @@ lv_anim_value_t lv_anim_path_ease_in(const lv_anim_path_t * path, const lv_anim_
else else
t = (uint32_t)((uint32_t)a->act_time * 1024) / a->time; t = (uint32_t)((uint32_t)a->act_time * 1024) / a->time;
int32_t step = _lv_bezier3(t, 0, 1, 1, 1024); int32_t step = _lv_bezier3(t, 0, 100, 200, 1024);
int32_t new_value; int32_t new_value;
new_value = (int32_t)step * (a->end - a->start); new_value = (int32_t)step * (a->end - a->start);
@ -287,7 +287,7 @@ lv_anim_value_t lv_anim_path_ease_out(const lv_anim_path_t * path, const lv_anim
else else
t = (uint32_t)((uint32_t)a->act_time * 1024) / a->time; t = (uint32_t)((uint32_t)a->act_time * 1024) / a->time;
int32_t step = _lv_bezier3(t, 0, 1023, 1023, 1024); int32_t step = _lv_bezier3(t, 0, 800, 900, 1024);
int32_t new_value; int32_t new_value;
new_value = (int32_t)step * (a->end - a->start); new_value = (int32_t)step * (a->end - a->start);

View File

@ -249,37 +249,6 @@ void _lv_ll_chg_list(lv_ll_t * ll_ori_p, lv_ll_t * ll_new_p, void * node, bool h
} }
} }
/**
* Return with head node of the linked list
* @param ll_p pointer to linked list
* @return pointer to the head of 'll_p'
*/
void * _lv_ll_get_head(const lv_ll_t * ll_p)
{
void * head = NULL;
if(ll_p != NULL) {
head = ll_p->head;
}
return head;
}
/**
* Return with tail node of the linked list
* @param ll_p pointer to linked list
* @return pointer to the head of 'll_p'
*/
void * _lv_ll_get_tail(const lv_ll_t * ll_p)
{
void * tail = NULL;
if(ll_p != NULL) {
tail = ll_p->tail;
}
return tail;
}
/** /**
* Return with the pointer of the next node after 'n_act' * Return with the pointer of the next node after 'n_act'
@ -289,8 +258,6 @@ void * _lv_ll_get_tail(const lv_ll_t * ll_p)
*/ */
void * _lv_ll_get_next(const lv_ll_t * ll_p, const void * n_act) void * _lv_ll_get_next(const lv_ll_t * ll_p, const void * n_act)
{ {
if(ll_p == NULL) return NULL;
/* Pointer to the next node is stored in the end of this node. /* Pointer to the next node is stored in the end of this node.
* Go there and return the address found there */ * Go there and return the address found there */
const lv_ll_node_t * n_act_d = n_act; const lv_ll_node_t * n_act_d = n_act;
@ -306,8 +273,6 @@ void * _lv_ll_get_next(const lv_ll_t * ll_p, const void * n_act)
*/ */
void * _lv_ll_get_prev(const lv_ll_t * ll_p, const void * n_act) void * _lv_ll_get_prev(const lv_ll_t * ll_p, const void * n_act)
{ {
if(ll_p == NULL) return NULL;
/* Pointer to the prev. node is stored in the end of this node. /* Pointer to the prev. node is stored in the end of this node.
* Go there and return the address found there */ * Go there and return the address found there */
const lv_ll_node_t * n_act_d = n_act; const lv_ll_node_t * n_act_d = n_act;

View File

@ -98,14 +98,20 @@ void _lv_ll_chg_list(lv_ll_t * ll_ori_p, lv_ll_t * ll_new_p, void * node, bool h
* @param ll_p pointer to linked list * @param ll_p pointer to linked list
* @return pointer to the head of 'll_p' * @return pointer to the head of 'll_p'
*/ */
void * _lv_ll_get_head(const lv_ll_t * ll_p); static inline void * _lv_ll_get_head(const lv_ll_t * ll_p)
{
return ll_p->head;
}
/** /**
* Return with tail node of the linked list * Return with tail node of the linked list
* @param ll_p pointer to linked list * @param ll_p pointer to linked list
* @return pointer to the head of 'll_p' * @return pointer to the head of 'll_p'
*/ */
void * _lv_ll_get_tail(const lv_ll_t * ll_p); static inline void * _lv_ll_get_tail(const lv_ll_t * ll_p)
{
return ll_p->tail;
}
/** /**
* Return with the pointer of the next node after 'n_act' * Return with the pointer of the next node after 'n_act'

View File

@ -73,7 +73,7 @@ typedef struct {
**********************/ **********************/
#if LV_MEM_CUSTOM == 0 #if LV_MEM_CUSTOM == 0
static lv_mem_ent_t * ent_get_next(lv_mem_ent_t * act_e); static lv_mem_ent_t * ent_get_next(lv_mem_ent_t * act_e);
static void * ent_alloc(lv_mem_ent_t * e, size_t size); static inline void * ent_alloc(lv_mem_ent_t * e, size_t size);
static void ent_trunc(lv_mem_ent_t * e, size_t size); static void ent_trunc(lv_mem_ent_t * e, size_t size);
#endif #endif
@ -84,9 +84,9 @@ typedef struct {
static uint8_t * work_mem; static uint8_t * work_mem;
#endif #endif
static uint32_t zero_mem; /*Give the address of this variable if 0 byte should be allocated*/ static uint32_t zero_mem; /*Give the address of this variable if 0 byte should be allocated*/
#if LV_MEM_CUSTOM == 0 #if LV_MEM_CUSTOM == 0
static uint8_t * last_mem; /*Address of the last valid byte*/
static uint32_t mem_max_size; /*Tracks the maximum total size of memory ever used from the internal heap*/ static uint32_t mem_max_size; /*Tracks the maximum total size of memory ever used from the internal heap*/
#endif #endif
@ -125,7 +125,7 @@ void _lv_mem_init(void)
#else #else
work_mem = (uint8_t *)LV_MEM_ADR; work_mem = (uint8_t *)LV_MEM_ADR;
#endif #endif
last_mem = &work_mem[LV_MEM_SIZE - 1];
lv_mem_ent_t * full = (lv_mem_ent_t *)work_mem; lv_mem_ent_t * full = (lv_mem_ent_t *)work_mem;
full->header.s.used = 0; full->header.s.used = 0;
/*The total mem size id reduced by the first header and the close patterns */ /*The total mem size id reduced by the first header and the close patterns */
@ -176,13 +176,11 @@ void * lv_mem_alloc(size_t size)
do { do {
/* Get the next entry*/ /* Get the next entry*/
e = ent_get_next(e); e = ent_get_next(e);
if( e == NULL) break;
/*If there is next entry then try to allocate there*/ /*If there is next entry then try to allocate there*/
if(e != NULL) { if(!e->header.s.used && e->header.s.d_size >= size) alloc = ent_alloc(e, size);
alloc = ent_alloc(e, size); /* End if the alloc. is successful*/
} } while(alloc == NULL);
/* End if there is not next entry OR the alloc. is successful*/
} while(e != NULL && alloc == NULL);
#else #else
/*Use custom, user defined malloc function*/ /*Use custom, user defined malloc function*/
@ -817,19 +815,15 @@ LV_ATTRIBUTE_FAST_MEM void _lv_memset_ff(void * dst, size_t len)
*/ */
static lv_mem_ent_t * ent_get_next(lv_mem_ent_t * act_e) static lv_mem_ent_t * ent_get_next(lv_mem_ent_t * act_e)
{ {
lv_mem_ent_t * next_e = NULL; /*NULL means: get the first entry; else get the next after `act_e`*/
if(act_e == NULL) return (lv_mem_ent_t *)work_mem;
if(act_e == NULL) { /*NULL means: get the first entry*/ else {
next_e = (lv_mem_ent_t *)work_mem;
}
else { /*Get the next entry */
uint8_t * data = &act_e->first_data; uint8_t * data = &act_e->first_data;
next_e = (lv_mem_ent_t *)&data[act_e->header.s.d_size]; lv_mem_ent_t * next_e = (lv_mem_ent_t *)&data[act_e->header.s.d_size];
if(&next_e->first_data >= &work_mem[LV_MEM_SIZE]) next_e = NULL; if(&next_e->first_data > last_mem) return NULL;
else return next_e;
} }
return next_e;
} }
/** /**
@ -838,20 +832,23 @@ static lv_mem_ent_t * ent_get_next(lv_mem_ent_t * act_e)
* @param size size of the new memory in bytes * @param size size of the new memory in bytes
* @return pointer to the allocated memory or NULL if not enough memory in the entry * @return pointer to the allocated memory or NULL if not enough memory in the entry
*/ */
static void * ent_alloc(lv_mem_ent_t * e, size_t size) static inline void * ent_alloc(lv_mem_ent_t * e, size_t size)
{ {
void * alloc = NULL; // static uint32_t cnt = 0;
/*If the memory is free and big enough then use it */ //
if(e->header.s.used == 0 && e->header.s.d_size >= size) { //// if((cnt & 0xFFFF) == 0)
// printf("alloc: %d\n", cnt);
// cnt++;
//
/*Truncate the entry to the desired size */ /*Truncate the entry to the desired size */
ent_trunc(e, size); ent_trunc(e, size);
e->header.s.used = 1; e->header.s.used = 1;
/*Save the allocated data*/ /*Save the allocated data*/
alloc = &e->first_data; return &e->first_data;
}
return alloc;
} }
/** /**