1
0
mirror of https://github.com/lvgl/lvgl.git synced 2025-01-28 07:03:00 +08:00

minor API updates

This commit is contained in:
Gabor Kiss-Vamosi 2019-06-25 15:14:47 +02:00
parent bba22bfa55
commit 4891f803fc
21 changed files with 193 additions and 122 deletions

View File

@ -54,7 +54,7 @@ lv_obj_t * lv_disp_get_scr_act(lv_disp_t * disp)
* Make a screen active
* @param scr pointer to a screen
*/
void lv_disp_set_scr_act(lv_obj_t * scr)
void lv_disp_load_scr(lv_obj_t * scr)
{
lv_disp_t * d = lv_obj_get_disp(scr);

View File

@ -40,7 +40,7 @@ lv_obj_t * lv_disp_get_scr_act(lv_disp_t * disp);
* Make a screen active
* @param scr pointer to a screen
*/
void lv_disp_set_scr_act(lv_obj_t * scr);
void lv_disp_load_scr(lv_obj_t * scr);
/**
* Return with the top layer. (Same on every screen and it is above the normal screen layer)
@ -119,7 +119,7 @@ static inline lv_obj_t * lv_layer_sys(void)
static inline void lv_scr_load(lv_obj_t * scr)
{
lv_disp_set_scr_act(scr);
lv_disp_load_scr(scr);
}
/**********************

View File

@ -554,7 +554,7 @@ static void style_mod_def(lv_group_t * group, lv_style_t * style)
style->body.border.opa = LV_OPA_COVER;
style->body.border.color = LV_COLOR_ORANGE;
/*If not empty or has border then emphasis the border*/
/*If not transparent or has border then emphasis the border*/
if(style->body.opa != LV_OPA_TRANSP || style->body.border.width != 0) style->body.border.width = LV_DPI / 20;
style->body.main_color = lv_color_mix(style->body.main_color, LV_COLOR_ORANGE, LV_OPA_70);

View File

@ -562,8 +562,7 @@ static void lv_refr_vdb_flush(void)
/*In double buffered mode wait until the other buffer is flushed before flushing the current
* one*/
if(lv_disp_is_double_buf(disp_refr)) {
while(vdb->flushing)
;
while(vdb->flushing);
}
vdb->flushing = 1;
@ -573,14 +572,7 @@ static void lv_refr_vdb_flush(void)
if(disp->driver.flush_cb) disp->driver.flush_cb(&disp->driver, &vdb->area, vdb->buf_act);
if(vdb->buf1 && vdb->buf2) {
if(vdb->buf_act == vdb->buf1)
vdb->buf_act = vdb->buf2;
else
vdb->buf_act = vdb->buf1;
/*If the screen is transparent initialize it when the new VDB is selected*/
#if LV_COLOR_SCREEN_TRANSP
memset(vdb[vdb_active].buf, 0x00, LV_VDB_SIZE_IN_BYTES);
#endif /*LV_COLOR_SCREEN_TRANSP*/
if(vdb->buf_act == vdb->buf1) vdb->buf_act = vdb->buf2;
else vdb->buf_act = vdb->buf1;
}
}

View File

@ -45,9 +45,7 @@ static void sw_mem_blend(lv_color_t * dest, const lv_color_t * src, uint32_t len
static void sw_color_fill(lv_color_t * mem, lv_coord_t mem_width, const lv_area_t * fill_area, lv_color_t color,
lv_opa_t opa);
#if LV_COLOR_SCREEN_TRANSP
static inline lv_color_t color_mix_2_alpha(lv_color_t bg_color, lv_opa_t bg_opa, lv_color_t fg_color, lv_opa_t fg_opa);
#endif
/**********************
* STATIC VARIABLES
@ -71,6 +69,7 @@ static inline lv_color_t color_mix_2_alpha(lv_color_t bg_color, lv_opa_t bg_opa,
*/
void lv_draw_px(lv_coord_t x, lv_coord_t y, const lv_area_t * mask_p, lv_color_t color, lv_opa_t opa)
{
if(opa < LV_OPA_MIN) return;
if(opa > LV_OPA_MAX) opa = LV_OPA_COVER;
@ -87,20 +86,27 @@ void lv_draw_px(lv_coord_t x, lv_coord_t y, const lv_area_t * mask_p, lv_color_t
x -= vdb->area.x1;
y -= vdb->area.y1;
if(disp->driver.set_px_cb) {
disp->driver.set_px_cb(&disp->driver, (uint8_t *)vdb->buf_act, vdb_width, x, y, color, opa);
} else {
bool scr_transp = false;
#if LV_COLOR_SCREEN_TRANSP
scr_transp = disp->driver.screen_transp;
#endif
lv_color_t * vdb_px_p = vdb->buf_act;
vdb_px_p += y * vdb_width + x;
#if LV_COLOR_SCREEN_TRANSP == 0
if(opa == LV_OPA_COVER) {
*vdb_px_p = color;
if(scr_transp == false) {
if(opa == LV_OPA_COVER) {
*vdb_px_p = color;
} else {
*vdb_px_p = lv_color_mix(color, *vdb_px_p, opa);
}
} else {
*vdb_px_p = lv_color_mix(color, *vdb_px_p, opa);
*vdb_px_p = color_mix_2_alpha(*vdb_px_p, (*vdb_px_p).ch.alpha, color, opa);
}
#else
*vdb_px_p = color_mix_2_alpha(*vdb_px_p, (*vdb_px_p).alpha, color, opa);
#endif
}
}
@ -309,6 +315,11 @@ void lv_draw_letter(const lv_point_t * pos_p, const lv_area_t * mask_p, const lv
uint16_t col_bit;
col_bit = bit_ofs & 0x7; /* "& 0x7" equals to "% 8" just faster */
bool scr_transp = false;
#if LV_COLOR_SCREEN_TRANSP
scr_transp = disp->driver.screen_transp;
#endif
for(row = row_start; row < row_end; row++) {
bitmask = bitmask_init >> col_bit;
for(col = col_start; col < col_end; col++) {
@ -328,11 +339,11 @@ void lv_draw_letter(const lv_point_t * pos_p, const lv_area_t * mask_p, const lv
if(px_opa > LV_OPA_MAX)
*vdb_buf_tmp = color;
else if(px_opa > LV_OPA_MIN) {
#if LV_COLOR_SCREEN_TRANSP == 0
*vdb_buf_tmp = lv_color_mix(color, *vdb_buf_tmp, px_opa);
#else
*vdb_buf_tmp = color_mix_2_alpha(*vdb_buf_tmp, (*vdb_buf_tmp).alpha, color, px_opa);
#endif
if(scr_transp == false) {
*vdb_buf_tmp = lv_color_mix(color, *vdb_buf_tmp, px_opa);
} else {
*vdb_buf_tmp = color_mix_2_alpha(*vdb_buf_tmp, (*vdb_buf_tmp).ch.alpha, color, px_opa);
}
}
}
}
@ -414,6 +425,13 @@ void lv_draw_map(const lv_area_t * cords_p, const lv_area_t * mask_p, const uint
lv_coord_t row;
lv_coord_t map_useful_w = lv_area_get_width(&masked_a);
bool scr_transp = false;
#if LV_COLOR_SCREEN_TRANSP
scr_transp = disp->driver.screen_transp;
#endif
/*The simplest case just copy the pixels into the VDB*/
if(chroma_key == false && alpha_byte == false && opa == LV_OPA_COVER && recolor_opa == LV_OPA_TRANSP) {
@ -449,6 +467,7 @@ void lv_draw_map(const lv_area_t * cords_p, const lv_area_t * mask_p, const uint
/*In the other cases every pixel need to be checked one-by-one*/
else {
lv_coord_t col;
lv_color_t last_img_px = LV_COLOR_BLACK;
lv_color_t recolored_px = lv_color_mix(recolor, last_img_px, recolor_opa);
@ -508,15 +527,17 @@ void lv_draw_map(const lv_area_t * cords_p, const lv_area_t * mask_p, const uint
}
/*Normal native VDB write*/
else {
if(opa_result == LV_OPA_COVER)
vdb_buf_tmp[col] = px_color;
else {
#if LV_COLOR_SCREEN_TRANSP == 0
vdb_buf_tmp[col] = lv_color_mix(px_color, vdb_buf_tmp[col], opa_result);
#else
vdb_buf_tmp[col] =
color_mix_2_alpha(vdb_buf_tmp[col], vdb_buf_tmp[col].alpha, px_color, opa_result);
#endif
if(scr_transp == false) {
vdb_buf_tmp[col] = lv_color_mix(px_color, vdb_buf_tmp[col], opa_result);
} else {
vdb_buf_tmp[col] =
color_mix_2_alpha(vdb_buf_tmp[col], vdb_buf_tmp[col].ch.alpha, px_color, opa_result);
}
}
}
}
@ -596,25 +617,27 @@ static void sw_color_fill(lv_color_t * mem, lv_coord_t mem_width, const lv_area_
}
/*Calculate with alpha too*/
else {
bool scr_transp = false;
#if LV_COLOR_SCREEN_TRANSP
scr_transp = disp->driver.screen_transp;
#endif
#if LV_COLOR_SCREEN_TRANSP == 0
lv_color_t bg_tmp = LV_COLOR_BLACK;
lv_color_t opa_tmp = lv_color_mix(color, bg_tmp, opa);
#endif
for(row = fill_area->y1; row <= fill_area->y2; row++) {
for(col = fill_area->x1; col <= fill_area->x2; col++) {
#if LV_COLOR_SCREEN_TRANSP == 0
/*If the bg color changed recalculate the result color*/
if(mem[col].full != bg_tmp.full) {
bg_tmp = mem[col];
opa_tmp = lv_color_mix(color, bg_tmp, opa);
if(scr_transp == false) {
/*If the bg color changed recalculate the result color*/
if(mem[col].full != bg_tmp.full) {
bg_tmp = mem[col];
opa_tmp = lv_color_mix(color, bg_tmp, opa);
}
mem[col] = opa_tmp;
} else {
mem[col] = color_mix_2_alpha(mem[col], mem[col].ch.alpha, color, opa);
}
mem[col] = opa_tmp;
#else
mem[col] = color_mix_2_alpha(mem[col], mem[col].alpha, color, opa);
#endif
}
mem += mem_width;
}
@ -622,7 +645,6 @@ static void sw_color_fill(lv_color_t * mem, lv_coord_t mem_width, const lv_area_
}
}
#if LV_COLOR_SCREEN_TRANSP
/**
* Mix two colors. Both color can have alpha value. It requires ARGB888 colors.
@ -634,8 +656,10 @@ static void sw_color_fill(lv_color_t * mem, lv_coord_t mem_width, const lv_area_
*/
static inline lv_color_t color_mix_2_alpha(lv_color_t bg_color, lv_opa_t bg_opa, lv_color_t fg_color, lv_opa_t fg_opa)
{
#if LV_COLOR_SCREEN_TRANSP
/* Pick the foreground if it's fully opaque or the Background is fully transparent*/
if(fg_opa == LV_OPA_COVER || bg_opa <= LV_OPA_MIN) {
if(fg_opa > LV_OPA_MAX|| bg_opa <= LV_OPA_MIN) {
fg_color.ch.alpha = fg_opa;
return fg_color;
}
@ -660,8 +684,8 @@ static inline lv_color_t color_mix_2_alpha(lv_color_t bg_color, lv_opa_t bg_opa,
bg_color.full != bg_color_save.full) {
fg_opa_save = fg_opa;
bg_opa_save = bg_opa;
fg_color.full = fg_color_save.full;
bg_color.full = bg_color_save.full;
fg_color_save.full = fg_color.full;
bg_color_save.full = bg_color.full;
/*Info:
* https://en.wikipedia.org/wiki/Alpha_compositing#Analytical_derivation_of_the_over_operator*/
lv_opa_t alpha_res = 255 - ((uint16_t)((uint16_t)(255 - fg_opa) * (255 - bg_opa)) >> 8);
@ -675,6 +699,12 @@ static inline lv_color_t color_mix_2_alpha(lv_color_t bg_color, lv_opa_t bg_opa,
}
return c;
}
}
#else
(void)bg_color; /*Unused*/
(void)fg_color; /*Unused*/
(void)bg_opa; /*Unused*/
(void)fg_opa; /*Unused*/
#endif /*LV_COLOR_SCREEN_TRANSP*/
}

View File

@ -452,18 +452,18 @@ static lv_res_t lv_img_draw_core(const lv_area_t * coords, const lv_area_t * mas
if(cdsc == NULL) return LV_RES_INV;
bool chroma_keyed = lv_img_color_format_is_chroma_keyed(cdsc->dsc.header.cf);
bool alpha_byte = lv_img_color_format_has_alpha(cdsc->dsc.header.cf);
bool chroma_keyed = lv_img_color_format_is_chroma_keyed(cdsc->dec_dsc.header.cf);
bool alpha_byte = lv_img_color_format_has_alpha(cdsc->dec_dsc.header.cf);
if(cdsc->dsc.error_msg != NULL) {
if(cdsc->dec_dsc.error_msg != NULL) {
LV_LOG_WARN("Image draw error");
lv_draw_rect(coords, mask, &lv_style_plain, LV_OPA_COVER);
lv_draw_label(coords, mask, &lv_style_plain, LV_OPA_COVER, cdsc->dsc.error_msg, LV_TXT_FLAG_NONE, NULL, -1, -1, NULL);
lv_draw_label(coords, mask, &lv_style_plain, LV_OPA_COVER, cdsc->dec_dsc.error_msg, LV_TXT_FLAG_NONE, NULL, -1, -1, NULL);
}
/* The decoder open could open the image and gave the entire uncompressed image.
* Just draw it!*/
else if(cdsc->dsc.img_data) {
lv_draw_map(coords, mask, cdsc->dsc.img_data, opa, chroma_keyed, alpha_byte, style->image.color, style->image.intense);
else if(cdsc->dec_dsc.img_data) {
lv_draw_map(coords, mask, cdsc->dec_dsc.img_data, opa, chroma_keyed, alpha_byte, style->image.color, style->image.intense);
}
/* The whole uncompressed image is not available. Try to read it line-by-line*/
else {
@ -482,9 +482,9 @@ static lv_res_t lv_img_draw_core(const lv_area_t * coords, const lv_area_t * mas
lv_coord_t row;
lv_res_t read_res;
for(row = mask_com.y1; row <= mask_com.y2; row++) {
read_res = lv_img_decoder_read_line(&cdsc->dsc, x, y, width, buf);
read_res = lv_img_decoder_read_line(&cdsc->dec_dsc, x, y, width, buf);
if(read_res != LV_RES_OK) {
lv_img_decoder_close(&cdsc->dsc);
lv_img_decoder_close(&cdsc->dec_dsc);
LV_LOG_WARN("Image draw can't read the line");
return LV_RES_INV;
}

View File

@ -41,7 +41,7 @@
/**********************
* STATIC VARIABLES
**********************/
static uint16_t slot_num;
static uint16_t entry_cnt;
/**********************
* MACROS
@ -61,7 +61,7 @@ static uint16_t slot_num;
*/
lv_img_cache_entry_t * lv_img_cache_open(const void * src, const lv_style_t * style)
{
if(slot_num == 0) {
if(entry_cnt == 0) {
LV_LOG_WARN("lv_img_cache_open: the cache size is 0");
return NULL;
}
@ -70,7 +70,7 @@ lv_img_cache_entry_t * lv_img_cache_open(const void * src, const lv_style_t * st
/*Decrement all lifes. Make the entries older*/
uint16_t i;
for(i = 0; i < slot_num; i++) {
for(i = 0; i < entry_cnt; i++) {
if(cache[i].life > INT32_MIN + LV_IMG_CACHE_AGING) {
cache[i].life -= LV_IMG_CACHE_AGING;
}
@ -78,54 +78,59 @@ lv_img_cache_entry_t * lv_img_cache_open(const void * src, const lv_style_t * st
/*Is the image cached?*/
lv_img_cache_entry_t * cached_src = NULL;
for(i = 0; i < slot_num; i++) {
if(cache[i].dsc.src == src) {
for(i = 0; i < entry_cnt; i++) {
if(cache[i].dec_dsc.src == src) {
/* If opened increment its life.
* Image difficult to open should live longer to keep avoid frequent their recaching.
* Therefore increase `life` with `time_to_open`*/
cached_src = &cache[i];
cached_src->life += cached_src->time_to_open * LV_IMG_CACHE_LIFE_GAIN ;
cached_src->life += cached_src->dec_dsc.time_to_open * LV_IMG_CACHE_LIFE_GAIN ;
if(cached_src->life > LV_IMG_CACHE_LIFE_LIMIT) cached_src->life = LV_IMG_CACHE_LIFE_LIMIT;
LV_LOG_TRACE("image draw: image found in the cache");
break;
}
}
/*The image is not cached then cache it now*/
if(cached_src == NULL) {
/*Find an entry to reuse. Select the entry with the least life*/
cached_src = &cache[0];
for(i = 1; i < slot_num; i++) {
for(i = 1; i < entry_cnt; i++) {
if(cache[i].life < cached_src->life) {
cached_src = &cache[i];
}
}
/*Close the slot to reuse if it was opened (has a valid source)*/
if(cached_src->dsc.src) {
lv_img_decoder_close(&cached_src->dsc);
LV_LOG_INFO("image draw: cache miss, close and reuse a slot");
/*Close the decoder to reuse if it was opened (has a valid source)*/
if(cached_src->dec_dsc.src) {
lv_img_decoder_close(&cached_src->dec_dsc);
LV_LOG_INFO("image draw: cache miss, close and reuse an entry");
} else {
LV_LOG_INFO("image draw: cache miss, cached in empty slot");
LV_LOG_INFO("image draw: cache miss, cached to an empty entry");
}
/*Open the image and measure the time to open*/
uint32_t t_start;
t_start = lv_tick_get();
lv_res_t open_res = lv_img_decoder_open(&cached_src->dsc, src, style);
cached_src->dec_dsc.time_to_open = 0;
lv_res_t open_res = lv_img_decoder_open(&cached_src->dec_dsc, src, style);
if(open_res ==LV_RES_INV) {
LV_LOG_WARN("Image draw cannot open the image resource");
lv_img_decoder_close(&cached_src->dsc);
memset(&cached_src->dsc, 0, sizeof(lv_img_decoder_dsc_t));
lv_img_decoder_close(&cached_src->dec_dsc);
memset(&cached_src->dec_dsc, 0, sizeof(lv_img_decoder_dsc_t));
memset(&cached_src, 0, sizeof(lv_img_cache_entry_t));
cached_src->life = INT32_MIN; /*Make the empty entry very "weak" to force its use */
return NULL;
}
cached_src->life = 0;
cached_src->time_to_open = lv_tick_elaps(t_start);
if(cached_src->time_to_open == 0) cached_src->time_to_open = 1;
/*If `time_to_open` was not set in the open function set it here*/
if(cached_src->dec_dsc.time_to_open == 0) {
cached_src->dec_dsc.time_to_open = lv_tick_elaps(t_start);
}
if(cached_src->dec_dsc.time_to_open == 0) cached_src->dec_dsc.time_to_open = 1;
}
return cached_src;
@ -135,9 +140,9 @@ lv_img_cache_entry_t * lv_img_cache_open(const void * src, const lv_style_t * st
* Set the number of images to be cached.
* More cached images mean more opened image at same time which might mean more memory usage.
* E.g. if 20 PNG or JPG images are open in the RAM they consume memory while opened in the cache.
* @param new_slot_num number of image to cache
* @param new_entry_cnt number of image to cache
*/
void lv_img_cache_set_size(uint16_t new_slot_num)
void lv_img_cache_set_size(uint16_t new_entry_cnt)
{
if(LV_GC_ROOT(_lv_img_cache_array) != NULL) {
/*Clean the cache before free it*/
@ -146,18 +151,18 @@ void lv_img_cache_set_size(uint16_t new_slot_num)
}
/*Reallocate the cache*/
LV_GC_ROOT(_lv_img_cache_array) = lv_mem_alloc(sizeof(lv_img_cache_entry_t) * new_slot_num);
LV_GC_ROOT(_lv_img_cache_array) = lv_mem_alloc(sizeof(lv_img_cache_entry_t) * new_entry_cnt);
lv_mem_assert(LV_GC_ROOT(_lv_img_cache_array));
if(LV_GC_ROOT(_lv_img_cache_array) == NULL) {
slot_num = 0;
entry_cnt = 0;
return;
}
slot_num = new_slot_num;
entry_cnt = new_entry_cnt;
/*Clean the cache*/
uint16_t i;
for(i = 0; i < slot_num; i++) {
memset(&LV_GC_ROOT(_lv_img_cache_array)[i].dsc, 0, sizeof(lv_img_decoder_dsc_t));
for(i = 0; i < entry_cnt; i++) {
memset(&LV_GC_ROOT(_lv_img_cache_array)[i].dec_dsc, 0, sizeof(lv_img_decoder_dsc_t));
memset(&LV_GC_ROOT(_lv_img_cache_array)[i], 0, sizeof(lv_img_cache_entry_t));
}
}
@ -173,13 +178,13 @@ void lv_img_cache_invalidate_src(const void * src)
lv_img_cache_entry_t * cache = LV_GC_ROOT(_lv_img_cache_array);
uint16_t i;
for(i = 0; i < slot_num; i++) {
if(cache[i].dsc.src == src || src == NULL) {
if(cache[i].dsc.src != NULL) {
lv_img_decoder_close(&cache[i].dsc);
for(i = 0; i < entry_cnt; i++) {
if(cache[i].dec_dsc.src == src || src == NULL) {
if(cache[i].dec_dsc.src != NULL) {
lv_img_decoder_close(&cache[i].dec_dsc);
}
memset(&cache[i].dsc, 0, sizeof(lv_img_decoder_dsc_t));
memset(&cache[i].dec_dsc, 0, sizeof(lv_img_decoder_dsc_t));
memset(&cache[i], 0, sizeof(lv_img_cache_entry_t));
}
}

View File

@ -24,10 +24,7 @@ extern "C" {
**********************/
typedef struct
{
lv_img_decoder_dsc_t dsc;
/* How much time did it take to open the image.*/
uint32_t time_to_open;
lv_img_decoder_dsc_t dec_dsc;
/* Count the cache entries's life. Add `time_tio_open` to `life` when the entry is used.
* Decrement all lifes by one every in every `lv_img_cache_open`.

View File

@ -178,6 +178,10 @@ typedef struct _lv_img_decoder_dsc
* MUST be set in `open` function*/
const uint8_t * img_data;
/** How much time did it take to open the image. [ms]
* If not set `lv_img_cache` will measure and set the time to open*/
uint32_t time_to_open;
/**A text to display instead of the image when the image can't be opened.
* Can be set in `open` function or set NULL. */
const char * error_msg;

View File

@ -67,6 +67,11 @@ void lv_disp_drv_init(lv_disp_drv_t * driver)
driver->antialiasing = true;
#endif
#if LV_COLOR_SCREEN_TRANSP
driver->screen_transp = 1;
#endif
#if LV_USE_GPU
driver->mem_blend_cb = NULL;
driver->mem_fill_cb = NULL;
@ -267,7 +272,9 @@ LV_ATTRIBUTE_FLUSH_READY void lv_disp_flush_ready(lv_disp_drv_t * disp_drv)
/*If the screen is transparent initialize it when the flushing is ready*/
#if LV_COLOR_SCREEN_TRANSP
memset(vdb_buf, 0x00, LV_VDB_SIZE_IN_BYTES);
if(disp_drv->screen_transp) {
memset(disp_drv->buffer->buf_act, 0x00, disp_drv->buffer->size * sizeof(lv_color32_t));
}
#endif
}

View File

@ -72,6 +72,12 @@ typedef struct _disp_drv_t
#endif
uint32_t rotated : 1; /*1: turn the display by 90 degree.*/
#if LV_COLOR_SCREEN_TRANSP
/**Handle if the the screen doesn't have a solid (opa == LV_OPA_COVER) background.
* Use only if required because it's slower.*/
uint32_t screen_transp : 1;
#endif
/* MANDATORY: Write the internal buffer (VDB) to the display. 'lv_disp_flush_ready()' has to be
* called when finished */
void (*flush_cb)(struct _disp_drv_t * disp_drv, const lv_area_t * area, lv_color_t * color_p);
@ -218,12 +224,16 @@ lv_coord_t lv_disp_get_ver_res(lv_disp_t * disp);
*/
bool lv_disp_get_antialiasing(lv_disp_t * disp);
//! @cond Doxygen_Suppress
/**
* Call in the display driver's `flush_cb` function when the flushing is finished
* @param disp_drv pointer to display driver in `flush_cb` where this function is called
*/
LV_ATTRIBUTE_FLUSH_READY void lv_disp_flush_ready(lv_disp_drv_t * disp_drv);
//! @endcond
/**
* Get the next display.
* @param disp pointer to the current display. NULL to initialize.

View File

@ -36,12 +36,16 @@ extern "C" {
* GLOBAL PROTOTYPES
**********************/
//! @cond Doxygen_Suppress
/**
* You have to call this function periodically
* @param tick_period the call period of this function in milliseconds
*/
LV_ATTRIBUTE_TICK_INC void lv_tick_inc(uint32_t tick_period);
//! @endcond
/**
* Get the elapsed milliseconds since start up
* @return the elapsed milliseconds

View File

@ -40,7 +40,6 @@ extern "C" {
#define LV_COLOR_WHITE LV_COLOR_MAKE(0xFF, 0xFF, 0xFF)
#define LV_COLOR_SILVER LV_COLOR_MAKE(0xC0, 0xC0, 0xC0)
#define LV_COLOR_GRAY LV_COLOR_MAKE(0x80, 0x80, 0x80)
#define LV_COLOR_LIGHT_GRAY LV_COLOR_MAKE(0xC0, 0xC0, 0xC0)
#define LV_COLOR_BLACK LV_COLOR_MAKE(0x00, 0x00, 0x00)
#define LV_COLOR_RED LV_COLOR_MAKE(0xFF, 0x00, 0x00)
#define LV_COLOR_MAROON LV_COLOR_MAKE(0x80, 0x00, 0x00)

View File

@ -38,7 +38,7 @@ extern "C" {
struct _lv_task_t;
/**
* Tasks execte this type type of functions.
* Tasks execute this type type of functions.
*/
typedef void (*lv_task_cb_t)(struct _lv_task_t *);
@ -80,11 +80,15 @@ typedef struct _lv_task_t
*/
void lv_task_core_init(void);
//! @cond Doxygen_Suppress
/**
* Call it periodically to handle lv_tasks.
*/
LV_ATTRIBUTE_TASK_HANDLER void lv_task_handler(void);
//! @endcond
/**
* Create an "empty" task. It needs to initialzed with at least
* `lv_task_set_cb` and `lv_task_set_period`

View File

@ -423,13 +423,13 @@ bool lv_page_on_edge(lv_obj_t * page, lv_page_edge_t edge)
lv_obj_get_coords(scrl, &scrl_coords);
lv_obj_get_coords(page, &page_coords);
if(edge == LV_PAGE_EDGE_TOP && scrl_coords.y1 == page_coords.y1 + page_style->body.padding.top)
if((edge & LV_PAGE_EDGE_TOP) && scrl_coords.y1 == page_coords.y1 + page_style->body.padding.top)
return true;
else if(edge == LV_PAGE_EDGE_BOTTOM && scrl_coords.y2 == page_coords.y2 - page_style->body.padding.bottom)
if((edge & LV_PAGE_EDGE_BOTTOM) && scrl_coords.y2 == page_coords.y2 - page_style->body.padding.bottom)
return true;
else if(edge == LV_PAGE_EDGE_LEFT && scrl_coords.x1 == page_coords.x1 + page_style->body.padding.left)
if((edge & LV_PAGE_EDGE_LEFT) && scrl_coords.x1 == page_coords.x1 + page_style->body.padding.left)
return true;
else if(edge == LV_PAGE_EDGE_RIGHT && scrl_coords.x2 == page_coords.x2 - page_style->body.padding.right)
if((edge & LV_PAGE_EDGE_RIGHT) && scrl_coords.x2 == page_coords.x2 - page_style->body.padding.right)
return true;
return false;
@ -940,6 +940,7 @@ static lv_res_t lv_page_scrollable_signal(lv_obj_t * scrl, lv_signal_t sign, voi
if(lv_obj_get_parent(page_parent) != NULL) { /*Do not propagate the scroll to a screen*/
page_ext->scroll_prop_ip = 1;
}
}
}

View File

@ -51,10 +51,10 @@ typedef uint8_t lv_sb_mode_t;
/*Edges: describes the four edges of the page*/
enum {
LV_PAGE_EDGE_LEFT = 0x0,
LV_PAGE_EDGE_TOP = 0x1,
LV_PAGE_EDGE_RIGHT = 0x2,
LV_PAGE_EDGE_BOTTOM = 0x3
LV_PAGE_EDGE_LEFT = 0x1,
LV_PAGE_EDGE_TOP = 0x2,
LV_PAGE_EDGE_RIGHT = 0x4,
LV_PAGE_EDGE_BOTTOM = 0x8
};
typedef uint8_t lv_page_edge_t;

View File

@ -107,7 +107,7 @@ lv_obj_t * lv_roller_create(lv_obj_t * par, const lv_obj_t * copy)
/*Copy an existing roller*/
else {
lv_roller_ext_t * copy_ext = lv_obj_get_ext_attr(copy);
ext->inf = copy_ext->inf;
ext->mode = copy_ext->mode;
lv_obj_t * scrl = lv_page_get_scrl(new_roller);
lv_ddlist_open(new_roller, false);
@ -130,13 +130,14 @@ lv_obj_t * lv_roller_create(lv_obj_t * par, const lv_obj_t * copy)
* Set the options on a roller
* @param roller pointer to roller object
* @param options a string with '\n' separated options. E.g. "One\nTwo\nThree"
* @param mode `LV_ROLLER_MODE_NORMAL` or `LV_ROLLER_MODE_INFINITE`
*/
void lv_roller_set_options(lv_obj_t * roller, const char * options, bool inf)
void lv_roller_set_options(lv_obj_t * roller, const char * options, lv_roller_mode_t mode)
{
lv_roller_ext_t * ext = lv_obj_get_ext_attr(roller);
if(inf == false) {
ext->inf = 0;
if(mode == LV_ROLLER_MODE_NORMAL) {
ext->mode = LV_ROLLER_MODE_NORMAL;
lv_ddlist_set_options(roller, options);
/* Make sure the roller's height and the scrollable's height is refreshed.
@ -144,7 +145,7 @@ void lv_roller_set_options(lv_obj_t * roller, const char * options, bool inf)
* that signal won't be called. (It called because LV_FIT_TIGHT hor fit)*/
refr_height(roller);
} else {
ext->inf = 1;
ext->mode = LV_ROLLER_MODE_INIFINITE;
uint32_t opt_len = strlen(options) + 1; /*+1 to add '\n' after option lists*/
char * opt_extra = lv_mem_alloc(opt_len * LV_ROLLER_INF_PAGES);
@ -238,7 +239,7 @@ void lv_roller_set_style(lv_obj_t * roller, lv_roller_style_t type, const lv_sty
uint16_t lv_roller_get_selected(const lv_obj_t * roller)
{
lv_roller_ext_t * ext = lv_obj_get_ext_attr(roller);
if(ext->inf) {
if(ext->mode == LV_ROLLER_MODE_INIFINITE) {
uint16_t real_id_cnt = ext->ddlist.option_cnt / LV_ROLLER_INF_PAGES;
return lv_ddlist_get_selected(roller) % real_id_cnt;
} else {
@ -675,7 +676,7 @@ static void inf_normalize(void * scrl)
lv_obj_t * roller = lv_obj_get_parent(roller_scrl);
lv_roller_ext_t * ext = lv_obj_get_ext_attr(roller);
if(ext->inf) {
if(ext->mode == LV_ROLLER_MODE_INIFINITE) {
uint16_t real_id_cnt = ext->ddlist.option_cnt / LV_ROLLER_INF_PAGES;
ext->ddlist.sel_opt_id = ext->ddlist.sel_opt_id % real_id_cnt;

View File

@ -37,12 +37,23 @@ extern "C" {
/**********************
* TYPEDEFS
**********************/
enum {
LV_ROLLER_MODE_NORMAL,
LV_ROLLER_MODE_INIFINITE,
};
typedef uint8_t lv_roller_mode_t;
/*Data of roller*/
typedef struct
{
lv_ddlist_ext_t ddlist; /*Ext. of ancestor*/
/*New data for this type */
uint8_t inf : 1; /*Infinite*/
lv_roller_mode_t mode : 1;
} lv_roller_ext_t;
enum {
@ -71,9 +82,9 @@ lv_obj_t * lv_roller_create(lv_obj_t * par, const lv_obj_t * copy);
* Set the options on a roller
* @param roller pointer to roller object
* @param options a string with '\n' separated options. E.g. "One\nTwo\nThree"
* @param inf True: Loop through the options
* @param mode `LV_ROLLER_MODE_NORMAL` or `LV_ROLLER_MODE_INFINITE`
*/
void lv_roller_set_options(lv_obj_t * roller, const char * options, bool inf);
void lv_roller_set_options(lv_obj_t * roller, const char * options, lv_roller_mode_t mode);
/**
* Set the align of the roller's options (left, right or center[default])

View File

@ -72,8 +72,9 @@ lv_obj_t * lv_spinbox_create(lv_obj_t * par, const lv_obj_t * copy)
ext->range_max = 99999;
ext->range_min = -99999;
lv_ta_set_cursor_type(new_spinbox, LV_CURSOR_BLOCK | LV_CURSOR_HIDDEN); /*hidden by default*/
lv_ta_set_cursor_type(new_spinbox, LV_CURSOR_BLOCK);
lv_ta_set_one_line(new_spinbox, true);
lv_ta_set_cursor_click_pos(new_spinbox, false);
/*The signal and design functions are not copied so set them here*/
lv_obj_set_signal_cb(new_spinbox, lv_spinbox_signal);
@ -243,7 +244,7 @@ void lv_spinbox_step_next(lv_obj_t * spinbox)
* Select next higher digit for edition
* @param spinbox pointer to spinbox
*/
void lv_spinbox_step_previous(lv_obj_t * spinbox)
void lv_spinbox_step_prev(lv_obj_t * spinbox)
{
lv_spinbox_ext_t * ext = lv_obj_get_ext_attr(spinbox);
int32_t step_limit;
@ -342,7 +343,7 @@ static lv_res_t lv_spinbox_signal(lv_obj_t * spinbox, lv_signal_t sign, void * p
if(new_step >= ext->range_max) break;
ext->step = new_step;
}
lv_spinbox_step_previous(spinbox);
lv_spinbox_step_prev(spinbox);
}
}
}
@ -359,7 +360,7 @@ static lv_res_t lv_spinbox_signal(lv_obj_t * spinbox, lv_signal_t sign, void * p
if(indev_type == LV_INDEV_TYPE_ENCODER)
lv_spinbox_decrement(spinbox);
else
lv_spinbox_step_previous(spinbox);
lv_spinbox_step_prev(spinbox);
} else if(c == LV_KEY_UP) {
lv_spinbox_increment(spinbox);
} else if(c == LV_KEY_DOWN) {

View File

@ -161,7 +161,7 @@ void lv_spinbox_step_next(lv_obj_t * spinbox);
* Select next higher digit for edition by multiplying the step by 10
* @param spinbox pointer to spinbox
*/
void lv_spinbox_step_previous(lv_obj_t * spinbox);
void lv_spinbox_step_prev(lv_obj_t * spinbox);
/**
* Increment spinbox value by one step

View File

@ -91,7 +91,12 @@ lv_obj_t * lv_tileview_create(lv_obj_t * par, const lv_obj_t * copy)
/*Init the new tileview*/
if(copy == NULL) {
lv_obj_set_size(new_tileview, LV_DPI * 3, LV_DPI * 3);
/* Set a size which fits into the parent.
* Don't use `par` directly because if the tileview is created on a page it is moved to the
* scrollable so the parent has changed */
lv_obj_set_size(new_tileview, lv_obj_get_width_fit(lv_obj_get_parent(new_tileview)),
lv_obj_get_height_fit(lv_obj_get_parent(new_tileview)));
lv_obj_set_drag_throw(lv_page_get_scrl(new_tileview), false);
lv_page_set_scrl_fit(new_tileview, LV_FIT_TIGHT);
lv_obj_set_event_cb(ext->page.scrl, tileview_scrl_event_cb);