diff --git a/lv_misc/lv_utils.c b/lv_misc/lv_utils.c new file mode 100644 index 000000000..5ea617710 --- /dev/null +++ b/lv_misc/lv_utils.c @@ -0,0 +1,116 @@ +/** + * @file lv_utils.c + * + */ + +/********************* + * INCLUDES + *********************/ +#include + +#include "lv_utils.h" +#include "lv_math.h" + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * STATIC PROTOTYPES + **********************/ + +/********************** + * STATIC VARIABLES + **********************/ + +/********************** + * MACROS + **********************/ + +/********************** + * GLOBAL FUNCTIONS + **********************/ + +/** + * Convert a number to string + * @param num a number + * @param buf pointer to a `char` buffer. The result will be stored here (max 10 elements) + * @return same as `buf` (just for convenience) + */ +char * lv_utils_num_to_str(int32_t num, char * buf) +{ + if (num == 0) { + buf[0] = '0'; + buf[1] = '\0'; + return buf; + } + int8_t digitCount = 0; + int8_t i = 0; + if (num < 0) { + buf[digitCount++] = '-'; + num = abs(num); + ++i; + } + while (num) { + char digit = num % 10; + buf[digitCount++] = digit + 48; + num /= 10; + } + buf[digitCount] = '\0'; + digitCount--; + while (digitCount > i) { + char temp = buf[i]; + buf[i] = buf[digitCount]; + buf[digitCount] = temp; + digitCount--; + i++; + } + return buf; +} + + +/** Searches base[0] to base[n - 1] for an item that matches *key. + * + * @note The function cmp must return negative if its first + * argument (the search key) is less that its second (a table entry), + * zero if equal, and positive if greater. + * + * @note Items in the array must be in ascending order. + * + * @param key Pointer to item being searched for + * @param base Pointer to first element to search + * @param n Number of elements + * @param size Size of each element + * @param cmp Pointer to comparison function (see #lv_font_codeCompare as a comparison function example) + * + * @return a pointer to a matching item, or NULL if none exists. + */ +void * lv_utils_bsearch(const void * key, const void * base, uint32_t n, uint32_t size, int32_t (* cmp)(const void * pRef, const void * pElement)) +{ + const char * middle; + int32_t c; + + for (middle = base; n != 0;) { + middle += (n/2) * size; + if ((c = (*cmp)(key, middle)) > 0) { + n = (n/2) - ((n&1) == 0); + base = (middle += size); + } else if (c < 0) { + n /= 2; + middle = base; + } else { + return (char *) middle; + } + } + return NULL; +} + +/********************** + * STATIC FUNCTIONS + **********************/ + + diff --git a/lv_misc/lv_utils.h b/lv_misc/lv_utils.h new file mode 100644 index 000000000..f39adc351 --- /dev/null +++ b/lv_misc/lv_utils.h @@ -0,0 +1,65 @@ +/** + * @file lv_utils.h + * + */ + +#ifndef LV_UTILS_H +#define LV_UTILS_H + +#ifdef __cplusplus +extern "C" { +#endif + + +/********************* + * INCLUDES + *********************/ +#include +#include + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * GLOBAL PROTOTYPES + **********************/ +/** + * Convert a number to string + * @param num a number + * @param buf pointer to a `char` buffer. The result will be stored here (max 10 elements) + * @return same as `buf` (just for convenience) + */ +char * lv_utils_num_to_str(int32_t num, char * buf); + +/** Searches base[0] to base[n - 1] for an item that matches *key. + * + * @note The function cmp must return negative if its first + * argument (the search key) is less that its second (a table entry), + * zero if equal, and positive if greater. + * + * @note Items in the array must be in ascending order. + * + * @param key Pointer to item being searched for + * @param base Pointer to first element to search + * @param n Number of elements + * @param size Size of each element + * @param cmp Pointer to comparison function (see #lv_font_codeCompare as a comparison function example) + * + * @return a pointer to a matching item, or NULL if none exists. + */ +void * lv_utils_bsearch(const void * key, const void * base, uint32_t n, uint32_t size, int32_t (* cmp)(const void * pRef, const void * pElement)); + +/********************** + * MACROS + **********************/ + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif diff --git a/src/lv_misc/lv_font.c b/src/lv_misc/lv_font.c index 0aa7fe22a..ed5550a7a 100644 --- a/src/lv_misc/lv_font.c +++ b/src/lv_misc/lv_font.c @@ -6,9 +6,10 @@ /********************* * INCLUDES *********************/ -#include + #include "lv_font.h" #include "lv_log.h" +#include "lv_utils.h" /********************* * DEFINES @@ -22,6 +23,8 @@ * STATIC PROTOTYPES **********************/ +static int32_t lv_font_codeCompare (const void* pRef, const void* pElement); + /********************** * STATIC VARIABLES **********************/ @@ -216,11 +219,17 @@ const uint8_t * lv_font_get_bitmap_sparse(const lv_font_t * font, uint32_t unico /*Check the range*/ if(unicode_letter < font->unicode_first || unicode_letter > font->unicode_last) return NULL; - uint32_t i; - for(i = 0; font->unicode_list[i] != 0; i++) { - if(font->unicode_list[i] == unicode_letter) { - return &font->glyph_bitmap[font->glyph_dsc[i].glyph_index]; - } + uint32_t* pUnicode; + + pUnicode = lv_utils_bsearch(&unicode_letter, + (uint32_t*) font->unicode_list, + font->glyph_cnt, + sizeof(uint32_t), + lv_font_codeCompare); + + if (pUnicode != NULL) { + uint32_t idx = (uint32_t) (pUnicode - font->unicode_list); + return &font->glyph_bitmap[font->glyph_dsc[idx].glyph_index]; } return NULL; @@ -254,11 +263,17 @@ int16_t lv_font_get_width_sparse(const lv_font_t * font, uint32_t unicode_letter /*Check the range*/ if(unicode_letter < font->unicode_first || unicode_letter > font->unicode_last) return -1; - uint32_t i; - for(i = 0; font->unicode_list[i] != 0; i++) { - if(font->unicode_list[i] == unicode_letter) { - return font->glyph_dsc[i].w_px; - } + uint32_t* pUnicode; + + pUnicode = lv_utils_bsearch(&unicode_letter, + (uint32_t*) font->unicode_list, + font->glyph_cnt, + sizeof(uint32_t), + lv_font_codeCompare); + + if (pUnicode != NULL) { + uint32_t idx = (uint32_t) (pUnicode - font->unicode_list); + return font->glyph_dsc[idx].w_px; } return -1; @@ -267,3 +282,22 @@ int16_t lv_font_get_width_sparse(const lv_font_t * font, uint32_t unicode_letter /********************** * STATIC FUNCTIONS **********************/ + +/** Code Comparator. + * + * Compares the value of both input arguments. + * + * @param[in] pRef Pointer to the reference. + * @param[in] pElement Pointer to the element to compare. + * + * @return Result of comparison. + * @retval < 0 Reference is greater than element. + * @retval = 0 Reference is equal to element. + * @retval > 0 Reference is less than element. + * + */ +static int32_t lv_font_codeCompare (const void* pRef, + const void* pElement) +{ + return (*(uint32_t*) pRef) - (*(uint32_t*) pElement); +} diff --git a/src/lv_misc/lv_math.c b/src/lv_misc/lv_math.c index 73c80ad40..7c56ea6f4 100644 --- a/src/lv_misc/lv_math.c +++ b/src/lv_misc/lv_math.c @@ -47,43 +47,6 @@ static int16_t sin0_90_table[] = { * GLOBAL FUNCTIONS **********************/ -/** - * Convert a number to string - * @param num a number - * @param buf pointer to a `char` buffer. The result will be stored here (max 10 elements) - * @return same as `buf` (just for convenience) - */ -char * lv_math_num_to_str(int32_t num, char * buf) -{ - if (num == 0) { - buf[0] = '0'; - buf[1] = '\0'; - return buf; - } - int8_t digitCount = 0; - int8_t i = 0; - if (num < 0) { - buf[digitCount++] = '-'; - num = abs(num); - ++i; - } - while (num) { - char digit = num % 10; - buf[digitCount++] = digit + 48; - num /= 10; - } - buf[digitCount] = '\0'; - digitCount--; - while (digitCount > i) { - char temp = buf[i]; - buf[i] = buf[digitCount]; - buf[digitCount] = temp; - digitCount--; - i++; - } - return buf; -} - /** * Return with sinus of an angle * @param angle diff --git a/src/lv_misc/lv_math.h b/src/lv_misc/lv_math.h index a0229eb1b..fea5bc950 100644 --- a/src/lv_misc/lv_math.h +++ b/src/lv_misc/lv_math.h @@ -36,13 +36,6 @@ extern "C" { /********************** * GLOBAL PROTOTYPES **********************/ -/** - * Convert a number to string - * @param num a number - * @param buf pointer to a `char` buffer. The result will be stored here (max 10 elements) - * @return same as `buf` (just for convenience) - */ -char * lv_math_num_to_str(int32_t num, char * buf); /** * Return with sinus of an angle diff --git a/src/lv_misc/lv_misc.mk b/src/lv_misc/lv_misc.mk index f9f2cbdc2..360cf2ee7 100644 --- a/src/lv_misc/lv_misc.mk +++ b/src/lv_misc/lv_misc.mk @@ -11,6 +11,7 @@ CSRCS += lv_txt.c CSRCS += lv_math.c CSRCS += lv_log.c CSRCS += lv_gc.c +CSRCS += lv_utils.c DEPPATH += --dep-path $(LVGL_DIR)/lvgl/src/lv_misc VPATH += :$(LVGL_DIR)/lvgl/src/lv_misc diff --git a/src/lv_objx/lv_calendar.c b/src/lv_objx/lv_calendar.c index e248bf4a2..6398a16c1 100644 --- a/src/lv_objx/lv_calendar.c +++ b/src/lv_objx/lv_calendar.c @@ -11,7 +11,7 @@ #include "../lv_draw/lv_draw.h" #include "../lv_hal/lv_hal_indev.h" -#include "../lv_misc/lv_math.h" +#include "../lv_misc/lv_utils.h" #include "../lv_core/lv_indev.h" #include "../lv_themes/lv_theme.h" #include @@ -681,7 +681,7 @@ static void draw_header(lv_obj_t * calendar, const lv_area_t * mask) /*Add the year + month name*/ char txt_buf[64]; - lv_math_num_to_str(ext->showed_date.year, txt_buf); + lv_utils_num_to_str(ext->showed_date.year, txt_buf); txt_buf[4] = ' '; txt_buf[5] = '\0'; strcpy(&txt_buf[5], get_month_name(calendar, ext->showed_date.month)); @@ -851,7 +851,7 @@ static void draw_days(lv_obj_t * calendar, const lv_area_t * mask) else final_style = act_style; /*Write the day's number*/ - lv_math_num_to_str(day_cnt, buf); + lv_utils_num_to_str(day_cnt, buf); lv_draw_label(&label_area, mask, final_style, opa_scale, buf, LV_TXT_FLAG_CENTER, NULL); /*Go to the next day*/ diff --git a/src/lv_objx/lv_gauge.c b/src/lv_objx/lv_gauge.c index 768e4c864..385d9f9bc 100644 --- a/src/lv_objx/lv_gauge.c +++ b/src/lv_objx/lv_gauge.c @@ -14,6 +14,7 @@ #include "../lv_themes/lv_theme.h" #include "../lv_misc/lv_txt.h" #include "../lv_misc/lv_math.h" +#include "../lv_misc/lv_utils.h" #include #include @@ -371,7 +372,7 @@ static void lv_gauge_draw_scale(lv_obj_t * gauge, const lv_area_t * mask) int16_t scale_act = (int32_t)((int32_t)(max - min) * i) / (label_num - 1); scale_act += min; - lv_math_num_to_str(scale_act, scale_txt); + lv_utils_num_to_str(scale_act, scale_txt); lv_area_t label_cord; lv_point_t label_size; diff --git a/src/lv_objx/lv_spinbox.c b/src/lv_objx/lv_spinbox.c index b59075135..b13182749 100644 --- a/src/lv_objx/lv_spinbox.c +++ b/src/lv_objx/lv_spinbox.c @@ -11,6 +11,7 @@ #if LV_USE_SPINBOX != 0 #include "../lv_themes/lv_theme.h" #include "../lv_misc/lv_math.h" +#include "../lv_misc/lv_utils.h" /********************* * DEFINES @@ -403,7 +404,7 @@ static void lv_spinbox_updatevalue(lv_obj_t * spinbox) char digits[64]; /*Convert the numbers to string (the sign is already handled so always covert positive number)*/ - lv_math_num_to_str(ext->value < 0 ? -ext->value : ext->value, digits); + lv_utils_num_to_str(ext->value < 0 ? -ext->value : ext->value, digits); /*Add leading zeros*/ int lz_cnt = ext->digit_count - (int)strlen(digits);