From 3d7713717831ff7f8c30ca24bd64b2a3203dbf0a Mon Sep 17 00:00:00 2001 From: Brian Pugh Date: Sun, 14 Apr 2019 11:18:31 -0700 Subject: [PATCH] lv_label: dynamically allocate space for dots if necessary. If the required dots storage space is 4 or less bytes, directly stores them in the extended data object --- src/lv_core/lv_obj.h | 3 +- src/lv_objx/lv_label.c | 97 +++++++++++++++++++++++++++++++++++++----- src/lv_objx/lv_label.h | 6 ++- 3 files changed, 92 insertions(+), 14 deletions(-) diff --git a/src/lv_core/lv_obj.h b/src/lv_core/lv_obj.h index 1fa0bf1df..7845ad7d6 100644 --- a/src/lv_core/lv_obj.h +++ b/src/lv_core/lv_obj.h @@ -208,8 +208,7 @@ typedef struct _lv_obj_t `lv_protect_t`*/ lv_opa_t opa_scale; /*Scale down the opacity by this factor. Effects all children as well*/ - lv_coord_t - ext_size; /*EXTtend the size of the object in every direction. E.g. for shadow drawing*/ + lv_coord_t ext_size; /*EXTtend the size of the object in every direction. E.g. for shadow drawing*/ #if LV_OBJ_REALIGN lv_reailgn_t realign; #endif diff --git a/src/lv_objx/lv_label.c b/src/lv_objx/lv_label.c index 630b6c7c1..d4d02b5ae 100644 --- a/src/lv_objx/lv_label.c +++ b/src/lv_objx/lv_label.c @@ -43,6 +43,11 @@ static void lv_label_revert_dots(lv_obj_t * label); static void lv_label_set_offset_x(lv_obj_t * label, lv_coord_t x); static void lv_label_set_offset_y(lv_obj_t * label, lv_coord_t y); #endif + +static bool lv_label_set_dot_tmp(lv_obj_t *label, char *data, int len); +static char * lv_label_get_dot_tmp(lv_obj_t *label); +static void lv_label_dot_tmp_free(lv_obj_t *label); + /********************** * STATIC VARIABLES **********************/ @@ -95,6 +100,8 @@ lv_obj_t * lv_label_create(lv_obj_t * par, const lv_obj_t * copy) ext->selection_end = 0; ext->selection_en = 0; #endif + ext->dot_tmp_ptr = NULL; + ext->dot_tmp_alloc = 0; lv_obj_set_design_cb(new_label, lv_label_design); lv_obj_set_signal_cb(new_label, lv_label_signal); @@ -126,7 +133,13 @@ lv_obj_t * lv_label_create(lv_obj_t * par, const lv_obj_t * copy) memcpy(ext->text, copy_ext->text, lv_mem_get_size(copy_ext->text)); } - memcpy(ext->dot_tmp, copy_ext->dot_tmp, sizeof(ext->dot_tmp)); + if(copy_ext->dot_tmp_alloc && copy_ext->dot_tmp_ptr ){ + int len = strlen(copy_ext->dot_tmp_ptr); + lv_label_set_dot_tmp(new_label, ext->dot_tmp_ptr, len); + } + else{ + memcpy(ext->dot_tmp, copy_ext->dot_tmp, sizeof(ext->dot_tmp)); + } ext->dot_end = copy_ext->dot_end; /*Refresh the style with new signal function*/ @@ -870,6 +883,7 @@ static lv_res_t lv_label_signal(lv_obj_t * label, lv_signal_t sign, void * param lv_mem_free(ext->text); ext->text = NULL; } + lv_label_dot_tmp_free(label); } else if(sign == LV_SIGNAL_STYLE_CHG) { /*Revert dots for proper refresh*/ lv_label_revert_dots(label); @@ -1040,15 +1054,13 @@ static void lv_label_refr_text(lv_obj_t * label) lv_txt_encoded_next(ext->text, &byte_id); } - memcpy(ext->dot_tmp, &ext->text[byte_id_ori], len); - ext->dot_tmp[len] = '\0'; /*Close with a zero*/ - - for(i = 0; i < LV_LABEL_DOT_NUM; i++) { - ext->text[byte_id_ori + i] = '.'; + if( lv_label_set_dot_tmp(label, &ext->text[byte_id_ori], len ) ){ + for(i = 0; i < LV_LABEL_DOT_NUM; i++) { + ext->text[byte_id_ori + i] = '.'; + } + ext->text[byte_id_ori + LV_LABEL_DOT_NUM] = '\0'; + ext->dot_end = letter_id + LV_LABEL_DOT_NUM; } - ext->text[byte_id_ori + LV_LABEL_DOT_NUM] = '\0'; - - ext->dot_end = letter_id + LV_LABEL_DOT_NUM; } } /*In break mode only the height can change*/ @@ -1073,10 +1085,13 @@ static void lv_label_revert_dots(lv_obj_t * label) /*Restore the characters*/ uint8_t i = 0; - while(ext->dot_tmp[i] != '\0') { - ext->text[byte_i + i] = ext->dot_tmp[i]; + char* dot_tmp = lv_label_get_dot_tmp(label); + while(ext->text[byte_i + i] != '\0') { + ext->text[byte_i + i] = dot_tmp[i]; i++; } + ext->text[byte_i + i] = dot_tmp[i]; + lv_label_dot_tmp_free(label); ext->dot_end = LV_LABEL_DOT_END_INV; } @@ -1096,4 +1111,64 @@ static void lv_label_set_offset_y(lv_obj_t * label, lv_coord_t y) lv_obj_invalidate(label); } #endif + +/** + * Store `len` characters from `data`. Allocates space if necessary. + * + * @param label pointer to label object + * @param len Number of characters to store. + * @return true on success. + */ +static bool lv_label_set_dot_tmp(lv_obj_t *label, char *data, int len){ + lv_label_ext_t * ext = lv_obj_get_ext_attr(label); + lv_label_dot_tmp_free( label ); /* Deallocate any existing space */ + if( len > 4 ){ + /* Memory needs to be allocated. Allocates an additional byte + * for a NULL-terminator so it can be copied. */ + ext->dot_tmp_ptr = lv_mem_alloc(len + 1); + if( ext->dot_tmp_ptr == NULL ){ + LV_LOG_ERROR("Failed to allocate memory for dot_tmp_ptr"); + return false; + } + memcpy(ext->dot_tmp_ptr, data, len); + ext->dot_tmp_ptr[len]='\0'; + ext->dot_tmp_alloc = true; + } + else { + /* Characters can be directly stored in object */ + ext->dot_tmp_alloc = false; + memcpy(ext->dot_tmp, data, len); + } + return true; +} + +/** + * Get the stored dot_tmp characters + * @param label pointer to label object + * @return char pointer to a stored characters. Is *not* necessarily NULL-terminated. + */ +static char * lv_label_get_dot_tmp(lv_obj_t *label){ + lv_label_ext_t * ext = lv_obj_get_ext_attr(label); + if( ext->dot_tmp_alloc ){ + return ext->dot_tmp_ptr; + } + else{ + return ext->dot_tmp; + } +} + +/** + * Free the dot_tmp_ptr field if it was previously allocated. + * Always clears the field + * @param label pointer to label object. + */ +static void lv_label_dot_tmp_free(lv_obj_t *label){ + lv_label_ext_t * ext = lv_obj_get_ext_attr(label); + if( ext->dot_tmp_alloc && ext->dot_tmp_ptr ){ + lv_mem_free(ext->dot_tmp_ptr); + } + ext->dot_tmp_alloc = false; + ext->dot_tmp_ptr = NULL; +} + #endif diff --git a/src/lv_objx/lv_label.h b/src/lv_objx/lv_label.h index 87e658373..98f7297f3 100644 --- a/src/lv_objx/lv_label.h +++ b/src/lv_objx/lv_label.h @@ -62,7 +62,10 @@ typedef struct /*Inherited from 'base_obj' so no inherited ext.*/ /*Ext. of ancestor*/ /*New data for this type */ char * text; /*Text of the label*/ - char dot_tmp[LV_LABEL_DOT_NUM * 4 ]; /*Store the character which are replaced by dots (Handled by the library)*/ + union{ + char * dot_tmp_ptr; /* Pointer to the allocated memory containing the character which are replaced by dots (Handled by the library)*/ + char dot_tmp[4]; /* Directly store the characters if <=4 characters */ + }; uint16_t dot_end; /*The text end position in dot mode (Handled by the library)*/ uint16_t anim_speed; /*Speed of scroll and roll animation in px/sec unit*/ lv_point_t offset; /*Text draw position offset*/ @@ -79,6 +82,7 @@ typedef struct uint8_t recolor : 1; /*Enable in-line letter re-coloring*/ uint8_t expand : 1; /*Ignore real width (used by the library with LV_LABEL_LONG_ROLL)*/ uint8_t body_draw : 1; /*Draw background body*/ + uint8_t dot_tmp_alloc : 1; /*True if dot_tmp has been allocated. False if dot_tmp directly holds up to 4 bytes of characters */ } lv_label_ext_t; /**********************