summaryrefslogtreecommitdiff
path: root/src/libs/lvgl/src/lv_misc
diff options
context:
space:
mode:
Diffstat (limited to 'src/libs/lvgl/src/lv_misc')
-rw-r--r--src/libs/lvgl/src/lv_misc/lv_anim.c216
-rw-r--r--src/libs/lvgl/src/lv_misc/lv_anim.h215
-rw-r--r--src/libs/lvgl/src/lv_misc/lv_area.c253
-rw-r--r--src/libs/lvgl/src/lv_misc/lv_area.h71
-rw-r--r--src/libs/lvgl/src/lv_misc/lv_async.c31
-rw-r--r--src/libs/lvgl/src/lv_misc/lv_async.h11
-rw-r--r--src/libs/lvgl/src/lv_misc/lv_bidi.c373
-rw-r--r--src/libs/lvgl/src/lv_misc/lv_bidi.h81
-rw-r--r--src/libs/lvgl/src/lv_misc/lv_circ.c79
-rw-r--r--src/libs/lvgl/src/lv_misc/lv_circ.h77
-rw-r--r--src/libs/lvgl/src/lv_misc/lv_color.c110
-rw-r--r--src/libs/lvgl/src/lv_misc/lv_color.h483
-rw-r--r--src/libs/lvgl/src/lv_misc/lv_debug.c138
-rw-r--r--src/libs/lvgl/src/lv_misc/lv_debug.h131
-rw-r--r--src/libs/lvgl/src/lv_misc/lv_fs.c142
-rw-r--r--src/libs/lvgl/src/lv_misc/lv_fs.h32
-rw-r--r--src/libs/lvgl/src/lv_misc/lv_gc.c12
-rw-r--r--src/libs/lvgl/src/lv_misc/lv_gc.h25
-rw-r--r--src/libs/lvgl/src/lv_misc/lv_ll.c153
-rw-r--r--src/libs/lvgl/src/lv_misc/lv_ll.h50
-rw-r--r--src/libs/lvgl/src/lv_misc/lv_log.c34
-rw-r--r--src/libs/lvgl/src/lv_misc/lv_log.h90
-rw-r--r--src/libs/lvgl/src/lv_misc/lv_math.c119
-rw-r--r--src/libs/lvgl/src/lv_misc/lv_math.h61
-rw-r--r--src/libs/lvgl/src/lv_misc/lv_mem.c528
-rw-r--r--src/libs/lvgl/src/lv_misc/lv_mem.h171
-rw-r--r--src/libs/lvgl/src/lv_misc/lv_misc.mk10
-rw-r--r--src/libs/lvgl/src/lv_misc/lv_printf.c1284
-rw-r--r--src/libs/lvgl/src/lv_misc/lv_printf.h20
-rw-r--r--src/libs/lvgl/src/lv_misc/lv_task.c187
-rw-r--r--src/libs/lvgl/src/lv_misc/lv_task.h44
-rw-r--r--src/libs/lvgl/src/lv_misc/lv_templ.c2
-rw-r--r--src/libs/lvgl/src/lv_misc/lv_txt.c259
-rw-r--r--src/libs/lvgl/src/lv_misc/lv_txt.h59
-rw-r--r--src/libs/lvgl/src/lv_misc/lv_txt_ap.c273
-rw-r--r--src/libs/lvgl/src/lv_misc/lv_txt_ap.h60
-rw-r--r--src/libs/lvgl/src/lv_misc/lv_types.h39
-rw-r--r--src/libs/lvgl/src/lv_misc/lv_utils.c14
-rw-r--r--src/libs/lvgl/src/lv_misc/lv_utils.h6
39 files changed, 3968 insertions, 1975 deletions
diff --git a/src/libs/lvgl/src/lv_misc/lv_anim.c b/src/libs/lvgl/src/lv_misc/lv_anim.c
index 77bd87b9..4b01b805 100644
--- a/src/libs/lvgl/src/lv_misc/lv_anim.c
+++ b/src/libs/lvgl/src/lv_misc/lv_anim.c
@@ -11,21 +11,18 @@
#if LV_USE_ANIMATION
#include <stddef.h>
#include <string.h>
-#include "../lv_core/lv_debug.h"
+#include "../lv_misc/lv_debug.h"
#include "../lv_hal/lv_hal_tick.h"
#include "lv_task.h"
#include "lv_math.h"
#include "lv_gc.h"
-#if defined(LV_GC_INCLUDE)
-#include LV_GC_INCLUDE
-#endif /* LV_ENABLE_GC */
-
/*********************
* DEFINES
*********************/
#define LV_ANIM_RESOLUTION 1024
#define LV_ANIM_RES_SHIFT 10
+#define LV_ANIM_TASK_PRIO LV_TASK_PRIO_HIGH
/**********************
* TYPEDEFS
@@ -35,6 +32,7 @@
* STATIC PROTOTYPES
**********************/
static void anim_task(lv_task_t * param);
+static void anim_mark_list_change(void);
static bool anim_ready_handler(lv_anim_t * a);
/**********************
@@ -42,6 +40,8 @@ static bool anim_ready_handler(lv_anim_t * a);
**********************/
static uint32_t last_task_run;
static bool anim_list_changed;
+static lv_task_t * _lv_anim_task;
+const lv_anim_path_t lv_anim_path_def = {.cb = lv_anim_path_linear};
/**********************
* MACROS
@@ -54,11 +54,13 @@ static bool anim_list_changed;
/**
* Init. the animation module
*/
-void lv_anim_core_init(void)
+void _lv_anim_core_init(void)
{
- lv_ll_init(&LV_GC_ROOT(_lv_anim_ll), sizeof(lv_anim_t));
+ _lv_ll_init(&LV_GC_ROOT(_lv_anim_ll), sizeof(lv_anim_t));
last_task_run = lv_tick_get();
- lv_task_create(anim_task, LV_DISP_DEF_REFR_PERIOD, LV_TASK_PRIO_MID, NULL);
+ _lv_anim_task = lv_task_create(anim_task, LV_DISP_DEF_REFR_PERIOD, LV_ANIM_TASK_PRIO, NULL);
+ anim_mark_list_change(); /*Turn off the animation task*/
+ anim_list_changed = false; /*The list has not actually changed*/
}
/**
@@ -67,42 +69,50 @@ void lv_anim_core_init(void)
* lv_anim_t a;
* lv_anim_init(&a);
* lv_anim_set_...(&a);
- * lv_anim_craete(&a);
* @param a pointer to an `lv_anim_t` variable to initialize
*/
void lv_anim_init(lv_anim_t * a)
{
- memset(a, 0, sizeof(lv_anim_t));
+ _lv_memset_00(a, sizeof(lv_anim_t));
a->time = 500;
a->start = 0;
a->end = 100;
- a->path_cb = lv_anim_path_linear;
+ _lv_memcpy_small(&a->path, &lv_anim_path_def, sizeof(lv_anim_path_cb_t));
+ a->repeat_cnt = 1;
+ a->early_apply = 1;
}
/**
* Create an animation
* @param a an initialized 'anim_t' variable. Not required after call.
*/
-void lv_anim_create(lv_anim_t * a)
+void lv_anim_start(lv_anim_t * a)
{
LV_LOG_TRACE("animation create started")
- /* Do not let two animations for the same 'var' with the same 'fp'*/
+ /* Do not let two animations for the same 'var' with the same 'fp'*/
if(a->exec_cb != NULL) lv_anim_del(a->var, a->exec_cb); /*fp == NULL would delete all animations of var*/
+ /*If the list is empty the anim task was suspended and it's last run measure is invalid*/
+ if(_lv_ll_is_empty(&LV_GC_ROOT(_lv_anim_ll))) {
+ last_task_run = lv_tick_get() - 1;
+ }
+
/*Add the new animation to the animation linked list*/
- lv_anim_t * new_anim = lv_ll_ins_head(&LV_GC_ROOT(_lv_anim_ll));
+ lv_anim_t * new_anim = _lv_ll_ins_head(&LV_GC_ROOT(_lv_anim_ll));
LV_ASSERT_MEM(new_anim);
if(new_anim == NULL) return;
/*Initialize the animation descriptor*/
- a->playback_now = 0;
- memcpy(new_anim, a, sizeof(lv_anim_t));
+ a->time_orig = a->time;
+ _lv_memcpy(new_anim, a, sizeof(lv_anim_t));
/*Set the start value*/
- if(new_anim->exec_cb) new_anim->exec_cb(new_anim->var, new_anim->start);
+ if(new_anim->early_apply) {
+ if(new_anim->exec_cb && new_anim->var) new_anim->exec_cb(new_anim->var, new_anim->start);
+ }
/* Creating an animation changed the linked list.
* It's important if it happens in a ready callback. (see `anim_task`)*/
- anim_list_changed = true;
+ anim_mark_list_change();
LV_LOG_TRACE("animation created")
}
@@ -119,15 +129,15 @@ bool lv_anim_del(void * var, lv_anim_exec_xcb_t exec_cb)
lv_anim_t * a;
lv_anim_t * a_next;
bool del = false;
- a = lv_ll_get_head(&LV_GC_ROOT(_lv_anim_ll));
+ a = _lv_ll_get_head(&LV_GC_ROOT(_lv_anim_ll));
while(a != NULL) {
/*'a' might be deleted, so get the next object while 'a' is valid*/
- a_next = lv_ll_get_next(&LV_GC_ROOT(_lv_anim_ll), a);
+ a_next = _lv_ll_get_next(&LV_GC_ROOT(_lv_anim_ll), a);
if(a->var == var && (a->exec_cb == exec_cb || exec_cb == NULL)) {
- lv_ll_rem(&LV_GC_ROOT(_lv_anim_ll), a);
+ _lv_ll_remove(&LV_GC_ROOT(_lv_anim_ll), a);
lv_mem_free(a);
- anim_list_changed = true; /*Read by `anim_task`. It need to know if a delete occurred in
+ anim_mark_list_change(); /*Read by `anim_task`. It need to know if a delete occurred in
the linked list*/
del = true;
}
@@ -139,6 +149,25 @@ bool lv_anim_del(void * var, lv_anim_exec_xcb_t exec_cb)
}
/**
+ * Get the animation of a variable and its `exec_cb`.
+ * @param var pointer to variable
+ * @param exec_cb a function pointer which is animating 'var',
+ * or NULL to delete all the animations of 'var'
+ * @return pointer to the animation.
+ */
+lv_anim_t * lv_anim_get(void * var, lv_anim_exec_xcb_t exec_cb)
+{
+ lv_anim_t * a;
+ _LV_LL_READ(LV_GC_ROOT(_lv_anim_ll), a) {
+ if(a->var == var && a->exec_cb == exec_cb) {
+ return a;
+ }
+ }
+
+ return NULL;
+}
+
+/**
* Get the number of currently running animations
* @return the number of running animations
*/
@@ -146,9 +175,9 @@ uint16_t lv_anim_count_running(void)
{
uint16_t cnt = 0;
lv_anim_t * a;
- LV_LL_READ(LV_GC_ROOT(_lv_anim_ll), a) cnt++;
+ _LV_LL_READ(LV_GC_ROOT(_lv_anim_ll), a) cnt++;
- return cnt++;
+ return cnt;
}
/**
@@ -158,12 +187,12 @@ uint16_t lv_anim_count_running(void)
* @param end end value of the animation
* @return the required time [ms] for the animation with the given parameters
*/
-uint32_t lv_anim_speed_to_time(uint16_t speed, lv_anim_value_t start, lv_anim_value_t end)
+uint16_t lv_anim_speed_to_time(uint16_t speed, lv_anim_value_t start, lv_anim_value_t end)
{
int32_t d = LV_MATH_ABS((int32_t)start - end);
uint32_t time = (int32_t)((int32_t)(d * 1000) / speed);
- if(time > UINT32_MAX) time = UINT32_MAX;
+ if(time > UINT16_MAX) time = UINT16_MAX;
if(time == 0) {
time++;
@@ -173,17 +202,31 @@ uint32_t lv_anim_speed_to_time(uint16_t speed, lv_anim_value_t start, lv_anim_va
}
/**
+ * Manually refresh the state of the animations.
+ * Useful to make the animations running in a blocking process where
+ * `lv_task_handler` can't run for a while.
+ * Shouldn't be used directly because it is called in `lv_refr_now()`.
+ */
+void lv_anim_refr_now(void)
+{
+ anim_task(NULL);
+}
+
+/**
* Calculate the current value of an animation applying linear characteristic
* @param a pointer to an animation
* @return the current value to set
*/
-lv_anim_value_t lv_anim_path_linear(const lv_anim_t * a)
+lv_anim_value_t lv_anim_path_linear(const lv_anim_path_t * path, const lv_anim_t * a)
{
+ LV_UNUSED(path);
+
/*Calculate the current step*/
uint32_t step;
if(a->time == a->act_time) {
step = LV_ANIM_RESOLUTION; /*Use the last value if the time fully elapsed*/
- } else {
+ }
+ else {
step = ((int32_t)a->act_time * LV_ANIM_RESOLUTION) / a->time;
}
@@ -202,8 +245,10 @@ lv_anim_value_t lv_anim_path_linear(const lv_anim_t * a)
* @param a pointer to an animation
* @return the current value to set
*/
-lv_anim_value_t lv_anim_path_ease_in(const lv_anim_t * a)
+lv_anim_value_t lv_anim_path_ease_in(const lv_anim_path_t * path, const lv_anim_t * a)
{
+ LV_UNUSED(path);
+
/*Calculate the current step*/
uint32_t t;
if(a->time == a->act_time)
@@ -211,7 +256,7 @@ lv_anim_value_t lv_anim_path_ease_in(const lv_anim_t * a)
else
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, 1, 1, 1024);
int32_t new_value;
new_value = (int32_t)step * (a->end - a->start);
@@ -226,8 +271,10 @@ lv_anim_value_t lv_anim_path_ease_in(const lv_anim_t * a)
* @param a pointer to an animation
* @return the current value to set
*/
-lv_anim_value_t lv_anim_path_ease_out(const lv_anim_t * a)
+lv_anim_value_t lv_anim_path_ease_out(const lv_anim_path_t * path, const lv_anim_t * a)
{
+ LV_UNUSED(path);
+
/*Calculate the current step*/
uint32_t t;
@@ -236,7 +283,7 @@ lv_anim_value_t lv_anim_path_ease_out(const lv_anim_t * a)
else
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, 1023, 1023, 1024);
int32_t new_value;
new_value = (int32_t)step * (a->end - a->start);
@@ -251,8 +298,10 @@ lv_anim_value_t lv_anim_path_ease_out(const lv_anim_t * a)
* @param a pointer to an animation
* @return the current value to set
*/
-lv_anim_value_t lv_anim_path_ease_in_out(const lv_anim_t * a)
+lv_anim_value_t lv_anim_path_ease_in_out(const lv_anim_path_t * path, const lv_anim_t * a)
{
+ LV_UNUSED(path);
+
/*Calculate the current step*/
uint32_t t;
@@ -261,7 +310,7 @@ lv_anim_value_t lv_anim_path_ease_in_out(const lv_anim_t * a)
else
t = (uint32_t)((uint32_t)a->act_time * 1024) / a->time;
- int32_t step = lv_bezier3(t, 0, 100, 924, 1024);
+ int32_t step = _lv_bezier3(t, 0, 100, 924, 1024);
int32_t new_value;
new_value = (int32_t)step * (a->end - a->start);
@@ -276,8 +325,10 @@ lv_anim_value_t lv_anim_path_ease_in_out(const lv_anim_t * a)
* @param a pointer to an animation
* @return the current value to set
*/
-lv_anim_value_t lv_anim_path_overshoot(const lv_anim_t * a)
+lv_anim_value_t lv_anim_path_overshoot(const lv_anim_path_t * path, const lv_anim_t * a)
{
+ LV_UNUSED(path);
+
/*Calculate the current step*/
uint32_t t;
@@ -286,7 +337,7 @@ lv_anim_value_t lv_anim_path_overshoot(const lv_anim_t * a)
else
t = (uint32_t)((uint32_t)a->act_time * 1024) / a->time;
- int32_t step = lv_bezier3(t, 0, 600, 1300, 1024);
+ int32_t step = _lv_bezier3(t, 0, 1000, 1300, 1024);
int32_t new_value;
new_value = (int32_t)step * (a->end - a->start);
@@ -301,10 +352,12 @@ lv_anim_value_t lv_anim_path_overshoot(const lv_anim_t * a)
* @param a pointer to an animation
* @return the current value to set
*/
-lv_anim_value_t lv_anim_path_bounce(const lv_anim_t * a)
+lv_anim_value_t lv_anim_path_bounce(const lv_anim_path_t * path, const lv_anim_t * a)
{
+ LV_UNUSED(path);
+
/*Calculate the current step*/
- uint32_t t;
+ int32_t t;
if(a->time == a->act_time)
t = 1024;
else
@@ -317,33 +370,38 @@ lv_anim_value_t lv_anim_path_bounce(const lv_anim_t * a)
if(t < 408) {
/*Go down*/
t = (t * 2500) >> 10; /*[0..1024] range*/
- } else if(t >= 408 && t < 614) {
+ }
+ else if(t >= 408 && t < 614) {
/*First bounce back*/
t -= 408;
t = t * 5; /*to [0..1024] range*/
t = 1024 - t;
- diff = diff / 6;
- } else if(t >= 614 && t < 819) {
+ diff = diff / 20;
+ }
+ else if(t >= 614 && t < 819) {
/*Fall back*/
t -= 614;
t = t * 5; /*to [0..1024] range*/
- diff = diff / 6;
- } else if(t >= 819 && t < 921) {
+ diff = diff / 20;
+ }
+ else if(t >= 819 && t < 921) {
/*Second bounce back*/
t -= 819;
t = t * 10; /*to [0..1024] range*/
t = 1024 - t;
- diff = diff / 16;
- } else if(t >= 921 && t <= 1024) {
+ diff = diff / 40;
+ }
+ else if(t >= 921 && t <= 1024) {
/*Fall back*/
t -= 921;
t = t * 10; /*to [0..1024] range*/
- diff = diff / 16;
+ diff = diff / 40;
}
if(t > 1024) t = 1024;
+ if(t < 0) t = 0;
- int32_t step = lv_bezier3(t, 1024, 1024, 800, 0);
+ int32_t step = _lv_bezier3(t, 1024, 800, 500, 0);
int32_t new_value;
new_value = (int32_t)step * diff;
@@ -359,8 +417,10 @@ lv_anim_value_t lv_anim_path_bounce(const lv_anim_t * a)
* @param a pointer to an animation
* @return the current value to set
*/
-lv_anim_value_t lv_anim_path_step(const lv_anim_t * a)
+lv_anim_value_t lv_anim_path_step(const lv_anim_path_t * path, const lv_anim_t * a)
{
+ LV_UNUSED(path);
+
if(a->act_time >= a->time)
return a->end;
else
@@ -380,14 +440,13 @@ static void anim_task(lv_task_t * param)
(void)param;
lv_anim_t * a;
- LV_LL_READ(LV_GC_ROOT(_lv_anim_ll), a)
- {
+ _LV_LL_READ(LV_GC_ROOT(_lv_anim_ll), a) {
a->has_run = 0;
}
uint32_t elaps = lv_tick_elaps(last_task_run);
- a = lv_ll_get_head(&LV_GC_ROOT(_lv_anim_ll));
+ a = _lv_ll_get_head(&LV_GC_ROOT(_lv_anim_ll));
while(a != NULL) {
/*It can be set by `lv_anim_del()` typically in `end_cb`. If set then an animation delete
@@ -397,16 +456,26 @@ static void anim_task(lv_task_t * param)
anim_list_changed = false;
if(!a->has_run) {
- a->has_run = 1; /*The list readying might be reseted so need to know which anim has run already*/
+ a->has_run = 1; /*The list readying might be reset so need to know which anim has run already*/
+
+ /*The animation will run now for the first time. Call `start_cb`*/
+ int32_t new_act_time = a->act_time + elaps;
+ if(a->act_time <= 0 && new_act_time >= 0) {
+ if(a->start_cb) a->start_cb(a);
+ }
a->act_time += elaps;
if(a->act_time >= 0) {
if(a->act_time > a->time) a->act_time = a->time;
int32_t new_value;
- new_value = a->path_cb(a);
+ if(a->path.cb) new_value = a->path.cb(&a->path, a);
+ else new_value = lv_anim_path_linear(&a->path, a);
- /*Apply the calculated value*/
- if(a->exec_cb) a->exec_cb(a->var, new_value);
+ if(new_value != a->current) {
+ a->current = new_value;
+ /*Apply the calculated value*/
+ if(a->exec_cb) a->exec_cb(a->var, new_value);
+ }
/*If the time is elapsed the animation is ready*/
if(a->act_time >= a->time) {
@@ -418,9 +487,9 @@ static void anim_task(lv_task_t * param)
/* If the linked list changed due to anim. delete then it's not safe to continue
* the reading of the list from here -> start from the head*/
if(anim_list_changed)
- a = lv_ll_get_head(&LV_GC_ROOT(_lv_anim_ll));
+ a = _lv_ll_get_head(&LV_GC_ROOT(_lv_anim_ll));
else
- a = lv_ll_get_next(&LV_GC_ROOT(_lv_anim_ll), a);
+ a = _lv_ll_get_next(&LV_GC_ROOT(_lv_anim_ll), a);
}
last_task_run = lv_tick_get();
@@ -430,34 +499,39 @@ static void anim_task(lv_task_t * param)
* Called when an animation is ready to do the necessary thinks
* e.g. repeat, play back, delete etc.
* @param a pointer to an animation descriptor
- * @return true: animation delete occurred nnd the `LV_GC_ROOT(_lv_anim_ll)` has changed
+ * @return true: animation delete occurred and the `LV_GC_ROOT(_lv_anim_ll)` has changed
* */
static bool anim_ready_handler(lv_anim_t * a)
{
+ /*In the end of a forward anim decrement repeat cnt.*/
+ if(a->playback_now == 0 && a->repeat_cnt > 0 && a->repeat_cnt != LV_ANIM_REPEAT_INFINITE) {
+ a->repeat_cnt--;
+ }
/*Delete the animation if
- * - no repeat and no play back (simple one shot animation)
+ * - no repeat left and no play back (simple one shot animation)
* - no repeat, play back is enabled and play back is ready */
- if((a->repeat == 0 && a->playback == 0) || (a->repeat == 0 && a->playback == 1 && a->playback_now == 1)) {
+ if(a->repeat_cnt == 0 && ((a->playback_time == 0) || (a->playback_time && a->playback_now == 1))) {
/*Create copy from the animation and delete the animation from the list.
* This way the `ready_cb` will see the animations like it's animation is ready deleted*/
lv_anim_t a_tmp;
- memcpy(&a_tmp, a, sizeof(lv_anim_t));
- lv_ll_rem(&LV_GC_ROOT(_lv_anim_ll), a);
+ _lv_memcpy(&a_tmp, a, sizeof(lv_anim_t));
+ _lv_ll_remove(&LV_GC_ROOT(_lv_anim_ll), a);
lv_mem_free(a);
- anim_list_changed = true;
+ /*Flag that the list has changed */
+ anim_mark_list_change();
/* Call the callback function at the end*/
if(a_tmp.ready_cb != NULL) a_tmp.ready_cb(&a_tmp);
}
/*If the animation is not deleted then restart it*/
else {
- a->act_time = -a->repeat_pause; /*Restart the animation*/
+ a->act_time = -(int32_t)(a->repeat_delay); /*Restart the animation*/
/*Swap the start and end values in play back mode*/
- if(a->playback != 0) {
+ if(a->playback_time != 0) {
/*If now turning back use the 'playback_pause*/
- if(a->playback_now == 0) a->act_time = -a->playback_pause;
+ if(a->playback_now == 0) a->act_time = -(int32_t)(a->playback_delay);
/*Toggle the play back state*/
a->playback_now = a->playback_now == 0 ? 1 : 0;
@@ -466,9 +540,19 @@ static bool anim_ready_handler(lv_anim_t * a)
tmp = a->start;
a->start = a->end;
a->end = tmp;
+
+ a->time = a->playback_now == 0 ? a->time_orig : a->playback_time;
}
}
return anim_list_changed;
}
+static void anim_mark_list_change(void)
+{
+ anim_list_changed = true;
+ if(_lv_ll_get_head(&LV_GC_ROOT(_lv_anim_ll)) == NULL)
+ lv_task_set_prio(_lv_anim_task, LV_TASK_PRIO_OFF);
+ else
+ lv_task_set_prio(_lv_anim_task, LV_ANIM_TASK_PRIO);
+}
#endif
diff --git a/src/libs/lvgl/src/lv_misc/lv_anim.h b/src/libs/lvgl/src/lv_misc/lv_anim.h
index b43035aa..54baf596 100644
--- a/src/libs/lvgl/src/lv_misc/lv_anim.h
+++ b/src/libs/lvgl/src/lv_misc/lv_anim.h
@@ -13,15 +13,12 @@ extern "C" {
/*********************
* INCLUDES
*********************/
-#ifdef LV_CONF_INCLUDE_SIMPLE
-#include "lv_conf.h"
-#else
-#include "../../../lv_conf.h"
-#endif
+#include "../lv_conf_internal.h"
#include <stdint.h>
#include <stdbool.h>
#include <string.h>
+#include "lv_mem.h"
/*********************
* DEFINES
@@ -44,7 +41,17 @@ typedef lv_coord_t lv_anim_value_t;
#if LV_USE_ANIMATION
+#define LV_ANIM_REPEAT_INFINITE 0xFFFF
+
struct _lv_anim_t;
+struct _lv_anim_path_t;
+/** Get the current value during an animation*/
+typedef lv_anim_value_t (*lv_anim_path_cb_t)(const struct _lv_anim_path_t *, const struct _lv_anim_t *);
+
+typedef struct _lv_anim_path_t {
+ lv_anim_path_cb_t cb;
+ void * user_data;
+} lv_anim_path_t;
/** Generic prototype of "animator" functions.
* First parameter is the variable to animate.
@@ -58,37 +65,39 @@ typedef void (*lv_anim_exec_xcb_t)(void *, lv_anim_value_t);
* It's more consistent but less convenient. Might be used by binding generator functions.*/
typedef void (*lv_anim_custom_exec_cb_t)(struct _lv_anim_t *, lv_anim_value_t);
-/** Get the current value during an animation*/
-typedef lv_anim_value_t (*lv_anim_path_cb_t)(const struct _lv_anim_t *);
-
/** Callback to call when the animation is ready*/
typedef void (*lv_anim_ready_cb_t)(struct _lv_anim_t *);
+/** Callback to call when the animation really stars (considering `delay`)*/
+typedef void (*lv_anim_start_cb_t)(struct _lv_anim_t *);
+
/** Describes an animation*/
-typedef struct _lv_anim_t
-{
+typedef struct _lv_anim_t {
void * var; /**<Variable to animate*/
lv_anim_exec_xcb_t exec_cb; /**< Function to execute to animate*/
- lv_anim_path_cb_t path_cb; /**< Function to get the steps of animations*/
+ lv_anim_start_cb_t start_cb; /**< Call it when the animation is starts (considering `delay`)*/
lv_anim_ready_cb_t ready_cb; /**< Call it when the animation is ready*/
+ lv_anim_path_t path; /**< Describe the path (curve) of animations*/
int32_t start; /**< Start value*/
+ int32_t current; /**< Current value */
int32_t end; /**< End value*/
- uint32_t time; /**< Animation time in ms*/
+ int32_t time; /**< Animation time in ms*/
int32_t act_time; /**< Current time in animation. Set to negative to make delay.*/
- uint16_t playback_pause; /**< Wait before play back*/
- uint16_t repeat_pause; /**< Wait before repeat*/
+ uint32_t playback_delay; /**< Wait before play back*/
+ uint32_t playback_time; /**< Duration of playback animation*/
+ uint32_t repeat_delay; /**< Wait before repeat*/
+ uint16_t repeat_cnt; /**< Repeat count for the animation*/
+ uint8_t early_apply : 1; /**< 1: Apply start value immediately even is there is `delay` */
#if LV_USE_USER_DATA
lv_anim_user_data_t user_data; /**< Custom user data*/
#endif
- uint8_t playback : 1; /**< When the animation is ready play it back*/
- uint8_t repeat : 1; /**< Repeat the animation infinitely*/
/*Animation system use these - user shouldn't set*/
+ uint32_t time_orig;
uint8_t playback_now : 1; /**< Play back is in progress*/
uint32_t has_run : 1; /**< Indicates the animation has run in this round*/
} lv_anim_t;
-
/**********************
* GLOBAL PROTOTYPES
**********************/
@@ -96,7 +105,7 @@ typedef struct _lv_anim_t
/**
* Init. the animation module
*/
-void lv_anim_core_init(void);
+void _lv_anim_core_init(void);
/**
* Initialize an animation variable.
@@ -104,35 +113,50 @@ void lv_anim_core_init(void);
* lv_anim_t a;
* lv_anim_init(&a);
* lv_anim_set_...(&a);
- * lv_anim_create(&a);
* @param a pointer to an `lv_anim_t` variable to initialize
*/
void lv_anim_init(lv_anim_t * a);
/**
- * Set a variable to animate function to execute on `var`
+ * Set a variable to animate
* @param a pointer to an initialized `lv_anim_t` variable
* @param var pointer to a variable to animate
- * @param exec_cb a function to execute.
+ */
+static inline void lv_anim_set_var(lv_anim_t * a, void * var)
+{
+ a->var = var;
+}
+
+/**
+ * Set a function to animate `var`
+ * @param a pointer to an initialized `lv_anim_t` variable
+ * @param exec_cb a function to execute during animation
* LittelvGL's built-in functions can be used.
* E.g. lv_obj_set_x
*/
-static inline void lv_anim_set_exec_cb(lv_anim_t * a, void * var, lv_anim_exec_xcb_t exec_cb)
+static inline void lv_anim_set_exec_cb(lv_anim_t * a, lv_anim_exec_xcb_t exec_cb)
{
- a->var = var;
a->exec_cb = exec_cb;
}
/**
- * Set the duration and delay of an animation
+ * Set the duration of an animation
* @param a pointer to an initialized `lv_anim_t` variable
* @param duration duration of the animation in milliseconds
- * @param delay delay before the animation in milliseconds
*/
-static inline void lv_anim_set_time(lv_anim_t * a, uint16_t duration, int16_t delay)
+static inline void lv_anim_set_time(lv_anim_t * a, uint32_t duration)
{
a->time = duration;
- a->act_time = (int16_t)(-delay);
+}
+
+/**
+ * Set a delay before starting the animation
+ * @param a pointer to an initialized `lv_anim_t` variable
+ * @param delay delay before the animation in milliseconds
+ */
+static inline void lv_anim_set_delay(lv_anim_t * a, uint32_t delay)
+{
+ a->act_time = -(int32_t)(delay);
}
/**
@@ -144,14 +168,16 @@ static inline void lv_anim_set_time(lv_anim_t * a, uint16_t duration, int16_t de
static inline void lv_anim_set_values(lv_anim_t * a, lv_anim_value_t start, lv_anim_value_t end)
{
a->start = start;
+ a->current = start;
a->end = end;
}
/**
- * Similar to `lv_anim_set_var_and_cb` but `lv_anim_custom_exec_cb_t` receives
+ * Similar to `lv_anim_set_exec_cb` but `lv_anim_custom_exec_cb_t` receives
* `lv_anim_t * ` as its first parameter instead of `void *`.
- * This function might be used when LittlevGL is binded to other languages because
+ * This function might be used when LVGL is binded to other languages because
* it's more consistent to have `lv_anim_t *` as first parameter.
+ * The variable to animate can be stored in the animation's `user_sata`
* @param a pointer to an initialized `lv_anim_t` variable
* @param exec_cb a function to execute.
*/
@@ -167,9 +193,19 @@ static inline void lv_anim_set_custom_exec_cb(lv_anim_t * a, lv_anim_custom_exec
* @param path_cb a function the get the current value of the animation.
* The built in functions starts with `lv_anim_path_...`
*/
-static inline void lv_anim_set_path_cb(lv_anim_t * a, lv_anim_path_cb_t path_cb)
+static inline void lv_anim_set_path(lv_anim_t * a, const lv_anim_path_t * path)
+{
+ _lv_memcpy_small(&a->path, path, sizeof(lv_anim_path_t));
+}
+
+/**
+ * Set a function call when the animation really starts (considering `delay`)
+ * @param a pointer to an initialized `lv_anim_t` variable
+ * @param start_cb a function call when the animation starts
+ */
+static inline void lv_anim_set_start_cb(lv_anim_t * a, lv_anim_ready_cb_t start_cb)
{
- a->path_cb = path_cb;
+ a->start_cb = start_cb;
}
/**
@@ -185,48 +221,87 @@ static inline void lv_anim_set_ready_cb(lv_anim_t * a, lv_anim_ready_cb_t ready_
/**
* Make the animation to play back to when the forward direction is ready
* @param a pointer to an initialized `lv_anim_t` variable
- * @param wait_time time in milliseconds to wait before starting the back direction
+ * @param time the duration of the playback animation in in milliseconds. 0: disable playback
*/
-static inline void lv_anim_set_playback(lv_anim_t * a, uint16_t wait_time)
+static inline void lv_anim_set_playback_time(lv_anim_t * a, uint16_t time)
{
- a->playback = 1;
- a->playback_pause = wait_time;
+ a->playback_time = time;
}
/**
- * Disable playback. (Disabled after `lv_anim_init()`)
+ * Make the animation to play back to when the forward direction is ready
* @param a pointer to an initialized `lv_anim_t` variable
+ * @param delay delay in milliseconds before starting the playback animation.
*/
-static inline void lv_anim_clear_playback(lv_anim_t * a)
+static inline void lv_anim_set_playback_delay(lv_anim_t * a, uint16_t delay)
{
- a->playback = 0;
+ a->playback_delay = delay;
}
/**
- * Make the animation to start again when ready.
+ * Make the animation repeat itself.
* @param a pointer to an initialized `lv_anim_t` variable
- * @param wait_time time in milliseconds to wait before starting the animation again
+ * @param cnt repeat count or `LV_ANIM_REPEAT_INFINITE` for infinite repetition. 0: to disable repetition.
*/
-static inline void lv_anim_set_repeat(lv_anim_t * a, uint16_t wait_time)
+static inline void lv_anim_set_repeat_count(lv_anim_t * a, uint16_t cnt)
{
- a->repeat = 1;
- a->repeat_pause = wait_time;
+ a->repeat_cnt = cnt;
}
/**
- * Disable repeat. (Disabled after `lv_anim_init()`)
+ * Set a delay before repeating the animation.
* @param a pointer to an initialized `lv_anim_t` variable
+ * @param delay delay in milliseconds before repeating the animation.
*/
-static inline void lv_anim_clear_repeat(lv_anim_t * a)
+static inline void lv_anim_set_repeat_delay(lv_anim_t * a, uint16_t delay)
{
- a->repeat = 0;
+ a->repeat_delay = delay;
}
/**
* Create an animation
* @param a an initialized 'anim_t' variable. Not required after call.
*/
-void lv_anim_create(lv_anim_t * a);
+void lv_anim_start(lv_anim_t * a);
+
+/**
+ * Initialize an animation path
+ * @param path pointer to path
+ */
+static inline void lv_anim_path_init(lv_anim_path_t * path)
+{
+ _lv_memset_00(path, sizeof(lv_anim_path_t));
+}
+
+/**
+ * Set a callback for a path
+ * @param path pointer to an initialized path
+ * @param cb the callback
+ */
+static inline void lv_anim_path_set_cb(lv_anim_path_t * path, lv_anim_path_cb_t cb)
+{
+ path->cb = cb;
+}
+
+/**
+ * Set a user data for a path
+ * @param path pointer to an initialized path
+ * @param user_data pointer to the user data
+ */
+static inline void lv_anim_path_set_user_data(lv_anim_path_t * path, void * user_data)
+{
+ path->user_data = user_data;
+}
+
+/**
+ * Get a delay before starting the animation
+ * @param a pointer to an initialized `lv_anim_t` variable
+ * @return delay before the animation in milliseconds
+ */
+static inline int32_t lv_anim_get_delay(lv_anim_t * a)
+{
+ return -a->act_time;
+}
/**
* Delete an animation of a variable with a given animator function
@@ -238,11 +313,20 @@ void lv_anim_create(lv_anim_t * a);
bool lv_anim_del(void * var, lv_anim_exec_xcb_t exec_cb);
/**
- * Delete an aniamation by getting the animated variable from `a`.
+ * Get the animation of a variable and its `exec_cb`.
+ * @param var pointer to variable
+ * @param exec_cb a function pointer which is animating 'var',
+ * or NULL to delete all the animations of 'var'
+ * @return pointer to the animation.
+ */
+lv_anim_t * lv_anim_get(void * var, lv_anim_exec_xcb_t exec_cb);
+
+/**
+ * Delete an animation by getting the animated variable from `a`.
* Only animations with `exec_cb` will be deleted.
- * This function exist becasue it's logical that all anim functions receives an
- * `lv_anim_t` as their first parameter. It's not practical in C but might makes
- * the API more conequent and makes easier to genrate bindings.
+ * This function exists because it's logical that all anim. functions receives an
+ * `lv_anim_t` as their first parameter. It's not practical in C but might make
+ * the API more consequent and makes easier to generate bindings.
* @param a pointer to an animation.
* @param exec_cb a function pointer which is animating 'var',
* or NULL to ignore it and delete all the animations of 'var
@@ -266,49 +350,57 @@ uint16_t lv_anim_count_running(void);
* @param end end value of the animation
* @return the required time [ms] for the animation with the given parameters
*/
-uint32_t lv_anim_speed_to_time(uint16_t speed, lv_anim_value_t start, lv_anim_value_t end);
+uint16_t lv_anim_speed_to_time(uint16_t speed, lv_anim_value_t start, lv_anim_value_t end);
+
+/**
+ * Manually refresh the state of the animations.
+ * Useful to make the animations running in a blocking process where
+ * `lv_task_handler` can't run for a while.
+ * Shouldn't be used directly because it is called in `lv_refr_now()`.
+ */
+void lv_anim_refr_now(void);
/**
* Calculate the current value of an animation applying linear characteristic
* @param a pointer to an animation
* @return the current value to set
*/
-lv_anim_value_t lv_anim_path_linear(const lv_anim_t * a);
+lv_anim_value_t lv_anim_path_linear(const lv_anim_path_t * path, const lv_anim_t * a);
/**
* Calculate the current value of an animation slowing down the start phase
* @param a pointer to an animation
* @return the current value to set
*/
-lv_anim_value_t lv_anim_path_ease_in(const lv_anim_t * a);
+lv_anim_value_t lv_anim_path_ease_in(const lv_anim_path_t * path, const lv_anim_t * a);
/**
* Calculate the current value of an animation slowing down the end phase
* @param a pointer to an animation
* @return the current value to set
*/
-lv_anim_value_t lv_anim_path_ease_out(const lv_anim_t * a);
+lv_anim_value_t lv_anim_path_ease_out(const lv_anim_path_t * path, const lv_anim_t * a);
/**
* Calculate the current value of an animation applying an "S" characteristic (cosine)
* @param a pointer to an animation
* @return the current value to set
*/
-lv_anim_value_t lv_anim_path_ease_in_out(const lv_anim_t * a);
+lv_anim_value_t lv_anim_path_ease_in_out(const lv_anim_path_t * path, const lv_anim_t * a);
/**
* Calculate the current value of an animation with overshoot at the end
* @param a pointer to an animation
* @return the current value to set
*/
-lv_anim_value_t lv_anim_path_overshoot(const lv_anim_t * a);
+lv_anim_value_t lv_anim_path_overshoot(const lv_anim_path_t * path, const lv_anim_t * a);
/**
* Calculate the current value of an animation with 3 bounces
* @param a pointer to an animation
* @return the current value to set
*/
-lv_anim_value_t lv_anim_path_bounce(const lv_anim_t * a);
+lv_anim_value_t lv_anim_path_bounce(const lv_anim_path_t * path, const lv_anim_t * a);
/**
* Calculate the current value of an animation applying step characteristic.
@@ -316,7 +408,12 @@ lv_anim_value_t lv_anim_path_bounce(const lv_anim_t * a);
* @param a pointer to an animation
* @return the current value to set
*/
-lv_anim_value_t lv_anim_path_step(const lv_anim_t * a);
+lv_anim_value_t lv_anim_path_step(const lv_anim_path_t * path, const lv_anim_t * a);
+
+/**********************
+ * GLOBAL VARIABLES
+ **********************/
+extern const lv_anim_path_t lv_anim_path_def;
/**********************
* MACROS
diff --git a/src/libs/lvgl/src/lv_misc/lv_area.c b/src/libs/lvgl/src/lv_misc/lv_area.c
index de649c5b..0fea6832 100644
--- a/src/libs/lvgl/src/lv_misc/lv_area.c
+++ b/src/libs/lvgl/src/lv_misc/lv_area.c
@@ -6,11 +6,7 @@
/*********************
* INCLUDES
*********************/
-#ifdef LV_CONF_INCLUDE_SIMPLE
-#include "lv_conf.h"
-#else
-#include "../../../lv_conf.h"
-#endif
+#include "../lv_conf_internal.h"
#include "lv_area.h"
#include "lv_math.h"
@@ -27,6 +23,8 @@
* STATIC PROTOTYPES
**********************/
+static bool lv_point_within_circle(const lv_area_t * area, const lv_point_t * p);
+
/**********************
* STATIC VARIABLES
**********************/
@@ -81,7 +79,7 @@ void lv_area_set_height(lv_area_t * area_p, lv_coord_t h)
* @param x the new x coordinate of the area
* @param y the new y coordinate of the area
*/
-void lv_area_set_pos(lv_area_t * area_p, lv_coord_t x, lv_coord_t y)
+void _lv_area_set_pos(lv_area_t * area_p, lv_coord_t x, lv_coord_t y)
{
lv_coord_t w = lv_area_get_width(area_p);
lv_coord_t h = lv_area_get_height(area_p);
@@ -112,7 +110,7 @@ uint32_t lv_area_get_size(const lv_area_t * area_p)
* @param a2_p pointer to the second area
* @return false: the two area has NO common parts, res_p is invalid
*/
-bool lv_area_intersect(lv_area_t * res_p, const lv_area_t * a1_p, const lv_area_t * a2_p)
+bool _lv_area_intersect(lv_area_t * res_p, const lv_area_t * a1_p, const lv_area_t * a2_p)
{
/* Get the smaller area from 'a1_p' and 'a2_p' */
res_p->x1 = LV_MATH_MAX(a1_p->x1, a2_p->x1);
@@ -134,7 +132,7 @@ bool lv_area_intersect(lv_area_t * res_p, const lv_area_t * a1_p, const lv_area_
* @param a1_p pointer to the first area
* @param a2_p pointer to the second area
*/
-void lv_area_join(lv_area_t * a_res_p, const lv_area_t * a1_p, const lv_area_t * a2_p)
+void _lv_area_join(lv_area_t * a_res_p, const lv_area_t * a1_p, const lv_area_t * a2_p)
{
a_res_p->x1 = LV_MATH_MIN(a1_p->x1, a2_p->x1);
a_res_p->y1 = LV_MATH_MIN(a1_p->y1, a2_p->y1);
@@ -146,17 +144,67 @@ void lv_area_join(lv_area_t * a_res_p, const lv_area_t * a1_p, const lv_area_t *
* Check if a point is on an area
* @param a_p pointer to an area
* @param p_p pointer to a point
+ * @param radius radius of area (e.g. for rounded rectangle)
* @return false:the point is out of the area
*/
-bool lv_area_is_point_on(const lv_area_t * a_p, const lv_point_t * p_p)
+bool _lv_area_is_point_on(const lv_area_t * a_p, const lv_point_t * p_p, lv_coord_t radius)
{
- bool is_on = false;
-
+ /*First check the basic area*/
+ bool is_on_rect = false;
if((p_p->x >= a_p->x1 && p_p->x <= a_p->x2) && ((p_p->y >= a_p->y1 && p_p->y <= a_p->y2))) {
- is_on = true;
+ is_on_rect = true;
+ }
+ if(!is_on_rect)
+ return false;
+ /*Now handle potential rounded rectangles*/
+ if(radius <= 0) {
+ /*No radius, it is within the rectangle*/
+ return true;
}
+ lv_coord_t w = lv_area_get_width(a_p) / 2;
+ lv_coord_t h = lv_area_get_height(a_p) / 2;
+ lv_coord_t max_radius = LV_MATH_MIN(w, h);
+ if(radius > max_radius)
+ radius = max_radius;
- return is_on;
+ /*Check if it's in one of the corners*/
+ lv_area_t corner_area;
+ /*Top left*/
+ corner_area.x1 = a_p->x1;
+ corner_area.x2 = a_p->x1 + radius;
+ corner_area.y1 = a_p->y1;
+ corner_area.y2 = a_p->y1 + radius;
+ if(_lv_area_is_point_on(&corner_area, p_p, 0)) {
+ corner_area.x2 += radius;
+ corner_area.y2 += radius;
+ return lv_point_within_circle(&corner_area, p_p);
+ }
+ /*Bottom left*/
+ corner_area.y1 = a_p->y2 - radius;
+ corner_area.y2 = a_p->y2;
+ if(_lv_area_is_point_on(&corner_area, p_p, 0)) {
+ corner_area.x2 += radius;
+ corner_area.y1 -= radius;
+ return lv_point_within_circle(&corner_area, p_p);
+ }
+ /*Bottom right*/
+ corner_area.x1 = a_p->x2 - radius;
+ corner_area.x2 = a_p->x2;
+ if(_lv_area_is_point_on(&corner_area, p_p, 0)) {
+ corner_area.x1 -= radius;
+ corner_area.y1 -= radius;
+ return lv_point_within_circle(&corner_area, p_p);
+ }
+ /*Top right*/
+ corner_area.y1 = a_p->y1;
+ corner_area.y2 = a_p->y1 + radius;
+ if(_lv_area_is_point_on(&corner_area, p_p, 0)) {
+ corner_area.x1 -= radius;
+ corner_area.y2 += radius;
+ return lv_point_within_circle(&corner_area, p_p);
+ }
+ /*Not within corners*/
+ return true;
}
/**
@@ -165,11 +213,12 @@ bool lv_area_is_point_on(const lv_area_t * a_p, const lv_point_t * p_p)
* @param a2_p pointer to an other area
* @return false: a1_p and a2_p has no common parts
*/
-bool lv_area_is_on(const lv_area_t * a1_p, const lv_area_t * a2_p)
+bool _lv_area_is_on(const lv_area_t * a1_p, const lv_area_t * a2_p)
{
if((a1_p->x1 <= a2_p->x2) && (a1_p->x2 >= a2_p->x1) && (a1_p->y1 <= a2_p->y2) && (a1_p->y2 >= a2_p->y1)) {
return true;
- } else {
+ }
+ else {
return false;
}
}
@@ -177,10 +226,11 @@ bool lv_area_is_on(const lv_area_t * a1_p, const lv_area_t * a2_p)
/**
* Check if an area is fully on an other
* @param ain_p pointer to an area which could be in 'aholder_p'
- * @param aholder pointer to an area which could involve 'ain_p'
- * @return
+ * @param aholder_p pointer to an area which could involve 'ain_p'
+ * @param radius radius of `aholder_p` (e.g. for rounded rectangle)
+ * @return true: `ain_p` is fully inside `aholder_p`
*/
-bool lv_area_is_in(const lv_area_t * ain_p, const lv_area_t * aholder_p)
+bool _lv_area_is_in(const lv_area_t * ain_p, const lv_area_t * aholder_p, lv_coord_t radius)
{
bool is_in = false;
@@ -189,22 +239,171 @@ bool lv_area_is_in(const lv_area_t * ain_p, const lv_area_t * aholder_p)
is_in = true;
}
- return is_in;
+ if(!is_in) return false;
+ if(radius == 0) return true;
+
+ /*Check if the corner points are inside the radius or not*/
+ lv_point_t p;
+
+ p.x = ain_p->x1;
+ p.y = ain_p->y1;
+ if(_lv_area_is_point_on(aholder_p, &p, radius) == false) return false;
+
+ p.x = ain_p->x2;
+ p.y = ain_p->y1;
+ if(_lv_area_is_point_on(aholder_p, &p, radius) == false) return false;
+
+ p.x = ain_p->x1;
+ p.y = ain_p->y2;
+ if(_lv_area_is_point_on(aholder_p, &p, radius) == false) return false;
+
+ p.x = ain_p->x2;
+ p.y = ain_p->y2;
+ if(_lv_area_is_point_on(aholder_p, &p, radius) == false) return false;
+
+ return true;
}
/**
- * Increment or decrement an area's size by a single amount
- * @param a_p pointer to an area to grow
- * @param amount amount to increment the area, or negative to decrement
+ * Align an area to an other
+ * @param base an are where the other will be aligned
+ * @param to_align the area to align
+ * @param align `LV_ALIGN_...`
+ * @param res x/y coordinates where `to_align` align area should be placed
*/
-void lv_area_increment(lv_area_t * a_p, const lv_coord_t amount)
+void _lv_area_align(const lv_area_t * base, const lv_area_t * to_align, lv_align_t align, lv_point_t * res)
{
- a_p->x1 -= amount;
- a_p->y1 -= amount;
- a_p->x2 += amount;
- a_p->y2 += amount;
+
+ switch(align) {
+ case LV_ALIGN_CENTER:
+ res->x = lv_area_get_width(base) / 2 - lv_area_get_width(to_align) / 2;
+ res->y = lv_area_get_height(base) / 2 - lv_area_get_height(to_align) / 2;
+ break;
+
+ case LV_ALIGN_IN_TOP_LEFT:
+ res->x = 0;
+ res->y = 0;
+ break;
+ case LV_ALIGN_IN_TOP_MID:
+ res->x = lv_area_get_width(base) / 2 - lv_area_get_width(to_align) / 2;
+ res->y = 0;
+ break;
+
+ case LV_ALIGN_IN_TOP_RIGHT:
+ res->x = lv_area_get_width(base) - lv_area_get_width(to_align);
+ res->y = 0;
+ break;
+
+ case LV_ALIGN_IN_BOTTOM_LEFT:
+ res->x = 0;
+ res->y = lv_area_get_height(base) - lv_area_get_height(to_align);
+ break;
+ case LV_ALIGN_IN_BOTTOM_MID:
+ res->x = lv_area_get_width(base) / 2 - lv_area_get_width(to_align) / 2;
+ res->y = lv_area_get_height(base) - lv_area_get_height(to_align);
+ break;
+
+ case LV_ALIGN_IN_BOTTOM_RIGHT:
+ res->x = lv_area_get_width(base) - lv_area_get_width(to_align);
+ res->y = lv_area_get_height(base) - lv_area_get_height(to_align);
+ break;
+
+ case LV_ALIGN_IN_LEFT_MID:
+ res->x = 0;
+ res->y = lv_area_get_height(base) / 2 - lv_area_get_height(to_align) / 2;
+ break;
+
+ case LV_ALIGN_IN_RIGHT_MID:
+ res->x = lv_area_get_width(base) - lv_area_get_width(to_align);
+ res->y = lv_area_get_height(base) / 2 - lv_area_get_height(to_align) / 2;
+ break;
+
+ case LV_ALIGN_OUT_TOP_LEFT:
+ res->x = 0;
+ res->y = -lv_area_get_height(to_align);
+ break;
+
+ case LV_ALIGN_OUT_TOP_MID:
+ res->x = lv_area_get_width(base) / 2 - lv_area_get_width(to_align) / 2;
+ res->y = -lv_area_get_height(to_align);
+ break;
+
+ case LV_ALIGN_OUT_TOP_RIGHT:
+ res->x = lv_area_get_width(base) - lv_area_get_width(to_align);
+ res->y = -lv_area_get_height(to_align);
+ break;
+
+ case LV_ALIGN_OUT_BOTTOM_LEFT:
+ res->x = 0;
+ res->y = lv_area_get_height(base);
+ break;
+
+ case LV_ALIGN_OUT_BOTTOM_MID:
+ res->x = lv_area_get_width(base) / 2 - lv_area_get_width(to_align) / 2;
+ res->y = lv_area_get_height(base);
+ break;
+
+ case LV_ALIGN_OUT_BOTTOM_RIGHT:
+ res->x = lv_area_get_width(base) - lv_area_get_width(to_align);
+ res->y = lv_area_get_height(base);
+ break;
+
+ case LV_ALIGN_OUT_LEFT_TOP:
+ res->x = -lv_area_get_width(to_align);
+ res->y = 0;
+ break;
+
+ case LV_ALIGN_OUT_LEFT_MID:
+ res->x = -lv_area_get_width(to_align);
+ res->y = lv_area_get_height(base) / 2 - lv_area_get_height(to_align) / 2;
+ break;
+
+ case LV_ALIGN_OUT_LEFT_BOTTOM:
+ res->x = -lv_area_get_width(to_align);
+ res->y = lv_area_get_height(base) - lv_area_get_height(to_align);
+ break;
+
+ case LV_ALIGN_OUT_RIGHT_TOP:
+ res->x = lv_area_get_width(base);
+ res->y = 0;
+ break;
+
+ case LV_ALIGN_OUT_RIGHT_MID:
+ res->x = lv_area_get_width(base);
+ res->y = lv_area_get_height(base) / 2 - lv_area_get_height(to_align) / 2;
+ break;
+
+ case LV_ALIGN_OUT_RIGHT_BOTTOM:
+ res->x = lv_area_get_width(base);
+ res->y = lv_area_get_height(base) - lv_area_get_height(to_align);
+ break;
+ }
+
+ res->x += base->x1;
+ res->y += base->y1;
}
/**********************
* STATIC FUNCTIONS
**********************/
+
+static bool lv_point_within_circle(const lv_area_t * area, const lv_point_t * p)
+{
+ lv_coord_t r = (area->x2 - area->x1) / 2;
+
+ /* Circle center */
+ lv_coord_t cx = area->x1 + r;
+ lv_coord_t cy = area->y1 + r;
+
+ /*Simplify the code by moving everything to (0, 0) */
+ lv_coord_t px = p->x - cx;
+ lv_coord_t py = p->y - cy;
+
+ uint32_t r_sqrd = r * r;
+ uint32_t dist = (px * px) + (py * py);
+
+ if(dist <= r_sqrd)
+ return true;
+ else
+ return false;
+}
diff --git a/src/libs/lvgl/src/lv_misc/lv_area.h b/src/libs/lvgl/src/lv_misc/lv_area.h
index 211bebd8..6394b73c 100644
--- a/src/libs/lvgl/src/lv_misc/lv_area.h
+++ b/src/libs/lvgl/src/lv_misc/lv_area.h
@@ -13,14 +13,11 @@ extern "C" {
/*********************
* INCLUDES
*********************/
+#include "../lv_conf_internal.h"
#include <string.h>
#include <stdbool.h>
#include <stdint.h>
-#ifdef LV_CONF_INCLUDE_SIMPLE
-#include "lv_conf.h"
-#else
-#include "../../../lv_conf.h"
-#endif
+#include "lv_mem.h"
/*********************
* DEFINES
@@ -39,21 +36,45 @@ LV_EXPORT_CONST_INT(LV_COORD_MIN);
/**
* Represents a point on the screen.
*/
-typedef struct
-{
+typedef struct {
lv_coord_t x;
lv_coord_t y;
} lv_point_t;
/** Represents an area of the screen. */
-typedef struct
-{
+typedef struct {
lv_coord_t x1;
lv_coord_t y1;
lv_coord_t x2;
lv_coord_t y2;
} lv_area_t;
+/** Alignments */
+enum {
+ LV_ALIGN_CENTER = 0,
+ LV_ALIGN_IN_TOP_LEFT,
+ LV_ALIGN_IN_TOP_MID,
+ LV_ALIGN_IN_TOP_RIGHT,
+ LV_ALIGN_IN_BOTTOM_LEFT,
+ LV_ALIGN_IN_BOTTOM_MID,
+ LV_ALIGN_IN_BOTTOM_RIGHT,
+ LV_ALIGN_IN_LEFT_MID,
+ LV_ALIGN_IN_RIGHT_MID,
+ LV_ALIGN_OUT_TOP_LEFT,
+ LV_ALIGN_OUT_TOP_MID,
+ LV_ALIGN_OUT_TOP_RIGHT,
+ LV_ALIGN_OUT_BOTTOM_LEFT,
+ LV_ALIGN_OUT_BOTTOM_MID,
+ LV_ALIGN_OUT_BOTTOM_RIGHT,
+ LV_ALIGN_OUT_LEFT_TOP,
+ LV_ALIGN_OUT_LEFT_MID,
+ LV_ALIGN_OUT_LEFT_BOTTOM,
+ LV_ALIGN_OUT_RIGHT_TOP,
+ LV_ALIGN_OUT_RIGHT_MID,
+ LV_ALIGN_OUT_RIGHT_BOTTOM,
+};
+typedef uint8_t lv_align_t;
+
/**********************
* GLOBAL PROTOTYPES
**********************/
@@ -75,7 +96,7 @@ void lv_area_set(lv_area_t * area_p, lv_coord_t x1, lv_coord_t y1, lv_coord_t x2
*/
inline static void lv_area_copy(lv_area_t * dest, const lv_area_t * src)
{
- memcpy(dest, src, sizeof(lv_area_t));
+ _lv_memcpy_small(dest, src, sizeof(lv_area_t));
}
/**
@@ -118,7 +139,7 @@ void lv_area_set_height(lv_area_t * area_p, lv_coord_t h);
* @param x the new x coordinate of the area
* @param y the new y coordinate of the area
*/
-void lv_area_set_pos(lv_area_t * area_p, lv_coord_t x, lv_coord_t y);
+void _lv_area_set_pos(lv_area_t * area_p, lv_coord_t x, lv_coord_t y);
/**
* Return with area of an area (x * y)
@@ -134,7 +155,7 @@ uint32_t lv_area_get_size(const lv_area_t * area_p);
* @param a2_p pointer to the second area
* @return false: the two area has NO common parts, res_p is invalid
*/
-bool lv_area_intersect(lv_area_t * res_p, const lv_area_t * a1_p, const lv_area_t * a2_p);
+bool _lv_area_intersect(lv_area_t * res_p, const lv_area_t * a1_p, const lv_area_t * a2_p);
/**
* Join two areas into a third which involves the other two
@@ -142,15 +163,16 @@ bool lv_area_intersect(lv_area_t * res_p, const lv_area_t * a1_p, const lv_area_
* @param a1_p pointer to the first area
* @param a2_p pointer to the second area
*/
-void lv_area_join(lv_area_t * a_res_p, const lv_area_t * a1_p, const lv_area_t * a2_p);
+void _lv_area_join(lv_area_t * a_res_p, const lv_area_t * a1_p, const lv_area_t * a2_p);
/**
* Check if a point is on an area
* @param a_p pointer to an area
* @param p_p pointer to a point
+ * @param radius radius of area (e.g. for rounded rectangle)
* @return false:the point is out of the area
*/
-bool lv_area_is_point_on(const lv_area_t * a_p, const lv_point_t * p_p);
+bool _lv_area_is_point_on(const lv_area_t * a_p, const lv_point_t * p_p, lv_coord_t radius);
/**
* Check if two area has common parts
@@ -158,22 +180,25 @@ bool lv_area_is_point_on(const lv_area_t * a_p, const lv_point_t * p_p);
* @param a2_p pointer to an other area
* @return false: a1_p and a2_p has no common parts
*/
-bool lv_area_is_on(const lv_area_t * a1_p, const lv_area_t * a2_p);
+bool _lv_area_is_on(const lv_area_t * a1_p, const lv_area_t * a2_p);
/**
* Check if an area is fully on an other
- * @param ain_p pointer to an area which could be on aholder_p
- * @param aholder pointer to an area which could involve ain_p
- * @return
+ * @param ain_p pointer to an area which could be in 'aholder_p'
+ * @param aholder_p pointer to an area which could involve 'ain_p'
+ * @param radius radius of `aholder_p` (e.g. for rounded rectangle)
+ * @return true: `ain_p` is fully inside `aholder_p`
*/
-bool lv_area_is_in(const lv_area_t * ain_p, const lv_area_t * aholder_p);
+bool _lv_area_is_in(const lv_area_t * ain_p, const lv_area_t * aholder_p, lv_coord_t radius);
/**
- * Increment or decrement an area's size by a single amount
- * @param a_p pointer to an area to grow
- * @param amount amount to increment the area, or negative to decrement
+ * Align an area to an other
+ * @param base an are where the other will be aligned
+ * @param to_align the area to align
+ * @param align `LV_ALIGN_...`
+ * @param res x/y coordinates where `to_align` align area should be placed
*/
-void lv_area_increment(lv_area_t * a_p, const lv_coord_t amount);
+void _lv_area_align(const lv_area_t * base, const lv_area_t * to_align, lv_align_t align, lv_point_t * res);
/**********************
* MACROS
diff --git a/src/libs/lvgl/src/lv_misc/lv_async.c b/src/libs/lvgl/src/lv_misc/lv_async.c
index 2a836432..41ec144a 100644
--- a/src/libs/lvgl/src/lv_misc/lv_async.c
+++ b/src/libs/lvgl/src/lv_misc/lv_async.c
@@ -17,11 +17,16 @@
* TYPEDEFS
**********************/
+typedef struct _lv_async_info_t {
+ lv_async_cb_t cb;
+ void * user_data;
+} lv_async_info_t;
+
/**********************
* STATIC PROTOTYPES
**********************/
-static void lv_async_task_cb(lv_task_t *task);
+static void lv_async_task_cb(lv_task_t * task);
/**********************
* STATIC VARIABLES
@@ -38,26 +43,24 @@ static void lv_async_task_cb(lv_task_t *task);
lv_res_t lv_async_call(lv_async_cb_t async_xcb, void * user_data)
{
/*Allocate an info structure */
- lv_async_info_t *info = lv_mem_alloc(sizeof(lv_async_info_t));
-
+ lv_async_info_t * info = lv_mem_alloc(sizeof(lv_async_info_t));
+
if(info == NULL)
return LV_RES_INV;
-
+
/* Create a new task */
/* Use highest priority so that it will run before a refresh */
- lv_task_t *task = lv_task_create(lv_async_task_cb, 0, LV_TASK_PRIO_HIGHEST, info);
-
+ lv_task_t * task = lv_task_create(lv_async_task_cb, 0, LV_TASK_PRIO_HIGHEST, info);
+
if(task == NULL) {
lv_mem_free(info);
return LV_RES_INV;
}
-
+
info->cb = async_xcb;
info->user_data = user_data;
- /* Set the task's user data */
- task->user_data = info;
- lv_task_once(task);
+ lv_task_set_repeat_count(task, 1);
return LV_RES_OK;
}
@@ -65,11 +68,11 @@ lv_res_t lv_async_call(lv_async_cb_t async_xcb, void * user_data)
* STATIC FUNCTIONS
**********************/
-static void lv_async_task_cb(lv_task_t *task)
+static void lv_async_task_cb(lv_task_t * task)
{
- lv_async_info_t *info = (lv_async_info_t *)task->user_data;
-
+ lv_async_info_t * info = (lv_async_info_t *)task->user_data;
+
info->cb(info->user_data);
-
+
lv_mem_free(info);
}
diff --git a/src/libs/lvgl/src/lv_misc/lv_async.h b/src/libs/lvgl/src/lv_misc/lv_async.h
index 9423cd8e..a3a9330b 100644
--- a/src/libs/lvgl/src/lv_misc/lv_async.h
+++ b/src/libs/lvgl/src/lv_misc/lv_async.h
@@ -30,13 +30,6 @@ extern "C" {
*/
typedef void (*lv_async_cb_t)(void *);
-typedef struct _lv_async_info_t {
- lv_async_cb_t cb;
- void *user_data;
-} lv_async_info_t;
-
-struct _lv_obj_t;
-
/**********************
* GLOBAL PROTOTYPES
**********************/
@@ -44,7 +37,7 @@ struct _lv_obj_t;
/**
* Call an asynchronous function the next time lv_task_handler() is run. This function is likely to return
* **before** the call actually happens!
- * @param task_xcb a callback which is the task itself.
+ * @param async_xcb a callback which is the task itself.
* (the 'x' in the argument name indicates that its not a fully generic function because it not follows
* the `func_name(object, callback, ...)` convention)
* @param user_data custom parameter
@@ -59,4 +52,4 @@ lv_res_t lv_async_call(lv_async_cb_t async_xcb, void * user_data);
} /* extern "C" */
#endif
-#endif /*LV_TEMPL_H*/
+#endif /*LV_ASYNC_H*/
diff --git a/src/libs/lvgl/src/lv_misc/lv_bidi.c b/src/libs/lvgl/src/lv_misc/lv_bidi.c
index 6e50d926..caa463a8 100644
--- a/src/libs/lvgl/src/lv_misc/lv_bidi.c
+++ b/src/libs/lvgl/src/lv_misc/lv_bidi.c
@@ -9,7 +9,7 @@
#include <stddef.h>
#include "lv_bidi.h"
#include "lv_txt.h"
-#include "../lv_draw/lv_draw.h"
+#include "../lv_misc/lv_mem.h"
#if LV_USE_BIDI
@@ -26,19 +26,28 @@
/**********************
* TYPEDEFS
**********************/
-typedef struct
-{
+typedef struct {
uint32_t bracklet_pos;
lv_bidi_dir_t dir;
-}bracket_stack_t;
+} bracket_stack_t;
/**********************
* STATIC PROTOTYPES
**********************/
-static lv_bidi_dir_t get_next_run(const char * txt, lv_bidi_dir_t base_dir, uint32_t max_len, uint32_t * len, uint16_t * pos_conv_len);
-static void rtl_reverse(char * dest, const char * src, uint32_t len, uint16_t *pos_conv_out, uint16_t pos_conv_rd_base, uint16_t pos_conv_len);
+
+static uint32_t lv_bidi_get_next_paragraph(const char * txt);
+static lv_bidi_dir_t lv_bidi_get_letter_dir(uint32_t letter);
+static bool lv_bidi_letter_is_weak(uint32_t letter);
+static bool lv_bidi_letter_is_rtl(uint32_t letter);
+static bool lv_bidi_letter_is_neutral(uint32_t letter);
+
+static lv_bidi_dir_t get_next_run(const char * txt, lv_bidi_dir_t base_dir, uint32_t max_len, uint32_t * len,
+ uint16_t * pos_conv_len);
+static void rtl_reverse(char * dest, const char * src, uint32_t len, uint16_t * pos_conv_out, uint16_t pos_conv_rd_base,
+ uint16_t pos_conv_len);
static uint32_t char_change_to_pair(uint32_t letter);
-static lv_bidi_dir_t bracket_process(const char * txt, uint32_t next_pos, uint32_t len, uint32_t letter, lv_bidi_dir_t base_dir);
+static lv_bidi_dir_t bracket_process(const char * txt, uint32_t next_pos, uint32_t len, uint32_t letter,
+ lv_bidi_dir_t base_dir);
static void fill_pos_conv(uint16_t * out, uint16_t len, uint16_t index);
static uint32_t get_txt_len(const char * txt, uint32_t max_len);
@@ -58,9 +67,16 @@ static uint8_t br_stack_p;
* GLOBAL FUNCTIONS
**********************/
-void lv_bidi_process(const char * str_in, char * str_out, lv_bidi_dir_t base_dir)
+/**
+ * Convert a text to get the characters in the correct visual order according to
+ * Unicode Bidirectional Algorithm
+ * @param str_in the text to process
+ * @param str_out store the result here. Has the be `strlen(str_in)` length
+ * @param base_dir `LV_BIDI_DIR_LTR` or `LV_BIDI_DIR_RTL`
+ */
+void _lv_bidi_process(const char * str_in, char * str_out, lv_bidi_dir_t base_dir)
{
- if(base_dir == LV_BIDI_DIR_AUTO) base_dir = lv_bidi_detect_base_dir(str_in);
+ if(base_dir == LV_BIDI_DIR_AUTO) base_dir = _lv_bidi_detect_base_dir(str_in);
uint32_t par_start = 0;
uint32_t par_len;
@@ -72,7 +88,7 @@ void lv_bidi_process(const char * str_in, char * str_out, lv_bidi_dir_t base_dir
while(str_in[par_start] != '\0') {
par_len = lv_bidi_get_next_paragraph(&str_in[par_start]);
- lv_bidi_process_paragraph(&str_in[par_start], &str_out[par_start], par_len, base_dir, NULL, 0);
+ _lv_bidi_process_paragraph(&str_in[par_start], &str_out[par_start], par_len, base_dir, NULL, 0);
par_start += par_len;
while(str_in[par_start] == '\n' || str_in[par_start] == '\r') {
@@ -84,12 +100,17 @@ void lv_bidi_process(const char * str_in, char * str_out, lv_bidi_dir_t base_dir
str_out[par_start] = '\0';
}
-lv_bidi_dir_t lv_bidi_detect_base_dir(const char * txt)
+/**
+ * Auto-detect the direction of a text based on the first strong character
+ * @param txt the text to process
+ * @return `LV_BIDI_DIR_LTR` or `LV_BIDI_DIR_RTL`
+ */
+lv_bidi_dir_t _lv_bidi_detect_base_dir(const char * txt)
{
uint32_t i = 0;
uint32_t letter;
while(txt[i] != '\0') {
- letter = lv_txt_encoded_next(txt, &i);
+ letter = _lv_txt_encoded_next(txt, &i);
lv_bidi_dir_t dir;
dir = lv_bidi_get_letter_dir(letter);
@@ -101,82 +122,99 @@ lv_bidi_dir_t lv_bidi_detect_base_dir(const char * txt)
else return LV_BIDI_BASE_DIR_DEF;
}
-lv_bidi_dir_t lv_bidi_get_letter_dir(uint32_t letter)
+/**
+ * Get the logical position of a character in a line
+ * @param str_in the input string. Can be only one line.
+ * @param bidi_txt internally the text is bidi processed which buffer can be get here.
+ * If not required anymore has to freed with `lv_mem_free()`
+ * Can be `NULL` is unused
+ * @param len length of the line in character count
+ * @param base_dir base direction of the text: `LV_BIDI_DIR_LTR` or `LV_BIDI_DIR_RTL`
+ * @param visual_pos the visual character position which logical position should be get
+ * @param is_rtl tell the char at `visual_pos` is RTL or LTR context
+ * @return the logical character position
+ */
+uint16_t _lv_bidi_get_logical_pos(const char * str_in, char ** bidi_txt, uint32_t len, lv_bidi_dir_t base_dir,
+ uint32_t visual_pos, bool * is_rtl)
{
- if(lv_bidi_letter_is_rtl(letter)) return LV_BIDI_DIR_RTL;
- if(lv_bidi_letter_is_neutral(letter)) return LV_BIDI_DIR_NEUTRAL;
- if(lv_bidi_letter_is_weak(letter)) return LV_BIDI_DIR_WEAK;
-
- return LV_BIDI_DIR_LTR;
-}
+ uint32_t pos_conv_len = get_txt_len(str_in, len);
+ char * buf = _lv_mem_buf_get(len + 1);
+ if(buf == NULL) return (uint16_t) -1;
-bool lv_bidi_letter_is_weak(uint32_t letter)
-{
- uint32_t i = 0;
- static const char weaks[] = "0123456789";
+ uint16_t * pos_conv_buf = _lv_mem_buf_get(pos_conv_len * sizeof(uint16_t));
+ if(pos_conv_buf == NULL) {
+ _lv_mem_buf_release(buf);
+ return (uint16_t) -1;
+ }
- do {
- uint32_t x = lv_txt_encoded_next(weaks, &i);
- if(letter == x) {
- return true;
- }
- } while(weaks[i] != '\0');
+ if(bidi_txt) *bidi_txt = buf;
- return false;
-}
+ _lv_bidi_process_paragraph(str_in, bidi_txt ? *bidi_txt : NULL, len, base_dir, pos_conv_buf, pos_conv_len);
-bool lv_bidi_letter_is_rtl(uint32_t letter)
-{
- if(letter >= 0x5d0 && letter <= 0x5ea) return true;
- if(letter == 0x202E) return true; /*Unicode of LV_BIDI_RLO*/
-// if(letter >= 'a' && letter <= 'z') return true;
+ if(is_rtl) *is_rtl = IS_RTL_POS(pos_conv_buf[visual_pos]);
- return false;
+ if(bidi_txt == NULL) _lv_mem_buf_release(buf);
+ uint16_t res = GET_POS(pos_conv_buf[visual_pos]);
+ _lv_mem_buf_release(pos_conv_buf);
+ return res;
}
-bool lv_bidi_letter_is_neutral(uint32_t letter)
+/**
+ * Get the visual position of a character in a line
+ * @param str_in the input string. Can be only one line.
+ * @param bidi_txt internally the text is bidi processed which buffer can be get here.
+ * If not required anymore has to freed with `lv_mem_free()`
+ * Can be `NULL` is unused
+ * @param len length of the line in character count
+ * @param base_dir base direction of the text: `LV_BIDI_DIR_LTR` or `LV_BIDI_DIR_RTL`
+ * @param logical_pos the logical character position which visual position should be get
+ * @param is_rtl tell the char at `logical_pos` is RTL or LTR context
+ * @return the visual character position
+ */
+uint16_t _lv_bidi_get_visual_pos(const char * str_in, char ** bidi_txt, uint16_t len, lv_bidi_dir_t base_dir,
+ uint32_t logical_pos, bool * is_rtl)
{
- uint16_t i;
- static const char neutrals[] = " \t\n\r.,:;'\"`!?%/\\-=()[]{}<>@#&$|";
- for(i = 0; neutrals[i] != '\0'; i++) {
- if(letter == (uint32_t)neutrals[i]) return true;
+ uint32_t pos_conv_len = get_txt_len(str_in, len);
+ char * buf = _lv_mem_buf_get(len + 1);
+ if(buf == NULL) return (uint16_t) -1;
+
+ uint16_t * pos_conv_buf = _lv_mem_buf_get(pos_conv_len * sizeof(uint16_t));
+ if(pos_conv_buf == NULL) {
+ _lv_mem_buf_release(buf);
+ return (uint16_t) -1;
}
- return false;
-}
+ if(bidi_txt) *bidi_txt = buf;
-uint16_t lv_bidi_get_logical_pos(const char * str_in, char **bidi_txt, uint32_t len, lv_bidi_dir_t base_dir, uint32_t visual_pos, bool *is_rtl)
-{
- uint32_t pos_conv_len = get_txt_len(str_in, len);
- uint32_t txt_buf_size = len + 1;
- txt_buf_size = (txt_buf_size + 3) & (~0x3);
- void *buf = lv_draw_get_buf(txt_buf_size + pos_conv_len * sizeof(uint16_t));
- if (bidi_txt) *bidi_txt = buf;
- uint16_t *pos_conv_buf = (uint16_t*) ((char*)buf + txt_buf_size);
- lv_bidi_process_paragraph(str_in, bidi_txt? *bidi_txt: NULL, len, base_dir, pos_conv_buf, pos_conv_len);
- if (is_rtl) *is_rtl = IS_RTL_POS(pos_conv_buf[visual_pos]);
- return GET_POS(pos_conv_buf[visual_pos]);
-}
+ _lv_bidi_process_paragraph(str_in, bidi_txt ? *bidi_txt : NULL, len, base_dir, pos_conv_buf, pos_conv_len);
-uint16_t lv_bidi_get_visual_pos(const char * str_in, char **bidi_txt, uint16_t len, lv_bidi_dir_t base_dir, uint32_t logical_pos, bool *is_rtl)
-{
- uint32_t pos_conv_len = get_txt_len(str_in, len);
- uint32_t txt_buf_size = len + 1;
- txt_buf_size = (txt_buf_size + 3) & (~0x3);
- void *buf = lv_draw_get_buf(txt_buf_size + pos_conv_len * sizeof(uint16_t));
- if (bidi_txt) *bidi_txt = buf;
- uint16_t *pos_conv_buf = (uint16_t*) ((char*)buf + txt_buf_size);
- lv_bidi_process_paragraph(str_in, bidi_txt? *bidi_txt: NULL, len, base_dir, pos_conv_buf, pos_conv_len);
- for (uint16_t i = 0; i < pos_conv_len; i++){
- if (GET_POS(pos_conv_buf[i]) == logical_pos){
- if (is_rtl) *is_rtl = IS_RTL_POS(pos_conv_buf[i]);
+ for(uint16_t i = 0; i < pos_conv_len; i++) {
+ if(GET_POS(pos_conv_buf[i]) == logical_pos) {
+
+ if(is_rtl) *is_rtl = IS_RTL_POS(pos_conv_buf[i]);
+ _lv_mem_buf_release(pos_conv_buf);
+
+ if(bidi_txt == NULL) _lv_mem_buf_release(buf);
return i;
}
}
+ _lv_mem_buf_release(pos_conv_buf);
+ if(bidi_txt == NULL) _lv_mem_buf_release(buf);
return (uint16_t) -1;
}
-void lv_bidi_process_paragraph(const char * str_in, char * str_out, uint32_t len, lv_bidi_dir_t base_dir, uint16_t *pos_conv_out, uint16_t pos_conv_len)
+/**
+ * Bidi process a paragraph of text
+ * @param str_in the string to process
+ * @param str_out store the result here
+ * @param len length of the text
+ * @param base_dir base dir of the text
+ * @param pos_conv_out an `uint16_t` array to store the related logical position of the character.
+ * Can be `NULL` is unused
+ * @param pos_conv_len length of `pos_conv_out` in element count
+ */
+void _lv_bidi_process_paragraph(const char * str_in, char * str_out, uint32_t len, lv_bidi_dir_t base_dir,
+ uint16_t * pos_conv_out, uint16_t pos_conv_len)
{
uint32_t run_len = 0;
lv_bidi_dir_t run_dir;
@@ -186,7 +224,7 @@ void lv_bidi_process_paragraph(const char * str_in, char * str_out, uint32_t len
uint16_t pos_conv_rd = 0;
uint16_t pos_conv_wr;
- if(base_dir == LV_BIDI_DIR_AUTO) base_dir = lv_bidi_detect_base_dir(str_in);
+ if(base_dir == LV_BIDI_DIR_AUTO) base_dir = _lv_bidi_detect_base_dir(str_in);
if(base_dir == LV_BIDI_DIR_RTL) {
wr = len;
pos_conv_wr = pos_conv_len;
@@ -196,7 +234,7 @@ void lv_bidi_process_paragraph(const char * str_in, char * str_out, uint32_t len
pos_conv_wr = 0;
}
- if (str_out) str_out[len] = '\0';
+ if(str_out) str_out[len] = '\0';
lv_bidi_dir_t dir = base_dir;
@@ -205,7 +243,7 @@ void lv_bidi_process_paragraph(const char * str_in, char * str_out, uint32_t len
/*Process neutral chars in the beginning*/
while(rd < len) {
- uint32_t letter = lv_txt_encoded_next(str_in, &rd);
+ uint32_t letter = _lv_txt_encoded_next(str_in, &rd);
pos_conv_rd++;
dir = lv_bidi_get_letter_dir(letter);
if(dir == LV_BIDI_DIR_NEUTRAL) dir = bracket_process(str_in, rd, len, letter, base_dir);
@@ -213,24 +251,26 @@ void lv_bidi_process_paragraph(const char * str_in, char * str_out, uint32_t len
}
if(rd && str_in[rd] != '\0') {
- lv_txt_encoded_prev(str_in, &rd);
- pos_conv_rd--;
+ _lv_txt_encoded_prev(str_in, &rd);
+ pos_conv_rd--;
}
if(rd) {
if(base_dir == LV_BIDI_DIR_LTR) {
- if (str_out) {
- memcpy(&str_out[wr], str_in, rd);
+ if(str_out) {
+ _lv_memcpy(&str_out[wr], str_in, rd);
wr += rd;
}
- if (pos_conv_out) {
+ if(pos_conv_out) {
fill_pos_conv(&pos_conv_out[pos_conv_wr], pos_conv_rd, 0);
pos_conv_wr += pos_conv_rd;
}
- } else {
+ }
+ else {
wr -= rd;
pos_conv_wr -= pos_conv_rd;
- rtl_reverse(str_out? &str_out[wr]: NULL, str_in, rd, pos_conv_out? &pos_conv_out[pos_conv_wr]: NULL, 0, pos_conv_rd);
+ rtl_reverse(str_out ? &str_out[wr] : NULL, str_in, rd, pos_conv_out ? &pos_conv_out[pos_conv_wr] : NULL, 0,
+ pos_conv_rd);
}
}
@@ -241,43 +281,117 @@ void lv_bidi_process_paragraph(const char * str_in, char * str_out, uint32_t len
if(base_dir == LV_BIDI_DIR_LTR) {
if(run_dir == LV_BIDI_DIR_LTR) {
- if (str_out) memcpy(&str_out[wr], &str_in[rd], run_len);
- if (pos_conv_out) fill_pos_conv(&pos_conv_out[pos_conv_wr], pos_conv_run_len, pos_conv_rd);
+ if(str_out) _lv_memcpy(&str_out[wr], &str_in[rd], run_len);
+ if(pos_conv_out) fill_pos_conv(&pos_conv_out[pos_conv_wr], pos_conv_run_len, pos_conv_rd);
}
- else rtl_reverse(str_out? &str_out[wr]: NULL, &str_in[rd], run_len, pos_conv_out? &pos_conv_out[pos_conv_wr] : NULL, pos_conv_rd, pos_conv_run_len);
- wr += run_len;
- pos_conv_wr += pos_conv_run_len;
- } else {
- wr -= run_len;
- pos_conv_wr -= pos_conv_run_len;
- if(run_dir == LV_BIDI_DIR_LTR) {
- if (str_out) memcpy(&str_out[wr], &str_in[rd], run_len);
- if (pos_conv_out) fill_pos_conv(&pos_conv_out[pos_conv_wr], pos_conv_run_len, pos_conv_rd);
- }
- else rtl_reverse(str_out? &str_out[wr]: NULL, &str_in[rd], run_len, pos_conv_out? &pos_conv_out[pos_conv_wr] : NULL, pos_conv_rd, pos_conv_run_len);
- }
+ else rtl_reverse(str_out ? &str_out[wr] : NULL, &str_in[rd], run_len, pos_conv_out ? &pos_conv_out[pos_conv_wr] : NULL,
+ pos_conv_rd, pos_conv_run_len);
+ wr += run_len;
+ pos_conv_wr += pos_conv_run_len;
+ }
+ else {
+ wr -= run_len;
+ pos_conv_wr -= pos_conv_run_len;
+ if(run_dir == LV_BIDI_DIR_LTR) {
+ if(str_out) _lv_memcpy(&str_out[wr], &str_in[rd], run_len);
+ if(pos_conv_out) fill_pos_conv(&pos_conv_out[pos_conv_wr], pos_conv_run_len, pos_conv_rd);
+ }
+ else rtl_reverse(str_out ? &str_out[wr] : NULL, &str_in[rd], run_len, pos_conv_out ? &pos_conv_out[pos_conv_wr] : NULL,
+ pos_conv_rd, pos_conv_run_len);
+ }
rd += run_len;
pos_conv_rd += pos_conv_run_len;
}
}
-uint32_t lv_bidi_get_next_paragraph(const char * txt)
+/**********************
+ * STATIC FUNCTIONS
+ **********************/
+
+/**
+ * Get the next paragraph from a text
+ * @param txt the text to process
+ * @return the length of the current paragraph in byte count
+ */
+static uint32_t lv_bidi_get_next_paragraph(const char * txt)
{
uint32_t i = 0;
- lv_txt_encoded_next(txt, &i);
+ _lv_txt_encoded_next(txt, &i);
while(txt[i] != '\0' && txt[i] != '\n' && txt[i] != '\r') {
- lv_txt_encoded_next(txt, &i);
+ _lv_txt_encoded_next(txt, &i);
}
return i;
}
-/**********************
- * STATIC FUNCTIONS
- **********************/
+/**
+ * Get the direction of a character
+ * @param letter an Unicode character
+ * @return `LV_BIDI_DIR_RTL/LTR/WEAK/NEUTRAL`
+ */
+static lv_bidi_dir_t lv_bidi_get_letter_dir(uint32_t letter)
+{
+ if(lv_bidi_letter_is_rtl(letter)) return LV_BIDI_DIR_RTL;
+ if(lv_bidi_letter_is_neutral(letter)) return LV_BIDI_DIR_NEUTRAL;
+ if(lv_bidi_letter_is_weak(letter)) return LV_BIDI_DIR_WEAK;
+
+ return LV_BIDI_DIR_LTR;
+}
+/**
+ * Tell whether a character is weak or not
+ * @param letter an Unicode character
+ * @return true/false
+ */
+static bool lv_bidi_letter_is_weak(uint32_t letter)
+{
+ uint32_t i = 0;
+ static const char weaks[] = "0123456789";
+
+ do {
+ uint32_t x = _lv_txt_encoded_next(weaks, &i);
+ if(letter == x) {
+ return true;
+ }
+ } while(weaks[i] != '\0');
+
+ return false;
+}
+/**
+ * Tell whether a character is RTL or not
+ * @param letter an Unicode character
+ * @return true/false
+ */
+static bool lv_bidi_letter_is_rtl(uint32_t letter)
+{
+ if(letter >= 0x5d0 && letter <= 0x5ea) return true;
+ if(letter == 0x202E) return true; /*Unicode of LV_BIDI_RLO*/
+
+ /* Check for Persian and Arabic characters [https://en.wikipedia.org/wiki/Arabic_script_in_Unicode]*/
+ if(letter >= 0x600 && letter <= 0x6FF) return true;
+ if(letter >= 0xFB50 && letter <= 0xFDFF) return true;
+ if(letter >= 0xFE70 && letter <= 0xFEFF) return true;
+
+ return false;
+}
+
+/**
+ * Tell whether a character is neutral or not
+ * @param letter an Unicode character
+ * @return true/false
+ */
+static bool lv_bidi_letter_is_neutral(uint32_t letter)
+{
+ uint16_t i;
+ static const char neutrals[] = " \t\n\r.,:;'\"`!?%/\\-=()[]{}<>@#&$|";
+ for(i = 0; neutrals[i] != '\0'; i++) {
+ if(letter == (uint32_t)neutrals[i]) return true;
+ }
+
+ return false;
+}
static uint32_t get_txt_len(const char * txt, uint32_t max_len)
{
@@ -285,7 +399,7 @@ static uint32_t get_txt_len(const char * txt, uint32_t max_len)
uint32_t i = 0;
while(i < max_len && txt[i] != '\0') {
- lv_txt_encoded_next(txt, &i);
+ _lv_txt_encoded_next(txt, &i);
len++;
}
@@ -294,27 +408,28 @@ static uint32_t get_txt_len(const char * txt, uint32_t max_len)
static void fill_pos_conv(uint16_t * out, uint16_t len, uint16_t index)
{
- for (uint16_t i = 0; i < len; i++)
- {
+ uint16_t i;
+ for(i = 0; i < len; i++) {
out[i] = SET_RTL_POS(index, false);
index++;
}
-}
+}
-static lv_bidi_dir_t get_next_run(const char * txt, lv_bidi_dir_t base_dir, uint32_t max_len, uint32_t * len, uint16_t * pos_conv_len)
+static lv_bidi_dir_t get_next_run(const char * txt, lv_bidi_dir_t base_dir, uint32_t max_len, uint32_t * len,
+ uint16_t * pos_conv_len)
{
uint32_t i = 0;
uint32_t letter;
uint16_t pos_conv_i = 0;
- letter = lv_txt_encoded_next(txt, NULL);
+ letter = _lv_txt_encoded_next(txt, NULL);
lv_bidi_dir_t dir = lv_bidi_get_letter_dir(letter);
if(dir == LV_BIDI_DIR_NEUTRAL) dir = bracket_process(txt, 0, max_len, letter, base_dir);
/*Find the first strong char. Skip the neutrals*/
while(dir == LV_BIDI_DIR_NEUTRAL || dir == LV_BIDI_DIR_WEAK) {
- letter = lv_txt_encoded_next(txt, &i);
+ letter = _lv_txt_encoded_next(txt, &i);
pos_conv_i++;
dir = lv_bidi_get_letter_dir(letter);
if(dir == LV_BIDI_DIR_NEUTRAL) dir = bracket_process(txt, i, max_len, letter, base_dir);
@@ -336,7 +451,7 @@ static lv_bidi_dir_t get_next_run(const char * txt, lv_bidi_dir_t base_dir, uint
/*Find the next char which has different direction*/
lv_bidi_dir_t next_dir = base_dir;
while(i_prev < max_len && txt[i] != '\0' && txt[i] != '\n' && txt[i] != '\r') {
- letter = lv_txt_encoded_next(txt, &i);
+ letter = _lv_txt_encoded_next(txt, &i);
pos_conv_i++;
next_dir = lv_bidi_get_letter_dir(letter);
if(next_dir == LV_BIDI_DIR_NEUTRAL) next_dir = bracket_process(txt, i, max_len, letter, base_dir);
@@ -382,7 +497,8 @@ static lv_bidi_dir_t get_next_run(const char * txt, lv_bidi_dir_t base_dir, uint
return run_dir;
}
-static void rtl_reverse(char * dest, const char * src, uint32_t len, uint16_t *pos_conv_out, uint16_t pos_conv_rd_base, uint16_t pos_conv_len)
+static void rtl_reverse(char * dest, const char * src, uint32_t len, uint16_t * pos_conv_out, uint16_t pos_conv_rd_base,
+ uint16_t pos_conv_len)
{
uint32_t i = len;
uint32_t wr = 0;
@@ -390,7 +506,7 @@ static void rtl_reverse(char * dest, const char * src, uint32_t len, uint16_t *p
uint16_t pos_conv_wr = 0;
while(i) {
- uint32_t letter = lv_txt_encoded_prev(src, &i);
+ uint32_t letter = _lv_txt_encoded_prev(src, &i);
uint16_t pos_conv_letter = --pos_conv_i;
/*Keep weak letters (numbers) as LTR*/
@@ -400,15 +516,15 @@ static void rtl_reverse(char * dest, const char * src, uint32_t len, uint16_t *p
uint16_t pos_conv_last_weak = pos_conv_i;
uint16_t pos_conv_first_weak = pos_conv_i;
while(i) {
- letter = lv_txt_encoded_prev(src, &i);
+ letter = _lv_txt_encoded_prev(src, &i);
pos_conv_letter = --pos_conv_i;
/*No need to call `char_change_to_pair` because there not such chars here*/
/*Finish on non-weak char */
/*but treat number and currency related chars as weak*/
- if (lv_bidi_letter_is_weak(letter) == false && letter != '.' && letter != ',' && letter != '$' && letter != '%') {
- lv_txt_encoded_next(src, &i); /*Rewind one letter*/
+ if(lv_bidi_letter_is_weak(letter) == false && letter != '.' && letter != ',' && letter != '$' && letter != '%') {
+ _lv_txt_encoded_next(src, &i); /*Rewind one letter*/
pos_conv_i++;
first_weak = i;
pos_conv_first_weak = pos_conv_i;
@@ -420,27 +536,28 @@ static void rtl_reverse(char * dest, const char * src, uint32_t len, uint16_t *p
pos_conv_first_weak = 0;
}
- if (dest) memcpy(&dest[wr], &src[first_weak], last_weak - first_weak + 1);
- if (pos_conv_out) fill_pos_conv(&pos_conv_out[pos_conv_wr], pos_conv_last_weak - pos_conv_first_weak + 1, pos_conv_rd_base + pos_conv_first_weak);
+ if(dest) _lv_memcpy(&dest[wr], &src[first_weak], last_weak - first_weak + 1);
+ if(pos_conv_out) fill_pos_conv(&pos_conv_out[pos_conv_wr], pos_conv_last_weak - pos_conv_first_weak + 1,
+ pos_conv_rd_base + pos_conv_first_weak);
wr += last_weak - first_weak + 1;
pos_conv_wr += pos_conv_last_weak - pos_conv_first_weak + 1;
}
/*Simply store in reversed order*/
else {
- uint32_t letter_size = lv_txt_encoded_size((const char *)&src[i]);
+ uint32_t letter_size = _lv_txt_encoded_size((const char *)&src[i]);
/*Swap arithmetical symbols*/
if(letter_size == 1) {
uint32_t new_letter = letter = char_change_to_pair(letter);
- if (dest) dest[wr] = (uint8_t)new_letter;
- if (pos_conv_out) pos_conv_out[pos_conv_wr] = SET_RTL_POS(pos_conv_rd_base + pos_conv_letter, true);
+ if(dest) dest[wr] = (uint8_t)new_letter;
+ if(pos_conv_out) pos_conv_out[pos_conv_wr] = SET_RTL_POS(pos_conv_rd_base + pos_conv_letter, true);
wr++;
pos_conv_wr++;
}
/*Just store the letter*/
else {
- if (dest) memcpy(&dest[wr], &src[i], letter_size);
- if (pos_conv_out) pos_conv_out[pos_conv_wr] = SET_RTL_POS(pos_conv_rd_base + pos_conv_i, true);
+ if(dest) _lv_memcpy(&dest[wr], &src[i], letter_size);
+ if(pos_conv_out) pos_conv_out[pos_conv_wr] = SET_RTL_POS(pos_conv_rd_base + pos_conv_i, true);
wr += letter_size;
pos_conv_wr++;
}
@@ -463,7 +580,8 @@ static uint32_t char_change_to_pair(uint32_t letter)
return letter;
}
-static lv_bidi_dir_t bracket_process(const char * txt, uint32_t next_pos, uint32_t len, uint32_t letter, lv_bidi_dir_t base_dir)
+static lv_bidi_dir_t bracket_process(const char * txt, uint32_t next_pos, uint32_t len, uint32_t letter,
+ lv_bidi_dir_t base_dir)
{
lv_bidi_dir_t bracket_dir = LV_BIDI_DIR_NEUTRAL;
@@ -475,11 +593,12 @@ static lv_bidi_dir_t bracket_process(const char * txt, uint32_t next_pos, uint32
* If a char with base dir. direction is found then the brackets will have `base_dir` direction*/
uint32_t txt_i = next_pos;
while(txt_i < len) {
- uint32_t letter_next = lv_txt_encoded_next(txt, &txt_i);
+ uint32_t letter_next = _lv_txt_encoded_next(txt, &txt_i);
if(letter_next == bracket_right[i]) {
/*Closing bracket found*/
break;
- } else {
+ }
+ else {
/*Save the dir*/
lv_bidi_dir_t letter_dir = lv_bidi_get_letter_dir(letter_next);
if(letter_dir == base_dir) {
@@ -496,9 +615,9 @@ static lv_bidi_dir_t bracket_process(const char * txt, uint32_t next_pos, uint32
/*If there were no matching strong chars in the brackets then check the previous chars*/
txt_i = next_pos;
- if(txt_i) lv_txt_encoded_prev(txt, &txt_i);
+ if(txt_i) _lv_txt_encoded_prev(txt, &txt_i);
while(txt_i > 0) {
- uint32_t letter_next = lv_txt_encoded_prev(txt, &txt_i);
+ uint32_t letter_next = _lv_txt_encoded_prev(txt, &txt_i);
lv_bidi_dir_t letter_dir = lv_bidi_get_letter_dir(letter_next);
if(letter_dir == LV_BIDI_DIR_LTR || letter_dir == LV_BIDI_DIR_RTL) {
bracket_dir = letter_dir;
@@ -506,7 +625,6 @@ static lv_bidi_dir_t bracket_process(const char * txt, uint32_t next_pos, uint32
}
}
-
/*There where a previous strong char which can be used*/
if(bracket_dir != LV_BIDI_DIR_NEUTRAL) break;
@@ -517,7 +635,6 @@ static lv_bidi_dir_t bracket_process(const char * txt, uint32_t next_pos, uint32
}
}
-
/*The letter was an opening bracket*/
if(bracket_left[i] != '\0') {
@@ -528,7 +645,8 @@ static lv_bidi_dir_t bracket_process(const char * txt, uint32_t next_pos, uint32
br_stack_p++;
return bracket_dir;
- } else if(br_stack_p > 0) {
+ }
+ else if(br_stack_p > 0) {
/*Is the letter a closing bracket of the last opening?*/
if(letter == bracket_right[br_stack[br_stack_p - 1].bracklet_pos]) {
bracket_dir = br_stack[br_stack_p - 1].dir;
@@ -540,5 +658,4 @@ static lv_bidi_dir_t bracket_process(const char * txt, uint32_t next_pos, uint32
return LV_BIDI_DIR_NEUTRAL;
}
-
#endif /*LV_USE_BIDI*/
diff --git a/src/libs/lvgl/src/lv_misc/lv_bidi.h b/src/libs/lvgl/src/lv_misc/lv_bidi.h
index 215727aa..8b2f765d 100644
--- a/src/libs/lvgl/src/lv_misc/lv_bidi.h
+++ b/src/libs/lvgl/src/lv_misc/lv_bidi.h
@@ -1,5 +1,5 @@
/**
- * @file lv_bifi.h
+ * @file lv_bidi.h
*
*/
@@ -13,11 +13,7 @@ extern "C" {
/*********************
* INCLUDES
*********************/
-#ifdef LV_CONF_INCLUDE_SIMPLE
-#include "lv_conf.h"
-#else
-#include "../../../lv_conf.h"
-#endif
+#include "../lv_conf_internal.h"
#include <stdbool.h>
#include <stdint.h>
@@ -25,7 +21,7 @@ extern "C" {
/*********************
* DEFINES
*********************/
-/* Special non printable strong characters.
+/* Special non printable strong characters.
* They can be inserted to texts to affect the run's direction*/
#define LV_BIDI_LRO "\xE2\x80\xAD" /*U+202D*/
#define LV_BIDI_RLO "\xE2\x80\xAE" /*U+202E*/
@@ -33,8 +29,7 @@ extern "C" {
/**********************
* TYPEDEFS
**********************/
-enum
-{
+enum {
/*The first 4 values are stored in `lv_obj_t` on 2 bits*/
LV_BIDI_DIR_LTR = 0x00,
LV_BIDI_DIR_RTL = 0x01,
@@ -52,16 +47,64 @@ typedef uint8_t lv_bidi_dir_t;
**********************/
#if LV_USE_BIDI
-void lv_bidi_process(const char * str_in, char * str_out, lv_bidi_dir_t base_dir);
-void lv_bidi_process_paragraph(const char * str_in, char * str_out, uint32_t len, lv_bidi_dir_t base_dir, uint16_t *pos_conv_out, uint16_t pos_conv_len);
-uint32_t lv_bidi_get_next_paragraph(const char * txt);
-lv_bidi_dir_t lv_bidi_detect_base_dir(const char * txt);
-lv_bidi_dir_t lv_bidi_get_letter_dir(uint32_t letter);
-bool lv_bidi_letter_is_weak(uint32_t letter);
-bool lv_bidi_letter_is_rtl(uint32_t letter);
-bool lv_bidi_letter_is_neutral(uint32_t letter);
-uint16_t lv_bidi_get_logical_pos(const char * str_in, char **bidi_txt, uint32_t len, lv_bidi_dir_t base_dir, uint32_t visual_pos, bool *is_rtl);
-uint16_t lv_bidi_get_visual_pos(const char * str_in, char **bidi_txt, uint16_t len, lv_bidi_dir_t base_dir, uint32_t logical_pos, bool *is_rtl);
+/**
+ * Convert a text to get the characters in the correct visual order according to
+ * Unicode Bidirectional Algorithm
+ * @param str_in the text to process
+ * @param str_out store the result here. Has the be `strlen(str_in)` length
+ * @param base_dir `LV_BIDI_DIR_LTR` or `LV_BIDI_DIR_RTL`
+ */
+void _lv_bidi_process(const char * str_in, char * str_out, lv_bidi_dir_t base_dir);
+
+/**
+ * Auto-detect the direction of a text based on the first strong character
+ * @param txt the text to process
+ * @return `LV_BIDI_DIR_LTR` or `LV_BIDI_DIR_RTL`
+ */
+lv_bidi_dir_t _lv_bidi_detect_base_dir(const char * txt);
+
+/**
+ * Get the logical position of a character in a line
+ * @param str_in the input string. Can be only one line.
+ * @param bidi_txt internally the text is bidi processed which buffer can be get here.
+ * If not required anymore has to freed with `lv_mem_free()`
+ * Can be `NULL` is unused
+ * @param len length of the line in character count
+ * @param base_dir base direction of the text: `LV_BIDI_DIR_LTR` or `LV_BIDI_DIR_RTL`
+ * @param visual_pos the visual character position which logical position should be get
+ * @param is_rtl tell the char at `visual_pos` is RTL or LTR context
+ * @return the logical character position
+ */
+uint16_t _lv_bidi_get_logical_pos(const char * str_in, char ** bidi_txt, uint32_t len, lv_bidi_dir_t base_dir,
+ uint32_t visual_pos, bool * is_rtl);
+
+/**
+ * Get the visual position of a character in a line
+ * @param str_in the input string. Can be only one line.
+ * @param bidi_txt internally the text is bidi processed which buffer can be get here.
+ * If not required anymore has to freed with `lv_mem_free()`
+ * Can be `NULL` is unused
+ * @param len length of the line in character count
+ * @param base_dir base direction of the text: `LV_BIDI_DIR_LTR` or `LV_BIDI_DIR_RTL`
+ * @param logical_pos the logical character position which visual position should be get
+ * @param is_rtl tell the char at `logical_pos` is RTL or LTR context
+ * @return the visual character position
+ */
+uint16_t _lv_bidi_get_visual_pos(const char * str_in, char ** bidi_txt, uint16_t len, lv_bidi_dir_t base_dir,
+ uint32_t logical_pos, bool * is_rtl);
+
+/**
+ * Bidi process a paragraph of text
+ * @param str_in the string to process
+ * @param str_out store the result here
+ * @param len length of the text
+ * @param base_dir base dir of the text
+ * @param pos_conv_out an `uint16_t` array to store the related logical position of the character.
+ * Can be `NULL` is unused
+ * @param pos_conv_len length of `pos_conv_out` in element count
+ */
+void _lv_bidi_process_paragraph(const char * str_in, char * str_out, uint32_t len, lv_bidi_dir_t base_dir,
+ uint16_t * pos_conv_out, uint16_t pos_conv_len);
/**********************
* MACROS
diff --git a/src/libs/lvgl/src/lv_misc/lv_circ.c b/src/libs/lvgl/src/lv_misc/lv_circ.c
deleted file mode 100644
index fc0e3e20..00000000
--- a/src/libs/lvgl/src/lv_misc/lv_circ.c
+++ /dev/null
@@ -1,79 +0,0 @@
-/**
- * @file lv_circ.c
- * Circle drawing algorithm (with Bresenham)
- * Only a 1/8 circle is calculated. Use CIRC_OCT1_X, CIRC_OCT1_Y macros to get
- * the other octets.
- */
-
-/*********************
- * INCLUDES
- *********************/
-#include "lv_circ.h"
-
-/*********************
- * DEFINES
- *********************/
-
-/**********************
- * TYPEDEFS
- **********************/
-
-/**********************
- * STATIC PROTOTYPES
- **********************/
-
-/**********************
- * STATIC VARIABLES
- **********************/
-
-/**********************
- * MACROS
- **********************/
-
-/**********************
- * GLOBAL FUNCTIONS
- **********************/
-
-/**
- * Initialize the circle drawing
- * @param c pointer to a point. The coordinates will be calculated here
- * @param tmp point to a variable. It will store temporary data
- * @param radius radius of the circle
- */
-void lv_circ_init(lv_point_t * c, lv_coord_t * tmp, lv_coord_t radius)
-{
- c->x = radius;
- c->y = 0;
- *tmp = 1 - radius;
-}
-
-/**
- * Test the circle drawing is ready or not
- * @param c same as in circ_init
- * @return true if the circle is not ready yet
- */
-bool lv_circ_cont(lv_point_t * c)
-{
- return c->y <= c->x ? true : false;
-}
-
-/**
- * Get the next point from the circle
- * @param c same as in circ_init. The next point stored here.
- * @param tmp same as in circ_init.
- */
-void lv_circ_next(lv_point_t * c, lv_coord_t * tmp)
-{
- c->y++;
-
- if(*tmp <= 0) {
- (*tmp) += 2 * c->y + 1; /*Change in decision criterion for y -> y+1*/
- } else {
- c->x--;
- (*tmp) += 2 * (c->y - c->x) + 1; /*Change for y -> y+1, x -> x-1*/
- }
-}
-
-/**********************
- * STATIC FUNCTIONS
- **********************/
diff --git a/src/libs/lvgl/src/lv_misc/lv_circ.h b/src/libs/lvgl/src/lv_misc/lv_circ.h
deleted file mode 100644
index 405a4b6c..00000000
--- a/src/libs/lvgl/src/lv_misc/lv_circ.h
+++ /dev/null
@@ -1,77 +0,0 @@
-/**
- * @file lv_circ.h
- *
- */
-
-#ifndef LV_CIRC_H
-#define LV_CIRC_H
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/*********************
- * INCLUDES
- *********************/
-#include <stddef.h>
-#include "lv_area.h"
-
-/*********************
- * DEFINES
- *********************/
-#define LV_CIRC_OCT1_X(p) (p.x)
-#define LV_CIRC_OCT1_Y(p) (p.y)
-#define LV_CIRC_OCT2_X(p) (p.y)
-#define LV_CIRC_OCT2_Y(p) (p.x)
-#define LV_CIRC_OCT3_X(p) (-p.y)
-#define LV_CIRC_OCT3_Y(p) (p.x)
-#define LV_CIRC_OCT4_X(p) (-p.x)
-#define LV_CIRC_OCT4_Y(p) (p.y)
-#define LV_CIRC_OCT5_X(p) (-p.x)
-#define LV_CIRC_OCT5_Y(p) (-p.y)
-#define LV_CIRC_OCT6_X(p) (-p.y)
-#define LV_CIRC_OCT6_Y(p) (-p.x)
-#define LV_CIRC_OCT7_X(p) (p.y)
-#define LV_CIRC_OCT7_Y(p) (-p.x)
-#define LV_CIRC_OCT8_X(p) (p.x)
-#define LV_CIRC_OCT8_Y(p) (-p.y)
-
-/**********************
- * TYPEDEFS
- **********************/
-
-/**********************
- * GLOBAL PROTOTYPES
- **********************/
-
-/**
- * Initialize the circle drawing
- * @param c pointer to a point. The coordinates will be calculated here
- * @param tmp point to a variable. It will store temporary data
- * @param radius radius of the circle
- */
-void lv_circ_init(lv_point_t * c, lv_coord_t * tmp, lv_coord_t radius);
-
-/**
- * Test the circle drawing is ready or not
- * @param c same as in circ_init
- * @return true if the circle is not ready yet
- */
-bool lv_circ_cont(lv_point_t * c);
-
-/**
- * Get the next point from the circle
- * @param c same as in circ_init. The next point stored here.
- * @param tmp same as in circ_init.
- */
-void lv_circ_next(lv_point_t * c, lv_coord_t * tmp);
-
-/**********************
- * MACROS
- **********************/
-
-#ifdef __cplusplus
-} /* extern "C" */
-#endif
-
-#endif
diff --git a/src/libs/lvgl/src/lv_misc/lv_color.c b/src/libs/lvgl/src/lv_misc/lv_color.c
index cd4825df..11f33618 100644
--- a/src/libs/lvgl/src/lv_misc/lv_color.c
+++ b/src/libs/lvgl/src/lv_misc/lv_color.c
@@ -7,7 +7,6 @@
* INCLUDES
*********************/
#include "lv_color.h"
-#include "lv_math.h"
/*********************
* DEFINES
@@ -33,9 +32,105 @@
* GLOBAL FUNCTIONS
**********************/
-/**********************
- * STATIC FUNCTIONS
- **********************/
+LV_ATTRIBUTE_FAST_MEM void lv_color_fill(lv_color_t * buf, lv_color_t color, uint32_t px_num)
+{
+#if LV_COLOR_DEPTH == 16
+ uintptr_t buf_int = (uintptr_t) buf;
+ if(buf_int & 0x3) {
+ *buf = color;
+ buf++;
+ px_num--;
+ }
+
+ uint32_t c32 = color.full + (color.full << 16);
+ uint32_t * buf32 = (uint32_t *)buf;
+
+ while(px_num > 16) {
+ *buf32 = c32;
+ buf32++;
+ *buf32 = c32;
+ buf32++;
+ *buf32 = c32;
+ buf32++;
+ *buf32 = c32;
+ buf32++;
+
+ *buf32 = c32;
+ buf32++;
+ *buf32 = c32;
+ buf32++;
+ *buf32 = c32;
+ buf32++;
+ *buf32 = c32;
+ buf32++;
+
+ px_num -= 16;
+ }
+
+ buf = (lv_color_t *)buf32;
+
+ while(px_num) {
+ *buf = color;
+ buf++;
+ px_num --;
+ }
+#else
+ while(px_num > 16) {
+ *buf = color;
+ buf++;
+ *buf = color;
+ buf++;
+ *buf = color;
+ buf++;
+ *buf = color;
+ buf++;
+
+ *buf = color;
+ buf++;
+ *buf = color;
+ buf++;
+ *buf = color;
+ buf++;
+ *buf = color;
+ buf++;
+
+ *buf = color;
+ buf++;
+ *buf = color;
+ buf++;
+ *buf = color;
+ buf++;
+ *buf = color;
+ buf++;
+
+ *buf = color;
+ buf++;
+ *buf = color;
+ buf++;
+ *buf = color;
+ buf++;
+ *buf = color;
+ buf++;
+
+ px_num -= 16;
+ }
+ while(px_num) {
+ *buf = color;
+ buf++;
+ px_num --;
+ }
+#endif
+}
+
+lv_color_t lv_color_lighten(lv_color_t c, lv_opa_t lvl)
+{
+ return lv_color_mix(LV_COLOR_WHITE, c, lvl);
+}
+
+lv_color_t lv_color_darken(lv_color_t c, lv_opa_t lvl)
+{
+ return lv_color_mix(LV_COLOR_BLACK, c, lvl);
+}
/**
* Convert a HSV color to RGB
@@ -55,9 +150,6 @@ lv_color_t lv_color_hsv_to_rgb(uint16_t h, uint8_t s, uint8_t v)
uint8_t region, remainder, p, q, t;
if(s == 0) {
- r = v;
- g = v;
- b = v;
return lv_color_make(v, v, v);
}
@@ -127,7 +219,7 @@ lv_color_hsv_t lv_color_rgb_to_hsv(uint8_t r8, uint8_t g8, uint8_t b8)
hsv.v = (100 * rgbMax) >> 10;
int32_t delta = rgbMax - rgbMin;
- if (LV_MATH_ABS(delta) < 3) {
+ if(delta < 3) {
hsv.h = 0;
hsv.s = 0;
return hsv;
@@ -152,7 +244,7 @@ lv_color_hsv_t lv_color_rgb_to_hsv(uint8_t r8, uint8_t g8, uint8_t b8)
h = 0;
h *= 60;
h >>= 10;
- if (h < 0) h += 360;
+ if(h < 0) h += 360;
hsv.h = h;
return hsv;
diff --git a/src/libs/lvgl/src/lv_misc/lv_color.h b/src/libs/lvgl/src/lv_misc/lv_color.h
index 1febbdce..75205edb 100644
--- a/src/libs/lvgl/src/lv_misc/lv_color.h
+++ b/src/libs/lvgl/src/lv_misc/lv_color.h
@@ -13,15 +13,13 @@ extern "C" {
/*********************
* INCLUDES
*********************/
-#ifdef LV_CONF_INCLUDE_SIMPLE
-#include "lv_conf.h"
-#else
-#include "../../../lv_conf.h"
-#endif
+#include "../lv_conf_internal.h"
+#include "lv_math.h"
+#include "lv_types.h"
/*Error checking*/
#if LV_COLOR_DEPTH == 24
-#error "LV_COLOR_DEPTH 24 is deprecated. Use LV_COLOR_DEPTH 32 instead (lv_conf.h)"
+#error "LV_COLOR_DEPTH 24 is deprecated. Use LV_COLOR_DEPTH 32 instead (lv_conf.h)"
#endif
#if LV_COLOR_DEPTH != 32 && LV_COLOR_SCREEN_TRANSP != 0
@@ -37,24 +35,24 @@ extern "C" {
/*********************
* DEFINES
*********************/
-#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_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)
-#define LV_COLOR_YELLOW LV_COLOR_MAKE(0xFF, 0xFF, 0x00)
-#define LV_COLOR_OLIVE LV_COLOR_MAKE(0x80, 0x80, 0x00)
-#define LV_COLOR_LIME LV_COLOR_MAKE(0x00, 0xFF, 0x00)
-#define LV_COLOR_GREEN LV_COLOR_MAKE(0x00, 0x80, 0x00)
-#define LV_COLOR_CYAN LV_COLOR_MAKE(0x00, 0xFF, 0xFF)
-#define LV_COLOR_AQUA LV_COLOR_CYAN
-#define LV_COLOR_TEAL LV_COLOR_MAKE(0x00, 0x80, 0x80)
-#define LV_COLOR_BLUE LV_COLOR_MAKE(0x00, 0x00, 0xFF)
-#define LV_COLOR_NAVY LV_COLOR_MAKE(0x00, 0x00, 0x80)
+#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_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)
+#define LV_COLOR_YELLOW LV_COLOR_MAKE(0xFF, 0xFF, 0x00)
+#define LV_COLOR_OLIVE LV_COLOR_MAKE(0x80, 0x80, 0x00)
+#define LV_COLOR_LIME LV_COLOR_MAKE(0x00, 0xFF, 0x00)
+#define LV_COLOR_GREEN LV_COLOR_MAKE(0x00, 0x80, 0x00)
+#define LV_COLOR_CYAN LV_COLOR_MAKE(0x00, 0xFF, 0xFF)
+#define LV_COLOR_AQUA LV_COLOR_CYAN
+#define LV_COLOR_TEAL LV_COLOR_MAKE(0x00, 0x80, 0x80)
+#define LV_COLOR_BLUE LV_COLOR_MAKE(0x00, 0x00, 0xFF)
+#define LV_COLOR_NAVY LV_COLOR_MAKE(0x00, 0x00, 0x80)
#define LV_COLOR_MAGENTA LV_COLOR_MAKE(0xFF, 0x00, 0xFF)
-#define LV_COLOR_PURPLE LV_COLOR_MAKE(0x80, 0x00, 0x80)
-#define LV_COLOR_ORANGE LV_COLOR_MAKE(0xFF, 0xA5, 0x00)
+#define LV_COLOR_PURPLE LV_COLOR_MAKE(0x80, 0x00, 0x80)
+#define LV_COLOR_ORANGE LV_COLOR_MAKE(0xFF, 0xA5, 0x00)
/**
* Opacity percentages.
@@ -75,8 +73,8 @@ enum {
LV_OPA_COVER = 255,
};
-#define LV_OPA_MIN 16 /*Opacities below this will be transparent*/
-#define LV_OPA_MAX 251 /*Opacities above this will fully cover*/
+#define LV_OPA_MIN 2 /*Opacities below this will be transparent*/
+#define LV_OPA_MAX 253 /*Opacities above this will fully cover*/
#if LV_COLOR_DEPTH == 1
#define LV_COLOR_SIZE 8
@@ -90,23 +88,70 @@ enum {
#error "Invalid LV_COLOR_DEPTH in lv_conf.h! Set it to 1, 8, 16 or 32!"
#endif
+/* Adjust color mix functions rounding.
+ * GPUs might calculate color mix (blending) differently.
+ * Should be in range of 0..254
+ * 0: no adjustment, get the integer part of the result (round down)
+ * 64: round up from x.75
+ * 128: round up from half
+ * 192: round up from x.25
+ * 254: round up */
+#ifndef LV_COLOR_MIX_ROUND_OFS
+#if LV_COLOR_DEPTH == 32
+#define LV_COLOR_MIX_ROUND_OFS 0
+#else
+#define LV_COLOR_MIX_ROUND_OFS 128
+#endif
+#endif
+
+#if defined(__cplusplus) && !defined(_LV_COLOR_HAS_MODERN_CPP)
+/**
+* MSVC compiler's definition of the __cplusplus indicating 199711L regardless to C++ standard version
+* see https://devblogs.microsoft.com/cppblog/msvc-now-correctly-reports-cplusplus
+* so we use _MSC_VER macro instead of __cplusplus
+*/
+#ifdef _MSC_VER
+#if _MSC_VER >= 1900 /* Visual Studio 2015 */
+#define _LV_COLOR_HAS_MODERN_CPP 1
+#endif
+#else
+#if __cplusplus >= 201103L
+#define _LV_COLOR_HAS_MODERN_CPP 1
+#endif
+#endif
+#endif /* __cplusplus */
+
+#ifndef _LV_COLOR_HAS_MODERN_CPP
+#define _LV_COLOR_HAS_MODERN_CPP 0
+#endif
+
+#if _LV_COLOR_HAS_MODERN_CPP
+/* Fix msvc compiler error C4576 inside C++ code */
+#define _LV_COLOR_MAKE_TYPE_HELPER lv_color_t
+#else
+#define _LV_COLOR_MAKE_TYPE_HELPER (lv_color_t)
+#endif
+
/*---------------------------------------
- * Macros for all existing color depths
+ * Macros for all existing color depths
* to set/get values of the color channels
*------------------------------------------*/
-# define LV_COLOR_SET_R1(c, v) (c).ch.red = (uint8_t)((v) & 0x1);
-# define LV_COLOR_SET_G1(c, v) (c).ch.green = (uint8_t)((v) & 0x1);
-# define LV_COLOR_SET_B1(c, v) (c).ch.blue = (uint8_t)((v) & 0x1);
-# define LV_COLOR_SET_A1(c, v)
+# define LV_COLOR_SET_R1(c, v) (c).ch.red = (uint8_t)((v) & 0x1)
+# define LV_COLOR_SET_G1(c, v) (c).ch.green = (uint8_t)((v) & 0x1)
+# define LV_COLOR_SET_B1(c, v) (c).ch.blue = (uint8_t)((v) & 0x1)
+# define LV_COLOR_SET_A1(c, v) do {} while(0)
# define LV_COLOR_GET_R1(c) (c).ch.red
# define LV_COLOR_GET_G1(c) (c).ch.green
# define LV_COLOR_GET_B1(c) (c).ch.blue
-# define LV_COLOR_GET_A1(c) 1
+# define LV_COLOR_GET_A1(c) 0xFF
-# define LV_COLOR_SET_R8(c, v) (c).ch.red = (uint8_t)(v) & 0x7U;
-# define LV_COLOR_SET_G8(c, v) (c).ch.green = (uint8_t)(v) & 0x7U;
-# define LV_COLOR_SET_B8(c, v) (c).ch.blue = (uint8_t)(v) & 0x3U;
+# define _LV_COLOR_ZERO_INITIALIZER1 {0x00}
+# define LV_COLOR_MAKE1(r8, g8, b8) (_LV_COLOR_MAKE_TYPE_HELPER{(uint8_t)((b8 >> 7) | (g8 >> 7) | (r8 >> 7))})
+
+# define LV_COLOR_SET_R8(c, v) (c).ch.red = (uint8_t)((v) & 0x7U)
+# define LV_COLOR_SET_G8(c, v) (c).ch.green = (uint8_t)((v) & 0x7U)
+# define LV_COLOR_SET_B8(c, v) (c).ch.blue = (uint8_t)((v) & 0x3U)
# define LV_COLOR_SET_A8(c, v) do {} while(0)
# define LV_COLOR_GET_R8(c) (c).ch.red
@@ -114,105 +159,80 @@ enum {
# define LV_COLOR_GET_B8(c) (c).ch.blue
# define LV_COLOR_GET_A8(c) 0xFF
-# define LV_COLOR_SET_R16(c, v) (c).ch.red = (uint8_t)(v) & 0x1FU;
-# define LV_COLOR_SET_G16(c, v) (c).ch.green = (uint8_t)(v) & 0x3FU;
-# define LV_COLOR_SET_G16_SWAP(c, v) {(c).ch.green_h = (uint8_t)(((v) >> 3) & 0x7); (c).ch.green_l = (uint8_t)((v) & 0x7);}
-# define LV_COLOR_SET_B16(c, v) (c).ch.blue = (uint8_t)(v) & 0x1FU;
+# define _LV_COLOR_ZERO_INITIALIZER8 {{0x00, 0x00, 0x00}}
+# define LV_COLOR_MAKE8(r8, g8, b8) (_LV_COLOR_MAKE_TYPE_HELPER{{(uint8_t)((b8 >> 6) & 0x3U), (uint8_t)((g8 >> 5) & 0x7U), (uint8_t)((r8 >> 5) & 0x7U)}})
+
+# define LV_COLOR_SET_R16(c, v) (c).ch.red = (uint8_t)((v) & 0x1FU)
+#if LV_COLOR_16_SWAP == 0
+# define LV_COLOR_SET_G16(c, v) (c).ch.green = (uint8_t)((v) & 0x3FU)
+#else
+# define LV_COLOR_SET_G16(c, v) {(c).ch.green_h = (uint8_t)(((v) >> 3) & 0x7); (c).ch.green_l = (uint8_t)((v) & 0x7);}
+#endif
+# define LV_COLOR_SET_B16(c, v) (c).ch.blue = (uint8_t)((v) & 0x1FU)
# define LV_COLOR_SET_A16(c, v) do {} while(0)
# define LV_COLOR_GET_R16(c) (c).ch.red
+#if LV_COLOR_16_SWAP == 0
# define LV_COLOR_GET_G16(c) (c).ch.green
-# define LV_COLOR_GET_G16_SWAP(c) (((c).ch.green_h << 3) + (c).ch.green_l)
+#else
+# define LV_COLOR_GET_G16(c) (((c).ch.green_h << 3) + (c).ch.green_l)
+#endif
# define LV_COLOR_GET_B16(c) (c).ch.blue
# define LV_COLOR_GET_A16(c) 0xFF
-# define LV_COLOR_SET_R32(c, v) (c).ch.red = (uint32_t)((v) & 0xFF);
-# define LV_COLOR_SET_G32(c, v) (c).ch.green = (uint32_t)((v) & 0xFF);
-# define LV_COLOR_SET_B32(c, v) (c).ch.blue = (uint32_t)((v) & 0xFF);
-# define LV_COLOR_SET_A32(c, v) (c).ch.alpha = (uint32_t)((v) & 0xFF);
+#if LV_COLOR_16_SWAP == 0
+# define _LV_COLOR_ZERO_INITIALIZER16 {{0x00, 0x00, 0x00}}
+# define LV_COLOR_MAKE16(r8, g8, b8) (_LV_COLOR_MAKE_TYPE_HELPER{{(uint8_t)((b8 >> 3) & 0x1FU), (uint8_t)((g8 >> 2) & 0x3FU), (uint8_t)((r8 >> 3) & 0x1FU)}})
+#else
+# define _LV_COLOR_ZERO_INITIALIZER16 {{0x00, 0x00, 0x00, 0x00}}
+# define LV_COLOR_MAKE16(r8, g8, b8) (_LV_COLOR_MAKE_TYPE_HELPER{{(uint8_t)((g8 >> 5) & 0x7U), (uint8_t)((r8 >> 3) & 0x1FU), (uint8_t)((b8 >> 3) & 0x1FU), (uint8_t)((g8 >> 2) & 0x7U)}})
+#endif
+
+# define LV_COLOR_SET_R32(c, v) (c).ch.red = (uint8_t)((v) & 0xFF)
+# define LV_COLOR_SET_G32(c, v) (c).ch.green = (uint8_t)((v) & 0xFF)
+# define LV_COLOR_SET_B32(c, v) (c).ch.blue = (uint8_t)((v) & 0xFF)
+# define LV_COLOR_SET_A32(c, v) (c).ch.alpha = (uint8_t)((v) & 0xFF)
# define LV_COLOR_GET_R32(c) (c).ch.red
# define LV_COLOR_GET_G32(c) (c).ch.green
# define LV_COLOR_GET_B32(c) (c).ch.blue
# define LV_COLOR_GET_A32(c) (c).ch.alpha
+# define _LV_COLOR_ZERO_INITIALIZER32 {{0x00, 0x00, 0x00, 0x00}}
+# define LV_COLOR_MAKE32(r8, g8, b8) (_LV_COLOR_MAKE_TYPE_HELPER{{b8, g8, r8, 0xff}}) /*Fix 0xff alpha*/
/*---------------------------------------
* Macros for the current color depth
* to set/get values of the color channels
*------------------------------------------*/
-#if LV_COLOR_DEPTH == 1
-# define LV_COLOR_SET_R(c, v) LV_COLOR_SET_R1(c,v)
-# define LV_COLOR_SET_G(c, v) LV_COLOR_SET_G1(c,v)
-# define LV_COLOR_SET_B(c, v) LV_COLOR_SET_B1(c,v)
-# define LV_COLOR_SET_A(c, v) LV_COLOR_SET_A1(c,v)
-
-# define LV_COLOR_GET_R(c) LV_COLOR_GET_R1(c)
-# define LV_COLOR_GET_G(c) LV_COLOR_GET_G1(c)
-# define LV_COLOR_GET_B(c) LV_COLOR_GET_B1(c)
-# define LV_COLOR_GET_A(c) LV_COLOR_GET_A1(c)
-
-#elif LV_COLOR_DEPTH == 8
-# define LV_COLOR_SET_R(c, v) LV_COLOR_SET_R8(c,v)
-# define LV_COLOR_SET_G(c, v) LV_COLOR_SET_G8(c,v)
-# define LV_COLOR_SET_B(c, v) LV_COLOR_SET_B8(c,v)
-# define LV_COLOR_SET_A(c, v) LV_COLOR_SET_A8(c,v)
+#define LV_COLOR_SET_R(c, v) LV_CONCAT(LV_COLOR_SET_R, LV_COLOR_DEPTH)(c, v)
+#define LV_COLOR_SET_G(c, v) LV_CONCAT(LV_COLOR_SET_G, LV_COLOR_DEPTH)(c, v)
+#define LV_COLOR_SET_B(c, v) LV_CONCAT(LV_COLOR_SET_B, LV_COLOR_DEPTH)(c, v)
+#define LV_COLOR_SET_A(c, v) LV_CONCAT(LV_COLOR_SET_A, LV_COLOR_DEPTH)(c, v)
-# define LV_COLOR_GET_R(c) LV_COLOR_GET_R8(c)
-# define LV_COLOR_GET_G(c) LV_COLOR_GET_G8(c)
-# define LV_COLOR_GET_B(c) LV_COLOR_GET_B8(c)
-# define LV_COLOR_GET_A(c) LV_COLOR_GET_A8(c)
+#define LV_COLOR_GET_R(c) LV_CONCAT(LV_COLOR_GET_R, LV_COLOR_DEPTH)(c)
+#define LV_COLOR_GET_G(c) LV_CONCAT(LV_COLOR_GET_G, LV_COLOR_DEPTH)(c)
+#define LV_COLOR_GET_B(c) LV_CONCAT(LV_COLOR_GET_B, LV_COLOR_DEPTH)(c)
+#define LV_COLOR_GET_A(c) LV_CONCAT(LV_COLOR_GET_A, LV_COLOR_DEPTH)(c)
-#elif LV_COLOR_DEPTH == 16
-# define LV_COLOR_SET_R(c, v) LV_COLOR_SET_R16(c,v)
-# if LV_COLOR_16_SWAP == 0
-# define LV_COLOR_SET_G(c, v) LV_COLOR_SET_G16(c,v)
-# else
-# define LV_COLOR_SET_G(c, v) LV_COLOR_SET_G16_SWAP(c,v)
-# endif
-# define LV_COLOR_SET_B(c, v) LV_COLOR_SET_B16(c,v)
-# define LV_COLOR_SET_A(c, v) LV_COLOR_SET_A16(c,v)
-
-# define LV_COLOR_GET_R(c) LV_COLOR_GET_R16(c)
-# if LV_COLOR_16_SWAP == 0
-# define LV_COLOR_GET_G(c) LV_COLOR_GET_G16(c)
-# else
-# define LV_COLOR_GET_G(c) LV_COLOR_GET_G16_SWAP(c)
-# endif
-# define LV_COLOR_GET_B(c) LV_COLOR_GET_B16(c)
-# define LV_COLOR_GET_A(c) LV_COLOR_GET_A16(c)
-
-#elif LV_COLOR_DEPTH == 32
-# define LV_COLOR_SET_R(c, v) LV_COLOR_SET_R32(c,v)
-# define LV_COLOR_SET_G(c, v) LV_COLOR_SET_G32(c,v)
-# define LV_COLOR_SET_B(c, v) LV_COLOR_SET_B32(c,v)
-# define LV_COLOR_SET_A(c, v) LV_COLOR_SET_A32(c,v)
-
-# define LV_COLOR_GET_R(c) LV_COLOR_GET_R32(c)
-# define LV_COLOR_GET_G(c) LV_COLOR_GET_G32(c)
-# define LV_COLOR_GET_B(c) LV_COLOR_GET_B32(c)
-# define LV_COLOR_GET_A(c) LV_COLOR_GET_A32(c)
-#endif
+#define _LV_COLOR_ZERO_INITIALIZER LV_CONCAT(_LV_COLOR_ZERO_INITIALIZER, LV_COLOR_DEPTH)
+#define LV_COLOR_MAKE(r8, g8, b8) LV_CONCAT(LV_COLOR_MAKE, LV_COLOR_DEPTH)(r8, g8, b8)
/**********************
* TYPEDEFS
**********************/
-typedef union
-{
- struct
- {
+typedef union {
+ uint8_t full; /*must be declared first to set all bits of byte via initializer list */
+ union {
uint8_t blue : 1;
uint8_t green : 1;
uint8_t red : 1;
} ch;
- uint8_t full;
} lv_color1_t;
-typedef union
-{
- struct
- {
+typedef union {
+ struct {
uint8_t blue : 2;
uint8_t green : 3;
uint8_t red : 3;
@@ -220,10 +240,8 @@ typedef union
uint8_t full;
} lv_color8_t;
-typedef union
-{
- struct
- {
+typedef union {
+ struct {
#if LV_COLOR_16_SWAP == 0
uint16_t blue : 5;
uint16_t green : 6;
@@ -238,10 +256,8 @@ typedef union
uint16_t full;
} lv_color16_t;
-typedef union
-{
- struct
- {
+typedef union {
+ struct {
uint8_t blue;
uint8_t green;
uint8_t red;
@@ -250,31 +266,20 @@ typedef union
uint32_t full;
} lv_color32_t;
-#if LV_COLOR_DEPTH == 1
-typedef uint8_t lv_color_int_t;
-typedef lv_color1_t lv_color_t;
-#elif LV_COLOR_DEPTH == 8
-typedef uint8_t lv_color_int_t;
-typedef lv_color8_t lv_color_t;
-#elif LV_COLOR_DEPTH == 16
-typedef uint16_t lv_color_int_t;
-typedef lv_color16_t lv_color_t;
-#elif LV_COLOR_DEPTH == 32
-typedef uint32_t lv_color_int_t;
-typedef lv_color32_t lv_color_t;
-#else
-#error "Invalid LV_COLOR_DEPTH in lv_conf.h! Set it to 1, 8, 16 or 32!"
-#endif
-
-typedef uint8_t lv_opa_t;
+typedef LV_CONCAT3(uint, LV_COLOR_SIZE, _t) lv_color_int_t;
+typedef LV_CONCAT3(lv_color, LV_COLOR_DEPTH, _t) lv_color_t;
-typedef struct
-{
+typedef struct {
uint16_t h;
uint8_t s;
uint8_t v;
} lv_color_hsv_t;
+//! @cond Doxygen_Suppress
+/*No idea where the guard is required but else throws warnings in the docs*/
+typedef uint8_t lv_opa_t;
+//! @endcond
+
/**********************
* GLOBAL PROTOTYPES
**********************/
@@ -282,17 +287,16 @@ typedef struct
/*In color conversations:
* - When converting to bigger color type the LSB weight of 1 LSB is calculated
* E.g. 16 bit Red has 5 bits
- * 8 bit Red has 2 bits
+ * 8 bit Red has 3 bits
* ----------------------
- * 8 bit red LSB = (2^5 - 1) / (2^2 - 1) = 31 / 3 = 10
+ * 8 bit red LSB = (2^5 - 1) / (2^3 - 1) = 31 / 7 = 4
*
* - When calculating to smaller color type simply shift out the LSBs
- * E.g. 8 bit Red has 2 bits
+ * E.g. 8 bit Red has 3 bits
* 16 bit Red has 5 bits
* ----------------------
* Shift right with 5 - 3 = 2
*/
-
static inline uint8_t lv_color_to1(lv_color_t color)
{
#if LV_COLOR_DEPTH == 1
@@ -300,19 +304,22 @@ static inline uint8_t lv_color_to1(lv_color_t color)
#elif LV_COLOR_DEPTH == 8
if((LV_COLOR_GET_R(color) & 0x4) || (LV_COLOR_GET_G(color) & 0x4) || (LV_COLOR_GET_B(color) & 0x2)) {
return 1;
- } else {
+ }
+ else {
return 0;
}
#elif LV_COLOR_DEPTH == 16
if((LV_COLOR_GET_R(color) & 0x10) || (LV_COLOR_GET_G(color) & 0x20) || (LV_COLOR_GET_B(color) & 0x10)) {
return 1;
- } else {
+ }
+ else {
return 0;
}
#elif LV_COLOR_DEPTH == 32
if((LV_COLOR_GET_R(color) & 0x80) || (LV_COLOR_GET_G(color) & 0x80) || (LV_COLOR_GET_B(color) & 0x80)) {
return 1;
- } else {
+ }
+ else {
return 0;
}
#endif
@@ -329,15 +336,15 @@ static inline uint8_t lv_color_to8(lv_color_t color)
return color.full;
#elif LV_COLOR_DEPTH == 16
lv_color8_t ret;
- LV_COLOR_SET_R8(ret, LV_COLOR_GET_R(color) >> 2); /* 5 - 3 = 2*/
+ LV_COLOR_SET_R8(ret, LV_COLOR_GET_R(color) >> 2); /* 5 - 3 = 2*/
LV_COLOR_SET_G8(ret, LV_COLOR_GET_G(color) >> 3); /* 6 - 3 = 3*/
- LV_COLOR_SET_B8(ret, LV_COLOR_GET_B(color) >> 3); /* 5 - 2 = 3*/
+ LV_COLOR_SET_B8(ret, LV_COLOR_GET_B(color) >> 3); /* 5 - 2 = 3*/
return ret.full;
#elif LV_COLOR_DEPTH == 32
lv_color8_t ret;
- LV_COLOR_SET_R8(ret, LV_COLOR_GET_R(color) >> 5); /* 8 - 3 = 5*/
+ LV_COLOR_SET_R8(ret, LV_COLOR_GET_R(color) >> 5); /* 8 - 3 = 5*/
LV_COLOR_SET_G8(ret, LV_COLOR_GET_G(color) >> 5); /* 8 - 3 = 5*/
- LV_COLOR_SET_B8(ret, LV_COLOR_GET_B(color) >> 6); /* 8 - 2 = 6*/
+ LV_COLOR_SET_B8(ret, LV_COLOR_GET_B(color) >> 6); /* 8 - 2 = 6*/
return ret.full;
#endif
}
@@ -351,42 +358,33 @@ static inline uint16_t lv_color_to16(lv_color_t color)
return 0xFFFF;
#elif LV_COLOR_DEPTH == 8
lv_color16_t ret;
- LV_COLOR_SET_R16(ret, LV_COLOR_GET_R(color) * 4); /*(2^5 - 1)/(2^3 - 1) = 31/7 = 4*/
-#if LV_COLOR_16_SWAP == 0
- LV_COLOR_SET_G16(ret, LV_COLOR_GET_G(color) * 9); /*(2^6 - 1)/(2^3 - 1) = 63/7 = 9*/
-#else
- LV_COLOR_SET_G16_SWAP(ret, (LV_COLOR_GET_G(color) * 9)); /*(2^6 - 1)/(2^3 - 1) = 63/7 = 9*/
-#endif
- LV_COLOR_SET_B16(ret, LV_COLOR_GET_B(color) * 10); /*(2^5 - 1)/(2^2 - 1) = 31/3 = 10*/
+ LV_COLOR_SET_R16(ret, LV_COLOR_GET_R(color) * 4); /*(2^5 - 1)/(2^3 - 1) = 31/7 = 4*/
+ LV_COLOR_SET_G16(ret, LV_COLOR_GET_G(color) * 9); /*(2^6 - 1)/(2^3 - 1) = 63/7 = 9*/
+ LV_COLOR_SET_B16(ret, LV_COLOR_GET_B(color) * 10); /*(2^5 - 1)/(2^2 - 1) = 31/3 = 10*/
return ret.full;
#elif LV_COLOR_DEPTH == 16
return color.full;
#elif LV_COLOR_DEPTH == 32
lv_color16_t ret;
- LV_COLOR_SET_R16(ret, LV_COLOR_GET_R(color) >> 3); /* 8 - 5 = 3*/
-
-#if LV_COLOR_16_SWAP == 0
+ LV_COLOR_SET_R16(ret, LV_COLOR_GET_R(color) >> 3); /* 8 - 5 = 3*/
LV_COLOR_SET_G16(ret, LV_COLOR_GET_G(color) >> 2); /* 8 - 6 = 2*/
-#else
- LV_COLOR_SET_G16_SWAP(ret, ret.ch.green_h = (LV_COLOR_GET_G(color) >> 2); /*(2^6 - 1)/(2^3 - 1) = 63/7 = 9*/
-#endif
- LV_COLOR_SET_B16(ret, LV_COLOR_GET_B(color) >> 3); /* 8 - 5 = 3*/
+ LV_COLOR_SET_B16(ret, LV_COLOR_GET_B(color) >> 3); /* 8 - 5 = 3*/
return ret.full;
-#endif
+#endif
}
static inline uint32_t lv_color_to32(lv_color_t color)
{
#if LV_COLOR_DEPTH == 1
if(color.full == 0)
- return 0;
+ return 0xFF000000;
else
return 0xFFFFFFFF;
#elif LV_COLOR_DEPTH == 8
lv_color32_t ret;
- LV_COLOR_SET_R32(ret, LV_COLOR_GET_R(color) * 36); /*(2^8 - 1)/(2^3 - 1) = 255/7 = 36*/
+ LV_COLOR_SET_R32(ret, LV_COLOR_GET_R(color) * 36); /*(2^8 - 1)/(2^3 - 1) = 255/7 = 36*/
LV_COLOR_SET_G32(ret, LV_COLOR_GET_G(color) * 36); /*(2^8 - 1)/(2^3 - 1) = 255/7 = 36*/
- LV_COLOR_SET_B32(ret, LV_COLOR_GET_B(color) * 85); /*(2^8 - 1)/(2^2 - 1) = 255/3 = 85*/
+ LV_COLOR_SET_B32(ret, LV_COLOR_GET_B(color) * 85); /*(2^8 - 1)/(2^2 - 1) = 255/3 = 85*/
LV_COLOR_SET_A32(ret, 0xFF);
return ret.full;
#elif LV_COLOR_DEPTH == 16
@@ -396,9 +394,9 @@ static inline uint32_t lv_color_to32(lv_color_t color)
* The faster integer math for conversion is:
* valueto = ( valuefrom * multiplier + adder ) >> divisor
* multiplier = FLOOR( ( (2^bitsto - 1) << divisor ) / (float)(2^bitsfrom - 1) )
- *
+ *
* Find the first divisor where ( adder >> divisor ) <= 0
- *
+ *
* 5-bit to 8-bit: ( 31 * multiplier + adder ) >> divisor = 255
* divisor multiplier adder min (0) max (31)
* 0 8 7 7 255
@@ -407,7 +405,7 @@ static inline uint32_t lv_color_to32(lv_color_t color)
* 3 65 25 3 255
* 4 131 19 1 255
* 5 263 7 0 255
- *
+ *
* 6-bit to 8-bit: 255 = ( 63 * multiplier + adder ) >> divisor
* divisor multiplier adder min (0) max (63)
* 0 4 3 3 255
@@ -418,10 +416,11 @@ static inline uint32_t lv_color_to32(lv_color_t color)
* 5 129 33 1 255
* 6 259 3 0 255
*/
+
lv_color32_t ret;
- LV_COLOR_SET_R32(ret, (LV_COLOR_GET_R(color) * 263 + 7 ) >> 5);
- LV_COLOR_SET_G32(ret, (LV_COLOR_GET_G(color) * 259 + 3 ) >> 6);
- LV_COLOR_SET_B32(ret, (LV_COLOR_GET_B(color) * 263 + 7 ) >> 5);
+ LV_COLOR_SET_R32(ret, (LV_COLOR_GET_R(color) * 263 + 7) >> 5);
+ LV_COLOR_SET_G32(ret, (LV_COLOR_GET_G(color) * 259 + 3) >> 6);
+ LV_COLOR_SET_B32(ret, (LV_COLOR_GET_B(color) * 263 + 7) >> 5);
LV_COLOR_SET_A32(ret, 0xFF);
return ret.full;
#elif LV_COLOR_DEPTH == 32
@@ -429,14 +428,26 @@ static inline uint32_t lv_color_to32(lv_color_t color)
#endif
}
-static inline lv_color_t lv_color_mix(lv_color_t c1, lv_color_t c2, uint8_t mix)
+//! @cond Doxygen_Suppress
+
+/**
+ * Mix two colors with a given ratio.
+ * @param c1 the first color to mix (usually the foreground)
+ * @param c2 the second color to mix (usually the background)
+ * @param mix The ratio of the colors. 0: full `c2`, 255: full `c1`, 127: half `c1` and half`c2`
+ * @return the mixed color
+ */
+LV_ATTRIBUTE_FAST_MEM static inline lv_color_t lv_color_mix(lv_color_t c1, lv_color_t c2, uint8_t mix)
{
lv_color_t ret;
#if LV_COLOR_DEPTH != 1
/*LV_COLOR_DEPTH == 8, 16 or 32*/
- LV_COLOR_SET_R(ret, (uint16_t)((uint16_t) LV_COLOR_GET_R(c1) * mix + LV_COLOR_GET_R(c2) * (255 - mix)) >> 8);
- LV_COLOR_SET_G(ret, (uint16_t)((uint16_t) LV_COLOR_GET_G(c1) * mix + LV_COLOR_GET_G(c2) * (255 - mix)) >> 8);
- LV_COLOR_SET_B(ret, (uint16_t)((uint16_t) LV_COLOR_GET_B(c1) * mix + LV_COLOR_GET_B(c2) * (255 - mix)) >> 8);
+ LV_COLOR_SET_R(ret, LV_MATH_UDIV255((uint16_t) LV_COLOR_GET_R(c1) * mix + LV_COLOR_GET_R(c2) *
+ (255 - mix) + LV_COLOR_MIX_ROUND_OFS));
+ LV_COLOR_SET_G(ret, LV_MATH_UDIV255((uint16_t) LV_COLOR_GET_G(c1) * mix + LV_COLOR_GET_G(c2) *
+ (255 - mix) + LV_COLOR_MIX_ROUND_OFS));
+ LV_COLOR_SET_B(ret, LV_MATH_UDIV255((uint16_t) LV_COLOR_GET_B(c1) * mix + LV_COLOR_GET_B(c2) *
+ (255 - mix) + LV_COLOR_MIX_ROUND_OFS));
LV_COLOR_SET_A(ret, 0xFF);
#else
/*LV_COLOR_DEPTH == 1*/
@@ -446,6 +457,116 @@ static inline lv_color_t lv_color_mix(lv_color_t c1, lv_color_t c2, uint8_t mix)
return ret;
}
+LV_ATTRIBUTE_FAST_MEM static inline void lv_color_premult(lv_color_t c, uint8_t mix, uint16_t * out)
+{
+#if LV_COLOR_DEPTH != 1
+ out[0] = (uint16_t) LV_COLOR_GET_R(c) * mix;
+ out[1] = (uint16_t) LV_COLOR_GET_G(c) * mix;
+ out[2] = (uint16_t) LV_COLOR_GET_B(c) * mix;
+#else
+ (void) mix;
+ /*Pre-multiplication can't be used with 1 bpp*/
+ out[0] = LV_COLOR_GET_R(c);
+ out[1] = LV_COLOR_GET_G(c);
+ out[2] = LV_COLOR_GET_B(c);
+#endif
+
+}
+
+/**
+ * Mix two colors with a given ratio. It runs faster then `lv_color_mix` but requires some pre computation.
+ * @param premult_c1 The first color. Should be preprocessed with `lv_color_premult(c1)`
+ * @param c2 The second color. As it is no pre computation required on it
+ * @param mix The ratio of the colors. 0: full `c1`, 255: full `c2`, 127: half `c1` and half `c2`.
+ * Should be modified like mix = `255 - mix`
+ * @return the mixed color
+ * @note 255 won't give clearly `c1`.
+ */
+LV_ATTRIBUTE_FAST_MEM static inline lv_color_t lv_color_mix_premult(uint16_t * premult_c1, lv_color_t c2, uint8_t mix)
+{
+ lv_color_t ret;
+#if LV_COLOR_DEPTH != 1
+ /*LV_COLOR_DEPTH == 8, 16 or 32*/
+ LV_COLOR_SET_R(ret, LV_MATH_UDIV255(premult_c1[0] + LV_COLOR_GET_R(c2) * mix + LV_COLOR_MIX_ROUND_OFS));
+ LV_COLOR_SET_G(ret, LV_MATH_UDIV255(premult_c1[1] + LV_COLOR_GET_G(c2) * mix + LV_COLOR_MIX_ROUND_OFS));
+ LV_COLOR_SET_B(ret, LV_MATH_UDIV255(premult_c1[2] + LV_COLOR_GET_B(c2) * mix + LV_COLOR_MIX_ROUND_OFS));
+ LV_COLOR_SET_A(ret, 0xFF);
+#else
+ /*LV_COLOR_DEPTH == 1*/
+ /*Restore color1*/
+ lv_color_t c1;
+ LV_COLOR_SET_R(c1, premult_c1[0]);
+ LV_COLOR_SET_G(c1, premult_c1[1]);
+ LV_COLOR_SET_B(c1, premult_c1[2]);
+ ret.full = mix > LV_OPA_50 ? c2.full : c1.full;
+#endif
+
+ return ret;
+}
+
+/**
+ * Mix two colors. Both color can have alpha value.
+ * @param bg_color background color
+ * @param bg_opa alpha of the background color
+ * @param fg_color foreground color
+ * @param fg_opa alpha of the foreground color
+ * @param res_color the result color
+ * @param res_opa the result opacity
+ */
+LV_ATTRIBUTE_FAST_MEM static inline void lv_color_mix_with_alpha(lv_color_t bg_color, lv_opa_t bg_opa,
+ lv_color_t fg_color, lv_opa_t fg_opa,
+ lv_color_t * res_color, lv_opa_t * res_opa)
+{
+ /* Pick the foreground if it's fully opaque or the Background is fully transparent*/
+ if(fg_opa >= LV_OPA_MAX || bg_opa <= LV_OPA_MIN) {
+ res_color->full = fg_color.full;
+ *res_opa = fg_opa;
+ }
+ /*Transparent foreground: use the Background*/
+ else if(fg_opa <= LV_OPA_MIN) {
+ res_color->full = bg_color.full;
+ *res_opa = bg_opa;
+ }
+ /*Opaque background: use simple mix*/
+ else if(bg_opa >= LV_OPA_MAX) {
+ *res_color = lv_color_mix(fg_color, bg_color, fg_opa);
+ *res_opa = LV_OPA_COVER;
+ }
+ /*Both colors have alpha. Expensive calculation need to be applied*/
+ else {
+ /*Save the parameters and the result. If they will be asked again don't compute again*/
+ static lv_opa_t fg_opa_save = 0;
+ static lv_opa_t bg_opa_save = 0;
+ static lv_color_t fg_color_save = _LV_COLOR_ZERO_INITIALIZER;
+ static lv_color_t bg_color_save = _LV_COLOR_ZERO_INITIALIZER;
+ static lv_color_t res_color_saved = _LV_COLOR_ZERO_INITIALIZER;
+ static lv_opa_t res_opa_saved = 0;
+
+ if(fg_opa != fg_opa_save || bg_opa != bg_opa_save || fg_color.full != fg_color_save.full ||
+ bg_color.full != bg_color_save.full) {
+ fg_opa_save = fg_opa;
+ bg_opa_save = bg_opa;
+ 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*/
+ res_opa_saved = 255 - ((uint16_t)((uint16_t)(255 - fg_opa) * (255 - bg_opa)) >> 8);
+ if(res_opa_saved == 0) {
+ while(1)
+ ;
+ }
+ lv_opa_t ratio = (uint16_t)((uint16_t)fg_opa * 255) / res_opa_saved;
+ res_color_saved = lv_color_mix(fg_color, bg_color, ratio);
+
+ }
+
+ res_color->full = res_color_saved.full;
+ *res_opa = res_opa_saved;
+ }
+}
+
+//! @endcond
+
/**
* Get the brightness of a color
* @param color a color
@@ -459,21 +580,6 @@ static inline uint8_t lv_color_brightness(lv_color_t color)
return (uint8_t)(bright >> 3);
}
-/* The most simple macro to create a color from R,G and B values */
-#if LV_COLOR_DEPTH == 1
-#define LV_COLOR_MAKE(r8, g8, b8) ((lv_color_t){.full = (uint8_t)((b8 >> 7) | (g8 >> 7) | (r8 >> 7))})
-#elif LV_COLOR_DEPTH == 8
-#define LV_COLOR_MAKE(r8, g8, b8) ((lv_color_t){{(uint8_t)((b8 >> 6) & 0x3U), (uint8_t)((g8 >> 5) & 0x7U), (uint8_t)((r8 >> 5) & 0x7U)}})
-#elif LV_COLOR_DEPTH == 16
-#if LV_COLOR_16_SWAP == 0
-#define LV_COLOR_MAKE(r8, g8, b8) ((lv_color_t){{(uint16_t)((b8 >> 3) & 0x1FU), (uint16_t)((g8 >> 2) & 0x3FU), (uint16_t)((r8 >> 3) & 0x1FU)}})
-#else
-#define LV_COLOR_MAKE(r8, g8, b8) ((lv_color_t){{(uint16_t)((g8 >> 5) & 0x7U), (uint16_t)((r8 >> 3) & 0x1FU), (uint16_t)((b8 >> 3) & 0x1FU), (uint16_t)((g8 >> 2) & 0x7U)}})
-#endif
-#elif LV_COLOR_DEPTH == 32
-#define LV_COLOR_MAKE(r8, g8, b8) ((lv_color_t){{b8, g8, r8, 0xff}}) /*Fix 0xff alpha*/
-#endif
-
static inline lv_color_t lv_color_make(uint8_t r, uint8_t g, uint8_t b)
{
return LV_COLOR_MAKE(r, g, b);
@@ -490,6 +596,15 @@ static inline lv_color_t lv_color_hex3(uint32_t c)
(uint8_t)((c & 0xF) | ((c & 0xF) << 4)));
}
+//! @cond Doxygen_Suppress
+//!
+LV_ATTRIBUTE_FAST_MEM void lv_color_fill(lv_color_t * buf, lv_color_t color, uint32_t px_num);
+
+//! @endcond
+lv_color_t lv_color_lighten(lv_color_t c, lv_opa_t lvl);
+
+lv_color_t lv_color_darken(lv_color_t c, lv_opa_t lvl);
+
/**
* Convert a HSV color to RGB
* @param h hue [0..359]
@@ -523,4 +638,4 @@ lv_color_hsv_t lv_color_to_hsv(lv_color_t color);
} /* extern "C" */
#endif
-#endif /*USE_COLOR*/
+#endif /*LV_COLOR_H*/
diff --git a/src/libs/lvgl/src/lv_misc/lv_debug.c b/src/libs/lvgl/src/lv_misc/lv_debug.c
new file mode 100644
index 00000000..24fc78ff
--- /dev/null
+++ b/src/libs/lvgl/src/lv_misc/lv_debug.c
@@ -0,0 +1,138 @@
+/**
+ * @file lv_debug.c
+ *
+ */
+
+/*********************
+ * INCLUDES
+ *********************/
+#include "lv_debug.h"
+
+#if LV_USE_DEBUG
+
+#include "lv_mem.h"
+#include <string.h>
+
+/*********************
+ * DEFINES
+ *********************/
+#ifndef LV_DEBUG_STR_MAX_LENGTH
+ #define LV_DEBUG_STR_MAX_LENGTH (1024 * 8)
+#endif
+
+#ifndef LV_DEBUG_STR_MAX_REPEAT
+ #define LV_DEBUG_STR_MAX_REPEAT 8
+#endif
+/**********************
+ * TYPEDEFS
+ **********************/
+
+/**********************
+ * STATIC PROTOTYPES
+ **********************/
+
+/**********************
+ * STATIC VARIABLES
+ **********************/
+
+/**********************
+ * MACROS
+ **********************/
+
+/**********************
+ * GLOBAL FUNCTIONS
+ **********************/
+
+bool lv_debug_check_null(const void * p)
+{
+ if(p) return true;
+
+ return false;
+}
+
+bool lv_debug_check_mem_integrity(void)
+{
+ return lv_mem_test() == LV_RES_OK ? true : false;
+}
+
+bool lv_debug_check_str(const void * str)
+{
+ const uint8_t * s = (const uint8_t *)str;
+ uint8_t last_byte = 0;
+ uint32_t rep = 0;
+ uint32_t i;
+
+ for(i = 0; i < LV_DEBUG_STR_MAX_LENGTH && s[i] != '\0'; i++) {
+ if(s[i] != last_byte) {
+ last_byte = s[i];
+ rep = 1;
+ }
+ else if(s[i] > 0x7F) {
+ rep++;
+ if(rep > LV_DEBUG_STR_MAX_REPEAT) {
+ LV_LOG_WARN("lv_debug_check_str: a non-ASCII char has repeated more than LV_DEBUG_STR_MAX_REPEAT times)");
+ return false;
+ }
+ }
+
+ if(s[i] < 10) {
+ LV_LOG_WARN("lv_debug_check_str: invalid char in the string (< 10 value)");
+ return false; /*Shouldn't occur in strings*/
+ }
+ }
+
+ if(s[i] == '\0') return true;
+
+ LV_LOG_WARN("lv_debug_check_str: string is longer than LV_DEBUG_STR_MAX_LENGTH");
+ return false;
+}
+
+void lv_debug_log_error(const char * msg, uint64_t value)
+{
+ static const char hex[] = "0123456789ABCDEF";
+
+ size_t msg_len = strlen(msg);
+ uint32_t value_len = sizeof(unsigned long int);
+
+ if(msg_len < 230) {
+ char buf[255];
+ char * bufp = buf;
+
+ /*Add the function name*/
+ _lv_memcpy(bufp, msg, msg_len);
+ bufp += msg_len;
+
+ /*Add value in hey*/
+ *bufp = ' ';
+ bufp ++;
+ *bufp = '(';
+ bufp ++;
+ *bufp = '0';
+ bufp ++;
+ *bufp = 'x';
+ bufp ++;
+
+ int8_t i;
+ for(i = value_len * 2 - 1; i >= 0; i--) {
+ uint8_t x = (unsigned long int)((unsigned long int)value >> (i * 4)) & 0xF;
+
+ *bufp = hex[x];
+ bufp++;
+ }
+
+ *bufp = ')';
+ bufp ++;
+
+ *bufp = '\0';
+ LV_LOG_ERROR(buf);
+ }
+ else {
+ LV_LOG_ERROR(msg);
+ }
+}
+
+/**********************
+ * STATIC FUNCTIONS
+ **********************/
+
+#endif /*LV_USE_DEBUG*/
diff --git a/src/libs/lvgl/src/lv_misc/lv_debug.h b/src/libs/lvgl/src/lv_misc/lv_debug.h
new file mode 100644
index 00000000..82c92fe0
--- /dev/null
+++ b/src/libs/lvgl/src/lv_misc/lv_debug.h
@@ -0,0 +1,131 @@
+/**
+ * @file lv_debug.h
+ *
+ */
+
+#ifndef LV_DEBUG_H
+#define LV_DEBUG_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*********************
+ * INCLUDES
+ *********************/
+#include "../lv_conf_internal.h"
+
+#if LV_USE_DEBUG
+#include <stdbool.h>
+
+/*********************
+ * DEFINES
+ *********************/
+
+/**********************
+ * TYPEDEFS
+ **********************/
+
+/**********************
+ * GLOBAL PROTOTYPES
+ **********************/
+bool lv_debug_check_null(const void * p);
+
+bool lv_debug_check_mem_integrity(void);
+
+bool lv_debug_check_str(const void * str);
+
+void lv_debug_log_error(const char * msg, uint64_t value);
+
+/**********************
+ * MACROS
+ **********************/
+
+#ifndef LV_DEBUG_ASSERT
+#define LV_DEBUG_ASSERT(expr, msg, value) \
+ do { \
+ if(!(expr)) { \
+ LV_LOG_ERROR(__func__); \
+ lv_debug_log_error(msg, (uint64_t)((uintptr_t)value)); \
+ while(1); \
+ } \
+ } while(0)
+#endif
+
+/*----------------
+ * CHECKS
+ *----------------*/
+
+#ifndef LV_DEBUG_IS_NULL
+#define LV_DEBUG_IS_NULL(p) (lv_debug_check_null(p))
+#endif
+
+#ifndef LV_DEBUG_CHECK_MEM_INTEGRITY
+#define LV_DEBUG_CHECK_MEM_INTEGRITY() (lv_debug_check_mem_integrity())
+#endif
+
+#ifndef LV_DEBUG_IS_STR
+#define LV_DEBUG_IS_STR(str) (lv_debug_check_null(str) && \
+ lv_debug_check_str(str))
+#endif
+
+/*-----------------
+ * ASSERTS
+ *-----------------*/
+
+/*clang-format off*/
+
+#if LV_USE_ASSERT_NULL
+# ifndef LV_ASSERT_NULL
+# define LV_ASSERT_NULL(p) LV_DEBUG_ASSERT(LV_DEBUG_IS_NULL(p), "NULL pointer", p);
+# endif
+#else
+# define LV_ASSERT_NULL(p)
+#endif
+
+#if LV_USE_ASSERT_MEM
+# ifndef LV_ASSERT_MEM
+# define LV_ASSERT_MEM(p) LV_DEBUG_ASSERT(LV_DEBUG_IS_NULL(p), "Out of memory", p);
+# endif
+#else
+# define LV_ASSERT_MEM(p)
+#endif
+
+#if LV_USE_ASSERT_MEM_INTEGRITY
+# ifndef LV_ASSERT_MEM_INTEGRITY
+# define LV_ASSERT_MEM_INTEGRITY() LV_DEBUG_ASSERT(LV_DEBUG_CHECK_MEM_INTEGRITY(), "Memory integrity error", 0);
+# endif
+#else
+# define LV_ASSERT_MEM_INTEGRITY()
+#endif
+
+#if LV_USE_ASSERT_STR
+# ifndef LV_ASSERT_STR
+# define LV_ASSERT_STR(str) LV_DEBUG_ASSERT(LV_DEBUG_IS_STR(str), "Strange or invalid string", str);
+# endif
+#else /* LV_USE_ASSERT_OBJ == 0 */
+# if LV_USE_ASSERT_NULL /*Use at least LV_ASSERT_NULL if enabled*/
+# define LV_ASSERT_STR(str) LV_ASSERT_NULL(str)
+# else
+# define LV_ASSERT_STR(str)
+# endif
+#endif
+
+#else /* LV_USE_DEBUG == 0 */
+
+#define LV_DEBUG_ASSERT(expr, msg, value) do{}while(0)
+
+#define LV_ASSERT_NULL(p)
+#define LV_ASSERT_MEM(p)
+#define LV_ASSERT_MEM_INTEGRITY()
+#define LV_ASSERT_STR(p)
+#define LV_ASSERT_OBJ(obj, obj_type)
+
+#endif /* LV_USE_DEBUG */
+/*clang-format on*/
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+#endif /*LV_DEBUG_H*/
diff --git a/src/libs/lvgl/src/lv_misc/lv_fs.c b/src/libs/lvgl/src/lv_misc/lv_fs.c
index a23081ce..6f66c765 100644
--- a/src/libs/lvgl/src/lv_misc/lv_fs.c
+++ b/src/libs/lvgl/src/lv_misc/lv_fs.c
@@ -9,15 +9,11 @@
#include "lv_fs.h"
#if LV_USE_FILESYSTEM
-#include "../lv_core/lv_debug.h"
+#include "../lv_misc/lv_debug.h"
#include "lv_ll.h"
#include <string.h>
#include "lv_gc.h"
-#if defined(LV_GC_INCLUDE)
-#include LV_GC_INCLUDE
-#endif /* LV_ENABLE_GC */
-
/*********************
* DEFINES
*********************/
@@ -27,7 +23,7 @@
* free function, otherwise compilation would fail.
*/
#ifdef free
-#undef free
+ #undef free
#endif
/**********************
@@ -54,13 +50,13 @@ static const char * lv_fs_get_real_path(const char * path);
/**
* Initialize the File system interface
*/
-void lv_fs_init(void)
+void _lv_fs_init(void)
{
- lv_ll_init(&LV_GC_ROOT(_lv_drv_ll), sizeof(lv_fs_drv_t));
+ _lv_ll_init(&LV_GC_ROOT(_lv_drv_ll), sizeof(lv_fs_drv_t));
}
/**
- * Test if a drive is rady or not. If the `ready` function was not initialized `true` will be
+ * Test if a drive is ready or not. If the `ready` function was not initialized `true` will be
* returned.
* @param letter letter of the drive
* @return true: drive is ready; false: drive is not ready
@@ -95,18 +91,28 @@ lv_fs_res_t lv_fs_open(lv_fs_file_t * file_p, const char * path, lv_fs_mode_t mo
file_p->drv = lv_fs_get_drv(letter);
if(file_p->drv == NULL) {
- file_p->file_d = NULL;
return LV_FS_RES_NOT_EX;
}
if(file_p->drv->ready_cb != NULL) {
if(file_p->drv->ready_cb(file_p->drv) == false) {
- file_p->drv = NULL;
- file_p->file_d = NULL;
+ file_p->drv = NULL;
return LV_FS_RES_HW_ERR;
}
}
+ if(file_p->drv->open_cb == NULL) {
+ file_p->drv = NULL;
+ return LV_FS_RES_NOT_IMP;
+ }
+
+ const char * real_path = lv_fs_get_real_path(path);
+
+ if(file_p->drv->file_size == 0) { /*Is file_d zero size?*/
+ /*Pass file_d's address to open_cb, so the implementor can allocate memory byself*/
+ return file_p->drv->open_cb(file_p->drv, &file_p->file_d, real_path, mode);
+ }
+
file_p->file_d = lv_mem_alloc(file_p->drv->file_size);
LV_ASSERT_MEM(file_p->file_d);
if(file_p->file_d == NULL) {
@@ -114,12 +120,7 @@ lv_fs_res_t lv_fs_open(lv_fs_file_t * file_p, const char * path, lv_fs_mode_t mo
return LV_FS_RES_OUT_OF_MEM; /* Out of memory */
}
- if(file_p->drv->open_cb == NULL) {
- return LV_FS_RES_NOT_IMP;
- }
-
- const char * real_path = lv_fs_get_real_path(path);
- lv_fs_res_t res = file_p->drv->open_cb(file_p->drv, file_p->file_d, real_path, mode);
+ lv_fs_res_t res = file_p->drv->open_cb(file_p->drv, file_p->file_d, real_path, mode);
if(res != LV_FS_RES_OK) {
lv_mem_free(file_p->file_d);
@@ -133,7 +134,7 @@ lv_fs_res_t lv_fs_open(lv_fs_file_t * file_p, const char * path, lv_fs_mode_t mo
/**
* Close an already opened file
* @param file_p pointer to a lv_fs_file_t variable
- * @return LV_FS_RES_OK or any error from lv_fs_res_t enum
+ * @return LV_FS_RES_OK or any error from lv_fs_res_t enum
*/
lv_fs_res_t lv_fs_close(lv_fs_file_t * file_p)
{
@@ -150,7 +151,6 @@ lv_fs_res_t lv_fs_close(lv_fs_file_t * file_p)
lv_mem_free(file_p->file_d); /*Clean up*/
file_p->file_d = NULL;
file_p->drv = NULL;
- file_p->file_d = NULL;
return res;
}
@@ -158,16 +158,15 @@ lv_fs_res_t lv_fs_close(lv_fs_file_t * file_p)
/**
* Delete a file
* @param path path of the file to delete
- * @return LV_FS_RES_OK or any error from lv_fs_res_t enum
+ * @return LV_FS_RES_OK or any error from lv_fs_res_t enum
*/
lv_fs_res_t lv_fs_remove(const char * path)
{
if(path == NULL) return LV_FS_RES_INV_PARAM;
- lv_fs_drv_t * drv = NULL;
char letter = path[0];
- drv = lv_fs_get_drv(letter);
+ lv_fs_drv_t * drv = lv_fs_get_drv(letter);
if(drv == NULL) return LV_FS_RES_NOT_EX;
if(drv->ready_cb != NULL) {
if(drv->ready_cb(drv) == false) return LV_FS_RES_HW_ERR;
@@ -259,12 +258,12 @@ lv_fs_res_t lv_fs_seek(lv_fs_file_t * file_p, uint32_t pos)
lv_fs_res_t lv_fs_tell(lv_fs_file_t * file_p, uint32_t * pos)
{
if(file_p->drv == NULL) {
- pos = 0;
+ *pos = 0;
return LV_FS_RES_INV_PARAM;
}
if(file_p->drv->tell_cb == NULL) {
- pos = 0;
+ *pos = 0;
return LV_FS_RES_NOT_IMP;
}
@@ -285,7 +284,7 @@ lv_fs_res_t lv_fs_trunc(lv_fs_file_t * file_p)
return LV_FS_RES_INV_PARAM;
}
- if(file_p->drv->tell_cb == NULL) {
+ if(file_p->drv->trunc_cb == NULL) {
return LV_FS_RES_NOT_IMP;
}
@@ -349,13 +348,16 @@ lv_fs_res_t lv_fs_rename(const char * oldname, const char * newname)
}
/**
- * Initialize a 'fs_read_dir_t' variable for directory reading
- * @param rddir_p pointer to a 'fs_read_dir_t' variable
+ * Initialize a 'lv_fs_dir_t' variable for directory reading
+ * @param rddir_p pointer to a 'lv_fs_dir_t' variable
* @param path path to a directory
* @return LV_FS_RES_OK or any error from lv_fs_res_t enum
*/
lv_fs_res_t lv_fs_dir_open(lv_fs_dir_t * rddir_p, const char * path)
{
+ rddir_p->drv = NULL;
+ rddir_p->dir_d = NULL;
+
if(path == NULL) return LV_FS_RES_INV_PARAM;
char letter = path[0];
@@ -363,32 +365,50 @@ lv_fs_res_t lv_fs_dir_open(lv_fs_dir_t * rddir_p, const char * path)
rddir_p->drv = lv_fs_get_drv(letter);
if(rddir_p->drv == NULL) {
- rddir_p->dir_d = NULL;
return LV_FS_RES_NOT_EX;
}
- rddir_p->dir_d = lv_mem_alloc(rddir_p->drv->rddir_size);
- LV_ASSERT_MEM(rddir_p->dir_d);
- if(rddir_p->dir_d == NULL) {
- rddir_p->dir_d = NULL;
- return LV_FS_RES_OUT_OF_MEM; /* Out of memory */
+ if(rddir_p->drv->ready_cb != NULL) {
+ if(rddir_p->drv->ready_cb(rddir_p->drv) == false) {
+ rddir_p->drv = NULL;
+ return LV_FS_RES_HW_ERR;
+ }
}
if(rddir_p->drv->dir_open_cb == NULL) {
+ rddir_p->drv = NULL;
return LV_FS_RES_NOT_IMP;
}
const char * real_path = lv_fs_get_real_path(path);
+ if(rddir_p->drv->rddir_size == 0) { /*Is dir_d zero size?*/
+ /*Pass dir_d's address to dir_open_cb, so the implementor can allocate memory byself*/
+ return rddir_p->drv->dir_open_cb(rddir_p->drv, &rddir_p->dir_d, real_path);
+ }
+
+ rddir_p->dir_d = lv_mem_alloc(rddir_p->drv->rddir_size);
+ LV_ASSERT_MEM(rddir_p->dir_d);
+ if(rddir_p->dir_d == NULL) {
+ rddir_p->drv = NULL;
+ return LV_FS_RES_OUT_OF_MEM; /* Out of memory */
+ }
+
lv_fs_res_t res = rddir_p->drv->dir_open_cb(rddir_p->drv, rddir_p->dir_d, real_path);
+ if(res != LV_FS_RES_OK) {
+ lv_mem_free(rddir_p->dir_d);
+ rddir_p->dir_d = NULL;
+ rddir_p->drv = NULL;
+ }
+
return res;
}
/**
* Read the next filename form a directory.
* The name of the directories will begin with '/'
- * @param rddir_p pointer to an initialized 'fs_read_dir_t' variable
+ * @param rddir_p pointer to an initialized 'lv_fs_dir_t' variable
* @param fn pointer to a buffer to store the filename
* @return LV_FS_RES_OK or any error from lv_fs_res_t enum
*/
@@ -400,6 +420,7 @@ lv_fs_res_t lv_fs_dir_read(lv_fs_dir_t * rddir_p, char * fn)
}
if(rddir_p->drv->dir_read_cb == NULL) {
+ fn[0] = '\0';
return LV_FS_RES_NOT_IMP;
}
@@ -410,7 +431,7 @@ lv_fs_res_t lv_fs_dir_read(lv_fs_dir_t * rddir_p, char * fn)
/**
* Close the directory reading
- * @param rddir_p pointer to an initialized 'fs_read_dir_t' variable
+ * @param rddir_p pointer to an initialized 'lv_fs_dir_t' variable
* @return LV_FS_RES_OK or any error from lv_fs_res_t enum
*/
lv_fs_res_t lv_fs_dir_close(lv_fs_dir_t * rddir_p)
@@ -419,18 +440,15 @@ lv_fs_res_t lv_fs_dir_close(lv_fs_dir_t * rddir_p)
return LV_FS_RES_INV_PARAM;
}
- lv_fs_res_t res;
-
if(rddir_p->drv->dir_close_cb == NULL) {
- res = LV_FS_RES_NOT_IMP;
- } else {
- res = rddir_p->drv->dir_close_cb(rddir_p->drv, rddir_p->dir_d);
+ return LV_FS_RES_NOT_IMP;
}
+ lv_fs_res_t res = rddir_p->drv->dir_close_cb(rddir_p->drv, rddir_p->dir_d);
+
lv_mem_free(rddir_p->dir_d); /*Clean up*/
rddir_p->dir_d = NULL;
rddir_p->drv = NULL;
- rddir_p->dir_d = NULL;
return res;
}
@@ -450,19 +468,23 @@ lv_fs_res_t lv_fs_free_space(char letter, uint32_t * total_p, uint32_t * free_p)
return LV_FS_RES_INV_PARAM;
}
- lv_fs_res_t res;
+ if(drv->ready_cb != NULL) {
+ if(drv->ready_cb(drv) == false) {
+ return LV_FS_RES_HW_ERR;
+ }
+ }
if(drv->free_space_cb == NULL) {
- res = LV_FS_RES_NOT_IMP;
- } else {
- uint32_t total_tmp = 0;
- uint32_t free_tmp = 0;
- res = drv->free_space_cb(drv, &total_tmp, &free_tmp);
-
- if(total_p != NULL) *total_p = total_tmp;
- if(free_p != NULL) *free_p = free_tmp;
+ return LV_FS_RES_NOT_IMP;
}
+ uint32_t total_tmp = 0;
+ uint32_t free_tmp = 0;
+ lv_fs_res_t res = drv->free_space_cb(drv, &total_tmp, &free_tmp);
+
+ if(total_p != NULL) *total_p = total_tmp;
+ if(free_p != NULL) *free_p = free_tmp;
+
return res;
}
@@ -474,7 +496,7 @@ lv_fs_res_t lv_fs_free_space(char letter, uint32_t * total_p, uint32_t * free_p)
*/
void lv_fs_drv_init(lv_fs_drv_t * drv)
{
- memset(drv, 0, sizeof(lv_fs_drv_t));
+ _lv_memset_00(drv, sizeof(lv_fs_drv_t));
}
/**
@@ -486,11 +508,11 @@ void lv_fs_drv_register(lv_fs_drv_t * drv_p)
{
/*Save the new driver*/
lv_fs_drv_t * new_drv;
- new_drv = lv_ll_ins_head(&LV_GC_ROOT(_lv_drv_ll));
+ new_drv = _lv_ll_ins_head(&LV_GC_ROOT(_lv_drv_ll));
LV_ASSERT_MEM(new_drv);
if(new_drv == NULL) return;
- memcpy(new_drv, drv_p, sizeof(lv_fs_drv_t));
+ _lv_memcpy(new_drv, drv_p, sizeof(lv_fs_drv_t));
}
/**
@@ -502,8 +524,7 @@ lv_fs_drv_t * lv_fs_get_drv(char letter)
{
lv_fs_drv_t * drv;
- LV_LL_READ(LV_GC_ROOT(_lv_drv_ll), drv)
- {
+ _LV_LL_READ(LV_GC_ROOT(_lv_drv_ll), drv) {
if(drv->letter == letter) {
return drv;
}
@@ -521,8 +542,7 @@ char * lv_fs_get_letters(char * buf)
lv_fs_drv_t * drv;
uint8_t i = 0;
- LV_LL_READ(LV_GC_ROOT(_lv_drv_ll), drv)
- {
+ _LV_LL_READ(LV_GC_ROOT(_lv_drv_ll), drv) {
buf[i] = drv->letter;
i++;
}
@@ -543,7 +563,8 @@ const char * lv_fs_get_ext(const char * fn)
for(i = strlen(fn); i > 0; i--) {
if(fn[i] == '.') {
return &fn[i + 1];
- } else if(fn[i] == '/' || fn[i] == '\\') {
+ }
+ else if(fn[i] == '/' || fn[i] == '\\') {
return ""; /*No extension if a '\' or '/' found*/
}
}
@@ -631,7 +652,8 @@ static const char * lv_fs_get_real_path(const char * path)
while(*path != '\0') {
if(*path == ':' || *path == '\\' || *path == '/') {
path++;
- } else {
+ }
+ else {
break;
}
}
diff --git a/src/libs/lvgl/src/lv_misc/lv_fs.h b/src/libs/lvgl/src/lv_misc/lv_fs.h
index f1824282..acaa895d 100644
--- a/src/libs/lvgl/src/lv_misc/lv_fs.h
+++ b/src/libs/lvgl/src/lv_misc/lv_fs.h
@@ -13,11 +13,7 @@ extern "C" {
/*********************
* INCLUDES
*********************/
-#ifdef LV_CONF_INCLUDE_SIMPLE
-#include "lv_conf.h"
-#else
-#include "../../../lv_conf.h"
-#endif
+#include "../lv_conf_internal.h"
#if LV_USE_FILESYSTEM
@@ -34,8 +30,9 @@ extern "C" {
/**********************
* TYPEDEFS
**********************/
+
/**
- * Errors in the filesystem module.
+ * Errors in the file system module.
*/
enum {
LV_FS_RES_OK = 0,
@@ -63,8 +60,7 @@ enum {
};
typedef uint8_t lv_fs_mode_t;
-typedef struct _lv_fs_drv_t
-{
+typedef struct _lv_fs_drv_t {
char letter;
uint16_t file_size;
uint16_t rddir_size;
@@ -91,14 +87,12 @@ typedef struct _lv_fs_drv_t
#endif
} lv_fs_drv_t;
-typedef struct
-{
+typedef struct {
void * file_d;
lv_fs_drv_t * drv;
} lv_fs_file_t;
-typedef struct
-{
+typedef struct {
void * dir_d;
lv_fs_drv_t * drv;
} lv_fs_dir_t;
@@ -110,7 +104,7 @@ typedef struct
/**
* Initialize the File system interface
*/
-void lv_fs_init(void);
+void _lv_fs_init(void);
/**
* Initialize a file system driver with default values.
@@ -135,7 +129,7 @@ void lv_fs_drv_register(lv_fs_drv_t * drv_p);
lv_fs_drv_t * lv_fs_get_drv(char letter);
/**
- * Test if a drive is rady or not. If the `ready` function was not initialized `true` will be
+ * Test if a drive is ready or not. If the `ready` function was not initialized `true` will be
* returned.
* @param letter letter of the drive
* @return true: drive is ready; false: drive is not ready
@@ -154,14 +148,14 @@ lv_fs_res_t lv_fs_open(lv_fs_file_t * file_p, const char * path, lv_fs_mode_t mo
/**
* Close an already opened file
* @param file_p pointer to a lv_fs_file_t variable
- * @return LV_FS_RES_OK or any error from lv_fs_res_t enum
+ * @return LV_FS_RES_OK or any error from lv_fs_res_t enum
*/
lv_fs_res_t lv_fs_close(lv_fs_file_t * file_p);
/**
* Delete a file
* @param path path of the file to delete
- * @return LV_FS_RES_OK or any error from lv_fs_res_t enum
+ * @return LV_FS_RES_OK or any error from lv_fs_res_t enum
*/
lv_fs_res_t lv_fs_remove(const char * path);
@@ -227,7 +221,7 @@ lv_fs_res_t lv_fs_rename(const char * oldname, const char * newname);
/**
* Initialize a 'fs_dir_t' variable for directory reading
- * @param rddir_p pointer to a 'fs_read_dir_t' variable
+ * @param rddir_p pointer to a 'lv_fs_dir_t' variable
* @param path path to a directory
* @return LV_FS_RES_OK or any error from lv_fs_res_t enum
*/
@@ -236,7 +230,7 @@ lv_fs_res_t lv_fs_dir_open(lv_fs_dir_t * rddir_p, const char * path);
/**
* Read the next filename form a directory.
* The name of the directories will begin with '/'
- * @param rddir_p pointer to an initialized 'fs_rdir_t' variable
+ * @param rddir_p pointer to an initialized 'fs_dir_t' variable
* @param fn pointer to a buffer to store the filename
* @return LV_FS_RES_OK or any error from lv_fs_res_t enum
*/
@@ -281,7 +275,7 @@ char * lv_fs_up(char * path);
/**
* Get the last element of a path (e.g. U:/folder/file -> file)
- * @param buf buffer to store the letters ('\0' added after the last letter)
+ * @param path pointer to a file name
* @return pointer to the beginning of the last element in the path
*/
const char * lv_fs_get_last(const char * path);
diff --git a/src/libs/lvgl/src/lv_misc/lv_gc.c b/src/libs/lvgl/src/lv_misc/lv_gc.c
index 94bf532a..3a37a48c 100644
--- a/src/libs/lvgl/src/lv_misc/lv_gc.c
+++ b/src/libs/lvgl/src/lv_misc/lv_gc.c
@@ -10,10 +10,6 @@
#include "lv_gc.h"
#include "string.h"
-#if defined(LV_GC_INCLUDE)
-#include LV_GC_INCLUDE
-#endif /* LV_ENABLE_GC */
-
/*********************
* DEFINES
*********************/
@@ -29,9 +25,11 @@
/**********************
* STATIC VARIABLES
**********************/
+
#if(!defined(LV_ENABLE_GC)) || LV_ENABLE_GC == 0
-LV_ROOTS
+ LV_ROOTS
#endif /* LV_ENABLE_GC */
+
/**********************
* MACROS
**********************/
@@ -40,9 +38,9 @@ LV_ROOTS
* GLOBAL FUNCTIONS
**********************/
-void lv_gc_clear_roots(void)
+void _lv_gc_clear_roots(void)
{
-#define LV_CLEAR_ROOT(root_type, root_name) memset(&LV_GC_ROOT(root_name), 0, sizeof(LV_GC_ROOT(root_name)));
+#define LV_CLEAR_ROOT(root_type, root_name) _lv_memset_00(&LV_GC_ROOT(root_name), sizeof(LV_GC_ROOT(root_name)));
LV_ITERATE_ROOTS(LV_CLEAR_ROOT)
}
diff --git a/src/libs/lvgl/src/lv_misc/lv_gc.h b/src/libs/lvgl/src/lv_misc/lv_gc.h
index afd4d600..915bf39a 100644
--- a/src/libs/lvgl/src/lv_misc/lv_gc.h
+++ b/src/libs/lvgl/src/lv_misc/lv_gc.h
@@ -13,18 +13,13 @@ extern "C" {
/*********************
* INCLUDES
*********************/
-
-#ifdef LV_CONF_INCLUDE_SIMPLE
-#include "lv_conf.h"
-#else
-#include "../../../lv_conf.h"
-#endif
-
#include <stdint.h>
#include <stdbool.h>
#include "lv_mem.h"
#include "lv_ll.h"
+#include "lv_task.h"
#include "../lv_draw/lv_img_cache.h"
+#include "../lv_draw/lv_draw_mask.h"
/*********************
* DEFINES
@@ -33,15 +28,22 @@ extern "C" {
#define LV_ITERATE_ROOTS(f) \
f(lv_ll_t, _lv_task_ll) /*Linked list to store the lv_tasks*/ \
f(lv_ll_t, _lv_disp_ll) /*Linked list of screens*/ \
- f(lv_ll_t, _lv_indev_ll) /*Linked list of screens*/ \
+ f(lv_ll_t, _lv_indev_ll) /*Linked list of input device*/ \
f(lv_ll_t, _lv_drv_ll) \
f(lv_ll_t, _lv_file_ll) \
f(lv_ll_t, _lv_anim_ll) \
f(lv_ll_t, _lv_group_ll) \
f(lv_ll_t, _lv_img_defoder_ll) \
+ f(lv_ll_t, _lv_obj_style_trans_ll) \
f(lv_img_cache_entry_t*, _lv_img_cache_array) \
- f(void*, _lv_task_act) \
- f(void*, _lv_draw_buf)
+ f(lv_task_t*, _lv_task_act) \
+ f(lv_mem_buf_arr_t , _lv_mem_buf) \
+ f(_lv_draw_mask_saved_arr_t , _lv_draw_mask_list) \
+ f(void * , _lv_theme_material_styles) \
+ f(void * , _lv_theme_template_styles) \
+ f(void * , _lv_theme_mono_styles) \
+ f(void * , _lv_theme_empty_styles) \
+ f(uint8_t *, _lv_font_decompr_buf) \
#define LV_DEFINE_ROOT(root_type, root_name) root_type root_name;
#define LV_ROOTS LV_ITERATE_ROOTS(LV_DEFINE_ROOT)
@@ -50,6 +52,7 @@ extern "C" {
#if LV_MEM_CUSTOM != 1
#error "GC requires CUSTOM_MEM"
#endif /* LV_MEM_CUSTOM */
+#include LV_GC_INCLUDE
#else /* LV_ENABLE_GC */
#define LV_GC_ROOT(x) x
#define LV_EXTERN_ROOT(root_type, root_name) extern root_type root_name;
@@ -64,7 +67,7 @@ LV_ITERATE_ROOTS(LV_EXTERN_ROOT)
* GLOBAL PROTOTYPES
**********************/
-void lv_gc_clear_roots(void);
+void _lv_gc_clear_roots(void);
/**********************
* MACROS
diff --git a/src/libs/lvgl/src/lv_misc/lv_ll.c b/src/libs/lvgl/src/lv_misc/lv_ll.c
index 99526659..56013682 100644
--- a/src/libs/lvgl/src/lv_misc/lv_ll.c
+++ b/src/libs/lvgl/src/lv_misc/lv_ll.c
@@ -47,22 +47,16 @@ static void node_set_next(lv_ll_t * ll_p, lv_ll_node_t * act, lv_ll_node_t * nex
* @param ll_dsc pointer to ll_dsc variable
* @param node_size the size of 1 node in bytes
*/
-void lv_ll_init(lv_ll_t * ll_p, uint32_t node_size)
+void _lv_ll_init(lv_ll_t * ll_p, uint32_t node_size)
{
ll_p->head = NULL;
ll_p->tail = NULL;
-#ifdef LV_MEM_ENV64
+#ifdef LV_ARCH_64
/*Round the size up to 8*/
- if(node_size & 0x7) {
- node_size = node_size & (~0x7);
- node_size += 8;
- }
+ node_size = (node_size + 7) & (~0x7);
#else
/*Round the size up to 4*/
- if(node_size & 0x3) {
- node_size = node_size & (~0x3);
- node_size += 4;
- }
+ node_size = (node_size + 3) & (~0x3);
#endif
ll_p->n_size = node_size;
@@ -73,7 +67,7 @@ void lv_ll_init(lv_ll_t * ll_p, uint32_t node_size)
* @param ll_p pointer to linked list
* @return pointer to the new head
*/
-void * lv_ll_ins_head(lv_ll_t * ll_p)
+void * _lv_ll_ins_head(lv_ll_t * ll_p)
{
lv_ll_node_t * n_new;
@@ -102,21 +96,22 @@ void * lv_ll_ins_head(lv_ll_t * ll_p)
* @param n_act pointer a node
* @return pointer to the new head
*/
-void * lv_ll_ins_prev(lv_ll_t * ll_p, void * n_act)
+void * _lv_ll_ins_prev(lv_ll_t * ll_p, void * n_act)
{
lv_ll_node_t * n_new;
- lv_ll_node_t * n_prev;
if(NULL == ll_p || NULL == n_act) return NULL;
- if(lv_ll_get_head(ll_p) == n_act) {
- n_new = lv_ll_ins_head(ll_p);
+ if(_lv_ll_get_head(ll_p) == n_act) {
+ n_new = _lv_ll_ins_head(ll_p);
if(n_new == NULL) return NULL;
- } else {
+ }
+ else {
n_new = lv_mem_alloc(ll_p->n_size + LL_NODE_META_SIZE);
if(n_new == NULL) return NULL;
- n_prev = lv_ll_get_prev(ll_p, n_act);
+ lv_ll_node_t * n_prev;
+ n_prev = _lv_ll_get_prev(ll_p, n_act);
node_set_next(ll_p, n_prev, n_new);
node_set_prev(ll_p, n_new, n_prev);
node_set_prev(ll_p, n_act, n_new);
@@ -131,16 +126,15 @@ void * lv_ll_ins_prev(lv_ll_t * ll_p, void * n_act)
* @param ll_p pointer to linked list
* @return pointer to the new tail
*/
-void * lv_ll_ins_tail(lv_ll_t * ll_p)
+void * _lv_ll_ins_tail(lv_ll_t * ll_p)
{
lv_ll_node_t * n_new;
n_new = lv_mem_alloc(ll_p->n_size + LL_NODE_META_SIZE);
- if(n_new == NULL) return NULL;
if(n_new != NULL) {
node_set_next(ll_p, n_new, NULL); /*No next after the new tail*/
- node_set_prev(ll_p, n_new, ll_p->tail); /*The prev. before new is tho old tail*/
+ node_set_prev(ll_p, n_new, ll_p->tail); /*The prev. before new is the old tail*/
if(ll_p->tail != NULL) { /*If there is old tail then the new comes after it*/
node_set_next(ll_p, ll_p->tail, n_new);
}
@@ -156,31 +150,35 @@ void * lv_ll_ins_tail(lv_ll_t * ll_p)
/**
* Remove the node 'node_p' from 'll_p' linked list.
- * It does not free the the memory of node.
+ * It does not free the memory of node.
* @param ll_p pointer to the linked list of 'node_p'
* @param node_p pointer to node in 'll_p' linked list
*/
-void lv_ll_rem(lv_ll_t * ll_p, void * node_p)
+void _lv_ll_remove(lv_ll_t * ll_p, void * node_p)
{
- if(lv_ll_get_head(ll_p) == node_p) {
+ if(_lv_ll_get_head(ll_p) == node_p) {
/*The new head will be the node after 'n_act'*/
- ll_p->head = lv_ll_get_next(ll_p, node_p);
+ ll_p->head = _lv_ll_get_next(ll_p, node_p);
if(ll_p->head == NULL) {
ll_p->tail = NULL;
- } else {
+ }
+ else {
node_set_prev(ll_p, ll_p->head, NULL);
}
- } else if(lv_ll_get_tail(ll_p) == node_p) {
- /*The new tail will be the node before 'n_act'*/
- ll_p->tail = lv_ll_get_prev(ll_p, node_p);
+ }
+ else if(_lv_ll_get_tail(ll_p) == node_p) {
+ /*The new tail will be the node before 'n_act'*/
+ ll_p->tail = _lv_ll_get_prev(ll_p, node_p);
if(ll_p->tail == NULL) {
ll_p->head = NULL;
- } else {
+ }
+ else {
node_set_next(ll_p, ll_p->tail, NULL);
}
- } else {
- lv_ll_node_t * n_prev = lv_ll_get_prev(ll_p, node_p);
- lv_ll_node_t * n_next = lv_ll_get_next(ll_p, node_p);
+ }
+ else {
+ lv_ll_node_t * n_prev = _lv_ll_get_prev(ll_p, node_p);
+ lv_ll_node_t * n_next = _lv_ll_get_next(ll_p, node_p);
node_set_next(ll_p, n_prev, n_next);
node_set_prev(ll_p, n_next, n_prev);
@@ -191,18 +189,18 @@ void lv_ll_rem(lv_ll_t * ll_p, void * node_p)
* Remove and free all elements from a linked list. The list remain valid but become empty.
* @param ll_p pointer to linked list
*/
-void lv_ll_clear(lv_ll_t * ll_p)
+void _lv_ll_clear(lv_ll_t * ll_p)
{
void * i;
void * i_next;
- i = lv_ll_get_head(ll_p);
+ i = _lv_ll_get_head(ll_p);
i_next = NULL;
while(i != NULL) {
- i_next = lv_ll_get_next(ll_p, i);
+ i_next = _lv_ll_get_next(ll_p, i);
- lv_ll_rem(ll_p, i);
+ _lv_ll_remove(ll_p, i);
lv_mem_free(i);
i = i_next;
@@ -217,9 +215,9 @@ void lv_ll_clear(lv_ll_t * ll_p)
* @param head true: be the head in the new list
* false be the head in the new list
*/
-void lv_ll_chg_list(lv_ll_t * ll_ori_p, lv_ll_t * ll_new_p, void * node, bool head)
+void _lv_ll_chg_list(lv_ll_t * ll_ori_p, lv_ll_t * ll_new_p, void * node, bool head)
{
- lv_ll_rem(ll_ori_p, node);
+ _lv_ll_remove(ll_ori_p, node);
if(head) {
/*Set node as head*/
@@ -234,7 +232,8 @@ void lv_ll_chg_list(lv_ll_t * ll_ori_p, lv_ll_t * ll_new_p, void * node, bool he
if(ll_new_p->tail == NULL) { /*If there is no tail (first node) set the tail too*/
ll_new_p->tail = node;
}
- } else {
+ }
+ else {
/*Set node as tail*/
node_set_prev(ll_new_p, node, ll_new_p->tail);
node_set_next(ll_new_p, node, NULL);
@@ -255,7 +254,7 @@ void lv_ll_chg_list(lv_ll_t * ll_ori_p, lv_ll_t * ll_new_p, void * node, bool he
* @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 * _lv_ll_get_head(const lv_ll_t * ll_p)
{
void * head = NULL;
@@ -271,7 +270,7 @@ void * lv_ll_get_head(const lv_ll_t * ll_p)
* @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 * _lv_ll_get_tail(const lv_ll_t * ll_p)
{
void * tail = NULL;
@@ -288,16 +287,15 @@ void * lv_ll_get_tail(const lv_ll_t * ll_p)
* @param n_act pointer a node
* @return pointer to the next node
*/
-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)
{
- void * next = NULL;
-
- if(ll_p != NULL) {
- const lv_ll_node_t * n_act_d = n_act;
- memcpy(&next, n_act_d + LL_NEXT_P_OFFSET(ll_p), sizeof(void *));
- }
+ if(ll_p == NULL) return NULL;
- return next;
+ /* Pointer to the next node is stored in the end of this node.
+ * Go there and return the address found there */
+ const lv_ll_node_t * n_act_d = n_act;
+ n_act_d += LL_NEXT_P_OFFSET(ll_p);
+ return *((lv_ll_node_t **)n_act_d);
}
/**
@@ -306,16 +304,15 @@ void * lv_ll_get_next(const lv_ll_t * ll_p, const void * n_act)
* @param n_act pointer a node
* @return pointer to the previous node
*/
-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)
{
- void * prev = NULL;
+ if(ll_p == NULL) return NULL;
- if(ll_p != NULL) {
- const lv_ll_node_t * n_act_d = n_act;
- memcpy(&prev, n_act_d + LL_PREV_P_OFFSET(ll_p), sizeof(void *));
- }
-
- return prev;
+ /* Pointer to the prev. node is stored in the end of this node.
+ * Go there and return the address found there */
+ const lv_ll_node_t * n_act_d = n_act;
+ n_act_d += LL_PREV_P_OFFSET(ll_p);
+ return *((lv_ll_node_t **)n_act_d);
}
/**
@@ -323,12 +320,12 @@ void * lv_ll_get_prev(const lv_ll_t * ll_p, const void * n_act)
* @param ll_p pointer to linked list
* @return length of the linked list
*/
-uint32_t lv_ll_get_len(const lv_ll_t * ll_p)
+uint32_t _lv_ll_get_len(const lv_ll_t * ll_p)
{
uint32_t len = 0;
void * node;
- for(node = lv_ll_get_head(ll_p); node != NULL; node = lv_ll_get_next(ll_p, node)) {
+ for(node = _lv_ll_get_head(ll_p); node != NULL; node = _lv_ll_get_next(ll_p, node)) {
len++;
}
@@ -336,25 +333,25 @@ uint32_t lv_ll_get_len(const lv_ll_t * ll_p)
}
/**
- * Move a nodw before an other node in the same linked list
+ * Move a node before an other node in the same linked list
* @param ll_p pointer to a linked list
* @param n_act pointer to node to move
* @param n_after pointer to a node which should be after `n_act`
*/
-void lv_ll_move_before(lv_ll_t * ll_p, void * n_act, void * n_after)
+void _lv_ll_move_before(lv_ll_t * ll_p, void * n_act, void * n_after)
{
if(n_act == n_after) return; /*Can't move before itself*/
void * n_before;
if(n_after != NULL)
- n_before = lv_ll_get_prev(ll_p, n_after);
+ n_before = _lv_ll_get_prev(ll_p, n_after);
else
- n_before = lv_ll_get_tail(ll_p); /*if `n_after` is NULL `n_act` should be the new tail*/
+ n_before = _lv_ll_get_tail(ll_p); /*if `n_after` is NULL `n_act` should be the new tail*/
if(n_act == n_before) return; /*Already before `n_after`*/
/*It's much easier to remove from the list and add again*/
- lv_ll_rem(ll_p, n_act);
+ _lv_ll_remove(ll_p, n_act);
/*Add again by setting the prev. and next nodes*/
node_set_next(ll_p, n_before, n_act);
@@ -374,7 +371,7 @@ void lv_ll_move_before(lv_ll_t * ll_p, void * n_act, void * n_after)
* @param ll_p pointer to a linked list
* @return true: the linked list is empty; false: not empty
*/
-bool lv_ll_is_empty(lv_ll_t * ll_p)
+bool _lv_ll_is_empty(lv_ll_t * ll_p)
{
if(ll_p == NULL) return true;
@@ -388,7 +385,7 @@ bool lv_ll_is_empty(lv_ll_t * ll_p)
**********************/
/**
- * Set the 'pervious node pointer' of a node
+ * Set the previous node pointer of a node
* @param ll_p pointer to linked list
* @param act pointer to a node which prev. node pointer should be set
* @param prev pointer to a node which should be the previous node before 'act'
@@ -397,11 +394,14 @@ static void node_set_prev(lv_ll_t * ll_p, lv_ll_node_t * act, lv_ll_node_t * pre
{
if(act == NULL) return; /*Can't set the prev node of `NULL`*/
- uint32_t node_p_size = sizeof(lv_ll_node_t *);
- if(prev)
- memcpy(act + LL_PREV_P_OFFSET(ll_p), &prev, node_p_size);
- else
- memset(act + LL_PREV_P_OFFSET(ll_p), 0, node_p_size);
+ uint8_t * act8 = (uint8_t *) act;
+
+ act8 += LL_PREV_P_OFFSET(ll_p);
+
+ lv_ll_node_t ** act_node_p = (lv_ll_node_t **) act8;
+ lv_ll_node_t ** prev_node_p = (lv_ll_node_t **) &prev;
+
+ *act_node_p = *prev_node_p;
}
/**
@@ -413,10 +413,11 @@ static void node_set_prev(lv_ll_t * ll_p, lv_ll_node_t * act, lv_ll_node_t * pre
static void node_set_next(lv_ll_t * ll_p, lv_ll_node_t * act, lv_ll_node_t * next)
{
if(act == NULL) return; /*Can't set the next node of `NULL`*/
+ uint8_t * act8 = (uint8_t *) act;
- uint32_t node_p_size = sizeof(lv_ll_node_t *);
- if(next)
- memcpy(act + LL_NEXT_P_OFFSET(ll_p), &next, node_p_size);
- else
- memset(act + LL_NEXT_P_OFFSET(ll_p), 0, node_p_size);
+ act8 += LL_NEXT_P_OFFSET(ll_p);
+ lv_ll_node_t ** act_node_p = (lv_ll_node_t **) act8;
+ lv_ll_node_t ** next_node_p = (lv_ll_node_t **) &next;
+
+ *act_node_p = *next_node_p;
}
diff --git a/src/libs/lvgl/src/lv_misc/lv_ll.h b/src/libs/lvgl/src/lv_misc/lv_ll.h
index 2c02eb48..9ccc1100 100644
--- a/src/libs/lvgl/src/lv_misc/lv_ll.h
+++ b/src/libs/lvgl/src/lv_misc/lv_ll.h
@@ -1,5 +1,5 @@
/**
- * @file lv_ll.c
+ * @file lv_ll.h
* Handle linked lists. The nodes are dynamically allocated by the 'lv_mem' module.
*/
@@ -30,8 +30,7 @@ extern "C" {
typedef uint8_t lv_ll_node_t;
/** Description of a linked list*/
-typedef struct
-{
+typedef struct {
uint32_t n_size;
lv_ll_node_t * head;
lv_ll_node_t * tail;
@@ -46,14 +45,14 @@ typedef struct
* @param ll_dsc pointer to ll_dsc variable
* @param node_size the size of 1 node in bytes
*/
-void lv_ll_init(lv_ll_t * ll_p, uint32_t node_size);
+void _lv_ll_init(lv_ll_t * ll_p, uint32_t node_size);
/**
* Add a new head to a linked list
* @param ll_p pointer to linked list
* @return pointer to the new head
*/
-void * lv_ll_ins_head(lv_ll_t * ll_p);
+void * _lv_ll_ins_head(lv_ll_t * ll_p);
/**
* Insert a new node in front of the n_act node
@@ -61,28 +60,28 @@ void * lv_ll_ins_head(lv_ll_t * ll_p);
* @param n_act pointer a node
* @return pointer to the new head
*/
-void * lv_ll_ins_prev(lv_ll_t * ll_p, void * n_act);
+void * _lv_ll_ins_prev(lv_ll_t * ll_p, void * n_act);
/**
* Add a new tail to a linked list
* @param ll_p pointer to linked list
* @return pointer to the new tail
*/
-void * lv_ll_ins_tail(lv_ll_t * ll_p);
+void * _lv_ll_ins_tail(lv_ll_t * ll_p);
/**
* Remove the node 'node_p' from 'll_p' linked list.
- * It does not free the the memory of node.
+ * It does not free the memory of node.
* @param ll_p pointer to the linked list of 'node_p'
* @param node_p pointer to node in 'll_p' linked list
*/
-void lv_ll_rem(lv_ll_t * ll_p, void * node_p);
+void _lv_ll_remove(lv_ll_t * ll_p, void * node_p);
/**
* Remove and free all elements from a linked list. The list remain valid but become empty.
* @param ll_p pointer to linked list
*/
-void lv_ll_clear(lv_ll_t * ll_p);
+void _lv_ll_clear(lv_ll_t * ll_p);
/**
* Move a node to a new linked list
@@ -92,21 +91,21 @@ void lv_ll_clear(lv_ll_t * ll_p);
* @param head true: be the head in the new list
* false be the head in the new list
*/
-void lv_ll_chg_list(lv_ll_t * ll_ori_p, lv_ll_t * ll_new_p, void * node, bool head);
+void _lv_ll_chg_list(lv_ll_t * ll_ori_p, lv_ll_t * ll_new_p, void * node, bool head);
/**
* 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 * _lv_ll_get_head(const lv_ll_t * ll_p);
/**
* 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 * _lv_ll_get_tail(const lv_ll_t * ll_p);
/**
* Return with the pointer of the next node after 'n_act'
@@ -114,7 +113,7 @@ void * lv_ll_get_tail(const lv_ll_t * ll_p);
* @param n_act pointer a node
* @return pointer to the next node
*/
-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);
/**
* Return with the pointer of the previous node after 'n_act'
@@ -122,36 +121,45 @@ void * lv_ll_get_next(const lv_ll_t * ll_p, const void * n_act);
* @param n_act pointer a node
* @return pointer to the previous node
*/
-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);
/**
* Return the length of the linked list.
* @param ll_p pointer to linked list
* @return length of the linked list
*/
-uint32_t lv_ll_get_len(const lv_ll_t * ll_p);
+uint32_t _lv_ll_get_len(const lv_ll_t * ll_p);
/**
- * Move a nodw before an other node in the same linked list
+ * TODO
+ * @param ll_p
+ * @param n1_p
+ * @param n2_p
+void lv_ll_swap(lv_ll_t * ll_p, void * n1_p, void * n2_p);
+ */
+
+/**
+ * Move a node before an other node in the same linked list
* @param ll_p pointer to a linked list
* @param n_act pointer to node to move
* @param n_after pointer to a node which should be after `n_act`
*/
-void lv_ll_move_before(lv_ll_t * ll_p, void * n_act, void * n_after);
+void _lv_ll_move_before(lv_ll_t * ll_p, void * n_act, void * n_after);
/**
* Check if a linked list is empty
* @param ll_p pointer to a linked list
* @return true: the linked list is empty; false: not empty
*/
-bool lv_ll_is_empty(lv_ll_t * ll_p);
+bool _lv_ll_is_empty(lv_ll_t * ll_p);
+
/**********************
* MACROS
**********************/
-#define LV_LL_READ(list, i) for(i = lv_ll_get_head(&list); i != NULL; i = lv_ll_get_next(&list, i))
+#define _LV_LL_READ(list, i) for(i = _lv_ll_get_head(&list); i != NULL; i = _lv_ll_get_next(&list, i))
-#define LV_LL_READ_BACK(list, i) for(i = lv_ll_get_tail(&list); i != NULL; i = lv_ll_get_prev(&list, i))
+#define _LV_LL_READ_BACK(list, i) for(i = _lv_ll_get_tail(&list); i != NULL; i = _lv_ll_get_prev(&list, i))
#ifdef __cplusplus
} /* extern "C" */
diff --git a/src/libs/lvgl/src/lv_misc/lv_log.c b/src/libs/lvgl/src/lv_misc/lv_log.c
index acbdfb73..42b3b025 100644
--- a/src/libs/lvgl/src/lv_misc/lv_log.c
+++ b/src/libs/lvgl/src/lv_misc/lv_log.c
@@ -9,8 +9,12 @@
#include "lv_log.h"
#if LV_USE_LOG
+#include <stdarg.h>
+#include <string.h>
+#include "lv_printf.h"
+
#if LV_LOG_PRINTF
-#include <stdio.h>
+ #include <stdio.h>
#endif
/*********************
@@ -41,7 +45,7 @@ static lv_log_print_g_cb_t custom_print_cb;
/**
* Register custom print/write function to call when a log is added.
* It can format its "File path", "Line number" and "Description" as required
- * and send the formatted log message to a consol or serial port.
+ * and send the formatted log message to a console or serial port.
* @param print_cb a function pointer to print a log
*/
void lv_log_register_print_cb(lv_log_print_g_cb_t print_cb)
@@ -54,19 +58,35 @@ void lv_log_register_print_cb(lv_log_print_g_cb_t print_cb)
* @param level the level of log. (From `lv_log_level_t` enum)
* @param file name of the file when the log added
* @param line line number in the source code where the log added
- * @param dsc description of the log
+ * @param func name of the function when the log added
+ * @param format printf-like format string
+ * @param ... parameters for `format`
*/
-void lv_log_add(lv_log_level_t level, const char * file, int line, const char * dsc)
+void _lv_log_add(lv_log_level_t level, const char * file, int line, const char * func, const char * format, ...)
{
if(level >= _LV_LOG_LEVEL_NUM) return; /*Invalid level*/
if(level >= LV_LOG_LEVEL) {
+ va_list args;
+ va_start(args, format);
+ char buf[256];
+ lv_vsnprintf(buf, sizeof(buf), format, args);
+ va_end(args);
#if LV_LOG_PRINTF
- static const char * lvl_prefix[] = {"Trace", "Info", "Warn", "Error"};
- printf("%s: %s \t(%s #%d)\n", lvl_prefix[level], dsc, file, line);
+ /*Use only the file name not the path*/
+ size_t p;
+ for(p = strlen(file); p > 0; p--) {
+ if(file[p] == '/' || file[p] == '\\') {
+ p++; /*Skip the slash*/
+ break;
+ }
+ }
+
+ static const char * lvl_prefix[] = {"Trace", "Info", "Warn", "Error", "User"};
+ printf("%s: %s \t(%s #%d %s())\n", lvl_prefix[level], buf, &file[p], line, func);
#else
- if(custom_print_cb) custom_print_cb(level, file, line, dsc);
+ if(custom_print_cb) custom_print_cb(level, file, line, func, buf);
#endif
}
}
diff --git a/src/libs/lvgl/src/lv_misc/lv_log.h b/src/libs/lvgl/src/lv_misc/lv_log.h
index 62c613b4..fe46cf44 100644
--- a/src/libs/lvgl/src/lv_misc/lv_log.h
+++ b/src/libs/lvgl/src/lv_misc/lv_log.h
@@ -13,11 +13,7 @@ extern "C" {
/*********************
* INCLUDES
*********************/
-#ifdef LV_CONF_INCLUDE_SIMPLE
-#include "lv_conf.h"
-#else
-#include "../../../lv_conf.h"
-#endif
+#include "../lv_conf_internal.h"
#include <stdint.h>
/*********************
@@ -27,16 +23,18 @@ extern "C" {
/*Possible log level. For compatibility declare it independently from `LV_USE_LOG`*/
#define LV_LOG_LEVEL_TRACE 0 /**< A lot of logs to give detailed information*/
-#define LV_LOG_LEVEL_INFO 1 /**< Log important events*/
-#define LV_LOG_LEVEL_WARN 2 /**< Log if something unwanted happened but didn't caused problem*/
+#define LV_LOG_LEVEL_INFO 1 /**< Log important events*/
+#define LV_LOG_LEVEL_WARN 2 /**< Log if something unwanted happened but didn't caused problem*/
#define LV_LOG_LEVEL_ERROR 3 /**< Only critical issue, when the system may fail*/
-#define LV_LOG_LEVEL_NONE 4 /**< Do not log anything*/
-#define _LV_LOG_LEVEL_NUM 5 /**< Number of log levels */
+#define LV_LOG_LEVEL_USER 4 /**< Custom logs from the user*/
+#define LV_LOG_LEVEL_NONE 5 /**< Do not log anything*/
+#define _LV_LOG_LEVEL_NUM 6 /**< Number of log levels */
LV_EXPORT_CONST_INT(LV_LOG_LEVEL_TRACE);
LV_EXPORT_CONST_INT(LV_LOG_LEVEL_INFO);
LV_EXPORT_CONST_INT(LV_LOG_LEVEL_WARN);
LV_EXPORT_CONST_INT(LV_LOG_LEVEL_ERROR);
+LV_EXPORT_CONST_INT(LV_LOG_LEVEL_USER);
LV_EXPORT_CONST_INT(LV_LOG_LEVEL_NONE);
typedef int8_t lv_log_level_t;
@@ -47,9 +45,9 @@ typedef int8_t lv_log_level_t;
**********************/
/**
- * Log print function. Receives "Log Level", "File path", "Line number" and "Description".
+ * Log print function. Receives "Log Level", "File path", "Line number", "Function name" and "Description".
*/
-typedef void (*lv_log_print_g_cb_t)(lv_log_level_t level, const char *, uint32_t, const char *);
+typedef void (*lv_log_print_g_cb_t)(lv_log_level_t level, const char *, uint32_t, const char *, const char *);
/**********************
* GLOBAL PROTOTYPES
@@ -58,7 +56,7 @@ typedef void (*lv_log_print_g_cb_t)(lv_log_level_t level, const char *, uint32_t
/**
* Register custom print/write function to call when a log is added.
* It can format its "File path", "Line number" and "Description" as required
- * and send the formatted log message to a consol or serial port.
+ * and send the formatted log message to a console or serial port.
* @param print_cb a function pointer to print a log
*/
void lv_log_register_print_cb(lv_log_print_g_cb_t print_cb);
@@ -68,73 +66,55 @@ void lv_log_register_print_cb(lv_log_print_g_cb_t print_cb);
* @param level the level of log. (From `lv_log_level_t` enum)
* @param file name of the file when the log added
* @param line line number in the source code where the log added
- * @param dsc description of the log
+ * @param func name of the function when the log added
+ * @param format printf-like format string
+ * @param ... parameters for `format`
*/
-void lv_log_add(lv_log_level_t level, const char * file, int line, const char * dsc);
+void _lv_log_add(lv_log_level_t level, const char * file, int line, const char * func, const char * format, ...);
/**********************
* MACROS
**********************/
#if LV_LOG_LEVEL <= LV_LOG_LEVEL_TRACE
-#define LV_LOG_TRACE(dsc) lv_log_add(LV_LOG_LEVEL_TRACE, __FILE__, __LINE__, dsc);
+#define LV_LOG_TRACE(...) _lv_log_add(LV_LOG_LEVEL_TRACE, __FILE__, __LINE__, __func__, __VA_ARGS__);
#else
-#define LV_LOG_TRACE(dsc) \
- { \
- ; \
- }
+#define LV_LOG_TRACE(...)
#endif
#if LV_LOG_LEVEL <= LV_LOG_LEVEL_INFO
-#define LV_LOG_INFO(dsc) lv_log_add(LV_LOG_LEVEL_INFO, __FILE__, __LINE__, dsc);
+#define LV_LOG_INFO(...) _lv_log_add(LV_LOG_LEVEL_INFO, __FILE__, __LINE__, __func__, __VA_ARGS__);
#else
-#define LV_LOG_INFO(dsc) \
- { \
- ; \
- }
+#define LV_LOG_INFO(...)
#endif
#if LV_LOG_LEVEL <= LV_LOG_LEVEL_WARN
-#define LV_LOG_WARN(dsc) lv_log_add(LV_LOG_LEVEL_WARN, __FILE__, __LINE__, dsc);
+#define LV_LOG_WARN(...) _lv_log_add(LV_LOG_LEVEL_WARN, __FILE__, __LINE__, __func__, __VA_ARGS__);
#else
-#define LV_LOG_WARN(dsc) \
- { \
- ; \
- }
+#define LV_LOG_WARN(...)
#endif
#if LV_LOG_LEVEL <= LV_LOG_LEVEL_ERROR
-#define LV_LOG_ERROR(dsc) lv_log_add(LV_LOG_LEVEL_ERROR, __FILE__, __LINE__, dsc);
+#define LV_LOG_ERROR(...) _lv_log_add(LV_LOG_LEVEL_ERROR, __FILE__, __LINE__, __func__, __VA_ARGS__);
+#else
+#define LV_LOG_ERROR(...)
+#endif
+
+#if LV_LOG_LEVEL <= LV_LOG_LEVEL_USER
+#define LV_LOG_USER(...) _lv_log_add(LV_LOG_LEVEL_USER, __FILE__, __LINE__, __func__, __VA_ARGS__);
#else
-#define LV_LOG_ERROR(dsc) \
- { \
- ; \
- }
+#define LV_LOG_USER(...)
#endif
#else /*LV_USE_LOG*/
-/*Do nothing if `LV_USE_LOG 0`*/
-#define lv_log_add(level, file, line, dsc) \
- { \
- ; \
- }
-#define LV_LOG_TRACE(dsc) \
- { \
- ; \
- }
-#define LV_LOG_INFO(dsc) \
- { \
- ; \
- }
-#define LV_LOG_WARN(dsc) \
- { \
- ; \
- }
-#define LV_LOG_ERROR(dsc) \
- { \
- ; \
- }
+/*Do nothing if `LV_USE_LOG 0`*/
+#define _lv_log_add(level, file, line, ...)
+#define LV_LOG_TRACE(...)
+#define LV_LOG_INFO(...)
+#define LV_LOG_WARN(...)
+#define LV_LOG_ERROR(...)
+#define LV_LOG_USER(...)
#endif /*LV_USE_LOG*/
#ifdef __cplusplus
diff --git a/src/libs/lvgl/src/lv_misc/lv_math.c b/src/libs/lvgl/src/lv_misc/lv_math.c
index f015456e..45b82cd5 100644
--- a/src/libs/lvgl/src/lv_misc/lv_math.c
+++ b/src/libs/lvgl/src/lv_misc/lv_math.c
@@ -9,6 +9,7 @@
#include "lv_math.h"
#include <stdbool.h>
#include <stdlib.h>
+#include <string.h>
/*********************
* DEFINES
@@ -31,7 +32,8 @@ static const int16_t sin0_90_table[] = {
17364, 17846, 18323, 18794, 19260, 19720, 20173, 20621, 21062, 21497, 21925, 22347, 22762, 23170, 23571, 23964,
24351, 24730, 25101, 25465, 25821, 26169, 26509, 26841, 27165, 27481, 27788, 28087, 28377, 28659, 28932, 29196,
29451, 29697, 29934, 30162, 30381, 30591, 30791, 30982, 31163, 31335, 31498, 31650, 31794, 31927, 32051, 32165,
- 32269, 32364, 32448, 32523, 32587, 32642, 32687, 32722, 32747, 32762, 32767};
+ 32269, 32364, 32448, 32523, 32587, 32642, 32687, 32722, 32747, 32762, 32767
+};
/**********************
* MACROS
@@ -46,7 +48,7 @@ static const int16_t sin0_90_table[] = {
* @param angle
* @return sinus of 'angle'. sin(-90) = -32767, sin(90) = 32767
*/
-int16_t lv_trigo_sin(int16_t angle)
+LV_ATTRIBUTE_FAST_MEM int16_t _lv_trigo_sin(int16_t angle)
{
int16_t ret = 0;
angle = angle % 360;
@@ -55,13 +57,16 @@ int16_t lv_trigo_sin(int16_t angle)
if(angle < 90) {
ret = sin0_90_table[angle];
- } else if(angle >= 90 && angle < 180) {
+ }
+ else if(angle >= 90 && angle < 180) {
angle = 180 - angle;
ret = sin0_90_table[angle];
- } else if(angle >= 180 && angle < 270) {
+ }
+ else if(angle >= 180 && angle < 270) {
angle = angle - 180;
ret = -sin0_90_table[angle];
- } else { /*angle >=270*/
+ }
+ else { /*angle >=270*/
angle = 360 - angle;
ret = -sin0_90_table[angle];
}
@@ -78,7 +83,7 @@ int16_t lv_trigo_sin(int16_t angle)
* @param u3 end values in range of [0..LV_BEZIER_VAL_MAX]
* @return the value calculated from the given parameters in range of [0..LV_BEZIER_VAL_MAX]
*/
-int32_t lv_bezier3(uint32_t t, int32_t u0, int32_t u1, int32_t u2, int32_t u3)
+uint32_t _lv_bezier3(uint32_t t, uint32_t u0, uint32_t u1, uint32_t u2, uint32_t u3)
{
uint32_t t_rem = 1024 - t;
uint32_t t_rem2 = (t_rem * t_rem) >> 10;
@@ -86,21 +91,48 @@ int32_t lv_bezier3(uint32_t t, int32_t u0, int32_t u1, int32_t u2, int32_t u3)
uint32_t t2 = (t * t) >> 10;
uint32_t t3 = (t2 * t) >> 10;
- uint32_t v1 = ((uint32_t)t_rem3 * u0) >> 10;
- uint32_t v2 = ((uint32_t)3 * t_rem2 * t * u1) >> 20;
- uint32_t v3 = ((uint32_t)3 * t_rem * t2 * u2) >> 20;
- uint32_t v4 = ((uint32_t)t3 * u3) >> 10;
+ uint32_t v1 = (t_rem3 * u0) >> 10;
+ uint32_t v2 = (3 * t_rem2 * t * u1) >> 20;
+ uint32_t v3 = (3 * t_rem * t2 * u2) >> 20;
+ uint32_t v4 = (t3 * u3) >> 10;
return v1 + v2 + v3 + v4;
}
/**
+ * Get the square root of a number
+ * @param x integer which square root should be calculated
+ * @param q store the result here. q->i: integer part, q->f: fractional part in 1/256 unit
+ * @param mask: optional to skip some iterations if the magnitude of the root is known.
+ * Set to 0x8000 by default.
+ * If root < 16: mask = 0x80
+ * If root < 256: mask = 0x800
+ * Else: mask = 0x8000
+ */
+LV_ATTRIBUTE_FAST_MEM void _lv_sqrt(uint32_t x, lv_sqrt_res_t * q, uint32_t mask)
+{
+ x = x << 8; /*To get 4 bit precision. (sqrt(256) = 16 = 4 bit)*/
+
+ uint32_t root = 0;
+ uint32_t trial;
+ // http://ww1.microchip.com/...en/AppNotes/91040a.pdf
+ do {
+ trial = root + mask;
+ if(trial * trial <= x) root = trial;
+ mask = mask >> 1;
+ } while(mask);
+
+ q->i = root >> 4;
+ q->f = (root & 0xf) << 4;
+}
+
+/**
* Calculate the atan2 of a vector.
* @param x
* @param y
* @return the angle in degree calculated from the given parameters in range of [0..360]
*/
-uint16_t lv_atan2(int x, int y)
+uint16_t _lv_atan2(int x, int y)
{
// Fast XY vector to integer degree algorithm - Jan 2011 www.RomanBlack.com
// Converts any XY values including 0 to a degree value that should be
@@ -138,7 +170,8 @@ uint16_t lv_atan2(int x, int y)
if(ux > uy) {
degree = (uy * 45) / ux; // degree result will be 0-45 range
negflag += 0x10; // octant flag bit
- } else {
+ }
+ else {
degree = (ux * 45) / uy; // degree result will be 0-45 range
}
@@ -150,7 +183,8 @@ uint16_t lv_atan2(int x, int y)
if(tempdegree <= 41) comp++;
if(tempdegree <= 37) comp++;
if(tempdegree <= 32) comp++; // max is 4 degrees compensated
- } else { // else is lower half of range
+ }
+ else { // else is lower half of range
if(tempdegree >= 2) comp++;
if(tempdegree >= 6) comp++;
if(tempdegree >= 10) comp++;
@@ -168,7 +202,8 @@ uint16_t lv_atan2(int x, int y)
degree = (180 + degree);
else // else is -Y +X
degree = (180 - degree);
- } else { // else is +Y
+ }
+ else { // else is +Y
if(negflag & 0x01) // if +Y -X
degree = (360 - degree);
}
@@ -176,26 +211,48 @@ uint16_t lv_atan2(int x, int y)
}
/**
- * Calculate the integer square root of a number.
- * @param num
- * @return square root of 'num'
+ * Calculate the integer exponents.
+ * @param base
+ * @param power
+ * @return base raised to the power exponent
*/
-uint32_t lv_sqrt(uint32_t num)
+int64_t _lv_pow(int64_t base, int8_t exp)
{
- // http://www.codecodex.com/wiki/Calculate_an_integer_square_root#C
- uint32_t root = 0;
- uint32_t place = 0x40000000;
-
- while(place > num) place >>= 2;
- while(place) {
- if(num >= root + place) {
- num -= root + place;
- root += (place << 1);
- }
- root >>= 1;
- place >>= 2;
+ int64_t result = 1;
+ while(exp) {
+ if(exp & 1)
+ result *= base;
+ exp >>= 1;
+ base *= base;
}
- return root;
+
+ return result;
+}
+
+/**
+ * Get the mapped of a number given an input and output range
+ * @param x integer which mapped value should be calculated
+ * @param min_in min input range
+ * @param max_in max input range
+ * @param min_out max output range
+ * @param max_out max output range
+ * @return the mapped number
+ */
+int32_t _lv_map(int32_t x, int32_t min_in, int32_t max_in, int32_t min_out, int32_t max_out)
+{
+ if(x <= min_in) return min_out;
+ if(x >= max_in) return max_out;
+
+ /* The equation should be:
+ * ((x - min_in) / delta in) * delta_out + min_out
+ * To avoid rounding error reorder the operations:
+ * (((x - min_in) * delta_out) / delta in) + min_out
+ */
+
+ int32_t delta_in = max_in - min_in;
+ int32_t delta_out = max_out - min_out;
+
+ return ((x - min_in) * delta_out) / delta_in + min_out;
}
/**********************
diff --git a/src/libs/lvgl/src/lv_misc/lv_math.h b/src/libs/lvgl/src/lv_misc/lv_math.h
index 0f93a7c6..1730b431 100644
--- a/src/libs/lvgl/src/lv_misc/lv_math.h
+++ b/src/libs/lvgl/src/lv_misc/lv_math.h
@@ -1,5 +1,5 @@
/**
- * @file math_base.h
+ * @file lv_math.h
*
*/
@@ -13,15 +13,24 @@ extern "C" {
/*********************
* INCLUDES
*********************/
+#include "../lv_conf_internal.h"
#include <stdint.h>
/*********************
* DEFINES
*********************/
#define LV_MATH_MIN(a, b) ((a) < (b) ? (a) : (b))
+#define LV_MATH_MIN3(a, b, c) (LV_MATH_MIN(LV_MATH_MIN(a,b), c))
+#define LV_MATH_MIN4(a, b, c, d) (LV_MATH_MIN(LV_MATH_MIN(a,b), LV_MATH_MIN(c,d)))
+
#define LV_MATH_MAX(a, b) ((a) > (b) ? (a) : (b))
+#define LV_MATH_MAX3(a, b, c) (LV_MATH_MAX(LV_MATH_MAX(a,b), c))
+#define LV_MATH_MAX4(a, b, c, d) (LV_MATH_MAX(LV_MATH_MAX(a,b), LV_MATH_MAX(c,d)))
+
#define LV_MATH_ABS(x) ((x) > 0 ? (x) : (-(x)))
+#define LV_MATH_UDIV255(x) ((uint32_t)((uint32_t) (x) * 0x8081) >> 0x17)
+
#define LV_IS_SIGNED(t) (((t)(-1)) < ((t) 0))
#define LV_UMAX_OF(t) (((0x1ULL << ((sizeof(t) * 8ULL) - 1ULL)) - 1ULL) | (0xFULL << ((sizeof(t) * 8ULL) - 4ULL)))
#define LV_SMAX_OF(t) (((0x1ULL << ((sizeof(t) * 8ULL) - 1ULL)) - 1ULL) | (0x7ULL << ((sizeof(t) * 8ULL) - 4ULL)))
@@ -37,16 +46,24 @@ extern "C" {
* TYPEDEFS
**********************/
+typedef struct {
+ uint16_t i;
+ uint16_t f;
+} lv_sqrt_res_t;
+
/**********************
* GLOBAL PROTOTYPES
**********************/
+//! @cond Doxygen_Suppress
/**
* Return with sinus of an angle
* @param angle
* @return sinus of 'angle'. sin(-90) = -32767, sin(90) = 32767
*/
-int16_t lv_trigo_sin(int16_t angle);
+LV_ATTRIBUTE_FAST_MEM int16_t _lv_trigo_sin(int16_t angle);
+
+//! @endcond
/**
* Calculate a value of a Cubic Bezier function.
@@ -57,7 +74,7 @@ int16_t lv_trigo_sin(int16_t angle);
* @param u3 end values in range of [0..LV_BEZIER_VAL_MAX]
* @return the value calculated from the given parameters in range of [0..LV_BEZIER_VAL_MAX]
*/
-int32_t lv_bezier3(uint32_t t, int32_t u0, int32_t u1, int32_t u2, int32_t u3);
+uint32_t _lv_bezier3(uint32_t t, uint32_t u0, uint32_t u1, uint32_t u2, uint32_t u3);
/**
* Calculate the atan2 of a vector.
@@ -65,14 +82,42 @@ int32_t lv_bezier3(uint32_t t, int32_t u0, int32_t u1, int32_t u2, int32_t u3);
* @param y
* @return the angle in degree calculated from the given parameters in range of [0..360]
*/
-uint16_t lv_atan2(int x, int y);
+uint16_t _lv_atan2(int x, int y);
+
+//! @cond Doxygen_Suppress
+
+/**
+ * Get the square root of a number
+ * @param x integer which square root should be calculated
+ * @param q store the result here. q->i: integer part, q->f: fractional part in 1/256 unit
+ * @param mask: optional to skip some iterations if the magnitude of the root is known.
+ * Set to 0x8000 by default.
+ * If root < 16: mask = 0x80
+ * If root < 256: mask = 0x800
+ * Else: mask = 0x8000
+ */
+LV_ATTRIBUTE_FAST_MEM void _lv_sqrt(uint32_t x, lv_sqrt_res_t * q, uint32_t mask);
+
+//! @endcond
+
+/**
+ * Calculate the integer exponents.
+ * @param base
+ * @param power
+ * @return base raised to the power exponent
+ */
+int64_t _lv_pow(int64_t base, int8_t exp);
/**
- * Calculate the integer square root of a number.
- * @param num
- * @return square root of 'num'
+ * Get the mapped of a number given an input and output range
+ * @param x integer which mapped value should be calculated
+ * @param min_in min input range
+ * @param max_in max input range
+ * @param min_out max output range
+ * @param max_out max output range
+ * @return the mapped number
*/
-uint32_t lv_sqrt(uint32_t num);
+int32_t _lv_map(int32_t x, int32_t min_in, int32_t max_in, int32_t min, int32_t max);
/**********************
* MACROS
diff --git a/src/libs/lvgl/src/lv_misc/lv_mem.c b/src/libs/lvgl/src/lv_misc/lv_mem.c
index 9e18310f..7a7f9e8c 100644
--- a/src/libs/lvgl/src/lv_misc/lv_mem.c
+++ b/src/libs/lvgl/src/lv_misc/lv_mem.c
@@ -9,10 +9,11 @@
*********************/
#include "lv_mem.h"
#include "lv_math.h"
+#include "lv_gc.h"
#include <string.h>
#if LV_MEM_CUSTOM != 0
-#include LV_MEM_CUSTOM_INCLUDE
+ #include LV_MEM_CUSTOM_INCLUDE
#endif
/*********************
@@ -20,13 +21,17 @@
*********************/
/*Add memory junk on alloc (0xaa) and free(0xbb) (just for testing purposes)*/
#ifndef LV_MEM_ADD_JUNK
-#define LV_MEM_ADD_JUNK 0
+ #define LV_MEM_ADD_JUNK 0
+#endif
+
+#ifndef LV_MEM_FULL_DEFRAG_CNT
+ #define LV_MEM_FULL_DEFRAG_CNT 16
#endif
#ifdef LV_ARCH_64
-#define MEM_UNIT uint64_t
+ #define MEM_UNIT uint64_t
#else
-#define MEM_UNIT uint32_t
+ #define MEM_UNIT uint32_t
#endif
/**********************
@@ -35,55 +40,77 @@
#if LV_ENABLE_GC == 0 /*gc custom allocations must not include header*/
-/*The size of this union must be 4 bytes (uint32_t)*/
-typedef union
-{
- struct
- {
+/*The size of this union must be 4/8 bytes (uint32_t/uint64_t)*/
+typedef union {
+ struct {
MEM_UNIT used : 1; /* 1: if the entry is used*/
- MEM_UNIT d_size : 31; /* Size off the data (1 means 4 bytes)*/
+ MEM_UNIT d_size : 31; /* Size of the data*/
} s;
MEM_UNIT header; /* The header (used + d_size)*/
} lv_mem_header_t;
-typedef struct
-{
+typedef struct {
lv_mem_header_t header;
uint8_t first_data; /*First data byte in the allocated data (Just for easily create a pointer)*/
} lv_mem_ent_t;
#endif /* LV_ENABLE_GC */
+#ifdef LV_ARCH_64
+ #define ALIGN_MASK 0x7
+#else
+ #define ALIGN_MASK 0x3
+#endif
+
+#define MEM_BUF_SMALL_SIZE 16
+
/**********************
* STATIC PROTOTYPES
**********************/
#if LV_MEM_CUSTOM == 0
-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 void ent_trunc(lv_mem_ent_t * e, size_t size);
+ 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 void ent_trunc(lv_mem_ent_t * e, size_t size);
#endif
/**********************
* STATIC VARIABLES
**********************/
#if LV_MEM_CUSTOM == 0
-static uint8_t * work_mem;
+ static uint8_t * work_mem;
#endif
static uint32_t zero_mem; /*Give the address of this variable if 0 byte should be allocated*/
+#if LV_MEM_CUSTOM == 0
+ static uint32_t mem_max_size; /*Tracks the maximum total size of memory ever used from the internal heap*/
+#endif
+
+static uint8_t mem_buf1_32[MEM_BUF_SMALL_SIZE];
+static uint8_t mem_buf2_32[MEM_BUF_SMALL_SIZE];
+
+static lv_mem_buf_t mem_buf_small[] = {{.p = mem_buf1_32, .size = MEM_BUF_SMALL_SIZE, .used = 0},
+ {.p = mem_buf2_32, .size = MEM_BUF_SMALL_SIZE, .used = 0}
+};
+
/**********************
* MACROS
**********************/
+#define COPY32 *d32 = *s32; d32++; s32++;
+#define COPY8 *d8 = *s8; d8++; s8++;
+#define SET32(x) *d32 = x; d32++;
+#define SET8(x) *d8 = x; d8++;
+#define REPEAT8(expr) expr expr expr expr expr expr expr expr
+
/**********************
* GLOBAL FUNCTIONS
**********************/
/**
- * Initiaiize the dyn_mem module (work memory and other variables)
+ * Initialize the dyn_mem module (work memory and other variables)
*/
-void lv_mem_init(void)
+void _lv_mem_init(void)
{
#if LV_MEM_CUSTOM == 0
@@ -97,7 +124,7 @@ void lv_mem_init(void)
lv_mem_ent_t * full = (lv_mem_ent_t *)work_mem;
full->header.s.used = 0;
- /*The total mem size id reduced by the first header and the close patterns */
+ /*The total mem size reduced by the first header and the close patterns */
full->header.s.d_size = LV_MEM_SIZE - sizeof(lv_mem_header_t);
#endif
}
@@ -106,13 +133,12 @@ void lv_mem_init(void)
* Clean up the memory buffer which frees all the allocated memories.
* @note It work only if `LV_MEM_CUSTOM == 0`
*/
-void lv_mem_deinit(void)
+void _lv_mem_deinit(void)
{
#if LV_MEM_CUSTOM == 0
- memset(work_mem, 0x00, (LV_MEM_SIZE / sizeof(MEM_UNIT)) * sizeof(MEM_UNIT));
lv_mem_ent_t * full = (lv_mem_ent_t *)work_mem;
full->header.s.used = 0;
- /*The total mem size id reduced by the first header and the close patterns */
+ /*The total mem size reduced by the first header and the close patterns */
full->header.s.d_size = LV_MEM_SIZE - sizeof(lv_mem_header_t);
#endif
}
@@ -128,19 +154,8 @@ void * lv_mem_alloc(size_t size)
return &zero_mem;
}
-#ifdef LV_ARCH_64
- /*Round the size up to 8*/
- if(size & 0x7) {
- size = size & (~0x7);
- size += 8;
- }
-#else
- /*Round the size up to 4*/
- if(size & 0x3) {
- size = size & (~0x3);
- size += 4;
- }
-#endif
+ /*Round the size up to ALIGN_MASK*/
+ size = (size + ALIGN_MASK) & (~ALIGN_MASK);
void * alloc = NULL;
#if LV_MEM_CUSTOM == 0
@@ -160,7 +175,7 @@ void * lv_mem_alloc(size_t size)
} while(e != NULL && alloc == NULL);
#else
-/*Use custom, user defined malloc function*/
+ /*Use custom, user defined malloc function*/
#if LV_ENABLE_GC == 1 /*gc must not include header*/
alloc = LV_MEM_CUSTOM_ALLOC(size);
#else /* LV_ENABLE_GC */
@@ -176,10 +191,22 @@ void * lv_mem_alloc(size_t size)
#endif /* LV_MEM_CUSTOM */
#if LV_MEM_ADD_JUNK
- if(alloc != NULL) memset(alloc, 0xaa, size);
+ if(alloc != NULL) _lv_memset(alloc, 0xaa, size);
#endif
- if(alloc == NULL) LV_LOG_WARN("Couldn't allocate memory");
+ if(alloc == NULL) {
+ LV_LOG_WARN("Couldn't allocate memory");
+ }
+ else {
+#if LV_MEM_CUSTOM == 0
+ /* just a safety check, should always be true */
+ if((uintptr_t) alloc > (uintptr_t) work_mem) {
+ if((((uintptr_t) alloc - (uintptr_t) work_mem) + size) > mem_max_size) {
+ mem_max_size = ((uintptr_t) alloc - (uintptr_t) work_mem) + size;
+ }
+ }
+#endif
+ }
return alloc;
}
@@ -194,7 +221,7 @@ void lv_mem_free(const void * data)
if(data == NULL) return;
#if LV_MEM_ADD_JUNK
- memset((void *)data, 0xbb, lv_mem_get_size(data));
+ _lv_memset((void *)data, 0xbb, _lv_mem_get_size(data));
#endif
#if LV_ENABLE_GC == 0
@@ -205,19 +232,29 @@ void lv_mem_free(const void * data)
#if LV_MEM_CUSTOM == 0
#if LV_MEM_AUTO_DEFRAG
- /* Make a simple defrag.
- * Join the following free entries after this*/
- lv_mem_ent_t * e_next;
- e_next = ent_get_next(e);
- while(e_next != NULL) {
- if(e_next->header.s.used == 0) {
- e->header.s.d_size += e_next->header.s.d_size + sizeof(e->header);
- } else {
- break;
+ static uint16_t full_defrag_cnt = 0;
+ full_defrag_cnt++;
+ if(full_defrag_cnt < LV_MEM_FULL_DEFRAG_CNT) {
+ /* Make a simple defrag.
+ * Join the following free entries after this*/
+ lv_mem_ent_t * e_next;
+ e_next = ent_get_next(e);
+ while(e_next != NULL) {
+ if(e_next->header.s.used == 0) {
+ e->header.s.d_size += e_next->header.s.d_size + sizeof(e->header);
+ }
+ else {
+ break;
+ }
+ e_next = ent_get_next(e_next);
}
- e_next = ent_get_next(e_next);
}
-#endif
+ else {
+ full_defrag_cnt = 0;
+ lv_mem_defrag();
+
+ }
+#endif /*LV_MEM_AUTO_DEFRAG*/
#else /*Use custom, user defined free function*/
#if LV_ENABLE_GC == 0
LV_MEM_CUSTOM_FREE(e);
@@ -239,6 +276,9 @@ void lv_mem_free(const void * data)
void * lv_mem_realloc(void * data_p, size_t new_size)
{
+ /*Round the size up to ALIGN_MASK*/
+ new_size = (new_size + ALIGN_MASK) & (~ALIGN_MASK);
+
/*data_p could be previously freed pointer (in this case it is invalid)*/
if(data_p != NULL) {
lv_mem_ent_t * e = (lv_mem_ent_t *)((uint8_t *)data_p - sizeof(lv_mem_header_t));
@@ -247,7 +287,7 @@ void * lv_mem_realloc(void * data_p, size_t new_size)
}
}
- uint32_t old_size = lv_mem_get_size(data_p);
+ uint32_t old_size = _lv_mem_get_size(data_p);
if(old_size == new_size) return data_p; /*Also avoid reallocating the same memory*/
#if LV_MEM_CUSTOM == 0
@@ -261,17 +301,19 @@ void * lv_mem_realloc(void * data_p, size_t new_size)
void * new_p;
new_p = lv_mem_alloc(new_size);
+ if(new_p == NULL) {
+ LV_LOG_WARN("Couldn't allocate memory");
+ return NULL;
+ }
- if(new_p != NULL && data_p != NULL) {
+ if(data_p != NULL) {
/*Copy the old data to the new. Use the smaller size*/
- if(old_size != 0) {
- memcpy(new_p, data_p, LV_MATH_MIN(new_size, old_size));
- lv_mem_free(data_p);
+ if(old_size != 0 && new_size != 0) {
+ _lv_memcpy(new_p, data_p, LV_MATH_MIN(new_size, old_size));
}
+ lv_mem_free(data_p);
}
- if(new_p == NULL) LV_LOG_WARN("Couldn't allocate memory");
-
return new_p;
}
@@ -301,7 +343,8 @@ void lv_mem_defrag(void)
while(e_free != NULL) {
if(e_free->header.s.used != 0) {
e_free = ent_get_next(e_free);
- } else {
+ }
+ else {
break;
}
}
@@ -313,7 +356,8 @@ void lv_mem_defrag(void)
while(e_next != NULL) {
if(e_next->header.s.used == 0) {
e_free->header.s.d_size += e_next->header.s.d_size + sizeof(e_next->header);
- } else {
+ }
+ else {
break;
}
@@ -328,6 +372,25 @@ void lv_mem_defrag(void)
#endif
}
+lv_res_t lv_mem_test(void)
+{
+#if LV_MEM_CUSTOM == 0
+ lv_mem_ent_t * e;
+ e = ent_get_next(NULL);
+ while(e) {
+ if(e->header.s.d_size > LV_MEM_SIZE) {
+ return LV_RES_INV;
+ }
+ uint8_t * e8 = (uint8_t *) e;
+ if(e8 + e->header.s.d_size > work_mem + LV_MEM_SIZE) {
+ return LV_RES_INV;
+ }
+ e = ent_get_next(e);
+ }
+#endif
+ return LV_RES_OK;
+}
+
/**
* Give information about the work memory of dynamic allocation
* @param mon_p pointer to a dm_mon_p variable,
@@ -336,12 +399,11 @@ void lv_mem_defrag(void)
void lv_mem_monitor(lv_mem_monitor_t * mon_p)
{
/*Init the data*/
- memset(mon_p, 0, sizeof(lv_mem_monitor_t));
+ _lv_memset(mon_p, 0, sizeof(lv_mem_monitor_t));
#if LV_MEM_CUSTOM == 0
lv_mem_ent_t * e;
- e = NULL;
- e = ent_get_next(e);
+ e = ent_get_next(NULL);
while(e != NULL) {
if(e->header.s.used == 0) {
@@ -350,16 +412,23 @@ void lv_mem_monitor(lv_mem_monitor_t * mon_p)
if(e->header.s.d_size > mon_p->free_biggest_size) {
mon_p->free_biggest_size = e->header.s.d_size;
}
- } else {
+ }
+ else {
mon_p->used_cnt++;
}
e = ent_get_next(e);
}
mon_p->total_size = LV_MEM_SIZE;
- mon_p->used_pct = 100 - (100U * mon_p->free_size) / mon_p->total_size;
- mon_p->frag_pct = (uint32_t)mon_p->free_biggest_size * 100U / mon_p->free_size;
- mon_p->frag_pct = 100 - mon_p->frag_pct;
+ mon_p->max_used = mem_max_size;
+ mon_p->used_pct = 100 - (100U * mon_p->free_size) / mon_p->total_size;
+ if(mon_p->free_size > 0) {
+ mon_p->frag_pct = mon_p->free_biggest_size * 100U / mon_p->free_size;
+ mon_p->frag_pct = 100 - mon_p->frag_pct;
+ }
+ else {
+ mon_p->frag_pct = 0; /*no fragmentation if all the RAM is used*/
+ }
#endif
}
@@ -371,7 +440,7 @@ void lv_mem_monitor(lv_mem_monitor_t * mon_p)
#if LV_ENABLE_GC == 0
-uint32_t lv_mem_get_size(const void * data)
+uint32_t _lv_mem_get_size(const void * data)
{
if(data == NULL) return 0;
if(data == &zero_mem) return 0;
@@ -383,13 +452,306 @@ uint32_t lv_mem_get_size(const void * data)
#else /* LV_ENABLE_GC */
-uint32_t lv_mem_get_size(const void * data)
+uint32_t _lv_mem_get_size(const void * data)
{
return LV_MEM_CUSTOM_GET_SIZE(data);
}
#endif /*LV_ENABLE_GC*/
+/**
+ * Get a temporal buffer with the given size.
+ * @param size the required size
+ */
+void * _lv_mem_buf_get(uint32_t size)
+{
+ if(size == 0) return NULL;
+
+ /*Try small static buffers first*/
+ uint8_t i;
+ if(size <= MEM_BUF_SMALL_SIZE) {
+ for(i = 0; i < sizeof(mem_buf_small) / sizeof(mem_buf_small[0]); i++) {
+ if(mem_buf_small[i].used == 0) {
+ mem_buf_small[i].used = 1;
+ return mem_buf_small[i].p;
+ }
+ }
+ }
+
+ /*Try to find a free buffer with suitable size */
+ int8_t i_guess = -1;
+ for(i = 0; i < LV_MEM_BUF_MAX_NUM; i++) {
+ if(LV_GC_ROOT(_lv_mem_buf[i]).used == 0 && LV_GC_ROOT(_lv_mem_buf[i]).size >= size) {
+ if(LV_GC_ROOT(_lv_mem_buf[i]).size == size) {
+ LV_GC_ROOT(_lv_mem_buf[i]).used = 1;
+ return LV_GC_ROOT(_lv_mem_buf[i]).p;
+ }
+ else if(i_guess < 0) {
+ i_guess = i;
+ }
+ /*If size of `i` is closer to `size` prefer it*/
+ else if(LV_GC_ROOT(_lv_mem_buf[i]).size < LV_GC_ROOT(_lv_mem_buf[i_guess]).size) {
+ i_guess = i;
+ }
+ }
+ }
+
+ if(i_guess >= 0) {
+ LV_GC_ROOT(_lv_mem_buf[i_guess]).used = 1;
+ return LV_GC_ROOT(_lv_mem_buf[i_guess]).p;
+ }
+
+ /*Reallocate a free buffer*/
+ for(i = 0; i < LV_MEM_BUF_MAX_NUM; i++) {
+ if(LV_GC_ROOT(_lv_mem_buf[i]).used == 0) {
+ /*if this fails you probably need to increase your LV_MEM_SIZE/heap size*/
+ void * buf = lv_mem_realloc(LV_GC_ROOT(_lv_mem_buf[i]).p, size);
+ if(buf == NULL) {
+ LV_DEBUG_ASSERT(false, "Out of memory, can't allocate a new buffer (increase your LV_MEM_SIZE/heap size)", 0x00);
+ return NULL;
+ }
+ LV_GC_ROOT(_lv_mem_buf[i]).used = 1;
+ LV_GC_ROOT(_lv_mem_buf[i]).size = size;
+ LV_GC_ROOT(_lv_mem_buf[i]).p = buf;
+ return LV_GC_ROOT(_lv_mem_buf[i]).p;
+ }
+ }
+
+ LV_DEBUG_ASSERT(false, "No free buffer. Increase LV_MEM_BUF_MAX_NUM.", 0x00);
+ return NULL;
+}
+
+/**
+ * Release a memory buffer
+ * @param p buffer to release
+ */
+void _lv_mem_buf_release(void * p)
+{
+ uint8_t i;
+
+ /*Try small static buffers first*/
+ for(i = 0; i < sizeof(mem_buf_small) / sizeof(mem_buf_small[0]); i++) {
+ if(mem_buf_small[i].p == p) {
+ mem_buf_small[i].used = 0;
+ return;
+ }
+ }
+
+ for(i = 0; i < LV_MEM_BUF_MAX_NUM; i++) {
+ if(LV_GC_ROOT(_lv_mem_buf[i]).p == p) {
+ LV_GC_ROOT(_lv_mem_buf[i]).used = 0;
+ return;
+ }
+ }
+
+ LV_LOG_ERROR("lv_mem_buf_release: p is not a known buffer")
+}
+
+/**
+ * Free all memory buffers
+ */
+void _lv_mem_buf_free_all(void)
+{
+ uint8_t i;
+ for(i = 0; i < sizeof(mem_buf_small) / sizeof(mem_buf_small[0]); i++) {
+ mem_buf_small[i].used = 0;
+ }
+
+ for(i = 0; i < LV_MEM_BUF_MAX_NUM; i++) {
+ if(LV_GC_ROOT(_lv_mem_buf[i]).p) {
+ lv_mem_free(LV_GC_ROOT(_lv_mem_buf[i]).p);
+ LV_GC_ROOT(_lv_mem_buf[i]).p = NULL;
+ LV_GC_ROOT(_lv_mem_buf[i]).used = 0;
+ LV_GC_ROOT(_lv_mem_buf[i]).size = 0;
+ }
+ }
+}
+
+#if LV_MEMCPY_MEMSET_STD == 0
+/**
+ * Same as `memcpy` but optimized for 4 byte operation.
+ * @param dst pointer to the destination buffer
+ * @param src pointer to the source buffer
+ * @param len number of byte to copy
+ */
+LV_ATTRIBUTE_FAST_MEM void * _lv_memcpy(void * dst, const void * src, size_t len)
+{
+ uint8_t * d8 = dst;
+ const uint8_t * s8 = src;
+
+ lv_uintptr_t d_align = (lv_uintptr_t)d8 & ALIGN_MASK;
+ lv_uintptr_t s_align = (lv_uintptr_t)s8 & ALIGN_MASK;
+
+ /*Byte copy for unaligned memories*/
+ if(s_align != d_align) {
+ while(len > 32) {
+ REPEAT8(COPY8);
+ REPEAT8(COPY8);
+ REPEAT8(COPY8);
+ REPEAT8(COPY8);
+ len -= 32;
+ }
+ while(len) {
+ COPY8
+ len--;
+ }
+ return dst;
+ }
+
+ /*Make the memories aligned*/
+ if(d_align) {
+ d_align = ALIGN_MASK + 1 - d_align;
+ while(d_align && len) {
+ COPY8;
+ d_align--;
+ len--;
+ }
+ }
+
+ uint32_t * d32 = (uint32_t *)d8;
+ const uint32_t * s32 = (uint32_t *)s8;
+ while(len > 32) {
+ REPEAT8(COPY32)
+ len -= 32;
+ }
+
+ while(len > 4) {
+ COPY32;
+ len -= 4;
+ }
+
+ d8 = (uint8_t *)d32;
+ s8 = (const uint8_t *)s32;
+ while(len) {
+ COPY8
+ len--;
+ }
+
+ return dst;
+}
+
+/**
+ * Same as `memset` but optimized for 4 byte operation.
+ * @param dst pointer to the destination buffer
+ * @param v value to set [0..255]
+ * @param len number of byte to set
+ */
+LV_ATTRIBUTE_FAST_MEM void _lv_memset(void * dst, uint8_t v, size_t len)
+{
+
+ uint8_t * d8 = (uint8_t *) dst;
+
+ uintptr_t d_align = (lv_uintptr_t) d8 & ALIGN_MASK;
+
+ /*Make the address aligned*/
+ if(d_align) {
+ d_align = ALIGN_MASK + 1 - d_align;
+ while(d_align && len) {
+ SET8(v);
+ len--;
+ d_align--;
+ }
+ }
+
+ uint32_t v32 = v + (v << 8) + (v << 16) + (v << 24);
+
+ uint32_t * d32 = (uint32_t *)d8;
+
+ while(len > 32) {
+ REPEAT8(SET32(v32));
+ len -= 32;
+ }
+
+ while(len > 4) {
+ SET32(v32);
+ len -= 4;
+ }
+
+ d8 = (uint8_t *)d32;
+ while(len) {
+ SET8(v);
+ len--;
+ }
+}
+
+/**
+ * Same as `memset(dst, 0x00, len)` but optimized for 4 byte operation.
+ * @param dst pointer to the destination buffer
+ * @param len number of byte to set
+ */
+LV_ATTRIBUTE_FAST_MEM void _lv_memset_00(void * dst, size_t len)
+{
+ uint8_t * d8 = (uint8_t *) dst;
+ uintptr_t d_align = (lv_uintptr_t) d8 & ALIGN_MASK;
+
+ /*Make the address aligned*/
+ if(d_align) {
+ d_align = ALIGN_MASK + 1 - d_align;
+ while(d_align && len) {
+ SET8(0);
+ len--;
+ d_align--;
+ }
+ }
+
+ uint32_t * d32 = (uint32_t *)d8;
+ while(len > 32) {
+ REPEAT8(SET32(0));
+ len -= 32;
+ }
+
+ while(len > 4) {
+ SET32(0);
+ len -= 4;
+ }
+
+ d8 = (uint8_t *)d32;
+ while(len) {
+ SET8(0);
+ len--;
+ }
+}
+
+/**
+ * Same as `memset(dst, 0xFF, len)` but optimized for 4 byte operation.
+ * @param dst pointer to the destination buffer
+ * @param len number of byte to set
+ */
+LV_ATTRIBUTE_FAST_MEM void _lv_memset_ff(void * dst, size_t len)
+{
+ uint8_t * d8 = (uint8_t *) dst;
+ uintptr_t d_align = (lv_uintptr_t) d8 & ALIGN_MASK;
+
+ /*Make the address aligned*/
+ if(d_align) {
+ d_align = ALIGN_MASK + 1 - d_align;
+ while(d_align && len) {
+ SET8(0xFF);
+ len--;
+ d_align--;
+ }
+ }
+
+ uint32_t * d32 = (uint32_t *)d8;
+ while(len > 32) {
+ REPEAT8(SET32(0xFFFFFFFF));
+ len -= 32;
+ }
+
+ while(len > 4) {
+ SET32(0xFFFFFFFF);
+ len -= 4;
+ }
+
+ d8 = (uint8_t *)d32;
+ while(len) {
+ SET8(0xFF);
+ len--;
+ }
+}
+
+#endif /*LV_MEMCPY_MEMSET_STD*/
+
/**********************
* STATIC FUNCTIONS
**********************/
@@ -406,7 +768,8 @@ static lv_mem_ent_t * ent_get_next(lv_mem_ent_t * act_e)
if(act_e == NULL) { /*NULL means: get the first entry*/
next_e = (lv_mem_ent_t *)work_mem;
- } else { /*Get the next entry */
+ }
+ else { /*Get the next entry */
uint8_t * data = &act_e->first_data;
next_e = (lv_mem_ent_t *)&data[act_e->header.s.d_size];
@@ -425,13 +788,11 @@ 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)
{
void * alloc = NULL;
-
/*If the memory is free and big enough then use it */
if(e->header.s.used == 0 && e->header.s.d_size >= size) {
/*Truncate the entry to the desired size */
- ent_trunc(e, size),
-
- e->header.s.used = 1;
+ ent_trunc(e, size);
+ e->header.s.used = 1;
/*Save the allocated data*/
alloc = &e->first_data;
@@ -447,19 +808,8 @@ static void * ent_alloc(lv_mem_ent_t * e, size_t size)
*/
static void ent_trunc(lv_mem_ent_t * e, size_t size)
{
-#ifdef LV_ARCH_64
- /*Round the size up to 8*/
- if(size & 0x7) {
- size = size & (~0x7);
- size += 8;
- }
-#else
- /*Round the size up to 4*/
- if(size & 0x3) {
- size = size & (~0x3);
- size += 4;
- }
-#endif
+ /*Round the size up to ALIGN_MASK*/
+ size = (size + ALIGN_MASK) & (~ALIGN_MASK);
/*Don't let empty space only for a header without data*/
if(e->header.s.d_size == size + sizeof(lv_mem_header_t)) {
@@ -472,10 +822,10 @@ static void ent_trunc(lv_mem_ent_t * e, size_t size)
lv_mem_ent_t * after_new_e = (lv_mem_ent_t *)&e_data[size];
after_new_e->header.s.used = 0;
after_new_e->header.s.d_size = (uint32_t)e->header.s.d_size - size - sizeof(lv_mem_header_t);
- }
- /* Set the new size for the original entry */
- e->header.s.d_size = (uint32_t)size;
+ /* Set the new size for the original entry */
+ e->header.s.d_size = (uint32_t)size;
+ }
}
#endif
diff --git a/src/libs/lvgl/src/lv_misc/lv_mem.h b/src/libs/lvgl/src/lv_misc/lv_mem.h
index f7240742..9c20a23f 100644
--- a/src/libs/lvgl/src/lv_misc/lv_mem.h
+++ b/src/libs/lvgl/src/lv_misc/lv_mem.h
@@ -13,21 +13,25 @@ extern "C" {
/*********************
* INCLUDES
*********************/
-#ifdef LV_CONF_INCLUDE_SIMPLE
-#include "lv_conf.h"
-#else
-#include "../../../lv_conf.h"
-#endif
+#include "../lv_conf_internal.h"
#include <stdint.h>
#include <stddef.h>
#include "lv_log.h"
#include "lv_types.h"
+#if LV_MEMCPY_MEMSET_STD
+#include <string.h>
+#endif
+
/*********************
* DEFINES
*********************/
+#ifndef LV_MEM_BUF_MAX_NUM
+#define LV_MEM_BUF_MAX_NUM 16
+#endif
+
/**********************
* TYPEDEFS
**********************/
@@ -35,31 +39,40 @@ extern "C" {
/**
* Heap information structure.
*/
-typedef struct
-{
+typedef struct {
uint32_t total_size; /**< Total heap size */
uint32_t free_cnt;
uint32_t free_size; /**< Size of available memory */
uint32_t free_biggest_size;
uint32_t used_cnt;
+ uint32_t max_used; /**< Max size of Heap memory used */
uint8_t used_pct; /**< Percentage used */
uint8_t frag_pct; /**< Amount of fragmentation */
} lv_mem_monitor_t;
+typedef struct {
+ void * p;
+ uint16_t size;
+ uint8_t used : 1;
+} lv_mem_buf_t;
+
+typedef lv_mem_buf_t lv_mem_buf_arr_t[LV_MEM_BUF_MAX_NUM];
+extern lv_mem_buf_arr_t _lv_mem_buf;
+
/**********************
* GLOBAL PROTOTYPES
**********************/
/**
- * Initiaize the dyn_mem module (work memory and other variables)
+ * Initialize the dyn_mem module (work memory and other variables)
*/
-void lv_mem_init(void);
+void _lv_mem_init(void);
/**
* Clean up the memory buffer which frees all the allocated memories.
* @note It work only if `LV_MEM_CUSTOM == 0`
*/
-void lv_mem_deinit(void);
+void _lv_mem_deinit(void);
/**
* Allocate a memory dynamically
@@ -89,6 +102,12 @@ void * lv_mem_realloc(void * data_p, size_t new_size);
void lv_mem_defrag(void);
/**
+ *
+ * @return
+ */
+lv_res_t lv_mem_test(void);
+
+/**
* Give information about the work memory of dynamic allocation
* @param mon_p pointer to a dm_mon_p variable,
* the result of the analysis will be stored here
@@ -100,7 +119,137 @@ void lv_mem_monitor(lv_mem_monitor_t * mon_p);
* @param data pointer to an allocated memory
* @return the size of data memory in bytes
*/
-uint32_t lv_mem_get_size(const void * data);
+uint32_t _lv_mem_get_size(const void * data);
+
+/**
+ * Get a temporal buffer with the given size.
+ * @param size the required size
+ */
+void * _lv_mem_buf_get(uint32_t size);
+
+/**
+ * Release a memory buffer
+ * @param p buffer to release
+ */
+void _lv_mem_buf_release(void * p);
+
+/**
+ * Free all memory buffers
+ */
+void _lv_mem_buf_free_all(void);
+
+//! @cond Doxygen_Suppress
+
+#if LV_MEMCPY_MEMSET_STD
+
+/**
+ * Wrapper for the standard memcpy
+ * @param dst pointer to the destination buffer
+ * @param src pointer to the source buffer
+ * @param len number of byte to copy
+ */
+static inline void * _lv_memcpy(void * dst, const void * src, size_t len)
+{
+ return memcpy(dst, src, len);
+}
+
+/**
+ * Wrapper for the standard memcpy
+ * @param dst pointer to the destination buffer
+ * @param src pointer to the source buffer
+ * @param len number of byte to copy
+ */
+static inline void * _lv_memcpy_small(void * dst, const void * src, size_t len)
+{
+ return memcpy(dst, src, len);
+}
+
+/**
+ * Wrapper for the standard memset
+ * @param dst pointer to the destination buffer
+ * @param v value to set [0..255]
+ * @param len number of byte to set
+ */
+static inline void _lv_memset(void * dst, uint8_t v, size_t len)
+{
+ memset(dst, v, len);
+}
+
+/**
+ * Wrapper for the standard memset with fixed 0x00 value
+ * @param dst pointer to the destination buffer
+ * @param len number of byte to set
+ */
+static inline void _lv_memset_00(void * dst, size_t len)
+{
+ memset(dst, 0x00, len);
+}
+
+/**
+ * Wrapper for the standard memset with fixed 0xFF value
+ * @param dst pointer to the destination buffer
+ * @param len number of byte to set
+ */
+static inline void _lv_memset_ff(void * dst, size_t len)
+{
+ memset(dst, 0xFF, len);
+}
+
+#else
+/**
+ * Same as `memcpy` but optimized for 4 byte operation.
+ * @param dst pointer to the destination buffer
+ * @param src pointer to the source buffer
+ * @param len number of byte to copy
+ */
+LV_ATTRIBUTE_FAST_MEM void * _lv_memcpy(void * dst, const void * src, size_t len);
+
+/**
+ * Same as `memcpy` but optimized to copy only a few bytes.
+ * @param dst pointer to the destination buffer
+ * @param src pointer to the source buffer
+ * @param len number of byte to copy
+ */
+LV_ATTRIBUTE_FAST_MEM static inline void * _lv_memcpy_small(void * dst, const void * src, size_t len)
+{
+ uint8_t * d8 = (uint8_t *)dst;
+ const uint8_t * s8 = (const uint8_t *)src;
+
+ while(len) {
+ *d8 = *s8;
+ d8++;
+ s8++;
+ len--;
+ }
+
+ return dst;
+}
+
+/**
+ * Same as `memset` but optimized for 4 byte operation.
+ * @param dst pointer to the destination buffer
+ * @param v value to set [0..255]
+ * @param len number of byte to set
+ */
+LV_ATTRIBUTE_FAST_MEM void _lv_memset(void * dst, uint8_t v, size_t len);
+
+/**
+ * Same as `memset(dst, 0x00, len)` but optimized for 4 byte operation.
+ * @param dst pointer to the destination buffer
+ * @param len number of byte to set
+ */
+LV_ATTRIBUTE_FAST_MEM void _lv_memset_00(void * dst, size_t len);
+
+/**
+ * Same as `memset(dst, 0xFF, len)` but optimized for 4 byte operation.
+ * @param dst pointer to the destination buffer
+ * @param len number of byte to set
+ */
+LV_ATTRIBUTE_FAST_MEM void _lv_memset_ff(void * dst, size_t len);
+
+//! @endcond
+
+#endif
/**********************
* MACROS
diff --git a/src/libs/lvgl/src/lv_misc/lv_misc.mk b/src/libs/lvgl/src/lv_misc/lv_misc.mk
index 67f496ba..898a248d 100644
--- a/src/libs/lvgl/src/lv_misc/lv_misc.mk
+++ b/src/libs/lvgl/src/lv_misc/lv_misc.mk
@@ -1,4 +1,3 @@
-CSRCS += lv_circ.c
CSRCS += lv_area.c
CSRCS += lv_task.c
CSRCS += lv_fs.c
@@ -7,6 +6,7 @@ CSRCS += lv_mem.c
CSRCS += lv_ll.c
CSRCS += lv_color.c
CSRCS += lv_txt.c
+CSRCS += lv_txt_ap.c
CSRCS += lv_math.c
CSRCS += lv_log.c
CSRCS += lv_gc.c
@@ -14,9 +14,9 @@ CSRCS += lv_utils.c
CSRCS += lv_async.c
CSRCS += lv_printf.c
CSRCS += lv_bidi.c
+CSRCS += lv_debug.c
+DEPPATH += --dep-path $(LVGL_DIR)/$(LVGL_DIR_NAME)/src/lv_misc
+VPATH += :$(LVGL_DIR)/$(LVGL_DIR_NAME)/src/lv_misc
-DEPPATH += --dep-path $(LVGL_DIR)/lvgl/src/lv_misc
-VPATH += :$(LVGL_DIR)/lvgl/src/lv_misc
-
-CFLAGS += "-I$(LVGL_DIR)/lvgl/src/lv_misc"
+CFLAGS += "-I$(LVGL_DIR)/$(LVGL_DIR_NAME)/src/lv_misc"
diff --git a/src/libs/lvgl/src/lv_misc/lv_printf.c b/src/libs/lvgl/src/lv_misc/lv_printf.c
index e05f35be..bb6f3430 100644
--- a/src/libs/lvgl/src/lv_misc/lv_printf.c
+++ b/src/libs/lvgl/src/lv_misc/lv_printf.c
@@ -37,56 +37,57 @@
#include <stdbool.h>
#include <stdint.h>
+#define PRINTF_DISABLE_SUPPORT_FLOAT LV_SPRINTF_DISABLE_FLOAT
// 'ntoa' conversion buffer size, this must be big enough to hold one converted
// numeric number including padded zeros (dynamically created on stack)
// default: 32 byte
#ifndef PRINTF_NTOA_BUFFER_SIZE
-#define PRINTF_NTOA_BUFFER_SIZE 32U
+ #define PRINTF_NTOA_BUFFER_SIZE 32U
#endif
// 'ftoa' conversion buffer size, this must be big enough to hold one converted
// float number including padded zeros (dynamically created on stack)
// default: 32 byte
#ifndef PRINTF_FTOA_BUFFER_SIZE
-#define PRINTF_FTOA_BUFFER_SIZE 32U
+ #define PRINTF_FTOA_BUFFER_SIZE 32U
#endif
// support for the floating point type (%f)
// default: activated
-#ifndef PRINTF_DISABLE_SUPPORT_FLOAT
-#define PRINTF_SUPPORT_FLOAT
+#if !PRINTF_DISABLE_SUPPORT_FLOAT
+ #define PRINTF_SUPPORT_FLOAT
#endif
// support for exponential floating point notation (%e/%g)
// default: activated
#ifndef PRINTF_DISABLE_SUPPORT_EXPONENTIAL
-#define PRINTF_SUPPORT_EXPONENTIAL
+ #define PRINTF_SUPPORT_EXPONENTIAL
#endif
// define the default floating point precision
// default: 6 digits
#ifndef PRINTF_DEFAULT_FLOAT_PRECISION
-#define PRINTF_DEFAULT_FLOAT_PRECISION 6U
+ #define PRINTF_DEFAULT_FLOAT_PRECISION 6U
#endif
// define the largest float suitable to print with %f
// default: 1e9
#ifndef PRINTF_MAX_FLOAT
-#define PRINTF_MAX_FLOAT 1e9
+ #define PRINTF_MAX_FLOAT 1e9
#endif
// support for the long long types (%llu or %p)
// default: activated
#ifndef PRINTF_DISABLE_SUPPORT_LONG_LONG
-#define PRINTF_SUPPORT_LONG_LONG
+ #define PRINTF_SUPPORT_LONG_LONG
#endif
// support for the ptrdiff_t type (%t)
// ptrdiff_t is normally defined in <stddef.h> as long or long long type
// default: activated
#ifndef PRINTF_DISABLE_SUPPORT_PTRDIFF_T
-#define PRINTF_SUPPORT_PTRDIFF_T
+ #define PRINTF_SUPPORT_PTRDIFF_T
#endif
///////////////////////////////////////////////////////////////////////////////
@@ -105,748 +106,769 @@
#define FLAGS_PRECISION (1U << 10U)
#define FLAGS_ADAPT_EXP (1U << 11U)
-
// import float.h for DBL_MAX
#if defined(PRINTF_SUPPORT_FLOAT)
-#include <float.h>
+ #include <float.h>
#endif
-
// output function type
-typedef void (*out_fct_type)(char character, void* buffer, size_t idx, size_t maxlen);
-
+typedef void (*out_fct_type)(char character, void * buffer, size_t idx, size_t maxlen);
// wrapper (used as buffer) for output function type
typedef struct {
- void (*fct)(char character, void* arg);
- void* arg;
+ void (*fct)(char character, void * arg);
+ void * arg;
} out_fct_wrap_type;
-
// internal buffer output
-static inline void _out_buffer(char character, void* buffer, size_t idx, size_t maxlen)
+static inline void _out_buffer(char character, void * buffer, size_t idx, size_t maxlen)
{
- if (idx < maxlen) {
- ((char*)buffer)[idx] = character;
- }
+ if(idx < maxlen) {
+ ((char *)buffer)[idx] = character;
+ }
}
-
// internal null output
-static inline void _out_null(char character, void* buffer, size_t idx, size_t maxlen)
+static inline void _out_null(char character, void * buffer, size_t idx, size_t maxlen)
{
- (void)character; (void)buffer; (void)idx; (void)maxlen;
+ (void)character;
+ (void)buffer;
+ (void)idx;
+ (void)maxlen;
}
-
-
// internal secure strlen
// \return The length of the string (excluding the terminating 0) limited by 'maxsize'
-static inline unsigned int _strnlen_s(const char* str, size_t maxsize)
+static inline unsigned int _strnlen_s(const char * str, size_t maxsize)
{
- const char* s;
- for (s = str; *s && maxsize--; ++s);
- return (unsigned int)(s - str);
+ const char * s;
+ for(s = str; *s && maxsize--; ++s);
+ return (unsigned int)(s - str);
}
-
// internal test if char is a digit (0-9)
// \return true if char is a digit
static inline bool _is_digit(char ch)
{
- return (ch >= '0') && (ch <= '9');
+ return (ch >= '0') && (ch <= '9');
}
-
// internal ASCII string to unsigned int conversion
-static unsigned int _atoi(const char** str)
+static unsigned int _atoi(const char ** str)
{
- unsigned int i = 0U;
- while (_is_digit(**str)) {
- i = i * 10U + (unsigned int)(*((*str)++) - '0');
- }
- return i;
+ unsigned int i = 0U;
+ while(_is_digit(**str)) {
+ i = i * 10U + (unsigned int)(*((*str)++) - '0');
+ }
+ return i;
}
-
// output the specified string in reverse, taking care of any zero-padding
-static size_t _out_rev(out_fct_type out, char* buffer, size_t idx, size_t maxlen, const char* buf, size_t len, unsigned int width, unsigned int flags)
+static size_t _out_rev(out_fct_type out, char * buffer, size_t idx, size_t maxlen, const char * buf, size_t len,
+ unsigned int width, unsigned int flags)
{
- const size_t start_idx = idx;
+ const size_t start_idx = idx;
- // pad spaces up to given width
- if (!(flags & FLAGS_LEFT) && !(flags & FLAGS_ZEROPAD)) {
- size_t i;
- for (i = len; i < width; i++) {
- out(' ', buffer, idx++, maxlen);
+ // pad spaces up to given width
+ if(!(flags & FLAGS_LEFT) && !(flags & FLAGS_ZEROPAD)) {
+ size_t i;
+ for(i = len; i < width; i++) {
+ out(' ', buffer, idx++, maxlen);
+ }
}
- }
- // reverse string
- while (len) {
- out(buf[--len], buffer, idx++, maxlen);
- }
+ // reverse string
+ while(len) {
+ out(buf[--len], buffer, idx++, maxlen);
+ }
- // append pad spaces up to given width
- if (flags & FLAGS_LEFT) {
- while (idx - start_idx < width) {
- out(' ', buffer, idx++, maxlen);
+ // append pad spaces up to given width
+ if(flags & FLAGS_LEFT) {
+ while(idx - start_idx < width) {
+ out(' ', buffer, idx++, maxlen);
+ }
}
- }
- return idx;
+ return idx;
}
-
// internal itoa format
-static size_t _ntoa_format(out_fct_type out, char* buffer, size_t idx, size_t maxlen, char* buf, size_t len, bool negative, unsigned int base, unsigned int prec, unsigned int width, unsigned int flags)
+static size_t _ntoa_format(out_fct_type out, char * buffer, size_t idx, size_t maxlen, char * buf, size_t len,
+ bool negative, unsigned int base, unsigned int prec, unsigned int width, unsigned int flags)
{
- // pad leading zeros
- if (!(flags & FLAGS_LEFT)) {
- if (width && (flags & FLAGS_ZEROPAD) && (negative || (flags & (FLAGS_PLUS | FLAGS_SPACE)))) {
- width--;
- }
- while ((len < prec) && (len < PRINTF_NTOA_BUFFER_SIZE)) {
- buf[len++] = '0';
- }
- while ((flags & FLAGS_ZEROPAD) && (len < width) && (len < PRINTF_NTOA_BUFFER_SIZE)) {
- buf[len++] = '0';
+ // pad leading zeros
+ if(!(flags & FLAGS_LEFT)) {
+ if(width && (flags & FLAGS_ZEROPAD) && (negative || (flags & (FLAGS_PLUS | FLAGS_SPACE)))) {
+ width--;
+ }
+ while((len < prec) && (len < PRINTF_NTOA_BUFFER_SIZE)) {
+ buf[len++] = '0';
+ }
+ while((flags & FLAGS_ZEROPAD) && (len < width) && (len < PRINTF_NTOA_BUFFER_SIZE)) {
+ buf[len++] = '0';
+ }
}
- }
- // handle hash
- if (flags & FLAGS_HASH) {
- if (!(flags & FLAGS_PRECISION) && len && ((len == prec) || (len == width))) {
- len--;
- if (len && (base == 16U)) {
- len--;
- }
- }
- if ((base == 16U) && !(flags & FLAGS_UPPERCASE) && (len < PRINTF_NTOA_BUFFER_SIZE)) {
- buf[len++] = 'x';
- }
- else if ((base == 16U) && (flags & FLAGS_UPPERCASE) && (len < PRINTF_NTOA_BUFFER_SIZE)) {
- buf[len++] = 'X';
- }
- else if ((base == 2U) && (len < PRINTF_NTOA_BUFFER_SIZE)) {
- buf[len++] = 'b';
- }
- if (len < PRINTF_NTOA_BUFFER_SIZE) {
- buf[len++] = '0';
+ // handle hash
+ if(flags & FLAGS_HASH) {
+ if(!(flags & FLAGS_PRECISION) && len && ((len == prec) || (len == width))) {
+ len--;
+ if(len && (base == 16U)) {
+ len--;
+ }
+ }
+ if((base == 16U) && !(flags & FLAGS_UPPERCASE) && (len < PRINTF_NTOA_BUFFER_SIZE)) {
+ buf[len++] = 'x';
+ }
+ else if((base == 16U) && (flags & FLAGS_UPPERCASE) && (len < PRINTF_NTOA_BUFFER_SIZE)) {
+ buf[len++] = 'X';
+ }
+ else if((base == 2U) && (len < PRINTF_NTOA_BUFFER_SIZE)) {
+ buf[len++] = 'b';
+ }
+ if(len < PRINTF_NTOA_BUFFER_SIZE) {
+ buf[len++] = '0';
+ }
}
- }
- if (len < PRINTF_NTOA_BUFFER_SIZE) {
- if (negative) {
- buf[len++] = '-';
- }
- else if (flags & FLAGS_PLUS) {
- buf[len++] = '+'; // ignore the space if the '+' exists
- }
- else if (flags & FLAGS_SPACE) {
- buf[len++] = ' ';
+ if(len < PRINTF_NTOA_BUFFER_SIZE) {
+ if(negative) {
+ buf[len++] = '-';
+ }
+ else if(flags & FLAGS_PLUS) {
+ buf[len++] = '+'; // ignore the space if the '+' exists
+ }
+ else if(flags & FLAGS_SPACE) {
+ buf[len++] = ' ';
+ }
}
- }
- return _out_rev(out, buffer, idx, maxlen, buf, len, width, flags);
+ return _out_rev(out, buffer, idx, maxlen, buf, len, width, flags);
}
-
// internal itoa for 'long' type
-static size_t _ntoa_long(out_fct_type out, char* buffer, size_t idx, size_t maxlen, unsigned long value, bool negative, unsigned long base, unsigned int prec, unsigned int width, unsigned int flags)
+static size_t _ntoa_long(out_fct_type out, char * buffer, size_t idx, size_t maxlen, unsigned long value, bool negative,
+ unsigned long base, unsigned int prec, unsigned int width, unsigned int flags)
{
- char buf[PRINTF_NTOA_BUFFER_SIZE];
- size_t len = 0U;
-
- // no hash for 0 values
- if (!value) {
- flags &= ~FLAGS_HASH;
- }
-
- // write if precision != 0 and value is != 0
- if (!(flags & FLAGS_PRECISION) || value) {
- do {
- const char digit = (char)(value % base);
- buf[len++] = digit < 10 ? '0' + digit : (flags & FLAGS_UPPERCASE ? 'A' : 'a') + digit - 10;
- value /= base;
- } while (value && (len < PRINTF_NTOA_BUFFER_SIZE));
- }
-
- return _ntoa_format(out, buffer, idx, maxlen, buf, len, negative, (unsigned int)base, prec, width, flags);
-}
+ char buf[PRINTF_NTOA_BUFFER_SIZE];
+ size_t len = 0U;
+
+ // no hash for 0 values
+ if(!value) {
+ flags &= ~FLAGS_HASH;
+ }
+ // write if precision != 0 and value is != 0
+ if(!(flags & FLAGS_PRECISION) || value) {
+ do {
+ const char digit = (char)(value % base);
+ buf[len++] = digit < 10 ? '0' + digit : (flags & FLAGS_UPPERCASE ? 'A' : 'a') + digit - 10;
+ value /= base;
+ } while(value && (len < PRINTF_NTOA_BUFFER_SIZE));
+ }
+
+ return _ntoa_format(out, buffer, idx, maxlen, buf, len, negative, (unsigned int)base, prec, width, flags);
+}
// internal itoa for 'long long' type
#if defined(PRINTF_SUPPORT_LONG_LONG)
-static size_t _ntoa_long_long(out_fct_type out, char* buffer, size_t idx, size_t maxlen, unsigned long long value, bool negative, unsigned long long base, unsigned int prec, unsigned int width, unsigned int flags)
+static size_t _ntoa_long_long(out_fct_type out, char * buffer, size_t idx, size_t maxlen, unsigned long long value,
+ bool negative, unsigned long long base, unsigned int prec, unsigned int width, unsigned int flags)
{
- char buf[PRINTF_NTOA_BUFFER_SIZE];
- size_t len = 0U;
-
- // no hash for 0 values
- if (!value) {
- flags &= ~FLAGS_HASH;
- }
-
- // write if precision != 0 and value is != 0
- if (!(flags & FLAGS_PRECISION) || value) {
- do {
- const char digit = (char)(value % base);
- buf[len++] = digit < 10 ? '0' + digit : (flags & FLAGS_UPPERCASE ? 'A' : 'a') + digit - 10;
- value /= base;
- } while (value && (len < PRINTF_NTOA_BUFFER_SIZE));
- }
-
- return _ntoa_format(out, buffer, idx, maxlen, buf, len, negative, (unsigned int)base, prec, width, flags);
+ char buf[PRINTF_NTOA_BUFFER_SIZE];
+ size_t len = 0U;
+
+ // no hash for 0 values
+ if(!value) {
+ flags &= ~FLAGS_HASH;
+ }
+
+ // write if precision != 0 and value is != 0
+ if(!(flags & FLAGS_PRECISION) || value) {
+ do {
+ const char digit = (char)(value % base);
+ buf[len++] = digit < 10 ? '0' + digit : (flags & FLAGS_UPPERCASE ? 'A' : 'a') + digit - 10;
+ value /= base;
+ } while(value && (len < PRINTF_NTOA_BUFFER_SIZE));
+ }
+
+ return _ntoa_format(out, buffer, idx, maxlen, buf, len, negative, (unsigned int)base, prec, width, flags);
}
#endif // PRINTF_SUPPORT_LONG_LONG
-
#if defined(PRINTF_SUPPORT_FLOAT)
#if defined(PRINTF_SUPPORT_EXPONENTIAL)
// forward declaration so that _ftoa can switch to exp notation for values > PRINTF_MAX_FLOAT
-static size_t _etoa(out_fct_type out, char* buffer, size_t idx, size_t maxlen, double value, unsigned int prec, unsigned int width, unsigned int flags);
+static size_t _etoa(out_fct_type out, char * buffer, size_t idx, size_t maxlen, double value, unsigned int prec,
+ unsigned int width, unsigned int flags);
#endif
-
// internal ftoa for fixed decimal floating point
-static size_t _ftoa(out_fct_type out, char* buffer, size_t idx, size_t maxlen, double value, unsigned int prec, unsigned int width, unsigned int flags)
+static size_t _ftoa(out_fct_type out, char * buffer, size_t idx, size_t maxlen, double value, unsigned int prec,
+ unsigned int width, unsigned int flags)
{
- char buf[PRINTF_FTOA_BUFFER_SIZE];
- size_t len = 0U;
- double diff = 0.0;
-
- // powers of 10
- static const double pow10[] = { 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000 };
-
- // test for special values
- if (value != value)
- return _out_rev(out, buffer, idx, maxlen, "nan", 3, width, flags);
- if (value < -DBL_MAX)
- return _out_rev(out, buffer, idx, maxlen, "fni-", 4, width, flags);
- if (value > DBL_MAX)
- return _out_rev(out, buffer, idx, maxlen, (flags & FLAGS_PLUS) ? "fni+" : "fni", (flags & FLAGS_PLUS) ? 4U : 3U, width, flags);
-
- // test for very large values
- // standard printf behavior is to print EVERY whole number digit -- which could be 100s of characters overflowing your buffers == bad
- if ((value > PRINTF_MAX_FLOAT) || (value < -PRINTF_MAX_FLOAT)) {
+ char buf[PRINTF_FTOA_BUFFER_SIZE];
+ size_t len = 0U;
+ double diff = 0.0;
+
+ // powers of 10
+ static const double pow10[] = { 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000 };
+
+ // test for special values
+ if(value != value)
+ return _out_rev(out, buffer, idx, maxlen, "nan", 3, width, flags);
+ if(value < -DBL_MAX)
+ return _out_rev(out, buffer, idx, maxlen, "fni-", 4, width, flags);
+ if(value > DBL_MAX)
+ return _out_rev(out, buffer, idx, maxlen, (flags & FLAGS_PLUS) ? "fni+" : "fni", (flags & FLAGS_PLUS) ? 4U : 3U, width,
+ flags);
+
+ // test for very large values
+ // standard printf behavior is to print EVERY whole number digit -- which could be 100s of characters overflowing your buffers == bad
+ if((value > PRINTF_MAX_FLOAT) || (value < -PRINTF_MAX_FLOAT)) {
#if defined(PRINTF_SUPPORT_EXPONENTIAL)
- return _etoa(out, buffer, idx, maxlen, value, prec, width, flags);
+ return _etoa(out, buffer, idx, maxlen, value, prec, width, flags);
#else
- return 0U;
+ return 0U;
#endif
- }
-
- // test for negative
- bool negative = false;
- if (value < 0) {
- negative = true;
- value = 0 - value;
- }
-
- // set default precision, if not set explicitly
- if (!(flags & FLAGS_PRECISION)) {
- prec = PRINTF_DEFAULT_FLOAT_PRECISION;
- }
- // limit precision to 9, cause a prec >= 10 can lead to overflow errors
- while ((len < PRINTF_FTOA_BUFFER_SIZE) && (prec > 9U)) {
- buf[len++] = '0';
- prec--;
- }
-
- int whole = (int)value;
- double tmp = (value - whole) * pow10[prec];
- unsigned long frac = (unsigned long)tmp;
- diff = tmp - frac;
-
- if (diff > 0.5) {
- ++frac;
- // handle rollover, e.g. case 0.99 with prec 1 is 1.0
- if (frac >= pow10[prec]) {
- frac = 0;
- ++whole;
- }
- }
- else if (diff < 0.5) {
- }
- else if ((frac == 0U) || (frac & 1U)) {
- // if halfway, round up if odd OR if last digit is 0
- ++frac;
- }
-
- if (prec == 0U) {
- diff = value - (double)whole;
- if ((!(diff < 0.5) || (diff > 0.5)) && (whole & 1)) {
- // exactly 0.5 and ODD, then round up
- // 1.5 -> 2, but 2.5 -> 2
- ++whole;
- }
- }
- else {
- unsigned int count = prec;
- // now do fractional part, as an unsigned number
- while (len < PRINTF_FTOA_BUFFER_SIZE) {
- --count;
- buf[len++] = (char)(48U + (frac % 10U));
- if (!(frac /= 10U)) {
- break;
- }
- }
- // add extra 0s
- while ((len < PRINTF_FTOA_BUFFER_SIZE) && (count-- > 0U)) {
- buf[len++] = '0';
- }
- if (len < PRINTF_FTOA_BUFFER_SIZE) {
- // add decimal
- buf[len++] = '.';
- }
- }
-
- // do whole part, number is reversed
- while (len < PRINTF_FTOA_BUFFER_SIZE) {
- buf[len++] = (char)(48 + (whole % 10));
- if (!(whole /= 10)) {
- break;
- }
- }
-
- // pad leading zeros
- if (!(flags & FLAGS_LEFT) && (flags & FLAGS_ZEROPAD)) {
- if (width && (negative || (flags & (FLAGS_PLUS | FLAGS_SPACE)))) {
- width--;
- }
- while ((len < width) && (len < PRINTF_FTOA_BUFFER_SIZE)) {
- buf[len++] = '0';
- }
- }
-
- if (len < PRINTF_FTOA_BUFFER_SIZE) {
- if (negative) {
- buf[len++] = '-';
- }
- else if (flags & FLAGS_PLUS) {
- buf[len++] = '+'; // ignore the space if the '+' exists
- }
- else if (flags & FLAGS_SPACE) {
- buf[len++] = ' ';
- }
- }
-
- return _out_rev(out, buffer, idx, maxlen, buf, len, width, flags);
-}
+ }
+
+ // test for negative
+ bool negative = false;
+ if(value < 0) {
+ negative = true;
+ value = 0 - value;
+ }
+
+ // set default precision, if not set explicitly
+ if(!(flags & FLAGS_PRECISION)) {
+ prec = PRINTF_DEFAULT_FLOAT_PRECISION;
+ }
+ // limit precision to 9, cause a prec >= 10 can lead to overflow errors
+ while((len < PRINTF_FTOA_BUFFER_SIZE) && (prec > 9U)) {
+ buf[len++] = '0';
+ prec--;
+ }
+
+ int whole = (int)value;
+ double tmp = (value - whole) * pow10[prec];
+ unsigned long frac = (unsigned long)tmp;
+ diff = tmp - frac;
+
+ if(diff > 0.5) {
+ ++frac;
+ // handle rollover, e.g. case 0.99 with prec 1 is 1.0
+ if(frac >= pow10[prec]) {
+ frac = 0;
+ ++whole;
+ }
+ }
+ else if(diff < 0.5) {
+ }
+ else if((frac == 0U) || (frac & 1U)) {
+ // if halfway, round up if odd OR if last digit is 0
+ ++frac;
+ }
+
+ if(prec == 0U) {
+ diff = value - (double)whole;
+ if((!(diff < 0.5) || (diff > 0.5)) && (whole & 1)) {
+ // exactly 0.5 and ODD, then round up
+ // 1.5 -> 2, but 2.5 -> 2
+ ++whole;
+ }
+ }
+ else {
+ unsigned int count = prec;
+ // now do fractional part, as an unsigned number
+ while(len < PRINTF_FTOA_BUFFER_SIZE) {
+ --count;
+ buf[len++] = (char)(48U + (frac % 10U));
+ if(!(frac /= 10U)) {
+ break;
+ }
+ }
+ // add extra 0s
+ while((len < PRINTF_FTOA_BUFFER_SIZE) && (count-- > 0U)) {
+ buf[len++] = '0';
+ }
+ if(len < PRINTF_FTOA_BUFFER_SIZE) {
+ // add decimal
+ buf[len++] = '.';
+ }
+ }
+ // do whole part, number is reversed
+ while(len < PRINTF_FTOA_BUFFER_SIZE) {
+ buf[len++] = (char)(48 + (whole % 10));
+ if(!(whole /= 10)) {
+ break;
+ }
+ }
+
+ // pad leading zeros
+ if(!(flags & FLAGS_LEFT) && (flags & FLAGS_ZEROPAD)) {
+ if(width && (negative || (flags & (FLAGS_PLUS | FLAGS_SPACE)))) {
+ width--;
+ }
+ while((len < width) && (len < PRINTF_FTOA_BUFFER_SIZE)) {
+ buf[len++] = '0';
+ }
+ }
+
+ if(len < PRINTF_FTOA_BUFFER_SIZE) {
+ if(negative) {
+ buf[len++] = '-';
+ }
+ else if(flags & FLAGS_PLUS) {
+ buf[len++] = '+'; // ignore the space if the '+' exists
+ }
+ else if(flags & FLAGS_SPACE) {
+ buf[len++] = ' ';
+ }
+ }
+
+ return _out_rev(out, buffer, idx, maxlen, buf, len, width, flags);
+}
#if defined(PRINTF_SUPPORT_EXPONENTIAL)
// internal ftoa variant for exponential floating-point type, contributed by Martijn Jasperse <m.jasperse@gmail.com>
-static size_t _etoa(out_fct_type out, char* buffer, size_t idx, size_t maxlen, double value, unsigned int prec, unsigned int width, unsigned int flags)
+static size_t _etoa(out_fct_type out, char * buffer, size_t idx, size_t maxlen, double value, unsigned int prec,
+ unsigned int width, unsigned int flags)
{
- // check for NaN and special values
- if ((value != value) || (value > DBL_MAX) || (value < -DBL_MAX)) {
- return _ftoa(out, buffer, idx, maxlen, value, prec, width, flags);
- }
-
- // determine the sign
- const bool negative = value < 0;
- if (negative) {
- value = -value;
- }
-
- // default precision
- if (!(flags & FLAGS_PRECISION)) {
- prec = PRINTF_DEFAULT_FLOAT_PRECISION;
- }
-
- // determine the decimal exponent
- // based on the algorithm by David Gay (https://www.ampl.com/netlib/fp/dtoa.c)
- union {
- uint64_t U;
- double F;
- } conv;
-
- conv.F = value;
- int exp2 = (int)((conv.U >> 52U) & 0x07FFU) - 1023; // effectively log2
- conv.U = (conv.U & ((1ULL << 52U) - 1U)) | (1023ULL << 52U); // drop the exponent so conv.F is now in [1,2)
- // now approximate log10 from the log2 integer part and an expansion of ln around 1.5
- int expval = (int)(0.1760912590558 + exp2 * 0.301029995663981 + (conv.F - 1.5) * 0.289529654602168);
- // now we want to compute 10^expval but we want to be sure it won't overflow
- exp2 = (int)(expval * 3.321928094887362 + 0.5);
- const double z = expval * 2.302585092994046 - exp2 * 0.6931471805599453;
- const double z2 = z * z;
- conv.U = (uint64_t)(exp2 + 1023) << 52U;
- // compute exp(z) using continued fractions, see https://en.wikipedia.org/wiki/Exponential_function#Continued_fractions_for_ex
- conv.F *= 1 + 2 * z / (2 - z + (z2 / (6 + (z2 / (10 + z2 / 14)))));
- // correct for rounding errors
- if (value < conv.F) {
- expval--;
- conv.F /= 10;
- }
-
- // the exponent format is "%+03d" and largest value is "307", so set aside 4-5 characters
- unsigned int minwidth = ((expval < 100) && (expval > -100)) ? 4U : 5U;
-
- // in "%g" mode, "prec" is the number of *significant figures* not decimals
- if (flags & FLAGS_ADAPT_EXP) {
- // do we want to fall-back to "%f" mode?
- if ((value >= 1e-4) && (value < 1e6)) {
- if ((int)prec > expval) {
- prec = (unsigned)((int)prec - expval - 1);
- }
- else {
- prec = 0;
- }
- flags |= FLAGS_PRECISION; // make sure _ftoa respects precision
- // no characters in exponent
- minwidth = 0U;
- expval = 0;
+ // check for NaN and special values
+ if((value != value) || (value > DBL_MAX) || (value < -DBL_MAX)) {
+ return _ftoa(out, buffer, idx, maxlen, value, prec, width, flags);
+ }
+
+ // determine the sign
+ const bool negative = value < 0;
+ if(negative) {
+ value = -value;
+ }
+
+ // default precision
+ if(!(flags & FLAGS_PRECISION)) {
+ prec = PRINTF_DEFAULT_FLOAT_PRECISION;
+ }
+
+ // determine the decimal exponent
+ // based on the algorithm by David Gay (https://www.ampl.com/netlib/fp/dtoa.c)
+ union {
+ uint64_t U;
+ double F;
+ } conv;
+
+ conv.F = value;
+ int exp2 = (int)((conv.U >> 52U) & 0x07FFU) - 1023; // effectively log2
+ conv.U = (conv.U & ((1ULL << 52U) - 1U)) | (1023ULL << 52U); // drop the exponent so conv.F is now in [1,2)
+ // now approximate log10 from the log2 integer part and an expansion of ln around 1.5
+ int expval = (int)(0.1760912590558 + exp2 * 0.301029995663981 + (conv.F - 1.5) * 0.289529654602168);
+ // now we want to compute 10^expval but we want to be sure it won't overflow
+ exp2 = (int)(expval * 3.321928094887362 + 0.5);
+ const double z = expval * 2.302585092994046 - exp2 * 0.6931471805599453;
+ const double z2 = z * z;
+ conv.U = (uint64_t)(exp2 + 1023) << 52U;
+ // compute exp(z) using continued fractions, see https://en.wikipedia.org/wiki/Exponential_function#Continued_fractions_for_ex
+ conv.F *= 1 + 2 * z / (2 - z + (z2 / (6 + (z2 / (10 + z2 / 14)))));
+ // correct for rounding errors
+ if(value < conv.F) {
+ expval--;
+ conv.F /= 10;
+ }
+
+ // the exponent format is "%+03d" and largest value is "307", so set aside 4-5 characters
+ unsigned int minwidth = ((expval < 100) && (expval > -100)) ? 4U : 5U;
+
+ // in "%g" mode, "prec" is the number of *significant figures* not decimals
+ if(flags & FLAGS_ADAPT_EXP) {
+ // do we want to fall-back to "%f" mode?
+ if((value >= 1e-4) && (value < 1e6)) {
+ if((int)prec > expval) {
+ prec = (unsigned)((int)prec - expval - 1);
+ }
+ else {
+ prec = 0;
+ }
+ flags |= FLAGS_PRECISION; // make sure _ftoa respects precision
+ // no characters in exponent
+ minwidth = 0U;
+ expval = 0;
+ }
+ else {
+ // we use one sigfig for the whole part
+ if((prec > 0) && (flags & FLAGS_PRECISION)) {
+ --prec;
+ }
+ }
+ }
+
+ // will everything fit?
+ unsigned int fwidth = width;
+ if(width > minwidth) {
+ // we didn't fall-back so subtract the characters required for the exponent
+ fwidth -= minwidth;
}
else {
- // we use one sigfig for the whole part
- if ((prec > 0) && (flags & FLAGS_PRECISION)) {
- --prec;
- }
- }
- }
-
- // will everything fit?
- unsigned int fwidth = width;
- if (width > minwidth) {
- // we didn't fall-back so subtract the characters required for the exponent
- fwidth -= minwidth;
- } else {
- // not enough characters, so go back to default sizing
- fwidth = 0U;
- }
- if ((flags & FLAGS_LEFT) && minwidth) {
- // if we're padding on the right, DON'T pad the floating part
- fwidth = 0U;
- }
-
- // rescale the float value
- if (expval) {
- value /= conv.F;
- }
-
- // output the floating part
- const size_t start_idx = idx;
- idx = _ftoa(out, buffer, idx, maxlen, negative ? -value : value, prec, fwidth, flags & ~FLAGS_ADAPT_EXP);
-
- // output the exponent part
- if (minwidth) {
- // output the exponential symbol
- out((flags & FLAGS_UPPERCASE) ? 'E' : 'e', buffer, idx++, maxlen);
- // output the exponent value
- idx = _ntoa_long(out, buffer, idx, maxlen, (expval < 0) ? -expval : expval, expval < 0, 10, 0, minwidth-1, FLAGS_ZEROPAD | FLAGS_PLUS);
- // might need to right-pad spaces
- if (flags & FLAGS_LEFT) {
- while (idx - start_idx < width) out(' ', buffer, idx++, maxlen);
- }
- }
- return idx;
+ // not enough characters, so go back to default sizing
+ fwidth = 0U;
+ }
+ if((flags & FLAGS_LEFT) && minwidth) {
+ // if we're padding on the right, DON'T pad the floating part
+ fwidth = 0U;
+ }
+
+ // rescale the float value
+ if(expval) {
+ value /= conv.F;
+ }
+
+ // output the floating part
+ const size_t start_idx = idx;
+ idx = _ftoa(out, buffer, idx, maxlen, negative ? -value : value, prec, fwidth, flags & ~FLAGS_ADAPT_EXP);
+
+ // output the exponent part
+ if(minwidth) {
+ // output the exponential symbol
+ out((flags & FLAGS_UPPERCASE) ? 'E' : 'e', buffer, idx++, maxlen);
+ // output the exponent value
+ idx = _ntoa_long(out, buffer, idx, maxlen, (expval < 0) ? -expval : expval, expval < 0, 10, 0, minwidth - 1,
+ FLAGS_ZEROPAD | FLAGS_PLUS);
+ // might need to right-pad spaces
+ if(flags & FLAGS_LEFT) {
+ while(idx - start_idx < width) out(' ', buffer, idx++, maxlen);
+ }
+ }
+ return idx;
}
#endif // PRINTF_SUPPORT_EXPONENTIAL
#endif // PRINTF_SUPPORT_FLOAT
-
// internal vsnprintf
-static int _vsnprintf(out_fct_type out, char* buffer, const size_t maxlen, const char* format, va_list va)
+static int _vsnprintf(out_fct_type out, char * buffer, const size_t maxlen, const char * format, va_list va)
{
- unsigned int flags, width, precision, n;
- size_t idx = 0U;
-
- if (!buffer) {
- // use null output function
- out = _out_null;
- }
-
- while (*format)
- {
- // format specifier? %[flags][width][.precision][length]
- if (*format != '%') {
- // no
- out(*format, buffer, idx++, maxlen);
- format++;
- continue;
+ unsigned int flags, width, precision, n;
+ size_t idx = 0U;
+
+ if(!buffer) {
+ // use null output function
+ out = _out_null;
}
- else {
- // yes, evaluate it
- format++;
- }
-
- // evaluate flags
- flags = 0U;
- do {
- switch (*format) {
- case '0': flags |= FLAGS_ZEROPAD; format++; n = 1U; break;
- case '-': flags |= FLAGS_LEFT; format++; n = 1U; break;
- case '+': flags |= FLAGS_PLUS; format++; n = 1U; break;
- case ' ': flags |= FLAGS_SPACE; format++; n = 1U; break;
- case '#': flags |= FLAGS_HASH; format++; n = 1U; break;
- default : n = 0U; break;
- }
- } while (n);
-
- // evaluate width field
- width = 0U;
- if (_is_digit(*format)) {
- width = _atoi(&format);
- }
- else if (*format == '*') {
- const int w = va_arg(va, int);
- if (w < 0) {
- flags |= FLAGS_LEFT; // reverse padding
- width = (unsigned int)-w;
- }
- else {
- width = (unsigned int)w;
- }
- format++;
- }
-
- // evaluate precision field
- precision = 0U;
- if (*format == '.') {
- flags |= FLAGS_PRECISION;
- format++;
- if (_is_digit(*format)) {
- precision = _atoi(&format);
- }
- else if (*format == '*') {
- const int prec = (int)va_arg(va, int);
- precision = prec > 0 ? (unsigned int)prec : 0U;
- format++;
- }
- }
-
- // evaluate length field
- switch (*format) {
- case 'l' :
- flags |= FLAGS_LONG;
- format++;
- if (*format == 'l') {
- flags |= FLAGS_LONG_LONG;
- format++;
- }
- break;
- case 'h' :
- flags |= FLAGS_SHORT;
- format++;
- if (*format == 'h') {
- flags |= FLAGS_CHAR;
- format++;
- }
- break;
-#if defined(PRINTF_SUPPORT_PTRDIFF_T)
- case 't' :
- flags |= (sizeof(ptrdiff_t) == sizeof(long) ? FLAGS_LONG : FLAGS_LONG_LONG);
- format++;
- break;
-#endif
- case 'j' :
- flags |= (sizeof(intmax_t) == sizeof(long) ? FLAGS_LONG : FLAGS_LONG_LONG);
- format++;
- break;
- case 'z' :
- flags |= (sizeof(size_t) == sizeof(long) ? FLAGS_LONG : FLAGS_LONG_LONG);
- format++;
- break;
- default :
- break;
- }
-
- // evaluate specifier
- switch (*format) {
- case 'd' :
- case 'i' :
- case 'u' :
- case 'x' :
- case 'X' :
- case 'o' :
- case 'b' : {
- // set the base
- unsigned int base;
- if (*format == 'x' || *format == 'X') {
- base = 16U;
- }
- else if (*format == 'o') {
- base = 8U;
- }
- else if (*format == 'b') {
- base = 2U;
+
+ while(*format) {
+ // format specifier? %[flags][width][.precision][length]
+ if(*format != '%') {
+ // no
+ out(*format, buffer, idx++, maxlen);
+ format++;
+ continue;
}
else {
- base = 10U;
- flags &= ~FLAGS_HASH; // no hash for dec format
+ // yes, evaluate it
+ format++;
+ }
+
+ // evaluate flags
+ flags = 0U;
+ do {
+ switch(*format) {
+ case '0':
+ flags |= FLAGS_ZEROPAD;
+ format++;
+ n = 1U;
+ break;
+ case '-':
+ flags |= FLAGS_LEFT;
+ format++;
+ n = 1U;
+ break;
+ case '+':
+ flags |= FLAGS_PLUS;
+ format++;
+ n = 1U;
+ break;
+ case ' ':
+ flags |= FLAGS_SPACE;
+ format++;
+ n = 1U;
+ break;
+ case '#':
+ flags |= FLAGS_HASH;
+ format++;
+ n = 1U;
+ break;
+ default :
+ n = 0U;
+ break;
+ }
+ } while(n);
+
+ // evaluate width field
+ width = 0U;
+ if(_is_digit(*format)) {
+ width = _atoi(&format);
}
- // uppercase
- if (*format == 'X') {
- flags |= FLAGS_UPPERCASE;
+ else if(*format == '*') {
+ const int w = va_arg(va, int);
+ if(w < 0) {
+ flags |= FLAGS_LEFT; // reverse padding
+ width = (unsigned int) - w;
+ }
+ else {
+ width = (unsigned int)w;
+ }
+ format++;
}
- // no plus or space flag for u, x, X, o, b
- if ((*format != 'i') && (*format != 'd')) {
- flags &= ~(FLAGS_PLUS | FLAGS_SPACE);
+ // evaluate precision field
+ precision = 0U;
+ if(*format == '.') {
+ flags |= FLAGS_PRECISION;
+ format++;
+ if(_is_digit(*format)) {
+ precision = _atoi(&format);
+ }
+ else if(*format == '*') {
+ const int prec = (int)va_arg(va, int);
+ precision = prec > 0 ? (unsigned int)prec : 0U;
+ format++;
+ }
}
- // ignore '0' flag when precision is given
- if (flags & FLAGS_PRECISION) {
- flags &= ~FLAGS_ZEROPAD;
+ // evaluate length field
+ switch(*format) {
+ case 'l' :
+ flags |= FLAGS_LONG;
+ format++;
+ if(*format == 'l') {
+ flags |= FLAGS_LONG_LONG;
+ format++;
+ }
+ break;
+ case 'h' :
+ flags |= FLAGS_SHORT;
+ format++;
+ if(*format == 'h') {
+ flags |= FLAGS_CHAR;
+ format++;
+ }
+ break;
+#if defined(PRINTF_SUPPORT_PTRDIFF_T)
+ case 't' :
+ flags |= (sizeof(ptrdiff_t) == sizeof(long) ? FLAGS_LONG : FLAGS_LONG_LONG);
+ format++;
+ break;
+#endif
+ case 'j' :
+ flags |= (sizeof(intmax_t) == sizeof(long) ? FLAGS_LONG : FLAGS_LONG_LONG);
+ format++;
+ break;
+ case 'z' :
+ flags |= (sizeof(size_t) == sizeof(long) ? FLAGS_LONG : FLAGS_LONG_LONG);
+ format++;
+ break;
+ default :
+ break;
}
- // convert the integer
- if ((*format == 'i') || (*format == 'd')) {
- // signed
- if (flags & FLAGS_LONG_LONG) {
+ // evaluate specifier
+ switch(*format) {
+ case 'd' :
+ case 'i' :
+ case 'u' :
+ case 'x' :
+ case 'X' :
+ case 'o' :
+ case 'b' : {
+ // set the base
+ unsigned int base;
+ if(*format == 'x' || *format == 'X') {
+ base = 16U;
+ }
+ else if(*format == 'o') {
+ base = 8U;
+ }
+ else if(*format == 'b') {
+ base = 2U;
+ }
+ else {
+ base = 10U;
+ flags &= ~FLAGS_HASH; // no hash for dec format
+ }
+ // uppercase
+ if(*format == 'X') {
+ flags |= FLAGS_UPPERCASE;
+ }
+
+ // no plus or space flag for u, x, X, o, b
+ if((*format != 'i') && (*format != 'd')) {
+ flags &= ~(FLAGS_PLUS | FLAGS_SPACE);
+ }
+
+ // ignore '0' flag when precision is given
+ if(flags & FLAGS_PRECISION) {
+ flags &= ~FLAGS_ZEROPAD;
+ }
+
+ // convert the integer
+ if((*format == 'i') || (*format == 'd')) {
+ // signed
+ if(flags & FLAGS_LONG_LONG) {
#if defined(PRINTF_SUPPORT_LONG_LONG)
- const long long value = va_arg(va, long long);
- idx = _ntoa_long_long(out, buffer, idx, maxlen, (unsigned long long)(value > 0 ? value : 0 - value), value < 0, base, precision, width, flags);
+ const long long value = va_arg(va, long long);
+ idx = _ntoa_long_long(out, buffer, idx, maxlen, (unsigned long long)(value > 0 ? value : 0 - value), value < 0, base,
+ precision, width, flags);
#endif
- }
- else if (flags & FLAGS_LONG) {
- const long value = va_arg(va, long);
- idx = _ntoa_long(out, buffer, idx, maxlen, (unsigned long)(value > 0 ? value : 0 - value), value < 0, base, precision, width, flags);
- }
- else {
- const int value = (flags & FLAGS_CHAR) ? (char)va_arg(va, int) : (flags & FLAGS_SHORT) ? (short int)va_arg(va, int) : va_arg(va, int);
- idx = _ntoa_long(out, buffer, idx, maxlen, (unsigned int)(value > 0 ? value : 0 - value), value < 0, base, precision, width, flags);
- }
- }
- else {
- // unsigned
- if (flags & FLAGS_LONG_LONG) {
+ }
+ else if(flags & FLAGS_LONG) {
+ const long value = va_arg(va, long);
+ idx = _ntoa_long(out, buffer, idx, maxlen, (unsigned long)(value > 0 ? value : 0 - value), value < 0, base, precision,
+ width, flags);
+ }
+ else {
+ const int value = (flags & FLAGS_CHAR) ? (char)va_arg(va, int) : (flags & FLAGS_SHORT) ? (short int)va_arg(va,
+ int) : va_arg(va, int);
+ idx = _ntoa_long(out, buffer, idx, maxlen, (unsigned int)(value > 0 ? value : 0 - value), value < 0, base, precision,
+ width, flags);
+ }
+ }
+ else {
+ // unsigned
+ if(flags & FLAGS_LONG_LONG) {
#if defined(PRINTF_SUPPORT_LONG_LONG)
- idx = _ntoa_long_long(out, buffer, idx, maxlen, va_arg(va, unsigned long long), false, base, precision, width, flags);
+ idx = _ntoa_long_long(out, buffer, idx, maxlen, va_arg(va, unsigned long long), false, base, precision, width, flags);
#endif
- }
- else if (flags & FLAGS_LONG) {
- idx = _ntoa_long(out, buffer, idx, maxlen, va_arg(va, unsigned long), false, base, precision, width, flags);
- }
- else {
- const unsigned int value = (flags & FLAGS_CHAR) ? (unsigned char)va_arg(va, unsigned int) : (flags & FLAGS_SHORT) ? (unsigned short int)va_arg(va, unsigned int) : va_arg(va, unsigned int);
- idx = _ntoa_long(out, buffer, idx, maxlen, value, false, base, precision, width, flags);
- }
- }
- format++;
- break;
- }
+ }
+ else if(flags & FLAGS_LONG) {
+ idx = _ntoa_long(out, buffer, idx, maxlen, va_arg(va, unsigned long), false, base, precision, width, flags);
+ }
+ else {
+ const unsigned int value = (flags & FLAGS_CHAR) ? (unsigned char)va_arg(va,
+ unsigned int) : (flags & FLAGS_SHORT) ? (unsigned short int)va_arg(va, unsigned int) : va_arg(va, unsigned int);
+ idx = _ntoa_long(out, buffer, idx, maxlen, value, false, base, precision, width, flags);
+ }
+ }
+ format++;
+ break;
+ }
#if defined(PRINTF_SUPPORT_FLOAT)
- case 'f' :
- case 'F' :
- if (*format == 'F') flags |= FLAGS_UPPERCASE;
- idx = _ftoa(out, buffer, idx, maxlen, va_arg(va, double), precision, width, flags);
- format++;
- break;
+ case 'f' :
+ case 'F' :
+ if(*format == 'F') flags |= FLAGS_UPPERCASE;
+ idx = _ftoa(out, buffer, idx, maxlen, va_arg(va, double), precision, width, flags);
+ format++;
+ break;
#if defined(PRINTF_SUPPORT_EXPONENTIAL)
- case 'e':
- case 'E':
- case 'g':
- case 'G':
- if ((*format == 'g')||(*format == 'G')) flags |= FLAGS_ADAPT_EXP;
- if ((*format == 'E')||(*format == 'G')) flags |= FLAGS_UPPERCASE;
- idx = _etoa(out, buffer, idx, maxlen, va_arg(va, double), precision, width, flags);
- format++;
- break;
+ case 'e':
+ case 'E':
+ case 'g':
+ case 'G':
+ if((*format == 'g') || (*format == 'G')) flags |= FLAGS_ADAPT_EXP;
+ if((*format == 'E') || (*format == 'G')) flags |= FLAGS_UPPERCASE;
+ idx = _etoa(out, buffer, idx, maxlen, va_arg(va, double), precision, width, flags);
+ format++;
+ break;
#endif // PRINTF_SUPPORT_EXPONENTIAL
#endif // PRINTF_SUPPORT_FLOAT
- case 'c' : {
- unsigned int l = 1U;
- // pre padding
- if (!(flags & FLAGS_LEFT)) {
- while (l++ < width) {
- out(' ', buffer, idx++, maxlen);
- }
- }
- // char output
- out((char)va_arg(va, int), buffer, idx++, maxlen);
- // post padding
- if (flags & FLAGS_LEFT) {
- while (l++ < width) {
- out(' ', buffer, idx++, maxlen);
- }
- }
- format++;
- break;
- }
-
- case 's' : {
- const char* p = va_arg(va, char*);
- unsigned int l = _strnlen_s(p, precision ? precision : (size_t)-1);
- // pre padding
- if (flags & FLAGS_PRECISION) {
- l = (l < precision ? l : precision);
- }
- if (!(flags & FLAGS_LEFT)) {
- while (l++ < width) {
- out(' ', buffer, idx++, maxlen);
- }
- }
- // string output
- while ((*p != 0) && (!(flags & FLAGS_PRECISION) || precision--)) {
- out(*(p++), buffer, idx++, maxlen);
- }
- // post padding
- if (flags & FLAGS_LEFT) {
- while (l++ < width) {
- out(' ', buffer, idx++, maxlen);
- }
- }
- format++;
- break;
- }
-
- case 'p' : {
- width = sizeof(void*) * 2U;
- flags |= FLAGS_ZEROPAD | FLAGS_UPPERCASE;
+ case 'c' : {
+ unsigned int l = 1U;
+ // pre padding
+ if(!(flags & FLAGS_LEFT)) {
+ while(l++ < width) {
+ out(' ', buffer, idx++, maxlen);
+ }
+ }
+ // char output
+ out((char)va_arg(va, int), buffer, idx++, maxlen);
+ // post padding
+ if(flags & FLAGS_LEFT) {
+ while(l++ < width) {
+ out(' ', buffer, idx++, maxlen);
+ }
+ }
+ format++;
+ break;
+ }
+
+ case 's' : {
+ const char * p = va_arg(va, char *);
+ unsigned int l = _strnlen_s(p, precision ? precision : (size_t) -1);
+ // pre padding
+ if(flags & FLAGS_PRECISION) {
+ l = (l < precision ? l : precision);
+ }
+ if(!(flags & FLAGS_LEFT)) {
+ while(l++ < width) {
+ out(' ', buffer, idx++, maxlen);
+ }
+ }
+ // string output
+ while((*p != 0) && (!(flags & FLAGS_PRECISION) || precision--)) {
+ out(*(p++), buffer, idx++, maxlen);
+ }
+ // post padding
+ if(flags & FLAGS_LEFT) {
+ while(l++ < width) {
+ out(' ', buffer, idx++, maxlen);
+ }
+ }
+ format++;
+ break;
+ }
+
+ case 'p' : {
+ width = sizeof(void *) * 2U;
+ flags |= FLAGS_ZEROPAD | FLAGS_UPPERCASE;
#if defined(PRINTF_SUPPORT_LONG_LONG)
- const bool is_ll = sizeof(uintptr_t) == sizeof(long long);
- if (is_ll) {
- idx = _ntoa_long_long(out, buffer, idx, maxlen, (uintptr_t)va_arg(va, void*), false, 16U, precision, width, flags);
- }
- else {
+ const bool is_ll = sizeof(uintptr_t) == sizeof(long long);
+ if(is_ll) {
+ idx = _ntoa_long_long(out, buffer, idx, maxlen, (uintptr_t)va_arg(va, void *), false, 16U, precision, width, flags);
+ }
+ else {
#endif
- idx = _ntoa_long(out, buffer, idx, maxlen, (unsigned long)((uintptr_t)va_arg(va, void*)), false, 16U, precision, width, flags);
+ idx = _ntoa_long(out, buffer, idx, maxlen, (unsigned long)((uintptr_t)va_arg(va, void *)), false, 16U, precision, width,
+ flags);
#if defined(PRINTF_SUPPORT_LONG_LONG)
- }
+ }
#endif
- format++;
- break;
- }
-
- case '%' :
- out('%', buffer, idx++, maxlen);
- format++;
- break;
-
- default :
- out(*format, buffer, idx++, maxlen);
- format++;
- break;
+ format++;
+ break;
+ }
+
+ case '%' :
+ out('%', buffer, idx++, maxlen);
+ format++;
+ break;
+
+ default :
+ out(*format, buffer, idx++, maxlen);
+ format++;
+ break;
+ }
}
- }
- // termination
- out((char)0, buffer, idx < maxlen ? idx : maxlen - 1U, maxlen);
+ // termination
+ out((char)0, buffer, idx < maxlen ? idx : maxlen - 1U, maxlen);
- // return written chars without terminating \0
- return (int)idx;
+ // return written chars without terminating \0
+ return (int)idx;
}
-
///////////////////////////////////////////////////////////////////////////////
-int lv_snprintf(char* buffer, size_t count, const char* format, ...)
+int lv_snprintf(char * buffer, size_t count, const char * format, ...)
{
- va_list va;
- va_start(va, format);
- const int ret = _vsnprintf(_out_buffer, buffer, count, format, va);
- va_end(va);
- return ret;
+ va_list va;
+ va_start(va, format);
+ const int ret = _vsnprintf(_out_buffer, buffer, count, format, va);
+ va_end(va);
+ return ret;
}
-int lv_vsnprintf(char* buffer, size_t count, const char* format, va_list va)
+int lv_vsnprintf(char * buffer, size_t count, const char * format, va_list va)
{
- return _vsnprintf(_out_buffer, buffer, count, format, va);
+ return _vsnprintf(_out_buffer, buffer, count, format, va);
}
#endif /*LV_SPRINTF_CUSTOM*/
-
diff --git a/src/libs/lvgl/src/lv_misc/lv_printf.h b/src/libs/lvgl/src/lv_misc/lv_printf.h
index b3b8598d..a89617cd 100644
--- a/src/libs/lvgl/src/lv_misc/lv_printf.h
+++ b/src/libs/lvgl/src/lv_misc/lv_printf.h
@@ -10,10 +10,10 @@
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
-//
+//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
-//
+//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
@@ -32,17 +32,11 @@
#ifndef _LV_PRINTF_H_
#define _LV_PRINTF_H_
-
#ifdef __cplusplus
extern "C" {
#endif
-
-#ifdef LV_CONF_INCLUDE_SIMPLE
-#include "lv_conf.h"
-#else
-#include "../../../lv_conf.h"
-#endif
+#include "../lv_conf_internal.h"
#if LV_SPRINTF_CUSTOM == 0
@@ -59,17 +53,15 @@ extern "C" {
* null character. A value equal or larger than count indicates truncation. Only when the returned value
* is non-negative and less than count, the string has been completely written.
*/
-int lv_snprintf(char* buffer, size_t count, const char* format, ...);
-int lv_vsnprintf(char* buffer, size_t count, const char* format, va_list va);
+int lv_snprintf(char * buffer, size_t count, const char * format, ...);
+int lv_vsnprintf(char * buffer, size_t count, const char * format, va_list va);
#else
#include LV_SPRINTF_INCLUDE
#endif
-
#ifdef __cplusplus
}
#endif
-
-#endif // _PRINTF_H_
+#endif // _LV_PRINTF_H_
diff --git a/src/libs/lvgl/src/lv_misc/lv_task.c b/src/libs/lvgl/src/lv_misc/lv_task.c
index 5ac36edb..147ada68 100644
--- a/src/libs/lvgl/src/lv_misc/lv_task.c
+++ b/src/libs/lvgl/src/lv_misc/lv_task.c
@@ -1,6 +1,6 @@
/**
* @file lv_task.c
- * An 'lv_task' is a void (*fp) (void* param) type function which will be called periodically.
+ * An 'lv_task' is a void (*fp) (struct _lv_task_t* param) type function which will be called periodically.
* A priority (5 levels + disable) can be assigned to lv_tasks.
*/
@@ -9,14 +9,10 @@
*********************/
#include <stddef.h>
#include "lv_task.h"
-#include "../lv_core/lv_debug.h"
+#include "../lv_misc/lv_debug.h"
#include "../lv_hal/lv_hal_tick.h"
#include "lv_gc.h"
-#if defined(LV_GC_INCLUDE)
-#include LV_GC_INCLUDE
-#endif /* LV_ENABLE_GC */
-
/*********************
* DEFINES
*********************/
@@ -32,6 +28,7 @@
* STATIC PROTOTYPES
**********************/
static bool lv_task_exec(lv_task_t * task);
+static uint32_t lv_task_time_remaining(lv_task_t * task);
/**********************
* STATIC VARIABLES
@@ -39,6 +36,7 @@ static bool lv_task_exec(lv_task_t * task);
static bool lv_task_run = false;
static uint8_t idle_last = 0;
static bool task_deleted;
+static bool task_list_changed;
static bool task_created;
/**********************
@@ -52,36 +50,36 @@ static bool task_created;
/**
* Init the lv_task module
*/
-void lv_task_core_init(void)
+void _lv_task_core_init(void)
{
- lv_ll_init(&LV_GC_ROOT(_lv_task_ll), sizeof(lv_task_t));
+ _lv_ll_init(&LV_GC_ROOT(_lv_task_ll), sizeof(lv_task_t));
/*Initially enable the lv_task handling*/
lv_task_enable(true);
}
/**
- * Call it periodically to handle lv_tasks.
+ * Call it periodically to handle lv_tasks.
+ * @return the time after which it must be called again
*/
-LV_ATTRIBUTE_TASK_HANDLER void lv_task_handler(void)
+LV_ATTRIBUTE_TASK_HANDLER uint32_t lv_task_handler(void)
{
LV_LOG_TRACE("lv_task_handler started");
/*Avoid concurrent running of the task handler*/
static bool already_running = false;
- if(already_running) return;
+ if(already_running) return 1;
already_running = true;
- static uint32_t idle_period_start = 0;
- static uint32_t handler_start = 0;
- static uint32_t busy_time = 0;
-
if(lv_task_run == false) {
already_running = false; /*Release mutex*/
- return;
+ return 1;
}
- handler_start = lv_tick_get();
+ static uint32_t idle_period_start = 0;
+ static uint32_t busy_time = 0;
+
+ uint32_t handler_start = lv_tick_get();
/* Run all task from the highest to the lowest priority
* If a lower priority task is executed check task again from the highest priority
@@ -93,14 +91,15 @@ LV_ATTRIBUTE_TASK_HANDLER void lv_task_handler(void)
end_flag = true;
task_deleted = false;
task_created = false;
- LV_GC_ROOT(_lv_task_act) = lv_ll_get_head(&LV_GC_ROOT(_lv_task_ll));
+ task_list_changed = false;
+ LV_GC_ROOT(_lv_task_act) = _lv_ll_get_head(&LV_GC_ROOT(_lv_task_ll));
while(LV_GC_ROOT(_lv_task_act)) {
/* The task might be deleted if it runs only once ('once = 1')
* So get next element until the current is surely valid*/
- next = lv_ll_get_next(&LV_GC_ROOT(_lv_task_ll), LV_GC_ROOT(_lv_task_act));
+ next = _lv_ll_get_next(&LV_GC_ROOT(_lv_task_ll), LV_GC_ROOT(_lv_task_act));
/*We reach priority of the turned off task. There is nothing more to do.*/
- if(((lv_task_t *)LV_GC_ROOT(_lv_task_act))->prio == LV_TASK_PRIO_OFF) {
+ if(LV_GC_ROOT(_lv_task_act)->prio == LV_TASK_PRIO_OFF) {
break;
}
@@ -113,12 +112,12 @@ LV_ATTRIBUTE_TASK_HANDLER void lv_task_handler(void)
}
/*Just try to run the tasks with highest priority.*/
- if(((lv_task_t *)LV_GC_ROOT(_lv_task_act))->prio == LV_TASK_PRIO_HIGHEST) {
+ if(LV_GC_ROOT(_lv_task_act)->prio == LV_TASK_PRIO_HIGHEST) {
lv_task_exec(LV_GC_ROOT(_lv_task_act));
}
/*Tasks with higher priority than the interrupted shall be run in every case*/
else if(task_interrupter) {
- if(((lv_task_t *)LV_GC_ROOT(_lv_task_act))->prio > task_interrupter->prio) {
+ if(LV_GC_ROOT(_lv_task_act)->prio > task_interrupter->prio) {
if(lv_task_exec(LV_GC_ROOT(_lv_task_act))) {
if(!task_created && !task_deleted) {
/*Check all tasks again from the highest priority */
@@ -147,16 +146,31 @@ LV_ATTRIBUTE_TASK_HANDLER void lv_task_handler(void)
break;
}
+ if(task_list_changed) {
+ task_interrupter = NULL;
+ end_flag = false;
+ break;
+ }
+
LV_GC_ROOT(_lv_task_act) = next; /*Load the next task*/
}
} while(!end_flag);
+ uint32_t time_till_next = LV_NO_TASK_READY;
+ next = _lv_ll_get_head(&LV_GC_ROOT(_lv_task_ll));
+ while(next && next->prio != LV_TASK_PRIO_OFF) {
+ uint32_t delay = lv_task_time_remaining(next);
+ if(delay < time_till_next)
+ time_till_next = delay;
+
+ next = _lv_ll_get_next(&LV_GC_ROOT(_lv_task_ll), next); /*Find the next task*/
+ }
+
busy_time += lv_tick_elaps(handler_start);
uint32_t idle_period_time = lv_tick_elaps(idle_period_start);
if(idle_period_time >= IDLE_MEAS_PERIOD) {
-
- idle_last = (uint32_t)((uint32_t)busy_time * 100) / IDLE_MEAS_PERIOD; /*Calculate the busy percentage*/
- idle_last = idle_last > 100 ? 0 : 100 - idle_last; /*But we need idle time*/
+ idle_last = (busy_time * 100) / idle_period_time; /*Calculate the busy percentage*/
+ idle_last = idle_last > 100 ? 0 : 100 - idle_last; /*But we need idle time*/
busy_time = 0;
idle_period_start = lv_tick_get();
}
@@ -164,54 +178,71 @@ LV_ATTRIBUTE_TASK_HANDLER void lv_task_handler(void)
already_running = false; /*Release the mutex*/
LV_LOG_TRACE("lv_task_handler ready");
+ return time_till_next;
}
/**
- * Create an "empty" task. It needs to initialzed with at least
+ * Create an "empty" task. It needs to initialized with at least
* `lv_task_set_cb` and `lv_task_set_period`
- * @return pointer to the craeted task
+ * @return pointer to the created task
*/
lv_task_t * lv_task_create_basic(void)
{
+ return lv_task_create(NULL, DEF_PERIOD, DEF_PRIO, NULL);
+}
+
+/**
+ * Create a new lv_task
+ * @param task_xcb a callback which is the task itself. It will be called periodically.
+ * (the 'x' in the argument name indicates that its not a fully generic function because it not follows
+ * the `func_name(object, callback, ...)` convention)
+ * @param period call period in ms unit
+ * @param prio priority of the task (LV_TASK_PRIO_OFF means the task is stopped)
+ * @param user_data custom parameter
+ * @return pointer to the new task
+ */
+lv_task_t * lv_task_create(lv_task_cb_t task_xcb, uint32_t period, lv_task_prio_t prio, void * user_data)
+{
lv_task_t * new_task = NULL;
lv_task_t * tmp;
/*Create task lists in order of priority from high to low*/
- tmp = lv_ll_get_head(&LV_GC_ROOT(_lv_task_ll));
+ tmp = _lv_ll_get_head(&LV_GC_ROOT(_lv_task_ll));
/*It's the first task*/
if(NULL == tmp) {
- new_task = lv_ll_ins_head(&LV_GC_ROOT(_lv_task_ll));
+ new_task = _lv_ll_ins_head(&LV_GC_ROOT(_lv_task_ll));
LV_ASSERT_MEM(new_task);
if(new_task == NULL) return NULL;
}
/*Insert the new task to proper place according to its priority*/
else {
do {
- if(tmp->prio <= DEF_PRIO) {
- new_task = lv_ll_ins_prev(&LV_GC_ROOT(_lv_task_ll), tmp);
+ if(tmp->prio <= prio) {
+ new_task = _lv_ll_ins_prev(&LV_GC_ROOT(_lv_task_ll), tmp);
LV_ASSERT_MEM(new_task);
if(new_task == NULL) return NULL;
break;
}
- tmp = lv_ll_get_next(&LV_GC_ROOT(_lv_task_ll), tmp);
+ tmp = _lv_ll_get_next(&LV_GC_ROOT(_lv_task_ll), tmp);
} while(tmp != NULL);
/*Only too high priority tasks were found. Add the task to the end*/
if(tmp == NULL) {
- new_task = lv_ll_ins_tail(&LV_GC_ROOT(_lv_task_ll));
+ new_task = _lv_ll_ins_tail(&LV_GC_ROOT(_lv_task_ll));
LV_ASSERT_MEM(new_task);
if(new_task == NULL) return NULL;
}
}
+ task_list_changed = true;
- new_task->period = DEF_PERIOD;
- new_task->task_cb = NULL;
- new_task->prio = DEF_PRIO;
+ new_task->period = period;
+ new_task->task_cb = task_xcb;
+ new_task->prio = prio;
- new_task->once = 0;
+ new_task->repeat_count = -1;
new_task->last_run = lv_tick_get();
- new_task->user_data = NULL;
+ new_task->user_data = user_data;
task_created = true;
@@ -219,33 +250,9 @@ lv_task_t * lv_task_create_basic(void)
}
/**
- * Create a new lv_task
- * @param task_xcb a callback which is the task itself. It will be called periodically.
- * (the 'x' in the argument name indicates that its not a fully generic function because it not follows
- * the `func_name(object, callback, ...)` convention)
- * @param period call period in ms unit
- * @param prio priority of the task (LV_TASK_PRIO_OFF means the task is stopped)
- * @param user_data custom parameter
- * @return pointer to the new task
- */
-lv_task_t * lv_task_create(lv_task_cb_t task_cb, uint32_t period, lv_task_prio_t prio, void * user_data)
-{
- lv_task_t * new_task = lv_task_create_basic();
- LV_ASSERT_MEM(new_task);
- if(new_task == NULL) return NULL;
-
- lv_task_set_cb(new_task, task_cb);
- lv_task_set_period(new_task, period);
- lv_task_set_prio(new_task, prio);
- new_task->user_data = user_data;
-
- return new_task;
-}
-
-/**
* Set the callback the task (the function to call periodically)
* @param task pointer to a task
- * @param task_cb teh function to call periodically
+ * @param task_cb the function to call periodically
*/
void lv_task_set_cb(lv_task_t * task, lv_task_cb_t task_cb)
{
@@ -258,7 +265,8 @@ void lv_task_set_cb(lv_task_t * task, lv_task_cb_t task_cb)
*/
void lv_task_del(lv_task_t * task)
{
- lv_ll_rem(&LV_GC_ROOT(_lv_task_ll), task);
+ _lv_ll_remove(&LV_GC_ROOT(_lv_task_ll), task);
+ task_list_changed = true;
lv_mem_free(task);
@@ -276,18 +284,18 @@ void lv_task_set_prio(lv_task_t * task, lv_task_prio_t prio)
/*Find the tasks with new priority*/
lv_task_t * i;
- LV_LL_READ(LV_GC_ROOT(_lv_task_ll), i)
- {
+ _LV_LL_READ(LV_GC_ROOT(_lv_task_ll), i) {
if(i->prio <= prio) {
- if(i != task) lv_ll_move_before(&LV_GC_ROOT(_lv_task_ll), task, i);
+ if(i != task) _lv_ll_move_before(&LV_GC_ROOT(_lv_task_ll), task, i);
break;
}
}
/*There was no such a low priority so far then add the node to the tail*/
if(i == NULL) {
- lv_ll_move_before(&LV_GC_ROOT(_lv_task_ll), task, NULL);
+ _lv_ll_move_before(&LV_GC_ROOT(_lv_task_ll), task, NULL);
}
+ task_list_changed = true;
task->prio = prio;
}
@@ -312,12 +320,13 @@ void lv_task_ready(lv_task_t * task)
}
/**
- * Delete the lv_task after one call
+ * Set the number of times a task will repeat.
* @param task pointer to a lv_task.
+ * @param repeat_count -1 : infinity; 0 : stop ; n>0: residual times
*/
-void lv_task_once(lv_task_t * task)
+void lv_task_set_repeat_count(lv_task_t * task, int32_t repeat_count)
{
- task->once = 1;
+ task->repeat_count = repeat_count;
}
/**
@@ -348,6 +357,17 @@ uint8_t lv_task_get_idle(void)
return idle_last;
}
+/**
+ * Iterate through the tasks
+ * @param task NULL to start iteration or the previous return value to get the next task
+ * @return the next task or NULL if there is no more task
+ */
+lv_task_t * lv_task_get_next(lv_task_t * task)
+{
+ if(task == NULL) return _lv_ll_get_head(&LV_GC_ROOT(_lv_task_ll));
+ else return _lv_ll_get_next(&LV_GC_ROOT(_lv_task_ll), task);
+}
+
/**********************
* STATIC FUNCTIONS
**********************/
@@ -361,17 +381,16 @@ static bool lv_task_exec(lv_task_t * task)
{
bool exec = false;
- /*Execute if at least 'period' time elapsed*/
- uint32_t elp = lv_tick_elaps(task->last_run);
- if(elp >= task->period) {
+ if(lv_task_time_remaining(task) == 0) {
task->last_run = lv_tick_get();
- task_deleted = false;
- task_created = false;
if(task->task_cb) task->task_cb(task);
/*Delete if it was a one shot lv_task*/
if(task_deleted == false) { /*The task might be deleted by itself as well*/
- if(task->once != 0) {
+ if(task->repeat_count > 0) {
+ task->repeat_count--;
+ }
+ if(task->repeat_count == 0) {
lv_task_del(task);
}
}
@@ -380,3 +399,17 @@ static bool lv_task_exec(lv_task_t * task)
return exec;
}
+
+/**
+ * Find out how much time remains before a task must be run.
+ * @param task pointer to lv_task
+ * @return the time remaining, or 0 if it needs to be run again
+ */
+static uint32_t lv_task_time_remaining(lv_task_t * task)
+{
+ /*Check if at least 'period' time elapsed*/
+ uint32_t elp = lv_tick_elaps(task->last_run);
+ if(elp >= task->period)
+ return 0;
+ return task->period - elp;
+}
diff --git a/src/libs/lvgl/src/lv_misc/lv_task.h b/src/libs/lvgl/src/lv_misc/lv_task.h
index 05ff02b6..9b5bfde1 100644
--- a/src/libs/lvgl/src/lv_misc/lv_task.h
+++ b/src/libs/lvgl/src/lv_misc/lv_task.h
@@ -1,6 +1,6 @@
/**
- * @file lv_task.c
- * An 'lv_task' is a void (*fp) (void* param) type function which will be called periodically.
+ * @file lv_task.h
+ * An 'lv_task' is a void (*fp) (struct _lv_task_t* param) type function which will be called periodically.
* A priority (5 levels + disable) can be assigned to lv_tasks.
*/
@@ -14,11 +14,7 @@ extern "C" {
/*********************
* INCLUDES
*********************/
-#ifdef LV_CONF_INCLUDE_SIMPLE
-#include "lv_conf.h"
-#else
-#include "../../../lv_conf.h"
-#endif
+#include "../lv_conf_internal.h"
#include <stdint.h>
#include <stdbool.h>
@@ -31,6 +27,8 @@ extern "C" {
#ifndef LV_ATTRIBUTE_TASK_HANDLER
#define LV_ATTRIBUTE_TASK_HANDLER
#endif
+
+#define LV_NO_TASK_READY 0xFFFFFFFF
/**********************
* TYPEDEFS
**********************/
@@ -38,7 +36,7 @@ extern "C" {
struct _lv_task_t;
/**
- * Tasks execute this type type of functions.
+ * Tasks execute this type of functions.
*/
typedef void (*lv_task_cb_t)(struct _lv_task_t *);
@@ -59,16 +57,15 @@ typedef uint8_t lv_task_prio_t;
/**
* Descriptor of a lv_task
*/
-typedef struct _lv_task_t
-{
+typedef struct _lv_task_t {
uint32_t period; /**< How often the task should run */
uint32_t last_run; /**< Last time the task ran */
lv_task_cb_t task_cb; /**< Task function */
void * user_data; /**< Custom user data */
+ int32_t repeat_count; /**< 1: Task times; -1 : infinity; 0 : stop ; n>0: residual times */
uint8_t prio : 3; /**< Task priority */
- uint8_t once : 1; /**< 1: one shot task */
} lv_task_t;
/**********************
@@ -78,21 +75,22 @@ typedef struct _lv_task_t
/**
* Init the lv_task module
*/
-void lv_task_core_init(void);
+void _lv_task_core_init(void);
//! @cond Doxygen_Suppress
/**
- * Call it periodically to handle lv_tasks.
+ * Call it periodically to handle lv_tasks.
+ * @return time till it needs to be run next (in ms)
*/
-LV_ATTRIBUTE_TASK_HANDLER void lv_task_handler(void);
+LV_ATTRIBUTE_TASK_HANDLER uint32_t lv_task_handler(void);
//! @endcond
/**
- * Create an "empty" task. It needs to initialzed with at least
+ * Create an "empty" task. It needs to initialized with at least
* `lv_task_set_cb` and `lv_task_set_period`
- * @return pointer to the craeted task
+ * @return pointer to the created task
*/
lv_task_t * lv_task_create_basic(void);
@@ -142,10 +140,11 @@ void lv_task_set_period(lv_task_t * task, uint32_t period);
void lv_task_ready(lv_task_t * task);
/**
- * Delete the lv_task after one call
+ * Set the number of times a task will repeat.
* @param task pointer to a lv_task.
+ * @param repeat_count -1 : infinity; 0 : stop ; n>0: residual times
*/
-void lv_task_once(lv_task_t * task);
+void lv_task_set_repeat_count(lv_task_t * task, int32_t repeat_count);
/**
* Reset a lv_task.
@@ -155,7 +154,7 @@ void lv_task_once(lv_task_t * task);
void lv_task_reset(lv_task_t * task);
/**
- * Enable or disable the whole lv_task handling
+ * Enable or disable the whole lv_task handling
* @param en: true: lv_task handling is running, false: lv_task handling is suspended
*/
void lv_task_enable(bool en);
@@ -166,6 +165,13 @@ void lv_task_enable(bool en);
*/
uint8_t lv_task_get_idle(void);
+/**
+ * Iterate through the tasks
+ * @param task NULL to start iteration or the previous return value to get the next task
+ * @return the next task or NULL if there is no more task
+ */
+lv_task_t * lv_task_get_next(lv_task_t * task);
+
/**********************
* MACROS
**********************/
diff --git a/src/libs/lvgl/src/lv_misc/lv_templ.c b/src/libs/lvgl/src/lv_misc/lv_templ.c
index c5bb68c0..45683915 100644
--- a/src/libs/lvgl/src/lv_misc/lv_templ.c
+++ b/src/libs/lvgl/src/lv_misc/lv_templ.c
@@ -17,7 +17,7 @@
/* This typedef exists purely to keep -Wpedantic happy when the file is empty. */
/* It can be removed. */
-typedef int keep_pedantic_happy;
+typedef int _keep_pedantic_happy;
/**********************
* STATIC PROTOTYPES
diff --git a/src/libs/lvgl/src/lv_misc/lv_txt.c b/src/libs/lvgl/src/lv_misc/lv_txt.c
index 9de132e9..e240485b 100644
--- a/src/libs/lvgl/src/lv_misc/lv_txt.c
+++ b/src/libs/lvgl/src/lv_misc/lv_txt.c
@@ -6,9 +6,12 @@
/*********************
* INCLUDES
*********************/
+#include <stdarg.h>
#include "lv_txt.h"
+#include "lv_txt_ap.h"
#include "lv_math.h"
#include "lv_log.h"
+#include "lv_debug.h"
/*********************
* DEFINES
@@ -25,23 +28,23 @@
static inline bool is_break_char(uint32_t letter);
#if LV_TXT_ENC == LV_TXT_ENC_UTF8
-static uint8_t lv_txt_utf8_size(const char * str);
-static uint32_t lv_txt_unicode_to_utf8(uint32_t letter_uni);
-static uint32_t lv_txt_utf8_conv_wc(uint32_t c);
-static uint32_t lv_txt_utf8_next(const char * txt, uint32_t * i);
-static uint32_t lv_txt_utf8_prev(const char * txt, uint32_t * i_start);
-static uint32_t lv_txt_utf8_get_byte_id(const char * txt, uint32_t utf8_id);
-static uint32_t lv_txt_utf8_get_char_id(const char * txt, uint32_t byte_id);
-static uint32_t lv_txt_utf8_get_length(const char * txt);
+ static uint8_t lv_txt_utf8_size(const char * str);
+ static uint32_t lv_txt_unicode_to_utf8(uint32_t letter_uni);
+ static uint32_t lv_txt_utf8_conv_wc(uint32_t c);
+ static uint32_t lv_txt_utf8_next(const char * txt, uint32_t * i);
+ static uint32_t lv_txt_utf8_prev(const char * txt, uint32_t * i_start);
+ static uint32_t lv_txt_utf8_get_byte_id(const char * txt, uint32_t utf8_id);
+ static uint32_t lv_txt_utf8_get_char_id(const char * txt, uint32_t byte_id);
+ static uint32_t lv_txt_utf8_get_length(const char * txt);
#elif LV_TXT_ENC == LV_TXT_ENC_ASCII
-static uint8_t lv_txt_iso8859_1_size(const char * str);
-static uint32_t lv_txt_unicode_to_iso8859_1(uint32_t letter_uni);
-static uint32_t lv_txt_iso8859_1_conv_wc(uint32_t c);
-static uint32_t lv_txt_iso8859_1_next(const char * txt, uint32_t * i);
-static uint32_t lv_txt_iso8859_1_prev(const char * txt, uint32_t * i_start);
-static uint32_t lv_txt_iso8859_1_get_byte_id(const char * txt, uint32_t utf8_id);
-static uint32_t lv_txt_iso8859_1_get_char_id(const char * txt, uint32_t byte_id);
-static uint32_t lv_txt_iso8859_1_get_length(const char * txt);
+ static uint8_t lv_txt_iso8859_1_size(const char * str);
+ static uint32_t lv_txt_unicode_to_iso8859_1(uint32_t letter_uni);
+ static uint32_t lv_txt_iso8859_1_conv_wc(uint32_t c);
+ static uint32_t lv_txt_iso8859_1_next(const char * txt, uint32_t * i);
+ static uint32_t lv_txt_iso8859_1_prev(const char * txt, uint32_t * i_start);
+ static uint32_t lv_txt_iso8859_1_get_byte_id(const char * txt, uint32_t utf8_id);
+ static uint32_t lv_txt_iso8859_1_get_char_id(const char * txt, uint32_t byte_id);
+ static uint32_t lv_txt_iso8859_1_get_length(const char * txt);
#endif
/**********************
* STATIC VARIABLES
@@ -51,23 +54,23 @@ static uint32_t lv_txt_iso8859_1_get_length(const char * txt);
* GLOBAL VARIABLES
**********************/
#if LV_TXT_ENC == LV_TXT_ENC_UTF8
-uint8_t (*lv_txt_encoded_size)(const char *) = lv_txt_utf8_size;
-uint32_t (*lv_txt_unicode_to_encoded)(uint32_t) = lv_txt_unicode_to_utf8;
-uint32_t (*lv_txt_encoded_conv_wc)(uint32_t) = lv_txt_utf8_conv_wc;
-uint32_t (*lv_txt_encoded_next)(const char *, uint32_t *) = lv_txt_utf8_next;
-uint32_t (*lv_txt_encoded_prev)(const char *, uint32_t *) = lv_txt_utf8_prev;
-uint32_t (*lv_txt_encoded_get_byte_id)(const char *, uint32_t) = lv_txt_utf8_get_byte_id;
-uint32_t (*lv_txt_encoded_get_char_id)(const char *, uint32_t) = lv_txt_utf8_get_char_id;
-uint32_t (*lv_txt_get_encoded_length)(const char *) = lv_txt_utf8_get_length;
+ uint8_t (*_lv_txt_encoded_size)(const char *) = lv_txt_utf8_size;
+ uint32_t (*_lv_txt_unicode_to_encoded)(uint32_t) = lv_txt_unicode_to_utf8;
+ uint32_t (*_lv_txt_encoded_conv_wc)(uint32_t) = lv_txt_utf8_conv_wc;
+ uint32_t (*_lv_txt_encoded_next)(const char *, uint32_t *) = lv_txt_utf8_next;
+ uint32_t (*_lv_txt_encoded_prev)(const char *, uint32_t *) = lv_txt_utf8_prev;
+ uint32_t (*_lv_txt_encoded_get_byte_id)(const char *, uint32_t) = lv_txt_utf8_get_byte_id;
+ uint32_t (*_lv_txt_encoded_get_char_id)(const char *, uint32_t) = lv_txt_utf8_get_char_id;
+ uint32_t (*_lv_txt_get_encoded_length)(const char *) = lv_txt_utf8_get_length;
#elif LV_TXT_ENC == LV_TXT_ENC_ASCII
-uint8_t (*lv_txt_encoded_size)(const char *) = lv_txt_iso8859_1_size;
-uint32_t (*lv_txt_unicode_to_encoded)(uint32_t) = lv_txt_unicode_to_iso8859_1;
-uint32_t (*lv_txt_encoded_conv_wc)(uint32_t) = lv_txt_iso8859_1_conv_wc;
-uint32_t (*lv_txt_encoded_next)(const char *, uint32_t *) = lv_txt_iso8859_1_next;
-uint32_t (*lv_txt_encoded_prev)(const char *, uint32_t *) = lv_txt_iso8859_1_prev;
-uint32_t (*lv_txt_encoded_get_byte_id)(const char *, uint32_t) = lv_txt_iso8859_1_get_byte_id;
-uint32_t (*lv_txt_encoded_get_char_id)(const char *, uint32_t) = lv_txt_iso8859_1_get_char_id;
-uint32_t (*lv_txt_get_encoded_length)(const char *) = lv_txt_iso8859_1_get_length;
+ uint8_t (*_lv_txt_encoded_size)(const char *) = lv_txt_iso8859_1_size;
+ uint32_t (*_lv_txt_unicode_to_encoded)(uint32_t) = lv_txt_unicode_to_iso8859_1;
+ uint32_t (*_lv_txt_encoded_conv_wc)(uint32_t) = lv_txt_iso8859_1_conv_wc;
+ uint32_t (*_lv_txt_encoded_next)(const char *, uint32_t *) = lv_txt_iso8859_1_next;
+ uint32_t (*_lv_txt_encoded_prev)(const char *, uint32_t *) = lv_txt_iso8859_1_prev;
+ uint32_t (*_lv_txt_encoded_get_byte_id)(const char *, uint32_t) = lv_txt_iso8859_1_get_byte_id;
+ uint32_t (*_lv_txt_encoded_get_char_id)(const char *, uint32_t) = lv_txt_iso8859_1_get_char_id;
+ uint32_t (*_lv_txt_get_encoded_length)(const char *) = lv_txt_iso8859_1_get_length;
#endif
@@ -83,15 +86,15 @@ uint32_t (*lv_txt_get_encoded_length)(const char *) = lv_txt_iso8859_
* Get size of a text
* @param size_res pointer to a 'point_t' variable to store the result
* @param text pointer to a text
- * @param font pinter to font of the text
+ * @param font pointer to font of the text
* @param letter_space letter space of the text
* @param txt.line_space line space of the text
* @param flags settings for the text from 'txt_flag_t' enum
* @param max_width max with of the text (break the lines to fit this size) Set CORD_MAX to avoid
* line breaks
*/
-void lv_txt_get_size(lv_point_t * size_res, const char * text, const lv_font_t * font, lv_coord_t letter_space,
- lv_coord_t line_space, lv_coord_t max_width, lv_txt_flag_t flag)
+void _lv_txt_get_size(lv_point_t * size_res, const char * text, const lv_font_t * font, lv_coord_t letter_space,
+ lv_coord_t line_space, lv_coord_t max_width, lv_txt_flag_t flag)
{
size_res->x = 0;
size_res->y = 0;
@@ -103,23 +106,24 @@ void lv_txt_get_size(lv_point_t * size_res, const char * text, const lv_font_t *
uint32_t line_start = 0;
uint32_t new_line_start = 0;
- lv_coord_t act_line_length;
- uint8_t letter_height = lv_font_get_line_height(font);
+ uint16_t letter_height = lv_font_get_line_height(font);
/*Calc. the height and longest line*/
while(text[line_start] != '\0') {
- new_line_start += lv_txt_get_next_line(&text[line_start], font, letter_space, max_width, flag);
+ new_line_start += _lv_txt_get_next_line(&text[line_start], font, letter_space, max_width, flag);
- if ((unsigned long)size_res->y + (unsigned long)letter_height + (unsigned long)line_space > LV_MAX_OF(lv_coord_t)) {
+ if((unsigned long)size_res->y + (unsigned long)letter_height + (unsigned long)line_space > LV_MAX_OF(lv_coord_t)) {
LV_LOG_WARN("lv_txt_get_size: integer overflow while calculating text height");
return;
- } else {
+ }
+ else {
size_res->y += letter_height;
size_res->y += line_space;
}
- /*Calculate the the longest line*/
- act_line_length = lv_txt_get_width(&text[line_start], new_line_start - line_start, font, letter_space, flag);
+ /*Calculate the longest line*/
+ lv_coord_t act_line_length = _lv_txt_get_width(&text[line_start], new_line_start - line_start, font, letter_space,
+ flag);
size_res->x = LV_MATH_MAX(act_line_length, size_res->x);
line_start = new_line_start;
@@ -146,7 +150,7 @@ void lv_txt_get_size(lv_point_t * size_res, const char * text, const lv_font_t *
*
* If the first character is a break character, returns the next index.
*
- * Example calls from lv_txt_get_next_line() assuming sufficent max_width and
+ * Example calls from lv_txt_get_next_line() assuming sufficient max_width and
* txt = "Test text\n"
* 0123456789
*
@@ -156,7 +160,7 @@ void lv_txt_get_size(lv_point_t * size_res, const char * text, const lv_font_t *
* 3. Return i=9, pointing at breakchar '\n'
* 4. Parenting lv_txt_get_next_line() would detect subsequent '\0'
*
- * TODO: Returned word_w_ptr may overestimate the returned word's width when
+ * TODO: Returned word_w_ptr may overestimate the returned word's width when
* max_width is reached. In current usage, this has no impact.
*
* @param txt a '\0' terminated string
@@ -168,9 +172,9 @@ void lv_txt_get_size(lv_point_t * size_res, const char * text, const lv_font_t *
* @param force Force return the fraction of the word that can fit in the provided space.
* @return the index of the first char of the next word (in byte index not letter index. With UTF-8 they are different)
*/
-static uint16_t lv_txt_get_next_word(const char * txt, const lv_font_t * font,
- lv_coord_t letter_space, lv_coord_t max_width,
- lv_txt_flag_t flag, uint32_t *word_w_ptr, lv_txt_cmd_state_t * cmd_state, bool force)
+static uint32_t lv_txt_get_next_word(const char * txt, const lv_font_t * font,
+ lv_coord_t letter_space, lv_coord_t max_width,
+ lv_txt_flag_t flag, uint32_t * word_w_ptr, lv_txt_cmd_state_t * cmd_state, bool force)
{
if(txt == NULL || txt[0] == '\0') return 0;
if(font == NULL) return 0;
@@ -186,17 +190,17 @@ static uint16_t lv_txt_get_next_word(const char * txt, const lv_font_t * font,
uint32_t break_index = NO_BREAK_FOUND; /* only used for "long" words */
uint32_t break_letter_count = 0; /* Number of characters up to the long word break point */
- letter = lv_txt_encoded_next(txt, &i_next);
+ letter = _lv_txt_encoded_next(txt, &i_next);
i_next_next = i_next;
/* Obtain the full word, regardless if it fits or not in max_width */
while(txt[i] != '\0') {
- letter_next = lv_txt_encoded_next(txt, &i_next_next);
+ letter_next = _lv_txt_encoded_next(txt, &i_next_next);
word_len++;
/*Handle the recolor command*/
if((flag & LV_TXT_FLAG_RECOLOR) != 0) {
- if(lv_txt_is_cmd(cmd_state, letter) != false) {
+ if(_lv_txt_is_cmd(cmd_state, letter) != false) {
i = i_next;
i_next = i_next_next;
letter = letter_next;
@@ -213,7 +217,7 @@ static uint16_t lv_txt_get_next_word(const char * txt, const lv_font_t * font,
/* Test if this character fits within max_width */
if(break_index == NO_BREAK_FOUND && (cur_w - letter_space) > max_width) {
- break_index = i;
+ break_index = i;
break_letter_count = word_len - 1;
/* break_index is now pointing at the character that doesn't fit */
}
@@ -221,15 +225,14 @@ static uint16_t lv_txt_get_next_word(const char * txt, const lv_font_t * font,
/*Check for new line chars and breakchars*/
if(letter == '\n' || letter == '\r' || is_break_char(letter)) {
/* Update the output width on the first character if it fits.
- * Must do this here incase first letter is a break character. */
+ * Must do this here in case first letter is a break character. */
if(i == 0 && break_index == NO_BREAK_FOUND && word_w_ptr != NULL) *word_w_ptr = cur_w;
word_len--;
break;
}
/* Update the output width */
- if( word_w_ptr != NULL && break_index == NO_BREAK_FOUND ) *word_w_ptr = cur_w;
-
+ if(word_w_ptr != NULL && break_index == NO_BREAK_FOUND) *word_w_ptr = cur_w;
i = i_next;
i_next = i_next_next;
@@ -237,22 +240,22 @@ static uint16_t lv_txt_get_next_word(const char * txt, const lv_font_t * font,
}
/* Entire Word fits in the provided space */
- if( break_index == NO_BREAK_FOUND ) {
- if( word_len == 0 || (letter == '\r' && letter_next == '\n') ) i = i_next;
+ if(break_index == NO_BREAK_FOUND) {
+ if(word_len == 0 || (letter == '\r' && letter_next == '\n')) i = i_next;
return i;
}
#if LV_TXT_LINE_BREAK_LONG_LEN > 0
/* Word doesn't fit in provided space, but isn't "long" */
if(word_len < LV_TXT_LINE_BREAK_LONG_LEN) {
- if( force ) return break_index;
+ if(force) return break_index;
if(word_w_ptr != NULL) *word_w_ptr = 0; /* Return no word */
return 0;
}
/* Word is "long," but insufficient amounts can fit in provided space */
if(break_letter_count < LV_TXT_LINE_BREAK_LONG_PRE_MIN_LEN) {
- if( force ) return break_index;
+ if(force) return break_index;
if(word_w_ptr != NULL) *word_w_ptr = 0;
return 0;
}
@@ -262,15 +265,15 @@ static uint16_t lv_txt_get_next_word(const char * txt, const lv_font_t * font,
i = break_index;
int32_t n_move = LV_TXT_LINE_BREAK_LONG_POST_MIN_LEN - (word_len - break_letter_count);
/* Move pointer "i" backwards */
- for(;n_move>0; n_move--){
- lv_txt_encoded_prev(txt, &i);
+ for(; n_move > 0; n_move--) {
+ _lv_txt_encoded_prev(txt, &i);
// TODO: it would be appropriate to update the returned word width here
// However, in current usage, this doesn't impact anything.
}
}
return i;
#else
- if( force ) return break_index;
+ if(force) return break_index;
if(word_w_ptr != NULL) *word_w_ptr = 0; /* Return no word */
(void) break_letter_count;
return 0;
@@ -289,23 +292,34 @@ static uint16_t lv_txt_get_next_word(const char * txt, const lv_font_t * font,
* @param flags settings for the text from 'txt_flag_type' enum
* @return the index of the first char of the new line (in byte index not letter index. With UTF-8 they are different)
*/
-uint16_t lv_txt_get_next_line(const char * txt, const lv_font_t * font,
- lv_coord_t letter_space, lv_coord_t max_width, lv_txt_flag_t flag)
+uint32_t _lv_txt_get_next_line(const char * txt, const lv_font_t * font,
+ lv_coord_t letter_space, lv_coord_t max_width, lv_txt_flag_t flag)
{
if(txt == NULL) return 0;
if(font == NULL) return 0;
+ /* If max_width doesn't mater simply find the new line character
+ * without thinking about word wrapping*/
+ if((flag & LV_TXT_FLAG_EXPAND) || (flag & LV_TXT_FLAG_FIT)) {
+ uint32_t i;
+ for(i = 0; txt[i] != '\n' && txt[i] != '\r' && txt[i] != '\0'; i++) {
+ /*Just find the new line chars or string ends by incrementing `i`*/
+ }
+ if(txt[i] != '\0') i++; /*To go beyond `\n`*/
+ return i;
+ }
+
if(flag & LV_TXT_FLAG_EXPAND) max_width = LV_COORD_MAX;
lv_txt_cmd_state_t cmd_state = LV_TXT_CMD_STATE_WAIT;
uint32_t i = 0; /* Iterating index into txt */
while(txt[i] != '\0' && max_width > 0) {
uint32_t word_w = 0;
- uint32_t advance = lv_txt_get_next_word(&txt[i], font, letter_space, max_width, flag, &word_w, &cmd_state, i==0);
+ uint32_t advance = lv_txt_get_next_word(&txt[i], font, letter_space, max_width, flag, &word_w, &cmd_state, i == 0);
max_width -= word_w;
- if( advance == 0 ){
- if(i == 0) lv_txt_encoded_next(txt, &i); // prevent inf loops
+ if(advance == 0) {
+ if(i == 0) _lv_txt_encoded_next(txt, &i); // prevent inf loops
break;
}
@@ -313,7 +327,7 @@ uint16_t lv_txt_get_next_line(const char * txt, const lv_font_t * font,
if(txt[0] == '\n' || txt[0] == '\r') break;
- if(txt[i] == '\n' || txt[i] == '\r'){
+ if(txt[i] == '\n' || txt[i] == '\r') {
i++; /* Include the following newline in the current line */
break;
}
@@ -322,7 +336,7 @@ uint16_t lv_txt_get_next_line(const char * txt, const lv_font_t * font,
/* Always step at least one to avoid infinite loops */
if(i == 0) {
- lv_txt_encoded_next(txt, &i);
+ _lv_txt_encoded_next(txt, &i);
}
return i;
@@ -338,24 +352,23 @@ uint16_t lv_txt_get_next_line(const char * txt, const lv_font_t * font,
* @param flags settings for the text from 'txt_flag_t' enum
* @return length of a char_num long text
*/
-lv_coord_t lv_txt_get_width(const char * txt, uint16_t length, const lv_font_t * font, lv_coord_t letter_space,
- lv_txt_flag_t flag)
+lv_coord_t _lv_txt_get_width(const char * txt, uint32_t length, const lv_font_t * font, lv_coord_t letter_space,
+ lv_txt_flag_t flag)
{
if(txt == NULL) return 0;
if(font == NULL) return 0;
+ if(txt[0] == '\0') return 0;
uint32_t i = 0;
lv_coord_t width = 0;
lv_txt_cmd_state_t cmd_state = LV_TXT_CMD_STATE_WAIT;
- uint32_t letter;
- uint32_t letter_next;
if(length != 0) {
while(i < length) {
- letter = lv_txt_encoded_next(txt, &i);
- letter_next = lv_txt_encoded_next(&txt[i], NULL);
+ uint32_t letter = _lv_txt_encoded_next(txt, &i);
+ uint32_t letter_next = _lv_txt_encoded_next(&txt[i], NULL);
if((flag & LV_TXT_FLAG_RECOLOR) != 0) {
- if(lv_txt_is_cmd(&cmd_state, letter) != false) {
+ if(_lv_txt_is_cmd(&cmd_state, letter) != false) {
continue;
}
}
@@ -379,12 +392,12 @@ lv_coord_t lv_txt_get_width(const char * txt, uint16_t length, const lv_font_t *
/**
* Check next character in a string and decide if the character is part of the command or not
* @param state pointer to a txt_cmd_state_t variable which stores the current state of command
- * processing (Initied. to TXT_CMD_STATE_WAIT )
+ * processing (Inited to TXT_CMD_STATE_WAIT )
* @param c the current character
* @return true: the character is part of a command and should not be written,
* false: the character should be written
*/
-bool lv_txt_is_cmd(lv_txt_cmd_state_t * state, uint32_t c)
+bool _lv_txt_is_cmd(lv_txt_cmd_state_t * state, uint32_t c)
{
bool ret = false;
@@ -422,12 +435,14 @@ bool lv_txt_is_cmd(lv_txt_cmd_state_t * state, uint32_t c)
* UTF-8) 0: before the original text, 1: after the first char etc.
* @param ins_txt text to insert
*/
-void lv_txt_ins(char * txt_buf, uint32_t pos, const char * ins_txt)
+void _lv_txt_ins(char * txt_buf, uint32_t pos, const char * ins_txt)
{
size_t old_len = strlen(txt_buf);
size_t ins_len = strlen(ins_txt);
+ if(ins_len == 0) return;
+
size_t new_len = ins_len + old_len;
- pos = lv_txt_encoded_get_byte_id(txt_buf, pos); /*Convert to byte index instead of letter index*/
+ pos = _lv_txt_encoded_get_byte_id(txt_buf, pos); /*Convert to byte index instead of letter index*/
/*Copy the second part into the end to make place to text to insert*/
size_t i;
@@ -436,7 +451,7 @@ void lv_txt_ins(char * txt_buf, uint32_t pos, const char * ins_txt)
}
/* Copy the text into the new space*/
- memcpy(txt_buf + pos, ins_txt, ins_len);
+ _lv_memcpy_small(txt_buf + pos, ins_txt, ins_len);
}
/**
@@ -446,13 +461,13 @@ void lv_txt_ins(char * txt_buf, uint32_t pos, const char * ins_txt)
* char etc.)
* @param len number of characters to delete
*/
-void lv_txt_cut(char * txt, uint32_t pos, uint32_t len)
+void _lv_txt_cut(char * txt, uint32_t pos, uint32_t len)
{
size_t old_len = strlen(txt);
- pos = lv_txt_encoded_get_byte_id(txt, pos); /*Convert to byte index instead of letter index*/
- len = lv_txt_encoded_get_byte_id(&txt[pos], len);
+ pos = _lv_txt_encoded_get_byte_id(txt, pos); /*Convert to byte index instead of letter index*/
+ len = _lv_txt_encoded_get_byte_id(&txt[pos], len);
/*Copy the second part into the end to make place to text to insert*/
uint32_t i;
@@ -461,9 +476,57 @@ void lv_txt_cut(char * txt, uint32_t pos, uint32_t len)
}
}
+/**
+ * return a new formatted text. Memory will be allocated to store the text.
+ * @param fmt `printf`-like format
+ * @return pointer to the allocated text string.
+ */
+char * _lv_txt_set_text_vfmt(const char * fmt, va_list ap)
+{
+ /*Allocate space for the new text by using trick from C99 standard section 7.19.6.12 */
+ va_list ap_copy;
+ va_copy(ap_copy, ap);
+ uint32_t len = lv_vsnprintf(NULL, 0, fmt, ap_copy);
+ va_end(ap_copy);
+
+ char * text = 0;
+#if LV_USE_ARABIC_PERSIAN_CHARS
+ /*Put together the text according to the format string*/
+ char * raw_txt = _lv_mem_buf_get(len + 1);
+ LV_ASSERT_MEM(raw_txt);
+ if(raw_txt == NULL) {
+ return NULL;
+ }
+
+ lv_vsnprintf(raw_txt, len + 1, fmt, ap);
+
+ /*Get the size of the Arabic text and process it*/
+ size_t len_ap = _lv_txt_ap_calc_bytes_cnt(raw_txt);
+ text = lv_mem_alloc(len_ap + 1);
+ LV_ASSERT_MEM(text);
+ if(text == NULL) {
+ return NULL;
+ }
+ _lv_txt_ap_proc(raw_txt, text);
+
+ _lv_mem_buf_release(raw_txt);
+#else
+ text = lv_mem_alloc(len + 1);
+ LV_ASSERT_MEM(text);
+ if(text == NULL) {
+ return NULL;
+ }
+ text[len] = 0; /* Ensure NULL termination */
+
+ lv_vsnprintf(text, len + 1, fmt, ap);
+#endif
+
+ return text;
+}
+
#if LV_TXT_ENC == LV_TXT_ENC_UTF8
/*******************************
- * UTF-8 ENCODER/DECOER
+ * UTF-8 ENCODER/DECODER
******************************/
/**
@@ -499,12 +562,14 @@ static uint32_t lv_txt_unicode_to_utf8(uint32_t letter_uni)
bytes[1] = ((letter_uni >> 0) & 0x3F) | 0x80;
bytes[2] = 0;
bytes[3] = 0;
- } else if(letter_uni < 0x010000) {
+ }
+ else if(letter_uni < 0x010000) {
bytes[0] = ((letter_uni >> 12) & 0x0F) | 0xE0;
bytes[1] = ((letter_uni >> 6) & 0x3F) | 0x80;
bytes[2] = ((letter_uni >> 0) & 0x3F) | 0x80;
bytes[3] = 0;
- } else if(letter_uni < 0x110000) {
+ }
+ else if(letter_uni < 0x110000) {
bytes[0] = ((letter_uni >> 18) & 0x07) | 0xF0;
bytes[1] = ((letter_uni >> 12) & 0x3F) | 0x80;
bytes[2] = ((letter_uni >> 6) & 0x3F) | 0x80;
@@ -517,16 +582,17 @@ static uint32_t lv_txt_unicode_to_utf8(uint32_t letter_uni)
/**
* Convert a wide character, e.g. 'Á' little endian to be UTF-8 compatible
- * @param c a wide character or a Little endian number
+ * @param c a wide character or a Little endian number
* @return `c` in big endian
*/
static uint32_t lv_txt_utf8_conv_wc(uint32_t c)
{
+#if LV_BIG_ENDIAN_SYSTEM == 0
/*Swap the bytes (UTF-8 is big endian, but the MCUs are little endian)*/
if((c & 0x80) != 0) {
uint32_t swapped;
uint8_t c8[4];
- memcpy(c8, &c, 4);
+ _lv_memcpy_small(c8, &c, 4);
swapped = (c8[0] << 24) + (c8[1] << 16) + (c8[2] << 8) + (c8[3]);
uint8_t i;
for(i = 0; i < 4; i++) {
@@ -535,7 +601,7 @@ static uint32_t lv_txt_utf8_conv_wc(uint32_t c)
}
c = swapped;
}
-
+#endif
return c;
}
@@ -606,7 +672,8 @@ static uint32_t lv_txt_utf8_next(const char * txt, uint32_t * i)
if((txt[*i] & 0xC0) != 0x80) return 0; /*Invalid UTF-8 code*/
result += txt[*i] & 0x3F;
(*i)++;
- } else {
+ }
+ else {
(*i)++; /*Not UTF-8 char. Go the next.*/
}
}
@@ -630,7 +697,7 @@ static uint32_t lv_txt_utf8_prev(const char * txt, uint32_t * i)
do {
if(cnt >= 4) return 0; /*No UTF-8 char found before the initial*/
- c_size = lv_txt_encoded_size(&txt[*i]);
+ c_size = _lv_txt_encoded_size(&txt[*i]);
if(c_size == 0) {
if(*i != 0)
(*i)--;
@@ -641,7 +708,7 @@ static uint32_t lv_txt_utf8_prev(const char * txt, uint32_t * i)
} while(c_size == 0);
uint32_t i_tmp = *i;
- uint32_t letter = lv_txt_encoded_next(txt, &i_tmp); /*Character found, get it*/
+ uint32_t letter = _lv_txt_encoded_next(txt, &i_tmp); /*Character found, get it*/
return letter;
}
@@ -658,7 +725,7 @@ static uint32_t lv_txt_utf8_get_byte_id(const char * txt, uint32_t utf8_id)
uint32_t i;
uint32_t byte_cnt = 0;
for(i = 0; i < utf8_id; i++) {
- uint8_t c_size = lv_txt_encoded_size(&txt[byte_cnt]);
+ uint8_t c_size = _lv_txt_encoded_size(&txt[byte_cnt]);
byte_cnt += c_size > 0 ? c_size : 1;
}
@@ -678,7 +745,7 @@ static uint32_t lv_txt_utf8_get_char_id(const char * txt, uint32_t byte_id)
uint32_t char_cnt = 0;
while(i < byte_id) {
- lv_txt_encoded_next(txt, &i); /*'i' points to the next letter so use the prev. value*/
+ _lv_txt_encoded_next(txt, &i); /*'i' points to the next letter so use the prev. value*/
char_cnt++;
}
@@ -697,7 +764,7 @@ static uint32_t lv_txt_utf8_get_length(const char * txt)
uint32_t i = 0;
while(txt[i] != '\0') {
- lv_txt_encoded_next(txt, &i);
+ _lv_txt_encoded_next(txt, &i);
len++;
}
@@ -727,7 +794,7 @@ static uint8_t lv_txt_iso8859_1_size(const char * str)
*/
static uint32_t lv_txt_unicode_to_iso8859_1(uint32_t letter_uni)
{
- if(letter_uni < 128)
+ if(letter_uni < 256)
return letter_uni;
else
return ' ';
diff --git a/src/libs/lvgl/src/lv_misc/lv_txt.h b/src/libs/lvgl/src/lv_misc/lv_txt.h
index 6dbce5d4..596846cd 100644
--- a/src/libs/lvgl/src/lv_misc/lv_txt.h
+++ b/src/libs/lvgl/src/lv_misc/lv_txt.h
@@ -13,16 +13,13 @@ extern "C" {
/*********************
* INCLUDES
*********************/
-#ifdef LV_CONF_INCLUDE_SIMPLE
-#include "lv_conf.h"
-#else
-#include "../../../lv_conf.h"
-#endif
+#include "../lv_conf_internal.h"
#include <stdbool.h>
-#include "lv_area.h"
+#include <stdarg.h>
#include "lv_area.h"
#include "../lv_font/lv_font.h"
+#include "lv_printf.h"
/*********************
* DEFINES
@@ -43,9 +40,10 @@ extern "C" {
enum {
LV_TXT_FLAG_NONE = 0x00,
LV_TXT_FLAG_RECOLOR = 0x01, /**< Enable parsing of recolor command*/
- LV_TXT_FLAG_EXPAND = 0x02, /**< Ignore width to avoid automatic word wrapping*/
+ LV_TXT_FLAG_EXPAND = 0x02, /**< Ignore max-width to avoid automatic word wrapping*/
LV_TXT_FLAG_CENTER = 0x04, /**< Align the text to the middle*/
LV_TXT_FLAG_RIGHT = 0x08, /**< Align the text to the right*/
+ LV_TXT_FLAG_FIT = 0x10, /**< Max-width is already equal to the longest line. (Used to skip some calculation)*/
};
typedef uint8_t lv_txt_flag_t;
@@ -66,15 +64,15 @@ typedef uint8_t lv_txt_cmd_state_t;
* Get size of a text
* @param size_res pointer to a 'point_t' variable to store the result
* @param text pointer to a text
- * @param font pinter to font of the text
+ * @param font pointer to font of the text
* @param letter_space letter space of the text
* @param line_space line space of the text
* @param flags settings for the text from 'txt_flag_t' enum
* @param max_width max with of the text (break the lines to fit this size) Set CORD_MAX to avoid
* line breaks
*/
-void lv_txt_get_size(lv_point_t * size_res, const char * text, const lv_font_t * font, lv_coord_t letter_space,
- lv_coord_t line_space, lv_coord_t max_width, lv_txt_flag_t flag);
+void _lv_txt_get_size(lv_point_t * size_res, const char * text, const lv_font_t * font, lv_coord_t letter_space,
+ lv_coord_t line_space, lv_coord_t max_width, lv_txt_flag_t flag);
/**
* Get the next line of text. Check line length and break chars too.
@@ -87,8 +85,8 @@ void lv_txt_get_size(lv_point_t * size_res, const char * text, const lv_font_t *
* @return the index of the first char of the new line (in byte index not letter index. With UTF-8
* they are different)
*/
-uint16_t lv_txt_get_next_line(const char * txt, const lv_font_t * font, lv_coord_t letter_space, lv_coord_t max_width,
- lv_txt_flag_t flag);
+uint32_t _lv_txt_get_next_line(const char * txt, const lv_font_t * font, lv_coord_t letter_space, lv_coord_t max_width,
+ lv_txt_flag_t flag);
/**
* Give the length of a text with a given font
@@ -100,18 +98,18 @@ uint16_t lv_txt_get_next_line(const char * txt, const lv_font_t * font, lv_coord
* @param flags settings for the text from 'txt_flag_t' enum
* @return length of a char_num long text
*/
-lv_coord_t lv_txt_get_width(const char * txt, uint16_t length, const lv_font_t * font, lv_coord_t letter_space,
- lv_txt_flag_t flag);
+lv_coord_t _lv_txt_get_width(const char * txt, uint32_t length, const lv_font_t * font, lv_coord_t letter_space,
+ lv_txt_flag_t flag);
/**
- * Check next character in a string and decide if te character is part of the command or not
+ * Check next character in a string and decide if the character is part of the command or not
* @param state pointer to a txt_cmd_state_t variable which stores the current state of command
* processing
* @param c the current character
* @return true: the character is part of a command and should not be written,
* false: the character should be written
*/
-bool lv_txt_is_cmd(lv_txt_cmd_state_t * state, uint32_t c);
+bool _lv_txt_is_cmd(lv_txt_cmd_state_t * state, uint32_t c);
/**
* Insert a string into an other
@@ -119,7 +117,7 @@ bool lv_txt_is_cmd(lv_txt_cmd_state_t * state, uint32_t c);
* @param pos position to insert (0: before the original text, 1: after the first char etc.)
* @param ins_txt text to insert
*/
-void lv_txt_ins(char * txt_buf, uint32_t pos, const char * ins_txt);
+void _lv_txt_ins(char * txt_buf, uint32_t pos, const char * ins_txt);
/**
* Delete a part of a string
@@ -128,10 +126,17 @@ void lv_txt_ins(char * txt_buf, uint32_t pos, const char * ins_txt);
* char etc.)
* @param len number of characters to delete
*/
-void lv_txt_cut(char * txt, uint32_t pos, uint32_t len);
+void _lv_txt_cut(char * txt, uint32_t pos, uint32_t len);
+
+/**
+ * return a new formatted text. Memory will be allocated to store the text.
+ * @param fmt `printf`-like format
+ * @return pointer to the allocated text string.
+ */
+char * _lv_txt_set_text_vfmt(const char * fmt, va_list ap);
/***************************************************************
- * GLOBAL FUNCTION POINTERS FOR CAHRACTER ENCODING INTERFACE
+ * GLOBAL FUNCTION POINTERS FOR CHARACTER ENCODING INTERFACE
***************************************************************/
/**
@@ -139,21 +144,21 @@ void lv_txt_cut(char * txt, uint32_t pos, uint32_t len);
* @param str pointer to a character in a string
* @return length of the encoded character (1,2,3 ...). O in invalid
*/
-extern uint8_t (*lv_txt_encoded_size)(const char *);
+extern uint8_t (*_lv_txt_encoded_size)(const char *);
/**
* Convert an Unicode letter to encoded
* @param letter_uni an Unicode letter
* @return Encoded character in Little Endian to be compatible with C chars (e.g. 'Á', 'Ü')
*/
-extern uint32_t (*lv_txt_unicode_to_encoded)(uint32_t);
+extern uint32_t (*_lv_txt_unicode_to_encoded)(uint32_t);
/**
* Convert a wide character, e.g. 'Á' little endian to be compatible with the encoded format.
* @param c a wide character
* @return `c` in the encoded format
*/
-extern uint32_t (*lv_txt_encoded_conv_wc)(uint32_t c);
+extern uint32_t (*_lv_txt_encoded_conv_wc)(uint32_t c);
/**
* Decode the next encoded character from a string.
@@ -163,7 +168,7 @@ extern uint32_t (*lv_txt_encoded_conv_wc)(uint32_t c);
* NULL to use txt[0] as index
* @return the decoded Unicode character or 0 on invalid data code
*/
-extern uint32_t (*lv_txt_encoded_next)(const char *, uint32_t *);
+extern uint32_t (*_lv_txt_encoded_next)(const char *, uint32_t *);
/**
* Get the previous encoded character form a string.
@@ -172,7 +177,7 @@ extern uint32_t (*lv_txt_encoded_next)(const char *, uint32_t *);
* encoded char in 'txt'.
* @return the decoded Unicode character or 0 on invalid data
*/
-extern uint32_t (*lv_txt_encoded_prev)(const char *, uint32_t *);
+extern uint32_t (*_lv_txt_encoded_prev)(const char *, uint32_t *);
/**
* Convert a letter index (in an the encoded text) to byte index.
@@ -181,7 +186,7 @@ extern uint32_t (*lv_txt_encoded_prev)(const char *, uint32_t *);
* @param enc_id letter index
* @return byte index of the 'enc_id'th letter
*/
-extern uint32_t (*lv_txt_encoded_get_byte_id)(const char *, uint32_t);
+extern uint32_t (*_lv_txt_encoded_get_byte_id)(const char *, uint32_t);
/**
* Convert a byte index (in an encoded text) to character index.
@@ -190,7 +195,7 @@ extern uint32_t (*lv_txt_encoded_get_byte_id)(const char *, uint32_t);
* @param byte_id byte index
* @return character index of the letter at 'byte_id'th position
*/
-extern uint32_t (*lv_txt_encoded_get_char_id)(const char *, uint32_t);
+extern uint32_t (*_lv_txt_encoded_get_char_id)(const char *, uint32_t);
/**
* Get the number of characters (and NOT bytes) in a string.
@@ -198,7 +203,7 @@ extern uint32_t (*lv_txt_encoded_get_char_id)(const char *, uint32_t);
* @param txt a '\0' terminated char string
* @return number of characters
*/
-extern uint32_t (*lv_txt_get_encoded_length)(const char *);
+extern uint32_t (*_lv_txt_get_encoded_length)(const char *);
/**********************
* MACROS
diff --git a/src/libs/lvgl/src/lv_misc/lv_txt_ap.c b/src/libs/lvgl/src/lv_misc/lv_txt_ap.c
new file mode 100644
index 00000000..fd99a59b
--- /dev/null
+++ b/src/libs/lvgl/src/lv_misc/lv_txt_ap.c
@@ -0,0 +1,273 @@
+/**
+ * @file lv_txt_ap.c
+ *
+ */
+
+/*********************
+ * INCLUDES
+ *********************/
+#include <stddef.h>
+#include "lv_bidi.h"
+#include "lv_txt.h"
+#include "lv_txt_ap.h"
+#include "../lv_draw/lv_draw.h"
+
+/*********************
+ * DEFINES
+ *********************/
+
+/**********************
+ * TYPEDEFS
+ **********************/
+
+/**********************
+ * STATIC PROTOTYPES
+ **********************/
+#if LV_USE_ARABIC_PERSIAN_CHARS == 1
+static uint32_t lv_ap_get_char_index(uint16_t c);
+static uint32_t lv_txt_lam_alef(uint32_t ch_curr, uint32_t ch_next);
+
+/**********************
+ * STATIC VARIABLES
+ **********************/
+
+const ap_chars_map_t ap_chars_map[] = {
+ /* {Key Offset, End, Beginning, Middle, Isolated, {conjunction}} */
+ {1, 0xFE84, -1, 0, -1, {1, 0}}, // أ
+ {2, 0xFE86, -1, 0, -1, {1, 0}}, // ؤ
+ {3, 0xFE88, -1, 0, -1, {1, 0}}, // ﺇ
+ {4, 0xFE8A, 1, 2, -1, {1, 0}}, // ئ
+ {5, 0xFE8E, -1, 0, -1, {1, 0}}, // آ
+ {6, 0xFE90, 1, 2, -1, {1, 1}}, // ب
+ {92, 0xFB57, 1, 2, -1, {1, 1}}, // پ
+ {8, 0xFE96, 1, 2, -1, {1, 1}}, // ت
+ {9, 0xFE9A, 1, 2, -1, {1, 1}}, // ث
+ {10, 0xFE9E, 1, 2, -1, {1, 1}}, // ج
+ {100, 0xFB7B, 1, 2, -1, {1, 1}}, // چ
+ {11, 0xFEA2, 1, 2, -1, {1, 1}}, // ح
+ {12, 0xFEA6, 1, 2, -1, {1, 1}}, // خ
+ {13, 0xFEAA, -1, 0, -1, {1, 0}}, // د
+ {14, 0xFEAC, -1, 0, -1, {1, 0}}, // ذ
+ {15, 0xFEAE, -1, 0, -1, {1, 0}}, // ر
+ {16, 0xFEB0, -1, 0, -1, {1, 0}}, // ز
+ {118, 0xFB8B, -1, 0, -1, {1, 0}}, // ژ
+ {17, 0xFEB2, 1, 2, -1, {1, 1}}, // س
+ {18, 0xFEB6, 1, 2, -1, {1, 1}}, // ش
+ {19, 0xFEBA, 1, 2, -1, {1, 1}}, // ص
+ {20, 0xFEBE, 1, 2, -1, {1, 1}}, // ض
+ {21, 0xFEC2, 1, 2, -1, {1, 1}}, // ط
+ {22, 0xFEC6, 1, 2, -1, {1, 1}}, // ظ
+ {23, 0xFECA, 1, 2, -1, {1, 1}}, // ع
+ {24, 0xFECE, 1, 2, -1, {1, 1}}, // غ
+ {30, 0x0640, 0, 0, 0, {1, 1}}, // - (mad, hyphen)
+ {31, 0xFED2, 1, 2, -1, {1, 1}}, // ف
+ {32, 0xFED6, 1, 2, -1, {1, 1}}, // ق
+ {135, 0xFB8F, 1, 2, -1, {1, 1}}, // ک
+ {33, 0xFEDA, 1, 2, -1, {1, 1}}, // ﻙ
+ {141, 0xFB93, 1, 2, -1, {1, 1}}, // گ
+ {34, 0xFEDE, 1, 2, -1, {1, 1}}, // ل
+ {35, 0xFEE2, 1, 2, -1, {1, 1}}, // م
+ {36, 0xFEE6, 1, 2, -1, {1, 1}}, // ن
+ {38, 0xFEEE, -1, 0, -1, {1, 0}}, // و
+ {37, 0xFEEA, 1, 2, -1, {1, 1}}, // ه
+ {39, 0xFEF0, 0, 0, -1, {1, 0}}, // ى
+ {40, 0xFEF2, 1, 2, -1, {1, 1}}, // ي
+ {170, 0xFBFD, 1, 2, -1, {1, 1}}, // ی
+ {7, 0xFE94, 1, 2, -1, {1, 0}}, // ة
+ {206, 0x06F0, 1, 2, -1, {0, 0}}, // ۰
+ {207, 0x06F1, 0, 0, 0, {0, 0}}, // ۱
+ {208, 0x06F2, 0, 0, 0, {0, 0}}, // ۲
+ {209, 0x06F3, 0, 0, 0, {0, 0}}, // ۳
+ {210, 0x06F4, 0, 0, 0, {0, 0}}, // ۴
+ {211, 0x06F5, 0, 0, 0, {0, 0}}, // ۵
+ {212, 0x06F6, 0, 0, 0, {0, 0}}, // ۶
+ {213, 0x06F7, 0, 0, 0, {0, 0}}, // ۷
+ {214, 0x06F8, 0, 0, 0, {0, 0}}, // ۸
+ {215, 0x06F9, 0, 0, 0, {0, 0}}, // ۹
+ LV_AP_END_CHARS_LIST
+};
+/**********************
+* MACROS
+**********************/
+
+/**********************
+* GLOBAL FUNCTIONS
+**********************/
+uint32_t _lv_txt_ap_calc_bytes_cnt(const char * txt)
+{
+ uint32_t txt_length = 0;
+ uint32_t chars_cnt = 0;
+ uint32_t current_ap_idx = 0;
+ uint32_t i, j;
+ uint32_t ch_enc;
+
+ txt_length = _lv_txt_get_encoded_length(txt);
+
+ i = 0;
+ j = 0;
+ while(i < txt_length) {
+ ch_enc = _lv_txt_encoded_next(txt, &j);
+ current_ap_idx = lv_ap_get_char_index(ch_enc);
+
+ if(current_ap_idx != LV_UNDEF_ARABIC_PERSIAN_CHARS)
+ ch_enc = ap_chars_map[current_ap_idx].char_end_form;
+
+ if(ch_enc < 0x80)
+ chars_cnt++;
+ else if(ch_enc < 0x0800)
+ chars_cnt += 2;
+ else if(ch_enc < 0x010000)
+ chars_cnt += 3;
+ else
+ chars_cnt += 4;
+
+ i++;
+ }
+
+ return chars_cnt + 1;
+}
+
+void _lv_txt_ap_proc(const char * txt, char * txt_out)
+{
+ uint32_t txt_length = 0;
+ uint32_t index_current, idx_next, idx_previous, i, j;
+ uint32_t * ch_enc;
+ uint32_t * ch_fin;
+ char * txt_out_temp;
+
+ txt_length = _lv_txt_get_encoded_length(txt);
+
+ ch_enc = (uint32_t *)lv_mem_alloc(sizeof(uint32_t) * (txt_length + 1));
+ ch_fin = (uint32_t *)lv_mem_alloc(sizeof(uint32_t) * (txt_length + 1));
+
+ i = 0;
+ j = 0;
+ while(j < txt_length)
+ ch_enc[j++] = _lv_txt_encoded_next(txt, &i);
+
+ ch_enc[j] = 0;
+
+ i = 0;
+ j = 0;
+ idx_previous = LV_UNDEF_ARABIC_PERSIAN_CHARS;
+ while(i < txt_length) {
+ index_current = lv_ap_get_char_index(ch_enc[i]);
+ idx_next = lv_ap_get_char_index(ch_enc[i + 1]);
+
+ if(index_current == LV_UNDEF_ARABIC_PERSIAN_CHARS) {
+ ch_fin[j] = ch_enc[i];
+ j++;
+ i++;
+ idx_previous = LV_UNDEF_ARABIC_PERSIAN_CHARS;
+ continue;
+ }
+
+ uint8_t conjunction_to_previuse = (i == 0 ||
+ idx_previous == LV_UNDEF_ARABIC_PERSIAN_CHARS) ? 0 : ap_chars_map[idx_previous].ap_chars_conjunction.conj_to_next;
+ uint8_t conjunction_to_next = ((i == txt_length - 1) ||
+ idx_next == LV_UNDEF_ARABIC_PERSIAN_CHARS) ? 0 : ap_chars_map[idx_next].ap_chars_conjunction.conj_to_previous;
+
+ uint32_t lam_alef = lv_txt_lam_alef(index_current, idx_next);
+ if(lam_alef) {
+ if(conjunction_to_previuse) {
+ lam_alef ++;
+ }
+ ch_fin[j] = lam_alef;
+ idx_previous = LV_UNDEF_ARABIC_PERSIAN_CHARS;
+ i += 2;
+ j++;
+ continue;
+ }
+
+ if(conjunction_to_previuse && conjunction_to_next)
+ ch_fin[j] = ap_chars_map[index_current].char_end_form + ap_chars_map[index_current].char_middle_form_offset;
+ else if(!conjunction_to_previuse && conjunction_to_next)
+ ch_fin[j] = ap_chars_map[index_current].char_end_form + ap_chars_map[index_current].char_begining_form_offset;
+ else if(conjunction_to_previuse && !conjunction_to_next)
+ ch_fin[j] = ap_chars_map[index_current].char_end_form;
+ else
+ ch_fin[j] = ap_chars_map[index_current].char_end_form + ap_chars_map[index_current].char_isolated_form_offset;
+ idx_previous = index_current;
+ i++;
+ j++;
+ }
+ ch_fin[j] = 0;
+ for(i = 0; i < txt_length; i++)
+ ch_enc[i] = 0;
+ for(i = 0; i < j; i++)
+ ch_enc[i] = ch_fin[i];
+ lv_mem_free(ch_fin);
+
+ txt_out_temp = txt_out;
+ i = 0;
+
+ while(i < txt_length) {
+ if(ch_enc[i] < 0x80) {
+ *(txt_out_temp++) = ch_enc[i] & 0xFF;
+ }
+ else if(ch_enc[i] < 0x0800) {
+ *(txt_out_temp++) = ((ch_enc[i] >> 6) & 0x1F) | 0xC0;
+ *(txt_out_temp++) = ((ch_enc[i] >> 0) & 0x3F) | 0x80;
+ }
+ else if(ch_enc[i] < 0x010000) {
+ *(txt_out_temp++) = ((ch_enc[i] >> 12) & 0x0F) | 0xE0;
+ *(txt_out_temp++) = ((ch_enc[i] >> 6) & 0x3F) | 0x80;
+ *(txt_out_temp++) = ((ch_enc[i] >> 0) & 0x3F) | 0x80;
+ }
+ else if(ch_enc[i] < 0x110000) {
+ *(txt_out_temp++) = ((ch_enc[i] >> 18) & 0x07) | 0xF0;
+ *(txt_out_temp++) = ((ch_enc[i] >> 12) & 0x3F) | 0x80;
+ *(txt_out_temp++) = ((ch_enc[i] >> 6) & 0x3F) | 0x80;
+ *(txt_out_temp++) = ((ch_enc[i] >> 0) & 0x3F) | 0x80;
+ }
+
+ i++;
+ }
+ *(txt_out_temp) = '\0';
+ lv_mem_free(ch_enc);
+}
+/**********************
+* STATIC FUNCTIONS
+**********************/
+
+static uint32_t lv_ap_get_char_index(uint16_t c)
+{
+ for(uint8_t i = 0; ap_chars_map[i].char_end_form; i++) {
+ if(c == (ap_chars_map[i].char_offset + LV_AP_ALPHABET_BASE_CODE))
+ return i;
+ else if(c == ap_chars_map[i].char_end_form //is it an End form
+ || c == (ap_chars_map[i].char_end_form + ap_chars_map[i].char_begining_form_offset) //is it a Beginning form
+ || c == (ap_chars_map[i].char_end_form + ap_chars_map[i].char_middle_form_offset) //is it a middle form
+ || c == (ap_chars_map[i].char_end_form + ap_chars_map[i].char_isolated_form_offset)) { //is it an isolated form
+ return i;
+ }
+ }
+ return LV_UNDEF_ARABIC_PERSIAN_CHARS;
+}
+
+static uint32_t lv_txt_lam_alef(uint32_t ch_curr, uint32_t ch_next)
+{
+ uint32_t ch_code = 0;
+ if(ap_chars_map[ch_curr].char_offset != 34) {
+ return 0;
+ }
+ if(ch_next == LV_UNDEF_ARABIC_PERSIAN_CHARS) {
+ return 0;
+ }
+ ch_code = ap_chars_map[ch_next].char_offset + LV_AP_ALPHABET_BASE_CODE;
+ if(ch_code == 0x0622) {
+ return 0xFEF5; // (lam-alef) mad
+ }
+ if(ch_code == 0x0623) {
+ return 0xFEF7; // (lam-alef) top hamza
+ }
+ if(ch_code == 0x0625) {
+ return 0xFEF9; // (lam-alef) bot hamza
+ }
+ if(ch_code == 0x0627) {
+ return 0xFEFB; // (lam-alef) alef
+ }
+ return 0;
+}
+
+#endif
diff --git a/src/libs/lvgl/src/lv_misc/lv_txt_ap.h b/src/libs/lvgl/src/lv_misc/lv_txt_ap.h
new file mode 100644
index 00000000..d5742013
--- /dev/null
+++ b/src/libs/lvgl/src/lv_misc/lv_txt_ap.h
@@ -0,0 +1,60 @@
+/**
+ * @file lv_txt_ap.h
+ *
+ */
+
+#ifndef LV_TXT_AP_H
+#define LV_TXT_AP_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*********************
+ * INCLUDES
+ *********************/
+#include <stddef.h>
+#include "lv_txt.h"
+#include "../lv_draw/lv_draw.h"
+
+#if LV_USE_ARABIC_PERSIAN_CHARS == 1
+
+/*********************
+ * DEFINES
+ *********************/
+
+#define LV_UNDEF_ARABIC_PERSIAN_CHARS (UINT32_MAX)
+#define LV_AP_ALPHABET_BASE_CODE 0x0622
+#define LV_AP_END_CHARS_LIST {0,0,0,0,0,{0,0}}
+/**********************
+ * TYPEDEFS
+ **********************/
+typedef struct {
+ uint8_t char_offset;
+ uint16_t char_end_form;
+ int8_t char_begining_form_offset;
+ int8_t char_middle_form_offset;
+ int8_t char_isolated_form_offset;
+ struct {
+ uint8_t conj_to_previous;
+ uint8_t conj_to_next;
+ } ap_chars_conjunction;
+} ap_chars_map_t;
+
+/**********************
+ * GLOBAL PROTOTYPES
+ **********************/
+uint32_t _lv_txt_ap_calc_bytes_cnt(const char * txt);
+void _lv_txt_ap_proc(const char * txt, char * txt_out);
+
+/**********************
+ * MACROS
+ **********************/
+
+#endif // LV_USE_ARABIC_PERSIAN_CHARS
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+#endif /*LV_TXT_AP_H*/
diff --git a/src/libs/lvgl/src/lv_misc/lv_types.h b/src/libs/lvgl/src/lv_misc/lv_types.h
index 2c28bca1..95663e3c 100644
--- a/src/libs/lvgl/src/lv_misc/lv_types.h
+++ b/src/libs/lvgl/src/lv_misc/lv_types.h
@@ -17,16 +17,22 @@ extern "C" {
/*********************
* DEFINES
*********************/
-// Check windows
-#ifdef _WIN64
-#define LV_ARCH_64
+
+#if defined(__cplusplus) || __STDC_VERSION__ >= 199901L // If c99 or newer, use stdint.h to determine arch size
+#include <stdint.h>
#endif
-// Check GCC
-#ifdef __GNUC__
-#if defined(__x86_64__) || defined(__ppc64__)
+// If __UINTPTR_MAX__ or UINTPTR_MAX are available, use them to determine arch size
+#if defined(__UINTPTR_MAX__) && __UINTPTR_MAX__ > 0xFFFFFFFF
#define LV_ARCH_64
-#endif
+
+#elif defined(UINTPTR_MAX) && UINTPTR_MAX > 0xFFFFFFFF
+#define LV_ARCH_64
+
+// Otherwise use compiler-dependent means to determine arch size
+#elif defined(_WIN64) || defined(__x86_64__) || defined(__ppc64__) || defined (__aarch64__)
+#define LV_ARCH_64
+
#endif
/**********************
@@ -34,7 +40,7 @@ extern "C" {
**********************/
/**
- * LittlevGL error codes.
+ * LVGL error codes.
*/
enum {
LV_RES_INV = 0, /*Typically indicates that the object is deleted (become invalid) in the action
@@ -43,12 +49,21 @@ enum {
};
typedef uint8_t lv_res_t;
+#if defined(__cplusplus) || __STDC_VERSION__ >= 199901L
+// If c99 or newer, use the definition of uintptr_t directly from <stdint.h>
+typedef uintptr_t lv_uintptr_t;
+
+#else
+
+// Otherwise, use the arch size determination
#ifdef LV_ARCH_64
typedef uint64_t lv_uintptr_t;
#else
typedef uint32_t lv_uintptr_t;
#endif
+#endif
+
/**********************
* GLOBAL PROTOTYPES
**********************/
@@ -57,6 +72,14 @@ typedef uint32_t lv_uintptr_t;
* MACROS
**********************/
+#define LV_UNUSED(x) ((void) x)
+
+#define _LV_CONCAT(x, y) x ## y
+#define LV_CONCAT(x, y) _LV_CONCAT(x, y)
+
+#define _LV_CONCAT3(x, y, z) x ## y ## z
+#define LV_CONCAT3(x, y, z) _LV_CONCAT3(x, y, z)
+
#ifdef __cplusplus
} /* extern "C" */
#endif
diff --git a/src/libs/lvgl/src/lv_misc/lv_utils.c b/src/libs/lvgl/src/lv_misc/lv_utils.c
index 3f189560..ea2a17b0 100644
--- a/src/libs/lvgl/src/lv_misc/lv_utils.c
+++ b/src/libs/lvgl/src/lv_misc/lv_utils.c
@@ -10,6 +10,8 @@
#include "lv_utils.h"
#include "lv_math.h"
+#include "lv_printf.h"
+#include "lv_txt.h"
/*********************
* DEFINES
@@ -41,7 +43,7 @@
* @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)
+char * _lv_utils_num_to_str(int32_t num, char * buf)
{
if(num == 0) {
buf[0] = '0';
@@ -89,8 +91,8 @@ char * lv_utils_num_to_str(int32_t num, char * buf)
*
* @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))
+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;
@@ -100,10 +102,12 @@ void * lv_utils_bsearch(const void * key, const void * base, uint32_t n, uint32_
if((c = (*cmp)(key, middle)) > 0) {
n = (n / 2) - ((n & 1) == 0);
base = (middle += size);
- } else if(c < 0) {
+ }
+ else if(c < 0) {
n /= 2;
middle = base;
- } else {
+ }
+ else {
return (char *)middle;
}
}
diff --git a/src/libs/lvgl/src/lv_misc/lv_utils.h b/src/libs/lvgl/src/lv_misc/lv_utils.h
index 6eed7950..4d74029f 100644
--- a/src/libs/lvgl/src/lv_misc/lv_utils.h
+++ b/src/libs/lvgl/src/lv_misc/lv_utils.h
@@ -33,7 +33,7 @@ extern "C" {
* @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);
+char * _lv_utils_num_to_str(int32_t num, char * buf);
/** Searches base[0] to base[n - 1] for an item that matches *key.
*
@@ -52,8 +52,8 @@ char * lv_utils_num_to_str(int32_t num, char * buf);
*
* @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));
+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