Merge branch 'dev-6.1'
This commit is contained in:
@@ -188,8 +188,8 @@ Styles can be assigned to the objects to changed their appearance. A style descr
|
||||
|
||||
You can create a new style like this:
|
||||
```c
|
||||
static lv_style_t style1; /*Declare a new style. Should be `static`*/
|
||||
lv_style_copy(&style1, &lv_style_plain); /*Copy a buil-in style*/
|
||||
static lv_style_t style1; /*Declare a new style. Should be `static`*/
|
||||
lv_style_copy(&style1, &lv_style_plain); /*Copy a built-in style*/
|
||||
style1.body.main_color = LV_COLOR_RED; /*Main color*/
|
||||
style1.body.grad_color = lv_color_hex(0xffd83c) /*Gradient color (orange)*/
|
||||
style1.body.radius = 3;
|
||||
|
||||
@@ -43,6 +43,9 @@
|
||||
/*Images pixels with this color will not be drawn (with chroma keying)*/
|
||||
#define LV_COLOR_TRANSP LV_COLOR_LIME /*LV_COLOR_LIME: pure green*/
|
||||
|
||||
/* Enable chroma keying for indexed images. */
|
||||
#define LV_INDEXED_CHROMA 1
|
||||
|
||||
/* Enable anti-aliasing (lines, and radiuses will be smoothed) */
|
||||
#define LV_ANTIALIAS 1
|
||||
|
||||
@@ -193,6 +196,14 @@ typedef void * lv_img_decoder_user_data_t;
|
||||
* font's bitmaps */
|
||||
#define LV_ATTRIBUTE_LARGE_CONST
|
||||
|
||||
/* Export integer constant to binding.
|
||||
* This macro is used with constants in the form of LV_<CONST> that
|
||||
* should also appear on lvgl binding API such as Micropython
|
||||
*
|
||||
* The default value just prevents a GCC warning.
|
||||
*/
|
||||
#define LV_EXPORT_CONST_INT(int_value) struct _silence_gcc_warning
|
||||
|
||||
/*===================
|
||||
* HAL settings
|
||||
*==================*/
|
||||
@@ -229,6 +240,42 @@ typedef void * lv_indev_drv_user_data_t; /*Type of user data in the i
|
||||
# define LV_LOG_PRINTF 0
|
||||
#endif /*LV_USE_LOG*/
|
||||
|
||||
/*=================
|
||||
* Debug settings
|
||||
*================*/
|
||||
|
||||
/* If Debug is enabled LittelvGL validates the parameters of the functions.
|
||||
* If an invalid parameter is found an error log message is printed and
|
||||
* the MCU halts at the error. (`LV_USE_LOG` should be enabled)
|
||||
* If you are debugging the MCU you can pause
|
||||
* the debugger to see exactly where the issue is.
|
||||
*
|
||||
* The behavior of asserts can be overwritten by redefining them here.
|
||||
* E.g. #define LV_ASSERT_MEM(p) <my_assert_code>
|
||||
*/
|
||||
#define LV_USE_DEBUG 1
|
||||
#if LV_USE_DEBUG
|
||||
|
||||
/*Check if the parameter is NULL. (Quite fast) */
|
||||
#define LV_USE_ASSERT_NULL 1
|
||||
|
||||
/*Checks is the memory is successfully allocated or no. (Quite fast)*/
|
||||
#define LV_USE_ASSERT_MEM 1
|
||||
|
||||
/* Check the strings.
|
||||
* Search for NULL, very long strings, invalid characters, and unnatural repetitions. (Slow)
|
||||
* If disabled `LV_USE_ASSERT_NULL` will be performed instead (if it's enabled) */
|
||||
#define LV_USE_ASSERT_STR 0
|
||||
|
||||
/* Check NULL, the object's type and existence (e.g. not deleted). (Quite slow)
|
||||
* If disabled `LV_USE_ASSERT_NULL` will be performed instead (if it's enabled) */
|
||||
#define LV_USE_ASSERT_OBJ 0
|
||||
|
||||
/*Check if the styles are properly initialized. (Fast)*/
|
||||
#define LV_USE_ASSERT_STYLE 1
|
||||
|
||||
#endif /*LV_USE_DEBUG*/
|
||||
|
||||
/*================
|
||||
* THEME USAGE
|
||||
*================*/
|
||||
@@ -260,6 +307,10 @@ typedef void * lv_indev_drv_user_data_t; /*Type of user data in the i
|
||||
#define LV_FONT_ROBOTO_22 0
|
||||
#define LV_FONT_ROBOTO_28 0
|
||||
|
||||
/* Demonstrate special features */
|
||||
#define LV_FONT_ROBOTO_12_SUBPX 1
|
||||
#define LV_FONT_ROBOTO_28_COMPRESSED 1 /*bpp = 3*/
|
||||
|
||||
/*Pixel perfect monospace font
|
||||
* http://pelulamu.net/unscii/ */
|
||||
#define LV_FONT_UNSCII_8 0
|
||||
@@ -280,6 +331,12 @@ typedef void * lv_indev_drv_user_data_t; /*Type of user data in the i
|
||||
* but with > 10,000 characters if you see issues probably you need to enable it.*/
|
||||
#define LV_FONT_FMT_TXT_LARGE 0
|
||||
|
||||
/* Set the pixel order of the display.
|
||||
* Important only if "subpx fonts" are used.
|
||||
* With "normal" font it doesn't matter.
|
||||
*/
|
||||
#define LV_FONT_SUBPX_BGR 0
|
||||
|
||||
/*Declare the type of the user data of fonts (can be e.g. `void *`, `int`, `struct`)*/
|
||||
typedef void * lv_font_user_data_t;
|
||||
|
||||
@@ -297,6 +354,42 @@ typedef void * lv_font_user_data_t;
|
||||
/*Can break (wrap) texts on these chars*/
|
||||
#define LV_TXT_BREAK_CHARS " ,.;:-_"
|
||||
|
||||
/* If a word is at least this long, will break wherever "prettiest"
|
||||
* To disable, set to a value <= 0 */
|
||||
#define LV_TXT_LINE_BREAK_LONG_LEN 12
|
||||
|
||||
/* Minimum number of characters in a long word to put on a line before a break.
|
||||
* Depends on LV_TXT_LINE_BREAK_LONG_LEN. */
|
||||
#define LV_TXT_LINE_BREAK_LONG_PRE_MIN_LEN 3
|
||||
|
||||
/* Minimum number of characters in a long word to put on a line after a break.
|
||||
* Depends on LV_TXT_LINE_BREAK_LONG_LEN. */
|
||||
#define LV_TXT_LINE_BREAK_LONG_POST_MIN_LEN 3
|
||||
|
||||
/* The control character to use for signalling text recoloring. */
|
||||
#define LV_TXT_COLOR_CMD "#"
|
||||
|
||||
/* Support bidirectional texts.
|
||||
* Allows mixing Left-to-Right and Right-to-Left texts.
|
||||
* The direction will be processed according to the Unicode Bidirectioanl Algorithm:
|
||||
* https://www.w3.org/International/articles/inline-bidi-markup/uba-basics*/
|
||||
#define LV_USE_BIDI 0
|
||||
#if LV_USE_BIDI
|
||||
/* Set the default direction. Supported values:
|
||||
* `LV_BIDI_DIR_LTR` Left-to-Right
|
||||
* `LV_BIDI_DIR_RTL` Right-to-Left
|
||||
* `LV_BIDI_DIR_AUTO` detect texts base direction */
|
||||
#define LV_BIDI_BASE_DIR_DEF LV_BIDI_DIR_AUTO
|
||||
#endif
|
||||
|
||||
/*Change the built in (v)snprintf functions*/
|
||||
#define LV_SPRINTF_CUSTOM 0
|
||||
#if LV_SPRINTF_CUSTOM
|
||||
# define LV_SPRINTF_INCLUDE <stdio.h>
|
||||
# define lv_snprintf snprintf
|
||||
# define lv_vsnprintf vsnprintf
|
||||
#endif /*LV_SPRINTF_CUSTOM*/
|
||||
|
||||
/*===================
|
||||
* LV_OBJ SETTINGS
|
||||
*==================*/
|
||||
@@ -355,6 +448,9 @@ typedef void * lv_obj_user_data_t;
|
||||
/*Container (dependencies: -*/
|
||||
#define LV_USE_CONT 1
|
||||
|
||||
/*Color picker (dependencies: -*/
|
||||
#define LV_USE_CPICKER 1
|
||||
|
||||
/*Drop down list (dependencies: lv_page, lv_label, lv_symbol_def.h)*/
|
||||
#define LV_USE_DDLIST 1
|
||||
#if LV_USE_DDLIST != 0
|
||||
|
||||
4
lvgl.h
4
lvgl.h
@@ -29,11 +29,14 @@ extern "C" {
|
||||
|
||||
#include "src/lv_core/lv_refr.h"
|
||||
#include "src/lv_core/lv_disp.h"
|
||||
#include "src/lv_core/lv_debug.h"
|
||||
|
||||
#include "src/lv_themes/lv_theme.h"
|
||||
|
||||
#include "src/lv_font/lv_font.h"
|
||||
#include "src/lv_font/lv_font_fmt_txt.h"
|
||||
#include "src/lv_misc/lv_bidi.h"
|
||||
#include "src/lv_misc/lv_printf.h"
|
||||
|
||||
#include "src/lv_objx/lv_btn.h"
|
||||
#include "src/lv_objx/lv_imgbtn.h"
|
||||
@@ -46,6 +49,7 @@ extern "C" {
|
||||
#include "src/lv_objx/lv_chart.h"
|
||||
#include "src/lv_objx/lv_table.h"
|
||||
#include "src/lv_objx/lv_cb.h"
|
||||
#include "src/lv_objx/lv_cpicker.h"
|
||||
#include "src/lv_objx/lv_bar.h"
|
||||
#include "src/lv_objx/lv_slider.h"
|
||||
#include "src/lv_objx/lv_led.h"
|
||||
|
||||
Binary file not shown.
BIN
scripts/built_in_font/FontAwesome5-Solid+Brands+Regular.woff
Normal file
BIN
scripts/built_in_font/FontAwesome5-Solid+Brands+Regular.woff
Normal file
Binary file not shown.
@@ -40,8 +40,8 @@ else:
|
||||
compr = ""
|
||||
|
||||
#Built in symbols
|
||||
syms = "61441,61448,61451,61452,61453,61457,61459,61460,61461,61465,61468,61473,61478,61479,61480,61502,61504,61512,61515,61516,61517,61521,61522,61523,61524,61543,61544,61553,61556,61559,61560,61561,61563,61587,61589,61636,61637,61639,61671,61683,61724,61732,61787,61931,62016,62017,62018,62019,62020,62099"
|
||||
syms = "61441,61448,61451,61452,61452,61453,61457,61459,61461,61465,61468,61473,61478,61479,61480,61502,61512,61515,61516,61517,61521,61522,61523,61524,61543,61544,61550,61552,61553,61556,61559,61560,61561,61563,61587,61589,61636,61637,61639,61671,61674,61683,61724,61732,61787,61931,62016,62017,62018,62019,62020,62087,62099,62212,62189,62810,63426,63650"
|
||||
|
||||
#Run the command
|
||||
cmd = "lv_font_conv {} --bpp {} --size {} --font ./Roboto-Regular.woff -r {} --font FontAwesome.ttf -r {} --format lvgl -o {} --force-fast-kern-format".format(compr, args.bpp, args.size, args.range[0], syms, args.output)
|
||||
cmd = "lv_font_conv {} --bpp {} --size {} --font Roboto-Regular.woff -r {} --font FontAwesome5-Solid+Brands+Regular.woff -r {} --format lvgl -o {} --force-fast-kern-format".format(compr, args.bpp, args.size, args.range[0], syms, args.output)
|
||||
os.system(cmd)
|
||||
|
||||
6
scripts/lv_conf_checker.py
Normal file → Executable file
6
scripts/lv_conf_checker.py
Normal file → Executable file
@@ -1,3 +1,5 @@
|
||||
#!/usr/bin/env python3.6
|
||||
|
||||
'''
|
||||
Generates a checker file for lv_conf.h from lv_conf_templ.h define all the not defined values
|
||||
'''
|
||||
@@ -34,9 +36,11 @@ for i in fin.read().splitlines():
|
||||
if '/*--END OF LV_CONF_H--*/' in i: break
|
||||
|
||||
r = re.search(r'^ *# *define ([^\s]+).*$', i)
|
||||
|
||||
if r:
|
||||
line = re.sub('\(.*?\)', '', r[1], 1) #remove parentheses from macros
|
||||
fout.write(
|
||||
f'#ifndef {r[1]}\n'
|
||||
f'#ifndef {line}\n'
|
||||
f'{i}\n'
|
||||
'#endif\n'
|
||||
)
|
||||
|
||||
@@ -50,6 +50,11 @@
|
||||
#define LV_COLOR_TRANSP LV_COLOR_LIME /*LV_COLOR_LIME: pure green*/
|
||||
#endif
|
||||
|
||||
/* Enable chroma keying for indexed images. */
|
||||
#ifndef LV_INDEXED_CHROMA
|
||||
#define LV_INDEXED_CHROMA 1
|
||||
#endif
|
||||
|
||||
/* Enable anti-aliasing (lines, and radiuses will be smoothed) */
|
||||
#ifndef LV_ANTIALIAS
|
||||
#define LV_ANTIALIAS 1
|
||||
@@ -261,6 +266,16 @@
|
||||
#define LV_ATTRIBUTE_LARGE_CONST
|
||||
#endif
|
||||
|
||||
/* Export integer constant to binding.
|
||||
* This macro is used with constants in the form of LV_<CONST> that
|
||||
* should also appear on lvgl binding API such as Micropython
|
||||
*
|
||||
* The default value just prevents a GCC warning.
|
||||
*/
|
||||
#ifndef LV_EXPORT_CONST_INT
|
||||
#define LV_EXPORT_CONST_INT(int_value) struct _silence_gcc_warning
|
||||
#endif
|
||||
|
||||
/*===================
|
||||
* HAL settings
|
||||
*==================*/
|
||||
@@ -301,12 +316,60 @@
|
||||
#endif
|
||||
|
||||
/* 1: Print the log with 'printf';
|
||||
* 0: user need to register a callback with `lv_log_register_print`*/
|
||||
* 0: user need to register a callback with `lv_log_register_print_cb`*/
|
||||
#ifndef LV_LOG_PRINTF
|
||||
# define LV_LOG_PRINTF 0
|
||||
#endif
|
||||
#endif /*LV_USE_LOG*/
|
||||
|
||||
/*=================
|
||||
* Debug settings
|
||||
*================*/
|
||||
|
||||
/* If Debug is enabled LittelvGL validates the parameters of the functions.
|
||||
* If an invalid parameter is found an error log message is printed and
|
||||
* the MCU halts at the error. (`LV_USE_LOG` should be enabled)
|
||||
* If you are debugging the MCU you can pause
|
||||
* the debugger to see exactly where the issue is.
|
||||
*
|
||||
* The behavior of asserts can be overwritten by redefining them here.
|
||||
* E.g. #define LV_ASSERT_MEM(p) <my_assert_code>
|
||||
*/
|
||||
#ifndef LV_USE_DEBUG
|
||||
#define LV_USE_DEBUG 1
|
||||
#endif
|
||||
#if LV_USE_DEBUG
|
||||
|
||||
/*Check if the parameter is NULL. (Quite fast) */
|
||||
#ifndef LV_USE_ASSERT_NULL
|
||||
#define LV_USE_ASSERT_NULL 1
|
||||
#endif
|
||||
|
||||
/*Checks is the memory is successfully allocated or no. (Quite fast)*/
|
||||
#ifndef LV_USE_ASSERT_MEM
|
||||
#define LV_USE_ASSERT_MEM 1
|
||||
#endif
|
||||
|
||||
/* Check the strings.
|
||||
* Search for NULL, very long strings, invalid characters, and unnatural repetitions. (Slow)
|
||||
* If disabled `LV_USE_ASSERT_NULL` will be performed instead (if it's enabled) */
|
||||
#ifndef LV_USE_ASSERT_STR
|
||||
#define LV_USE_ASSERT_STR 0
|
||||
#endif
|
||||
|
||||
/* Check NULL, the object's type and existence (e.g. not deleted). (Quite slow)
|
||||
* If disabled `LV_USE_ASSERT_NULL` will be performed instead (if it's enabled) */
|
||||
#ifndef LV_USE_ASSERT_OBJ
|
||||
#define LV_USE_ASSERT_OBJ 0
|
||||
#endif
|
||||
|
||||
/*Check if the styles are properly initialized. (Fast)*/
|
||||
#ifndef LV_USE_ASSERT_STYLE
|
||||
#define LV_USE_ASSERT_STYLE 1
|
||||
#endif
|
||||
|
||||
#endif /*LV_USE_DEBUG*/
|
||||
|
||||
/*================
|
||||
* THEME USAGE
|
||||
*================*/
|
||||
@@ -364,6 +427,14 @@
|
||||
#define LV_FONT_ROBOTO_28 0
|
||||
#endif
|
||||
|
||||
/* Demonstrate special features */
|
||||
#ifndef LV_FONT_ROBOTO_12_SUBPX
|
||||
#define LV_FONT_ROBOTO_12_SUBPX 1
|
||||
#endif
|
||||
#ifndef LV_FONT_ROBOTO_28_COMPRESSED
|
||||
#define LV_FONT_ROBOTO_28_COMPRESSED 1 /*bpp = 3*/
|
||||
#endif
|
||||
|
||||
/*Pixel perfect monospace font
|
||||
* http://pelulamu.net/unscii/ */
|
||||
#ifndef LV_FONT_UNSCII_8
|
||||
@@ -392,6 +463,14 @@
|
||||
#define LV_FONT_FMT_TXT_LARGE 0
|
||||
#endif
|
||||
|
||||
/* Set the pixel order of the display.
|
||||
* Important only if "subpx fonts" are used.
|
||||
* With "normal" font it doesn't matter.
|
||||
*/
|
||||
#ifndef LV_FONT_SUBPX_BGR
|
||||
#define LV_FONT_SUBPX_BGR 0
|
||||
#endif
|
||||
|
||||
/*Declare the type of the user data of fonts (can be e.g. `void *`, `int`, `struct`)*/
|
||||
|
||||
/*=================
|
||||
@@ -412,6 +491,62 @@
|
||||
#define LV_TXT_BREAK_CHARS " ,.;:-_"
|
||||
#endif
|
||||
|
||||
/* If a word is at least this long, will break wherever "prettiest"
|
||||
* To disable, set to a value <= 0 */
|
||||
#ifndef LV_TXT_LINE_BREAK_LONG_LEN
|
||||
#define LV_TXT_LINE_BREAK_LONG_LEN 12
|
||||
#endif
|
||||
|
||||
/* Minimum number of characters in a long word to put on a line before a break.
|
||||
* Depends on LV_TXT_LINE_BREAK_LONG_LEN. */
|
||||
#ifndef LV_TXT_LINE_BREAK_LONG_PRE_MIN_LEN
|
||||
#define LV_TXT_LINE_BREAK_LONG_PRE_MIN_LEN 3
|
||||
#endif
|
||||
|
||||
/* Minimum number of characters in a long word to put on a line after a break.
|
||||
* Depends on LV_TXT_LINE_BREAK_LONG_LEN. */
|
||||
#ifndef LV_TXT_LINE_BREAK_LONG_POST_MIN_LEN
|
||||
#define LV_TXT_LINE_BREAK_LONG_POST_MIN_LEN 3
|
||||
#endif
|
||||
|
||||
/* The control character to use for signalling text recoloring. */
|
||||
#ifndef LV_TXT_COLOR_CMD
|
||||
#define LV_TXT_COLOR_CMD "#"
|
||||
#endif
|
||||
|
||||
/* Support bidirectional texts.
|
||||
* Allows mixing Left-to-Right and Right-to-Left texts.
|
||||
* The direction will be processed according to the Unicode Bidirectioanl Algorithm:
|
||||
* https://www.w3.org/International/articles/inline-bidi-markup/uba-basics*/
|
||||
#ifndef LV_USE_BIDI
|
||||
#define LV_USE_BIDI 0
|
||||
#endif
|
||||
#if LV_USE_BIDI
|
||||
/* Set the default direction. Supported values:
|
||||
* `LV_BIDI_DIR_LTR` Left-to-Right
|
||||
* `LV_BIDI_DIR_RTL` Right-to-Left
|
||||
* `LV_BIDI_DIR_AUTO` detect texts base direction */
|
||||
#ifndef LV_BIDI_BASE_DIR_DEF
|
||||
#define LV_BIDI_BASE_DIR_DEF LV_BIDI_DIR_AUTO
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/*Change the built in (v)snprintf functions*/
|
||||
#ifndef LV_SPRINTF_CUSTOM
|
||||
#define LV_SPRINTF_CUSTOM 0
|
||||
#endif
|
||||
#if LV_SPRINTF_CUSTOM
|
||||
#ifndef LV_SPRINTF_INCLUDE
|
||||
# define LV_SPRINTF_INCLUDE <stdio.h>
|
||||
#endif
|
||||
#ifndef lv_snprintf
|
||||
# define lv_snprintf snprintf
|
||||
#endif
|
||||
#ifndef lv_vsnprintf
|
||||
# define lv_vsnprintf vsnprintf
|
||||
#endif
|
||||
#endif /*LV_SPRINTF_CUSTOM*/
|
||||
|
||||
/*===================
|
||||
* LV_OBJ SETTINGS
|
||||
*==================*/
|
||||
@@ -495,6 +630,11 @@
|
||||
#define LV_USE_CONT 1
|
||||
#endif
|
||||
|
||||
/*Color picker (dependencies: -*/
|
||||
#ifndef LV_USE_CPICKER
|
||||
#define LV_USE_CPICKER 1
|
||||
#endif
|
||||
|
||||
/*Drop down list (dependencies: lv_page, lv_label, lv_symbol_def.h)*/
|
||||
#ifndef LV_USE_DDLIST
|
||||
#define LV_USE_DDLIST 1
|
||||
|
||||
@@ -4,6 +4,7 @@ CSRCS += lv_disp.c
|
||||
CSRCS += lv_obj.c
|
||||
CSRCS += lv_refr.c
|
||||
CSRCS += lv_style.c
|
||||
CSRCS += lv_debug.c
|
||||
|
||||
DEPPATH += --dep-path $(LVGL_DIR)/lvgl/src/lv_core
|
||||
VPATH += :$(LVGL_DIR)/lvgl/src/lv_core
|
||||
|
||||
193
src/lv_core/lv_debug.c
Normal file
193
src/lv_core/lv_debug.c
Normal file
@@ -0,0 +1,193 @@
|
||||
/**
|
||||
* @file lv_debug.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "lv_obj.h"
|
||||
#include "lv_debug.h"
|
||||
|
||||
#if LV_USE_DEBUG
|
||||
|
||||
/*********************
|
||||
* 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 bool obj_valid_child(const lv_obj_t * parent, const lv_obj_t * obj_to_find);
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
bool lv_debug_check_null(const void * p)
|
||||
{
|
||||
if(p) return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool lv_debug_check_obj_type(const lv_obj_t * obj, const char * obj_type)
|
||||
{
|
||||
if(obj_type[0] == '\0') return true;
|
||||
|
||||
lv_obj_type_t types;
|
||||
lv_obj_get_type((lv_obj_t *)obj, &types);
|
||||
|
||||
uint8_t i;
|
||||
for(i = 0; i < LV_MAX_ANCESTOR_NUM; i++) {
|
||||
if(strcmp(types.type[i], obj_type) == 0) return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool lv_debug_check_obj_valid(const lv_obj_t * obj)
|
||||
{
|
||||
lv_disp_t * disp = lv_disp_get_next(NULL);
|
||||
while(disp) {
|
||||
lv_obj_t * scr;
|
||||
LV_LL_READ(disp->scr_ll, scr) {
|
||||
|
||||
if(scr == obj) return true;
|
||||
bool found = obj_valid_child(scr, obj);
|
||||
if(found) return true;
|
||||
}
|
||||
|
||||
disp = lv_disp_get_next(disp);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool lv_debug_check_style(const lv_style_t * style)
|
||||
{
|
||||
if(style == NULL) return true; /*NULL style is still valid*/
|
||||
|
||||
#if LV_USE_ASSERT_STYLE
|
||||
if(style->debug_sentinel != LV_STYLE_DEGUG_SENTINEL_VALUE) {
|
||||
LV_LOG_WARN("Invalid style (local variable or not initialized?)");
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
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; s[i] != '\0' && i < LV_DEBUG_STR_MAX_LENGTH; 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";
|
||||
|
||||
uint32_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*/
|
||||
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
|
||||
**********************/
|
||||
|
||||
static bool obj_valid_child(const lv_obj_t * parent, const lv_obj_t * obj_to_find)
|
||||
{
|
||||
/*Check all children of `parent`*/
|
||||
lv_obj_t * child;
|
||||
LV_LL_READ(parent->child_ll, child) {
|
||||
if(child == obj_to_find) return true;
|
||||
|
||||
/*Check the children*/
|
||||
bool found = obj_valid_child(child, obj_to_find);
|
||||
if(found) return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
#endif /*LV_USE_DEBUG*/
|
||||
|
||||
154
src/lv_core/lv_debug.h
Normal file
154
src/lv_core/lv_debug.h
Normal file
@@ -0,0 +1,154 @@
|
||||
/**
|
||||
* @file lv_debug.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LV_DEBUG_H
|
||||
#define LV_DEBUG_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "lv_obj.h"
|
||||
|
||||
#if LV_USE_DEBUG
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
bool lv_debug_check_null(const void * p);
|
||||
|
||||
bool lv_debug_check_obj_type(const lv_obj_t * obj, const char * obj_type);
|
||||
|
||||
bool lv_debug_check_obj_valid(const lv_obj_t * obj);
|
||||
|
||||
bool lv_debug_check_style(const lv_style_t * style);
|
||||
|
||||
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) \
|
||||
{ \
|
||||
if(!(expr)) { \
|
||||
LV_LOG_ERROR(__func__); \
|
||||
lv_debug_log_error(msg, (unsigned long int)value); \
|
||||
while(1); \
|
||||
} \
|
||||
}
|
||||
#endif
|
||||
|
||||
/*----------------
|
||||
* CHECKS
|
||||
*----------------*/
|
||||
|
||||
#ifndef LV_DEBUG_IS_NULL
|
||||
#define LV_DEBUG_IS_NULL(p) (lv_debug_check_null(p))
|
||||
#endif
|
||||
|
||||
#ifndef LV_DEBUG_IS_STR
|
||||
#define LV_DEBUG_IS_STR(str) (lv_debug_check_null(str) && \
|
||||
lv_debug_check_str(str))
|
||||
#endif
|
||||
|
||||
#ifndef LV_DEBUG_IS_OBJ
|
||||
#define LV_DEBUG_IS_OBJ(obj_p, obj_type) (lv_debug_check_null(obj_p) && \
|
||||
lv_debug_check_obj_valid(obj_p) && \
|
||||
lv_debug_check_obj_type(obj_p, obj_type))
|
||||
#endif
|
||||
|
||||
#ifndef LV_DEBUG_IS_STYLE
|
||||
#define LV_DEBUG_IS_STYLE(style_p) (lv_debug_check_style(style_p))
|
||||
#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) true
|
||||
#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) true
|
||||
#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) true
|
||||
# endif
|
||||
#endif
|
||||
|
||||
|
||||
#if LV_USE_ASSERT_OBJ
|
||||
# ifndef LV_ASSERT_OBJ
|
||||
# define LV_ASSERT_OBJ(obj_p, obj_type) LV_DEBUG_ASSERT(LV_DEBUG_IS_OBJ(obj_p, obj_type), "Invalid object", obj_p);
|
||||
# endif
|
||||
#else /* LV_USE_ASSERT_OBJ == 0 */
|
||||
# if LV_USE_ASSERT_NULL /*Use at least LV_ASSERT_NULL if enabled*/
|
||||
# define LV_ASSERT_OBJ(obj_p, obj_type) LV_ASSERT_NULL(obj_p)
|
||||
# else
|
||||
# define LV_ASSERT_OBJ(obj_p, obj_type) true
|
||||
# endif
|
||||
#endif
|
||||
|
||||
|
||||
#if LV_USE_ASSERT_STYLE
|
||||
# ifndef LV_ASSERT_STYLE
|
||||
# define LV_ASSERT_STYLE(style_p) LV_DEBUG_ASSERT(LV_DEBUG_IS_STYLE(style_p), "Invalid style", style_p);
|
||||
# endif
|
||||
#else
|
||||
# define LV_ASSERT_STYLE(style) true
|
||||
#endif
|
||||
|
||||
#else /* LV_USE_DEBUG == 0 */
|
||||
|
||||
#define LV_DEBUG_ASSERT(expr, msg, value) do{}while(0)
|
||||
|
||||
#define LV_ASSERT_NULL(p) true
|
||||
#define LV_ASSERT_MEM(p) true
|
||||
#define LV_ASSERT_STR(p) true
|
||||
#define LV_ASSERT_OBJ(obj, obj_type) true
|
||||
#define LV_ASSERT_STYLE(p) true
|
||||
|
||||
#endif /* LV_USE_DEBUG */
|
||||
/*clang-format on*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /*LV_DEBUG_H*/
|
||||
@@ -8,8 +8,9 @@
|
||||
*********************/
|
||||
#include "lv_group.h"
|
||||
#if LV_USE_GROUP != 0
|
||||
#include "../lv_themes/lv_theme.h"
|
||||
#include <stddef.h>
|
||||
#include "../lv_core/lv_debug.h"
|
||||
#include "../lv_themes/lv_theme.h"
|
||||
#include "../lv_misc/lv_gc.h"
|
||||
|
||||
#if defined(LV_GC_INCLUDE)
|
||||
@@ -62,7 +63,7 @@ void lv_group_init(void)
|
||||
lv_group_t * lv_group_create(void)
|
||||
{
|
||||
lv_group_t * group = lv_ll_ins_head(&LV_GC_ROOT(_lv_group_ll));
|
||||
lv_mem_assert(group);
|
||||
LV_ASSERT_MEM(group);
|
||||
if(group == NULL) return NULL;
|
||||
lv_ll_init(&group->obj_ll, sizeof(lv_obj_t *));
|
||||
|
||||
@@ -138,7 +139,7 @@ void lv_group_add_obj(lv_group_t * group, lv_obj_t * obj)
|
||||
|
||||
obj->group_p = group;
|
||||
lv_obj_t ** next = lv_ll_ins_tail(&group->obj_ll);
|
||||
lv_mem_assert(next);
|
||||
LV_ASSERT_MEM(next);
|
||||
if(next == NULL) return;
|
||||
*next = obj;
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -28,6 +28,7 @@ extern "C" {
|
||||
#include "../lv_misc/lv_ll.h"
|
||||
#include "../lv_misc/lv_color.h"
|
||||
#include "../lv_misc/lv_log.h"
|
||||
#include "../lv_misc/lv_bidi.h"
|
||||
#include "../lv_hal/lv_hal.h"
|
||||
|
||||
/*********************
|
||||
@@ -111,7 +112,8 @@ enum {
|
||||
LV_SIGNAL_CHILD_CHG, /**< Child was removed/added */
|
||||
LV_SIGNAL_CORD_CHG, /**< Object coordinates/size have changed */
|
||||
LV_SIGNAL_PARENT_SIZE_CHG, /**< Parent's size has changed */
|
||||
LV_SIGNAL_STYLE_CHG, /**< Object's style has changed */
|
||||
LV_SIGNAL_STYLE_CHG, /**< Object's style has changed */
|
||||
LV_SIGNAL_BASE_DIR_CHG, /**<The base dir has changed*/
|
||||
LV_SIGNAL_REFR_EXT_DRAW_PAD, /**< Object's extra padding has changed */
|
||||
LV_SIGNAL_GET_TYPE, /**< LittlevGL needs to retrieve the object's type */
|
||||
|
||||
@@ -123,7 +125,8 @@ enum {
|
||||
LV_SIGNAL_LONG_PRESS, /**< Object has been pressed for at least `LV_INDEV_LONG_PRESS_TIME`. Not called if dragged.*/
|
||||
LV_SIGNAL_LONG_PRESS_REP, /**< Called after `LV_INDEV_LONG_PRESS_TIME` in every `LV_INDEV_LONG_PRESS_REP_TIME` ms. Not called if dragged.*/
|
||||
LV_SIGNAL_DRAG_BEGIN,
|
||||
LV_SIGNAL_DRAG_END,
|
||||
LV_SIGNAL_DRAG_END,
|
||||
|
||||
/*Group related*/
|
||||
LV_SIGNAL_FOCUS,
|
||||
LV_SIGNAL_DEFOCUS,
|
||||
@@ -218,7 +221,8 @@ typedef struct _lv_obj_t
|
||||
uint8_t opa_scale_en : 1; /**< 1: opa_scale is set*/
|
||||
uint8_t parent_event : 1; /**< 1: Send the object's events to the parent too. */
|
||||
lv_drag_dir_t drag_dir : 2; /**< Which directions the object can be dragged in */
|
||||
uint8_t reserved : 6; /**< Reserved for future use*/
|
||||
lv_bidi_dir_t base_dir : 2; /**< Base direction of texts related to this object */
|
||||
uint8_t reserved : 3; /**< Reserved for future use*/
|
||||
uint8_t protect; /**< Automatically happening actions can be prevented. 'OR'ed values from
|
||||
`lv_protect_t`*/
|
||||
lv_opa_t opa_scale; /**< Scale down the opacity by this factor. Effects all children as well*/
|
||||
@@ -510,6 +514,7 @@ void lv_obj_set_drag_parent(lv_obj_t * obj, bool en);
|
||||
*/
|
||||
void lv_obj_set_parent_event(lv_obj_t * obj, bool en);
|
||||
|
||||
void lv_obj_set_base_dir(lv_obj_t * obj, lv_bidi_dir_t dir);
|
||||
/**
|
||||
* Set the opa scale enable parameter (required to set opa_scale with `lv_obj_set_opa_scale()`)
|
||||
* @param obj pointer to an object
|
||||
@@ -849,6 +854,9 @@ bool lv_obj_get_drag_parent(const lv_obj_t * obj);
|
||||
*/
|
||||
bool lv_obj_get_parent_event(const lv_obj_t * obj);
|
||||
|
||||
|
||||
lv_bidi_dir_t lv_obj_get_base_dir(const lv_obj_t * obj);
|
||||
|
||||
/**
|
||||
* Get the opa scale enable parameter
|
||||
* @param obj pointer to an object
|
||||
@@ -960,6 +968,18 @@ bool lv_obj_is_focused(const lv_obj_t * obj);
|
||||
|
||||
#endif
|
||||
|
||||
/*-------------------
|
||||
* OTHER FUNCTIONS
|
||||
*------------------*/
|
||||
|
||||
/**
|
||||
* Used in the signal callback to handle `LV_SIGNAL_GET_TYPE` signal
|
||||
* @param buf pointer to `lv_obj_type_t`. (`param` i nteh signal callback)
|
||||
* @param name name of the object. E.g. "lv_btn". (Only teh pointer is saved)
|
||||
* @return LV_RES_OK
|
||||
*/
|
||||
lv_res_t lv_obj_handle_get_type_signal(lv_obj_type_t * buf, const char * name);
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
@@ -318,19 +318,19 @@ static void lv_refr_area(const lv_area_t * area_p)
|
||||
tmp.x2 = 0;
|
||||
tmp.y1 = 0;
|
||||
|
||||
lv_coord_t y_tmp = max_row - 1;
|
||||
lv_coord_t h_tmp = max_row;
|
||||
do {
|
||||
tmp.y2 = y_tmp;
|
||||
tmp.y2 = h_tmp - 1;
|
||||
disp_refr->driver.rounder_cb(&disp_refr->driver, &tmp);
|
||||
|
||||
/*If this height fits into `max_row` then fine*/
|
||||
if(lv_area_get_height(&tmp) <= max_row) break;
|
||||
|
||||
/*Decrement the height of the area until it fits into `max_row` after rounding*/
|
||||
y_tmp--;
|
||||
} while(y_tmp != 0);
|
||||
h_tmp--;
|
||||
} while(h_tmp > 0);
|
||||
|
||||
if(y_tmp == 0) {
|
||||
if(h_tmp <= 0) {
|
||||
LV_LOG_WARN("Can't set VDB height using the round function. (Wrong round_cb or to "
|
||||
"small VDB)");
|
||||
return;
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "lv_obj.h"
|
||||
#include "../lv_core/lv_debug.h"
|
||||
#include "../lv_misc/lv_mem.h"
|
||||
#include "../lv_misc/lv_anim.h"
|
||||
|
||||
@@ -106,6 +107,12 @@ void lv_style_init(void)
|
||||
lv_style_scr.line.width = 2;
|
||||
lv_style_scr.line.rounded = 0;
|
||||
|
||||
#if LV_USE_DEBUG
|
||||
#if LV_USE_ASSERT_STYLE
|
||||
lv_style_scr.debug_sentinel = LV_STYLE_DEGUG_SENTINEL_VALUE;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/*Plain style (by default near the same as the screen style)*/
|
||||
lv_style_copy(&lv_style_plain, &lv_style_scr);
|
||||
lv_style_plain.body.padding.left = LV_DPI / 20;
|
||||
@@ -287,7 +294,7 @@ void lv_style_anim_init(lv_anim_t * a)
|
||||
|
||||
lv_style_anim_dsc_t * dsc;
|
||||
dsc = lv_mem_alloc(sizeof(lv_style_anim_dsc_t));
|
||||
lv_mem_assert(dsc);
|
||||
LV_ASSERT_MEM(dsc);
|
||||
if(dsc == NULL) return;
|
||||
dsc->ready_cb = NULL;
|
||||
dsc->style_anim = NULL;
|
||||
|
||||
@@ -23,6 +23,9 @@ extern "C" {
|
||||
* DEFINES
|
||||
*********************/
|
||||
#define LV_RADIUS_CIRCLE (LV_COORD_MAX) /**< A very big radius to always draw as circle*/
|
||||
#define LV_STYLE_DEGUG_SENTINEL_VALUE 0x12345678
|
||||
|
||||
LV_EXPORT_CONST_INT(LV_RADIUS_CIRCLE);
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
@@ -119,6 +122,13 @@ typedef struct
|
||||
lv_opa_t opa;
|
||||
uint8_t rounded : 1; /**< 1: rounded line endings*/
|
||||
} line;
|
||||
|
||||
#if LV_USE_DEBUG
|
||||
#if LV_USE_ASSERT_STYLE
|
||||
uint32_t debug_sentinel; /**<Should `LV_STYLE_DEGUG_SENTINEL_VALUE` to indicate that the style is valid*/
|
||||
#endif
|
||||
#endif
|
||||
|
||||
} lv_style_t;
|
||||
|
||||
#if LV_USE_ANIMATION
|
||||
@@ -186,7 +196,7 @@ void lv_style_anim_set_styles(lv_anim_t * a, lv_style_t * to_anim, const lv_styl
|
||||
* @param duration duration of the animation in milliseconds
|
||||
* @param delay delay before the animation in milliseconds
|
||||
*/
|
||||
static inline void lv_style_anim_set_time(lv_anim_t * a, uint16_t duration, uint16_t delay)
|
||||
static inline void lv_style_anim_set_time(lv_anim_t * a, uint16_t duration, int16_t delay)
|
||||
{
|
||||
lv_anim_set_time(a, duration, delay);
|
||||
}
|
||||
@@ -272,6 +282,18 @@ extern lv_style_t lv_style_btn_ina;
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Create and initialize a `static` style
|
||||
* Example:
|
||||
* LV_STYLE_CREATE(my_style, &lv_style_plain);
|
||||
* is equivalent to
|
||||
* static lv_style_t my_style;
|
||||
* lv_style_copy(my_style, &lv_style_plain);
|
||||
*
|
||||
* If the style to copy is `NULL` `lv_style_plain` will be used.
|
||||
*/
|
||||
#define LV_STYLE_CREATE(name, copy_p) static lv_style_t name; lv_style_copy(&name, copy_p == NULL ? &lv_style_plain : copy_p);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
#include <stdio.h>
|
||||
#include <stdbool.h>
|
||||
#include "lv_draw.h"
|
||||
#include "../lv_core/lv_debug.h"
|
||||
#include "../lv_misc/lv_math.h"
|
||||
#include "../lv_misc/lv_log.h"
|
||||
#include "../lv_misc/lv_math.h"
|
||||
@@ -60,12 +61,12 @@ void * lv_draw_get_buf(uint32_t size)
|
||||
|
||||
if(LV_GC_ROOT(_lv_draw_buf) == NULL) {
|
||||
LV_GC_ROOT(_lv_draw_buf) = lv_mem_alloc(size);
|
||||
lv_mem_assert(LV_GC_ROOT(_lv_draw_buf));
|
||||
LV_ASSERT_MEM(LV_GC_ROOT(_lv_draw_buf));
|
||||
return LV_GC_ROOT(_lv_draw_buf);
|
||||
}
|
||||
|
||||
LV_GC_ROOT(_lv_draw_buf) = lv_mem_realloc(LV_GC_ROOT(_lv_draw_buf), size);
|
||||
lv_mem_assert(LV_GC_ROOT(_lv_draw_buf));
|
||||
LV_ASSERT_MEM(LV_GC_ROOT(_lv_draw_buf));
|
||||
return LV_GC_ROOT(_lv_draw_buf);
|
||||
}
|
||||
|
||||
|
||||
@@ -20,7 +20,6 @@
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
static uint16_t fast_atan2(int x, int y);
|
||||
static void ver_line(lv_coord_t x, lv_coord_t y, const lv_area_t * mask, lv_coord_t len, lv_color_t color,
|
||||
lv_opa_t opa);
|
||||
static void hor_line(lv_coord_t x, lv_coord_t y, const lv_area_t * mask, lv_coord_t len, lv_color_t color,
|
||||
@@ -57,6 +56,11 @@ void lv_draw_arc(lv_coord_t center_x, lv_coord_t center_y, uint16_t radius, cons
|
||||
lv_coord_t thickness = style->line.width;
|
||||
if(thickness > radius) thickness = radius;
|
||||
|
||||
#if LV_ANTIALIAS
|
||||
thickness--;
|
||||
radius--;
|
||||
#endif
|
||||
|
||||
lv_coord_t r_out = radius;
|
||||
lv_coord_t r_in = r_out - thickness;
|
||||
int16_t deg_base;
|
||||
@@ -73,17 +77,26 @@ void lv_draw_arc(lv_coord_t center_x, lv_coord_t center_y, uint16_t radius, cons
|
||||
else
|
||||
deg_test = deg_test_inv;
|
||||
|
||||
int middle_r_out = r_out;
|
||||
#if !LV_ANTIALIAS
|
||||
thickness--;
|
||||
middle_r_out = r_out - 1;
|
||||
#endif
|
||||
if(deg_test(270, start_angle, end_angle))
|
||||
hor_line(center_x - r_out + 1, center_y, mask, thickness - 1, color, opa); /*Left Middle*/
|
||||
hor_line(center_x - middle_r_out, center_y, mask, thickness, color, opa); /*Left Middle*/
|
||||
if(deg_test(90, start_angle, end_angle))
|
||||
hor_line(center_x + r_in, center_y, mask, thickness - 1, color, opa); /*Right Middle*/
|
||||
hor_line(center_x + r_in, center_y, mask, thickness, color, opa); /*Right Middle*/
|
||||
if(deg_test(180, start_angle, end_angle))
|
||||
ver_line(center_x, center_y - r_out + 1, mask, thickness - 1, color, opa); /*Top Middle*/
|
||||
ver_line(center_x, center_y - middle_r_out, mask, thickness, color, opa); /*Top Middle*/
|
||||
if(deg_test(0, start_angle, end_angle))
|
||||
ver_line(center_x, center_y + r_in, mask, thickness - 1, color, opa); /*Bottom middle*/
|
||||
ver_line(center_x, center_y + r_in, mask, thickness, color, opa); /*Bottom middle*/
|
||||
|
||||
uint32_t r_out_sqr = r_out * r_out;
|
||||
uint32_t r_in_sqr = r_in * r_in;
|
||||
#if LV_ANTIALIAS
|
||||
uint32_t r_out_aa_sqr = (r_out + 1) * (r_out + 1);
|
||||
uint32_t r_in_aa_sqr = (r_in - 1) * (r_in - 1);
|
||||
#endif
|
||||
int16_t xi;
|
||||
int16_t yi;
|
||||
for(yi = -r_out; yi < 0; yi++) {
|
||||
@@ -95,12 +108,55 @@ void lv_draw_arc(lv_coord_t center_x, lv_coord_t center_y, uint16_t radius, cons
|
||||
x_end[1] = LV_COORD_MIN;
|
||||
x_end[2] = LV_COORD_MIN;
|
||||
x_end[3] = LV_COORD_MIN;
|
||||
int xe = 0;
|
||||
for(xi = -r_out; xi < 0; xi++) {
|
||||
|
||||
uint32_t r_act_sqr = xi * xi + yi * yi;
|
||||
#if LV_ANTIALIAS
|
||||
if(r_act_sqr > r_out_aa_sqr) {
|
||||
continue;
|
||||
}
|
||||
#else
|
||||
if(r_act_sqr > r_out_sqr) continue;
|
||||
#endif
|
||||
|
||||
deg_base = fast_atan2(xi, yi) - 180;
|
||||
deg_base = lv_atan2(xi, yi) - 180;
|
||||
|
||||
#if LV_ANTIALIAS
|
||||
int opa2 = -1;
|
||||
if(r_act_sqr > r_out_sqr) {
|
||||
opa2 = LV_OPA_100 * (r_out + 1) - lv_sqrt(LV_OPA_100 * LV_OPA_100 * r_act_sqr);
|
||||
if(opa2 < LV_OPA_0)
|
||||
opa2 = LV_OPA_0;
|
||||
else if(opa2 > LV_OPA_100)
|
||||
opa2 = LV_OPA_100;
|
||||
} else if(r_act_sqr < r_in_sqr) {
|
||||
if(xe == 0) xe = xi;
|
||||
opa2 = lv_sqrt(LV_OPA_100 * LV_OPA_100 * r_act_sqr) - LV_OPA_100 * (r_in - 1);
|
||||
if(opa2 < LV_OPA_0)
|
||||
opa2 = LV_OPA_0;
|
||||
else if(opa2 > LV_OPA_100)
|
||||
opa2 = LV_OPA_100;
|
||||
if(r_act_sqr < r_in_aa_sqr)
|
||||
break; /*No need to continue the iteration in x once we found the inner edge of the
|
||||
arc*/
|
||||
}
|
||||
if(opa2 != -1) {
|
||||
if(deg_test(180 + deg_base, start_angle, end_angle)) {
|
||||
lv_draw_px(center_x + xi, center_y + yi, mask, color, opa2);
|
||||
}
|
||||
if(deg_test(360 - deg_base, start_angle, end_angle)) {
|
||||
lv_draw_px(center_x + xi, center_y - yi, mask, color, opa2);
|
||||
}
|
||||
if(deg_test(180 - deg_base, start_angle, end_angle)) {
|
||||
lv_draw_px(center_x - xi, center_y + yi, mask, color, opa2);
|
||||
}
|
||||
if(deg_test(deg_base, start_angle, end_angle)) {
|
||||
lv_draw_px(center_x - xi, center_y - yi, mask, color, opa2);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
|
||||
deg = 180 + deg_base;
|
||||
if(deg_test(deg, start_angle, end_angle)) {
|
||||
@@ -130,111 +186,35 @@ void lv_draw_arc(lv_coord_t center_x, lv_coord_t center_y, uint16_t radius, cons
|
||||
x_end[3] = xi - 1;
|
||||
}
|
||||
|
||||
if(r_act_sqr < r_in_sqr)
|
||||
if(r_act_sqr < r_in_sqr) {
|
||||
xe = xi;
|
||||
break; /*No need to continue the iteration in x once we found the inner edge of the
|
||||
arc*/
|
||||
}
|
||||
}
|
||||
|
||||
if(x_start[0] != LV_COORD_MIN) {
|
||||
if(x_end[0] == LV_COORD_MIN) x_end[0] = xi - 1;
|
||||
if(x_end[0] == LV_COORD_MIN) x_end[0] = xe - 1;
|
||||
hor_line(center_x + x_start[0], center_y + yi, mask, x_end[0] - x_start[0], color, opa);
|
||||
}
|
||||
|
||||
if(x_start[1] != LV_COORD_MIN) {
|
||||
if(x_end[1] == LV_COORD_MIN) x_end[1] = xi - 1;
|
||||
if(x_end[1] == LV_COORD_MIN) x_end[1] = xe - 1;
|
||||
hor_line(center_x + x_start[1], center_y - yi, mask, x_end[1] - x_start[1], color, opa);
|
||||
}
|
||||
|
||||
if(x_start[2] != LV_COORD_MIN) {
|
||||
if(x_end[2] == LV_COORD_MIN) x_end[2] = xi - 1;
|
||||
if(x_end[2] == LV_COORD_MIN) x_end[2] = xe - 1;
|
||||
hor_line(center_x - x_end[2], center_y + yi, mask, LV_MATH_ABS(x_end[2] - x_start[2]), color, opa);
|
||||
}
|
||||
|
||||
if(x_start[3] != LV_COORD_MIN) {
|
||||
if(x_end[3] == LV_COORD_MIN) x_end[3] = xi - 1;
|
||||
if(x_end[3] == LV_COORD_MIN) x_end[3] = xe - 1;
|
||||
hor_line(center_x - x_end[3], center_y - yi, mask, LV_MATH_ABS(x_end[3] - x_start[3]), color, opa);
|
||||
}
|
||||
|
||||
#if LV_ANTIALIAS
|
||||
/*TODO*/
|
||||
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
static uint16_t fast_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
|
||||
// within +/- 1 degree of the accurate value without needing
|
||||
// large slow trig functions like ArcTan() or ArcCos().
|
||||
// NOTE! at least one of the X or Y values must be non-zero!
|
||||
// This is the full version, for all 4 quadrants and will generate
|
||||
// the angle in integer degrees from 0-360.
|
||||
// Any values of X and Y are usable including negative values provided
|
||||
// they are between -1456 and 1456 so the 16bit multiply does not overflow.
|
||||
|
||||
unsigned char negflag;
|
||||
unsigned char tempdegree;
|
||||
unsigned char comp;
|
||||
unsigned int degree; /*this will hold the result*/
|
||||
unsigned int ux;
|
||||
unsigned int uy;
|
||||
|
||||
/*Save the sign flags then remove signs and get XY as unsigned ints*/
|
||||
negflag = 0;
|
||||
if(x < 0) {
|
||||
negflag += 0x01; /*x flag bit*/
|
||||
x = (0 - x); /*is now +*/
|
||||
}
|
||||
ux = x; /*copy to unsigned var before multiply*/
|
||||
if(y < 0) {
|
||||
negflag += 0x02; /*y flag bit*/
|
||||
y = (0 - y); /*is now +*/
|
||||
}
|
||||
uy = y; /*copy to unsigned var before multiply*/
|
||||
|
||||
/*1. Calc the scaled "degrees"*/
|
||||
if(ux > uy) {
|
||||
degree = (uy * 45) / ux; /*degree result will be 0-45 range*/
|
||||
negflag += 0x10; /*octant flag bit*/
|
||||
} else {
|
||||
degree = (ux * 45) / uy; /*degree result will be 0-45 range*/
|
||||
}
|
||||
|
||||
/*2. Compensate for the 4 degree error curve*/
|
||||
comp = 0;
|
||||
tempdegree = degree; /*use an unsigned char for speed!*/
|
||||
if(tempdegree > 22) { /*if top half of range*/
|
||||
if(tempdegree <= 44) comp++;
|
||||
if(tempdegree <= 41) comp++;
|
||||
if(tempdegree <= 37) comp++;
|
||||
if(tempdegree <= 32) comp++; /*max is 4 degrees compensated*/
|
||||
} else { /*else is lower half of range*/
|
||||
if(tempdegree >= 2) comp++;
|
||||
if(tempdegree >= 6) comp++;
|
||||
if(tempdegree >= 10) comp++;
|
||||
if(tempdegree >= 15) comp++; /*max is 4 degrees compensated*/
|
||||
}
|
||||
degree += comp; /*degree is now accurate to +/- 1 degree!*/
|
||||
|
||||
/*Invert degree if it was X>Y octant, makes 0-45 into 90-45*/
|
||||
if(negflag & 0x10) degree = (90 - degree);
|
||||
|
||||
/*3. Degree is now 0-90 range for this quadrant,*/
|
||||
/*need to invert it for whichever quadrant it was in*/
|
||||
if(negflag & 0x02) { /*if -Y*/
|
||||
if(negflag & 0x01) /*if -Y -X*/
|
||||
degree = (180 + degree);
|
||||
else /*else is -Y +X*/
|
||||
degree = (180 - degree);
|
||||
} else { /*else is +Y*/
|
||||
if(negflag & 0x01) /*if +Y -X*/
|
||||
degree = (360 - degree);
|
||||
}
|
||||
return degree;
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
@@ -252,6 +252,7 @@ void lv_draw_letter(const lv_point_t * pos_p, const lv_area_t * mask_p, const lv
|
||||
bool g_ret = lv_font_get_glyph_dsc(font_p, &g, letter, '\0');
|
||||
if(g_ret == false) return;
|
||||
|
||||
|
||||
lv_coord_t pos_x = pos_p->x + g.ofs_x;
|
||||
lv_coord_t pos_y = pos_p->y + (font_p->line_height - font_p->base_line) - g.box_h - g.ofs_y;
|
||||
|
||||
@@ -259,6 +260,9 @@ void lv_draw_letter(const lv_point_t * pos_p, const lv_area_t * mask_p, const lv
|
||||
uint8_t bitmask_init;
|
||||
uint8_t bitmask;
|
||||
|
||||
/*bpp = 3 should be converted to bpp = 4 in lv_font_get_glyph_bitmap */
|
||||
if(g.bpp == 3) g.bpp = 4;
|
||||
|
||||
switch(g.bpp) {
|
||||
case 1:
|
||||
bpp_opa_table = bpp1_opa_table;
|
||||
@@ -297,17 +301,32 @@ void lv_draw_letter(const lv_point_t * pos_p, const lv_area_t * mask_p, const lv
|
||||
if(g.box_w & 0x7) width_byte_scr++;
|
||||
uint16_t width_bit = g.box_w * g.bpp; /*Letter width in bits*/
|
||||
|
||||
bool subpx = font_p->subpx == LV_FONT_SUBPX_NONE ? false : true;
|
||||
|
||||
/* Calculate the col/row start/end on the map*/
|
||||
lv_coord_t col_start = pos_x >= mask_p->x1 ? 0 : mask_p->x1 - pos_x;
|
||||
lv_coord_t col_end = pos_x + g.box_w <= mask_p->x2 ? g.box_w : mask_p->x2 - pos_x + 1;
|
||||
lv_coord_t row_start = pos_y >= mask_p->y1 ? 0 : mask_p->y1 - pos_y;
|
||||
lv_coord_t row_end = pos_y + g.box_h <= mask_p->y2 ? g.box_h : mask_p->y2 - pos_y + 1;
|
||||
lv_coord_t col_start;
|
||||
lv_coord_t col_end;
|
||||
lv_coord_t row_start;
|
||||
lv_coord_t row_end;
|
||||
|
||||
if(subpx == false) {
|
||||
col_start = pos_x >= mask_p->x1 ? 0 : mask_p->x1 - pos_x;
|
||||
col_end = pos_x + g.box_w <= mask_p->x2 ? g.box_w : mask_p->x2 - pos_x + 1;
|
||||
row_start = pos_y >= mask_p->y1 ? 0 : mask_p->y1 - pos_y;
|
||||
row_end = pos_y + g.box_h <= mask_p->y2 ? g.box_h : mask_p->y2 - pos_y + 1;
|
||||
} else {
|
||||
col_start = pos_x >= mask_p->x1 ? 0 : (mask_p->x1 - pos_x) * 3;
|
||||
col_end = pos_x + g.box_w / 3 <= mask_p->x2 ? g.box_w : (mask_p->x2 - pos_x + 1) * 3;
|
||||
row_start = pos_y >= mask_p->y1 ? 0 : mask_p->y1 - pos_y;
|
||||
row_end = pos_y + g.box_h <= mask_p->y2 ? g.box_h : mask_p->y2 - pos_y + 1;
|
||||
}
|
||||
|
||||
/*Set a pointer on VDB to the first pixel of the letter*/
|
||||
vdb_buf_tmp += ((pos_y - vdb->area.y1) * vdb_width) + pos_x - vdb->area.x1;
|
||||
|
||||
/*If the letter is partially out of mask the move there on VDB*/
|
||||
vdb_buf_tmp += (row_start * vdb_width) + col_start;
|
||||
if(subpx) vdb_buf_tmp += (row_start * vdb_width) + col_start / 3;
|
||||
else vdb_buf_tmp += (row_start * vdb_width) + col_start;
|
||||
|
||||
/*Move on the map too*/
|
||||
uint32_t bit_ofs = (row_start * width_bit) + (col_start * g.bpp);
|
||||
@@ -323,37 +342,90 @@ void lv_draw_letter(const lv_point_t * pos_p, const lv_area_t * mask_p, const lv
|
||||
scr_transp = disp->driver.screen_transp;
|
||||
#endif
|
||||
|
||||
uint8_t font_rgb[3];
|
||||
uint8_t txt_rgb[3] = {LV_COLOR_GET_R(color), LV_COLOR_GET_G(color), LV_COLOR_GET_B(color)};
|
||||
|
||||
for(row = row_start; row < row_end; row++) {
|
||||
bitmask = bitmask_init >> col_bit;
|
||||
uint8_t sub_px_cnt = 0;
|
||||
for(col = col_start; col < col_end; col++) {
|
||||
letter_px = (*map_p & bitmask) >> (8 - col_bit - g.bpp);
|
||||
if(letter_px != 0) {
|
||||
if(opa == LV_OPA_COVER) {
|
||||
px_opa = g.bpp == 8 ? letter_px : bpp_opa_table[letter_px];
|
||||
} else {
|
||||
px_opa = g.bpp == 8 ? (uint16_t)((uint16_t)letter_px * opa) >> 8
|
||||
: (uint16_t)((uint16_t)bpp_opa_table[letter_px] * opa) >> 8;
|
||||
}
|
||||
|
||||
if(disp->driver.set_px_cb) {
|
||||
disp->driver.set_px_cb(&disp->driver, (uint8_t *)vdb->buf_act, vdb_width,
|
||||
(col + pos_x) - vdb->area.x1, (row + pos_y) - vdb->area.y1, color, px_opa);
|
||||
} else if(vdb_buf_tmp->full != color.full) {
|
||||
if(px_opa > LV_OPA_MAX)
|
||||
*vdb_buf_tmp = color;
|
||||
else if(px_opa > LV_OPA_MIN) {
|
||||
if(scr_transp == false) {
|
||||
*vdb_buf_tmp = lv_color_mix(color, *vdb_buf_tmp, px_opa);
|
||||
} else {
|
||||
/*subpx == 0*/
|
||||
if(subpx == false) {
|
||||
if(letter_px != 0) {
|
||||
if(opa == LV_OPA_COVER) {
|
||||
px_opa = g.bpp == 8 ? letter_px : bpp_opa_table[letter_px];
|
||||
} else {
|
||||
px_opa = g.bpp == 8 ? (uint16_t)((uint16_t)letter_px * opa) >> 8
|
||||
: (uint16_t)((uint16_t)bpp_opa_table[letter_px] * opa) >> 8;
|
||||
}
|
||||
|
||||
if(disp->driver.set_px_cb) {
|
||||
disp->driver.set_px_cb(&disp->driver, (uint8_t *)vdb->buf_act, vdb_width,
|
||||
(col + pos_x) - vdb->area.x1, (row + pos_y) - vdb->area.y1, color, px_opa);
|
||||
} else if(vdb_buf_tmp->full != color.full) {
|
||||
if(px_opa > LV_OPA_MAX) {
|
||||
*vdb_buf_tmp = color;
|
||||
} else if(px_opa > LV_OPA_MIN) {
|
||||
if(scr_transp == false) {
|
||||
*vdb_buf_tmp = lv_color_mix(color, *vdb_buf_tmp, px_opa);
|
||||
} else {
|
||||
#if LV_COLOR_DEPTH == 32 && LV_COLOR_SCREEN_TRANSP
|
||||
*vdb_buf_tmp = color_mix_2_alpha(*vdb_buf_tmp, (*vdb_buf_tmp).ch.alpha, color, px_opa);
|
||||
*vdb_buf_tmp = color_mix_2_alpha(*vdb_buf_tmp, (*vdb_buf_tmp).ch.alpha, color, px_opa);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
vdb_buf_tmp++;
|
||||
}
|
||||
/*Handle subpx drawing*/
|
||||
else {
|
||||
if(letter_px != 0) {
|
||||
if(opa == LV_OPA_COVER) {
|
||||
px_opa = g.bpp == 8 ? letter_px : bpp_opa_table[letter_px];
|
||||
} else {
|
||||
px_opa = g.bpp == 8 ? (uint16_t)((uint16_t)letter_px * opa) >> 8
|
||||
: (uint16_t)((uint16_t)bpp_opa_table[letter_px] * opa) >> 8;
|
||||
}
|
||||
|
||||
font_rgb[sub_px_cnt] = px_opa;
|
||||
} else {
|
||||
font_rgb[sub_px_cnt] = 0;
|
||||
}
|
||||
sub_px_cnt ++;
|
||||
|
||||
if(sub_px_cnt == 3) {
|
||||
lv_color_t res_color;
|
||||
|
||||
if(font_rgb[0] == 0 && font_rgb[1] == 0 && font_rgb[2] == 0) {
|
||||
res_color = *vdb_buf_tmp;
|
||||
} else {
|
||||
|
||||
uint8_t bg_rgb[3] = {LV_COLOR_GET_R(*vdb_buf_tmp), LV_COLOR_GET_G(*vdb_buf_tmp), LV_COLOR_GET_B(*vdb_buf_tmp)};
|
||||
|
||||
#if LV_FONT_SUBPX_BGR
|
||||
LV_COLOR_SET_B(res_color, (uint16_t)((uint16_t)txt_rgb[0] * font_rgb[0] + (bg_rgb[2] * (255 - font_rgb[0]))) >> 8);
|
||||
LV_COLOR_SET_R(res_color, (uint16_t)((uint16_t)txt_rgb[2] * font_rgb[2] + (bg_rgb[0] * (255 - font_rgb[2]))) >> 8);
|
||||
#else
|
||||
LV_COLOR_SET_R(res_color, (uint16_t)((uint16_t)txt_rgb[0] * font_rgb[0] + (bg_rgb[0] * (255 - font_rgb[0]))) >> 8);
|
||||
LV_COLOR_SET_B(res_color, (uint16_t)((uint16_t)txt_rgb[2] * font_rgb[2] + (bg_rgb[2] * (255 - font_rgb[2]))) >> 8);
|
||||
#endif
|
||||
LV_COLOR_SET_G(res_color, (uint16_t)((uint16_t)txt_rgb[1] * font_rgb[1] + (bg_rgb[1] * (255 - font_rgb[1]))) >> 8);
|
||||
}
|
||||
if(scr_transp == false) {
|
||||
vdb_buf_tmp->full = res_color.full;
|
||||
#if LV_COLOR_DEPTH == 32 && LV_COLOR_SCREEN_TRANSP
|
||||
} else {
|
||||
*vdb_buf_tmp = color_mix_2_alpha(*vdb_buf_tmp, (*vdb_buf_tmp).ch.alpha, color, px_opa);
|
||||
#endif
|
||||
}
|
||||
sub_px_cnt = 0;
|
||||
vdb_buf_tmp++;
|
||||
}
|
||||
}
|
||||
|
||||
vdb_buf_tmp++;
|
||||
|
||||
if(col_bit < 8 - g.bpp) {
|
||||
col_bit += g.bpp;
|
||||
@@ -364,11 +436,15 @@ void lv_draw_letter(const lv_point_t * pos_p, const lv_area_t * mask_p, const lv
|
||||
map_p++;
|
||||
}
|
||||
}
|
||||
|
||||
col_bit += ((g.box_w - col_end) + col_start) * g.bpp;
|
||||
|
||||
map_p += (col_bit >> 3);
|
||||
col_bit = col_bit & 0x7;
|
||||
vdb_buf_tmp += vdb_width - (col_end - col_start); /*Next row in VDB*/
|
||||
|
||||
/*Next row in VDB*/
|
||||
if(subpx) vdb_buf_tmp += vdb_width - (col_end - col_start) / 3;
|
||||
else vdb_buf_tmp += vdb_width - (col_end - col_start);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#include "lv_draw_img.h"
|
||||
#include "lv_img_cache.h"
|
||||
#include "../lv_misc/lv_log.h"
|
||||
#include "../lv_misc/lv_mem.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
@@ -50,7 +51,7 @@ void lv_draw_img(const lv_area_t * coords, const lv_area_t * mask, const void *
|
||||
if(src == NULL) {
|
||||
LV_LOG_WARN("Image draw: src is NULL");
|
||||
lv_draw_rect(coords, mask, &lv_style_plain, LV_OPA_COVER);
|
||||
lv_draw_label(coords, mask, &lv_style_plain, LV_OPA_COVER, "No\ndata", LV_TXT_FLAG_NONE, NULL, -1, -1, NULL);
|
||||
lv_draw_label(coords, mask, &lv_style_plain, LV_OPA_COVER, "No\ndata", LV_TXT_FLAG_NONE, NULL, NULL, NULL, LV_BIDI_DIR_LTR);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -60,7 +61,7 @@ void lv_draw_img(const lv_area_t * coords, const lv_area_t * mask, const void *
|
||||
if(res == LV_RES_INV) {
|
||||
LV_LOG_WARN("Image draw error");
|
||||
lv_draw_rect(coords, mask, &lv_style_plain, LV_OPA_COVER);
|
||||
lv_draw_label(coords, mask, &lv_style_plain, LV_OPA_COVER, "No\ndata", LV_TXT_FLAG_NONE, NULL, -1, -1, NULL);
|
||||
lv_draw_label(coords, mask, &lv_style_plain, LV_OPA_COVER, "No\ndata", LV_TXT_FLAG_NONE, NULL, NULL, NULL, LV_BIDI_DIR_LTR);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -401,10 +402,14 @@ bool lv_img_color_format_is_chroma_keyed(lv_img_cf_t cf)
|
||||
switch(cf) {
|
||||
case LV_IMG_CF_TRUE_COLOR_CHROMA_KEYED:
|
||||
case LV_IMG_CF_RAW_CHROMA_KEYED:
|
||||
#if LV_INDEXED_CHROMA
|
||||
case LV_IMG_CF_INDEXED_1BIT:
|
||||
case LV_IMG_CF_INDEXED_2BIT:
|
||||
case LV_IMG_CF_INDEXED_4BIT:
|
||||
case LV_IMG_CF_INDEXED_8BIT: is_chroma_keyed = true; break;
|
||||
case LV_IMG_CF_INDEXED_8BIT:
|
||||
#endif
|
||||
is_chroma_keyed = true; break;
|
||||
|
||||
default: is_chroma_keyed = false; break;
|
||||
}
|
||||
|
||||
@@ -423,6 +428,10 @@ bool lv_img_color_format_has_alpha(lv_img_cf_t cf)
|
||||
switch(cf) {
|
||||
case LV_IMG_CF_TRUE_COLOR_ALPHA:
|
||||
case LV_IMG_CF_RAW_ALPHA:
|
||||
case LV_IMG_CF_INDEXED_1BIT:
|
||||
case LV_IMG_CF_INDEXED_2BIT:
|
||||
case LV_IMG_CF_INDEXED_4BIT:
|
||||
case LV_IMG_CF_INDEXED_8BIT:
|
||||
case LV_IMG_CF_ALPHA_1BIT:
|
||||
case LV_IMG_CF_ALPHA_2BIT:
|
||||
case LV_IMG_CF_ALPHA_4BIT:
|
||||
@@ -464,6 +473,66 @@ lv_img_src_t lv_img_src_get_type(const void * src)
|
||||
return img_src_type;
|
||||
}
|
||||
|
||||
lv_img_dsc_t *lv_img_buf_alloc(lv_coord_t w, lv_coord_t h, lv_img_cf_t cf)
|
||||
{
|
||||
/* Allocate image descriptor */
|
||||
lv_img_dsc_t *dsc = lv_mem_alloc(sizeof(lv_img_dsc_t));
|
||||
if(dsc == NULL)
|
||||
return NULL;
|
||||
|
||||
memset(dsc, 0, sizeof(lv_img_dsc_t));
|
||||
|
||||
/* Get image data size */
|
||||
dsc->data_size = lv_img_buf_get_img_size(w, h, cf);
|
||||
if(dsc->data_size == 0) {
|
||||
lv_mem_free(dsc);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Allocate raw buffer */
|
||||
dsc->data = lv_mem_alloc(dsc->data_size);
|
||||
if(dsc->data == NULL) {
|
||||
lv_mem_free(dsc);
|
||||
return NULL;
|
||||
}
|
||||
memset((uint8_t *)dsc->data, 0, dsc->data_size);
|
||||
|
||||
/* Fill in header */
|
||||
dsc->header.always_zero = 0;
|
||||
dsc->header.w = w;
|
||||
dsc->header.h = h;
|
||||
dsc->header.cf = cf;
|
||||
return dsc;
|
||||
}
|
||||
|
||||
void lv_img_buf_free(lv_img_dsc_t *dsc)
|
||||
{
|
||||
if(dsc != NULL) {
|
||||
if(dsc->data != NULL)
|
||||
lv_mem_free(dsc->data);
|
||||
|
||||
lv_mem_free(dsc);
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t lv_img_buf_get_img_size(lv_coord_t w, lv_coord_t h, lv_img_cf_t cf)
|
||||
{
|
||||
switch(cf) {
|
||||
case LV_IMG_CF_TRUE_COLOR: return LV_IMG_BUF_SIZE_TRUE_COLOR(w, h);
|
||||
case LV_IMG_CF_TRUE_COLOR_ALPHA: return LV_IMG_BUF_SIZE_TRUE_COLOR_ALPHA(w, h);
|
||||
case LV_IMG_CF_TRUE_COLOR_CHROMA_KEYED: return LV_IMG_BUF_SIZE_TRUE_COLOR_CHROMA_KEYED(w, h);
|
||||
case LV_IMG_CF_ALPHA_1BIT: return LV_IMG_BUF_SIZE_ALPHA_1BIT(w, h);
|
||||
case LV_IMG_CF_ALPHA_2BIT: return LV_IMG_BUF_SIZE_ALPHA_2BIT(w, h);
|
||||
case LV_IMG_CF_ALPHA_4BIT: return LV_IMG_BUF_SIZE_ALPHA_4BIT(w, h);
|
||||
case LV_IMG_CF_ALPHA_8BIT: return LV_IMG_BUF_SIZE_ALPHA_8BIT(w, h);
|
||||
case LV_IMG_CF_INDEXED_1BIT: return LV_IMG_BUF_SIZE_INDEXED_1BIT(w, h);
|
||||
case LV_IMG_CF_INDEXED_2BIT: return LV_IMG_BUF_SIZE_INDEXED_2BIT(w, h);
|
||||
case LV_IMG_CF_INDEXED_4BIT: return LV_IMG_BUF_SIZE_INDEXED_4BIT(w, h);
|
||||
case LV_IMG_CF_INDEXED_8BIT: return LV_IMG_BUF_SIZE_INDEXED_8BIT(w, h);
|
||||
default: return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
@@ -493,8 +562,7 @@ static lv_res_t lv_img_draw_core(const lv_area_t * coords, const lv_area_t * mas
|
||||
if(cdsc->dec_dsc.error_msg != NULL) {
|
||||
LV_LOG_WARN("Image draw error");
|
||||
lv_draw_rect(coords, mask, &lv_style_plain, LV_OPA_COVER);
|
||||
lv_draw_label(coords, mask, &lv_style_plain, LV_OPA_COVER, cdsc->dec_dsc.error_msg, LV_TXT_FLAG_NONE, NULL, -1,
|
||||
-1, NULL);
|
||||
lv_draw_label(coords, mask, &lv_style_plain, LV_OPA_COVER, cdsc->dec_dsc.error_msg, LV_TXT_FLAG_NONE, NULL, NULL, NULL, LV_BIDI_DIR_LTR);
|
||||
}
|
||||
/* The decoder open could open the image and gave the entire uncompressed image.
|
||||
* Just draw it!*/
|
||||
@@ -506,7 +574,7 @@ static lv_res_t lv_img_draw_core(const lv_area_t * coords, const lv_area_t * mas
|
||||
else {
|
||||
lv_coord_t width = lv_area_get_width(&mask_com);
|
||||
|
||||
uint8_t * buf = lv_draw_get_buf(lv_area_get_width(&mask_com) * ((LV_COLOR_DEPTH >> 3) + 1)); /*+1 because of the possible alpha byte*/
|
||||
uint8_t * buf = lv_draw_get_buf(lv_area_get_width(&mask_com) * LV_IMG_PX_SIZE_ALPHA_BYTE); /*space for the possible alpha byte*/
|
||||
|
||||
lv_area_t line;
|
||||
lv_area_copy(&line, &mask_com);
|
||||
|
||||
@@ -20,6 +20,26 @@ extern "C" {
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#define LV_IMG_BUF_SIZE_TRUE_COLOR(w, h) ((LV_COLOR_SIZE / 8) * w * h)
|
||||
#define LV_IMG_BUF_SIZE_TRUE_COLOR_CHROMA_KEYED(w, h) ((LV_COLOR_SIZE / 8) * w * h)
|
||||
#define LV_IMG_BUF_SIZE_TRUE_COLOR_ALPHA(w, h) (LV_IMG_PX_SIZE_ALPHA_BYTE * w * h)
|
||||
|
||||
/*+ 1: to be sure no fractional row*/
|
||||
#define LV_IMG_BUF_SIZE_ALPHA_1BIT(w, h) ((((w / 8) + 1) * h))
|
||||
#define LV_IMG_BUF_SIZE_ALPHA_2BIT(w, h) ((((w / 4) + 1) * h))
|
||||
#define LV_IMG_BUF_SIZE_ALPHA_4BIT(w, h) ((((w / 2) + 1) * h))
|
||||
#define LV_IMG_BUF_SIZE_ALPHA_8BIT(w, h) ((w * h))
|
||||
|
||||
/*4 * X: for palette*/
|
||||
#define LV_IMG_BUF_SIZE_INDEXED_1BIT(w, h) (LV_IMG_BUF_SIZE_ALPHA_1BIT(w, h) + 4 * 2)
|
||||
#define LV_IMG_BUF_SIZE_INDEXED_2BIT(w, h) (LV_IMG_BUF_SIZE_ALPHA_2BIT(w, h) + 4 * 4)
|
||||
#define LV_IMG_BUF_SIZE_INDEXED_4BIT(w, h) (LV_IMG_BUF_SIZE_ALPHA_4BIT(w, h) + 4 * 16)
|
||||
#define LV_IMG_BUF_SIZE_INDEXED_8BIT(w, h) (LV_IMG_BUF_SIZE_ALPHA_8BIT(w, h) + 4 * 256)
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
@@ -120,9 +140,30 @@ bool lv_img_color_format_is_chroma_keyed(lv_img_cf_t cf);
|
||||
*/
|
||||
bool lv_img_color_format_has_alpha(lv_img_cf_t cf);
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
/**
|
||||
* Allocate an image buffer in RAM
|
||||
* @param w width of image
|
||||
* @param h height of image
|
||||
* @param cf a color format (`LV_IMG_CF_...`)
|
||||
* @return an allocated image, or NULL on failure
|
||||
*/
|
||||
lv_img_dsc_t *lv_img_buf_alloc(lv_coord_t w, lv_coord_t h, lv_img_cf_t cf);
|
||||
|
||||
/**
|
||||
* Free an allocated image buffer
|
||||
* @param dsc image buffer to free
|
||||
*/
|
||||
void lv_img_buf_free(lv_img_dsc_t *dsc);
|
||||
|
||||
/**
|
||||
* Get the memory consumption of a raw bitmap, given color format and dimensions.
|
||||
* @param w width
|
||||
* @param h height
|
||||
* @param cf color format
|
||||
* @return size in bytes
|
||||
*/
|
||||
uint32_t lv_img_buf_get_img_size(lv_coord_t w, lv_coord_t h, lv_img_cf_t cf);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
*********************/
|
||||
#include "lv_draw_label.h"
|
||||
#include "../lv_misc/lv_math.h"
|
||||
#include "../lv_misc/lv_bidi.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
@@ -51,15 +52,18 @@ static uint8_t hex_char_to_num(char hex);
|
||||
* @param txt 0 terminated text to write
|
||||
* @param flag settings for the text from 'txt_flag_t' enum
|
||||
* @param offset text offset in x and y direction (NULL if unused)
|
||||
* @param sel_start start index of selected area (`LV_LABEL_TXT_SEL_OFF` if none)
|
||||
* @param sel_end end index of selected area (`LV_LABEL_TXT_SEL_OFF` if none)
|
||||
* @param sel make the text selected in the range by drawing a background there
|
||||
*/
|
||||
void lv_draw_label(const lv_area_t * coords, const lv_area_t * mask, const lv_style_t * style, lv_opa_t opa_scale,
|
||||
const char * txt, lv_txt_flag_t flag, lv_point_t * offset, uint16_t sel_start, uint16_t sel_end,
|
||||
lv_draw_label_hint_t * hint)
|
||||
const char * txt, lv_txt_flag_t flag, lv_point_t * offset, lv_draw_label_txt_sel_t * sel,
|
||||
lv_draw_label_hint_t * hint, lv_bidi_dir_t bidi_dir)
|
||||
{
|
||||
const lv_font_t * font = style->text.font;
|
||||
lv_coord_t w;
|
||||
|
||||
/*No need to waste processor time if string is empty*/
|
||||
if (txt[0] == '\0') return;
|
||||
|
||||
if((flag & LV_TXT_FLAG_EXPAND) == 0) {
|
||||
/*Normally use the label's width as width*/
|
||||
w = lv_area_get_width(coords);
|
||||
@@ -67,7 +71,7 @@ void lv_draw_label(const lv_area_t * coords, const lv_area_t * mask, const lv_st
|
||||
/*If EXAPND is enabled then not limit the text's width to the object's width*/
|
||||
lv_point_t p;
|
||||
lv_txt_get_size(&p, txt, style->text.font, style->text.letter_space, style->text.line_space, LV_COORD_MAX,
|
||||
flag);
|
||||
flag);
|
||||
w = p.x;
|
||||
}
|
||||
|
||||
@@ -105,6 +109,7 @@ void lv_draw_label(const lv_area_t * coords, const lv_area_t * mask, const lv_st
|
||||
pos.y += hint->y;
|
||||
}
|
||||
|
||||
|
||||
uint32_t line_end = line_start + lv_txt_get_next_line(&txt[line_start], font, style->text.letter_space, w, flag);
|
||||
|
||||
/*Go the first visible line*/
|
||||
@@ -139,6 +144,18 @@ void lv_draw_label(const lv_area_t * coords, const lv_area_t * mask, const lv_st
|
||||
|
||||
lv_opa_t opa = opa_scale == LV_OPA_COVER ? style->text.opa : (uint16_t)((uint16_t)style->text.opa * opa_scale) >> 8;
|
||||
|
||||
uint16_t sel_start = 0xFFFF;
|
||||
uint16_t sel_end = 0xFFFF;
|
||||
if(sel) {
|
||||
sel_start = sel->start;
|
||||
sel_end = sel->end;
|
||||
if(sel_start > sel_end) {
|
||||
uint16_t tmp = sel_start;
|
||||
sel_start = sel_end;
|
||||
sel_end = tmp;
|
||||
}
|
||||
}
|
||||
|
||||
cmd_state_t cmd_state = CMD_STATE_WAIT;
|
||||
uint32_t i;
|
||||
uint16_t par_start = 0;
|
||||
@@ -155,12 +172,31 @@ void lv_draw_label(const lv_area_t * coords, const lv_area_t * mask, const lv_st
|
||||
}
|
||||
/*Write all letter of a line*/
|
||||
cmd_state = CMD_STATE_WAIT;
|
||||
i = line_start;
|
||||
i = 0;
|
||||
uint32_t letter;
|
||||
uint32_t letter_next;
|
||||
while(i < line_end) {
|
||||
letter = lv_txt_encoded_next(txt, &i);
|
||||
letter_next = lv_txt_encoded_next(&txt[i], NULL);
|
||||
#if LV_USE_BIDI
|
||||
char *bidi_txt = lv_draw_get_buf(line_end - line_start + 1);
|
||||
lv_bidi_process_paragraph(txt + line_start, bidi_txt, line_end - line_start, bidi_dir, NULL, 0);
|
||||
#else
|
||||
const char *bidi_txt = txt + line_start;
|
||||
#endif
|
||||
|
||||
while(i < line_end - line_start) {
|
||||
uint16_t logical_char_pos = 0;
|
||||
if(sel_start != 0xFFFF && sel_end != 0xFFFF) {
|
||||
#if LV_USE_BIDI
|
||||
logical_char_pos = lv_txt_encoded_get_char_id(txt, line_start);
|
||||
uint16_t t = lv_txt_encoded_get_char_id(bidi_txt, i);
|
||||
logical_char_pos += lv_bidi_get_logical_pos(bidi_txt, NULL, line_end - line_start, bidi_dir, t, NULL);
|
||||
#else
|
||||
logical_char_pos = lv_txt_encoded_get_char_id(txt, line_start + i);
|
||||
#endif
|
||||
}
|
||||
|
||||
letter = lv_txt_encoded_next(bidi_txt, &i);
|
||||
letter_next = lv_txt_encoded_next(&bidi_txt[i], NULL);
|
||||
|
||||
|
||||
/*Handle the re-color command*/
|
||||
if((flag & LV_TXT_FLAG_RECOLOR) != 0) {
|
||||
@@ -183,7 +219,7 @@ void lv_draw_label(const lv_area_t * coords, const lv_area_t * mask, const lv_st
|
||||
/*Get the parameter*/
|
||||
if(i - par_start == LABEL_RECOLOR_PAR_LENGTH + 1) {
|
||||
char buf[LABEL_RECOLOR_PAR_LENGTH + 1];
|
||||
memcpy(buf, &txt[par_start], LABEL_RECOLOR_PAR_LENGTH);
|
||||
memcpy(buf, &bidi_txt[par_start], LABEL_RECOLOR_PAR_LENGTH);
|
||||
buf[LABEL_RECOLOR_PAR_LENGTH] = '\0';
|
||||
int r, g, b;
|
||||
r = (hex_char_to_num(buf[0]) << 4) + hex_char_to_num(buf[1]);
|
||||
@@ -206,9 +242,7 @@ void lv_draw_label(const lv_area_t * coords, const lv_area_t * mask, const lv_st
|
||||
letter_w = lv_font_get_glyph_width(font, letter, letter_next);
|
||||
|
||||
if(sel_start != 0xFFFF && sel_end != 0xFFFF) {
|
||||
int char_ind = lv_encoded_get_char_id(txt, i);
|
||||
/*Do not draw the rectangle on the character at `sel_start`.*/
|
||||
if(char_ind > sel_start && char_ind <= sel_end) {
|
||||
if(logical_char_pos >= sel_start && logical_char_pos < sel_end) {
|
||||
lv_area_t sel_coords;
|
||||
sel_coords.x1 = pos.x;
|
||||
sel_coords.y1 = pos.y;
|
||||
@@ -217,6 +251,7 @@ void lv_draw_label(const lv_area_t * coords, const lv_area_t * mask, const lv_st
|
||||
lv_draw_rect(&sel_coords, mask, &sel_style, opa);
|
||||
}
|
||||
}
|
||||
|
||||
lv_draw_letter(&pos, mask, font, letter, color, opa);
|
||||
|
||||
if(letter_w > 0) {
|
||||
@@ -231,7 +266,7 @@ void lv_draw_label(const lv_area_t * coords, const lv_area_t * mask, const lv_st
|
||||
/*Align to middle*/
|
||||
if(flag & LV_TXT_FLAG_CENTER) {
|
||||
line_width =
|
||||
lv_txt_get_width(&txt[line_start], line_end - line_start, font, style->text.letter_space, flag);
|
||||
lv_txt_get_width(&txt[line_start], line_end - line_start, font, style->text.letter_space, flag);
|
||||
|
||||
pos.x += (lv_area_get_width(coords) - line_width) / 2;
|
||||
|
||||
@@ -239,7 +274,7 @@ void lv_draw_label(const lv_area_t * coords, const lv_area_t * mask, const lv_st
|
||||
/*Align to the right*/
|
||||
else if(flag & LV_TXT_FLAG_RIGHT) {
|
||||
line_width =
|
||||
lv_txt_get_width(&txt[line_start], line_end - line_start, font, style->text.letter_space, flag);
|
||||
lv_txt_get_width(&txt[line_start], line_end - line_start, font, style->text.letter_space, flag);
|
||||
pos.x += lv_area_get_width(coords) - line_width;
|
||||
}
|
||||
|
||||
@@ -269,13 +304,13 @@ static uint8_t hex_char_to_num(char hex)
|
||||
if(hex >= 'a') hex -= 'a' - 'A'; /*Convert to upper case*/
|
||||
|
||||
switch(hex) {
|
||||
case 'A': result = 10; break;
|
||||
case 'B': result = 11; break;
|
||||
case 'C': result = 12; break;
|
||||
case 'D': result = 13; break;
|
||||
case 'E': result = 14; break;
|
||||
case 'F': result = 15; break;
|
||||
default: result = 0; break;
|
||||
case 'A': result = 10; break;
|
||||
case 'B': result = 11; break;
|
||||
case 'C': result = 12; break;
|
||||
case 'D': result = 13; break;
|
||||
case 'E': result = 14; break;
|
||||
case 'F': result = 15; break;
|
||||
default: result = 0; break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -14,15 +14,24 @@ extern "C" {
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "lv_draw.h"
|
||||
#include "../lv_misc/lv_bidi.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
#define LV_DRAW_LABEL_NO_TXT_SEL (0xFFFF)
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint16_t start;
|
||||
uint16_t end;
|
||||
}lv_draw_label_txt_sel_t;
|
||||
|
||||
|
||||
/** Store some info to speed up drawing of very large texts
|
||||
* It takes a lot of time to get the first visible character because
|
||||
* all the previous characters needs to be checked to calculate the positions.
|
||||
@@ -54,11 +63,11 @@ typedef struct {
|
||||
* @param flag settings for the text from 'txt_flag_t' enum
|
||||
* @param offset text offset in x and y direction (NULL if unused)
|
||||
* @param sel_start start index of selected area (`LV_LABEL_TXT_SEL_OFF` if none)
|
||||
* @param sel_end end index of selected area (`LV_LABEL_TXT_SEL_OFF` if none)
|
||||
* @param bidi_dir base direction of the text
|
||||
*/
|
||||
void lv_draw_label(const lv_area_t * coords, const lv_area_t * mask, const lv_style_t * style, lv_opa_t opa_scale,
|
||||
const char * txt, lv_txt_flag_t flag, lv_point_t * offset, uint16_t sel_start, uint16_t sel_end,
|
||||
lv_draw_label_hint_t * hint);
|
||||
const char * txt, lv_txt_flag_t flag, lv_point_t * offset, lv_draw_label_txt_sel_t * sel,
|
||||
lv_draw_label_hint_t * hint, lv_bidi_dir_t bidi_dir);
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
|
||||
@@ -45,8 +45,7 @@ static void point_swap(lv_point_t * p1, lv_point_t * p2);
|
||||
*/
|
||||
void lv_draw_triangle(const lv_point_t * points, const lv_area_t * mask, const lv_style_t * style, lv_opa_t opa_scale)
|
||||
{
|
||||
|
||||
/*Return is the triangle is degenerated*/
|
||||
/*Return if the triangle is degenerated*/
|
||||
if(points[0].x == points[1].x && points[0].y == points[1].y) return;
|
||||
if(points[1].x == points[2].x && points[1].y == points[2].y) return;
|
||||
if(points[0].x == points[2].x && points[0].y == points[2].y) return;
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "../lv_core/lv_debug.h"
|
||||
#include "lv_img_cache.h"
|
||||
#include "lv_img_decoder.h"
|
||||
#include "lv_draw_img.h"
|
||||
@@ -162,7 +163,7 @@ void lv_img_cache_set_size(uint16_t new_entry_cnt)
|
||||
|
||||
/*Reallocate the cache*/
|
||||
LV_GC_ROOT(_lv_img_cache_array) = lv_mem_alloc(sizeof(lv_img_cache_entry_t) * new_entry_cnt);
|
||||
lv_mem_assert(LV_GC_ROOT(_lv_img_cache_array));
|
||||
LV_ASSERT_MEM(LV_GC_ROOT(_lv_img_cache_array));
|
||||
if(LV_GC_ROOT(_lv_img_cache_array) == NULL) {
|
||||
entry_cnt = 0;
|
||||
return;
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "lv_img_decoder.h"
|
||||
#include "../lv_core/lv_debug.h"
|
||||
#include "../lv_draw/lv_draw_img.h"
|
||||
#include "../lv_misc/lv_ll.h"
|
||||
#include "../lv_misc/lv_color.h"
|
||||
@@ -31,6 +32,7 @@ typedef struct
|
||||
lv_fs_file_t * f;
|
||||
#endif
|
||||
lv_color_t * palette;
|
||||
lv_opa_t * opa;
|
||||
} lv_img_decoder_built_in_data_t;
|
||||
|
||||
/**********************
|
||||
@@ -68,7 +70,7 @@ void lv_img_decoder_init(void)
|
||||
decoder = lv_img_decoder_create();
|
||||
if(decoder == NULL) {
|
||||
LV_LOG_WARN("lv_img_decoder_init: out of memory");
|
||||
lv_mem_assert(decoder);
|
||||
LV_ASSERT_MEM(decoder);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -198,7 +200,7 @@ lv_img_decoder_t * lv_img_decoder_create(void)
|
||||
{
|
||||
lv_img_decoder_t * decoder;
|
||||
decoder = lv_ll_ins_head(&LV_GC_ROOT(_lv_img_defoder_ll));
|
||||
lv_mem_assert(decoder);
|
||||
LV_ASSERT_MEM(decoder);
|
||||
if(decoder == NULL) return NULL;
|
||||
|
||||
memset(decoder, 0, sizeof(lv_img_decoder_t));
|
||||
@@ -333,7 +335,7 @@ lv_res_t lv_img_decoder_built_in_open(lv_img_decoder_t * decoder, lv_img_decoder
|
||||
dsc->user_data = lv_mem_alloc(sizeof(lv_img_decoder_built_in_data_t));
|
||||
if(dsc->user_data == NULL) {
|
||||
LV_LOG_ERROR("img_decoder_built_in_open: out of memory");
|
||||
lv_mem_assert(dsc->user_data);
|
||||
LV_ASSERT_MEM(dsc->user_data);
|
||||
}
|
||||
memset(dsc->user_data, 0, sizeof(lv_img_decoder_built_in_data_t));
|
||||
}
|
||||
@@ -342,7 +344,7 @@ lv_res_t lv_img_decoder_built_in_open(lv_img_decoder_t * decoder, lv_img_decoder
|
||||
user_data->f = lv_mem_alloc(sizeof(f));
|
||||
if(user_data->f == NULL) {
|
||||
LV_LOG_ERROR("img_decoder_built_in_open: out of memory");
|
||||
lv_mem_assert(user_data->f);
|
||||
LV_ASSERT_MEM(user_data->f);
|
||||
}
|
||||
|
||||
memcpy(user_data->f, &f, sizeof(f));
|
||||
@@ -380,17 +382,18 @@ lv_res_t lv_img_decoder_built_in_open(lv_img_decoder_t * decoder, lv_img_decoder
|
||||
dsc->user_data = lv_mem_alloc(sizeof(lv_img_decoder_built_in_data_t));
|
||||
if(dsc->user_data == NULL) {
|
||||
LV_LOG_ERROR("img_decoder_built_in_open: out of memory");
|
||||
lv_mem_assert(dsc->user_data);
|
||||
LV_ASSERT_MEM(dsc->user_data);
|
||||
}
|
||||
memset(dsc->user_data, 0, sizeof(lv_img_decoder_built_in_data_t));
|
||||
}
|
||||
|
||||
lv_img_decoder_built_in_data_t * user_data = dsc->user_data;
|
||||
user_data->palette = lv_mem_alloc(palette_size * sizeof(lv_color_t));
|
||||
if(user_data->palette == NULL) {
|
||||
user_data->opa = lv_mem_alloc(palette_size * sizeof(lv_opa_t));
|
||||
if(user_data->palette == NULL || user_data->opa == NULL) {
|
||||
LV_LOG_ERROR("img_decoder_built_in_open: out of memory");
|
||||
#if LV_USE_FILESYSTEM
|
||||
lv_mem_assert(user_data->f);
|
||||
LV_ASSERT_MEM(user_data->f);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -398,7 +401,13 @@ lv_res_t lv_img_decoder_built_in_open(lv_img_decoder_t * decoder, lv_img_decoder
|
||||
/*Read the palette from file*/
|
||||
#if LV_USE_FILESYSTEM
|
||||
lv_fs_seek(user_data->f, 4); /*Skip the header*/
|
||||
lv_fs_read(user_data->f, user_data->palette, palette_size * sizeof(lv_color_t), NULL);
|
||||
lv_color32_t cur_color;
|
||||
uint32_t i;
|
||||
for(i = 0; i < palette_size; i++) {
|
||||
lv_fs_read(user_data->f, &cur_color, sizeof(lv_color32_t), NULL);
|
||||
user_data->palette[i] = lv_color_make(cur_color.ch.red, cur_color.ch.green, cur_color.ch.blue);
|
||||
user_data->opa[i] = cur_color.ch.alpha;
|
||||
}
|
||||
#else
|
||||
LV_LOG_WARN("Image built-in decoder can read the palette because LV_USE_FILESYSTEM = 0");
|
||||
return LV_RES_INV;
|
||||
@@ -410,6 +419,7 @@ lv_res_t lv_img_decoder_built_in_open(lv_img_decoder_t * decoder, lv_img_decoder
|
||||
uint32_t i;
|
||||
for(i = 0; i < palette_size; i++) {
|
||||
user_data->palette[i] = lv_color_make(palette_p[i].ch.red, palette_p[i].ch.green, palette_p[i].ch.blue);
|
||||
user_data->opa[i] = palette_p[i].ch.alpha;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -711,13 +721,24 @@ static lv_res_t lv_img_decoder_built_in_line_indexed(lv_img_decoder_dsc_t * dsc,
|
||||
#endif
|
||||
}
|
||||
|
||||
uint8_t byte_act = 0;
|
||||
uint8_t val_act;
|
||||
lv_coord_t i;
|
||||
lv_color_t * cbuf = (lv_color_t *)buf;
|
||||
for(i = 0; i < len; i++) {
|
||||
val_act = (data_tmp[byte_act] & (mask << pos)) >> pos;
|
||||
cbuf[i] = user_data->palette[val_act];
|
||||
val_act = (*data_tmp & (mask << pos)) >> pos;
|
||||
|
||||
lv_color_t color = user_data->palette[val_act];
|
||||
#if LV_COLOR_DEPTH == 8 || LV_COLOR_DEPTH == 1
|
||||
buf[i * LV_IMG_PX_SIZE_ALPHA_BYTE] = color.full;
|
||||
#elif LV_COLOR_DEPTH == 16
|
||||
/*Because of Alpha byte 16 bit color can start on odd address which can cause crash*/
|
||||
buf[i * LV_IMG_PX_SIZE_ALPHA_BYTE] = color.full & 0xFF;
|
||||
buf[i * LV_IMG_PX_SIZE_ALPHA_BYTE + 1] = (color.full >> 8) & 0xFF;
|
||||
#elif LV_COLOR_DEPTH == 32
|
||||
*((uint32_t *)&buf[i * LV_IMG_PX_SIZE_ALPHA_BYTE]) = color.full;
|
||||
#else
|
||||
#error "Invalid LV_COLOR_DEPTH. Check it in lv_conf.h"
|
||||
#endif
|
||||
buf[i * LV_IMG_PX_SIZE_ALPHA_BYTE + LV_IMG_PX_SIZE_ALPHA_BYTE - 1] = user_data->opa[val_act];
|
||||
|
||||
pos -= px_size;
|
||||
if(pos < 0) {
|
||||
|
||||
@@ -53,7 +53,18 @@ typedef struct
|
||||
uint8_t bpp; /**< Bit-per-pixel: 1, 2, 4, 8*/
|
||||
}lv_font_glyph_dsc_t;
|
||||
|
||||
/*Describe the properties of a font*/
|
||||
|
||||
/** The bitmaps might be upscaled by 3 to achieve subpixel rendering. */
|
||||
enum {
|
||||
LV_FONT_SUBPX_NONE,
|
||||
LV_FONT_SUBPX_HOR,
|
||||
LV_FONT_SUBPX_VER,
|
||||
LV_FONT_SUBPX_BOTH,
|
||||
};
|
||||
|
||||
typedef uint8_t lv_font_subpx_t;
|
||||
|
||||
/** Describe the properties of a font*/
|
||||
typedef struct _lv_font_struct
|
||||
{
|
||||
/** Get a glyph's descriptor from a font*/
|
||||
@@ -65,10 +76,13 @@ typedef struct _lv_font_struct
|
||||
/*Pointer to the font in a font pack (must have the same line height)*/
|
||||
uint8_t line_height; /**< The real line height where any text fits*/
|
||||
uint8_t base_line; /**< Base line measured from the top of the line_height*/
|
||||
uint8_t subpx :2; /**< An element of `lv_font_subpx_t`*/
|
||||
void * dsc; /**< Store implementation specific data here*/
|
||||
#if LV_USE_USER_DATA
|
||||
lv_font_user_data_t user_data; /**< Custom user data for font. */
|
||||
#endif
|
||||
|
||||
|
||||
} lv_font_t;
|
||||
|
||||
/**********************
|
||||
|
||||
@@ -8,9 +8,12 @@
|
||||
*********************/
|
||||
#include "lv_font.h"
|
||||
#include "lv_font_fmt_txt.h"
|
||||
#include "../lv_core/lv_debug.h"
|
||||
#include "../lv_draw/lv_draw.h"
|
||||
#include "../lv_misc/lv_types.h"
|
||||
#include "../lv_misc/lv_log.h"
|
||||
#include "../lv_misc/lv_utils.h"
|
||||
#include "../lv_misc/lv_mem.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
@@ -19,6 +22,11 @@
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
typedef enum {
|
||||
RLE_STATE_SINGLE = 0,
|
||||
RLE_STATE_REPEATE,
|
||||
RLE_STATE_COUNTER,
|
||||
}rle_state_t;
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
@@ -29,10 +37,25 @@ static int32_t unicode_list_compare(const void * ref, const void * element);
|
||||
static int32_t kern_pair_8_compare(const void * ref, const void * element);
|
||||
static int32_t kern_pair_16_compare(const void * ref, const void * element);
|
||||
|
||||
static void decompress(const uint8_t * in, uint8_t * out, lv_coord_t w, lv_coord_t h, uint8_t bpp);
|
||||
static void decompress_line(uint8_t * out, lv_coord_t w);
|
||||
static uint8_t get_bits(const uint8_t * in, uint32_t bit_pos, uint8_t len);
|
||||
static void bits_write(uint8_t * out, uint32_t bit_pos, uint8_t val, uint8_t len);
|
||||
static void rle_init(const uint8_t * in, uint8_t bpp);
|
||||
static uint8_t rle_next(void);
|
||||
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
|
||||
static uint32_t rle_rdp;
|
||||
static const uint8_t * rle_in;
|
||||
static uint8_t rle_bpp;
|
||||
static uint8_t rle_prev_v;
|
||||
static uint8_t rle_cnt;
|
||||
static rle_state_t rle_state;
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
@@ -59,7 +82,34 @@ const uint8_t * lv_font_get_bitmap_fmt_txt(const lv_font_t * font, uint32_t unic
|
||||
|
||||
const lv_font_fmt_txt_glyph_dsc_t * gdsc = &fdsc->glyph_dsc[gid];
|
||||
|
||||
if(gdsc) return &fdsc->glyph_bitmap[gdsc->bitmap_index];
|
||||
if(fdsc->bitmap_format == LV_FONT_FMT_TXT_PLAIN) {
|
||||
if(gdsc) return &fdsc->glyph_bitmap[gdsc->bitmap_index];
|
||||
}
|
||||
/*Handle compressed bitmap*/
|
||||
else
|
||||
{
|
||||
static uint8_t * buf = NULL;
|
||||
|
||||
uint32_t gsize = gdsc->box_w * gdsc->box_h;
|
||||
if(gsize == 0) return NULL;
|
||||
|
||||
uint32_t buf_size = gsize;
|
||||
switch(fdsc->bpp) {
|
||||
case 1: buf_size = gsize >> 3; break;
|
||||
case 2: buf_size = gsize >> 2; break;
|
||||
case 3: buf_size = gsize >> 1; break;
|
||||
case 4: buf_size = gsize >> 1; break;
|
||||
}
|
||||
|
||||
if(lv_mem_get_size(buf) < buf_size) {
|
||||
buf = lv_mem_realloc(buf, buf_size);
|
||||
LV_ASSERT_MEM(buf);
|
||||
if(buf == NULL) return NULL;
|
||||
}
|
||||
|
||||
decompress(&fdsc->glyph_bitmap[gdsc->bitmap_index], buf, gdsc->box_w , gdsc->box_h, fdsc->bpp);
|
||||
return buf;
|
||||
}
|
||||
|
||||
/*If not returned earlier then the letter is not found in this font*/
|
||||
return NULL;
|
||||
@@ -90,7 +140,9 @@ bool lv_font_get_glyph_dsc_fmt_txt(const lv_font_t * font, lv_font_glyph_dsc_t *
|
||||
/*Put together a glyph dsc*/
|
||||
const lv_font_fmt_txt_glyph_dsc_t * gdsc = &fdsc->glyph_dsc[gid];
|
||||
|
||||
uint32_t adv_w = gdsc->adv_w + ((int32_t)((int32_t)kvalue * fdsc->kern_scale) >> 4);
|
||||
int32_t kv = ((int32_t)((int32_t)kvalue * fdsc->kern_scale) >> 4);
|
||||
|
||||
uint32_t adv_w = gdsc->adv_w + kv;
|
||||
adv_w = (adv_w + (1 << 3)) >> 4;
|
||||
|
||||
dsc_out->adv_w = adv_w;
|
||||
@@ -238,6 +290,176 @@ static int32_t kern_pair_16_compare(const void * ref, const void * element)
|
||||
else return (int32_t) ref16_p[1] - element16_p[1];
|
||||
}
|
||||
|
||||
/**
|
||||
* The compress a glyph's bitmap
|
||||
* @param in the compressed bitmap
|
||||
* @param out buffer to store the result
|
||||
* @param px_num number of pixels in the glyph (width * height)
|
||||
* @param bpp bit per pixel (bpp = 3 will be converted to bpp = 4)
|
||||
*/
|
||||
static void decompress(const uint8_t * in, uint8_t * out, lv_coord_t w, lv_coord_t h, uint8_t bpp)
|
||||
{
|
||||
uint32_t wrp = 0;
|
||||
uint8_t wr_size = bpp;
|
||||
if(bpp == 3) wr_size = 4;
|
||||
|
||||
rle_init(in, bpp);
|
||||
|
||||
uint8_t * line_buf = lv_draw_get_buf(w * 2);
|
||||
uint8_t * line_buf1 = line_buf;
|
||||
uint8_t * line_buf2 = line_buf + w;
|
||||
|
||||
decompress_line(line_buf1, w);
|
||||
|
||||
lv_coord_t y;
|
||||
lv_coord_t x;
|
||||
for(x = 0; x < w; x++) {
|
||||
bits_write(out,wrp, line_buf1[x], bpp);
|
||||
wrp += wr_size;
|
||||
}
|
||||
|
||||
for(y = 1; y < h; y++) {
|
||||
decompress_line(line_buf2, w);
|
||||
|
||||
for(x = 0; x < w; x++) {
|
||||
line_buf1[x] = line_buf2[x] ^ line_buf1[x];
|
||||
bits_write(out,wrp, line_buf1[x], bpp);
|
||||
wrp += wr_size;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Decompress one line. Store one pixel per byte
|
||||
* @param out output buffer
|
||||
* @param w width of the line in pixel count
|
||||
*/
|
||||
static void decompress_line(uint8_t * out, lv_coord_t w)
|
||||
{
|
||||
lv_coord_t i;
|
||||
for(i = 0; i < w; i++) {
|
||||
out[i] = rle_next();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Read bits from an input buffer. The read can cross byte boundary.
|
||||
* @param in the input buffer to read from.
|
||||
* @param bit_pos index of teh first bit to read.
|
||||
* @param len number of bits to read (must be <= 8).
|
||||
* @return the read bits
|
||||
*/
|
||||
static uint8_t get_bits(const uint8_t * in, uint32_t bit_pos, uint8_t len)
|
||||
{
|
||||
uint8_t res = 0;
|
||||
uint32_t byte_pos = bit_pos >> 3;
|
||||
bit_pos = bit_pos & 0x7;
|
||||
uint8_t bit_mask = (uint16_t)((uint16_t) 1 << len) - 1;
|
||||
uint16_t in16 = (in[byte_pos] << 8) + in[byte_pos + 1];
|
||||
|
||||
res = (in16 >> (16 - bit_pos - len)) & bit_mask;
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
* Write `val` data to `bit_pos` position of `out`. The write can NOT cross byte boundary.
|
||||
* @param out buffer where to write
|
||||
* @param bit_pos bit index to write
|
||||
* @param val value to write
|
||||
* @param len length of bits to write from `val`. (Counted from the LSB).
|
||||
* @note `len == 3` will be converted to `len = 4` and `val` will be upscaled too
|
||||
*/
|
||||
static void bits_write(uint8_t * out, uint32_t bit_pos, uint8_t val, uint8_t len)
|
||||
{
|
||||
if(len == 3) {
|
||||
len = 4;
|
||||
switch(val) {
|
||||
case 0: val = 0; break;
|
||||
case 1: val = 2; break;
|
||||
case 2: val = 4; break;
|
||||
case 3: val = 6; break;
|
||||
case 4: val = 9; break;
|
||||
case 5: val = 11; break;
|
||||
case 6: val = 13; break;
|
||||
case 7: val = 15; break;
|
||||
}
|
||||
}
|
||||
|
||||
uint16_t byte_pos = bit_pos >> 3;
|
||||
bit_pos = bit_pos & 0x7;
|
||||
bit_pos = 8 - bit_pos - len;
|
||||
|
||||
uint8_t bit_mask = (uint16_t)((uint16_t) 1 << len) - 1;
|
||||
out[byte_pos] &= ((~bit_mask) << bit_pos);
|
||||
out[byte_pos] |= (val << bit_pos);
|
||||
}
|
||||
|
||||
static void rle_init(const uint8_t * in, uint8_t bpp)
|
||||
{
|
||||
rle_in = in;
|
||||
rle_bpp = bpp;
|
||||
rle_state = RLE_STATE_SINGLE;
|
||||
rle_rdp = 0;
|
||||
rle_prev_v = 0;
|
||||
rle_cnt = 0;
|
||||
}
|
||||
|
||||
static uint8_t rle_next(void)
|
||||
{
|
||||
uint8_t v = 0;
|
||||
uint8_t ret = 0;
|
||||
|
||||
if(rle_state == RLE_STATE_SINGLE) {
|
||||
ret = get_bits(rle_in, rle_rdp, rle_bpp);
|
||||
if(rle_rdp != 0 && rle_prev_v == ret) {
|
||||
rle_cnt = 0;
|
||||
rle_state = RLE_STATE_REPEATE;
|
||||
}
|
||||
|
||||
rle_prev_v = ret;
|
||||
rle_rdp += rle_bpp;
|
||||
}
|
||||
else if(rle_state == RLE_STATE_REPEATE) {
|
||||
v = get_bits(rle_in, rle_rdp, 1);
|
||||
rle_cnt++;
|
||||
rle_rdp += 1;
|
||||
if(v == 1) {
|
||||
ret = rle_prev_v;
|
||||
if(rle_cnt == 11) {
|
||||
rle_cnt = get_bits(rle_in, rle_rdp, 6);
|
||||
rle_rdp += 6;
|
||||
if(rle_cnt != 0) {
|
||||
rle_state = RLE_STATE_COUNTER;
|
||||
} else {
|
||||
ret = get_bits(rle_in, rle_rdp, rle_bpp);
|
||||
rle_prev_v = ret;
|
||||
rle_rdp += rle_bpp;
|
||||
rle_state = RLE_STATE_SINGLE;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
ret = get_bits(rle_in, rle_rdp, rle_bpp);
|
||||
rle_prev_v = ret;
|
||||
rle_rdp += rle_bpp;
|
||||
rle_state = RLE_STATE_SINGLE;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
else if(rle_state == RLE_STATE_COUNTER) {
|
||||
ret = rle_prev_v;
|
||||
rle_cnt--;
|
||||
if(rle_cnt == 0) {
|
||||
ret = get_bits(rle_in, rle_rdp, rle_bpp);
|
||||
rle_prev_v = ret;
|
||||
rle_rdp += rle_bpp;
|
||||
rle_state = RLE_STATE_SINGLE;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/** Code Comparator.
|
||||
*
|
||||
* Compares the value of both input arguments.
|
||||
|
||||
@@ -45,7 +45,7 @@ typedef struct
|
||||
uint8_t box_w; /**< Width of the glyph's bounding box*/
|
||||
uint8_t box_h; /**< Height of the glyph's bounding box*/
|
||||
int8_t ofs_x; /**< x offset of the bounding box*/
|
||||
uint8_t ofs_y; /**< y offset of the bounding box. Measured from the top of the line*/
|
||||
int8_t ofs_y; /**< y offset of the bounding box. Measured from the top of the line*/
|
||||
}lv_font_fmt_txt_glyph_dsc_t;
|
||||
|
||||
|
||||
@@ -141,7 +141,7 @@ typedef struct {
|
||||
3. value = class_pair_values[(left_class-1)*right_class_cnt + (righ_class-1)]
|
||||
*/
|
||||
|
||||
const uint8_t * class_pair_values; /*left_class_num * right_class_num value*/
|
||||
const int8_t * class_pair_values; /*left_class_num * right_class_num value*/
|
||||
const uint8_t * left_class_mapping; /*Map the glyph_ids to classes: index -> glyph_id -> class_id*/
|
||||
const uint8_t * right_class_mapping; /*Map the glyph_ids to classes: index -> glyph_id -> class_id*/
|
||||
uint8_t left_class_cnt;
|
||||
@@ -180,7 +180,7 @@ typedef struct {
|
||||
/*Number of cmap tables*/
|
||||
uint16_t cmap_num :10;
|
||||
|
||||
/*Bit per pixel: 1, 2, 4 or 8*/
|
||||
/*Bit per pixel: 1, 2, 3, 4*/
|
||||
uint16_t bpp :3;
|
||||
|
||||
/*Type of `kern_dsc`*/
|
||||
@@ -191,6 +191,7 @@ typedef struct {
|
||||
* from `lv_font_fmt_txt_bitmap_format_t`
|
||||
*/
|
||||
uint16_t bitmap_format :2;
|
||||
uint16_t subpx :1;
|
||||
|
||||
/*Cache the last letter and is glyph id*/
|
||||
uint32_t last_letter;
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
3419
src/lv_font/lv_font_roboto_12_subpx.c
Normal file
3419
src/lv_font/lv_font_roboto_12_subpx.c
Normal file
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
2451
src/lv_font/lv_font_roboto_28_compressed.c
Normal file
2451
src/lv_font/lv_font_roboto_28_compressed.c
Normal file
File diff suppressed because it is too large
Load Diff
@@ -11,57 +11,72 @@ extern "C" {
|
||||
#include "../../../lv_conf.h"
|
||||
#endif
|
||||
|
||||
/* In the font converter use this list as range:
|
||||
61441, 61448, 61451, 61452, 61452, 61453, 61457, 61459, 61461, 61465,
|
||||
61468, 61473, 61478, 61479, 61480, 61502, 61512, 61515, 61516, 61517,
|
||||
61521, 61522, 61523, 61524, 61543, 61544, 61550, 61552, 61553, 61556,
|
||||
61559, 61560, 61561, 61563, 61587, 61589, 61636, 61637, 61639, 61671,
|
||||
61674, 61683, 61724, 61732, 61787, 61931, 62016, 62017, 62018, 62019,
|
||||
62020, 62087, 62099, 62212, 62189, 62810, 63426, 63650
|
||||
*/
|
||||
|
||||
#define LV_SYMBOL_AUDIO "\xef\x80\x81"
|
||||
#define LV_SYMBOL_VIDEO "\xef\x80\x88"
|
||||
#define LV_SYMBOL_LIST "\xef\x80\x8b"
|
||||
#define LV_SYMBOL_OK "\xef\x80\x8c"
|
||||
#define LV_SYMBOL_CLOSE "\xef\x80\x8d"
|
||||
#define LV_SYMBOL_POWER "\xef\x80\x91"
|
||||
#define LV_SYMBOL_SETTINGS "\xef\x80\x93"
|
||||
#define LV_SYMBOL_TRASH "\xef\x80\x94"
|
||||
#define LV_SYMBOL_HOME "\xef\x80\x95"
|
||||
#define LV_SYMBOL_DOWNLOAD "\xef\x80\x99"
|
||||
#define LV_SYMBOL_DRIVE "\xef\x80\x9c"
|
||||
#define LV_SYMBOL_REFRESH "\xef\x80\xa1"
|
||||
#define LV_SYMBOL_MUTE "\xef\x80\xa6"
|
||||
#define LV_SYMBOL_VOLUME_MID "\xef\x80\xa7"
|
||||
#define LV_SYMBOL_VOLUME_MAX "\xef\x80\xa8"
|
||||
#define LV_SYMBOL_IMAGE "\xef\x80\xbe"
|
||||
#define LV_SYMBOL_EDIT "\xef\x81\x80"
|
||||
#define LV_SYMBOL_PREV "\xef\x81\x88"
|
||||
#define LV_SYMBOL_PLAY "\xef\x81\x8b"
|
||||
#define LV_SYMBOL_PAUSE "\xef\x81\x8c"
|
||||
#define LV_SYMBOL_STOP "\xef\x81\x8d"
|
||||
#define LV_SYMBOL_NEXT "\xef\x81\x91"
|
||||
#define LV_SYMBOL_EJECT "\xef\x81\x92"
|
||||
#define LV_SYMBOL_LEFT "\xef\x81\x93"
|
||||
#define LV_SYMBOL_RIGHT "\xef\x81\x94"
|
||||
#define LV_SYMBOL_PLUS "\xef\x81\xa7"
|
||||
#define LV_SYMBOL_MINUS "\xef\x81\xa8"
|
||||
#define LV_SYMBOL_WARNING "\xef\x81\xb1"
|
||||
#define LV_SYMBOL_SHUFFLE "\xef\x81\xb4"
|
||||
#define LV_SYMBOL_UP "\xef\x81\xb7"
|
||||
#define LV_SYMBOL_DOWN "\xef\x81\xb8"
|
||||
#define LV_SYMBOL_LOOP "\xef\x81\xb9"
|
||||
#define LV_SYMBOL_DIRECTORY "\xef\x81\xbb"
|
||||
#define LV_SYMBOL_UPLOAD "\xef\x82\x93"
|
||||
#define LV_SYMBOL_CALL "\xef\x82\x95"
|
||||
#define LV_SYMBOL_CUT "\xef\x83\x84"
|
||||
#define LV_SYMBOL_COPY "\xef\x83\x85"
|
||||
#define LV_SYMBOL_SAVE "\xef\x83\x87"
|
||||
#define LV_SYMBOL_CHARGE "\xef\x83\xa7"
|
||||
#define LV_SYMBOL_BELL "\xef\x83\xb3"
|
||||
#define LV_SYMBOL_KEYBOARD "\xef\x84\x9c"
|
||||
#define LV_SYMBOL_GPS "\xef\x84\xa4"
|
||||
#define LV_SYMBOL_FILE "\xef\x85\x9b"
|
||||
#define LV_SYMBOL_WIFI "\xef\x87\xab"
|
||||
#define LV_SYMBOL_BATTERY_FULL "\xef\x89\x80"
|
||||
#define LV_SYMBOL_BATTERY_3 "\xef\x89\x81"
|
||||
#define LV_SYMBOL_BATTERY_2 "\xef\x89\x82"
|
||||
#define LV_SYMBOL_BATTERY_1 "\xef\x89\x83"
|
||||
#define LV_SYMBOL_BATTERY_EMPTY "\xef\x89\x84"
|
||||
#define LV_SYMBOL_BLUETOOTH "\xef\x8a\x93"
|
||||
#define LV_SYMBOL_AUDIO "\xef\x80\x81" /*61441, 0xF001*/
|
||||
#define LV_SYMBOL_VIDEO "\xef\x80\x88" /*61448, 0xF008*/
|
||||
#define LV_SYMBOL_LIST "\xef\x80\x8b" /*61451, 0xF00B*/
|
||||
#define LV_SYMBOL_OK "\xef\x80\x8c" /*61452, 0xF00C*/
|
||||
#define LV_SYMBOL_CLOSE "\xef\x80\x8d" /*61453, 0xF00D*/
|
||||
#define LV_SYMBOL_POWER "\xef\x80\x91" /*61457, 0xF011*/
|
||||
#define LV_SYMBOL_SETTINGS "\xef\x80\x93" /*61459, 0xF013*/
|
||||
#define LV_SYMBOL_HOME "\xef\x80\x95" /*61461, 0xF015*/
|
||||
#define LV_SYMBOL_DOWNLOAD "\xef\x80\x99" /*61465, 0xF019*/
|
||||
#define LV_SYMBOL_DRIVE "\xef\x80\x9c" /*61468, 0xF01C*/
|
||||
#define LV_SYMBOL_REFRESH "\xef\x80\xa1" /*61473, 0xF021*/
|
||||
#define LV_SYMBOL_MUTE "\xef\x80\xa6" /*61478, 0xF026*/
|
||||
#define LV_SYMBOL_VOLUME_MID "\xef\x80\xa7" /*61479, 0xF027*/
|
||||
#define LV_SYMBOL_VOLUME_MAX "\xef\x80\xa8" /*61480, 0xF028*/
|
||||
#define LV_SYMBOL_IMAGE "\xef\x80\xbe" /*61502, 0xF03E*/
|
||||
#define LV_SYMBOL_EDIT "\xef\x8C\x84" /*62212, 0xF304*/
|
||||
#define LV_SYMBOL_PREV "\xef\x81\x88" /*61512, 0xF048*/
|
||||
#define LV_SYMBOL_PLAY "\xef\x81\x8b" /*61515, 0xF04B*/
|
||||
#define LV_SYMBOL_PAUSE "\xef\x81\x8c" /*61516, 0xF04C*/
|
||||
#define LV_SYMBOL_STOP "\xef\x81\x8d" /*61517, 0xF04D*/
|
||||
#define LV_SYMBOL_NEXT "\xef\x81\x91" /*61521, 0xF051*/
|
||||
#define LV_SYMBOL_EJECT "\xef\x81\x92" /*61522, 0xF052*/
|
||||
#define LV_SYMBOL_LEFT "\xef\x81\x93" /*61523, 0xF053*/
|
||||
#define LV_SYMBOL_RIGHT "\xef\x81\x94" /*61524, 0xF054*/
|
||||
#define LV_SYMBOL_PLUS "\xef\x81\xa7" /*61543, 0xF067*/
|
||||
#define LV_SYMBOL_MINUS "\xef\x81\xa8" /*61544, 0xF068*/
|
||||
#define LV_SYMBOL_EYE_OPEN "\xef\x81\xae" /*61550, 0xF06E*/
|
||||
#define LV_SYMBOL_EYE_CLOSE "\xef\x81\xb0" /*61552, 0xF070*/
|
||||
#define LV_SYMBOL_WARNING "\xef\x81\xb1" /*61553, 0xF071*/
|
||||
#define LV_SYMBOL_SHUFFLE "\xef\x81\xb4" /*61556, 0xF074*/
|
||||
#define LV_SYMBOL_UP "\xef\x81\xb7" /*61559, 0xF077*/
|
||||
#define LV_SYMBOL_DOWN "\xef\x81\xb8" /*61560, 0xF078*/
|
||||
#define LV_SYMBOL_LOOP "\xef\x81\xb9" /*61561, 0xF079*/
|
||||
#define LV_SYMBOL_DIRECTORY "\xef\x81\xbb" /*61563, 0xF07B*/
|
||||
#define LV_SYMBOL_UPLOAD "\xef\x82\x93" /*61587, 0xF093*/
|
||||
#define LV_SYMBOL_CALL "\xef\x82\x95" /*61589, 0xF095*/
|
||||
#define LV_SYMBOL_CUT "\xef\x83\x84" /*61636, 0xF0C4*/
|
||||
#define LV_SYMBOL_COPY "\xef\x83\x85" /*61637, 0xF0C5*/
|
||||
#define LV_SYMBOL_SAVE "\xef\x83\x87" /*61639, 0xF0C7*/
|
||||
#define LV_SYMBOL_CHARGE "\xef\x83\xa7" /*61671, 0xF0E7*/
|
||||
#define LV_SYMBOL_PASTE "\xef\x83\xAA" /*61674, 0xF0EA*/
|
||||
#define LV_SYMBOL_BELL "\xef\x83\xb3" /*61683, 0xF0F3*/
|
||||
#define LV_SYMBOL_KEYBOARD "\xef\x84\x9c" /*61724, 0xF11C*/
|
||||
#define LV_SYMBOL_GPS "\xef\x84\xa4" /*61732, 0xF124*/
|
||||
#define LV_SYMBOL_FILE "\xef\x85\x9b" /*61787, 0xF158*/
|
||||
#define LV_SYMBOL_WIFI "\xef\x87\xab" /*61931, 0xF1EB*/
|
||||
#define LV_SYMBOL_BATTERY_FULL "\xef\x89\x80" /*62016, 0xF240*/
|
||||
#define LV_SYMBOL_BATTERY_3 "\xef\x89\x81" /*62017, 0xF241*/
|
||||
#define LV_SYMBOL_BATTERY_2 "\xef\x89\x82" /*62018, 0xF242*/
|
||||
#define LV_SYMBOL_BATTERY_1 "\xef\x89\x83" /*62019, 0xF243*/
|
||||
#define LV_SYMBOL_BATTERY_EMPTY "\xef\x89\x84" /*62020, 0xF244*/
|
||||
#define LV_SYMBOL_USB "\xef\x8a\x87" /*62087, 0xF287*/
|
||||
#define LV_SYMBOL_BLUETOOTH "\xef\x8a\x93" /*62099, 0xF293*/
|
||||
#define LV_SYMBOL_TRASH "\xef\x8B\xAD" /*62189, 0xF2ED*/
|
||||
#define LV_SYMBOL_BACKSPACE "\xef\x95\x9A" /*62810, 0xF55A*/
|
||||
#define LV_SYMBOL_SD_CARD "\xef\x9F\x82" /*63426, 0xF7C2*/
|
||||
#define LV_SYMBOL_NEW_LINE "\xef\xA2\xA2" /*63650, 0xF8A2*/
|
||||
|
||||
/** Invalid symbol at (U+F8FF). If written before a string then `lv_img` will show it as a label*/
|
||||
#define LV_SYMBOL_DUMMY "\xEF\xA3\xBF"
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include "lv_hal.h"
|
||||
#include "../lv_core/lv_debug.h"
|
||||
#include "../lv_misc/lv_mem.h"
|
||||
#include "../lv_core/lv_obj.h"
|
||||
#include "../lv_core/lv_refr.h"
|
||||
@@ -118,7 +119,7 @@ lv_disp_t * lv_disp_drv_register(lv_disp_drv_t * driver)
|
||||
{
|
||||
lv_disp_t * disp = lv_ll_ins_head(&LV_GC_ROOT(_lv_disp_ll));
|
||||
if(!disp) {
|
||||
lv_mem_assert(disp);
|
||||
LV_ASSERT_MEM(disp);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -147,7 +148,7 @@ lv_disp_t * lv_disp_drv_register(lv_disp_drv_t * driver)
|
||||
|
||||
/*Create a refresh task*/
|
||||
disp->refr_task = lv_task_create(lv_disp_refr_task, LV_DISP_DEF_REFR_PERIOD, LV_TASK_PRIO_MID, disp);
|
||||
lv_mem_assert(disp->refr_task);
|
||||
LV_ASSERT_MEM(disp->refr_task);
|
||||
if(disp->refr_task == NULL) return NULL;
|
||||
|
||||
lv_task_ready(disp->refr_task); /*Be sure the screen will be refreshed immediately on start up*/
|
||||
@@ -267,14 +268,14 @@ bool lv_disp_get_antialiasing(lv_disp_t * disp)
|
||||
*/
|
||||
LV_ATTRIBUTE_FLUSH_READY void lv_disp_flush_ready(lv_disp_drv_t * disp_drv)
|
||||
{
|
||||
disp_drv->buffer->flushing = 0;
|
||||
|
||||
/*If the screen is transparent initialize it when the flushing is ready*/
|
||||
#if LV_COLOR_SCREEN_TRANSP
|
||||
if(disp_drv->screen_transp) {
|
||||
memset(disp_drv->buffer->buf_act, 0x00, disp_drv->buffer->size * sizeof(lv_color32_t));
|
||||
}
|
||||
#endif
|
||||
|
||||
disp_drv->buffer->flushing = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "../lv_core/lv_debug.h"
|
||||
#include "../lv_hal/lv_hal_indev.h"
|
||||
#include "../lv_core/lv_indev.h"
|
||||
#include "../lv_misc/lv_mem.h"
|
||||
@@ -77,7 +78,7 @@ lv_indev_t * lv_indev_drv_register(lv_indev_drv_t * driver)
|
||||
|
||||
lv_indev_t * indev = lv_ll_ins_head(&LV_GC_ROOT(_lv_indev_ll));
|
||||
if(!indev) {
|
||||
lv_mem_assert(indev);
|
||||
LV_ASSERT_MEM(indev);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
#if LV_USE_ANIMATION
|
||||
#include <stddef.h>
|
||||
#include <string.h>
|
||||
#include "../lv_core/lv_debug.h"
|
||||
#include "../lv_hal/lv_hal_tick.h"
|
||||
#include "lv_task.h"
|
||||
#include "lv_math.h"
|
||||
@@ -89,7 +90,7 @@ void lv_anim_create(lv_anim_t * a)
|
||||
|
||||
/*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_mem_assert(new_anim);
|
||||
LV_ASSERT_MEM(new_anim);
|
||||
if(new_anim == NULL) return;
|
||||
|
||||
/*Initialize the animation descriptor*/
|
||||
|
||||
@@ -129,10 +129,10 @@ static inline void lv_anim_set_exec_cb(lv_anim_t * a, void * var, lv_anim_exec_x
|
||||
* @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, uint16_t delay)
|
||||
static inline void lv_anim_set_time(lv_anim_t * a, uint16_t duration, int16_t delay)
|
||||
{
|
||||
a->time = duration;
|
||||
a->act_time = -delay;
|
||||
a->act_time = (int16_t)(-delay);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -192,6 +192,19 @@ bool lv_area_is_in(const lv_area_t * ain_p, const lv_area_t * aholder_p)
|
||||
return is_in;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
void lv_area_increment(lv_area_t * a_p, const lv_coord_t amount)
|
||||
{
|
||||
a_p->x1 -= amount;
|
||||
a_p->y1 -= amount;
|
||||
a_p->x2 += amount;
|
||||
a_p->y2 += amount;
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
@@ -29,6 +29,9 @@ extern "C" {
|
||||
#define LV_COORD_MAX ((lv_coord_t)((uint32_t)((uint32_t)1 << (8 * sizeof(lv_coord_t) - 1)) - 1000))
|
||||
#define LV_COORD_MIN (-LV_COORD_MAX)
|
||||
|
||||
LV_EXPORT_CONST_INT(LV_COORD_MAX);
|
||||
LV_EXPORT_CONST_INT(LV_COORD_MIN);
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
@@ -82,7 +85,7 @@ inline static void lv_area_copy(lv_area_t * dest, const lv_area_t * src)
|
||||
*/
|
||||
static inline lv_coord_t lv_area_get_width(const lv_area_t * area_p)
|
||||
{
|
||||
return area_p->x2 - area_p->x1 + 1;
|
||||
return (lv_coord_t)(area_p->x2 - area_p->x1 + 1);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -92,7 +95,7 @@ static inline lv_coord_t lv_area_get_width(const lv_area_t * area_p)
|
||||
*/
|
||||
static inline lv_coord_t lv_area_get_height(const lv_area_t * area_p)
|
||||
{
|
||||
return area_p->y2 - area_p->y1 + 1;
|
||||
return (lv_coord_t)(area_p->y2 - area_p->y1 + 1);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -165,6 +168,13 @@ bool lv_area_is_on(const lv_area_t * a1_p, const lv_area_t * a2_p);
|
||||
*/
|
||||
bool lv_area_is_in(const lv_area_t * ain_p, const lv_area_t * aholder_p);
|
||||
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
void lv_area_increment(lv_area_t * a_p, const lv_coord_t amount);
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
540
src/lv_misc/lv_bidi.c
Normal file
540
src/lv_misc/lv_bidi.c
Normal file
@@ -0,0 +1,540 @@
|
||||
/**
|
||||
* @file lv_bidi.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include <stddef.h>
|
||||
#include "lv_bidi.h"
|
||||
#include "lv_txt.h"
|
||||
#include "../lv_draw/lv_draw.h"
|
||||
|
||||
#if LV_USE_BIDI
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
#define LV_BIDI_BRACKLET_DEPTH 4
|
||||
|
||||
// Highest bit of the 16-bit pos_conv value specifies whether this pos is RTL or not
|
||||
#define GET_POS(x) ((x) & 0x7FFF)
|
||||
#define IS_RTL_POS(x) (((x) & 0x8000) != 0)
|
||||
#define SET_RTL_POS(x, is_rtl) (GET_POS(x) | ((is_rtl)? 0x8000: 0))
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
typedef struct
|
||||
{
|
||||
uint32_t bracklet_pos;
|
||||
lv_bidi_dir_t dir;
|
||||
}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 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 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);
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
static const uint8_t bracket_left[] = {"<({["};
|
||||
static const uint8_t bracket_right[] = {">)}]"};
|
||||
static bracket_stack_t br_stack[LV_BIDI_BRACKLET_DEPTH];
|
||||
static uint8_t br_stack_p;
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
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);
|
||||
|
||||
uint32_t par_start = 0;
|
||||
uint32_t par_len;
|
||||
|
||||
while(str_in[par_start] == '\n' || str_in[par_start] == '\r') {
|
||||
str_out[par_start] = str_in[par_start];
|
||||
par_start ++;
|
||||
}
|
||||
|
||||
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);
|
||||
par_start += par_len;
|
||||
|
||||
while(str_in[par_start] == '\n' || str_in[par_start] == '\r') {
|
||||
str_out[par_start] = str_in[par_start];
|
||||
par_start ++;
|
||||
}
|
||||
}
|
||||
|
||||
str_out[par_start] = '\0';
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
lv_bidi_dir_t dir;
|
||||
dir = lv_bidi_get_letter_dir(letter);
|
||||
if(dir == LV_BIDI_DIR_RTL || dir == LV_BIDI_DIR_LTR) return dir;
|
||||
}
|
||||
|
||||
/*If there were no strong char earlier return with the default base dir */
|
||||
if(LV_BIDI_BASE_DIR_DEF == LV_BIDI_DIR_AUTO) return LV_BIDI_DIR_LTR;
|
||||
else return LV_BIDI_BASE_DIR_DEF;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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);
|
||||
void *buf = lv_draw_get_buf(len + pos_conv_len * sizeof(uint16_t));
|
||||
if (bidi_txt) *bidi_txt = buf;
|
||||
uint16_t *pos_conv_buf = (uint16_t*) ((char*)buf + len);
|
||||
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]);
|
||||
}
|
||||
|
||||
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);
|
||||
void *buf = lv_draw_get_buf(len + pos_conv_len * sizeof(uint16_t));
|
||||
if (bidi_txt) *bidi_txt = buf;
|
||||
uint16_t *pos_conv_buf = (uint16_t*) ((char*)buf + len);
|
||||
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]);
|
||||
return i;
|
||||
}
|
||||
}
|
||||
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)
|
||||
{
|
||||
uint32_t run_len = 0;
|
||||
lv_bidi_dir_t run_dir;
|
||||
uint32_t rd = 0;
|
||||
uint32_t wr;
|
||||
uint16_t pos_conv_run_len = 0;
|
||||
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_RTL) {
|
||||
wr = len;
|
||||
pos_conv_wr = pos_conv_len;
|
||||
}
|
||||
else {
|
||||
wr = 0;
|
||||
pos_conv_wr = 0;
|
||||
}
|
||||
|
||||
if (str_out) str_out[len] = '\0';
|
||||
|
||||
lv_bidi_dir_t dir = base_dir;
|
||||
|
||||
/*Empty the bracket stack*/
|
||||
br_stack_p = 0;
|
||||
|
||||
/*Process neutral chars in the beginning*/
|
||||
while(rd < len) {
|
||||
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);
|
||||
if(dir != LV_BIDI_DIR_NEUTRAL && dir != LV_BIDI_DIR_WEAK) break;
|
||||
}
|
||||
|
||||
if(rd && str_in[rd] != '\0') {
|
||||
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);
|
||||
wr += rd;
|
||||
}
|
||||
if (pos_conv_out) {
|
||||
fill_pos_conv(&pos_conv_out[pos_conv_wr], pos_conv_rd, 0);
|
||||
pos_conv_wr += pos_conv_rd;
|
||||
}
|
||||
} 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);
|
||||
}
|
||||
}
|
||||
|
||||
/*Get and process the runs*/
|
||||
|
||||
while(rd < len && str_in[rd]) {
|
||||
run_dir = get_next_run(&str_in[rd], base_dir, len - rd, &run_len, &pos_conv_run_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);
|
||||
}
|
||||
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);
|
||||
}
|
||||
|
||||
rd += run_len;
|
||||
pos_conv_rd += pos_conv_run_len;
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t lv_bidi_get_next_paragraph(const char * txt)
|
||||
{
|
||||
uint32_t i = 0;
|
||||
|
||||
lv_txt_encoded_next(txt, &i);
|
||||
|
||||
while(txt[i] != '\0' && txt[i] != '\n' && txt[i] != '\r') {
|
||||
lv_txt_encoded_next(txt, &i);
|
||||
}
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
static uint32_t get_txt_len(const char * txt, uint32_t max_len)
|
||||
{
|
||||
uint32_t len = 0;
|
||||
uint32_t i = 0;
|
||||
|
||||
while(i < max_len && txt[i] != '\0') {
|
||||
lv_txt_encoded_next(txt, &i);
|
||||
len++;
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
static void fill_pos_conv(uint16_t * out, uint16_t len, uint16_t index)
|
||||
{
|
||||
for (uint16_t 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)
|
||||
{
|
||||
uint32_t i = 0;
|
||||
uint32_t letter;
|
||||
|
||||
uint16_t pos_conv_i = 0;
|
||||
|
||||
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);
|
||||
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);
|
||||
|
||||
if(i >= max_len || txt[i] == '\0' || txt[i] == '\n' || txt[i] == '\r') {
|
||||
*len = i;
|
||||
*pos_conv_len = pos_conv_i;
|
||||
return base_dir;
|
||||
}
|
||||
}
|
||||
|
||||
lv_bidi_dir_t run_dir = dir;
|
||||
|
||||
uint32_t i_prev = i;
|
||||
uint32_t i_last_strong = i;
|
||||
uint16_t pos_conv_i_prev = pos_conv_i;
|
||||
uint16_t pos_conv_i_last_strong = pos_conv_i;
|
||||
|
||||
/*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);
|
||||
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);
|
||||
|
||||
/*New dir found?*/
|
||||
if((next_dir == LV_BIDI_DIR_RTL || next_dir == LV_BIDI_DIR_LTR) && next_dir != run_dir) {
|
||||
/*Include neutrals if `run_dir == base_dir` */
|
||||
if(run_dir == base_dir) {
|
||||
*len = i_prev;
|
||||
*pos_conv_len = pos_conv_i_prev;
|
||||
}
|
||||
/*Exclude neutrals if `run_dir != base_dir` */
|
||||
else {
|
||||
*len = i_last_strong;
|
||||
*pos_conv_len = pos_conv_i_last_strong;
|
||||
}
|
||||
|
||||
return run_dir;
|
||||
}
|
||||
|
||||
if(next_dir != LV_BIDI_DIR_NEUTRAL) {
|
||||
i_last_strong = i;
|
||||
pos_conv_i_last_strong = pos_conv_i;
|
||||
}
|
||||
|
||||
i_prev = i;
|
||||
pos_conv_i_prev = pos_conv_i;
|
||||
}
|
||||
|
||||
/*Handle end of of string. Apply `base_dir` on trailing neutrals*/
|
||||
|
||||
/*Include neutrals if `run_dir == base_dir` */
|
||||
if(run_dir == base_dir) {
|
||||
*len = i_prev;
|
||||
*pos_conv_len = pos_conv_i_prev;
|
||||
}
|
||||
/*Exclude neutrals if `run_dir != base_dir` */
|
||||
else {
|
||||
*len = i_last_strong;
|
||||
*pos_conv_len = pos_conv_i_last_strong;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
uint32_t i = len;
|
||||
uint32_t wr = 0;
|
||||
uint16_t pos_conv_i = pos_conv_len;
|
||||
uint16_t pos_conv_wr = 0;
|
||||
|
||||
while(i) {
|
||||
uint32_t letter = lv_txt_encoded_prev(src, &i);
|
||||
uint16_t pos_conv_letter = --pos_conv_i;
|
||||
|
||||
/*Keep weak letters (numbers) as LTR*/
|
||||
if(lv_bidi_letter_is_weak(letter)) {
|
||||
uint32_t last_weak = i;
|
||||
uint32_t first_weak = i;
|
||||
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);
|
||||
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*/
|
||||
pos_conv_i++;
|
||||
first_weak = i;
|
||||
pos_conv_first_weak = pos_conv_i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(i == 0) {
|
||||
first_weak = 0;
|
||||
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);
|
||||
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]);
|
||||
/*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);
|
||||
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);
|
||||
wr += letter_size;
|
||||
pos_conv_wr++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static uint32_t char_change_to_pair(uint32_t letter)
|
||||
{
|
||||
|
||||
uint8_t i;
|
||||
for(i = 0; bracket_left[i] != '\0'; i++) {
|
||||
if(letter == bracket_left[i]) return bracket_right[i];
|
||||
}
|
||||
|
||||
for(i = 0; bracket_right[i] != '\0'; i++) {
|
||||
if(letter == bracket_right[i]) return bracket_left[i];
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
lv_bidi_dir_t bracket_dir = LV_BIDI_DIR_NEUTRAL;
|
||||
|
||||
uint8_t i;
|
||||
/*Is the letter an opening bracket?*/
|
||||
for(i = 0; bracket_left[i] != '\0'; i++) {
|
||||
if(bracket_left[i] == letter) {
|
||||
/* If so find it's matching closing bracket.
|
||||
* 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);
|
||||
if(letter_next == bracket_right[i]) {
|
||||
/*Closing bracket found*/
|
||||
break;
|
||||
} else {
|
||||
/*Save the dir*/
|
||||
lv_bidi_dir_t letter_dir = lv_bidi_get_letter_dir(letter_next);
|
||||
if(letter_dir == base_dir) {
|
||||
bracket_dir = base_dir;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*There were no matching closing bracket*/
|
||||
if(txt_i > len) return LV_BIDI_DIR_NEUTRAL;
|
||||
|
||||
/*There where a strong char with base dir in the bracket so the dir is found.*/
|
||||
if(bracket_dir != LV_BIDI_DIR_NEUTRAL && bracket_dir != LV_BIDI_DIR_WEAK) break;
|
||||
|
||||
/*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);
|
||||
while(txt_i > 0) {
|
||||
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;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*There where a previous strong char which can be used*/
|
||||
if(bracket_dir != LV_BIDI_DIR_NEUTRAL) break;
|
||||
|
||||
/*There were no strong chars before the bracket, so use the base dir.*/
|
||||
if(txt_i == 0) bracket_dir = base_dir;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*The letter was an opening bracket*/
|
||||
if(bracket_left[i] != '\0') {
|
||||
|
||||
if(bracket_dir == LV_BIDI_DIR_NEUTRAL || br_stack_p == LV_BIDI_BRACKLET_DEPTH) return LV_BIDI_DIR_NEUTRAL;
|
||||
|
||||
br_stack[br_stack_p].bracklet_pos = i;
|
||||
br_stack[br_stack_p].dir = bracket_dir;
|
||||
|
||||
br_stack_p++;
|
||||
return bracket_dir;
|
||||
} 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;
|
||||
br_stack_p--;
|
||||
return bracket_dir;
|
||||
}
|
||||
}
|
||||
|
||||
return LV_BIDI_DIR_NEUTRAL;
|
||||
}
|
||||
|
||||
|
||||
#endif /*LV_USE_BIDI*/
|
||||
76
src/lv_misc/lv_bidi.h
Normal file
76
src/lv_misc/lv_bidi.h
Normal file
@@ -0,0 +1,76 @@
|
||||
/**
|
||||
* @file lv_bifi.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LV_BIDI_H
|
||||
#define LV_BIDI_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#ifdef LV_CONF_INCLUDE_SIMPLE
|
||||
#include "lv_conf.h"
|
||||
#else
|
||||
#include "../../../lv_conf.h"
|
||||
#endif
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
/* 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*/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
enum
|
||||
{
|
||||
/*The first 4 values are stored in `lv_obj_t` on 2 bits*/
|
||||
LV_BIDI_DIR_LTR = 0x00,
|
||||
LV_BIDI_DIR_RTL = 0x01,
|
||||
LV_BIDI_DIR_AUTO = 0x02,
|
||||
LV_BIDI_DIR_INHERIT = 0x03,
|
||||
|
||||
LV_BIDI_DIR_NEUTRAL = 0x20,
|
||||
LV_BIDI_DIR_WEAK = 0x21,
|
||||
};
|
||||
|
||||
typedef uint8_t lv_bidi_dir_t;
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
#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);
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#endif /*LV_USE_BIDI*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /*LV_BIDI_H*/
|
||||
@@ -7,6 +7,7 @@
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "lv_color.h"
|
||||
#include "lv_math.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
@@ -105,39 +106,66 @@ lv_color_t lv_color_hsv_to_rgb(uint16_t h, uint8_t s, uint8_t v)
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert an RGB color to HSV
|
||||
* @param r red
|
||||
* @param g green
|
||||
* @param b blue
|
||||
* @return the given RGB color n HSV
|
||||
* Convert a 32-bit RGB color to HSV
|
||||
* @param r8 8-bit red
|
||||
* @param g8 8-bit green
|
||||
* @param b8 8-bit blue
|
||||
* @return the given RGB color in HSV
|
||||
*/
|
||||
lv_color_hsv_t lv_color_rgb_to_hsv(uint8_t r, uint8_t g, uint8_t b)
|
||||
lv_color_hsv_t lv_color_rgb_to_hsv(uint8_t r8, uint8_t g8, uint8_t b8)
|
||||
{
|
||||
uint16_t r = ((uint32_t)r8 << 10) / 255;
|
||||
uint16_t g = ((uint32_t)g8 << 10) / 255;
|
||||
uint16_t b = ((uint32_t)b8 << 10) / 255;
|
||||
|
||||
uint16_t rgbMin = r < g ? (r < b ? r : b) : (g < b ? g : b);
|
||||
uint16_t rgbMax = r > g ? (r > b ? r : b) : (g > b ? g : b);
|
||||
|
||||
lv_color_hsv_t hsv;
|
||||
uint8_t rgbMin, rgbMax;
|
||||
|
||||
rgbMin = r < g ? (r < b ? r : b) : (g < b ? g : b);
|
||||
rgbMax = r > g ? (r > b ? r : b) : (g > b ? g : b);
|
||||
// https://en.wikipedia.org/wiki/HSL_and_HSV#Lightness
|
||||
hsv.v = (100 * rgbMax) >> 10;
|
||||
|
||||
hsv.v = rgbMax;
|
||||
if(hsv.v == 0) {
|
||||
int32_t delta = rgbMax - rgbMin;
|
||||
if (LV_MATH_ABS(delta) < 3) {
|
||||
hsv.h = 0;
|
||||
hsv.s = 0;
|
||||
return hsv;
|
||||
}
|
||||
|
||||
hsv.s = 255 * (long)(rgbMax - rgbMin) / hsv.v;
|
||||
if(hsv.s == 0) {
|
||||
// https://en.wikipedia.org/wiki/HSL_and_HSV#Saturation
|
||||
hsv.s = 100 * delta / rgbMax;
|
||||
if(hsv.s < 3) {
|
||||
hsv.h = 0;
|
||||
return hsv;
|
||||
}
|
||||
|
||||
// https://en.wikipedia.org/wiki/HSL_and_HSV#Hue_and_chroma
|
||||
int32_t h;
|
||||
if(rgbMax == r)
|
||||
hsv.h = 0 + 43 * (g - b) / (rgbMax - rgbMin);
|
||||
h = (((g - b) << 10) / delta) + (g < b ? (6 << 10) : 0); // between yellow & magenta
|
||||
else if(rgbMax == g)
|
||||
hsv.h = 85 + 43 * (b - r) / (rgbMax - rgbMin);
|
||||
h = (((b - r) << 10) / delta) + (2 << 10); // between cyan & yellow
|
||||
else if(rgbMax == b)
|
||||
h = (((r - g) << 10) / delta) + (4 << 10); // between magenta & cyan
|
||||
else
|
||||
hsv.h = 171 + 43 * (r - g) / (rgbMax - rgbMin);
|
||||
h = 0;
|
||||
h *= 60;
|
||||
h >>= 10;
|
||||
if (h < 0) h += 360;
|
||||
|
||||
hsv.h = h;
|
||||
return hsv;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a color to HSV
|
||||
* @param color color
|
||||
* @return the given color in HSV
|
||||
*/
|
||||
lv_color_hsv_t lv_color_to_hsv(lv_color_t color)
|
||||
{
|
||||
lv_color32_t color32;
|
||||
color32.full = lv_color_to32(color);
|
||||
return lv_color_rgb_to_hsv(color32.ch.red, color32.ch.green, color32.ch.blue);
|
||||
}
|
||||
|
||||
@@ -90,16 +90,123 @@ enum {
|
||||
#error "Invalid LV_COLOR_DEPTH in lv_conf.h! Set it to 1, 8, 16 or 32!"
|
||||
#endif
|
||||
|
||||
/*---------------------------------------
|
||||
* 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_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_SET_R8(c, v) (c).ch.red = (uint8_t)((v) & 0x7);
|
||||
# define LV_COLOR_SET_G8(c, v) (c).ch.green = (uint8_t)((v) & 0x7);
|
||||
# define LV_COLOR_SET_B8(c, v) (c).ch.blue = (uint8_t)((v) & 0x3);
|
||||
# define LV_COLOR_SET_A8(c, v) do {} while(0)
|
||||
|
||||
# define LV_COLOR_GET_R8(c) (c).ch.red
|
||||
# define LV_COLOR_GET_G8(c) (c).ch.green
|
||||
# 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)(((uint8_t)(v)) & 0x1F);
|
||||
# define LV_COLOR_SET_G16(c, v) (c).ch.green = (uint8_t)((v) & 0x3F);
|
||||
# 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) & 0x1F);
|
||||
# define LV_COLOR_SET_A16(c, v) do {} while(0)
|
||||
|
||||
# define LV_COLOR_GET_R16(c) (c).ch.red
|
||||
# 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)
|
||||
# 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);
|
||||
|
||||
# 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
|
||||
|
||||
|
||||
/*---------------------------------------
|
||||
* 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_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)
|
||||
|
||||
#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
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
typedef union
|
||||
{
|
||||
uint8_t blue : 1;
|
||||
uint8_t green : 1;
|
||||
uint8_t red : 1;
|
||||
uint8_t full : 1;
|
||||
struct
|
||||
{
|
||||
uint8_t blue : 1;
|
||||
uint8_t green : 1;
|
||||
uint8_t red : 1;
|
||||
} ch;
|
||||
uint8_t full;
|
||||
} lv_color1_t;
|
||||
|
||||
typedef union
|
||||
@@ -191,24 +298,19 @@ static inline uint8_t lv_color_to1(lv_color_t color)
|
||||
#if LV_COLOR_DEPTH == 1
|
||||
return color.full;
|
||||
#elif LV_COLOR_DEPTH == 8
|
||||
if((color.ch.red & 0x4) || (color.ch.green & 0x4) || (color.ch.blue & 0x2)) {
|
||||
if((LV_COLOR_GET_R(color) & 0x4) || (LV_COLOR_GET_G(color) & 0x4) || (LV_COLOR_GET_B(color) & 0x2)) {
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
#elif LV_COLOR_DEPTH == 16
|
||||
#if LV_COLOR_16_SWAP == 0
|
||||
if((color.ch.red & 0x10) || (color.ch.green & 0x20) || (color.ch.blue & 0x10)) {
|
||||
if((LV_COLOR_GET_R(color) & 0x10) || (LV_COLOR_GET_G(color) & 0x20) || (LV_COLOR_GET_B(color) & 0x10)) {
|
||||
return 1;
|
||||
#else
|
||||
if((color.ch.red & 0x10) || (color.ch.green_h & 0x20) || (color.ch.blue & 0x10)) {
|
||||
return 1;
|
||||
#endif
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
#elif LV_COLOR_DEPTH == 32
|
||||
if((color.ch.red & 0x80) || (color.ch.green & 0x80) || (color.ch.blue & 0x80)) {
|
||||
if((LV_COLOR_GET_R(color) & 0x80) || (LV_COLOR_GET_G(color) & 0x80) || (LV_COLOR_GET_B(color) & 0x80)) {
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
@@ -226,31 +328,23 @@ static inline uint8_t lv_color_to8(lv_color_t color)
|
||||
#elif LV_COLOR_DEPTH == 8
|
||||
return color.full;
|
||||
#elif LV_COLOR_DEPTH == 16
|
||||
|
||||
#if LV_COLOR_16_SWAP == 0
|
||||
lv_color8_t ret;
|
||||
ret.ch.red = color.ch.red >> 2; /* 5 - 3 = 2*/
|
||||
ret.ch.green = color.ch.green >> 3; /* 6 - 3 = 3*/
|
||||
ret.ch.blue = color.ch.blue >> 3; /* 5 - 2 = 3*/
|
||||
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*/
|
||||
return ret.full;
|
||||
#else
|
||||
lv_color8_t ret;
|
||||
ret.ch.red = color.ch.red >> 2; /* 5 - 3 = 2*/
|
||||
ret.ch.green = color.ch.green_h; /* 6 - 3 = 3*/
|
||||
ret.ch.blue = color.ch.blue >> 3; /* 5 - 2 = 3*/
|
||||
return ret.full;
|
||||
#endif
|
||||
#elif LV_COLOR_DEPTH == 32
|
||||
lv_color8_t ret;
|
||||
ret.ch.red = color.ch.red >> 5; /* 8 - 3 = 5*/
|
||||
ret.ch.green = color.ch.green >> 5; /* 8 - 3 = 5*/
|
||||
ret.ch.blue = color.ch.blue >> 6; /* 8 - 2 = 6*/
|
||||
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*/
|
||||
return ret.full;
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline uint16_t lv_color_to16(lv_color_t color)
|
||||
{
|
||||
|
||||
#if LV_COLOR_DEPTH == 1
|
||||
if(color.full == 0)
|
||||
return 0;
|
||||
@@ -258,34 +352,30 @@ 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
|
||||
ret.ch.red = color.ch.red * 4; /*(2^5 - 1)/(2^3 - 1) = 31/7 = 4*/
|
||||
ret.ch.green = color.ch.green * 9; /*(2^6 - 1)/(2^3 - 1) = 63/7 = 9*/
|
||||
ret.ch.blue = color.ch.blue * 10; /*(2^5 - 1)/(2^2 - 1) = 31/3 = 10*/
|
||||
LV_COLOR_SET_G16(ret, LV_COLOR_GET_G(color) * 9); /*(2^6 - 1)/(2^3 - 1) = 63/7 = 9*/
|
||||
#else
|
||||
ret.red = color.ch.red * 4;
|
||||
uint8_t g_tmp = color.ch.green * 9;
|
||||
ret.ch.green_h = (g_tmp & 0x1F) >> 3;
|
||||
ret.ch.green_l = g_tmp & 0x07;
|
||||
ret.ch.blue = color.ch.blue * 10;
|
||||
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*/
|
||||
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
|
||||
ret.ch.red = color.ch.red >> 3; /* 8 - 5 = 3*/
|
||||
ret.ch.green = color.ch.green >> 2; /* 8 - 6 = 2*/
|
||||
ret.ch.blue = color.ch.blue >> 3; /* 8 - 5 = 3*/
|
||||
LV_COLOR_SET_G16(ret, LV_COLOR_GET_G(color) >> 2); /* 8 - 6 = 2*/
|
||||
#else
|
||||
ret.ch.red = color.ch.red >> 3;
|
||||
ret.ch.green_h = (color.ch.green & 0xE0) >> 5;
|
||||
ret.ch.green_l = (color.ch.green & 0x1C) >> 2;
|
||||
ret.ch.blue = color.ch.blue >> 3;
|
||||
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*/
|
||||
return ret.full;
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline uint32_t lv_color_to32(lv_color_t color)
|
||||
@@ -297,27 +387,46 @@ static inline uint32_t lv_color_to32(lv_color_t color)
|
||||
return 0xFFFFFFFF;
|
||||
#elif LV_COLOR_DEPTH == 8
|
||||
lv_color32_t ret;
|
||||
ret.ch.red = color.ch.red * 36; /*(2^8 - 1)/(2^3 - 1) = 255/7 = 36*/
|
||||
ret.ch.green = color.ch.green * 36; /*(2^8 - 1)/(2^3 - 1) = 255/7 = 36*/
|
||||
ret.ch.blue = color.ch.blue * 85; /*(2^8 - 1)/(2^2 - 1) = 255/3 = 85*/
|
||||
ret.ch.alpha = 0xFF;
|
||||
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_A32(color, 0xFF);
|
||||
return ret.full;
|
||||
#elif LV_COLOR_DEPTH == 16
|
||||
#if LV_COLOR_16_SWAP == 0
|
||||
/**
|
||||
* The floating point math for conversion is:
|
||||
* valueto = valuefrom * ( (2^bitsto - 1) / (float)(2^bitsfrom - 1) )
|
||||
* 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
|
||||
* 1 16 14 7 255
|
||||
* 2 32 28 7 255
|
||||
* 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
|
||||
* 1 8 6 3 255
|
||||
* 2 16 12 3 255
|
||||
* 3 32 24 3 255
|
||||
* 4 64 48 3 255
|
||||
* 5 129 33 1 255
|
||||
* 6 259 3 0 255
|
||||
*/
|
||||
lv_color32_t ret;
|
||||
ret.ch.red = color.ch.red * 8; /*(2^8 - 1)/(2^5 - 1) = 255/31 = 8*/
|
||||
ret.ch.green = color.ch.green * 4; /*(2^8 - 1)/(2^6 - 1) = 255/63 = 4*/
|
||||
ret.ch.blue = color.ch.blue * 8; /*(2^8 - 1)/(2^5 - 1) = 255/31 = 8*/
|
||||
ret.ch.alpha = 0xFF;
|
||||
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;
|
||||
#else
|
||||
lv_color32_t ret;
|
||||
ret.ch.red = color.ch.red * 8; /*(2^8 - 1)/(2^5 - 1) = 255/31 = 8*/
|
||||
ret.ch.green = ((color.ch.green_h << 3) + color.ch.green_l) * 4; /*(2^8 - 1)/(2^6 - 1) = 255/63 = 4*/
|
||||
ret.ch.blue = color.ch.blue * 8; /*(2^8 - 1)/(2^5 - 1) = 255/31 = 8*/
|
||||
ret.ch.alpha = 0xFF;
|
||||
return ret.full;
|
||||
#endif
|
||||
#elif LV_COLOR_DEPTH == 32
|
||||
return color.full;
|
||||
#endif
|
||||
@@ -328,21 +437,10 @@ 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*/
|
||||
ret.ch.red = (uint16_t)((uint16_t)c1.ch.red * mix + (c2.ch.red * (255 - mix))) >> 8;
|
||||
#if LV_COLOR_DEPTH == 16 && LV_COLOR_16_SWAP
|
||||
/*If swapped Green is in 2 parts*/
|
||||
uint16_t g_1 = (c1.ch.green_h << 3) + c1.ch.green_l;
|
||||
uint16_t g_2 = (c2.ch.green_h << 3) + c2.ch.green_l;
|
||||
uint16_t g_out = (uint16_t)((uint16_t)g_1 * mix + (g_2 * (255 - mix))) >> 8;
|
||||
ret.ch.green_h = g_out >> 3;
|
||||
ret.ch.green_l = g_out & 0x7;
|
||||
#else
|
||||
ret.ch.green = (uint16_t)((uint16_t)c1.ch.green * mix + (c2.ch.green * (255 - mix))) >> 8;
|
||||
#endif
|
||||
ret.ch.blue = (uint16_t)((uint16_t)c1.ch.blue * mix + (c2.ch.blue * (255 - mix))) >> 8;
|
||||
#if LV_COLOR_DEPTH == 32
|
||||
ret.ch.alpha = 0xFF;
|
||||
#endif
|
||||
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_A(ret, 0xFF);
|
||||
#else
|
||||
/*LV_COLOR_DEPTH == 1*/
|
||||
ret.full = mix > LV_OPA_50 ? c1.full : c2.full;
|
||||
@@ -360,65 +458,31 @@ static inline uint8_t lv_color_brightness(lv_color_t color)
|
||||
{
|
||||
lv_color32_t c32;
|
||||
c32.full = lv_color_to32(color);
|
||||
uint16_t bright = 3 * c32.ch.red + c32.ch.blue + 4 * c32.ch.green;
|
||||
return (uint16_t)bright >> 3;
|
||||
uint16_t bright = (uint16_t)(3u * LV_COLOR_GET_R32(c32) + LV_COLOR_GET_B32(c32) + 4u * LV_COLOR_GET_G32(c32));
|
||||
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){(b8 >> 7 | g8 >> 7 | r8 >> 7)})
|
||||
static inline lv_color_t lv_color_make(int r8, int g8, int b8)
|
||||
{
|
||||
lv_color_t color;
|
||||
color.full = (b8 >> 7 | g8 >> 7 | r8 >> 7);
|
||||
return color;
|
||||
}
|
||||
#define LV_COLOR_MAKE(r8, g8, b8) ((lv_color_t){.full = (b8 >> 7 | g8 >> 7 | r8 >> 7)})
|
||||
#elif LV_COLOR_DEPTH == 8
|
||||
#define LV_COLOR_MAKE(r8, g8, b8) ((lv_color_t){{b8 >> 6, g8 >> 5, r8 >> 5}})
|
||||
static inline lv_color_t lv_color_make(uint8_t r8, int g8, int b8)
|
||||
{
|
||||
lv_color_t color;
|
||||
color.ch.blue = b8 >> 6;
|
||||
color.ch.green = g8 >> 5;
|
||||
color.ch.red = r8 >> 5;
|
||||
return color;
|
||||
}
|
||||
#elif LV_COLOR_DEPTH == 16
|
||||
#if LV_COLOR_16_SWAP == 0
|
||||
#define LV_COLOR_MAKE(r8, g8, b8) ((lv_color_t){{b8 >> 3, g8 >> 2, r8 >> 3}})
|
||||
static inline lv_color_t lv_color_make(uint8_t r8, uint8_t g8, uint8_t b8)
|
||||
{
|
||||
lv_color_t color;
|
||||
color.ch.blue = (uint16_t)(b8 >> 3);
|
||||
color.ch.green = (uint16_t)(g8 >> 2);
|
||||
color.ch.red = (uint16_t)(r8 >> 3);
|
||||
return color;
|
||||
}
|
||||
#else
|
||||
#define LV_COLOR_MAKE(r8, g8, b8) ((lv_color_t){{g8 >> 5, r8 >> 3, b8 >> 3, (g8 >> 2) & 0x7}})
|
||||
static inline lv_color_t lv_color_make(uint8_t r8, uint8_t g8, uint8_t b8)
|
||||
{
|
||||
lv_color_t color;
|
||||
color.ch.green_h = (uint16_t)(g8 >> 5);
|
||||
color.ch.red = (uint16_t)(r8 >> 3);
|
||||
color.ch.blue = (uint16_t)(b8 >> 3);
|
||||
color.ch.green_l = (uint16_t)((g8 >> 2) & 0x7);
|
||||
return color;
|
||||
}
|
||||
#endif
|
||||
static inline lv_color_t lv_color_make(uint8_t r8, uint8_t g8, uint8_t b8)
|
||||
#elif LV_COLOR_DEPTH == 32
|
||||
#define LV_COLOR_MAKE(r8, g8, b8) ((lv_color_t){{b8, g8, r8, 0xff}}) /*Fix 0xff alpha*/
|
||||
static inline lv_color_t lv_color_make(uint8_t r8, uint8_t g8, uint8_t b8)
|
||||
{
|
||||
lv_color_t color;
|
||||
color.ch.blue = b8;
|
||||
color.ch.green = g8;
|
||||
color.ch.red = r8;
|
||||
color.ch.alpha = 0xff;
|
||||
return color;
|
||||
}
|
||||
#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);
|
||||
}
|
||||
|
||||
static inline lv_color_t lv_color_hex(uint32_t c)
|
||||
{
|
||||
return lv_color_make((uint8_t)((c >> 16) & 0xFF), (uint8_t)((c >> 8) & 0xFF), (uint8_t)(c & 0xFF));
|
||||
@@ -440,13 +504,20 @@ static inline lv_color_t lv_color_hex3(uint32_t c)
|
||||
lv_color_t lv_color_hsv_to_rgb(uint16_t h, uint8_t s, uint8_t v);
|
||||
|
||||
/**
|
||||
* Convert an RGB color to HSV
|
||||
* @param r red
|
||||
* @param g green
|
||||
* @param b blue
|
||||
* @return the given RGB color n HSV
|
||||
* Convert a 32-bit RGB color to HSV
|
||||
* @param r8 8-bit red
|
||||
* @param g8 8-bit green
|
||||
* @param b8 8-bit blue
|
||||
* @return the given RGB color in HSV
|
||||
*/
|
||||
lv_color_hsv_t lv_color_rgb_to_hsv(uint8_t r, uint8_t g, uint8_t b);
|
||||
lv_color_hsv_t lv_color_rgb_to_hsv(uint8_t r8, uint8_t g8, uint8_t b8);
|
||||
|
||||
/**
|
||||
* Convert a color to HSV
|
||||
* @param color color
|
||||
* @return the given color in HSV
|
||||
*/
|
||||
lv_color_hsv_t lv_color_to_hsv(lv_color_t color);
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#include "lv_fs.h"
|
||||
#if LV_USE_FILESYSTEM
|
||||
|
||||
#include "../lv_core/lv_debug.h"
|
||||
#include "lv_ll.h"
|
||||
#include <string.h>
|
||||
#include "lv_gc.h"
|
||||
@@ -107,7 +108,7 @@ lv_fs_res_t lv_fs_open(lv_fs_file_t * file_p, const char * path, lv_fs_mode_t mo
|
||||
}
|
||||
|
||||
file_p->file_d = lv_mem_alloc(file_p->drv->file_size);
|
||||
lv_mem_assert(file_p->file_d);
|
||||
LV_ASSERT_MEM(file_p->file_d);
|
||||
if(file_p->file_d == NULL) {
|
||||
file_p->drv = NULL;
|
||||
return LV_FS_RES_OUT_OF_MEM; /* Out of memory */
|
||||
@@ -367,7 +368,7 @@ lv_fs_res_t lv_fs_dir_open(lv_fs_dir_t * rddir_p, const char * path)
|
||||
}
|
||||
|
||||
rddir_p->dir_d = lv_mem_alloc(rddir_p->drv->rddir_size);
|
||||
lv_mem_assert(rddir_p->dir_d);
|
||||
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 */
|
||||
@@ -486,7 +487,7 @@ 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));
|
||||
lv_mem_assert(new_drv);
|
||||
LV_ASSERT_MEM(new_drv);
|
||||
if(new_drv == NULL) return;
|
||||
|
||||
memcpy(new_drv, drv_p, sizeof(lv_fs_drv_t));
|
||||
|
||||
@@ -29,6 +29,7 @@ extern "C" {
|
||||
* DEFINES
|
||||
*********************/
|
||||
#define LV_FS_MAX_FN_LENGTH 64
|
||||
#define LV_FS_MAX_PATH_LENGTH 256
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
#if LV_LOG_PRINTF
|
||||
#include <stdio.h>
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
@@ -33,6 +33,12 @@ extern "C" {
|
||||
#define LV_LOG_LEVEL_NONE 4 /**< Do not log anything*/
|
||||
#define _LV_LOG_LEVEL_NUM 5 /**< 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_NONE);
|
||||
|
||||
typedef int8_t lv_log_level_t;
|
||||
|
||||
#if LV_USE_LOG
|
||||
|
||||
@@ -94,6 +94,110 @@ int32_t lv_bezier3(uint32_t t, int32_t u0, int32_t u1, int32_t u2, int32_t u3)
|
||||
return v1 + v2 + v3 + v4;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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)
|
||||
{
|
||||
// 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
|
||||
// within +/- 1 degree of the accurate value without needing
|
||||
// large slow trig functions like ArcTan() or ArcCos().
|
||||
// NOTE! at least one of the X or Y values must be non-zero!
|
||||
// This is the full version, for all 4 quadrants and will generate
|
||||
// the angle in integer degrees from 0-360.
|
||||
// Any values of X and Y are usable including negative values provided
|
||||
// they are between -1456 and 1456 so the 16bit multiply does not overflow.
|
||||
|
||||
unsigned char negflag;
|
||||
unsigned char tempdegree;
|
||||
unsigned char comp;
|
||||
unsigned int degree; // this will hold the result
|
||||
//signed int x; // these hold the XY vector at the start
|
||||
//signed int y; // (and they will be destroyed)
|
||||
unsigned int ux;
|
||||
unsigned int uy;
|
||||
|
||||
// Save the sign flags then remove signs and get XY as unsigned ints
|
||||
negflag = 0;
|
||||
if(x < 0) {
|
||||
negflag += 0x01; // x flag bit
|
||||
x = (0 - x); // is now +
|
||||
}
|
||||
ux = x; // copy to unsigned var before multiply
|
||||
if(y < 0) {
|
||||
negflag += 0x02; // y flag bit
|
||||
y = (0 - y); // is now +
|
||||
}
|
||||
uy = y; // copy to unsigned var before multiply
|
||||
|
||||
// 1. Calc the scaled "degrees"
|
||||
if(ux > uy) {
|
||||
degree = (uy * 45) / ux; // degree result will be 0-45 range
|
||||
negflag += 0x10; // octant flag bit
|
||||
} else {
|
||||
degree = (ux * 45) / uy; // degree result will be 0-45 range
|
||||
}
|
||||
|
||||
// 2. Compensate for the 4 degree error curve
|
||||
comp = 0;
|
||||
tempdegree = degree; // use an unsigned char for speed!
|
||||
if(tempdegree > 22) { // if top half of range
|
||||
if(tempdegree <= 44) comp++;
|
||||
if(tempdegree <= 41) comp++;
|
||||
if(tempdegree <= 37) comp++;
|
||||
if(tempdegree <= 32) comp++; // max is 4 degrees compensated
|
||||
} else { // else is lower half of range
|
||||
if(tempdegree >= 2) comp++;
|
||||
if(tempdegree >= 6) comp++;
|
||||
if(tempdegree >= 10) comp++;
|
||||
if(tempdegree >= 15) comp++; // max is 4 degrees compensated
|
||||
}
|
||||
degree += comp; // degree is now accurate to +/- 1 degree!
|
||||
|
||||
// Invert degree if it was X>Y octant, makes 0-45 into 90-45
|
||||
if(negflag & 0x10) degree = (90 - degree);
|
||||
|
||||
// 3. Degree is now 0-90 range for this quadrant,
|
||||
// need to invert it for whichever quadrant it was in
|
||||
if(negflag & 0x02) { // if -Y
|
||||
if(negflag & 0x01) // if -Y -X
|
||||
degree = (180 + degree);
|
||||
else // else is -Y +X
|
||||
degree = (180 - degree);
|
||||
} else { // else is +Y
|
||||
if(negflag & 0x01) // if +Y -X
|
||||
degree = (360 - degree);
|
||||
}
|
||||
return degree;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate the integer square root of a number.
|
||||
* @param num
|
||||
* @return square root of 'num'
|
||||
*/
|
||||
uint32_t lv_sqrt(uint32_t num)
|
||||
{
|
||||
// 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;
|
||||
}
|
||||
return root;
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
@@ -54,6 +54,21 @@ int16_t lv_trigo_sin(int16_t angle);
|
||||
*/
|
||||
int32_t lv_bezier3(uint32_t t, int32_t u0, int32_t u1, int32_t u2, int32_t u3);
|
||||
|
||||
/**
|
||||
* 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);
|
||||
|
||||
/**
|
||||
* Calculate the integer square root of a number.
|
||||
* @param num
|
||||
* @return square root of 'num'
|
||||
*/
|
||||
uint32_t lv_sqrt(uint32_t num);
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
@@ -19,7 +19,9 @@
|
||||
* DEFINES
|
||||
*********************/
|
||||
/*Add memory junk on alloc (0xaa) and free(0xbb) (just for testing purposes)*/
|
||||
#define LV_MEM_ADD_JUNK 1
|
||||
#ifndef LV_MEM_ADD_JUNK
|
||||
#define LV_MEM_ADD_JUNK 0
|
||||
#endif
|
||||
|
||||
#ifdef LV_MEM_ENV64
|
||||
#define MEM_UNIT uint64_t
|
||||
|
||||
@@ -110,27 +110,6 @@ uint32_t lv_mem_get_size(const void * data);
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Halt on NULL pointer
|
||||
* p pointer to a memory
|
||||
*/
|
||||
#if LV_USE_LOG == 0
|
||||
#define lv_mem_assert(p) \
|
||||
{ \
|
||||
if(p == NULL) \
|
||||
while(1) \
|
||||
; \
|
||||
}
|
||||
#else
|
||||
#define lv_mem_assert(p) \
|
||||
{ \
|
||||
if(p == NULL) { \
|
||||
LV_LOG_ERROR("Out of memory!"); \
|
||||
while(1) \
|
||||
; \
|
||||
} \
|
||||
}
|
||||
#endif
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
@@ -12,6 +12,9 @@ CSRCS += lv_log.c
|
||||
CSRCS += lv_gc.c
|
||||
CSRCS += lv_utils.c
|
||||
CSRCS += lv_async.c
|
||||
CSRCS += lv_printf.c
|
||||
CSRCS += lv_bidi.c
|
||||
|
||||
|
||||
DEPPATH += --dep-path $(LVGL_DIR)/lvgl/src/lv_misc
|
||||
VPATH += :$(LVGL_DIR)/lvgl/src/lv_misc
|
||||
|
||||
852
src/lv_misc/lv_printf.c
Normal file
852
src/lv_misc/lv_printf.c
Normal file
@@ -0,0 +1,852 @@
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// \author (c) Marco Paland (info@paland.com)
|
||||
// 2014-2019, PALANDesign Hannover, Germany
|
||||
//
|
||||
// \license The MIT License (MIT)
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// 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
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
//
|
||||
// \brief Tiny printf, sprintf and (v)snprintf implementation, optimized for speed on
|
||||
// embedded systems with a very limited resources. These routines are thread
|
||||
// safe and reentrant!
|
||||
// Use this instead of the bloated standard/newlib printf cause these use
|
||||
// malloc for printf (and may not be thread safe).
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "lv_printf.h"
|
||||
|
||||
#if LV_SPRINTF_CUSTOM == 0
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
|
||||
// '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
|
||||
#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
|
||||
#endif
|
||||
|
||||
// support for the floating point type (%f)
|
||||
// default: activated
|
||||
#ifndef 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
|
||||
#endif
|
||||
|
||||
// define the default floating point precision
|
||||
// default: 6 digits
|
||||
#ifndef PRINTF_DEFAULT_FLOAT_PRECISION
|
||||
#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
|
||||
#endif
|
||||
|
||||
// support for the long long types (%llu or %p)
|
||||
// default: activated
|
||||
#ifndef PRINTF_DISABLE_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
|
||||
#endif
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// internal flag definitions
|
||||
#define FLAGS_ZEROPAD (1U << 0U)
|
||||
#define FLAGS_LEFT (1U << 1U)
|
||||
#define FLAGS_PLUS (1U << 2U)
|
||||
#define FLAGS_SPACE (1U << 3U)
|
||||
#define FLAGS_HASH (1U << 4U)
|
||||
#define FLAGS_UPPERCASE (1U << 5U)
|
||||
#define FLAGS_CHAR (1U << 6U)
|
||||
#define FLAGS_SHORT (1U << 7U)
|
||||
#define FLAGS_LONG (1U << 8U)
|
||||
#define FLAGS_LONG_LONG (1U << 9U)
|
||||
#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>
|
||||
#endif
|
||||
|
||||
|
||||
// output function type
|
||||
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;
|
||||
} out_fct_wrap_type;
|
||||
|
||||
|
||||
// internal buffer output
|
||||
static inline void _out_buffer(char character, void* buffer, size_t idx, size_t maxlen)
|
||||
{
|
||||
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)
|
||||
{
|
||||
(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)
|
||||
{
|
||||
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');
|
||||
}
|
||||
|
||||
|
||||
// internal ASCII string to unsigned int conversion
|
||||
static unsigned int _atoi(const char** str)
|
||||
{
|
||||
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)
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
// 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);
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
// 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';
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
// 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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
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);
|
||||
#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)
|
||||
{
|
||||
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);
|
||||
#else
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
#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)
|
||||
{
|
||||
// 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 {
|
||||
// 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)
|
||||
{
|
||||
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;
|
||||
}
|
||||
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;
|
||||
}
|
||||
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);
|
||||
#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) {
|
||||
#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);
|
||||
#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;
|
||||
}
|
||||
#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;
|
||||
#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;
|
||||
#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;
|
||||
#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 {
|
||||
#endif
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
// termination
|
||||
out((char)0, buffer, idx < maxlen ? idx : maxlen - 1U, maxlen);
|
||||
|
||||
// return written chars without terminating \0
|
||||
return (int)idx;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
int lv_vsnprintf(char* buffer, size_t count, const char* format, va_list va)
|
||||
{
|
||||
return _vsnprintf(_out_buffer, buffer, count, format, va);
|
||||
}
|
||||
|
||||
#endif /*LV_SPRINTF_CUSTOM*/
|
||||
|
||||
75
src/lv_misc/lv_printf.h
Normal file
75
src/lv_misc/lv_printf.h
Normal file
@@ -0,0 +1,75 @@
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// \author (c) Marco Paland (info@paland.com)
|
||||
// 2014-2019, PALANDesign Hannover, Germany
|
||||
//
|
||||
// \license The MIT License (MIT)
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// 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
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
//
|
||||
// \brief Tiny printf, sprintf and snprintf implementation, optimized for speed on
|
||||
// embedded systems with a very limited resources.
|
||||
// Use this instead of bloated standard/newlib printf.
|
||||
// These routines are thread safe and reentrant.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#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
|
||||
|
||||
#if LV_SPRINTF_CUSTOM == 0
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stddef.h>
|
||||
|
||||
/**
|
||||
* Tiny snprintf/vsnprintf implementation
|
||||
* \param buffer A pointer to the buffer where to store the formatted string
|
||||
* \param count The maximum number of characters to store in the buffer, including a terminating null character
|
||||
* \param format A string that specifies the format of the output
|
||||
* \param va A value identifying a variable arguments list
|
||||
* \return The number of characters that COULD have been written into the buffer, not counting the terminating
|
||||
* 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);
|
||||
|
||||
#else
|
||||
#include LV_SPRINTF_INCLUDE
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#endif // _PRINTF_H_
|
||||
@@ -9,6 +9,7 @@
|
||||
*********************/
|
||||
#include <stddef.h>
|
||||
#include "lv_task.h"
|
||||
#include "../lv_core/lv_debug.h"
|
||||
#include "../lv_hal/lv_hal_tick.h"
|
||||
#include "lv_gc.h"
|
||||
|
||||
@@ -67,16 +68,16 @@ LV_ATTRIBUTE_TASK_HANDLER void lv_task_handler(void)
|
||||
LV_LOG_TRACE("lv_task_handler started");
|
||||
|
||||
/*Avoid concurrent running of the task handler*/
|
||||
static bool task_handler_mutex = false;
|
||||
if(task_handler_mutex) return;
|
||||
task_handler_mutex = true;
|
||||
static bool already_running = false;
|
||||
if(already_running) return;
|
||||
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) {
|
||||
task_handler_mutex = false; /*Release mutex*/
|
||||
already_running = false; /*Release mutex*/
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -160,7 +161,7 @@ LV_ATTRIBUTE_TASK_HANDLER void lv_task_handler(void)
|
||||
idle_period_start = lv_tick_get();
|
||||
}
|
||||
|
||||
task_handler_mutex = false; /*Release the mutex*/
|
||||
already_running = false; /*Release the mutex*/
|
||||
|
||||
LV_LOG_TRACE("lv_task_handler ready");
|
||||
}
|
||||
@@ -180,7 +181,7 @@ lv_task_t * lv_task_create_basic(void)
|
||||
/*It's the first task*/
|
||||
if(NULL == tmp) {
|
||||
new_task = lv_ll_ins_head(&LV_GC_ROOT(_lv_task_ll));
|
||||
lv_mem_assert(new_task);
|
||||
LV_ASSERT_MEM(new_task);
|
||||
if(new_task == NULL) return NULL;
|
||||
}
|
||||
/*Insert the new task to proper place according to its priority*/
|
||||
@@ -188,7 +189,7 @@ lv_task_t * lv_task_create_basic(void)
|
||||
do {
|
||||
if(tmp->prio <= DEF_PRIO) {
|
||||
new_task = lv_ll_ins_prev(&LV_GC_ROOT(_lv_task_ll), tmp);
|
||||
lv_mem_assert(new_task);
|
||||
LV_ASSERT_MEM(new_task);
|
||||
if(new_task == NULL) return NULL;
|
||||
break;
|
||||
}
|
||||
@@ -198,7 +199,7 @@ lv_task_t * lv_task_create_basic(void)
|
||||
/*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));
|
||||
lv_mem_assert(new_task);
|
||||
LV_ASSERT_MEM(new_task);
|
||||
if(new_task == NULL) return NULL;
|
||||
}
|
||||
}
|
||||
@@ -230,7 +231,7 @@ lv_task_t * lv_task_create_basic(void)
|
||||
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_mem_assert(new_task);
|
||||
LV_ASSERT_MEM(new_task);
|
||||
if(new_task == NULL) return NULL;
|
||||
|
||||
lv_task_set_cb(new_task, task_cb);
|
||||
|
||||
@@ -56,7 +56,7 @@ uint32_t (*lv_txt_encoded_conv_wc)(uint32_t) = lv_txt_utf8_con
|
||||
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_encoded_get_char_id)(const char *, uint32_t) = lv_txt_utf8_get_char_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;
|
||||
@@ -65,7 +65,7 @@ uint32_t (*lv_txt_encoded_conv_wc)(uint32_t) = lv_txt_iso8859_
|
||||
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_encoded_get_char_id)(const char *, uint32_t) = lv_txt_iso8859_1_get_char_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
|
||||
@@ -130,8 +130,150 @@ void lv_txt_get_size(lv_point_t * size_res, const char * text, const lv_font_t *
|
||||
size_res->y -= line_space;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the next word of text. A word is delimited by break characters.
|
||||
*
|
||||
* If the word cannot fit in the max_width space, obey LV_TXT_LINE_BREAK_LONG_* rules.
|
||||
*
|
||||
* If the next word cannot fit anything, return 0.
|
||||
*
|
||||
* 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
|
||||
* txt = "Test text\n"
|
||||
* 0123456789
|
||||
*
|
||||
* Calls would be as follows:
|
||||
* 1. Return i=4, pointing at breakchar ' ', for the string "Test"
|
||||
* 2. Return i=5, since i=4 was a breakchar.
|
||||
* 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
|
||||
* max_width is reached. In current usage, this has no impact.
|
||||
*
|
||||
* @param txt a '\0' terminated string
|
||||
* @param font pointer to a font
|
||||
* @param letter_space letter space
|
||||
* @param max_width max with of the text (break the lines to fit this size) Set CORD_MAX to avoid line breaks
|
||||
* @param flags settings for the text from 'txt_flag_type' enum
|
||||
* @param[out] word_w_ptr width (in pixels) of the parsed word. May be NULL.
|
||||
* @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)
|
||||
{
|
||||
if(txt == NULL || txt[0] == '\0') return 0;
|
||||
if(font == NULL) return 0;
|
||||
|
||||
if(flag & LV_TXT_FLAG_EXPAND) max_width = LV_COORD_MAX;
|
||||
|
||||
uint32_t i = 0, i_next = 0, i_next_next = 0; /* Iterating index into txt */
|
||||
uint32_t letter = 0; /* Letter at i */
|
||||
uint32_t letter_next = 0; /* Letter at i_next */
|
||||
lv_coord_t letter_w;
|
||||
lv_coord_t cur_w = 0; /* Pixel Width of transversed string */
|
||||
uint32_t word_len = 0; /* Number of characters in the transversed word */
|
||||
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);
|
||||
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);
|
||||
word_len++;
|
||||
|
||||
/*Handle the recolor command*/
|
||||
if((flag & LV_TXT_FLAG_RECOLOR) != 0) {
|
||||
if(lv_txt_is_cmd(cmd_state, letter) != false) {
|
||||
i = i_next;
|
||||
i_next = i_next_next;
|
||||
letter = letter_next;
|
||||
continue; /*Skip the letter is it is part of a command*/
|
||||
}
|
||||
}
|
||||
|
||||
letter_w = lv_font_get_glyph_width(font, letter, letter_next);
|
||||
cur_w += letter_w;
|
||||
|
||||
/* Test if this character fits within max_width */
|
||||
if(break_index == NO_BREAK_FOUND && cur_w > max_width) {
|
||||
break_index = i;
|
||||
break_letter_count = word_len - 1;
|
||||
/* break_index is now pointing at the character that doesn't fit */
|
||||
}
|
||||
|
||||
/*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. */
|
||||
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(letter_w > 0) {
|
||||
cur_w += letter_space;
|
||||
}
|
||||
|
||||
i = i_next;
|
||||
i_next = i_next_next;
|
||||
letter = letter_next;
|
||||
}
|
||||
|
||||
/* 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;
|
||||
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(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(word_w_ptr != NULL) *word_w_ptr = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Word is a "long", but letters may need to be better distributed */
|
||||
{
|
||||
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);
|
||||
// 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(word_w_ptr != NULL) *word_w_ptr = 0; /* Return no word */
|
||||
(void) break_letter_count;
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the next line of text. Check line length and break chars too.
|
||||
*
|
||||
* A line of txt includes the \n character.
|
||||
*
|
||||
* @param txt a '\0' terminated string
|
||||
* @param font pointer to a font
|
||||
* @param letter_space letter space
|
||||
@@ -139,75 +281,40 @@ void lv_txt_get_size(lv_point_t * size_res, const char * text, const lv_font_t *
|
||||
* @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)
|
||||
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)
|
||||
{
|
||||
if(txt == NULL) return 0;
|
||||
if(font == NULL) return 0;
|
||||
|
||||
if(flag & LV_TXT_FLAG_EXPAND) max_width = LV_COORD_MAX;
|
||||
|
||||
uint32_t i = 0;
|
||||
uint32_t i_next = 0;
|
||||
lv_coord_t cur_w = 0;
|
||||
uint32_t last_break = NO_BREAK_FOUND;
|
||||
lv_txt_cmd_state_t cmd_state = LV_TXT_CMD_STATE_WAIT;
|
||||
uint32_t letter_w;
|
||||
uint32_t letter = 0;
|
||||
uint32_t letter_next = 0;
|
||||
uint32_t i = 0; /* Iterating index into txt */
|
||||
|
||||
letter_next = lv_txt_encoded_next(txt, &i_next);
|
||||
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);
|
||||
max_width -= word_w;
|
||||
|
||||
while(txt[i] != '\0') {
|
||||
letter = letter_next;
|
||||
i = i_next;
|
||||
letter_next = lv_txt_encoded_next(txt, &i_next);
|
||||
|
||||
/*Handle the recolor command*/
|
||||
if((flag & LV_TXT_FLAG_RECOLOR) != 0) {
|
||||
if(lv_txt_is_cmd(&cmd_state, letter) != false) {
|
||||
continue; /*Skip the letter is it is part of a command*/
|
||||
}
|
||||
if( advance == 0 ){
|
||||
if(i == 0) lv_txt_encoded_next(txt, &i); // prevent inf loops
|
||||
break;
|
||||
}
|
||||
|
||||
/*Check for new line chars*/
|
||||
if(letter == '\n' || letter == '\r') {
|
||||
/*Return with the first letter of the next line*/
|
||||
if(letter == '\r' && letter_next == '\n')
|
||||
return i_next;
|
||||
else
|
||||
return i;
|
||||
} else { /*Check the actual length*/
|
||||
letter_w = lv_font_get_glyph_width(font, letter, letter_next);
|
||||
cur_w += letter_w;
|
||||
i += advance;
|
||||
|
||||
/*If the txt is too long then finish, this is the line end*/
|
||||
if(cur_w > max_width) {
|
||||
/*If a break character was already found break there*/
|
||||
if(last_break != NO_BREAK_FOUND) {
|
||||
i = last_break;
|
||||
} else {
|
||||
/* Now this character is out of the area so it will be first character of the next line*/
|
||||
/* But 'i' already points to the next character (because of lv_txt_utf8_next) step beck one*/
|
||||
lv_txt_encoded_prev(txt, &i);
|
||||
}
|
||||
if(txt[0] == '\n') break;
|
||||
|
||||
/* Do not let to return without doing nothing.
|
||||
* Find at least one character (Avoid infinite loop )*/
|
||||
if(i == 0) lv_txt_encoded_next(txt, &i);
|
||||
|
||||
return i;
|
||||
}
|
||||
/*If this char still can fit to this line then check if
|
||||
* txt can be broken here later */
|
||||
else if(is_break_char(letter)) {
|
||||
last_break = i; /*Save the first char index after break*/
|
||||
}
|
||||
if(txt[i] == '\n'){
|
||||
i++; /* Include the following newline in the current line */
|
||||
break;
|
||||
}
|
||||
|
||||
if(letter_w > 0) {
|
||||
cur_w += letter_space;
|
||||
}
|
||||
}
|
||||
|
||||
/* Always step at least one to avoid infinite loops */
|
||||
if(i == 0) {
|
||||
lv_txt_encoded_next(txt, &i);
|
||||
}
|
||||
|
||||
return i;
|
||||
@@ -366,7 +473,7 @@ static uint8_t lv_txt_utf8_size(const char * str)
|
||||
return 3;
|
||||
else if((str[0] & 0xF8) == 0xF0)
|
||||
return 4;
|
||||
return 1; /*If the char was invalid step tell it's 1 byte long*/
|
||||
return 0; /*If the char was invalid tell it's 1 byte long*/
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -543,7 +650,8 @@ 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++) {
|
||||
byte_cnt += 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;
|
||||
}
|
||||
|
||||
return byte_cnt;
|
||||
|
||||
@@ -27,7 +27,9 @@ extern "C" {
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
#ifndef LV_TXT_COLOR_CMD
|
||||
#define LV_TXT_COLOR_CMD "#"
|
||||
#endif
|
||||
|
||||
#define LV_TXT_ENC_UTF8 1
|
||||
#define LV_TXT_ENC_ASCII 2
|
||||
@@ -188,7 +190,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_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.
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#include "lv_arc.h"
|
||||
#if LV_USE_ARC != 0
|
||||
|
||||
#include "../lv_core/lv_debug.h"
|
||||
#include "../lv_misc/lv_math.h"
|
||||
#include "../lv_draw/lv_draw_arc.h"
|
||||
#include "../lv_themes/lv_theme.h"
|
||||
@@ -16,6 +17,7 @@
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
#define LV_OBJX_NAME "lv_arc"
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
@@ -54,12 +56,12 @@ lv_obj_t * lv_arc_create(lv_obj_t * par, const lv_obj_t * copy)
|
||||
|
||||
/*Create the ancestor of arc*/
|
||||
lv_obj_t * new_arc = lv_obj_create(par, copy);
|
||||
lv_mem_assert(new_arc);
|
||||
LV_ASSERT_MEM(new_arc);
|
||||
if(new_arc == NULL) return NULL;
|
||||
|
||||
/*Allocate the arc type specific extended data*/
|
||||
lv_arc_ext_t * ext = lv_obj_allocate_ext_attr(new_arc, sizeof(lv_arc_ext_t));
|
||||
lv_mem_assert(ext);
|
||||
LV_ASSERT_MEM(ext);
|
||||
if(ext == NULL) return NULL;
|
||||
|
||||
if(ancestor_signal == NULL) ancestor_signal = lv_obj_get_signal_cb(new_arc);
|
||||
@@ -119,6 +121,8 @@ lv_obj_t * lv_arc_create(lv_obj_t * par, const lv_obj_t * copy)
|
||||
*/
|
||||
void lv_arc_set_angles(lv_obj_t * arc, uint16_t start, uint16_t end)
|
||||
{
|
||||
LV_ASSERT_OBJ(arc, LV_OBJX_NAME);
|
||||
|
||||
lv_arc_ext_t * ext = lv_obj_get_ext_attr(arc);
|
||||
|
||||
if(start > 360) start = 360;
|
||||
@@ -138,6 +142,8 @@ void lv_arc_set_angles(lv_obj_t * arc, uint16_t start, uint16_t end)
|
||||
* */
|
||||
void lv_arc_set_style(lv_obj_t * arc, lv_arc_style_t type, const lv_style_t * style)
|
||||
{
|
||||
LV_ASSERT_OBJ(arc, LV_OBJX_NAME);
|
||||
|
||||
switch(type) {
|
||||
case LV_ARC_STYLE_MAIN: lv_obj_set_style(arc, style); break;
|
||||
}
|
||||
@@ -154,6 +160,8 @@ void lv_arc_set_style(lv_obj_t * arc, lv_arc_style_t type, const lv_style_t * st
|
||||
*/
|
||||
uint16_t lv_arc_get_angle_start(lv_obj_t * arc)
|
||||
{
|
||||
LV_ASSERT_OBJ(arc, LV_OBJX_NAME);
|
||||
|
||||
lv_arc_ext_t * ext = lv_obj_get_ext_attr(arc);
|
||||
|
||||
return ext->angle_start;
|
||||
@@ -166,6 +174,8 @@ uint16_t lv_arc_get_angle_start(lv_obj_t * arc)
|
||||
*/
|
||||
uint16_t lv_arc_get_angle_end(lv_obj_t * arc)
|
||||
{
|
||||
LV_ASSERT_OBJ(arc, LV_OBJX_NAME);
|
||||
|
||||
lv_arc_ext_t * ext = lv_obj_get_ext_attr(arc);
|
||||
|
||||
return ext->angle_end;
|
||||
@@ -179,6 +189,8 @@ uint16_t lv_arc_get_angle_end(lv_obj_t * arc)
|
||||
* */
|
||||
const lv_style_t * lv_arc_get_style(const lv_obj_t * arc, lv_arc_style_t type)
|
||||
{
|
||||
LV_ASSERT_OBJ(arc, LV_OBJX_NAME);
|
||||
|
||||
const lv_style_t * style = NULL;
|
||||
|
||||
switch(type) {
|
||||
@@ -281,15 +293,10 @@ static lv_res_t lv_arc_signal(lv_obj_t * arc, lv_signal_t sign, void * param)
|
||||
res = ancestor_signal(arc, sign, param);
|
||||
if(res != LV_RES_OK) return res;
|
||||
|
||||
if(sign == LV_SIGNAL_GET_TYPE) return lv_obj_handle_get_type_signal(param, LV_OBJX_NAME);
|
||||
|
||||
if(sign == LV_SIGNAL_CLEANUP) {
|
||||
/*Nothing to cleanup. (No dynamically allocated memory in 'ext')*/
|
||||
} else if(sign == LV_SIGNAL_GET_TYPE) {
|
||||
lv_obj_type_t * buf = param;
|
||||
uint8_t i;
|
||||
for(i = 0; i < LV_MAX_ANCESTOR_NUM - 1; i++) { /*Find the last set data*/
|
||||
if(buf->type[i] == NULL) break;
|
||||
}
|
||||
buf->type[i] = "lv_arc";
|
||||
}
|
||||
|
||||
return res;
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
#include "lv_bar.h"
|
||||
#if LV_USE_BAR != 0
|
||||
|
||||
#include "../lv_core/lv_debug.h"
|
||||
#include "../lv_draw/lv_draw.h"
|
||||
#include "../lv_themes/lv_theme.h"
|
||||
#include "../lv_misc/lv_anim.h"
|
||||
@@ -19,6 +20,7 @@
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
#define LV_OBJX_NAME "lv_bar"
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
@@ -61,7 +63,7 @@ lv_obj_t * lv_bar_create(lv_obj_t * par, const lv_obj_t * copy)
|
||||
|
||||
/*Create the ancestor basic object*/
|
||||
lv_obj_t * new_bar = lv_obj_create(par, copy);
|
||||
lv_mem_assert(new_bar);
|
||||
LV_ASSERT_MEM(new_bar);
|
||||
if(new_bar == NULL) return NULL;
|
||||
|
||||
if(ancestor_signal == NULL) ancestor_signal = lv_obj_get_signal_cb(new_bar);
|
||||
@@ -69,7 +71,7 @@ lv_obj_t * lv_bar_create(lv_obj_t * par, const lv_obj_t * copy)
|
||||
|
||||
/*Allocate the object type specific extended data*/
|
||||
lv_bar_ext_t * ext = lv_obj_allocate_ext_attr(new_bar, sizeof(lv_bar_ext_t));
|
||||
lv_mem_assert(ext);
|
||||
LV_ASSERT_MEM(ext);
|
||||
if(ext == NULL) return NULL;
|
||||
|
||||
ext->min_value = 0;
|
||||
@@ -130,6 +132,8 @@ lv_obj_t * lv_bar_create(lv_obj_t * par, const lv_obj_t * copy)
|
||||
*/
|
||||
void lv_bar_set_value(lv_obj_t * bar, int16_t value, lv_anim_enable_t anim)
|
||||
{
|
||||
LV_ASSERT_OBJ(bar, LV_OBJX_NAME);
|
||||
|
||||
#if LV_USE_ANIMATION == 0
|
||||
anim = false;
|
||||
#endif
|
||||
@@ -185,6 +189,8 @@ void lv_bar_set_value(lv_obj_t * bar, int16_t value, lv_anim_enable_t anim)
|
||||
*/
|
||||
void lv_bar_set_range(lv_obj_t * bar, int16_t min, int16_t max)
|
||||
{
|
||||
LV_ASSERT_OBJ(bar, LV_OBJX_NAME);
|
||||
|
||||
lv_bar_ext_t * ext = lv_obj_get_ext_attr(bar);
|
||||
if(ext->min_value == min && ext->max_value == max) return;
|
||||
|
||||
@@ -209,6 +215,8 @@ void lv_bar_set_range(lv_obj_t * bar, int16_t min, int16_t max)
|
||||
*/
|
||||
void lv_bar_set_sym(lv_obj_t * bar, bool en)
|
||||
{
|
||||
LV_ASSERT_OBJ(bar, LV_OBJX_NAME);
|
||||
|
||||
lv_bar_ext_t * ext = lv_obj_get_ext_attr(bar);
|
||||
ext->sym = en ? 1 : 0;
|
||||
}
|
||||
@@ -220,6 +228,8 @@ void lv_bar_set_sym(lv_obj_t * bar, bool en)
|
||||
*/
|
||||
void lv_bar_set_anim_time(lv_obj_t * bar, uint16_t anim_time)
|
||||
{
|
||||
LV_ASSERT_OBJ(bar, LV_OBJX_NAME);
|
||||
|
||||
#if LV_USE_ANIMATION
|
||||
lv_bar_ext_t * ext = lv_obj_get_ext_attr(bar);
|
||||
ext->anim_time = anim_time;
|
||||
@@ -237,6 +247,8 @@ void lv_bar_set_anim_time(lv_obj_t * bar, uint16_t anim_time)
|
||||
*/
|
||||
void lv_bar_set_style(lv_obj_t * bar, lv_bar_style_t type, const lv_style_t * style)
|
||||
{
|
||||
LV_ASSERT_OBJ(bar, LV_OBJX_NAME);
|
||||
|
||||
lv_bar_ext_t * ext = lv_obj_get_ext_attr(bar);
|
||||
|
||||
switch(type) {
|
||||
@@ -259,6 +271,8 @@ void lv_bar_set_style(lv_obj_t * bar, lv_bar_style_t type, const lv_style_t * st
|
||||
*/
|
||||
int16_t lv_bar_get_value(const lv_obj_t * bar)
|
||||
{
|
||||
LV_ASSERT_OBJ(bar, LV_OBJX_NAME);
|
||||
|
||||
lv_bar_ext_t * ext = lv_obj_get_ext_attr(bar);
|
||||
/*If animated tell that it's already at the end value*/
|
||||
#if LV_USE_ANIMATION
|
||||
@@ -275,6 +289,8 @@ int16_t lv_bar_get_value(const lv_obj_t * bar)
|
||||
*/
|
||||
int16_t lv_bar_get_min_value(const lv_obj_t * bar)
|
||||
{
|
||||
LV_ASSERT_OBJ(bar, LV_OBJX_NAME);
|
||||
|
||||
lv_bar_ext_t * ext = lv_obj_get_ext_attr(bar);
|
||||
return ext->min_value;
|
||||
}
|
||||
@@ -286,6 +302,8 @@ int16_t lv_bar_get_min_value(const lv_obj_t * bar)
|
||||
*/
|
||||
int16_t lv_bar_get_max_value(const lv_obj_t * bar)
|
||||
{
|
||||
LV_ASSERT_OBJ(bar, LV_OBJX_NAME);
|
||||
|
||||
lv_bar_ext_t * ext = lv_obj_get_ext_attr(bar);
|
||||
return ext->max_value;
|
||||
}
|
||||
@@ -297,6 +315,8 @@ int16_t lv_bar_get_max_value(const lv_obj_t * bar)
|
||||
*/
|
||||
bool lv_bar_get_sym(lv_obj_t * bar)
|
||||
{
|
||||
LV_ASSERT_OBJ(bar, LV_OBJX_NAME);
|
||||
|
||||
lv_bar_ext_t * ext = lv_obj_get_ext_attr(bar);
|
||||
return ext->sym ? true : false;
|
||||
}
|
||||
@@ -308,6 +328,8 @@ bool lv_bar_get_sym(lv_obj_t * bar)
|
||||
*/
|
||||
uint16_t lv_bar_get_anim_time(lv_obj_t * bar)
|
||||
{
|
||||
LV_ASSERT_OBJ(bar, LV_OBJX_NAME);
|
||||
|
||||
#if LV_USE_ANIMATION
|
||||
lv_bar_ext_t * ext = lv_obj_get_ext_attr(bar);
|
||||
return ext->anim_time;
|
||||
@@ -325,6 +347,8 @@ uint16_t lv_bar_get_anim_time(lv_obj_t * bar)
|
||||
*/
|
||||
const lv_style_t * lv_bar_get_style(const lv_obj_t * bar, lv_bar_style_t type)
|
||||
{
|
||||
LV_ASSERT_OBJ(bar, LV_OBJX_NAME);
|
||||
|
||||
const lv_style_t * style = NULL;
|
||||
lv_bar_ext_t * ext = lv_obj_get_ext_attr(bar);
|
||||
|
||||
@@ -495,17 +519,11 @@ static lv_res_t lv_bar_signal(lv_obj_t * bar, lv_signal_t sign, void * param)
|
||||
/* Include the ancient signal function */
|
||||
res = ancestor_signal(bar, sign, param);
|
||||
if(res != LV_RES_OK) return res;
|
||||
if(sign == LV_SIGNAL_GET_TYPE) return lv_obj_handle_get_type_signal(param, LV_OBJX_NAME);
|
||||
|
||||
if(sign == LV_SIGNAL_REFR_EXT_DRAW_PAD) {
|
||||
const lv_style_t * style_indic = lv_bar_get_style(bar, LV_BAR_STYLE_INDIC);
|
||||
if(style_indic->body.shadow.width > bar->ext_draw_pad) bar->ext_draw_pad = style_indic->body.shadow.width;
|
||||
} else if(sign == LV_SIGNAL_GET_TYPE) {
|
||||
lv_obj_type_t * buf = param;
|
||||
uint8_t i;
|
||||
for(i = 0; i < LV_MAX_ANCESTOR_NUM - 1; i++) { /*Find the last set data*/
|
||||
if(buf->type[i] == NULL) break;
|
||||
}
|
||||
buf->type[i] = "lv_bar";
|
||||
}
|
||||
|
||||
return res;
|
||||
|
||||
@@ -43,6 +43,11 @@ extern "C" {
|
||||
/** log2(LV_BAR_ANIM_STATE_END) used to normalize data*/
|
||||
#define LV_BAR_ANIM_STATE_NORM 8
|
||||
|
||||
LV_EXPORT_CONST_INT(LV_BAR_ANIM_STATE_START);
|
||||
LV_EXPORT_CONST_INT(LV_BAR_ANIM_STATE_END);
|
||||
LV_EXPORT_CONST_INT(LV_BAR_ANIM_STATE_INV);
|
||||
LV_EXPORT_CONST_INT(LV_BAR_ANIM_STATE_NORM);
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
|
||||
#include <string.h>
|
||||
#include "../lv_core/lv_group.h"
|
||||
#include "../lv_core/lv_debug.h"
|
||||
#include "../lv_draw/lv_draw.h"
|
||||
#include "../lv_themes/lv_theme.h"
|
||||
#include "../lv_misc/lv_area.h"
|
||||
@@ -21,6 +22,7 @@
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
#define LV_OBJX_NAME "lv_btn"
|
||||
#define LV_BTN_INK_VALUE_MAX 256
|
||||
#define LV_BTN_INK_VALUE_MAX_SHIFT 8
|
||||
|
||||
@@ -76,7 +78,7 @@ lv_obj_t * lv_btn_create(lv_obj_t * par, const lv_obj_t * copy)
|
||||
lv_obj_t * new_btn;
|
||||
|
||||
new_btn = lv_cont_create(par, copy);
|
||||
lv_mem_assert(new_btn);
|
||||
LV_ASSERT_MEM(new_btn);
|
||||
if(new_btn == NULL) return NULL;
|
||||
|
||||
if(ancestor_signal == NULL) ancestor_signal = lv_obj_get_signal_cb(new_btn);
|
||||
@@ -84,7 +86,7 @@ lv_obj_t * lv_btn_create(lv_obj_t * par, const lv_obj_t * copy)
|
||||
|
||||
/*Allocate the extended data*/
|
||||
lv_btn_ext_t * ext = lv_obj_allocate_ext_attr(new_btn, sizeof(lv_btn_ext_t));
|
||||
lv_mem_assert(ext);
|
||||
LV_ASSERT_MEM(ext);
|
||||
if(ext == NULL) return NULL;
|
||||
|
||||
ext->state = LV_BTN_STATE_REL;
|
||||
@@ -158,6 +160,8 @@ lv_obj_t * lv_btn_create(lv_obj_t * par, const lv_obj_t * copy)
|
||||
*/
|
||||
void lv_btn_set_toggle(lv_obj_t * btn, bool tgl)
|
||||
{
|
||||
LV_ASSERT_OBJ(btn, LV_OBJX_NAME);
|
||||
|
||||
lv_btn_ext_t * ext = lv_obj_get_ext_attr(btn);
|
||||
|
||||
ext->toggle = tgl != false ? 1 : 0;
|
||||
@@ -170,6 +174,8 @@ void lv_btn_set_toggle(lv_obj_t * btn, bool tgl)
|
||||
*/
|
||||
void lv_btn_set_state(lv_obj_t * btn, lv_btn_state_t state)
|
||||
{
|
||||
LV_ASSERT_OBJ(btn, LV_OBJX_NAME);
|
||||
|
||||
lv_btn_ext_t * ext = lv_obj_get_ext_attr(btn);
|
||||
if(ext->state != state) {
|
||||
ext->state = state;
|
||||
@@ -183,6 +189,8 @@ void lv_btn_set_state(lv_obj_t * btn, lv_btn_state_t state)
|
||||
*/
|
||||
void lv_btn_toggle(lv_obj_t * btn)
|
||||
{
|
||||
LV_ASSERT_OBJ(btn, LV_OBJX_NAME);
|
||||
|
||||
lv_btn_ext_t * ext = lv_obj_get_ext_attr(btn);
|
||||
switch(ext->state) {
|
||||
case LV_BTN_STATE_REL: lv_btn_set_state(btn, LV_BTN_STATE_TGL_REL); break;
|
||||
@@ -200,6 +208,8 @@ void lv_btn_toggle(lv_obj_t * btn)
|
||||
*/
|
||||
void lv_btn_set_ink_in_time(lv_obj_t * btn, uint16_t time)
|
||||
{
|
||||
LV_ASSERT_OBJ(btn, LV_OBJX_NAME);
|
||||
|
||||
#if LV_USE_ANIMATION && LV_BTN_INK_EFFECT
|
||||
lv_btn_ext_t * ext = lv_obj_get_ext_attr(btn);
|
||||
ext->ink_in_time = time;
|
||||
@@ -218,6 +228,8 @@ void lv_btn_set_ink_in_time(lv_obj_t * btn, uint16_t time)
|
||||
*/
|
||||
void lv_btn_set_ink_wait_time(lv_obj_t * btn, uint16_t time)
|
||||
{
|
||||
LV_ASSERT_OBJ(btn, LV_OBJX_NAME);
|
||||
|
||||
|
||||
#if LV_USE_ANIMATION && LV_BTN_INK_EFFECT
|
||||
lv_btn_ext_t * ext = lv_obj_get_ext_attr(btn);
|
||||
@@ -237,6 +249,8 @@ void lv_btn_set_ink_wait_time(lv_obj_t * btn, uint16_t time)
|
||||
*/
|
||||
void lv_btn_set_ink_out_time(lv_obj_t * btn, uint16_t time)
|
||||
{
|
||||
LV_ASSERT_OBJ(btn, LV_OBJX_NAME);
|
||||
|
||||
#if LV_USE_ANIMATION && LV_BTN_INK_EFFECT
|
||||
lv_btn_ext_t * ext = lv_obj_get_ext_attr(btn);
|
||||
ext->ink_out_time = time;
|
||||
@@ -256,6 +270,8 @@ void lv_btn_set_ink_out_time(lv_obj_t * btn, uint16_t time)
|
||||
*/
|
||||
void lv_btn_set_style(lv_obj_t * btn, lv_btn_style_t type, const lv_style_t * style)
|
||||
{
|
||||
LV_ASSERT_OBJ(btn, LV_OBJX_NAME);
|
||||
|
||||
lv_btn_ext_t * ext = lv_obj_get_ext_attr(btn);
|
||||
|
||||
switch(type) {
|
||||
@@ -281,6 +297,8 @@ void lv_btn_set_style(lv_obj_t * btn, lv_btn_style_t type, const lv_style_t * st
|
||||
*/
|
||||
lv_btn_state_t lv_btn_get_state(const lv_obj_t * btn)
|
||||
{
|
||||
LV_ASSERT_OBJ(btn, LV_OBJX_NAME);
|
||||
|
||||
lv_btn_ext_t * ext = lv_obj_get_ext_attr(btn);
|
||||
return ext->state;
|
||||
}
|
||||
@@ -292,6 +310,8 @@ lv_btn_state_t lv_btn_get_state(const lv_obj_t * btn)
|
||||
*/
|
||||
bool lv_btn_get_toggle(const lv_obj_t * btn)
|
||||
{
|
||||
LV_ASSERT_OBJ(btn, LV_OBJX_NAME);
|
||||
|
||||
lv_btn_ext_t * ext = lv_obj_get_ext_attr(btn);
|
||||
|
||||
return ext->toggle != 0 ? true : false;
|
||||
@@ -304,6 +324,8 @@ bool lv_btn_get_toggle(const lv_obj_t * btn)
|
||||
*/
|
||||
uint16_t lv_btn_get_ink_in_time(const lv_obj_t * btn)
|
||||
{
|
||||
LV_ASSERT_OBJ(btn, LV_OBJX_NAME);
|
||||
|
||||
#if LV_USE_ANIMATION && LV_BTN_INK_EFFECT
|
||||
lv_btn_ext_t * ext = lv_obj_get_ext_attr(btn);
|
||||
return ext->ink_in_time;
|
||||
@@ -320,6 +342,8 @@ uint16_t lv_btn_get_ink_in_time(const lv_obj_t * btn)
|
||||
*/
|
||||
uint16_t lv_btn_get_ink_wait_time(const lv_obj_t * btn)
|
||||
{
|
||||
LV_ASSERT_OBJ(btn, LV_OBJX_NAME);
|
||||
|
||||
#if LV_USE_ANIMATION && LV_BTN_INK_EFFECT
|
||||
lv_btn_ext_t * ext = lv_obj_get_ext_attr(btn);
|
||||
return ext->ink_wait_time;
|
||||
@@ -335,6 +359,8 @@ uint16_t lv_btn_get_ink_wait_time(const lv_obj_t * btn)
|
||||
*/
|
||||
uint16_t lv_btn_get_ink_out_time(const lv_obj_t * btn)
|
||||
{
|
||||
LV_ASSERT_OBJ(btn, LV_OBJX_NAME);
|
||||
|
||||
#if LV_USE_ANIMATION && LV_BTN_INK_EFFECT
|
||||
lv_btn_ext_t * ext = lv_obj_get_ext_attr(btn);
|
||||
return ext->ink_out_time;
|
||||
@@ -352,6 +378,8 @@ uint16_t lv_btn_get_ink_out_time(const lv_obj_t * btn)
|
||||
*/
|
||||
const lv_style_t * lv_btn_get_style(const lv_obj_t * btn, lv_btn_style_t type)
|
||||
{
|
||||
LV_ASSERT_OBJ(btn, LV_OBJX_NAME);
|
||||
|
||||
const lv_style_t * style = NULL;
|
||||
lv_btn_ext_t * ext = lv_obj_get_ext_attr(btn);
|
||||
lv_btn_state_t state = lv_btn_get_state(btn);
|
||||
@@ -483,6 +511,7 @@ static lv_res_t lv_btn_signal(lv_obj_t * btn, lv_signal_t sign, void * param)
|
||||
/* Include the ancient signal function */
|
||||
res = ancestor_signal(btn, sign, param);
|
||||
if(res != LV_RES_OK) return res;
|
||||
if(sign == LV_SIGNAL_GET_TYPE) return lv_obj_handle_get_type_signal(param, LV_OBJX_NAME);
|
||||
|
||||
lv_btn_ext_t * ext = lv_obj_get_ext_attr(btn);
|
||||
bool tgl = lv_btn_get_toggle(btn);
|
||||
@@ -634,13 +663,6 @@ static lv_res_t lv_btn_signal(lv_obj_t * btn, lv_signal_t sign, void * param)
|
||||
ink_obj = NULL;
|
||||
}
|
||||
#endif
|
||||
} else if(sign == LV_SIGNAL_GET_TYPE) {
|
||||
lv_obj_type_t * buf = param;
|
||||
uint8_t i;
|
||||
for(i = 0; i < LV_MAX_ANCESTOR_NUM - 1; i++) { /*Find the last set data*/
|
||||
if(buf->type[i] == NULL) break;
|
||||
}
|
||||
buf->type[i] = "lv_btn";
|
||||
}
|
||||
|
||||
return res;
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#include "lv_btnm.h"
|
||||
#if LV_USE_BTNM != 0
|
||||
|
||||
#include "../lv_core/lv_debug.h"
|
||||
#include "../lv_core/lv_group.h"
|
||||
#include "../lv_draw/lv_draw.h"
|
||||
#include "../lv_core/lv_refr.h"
|
||||
@@ -18,6 +19,7 @@
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
#define LV_OBJX_NAME "lv_btnm"
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
@@ -70,14 +72,14 @@ lv_obj_t * lv_btnm_create(lv_obj_t * par, const lv_obj_t * copy)
|
||||
|
||||
/*Create the ancestor object*/
|
||||
lv_obj_t * new_btnm = lv_obj_create(par, copy);
|
||||
lv_mem_assert(new_btnm);
|
||||
LV_ASSERT_MEM(new_btnm);
|
||||
if(new_btnm == NULL) return NULL;
|
||||
|
||||
if(ancestor_signal == NULL) ancestor_signal = lv_obj_get_signal_cb(new_btnm);
|
||||
|
||||
/*Allocate the object type specific extended data*/
|
||||
lv_btnm_ext_t * ext = lv_obj_allocate_ext_attr(new_btnm, sizeof(lv_btnm_ext_t));
|
||||
lv_mem_assert(ext);
|
||||
LV_ASSERT_MEM(ext);
|
||||
if(ext == NULL) return NULL;
|
||||
|
||||
ext->btn_cnt = 0;
|
||||
@@ -101,8 +103,8 @@ lv_obj_t * lv_btnm_create(lv_obj_t * par, const lv_obj_t * copy)
|
||||
|
||||
/*Init the new button matrix object*/
|
||||
if(copy == NULL) {
|
||||
lv_obj_set_size(new_btnm, LV_DPI * 3, LV_DPI * 2);
|
||||
lv_btnm_set_map(new_btnm, lv_btnm_def_map);
|
||||
lv_obj_set_size(new_btnm, LV_DPI * 3, LV_DPI * 2);
|
||||
|
||||
/*Set the default styles*/
|
||||
lv_theme_t * th = lv_theme_get_current();
|
||||
@@ -142,7 +144,8 @@ lv_obj_t * lv_btnm_create(lv_obj_t * par, const lv_obj_t * copy)
|
||||
*/
|
||||
void lv_btnm_set_map(const lv_obj_t * btnm, const char * map[])
|
||||
{
|
||||
if(map == NULL) return;
|
||||
LV_ASSERT_OBJ(btnm, LV_OBJX_NAME);
|
||||
LV_ASSERT_NULL(map);
|
||||
|
||||
/*
|
||||
* lv_btnm_set_map is called on receipt of signals such as
|
||||
@@ -204,6 +207,8 @@ void lv_btnm_set_map(const lv_obj_t * btnm, const char * map[])
|
||||
btn_h = lv_obj_get_height(btnm)- act_y - style_bg->body.padding.bottom - 1;
|
||||
}
|
||||
|
||||
lv_bidi_dir_t base_dir = lv_obj_get_base_dir(btnm);
|
||||
|
||||
/*Only deal with the non empty lines*/
|
||||
if(btn_cnt != 0) {
|
||||
/*Calculate the width of all units*/
|
||||
@@ -211,7 +216,8 @@ void lv_btnm_set_map(const lv_obj_t * btnm, const char * map[])
|
||||
|
||||
/*Set the button size and positions and set the texts*/
|
||||
uint16_t i;
|
||||
lv_coord_t act_x = style_bg->body.padding.left;
|
||||
lv_coord_t act_x;
|
||||
|
||||
lv_coord_t act_unit_w;
|
||||
unit_act_cnt = 0;
|
||||
for(i = 0; i < btn_cnt; i++) {
|
||||
@@ -222,9 +228,13 @@ void lv_btnm_set_map(const lv_obj_t * btnm, const char * map[])
|
||||
act_unit_w--; /*-1 because e.g. width = 100 means 101 pixels (0..100)*/
|
||||
|
||||
/*Always recalculate act_x because of rounding errors */
|
||||
act_x = (unit_act_cnt * all_unit_w) / unit_cnt + i * style_bg->body.padding.inner +
|
||||
style_bg->body.padding.left;
|
||||
|
||||
if(base_dir == LV_BIDI_DIR_RTL) {
|
||||
act_x = (unit_act_cnt * all_unit_w) / unit_cnt + i * style_bg->body.padding.inner;
|
||||
act_x = lv_obj_get_width(btnm) - style_bg->body.padding.right - act_x - act_unit_w - 1;
|
||||
} else {
|
||||
act_x = (unit_act_cnt * all_unit_w) / unit_cnt + i * style_bg->body.padding.inner +
|
||||
style_bg->body.padding.left;
|
||||
}
|
||||
/* Set the button's area.
|
||||
* If inner padding is zero then use the prev. button x2 as x1 to avoid rounding
|
||||
* errors*/
|
||||
@@ -265,6 +275,8 @@ void lv_btnm_set_map(const lv_obj_t * btnm, const char * map[])
|
||||
*/
|
||||
void lv_btnm_set_ctrl_map(const lv_obj_t * btnm, const lv_btnm_ctrl_t ctrl_map[])
|
||||
{
|
||||
LV_ASSERT_OBJ(btnm, LV_OBJX_NAME);
|
||||
|
||||
lv_btnm_ext_t * ext = lv_obj_get_ext_attr(btnm);
|
||||
memcpy(ext->ctrl_bits, ctrl_map, sizeof(lv_btnm_ctrl_t) * ext->btn_cnt);
|
||||
|
||||
@@ -279,6 +291,8 @@ void lv_btnm_set_ctrl_map(const lv_obj_t * btnm, const lv_btnm_ctrl_t ctrl_map[]
|
||||
*/
|
||||
void lv_btnm_set_pressed(const lv_obj_t * btnm, uint16_t id)
|
||||
{
|
||||
LV_ASSERT_OBJ(btnm, LV_OBJX_NAME);
|
||||
|
||||
lv_btnm_ext_t * ext = lv_obj_get_ext_attr(btnm);
|
||||
|
||||
if(id >= ext->btn_cnt && id != LV_BTNM_BTN_NONE) return;
|
||||
@@ -297,6 +311,8 @@ void lv_btnm_set_pressed(const lv_obj_t * btnm, uint16_t id)
|
||||
*/
|
||||
void lv_btnm_set_style(lv_obj_t * btnm, lv_btnm_style_t type, const lv_style_t * style)
|
||||
{
|
||||
LV_ASSERT_OBJ(btnm, LV_OBJX_NAME);
|
||||
|
||||
lv_btnm_ext_t * ext = lv_obj_get_ext_attr(btnm);
|
||||
|
||||
switch(type) {
|
||||
@@ -331,6 +347,8 @@ void lv_btnm_set_style(lv_obj_t * btnm, lv_btnm_style_t type, const lv_style_t *
|
||||
*/
|
||||
void lv_btnm_set_recolor(const lv_obj_t * btnm, bool en)
|
||||
{
|
||||
LV_ASSERT_OBJ(btnm, LV_OBJX_NAME);
|
||||
|
||||
lv_btnm_ext_t * ext = lv_obj_get_ext_attr(btnm);
|
||||
|
||||
ext->recolor = en;
|
||||
@@ -344,6 +362,8 @@ void lv_btnm_set_recolor(const lv_obj_t * btnm, bool en)
|
||||
*/
|
||||
void lv_btnm_set_btn_ctrl(const lv_obj_t * btnm, uint16_t btn_id, lv_btnm_ctrl_t ctrl)
|
||||
{
|
||||
LV_ASSERT_OBJ(btnm, LV_OBJX_NAME);
|
||||
|
||||
lv_btnm_ext_t * ext = lv_obj_get_ext_attr(btnm);
|
||||
|
||||
if(btn_id >= ext->btn_cnt) return;
|
||||
@@ -359,6 +379,8 @@ void lv_btnm_set_btn_ctrl(const lv_obj_t * btnm, uint16_t btn_id, lv_btnm_ctrl_t
|
||||
*/
|
||||
void lv_btnm_clear_btn_ctrl(const lv_obj_t * btnm, uint16_t btn_id, lv_btnm_ctrl_t ctrl)
|
||||
{
|
||||
LV_ASSERT_OBJ(btnm, LV_OBJX_NAME);
|
||||
|
||||
lv_btnm_ext_t * ext = lv_obj_get_ext_attr(btnm);
|
||||
|
||||
if(btn_id >= ext->btn_cnt) return;
|
||||
@@ -374,6 +396,8 @@ void lv_btnm_clear_btn_ctrl(const lv_obj_t * btnm, uint16_t btn_id, lv_btnm_ctrl
|
||||
*/
|
||||
void lv_btnm_set_btn_ctrl_all(lv_obj_t * btnm, lv_btnm_ctrl_t ctrl)
|
||||
{
|
||||
LV_ASSERT_OBJ(btnm, LV_OBJX_NAME);
|
||||
|
||||
lv_btnm_ext_t * ext = lv_obj_get_ext_attr(btnm);
|
||||
uint16_t i;
|
||||
for(i = 0; i < ext->btn_cnt; i++) {
|
||||
@@ -389,6 +413,8 @@ void lv_btnm_set_btn_ctrl_all(lv_obj_t * btnm, lv_btnm_ctrl_t ctrl)
|
||||
*/
|
||||
void lv_btnm_clear_btn_ctrl_all(lv_obj_t * btnm, lv_btnm_ctrl_t ctrl)
|
||||
{
|
||||
LV_ASSERT_OBJ(btnm, LV_OBJX_NAME);
|
||||
|
||||
lv_btnm_ext_t * ext = lv_obj_get_ext_attr(btnm);
|
||||
uint16_t i;
|
||||
for(i = 0; i < ext->btn_cnt; i++) {
|
||||
@@ -407,6 +433,8 @@ void lv_btnm_clear_btn_ctrl_all(lv_obj_t * btnm, lv_btnm_ctrl_t ctrl)
|
||||
*/
|
||||
void lv_btnm_set_btn_width(const lv_obj_t * btnm, uint16_t btn_id, uint8_t width)
|
||||
{
|
||||
LV_ASSERT_OBJ(btnm, LV_OBJX_NAME);
|
||||
|
||||
|
||||
lv_btnm_ext_t * ext = lv_obj_get_ext_attr(btnm);
|
||||
if(btn_id >= ext->btn_cnt) return;
|
||||
@@ -427,6 +455,8 @@ void lv_btnm_set_btn_width(const lv_obj_t * btnm, uint16_t btn_id, uint8_t width
|
||||
*/
|
||||
void lv_btnm_set_one_toggle(lv_obj_t * btnm, bool one_toggle)
|
||||
{
|
||||
LV_ASSERT_OBJ(btnm, LV_OBJX_NAME);
|
||||
|
||||
lv_btnm_ext_t * ext = lv_obj_get_ext_attr(btnm);
|
||||
ext->one_toggle = one_toggle;
|
||||
|
||||
@@ -445,6 +475,8 @@ void lv_btnm_set_one_toggle(lv_obj_t * btnm, bool one_toggle)
|
||||
*/
|
||||
const char ** lv_btnm_get_map_array(const lv_obj_t * btnm)
|
||||
{
|
||||
LV_ASSERT_OBJ(btnm, LV_OBJX_NAME);
|
||||
|
||||
lv_btnm_ext_t * ext = lv_obj_get_ext_attr(btnm);
|
||||
return ext->map_p;
|
||||
}
|
||||
@@ -456,6 +488,8 @@ const char ** lv_btnm_get_map_array(const lv_obj_t * btnm)
|
||||
*/
|
||||
bool lv_btnm_get_recolor(const lv_obj_t * btnm)
|
||||
{
|
||||
LV_ASSERT_OBJ(btnm, LV_OBJX_NAME);
|
||||
|
||||
lv_btnm_ext_t * ext = lv_obj_get_ext_attr(btnm);
|
||||
|
||||
return ext->recolor;
|
||||
@@ -469,6 +503,8 @@ bool lv_btnm_get_recolor(const lv_obj_t * btnm)
|
||||
*/
|
||||
uint16_t lv_btnm_get_active_btn(const lv_obj_t * btnm)
|
||||
{
|
||||
LV_ASSERT_OBJ(btnm, LV_OBJX_NAME);
|
||||
|
||||
lv_btnm_ext_t * ext = lv_obj_get_ext_attr(btnm);
|
||||
return ext->btn_id_act;
|
||||
}
|
||||
@@ -481,6 +517,8 @@ uint16_t lv_btnm_get_active_btn(const lv_obj_t * btnm)
|
||||
*/
|
||||
const char * lv_btnm_get_active_btn_text(const lv_obj_t * btnm)
|
||||
{
|
||||
LV_ASSERT_OBJ(btnm, LV_OBJX_NAME);
|
||||
|
||||
lv_btnm_ext_t * ext = lv_obj_get_ext_attr(btnm);
|
||||
if(ext->btn_id_act != LV_BTNM_BTN_NONE) {
|
||||
return lv_btnm_get_btn_text(btnm, ext->btn_id_act);
|
||||
@@ -497,6 +535,8 @@ const char * lv_btnm_get_active_btn_text(const lv_obj_t * btnm)
|
||||
*/
|
||||
uint16_t lv_btnm_get_pressed_btn(const lv_obj_t * btnm)
|
||||
{
|
||||
LV_ASSERT_OBJ(btnm, LV_OBJX_NAME);
|
||||
|
||||
lv_btnm_ext_t * ext = lv_obj_get_ext_attr(btnm);
|
||||
return ext->btn_id_pr;
|
||||
}
|
||||
@@ -510,6 +550,8 @@ uint16_t lv_btnm_get_pressed_btn(const lv_obj_t * btnm)
|
||||
*/
|
||||
const char * lv_btnm_get_btn_text(const lv_obj_t * btnm, uint16_t btn_id)
|
||||
{
|
||||
LV_ASSERT_OBJ(btnm, LV_OBJX_NAME);
|
||||
|
||||
lv_btnm_ext_t * ext = lv_obj_get_ext_attr(btnm);
|
||||
if(btn_id > ext->btn_cnt) return NULL;
|
||||
|
||||
@@ -539,6 +581,8 @@ const char * lv_btnm_get_btn_text(const lv_obj_t * btnm, uint16_t btn_id)
|
||||
*/
|
||||
bool lv_btnm_get_btn_ctrl(lv_obj_t * btnm, uint16_t btn_id, lv_btnm_ctrl_t ctrl)
|
||||
{
|
||||
LV_ASSERT_OBJ(btnm, LV_OBJX_NAME);
|
||||
|
||||
lv_btnm_ext_t * ext = lv_obj_get_ext_attr(btnm);
|
||||
if(btn_id >= ext->btn_cnt) return false;
|
||||
|
||||
@@ -553,6 +597,8 @@ bool lv_btnm_get_btn_ctrl(lv_obj_t * btnm, uint16_t btn_id, lv_btnm_ctrl_t ctrl)
|
||||
*/
|
||||
const lv_style_t * lv_btnm_get_style(const lv_obj_t * btnm, lv_btnm_style_t type)
|
||||
{
|
||||
LV_ASSERT_OBJ(btnm, LV_OBJX_NAME);
|
||||
|
||||
const lv_style_t * style = NULL;
|
||||
lv_btnm_ext_t * ext = lv_obj_get_ext_attr(btnm);
|
||||
|
||||
@@ -576,6 +622,8 @@ const lv_style_t * lv_btnm_get_style(const lv_obj_t * btnm, lv_btnm_style_t type
|
||||
*/
|
||||
bool lv_btnm_get_one_toggle(const lv_obj_t * btnm)
|
||||
{
|
||||
LV_ASSERT_OBJ(btnm, LV_OBJX_NAME);
|
||||
|
||||
lv_btnm_ext_t * ext = lv_obj_get_ext_attr(btnm);
|
||||
|
||||
return ext->one_toggle;
|
||||
@@ -603,7 +651,6 @@ static bool lv_btnm_design(lv_obj_t * btnm, const lv_area_t * mask, lv_design_mo
|
||||
}
|
||||
/*Draw the object*/
|
||||
else if(mode == LV_DESIGN_DRAW_MAIN) {
|
||||
|
||||
ancestor_design_f(btnm, mask, mode);
|
||||
|
||||
lv_btnm_ext_t * ext = lv_obj_get_ext_attr(btnm);
|
||||
@@ -624,7 +671,6 @@ static bool lv_btnm_design(lv_obj_t * btnm, const lv_area_t * mask, lv_design_mo
|
||||
lv_txt_flag_t txt_flag = LV_TXT_FLAG_NONE;
|
||||
|
||||
if(ext->recolor) txt_flag = LV_TXT_FLAG_RECOLOR;
|
||||
|
||||
for(btn_i = 0; btn_i < ext->btn_cnt; btn_i++, txt_i++) {
|
||||
/*Search the next valid text in the map*/
|
||||
while(strcmp(ext->map_p[txt_i], "\n") == 0) {
|
||||
@@ -693,9 +739,10 @@ static bool lv_btnm_design(lv_obj_t * btnm, const lv_area_t * mask, lv_design_mo
|
||||
area_tmp.x2 = area_tmp.x1 + txt_size.x;
|
||||
area_tmp.y2 = area_tmp.y1 + txt_size.y;
|
||||
|
||||
lv_draw_label(&area_tmp, mask, btn_style, opa_scale, ext->map_p[txt_i], txt_flag, NULL, -1, -1, NULL);
|
||||
lv_draw_label(&area_tmp, mask, btn_style, opa_scale, ext->map_p[txt_i], txt_flag, NULL, NULL, NULL, lv_obj_get_base_dir(btnm));
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -713,6 +760,7 @@ static lv_res_t lv_btnm_signal(lv_obj_t * btnm, lv_signal_t sign, void * param)
|
||||
/* Include the ancient signal function */
|
||||
res = ancestor_signal(btnm, sign, param);
|
||||
if(res != LV_RES_OK) return res;
|
||||
if(sign == LV_SIGNAL_GET_TYPE) return lv_obj_handle_get_type_signal(param, LV_OBJX_NAME);
|
||||
|
||||
lv_btnm_ext_t * ext = lv_obj_get_ext_attr(btnm);
|
||||
lv_point_t p;
|
||||
@@ -813,6 +861,12 @@ static lv_res_t lv_btnm_signal(lv_obj_t * btnm, lv_signal_t sign, void * param)
|
||||
#if LV_USE_GROUP
|
||||
lv_indev_t * indev = lv_indev_get_act();
|
||||
lv_indev_type_t indev_type = lv_indev_get_type(indev);
|
||||
|
||||
/*If not focused by an input device assume the last input device*/
|
||||
if(indev_type == LV_INDEV_TYPE_NONE) {
|
||||
indev_type = lv_indev_get_type(lv_indev_get_next(NULL));
|
||||
}
|
||||
|
||||
if(indev_type == LV_INDEV_TYPE_POINTER) {
|
||||
/*Select the clicked button*/
|
||||
lv_point_t p1;
|
||||
@@ -897,15 +951,7 @@ static lv_res_t lv_btnm_signal(lv_obj_t * btnm, lv_signal_t sign, void * param)
|
||||
} else if(sign == LV_SIGNAL_GET_EDITABLE) {
|
||||
bool * editable = (bool *)param;
|
||||
*editable = true;
|
||||
} else if(sign == LV_SIGNAL_GET_TYPE) {
|
||||
lv_obj_type_t * buf = param;
|
||||
uint8_t i;
|
||||
for(i = 0; i < LV_MAX_ANCESTOR_NUM - 1; i++) { /*Find the last set data*/
|
||||
if(buf->type[i] == NULL) break;
|
||||
}
|
||||
buf->type[i] = "lv_btnm";
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
@@ -938,9 +984,9 @@ static void allocate_btn_areas_and_controls(const lv_obj_t * btnm, const char **
|
||||
}
|
||||
|
||||
ext->button_areas = lv_mem_alloc(sizeof(lv_area_t) * btn_cnt);
|
||||
lv_mem_assert(ext->button_areas);
|
||||
LV_ASSERT_MEM(ext->button_areas);
|
||||
ext->ctrl_bits = lv_mem_alloc(sizeof(lv_btnm_ctrl_t) * btn_cnt);
|
||||
lv_mem_assert(ext->ctrl_bits);
|
||||
LV_ASSERT_MEM(ext->ctrl_bits);
|
||||
if(ext->button_areas == NULL || ext->ctrl_bits == NULL) btn_cnt = 0;
|
||||
|
||||
memset(ext->ctrl_bits, 0, sizeof(lv_btnm_ctrl_t) * btn_cnt);
|
||||
|
||||
@@ -31,6 +31,8 @@ extern "C" {
|
||||
#define LV_BTNM_WIDTH_MASK 0x0007
|
||||
#define LV_BTNM_BTN_NONE 0xFFFF
|
||||
|
||||
LV_EXPORT_CONST_INT(LV_BTNM_BTN_NONE);
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#include "lv_calendar.h"
|
||||
#if LV_USE_CALENDAR != 0
|
||||
|
||||
#include "../lv_core/lv_debug.h"
|
||||
#include "../lv_draw/lv_draw.h"
|
||||
#include "../lv_hal/lv_hal_indev.h"
|
||||
#include "../lv_misc/lv_utils.h"
|
||||
@@ -19,6 +20,7 @@
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
#define LV_OBJX_NAME "lv_calendar"
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
@@ -77,12 +79,12 @@ lv_obj_t * lv_calendar_create(lv_obj_t * par, const lv_obj_t * copy)
|
||||
|
||||
/*Create the ancestor of calendar*/
|
||||
lv_obj_t * new_calendar = lv_obj_create(par, copy);
|
||||
lv_mem_assert(new_calendar);
|
||||
LV_ASSERT_MEM(new_calendar);
|
||||
if(new_calendar == NULL) return NULL;
|
||||
|
||||
/*Allocate the calendar type specific extended data*/
|
||||
lv_calendar_ext_t * ext = lv_obj_allocate_ext_attr(new_calendar, sizeof(lv_calendar_ext_t));
|
||||
lv_mem_assert(ext);
|
||||
LV_ASSERT_MEM(ext);
|
||||
if(ext == NULL) return NULL;
|
||||
if(ancestor_signal == NULL) ancestor_signal = lv_obj_get_signal_cb(new_calendar);
|
||||
if(ancestor_design == NULL) ancestor_design = lv_obj_get_design_cb(new_calendar);
|
||||
@@ -195,6 +197,9 @@ lv_obj_t * lv_calendar_create(lv_obj_t * par, const lv_obj_t * copy)
|
||||
*/
|
||||
void lv_calendar_set_today_date(lv_obj_t * calendar, lv_calendar_date_t * today)
|
||||
{
|
||||
LV_ASSERT_OBJ(calendar, LV_OBJX_NAME);
|
||||
LV_ASSERT_NULL(today);
|
||||
|
||||
lv_calendar_ext_t * ext = lv_obj_get_ext_attr(calendar);
|
||||
ext->today.year = today->year;
|
||||
ext->today.month = today->month;
|
||||
@@ -211,6 +216,9 @@ void lv_calendar_set_today_date(lv_obj_t * calendar, lv_calendar_date_t * today)
|
||||
*/
|
||||
void lv_calendar_set_showed_date(lv_obj_t * calendar, lv_calendar_date_t * showed)
|
||||
{
|
||||
LV_ASSERT_OBJ(calendar, LV_OBJX_NAME);
|
||||
LV_ASSERT_NULL(showed);
|
||||
|
||||
lv_calendar_ext_t * ext = lv_obj_get_ext_attr(calendar);
|
||||
ext->showed_date.year = showed->year;
|
||||
ext->showed_date.month = showed->month;
|
||||
@@ -226,8 +234,11 @@ void lv_calendar_set_showed_date(lv_obj_t * calendar, lv_calendar_date_t * showe
|
||||
* WILL BE SAVED! CAN'T BE LOCAL ARRAY.
|
||||
* @param date_num number of dates in the array
|
||||
*/
|
||||
void lv_calendar_set_highlighted_dates(lv_obj_t * calendar, lv_calendar_date_t * highlighted, uint16_t date_num)
|
||||
void lv_calendar_set_highlighted_dates(lv_obj_t * calendar, lv_calendar_date_t highlighted[], uint16_t date_num)
|
||||
{
|
||||
LV_ASSERT_OBJ(calendar, LV_OBJX_NAME);
|
||||
LV_ASSERT_NULL(highlighted);
|
||||
|
||||
lv_calendar_ext_t * ext = lv_obj_get_ext_attr(calendar);
|
||||
ext->highlighted_dates = highlighted;
|
||||
ext->highlighted_dates_num = date_num;
|
||||
@@ -244,6 +255,9 @@ void lv_calendar_set_highlighted_dates(lv_obj_t * calendar, lv_calendar_date_t *
|
||||
*/
|
||||
void lv_calendar_set_day_names(lv_obj_t * calendar, const char ** day_names)
|
||||
{
|
||||
LV_ASSERT_OBJ(calendar, LV_OBJX_NAME);
|
||||
LV_ASSERT_NULL(day_names);
|
||||
|
||||
lv_calendar_ext_t * ext = lv_obj_get_ext_attr(calendar);
|
||||
ext->day_names = day_names;
|
||||
lv_obj_invalidate(calendar);
|
||||
@@ -252,14 +266,17 @@ void lv_calendar_set_day_names(lv_obj_t * calendar, const char ** day_names)
|
||||
/**
|
||||
* Set the name of the month
|
||||
* @param calendar pointer to a calendar object
|
||||
* @param day_names pointer to an array with the names. E.g. `const char * days[12] = {"Jan", "Feb",
|
||||
* @param month_names pointer to an array with the names. E.g. `const char * days[12] = {"Jan", "Feb",
|
||||
* ...}` Only the pointer will be saved so this variable can't be local which will be destroyed
|
||||
* later.
|
||||
*/
|
||||
void lv_calendar_set_month_names(lv_obj_t * calendar, const char ** day_names)
|
||||
void lv_calendar_set_month_names(lv_obj_t * calendar, const char ** month_names)
|
||||
{
|
||||
LV_ASSERT_OBJ(calendar, LV_OBJX_NAME);
|
||||
LV_ASSERT_NULL(month_names);
|
||||
|
||||
lv_calendar_ext_t * ext = lv_obj_get_ext_attr(calendar);
|
||||
ext->month_names = day_names;
|
||||
ext->month_names = month_names;
|
||||
lv_obj_invalidate(calendar);
|
||||
}
|
||||
|
||||
@@ -271,6 +288,8 @@ void lv_calendar_set_month_names(lv_obj_t * calendar, const char ** day_names)
|
||||
* */
|
||||
void lv_calendar_set_style(lv_obj_t * calendar, lv_calendar_style_t type, const lv_style_t * style)
|
||||
{
|
||||
LV_ASSERT_OBJ(calendar, LV_OBJX_NAME);
|
||||
|
||||
lv_calendar_ext_t * ext = lv_obj_get_ext_attr(calendar);
|
||||
|
||||
switch(type) {
|
||||
@@ -298,6 +317,8 @@ void lv_calendar_set_style(lv_obj_t * calendar, lv_calendar_style_t type, const
|
||||
*/
|
||||
lv_calendar_date_t * lv_calendar_get_today_date(const lv_obj_t * calendar)
|
||||
{
|
||||
LV_ASSERT_OBJ(calendar, LV_OBJX_NAME);
|
||||
|
||||
lv_calendar_ext_t * ext = lv_obj_get_ext_attr(calendar);
|
||||
return &ext->today;
|
||||
}
|
||||
@@ -309,6 +330,8 @@ lv_calendar_date_t * lv_calendar_get_today_date(const lv_obj_t * calendar)
|
||||
*/
|
||||
lv_calendar_date_t * lv_calendar_get_showed_date(const lv_obj_t * calendar)
|
||||
{
|
||||
LV_ASSERT_OBJ(calendar, LV_OBJX_NAME);
|
||||
|
||||
lv_calendar_ext_t * ext = lv_obj_get_ext_attr(calendar);
|
||||
return &ext->showed_date;
|
||||
}
|
||||
@@ -321,6 +344,8 @@ lv_calendar_date_t * lv_calendar_get_showed_date(const lv_obj_t * calendar)
|
||||
*/
|
||||
lv_calendar_date_t * lv_calendar_get_pressed_date(const lv_obj_t * calendar)
|
||||
{
|
||||
LV_ASSERT_OBJ(calendar, LV_OBJX_NAME);
|
||||
|
||||
lv_calendar_ext_t * ext = lv_obj_get_ext_attr(calendar);
|
||||
return ext->pressed_date.year != 0 ? &ext->pressed_date : NULL;
|
||||
}
|
||||
@@ -332,6 +357,8 @@ lv_calendar_date_t * lv_calendar_get_pressed_date(const lv_obj_t * calendar)
|
||||
*/
|
||||
lv_calendar_date_t * lv_calendar_get_highlighted_dates(const lv_obj_t * calendar)
|
||||
{
|
||||
LV_ASSERT_OBJ(calendar, LV_OBJX_NAME);
|
||||
|
||||
lv_calendar_ext_t * ext = lv_obj_get_ext_attr(calendar);
|
||||
return ext->highlighted_dates;
|
||||
}
|
||||
@@ -343,6 +370,8 @@ lv_calendar_date_t * lv_calendar_get_highlighted_dates(const lv_obj_t * calendar
|
||||
*/
|
||||
uint16_t lv_calendar_get_highlighted_dates_num(const lv_obj_t * calendar)
|
||||
{
|
||||
LV_ASSERT_OBJ(calendar, LV_OBJX_NAME);
|
||||
|
||||
lv_calendar_ext_t * ext = lv_obj_get_ext_attr(calendar);
|
||||
return ext->highlighted_dates_num;
|
||||
}
|
||||
@@ -354,6 +383,8 @@ uint16_t lv_calendar_get_highlighted_dates_num(const lv_obj_t * calendar)
|
||||
*/
|
||||
const char ** lv_calendar_get_day_names(const lv_obj_t * calendar)
|
||||
{
|
||||
LV_ASSERT_OBJ(calendar, LV_OBJX_NAME);
|
||||
|
||||
lv_calendar_ext_t * ext = lv_obj_get_ext_attr(calendar);
|
||||
return ext->day_names;
|
||||
}
|
||||
@@ -365,6 +396,8 @@ const char ** lv_calendar_get_day_names(const lv_obj_t * calendar)
|
||||
*/
|
||||
const char ** lv_calendar_get_month_names(const lv_obj_t * calendar)
|
||||
{
|
||||
LV_ASSERT_OBJ(calendar, LV_OBJX_NAME);
|
||||
|
||||
lv_calendar_ext_t * ext = lv_obj_get_ext_attr(calendar);
|
||||
return ext->month_names;
|
||||
}
|
||||
@@ -377,6 +410,8 @@ const char ** lv_calendar_get_month_names(const lv_obj_t * calendar)
|
||||
* */
|
||||
const lv_style_t * lv_calendar_get_style(const lv_obj_t * calendar, lv_calendar_style_t type)
|
||||
{
|
||||
LV_ASSERT_OBJ(calendar, LV_OBJX_NAME);
|
||||
|
||||
const lv_style_t * style = NULL;
|
||||
lv_calendar_ext_t * ext = lv_obj_get_ext_attr(calendar);
|
||||
|
||||
@@ -454,6 +489,7 @@ static lv_res_t lv_calendar_signal(lv_obj_t * calendar, lv_signal_t sign, void *
|
||||
/* Include the ancient signal function */
|
||||
res = ancestor_signal(calendar, sign, param);
|
||||
if(res != LV_RES_OK) return res;
|
||||
if(sign == LV_SIGNAL_GET_TYPE) return lv_obj_handle_get_type_signal(param, LV_OBJX_NAME);
|
||||
|
||||
if(sign == LV_SIGNAL_CLEANUP) {
|
||||
/*Nothing to cleanup. (No dynamically allocated memory in 'ext')*/
|
||||
@@ -542,13 +578,6 @@ static lv_res_t lv_calendar_signal(lv_obj_t * calendar, lv_signal_t sign, void *
|
||||
}
|
||||
lv_obj_invalidate(calendar);
|
||||
}
|
||||
} else if(sign == LV_SIGNAL_GET_TYPE) {
|
||||
lv_obj_type_t * buf = param;
|
||||
uint8_t i;
|
||||
for(i = 0; i < LV_MAX_ANCESTOR_NUM - 1; i++) { /*Find the last set date*/
|
||||
if(buf->type[i] == NULL) break;
|
||||
}
|
||||
buf->type[i] = "lv_calendar";
|
||||
}
|
||||
|
||||
return res;
|
||||
@@ -641,6 +670,9 @@ static lv_coord_t get_day_names_height(lv_obj_t * calendar)
|
||||
static void draw_header(lv_obj_t * calendar, const lv_area_t * mask)
|
||||
{
|
||||
lv_calendar_ext_t * ext = lv_obj_get_ext_attr(calendar);
|
||||
|
||||
lv_bidi_dir_t bidi_dir = lv_obj_get_base_dir(calendar);
|
||||
|
||||
lv_opa_t opa_scale = lv_obj_get_opa_scale(calendar);
|
||||
|
||||
lv_area_t header_area;
|
||||
@@ -658,19 +690,19 @@ static void draw_header(lv_obj_t * calendar, const lv_area_t * mask)
|
||||
txt_buf[5] = '\0';
|
||||
strcpy(&txt_buf[5], get_month_name(calendar, ext->showed_date.month));
|
||||
header_area.y1 += ext->style_header->body.padding.top;
|
||||
lv_draw_label(&header_area, mask, ext->style_header, opa_scale, txt_buf, LV_TXT_FLAG_CENTER, NULL, -1, -1, NULL);
|
||||
lv_draw_label(&header_area, mask, ext->style_header, opa_scale, txt_buf, LV_TXT_FLAG_CENTER, NULL, NULL, NULL, bidi_dir);
|
||||
|
||||
/*Add the left arrow*/
|
||||
const lv_style_t * arrow_style = ext->btn_pressing < 0 ? ext->style_header_pr : ext->style_header;
|
||||
header_area.x1 += ext->style_header->body.padding.left;
|
||||
lv_draw_label(&header_area, mask, arrow_style, opa_scale, LV_SYMBOL_LEFT, LV_TXT_FLAG_NONE, NULL, -1, -1, NULL);
|
||||
lv_draw_label(&header_area, mask, arrow_style, opa_scale, LV_SYMBOL_LEFT, LV_TXT_FLAG_NONE, NULL, NULL, NULL, bidi_dir);
|
||||
|
||||
/*Add the right arrow*/
|
||||
arrow_style = ext->btn_pressing > 0 ? ext->style_header_pr : ext->style_header;
|
||||
header_area.x1 = header_area.x2 - ext->style_header->body.padding.right -
|
||||
lv_txt_get_width(LV_SYMBOL_RIGHT, strlen(LV_SYMBOL_RIGHT), arrow_style->text.font,
|
||||
arrow_style->text.line_space, LV_TXT_FLAG_NONE);
|
||||
lv_draw_label(&header_area, mask, arrow_style, opa_scale, LV_SYMBOL_RIGHT, LV_TXT_FLAG_NONE, NULL, -1, -1, NULL);
|
||||
lv_draw_label(&header_area, mask, arrow_style, opa_scale, LV_SYMBOL_RIGHT, LV_TXT_FLAG_NONE, NULL, NULL, NULL, bidi_dir);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -681,6 +713,7 @@ static void draw_header(lv_obj_t * calendar, const lv_area_t * mask)
|
||||
static void draw_day_names(lv_obj_t * calendar, const lv_area_t * mask)
|
||||
{
|
||||
lv_calendar_ext_t * ext = lv_obj_get_ext_attr(calendar);
|
||||
lv_bidi_dir_t bidi_dir = lv_obj_get_base_dir(calendar);
|
||||
lv_opa_t opa_scale = lv_obj_get_opa_scale(calendar);
|
||||
|
||||
lv_coord_t l_pad = ext->style_day_names->body.padding.left;
|
||||
@@ -695,7 +728,7 @@ static void draw_day_names(lv_obj_t * calendar, const lv_area_t * mask)
|
||||
label_area.x1 = calendar->coords.x1 + (w * i) / 7 + l_pad;
|
||||
label_area.x2 = label_area.x1 + box_w - 1;
|
||||
lv_draw_label(&label_area, mask, ext->style_day_names, opa_scale, get_day_name(calendar, i), LV_TXT_FLAG_CENTER,
|
||||
NULL, -1, -1, NULL);
|
||||
NULL, NULL, NULL, bidi_dir);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -707,6 +740,7 @@ static void draw_day_names(lv_obj_t * calendar, const lv_area_t * mask)
|
||||
static void draw_days(lv_obj_t * calendar, const lv_area_t * mask)
|
||||
{
|
||||
lv_calendar_ext_t * ext = lv_obj_get_ext_attr(calendar);
|
||||
lv_bidi_dir_t bidi_dir = lv_obj_get_base_dir(calendar);
|
||||
const lv_style_t * style_bg = lv_calendar_get_style(calendar, LV_CALENDAR_STYLE_BG);
|
||||
lv_area_t label_area;
|
||||
lv_opa_t opa_scale = lv_obj_get_opa_scale(calendar);
|
||||
@@ -824,7 +858,7 @@ static void draw_days(lv_obj_t * calendar, const lv_area_t * mask)
|
||||
|
||||
/*Write the day's number*/
|
||||
lv_utils_num_to_str(day_cnt, buf);
|
||||
lv_draw_label(&label_area, mask, final_style, opa_scale, buf, LV_TXT_FLAG_CENTER, NULL, -1, -1, NULL);
|
||||
lv_draw_label(&label_area, mask, final_style, opa_scale, buf, LV_TXT_FLAG_CENTER, NULL, NULL, NULL, bidi_dir);
|
||||
|
||||
/*Go to the next day*/
|
||||
day_cnt++;
|
||||
|
||||
@@ -122,7 +122,7 @@ void lv_calendar_set_showed_date(lv_obj_t * calendar, lv_calendar_date_t * showe
|
||||
* WILL BE SAVED! CAN'T BE LOCAL ARRAY.
|
||||
* @param date_num number of dates in the array
|
||||
*/
|
||||
void lv_calendar_set_highlighted_dates(lv_obj_t * calendar, lv_calendar_date_t * highlighted, uint16_t date_num);
|
||||
void lv_calendar_set_highlighted_dates(lv_obj_t * calendar, lv_calendar_date_t highlighted[], uint16_t date_num);
|
||||
|
||||
/**
|
||||
* Set the name of the days
|
||||
@@ -136,11 +136,11 @@ void lv_calendar_set_day_names(lv_obj_t * calendar, const char ** day_names);
|
||||
/**
|
||||
* Set the name of the month
|
||||
* @param calendar pointer to a calendar object
|
||||
* @param day_names pointer to an array with the names. E.g. `const char * days[12] = {"Jan", "Feb",
|
||||
* @param month_names pointer to an array with the names. E.g. `const char * days[12] = {"Jan", "Feb",
|
||||
* ...}` Only the pointer will be saved so this variable can't be local which will be destroyed
|
||||
* later.
|
||||
*/
|
||||
void lv_calendar_set_month_names(lv_obj_t * calendar, const char ** day_names);
|
||||
void lv_calendar_set_month_names(lv_obj_t * calendar, const char ** month_names);
|
||||
|
||||
/**
|
||||
* Set a style of a calendar.
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
*********************/
|
||||
#include <stdlib.h>
|
||||
#include "lv_canvas.h"
|
||||
#include "../lv_core/lv_debug.h"
|
||||
#include "../lv_misc/lv_math.h"
|
||||
#include "../lv_draw/lv_draw.h"
|
||||
#include "../lv_core/lv_refr.h"
|
||||
@@ -17,6 +18,7 @@
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
#define LV_OBJX_NAME "lv_canvas"
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
@@ -53,12 +55,12 @@ lv_obj_t * lv_canvas_create(lv_obj_t * par, const lv_obj_t * copy)
|
||||
|
||||
/*Create the ancestor of canvas*/
|
||||
lv_obj_t * new_canvas = lv_img_create(par, copy);
|
||||
lv_mem_assert(new_canvas);
|
||||
LV_ASSERT_MEM(new_canvas);
|
||||
if(new_canvas == NULL) return NULL;
|
||||
|
||||
/*Allocate the canvas type specific extended data*/
|
||||
lv_canvas_ext_t * ext = lv_obj_allocate_ext_attr(new_canvas, sizeof(lv_canvas_ext_t));
|
||||
lv_mem_assert(ext);
|
||||
LV_ASSERT_MEM(ext);
|
||||
if(ext == NULL) return NULL;
|
||||
if(ancestor_signal == NULL) ancestor_signal = lv_obj_get_signal_cb(new_canvas);
|
||||
if(ancestor_design == NULL) ancestor_design = lv_obj_get_design_cb(new_canvas);
|
||||
@@ -111,6 +113,9 @@ lv_obj_t * lv_canvas_create(lv_obj_t * par, const lv_obj_t * copy)
|
||||
*/
|
||||
void lv_canvas_set_buffer(lv_obj_t * canvas, void * buf, lv_coord_t w, lv_coord_t h, lv_img_cf_t cf)
|
||||
{
|
||||
LV_ASSERT_OBJ(canvas, LV_OBJX_NAME);
|
||||
LV_ASSERT_NULL(buf);
|
||||
|
||||
lv_canvas_ext_t * ext = lv_obj_get_ext_attr(canvas);
|
||||
|
||||
ext->dsc.header.cf = cf;
|
||||
@@ -131,6 +136,8 @@ void lv_canvas_set_buffer(lv_obj_t * canvas, void * buf, lv_coord_t w, lv_coord_
|
||||
*/
|
||||
void lv_canvas_set_px(lv_obj_t * canvas, lv_coord_t x, lv_coord_t y, lv_color_t c)
|
||||
{
|
||||
LV_ASSERT_OBJ(canvas, LV_OBJX_NAME);
|
||||
|
||||
lv_canvas_ext_t * ext = lv_obj_get_ext_attr(canvas);
|
||||
|
||||
lv_img_buf_set_px_color(&ext->dsc, x, y, c);
|
||||
@@ -149,6 +156,8 @@ void lv_canvas_set_px(lv_obj_t * canvas, lv_coord_t x, lv_coord_t y, lv_color_t
|
||||
*/
|
||||
void lv_canvas_set_palette(lv_obj_t * canvas, uint8_t id, lv_color_t c)
|
||||
{
|
||||
LV_ASSERT_OBJ(canvas, LV_OBJX_NAME);
|
||||
|
||||
lv_canvas_ext_t * ext = lv_obj_get_ext_attr(canvas);
|
||||
|
||||
lv_img_buf_set_palette(&ext->dsc, id, c);
|
||||
@@ -163,6 +172,8 @@ void lv_canvas_set_palette(lv_obj_t * canvas, uint8_t id, lv_color_t c)
|
||||
*/
|
||||
void lv_canvas_set_style(lv_obj_t * canvas, lv_canvas_style_t type, const lv_style_t * style)
|
||||
{
|
||||
LV_ASSERT_OBJ(canvas, LV_OBJX_NAME);
|
||||
|
||||
switch(type) {
|
||||
case LV_CANVAS_STYLE_MAIN: lv_img_set_style(canvas, LV_IMG_STYLE_MAIN, style); break;
|
||||
}
|
||||
@@ -181,6 +192,8 @@ void lv_canvas_set_style(lv_obj_t * canvas, lv_canvas_style_t type, const lv_sty
|
||||
*/
|
||||
lv_color_t lv_canvas_get_px(lv_obj_t * canvas, lv_coord_t x, lv_coord_t y)
|
||||
{
|
||||
LV_ASSERT_OBJ(canvas, LV_OBJX_NAME);
|
||||
|
||||
lv_canvas_ext_t * ext = lv_obj_get_ext_attr(canvas);
|
||||
const lv_style_t * style = lv_canvas_get_style(canvas, LV_CANVAS_STYLE_MAIN);
|
||||
|
||||
@@ -194,6 +207,8 @@ lv_color_t lv_canvas_get_px(lv_obj_t * canvas, lv_coord_t x, lv_coord_t y)
|
||||
*/
|
||||
lv_img_dsc_t * lv_canvas_get_img(lv_obj_t * canvas)
|
||||
{
|
||||
LV_ASSERT_OBJ(canvas, LV_OBJX_NAME);
|
||||
|
||||
lv_canvas_ext_t * ext = lv_obj_get_ext_attr(canvas);
|
||||
|
||||
return &ext->dsc;
|
||||
@@ -207,6 +222,8 @@ lv_img_dsc_t * lv_canvas_get_img(lv_obj_t * canvas)
|
||||
*/
|
||||
const lv_style_t * lv_canvas_get_style(const lv_obj_t * canvas, lv_canvas_style_t type)
|
||||
{
|
||||
LV_ASSERT_OBJ(canvas, LV_OBJX_NAME);
|
||||
|
||||
const lv_style_t * style = NULL;
|
||||
|
||||
switch(type) {
|
||||
@@ -233,6 +250,9 @@ const lv_style_t * lv_canvas_get_style(const lv_obj_t * canvas, lv_canvas_style_
|
||||
*/
|
||||
void lv_canvas_copy_buf(lv_obj_t * canvas, const void * to_copy, lv_coord_t x, lv_coord_t y, lv_coord_t w, lv_coord_t h)
|
||||
{
|
||||
LV_ASSERT_OBJ(canvas, LV_OBJX_NAME);
|
||||
LV_ASSERT_NULL(to_copy);
|
||||
|
||||
lv_canvas_ext_t * ext = lv_obj_get_ext_attr(canvas);
|
||||
if(x + w >= ext->dsc.header.w || y + h >= ext->dsc.header.h) {
|
||||
LV_LOG_WARN("lv_canvas_copy_buf: x or y out of the canvas");
|
||||
@@ -266,6 +286,9 @@ void lv_canvas_copy_buf(lv_obj_t * canvas, const void * to_copy, lv_coord_t x, l
|
||||
void lv_canvas_rotate(lv_obj_t * canvas, lv_img_dsc_t * img, int16_t angle, lv_coord_t offset_x, lv_coord_t offset_y,
|
||||
int32_t pivot_x, int32_t pivot_y)
|
||||
{
|
||||
LV_ASSERT_OBJ(canvas, LV_OBJX_NAME);
|
||||
LV_ASSERT_NULL(img);
|
||||
|
||||
lv_canvas_ext_t * ext_dst = lv_obj_get_ext_attr(canvas);
|
||||
const lv_style_t * style = lv_canvas_get_style(canvas, LV_CANVAS_STYLE_MAIN);
|
||||
int32_t sinma = lv_trigo_sin(-angle);
|
||||
@@ -430,6 +453,8 @@ void lv_canvas_rotate(lv_obj_t * canvas, lv_img_dsc_t * img, int16_t angle, lv_c
|
||||
*/
|
||||
void lv_canvas_fill_bg(lv_obj_t * canvas, lv_color_t color)
|
||||
{
|
||||
LV_ASSERT_OBJ(canvas, LV_OBJX_NAME);
|
||||
|
||||
lv_img_dsc_t * dsc = lv_canvas_get_img(canvas);
|
||||
|
||||
uint32_t x = dsc->header.w * dsc->header.h;
|
||||
@@ -453,6 +478,9 @@ void lv_canvas_fill_bg(lv_obj_t * canvas, lv_color_t color)
|
||||
void lv_canvas_draw_rect(lv_obj_t * canvas, lv_coord_t x, lv_coord_t y, lv_coord_t w, lv_coord_t h,
|
||||
const lv_style_t * style)
|
||||
{
|
||||
LV_ASSERT_OBJ(canvas, LV_OBJX_NAME);
|
||||
LV_ASSERT_NULL(style);
|
||||
|
||||
lv_img_dsc_t * dsc = lv_canvas_get_img(canvas);
|
||||
|
||||
/* Create a dummy display to fool the lv_draw function.
|
||||
@@ -514,6 +542,9 @@ void lv_canvas_draw_rect(lv_obj_t * canvas, lv_coord_t x, lv_coord_t y, lv_coord
|
||||
void lv_canvas_draw_text(lv_obj_t * canvas, lv_coord_t x, lv_coord_t y, lv_coord_t max_w, const lv_style_t * style,
|
||||
const char * txt, lv_label_align_t align)
|
||||
{
|
||||
LV_ASSERT_OBJ(canvas, LV_OBJX_NAME);
|
||||
LV_ASSERT_NULL(style);
|
||||
|
||||
lv_img_dsc_t * dsc = lv_canvas_get_img(canvas);
|
||||
|
||||
/* Create a dummy display to fool the lv_draw function.
|
||||
@@ -554,8 +585,7 @@ void lv_canvas_draw_text(lv_obj_t * canvas, lv_coord_t x, lv_coord_t y, lv_coord
|
||||
default: flag = LV_TXT_FLAG_NONE; break;
|
||||
}
|
||||
|
||||
lv_draw_label(&coords, &mask, style, LV_OPA_COVER, txt, flag, NULL, LV_LABEL_TEXT_SEL_OFF, LV_LABEL_TEXT_SEL_OFF,
|
||||
NULL);
|
||||
lv_draw_label(&coords, &mask, style, LV_OPA_COVER, txt, flag, NULL, NULL, NULL, lv_obj_get_base_dir(canvas));
|
||||
|
||||
lv_refr_set_disp_refreshing(refr_ori);
|
||||
}
|
||||
@@ -568,6 +598,9 @@ void lv_canvas_draw_text(lv_obj_t * canvas, lv_coord_t x, lv_coord_t y, lv_coord
|
||||
*/
|
||||
void lv_canvas_draw_img(lv_obj_t * canvas, lv_coord_t x, lv_coord_t y, const void * src, const lv_style_t * style)
|
||||
{
|
||||
LV_ASSERT_OBJ(canvas, LV_OBJX_NAME);
|
||||
LV_ASSERT_NULL(style);
|
||||
|
||||
lv_img_dsc_t * dsc = lv_canvas_get_img(canvas);
|
||||
|
||||
/* Create a dummy display to fool the lv_draw function.
|
||||
@@ -621,6 +654,9 @@ void lv_canvas_draw_img(lv_obj_t * canvas, lv_coord_t x, lv_coord_t y, const voi
|
||||
*/
|
||||
void lv_canvas_draw_line(lv_obj_t * canvas, const lv_point_t * points, uint32_t point_cnt, const lv_style_t * style)
|
||||
{
|
||||
LV_ASSERT_OBJ(canvas, LV_OBJX_NAME);
|
||||
LV_ASSERT_NULL(style);
|
||||
|
||||
lv_img_dsc_t * dsc = lv_canvas_get_img(canvas);
|
||||
|
||||
/* Create a dummy display to fool the lv_draw function.
|
||||
@@ -658,11 +694,37 @@ void lv_canvas_draw_line(lv_obj_t * canvas, const lv_point_t * points, uint32_t
|
||||
lv_disp_t * refr_ori = lv_refr_get_disp_refreshing();
|
||||
lv_refr_set_disp_refreshing(&disp);
|
||||
|
||||
lv_style_t circle_style_tmp; /*If rounded...*/
|
||||
if(style->line.rounded) {
|
||||
lv_style_copy(&circle_style_tmp, style);
|
||||
circle_style_tmp.body.radius = LV_RADIUS_CIRCLE;
|
||||
circle_style_tmp.body.main_color = style->line.color;
|
||||
circle_style_tmp.body.grad_color = style->line.color;
|
||||
circle_style_tmp.body.opa = style->line.opa;
|
||||
}
|
||||
lv_area_t circle_area;
|
||||
uint32_t i;
|
||||
for(i = 0; i < point_cnt - 1; i++) {
|
||||
lv_draw_line(&points[i], &points[i + 1], &mask, style, LV_OPA_COVER);
|
||||
|
||||
/*Draw circle on the joints if enabled*/
|
||||
if(style->line.rounded) {
|
||||
circle_area.x1 = points[i].x - ((style->line.width - 1) >> 1) - ((style->line.width - 1) & 0x1);
|
||||
circle_area.y1 = points[i].y - ((style->line.width - 1) >> 1) - ((style->line.width - 1) & 0x1);
|
||||
circle_area.x2 = points[i].x + ((style->line.width - 1) >> 1);
|
||||
circle_area.y2 = points[i].y + ((style->line.width - 1) >> 1);
|
||||
lv_draw_rect(&circle_area, &mask, &circle_style_tmp, LV_OPA_COVER);
|
||||
}
|
||||
}
|
||||
|
||||
/*Draw circle on the last point too if enabled*/
|
||||
if(style->line.rounded) {
|
||||
circle_area.x1 = points[i].x - ((style->line.width - 1) >> 1) - ((style->line.width - 1) & 0x1);
|
||||
circle_area.y1 = points[i].y - ((style->line.width - 1) >> 1) - ((style->line.width - 1) & 0x1);
|
||||
circle_area.x2 = points[i].x + ((style->line.width - 1) >> 1);
|
||||
circle_area.y2 = points[i].y + ((style->line.width - 1) >> 1);
|
||||
lv_draw_rect(&circle_area, &mask, &circle_style_tmp, LV_OPA_COVER);
|
||||
}
|
||||
|
||||
lv_refr_set_disp_refreshing(refr_ori);
|
||||
}
|
||||
|
||||
@@ -675,6 +737,9 @@ void lv_canvas_draw_line(lv_obj_t * canvas, const lv_point_t * points, uint32_t
|
||||
*/
|
||||
void lv_canvas_draw_polygon(lv_obj_t * canvas, const lv_point_t * points, uint32_t point_cnt, const lv_style_t * style)
|
||||
{
|
||||
LV_ASSERT_OBJ(canvas, LV_OBJX_NAME);
|
||||
LV_ASSERT_NULL(style);
|
||||
|
||||
lv_img_dsc_t * dsc = lv_canvas_get_img(canvas);
|
||||
|
||||
/* Create a dummy display to fool the lv_draw function.
|
||||
@@ -730,6 +795,9 @@ void lv_canvas_draw_polygon(lv_obj_t * canvas, const lv_point_t * points, uint32
|
||||
void lv_canvas_draw_arc(lv_obj_t * canvas, lv_coord_t x, lv_coord_t y, lv_coord_t r, int32_t start_angle,
|
||||
int32_t end_angle, const lv_style_t * style)
|
||||
{
|
||||
LV_ASSERT_OBJ(canvas, LV_OBJX_NAME);
|
||||
LV_ASSERT_NULL(style);
|
||||
|
||||
lv_img_dsc_t * dsc = lv_canvas_get_img(canvas);
|
||||
|
||||
/* Create a dummy display to fool the lv_draw function.
|
||||
@@ -790,16 +858,10 @@ static lv_res_t lv_canvas_signal(lv_obj_t * canvas, lv_signal_t sign, void * par
|
||||
/* Include the ancient signal function */
|
||||
res = ancestor_signal(canvas, sign, param);
|
||||
if(res != LV_RES_OK) return res;
|
||||
if(sign == LV_SIGNAL_GET_TYPE) return lv_obj_handle_get_type_signal(param, LV_OBJX_NAME);
|
||||
|
||||
if(sign == LV_SIGNAL_CLEANUP) {
|
||||
/*Nothing to cleanup. (No dynamically allocated memory in 'ext')*/
|
||||
} else if(sign == LV_SIGNAL_GET_TYPE) {
|
||||
lv_obj_type_t * buf = param;
|
||||
uint8_t i;
|
||||
for(i = 0; i < LV_MAX_ANCESTOR_NUM - 1; i++) { /*Find the last set data*/
|
||||
if(buf->type[i] == NULL) break;
|
||||
}
|
||||
buf->type[i] = "lv_canvas";
|
||||
}
|
||||
|
||||
return res;
|
||||
|
||||
@@ -23,6 +23,7 @@ extern "C" {
|
||||
|
||||
#include "../lv_core/lv_obj.h"
|
||||
#include "../lv_objx/lv_img.h"
|
||||
#include "../lv_draw/lv_draw_img.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
@@ -239,21 +240,21 @@ void lv_canvas_draw_arc(lv_obj_t * canvas, lv_coord_t x, lv_coord_t y, lv_coord_
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
#define LV_CANVAS_BUF_SIZE_TRUE_COLOR(w, h) ((LV_COLOR_SIZE / 8) * w * h)
|
||||
#define LV_CANVAS_BUF_SIZE_TRUE_COLOR_CHROMA_KEYED(w, h) ((LV_COLOR_SIZE / 8) * w * h)
|
||||
#define LV_CANVAS_BUF_SIZE_TRUE_COLOR_ALPHA(w, h) (LV_IMG_PX_SIZE_ALPHA_BYTE * w * h)
|
||||
#define LV_CANVAS_BUF_SIZE_TRUE_COLOR(w, h) LV_IMG_BUF_SIZE_TRUE_COLOR(w, h)
|
||||
#define LV_CANVAS_BUF_SIZE_TRUE_COLOR_CHROMA_KEYED(w, h) LV_IMG_BUF_SIZE_TRUE_COLOR_CHROMA_KEYED(w, h)
|
||||
#define LV_CANVAS_BUF_SIZE_TRUE_COLOR_ALPHA(w, h) LV_IMG_BUF_SIZE_TRUE_COLOR_ALPHA(w, h)
|
||||
|
||||
/*+ 1: to be sure no fractional row*/
|
||||
#define LV_CANVAS_BUF_SIZE_ALPHA_1BIT(w, h) ((((w / 8) + 1) * h))
|
||||
#define LV_CANVAS_BUF_SIZE_ALPHA_2BIT(w, h) ((((w / 4) + 1) * h))
|
||||
#define LV_CANVAS_BUF_SIZE_ALPHA_4BIT(w, h) ((((w / 2) + 1) * h))
|
||||
#define LV_CANVAS_BUF_SIZE_ALPHA_8BIT(w, h) ((w * h))
|
||||
#define LV_CANVAS_BUF_SIZE_ALPHA_1BIT(w, h) LV_IMG_BUF_SIZE_ALPHA_1BIT(w, h)
|
||||
#define LV_CANVAS_BUF_SIZE_ALPHA_2BIT(w, h) LV_IMG_BUF_SIZE_ALPHA_2BIT(w, h)
|
||||
#define LV_CANVAS_BUF_SIZE_ALPHA_4BIT(w, h) LV_IMG_BUF_SIZE_ALPHA_4BIT(w, h)
|
||||
#define LV_CANVAS_BUF_SIZE_ALPHA_8BIT(w, h) LV_IMG_BUF_SIZE_ALPHA_8BIT(w, h)
|
||||
|
||||
/*4 * X: for palette*/
|
||||
#define LV_CANVAS_BUF_SIZE_INDEXED_1BIT(w, h) (LV_CANVAS_BUF_SIZE_ALPHA_1BIT(w, h) + 4 * 2)
|
||||
#define LV_CANVAS_BUF_SIZE_INDEXED_2BIT(w, h) (LV_CANVAS_BUF_SIZE_ALPHA_2BIT(w, h) + 4 * 4)
|
||||
#define LV_CANVAS_BUF_SIZE_INDEXED_4BIT(w, h) (LV_CANVAS_BUF_SIZE_ALPHA_4BIT(w, h) + 4 * 16)
|
||||
#define LV_CANVAS_BUF_SIZE_INDEXED_8BIT(w, h) (LV_CANVAS_BUF_SIZE_ALPHA_8BIT(w, h) + 4 * 256)
|
||||
#define LV_CANVAS_BUF_SIZE_INDEXED_1BIT(w, h) LV_IMG_BUF_SIZE_INDEXED_1BIT(w, h)
|
||||
#define LV_CANVAS_BUF_SIZE_INDEXED_2BIT(w, h) LV_IMG_BUF_SIZE_INDEXED_2BIT(w, h)
|
||||
#define LV_CANVAS_BUF_SIZE_INDEXED_4BIT(w, h) LV_IMG_BUF_SIZE_INDEXED_4BIT(w, h)
|
||||
#define LV_CANVAS_BUF_SIZE_INDEXED_8BIT(w, h) LV_IMG_BUF_SIZE_INDEXED_8BIT(w, h)
|
||||
|
||||
#endif /*LV_USE_CANVAS*/
|
||||
|
||||
|
||||
@@ -9,12 +9,14 @@
|
||||
#include "lv_cb.h"
|
||||
#if LV_USE_CB != 0
|
||||
|
||||
#include "../lv_core/lv_debug.h"
|
||||
#include "../lv_core/lv_group.h"
|
||||
#include "../lv_themes/lv_theme.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
#define LV_OBJX_NAME "lv_cb"
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
@@ -55,14 +57,14 @@ lv_obj_t * lv_cb_create(lv_obj_t * par, const lv_obj_t * copy)
|
||||
|
||||
/*Create the ancestor basic object*/
|
||||
lv_obj_t * new_cb = lv_btn_create(par, copy);
|
||||
lv_mem_assert(new_cb);
|
||||
LV_ASSERT_MEM(new_cb);
|
||||
if(new_cb == NULL) return NULL;
|
||||
|
||||
if(ancestor_signal == NULL) ancestor_signal = lv_obj_get_signal_cb(new_cb);
|
||||
if(ancestor_bg_design == NULL) ancestor_bg_design = lv_obj_get_design_cb(new_cb);
|
||||
|
||||
lv_cb_ext_t * ext = lv_obj_allocate_ext_attr(new_cb, sizeof(lv_cb_ext_t));
|
||||
lv_mem_assert(ext);
|
||||
LV_ASSERT_MEM(ext);
|
||||
if(ext == NULL) return NULL;
|
||||
|
||||
ext->bullet = NULL;
|
||||
@@ -126,6 +128,8 @@ lv_obj_t * lv_cb_create(lv_obj_t * par, const lv_obj_t * copy)
|
||||
*/
|
||||
void lv_cb_set_text(lv_obj_t * cb, const char * txt)
|
||||
{
|
||||
LV_ASSERT_OBJ(cb, LV_OBJX_NAME);
|
||||
|
||||
lv_cb_ext_t * ext = lv_obj_get_ext_attr(cb);
|
||||
lv_label_set_text(ext->label, txt);
|
||||
}
|
||||
@@ -138,6 +142,8 @@ void lv_cb_set_text(lv_obj_t * cb, const char * txt)
|
||||
*/
|
||||
void lv_cb_set_static_text(lv_obj_t * cb, const char * txt)
|
||||
{
|
||||
LV_ASSERT_OBJ(cb, LV_OBJX_NAME);
|
||||
|
||||
lv_cb_ext_t * ext = lv_obj_get_ext_attr(cb);
|
||||
lv_label_set_static_text(ext->label, txt);
|
||||
}
|
||||
@@ -150,6 +156,8 @@ void lv_cb_set_static_text(lv_obj_t * cb, const char * txt)
|
||||
* */
|
||||
void lv_cb_set_style(lv_obj_t * cb, lv_cb_style_t type, const lv_style_t * style)
|
||||
{
|
||||
LV_ASSERT_OBJ(cb, LV_OBJX_NAME);
|
||||
|
||||
lv_cb_ext_t * ext = lv_obj_get_ext_attr(cb);
|
||||
|
||||
switch(type) {
|
||||
@@ -179,6 +187,8 @@ void lv_cb_set_style(lv_obj_t * cb, lv_cb_style_t type, const lv_style_t * style
|
||||
*/
|
||||
const char * lv_cb_get_text(const lv_obj_t * cb)
|
||||
{
|
||||
LV_ASSERT_OBJ(cb, LV_OBJX_NAME);
|
||||
|
||||
lv_cb_ext_t * ext = lv_obj_get_ext_attr(cb);
|
||||
return lv_label_get_text(ext->label);
|
||||
}
|
||||
@@ -191,6 +201,8 @@ const char * lv_cb_get_text(const lv_obj_t * cb)
|
||||
* */
|
||||
const lv_style_t * lv_cb_get_style(const lv_obj_t * cb, lv_cb_style_t type)
|
||||
{
|
||||
LV_ASSERT_OBJ(cb, LV_OBJX_NAME);
|
||||
|
||||
const lv_style_t * style = NULL;
|
||||
lv_cb_ext_t * ext = lv_obj_get_ext_attr(cb);
|
||||
|
||||
@@ -301,6 +313,7 @@ static lv_res_t lv_cb_signal(lv_obj_t * cb, lv_signal_t sign, void * param)
|
||||
/* Include the ancient signal function */
|
||||
res = ancestor_signal(cb, sign, param);
|
||||
if(res != LV_RES_OK) return res;
|
||||
if(sign == LV_SIGNAL_GET_TYPE) return lv_obj_handle_get_type_signal(param, LV_OBJX_NAME);
|
||||
|
||||
lv_cb_ext_t * ext = lv_obj_get_ext_attr(cb);
|
||||
|
||||
@@ -317,13 +330,6 @@ static lv_res_t lv_cb_signal(lv_obj_t * cb, lv_signal_t sign, void * param)
|
||||
/*Follow the backgrounds state with the bullet*/
|
||||
lv_btn_set_state(ext->bullet, lv_btn_get_state(cb));
|
||||
}
|
||||
} else if(sign == LV_SIGNAL_GET_TYPE) {
|
||||
lv_obj_type_t * buf = param;
|
||||
uint8_t i;
|
||||
for(i = 0; i < LV_MAX_ANCESTOR_NUM - 1; i++) { /*Find the last set data*/
|
||||
if(buf->type[i] == NULL) break;
|
||||
}
|
||||
buf->type[i] = "lv_cb";
|
||||
}
|
||||
|
||||
return res;
|
||||
|
||||
@@ -149,7 +149,7 @@ static inline bool lv_cb_is_checked(const lv_obj_t * cb)
|
||||
*/
|
||||
static inline bool lv_cb_is_inactive(const lv_obj_t * cb)
|
||||
{
|
||||
return lv_btn_get_state(cb) == LV_BTN_STATE_INA ? false : true;
|
||||
return lv_btn_get_state(cb) == LV_BTN_STATE_INA ? true :false;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#include "lv_chart.h"
|
||||
#if LV_USE_CHART != 0
|
||||
|
||||
#include "../lv_core/lv_debug.h"
|
||||
#include "../lv_core/lv_refr.h"
|
||||
#include "../lv_draw/lv_draw.h"
|
||||
#include "../lv_themes/lv_theme.h"
|
||||
@@ -16,6 +17,8 @@
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
#define LV_OBJX_NAME "lv_chart"
|
||||
|
||||
#define LV_CHART_YMIN_DEF 0
|
||||
#define LV_CHART_YMAX_DEF 100
|
||||
#define LV_CHART_HDIV_DEF 3
|
||||
@@ -24,11 +27,22 @@
|
||||
#define LV_CHART_AXIS_TO_LABEL_DISTANCE 4
|
||||
#define LV_CHART_AXIS_MAJOR_TICK_LEN_COE 1 / 15
|
||||
#define LV_CHART_AXIS_MINOR_TICK_LEN_COE 2 / 3
|
||||
#define LV_CHART_AXIS_PRIMARY_Y 1
|
||||
#define LV_CHART_AXIS_SECONDARY_Y 0
|
||||
#define LV_CHART_LABEL_ITERATOR_FORWARD 1
|
||||
#define LV_CHART_LABEL_ITERATOR_REVERSE 0
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
typedef struct {
|
||||
const char * list_start;
|
||||
const char * current_pos;
|
||||
uint8_t items_left;
|
||||
uint8_t is_reverse_iter;
|
||||
} lv_chart_label_iterator_t;
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
@@ -44,6 +58,9 @@ static void lv_chart_draw_axes(lv_obj_t * chart, const lv_area_t * mask);
|
||||
static void lv_chart_inv_lines(lv_obj_t * chart, uint16_t i);
|
||||
static void lv_chart_inv_points(lv_obj_t * chart, uint16_t i);
|
||||
static void lv_chart_inv_cols(lv_obj_t * chart, uint16_t i);
|
||||
static void lv_chart_get_next_label(lv_chart_label_iterator_t * iterator, char * buf);
|
||||
static inline bool lv_chart_is_tick_with_label(uint8_t tick_num, lv_chart_axis_cfg_t * axis);
|
||||
static lv_chart_label_iterator_t lv_chart_create_label_iter(const char * list, uint8_t iterator_dir);
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
@@ -72,12 +89,12 @@ lv_obj_t * lv_chart_create(lv_obj_t * par, const lv_obj_t * copy)
|
||||
|
||||
/*Create the ancestor basic object*/
|
||||
lv_obj_t * new_chart = lv_obj_create(par, copy);
|
||||
lv_mem_assert(new_chart);
|
||||
LV_ASSERT_MEM(new_chart);
|
||||
if(new_chart == NULL) return NULL;
|
||||
|
||||
/*Allocate the object type specific extended data*/
|
||||
lv_chart_ext_t * ext = lv_obj_allocate_ext_attr(new_chart, sizeof(lv_chart_ext_t));
|
||||
lv_mem_assert(ext);
|
||||
LV_ASSERT_MEM(ext);
|
||||
if(ext == NULL) return NULL;
|
||||
|
||||
lv_ll_init(&ext->series_ll, sizeof(lv_chart_series_t));
|
||||
@@ -96,10 +113,13 @@ lv_obj_t * lv_chart_create(lv_obj_t * par, const lv_obj_t * copy)
|
||||
ext->margin = 0;
|
||||
memset(&ext->x_axis, 0, sizeof(ext->x_axis));
|
||||
memset(&ext->y_axis, 0, sizeof(ext->y_axis));
|
||||
memset(&ext->secondary_y_axis, 0, sizeof(ext->secondary_y_axis));
|
||||
ext->x_axis.major_tick_len = LV_CHART_TICK_LENGTH_AUTO;
|
||||
ext->x_axis.minor_tick_len = LV_CHART_TICK_LENGTH_AUTO;
|
||||
ext->y_axis.major_tick_len = LV_CHART_TICK_LENGTH_AUTO;
|
||||
ext->y_axis.minor_tick_len = LV_CHART_TICK_LENGTH_AUTO;
|
||||
ext->secondary_y_axis.major_tick_len = LV_CHART_TICK_LENGTH_AUTO;
|
||||
ext->secondary_y_axis.minor_tick_len = LV_CHART_TICK_LENGTH_AUTO;
|
||||
|
||||
if(ancestor_design_f == NULL) ancestor_design_f = lv_obj_get_design_cb(new_chart);
|
||||
if(ancestor_signal == NULL) ancestor_signal = lv_obj_get_signal_cb(new_chart);
|
||||
@@ -132,6 +152,7 @@ lv_obj_t * lv_chart_create(lv_obj_t * par, const lv_obj_t * copy)
|
||||
ext->margin = ext_copy->margin;
|
||||
memcpy(&ext->x_axis, &ext_copy->x_axis, sizeof(lv_chart_axis_cfg_t));
|
||||
memcpy(&ext->y_axis, &ext_copy->y_axis, sizeof(lv_chart_axis_cfg_t));
|
||||
memcpy(&ext->secondary_y_axis, &ext_copy->secondary_y_axis, sizeof(lv_chart_axis_cfg_t));
|
||||
|
||||
/*Refresh the style with new signal function*/
|
||||
lv_obj_refresh_style(new_chart);
|
||||
@@ -154,9 +175,11 @@ lv_obj_t * lv_chart_create(lv_obj_t * par, const lv_obj_t * copy)
|
||||
*/
|
||||
lv_chart_series_t * lv_chart_add_series(lv_obj_t * chart, lv_color_t color)
|
||||
{
|
||||
LV_ASSERT_OBJ(chart, LV_OBJX_NAME);
|
||||
|
||||
lv_chart_ext_t * ext = lv_obj_get_ext_attr(chart);
|
||||
lv_chart_series_t * ser = lv_ll_ins_head(&ext->series_ll);
|
||||
lv_mem_assert(ser);
|
||||
LV_ASSERT_MEM(ser);
|
||||
if(ser == NULL) return NULL;
|
||||
|
||||
lv_coord_t def = LV_CHART_POINT_DEF;
|
||||
@@ -165,7 +188,7 @@ lv_chart_series_t * lv_chart_add_series(lv_obj_t * chart, lv_color_t color)
|
||||
|
||||
ser->color = color;
|
||||
ser->points = lv_mem_alloc(sizeof(lv_coord_t) * ext->point_cnt);
|
||||
lv_mem_assert(ser->points);
|
||||
LV_ASSERT_MEM(ser->points);
|
||||
if(ser->points == NULL) {
|
||||
lv_ll_rem(&ext->series_ll, ser);
|
||||
lv_mem_free(ser);
|
||||
@@ -193,6 +216,9 @@ lv_chart_series_t * lv_chart_add_series(lv_obj_t * chart, lv_color_t color)
|
||||
*/
|
||||
void lv_chart_clear_serie(lv_obj_t * chart, lv_chart_series_t * serie)
|
||||
{
|
||||
LV_ASSERT_OBJ(chart, LV_OBJX_NAME);
|
||||
LV_ASSERT_NULL(serie);
|
||||
|
||||
if(chart == NULL || serie == NULL) return;
|
||||
lv_chart_ext_t * ext = lv_obj_get_ext_attr(chart);
|
||||
if(ext == NULL) return;
|
||||
@@ -217,6 +243,8 @@ void lv_chart_clear_serie(lv_obj_t * chart, lv_chart_series_t * serie)
|
||||
*/
|
||||
void lv_chart_set_div_line_count(lv_obj_t * chart, uint8_t hdiv, uint8_t vdiv)
|
||||
{
|
||||
LV_ASSERT_OBJ(chart, LV_OBJX_NAME);
|
||||
|
||||
lv_chart_ext_t * ext = lv_obj_get_ext_attr(chart);
|
||||
if(ext->hdiv_cnt == hdiv && ext->vdiv_cnt == vdiv) return;
|
||||
|
||||
@@ -234,6 +262,8 @@ void lv_chart_set_div_line_count(lv_obj_t * chart, uint8_t hdiv, uint8_t vdiv)
|
||||
*/
|
||||
void lv_chart_set_range(lv_obj_t * chart, lv_coord_t ymin, lv_coord_t ymax)
|
||||
{
|
||||
LV_ASSERT_OBJ(chart, LV_OBJX_NAME);
|
||||
|
||||
lv_chart_ext_t * ext = lv_obj_get_ext_attr(chart);
|
||||
if(ext->ymin == ymin && ext->ymax == ymax) return;
|
||||
|
||||
@@ -250,6 +280,8 @@ void lv_chart_set_range(lv_obj_t * chart, lv_coord_t ymin, lv_coord_t ymax)
|
||||
*/
|
||||
void lv_chart_set_type(lv_obj_t * chart, lv_chart_type_t type)
|
||||
{
|
||||
LV_ASSERT_OBJ(chart, LV_OBJX_NAME);
|
||||
|
||||
lv_chart_ext_t * ext = lv_obj_get_ext_attr(chart);
|
||||
if(ext->type == type) return;
|
||||
|
||||
@@ -265,6 +297,8 @@ void lv_chart_set_type(lv_obj_t * chart, lv_chart_type_t type)
|
||||
*/
|
||||
void lv_chart_set_point_count(lv_obj_t * chart, uint16_t point_cnt)
|
||||
{
|
||||
LV_ASSERT_OBJ(chart, LV_OBJX_NAME);
|
||||
|
||||
lv_chart_ext_t * ext = lv_obj_get_ext_attr(chart);
|
||||
if(ext->point_cnt == point_cnt) return;
|
||||
|
||||
@@ -279,7 +313,7 @@ void lv_chart_set_point_count(lv_obj_t * chart, uint16_t point_cnt)
|
||||
{
|
||||
if(ser->start_point != 0) {
|
||||
lv_coord_t * new_points = lv_mem_alloc(sizeof(lv_coord_t) * point_cnt);
|
||||
lv_mem_assert(new_points);
|
||||
LV_ASSERT_MEM(new_points);
|
||||
if(new_points == NULL) return;
|
||||
|
||||
if(point_cnt >= point_cnt_old) {
|
||||
@@ -302,7 +336,7 @@ void lv_chart_set_point_count(lv_obj_t * chart, uint16_t point_cnt)
|
||||
ser->points = new_points;
|
||||
} else {
|
||||
ser->points = lv_mem_realloc(ser->points, sizeof(lv_coord_t) * point_cnt);
|
||||
lv_mem_assert(ser->points);
|
||||
LV_ASSERT_MEM(ser->points);
|
||||
if(ser->points == NULL) return;
|
||||
/*Initialize the new points*/
|
||||
if(point_cnt > point_cnt_old) {
|
||||
@@ -327,6 +361,8 @@ void lv_chart_set_point_count(lv_obj_t * chart, uint16_t point_cnt)
|
||||
*/
|
||||
void lv_chart_set_series_opa(lv_obj_t * chart, lv_opa_t opa)
|
||||
{
|
||||
LV_ASSERT_OBJ(chart, LV_OBJX_NAME);
|
||||
|
||||
lv_chart_ext_t * ext = lv_obj_get_ext_attr(chart);
|
||||
if(ext->series.opa == opa) return;
|
||||
|
||||
@@ -341,6 +377,8 @@ void lv_chart_set_series_opa(lv_obj_t * chart, lv_opa_t opa)
|
||||
*/
|
||||
void lv_chart_set_series_width(lv_obj_t * chart, lv_coord_t width)
|
||||
{
|
||||
LV_ASSERT_OBJ(chart, LV_OBJX_NAME);
|
||||
|
||||
lv_chart_ext_t * ext = lv_obj_get_ext_attr(chart);
|
||||
if(ext->series.width == width) return;
|
||||
|
||||
@@ -354,6 +392,8 @@ void lv_chart_set_series_width(lv_obj_t * chart, lv_coord_t width)
|
||||
*/
|
||||
void lv_chart_set_series_darking(lv_obj_t * chart, lv_opa_t dark_eff)
|
||||
{
|
||||
LV_ASSERT_OBJ(chart, LV_OBJX_NAME);
|
||||
|
||||
lv_chart_ext_t * ext = lv_obj_get_ext_attr(chart);
|
||||
if(ext->series.dark == dark_eff) return;
|
||||
|
||||
@@ -369,6 +409,9 @@ void lv_chart_set_series_darking(lv_obj_t * chart, lv_opa_t dark_eff)
|
||||
*/
|
||||
void lv_chart_init_points(lv_obj_t * chart, lv_chart_series_t * ser, lv_coord_t y)
|
||||
{
|
||||
LV_ASSERT_OBJ(chart, LV_OBJX_NAME);
|
||||
LV_ASSERT_NULL(ser);
|
||||
|
||||
lv_chart_ext_t * ext = lv_obj_get_ext_attr(chart);
|
||||
uint16_t i;
|
||||
for(i = 0; i < ext->point_cnt; i++) {
|
||||
@@ -386,6 +429,9 @@ void lv_chart_init_points(lv_obj_t * chart, lv_chart_series_t * ser, lv_coord_t
|
||||
*/
|
||||
void lv_chart_set_points(lv_obj_t * chart, lv_chart_series_t * ser, lv_coord_t y_array[])
|
||||
{
|
||||
LV_ASSERT_OBJ(chart, LV_OBJX_NAME);
|
||||
LV_ASSERT_NULL(ser);
|
||||
|
||||
lv_chart_ext_t * ext = lv_obj_get_ext_attr(chart);
|
||||
memcpy(ser->points, y_array, ext->point_cnt * (sizeof(lv_coord_t)));
|
||||
ser->start_point = 0;
|
||||
@@ -400,6 +446,9 @@ void lv_chart_set_points(lv_obj_t * chart, lv_chart_series_t * ser, lv_coord_t y
|
||||
*/
|
||||
void lv_chart_set_next(lv_obj_t * chart, lv_chart_series_t * ser, lv_coord_t y)
|
||||
{
|
||||
LV_ASSERT_OBJ(chart, LV_OBJX_NAME);
|
||||
LV_ASSERT_NULL(ser);
|
||||
|
||||
lv_chart_ext_t * ext = lv_obj_get_ext_attr(chart);
|
||||
if(ext->update_mode == LV_CHART_UPDATE_MODE_SHIFT) {
|
||||
ser->points[ser->start_point] =
|
||||
@@ -426,6 +475,8 @@ void lv_chart_set_next(lv_obj_t * chart, lv_chart_series_t * ser, lv_coord_t y)
|
||||
*/
|
||||
void lv_chart_set_update_mode(lv_obj_t * chart, lv_chart_update_mode_t update_mode)
|
||||
{
|
||||
LV_ASSERT_OBJ(chart, LV_OBJX_NAME);
|
||||
|
||||
lv_chart_ext_t * ext = lv_obj_get_ext_attr(chart);
|
||||
if(ext->update_mode == update_mode) return;
|
||||
|
||||
@@ -443,6 +494,8 @@ void lv_chart_set_update_mode(lv_obj_t * chart, lv_chart_update_mode_t update_mo
|
||||
*/
|
||||
void lv_chart_set_x_tick_length(lv_obj_t * chart, uint8_t major_tick_len, uint8_t minor_tick_len)
|
||||
{
|
||||
LV_ASSERT_OBJ(chart, LV_OBJX_NAME);
|
||||
|
||||
lv_chart_ext_t * ext = lv_obj_get_ext_attr(chart);
|
||||
ext->x_axis.major_tick_len = major_tick_len;
|
||||
ext->x_axis.minor_tick_len = minor_tick_len;
|
||||
@@ -458,11 +511,30 @@ void lv_chart_set_x_tick_length(lv_obj_t * chart, uint8_t major_tick_len, uint8_
|
||||
*/
|
||||
void lv_chart_set_y_tick_length(lv_obj_t * chart, uint8_t major_tick_len, uint8_t minor_tick_len)
|
||||
{
|
||||
LV_ASSERT_OBJ(chart, LV_OBJX_NAME);
|
||||
|
||||
lv_chart_ext_t * ext = lv_obj_get_ext_attr(chart);
|
||||
ext->y_axis.major_tick_len = major_tick_len;
|
||||
ext->y_axis.minor_tick_len = minor_tick_len;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the length of the tick marks on the secondary y axis
|
||||
* @param chart pointer to the chart
|
||||
* @param major_tick_len the length of the major tick or `LV_CHART_TICK_LENGTH_AUTO` to set automatically
|
||||
* (where labels are added)
|
||||
* @param minor_tick_len the length of the minor tick, `LV_CHART_TICK_LENGTH_AUTO` to set automatically
|
||||
* (where no labels are added)
|
||||
*/
|
||||
void lv_chart_set_secondary_y_tick_length(lv_obj_t * chart, uint8_t major_tick_len, uint8_t minor_tick_len)
|
||||
{
|
||||
LV_ASSERT_OBJ(chart, LV_OBJX_NAME);
|
||||
|
||||
lv_chart_ext_t * ext = lv_obj_get_ext_attr(chart);
|
||||
ext->secondary_y_axis.major_tick_len = major_tick_len;
|
||||
ext->secondary_y_axis.minor_tick_len = minor_tick_len;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the x-axis tick count and labels of a chart
|
||||
* @param chart pointer to a chart object
|
||||
@@ -474,6 +546,9 @@ void lv_chart_set_y_tick_length(lv_obj_t * chart, uint8_t major_tick_len, uint8_
|
||||
void lv_chart_set_x_tick_texts(lv_obj_t * chart, const char * list_of_values, uint8_t num_tick_marks,
|
||||
lv_chart_axis_options_t options)
|
||||
{
|
||||
LV_ASSERT_OBJ(chart, LV_OBJX_NAME);
|
||||
LV_ASSERT_NULL(list_of_values);
|
||||
|
||||
lv_chart_ext_t * ext = lv_obj_get_ext_attr(chart);
|
||||
ext->x_axis.num_tick_marks = num_tick_marks;
|
||||
ext->x_axis.list_of_values = list_of_values;
|
||||
@@ -491,12 +566,35 @@ void lv_chart_set_x_tick_texts(lv_obj_t * chart, const char * list_of_values, ui
|
||||
void lv_chart_set_y_tick_texts(lv_obj_t * chart, const char * list_of_values, uint8_t num_tick_marks,
|
||||
lv_chart_axis_options_t options)
|
||||
{
|
||||
LV_ASSERT_OBJ(chart, LV_OBJX_NAME);
|
||||
LV_ASSERT_NULL(list_of_values);
|
||||
|
||||
lv_chart_ext_t * ext = lv_obj_get_ext_attr(chart);
|
||||
ext->y_axis.num_tick_marks = num_tick_marks;
|
||||
ext->y_axis.list_of_values = list_of_values;
|
||||
ext->y_axis.options = options;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the secondary y-axis tick count and labels of a chart
|
||||
* @param chart pointer to a chart object
|
||||
* @param list_of_values list of string values, terminated with \n, except the last
|
||||
* @param num_tick_marks if list_of_values is NULL: total number of ticks per axis
|
||||
* else number of ticks between two value labels
|
||||
* @param options extra options
|
||||
*/
|
||||
void lv_chart_set_secondary_y_tick_texts(lv_obj_t * chart, const char * list_of_values, uint8_t num_tick_marks,
|
||||
lv_chart_axis_options_t options)
|
||||
{
|
||||
LV_ASSERT_OBJ(chart, LV_OBJX_NAME);
|
||||
LV_ASSERT_NULL(list_of_values);
|
||||
|
||||
lv_chart_ext_t * ext = lv_obj_get_ext_attr(chart);
|
||||
ext->secondary_y_axis.num_tick_marks = num_tick_marks;
|
||||
ext->secondary_y_axis.list_of_values = list_of_values;
|
||||
ext->secondary_y_axis.options = options;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the margin around the chart, used for axes value and ticks
|
||||
* @param chart pointer to an chart object
|
||||
@@ -504,6 +602,8 @@ void lv_chart_set_y_tick_texts(lv_obj_t * chart, const char * list_of_values, ui
|
||||
*/
|
||||
void lv_chart_set_margin(lv_obj_t * chart, uint16_t margin)
|
||||
{
|
||||
LV_ASSERT_OBJ(chart, LV_OBJX_NAME);
|
||||
|
||||
lv_chart_ext_t * ext = lv_obj_get_ext_attr(chart);
|
||||
ext->margin = margin;
|
||||
lv_obj_refresh_ext_draw_pad(chart);
|
||||
@@ -520,6 +620,8 @@ void lv_chart_set_margin(lv_obj_t * chart, uint16_t margin)
|
||||
*/
|
||||
lv_chart_type_t lv_chart_get_type(const lv_obj_t * chart)
|
||||
{
|
||||
LV_ASSERT_OBJ(chart, LV_OBJX_NAME);
|
||||
|
||||
lv_chart_ext_t * ext = lv_obj_get_ext_attr(chart);
|
||||
return ext->type;
|
||||
}
|
||||
@@ -531,6 +633,8 @@ lv_chart_type_t lv_chart_get_type(const lv_obj_t * chart)
|
||||
*/
|
||||
uint16_t lv_chart_get_point_cnt(const lv_obj_t * chart)
|
||||
{
|
||||
LV_ASSERT_OBJ(chart, LV_OBJX_NAME);
|
||||
|
||||
lv_chart_ext_t * ext = lv_obj_get_ext_attr(chart);
|
||||
return ext->point_cnt;
|
||||
}
|
||||
@@ -542,6 +646,8 @@ uint16_t lv_chart_get_point_cnt(const lv_obj_t * chart)
|
||||
*/
|
||||
lv_opa_t lv_chart_get_series_opa(const lv_obj_t * chart)
|
||||
{
|
||||
LV_ASSERT_OBJ(chart, LV_OBJX_NAME);
|
||||
|
||||
lv_chart_ext_t * ext = lv_obj_get_ext_attr(chart);
|
||||
return ext->series.opa;
|
||||
}
|
||||
@@ -553,6 +659,8 @@ lv_opa_t lv_chart_get_series_opa(const lv_obj_t * chart)
|
||||
*/
|
||||
lv_coord_t lv_chart_get_series_width(const lv_obj_t * chart)
|
||||
{
|
||||
LV_ASSERT_OBJ(chart, LV_OBJX_NAME);
|
||||
|
||||
lv_chart_ext_t * ext = lv_obj_get_ext_attr(chart);
|
||||
return ext->series.width;
|
||||
}
|
||||
@@ -564,6 +672,8 @@ lv_coord_t lv_chart_get_series_width(const lv_obj_t * chart)
|
||||
*/
|
||||
lv_opa_t lv_chart_get_series_darking(const lv_obj_t * chart)
|
||||
{
|
||||
LV_ASSERT_OBJ(chart, LV_OBJX_NAME);
|
||||
|
||||
lv_chart_ext_t * ext = lv_obj_get_ext_attr(chart);
|
||||
return ext->series.dark;
|
||||
}
|
||||
@@ -578,6 +688,8 @@ lv_opa_t lv_chart_get_series_darking(const lv_obj_t * chart)
|
||||
*/
|
||||
void lv_chart_refresh(lv_obj_t * chart)
|
||||
{
|
||||
LV_ASSERT_OBJ(chart, LV_OBJX_NAME);
|
||||
|
||||
lv_obj_invalidate(chart);
|
||||
}
|
||||
|
||||
@@ -588,6 +700,8 @@ void lv_chart_refresh(lv_obj_t * chart)
|
||||
*/
|
||||
uint16_t lv_chart_get_margin(lv_obj_t * chart)
|
||||
{
|
||||
LV_ASSERT_OBJ(chart, LV_OBJX_NAME);
|
||||
|
||||
lv_chart_ext_t * ext = lv_obj_get_ext_attr(chart);
|
||||
return ext->margin;
|
||||
}
|
||||
@@ -647,12 +761,13 @@ static bool lv_chart_design(lv_obj_t * chart, const lv_area_t * mask, lv_design_
|
||||
*/
|
||||
static lv_res_t lv_chart_signal(lv_obj_t * chart, lv_signal_t sign, void * param)
|
||||
{
|
||||
lv_res_t res;
|
||||
lv_chart_ext_t * ext = lv_obj_get_ext_attr(chart);
|
||||
|
||||
/* Include the ancient signal function */
|
||||
lv_res_t res;
|
||||
res = ancestor_signal(chart, sign, param);
|
||||
if(res != LV_RES_OK) return res;
|
||||
if(sign == LV_SIGNAL_GET_TYPE) return lv_obj_handle_get_type_signal(param, LV_OBJX_NAME);
|
||||
|
||||
lv_chart_ext_t * ext = lv_obj_get_ext_attr(chart);
|
||||
|
||||
if(sign == LV_SIGNAL_CLEANUP) {
|
||||
lv_coord_t ** datal;
|
||||
@@ -661,13 +776,6 @@ static lv_res_t lv_chart_signal(lv_obj_t * chart, lv_signal_t sign, void * param
|
||||
lv_mem_free(*datal);
|
||||
}
|
||||
lv_ll_clear(&ext->series_ll);
|
||||
} else if(sign == LV_SIGNAL_GET_TYPE) {
|
||||
lv_obj_type_t * buf = param;
|
||||
uint8_t i;
|
||||
for(i = 0; i < LV_MAX_ANCESTOR_NUM - 1; i++) { /*Find the last set data*/
|
||||
if(buf->type[i] == NULL) break;
|
||||
}
|
||||
buf->type[i] = "lv_chart";
|
||||
} else if(sign == LV_SIGNAL_REFR_EXT_DRAW_PAD) {
|
||||
/*Provide extra px draw area around the chart*/
|
||||
chart->ext_draw_pad = ext->margin;
|
||||
@@ -1046,65 +1154,187 @@ static void lv_chart_draw_areas(lv_obj_t * chart, const lv_area_t * mask)
|
||||
}
|
||||
}
|
||||
|
||||
static void lv_chart_draw_y_ticks(lv_obj_t * chart, const lv_area_t * mask)
|
||||
/**
|
||||
* Create iterator for newline-separated list
|
||||
* @param list pointer to newline-separated labels list
|
||||
* @param iterator_dir LV_CHART_ITERATOR_FORWARD or LV_CHART_LABEL_ITERATOR_REVERSE
|
||||
* @return lv_chart_label_iterator_t
|
||||
*/
|
||||
static lv_chart_label_iterator_t lv_chart_create_label_iter(const char * list, uint8_t iterator_dir)
|
||||
{
|
||||
lv_chart_label_iterator_t iterator = {0};
|
||||
uint8_t j;
|
||||
|
||||
iterator.list_start = list;
|
||||
|
||||
/* count number of list items */
|
||||
for(j = 0; list[j] != '\0'; j++) {
|
||||
if(list[j] == '\n')
|
||||
iterator.items_left++;
|
||||
}
|
||||
|
||||
if(iterator_dir == LV_CHART_LABEL_ITERATOR_FORWARD) {
|
||||
iterator.is_reverse_iter = 0;
|
||||
iterator.current_pos = list;
|
||||
} else {
|
||||
iterator.is_reverse_iter = 1;
|
||||
// -1 to skip '\0' at the end of the string
|
||||
iterator.current_pos = list + j - 1;
|
||||
}
|
||||
iterator.items_left++;
|
||||
return iterator;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get next label from iterator created by lv_chart_create_label_iter()
|
||||
* @param iterator iterator to get label from
|
||||
* @param[out] buf buffer to point next label to
|
||||
*/
|
||||
static void lv_chart_get_next_label(lv_chart_label_iterator_t * iterator, char * buf)
|
||||
{
|
||||
uint8_t label_len = 0;
|
||||
if (iterator->is_reverse_iter) {
|
||||
const char * label_start;
|
||||
/* count the length of the current label*/
|
||||
while ((*iterator->current_pos != '\n') &&
|
||||
(iterator->current_pos != iterator->list_start)) {
|
||||
iterator->current_pos--;
|
||||
label_len++;
|
||||
}
|
||||
|
||||
label_start = iterator->current_pos;
|
||||
|
||||
if (*iterator->current_pos == '\n') {
|
||||
/* do not copy \n symbol, +1 to skip it*/
|
||||
label_start++;
|
||||
/* skip newline*/
|
||||
iterator->current_pos--;
|
||||
} else {
|
||||
/* it is last label in list (first one from the beginning )*/
|
||||
label_len++;
|
||||
}
|
||||
|
||||
/* do not allow output buffer overflow */
|
||||
if (label_len > LV_CHART_AXIS_TICK_LABEL_MAX_LEN) {
|
||||
label_len = LV_CHART_AXIS_TICK_LABEL_MAX_LEN;
|
||||
}
|
||||
|
||||
strncpy(buf, label_start, label_len);
|
||||
} else {
|
||||
/* search for tick string */
|
||||
while(iterator->current_pos[label_len] != '\n' &&
|
||||
iterator->current_pos[label_len] != '\0') {
|
||||
/* do not overflow the buffer, but move to the end of the current label */
|
||||
if(label_len < LV_CHART_AXIS_TICK_LABEL_MAX_LEN) {
|
||||
buf[label_len] = iterator->current_pos[label_len];
|
||||
label_len++;
|
||||
} else {
|
||||
label_len++;
|
||||
}
|
||||
}
|
||||
|
||||
iterator->current_pos += label_len;
|
||||
|
||||
/* do not allow output buffer overflow */
|
||||
if (label_len > LV_CHART_AXIS_TICK_LABEL_MAX_LEN) {
|
||||
label_len = LV_CHART_AXIS_TICK_LABEL_MAX_LEN;
|
||||
}
|
||||
|
||||
if(*iterator->current_pos == '\n') iterator->current_pos++;
|
||||
}
|
||||
|
||||
/* terminate the string */
|
||||
buf[label_len] = '\0';
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether there should be a label next to tick with given
|
||||
* number
|
||||
* @param tick_num number of the tick to check
|
||||
* @param axis pointer to struct containing info on the axis
|
||||
* @return true if label should be located next to current tick
|
||||
*/
|
||||
static inline bool lv_chart_is_tick_with_label(uint8_t tick_num, lv_chart_axis_cfg_t * axis)
|
||||
{
|
||||
return ((tick_num == 0) || ((tick_num % axis->num_tick_marks) == 0));
|
||||
}
|
||||
|
||||
static void lv_chart_draw_y_ticks(lv_obj_t * chart, const lv_area_t * mask, uint8_t which_axis)
|
||||
{
|
||||
lv_chart_ext_t * ext = lv_obj_get_ext_attr(chart);
|
||||
lv_chart_axis_cfg_t * y_axis = (which_axis == LV_CHART_AXIS_PRIMARY_Y) ?
|
||||
&ext->y_axis : &ext->secondary_y_axis;
|
||||
|
||||
if(ext->y_axis.list_of_values != NULL || ext->y_axis.num_tick_marks != 0) {
|
||||
if(y_axis->list_of_values != NULL || y_axis->num_tick_marks != 0) {
|
||||
|
||||
const lv_style_t * style = lv_obj_get_style(chart);
|
||||
lv_opa_t opa_scale = lv_obj_get_opa_scale(chart);
|
||||
|
||||
uint8_t i, j;
|
||||
uint8_t list_index;
|
||||
uint8_t i;
|
||||
uint8_t num_of_labels;
|
||||
uint8_t num_scale_ticks;
|
||||
uint8_t major_tick_len, minor_tick_len;
|
||||
int8_t major_tick_len, minor_tick_len;
|
||||
uint8_t iter_dir;
|
||||
|
||||
lv_point_t p1;
|
||||
lv_point_t p2;
|
||||
lv_coord_t x_ofs = chart->coords.x1;
|
||||
lv_coord_t x_ofs;
|
||||
lv_chart_label_iterator_t iter;
|
||||
lv_coord_t y_ofs = chart->coords.y1;
|
||||
lv_coord_t h = lv_obj_get_height(chart);
|
||||
lv_coord_t w = lv_obj_get_width(chart);
|
||||
char buf[LV_CHART_AXIS_TICK_LABEL_MAX_LEN + 1]; /* up to N symbols per label + null terminator */
|
||||
|
||||
/* chose correct side of the chart */
|
||||
if(which_axis == LV_CHART_AXIS_PRIMARY_Y)
|
||||
x_ofs = chart->coords.x1;
|
||||
else
|
||||
x_ofs = chart->coords.x2;
|
||||
|
||||
/* calculate the size of tick marks */
|
||||
if(ext->y_axis.major_tick_len == LV_CHART_TICK_LENGTH_AUTO)
|
||||
if(y_axis->major_tick_len == LV_CHART_TICK_LENGTH_AUTO)
|
||||
major_tick_len = (int32_t)w * LV_CHART_AXIS_MAJOR_TICK_LEN_COE;
|
||||
else
|
||||
major_tick_len = ext->y_axis.major_tick_len;
|
||||
major_tick_len = y_axis->major_tick_len;
|
||||
|
||||
if(ext->y_axis.minor_tick_len == LV_CHART_TICK_LENGTH_AUTO)
|
||||
if(y_axis->minor_tick_len == LV_CHART_TICK_LENGTH_AUTO)
|
||||
minor_tick_len = major_tick_len * LV_CHART_AXIS_MINOR_TICK_LEN_COE;
|
||||
else
|
||||
minor_tick_len = ext->y_axis.minor_tick_len;
|
||||
minor_tick_len = y_axis->minor_tick_len;
|
||||
|
||||
/* count the '\n'-s to determine the number of options */
|
||||
list_index = 0;
|
||||
num_of_labels = 0;
|
||||
if(ext->y_axis.list_of_values != NULL) {
|
||||
for(j = 0; ext->y_axis.list_of_values[j] != '\0'; j++) {
|
||||
if(ext->y_axis.list_of_values[j] == '\n') num_of_labels++;
|
||||
}
|
||||
|
||||
num_of_labels++; /* last option in the at row*/
|
||||
/* tick lines on secondary y axis are drawn in other direction*/
|
||||
if(which_axis == LV_CHART_AXIS_SECONDARY_Y) {
|
||||
major_tick_len *= -1;
|
||||
minor_tick_len *= -1;
|
||||
}
|
||||
|
||||
iter_dir = (y_axis->options & LV_CHART_AXIS_INVERSE_LABELS_ORDER) ? LV_CHART_LABEL_ITERATOR_REVERSE : LV_CHART_LABEL_ITERATOR_FORWARD;
|
||||
iter = lv_chart_create_label_iter(y_axis->list_of_values, iter_dir);
|
||||
|
||||
/*determine the number of options */
|
||||
num_of_labels = iter.items_left;
|
||||
|
||||
/* we can't have string labels without ticks step, set to 1 if not specified */
|
||||
if(ext->y_axis.num_tick_marks == 0) ext->y_axis.num_tick_marks = 1;
|
||||
if(y_axis->num_tick_marks == 0) y_axis->num_tick_marks = 1;
|
||||
|
||||
/* calculate total number of ticks */
|
||||
if(num_of_labels < 2)
|
||||
num_scale_ticks = ext->y_axis.num_tick_marks;
|
||||
num_scale_ticks = y_axis->num_tick_marks;
|
||||
else
|
||||
num_scale_ticks = (ext->y_axis.num_tick_marks * (num_of_labels - 1));
|
||||
num_scale_ticks = (y_axis->num_tick_marks * (num_of_labels - 1));
|
||||
|
||||
for(i = 0; i < (num_scale_ticks + 1); i++) { /* one extra loop - it may not exist in the list, empty label */
|
||||
/* first point of the tick */
|
||||
p1.x = x_ofs - 1;
|
||||
p1.x = x_ofs;
|
||||
|
||||
/* move extra pixel out of chart boundary */
|
||||
if (which_axis == LV_CHART_AXIS_PRIMARY_Y)
|
||||
p1.x--;
|
||||
else
|
||||
p1.x++;
|
||||
|
||||
/* second point of the tick */
|
||||
if((num_of_labels != 0) && (i == 0 || i % ext->y_axis.num_tick_marks == 0))
|
||||
if((num_of_labels != 0) && (i == 0 || i % y_axis->num_tick_marks == 0))
|
||||
p2.x = p1.x - major_tick_len; /* major tick */
|
||||
else
|
||||
p2.x = p1.x - minor_tick_len; /* minor tick */
|
||||
@@ -1113,31 +1343,25 @@ static void lv_chart_draw_y_ticks(lv_obj_t * chart, const lv_area_t * mask)
|
||||
p2.y = p1.y =
|
||||
y_ofs + (int32_t)((int32_t)(h - style->line.width) * i) / num_scale_ticks;
|
||||
|
||||
if(i != num_scale_ticks)
|
||||
lv_draw_line(&p1, &p2, mask, style, opa_scale);
|
||||
else if((ext->y_axis.options & LV_CHART_AXIS_DRAW_LAST_TICK) != 0)
|
||||
lv_draw_line(&p1, &p2, mask, style, opa_scale);
|
||||
if(y_axis->options & LV_CHART_AXIS_INVERSE_LABELS_ORDER) {
|
||||
/*if label order is inversed last tick have number 0*/
|
||||
if(i != 0)
|
||||
lv_draw_line(&p1, &p2, mask, style, opa_scale);
|
||||
else if((y_axis->options & LV_CHART_AXIS_DRAW_LAST_TICK) != 0)
|
||||
lv_draw_line(&p1, &p2, mask, style, opa_scale);
|
||||
} else {
|
||||
if(i != num_scale_ticks)
|
||||
lv_draw_line(&p1, &p2, mask, style, opa_scale);
|
||||
else if((y_axis->options & LV_CHART_AXIS_DRAW_LAST_TICK) != 0)
|
||||
lv_draw_line(&p1, &p2, mask, style, opa_scale);
|
||||
}
|
||||
|
||||
/* draw values if available */
|
||||
if(num_of_labels != 0) {
|
||||
/* add text only to major tick */
|
||||
if(i == 0 || i % ext->y_axis.num_tick_marks == 0) {
|
||||
/* search for tick string */
|
||||
j = 0;
|
||||
while(ext->y_axis.list_of_values[list_index] != '\n' &&
|
||||
ext->y_axis.list_of_values[list_index] != '\0') {
|
||||
/* do not overflow the buffer, but move to the end of the current label */
|
||||
if(j < LV_CHART_AXIS_TICK_LABEL_MAX_LEN)
|
||||
buf[j++] = ext->y_axis.list_of_values[list_index++];
|
||||
else
|
||||
list_index++;
|
||||
}
|
||||
if(lv_chart_is_tick_with_label(i, y_axis)) {
|
||||
|
||||
/* this was a string, but not end of the list, so jump to the next string */
|
||||
if(ext->y_axis.list_of_values[list_index] == '\n') list_index++;
|
||||
|
||||
/* terminate the string */
|
||||
buf[j] = '\0';
|
||||
lv_chart_get_next_label(&iter, buf);
|
||||
|
||||
/* reserve appropriate area */
|
||||
lv_point_t size;
|
||||
@@ -1145,9 +1369,17 @@ static void lv_chart_draw_y_ticks(lv_obj_t * chart, const lv_area_t * mask)
|
||||
LV_COORD_MAX, LV_TXT_FLAG_CENTER);
|
||||
|
||||
/* set the area at some distance of the major tick len left of the tick */
|
||||
lv_area_t a = {(p2.x - size.x - LV_CHART_AXIS_TO_LABEL_DISTANCE), (p2.y - size.y / 2),
|
||||
(p2.x - LV_CHART_AXIS_TO_LABEL_DISTANCE), (p2.y + size.y / 2)};
|
||||
lv_draw_label(&a, mask, style, opa_scale, buf, LV_TXT_FLAG_CENTER, NULL, -1, -1, NULL);
|
||||
lv_area_t a = {.y1 = p2.y - size.y / 2, .y2 = p2.y + size.y / 2};
|
||||
|
||||
if(which_axis == LV_CHART_AXIS_PRIMARY_Y) {
|
||||
a.x1 = p2.x - size.x - LV_CHART_AXIS_TO_LABEL_DISTANCE;
|
||||
a.x2 = p2.x - LV_CHART_AXIS_TO_LABEL_DISTANCE;
|
||||
} else {
|
||||
a.x1 = p2.x + LV_CHART_AXIS_TO_LABEL_DISTANCE;
|
||||
a.x2 = p2.x + size.x + LV_CHART_AXIS_TO_LABEL_DISTANCE;
|
||||
}
|
||||
|
||||
lv_draw_label(&a, mask, style, opa_scale, buf, LV_TXT_FLAG_CENTER, NULL, NULL, NULL, lv_obj_get_base_dir(chart));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1164,11 +1396,11 @@ static void lv_chart_draw_x_ticks(lv_obj_t * chart, const lv_area_t * mask)
|
||||
const lv_style_t * style = lv_obj_get_style(chart);
|
||||
lv_opa_t opa_scale = lv_obj_get_opa_scale(chart);
|
||||
|
||||
uint8_t i, j;
|
||||
uint8_t list_index;
|
||||
uint8_t i;
|
||||
uint8_t num_of_labels;
|
||||
uint8_t num_scale_ticks;
|
||||
uint8_t major_tick_len, minor_tick_len;
|
||||
lv_chart_label_iterator_t iter;
|
||||
lv_point_t p1;
|
||||
lv_point_t p2;
|
||||
lv_coord_t x_ofs = chart->coords.x1;
|
||||
@@ -1188,16 +1420,9 @@ static void lv_chart_draw_x_ticks(lv_obj_t * chart, const lv_area_t * mask)
|
||||
else
|
||||
minor_tick_len = ext->x_axis.minor_tick_len;
|
||||
|
||||
/* count the '\n'-s to determine the number of options */
|
||||
list_index = 0;
|
||||
num_of_labels = 0;
|
||||
if(ext->x_axis.list_of_values != NULL) {
|
||||
for(j = 0; ext->x_axis.list_of_values[j] != '\0'; j++) {
|
||||
if(ext->x_axis.list_of_values[j] == '\n') num_of_labels++;
|
||||
}
|
||||
|
||||
num_of_labels++; /* last option in the at row*/
|
||||
}
|
||||
/*determine the number of options */
|
||||
iter = lv_chart_create_label_iter(ext->x_axis.list_of_values, LV_CHART_LABEL_ITERATOR_FORWARD);
|
||||
num_of_labels = iter.items_left;
|
||||
|
||||
/* we can't have string labels without ticks step, set to 1 if not specified */
|
||||
if(ext->x_axis.num_tick_marks == 0) ext->x_axis.num_tick_marks = 1;
|
||||
@@ -1229,23 +1454,8 @@ static void lv_chart_draw_x_ticks(lv_obj_t * chart, const lv_area_t * mask)
|
||||
/* draw values if available */
|
||||
if(num_of_labels != 0) {
|
||||
/* add text only to major tick */
|
||||
if(i == 0 || i % ext->x_axis.num_tick_marks == 0) {
|
||||
/* search for tick string */
|
||||
j = 0;
|
||||
while(ext->x_axis.list_of_values[list_index] != '\n' &&
|
||||
ext->x_axis.list_of_values[list_index] != '\0') {
|
||||
/* do not overflow the buffer, but move to the end of the current label */
|
||||
if(j < LV_CHART_AXIS_TICK_LABEL_MAX_LEN)
|
||||
buf[j++] = ext->x_axis.list_of_values[list_index++];
|
||||
else
|
||||
list_index++;
|
||||
}
|
||||
|
||||
/* this was a string, but not end of the list, so jump to the next string */
|
||||
if(ext->x_axis.list_of_values[list_index] == '\n') list_index++;
|
||||
|
||||
/* terminate the string */
|
||||
buf[j] = '\0';
|
||||
if(lv_chart_is_tick_with_label(i, &(ext->x_axis))) {
|
||||
lv_chart_get_next_label(&iter, buf);
|
||||
|
||||
/* reserve appropriate area */
|
||||
lv_point_t size;
|
||||
@@ -1255,7 +1465,7 @@ static void lv_chart_draw_x_ticks(lv_obj_t * chart, const lv_area_t * mask)
|
||||
/* set the area at some distance of the major tick len under of the tick */
|
||||
lv_area_t a = {(p2.x - size.x / 2), (p2.y + LV_CHART_AXIS_TO_LABEL_DISTANCE), (p2.x + size.x / 2),
|
||||
(p2.y + size.y + LV_CHART_AXIS_TO_LABEL_DISTANCE)};
|
||||
lv_draw_label(&a, mask, style, opa_scale, buf, LV_TXT_FLAG_CENTER, NULL, -1, -1, NULL);
|
||||
lv_draw_label(&a, mask, style, opa_scale, buf, LV_TXT_FLAG_CENTER, NULL, NULL, NULL, lv_obj_get_base_dir(chart));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1264,7 +1474,8 @@ static void lv_chart_draw_x_ticks(lv_obj_t * chart, const lv_area_t * mask)
|
||||
|
||||
static void lv_chart_draw_axes(lv_obj_t * chart, const lv_area_t * mask)
|
||||
{
|
||||
lv_chart_draw_y_ticks(chart, mask);
|
||||
lv_chart_draw_y_ticks(chart, mask, LV_CHART_AXIS_PRIMARY_Y);
|
||||
lv_chart_draw_y_ticks(chart, mask, LV_CHART_AXIS_SECONDARY_Y);
|
||||
lv_chart_draw_x_ticks(chart, mask);
|
||||
}
|
||||
|
||||
|
||||
@@ -34,6 +34,9 @@ extern "C" {
|
||||
/**Automatically calculate the tick length*/
|
||||
#define LV_CHART_TICK_LENGTH_AUTO 255
|
||||
|
||||
LV_EXPORT_CONST_INT(LV_CHART_POINT_DEF);
|
||||
LV_EXPORT_CONST_INT(LV_CHART_TICK_LENGTH_AUTO);
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
@@ -65,8 +68,9 @@ typedef struct
|
||||
|
||||
/** Data of axis */
|
||||
enum {
|
||||
LV_CHART_AXIS_SKIP_LAST_TICK = 0x00, /**< don't draw the last tick */
|
||||
LV_CHART_AXIS_DRAW_LAST_TICK = 0x01 /**< draw the last tick */
|
||||
LV_CHART_AXIS_SKIP_LAST_TICK = 0x00, /**< don't draw the last tick */
|
||||
LV_CHART_AXIS_DRAW_LAST_TICK = 0x01, /**< draw the last tick */
|
||||
LV_CHART_AXIS_INVERSE_LABELS_ORDER = 0x02 /**< draw tick labels in an inversed order*/
|
||||
};
|
||||
typedef uint8_t lv_chart_axis_options_t;
|
||||
|
||||
@@ -93,6 +97,7 @@ typedef struct
|
||||
lv_chart_type_t type; /*Line, column or point chart (from 'lv_chart_type_t')*/
|
||||
lv_chart_axis_cfg_t y_axis;
|
||||
lv_chart_axis_cfg_t x_axis;
|
||||
lv_chart_axis_cfg_t secondary_y_axis;
|
||||
uint16_t margin;
|
||||
uint8_t update_mode : 1;
|
||||
struct
|
||||
@@ -259,6 +264,16 @@ void lv_chart_set_x_tick_length(lv_obj_t * chart, uint8_t major_tick_len, uint8_
|
||||
*/
|
||||
void lv_chart_set_y_tick_length(lv_obj_t * chart, uint8_t major_tick_len, uint8_t minor_tick_len);
|
||||
|
||||
/**
|
||||
* Set the length of the tick marks on the secondary y axis
|
||||
* @param chart pointer to the chart
|
||||
* @param major_tick_len the length of the major tick or `LV_CHART_TICK_LENGTH_AUTO` to set automatically
|
||||
* (where labels are added)
|
||||
* @param minor_tick_len the length of the minor tick, `LV_CHART_TICK_LENGTH_AUTO` to set automatically
|
||||
* (where no labels are added)
|
||||
*/
|
||||
void lv_chart_set_secondary_y_tick_length(lv_obj_t * chart, uint8_t major_tick_len, uint8_t minor_tick_len);
|
||||
|
||||
/**
|
||||
* Set the x-axis tick count and labels of a chart
|
||||
* @param chart pointer to a chart object
|
||||
@@ -270,6 +285,17 @@ void lv_chart_set_y_tick_length(lv_obj_t * chart, uint8_t major_tick_len, uint8_
|
||||
void lv_chart_set_x_tick_texts(lv_obj_t * chart, const char * list_of_values, uint8_t num_tick_marks,
|
||||
lv_chart_axis_options_t options);
|
||||
|
||||
/**
|
||||
* Set the secondary y-axis tick count and labels of a chart
|
||||
* @param chart pointer to a chart object
|
||||
* @param list_of_values list of string values, terminated with \n, except the last
|
||||
* @param num_tick_marks if list_of_values is NULL: total number of ticks per axis
|
||||
* else number of ticks between two value labels
|
||||
* @param options extra options
|
||||
*/
|
||||
void lv_chart_set_secondary_y_tick_texts(lv_obj_t * chart, const char * list_of_values, uint8_t num_tick_marks,
|
||||
lv_chart_axis_options_t options);
|
||||
|
||||
/**
|
||||
* Set the y-axis tick count and labels of a chart
|
||||
* @param chart pointer to a chart object
|
||||
|
||||
@@ -14,16 +14,19 @@
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "../lv_core/lv_debug.h"
|
||||
#include "../lv_draw/lv_draw.h"
|
||||
#include "../lv_draw/lv_draw_basic.h"
|
||||
#include "../lv_themes/lv_theme.h"
|
||||
#include "../lv_misc/lv_area.h"
|
||||
#include "../lv_misc/lv_color.h"
|
||||
#include "../lv_misc/lv_math.h"
|
||||
#include "../lv_misc/lv_bidi.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
#define LV_OBJX_NAME "lv_cont"
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
@@ -67,7 +70,7 @@ lv_obj_t * lv_cont_create(lv_obj_t * par, const lv_obj_t * copy)
|
||||
|
||||
/*Create a basic object*/
|
||||
lv_obj_t * new_cont = lv_obj_create(par, copy);
|
||||
lv_mem_assert(new_cont);
|
||||
LV_ASSERT_MEM(new_cont);
|
||||
if(new_cont == NULL) return NULL;
|
||||
|
||||
if(ancestor_signal == NULL) ancestor_signal = lv_obj_get_signal_cb(new_cont);
|
||||
@@ -76,7 +79,7 @@ lv_obj_t * lv_cont_create(lv_obj_t * par, const lv_obj_t * copy)
|
||||
lv_cont_ext_t * ext = lv_obj_get_ext_attr(new_cont);
|
||||
if(ext == NULL) return NULL;
|
||||
|
||||
lv_mem_assert(ext);
|
||||
LV_ASSERT_MEM(ext);
|
||||
ext->fit_left = LV_FIT_NONE;
|
||||
ext->fit_right = LV_FIT_NONE;
|
||||
ext->fit_top = LV_FIT_NONE;
|
||||
@@ -126,6 +129,8 @@ lv_obj_t * lv_cont_create(lv_obj_t * par, const lv_obj_t * copy)
|
||||
*/
|
||||
void lv_cont_set_layout(lv_obj_t * cont, lv_layout_t layout)
|
||||
{
|
||||
LV_ASSERT_OBJ(cont, LV_OBJX_NAME);
|
||||
|
||||
lv_cont_ext_t * ext = lv_obj_get_ext_attr(cont);
|
||||
if(ext->layout == layout) return;
|
||||
|
||||
@@ -146,6 +151,8 @@ void lv_cont_set_layout(lv_obj_t * cont, lv_layout_t layout)
|
||||
*/
|
||||
void lv_cont_set_fit4(lv_obj_t * cont, lv_fit_t left, lv_fit_t right, lv_fit_t top, lv_fit_t bottom)
|
||||
{
|
||||
LV_ASSERT_OBJ(cont, LV_OBJX_NAME);
|
||||
|
||||
lv_obj_invalidate(cont);
|
||||
lv_cont_ext_t * ext = lv_obj_get_ext_attr(cont);
|
||||
if(ext->fit_left == left && ext->fit_right == right && ext->fit_top == top && ext->fit_bottom == bottom) {
|
||||
@@ -172,6 +179,8 @@ void lv_cont_set_fit4(lv_obj_t * cont, lv_fit_t left, lv_fit_t right, lv_fit_t t
|
||||
*/
|
||||
lv_layout_t lv_cont_get_layout(const lv_obj_t * cont)
|
||||
{
|
||||
LV_ASSERT_OBJ(cont, LV_OBJX_NAME);
|
||||
|
||||
lv_cont_ext_t * ext = lv_obj_get_ext_attr(cont);
|
||||
return ext->layout;
|
||||
}
|
||||
@@ -183,6 +192,8 @@ lv_layout_t lv_cont_get_layout(const lv_obj_t * cont)
|
||||
*/
|
||||
lv_fit_t lv_cont_get_fit_left(const lv_obj_t * cont)
|
||||
{
|
||||
LV_ASSERT_OBJ(cont, LV_OBJX_NAME);
|
||||
|
||||
lv_cont_ext_t * ext = lv_obj_get_ext_attr(cont);
|
||||
return ext->fit_left;
|
||||
}
|
||||
@@ -194,6 +205,8 @@ lv_fit_t lv_cont_get_fit_left(const lv_obj_t * cont)
|
||||
*/
|
||||
lv_fit_t lv_cont_get_fit_right(const lv_obj_t * cont)
|
||||
{
|
||||
LV_ASSERT_OBJ(cont, LV_OBJX_NAME);
|
||||
|
||||
lv_cont_ext_t * ext = lv_obj_get_ext_attr(cont);
|
||||
return ext->fit_right;
|
||||
}
|
||||
@@ -205,6 +218,8 @@ lv_fit_t lv_cont_get_fit_right(const lv_obj_t * cont)
|
||||
*/
|
||||
lv_fit_t lv_cont_get_fit_top(const lv_obj_t * cont)
|
||||
{
|
||||
LV_ASSERT_OBJ(cont, LV_OBJX_NAME);
|
||||
|
||||
lv_cont_ext_t * ext = lv_obj_get_ext_attr(cont);
|
||||
return ext->fit_top;
|
||||
}
|
||||
@@ -216,6 +231,8 @@ lv_fit_t lv_cont_get_fit_top(const lv_obj_t * cont)
|
||||
*/
|
||||
lv_fit_t lv_cont_get_fit_bottom(const lv_obj_t * cont)
|
||||
{
|
||||
LV_ASSERT_OBJ(cont, LV_OBJX_NAME);
|
||||
|
||||
lv_cont_ext_t * ext = lv_obj_get_ext_attr(cont);
|
||||
return ext->fit_bottom;
|
||||
}
|
||||
@@ -238,6 +255,7 @@ static lv_res_t lv_cont_signal(lv_obj_t * cont, lv_signal_t sign, void * param)
|
||||
/* Include the ancient signal function */
|
||||
res = ancestor_signal(cont, sign, param);
|
||||
if(res != LV_RES_OK) return res;
|
||||
if(sign == LV_SIGNAL_GET_TYPE) return lv_obj_handle_get_type_signal(param, LV_OBJX_NAME);
|
||||
|
||||
if(sign == LV_SIGNAL_STYLE_CHG) { /*Recalculate the padding if the style changed*/
|
||||
lv_cont_refr_layout(cont);
|
||||
@@ -254,13 +272,6 @@ static lv_res_t lv_cont_signal(lv_obj_t * cont, lv_signal_t sign, void * param)
|
||||
/*FLOOD and FILL fit needs to be refreshed if the parent size has changed*/
|
||||
lv_cont_refr_autofit(cont);
|
||||
|
||||
} else if(sign == LV_SIGNAL_GET_TYPE) {
|
||||
lv_obj_type_t * buf = param;
|
||||
uint8_t i;
|
||||
for(i = 0; i < LV_MAX_ANCESTOR_NUM - 1; i++) { /*Find the last set data*/
|
||||
if(buf->type[i] == NULL) break;
|
||||
}
|
||||
buf->type[i] = "lv_cont";
|
||||
}
|
||||
|
||||
return res;
|
||||
@@ -354,23 +365,23 @@ static void lv_cont_layout_row(lv_obj_t * cont)
|
||||
lv_align_t align;
|
||||
const lv_style_t * style = lv_obj_get_style(cont);
|
||||
lv_coord_t vpad_corr;
|
||||
|
||||
lv_bidi_dir_t base_dir = lv_obj_get_base_dir(cont);
|
||||
switch(type) {
|
||||
case LV_LAYOUT_ROW_T:
|
||||
vpad_corr = style->body.padding.top;
|
||||
align = LV_ALIGN_IN_TOP_LEFT;
|
||||
align = base_dir == LV_BIDI_DIR_RTL ? LV_ALIGN_IN_TOP_RIGHT : LV_ALIGN_IN_TOP_LEFT;
|
||||
break;
|
||||
case LV_LAYOUT_ROW_M:
|
||||
vpad_corr = 0;
|
||||
align = LV_ALIGN_IN_LEFT_MID;
|
||||
align = base_dir == LV_BIDI_DIR_RTL ? LV_ALIGN_IN_RIGHT_MID: LV_ALIGN_IN_LEFT_MID;
|
||||
break;
|
||||
case LV_LAYOUT_ROW_B:
|
||||
vpad_corr = -style->body.padding.bottom;
|
||||
align = LV_ALIGN_IN_BOTTOM_LEFT;
|
||||
align = base_dir == LV_BIDI_DIR_RTL ? LV_ALIGN_IN_BOTTOM_RIGHT: LV_ALIGN_IN_BOTTOM_LEFT;
|
||||
break;
|
||||
default:
|
||||
vpad_corr = 0;
|
||||
align = LV_ALIGN_IN_TOP_LEFT;
|
||||
align = base_dir == LV_BIDI_DIR_RTL ? LV_ALIGN_IN_TOP_RIGHT : LV_ALIGN_IN_TOP_LEFT;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -379,12 +390,19 @@ static void lv_cont_layout_row(lv_obj_t * cont)
|
||||
lv_obj_set_protect(cont, LV_PROTECT_CHILD_CHG);
|
||||
|
||||
/* Align the children */
|
||||
lv_coord_t last_cord = style->body.padding.left;
|
||||
lv_coord_t last_cord;
|
||||
if(base_dir == LV_BIDI_DIR_RTL) last_cord = style->body.padding.right;
|
||||
else last_cord = style->body.padding.left;
|
||||
|
||||
LV_LL_READ_BACK(cont->child_ll, child)
|
||||
{
|
||||
if(lv_obj_get_hidden(child) != false || lv_obj_is_protected(child, LV_PROTECT_POS) != false) continue;
|
||||
|
||||
lv_obj_align(child, cont, align, last_cord, vpad_corr);
|
||||
// last_cord -= lv_obj_get_width(child);
|
||||
|
||||
if(base_dir == LV_BIDI_DIR_RTL) lv_obj_align(child, cont, align, -last_cord, vpad_corr);
|
||||
else lv_obj_align(child, cont, align, last_cord, vpad_corr);
|
||||
|
||||
last_cord += lv_obj_get_width(child) + style->body.padding.inner;
|
||||
}
|
||||
|
||||
|
||||
1068
src/lv_objx/lv_cpicker.c
Normal file
1068
src/lv_objx/lv_cpicker.c
Normal file
File diff suppressed because it is too large
Load Diff
263
src/lv_objx/lv_cpicker.h
Normal file
263
src/lv_objx/lv_cpicker.h
Normal file
@@ -0,0 +1,263 @@
|
||||
/**
|
||||
* @file lv_cpicker.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LV_CPICKER_H
|
||||
#define LV_CPICKER_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#ifdef LV_CONF_INCLUDE_SIMPLE
|
||||
#include "lv_conf.h"
|
||||
#else
|
||||
#include "../../../lv_conf.h"
|
||||
#endif
|
||||
|
||||
#if LV_USE_CPICKER != 0
|
||||
|
||||
#include "../lv_core/lv_obj.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
enum {
|
||||
LV_CPICKER_TYPE_RECT,
|
||||
LV_CPICKER_TYPE_DISC,
|
||||
};
|
||||
typedef uint8_t lv_cpicker_type_t;
|
||||
|
||||
enum {
|
||||
LV_CPICKER_COLOR_MODE_HUE,
|
||||
LV_CPICKER_COLOR_MODE_SATURATION,
|
||||
LV_CPICKER_COLOR_MODE_VALUE
|
||||
};
|
||||
typedef uint8_t lv_cpicker_color_mode_t;
|
||||
|
||||
|
||||
|
||||
/*Data of colorpicker*/
|
||||
typedef struct {
|
||||
lv_color_hsv_t hsv;
|
||||
struct {
|
||||
lv_style_t * style;
|
||||
lv_point_t pos;
|
||||
uint8_t colored :1;
|
||||
|
||||
} indic;
|
||||
uint32_t last_click_time;
|
||||
uint32_t last_change_time;
|
||||
lv_point_t last_press_point;
|
||||
lv_cpicker_color_mode_t color_mode :2;
|
||||
uint8_t color_mode_fixed :1;
|
||||
lv_cpicker_type_t type :1;
|
||||
uint8_t preview :1;
|
||||
} lv_cpicker_ext_t;
|
||||
|
||||
/*Styles*/
|
||||
enum {
|
||||
LV_CPICKER_STYLE_MAIN,
|
||||
LV_CPICKER_STYLE_INDICATOR,
|
||||
};
|
||||
typedef uint8_t lv_cpicker_style_t;
|
||||
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Create a colorpicker objects
|
||||
* @param par pointer to an object, it will be the parent of the new colorpicker
|
||||
* @param copy pointer to a colorpicker object, if not NULL then the new object will be copied from it
|
||||
* @return pointer to the created colorpicker
|
||||
*/
|
||||
lv_obj_t * lv_cpicker_create(lv_obj_t * par, const lv_obj_t * copy);
|
||||
|
||||
/*=====================
|
||||
* Setter functions
|
||||
*====================*/
|
||||
|
||||
/**
|
||||
* Set a new type for a colorpicker
|
||||
* @param cpicker pointer to a colorpicker object
|
||||
* @param type new type of the colorpicker (from 'lv_cpicker_type_t' enum)
|
||||
*/
|
||||
void lv_cpicker_set_type(lv_obj_t * cpicker, lv_cpicker_type_t type);
|
||||
|
||||
/**
|
||||
* Set a style of a colorpicker.
|
||||
* @param cpicker pointer to colorpicker object
|
||||
* @param type which style should be set
|
||||
* @param style pointer to a style
|
||||
*/
|
||||
void lv_cpicker_set_style(lv_obj_t * cpicker, lv_cpicker_style_t type, lv_style_t *style);
|
||||
|
||||
/**
|
||||
* Set the current hue of a colorpicker.
|
||||
* @param cpicker pointer to colorpicker object
|
||||
* @param hue current selected hue [0..360]
|
||||
* @return true if changed, otherwise false
|
||||
*/
|
||||
bool lv_cpicker_set_hue(lv_obj_t * cpicker, uint16_t hue);
|
||||
|
||||
/**
|
||||
* Set the current saturation of a colorpicker.
|
||||
* @param cpicker pointer to colorpicker object
|
||||
* @param saturation current selected saturation [0..100]
|
||||
* @return true if changed, otherwise false
|
||||
*/
|
||||
bool lv_cpicker_set_saturation(lv_obj_t * cpicker, uint8_t saturation);
|
||||
|
||||
/**
|
||||
* Set the current value of a colorpicker.
|
||||
* @param cpicker pointer to colorpicker object
|
||||
* @param val current selected value [0..100]
|
||||
* @return true if changed, otherwise false
|
||||
*/
|
||||
bool lv_cpicker_set_value(lv_obj_t * cpicker, uint8_t val);
|
||||
|
||||
/**
|
||||
* Set the current hsv of a colorpicker.
|
||||
* @param cpicker pointer to colorpicker object
|
||||
* @param hsv current selected hsv
|
||||
* @return true if changed, otherwise false
|
||||
*/
|
||||
bool lv_cpicker_set_hsv(lv_obj_t * cpicker, lv_color_hsv_t hsv);
|
||||
|
||||
/**
|
||||
* Set the current color of a colorpicker.
|
||||
* @param cpicker pointer to colorpicker object
|
||||
* @param color current selected color
|
||||
* @return true if changed, otherwise false
|
||||
*/
|
||||
bool lv_cpicker_set_color(lv_obj_t * cpicker, lv_color_t color);
|
||||
|
||||
/**
|
||||
* Set the current color mode.
|
||||
* @param cpicker pointer to colorpicker object
|
||||
* @param mode color mode (hue/sat/val)
|
||||
*/
|
||||
void lv_cpicker_set_color_mode(lv_obj_t * cpicker, lv_cpicker_color_mode_t mode);
|
||||
|
||||
/**
|
||||
* Set if the color mode is changed on long press on center
|
||||
* @param cpicker pointer to colorpicker object
|
||||
* @param fixed color mode cannot be changed on long press
|
||||
*/
|
||||
void lv_cpicker_set_color_mode_fixed(lv_obj_t * cpicker, bool fixed);
|
||||
|
||||
/**
|
||||
* Make the indicator to be colored to the current color
|
||||
* @param cpicker pointer to colorpicker object
|
||||
* @param en true: color the indicator; false: not color the indicator
|
||||
*/
|
||||
void lv_cpicker_set_indic_colored(lv_obj_t * cpicker, bool en);
|
||||
|
||||
/**
|
||||
* Add a color preview in the middle of the DISC type color picker
|
||||
* @param cpicker pointer to colorpicker object
|
||||
* @param en true: enable preview; false: disable preview
|
||||
*/
|
||||
void lv_cpicker_set_preview(lv_obj_t * cpicker, bool en);
|
||||
|
||||
/*=====================
|
||||
* Getter functions
|
||||
*====================*/
|
||||
|
||||
/**
|
||||
* Get the current color mode.
|
||||
* @param cpicker pointer to colorpicker object
|
||||
* @return color mode (hue/sat/val)
|
||||
*/
|
||||
lv_cpicker_color_mode_t lv_cpicker_get_color_mode(lv_obj_t * cpicker);
|
||||
|
||||
/**
|
||||
* Get if the color mode is changed on long press on center
|
||||
* @param cpicker pointer to colorpicker object
|
||||
* @return mode cannot be changed on long press
|
||||
*/
|
||||
bool lv_cpicker_get_color_mode_fixed(lv_obj_t * cpicker);
|
||||
|
||||
/**
|
||||
* Get style of a colorpicker.
|
||||
* @param cpicker pointer to colorpicker object
|
||||
* @param type which style should be get
|
||||
* @return pointer to the style
|
||||
*/
|
||||
const lv_style_t * lv_cpicker_get_style(const lv_obj_t * cpicker, lv_cpicker_style_t type);
|
||||
|
||||
/**
|
||||
* Get the current hue of a colorpicker.
|
||||
* @param cpicker pointer to colorpicker object
|
||||
* @return current selected hue
|
||||
*/
|
||||
uint16_t lv_cpicker_get_hue(lv_obj_t * cpicker);
|
||||
|
||||
/**
|
||||
* Get the current saturation of a colorpicker.
|
||||
* @param cpicker pointer to colorpicker object
|
||||
* @return current selected saturation
|
||||
*/
|
||||
uint8_t lv_cpicker_get_saturation(lv_obj_t * cpicker);
|
||||
|
||||
/**
|
||||
* Get the current hue of a colorpicker.
|
||||
* @param cpicker pointer to colorpicker object
|
||||
* @return current selected value
|
||||
*/
|
||||
uint8_t lv_cpicker_get_value(lv_obj_t * cpicker);
|
||||
|
||||
/**
|
||||
* Get the current selected hsv of a colorpicker.
|
||||
* @param cpicker pointer to colorpicker object
|
||||
* @return current selected hsv
|
||||
*/
|
||||
lv_color_hsv_t lv_cpicker_get_hsv(lv_obj_t * cpicker);
|
||||
|
||||
/**
|
||||
* Get the current selected color of a colorpicker.
|
||||
* @param cpicker pointer to colorpicker object
|
||||
* @return current selected color
|
||||
*/
|
||||
lv_color_t lv_cpicker_get_color(lv_obj_t * cpicker);
|
||||
|
||||
/**
|
||||
* Whether the indicator is colored to the current color or not
|
||||
* @param cpicker pointer to colorpicker object
|
||||
* @return true: color the indicator; false: not color the indicator
|
||||
*/
|
||||
bool lv_cpicker_get_indic_colored(lv_obj_t * cpicker);
|
||||
|
||||
/**
|
||||
* Whether the preview is enabled or not
|
||||
* @param cpicker pointer to colorpicker object
|
||||
* @return en true: preview is enabled; false: preview is disabled
|
||||
*/
|
||||
bool lv_cpicker_get_preview(lv_obj_t * cpicker);
|
||||
|
||||
/*=====================
|
||||
* Other functions
|
||||
*====================*/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#endif /*LV_USE_CPICKER*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /*LV_CPICKER_H*/
|
||||
@@ -9,6 +9,7 @@
|
||||
#include "lv_ddlist.h"
|
||||
#if LV_USE_DDLIST != 0
|
||||
|
||||
#include "../lv_core/lv_debug.h"
|
||||
#include "../lv_draw/lv_draw.h"
|
||||
#include "../lv_core/lv_group.h"
|
||||
#include "../lv_core/lv_indev.h"
|
||||
@@ -21,6 +22,8 @@
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
#define LV_OBJX_NAME "lv_ddlist"
|
||||
|
||||
#if LV_USE_ANIMATION == 0
|
||||
#undef LV_DDLIST_DEF_ANIM_TIME
|
||||
#define LV_DDLIST_DEF_ANIM_TIME 0 /*No animation*/
|
||||
@@ -74,7 +77,7 @@ lv_obj_t * lv_ddlist_create(lv_obj_t * par, const lv_obj_t * copy)
|
||||
|
||||
/*Create the ancestor drop down list*/
|
||||
lv_obj_t * new_ddlist = lv_page_create(par, copy);
|
||||
lv_mem_assert(new_ddlist);
|
||||
LV_ASSERT_MEM(new_ddlist);
|
||||
if(new_ddlist == NULL) return NULL;
|
||||
|
||||
if(ancestor_signal == NULL) ancestor_signal = lv_obj_get_signal_cb(new_ddlist);
|
||||
@@ -83,7 +86,7 @@ lv_obj_t * lv_ddlist_create(lv_obj_t * par, const lv_obj_t * copy)
|
||||
|
||||
/*Allocate the drop down list type specific extended data*/
|
||||
lv_ddlist_ext_t * ext = lv_obj_allocate_ext_attr(new_ddlist, sizeof(lv_ddlist_ext_t));
|
||||
lv_mem_assert(ext);
|
||||
LV_ASSERT_MEM(ext);
|
||||
if(ext == NULL) return NULL;
|
||||
|
||||
/*Initialize the allocated 'ext' */
|
||||
@@ -110,6 +113,11 @@ lv_obj_t * lv_ddlist_create(lv_obj_t * par, const lv_obj_t * copy)
|
||||
lv_obj_set_drag(scrl, false);
|
||||
lv_page_set_scrl_fit2(new_ddlist, LV_FIT_FILL, LV_FIT_TIGHT);
|
||||
|
||||
/*Save (a later restore) the original X coordinate because it changes as the FITs applies*/
|
||||
lv_coord_t x;
|
||||
if(lv_obj_get_base_dir(new_ddlist) == LV_BIDI_DIR_RTL) x = lv_obj_get_x(new_ddlist) + lv_obj_get_width(new_ddlist);
|
||||
else x = lv_obj_get_x(new_ddlist);
|
||||
|
||||
ext->label = lv_label_create(new_ddlist, NULL);
|
||||
lv_cont_set_fit2(new_ddlist, LV_FIT_TIGHT, LV_FIT_NONE);
|
||||
lv_page_set_sb_mode(new_ddlist, LV_SB_MODE_HIDE);
|
||||
@@ -117,6 +125,10 @@ lv_obj_t * lv_ddlist_create(lv_obj_t * par, const lv_obj_t * copy)
|
||||
|
||||
lv_ddlist_set_options(new_ddlist, "Option 1\nOption 2\nOption 3");
|
||||
|
||||
/*Restore the original X coordinate*/
|
||||
if(lv_obj_get_base_dir(new_ddlist) == LV_BIDI_DIR_RTL) lv_obj_set_x(new_ddlist, x - lv_obj_get_width(new_ddlist));
|
||||
else lv_obj_set_x(new_ddlist, x);
|
||||
|
||||
/*Set the default styles*/
|
||||
lv_theme_t * th = lv_theme_get_current();
|
||||
if(th) {
|
||||
@@ -128,6 +140,8 @@ lv_obj_t * lv_ddlist_create(lv_obj_t * par, const lv_obj_t * copy)
|
||||
lv_ddlist_set_style(new_ddlist, LV_DDLIST_STYLE_SEL, &lv_style_plain_color);
|
||||
lv_ddlist_set_style(new_ddlist, LV_DDLIST_STYLE_SB, &lv_style_pretty_color);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
/*Copy an existing drop down list*/
|
||||
else {
|
||||
@@ -164,6 +178,9 @@ lv_obj_t * lv_ddlist_create(lv_obj_t * par, const lv_obj_t * copy)
|
||||
*/
|
||||
void lv_ddlist_set_options(lv_obj_t * ddlist, const char * options)
|
||||
{
|
||||
LV_ASSERT_OBJ(ddlist, LV_OBJX_NAME);
|
||||
LV_ASSERT_STR(options);
|
||||
|
||||
lv_ddlist_ext_t * ext = lv_obj_get_ext_attr(ddlist);
|
||||
|
||||
/*Count the '\n'-s to determine the number of options*/
|
||||
@@ -180,7 +197,8 @@ void lv_ddlist_set_options(lv_obj_t * ddlist, const char * options)
|
||||
|
||||
lv_ddlist_refr_width(ddlist);
|
||||
|
||||
switch(lv_label_get_align(ext->label)) {
|
||||
lv_label_align_t align = lv_label_get_align(ext->label);
|
||||
switch(align) {
|
||||
case LV_LABEL_ALIGN_LEFT: lv_obj_align(ext->label, NULL, LV_ALIGN_IN_LEFT_MID, 0, 0); break;
|
||||
case LV_LABEL_ALIGN_CENTER: lv_obj_align(ext->label, NULL, LV_ALIGN_CENTER, 0, 0); break;
|
||||
case LV_LABEL_ALIGN_RIGHT: lv_obj_align(ext->label, NULL, LV_ALIGN_IN_RIGHT_MID, 0, 0); break;
|
||||
@@ -196,6 +214,8 @@ void lv_ddlist_set_options(lv_obj_t * ddlist, const char * options)
|
||||
*/
|
||||
void lv_ddlist_set_selected(lv_obj_t * ddlist, uint16_t sel_opt)
|
||||
{
|
||||
LV_ASSERT_OBJ(ddlist, LV_OBJX_NAME);
|
||||
|
||||
lv_ddlist_ext_t * ext = lv_obj_get_ext_attr(ddlist);
|
||||
if(ext->sel_opt_id == sel_opt) return;
|
||||
|
||||
@@ -217,6 +237,8 @@ void lv_ddlist_set_selected(lv_obj_t * ddlist, uint16_t sel_opt)
|
||||
*/
|
||||
void lv_ddlist_set_fix_height(lv_obj_t * ddlist, lv_coord_t h)
|
||||
{
|
||||
LV_ASSERT_OBJ(ddlist, LV_OBJX_NAME);
|
||||
|
||||
lv_ddlist_ext_t * ext = lv_obj_get_ext_attr(ddlist);
|
||||
if(ext->fix_height == h) return;
|
||||
|
||||
@@ -232,6 +254,8 @@ void lv_ddlist_set_fix_height(lv_obj_t * ddlist, lv_coord_t h)
|
||||
*/
|
||||
void lv_ddlist_set_fix_width(lv_obj_t * ddlist, lv_coord_t w)
|
||||
{
|
||||
LV_ASSERT_OBJ(ddlist, LV_OBJX_NAME);
|
||||
|
||||
lv_ddlist_ext_t * ext = lv_obj_get_ext_attr(ddlist);
|
||||
if(w == 0) {
|
||||
lv_cont_set_fit2(ddlist, LV_FIT_TIGHT, lv_cont_get_fit_bottom(ddlist));
|
||||
@@ -256,6 +280,8 @@ void lv_ddlist_set_fix_width(lv_obj_t * ddlist, lv_coord_t w)
|
||||
*/
|
||||
void lv_ddlist_set_draw_arrow(lv_obj_t * ddlist, bool en)
|
||||
{
|
||||
LV_ASSERT_OBJ(ddlist, LV_OBJX_NAME);
|
||||
|
||||
lv_ddlist_ext_t * ext = lv_obj_get_ext_attr(ddlist);
|
||||
|
||||
/*Set the flag*/
|
||||
@@ -269,6 +295,8 @@ void lv_ddlist_set_draw_arrow(lv_obj_t * ddlist, bool en)
|
||||
*/
|
||||
void lv_ddlist_set_stay_open(lv_obj_t * ddlist, bool en)
|
||||
{
|
||||
LV_ASSERT_OBJ(ddlist, LV_OBJX_NAME);
|
||||
|
||||
lv_ddlist_ext_t * ext = lv_obj_get_ext_attr(ddlist);
|
||||
|
||||
/*Set the flag*/
|
||||
@@ -283,6 +311,8 @@ void lv_ddlist_set_stay_open(lv_obj_t * ddlist, bool en)
|
||||
*/
|
||||
void lv_ddlist_set_style(lv_obj_t * ddlist, lv_ddlist_style_t type, const lv_style_t * style)
|
||||
{
|
||||
LV_ASSERT_OBJ(ddlist, LV_OBJX_NAME);
|
||||
|
||||
lv_ddlist_ext_t * ext = lv_obj_get_ext_attr(ddlist);
|
||||
|
||||
switch(type) {
|
||||
@@ -301,6 +331,8 @@ void lv_ddlist_set_style(lv_obj_t * ddlist, lv_ddlist_style_t type, const lv_sty
|
||||
|
||||
void lv_ddlist_set_align(lv_obj_t * ddlist, lv_label_align_t align)
|
||||
{
|
||||
LV_ASSERT_OBJ(ddlist, LV_OBJX_NAME);
|
||||
|
||||
lv_ddlist_ext_t * ext = lv_obj_get_ext_attr(ddlist);
|
||||
|
||||
lv_label_set_align(ext->label, align);
|
||||
@@ -321,6 +353,8 @@ void lv_ddlist_set_align(lv_obj_t * ddlist, lv_label_align_t align)
|
||||
*/
|
||||
const char * lv_ddlist_get_options(const lv_obj_t * ddlist)
|
||||
{
|
||||
LV_ASSERT_OBJ(ddlist, LV_OBJX_NAME);
|
||||
|
||||
lv_ddlist_ext_t * ext = lv_obj_get_ext_attr(ddlist);
|
||||
return lv_label_get_text(ext->label);
|
||||
}
|
||||
@@ -332,6 +366,8 @@ const char * lv_ddlist_get_options(const lv_obj_t * ddlist)
|
||||
*/
|
||||
uint16_t lv_ddlist_get_selected(const lv_obj_t * ddlist)
|
||||
{
|
||||
LV_ASSERT_OBJ(ddlist, LV_OBJX_NAME);
|
||||
|
||||
lv_ddlist_ext_t * ext = lv_obj_get_ext_attr(ddlist);
|
||||
|
||||
return ext->sel_opt_id;
|
||||
@@ -345,6 +381,8 @@ uint16_t lv_ddlist_get_selected(const lv_obj_t * ddlist)
|
||||
*/
|
||||
void lv_ddlist_get_selected_str(const lv_obj_t * ddlist, char * buf, uint16_t buf_size)
|
||||
{
|
||||
LV_ASSERT_OBJ(ddlist, LV_OBJX_NAME);
|
||||
|
||||
lv_ddlist_ext_t * ext = lv_obj_get_ext_attr(ddlist);
|
||||
|
||||
uint16_t i;
|
||||
@@ -375,6 +413,8 @@ void lv_ddlist_get_selected_str(const lv_obj_t * ddlist, char * buf, uint16_t bu
|
||||
*/
|
||||
lv_coord_t lv_ddlist_get_fix_height(const lv_obj_t * ddlist)
|
||||
{
|
||||
LV_ASSERT_OBJ(ddlist, LV_OBJX_NAME);
|
||||
|
||||
lv_ddlist_ext_t * ext = lv_obj_get_ext_attr(ddlist);
|
||||
return ext->fix_height;
|
||||
}
|
||||
@@ -385,6 +425,8 @@ lv_coord_t lv_ddlist_get_fix_height(const lv_obj_t * ddlist)
|
||||
*/
|
||||
bool lv_ddlist_get_draw_arrow(lv_obj_t * ddlist)
|
||||
{
|
||||
LV_ASSERT_OBJ(ddlist, LV_OBJX_NAME);
|
||||
|
||||
lv_ddlist_ext_t * ext = lv_obj_get_ext_attr(ddlist);
|
||||
|
||||
return ext->draw_arrow ? true : false;
|
||||
@@ -396,6 +438,8 @@ bool lv_ddlist_get_draw_arrow(lv_obj_t * ddlist)
|
||||
*/
|
||||
bool lv_ddlist_get_stay_open(lv_obj_t * ddlist)
|
||||
{
|
||||
LV_ASSERT_OBJ(ddlist, LV_OBJX_NAME);
|
||||
|
||||
lv_ddlist_ext_t * ext = lv_obj_get_ext_attr(ddlist);
|
||||
|
||||
return ext->stay_open ? true : false;
|
||||
@@ -409,6 +453,8 @@ bool lv_ddlist_get_stay_open(lv_obj_t * ddlist)
|
||||
*/
|
||||
const lv_style_t * lv_ddlist_get_style(const lv_obj_t * ddlist, lv_ddlist_style_t type)
|
||||
{
|
||||
LV_ASSERT_OBJ(ddlist, LV_OBJX_NAME);
|
||||
|
||||
lv_ddlist_ext_t * ext = lv_obj_get_ext_attr(ddlist);
|
||||
|
||||
switch(type) {
|
||||
@@ -563,7 +609,7 @@ static bool lv_ddlist_design(lv_obj_t * ddlist, const lv_area_t * mask, lv_desig
|
||||
new_style.text.opa = sel_style->text.opa;
|
||||
lv_txt_flag_t flag = lv_ddlist_get_txt_flag(ddlist);
|
||||
lv_draw_label(&ext->label->coords, &mask_sel, &new_style, opa_scale, lv_label_get_text(ext->label),
|
||||
flag, NULL, -1, -1, NULL);
|
||||
flag, NULL, NULL, NULL, lv_obj_get_base_dir(ddlist));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -580,9 +626,14 @@ static bool lv_ddlist_design(lv_obj_t * ddlist, const lv_area_t * mask, lv_desig
|
||||
new_style.text.color = sel_style->text.color;
|
||||
new_style.text.opa = sel_style->text.opa;
|
||||
lv_area_t area_arrow;
|
||||
area_arrow.x2 = ddlist->coords.x2 - style->body.padding.right;
|
||||
area_arrow.x1 = area_arrow.x2 -
|
||||
lv_txt_get_width(LV_SYMBOL_DOWN, strlen(LV_SYMBOL_DOWN), sel_style->text.font, 0, 0);
|
||||
lv_coord_t arrow_width = lv_txt_get_width(LV_SYMBOL_DOWN, strlen(LV_SYMBOL_DOWN), sel_style->text.font, 0, 0);
|
||||
if(lv_label_get_align(ext->label) != LV_LABEL_ALIGN_RIGHT) {
|
||||
area_arrow.x2 = ddlist->coords.x2 - style->body.padding.right;
|
||||
area_arrow.x1 = area_arrow.x2 - arrow_width;
|
||||
} else {
|
||||
area_arrow.x1 = ddlist->coords.x1 + style->body.padding.left;
|
||||
area_arrow.x2 = area_arrow.x1 + arrow_width;
|
||||
}
|
||||
|
||||
area_arrow.y1 = ddlist->coords.y1 + style->text.line_space;
|
||||
area_arrow.y2 = area_arrow.y1 + font_h;
|
||||
@@ -591,9 +642,9 @@ static bool lv_ddlist_design(lv_obj_t * ddlist, const lv_area_t * mask, lv_desig
|
||||
bool area_ok;
|
||||
area_ok = lv_area_intersect(&mask_arrow, mask, &area_arrow);
|
||||
if(area_ok) {
|
||||
/*Use a down arrow in ddlist, you can replace it with yourcustom symbol*/
|
||||
lv_draw_label(&area_arrow, &mask_arrow, &new_style, opa_scale, LV_SYMBOL_DOWN, LV_TXT_FLAG_NONE,
|
||||
NULL, -1, -1, NULL); /*Use a down arrow in ddlist, you can replace it with your
|
||||
custom symbol*/
|
||||
NULL, NULL, NULL, lv_obj_get_base_dir(ddlist));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -617,10 +668,20 @@ static lv_res_t lv_ddlist_signal(lv_obj_t * ddlist, lv_signal_t sign, void * par
|
||||
/* Include the ancient signal function */
|
||||
res = ancestor_signal(ddlist, sign, param);
|
||||
if(res != LV_RES_OK) return res;
|
||||
if(sign == LV_SIGNAL_GET_TYPE) return lv_obj_handle_get_type_signal(param, LV_OBJX_NAME);
|
||||
|
||||
lv_ddlist_ext_t * ext = lv_obj_get_ext_attr(ddlist);
|
||||
|
||||
if(sign == LV_SIGNAL_STYLE_CHG) {
|
||||
lv_ddlist_refr_size(ddlist, 0);
|
||||
} else if(sign == LV_SIGNAL_BASE_DIR_CHG) {
|
||||
lv_label_align_t align = lv_label_get_align(ext->label);
|
||||
switch(align) {
|
||||
case LV_LABEL_ALIGN_LEFT: lv_obj_align(ext->label, NULL, LV_ALIGN_IN_LEFT_MID, 0, 0); break;
|
||||
case LV_LABEL_ALIGN_CENTER: lv_obj_align(ext->label, NULL, LV_ALIGN_CENTER, 0, 0); break;
|
||||
case LV_LABEL_ALIGN_RIGHT: lv_obj_align(ext->label, NULL, LV_ALIGN_IN_RIGHT_MID, 0, 0); break;
|
||||
}
|
||||
|
||||
lv_ddlist_refr_size(ddlist, 0);
|
||||
} else if(sign == LV_SIGNAL_CLEANUP) {
|
||||
ext->label = NULL;
|
||||
@@ -695,13 +756,6 @@ static lv_res_t lv_ddlist_signal(lv_obj_t * ddlist, lv_signal_t sign, void * par
|
||||
} else if(sign == LV_SIGNAL_GET_EDITABLE) {
|
||||
bool * editable = (bool *)param;
|
||||
*editable = true;
|
||||
} else if(sign == LV_SIGNAL_GET_TYPE) {
|
||||
lv_obj_type_t * buf = param;
|
||||
uint8_t i;
|
||||
for(i = 0; i < LV_MAX_ANCESTOR_NUM - 1; i++) { /*Find the last set data*/
|
||||
if(buf->type[i] == NULL) break;
|
||||
}
|
||||
buf->type[i] = "lv_ddlist";
|
||||
}
|
||||
|
||||
return res;
|
||||
@@ -947,11 +1001,27 @@ static void lv_ddlist_pos_current_option(lv_obj_t * ddlist)
|
||||
*/
|
||||
static void lv_ddlist_refr_width(lv_obj_t * ddlist)
|
||||
{
|
||||
lv_ddlist_ext_t * ext = lv_obj_get_ext_attr(ddlist);
|
||||
|
||||
/*Save the current x coordinate because it should be kept after the refrsh*/
|
||||
lv_coord_t x;
|
||||
if(lv_obj_get_base_dir(ddlist) == LV_BIDI_DIR_RTL) x = lv_obj_get_x(ddlist) + lv_obj_get_width(ddlist);
|
||||
else x = lv_obj_get_x(ddlist);
|
||||
|
||||
/*Set the TIGHT fit horizontally the set the width to the content*/
|
||||
lv_page_set_scrl_fit2(ddlist, LV_FIT_TIGHT, lv_page_get_scrl_fit_bottom(ddlist));
|
||||
|
||||
/*Revert FILL fit to fill the parent with the options area. It allows to RIGHT/CENTER align the text*/
|
||||
lv_page_set_scrl_fit2(ddlist, LV_FIT_FILL, lv_page_get_scrl_fit_bottom(ddlist));
|
||||
|
||||
if(lv_obj_get_base_dir(ddlist) == LV_BIDI_DIR_RTL) lv_obj_set_x(ddlist, x - lv_obj_get_width(ddlist));
|
||||
else lv_obj_set_x(ddlist, x);
|
||||
|
||||
switch(lv_label_get_align(ext->label)) {
|
||||
case LV_LABEL_ALIGN_LEFT: lv_obj_align(ext->label, NULL, LV_ALIGN_IN_LEFT_MID, 0, 0); break;
|
||||
case LV_LABEL_ALIGN_CENTER: lv_obj_align(ext->label, NULL, LV_ALIGN_CENTER, 0, 0); break;
|
||||
case LV_LABEL_ALIGN_RIGHT: lv_obj_align(ext->label, NULL, LV_ALIGN_IN_RIGHT_MID, 0, 0); break;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#include "lv_gauge.h"
|
||||
#if LV_USE_GAUGE != 0
|
||||
|
||||
#include "../lv_core/lv_debug.h"
|
||||
#include "../lv_draw/lv_draw.h"
|
||||
#include "../lv_themes/lv_theme.h"
|
||||
#include "../lv_misc/lv_txt.h"
|
||||
@@ -20,6 +21,8 @@
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
#define LV_OBJX_NAME "lv_gauge"
|
||||
|
||||
#define LV_GAUGE_DEF_NEEDLE_COLOR LV_COLOR_RED
|
||||
#define LV_GAUGE_DEF_LABEL_COUNT 6
|
||||
#define LV_GAUGE_DEF_LINE_COUNT 21 /*Should be: ((label_cnt - 1) * internal_lines) + 1*/
|
||||
@@ -65,12 +68,12 @@ lv_obj_t * lv_gauge_create(lv_obj_t * par, const lv_obj_t * copy)
|
||||
|
||||
/*Create the ancestor gauge*/
|
||||
lv_obj_t * new_gauge = lv_lmeter_create(par, copy);
|
||||
lv_mem_assert(new_gauge);
|
||||
LV_ASSERT_MEM(new_gauge);
|
||||
if(new_gauge == NULL) return NULL;
|
||||
|
||||
/*Allocate the gauge type specific extended data*/
|
||||
lv_gauge_ext_t * ext = lv_obj_allocate_ext_attr(new_gauge, sizeof(lv_gauge_ext_t));
|
||||
lv_mem_assert(ext);
|
||||
LV_ASSERT_MEM(ext);
|
||||
if(ext == NULL) return NULL;
|
||||
|
||||
/*Initialize the allocated 'ext' */
|
||||
@@ -131,6 +134,8 @@ lv_obj_t * lv_gauge_create(lv_obj_t * par, const lv_obj_t * copy)
|
||||
*/
|
||||
void lv_gauge_set_needle_count(lv_obj_t * gauge, uint8_t needle_cnt, const lv_color_t colors[])
|
||||
{
|
||||
LV_ASSERT_OBJ(gauge, LV_OBJX_NAME);
|
||||
|
||||
lv_gauge_ext_t * ext = lv_obj_get_ext_attr(gauge);
|
||||
|
||||
if(ext->needle_count != needle_cnt) {
|
||||
@@ -140,7 +145,7 @@ void lv_gauge_set_needle_count(lv_obj_t * gauge, uint8_t needle_cnt, const lv_co
|
||||
}
|
||||
|
||||
ext->values = lv_mem_realloc(ext->values, needle_cnt * sizeof(int16_t));
|
||||
lv_mem_assert(ext->values);
|
||||
LV_ASSERT_MEM(ext->values);
|
||||
if(ext->values == NULL) return;
|
||||
|
||||
int16_t min = lv_gauge_get_min_value(gauge);
|
||||
@@ -164,6 +169,8 @@ void lv_gauge_set_needle_count(lv_obj_t * gauge, uint8_t needle_cnt, const lv_co
|
||||
*/
|
||||
void lv_gauge_set_value(lv_obj_t * gauge, uint8_t needle_id, int16_t value)
|
||||
{
|
||||
LV_ASSERT_OBJ(gauge, LV_OBJX_NAME);
|
||||
|
||||
lv_gauge_ext_t * ext = lv_obj_get_ext_attr(gauge);
|
||||
|
||||
if(needle_id >= ext->needle_count) return;
|
||||
@@ -193,6 +200,8 @@ void lv_gauge_set_value(lv_obj_t * gauge, uint8_t needle_id, int16_t value)
|
||||
*/
|
||||
void lv_gauge_set_scale(lv_obj_t * gauge, uint16_t angle, uint8_t line_cnt, uint8_t label_cnt)
|
||||
{
|
||||
LV_ASSERT_OBJ(gauge, LV_OBJX_NAME);
|
||||
|
||||
lv_lmeter_set_scale(gauge, angle, line_cnt);
|
||||
|
||||
lv_gauge_ext_t * ext = lv_obj_get_ext_attr(gauge);
|
||||
@@ -212,6 +221,8 @@ void lv_gauge_set_scale(lv_obj_t * gauge, uint16_t angle, uint8_t line_cnt, uint
|
||||
*/
|
||||
int16_t lv_gauge_get_value(const lv_obj_t * gauge, uint8_t needle)
|
||||
{
|
||||
LV_ASSERT_OBJ(gauge, LV_OBJX_NAME);
|
||||
|
||||
lv_gauge_ext_t * ext = lv_obj_get_ext_attr(gauge);
|
||||
int16_t min = lv_gauge_get_min_value(gauge);
|
||||
|
||||
@@ -227,6 +238,8 @@ int16_t lv_gauge_get_value(const lv_obj_t * gauge, uint8_t needle)
|
||||
*/
|
||||
uint8_t lv_gauge_get_needle_count(const lv_obj_t * gauge)
|
||||
{
|
||||
LV_ASSERT_OBJ(gauge, LV_OBJX_NAME);
|
||||
|
||||
lv_gauge_ext_t * ext = lv_obj_get_ext_attr(gauge);
|
||||
return ext->needle_count;
|
||||
}
|
||||
@@ -238,6 +251,8 @@ uint8_t lv_gauge_get_needle_count(const lv_obj_t * gauge)
|
||||
*/
|
||||
uint8_t lv_gauge_get_label_count(const lv_obj_t * gauge)
|
||||
{
|
||||
LV_ASSERT_OBJ(gauge, LV_OBJX_NAME);
|
||||
|
||||
lv_gauge_ext_t * ext = lv_obj_get_ext_attr(gauge);
|
||||
return ext->label_count;
|
||||
}
|
||||
@@ -258,7 +273,6 @@ uint8_t lv_gauge_get_label_count(const lv_obj_t * gauge)
|
||||
*/
|
||||
static bool lv_gauge_design(lv_obj_t * gauge, const lv_area_t * mask, lv_design_mode_t mode)
|
||||
{
|
||||
|
||||
/*Return false if the object is not covers the mask_p area*/
|
||||
if(mode == LV_DESIGN_COVER_CHK) {
|
||||
return false;
|
||||
@@ -317,18 +331,12 @@ static lv_res_t lv_gauge_signal(lv_obj_t * gauge, lv_signal_t sign, void * param
|
||||
/* Include the ancient signal function */
|
||||
res = ancestor_signal(gauge, sign, param);
|
||||
if(res != LV_RES_OK) return res;
|
||||
if(sign == LV_SIGNAL_GET_TYPE) return lv_obj_handle_get_type_signal(param, LV_OBJX_NAME);
|
||||
|
||||
lv_gauge_ext_t * ext = lv_obj_get_ext_attr(gauge);
|
||||
if(sign == LV_SIGNAL_CLEANUP) {
|
||||
lv_mem_free(ext->values);
|
||||
ext->values = NULL;
|
||||
} else if(sign == LV_SIGNAL_GET_TYPE) {
|
||||
lv_obj_type_t * buf = param;
|
||||
uint8_t i;
|
||||
for(i = 0; i < LV_MAX_ANCESTOR_NUM - 1; i++) { /*Find the last set data*/
|
||||
if(buf->type[i] == NULL) break;
|
||||
}
|
||||
buf->type[i] = "lv_gauge";
|
||||
}
|
||||
|
||||
return res;
|
||||
@@ -381,7 +389,7 @@ static void lv_gauge_draw_scale(lv_obj_t * gauge, const lv_area_t * mask)
|
||||
label_cord.x2 = label_cord.x1 + label_size.x;
|
||||
label_cord.y2 = label_cord.y1 + label_size.y;
|
||||
|
||||
lv_draw_label(&label_cord, mask, style, opa_scale, scale_txt, LV_TXT_FLAG_NONE, NULL, -1, -1, NULL);
|
||||
lv_draw_label(&label_cord, mask, style, opa_scale, scale_txt, LV_TXT_FLAG_NONE, NULL, NULL, NULL, lv_obj_get_base_dir(gauge));
|
||||
}
|
||||
}
|
||||
/**
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
#error "lv_img: lv_label is required. Enable it in lv_conf.h (LV_USE_LABEL 1) "
|
||||
#endif
|
||||
|
||||
#include "../lv_core/lv_debug.h"
|
||||
#include "../lv_themes/lv_theme.h"
|
||||
#include "../lv_draw/lv_img_decoder.h"
|
||||
#include "../lv_misc/lv_fs.h"
|
||||
@@ -23,6 +24,7 @@
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
#define LV_OBJX_NAME "lv_img"
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
@@ -61,14 +63,14 @@ lv_obj_t * lv_img_create(lv_obj_t * par, const lv_obj_t * copy)
|
||||
|
||||
/*Create a basic object*/
|
||||
new_img = lv_obj_create(par, copy);
|
||||
lv_mem_assert(new_img);
|
||||
LV_ASSERT_MEM(new_img);
|
||||
if(new_img == NULL) return NULL;
|
||||
|
||||
if(ancestor_signal == NULL) ancestor_signal = lv_obj_get_signal_cb(new_img);
|
||||
|
||||
/*Extend the basic object to image object*/
|
||||
lv_img_ext_t * ext = lv_obj_allocate_ext_attr(new_img, sizeof(lv_img_ext_t));
|
||||
lv_mem_assert(ext);
|
||||
LV_ASSERT_MEM(ext);
|
||||
if(ext == NULL) return NULL;
|
||||
|
||||
ext->src = NULL;
|
||||
@@ -121,6 +123,8 @@ lv_obj_t * lv_img_create(lv_obj_t * par, const lv_obj_t * copy)
|
||||
*/
|
||||
void lv_img_set_src(lv_obj_t * img, const void * src_img)
|
||||
{
|
||||
LV_ASSERT_OBJ(img, LV_OBJX_NAME);
|
||||
|
||||
lv_img_src_t src_type = lv_img_src_get_type(src_img);
|
||||
lv_img_ext_t * ext = lv_obj_get_ext_attr(img);
|
||||
|
||||
@@ -167,7 +171,7 @@ void lv_img_set_src(lv_obj_t * img, const void * src_img)
|
||||
old_src = ext->src;
|
||||
}
|
||||
char * new_str = lv_mem_alloc(strlen(src_img) + 1);
|
||||
lv_mem_assert(new_str);
|
||||
LV_ASSERT_MEM(new_str);
|
||||
if(new_str == NULL) return;
|
||||
strcpy(new_str, src_img);
|
||||
ext->src = new_str;
|
||||
@@ -206,6 +210,8 @@ void lv_img_set_src(lv_obj_t * img, const void * src_img)
|
||||
*/
|
||||
void lv_img_set_auto_size(lv_obj_t * img, bool en)
|
||||
{
|
||||
LV_ASSERT_OBJ(img, LV_OBJX_NAME);
|
||||
|
||||
lv_img_ext_t * ext = lv_obj_get_ext_attr(img);
|
||||
|
||||
ext->auto_size = (en == false ? 0 : 1);
|
||||
@@ -219,6 +225,8 @@ void lv_img_set_auto_size(lv_obj_t * img, bool en)
|
||||
*/
|
||||
void lv_img_set_offset_x(lv_obj_t * img, lv_coord_t x)
|
||||
{
|
||||
LV_ASSERT_OBJ(img, LV_OBJX_NAME);
|
||||
|
||||
lv_img_ext_t * ext = lv_obj_get_ext_attr(img);
|
||||
|
||||
if(x < ext->w - 1) {
|
||||
@@ -235,6 +243,8 @@ void lv_img_set_offset_x(lv_obj_t * img, lv_coord_t x)
|
||||
*/
|
||||
void lv_img_set_offset_y(lv_obj_t * img, lv_coord_t y)
|
||||
{
|
||||
LV_ASSERT_OBJ(img, LV_OBJX_NAME);
|
||||
|
||||
lv_img_ext_t * ext = lv_obj_get_ext_attr(img);
|
||||
|
||||
if(y < ext->h - 1) {
|
||||
@@ -254,6 +264,8 @@ void lv_img_set_offset_y(lv_obj_t * img, lv_coord_t y)
|
||||
*/
|
||||
const void * lv_img_get_src(lv_obj_t * img)
|
||||
{
|
||||
LV_ASSERT_OBJ(img, LV_OBJX_NAME);
|
||||
|
||||
lv_img_ext_t * ext = lv_obj_get_ext_attr(img);
|
||||
|
||||
return ext->src;
|
||||
@@ -266,6 +278,8 @@ const void * lv_img_get_src(lv_obj_t * img)
|
||||
*/
|
||||
const char * lv_img_get_file_name(const lv_obj_t * img)
|
||||
{
|
||||
LV_ASSERT_OBJ(img, LV_OBJX_NAME);
|
||||
|
||||
lv_img_ext_t * ext = lv_obj_get_ext_attr(img);
|
||||
|
||||
if(ext->src_type == LV_IMG_SRC_FILE)
|
||||
@@ -281,6 +295,8 @@ const char * lv_img_get_file_name(const lv_obj_t * img)
|
||||
*/
|
||||
bool lv_img_get_auto_size(const lv_obj_t * img)
|
||||
{
|
||||
LV_ASSERT_OBJ(img, LV_OBJX_NAME);
|
||||
|
||||
lv_img_ext_t * ext = lv_obj_get_ext_attr(img);
|
||||
|
||||
return ext->auto_size == 0 ? false : true;
|
||||
@@ -293,6 +309,8 @@ bool lv_img_get_auto_size(const lv_obj_t * img)
|
||||
*/
|
||||
lv_coord_t lv_img_get_offset_x(lv_obj_t * img)
|
||||
{
|
||||
LV_ASSERT_OBJ(img, LV_OBJX_NAME);
|
||||
|
||||
lv_img_ext_t * ext = lv_obj_get_ext_attr(img);
|
||||
|
||||
return ext->offset.x;
|
||||
@@ -305,6 +323,8 @@ lv_coord_t lv_img_get_offset_x(lv_obj_t * img)
|
||||
*/
|
||||
lv_coord_t lv_img_get_offset_y(lv_obj_t * img)
|
||||
{
|
||||
LV_ASSERT_OBJ(img, LV_OBJX_NAME);
|
||||
|
||||
lv_img_ext_t * ext = lv_obj_get_ext_attr(img);
|
||||
|
||||
return ext->offset.y;
|
||||
@@ -352,10 +372,10 @@ static bool lv_img_design(lv_obj_t * img, const lv_area_t * mask, lv_design_mode
|
||||
cords_tmp.y1 = coords.y1;
|
||||
cords_tmp.y2 = coords.y1 + ext->h - 1;
|
||||
|
||||
for(; cords_tmp.y1 < coords.y2; cords_tmp.y1 += ext->h, cords_tmp.y2 += ext->h) {
|
||||
for(; cords_tmp.y1 <= coords.y2; cords_tmp.y1 += ext->h, cords_tmp.y2 += ext->h) {
|
||||
cords_tmp.x1 = coords.x1;
|
||||
cords_tmp.x2 = coords.x1 + ext->w - 1;
|
||||
for(; cords_tmp.x1 < coords.x2; cords_tmp.x1 += ext->w, cords_tmp.x2 += ext->w) {
|
||||
for(; cords_tmp.x1 <= coords.x2; cords_tmp.x1 += ext->w, cords_tmp.x2 += ext->w) {
|
||||
lv_draw_img(&cords_tmp, mask, ext->src, style, opa_scale);
|
||||
}
|
||||
}
|
||||
@@ -364,7 +384,7 @@ static bool lv_img_design(lv_obj_t * img, const lv_area_t * mask, lv_design_mode
|
||||
lv_style_t style_mod;
|
||||
lv_style_copy(&style_mod, style);
|
||||
style_mod.text.color = style->image.color;
|
||||
lv_draw_label(&coords, mask, &style_mod, opa_scale, ext->src, LV_TXT_FLAG_NONE, NULL, -1, -1, NULL);
|
||||
lv_draw_label(&coords, mask, &style_mod, opa_scale, ext->src, LV_TXT_FLAG_NONE, NULL, NULL, NULL, lv_obj_get_base_dir(img));
|
||||
} else {
|
||||
/*Trigger the error handler of image drawer*/
|
||||
LV_LOG_WARN("lv_img_design: image source type is unknown");
|
||||
@@ -390,6 +410,8 @@ static lv_res_t lv_img_signal(lv_obj_t * img, lv_signal_t sign, void * param)
|
||||
res = ancestor_signal(img, sign, param);
|
||||
if(res != LV_RES_OK) return res;
|
||||
|
||||
if(sign == LV_SIGNAL_GET_TYPE) return lv_obj_handle_get_type_signal(param, LV_OBJX_NAME);
|
||||
|
||||
lv_img_ext_t * ext = lv_obj_get_ext_attr(img);
|
||||
if(sign == LV_SIGNAL_CLEANUP) {
|
||||
if(ext->src_type == LV_IMG_SRC_FILE || ext->src_type == LV_IMG_SRC_SYMBOL) {
|
||||
@@ -402,13 +424,6 @@ static lv_res_t lv_img_signal(lv_obj_t * img, lv_signal_t sign, void * param)
|
||||
if(ext->src_type == LV_IMG_SRC_SYMBOL) {
|
||||
lv_img_set_src(img, ext->src);
|
||||
}
|
||||
} else if(sign == LV_SIGNAL_GET_TYPE) {
|
||||
lv_obj_type_t * buf = param;
|
||||
uint8_t i;
|
||||
for(i = 0; i < LV_MAX_ANCESTOR_NUM - 1; i++) { /*Find the last set data*/
|
||||
if(buf->type[i] == NULL) break;
|
||||
}
|
||||
buf->type[i] = "lv_img";
|
||||
}
|
||||
|
||||
return res;
|
||||
|
||||
@@ -6,12 +6,17 @@
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
|
||||
#include "../lv_core/lv_debug.h"
|
||||
#include "lv_imgbtn.h"
|
||||
#include "lv_label.h"
|
||||
|
||||
#if LV_USE_IMGBTN != 0
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
#define LV_OBJX_NAME "lv_imgbtn"
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
@@ -51,12 +56,12 @@ lv_obj_t * lv_imgbtn_create(lv_obj_t * par, const lv_obj_t * copy)
|
||||
|
||||
/*Create the ancestor of image button*/
|
||||
lv_obj_t * new_imgbtn = lv_btn_create(par, copy);
|
||||
lv_mem_assert(new_imgbtn);
|
||||
LV_ASSERT_MEM(new_imgbtn);
|
||||
if(new_imgbtn == NULL) return NULL;
|
||||
|
||||
/*Allocate the image button type specific extended data*/
|
||||
lv_imgbtn_ext_t * ext = lv_obj_allocate_ext_attr(new_imgbtn, sizeof(lv_imgbtn_ext_t));
|
||||
lv_mem_assert(ext);
|
||||
LV_ASSERT_MEM(ext);
|
||||
if(ext == NULL) return NULL;
|
||||
if(ancestor_signal == NULL) ancestor_signal = lv_obj_get_signal_cb(new_imgbtn);
|
||||
if(ancestor_design == NULL) ancestor_design = lv_obj_get_design_cb(new_imgbtn);
|
||||
@@ -112,6 +117,8 @@ lv_obj_t * lv_imgbtn_create(lv_obj_t * par, const lv_obj_t * copy)
|
||||
*/
|
||||
void lv_imgbtn_set_src(lv_obj_t * imgbtn, lv_btn_state_t state, const void * src)
|
||||
{
|
||||
LV_ASSERT_OBJ(imgbtn, LV_OBJX_NAME);
|
||||
|
||||
lv_imgbtn_ext_t * ext = lv_obj_get_ext_attr(imgbtn);
|
||||
|
||||
ext->img_src[state] = src;
|
||||
@@ -134,6 +141,17 @@ void lv_imgbtn_set_src(lv_obj_t * imgbtn, lv_btn_state_t state, const void * src
|
||||
void lv_imgbtn_set_src(lv_obj_t * imgbtn, lv_btn_state_t state, const void * src_left, const void * src_mid,
|
||||
const void * src_right)
|
||||
{
|
||||
LV_ASSERT_OBJ(imgbtn, LV_OBJX_NAME);
|
||||
|
||||
|
||||
if(lv_img_src_get_type(src_left) == LV_IMG_SRC_SYMBOL ||
|
||||
lv_img_src_get_type(src_mid) == LV_IMG_SRC_SYMBOL ||
|
||||
lv_img_src_get_type(src_right) == LV_IMG_SRC_SYMBOL )
|
||||
{
|
||||
LV_LOG_WARN("lv_imgbtn_set_src: symbols are not supported in tiled mode");
|
||||
return;
|
||||
}
|
||||
|
||||
lv_imgbtn_ext_t * ext = lv_obj_get_ext_attr(imgbtn);
|
||||
|
||||
ext->img_src_left[state] = src_left;
|
||||
@@ -153,6 +171,8 @@ void lv_imgbtn_set_src(lv_obj_t * imgbtn, lv_btn_state_t state, const void * src
|
||||
*/
|
||||
void lv_imgbtn_set_style(lv_obj_t * imgbtn, lv_imgbtn_style_t type, const lv_style_t * style)
|
||||
{
|
||||
LV_ASSERT_OBJ(imgbtn, LV_OBJX_NAME);
|
||||
|
||||
lv_btn_set_style(imgbtn, type, style);
|
||||
}
|
||||
|
||||
@@ -169,6 +189,8 @@ void lv_imgbtn_set_style(lv_obj_t * imgbtn, lv_imgbtn_style_t type, const lv_sty
|
||||
*/
|
||||
const void * lv_imgbtn_get_src(lv_obj_t * imgbtn, lv_btn_state_t state)
|
||||
{
|
||||
LV_ASSERT_OBJ(imgbtn, LV_OBJX_NAME);
|
||||
|
||||
lv_imgbtn_ext_t * ext = lv_obj_get_ext_attr(imgbtn);
|
||||
|
||||
return ext->img_src[state];
|
||||
@@ -183,6 +205,8 @@ const void * lv_imgbtn_get_src(lv_obj_t * imgbtn, lv_btn_state_t state)
|
||||
*/
|
||||
const void * lv_imgbtn_get_src_left(lv_obj_t * imgbtn, lv_btn_state_t state)
|
||||
{
|
||||
LV_ASSERT_OBJ(imgbtn, LV_OBJX_NAME);
|
||||
|
||||
lv_imgbtn_ext_t * ext = lv_obj_get_ext_attr(imgbtn);
|
||||
|
||||
return ext->img_src_left[state];
|
||||
@@ -196,6 +220,8 @@ const void * lv_imgbtn_get_src_left(lv_obj_t * imgbtn, lv_btn_state_t state)
|
||||
*/
|
||||
const void * lv_imgbtn_get_src_middle(lv_obj_t * imgbtn, lv_btn_state_t state)
|
||||
{
|
||||
LV_ASSERT_OBJ(imgbtn, LV_OBJX_NAME);
|
||||
|
||||
lv_imgbtn_ext_t * ext = lv_obj_get_ext_attr(imgbtn);
|
||||
|
||||
return ext->img_src_mid[state];
|
||||
@@ -209,6 +235,8 @@ const void * lv_imgbtn_get_src_middle(lv_obj_t * imgbtn, lv_btn_state_t state)
|
||||
*/
|
||||
const void * lv_imgbtn_get_src_right(lv_obj_t * imgbtn, lv_btn_state_t state)
|
||||
{
|
||||
LV_ASSERT_OBJ(imgbtn, LV_OBJX_NAME);
|
||||
|
||||
lv_imgbtn_ext_t * ext = lv_obj_get_ext_attr(imgbtn);
|
||||
|
||||
return ext->img_src_right[state];
|
||||
@@ -224,6 +252,8 @@ const void * lv_imgbtn_get_src_right(lv_obj_t * imgbtn, lv_btn_state_t state)
|
||||
*/
|
||||
const lv_style_t * lv_imgbtn_get_style(const lv_obj_t * imgbtn, lv_imgbtn_style_t type)
|
||||
{
|
||||
LV_ASSERT_OBJ(imgbtn, LV_OBJX_NAME);
|
||||
|
||||
return lv_btn_get_style(imgbtn, type);
|
||||
}
|
||||
|
||||
@@ -269,17 +299,28 @@ static bool lv_imgbtn_design(lv_obj_t * imgbtn, const lv_area_t * mask, lv_desig
|
||||
const lv_style_t * style = lv_imgbtn_get_style(imgbtn, state);
|
||||
lv_opa_t opa_scale = lv_obj_get_opa_scale(imgbtn);
|
||||
|
||||
|
||||
|
||||
#if LV_IMGBTN_TILED == 0
|
||||
const void * src = ext->img_src[state];
|
||||
lv_draw_img(&imgbtn->coords, mask, src, style, opa_scale);
|
||||
if(lv_img_src_get_type(src) == LV_IMG_SRC_SYMBOL) {
|
||||
lv_draw_label(&imgbtn->coords, mask, style, opa_scale, src, LV_TXT_FLAG_NONE, NULL, NULL, NULL, lv_obj_get_base_dir(imgbtn));
|
||||
} else {
|
||||
lv_draw_img(&imgbtn->coords, mask, src, style, opa_scale);
|
||||
}
|
||||
#else
|
||||
const void * src;
|
||||
src = ext->img_src_left[state];
|
||||
if(lv_img_src_get_type(src) == LV_IMG_SRC_SYMBOL) {
|
||||
LV_LOG_WARN("lv_imgbtn_design: SYMBOLS are not supported in tiled mode")
|
||||
return true;
|
||||
}
|
||||
|
||||
lv_img_header_t header;
|
||||
lv_area_t coords;
|
||||
lv_coord_t left_w = 0;
|
||||
lv_coord_t right_w = 0;
|
||||
|
||||
src = ext->img_src_left[state];
|
||||
if(src) {
|
||||
lv_img_decoder_get_info(src, &header);
|
||||
left_w = header.w;
|
||||
@@ -343,6 +384,7 @@ static lv_res_t lv_imgbtn_signal(lv_obj_t * imgbtn, lv_signal_t sign, void * par
|
||||
/* Include the ancient signal function */
|
||||
res = ancestor_signal(imgbtn, sign, param);
|
||||
if(res != LV_RES_OK) return res;
|
||||
if(sign == LV_SIGNAL_GET_TYPE) return lv_obj_handle_get_type_signal(param, LV_OBJX_NAME);
|
||||
|
||||
if(sign == LV_SIGNAL_STYLE_CHG) {
|
||||
/* If the style changed then the button was clicked, released etc. so probably the state was
|
||||
@@ -350,13 +392,6 @@ static lv_res_t lv_imgbtn_signal(lv_obj_t * imgbtn, lv_signal_t sign, void * par
|
||||
refr_img(imgbtn);
|
||||
} else if(sign == LV_SIGNAL_CLEANUP) {
|
||||
/*Nothing to cleanup. (No dynamically allocated memory in 'ext')*/
|
||||
} else if(sign == LV_SIGNAL_GET_TYPE) {
|
||||
lv_obj_type_t * buf = param;
|
||||
uint8_t i;
|
||||
for(i = 0; i < LV_MAX_ANCESTOR_NUM - 1; i++) { /*Find the last set data*/
|
||||
if(buf->type[i] == NULL) break;
|
||||
}
|
||||
buf->type[i] = "lv_imgbtn";
|
||||
}
|
||||
|
||||
return res;
|
||||
@@ -374,8 +409,17 @@ static void refr_img(lv_obj_t * imgbtn)
|
||||
const void * src = ext->img_src_mid[state];
|
||||
#endif
|
||||
|
||||
lv_res_t info_res;
|
||||
info_res = lv_img_decoder_get_info(src, &header);
|
||||
lv_res_t info_res = LV_RES_OK;
|
||||
if(lv_img_src_get_type(src) == LV_IMG_SRC_SYMBOL) {
|
||||
const lv_style_t * style = ext->btn.styles[state];
|
||||
header.h = lv_font_get_line_height(style->text.font);
|
||||
header.w = lv_txt_get_width(src, strlen(src), style->text.font, style->text.letter_space, LV_TXT_FLAG_NONE);
|
||||
header.always_zero = 0;
|
||||
header.cf = LV_IMG_CF_ALPHA_1BIT;
|
||||
} else {
|
||||
info_res = lv_img_decoder_get_info(src, &header);
|
||||
}
|
||||
|
||||
if(info_res == LV_RES_OK) {
|
||||
ext->act_cf = header.cf;
|
||||
#if LV_IMGBTN_TILED == 0
|
||||
|
||||
@@ -10,12 +10,15 @@
|
||||
#include "lv_kb.h"
|
||||
#if LV_USE_KB != 0
|
||||
|
||||
#include "lv_ta.h"
|
||||
#include "../lv_core/lv_debug.h"
|
||||
#include "../lv_themes/lv_theme.h"
|
||||
#include "lv_ta.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
#define LV_OBJX_NAME "lv_kb"
|
||||
|
||||
#define LV_KB_CTRL_BTN_FLAGS (LV_BTNM_CTRL_NO_REPEAT | LV_BTNM_CTRL_CLICK_TRIG)
|
||||
|
||||
/**********************
|
||||
@@ -32,8 +35,8 @@ static lv_res_t lv_kb_signal(lv_obj_t * kb, lv_signal_t sign, void * param);
|
||||
**********************/
|
||||
static lv_signal_cb_t ancestor_signal;
|
||||
/* clang-format off */
|
||||
static const char * kb_map_lc[] = {"1#", "q", "w", "e", "r", "t", "y", "u", "i", "o", "p", "Bksp", "\n",
|
||||
"ABC", "a", "s", "d", "f", "g", "h", "j", "k", "l", "Enter", "\n",
|
||||
static const char * kb_map_lc[] = {"1#", "q", "w", "e", "r", "t", "y", "u", "i", "o", "p", LV_SYMBOL_BACKSPACE, "\n",
|
||||
"ABC", "a", "s", "d", "f", "g", "h", "j", "k", "l", LV_SYMBOL_NEW_LINE, "\n",
|
||||
"_", "-", "z", "x", "c", "v", "b", "n", "m", ".", ",", ":", "\n",
|
||||
LV_SYMBOL_CLOSE, LV_SYMBOL_LEFT, " ", LV_SYMBOL_RIGHT, LV_SYMBOL_OK, ""};
|
||||
|
||||
@@ -43,8 +46,8 @@ static const lv_btnm_ctrl_t kb_ctrl_lc_map[] = {
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
||||
LV_KB_CTRL_BTN_FLAGS | 2, 2, 6, 2, LV_KB_CTRL_BTN_FLAGS | 2};
|
||||
|
||||
static const char * kb_map_uc[] = {"1#", "Q", "W", "E", "R", "T", "Y", "U", "I", "O", "P", "Bksp", "\n",
|
||||
"abc", "A", "S", "D", "F", "G", "H", "J", "K", "L", "Enter", "\n",
|
||||
static const char * kb_map_uc[] = {"1#", "Q", "W", "E", "R", "T", "Y", "U", "I", "O", "P", LV_SYMBOL_BACKSPACE, "\n",
|
||||
"abc", "A", "S", "D", "F", "G", "H", "J", "K", "L", LV_SYMBOL_NEW_LINE, "\n",
|
||||
"_", "-", "Z", "X", "C", "V", "B", "N", "M", ".", ",", ":", "\n",
|
||||
LV_SYMBOL_CLOSE, LV_SYMBOL_LEFT, " ", LV_SYMBOL_RIGHT, LV_SYMBOL_OK, ""};
|
||||
|
||||
@@ -54,7 +57,7 @@ static const lv_btnm_ctrl_t kb_ctrl_uc_map[] = {
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
||||
LV_KB_CTRL_BTN_FLAGS | 2, 2, 6, 2, LV_KB_CTRL_BTN_FLAGS | 2};
|
||||
|
||||
static const char * kb_map_spec[] = {"0", "1", "2", "3", "4" ,"5", "6", "7", "8", "9", "Bksp", "\n",
|
||||
static const char * kb_map_spec[] = {"0", "1", "2", "3", "4" ,"5", "6", "7", "8", "9", LV_SYMBOL_BACKSPACE, "\n",
|
||||
"abc", "+", "-", "/", "*", "=", "%", "!", "?", "#", "<", ">", "\n",
|
||||
"\\", "@", "$", "(", ")", "{", "}", "[", "]", ";", "\"", "'", "\n",
|
||||
LV_SYMBOL_CLOSE, LV_SYMBOL_LEFT, " ", LV_SYMBOL_RIGHT, LV_SYMBOL_OK, ""};
|
||||
@@ -67,7 +70,7 @@ static const lv_btnm_ctrl_t kb_ctrl_spec_map[] = {
|
||||
|
||||
static const char * kb_map_num[] = {"1", "2", "3", LV_SYMBOL_CLOSE, "\n",
|
||||
"4", "5", "6", LV_SYMBOL_OK, "\n",
|
||||
"7", "8", "9", "Bksp", "\n",
|
||||
"7", "8", "9", LV_SYMBOL_BACKSPACE, "\n",
|
||||
"+/-", "0", ".", LV_SYMBOL_LEFT, LV_SYMBOL_RIGHT, ""};
|
||||
|
||||
static const lv_btnm_ctrl_t kb_ctrl_num_map[] = {
|
||||
@@ -97,14 +100,14 @@ lv_obj_t * lv_kb_create(lv_obj_t * par, const lv_obj_t * copy)
|
||||
|
||||
/*Create the ancestor of keyboard*/
|
||||
lv_obj_t * new_kb = lv_btnm_create(par, copy);
|
||||
lv_mem_assert(new_kb);
|
||||
LV_ASSERT_MEM(new_kb);
|
||||
if(new_kb == NULL) return NULL;
|
||||
|
||||
if(ancestor_signal == NULL) ancestor_signal = lv_obj_get_signal_cb(new_kb);
|
||||
|
||||
/*Allocate the keyboard type specific extended data*/
|
||||
lv_kb_ext_t * ext = lv_obj_allocate_ext_attr(new_kb, sizeof(lv_kb_ext_t));
|
||||
lv_mem_assert(ext);
|
||||
LV_ASSERT_MEM(ext);
|
||||
if(ext == NULL) return NULL;
|
||||
|
||||
/*Initialize the allocated 'ext' */
|
||||
@@ -128,6 +131,7 @@ lv_obj_t * lv_kb_create(lv_obj_t * par, const lv_obj_t * copy)
|
||||
lv_obj_set_event_cb(new_kb, lv_kb_def_event_cb);
|
||||
lv_btnm_set_map(new_kb, kb_map_lc);
|
||||
lv_btnm_set_ctrl_map(new_kb, kb_ctrl_lc_map);
|
||||
lv_obj_set_base_dir(new_kb, LV_BIDI_DIR_LTR);
|
||||
|
||||
/*Set the default styles*/
|
||||
lv_theme_t * th = lv_theme_get_current();
|
||||
@@ -170,6 +174,9 @@ lv_obj_t * lv_kb_create(lv_obj_t * par, const lv_obj_t * copy)
|
||||
*/
|
||||
void lv_kb_set_ta(lv_obj_t * kb, lv_obj_t * ta)
|
||||
{
|
||||
LV_ASSERT_OBJ(kb, LV_OBJX_NAME);
|
||||
if(ta) LV_ASSERT_OBJ(ta, "lv_ta");
|
||||
|
||||
lv_kb_ext_t * ext = lv_obj_get_ext_attr(kb);
|
||||
lv_cursor_type_t cur_type;
|
||||
|
||||
@@ -195,6 +202,8 @@ void lv_kb_set_ta(lv_obj_t * kb, lv_obj_t * ta)
|
||||
*/
|
||||
void lv_kb_set_mode(lv_obj_t * kb, lv_kb_mode_t mode)
|
||||
{
|
||||
LV_ASSERT_OBJ(kb, LV_OBJX_NAME);
|
||||
|
||||
lv_kb_ext_t * ext = lv_obj_get_ext_attr(kb);
|
||||
if(ext->mode == mode) return;
|
||||
|
||||
@@ -205,6 +214,9 @@ void lv_kb_set_mode(lv_obj_t * kb, lv_kb_mode_t mode)
|
||||
} else if(mode == LV_KB_MODE_NUM) {
|
||||
lv_btnm_set_map(kb, kb_map_num);
|
||||
lv_btnm_set_ctrl_map(kb, kb_ctrl_num_map);
|
||||
} else if(mode == LV_KB_MODE_TEXT_UPPER) {
|
||||
lv_btnm_set_map(kb, kb_map_uc);
|
||||
lv_btnm_set_ctrl_map(kb, kb_ctrl_uc_map);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -215,6 +227,8 @@ void lv_kb_set_mode(lv_obj_t * kb, lv_kb_mode_t mode)
|
||||
*/
|
||||
void lv_kb_set_cursor_manage(lv_obj_t * kb, bool en)
|
||||
{
|
||||
LV_ASSERT_OBJ(kb, LV_OBJX_NAME);
|
||||
|
||||
lv_kb_ext_t * ext = lv_obj_get_ext_attr(kb);
|
||||
if(ext->cursor_mng == en) return;
|
||||
|
||||
@@ -240,6 +254,8 @@ void lv_kb_set_cursor_manage(lv_obj_t * kb, bool en)
|
||||
*/
|
||||
void lv_kb_set_style(lv_obj_t * kb, lv_kb_style_t type, const lv_style_t * style)
|
||||
{
|
||||
LV_ASSERT_OBJ(kb, LV_OBJX_NAME);
|
||||
|
||||
switch(type) {
|
||||
case LV_KB_STYLE_BG: lv_btnm_set_style(kb, LV_BTNM_STYLE_BG, style); break;
|
||||
case LV_KB_STYLE_BTN_REL: lv_btnm_set_style(kb, LV_BTNM_STYLE_BTN_REL, style); break;
|
||||
@@ -261,6 +277,8 @@ void lv_kb_set_style(lv_obj_t * kb, lv_kb_style_t type, const lv_style_t * style
|
||||
*/
|
||||
lv_obj_t * lv_kb_get_ta(const lv_obj_t * kb)
|
||||
{
|
||||
LV_ASSERT_OBJ(kb, LV_OBJX_NAME);
|
||||
|
||||
lv_kb_ext_t * ext = lv_obj_get_ext_attr(kb);
|
||||
return ext->ta;
|
||||
}
|
||||
@@ -272,6 +290,8 @@ lv_obj_t * lv_kb_get_ta(const lv_obj_t * kb)
|
||||
*/
|
||||
lv_kb_mode_t lv_kb_get_mode(const lv_obj_t * kb)
|
||||
{
|
||||
LV_ASSERT_OBJ(kb, LV_OBJX_NAME);
|
||||
|
||||
lv_kb_ext_t * ext = lv_obj_get_ext_attr(kb);
|
||||
return ext->mode;
|
||||
}
|
||||
@@ -283,6 +303,8 @@ lv_kb_mode_t lv_kb_get_mode(const lv_obj_t * kb)
|
||||
*/
|
||||
bool lv_kb_get_cursor_manage(const lv_obj_t * kb)
|
||||
{
|
||||
LV_ASSERT_OBJ(kb, LV_OBJX_NAME);
|
||||
|
||||
lv_kb_ext_t * ext = lv_obj_get_ext_attr(kb);
|
||||
return ext->cursor_mng == 0 ? false : true;
|
||||
}
|
||||
@@ -295,6 +317,8 @@ bool lv_kb_get_cursor_manage(const lv_obj_t * kb)
|
||||
*/
|
||||
const lv_style_t * lv_kb_get_style(const lv_obj_t * kb, lv_kb_style_t type)
|
||||
{
|
||||
LV_ASSERT_OBJ(kb, LV_OBJX_NAME);
|
||||
|
||||
const lv_style_t * style = NULL;
|
||||
|
||||
switch(type) {
|
||||
@@ -323,6 +347,8 @@ const lv_style_t * lv_kb_get_style(const lv_obj_t * kb, lv_kb_style_t type)
|
||||
*/
|
||||
void lv_kb_def_event_cb(lv_obj_t * kb, lv_event_t event)
|
||||
{
|
||||
LV_ASSERT_OBJ(kb, LV_OBJX_NAME);
|
||||
|
||||
if(event != LV_EVENT_VALUE_CHANGED) return;
|
||||
|
||||
lv_kb_ext_t * ext = lv_obj_get_ext_attr(kb);
|
||||
@@ -370,13 +396,13 @@ void lv_kb_def_event_cb(lv_obj_t * kb, lv_event_t event)
|
||||
/*Add the characters to the text area if set*/
|
||||
if(ext->ta == NULL) return;
|
||||
|
||||
if(strcmp(txt, "Enter") == 0)
|
||||
if(strcmp(txt, "Enter") == 0 || strcmp(txt, LV_SYMBOL_NEW_LINE) == 0)
|
||||
lv_ta_add_char(ext->ta, '\n');
|
||||
else if(strcmp(txt, LV_SYMBOL_LEFT) == 0)
|
||||
lv_ta_cursor_left(ext->ta);
|
||||
else if(strcmp(txt, LV_SYMBOL_RIGHT) == 0)
|
||||
lv_ta_cursor_right(ext->ta);
|
||||
else if(strcmp(txt, "Bksp") == 0)
|
||||
else if(strcmp(txt, LV_SYMBOL_BACKSPACE) == 0)
|
||||
lv_ta_del_char(ext->ta);
|
||||
else if(strcmp(txt, "+/-") == 0) {
|
||||
uint16_t cur = lv_ta_get_cursor_pos(ext->ta);
|
||||
@@ -419,6 +445,7 @@ static lv_res_t lv_kb_signal(lv_obj_t * kb, lv_signal_t sign, void * param)
|
||||
/* Include the ancient signal function */
|
||||
res = ancestor_signal(kb, sign, param);
|
||||
if(res != LV_RES_OK) return res;
|
||||
if(sign == LV_SIGNAL_GET_TYPE) return lv_obj_handle_get_type_signal(param, LV_OBJX_NAME);
|
||||
|
||||
if(sign == LV_SIGNAL_CLEANUP) {
|
||||
/*Nothing to cleanup. (No dynamically allocated memory in 'ext')*/
|
||||
@@ -436,13 +463,6 @@ static lv_res_t lv_kb_signal(lv_obj_t * kb, lv_signal_t sign, void * param)
|
||||
lv_cursor_type_t cur_type = lv_ta_get_cursor_type(ext->ta);
|
||||
lv_ta_set_cursor_type(ext->ta, cur_type | LV_CURSOR_HIDDEN);
|
||||
}
|
||||
} else if(sign == LV_SIGNAL_GET_TYPE) {
|
||||
lv_obj_type_t * buf = param;
|
||||
uint8_t i;
|
||||
for(i = 0; i < LV_MAX_ANCESTOR_NUM - 1; i++) { /*Find the last set data*/
|
||||
if(buf->type[i] == NULL) break;
|
||||
}
|
||||
buf->type[i] = "lv_kb";
|
||||
}
|
||||
|
||||
return res;
|
||||
|
||||
@@ -45,6 +45,7 @@ extern "C" {
|
||||
enum {
|
||||
LV_KB_MODE_TEXT,
|
||||
LV_KB_MODE_NUM,
|
||||
LV_KB_MODE_TEXT_UPPER,
|
||||
};
|
||||
typedef uint8_t lv_kb_mode_t;
|
||||
|
||||
|
||||
@@ -10,13 +10,18 @@
|
||||
#if LV_USE_LABEL != 0
|
||||
|
||||
#include "../lv_core/lv_obj.h"
|
||||
#include "../lv_core/lv_debug.h"
|
||||
#include "../lv_core/lv_group.h"
|
||||
#include "../lv_misc/lv_color.h"
|
||||
#include "../lv_misc/lv_math.h"
|
||||
#include "../lv_misc/lv_bidi.h"
|
||||
#include "../lv_misc/lv_printf.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
#define LV_OBJX_NAME "lv_label"
|
||||
|
||||
/*Test configurations*/
|
||||
#ifndef LV_LABEL_DEF_SCROLL_SPEED
|
||||
#define LV_LABEL_DEF_SCROLL_SPEED (25)
|
||||
@@ -72,7 +77,7 @@ lv_obj_t * lv_label_create(lv_obj_t * par, const lv_obj_t * copy)
|
||||
|
||||
/*Create a basic object*/
|
||||
lv_obj_t * new_label = lv_obj_create(par, copy);
|
||||
lv_mem_assert(new_label);
|
||||
LV_ASSERT_MEM(new_label);
|
||||
if(new_label == NULL) return NULL;
|
||||
|
||||
if(ancestor_signal == NULL) ancestor_signal = lv_obj_get_signal_cb(new_label);
|
||||
@@ -81,14 +86,14 @@ lv_obj_t * lv_label_create(lv_obj_t * par, const lv_obj_t * copy)
|
||||
lv_obj_allocate_ext_attr(new_label, sizeof(lv_label_ext_t));
|
||||
|
||||
lv_label_ext_t * ext = lv_obj_get_ext_attr(new_label);
|
||||
lv_mem_assert(ext);
|
||||
LV_ASSERT_MEM(ext);
|
||||
if(ext == NULL) return NULL;
|
||||
|
||||
ext->text = NULL;
|
||||
ext->static_txt = 0;
|
||||
ext->recolor = 0;
|
||||
ext->body_draw = 0;
|
||||
ext->align = LV_LABEL_ALIGN_LEFT;
|
||||
ext->align = LV_LABEL_ALIGN_AUTO;
|
||||
ext->dot_end = LV_LABEL_DOT_END_INV;
|
||||
ext->long_mode = LV_LABEL_LONG_EXPAND;
|
||||
#if LV_USE_ANIMATION
|
||||
@@ -104,8 +109,8 @@ lv_obj_t * lv_label_create(lv_obj_t * par, const lv_obj_t * copy)
|
||||
#endif
|
||||
|
||||
#if LV_LABEL_TEXT_SEL
|
||||
ext->txt_sel_start = LV_LABEL_TEXT_SEL_OFF;
|
||||
ext->txt_sel_end = LV_LABEL_TEXT_SEL_OFF;
|
||||
ext->txt_sel_start = LV_DRAW_LABEL_NO_TXT_SEL;
|
||||
ext->txt_sel_end = LV_DRAW_LABEL_NO_TXT_SEL;
|
||||
#endif
|
||||
ext->dot.tmp_ptr = NULL;
|
||||
ext->dot_tmp_alloc = 0;
|
||||
@@ -135,7 +140,7 @@ lv_obj_t * lv_label_create(lv_obj_t * par, const lv_obj_t * copy)
|
||||
/*In DOT mode save the text byte-to-byte because a '\0' can be in the middle*/
|
||||
if(copy_ext->long_mode == LV_LABEL_LONG_DOT) {
|
||||
ext->text = lv_mem_realloc(ext->text, lv_mem_get_size(copy_ext->text));
|
||||
lv_mem_assert(ext->text);
|
||||
LV_ASSERT_MEM(ext->text);
|
||||
if(ext->text == NULL) return NULL;
|
||||
memcpy(ext->text, copy_ext->text, lv_mem_get_size(copy_ext->text));
|
||||
}
|
||||
@@ -169,6 +174,8 @@ lv_obj_t * lv_label_create(lv_obj_t * par, const lv_obj_t * copy)
|
||||
*/
|
||||
void lv_label_set_text(lv_obj_t * label, const char * text)
|
||||
{
|
||||
LV_ASSERT_OBJ(label, LV_OBJX_NAME);
|
||||
|
||||
lv_obj_invalidate(label);
|
||||
|
||||
lv_label_ext_t * ext = lv_obj_get_ext_attr(label);
|
||||
@@ -179,10 +186,12 @@ void lv_label_set_text(lv_obj_t * label, const char * text)
|
||||
return;
|
||||
}
|
||||
|
||||
LV_ASSERT_STR(text);
|
||||
|
||||
if(ext->text == text) {
|
||||
/*If set its own text then reallocate it (maybe its size changed)*/
|
||||
ext->text = lv_mem_realloc(ext->text, strlen(ext->text) + 1);
|
||||
lv_mem_assert(ext->text);
|
||||
LV_ASSERT_MEM(ext->text);
|
||||
if(ext->text == NULL) return;
|
||||
} else {
|
||||
/*Allocate space for the new text*/
|
||||
@@ -193,16 +202,66 @@ void lv_label_set_text(lv_obj_t * label, const char * text)
|
||||
}
|
||||
|
||||
ext->text = lv_mem_alloc(len);
|
||||
lv_mem_assert(ext->text);
|
||||
LV_ASSERT_MEM(ext->text);
|
||||
if(ext->text == NULL) return;
|
||||
|
||||
strcpy(ext->text, text);
|
||||
ext->static_txt = 0; /*Now the text is dynamically allocated*/
|
||||
|
||||
/*Now the text is dynamically allocated*/
|
||||
ext->static_txt = 0;
|
||||
}
|
||||
|
||||
lv_label_refr_text(label);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a new formatted text for a label. Memory will be allocated to store the text by the label.
|
||||
* @param label pointer to a label object
|
||||
* @param fmt `printf`-like format
|
||||
*/
|
||||
void lv_label_set_text_fmt(lv_obj_t * label, const char * fmt, ...)
|
||||
{
|
||||
LV_ASSERT_OBJ(label, LV_OBJX_NAME);
|
||||
LV_ASSERT_STR(fmt);
|
||||
|
||||
lv_obj_invalidate(label);
|
||||
|
||||
lv_label_ext_t * ext = lv_obj_get_ext_attr(label);
|
||||
|
||||
/*If text is NULL then refresh */
|
||||
if(fmt == NULL) {
|
||||
lv_label_refr_text(label);
|
||||
return;
|
||||
}
|
||||
|
||||
if(ext->text != NULL && ext->static_txt == 0) {
|
||||
lv_mem_free(ext->text);
|
||||
ext->text = NULL;
|
||||
}
|
||||
|
||||
va_list ap, ap2;
|
||||
va_start(ap, fmt);
|
||||
va_copy(ap2, ap);
|
||||
|
||||
/*Allocate space for the new text by using trick from C99 standard section 7.19.6.12 */
|
||||
uint32_t len = lv_vsnprintf(NULL, 0, fmt, ap);
|
||||
|
||||
va_end(ap);
|
||||
|
||||
|
||||
ext->text = lv_mem_alloc(len+1);
|
||||
LV_ASSERT_MEM(ext->text);
|
||||
if(ext->text == NULL) return;
|
||||
ext->text[len-1] = 0; /* Ensure NULL termination */
|
||||
|
||||
lv_vsnprintf(ext->text, len+1, fmt, ap2);
|
||||
|
||||
va_end(ap2);
|
||||
ext->static_txt = 0; /*Now the text is dynamically allocated*/
|
||||
|
||||
lv_label_refr_text(label);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a new text for a label from a character array. The array don't has to be '\0' terminated.
|
||||
* Memory will be allocated to store the array by the label.
|
||||
@@ -212,6 +271,8 @@ void lv_label_set_text(lv_obj_t * label, const char * text)
|
||||
*/
|
||||
void lv_label_set_array_text(lv_obj_t * label, const char * array, uint16_t size)
|
||||
{
|
||||
LV_ASSERT_OBJ(label, LV_OBJX_NAME);
|
||||
|
||||
lv_obj_invalidate(label);
|
||||
|
||||
lv_label_ext_t * ext = lv_obj_get_ext_attr(label);
|
||||
@@ -228,7 +289,7 @@ void lv_label_set_array_text(lv_obj_t * label, const char * array, uint16_t size
|
||||
ext->text = NULL;
|
||||
}
|
||||
ext->text = lv_mem_alloc(size + 1);
|
||||
lv_mem_assert(ext->text);
|
||||
LV_ASSERT_MEM(ext->text);
|
||||
if(ext->text == NULL) return;
|
||||
|
||||
memcpy(ext->text, array, size);
|
||||
@@ -246,6 +307,9 @@ void lv_label_set_array_text(lv_obj_t * label, const char * array, uint16_t size
|
||||
*/
|
||||
void lv_label_set_static_text(lv_obj_t * label, const char * text)
|
||||
{
|
||||
LV_ASSERT_OBJ(label, LV_OBJX_NAME);
|
||||
LV_ASSERT_STR(text);
|
||||
|
||||
lv_label_ext_t * ext = lv_obj_get_ext_attr(label);
|
||||
if(ext->static_txt == 0 && ext->text != NULL) {
|
||||
lv_mem_free(ext->text);
|
||||
@@ -269,6 +333,8 @@ void lv_label_set_static_text(lv_obj_t * label, const char * text)
|
||||
*/
|
||||
void lv_label_set_long_mode(lv_obj_t * label, lv_label_long_mode_t long_mode)
|
||||
{
|
||||
LV_ASSERT_OBJ(label, LV_OBJX_NAME);
|
||||
|
||||
lv_label_ext_t * ext = lv_obj_get_ext_attr(label);
|
||||
|
||||
#if LV_USE_ANIMATION
|
||||
@@ -302,6 +368,8 @@ void lv_label_set_long_mode(lv_obj_t * label, lv_label_long_mode_t long_mode)
|
||||
*/
|
||||
void lv_label_set_align(lv_obj_t * label, lv_label_align_t align)
|
||||
{
|
||||
LV_ASSERT_OBJ(label, LV_OBJX_NAME);
|
||||
|
||||
lv_label_ext_t * ext = lv_obj_get_ext_attr(label);
|
||||
if(ext->align == align) return;
|
||||
|
||||
@@ -318,6 +386,8 @@ void lv_label_set_align(lv_obj_t * label, lv_label_align_t align)
|
||||
*/
|
||||
void lv_label_set_recolor(lv_obj_t * label, bool en)
|
||||
{
|
||||
LV_ASSERT_OBJ(label, LV_OBJX_NAME);
|
||||
|
||||
lv_label_ext_t * ext = lv_obj_get_ext_attr(label);
|
||||
if(ext->recolor == en) return;
|
||||
|
||||
@@ -334,6 +404,8 @@ void lv_label_set_recolor(lv_obj_t * label, bool en)
|
||||
*/
|
||||
void lv_label_set_body_draw(lv_obj_t * label, bool en)
|
||||
{
|
||||
LV_ASSERT_OBJ(label, LV_OBJX_NAME);
|
||||
|
||||
lv_label_ext_t * ext = lv_obj_get_ext_attr(label);
|
||||
if(ext->body_draw == en) return;
|
||||
|
||||
@@ -351,6 +423,8 @@ void lv_label_set_body_draw(lv_obj_t * label, bool en)
|
||||
*/
|
||||
void lv_label_set_anim_speed(lv_obj_t * label, uint16_t anim_speed)
|
||||
{
|
||||
LV_ASSERT_OBJ(label, LV_OBJX_NAME);
|
||||
|
||||
#if LV_USE_ANIMATION
|
||||
lv_label_ext_t * ext = lv_obj_get_ext_attr(label);
|
||||
if(ext->anim_speed == anim_speed) return;
|
||||
@@ -368,6 +442,8 @@ void lv_label_set_anim_speed(lv_obj_t * label, uint16_t anim_speed)
|
||||
|
||||
void lv_label_set_text_sel_start(lv_obj_t * label, uint16_t index)
|
||||
{
|
||||
LV_ASSERT_OBJ(label, LV_OBJX_NAME);
|
||||
|
||||
#if LV_LABEL_TEXT_SEL
|
||||
lv_label_ext_t * ext = lv_obj_get_ext_attr(label);
|
||||
ext->txt_sel_start = index;
|
||||
@@ -380,6 +456,8 @@ void lv_label_set_text_sel_start(lv_obj_t * label, uint16_t index)
|
||||
|
||||
void lv_label_set_text_sel_end(lv_obj_t * label, uint16_t index)
|
||||
{
|
||||
LV_ASSERT_OBJ(label, LV_OBJX_NAME);
|
||||
|
||||
#if LV_LABEL_TEXT_SEL
|
||||
lv_label_ext_t * ext = lv_obj_get_ext_attr(label);
|
||||
ext->txt_sel_end = index;
|
||||
@@ -401,6 +479,8 @@ void lv_label_set_text_sel_end(lv_obj_t * label, uint16_t index)
|
||||
*/
|
||||
char * lv_label_get_text(const lv_obj_t * label)
|
||||
{
|
||||
LV_ASSERT_OBJ(label, LV_OBJX_NAME);
|
||||
|
||||
lv_label_ext_t * ext = lv_obj_get_ext_attr(label);
|
||||
|
||||
return ext->text;
|
||||
@@ -413,6 +493,8 @@ char * lv_label_get_text(const lv_obj_t * label)
|
||||
*/
|
||||
lv_label_long_mode_t lv_label_get_long_mode(const lv_obj_t * label)
|
||||
{
|
||||
LV_ASSERT_OBJ(label, LV_OBJX_NAME);
|
||||
|
||||
lv_label_ext_t * ext = lv_obj_get_ext_attr(label);
|
||||
return ext->long_mode;
|
||||
}
|
||||
@@ -424,8 +506,25 @@ lv_label_long_mode_t lv_label_get_long_mode(const lv_obj_t * label)
|
||||
*/
|
||||
lv_label_align_t lv_label_get_align(const lv_obj_t * label)
|
||||
{
|
||||
LV_ASSERT_OBJ(label, LV_OBJX_NAME);
|
||||
|
||||
lv_label_ext_t * ext = lv_obj_get_ext_attr(label);
|
||||
return ext->align;
|
||||
|
||||
lv_label_align_t align = ext->align;
|
||||
|
||||
if(align == LV_LABEL_ALIGN_AUTO) {
|
||||
#if LV_USE_BIDI
|
||||
lv_bidi_dir_t base_dir = lv_obj_get_base_dir(label);
|
||||
if(base_dir == LV_BIDI_DIR_AUTO) base_dir = lv_bidi_detect_base_dir(ext->text);
|
||||
|
||||
if(base_dir == LV_BIDI_DIR_LTR) align = LV_LABEL_ALIGN_LEFT;
|
||||
else if (base_dir == LV_BIDI_DIR_RTL) align = LV_LABEL_ALIGN_RIGHT;
|
||||
#else
|
||||
align = LV_LABEL_ALIGN_LEFT;
|
||||
#endif
|
||||
}
|
||||
|
||||
return align;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -435,6 +534,8 @@ lv_label_align_t lv_label_get_align(const lv_obj_t * label)
|
||||
*/
|
||||
bool lv_label_get_recolor(const lv_obj_t * label)
|
||||
{
|
||||
LV_ASSERT_OBJ(label, LV_OBJX_NAME);
|
||||
|
||||
lv_label_ext_t * ext = lv_obj_get_ext_attr(label);
|
||||
return ext->recolor == 0 ? false : true;
|
||||
}
|
||||
@@ -446,6 +547,8 @@ bool lv_label_get_recolor(const lv_obj_t * label)
|
||||
*/
|
||||
bool lv_label_get_body_draw(const lv_obj_t * label)
|
||||
{
|
||||
LV_ASSERT_OBJ(label, LV_OBJX_NAME);
|
||||
|
||||
lv_label_ext_t * ext = lv_obj_get_ext_attr(label);
|
||||
return ext->body_draw == 0 ? false : true;
|
||||
}
|
||||
@@ -457,6 +560,8 @@ bool lv_label_get_body_draw(const lv_obj_t * label)
|
||||
*/
|
||||
uint16_t lv_label_get_anim_speed(const lv_obj_t * label)
|
||||
{
|
||||
LV_ASSERT_OBJ(label, LV_OBJX_NAME);
|
||||
|
||||
#if LV_USE_ANIMATION
|
||||
lv_label_ext_t * ext = lv_obj_get_ext_attr(label);
|
||||
return ext->anim_speed;
|
||||
@@ -473,8 +578,11 @@ uint16_t lv_label_get_anim_speed(const lv_obj_t * label)
|
||||
* index (different in UTF-8)
|
||||
* @param pos store the result here (E.g. index = 0 gives 0;0 coordinates)
|
||||
*/
|
||||
void lv_label_get_letter_pos(const lv_obj_t * label, uint16_t index, lv_point_t * pos)
|
||||
void lv_label_get_letter_pos(const lv_obj_t * label, uint16_t char_id, lv_point_t * pos)
|
||||
{
|
||||
LV_ASSERT_OBJ(label, LV_OBJX_NAME);
|
||||
LV_ASSERT_NULL(pos);
|
||||
|
||||
const char * txt = lv_label_get_text(label);
|
||||
lv_label_ext_t * ext = lv_obj_get_ext_attr(label);
|
||||
uint32_t line_start = 0;
|
||||
@@ -488,19 +596,22 @@ void lv_label_get_letter_pos(const lv_obj_t * label, uint16_t index, lv_point_t
|
||||
|
||||
if(ext->recolor != 0) flag |= LV_TXT_FLAG_RECOLOR;
|
||||
if(ext->expand != 0) flag |= LV_TXT_FLAG_EXPAND;
|
||||
if(ext->align == LV_LABEL_ALIGN_CENTER) flag |= LV_TXT_FLAG_CENTER;
|
||||
|
||||
lv_label_align_t align = lv_label_get_align(label);
|
||||
if(align == LV_LABEL_ALIGN_CENTER) flag |= LV_TXT_FLAG_CENTER;
|
||||
if(align == LV_LABEL_ALIGN_RIGHT) flag |= LV_TXT_FLAG_RIGHT;
|
||||
|
||||
/*If the width will be expanded the set the max length to very big */
|
||||
if(ext->long_mode == LV_LABEL_LONG_EXPAND) {
|
||||
max_w = LV_COORD_MAX;
|
||||
}
|
||||
|
||||
index = lv_txt_encoded_get_byte_id(txt, index);
|
||||
uint16_t byte_id = lv_txt_encoded_get_byte_id(txt, char_id);
|
||||
|
||||
/*Search the line of the index letter */;
|
||||
while(txt[new_line_start] != '\0') {
|
||||
new_line_start += lv_txt_get_next_line(&txt[line_start], font, style->text.letter_space, max_w, flag);
|
||||
if(index < new_line_start || txt[new_line_start] == '\0')
|
||||
if(byte_id < new_line_start || txt[new_line_start] == '\0')
|
||||
break; /*The line of 'index' letter begins at 'line_start'*/
|
||||
|
||||
y += letter_height + style->text.line_space;
|
||||
@@ -508,26 +619,50 @@ void lv_label_get_letter_pos(const lv_obj_t * label, uint16_t index, lv_point_t
|
||||
}
|
||||
|
||||
/*If the last character is line break then go to the next line*/
|
||||
if(index > 0) {
|
||||
if((txt[index - 1] == '\n' || txt[index - 1] == '\r') && txt[index] == '\0') {
|
||||
if(byte_id > 0) {
|
||||
if((txt[byte_id - 1] == '\n' || txt[byte_id - 1] == '\r') && txt[byte_id] == '\0') {
|
||||
y += letter_height + style->text.line_space;
|
||||
line_start = index;
|
||||
line_start = byte_id;
|
||||
}
|
||||
}
|
||||
|
||||
const char *bidi_txt;
|
||||
uint16_t visual_byte_pos;
|
||||
#if LV_USE_BIDI
|
||||
/*Handle Bidi*/
|
||||
if(new_line_start == byte_id) {
|
||||
visual_byte_pos = byte_id - line_start;
|
||||
bidi_txt = &txt[line_start];
|
||||
}
|
||||
else {
|
||||
uint16_t line_char_id = lv_txt_encoded_get_char_id(&txt[line_start], byte_id - line_start);
|
||||
|
||||
bool is_rtl;
|
||||
char *mutable_bidi_txt;
|
||||
uint16_t visual_char_pos = lv_bidi_get_visual_pos(&txt[line_start], &mutable_bidi_txt, new_line_start - line_start, lv_obj_get_base_dir(label), line_char_id, &is_rtl);
|
||||
bidi_txt = mutable_bidi_txt;
|
||||
if (is_rtl) visual_char_pos++;
|
||||
visual_byte_pos = lv_txt_encoded_get_byte_id(bidi_txt, visual_char_pos);
|
||||
}
|
||||
#else
|
||||
bidi_txt = &txt[line_start];
|
||||
visual_byte_pos = byte_id - line_start;
|
||||
#endif
|
||||
|
||||
|
||||
/*Calculate the x coordinate*/
|
||||
lv_coord_t x = lv_txt_get_width(&txt[line_start], index - line_start, font, style->text.letter_space, flag);
|
||||
lv_coord_t x = lv_txt_get_width(bidi_txt, visual_byte_pos, font, style->text.letter_space, flag);
|
||||
|
||||
if(index != line_start) x += style->text.letter_space;
|
||||
if(char_id != line_start) x += style->text.letter_space;
|
||||
|
||||
if(ext->align == LV_LABEL_ALIGN_CENTER) {
|
||||
if(align == LV_LABEL_ALIGN_CENTER) {
|
||||
lv_coord_t line_w;
|
||||
line_w = lv_txt_get_width(&txt[line_start], new_line_start - line_start, font, style->text.letter_space, flag);
|
||||
line_w = lv_txt_get_width(bidi_txt, new_line_start - line_start, font, style->text.letter_space, flag);
|
||||
x += lv_obj_get_width(label) / 2 - line_w / 2;
|
||||
|
||||
} else if(ext->align == LV_LABEL_ALIGN_RIGHT) {
|
||||
} else if(align == LV_LABEL_ALIGN_RIGHT) {
|
||||
lv_coord_t line_w;
|
||||
line_w = lv_txt_get_width(&txt[line_start], new_line_start - line_start, font, style->text.letter_space, flag);
|
||||
line_w = lv_txt_get_width(bidi_txt, new_line_start - line_start, font, style->text.letter_space, flag);
|
||||
|
||||
x += lv_obj_get_width(label) - line_w;
|
||||
}
|
||||
@@ -544,6 +679,9 @@ void lv_label_get_letter_pos(const lv_obj_t * label, uint16_t index, lv_point_t
|
||||
*/
|
||||
uint16_t lv_label_get_letter_on(const lv_obj_t * label, lv_point_t * pos)
|
||||
{
|
||||
LV_ASSERT_OBJ(label, LV_OBJX_NAME);
|
||||
LV_ASSERT_NULL(pos);
|
||||
|
||||
const char * txt = lv_label_get_text(label);
|
||||
lv_label_ext_t * ext = lv_obj_get_ext_attr(label);
|
||||
uint32_t line_start = 0;
|
||||
@@ -554,10 +692,15 @@ uint16_t lv_label_get_letter_on(const lv_obj_t * label, lv_point_t * pos)
|
||||
uint8_t letter_height = lv_font_get_line_height(font);
|
||||
lv_coord_t y = 0;
|
||||
lv_txt_flag_t flag = LV_TXT_FLAG_NONE;
|
||||
uint16_t logical_pos;
|
||||
char *bidi_txt;
|
||||
|
||||
if(ext->recolor != 0) flag |= LV_TXT_FLAG_RECOLOR;
|
||||
if(ext->expand != 0) flag |= LV_TXT_FLAG_EXPAND;
|
||||
if(ext->align == LV_LABEL_ALIGN_CENTER) flag |= LV_TXT_FLAG_CENTER;
|
||||
|
||||
lv_label_align_t align = lv_label_get_align(label);
|
||||
if(align == LV_LABEL_ALIGN_CENTER) flag |= LV_TXT_FLAG_CENTER;
|
||||
if(align == LV_LABEL_ALIGN_RIGHT) flag |= LV_TXT_FLAG_RIGHT;
|
||||
|
||||
/*If the width will be expanded set the max length to very big */
|
||||
if(ext->long_mode == LV_LABEL_LONG_EXPAND) {
|
||||
@@ -568,38 +711,60 @@ uint16_t lv_label_get_letter_on(const lv_obj_t * label, lv_point_t * pos)
|
||||
while(txt[line_start] != '\0') {
|
||||
new_line_start += lv_txt_get_next_line(&txt[line_start], font, style->text.letter_space, max_w, flag);
|
||||
|
||||
if(pos->y <= y + letter_height) break; /*The line is found (stored in 'line_start')*/
|
||||
if(pos->y <= y + letter_height) {
|
||||
/*The line is found (stored in 'line_start')*/
|
||||
/* Include the NULL terminator in the last line */
|
||||
uint32_t tmp = new_line_start;
|
||||
uint32_t letter;
|
||||
letter = lv_txt_encoded_prev(txt, &tmp);
|
||||
if(letter != '\n' && txt[new_line_start] == '\0' ) new_line_start++;
|
||||
break;
|
||||
}
|
||||
y += letter_height + style->text.line_space;
|
||||
|
||||
line_start = new_line_start;
|
||||
}
|
||||
|
||||
#if LV_USE_BIDI
|
||||
bidi_txt = lv_draw_get_buf(new_line_start - line_start + 1);
|
||||
uint16_t txt_len = new_line_start - line_start;
|
||||
if(bidi_txt[new_line_start] == '\0') txt_len--;
|
||||
lv_bidi_process_paragraph(txt + line_start, bidi_txt, txt_len, lv_obj_get_base_dir(label), NULL, 0);
|
||||
#else
|
||||
bidi_txt = (char*)txt + line_start;
|
||||
#endif
|
||||
|
||||
/*Calculate the x coordinate*/
|
||||
lv_coord_t x = 0;
|
||||
if(ext->align == LV_LABEL_ALIGN_CENTER) {
|
||||
if(align == LV_LABEL_ALIGN_CENTER) {
|
||||
lv_coord_t line_w;
|
||||
line_w = lv_txt_get_width(&txt[line_start], new_line_start - line_start, font, style->text.letter_space, flag);
|
||||
line_w = lv_txt_get_width(bidi_txt, new_line_start - line_start, font, style->text.letter_space, flag);
|
||||
x += lv_obj_get_width(label) / 2 - line_w / 2;
|
||||
}
|
||||
else if(align == LV_LABEL_ALIGN_RIGHT) {
|
||||
lv_coord_t line_w;
|
||||
line_w = lv_txt_get_width(bidi_txt, new_line_start - line_start, font, style->text.letter_space, flag);
|
||||
x += lv_obj_get_width(label) - line_w;
|
||||
}
|
||||
|
||||
lv_txt_cmd_state_t cmd_state = LV_TXT_CMD_STATE_WAIT;
|
||||
|
||||
uint32_t i = line_start;
|
||||
uint32_t i = 0;
|
||||
uint32_t i_act = i;
|
||||
uint32_t letter;
|
||||
uint32_t letter_next;
|
||||
|
||||
if(new_line_start > 0) {
|
||||
while(i < new_line_start) {
|
||||
while(i + line_start < new_line_start) {
|
||||
/* Get the current letter.*/
|
||||
letter = lv_txt_encoded_next(txt, &i);
|
||||
letter = lv_txt_encoded_next(bidi_txt, &i);
|
||||
|
||||
/*Get the next letter too for kerning*/
|
||||
letter_next = lv_txt_encoded_next(&txt[i], NULL);
|
||||
letter_next = lv_txt_encoded_next(&bidi_txt[i], NULL);
|
||||
|
||||
/*Handle the recolor command*/
|
||||
if((flag & LV_TXT_FLAG_RECOLOR) != 0) {
|
||||
if(lv_txt_is_cmd(&cmd_state, txt[i]) != false) {
|
||||
if(lv_txt_is_cmd(&cmd_state, bidi_txt[i]) != false) {
|
||||
continue; /*Skip the letter is it is part of a command*/
|
||||
}
|
||||
}
|
||||
@@ -607,7 +772,7 @@ uint16_t lv_label_get_letter_on(const lv_obj_t * label, lv_point_t * pos)
|
||||
x += lv_font_get_glyph_width(font, letter, letter_next);
|
||||
|
||||
/*Finish if the x position or the last char of the line is reached*/
|
||||
if(pos->x < x || i == new_line_start) {
|
||||
if(pos->x < x || i + line_start == new_line_start) {
|
||||
i = i_act;
|
||||
break;
|
||||
}
|
||||
@@ -616,7 +781,16 @@ uint16_t lv_label_get_letter_on(const lv_obj_t * label, lv_point_t * pos)
|
||||
}
|
||||
}
|
||||
|
||||
return lv_encoded_get_char_id(txt, i);
|
||||
#if LV_USE_BIDI
|
||||
/*Handle Bidi*/
|
||||
bool is_rtl;
|
||||
logical_pos = lv_bidi_get_logical_pos(&txt[line_start], NULL, txt_len, lv_obj_get_base_dir(label), lv_txt_encoded_get_char_id(bidi_txt, i), &is_rtl);
|
||||
if (is_rtl) logical_pos++;
|
||||
#else
|
||||
logical_pos = lv_txt_encoded_get_char_id(bidi_txt, i);
|
||||
#endif
|
||||
|
||||
return logical_pos + lv_txt_encoded_get_char_id(txt, line_start);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -626,6 +800,8 @@ uint16_t lv_label_get_letter_on(const lv_obj_t * label, lv_point_t * pos)
|
||||
*/
|
||||
uint16_t lv_label_get_text_sel_start(const lv_obj_t * label)
|
||||
{
|
||||
LV_ASSERT_OBJ(label, LV_OBJX_NAME);
|
||||
|
||||
#if LV_LABEL_TEXT_SEL
|
||||
lv_label_ext_t * ext = lv_obj_get_ext_attr(label);
|
||||
return ext->txt_sel_start;
|
||||
@@ -643,6 +819,8 @@ uint16_t lv_label_get_text_sel_start(const lv_obj_t * label)
|
||||
*/
|
||||
uint16_t lv_label_get_text_sel_end(const lv_obj_t * label)
|
||||
{
|
||||
LV_ASSERT_OBJ(label, LV_OBJX_NAME);
|
||||
|
||||
#if LV_LABEL_TEXT_SEL
|
||||
lv_label_ext_t * ext = lv_obj_get_ext_attr(label);
|
||||
return ext->txt_sel_end;
|
||||
@@ -660,6 +838,9 @@ uint16_t lv_label_get_text_sel_end(const lv_obj_t * label)
|
||||
*/
|
||||
bool lv_label_is_char_under_pos(const lv_obj_t * label, lv_point_t * pos)
|
||||
{
|
||||
LV_ASSERT_OBJ(label, LV_OBJX_NAME);
|
||||
LV_ASSERT_NULL(pos);
|
||||
|
||||
const char * txt = lv_label_get_text(label);
|
||||
lv_label_ext_t * ext = lv_obj_get_ext_attr(label);
|
||||
uint32_t line_start = 0;
|
||||
@@ -670,10 +851,11 @@ bool lv_label_is_char_under_pos(const lv_obj_t * label, lv_point_t * pos)
|
||||
uint8_t letter_height = lv_font_get_line_height(font);
|
||||
lv_coord_t y = 0;
|
||||
lv_txt_flag_t flag = LV_TXT_FLAG_NONE;
|
||||
lv_label_align_t align = lv_label_get_align(label);
|
||||
|
||||
if(ext->recolor != 0) flag |= LV_TXT_FLAG_RECOLOR;
|
||||
if(ext->expand != 0) flag |= LV_TXT_FLAG_EXPAND;
|
||||
if(ext->align == LV_LABEL_ALIGN_CENTER) flag |= LV_TXT_FLAG_CENTER;
|
||||
if(align == LV_LABEL_ALIGN_CENTER) flag |= LV_TXT_FLAG_CENTER;
|
||||
|
||||
/*If the width will be expanded set the max length to very big */
|
||||
if(ext->long_mode == LV_LABEL_LONG_EXPAND) {
|
||||
@@ -693,11 +875,16 @@ bool lv_label_is_char_under_pos(const lv_obj_t * label, lv_point_t * pos)
|
||||
/*Calculate the x coordinate*/
|
||||
lv_coord_t x = 0;
|
||||
lv_coord_t last_x = 0;
|
||||
if(ext->align == LV_LABEL_ALIGN_CENTER) {
|
||||
if(align == LV_LABEL_ALIGN_CENTER) {
|
||||
lv_coord_t line_w;
|
||||
line_w = lv_txt_get_width(&txt[line_start], new_line_start - line_start, font, style->text.letter_space, flag);
|
||||
x += lv_obj_get_width(label) / 2 - line_w / 2;
|
||||
}
|
||||
else if(align == LV_LABEL_ALIGN_RIGHT) {
|
||||
lv_coord_t line_w;
|
||||
line_w = lv_txt_get_width(&txt[line_start], new_line_start - line_start, font, style->text.letter_space, flag);
|
||||
x += lv_obj_get_width(label) - line_w;
|
||||
}
|
||||
|
||||
lv_txt_cmd_state_t cmd_state = LV_TXT_CMD_STATE_WAIT;
|
||||
|
||||
@@ -749,6 +936,9 @@ bool lv_label_is_char_under_pos(const lv_obj_t * label, lv_point_t * pos)
|
||||
*/
|
||||
void lv_label_ins_text(lv_obj_t * label, uint32_t pos, const char * txt)
|
||||
{
|
||||
LV_ASSERT_OBJ(label, LV_OBJX_NAME);
|
||||
LV_ASSERT_STR(txt);
|
||||
|
||||
lv_label_ext_t * ext = lv_obj_get_ext_attr(label);
|
||||
|
||||
/*Can not append to static text*/
|
||||
@@ -761,7 +951,7 @@ void lv_label_ins_text(lv_obj_t * label, uint32_t pos, const char * txt)
|
||||
uint32_t ins_len = strlen(txt);
|
||||
uint32_t new_len = ins_len + old_len;
|
||||
ext->text = lv_mem_realloc(ext->text, new_len + 1);
|
||||
lv_mem_assert(ext->text);
|
||||
LV_ASSERT_MEM(ext->text);
|
||||
if(ext->text == NULL) return;
|
||||
|
||||
if(pos == LV_LABEL_POS_LAST) {
|
||||
@@ -769,7 +959,6 @@ void lv_label_ins_text(lv_obj_t * label, uint32_t pos, const char * txt)
|
||||
}
|
||||
|
||||
lv_txt_ins(ext->text, pos, txt);
|
||||
|
||||
lv_label_refr_text(label);
|
||||
}
|
||||
|
||||
@@ -782,6 +971,8 @@ void lv_label_ins_text(lv_obj_t * label, uint32_t pos, const char * txt)
|
||||
*/
|
||||
void lv_label_cut_text(lv_obj_t * label, uint32_t pos, uint32_t cnt)
|
||||
{
|
||||
LV_ASSERT_OBJ(label, LV_OBJX_NAME);
|
||||
|
||||
lv_label_ext_t * ext = lv_obj_get_ext_attr(label);
|
||||
|
||||
/*Can not append to static text*/
|
||||
@@ -842,14 +1033,13 @@ static bool lv_label_design(lv_obj_t * label, const lv_area_t * mask, lv_design_
|
||||
lv_draw_rect(&bg, mask, style, lv_obj_get_opa_scale(label));
|
||||
}
|
||||
|
||||
/*TEST: draw a background for the label*/
|
||||
// lv_draw_rect(&label->coords, mask, &lv_style_plain_color, LV_OPA_COVER);
|
||||
lv_label_align_t align = lv_label_get_align(label);
|
||||
|
||||
lv_txt_flag_t flag = LV_TXT_FLAG_NONE;
|
||||
if(ext->recolor != 0) flag |= LV_TXT_FLAG_RECOLOR;
|
||||
if(ext->expand != 0) flag |= LV_TXT_FLAG_EXPAND;
|
||||
if(ext->align == LV_LABEL_ALIGN_CENTER) flag |= LV_TXT_FLAG_CENTER;
|
||||
if(ext->align == LV_LABEL_ALIGN_RIGHT) flag |= LV_TXT_FLAG_RIGHT;
|
||||
if(align == LV_LABEL_ALIGN_CENTER) flag |= LV_TXT_FLAG_CENTER;
|
||||
if(align == LV_LABEL_ALIGN_RIGHT) flag |= LV_TXT_FLAG_RIGHT;
|
||||
|
||||
/* In ROLL mode the CENTER and RIGHT are pointless so remove them.
|
||||
* (In addition they will result mis-alignment is this case)*/
|
||||
@@ -872,8 +1062,11 @@ static bool lv_label_design(lv_obj_t * label, const lv_area_t * mask, lv_design_
|
||||
/*Just for compatibility*/
|
||||
lv_draw_label_hint_t * hint = NULL;
|
||||
#endif
|
||||
lv_draw_label(&coords, mask, style, opa_scale, ext->text, flag, &ext->offset,
|
||||
lv_label_get_text_sel_start(label), lv_label_get_text_sel_end(label), hint);
|
||||
lv_draw_label_txt_sel_t sel;
|
||||
|
||||
sel.start = lv_label_get_text_sel_start(label);
|
||||
sel.end = lv_label_get_text_sel_end(label);
|
||||
lv_draw_label(&coords, mask, style, opa_scale, ext->text, flag, &ext->offset, &sel, hint, lv_obj_get_base_dir(label));
|
||||
|
||||
|
||||
if(ext->long_mode == LV_LABEL_LONG_SROLL_CIRC) {
|
||||
@@ -889,16 +1082,14 @@ static bool lv_label_design(lv_obj_t * label, const lv_area_t * mask, lv_design_
|
||||
lv_font_get_glyph_width(style->text.font, ' ', ' ') * LV_LABEL_WAIT_CHAR_COUNT;
|
||||
ofs.y = ext->offset.y;
|
||||
|
||||
lv_draw_label(&coords, mask, style, opa_scale, ext->text, flag, &ofs,
|
||||
lv_label_get_text_sel_start(label), lv_label_get_text_sel_end(label), NULL);
|
||||
lv_draw_label(&coords, mask, style, opa_scale, ext->text, flag, &ofs, &sel, NULL, lv_obj_get_base_dir(label));
|
||||
}
|
||||
|
||||
/*Draw the text again below the original to make an circular effect */
|
||||
if(size.y > lv_obj_get_height(label)) {
|
||||
ofs.x = ext->offset.x;
|
||||
ofs.y = ext->offset.y + size.y + lv_font_get_line_height(style->text.font);
|
||||
lv_draw_label(&coords, mask, style, opa_scale, ext->text, flag, &ofs,
|
||||
lv_label_get_text_sel_start(label), lv_label_get_text_sel_end(label), NULL);
|
||||
lv_draw_label(&coords, mask, style, opa_scale, ext->text, flag, &ofs, &sel, NULL, lv_obj_get_base_dir(label));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -919,6 +1110,7 @@ static lv_res_t lv_label_signal(lv_obj_t * label, lv_signal_t sign, void * param
|
||||
/* Include the ancient signal function */
|
||||
res = ancestor_signal(label, sign, param);
|
||||
if(res != LV_RES_OK) return res;
|
||||
if(sign == LV_SIGNAL_GET_TYPE) return lv_obj_handle_get_type_signal(param, LV_OBJX_NAME);
|
||||
|
||||
lv_label_ext_t * ext = lv_obj_get_ext_attr(label);
|
||||
if(sign == LV_SIGNAL_CLEANUP) {
|
||||
@@ -947,6 +1139,11 @@ static lv_res_t lv_label_signal(lv_obj_t * label, lv_signal_t sign, void * param
|
||||
label->ext_draw_pad = LV_MATH_MAX(label->ext_draw_pad, style->body.padding.top);
|
||||
label->ext_draw_pad = LV_MATH_MAX(label->ext_draw_pad, style->body.padding.bottom);
|
||||
}
|
||||
}
|
||||
else if(sign == LV_SIGNAL_BASE_DIR_CHG) {
|
||||
#if LV_USE_BIDI
|
||||
if(ext->static_txt == 0) lv_label_set_text(label, NULL);
|
||||
#endif
|
||||
} else if(sign == LV_SIGNAL_GET_TYPE) {
|
||||
lv_obj_type_t * buf = param;
|
||||
uint8_t i;
|
||||
@@ -1038,11 +1235,12 @@ static void lv_label_refr_text(lv_obj_t * label)
|
||||
/*In roll inf. mode keep the size but start offset animations*/
|
||||
else if(ext->long_mode == LV_LABEL_LONG_SROLL_CIRC) {
|
||||
#if LV_USE_ANIMATION
|
||||
lv_label_align_t align = lv_label_get_align(label);
|
||||
|
||||
lv_anim_t anim;
|
||||
anim.var = label;
|
||||
anim.repeat = 1;
|
||||
anim.playback = 0;
|
||||
anim.start = 0;
|
||||
anim.act_time = -(((lv_font_get_glyph_width(style->text.font, ' ', ' ') + style->text.letter_space) * 1000) /
|
||||
ext->anim_speed) *
|
||||
LV_LABEL_WAIT_CHAR_COUNT;
|
||||
@@ -1053,7 +1251,14 @@ static void lv_label_refr_text(lv_obj_t * label)
|
||||
|
||||
bool hor_anim = false;
|
||||
if(size.x > lv_obj_get_width(label)) {
|
||||
anim.end = -size.x - lv_font_get_glyph_width(font, ' ', ' ') * LV_LABEL_WAIT_CHAR_COUNT;
|
||||
if(align == LV_LABEL_ALIGN_RIGHT) {
|
||||
anim.end = 0;
|
||||
anim.start = -size.x - lv_font_get_glyph_width(font, ' ', ' ') * LV_LABEL_WAIT_CHAR_COUNT;
|
||||
} else {
|
||||
anim.start = 0;
|
||||
anim.end = -size.x - lv_font_get_glyph_width(font, ' ', ' ') * LV_LABEL_WAIT_CHAR_COUNT;
|
||||
}
|
||||
|
||||
anim.exec_cb = (lv_anim_exec_xcb_t)lv_label_set_offset_x;
|
||||
anim.time = lv_anim_speed_to_time(ext->anim_speed, anim.start, anim.end);
|
||||
lv_anim_create(&anim);
|
||||
@@ -1065,7 +1270,14 @@ static void lv_label_refr_text(lv_obj_t * label)
|
||||
}
|
||||
|
||||
if(size.y > lv_obj_get_height(label) && hor_anim == false) {
|
||||
anim.end = -size.y - (lv_font_get_line_height(font));
|
||||
if(align == LV_LABEL_ALIGN_RIGHT) {
|
||||
anim.end = 0;
|
||||
anim.start = -size.y - (lv_font_get_line_height(font));
|
||||
} else {
|
||||
anim.start = 0;
|
||||
anim.end = -size.y - (lv_font_get_line_height(font));
|
||||
}
|
||||
|
||||
anim.exec_cb = (lv_anim_exec_xcb_t)lv_label_set_offset_y;
|
||||
anim.time = lv_anim_speed_to_time(ext->anim_speed, anim.start, anim.end);
|
||||
lv_anim_create(&anim);
|
||||
|
||||
@@ -21,6 +21,7 @@ extern "C" {
|
||||
|
||||
#if LV_USE_LABEL != 0
|
||||
|
||||
#include <stdarg.h>
|
||||
#include "../lv_core/lv_obj.h"
|
||||
#include "../lv_font/lv_font.h"
|
||||
#include "../lv_font/lv_symbol_def.h"
|
||||
@@ -32,7 +33,11 @@ extern "C" {
|
||||
*********************/
|
||||
#define LV_LABEL_DOT_NUM 3
|
||||
#define LV_LABEL_POS_LAST 0xFFFF
|
||||
#define LV_LABEL_TEXT_SEL_OFF 0xFFFF
|
||||
#define LV_LABEL_TEXT_SEL_OFF LV_DRAW_LABEL_NO_TXT_SEL
|
||||
|
||||
LV_EXPORT_CONST_INT(LV_LABEL_DOT_NUM);
|
||||
LV_EXPORT_CONST_INT(LV_LABEL_POS_LAST);
|
||||
LV_EXPORT_CONST_INT(LV_LABEL_TEXT_SEL_OFF);
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
@@ -55,6 +60,7 @@ enum {
|
||||
LV_LABEL_ALIGN_LEFT, /**< Align text to left */
|
||||
LV_LABEL_ALIGN_CENTER, /**< Align text to center */
|
||||
LV_LABEL_ALIGN_RIGHT, /**< Align text to right */
|
||||
LV_LABEL_ALIGN_AUTO, /**< Use LEFT or RIGHT depending on the direction of the text (LTR/RTL)*/
|
||||
};
|
||||
typedef uint8_t lv_label_align_t;
|
||||
|
||||
@@ -63,12 +69,13 @@ typedef struct
|
||||
{
|
||||
/*Inherited from 'base_obj' so no inherited ext.*/ /*Ext. of ancestor*/
|
||||
/*New data for this type */
|
||||
char * text; /*Text of the label*/
|
||||
char * text; /*Text of the label*/
|
||||
|
||||
union
|
||||
{
|
||||
char * tmp_ptr; /* Pointer to the allocated memory containing the character which are replaced by dots (Handled
|
||||
by the library)*/
|
||||
char tmp[sizeof(char *)]; /* Directly store the characters if <=4 characters */
|
||||
char tmp[LV_LABEL_DOT_NUM + 1]; /* Directly store the characters if <=4 characters */
|
||||
} dot;
|
||||
uint16_t dot_end; /*The text end position in dot mode (Handled by the library)*/
|
||||
lv_point_t offset; /*Text draw position offset*/
|
||||
@@ -124,6 +131,13 @@ lv_obj_t * lv_label_create(lv_obj_t * par, const lv_obj_t * copy);
|
||||
*/
|
||||
void lv_label_set_text(lv_obj_t * label, const char * text);
|
||||
|
||||
/**
|
||||
* Set a new formatted text for a label. Memory will be allocated to store the text by the label.
|
||||
* @param label pointer to a label object
|
||||
* @param fmt `printf`-like format
|
||||
*/
|
||||
void lv_label_set_text_fmt(lv_obj_t * label, const char * fmt, ...);
|
||||
|
||||
/**
|
||||
* Set a new text for a label from a character array. The array don't has to be '\0' terminated.
|
||||
* Memory will be allocated to store the array by the label.
|
||||
|
||||
@@ -9,12 +9,15 @@
|
||||
#include "lv_led.h"
|
||||
#if LV_USE_LED != 0
|
||||
|
||||
#include "../lv_core/lv_debug.h"
|
||||
#include "../lv_themes/lv_theme.h"
|
||||
#include "../lv_draw/lv_draw.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
#define LV_OBJX_NAME "lv_led"
|
||||
|
||||
#define LV_LED_WIDTH_DEF (LV_DPI / 3)
|
||||
#define LV_LED_HEIGHT_DEF (LV_DPI / 3)
|
||||
#define LV_LED_BRIGHT_OFF 100
|
||||
@@ -56,7 +59,7 @@ lv_obj_t * lv_led_create(lv_obj_t * par, const lv_obj_t * copy)
|
||||
|
||||
/*Create the ancestor basic object*/
|
||||
lv_obj_t * new_led = lv_obj_create(par, copy);
|
||||
lv_mem_assert(new_led);
|
||||
LV_ASSERT_MEM(new_led);
|
||||
if(new_led == NULL) return NULL;
|
||||
|
||||
if(ancestor_signal == NULL) ancestor_signal = lv_obj_get_signal_cb(new_led);
|
||||
@@ -64,7 +67,7 @@ lv_obj_t * lv_led_create(lv_obj_t * par, const lv_obj_t * copy)
|
||||
|
||||
/*Allocate the object type specific extended data*/
|
||||
lv_led_ext_t * ext = lv_obj_allocate_ext_attr(new_led, sizeof(lv_led_ext_t));
|
||||
lv_mem_assert(ext);
|
||||
LV_ASSERT_MEM(ext);
|
||||
if(ext == NULL) return NULL;
|
||||
|
||||
ext->bright = LV_LED_BRIGHT_ON;
|
||||
@@ -109,6 +112,8 @@ lv_obj_t * lv_led_create(lv_obj_t * par, const lv_obj_t * copy)
|
||||
*/
|
||||
void lv_led_set_bright(lv_obj_t * led, uint8_t bright)
|
||||
{
|
||||
LV_ASSERT_OBJ(led, LV_OBJX_NAME);
|
||||
|
||||
/*Set the brightness*/
|
||||
lv_led_ext_t * ext = lv_obj_get_ext_attr(led);
|
||||
if(ext->bright == bright) return;
|
||||
@@ -125,6 +130,8 @@ void lv_led_set_bright(lv_obj_t * led, uint8_t bright)
|
||||
*/
|
||||
void lv_led_on(lv_obj_t * led)
|
||||
{
|
||||
LV_ASSERT_OBJ(led, LV_OBJX_NAME);
|
||||
|
||||
lv_led_set_bright(led, LV_LED_BRIGHT_ON);
|
||||
}
|
||||
|
||||
@@ -134,6 +141,8 @@ void lv_led_on(lv_obj_t * led)
|
||||
*/
|
||||
void lv_led_off(lv_obj_t * led)
|
||||
{
|
||||
LV_ASSERT_OBJ(led, LV_OBJX_NAME);
|
||||
|
||||
lv_led_set_bright(led, LV_LED_BRIGHT_OFF);
|
||||
}
|
||||
|
||||
@@ -143,6 +152,8 @@ void lv_led_off(lv_obj_t * led)
|
||||
*/
|
||||
void lv_led_toggle(lv_obj_t * led)
|
||||
{
|
||||
LV_ASSERT_OBJ(led, LV_OBJX_NAME);
|
||||
|
||||
uint8_t bright = lv_led_get_bright(led);
|
||||
if(bright > (LV_LED_BRIGHT_OFF + LV_LED_BRIGHT_ON) >> 1)
|
||||
lv_led_off(led);
|
||||
@@ -161,6 +172,8 @@ void lv_led_toggle(lv_obj_t * led)
|
||||
*/
|
||||
uint8_t lv_led_get_bright(const lv_obj_t * led)
|
||||
{
|
||||
LV_ASSERT_OBJ(led, LV_OBJX_NAME);
|
||||
|
||||
lv_led_ext_t * ext = lv_obj_get_ext_attr(led);
|
||||
return ext->bright;
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#include "lv_line.h"
|
||||
|
||||
#if LV_USE_LINE != 0
|
||||
#include "../lv_core/lv_debug.h"
|
||||
#include "../lv_draw/lv_draw.h"
|
||||
#include "../lv_misc/lv_math.h"
|
||||
#include <stdbool.h>
|
||||
@@ -18,6 +19,7 @@
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
#define LV_OBJX_NAME "lv_line"
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
@@ -53,14 +55,14 @@ lv_obj_t * lv_line_create(lv_obj_t * par, const lv_obj_t * copy)
|
||||
|
||||
/*Create a basic object*/
|
||||
lv_obj_t * new_line = lv_obj_create(par, copy);
|
||||
lv_mem_assert(new_line);
|
||||
LV_ASSERT_MEM(new_line);
|
||||
if(new_line == NULL) return NULL;
|
||||
|
||||
if(ancestor_signal == NULL) ancestor_signal = lv_obj_get_signal_cb(new_line);
|
||||
|
||||
/*Extend the basic object to line object*/
|
||||
lv_line_ext_t * ext = lv_obj_allocate_ext_attr(new_line, sizeof(lv_line_ext_t));
|
||||
lv_mem_assert(ext);
|
||||
LV_ASSERT_MEM(ext);
|
||||
if(ext == NULL) return NULL;
|
||||
|
||||
ext->point_num = 0;
|
||||
@@ -107,6 +109,8 @@ lv_obj_t * lv_line_create(lv_obj_t * par, const lv_obj_t * copy)
|
||||
*/
|
||||
void lv_line_set_points(lv_obj_t * line, const lv_point_t point_a[], uint16_t point_num)
|
||||
{
|
||||
LV_ASSERT_OBJ(line, LV_OBJX_NAME);
|
||||
|
||||
lv_line_ext_t * ext = lv_obj_get_ext_attr(line);
|
||||
ext->point_array = point_a;
|
||||
ext->point_num = point_num;
|
||||
@@ -135,6 +139,8 @@ void lv_line_set_points(lv_obj_t * line, const lv_point_t point_a[], uint16_t po
|
||||
*/
|
||||
void lv_line_set_auto_size(lv_obj_t * line, bool en)
|
||||
{
|
||||
LV_ASSERT_OBJ(line, LV_OBJX_NAME);
|
||||
|
||||
lv_line_ext_t * ext = lv_obj_get_ext_attr(line);
|
||||
if(ext->auto_size == en) return;
|
||||
|
||||
@@ -153,6 +159,8 @@ void lv_line_set_auto_size(lv_obj_t * line, bool en)
|
||||
*/
|
||||
void lv_line_set_y_invert(lv_obj_t * line, bool en)
|
||||
{
|
||||
LV_ASSERT_OBJ(line, LV_OBJX_NAME);
|
||||
|
||||
lv_line_ext_t * ext = lv_obj_get_ext_attr(line);
|
||||
if(ext->y_inv == en) return;
|
||||
|
||||
@@ -172,6 +180,8 @@ void lv_line_set_y_invert(lv_obj_t * line, bool en)
|
||||
*/
|
||||
bool lv_line_get_auto_size(const lv_obj_t * line)
|
||||
{
|
||||
LV_ASSERT_OBJ(line, LV_OBJX_NAME);
|
||||
|
||||
lv_line_ext_t * ext = lv_obj_get_ext_attr(line);
|
||||
|
||||
return ext->auto_size == 0 ? false : true;
|
||||
@@ -184,6 +194,8 @@ bool lv_line_get_auto_size(const lv_obj_t * line)
|
||||
*/
|
||||
bool lv_line_get_y_invert(const lv_obj_t * line)
|
||||
{
|
||||
LV_ASSERT_OBJ(line, LV_OBJX_NAME);
|
||||
|
||||
lv_line_ext_t * ext = lv_obj_get_ext_attr(line);
|
||||
|
||||
return ext->y_inv == 0 ? false : true;
|
||||
@@ -225,11 +237,13 @@ static bool lv_line_design(lv_obj_t * line, const lv_area_t * mask, lv_design_mo
|
||||
uint16_t i;
|
||||
|
||||
lv_style_t circle_style_tmp; /*If rounded...*/
|
||||
lv_style_copy(&circle_style_tmp, style);
|
||||
circle_style_tmp.body.radius = LV_RADIUS_CIRCLE;
|
||||
circle_style_tmp.body.main_color = style->line.color;
|
||||
circle_style_tmp.body.grad_color = style->line.color;
|
||||
circle_style_tmp.body.opa = style->line.opa;
|
||||
if(style->line.rounded) {
|
||||
lv_style_copy(&circle_style_tmp, style);
|
||||
circle_style_tmp.body.radius = LV_RADIUS_CIRCLE;
|
||||
circle_style_tmp.body.main_color = style->line.color;
|
||||
circle_style_tmp.body.grad_color = style->line.color;
|
||||
circle_style_tmp.body.opa = style->line.opa;
|
||||
}
|
||||
lv_area_t circle_area;
|
||||
|
||||
/*Read all points and draw the lines*/
|
||||
@@ -282,15 +296,9 @@ static lv_res_t lv_line_signal(lv_obj_t * line, lv_signal_t sign, void * param)
|
||||
/* Include the ancient signal function */
|
||||
res = ancestor_signal(line, sign, param);
|
||||
if(res != LV_RES_OK) return res;
|
||||
if(sign == LV_SIGNAL_GET_TYPE) return lv_obj_handle_get_type_signal(param, LV_OBJX_NAME);
|
||||
|
||||
if(sign == LV_SIGNAL_GET_TYPE) {
|
||||
lv_obj_type_t * buf = param;
|
||||
uint8_t i;
|
||||
for(i = 0; i < LV_MAX_ANCESTOR_NUM - 1; i++) { /*Find the last set data*/
|
||||
if(buf->type[i] == NULL) break;
|
||||
}
|
||||
buf->type[i] = "lv_line";
|
||||
} else if(sign == LV_SIGNAL_REFR_EXT_DRAW_PAD) {
|
||||
if(sign == LV_SIGNAL_REFR_EXT_DRAW_PAD) {
|
||||
const lv_style_t * style = lv_line_get_style(line, LV_LINE_STYLE_MAIN);
|
||||
if(line->ext_draw_pad < style->line.width) line->ext_draw_pad = style->line.width;
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#include "lv_list.h"
|
||||
#if LV_USE_LIST != 0
|
||||
|
||||
#include "../lv_core/lv_debug.h"
|
||||
#include "../lv_core/lv_group.h"
|
||||
#include "../lv_themes/lv_theme.h"
|
||||
#include "../lv_misc/lv_anim.h"
|
||||
@@ -17,6 +18,8 @@
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
#define LV_OBJX_NAME "lv_list"
|
||||
|
||||
#define LV_LIST_LAYOUT_DEF LV_LAYOUT_COL_M
|
||||
|
||||
#if LV_USE_ANIMATION == 0
|
||||
@@ -69,13 +72,13 @@ lv_obj_t * lv_list_create(lv_obj_t * par, const lv_obj_t * copy)
|
||||
|
||||
/*Create the ancestor basic object*/
|
||||
lv_obj_t * new_list = lv_page_create(par, copy);
|
||||
lv_mem_assert(new_list);
|
||||
LV_ASSERT_MEM(new_list);
|
||||
if(new_list == NULL) return NULL;
|
||||
|
||||
if(ancestor_page_signal == NULL) ancestor_page_signal = lv_obj_get_signal_cb(new_list);
|
||||
|
||||
lv_list_ext_t * ext = lv_obj_allocate_ext_attr(new_list, sizeof(lv_list_ext_t));
|
||||
lv_mem_assert(ext);
|
||||
LV_ASSERT_MEM(ext);
|
||||
if(ext == NULL) return NULL;
|
||||
|
||||
ext->style_img = NULL;
|
||||
@@ -149,13 +152,15 @@ lv_obj_t * lv_list_create(lv_obj_t * par, const lv_obj_t * copy)
|
||||
|
||||
/**
|
||||
* Delete all children of the scrl object, without deleting scrl child.
|
||||
* @param obj pointer to an object
|
||||
* @param list pointer to an object
|
||||
*/
|
||||
void lv_list_clean(lv_obj_t * obj)
|
||||
void lv_list_clean(lv_obj_t * list)
|
||||
{
|
||||
lv_obj_t * scrl = lv_page_get_scrl(obj);
|
||||
LV_ASSERT_OBJ(list, LV_OBJX_NAME);
|
||||
|
||||
lv_obj_t * scrl = lv_page_get_scrl(list);
|
||||
lv_obj_clean(scrl);
|
||||
lv_list_ext_t * ext = lv_obj_get_ext_attr(obj);
|
||||
lv_list_ext_t * ext = lv_obj_get_ext_attr(list);
|
||||
ext->size = 0;
|
||||
}
|
||||
|
||||
@@ -172,6 +177,8 @@ void lv_list_clean(lv_obj_t * obj)
|
||||
*/
|
||||
lv_obj_t * lv_list_add_btn(lv_obj_t * list, const void * img_src, const char * txt)
|
||||
{
|
||||
LV_ASSERT_OBJ(list, LV_OBJX_NAME);
|
||||
|
||||
lv_list_ext_t * ext = lv_obj_get_ext_attr(list);
|
||||
ext->size++;
|
||||
/*Create a list element with the image an the text*/
|
||||
@@ -211,7 +218,8 @@ lv_obj_t * lv_list_add_btn(lv_obj_t * list, const void * img_src, const char * t
|
||||
lv_label_set_text(label, txt);
|
||||
lv_obj_set_click(label, false);
|
||||
lv_label_set_long_mode(label, LV_LABEL_LONG_SROLL_CIRC);
|
||||
lv_obj_set_width(label, liste->coords.x2 - label->coords.x1 - btn_hor_pad);
|
||||
if(lv_obj_get_base_dir(liste) == LV_BIDI_DIR_RTL) lv_obj_set_width(label, label->coords.x2 - liste->coords.x1 - btn_hor_pad);
|
||||
else lv_obj_set_width(label, liste->coords.x2 - label->coords.x1 - btn_hor_pad);
|
||||
if(label_signal == NULL) label_signal = lv_obj_get_signal_cb(label);
|
||||
}
|
||||
#if LV_USE_GROUP
|
||||
@@ -237,6 +245,8 @@ lv_obj_t * lv_list_add_btn(lv_obj_t * list, const void * img_src, const char * t
|
||||
*/
|
||||
bool lv_list_remove(const lv_obj_t * list, uint16_t index)
|
||||
{
|
||||
LV_ASSERT_OBJ(list, LV_OBJX_NAME);
|
||||
|
||||
lv_list_ext_t * ext = lv_obj_get_ext_attr(list);
|
||||
if(index >= ext->size) return false;
|
||||
uint16_t count = 0;
|
||||
@@ -264,6 +274,8 @@ bool lv_list_remove(const lv_obj_t * list, uint16_t index)
|
||||
*/
|
||||
void lv_list_set_single_mode(lv_obj_t * list, bool mode)
|
||||
{
|
||||
LV_ASSERT_OBJ(list, LV_OBJX_NAME);
|
||||
|
||||
lv_list_ext_t * ext = lv_obj_get_ext_attr(list);
|
||||
|
||||
ext->single_mode = mode;
|
||||
@@ -279,6 +291,9 @@ void lv_list_set_single_mode(lv_obj_t * list, bool mode)
|
||||
*/
|
||||
void lv_list_set_btn_selected(lv_obj_t * list, lv_obj_t * btn)
|
||||
{
|
||||
LV_ASSERT_OBJ(list, LV_OBJX_NAME);
|
||||
if(btn) LV_ASSERT_OBJ(list, "lv_btn");
|
||||
|
||||
lv_list_ext_t * ext = lv_obj_get_ext_attr(list);
|
||||
|
||||
if(ext->selected_btn) {
|
||||
@@ -318,6 +333,8 @@ void lv_list_set_btn_selected(lv_obj_t * list, lv_obj_t * btn)
|
||||
*/
|
||||
void lv_list_set_style(lv_obj_t * list, lv_list_style_t type, const lv_style_t * style)
|
||||
{
|
||||
LV_ASSERT_OBJ(list, LV_OBJX_NAME);
|
||||
|
||||
lv_list_ext_t * ext = lv_obj_get_ext_attr(list);
|
||||
lv_btn_style_t btn_style_refr = LV_BTN_STYLE_REL;
|
||||
lv_obj_t * btn;
|
||||
@@ -363,6 +380,38 @@ void lv_list_set_style(lv_obj_t * list, lv_list_style_t type, const lv_style_t *
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set layout of a list
|
||||
* @param list pointer to a list object
|
||||
* @param layout which layout should be used
|
||||
*/
|
||||
void lv_list_set_layout(lv_obj_t * list, lv_layout_t layout)
|
||||
{
|
||||
LV_ASSERT_OBJ(list, LV_OBJX_NAME);
|
||||
|
||||
/* Update list layout if necessary */
|
||||
if (layout == lv_list_get_layout(list)) return;
|
||||
|
||||
/* Get the first button on the list */
|
||||
lv_obj_t * btn = lv_list_get_prev_btn(list, NULL);
|
||||
|
||||
/* Visit all buttons on the list and update their layout */
|
||||
while(btn != NULL) {
|
||||
/*If a column layout set the buttons' width to list width*/
|
||||
if(layout == LV_LAYOUT_COL_M || layout == LV_LAYOUT_COL_L || layout == LV_LAYOUT_COL_R) {
|
||||
lv_btn_set_fit2(list, LV_FIT_FLOOD, LV_FIT_TIGHT);
|
||||
}
|
||||
/*If a row layout set the buttons' width according to the content*/
|
||||
else if (layout == LV_LAYOUT_ROW_M || layout == LV_LAYOUT_ROW_T || layout == LV_LAYOUT_ROW_B) {
|
||||
lv_btn_set_fit(list, LV_FIT_TIGHT);
|
||||
}
|
||||
|
||||
btn = lv_list_get_prev_btn(list, btn);
|
||||
}
|
||||
|
||||
lv_page_set_scrl_layout(list, layout);
|
||||
}
|
||||
|
||||
/*=====================
|
||||
* Getter functions
|
||||
*====================*/
|
||||
@@ -373,6 +422,8 @@ void lv_list_set_style(lv_obj_t * list, lv_list_style_t type, const lv_style_t *
|
||||
*/
|
||||
bool lv_list_get_single_mode(lv_obj_t * list)
|
||||
{
|
||||
LV_ASSERT_OBJ(list, LV_OBJX_NAME);
|
||||
|
||||
lv_list_ext_t * ext = lv_obj_get_ext_attr(list);
|
||||
|
||||
return (ext->single_mode);
|
||||
@@ -385,6 +436,8 @@ bool lv_list_get_single_mode(lv_obj_t * list)
|
||||
*/
|
||||
const char * lv_list_get_btn_text(const lv_obj_t * btn)
|
||||
{
|
||||
LV_ASSERT_OBJ(btn, "lv_btn");
|
||||
|
||||
lv_obj_t * label = lv_list_get_btn_label(btn);
|
||||
if(label == NULL) return "";
|
||||
return lv_label_get_text(label);
|
||||
@@ -397,6 +450,8 @@ const char * lv_list_get_btn_text(const lv_obj_t * btn)
|
||||
*/
|
||||
lv_obj_t * lv_list_get_btn_label(const lv_obj_t * btn)
|
||||
{
|
||||
LV_ASSERT_OBJ(btn, "lv_btn");
|
||||
|
||||
lv_obj_t * label = lv_obj_get_child(btn, NULL);
|
||||
if(label == NULL) return NULL;
|
||||
|
||||
@@ -415,6 +470,8 @@ lv_obj_t * lv_list_get_btn_label(const lv_obj_t * btn)
|
||||
*/
|
||||
lv_obj_t * lv_list_get_btn_img(const lv_obj_t * btn)
|
||||
{
|
||||
LV_ASSERT_OBJ(btn, "lv_btn");
|
||||
|
||||
#if LV_USE_IMG != 0
|
||||
lv_obj_t * img = lv_obj_get_child(btn, NULL);
|
||||
if(img == NULL) return NULL;
|
||||
@@ -438,6 +495,8 @@ lv_obj_t * lv_list_get_btn_img(const lv_obj_t * btn)
|
||||
*/
|
||||
lv_obj_t * lv_list_get_prev_btn(const lv_obj_t * list, lv_obj_t * prev_btn)
|
||||
{
|
||||
LV_ASSERT_OBJ(list, LV_OBJX_NAME);
|
||||
|
||||
/* Not a good practice but user can add/create objects to the lists manually.
|
||||
* When getting the next button try to be sure that it is at least a button */
|
||||
|
||||
@@ -463,6 +522,8 @@ lv_obj_t * lv_list_get_prev_btn(const lv_obj_t * list, lv_obj_t * prev_btn)
|
||||
*/
|
||||
lv_obj_t * lv_list_get_next_btn(const lv_obj_t * list, lv_obj_t * prev_btn)
|
||||
{
|
||||
LV_ASSERT_OBJ(list, LV_OBJX_NAME);
|
||||
|
||||
/* Not a good practice but user can add/create objects to the lists manually.
|
||||
* When getting the next button try to be sure that it is at least a button */
|
||||
|
||||
@@ -488,6 +549,9 @@ lv_obj_t * lv_list_get_next_btn(const lv_obj_t * list, lv_obj_t * prev_btn)
|
||||
*/
|
||||
int32_t lv_list_get_btn_index(const lv_obj_t * list, const lv_obj_t * btn)
|
||||
{
|
||||
LV_ASSERT_OBJ(list, LV_OBJX_NAME);
|
||||
LV_ASSERT_OBJ(btn, "lv_btn");
|
||||
|
||||
int index = 0;
|
||||
if(list == NULL) {
|
||||
/* no list provided, assuming btn is part of a list */
|
||||
@@ -511,6 +575,8 @@ int32_t lv_list_get_btn_index(const lv_obj_t * list, const lv_obj_t * btn)
|
||||
*/
|
||||
uint16_t lv_list_get_size(const lv_obj_t * list)
|
||||
{
|
||||
LV_ASSERT_OBJ(list, LV_OBJX_NAME);
|
||||
|
||||
lv_list_ext_t * ext = lv_obj_get_ext_attr(list);
|
||||
return ext->size;
|
||||
}
|
||||
@@ -523,20 +589,35 @@ uint16_t lv_list_get_size(const lv_obj_t * list)
|
||||
*/
|
||||
lv_obj_t * lv_list_get_btn_selected(const lv_obj_t * list)
|
||||
{
|
||||
LV_ASSERT_OBJ(list, LV_OBJX_NAME);
|
||||
|
||||
lv_list_ext_t * ext = lv_obj_get_ext_attr(list);
|
||||
return ext->selected_btn;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Get layout of a list
|
||||
* @param list pointer to a list object
|
||||
* @return layout of the list object
|
||||
*/
|
||||
lv_layout_t lv_list_get_layout(lv_obj_t * list)
|
||||
{
|
||||
LV_ASSERT_OBJ(list, LV_OBJX_NAME);
|
||||
|
||||
return lv_page_get_scrl_layout(list);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a style of a list
|
||||
* @param list pointer to a list object
|
||||
* @param type which style should be get
|
||||
* @return style pointer to a style
|
||||
* */
|
||||
*/
|
||||
const lv_style_t * lv_list_get_style(const lv_obj_t * list, lv_list_style_t type)
|
||||
{
|
||||
LV_ASSERT_OBJ(list, LV_OBJX_NAME);
|
||||
|
||||
const lv_style_t * style = NULL;
|
||||
lv_list_ext_t * ext = lv_obj_get_ext_attr(list);
|
||||
|
||||
@@ -555,6 +636,7 @@ const lv_style_t * lv_list_get_style(const lv_obj_t * list, lv_list_style_t type
|
||||
|
||||
return style;
|
||||
}
|
||||
|
||||
/*=====================
|
||||
* Other functions
|
||||
*====================*/
|
||||
@@ -565,6 +647,8 @@ const lv_style_t * lv_list_get_style(const lv_obj_t * list, lv_list_style_t type
|
||||
*/
|
||||
void lv_list_up(const lv_obj_t * list)
|
||||
{
|
||||
LV_ASSERT_OBJ(list, LV_OBJX_NAME);
|
||||
|
||||
/*Search the first list element which 'y' coordinate is below the parent
|
||||
* and position the list to show this element on the bottom*/
|
||||
lv_obj_t * scrl = lv_page_get_scrl(list);
|
||||
@@ -610,6 +694,8 @@ void lv_list_up(const lv_obj_t * list)
|
||||
*/
|
||||
void lv_list_down(const lv_obj_t * list)
|
||||
{
|
||||
LV_ASSERT_OBJ(list, LV_OBJX_NAME);
|
||||
|
||||
/*Search the first list element which 'y' coordinate is above the parent
|
||||
* and position the list to show this element on the top*/
|
||||
lv_obj_t * scrl = lv_page_get_scrl(list);
|
||||
@@ -651,6 +737,7 @@ void lv_list_down(const lv_obj_t * list)
|
||||
*/
|
||||
void lv_list_focus(const lv_obj_t * btn, lv_anim_enable_t anim)
|
||||
{
|
||||
LV_ASSERT_OBJ(btn, "");
|
||||
|
||||
#if LV_USE_ANIMATION == 0
|
||||
anim = false;
|
||||
@@ -679,6 +766,7 @@ static lv_res_t lv_list_signal(lv_obj_t * list, lv_signal_t sign, void * param)
|
||||
/* Include the ancient signal function */
|
||||
res = ancestor_page_signal(list, sign, param);
|
||||
if(res != LV_RES_OK) return res;
|
||||
if(sign == LV_SIGNAL_GET_TYPE) return lv_obj_handle_get_type_signal(param, LV_OBJX_NAME);
|
||||
|
||||
if(sign == LV_SIGNAL_RELEASED || sign == LV_SIGNAL_PRESSED || sign == LV_SIGNAL_PRESSING ||
|
||||
sign == LV_SIGNAL_LONG_PRESS || sign == LV_SIGNAL_LONG_PRESS_REP) {
|
||||
@@ -808,13 +896,6 @@ static lv_res_t lv_list_signal(lv_obj_t * list, lv_signal_t sign, void * param)
|
||||
}
|
||||
}
|
||||
#endif
|
||||
} else if(sign == LV_SIGNAL_GET_TYPE) {
|
||||
lv_obj_type_t * buf = param;
|
||||
uint8_t i;
|
||||
for(i = 0; i < LV_MAX_ANCESTOR_NUM - 1; i++) { /*Find the last set data*/
|
||||
if(buf->type[i] == NULL) break;
|
||||
}
|
||||
buf->type[i] = "lv_list";
|
||||
}
|
||||
return res;
|
||||
}
|
||||
@@ -833,6 +914,7 @@ static lv_res_t lv_list_btn_signal(lv_obj_t * btn, lv_signal_t sign, void * para
|
||||
/* Include the ancient signal function */
|
||||
res = ancestor_btn_signal(btn, sign, param);
|
||||
if(res != LV_RES_OK) return res;
|
||||
if(sign == LV_SIGNAL_GET_TYPE) return lv_obj_handle_get_type_signal(param, "");
|
||||
|
||||
if(sign == LV_SIGNAL_RELEASED) {
|
||||
lv_obj_t * list = lv_obj_get_parent(lv_obj_get_parent(btn));
|
||||
|
||||
@@ -95,9 +95,9 @@ lv_obj_t * lv_list_create(lv_obj_t * par, const lv_obj_t * copy);
|
||||
|
||||
/**
|
||||
* Delete all children of the scrl object, without deleting scrl child.
|
||||
* @param obj pointer to an object
|
||||
* @param list pointer to an object
|
||||
*/
|
||||
void lv_list_clean(lv_obj_t * obj);
|
||||
void lv_list_clean(lv_obj_t * list);
|
||||
|
||||
/*======================
|
||||
* Add/remove functions
|
||||
@@ -192,6 +192,13 @@ static inline void lv_list_set_anim_time(lv_obj_t * list, uint16_t anim_time)
|
||||
*/
|
||||
void lv_list_set_style(lv_obj_t * list, lv_list_style_t type, const lv_style_t * style);
|
||||
|
||||
/**
|
||||
* Set layout of a list
|
||||
* @param list pointer to a list object
|
||||
* @param layout which layout should be used
|
||||
*/
|
||||
void lv_list_set_layout(lv_obj_t * list, lv_layout_t layout);
|
||||
|
||||
/*=====================
|
||||
* Getter functions
|
||||
*====================*/
|
||||
@@ -262,6 +269,13 @@ uint16_t lv_list_get_size(const lv_obj_t * list);
|
||||
lv_obj_t * lv_list_get_btn_selected(const lv_obj_t * list);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Get layout of a list
|
||||
* @param list pointer to a list object
|
||||
* @return layout of the list object
|
||||
*/
|
||||
lv_layout_t lv_list_get_layout(lv_obj_t * list);
|
||||
|
||||
/**
|
||||
* Get the scroll bar mode of a list
|
||||
* @param list pointer to a list object
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#include "lv_lmeter.h"
|
||||
#if LV_USE_LMETER != 0
|
||||
|
||||
#include "../lv_core/lv_debug.h"
|
||||
#include "../lv_draw/lv_draw.h"
|
||||
#include "../lv_themes/lv_theme.h"
|
||||
#include "../lv_core/lv_group.h"
|
||||
@@ -17,6 +18,8 @@
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
#define LV_OBJX_NAME "lv_lmeter"
|
||||
|
||||
#define LV_LMETER_LINE_UPSCALE 5 /*2^x upscale of line to make rounding*/
|
||||
#define LV_LMETER_LINE_UPSCALE_MASK ((1 << LV_LMETER_LINE_UPSCALE) - 1)
|
||||
|
||||
@@ -57,14 +60,14 @@ lv_obj_t * lv_lmeter_create(lv_obj_t * par, const lv_obj_t * copy)
|
||||
|
||||
/*Create the ancestor of line meter*/
|
||||
lv_obj_t * new_lmeter = lv_obj_create(par, copy);
|
||||
lv_mem_assert(new_lmeter);
|
||||
LV_ASSERT_MEM(new_lmeter);
|
||||
if(new_lmeter == NULL) return NULL;
|
||||
|
||||
if(ancestor_signal == NULL) ancestor_signal = lv_obj_get_signal_cb(new_lmeter);
|
||||
|
||||
/*Allocate the line meter type specific extended data*/
|
||||
lv_lmeter_ext_t * ext = lv_obj_allocate_ext_attr(new_lmeter, sizeof(lv_lmeter_ext_t));
|
||||
lv_mem_assert(ext);
|
||||
LV_ASSERT_MEM(ext);
|
||||
if(ext == NULL) return NULL;
|
||||
|
||||
/*Initialize the allocated 'ext' */
|
||||
@@ -73,6 +76,7 @@ lv_obj_t * lv_lmeter_create(lv_obj_t * par, const lv_obj_t * copy)
|
||||
ext->cur_value = 0;
|
||||
ext->line_cnt = 21; /*Odd scale number looks better*/
|
||||
ext->scale_angle = 240; /*(scale_num - 1) * N looks better */
|
||||
ext->angle_ofs = 0;
|
||||
|
||||
/*The signal and design functions are not copied so set them here*/
|
||||
lv_obj_set_signal_cb(new_lmeter, lv_lmeter_signal);
|
||||
@@ -119,6 +123,8 @@ lv_obj_t * lv_lmeter_create(lv_obj_t * par, const lv_obj_t * copy)
|
||||
*/
|
||||
void lv_lmeter_set_value(lv_obj_t * lmeter, int16_t value)
|
||||
{
|
||||
LV_ASSERT_OBJ(lmeter, LV_OBJX_NAME);
|
||||
|
||||
lv_lmeter_ext_t * ext = lv_obj_get_ext_attr(lmeter);
|
||||
if(ext->cur_value == value) return;
|
||||
|
||||
@@ -135,6 +141,8 @@ void lv_lmeter_set_value(lv_obj_t * lmeter, int16_t value)
|
||||
*/
|
||||
void lv_lmeter_set_range(lv_obj_t * lmeter, int16_t min, int16_t max)
|
||||
{
|
||||
LV_ASSERT_OBJ(lmeter, LV_OBJX_NAME);
|
||||
|
||||
lv_lmeter_ext_t * ext = lv_obj_get_ext_attr(lmeter);
|
||||
if(ext->min_value == min && ext->max_value == max) return;
|
||||
|
||||
@@ -159,6 +167,8 @@ void lv_lmeter_set_range(lv_obj_t * lmeter, int16_t min, int16_t max)
|
||||
*/
|
||||
void lv_lmeter_set_scale(lv_obj_t * lmeter, uint16_t angle, uint8_t line_cnt)
|
||||
{
|
||||
LV_ASSERT_OBJ(lmeter, LV_OBJX_NAME);
|
||||
|
||||
lv_lmeter_ext_t * ext = lv_obj_get_ext_attr(lmeter);
|
||||
if(ext->scale_angle == angle && ext->line_cnt == line_cnt) return;
|
||||
|
||||
@@ -168,6 +178,21 @@ void lv_lmeter_set_scale(lv_obj_t * lmeter, uint16_t angle, uint8_t line_cnt)
|
||||
lv_obj_invalidate(lmeter);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the set an offset for the line meter's angles to rotate it.
|
||||
* @param lmeter pointer to a line meter object
|
||||
* @param angle angle where the meter will be facing (with its center)
|
||||
*/
|
||||
void lv_lmeter_set_angle_offset(lv_obj_t * lmeter, uint16_t angle)
|
||||
{
|
||||
lv_lmeter_ext_t * ext = lv_obj_get_ext_attr(lmeter);
|
||||
if(ext->angle_ofs == angle) return;
|
||||
|
||||
ext->angle_ofs = angle;
|
||||
|
||||
lv_obj_invalidate(lmeter);
|
||||
}
|
||||
|
||||
/*=====================
|
||||
* Getter functions
|
||||
*====================*/
|
||||
@@ -179,6 +204,8 @@ void lv_lmeter_set_scale(lv_obj_t * lmeter, uint16_t angle, uint8_t line_cnt)
|
||||
*/
|
||||
int16_t lv_lmeter_get_value(const lv_obj_t * lmeter)
|
||||
{
|
||||
LV_ASSERT_OBJ(lmeter, LV_OBJX_NAME);
|
||||
|
||||
lv_lmeter_ext_t * ext = lv_obj_get_ext_attr(lmeter);
|
||||
return ext->cur_value;
|
||||
}
|
||||
@@ -190,6 +217,8 @@ int16_t lv_lmeter_get_value(const lv_obj_t * lmeter)
|
||||
*/
|
||||
int16_t lv_lmeter_get_min_value(const lv_obj_t * lmeter)
|
||||
{
|
||||
LV_ASSERT_OBJ(lmeter, LV_OBJX_NAME);
|
||||
|
||||
lv_lmeter_ext_t * ext = lv_obj_get_ext_attr(lmeter);
|
||||
return ext->min_value;
|
||||
}
|
||||
@@ -201,6 +230,8 @@ int16_t lv_lmeter_get_min_value(const lv_obj_t * lmeter)
|
||||
*/
|
||||
int16_t lv_lmeter_get_max_value(const lv_obj_t * lmeter)
|
||||
{
|
||||
LV_ASSERT_OBJ(lmeter, LV_OBJX_NAME);
|
||||
|
||||
lv_lmeter_ext_t * ext = lv_obj_get_ext_attr(lmeter);
|
||||
return ext->max_value;
|
||||
}
|
||||
@@ -212,6 +243,8 @@ int16_t lv_lmeter_get_max_value(const lv_obj_t * lmeter)
|
||||
*/
|
||||
uint8_t lv_lmeter_get_line_count(const lv_obj_t * lmeter)
|
||||
{
|
||||
LV_ASSERT_OBJ(lmeter, LV_OBJX_NAME);
|
||||
|
||||
lv_lmeter_ext_t * ext = lv_obj_get_ext_attr(lmeter);
|
||||
return ext->line_cnt;
|
||||
}
|
||||
@@ -219,14 +252,27 @@ uint8_t lv_lmeter_get_line_count(const lv_obj_t * lmeter)
|
||||
/**
|
||||
* Get the scale angle of a line meter
|
||||
* @param lmeter pointer to a line meter object
|
||||
* @return angle of the scale
|
||||
* @return angle_ofs of the scale
|
||||
*/
|
||||
uint16_t lv_lmeter_get_scale_angle(const lv_obj_t * lmeter)
|
||||
{
|
||||
LV_ASSERT_OBJ(lmeter, LV_OBJX_NAME);
|
||||
|
||||
lv_lmeter_ext_t * ext = lv_obj_get_ext_attr(lmeter);
|
||||
return ext->scale_angle;
|
||||
}
|
||||
|
||||
/**
|
||||
* get the set an offset for the line meter.
|
||||
* @param lmeter pointer to a line meter object
|
||||
* @return angle offset (0..360)
|
||||
*/
|
||||
uint16_t lv_lmeter_get_angle_offset(lv_obj_t * lmeter)
|
||||
{
|
||||
lv_lmeter_ext_t * ext = lv_obj_get_ext_attr(lmeter);
|
||||
|
||||
return ext->angle_ofs;
|
||||
}
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
@@ -268,7 +314,7 @@ static bool lv_lmeter_design(lv_obj_t * lmeter, const lv_area_t * mask, lv_desig
|
||||
|
||||
lv_coord_t x_ofs = lv_obj_get_width(lmeter) / 2 + lmeter->coords.x1;
|
||||
lv_coord_t y_ofs = lv_obj_get_height(lmeter) / 2 + lmeter->coords.y1;
|
||||
int16_t angle_ofs = 90 + (360 - ext->scale_angle) / 2;
|
||||
int16_t angle_ofs = ext->angle_ofs + 90 + (360 - ext->scale_angle) / 2;
|
||||
int16_t level =
|
||||
(int32_t)((int32_t)(ext->cur_value - ext->min_value) * ext->line_cnt) / (ext->max_value - ext->min_value);
|
||||
uint8_t i;
|
||||
@@ -335,6 +381,7 @@ static lv_res_t lv_lmeter_signal(lv_obj_t * lmeter, lv_signal_t sign, void * par
|
||||
/* Include the ancient signal function */
|
||||
res = ancestor_signal(lmeter, sign, param);
|
||||
if(res != LV_RES_OK) return res;
|
||||
if(sign == LV_SIGNAL_GET_TYPE) return lv_obj_handle_get_type_signal(param, LV_OBJX_NAME);
|
||||
|
||||
if(sign == LV_SIGNAL_CLEANUP) {
|
||||
/*Nothing to cleanup. (No dynamically allocated memory in 'ext')*/
|
||||
@@ -343,13 +390,6 @@ static lv_res_t lv_lmeter_signal(lv_obj_t * lmeter, lv_signal_t sign, void * par
|
||||
} else if(sign == LV_SIGNAL_REFR_EXT_DRAW_PAD) {
|
||||
const lv_style_t * style = lv_lmeter_get_style(lmeter, LV_LMETER_STYLE_MAIN);
|
||||
lmeter->ext_draw_pad = LV_MATH_MAX(lmeter->ext_draw_pad, style->line.width);
|
||||
} else if(sign == LV_SIGNAL_GET_TYPE) {
|
||||
lv_obj_type_t * buf = param;
|
||||
uint8_t i;
|
||||
for(i = 0; i < LV_MAX_ANCESTOR_NUM - 1; i++) { /*Find the last set data*/
|
||||
if(buf->type[i] == NULL) break;
|
||||
}
|
||||
buf->type[i] = "lv_lmeter";
|
||||
}
|
||||
|
||||
return res;
|
||||
|
||||
@@ -36,6 +36,7 @@ typedef struct
|
||||
/*No inherited ext.*/ /*Ext. of ancestor*/
|
||||
/*New data for this type */
|
||||
uint16_t scale_angle; /*Angle of the scale in deg. (0..360)*/
|
||||
uint16_t angle_ofs;
|
||||
uint8_t line_cnt; /*Count of lines */
|
||||
int16_t cur_value;
|
||||
int16_t min_value;
|
||||
@@ -88,6 +89,13 @@ void lv_lmeter_set_range(lv_obj_t * lmeter, int16_t min, int16_t max);
|
||||
*/
|
||||
void lv_lmeter_set_scale(lv_obj_t * lmeter, uint16_t angle, uint8_t line_cnt);
|
||||
|
||||
/**
|
||||
* Set the set an offset for the line meter's angles to rotate it.
|
||||
* @param lmeter pointer to a line meter object
|
||||
* @param angle angle offset (0..360), rotates clockwise
|
||||
*/
|
||||
void lv_lmeter_set_angle_offset(lv_obj_t * lmeter, uint16_t angle);
|
||||
|
||||
/**
|
||||
* Set the styles of a line meter
|
||||
* @param lmeter pointer to a line meter object
|
||||
@@ -139,6 +147,13 @@ uint8_t lv_lmeter_get_line_count(const lv_obj_t * lmeter);
|
||||
*/
|
||||
uint16_t lv_lmeter_get_scale_angle(const lv_obj_t * lmeter);
|
||||
|
||||
/**
|
||||
* get the set an offset for the line meter.
|
||||
* @param lmeter pointer to a line meter object
|
||||
* @return angle offset (0..360)
|
||||
*/
|
||||
uint16_t lv_lmeter_get_angle_offset(lv_obj_t * lmeter);
|
||||
|
||||
/**
|
||||
* Get the style of a line meter
|
||||
* @param lmeter pointer to a line meter object
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#include "lv_mbox.h"
|
||||
#if LV_USE_MBOX != 0
|
||||
|
||||
#include "../lv_core/lv_debug.h"
|
||||
#include "../lv_core/lv_group.h"
|
||||
#include "../lv_themes/lv_theme.h"
|
||||
#include "../lv_misc/lv_anim.h"
|
||||
@@ -17,6 +18,7 @@
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
#define LV_OBJX_NAME "lv_mbos"
|
||||
|
||||
#if LV_USE_ANIMATION
|
||||
#ifndef LV_MBOX_CLOSE_ANIM_TIME
|
||||
@@ -68,14 +70,14 @@ lv_obj_t * lv_mbox_create(lv_obj_t * par, const lv_obj_t * copy)
|
||||
|
||||
/*Create the ancestor message box*/
|
||||
lv_obj_t * new_mbox = lv_cont_create(par, copy);
|
||||
lv_mem_assert(new_mbox);
|
||||
LV_ASSERT_MEM(new_mbox);
|
||||
if(new_mbox == NULL) return NULL;
|
||||
|
||||
if(ancestor_signal == NULL) ancestor_signal = lv_obj_get_signal_cb(new_mbox);
|
||||
|
||||
/*Allocate the message box type specific extended data*/
|
||||
lv_mbox_ext_t * ext = lv_obj_allocate_ext_attr(new_mbox, sizeof(lv_mbox_ext_t));
|
||||
lv_mem_assert(ext);
|
||||
LV_ASSERT_MEM(ext);
|
||||
if(ext == NULL) return NULL;
|
||||
|
||||
ext->text = NULL;
|
||||
@@ -137,8 +139,11 @@ lv_obj_t * lv_mbox_create(lv_obj_t * par, const lv_obj_t * copy)
|
||||
* @param btn_map button descriptor (button matrix map).
|
||||
* E.g. a const char *txt[] = {"ok", "close", ""} (Can not be local variable)
|
||||
*/
|
||||
void lv_mbox_add_btns(lv_obj_t * mbox, const char ** btn_map)
|
||||
void lv_mbox_add_btns(lv_obj_t * mbox, const char * btn_map[])
|
||||
{
|
||||
LV_ASSERT_OBJ(mbox, LV_OBJX_NAME);
|
||||
LV_ASSERT_NULL(btn_map);
|
||||
|
||||
lv_mbox_ext_t * ext = lv_obj_get_ext_attr(mbox);
|
||||
|
||||
/*Create a button matrix if not exists yet*/
|
||||
@@ -174,6 +179,9 @@ void lv_mbox_add_btns(lv_obj_t * mbox, const char ** btn_map)
|
||||
*/
|
||||
void lv_mbox_set_text(lv_obj_t * mbox, const char * txt)
|
||||
{
|
||||
LV_ASSERT_OBJ(mbox, LV_OBJX_NAME);
|
||||
LV_ASSERT_STR(txt);
|
||||
|
||||
lv_mbox_ext_t * ext = lv_obj_get_ext_attr(mbox);
|
||||
lv_label_set_text(ext->text, txt);
|
||||
|
||||
@@ -187,6 +195,8 @@ void lv_mbox_set_text(lv_obj_t * mbox, const char * txt)
|
||||
*/
|
||||
void lv_mbox_set_anim_time(lv_obj_t * mbox, uint16_t anim_time)
|
||||
{
|
||||
LV_ASSERT_OBJ(mbox, LV_OBJX_NAME);
|
||||
|
||||
#if LV_USE_ANIMATION
|
||||
lv_mbox_ext_t * ext = lv_obj_get_ext_attr(mbox);
|
||||
anim_time = 0;
|
||||
@@ -204,6 +214,8 @@ void lv_mbox_set_anim_time(lv_obj_t * mbox, uint16_t anim_time)
|
||||
*/
|
||||
void lv_mbox_start_auto_close(lv_obj_t * mbox, uint16_t delay)
|
||||
{
|
||||
LV_ASSERT_OBJ(mbox, LV_OBJX_NAME);
|
||||
|
||||
#if LV_USE_ANIMATION
|
||||
if(lv_mbox_get_anim_time(mbox) != 0) {
|
||||
/*Add shrinking animations*/
|
||||
@@ -258,6 +270,8 @@ void lv_mbox_start_auto_close(lv_obj_t * mbox, uint16_t delay)
|
||||
*/
|
||||
void lv_mbox_stop_auto_close(lv_obj_t * mbox)
|
||||
{
|
||||
LV_ASSERT_OBJ(mbox, LV_OBJX_NAME);
|
||||
|
||||
#if LV_USE_ANIMATION
|
||||
lv_anim_del(mbox, NULL);
|
||||
#else
|
||||
@@ -273,6 +287,8 @@ void lv_mbox_stop_auto_close(lv_obj_t * mbox)
|
||||
*/
|
||||
void lv_mbox_set_style(lv_obj_t * mbox, lv_mbox_style_t type, const lv_style_t * style)
|
||||
{
|
||||
LV_ASSERT_OBJ(mbox, LV_OBJX_NAME);
|
||||
|
||||
lv_mbox_ext_t * ext = lv_obj_get_ext_attr(mbox);
|
||||
|
||||
switch(type) {
|
||||
@@ -295,6 +311,8 @@ void lv_mbox_set_style(lv_obj_t * mbox, lv_mbox_style_t type, const lv_style_t *
|
||||
*/
|
||||
void lv_mbox_set_recolor(lv_obj_t * mbox, bool en)
|
||||
{
|
||||
LV_ASSERT_OBJ(mbox, LV_OBJX_NAME);
|
||||
|
||||
lv_mbox_ext_t * ext = lv_obj_get_ext_attr(mbox);
|
||||
|
||||
if(ext->btnm) lv_btnm_set_recolor(ext->btnm, en);
|
||||
@@ -311,6 +329,8 @@ void lv_mbox_set_recolor(lv_obj_t * mbox, bool en)
|
||||
*/
|
||||
const char * lv_mbox_get_text(const lv_obj_t * mbox)
|
||||
{
|
||||
LV_ASSERT_OBJ(mbox, LV_OBJX_NAME);
|
||||
|
||||
lv_mbox_ext_t * ext = lv_obj_get_ext_attr(mbox);
|
||||
|
||||
return lv_label_get_text(ext->text);
|
||||
@@ -324,6 +344,8 @@ const char * lv_mbox_get_text(const lv_obj_t * mbox)
|
||||
*/
|
||||
uint16_t lv_mbox_get_active_btn(lv_obj_t * mbox)
|
||||
{
|
||||
LV_ASSERT_OBJ(mbox, LV_OBJX_NAME);
|
||||
|
||||
lv_mbox_ext_t * ext = lv_obj_get_ext_attr(mbox);
|
||||
if(ext->btnm)
|
||||
return lv_btnm_get_active_btn(ext->btnm);
|
||||
@@ -339,6 +361,8 @@ uint16_t lv_mbox_get_active_btn(lv_obj_t * mbox)
|
||||
*/
|
||||
const char * lv_mbox_get_active_btn_text(lv_obj_t * mbox)
|
||||
{
|
||||
LV_ASSERT_OBJ(mbox, LV_OBJX_NAME);
|
||||
|
||||
lv_mbox_ext_t * ext = lv_obj_get_ext_attr(mbox);
|
||||
if(ext->btnm)
|
||||
return lv_btnm_get_active_btn_text(ext->btnm);
|
||||
@@ -353,6 +377,8 @@ const char * lv_mbox_get_active_btn_text(lv_obj_t * mbox)
|
||||
*/
|
||||
uint16_t lv_mbox_get_anim_time(const lv_obj_t * mbox)
|
||||
{
|
||||
LV_ASSERT_OBJ(mbox, LV_OBJX_NAME);
|
||||
|
||||
#if LV_USE_ANIMATION
|
||||
lv_mbox_ext_t * ext = lv_obj_get_ext_attr(mbox);
|
||||
return ext->anim_time;
|
||||
@@ -370,6 +396,8 @@ uint16_t lv_mbox_get_anim_time(const lv_obj_t * mbox)
|
||||
*/
|
||||
const lv_style_t * lv_mbox_get_style(const lv_obj_t * mbox, lv_mbox_style_t type)
|
||||
{
|
||||
LV_ASSERT_OBJ(mbox, LV_OBJX_NAME);
|
||||
|
||||
const lv_style_t * style = NULL;
|
||||
lv_mbox_ext_t * ext = lv_obj_get_ext_attr(mbox);
|
||||
|
||||
@@ -394,6 +422,8 @@ const lv_style_t * lv_mbox_get_style(const lv_obj_t * mbox, lv_mbox_style_t type
|
||||
*/
|
||||
bool lv_mbox_get_recolor(const lv_obj_t * mbox)
|
||||
{
|
||||
LV_ASSERT_OBJ(mbox, LV_OBJX_NAME);
|
||||
|
||||
lv_mbox_ext_t * ext = lv_obj_get_ext_attr(mbox);
|
||||
|
||||
if(!ext->btnm) return false;
|
||||
@@ -409,6 +439,8 @@ bool lv_mbox_get_recolor(const lv_obj_t * mbox)
|
||||
*/
|
||||
lv_obj_t * lv_mbox_get_btnm(lv_obj_t * mbox)
|
||||
{
|
||||
LV_ASSERT_OBJ(mbox, LV_OBJX_NAME);
|
||||
|
||||
lv_mbox_ext_t * ext = lv_obj_get_ext_attr(mbox);
|
||||
return ext->btnm;
|
||||
}
|
||||
@@ -441,6 +473,7 @@ static lv_res_t lv_mbox_signal(lv_obj_t * mbox, lv_signal_t sign, void * param)
|
||||
/* Include the ancient signal function */
|
||||
res = ancestor_signal(mbox, sign, param);
|
||||
if(res != LV_RES_OK) return res;
|
||||
if(sign == LV_SIGNAL_GET_TYPE) return lv_obj_handle_get_type_signal(param, LV_OBJX_NAME);
|
||||
|
||||
lv_mbox_ext_t * ext = lv_obj_get_ext_attr(mbox);
|
||||
if(sign == LV_SIGNAL_CORD_CHG) {
|
||||
@@ -476,13 +509,6 @@ static lv_res_t lv_mbox_signal(lv_obj_t * mbox, lv_signal_t sign, void * param)
|
||||
}
|
||||
#endif
|
||||
}
|
||||
} else if(sign == LV_SIGNAL_GET_TYPE) {
|
||||
lv_obj_type_t * buf = param;
|
||||
uint8_t i;
|
||||
for(i = 0; i < LV_MAX_ANCESTOR_NUM - 1; i++) { /*Find the last set data*/
|
||||
if(buf->type[i] == NULL) break;
|
||||
}
|
||||
buf->type[i] = "lv_mbox";
|
||||
}
|
||||
|
||||
return res;
|
||||
|
||||
@@ -94,7 +94,7 @@ lv_obj_t * lv_mbox_create(lv_obj_t * par, const lv_obj_t * copy);
|
||||
* @param btn_map button descriptor (button matrix map).
|
||||
* E.g. a const char *txt[] = {"ok", "close", ""} (Can not be local variable)
|
||||
*/
|
||||
void lv_mbox_add_btns(lv_obj_t * mbox, const char ** btn_mapaction);
|
||||
void lv_mbox_add_btns(lv_obj_t * mbox, const char * btn_mapaction[]);
|
||||
|
||||
/*=====================
|
||||
* Setter functions
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
CSRCS += lv_arc.c
|
||||
CSRCS += lv_bar.c
|
||||
CSRCS += lv_cb.c
|
||||
CSRCS += lv_cpicker.c
|
||||
CSRCS += lv_ddlist.c
|
||||
CSRCS += lv_kb.c
|
||||
CSRCS += lv_line.c
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "../lv_core/lv_debug.h"
|
||||
//#include "lv_templ.h" /*TODO uncomment this*/
|
||||
|
||||
#if defined(LV_USE_TEMPL) && LV_USE_TEMPL != 0
|
||||
@@ -22,6 +23,7 @@
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
#define LV_OBJX_NAME "lv_templ"
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
@@ -118,6 +120,8 @@ lv_obj_t * lv_templ_create(lv_obj_t * par, const lv_obj_t * copy)
|
||||
*/
|
||||
void lv_templ_set_style(lv_obj_t * templ, lv_templ_style_t type, const lv_style_t * style)
|
||||
{
|
||||
LV_ASSERT_OBJ(templ, LV_OBJX_NAME);
|
||||
|
||||
lv_templ_ext_t * ext = lv_obj_get_ext_attr(templ);
|
||||
|
||||
switch(type) {
|
||||
@@ -142,6 +146,8 @@ void lv_templ_set_style(lv_obj_t * templ, lv_templ_style_t type, const lv_style_
|
||||
*/
|
||||
lv_style_t * lv_templ_get_style(const lv_obj_t * templ, lv_templ_style_t type)
|
||||
{
|
||||
LV_ASSERT_OBJ(templ, LV_OBJX_NAME);
|
||||
|
||||
lv_templ_ext_t * ext = lv_obj_get_ext_attr(templ);
|
||||
lv_style_t * style = NULL;
|
||||
|
||||
@@ -207,16 +213,10 @@ static lv_res_t lv_templ_signal(lv_obj_t * templ, lv_signal_t sign, void * param
|
||||
/* Include the ancient signal function */
|
||||
res = ancestor_signal(templ, sign, param);
|
||||
if(res != LV_RES_OK) return res;
|
||||
if(sign == LV_SIGNAL_GET_TYPE) return lv_obj_handle_get_type_signal(param, LV_OBJX_NAME);
|
||||
|
||||
if(sign == LV_SIGNAL_CLEANUP) {
|
||||
/*Nothing to cleanup. (No dynamically allocated memory in 'ext')*/
|
||||
} else if(sign == LV_SIGNAL_GET_TYPE) {
|
||||
lv_obj_type_t * buf = param;
|
||||
uint8_t i;
|
||||
for(i = 0; i < LV_MAX_ANCESTOR_NUM - 1; i++) { /*Find the last set data*/
|
||||
if(buf->type[i] == NULL) break;
|
||||
}
|
||||
buf->type[i] = "lv_templ";
|
||||
}
|
||||
|
||||
return res;
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#include "../lv_objx/lv_page.h"
|
||||
#if LV_USE_PAGE != 0
|
||||
|
||||
#include "../lv_core/lv_debug.h"
|
||||
#include "../lv_core/lv_group.h"
|
||||
#include "../lv_draw/lv_draw.h"
|
||||
#include "../lv_themes/lv_theme.h"
|
||||
@@ -19,6 +20,8 @@
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
#define LV_OBJX_NAME "lv_page"
|
||||
|
||||
#define LV_PAGE_SB_MIN_SIZE (LV_DPI / 8)
|
||||
|
||||
/*[ms] Scroll anim time on `lv_page_scroll_up/down/left/rigth`*/
|
||||
@@ -77,7 +80,7 @@ lv_obj_t * lv_page_create(lv_obj_t * par, const lv_obj_t * copy)
|
||||
|
||||
/*Create the ancestor object*/
|
||||
lv_obj_t * new_page = lv_cont_create(par, copy);
|
||||
lv_mem_assert(new_page);
|
||||
LV_ASSERT_MEM(new_page);
|
||||
if(new_page == NULL) return NULL;
|
||||
|
||||
if(ancestor_signal == NULL) ancestor_signal = lv_obj_get_signal_cb(new_page);
|
||||
@@ -85,7 +88,7 @@ lv_obj_t * lv_page_create(lv_obj_t * par, const lv_obj_t * copy)
|
||||
|
||||
/*Allocate the object type specific extended data*/
|
||||
lv_page_ext_t * ext = lv_obj_allocate_ext_attr(new_page, sizeof(lv_page_ext_t));
|
||||
lv_mem_assert(ext);
|
||||
LV_ASSERT_MEM(ext);
|
||||
if(ext == NULL) return NULL;
|
||||
|
||||
ext->scrl = NULL;
|
||||
@@ -171,11 +174,13 @@ lv_obj_t * lv_page_create(lv_obj_t * par, const lv_obj_t * copy)
|
||||
|
||||
/**
|
||||
* Delete all children of the scrl object, without deleting scrl child.
|
||||
* @param obj pointer to an object
|
||||
* @param page pointer to an object
|
||||
*/
|
||||
void lv_page_clean(lv_obj_t * obj)
|
||||
void lv_page_clean(lv_obj_t * page)
|
||||
{
|
||||
lv_obj_t * scrl = lv_page_get_scrl(obj);
|
||||
LV_ASSERT_OBJ(page, LV_OBJX_NAME);
|
||||
|
||||
lv_obj_t * scrl = lv_page_get_scrl(page);
|
||||
lv_obj_clean(scrl);
|
||||
}
|
||||
|
||||
@@ -190,6 +195,8 @@ void lv_page_clean(lv_obj_t * obj)
|
||||
*/
|
||||
void lv_page_set_sb_mode(lv_obj_t * page, lv_sb_mode_t sb_mode)
|
||||
{
|
||||
LV_ASSERT_OBJ(page, LV_OBJX_NAME);
|
||||
|
||||
lv_page_ext_t * ext = lv_obj_get_ext_attr(page);
|
||||
if(ext->sb.mode == sb_mode) return;
|
||||
|
||||
@@ -216,6 +223,8 @@ void lv_page_set_sb_mode(lv_obj_t * page, lv_sb_mode_t sb_mode)
|
||||
*/
|
||||
void lv_page_set_anim_time(lv_obj_t * page, uint16_t anim_time)
|
||||
{
|
||||
LV_ASSERT_OBJ(page, LV_OBJX_NAME);
|
||||
|
||||
#if LV_USE_ANIMATION
|
||||
lv_page_ext_t * ext = lv_obj_get_ext_attr(page);
|
||||
ext->anim_time = anim_time;
|
||||
@@ -233,6 +242,8 @@ void lv_page_set_anim_time(lv_obj_t * page, uint16_t anim_time)
|
||||
*/
|
||||
void lv_page_set_scroll_propagation(lv_obj_t * page, bool en)
|
||||
{
|
||||
LV_ASSERT_OBJ(page, LV_OBJX_NAME);
|
||||
|
||||
lv_page_ext_t * ext = lv_obj_get_ext_attr(page);
|
||||
ext->scroll_prop = en ? 1 : 0;
|
||||
}
|
||||
@@ -244,6 +255,8 @@ void lv_page_set_scroll_propagation(lv_obj_t * page, bool en)
|
||||
*/
|
||||
void lv_page_set_edge_flash(lv_obj_t * page, bool en)
|
||||
{
|
||||
LV_ASSERT_OBJ(page, LV_OBJX_NAME);
|
||||
|
||||
#if LV_USE_ANIMATION
|
||||
lv_page_ext_t * ext = lv_obj_get_ext_attr(page);
|
||||
ext->edge_flash.enabled = en ? 1 : 0;
|
||||
@@ -261,6 +274,8 @@ void lv_page_set_edge_flash(lv_obj_t * page, bool en)
|
||||
* */
|
||||
void lv_page_set_style(lv_obj_t * page, lv_page_style_t type, const lv_style_t * style)
|
||||
{
|
||||
LV_ASSERT_OBJ(page, LV_OBJX_NAME);
|
||||
|
||||
lv_page_ext_t * ext = lv_obj_get_ext_attr(page);
|
||||
|
||||
switch(type) {
|
||||
@@ -291,6 +306,8 @@ void lv_page_set_style(lv_obj_t * page, lv_page_style_t type, const lv_style_t *
|
||||
*/
|
||||
lv_obj_t * lv_page_get_scrl(const lv_obj_t * page)
|
||||
{
|
||||
LV_ASSERT_OBJ(page, LV_OBJX_NAME);
|
||||
|
||||
lv_page_ext_t * ext = lv_obj_get_ext_attr(page);
|
||||
|
||||
return ext->scrl;
|
||||
@@ -303,6 +320,8 @@ lv_obj_t * lv_page_get_scrl(const lv_obj_t * page)
|
||||
*/
|
||||
uint16_t lv_page_get_anim_time(const lv_obj_t * page)
|
||||
{
|
||||
LV_ASSERT_OBJ(page, LV_OBJX_NAME);
|
||||
|
||||
#if LV_USE_ANIMATION
|
||||
lv_page_ext_t * ext = lv_obj_get_ext_attr(page);
|
||||
return ext->anim_time;
|
||||
@@ -319,6 +338,8 @@ uint16_t lv_page_get_anim_time(const lv_obj_t * page)
|
||||
*/
|
||||
lv_sb_mode_t lv_page_get_sb_mode(const lv_obj_t * page)
|
||||
{
|
||||
LV_ASSERT_OBJ(page, LV_OBJX_NAME);
|
||||
|
||||
lv_page_ext_t * ext = lv_obj_get_ext_attr(page);
|
||||
return ext->sb.mode;
|
||||
}
|
||||
@@ -330,6 +351,8 @@ lv_sb_mode_t lv_page_get_sb_mode(const lv_obj_t * page)
|
||||
*/
|
||||
bool lv_page_get_scroll_propagation(lv_obj_t * page)
|
||||
{
|
||||
LV_ASSERT_OBJ(page, LV_OBJX_NAME);
|
||||
|
||||
lv_page_ext_t * ext = lv_obj_get_ext_attr(page);
|
||||
return ext->scroll_prop == 0 ? false : true;
|
||||
}
|
||||
@@ -341,6 +364,8 @@ bool lv_page_get_scroll_propagation(lv_obj_t * page)
|
||||
*/
|
||||
bool lv_page_get_edge_flash(lv_obj_t * page)
|
||||
{
|
||||
LV_ASSERT_OBJ(page, LV_OBJX_NAME);
|
||||
|
||||
#if LV_USE_ANIMATION
|
||||
lv_page_ext_t * ext = lv_obj_get_ext_attr(page);
|
||||
return ext->edge_flash.enabled == 0 ? false : true;
|
||||
@@ -357,6 +382,8 @@ bool lv_page_get_edge_flash(lv_obj_t * page)
|
||||
*/
|
||||
lv_coord_t lv_page_get_fit_width(lv_obj_t * page)
|
||||
{
|
||||
LV_ASSERT_OBJ(page, LV_OBJX_NAME);
|
||||
|
||||
const lv_style_t * bg_style = lv_page_get_style(page, LV_PAGE_STYLE_BG);
|
||||
const lv_style_t * scrl_style = lv_page_get_style(page, LV_PAGE_STYLE_SCRL);
|
||||
|
||||
@@ -371,6 +398,8 @@ lv_coord_t lv_page_get_fit_width(lv_obj_t * page)
|
||||
*/
|
||||
lv_coord_t lv_page_get_fit_height(lv_obj_t * page)
|
||||
{
|
||||
LV_ASSERT_OBJ(page, LV_OBJX_NAME);
|
||||
|
||||
const lv_style_t * bg_style = lv_page_get_style(page, LV_PAGE_STYLE_BG);
|
||||
const lv_style_t * scrl_style = lv_page_get_style(page, LV_PAGE_STYLE_SCRL);
|
||||
|
||||
@@ -386,6 +415,8 @@ lv_coord_t lv_page_get_fit_height(lv_obj_t * page)
|
||||
* */
|
||||
const lv_style_t * lv_page_get_style(const lv_obj_t * page, lv_page_style_t type)
|
||||
{
|
||||
LV_ASSERT_OBJ(page, LV_OBJX_NAME);
|
||||
|
||||
const lv_style_t * style = NULL;
|
||||
lv_page_ext_t * ext = lv_obj_get_ext_attr(page);
|
||||
|
||||
@@ -792,12 +823,15 @@ static lv_res_t lv_page_signal(lv_obj_t * page, lv_signal_t sign, void * param)
|
||||
/* Include the ancient signal function */
|
||||
res = ancestor_signal(page, sign, param);
|
||||
if(res != LV_RES_OK) return res;
|
||||
if(sign == LV_SIGNAL_GET_TYPE) return lv_obj_handle_get_type_signal(param, LV_OBJX_NAME);
|
||||
|
||||
lv_page_ext_t * ext = lv_obj_get_ext_attr(page);
|
||||
lv_obj_t * child;
|
||||
if(sign == LV_SIGNAL_CHILD_CHG) { /*Automatically move children to the scrollable object*/
|
||||
const lv_style_t * style = lv_page_get_style(page, LV_PAGE_STYLE_SCRL);
|
||||
const lv_style_t * style_bg = lv_page_get_style(page, LV_PAGE_STYLE_BG);
|
||||
const lv_style_t * style_scrl = lv_page_get_style(page, LV_PAGE_STYLE_SCRL);
|
||||
lv_fit_t fit_left = lv_page_get_scrl_fit_left(page);
|
||||
lv_fit_t fit_right = lv_page_get_scrl_fit_right(page);
|
||||
lv_fit_t fit_top = lv_page_get_scrl_fit_top(page);
|
||||
child = lv_obj_get_child(page, NULL);
|
||||
while(child != NULL) {
|
||||
@@ -805,15 +839,19 @@ static lv_res_t lv_page_signal(lv_obj_t * page, lv_signal_t sign, void * param)
|
||||
lv_obj_t * tmp = child;
|
||||
child = lv_obj_get_child(page, child); /*Get the next child before move this*/
|
||||
|
||||
/* Reposition the child to take padding into account (Only if it's on (0;0) now)
|
||||
/* Reposition the child to take padding into account (Only if it's on (0;0) or (widht;height) coordinates now)
|
||||
* It's required to keep new the object on the same coordinate if FIT is enabled.*/
|
||||
if((tmp->coords.x1 == page->coords.x1) && (fit_left == LV_FIT_TIGHT || fit_left == LV_FIT_FILL)) {
|
||||
tmp->coords.x1 += style->body.padding.left;
|
||||
tmp->coords.x2 += style->body.padding.left;
|
||||
tmp->coords.x1 += style_scrl->body.padding.left;
|
||||
tmp->coords.x2 += style_scrl->body.padding.left;
|
||||
}
|
||||
else if((tmp->coords.x2 == page->coords.x2) && (fit_right == LV_FIT_TIGHT || fit_right == LV_FIT_FILL)) {
|
||||
tmp->coords.x1 -= style_scrl->body.padding.right + style_bg->body.padding.right;
|
||||
tmp->coords.x2 -= style_scrl->body.padding.right + style_bg->body.padding.right;
|
||||
}
|
||||
if((tmp->coords.y1 == page->coords.y1) && (fit_top == LV_FIT_TIGHT || fit_top == LV_FIT_FILL)) {
|
||||
tmp->coords.y1 += style->body.padding.top;
|
||||
tmp->coords.y2 += style->body.padding.top;
|
||||
tmp->coords.y1 += style_scrl->body.padding.top;
|
||||
tmp->coords.y2 += style_scrl->body.padding.top;
|
||||
}
|
||||
lv_obj_set_parent(tmp, ext->scrl);
|
||||
} else {
|
||||
@@ -869,13 +907,6 @@ static lv_res_t lv_page_signal(lv_obj_t * page, lv_signal_t sign, void * param)
|
||||
} else if(sign == LV_SIGNAL_GET_EDITABLE) {
|
||||
bool * editable = (bool *)param;
|
||||
*editable = true;
|
||||
} else if(sign == LV_SIGNAL_GET_TYPE) {
|
||||
lv_obj_type_t * buf = param;
|
||||
uint8_t i;
|
||||
for(i = 0; i < LV_MAX_ANCESTOR_NUM - 1; i++) { /*Find the last set data*/
|
||||
if(buf->type[i] == NULL) break;
|
||||
}
|
||||
buf->type[i] = "lv_page";
|
||||
}
|
||||
|
||||
return res;
|
||||
@@ -895,6 +926,7 @@ static lv_res_t lv_page_scrollable_signal(lv_obj_t * scrl, lv_signal_t sign, voi
|
||||
/* Include the ancient signal function */
|
||||
res = ancestor_signal(scrl, sign, param);
|
||||
if(res != LV_RES_OK) return res;
|
||||
if(sign == LV_SIGNAL_GET_TYPE) return lv_obj_handle_get_type_signal(param, "");
|
||||
|
||||
lv_obj_t * page = lv_obj_get_parent(scrl);
|
||||
const lv_style_t * page_style = lv_obj_get_style(page);
|
||||
|
||||
@@ -113,9 +113,9 @@ lv_obj_t * lv_page_create(lv_obj_t * par, const lv_obj_t * copy);
|
||||
|
||||
/**
|
||||
* Delete all children of the scrl object, without deleting scrl child.
|
||||
* @param obj pointer to an object
|
||||
* @param page pointer to an object
|
||||
*/
|
||||
void lv_page_clean(lv_obj_t * obj);
|
||||
void lv_page_clean(lv_obj_t * page);
|
||||
|
||||
/**
|
||||
* Get the scrollable object of a page
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#include "lv_preload.h"
|
||||
#if LV_USE_PRELOAD != 0
|
||||
|
||||
#include "../lv_core/lv_debug.h"
|
||||
#include "../lv_misc/lv_math.h"
|
||||
#include "../lv_draw/lv_draw_rect.h"
|
||||
#include "../lv_draw/lv_draw_arc.h"
|
||||
@@ -17,6 +18,8 @@
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
#define LV_OBJX_NAME "lv_preloader"
|
||||
|
||||
#ifndef LV_PRELOAD_DEF_ARC_LENGTH
|
||||
#define LV_PRELOAD_DEF_ARC_LENGTH 60 /*[deg]*/
|
||||
#endif
|
||||
@@ -66,12 +69,12 @@ lv_obj_t * lv_preload_create(lv_obj_t * par, const lv_obj_t * copy)
|
||||
|
||||
/*Create the ancestor of pre loader*/
|
||||
lv_obj_t * new_preload = lv_arc_create(par, copy);
|
||||
lv_mem_assert(new_preload);
|
||||
LV_ASSERT_MEM(new_preload);
|
||||
if(new_preload == NULL) return NULL;
|
||||
|
||||
/*Allocate the pre loader type specific extended data*/
|
||||
lv_preload_ext_t * ext = lv_obj_allocate_ext_attr(new_preload, sizeof(lv_preload_ext_t));
|
||||
lv_mem_assert(ext);
|
||||
LV_ASSERT_MEM(ext);
|
||||
if(ext == NULL) return NULL;
|
||||
|
||||
if(ancestor_signal == NULL) ancestor_signal = lv_obj_get_signal_cb(new_preload);
|
||||
@@ -129,6 +132,8 @@ lv_obj_t * lv_preload_create(lv_obj_t * par, const lv_obj_t * copy)
|
||||
*/
|
||||
void lv_preload_set_arc_length(lv_obj_t * preload, lv_anim_value_t deg)
|
||||
{
|
||||
LV_ASSERT_OBJ(preload, LV_OBJX_NAME);
|
||||
|
||||
lv_preload_ext_t * ext = lv_obj_get_ext_attr(preload);
|
||||
|
||||
ext->arc_length = deg;
|
||||
@@ -141,6 +146,8 @@ void lv_preload_set_arc_length(lv_obj_t * preload, lv_anim_value_t deg)
|
||||
*/
|
||||
void lv_preload_set_spin_time(lv_obj_t * preload, uint16_t time)
|
||||
{
|
||||
LV_ASSERT_OBJ(preload, LV_OBJX_NAME);
|
||||
|
||||
lv_preload_ext_t * ext = lv_obj_get_ext_attr(preload);
|
||||
|
||||
ext->time = time;
|
||||
@@ -158,6 +165,8 @@ void lv_preload_set_spin_time(lv_obj_t * preload, uint16_t time)
|
||||
* */
|
||||
void lv_preload_set_style(lv_obj_t * preload, lv_preload_style_t type, const lv_style_t * style)
|
||||
{
|
||||
LV_ASSERT_OBJ(preload, LV_OBJX_NAME);
|
||||
|
||||
switch(type) {
|
||||
case LV_PRELOAD_STYLE_MAIN: lv_arc_set_style(preload, LV_ARC_STYLE_MAIN, style); break;
|
||||
}
|
||||
@@ -170,6 +179,8 @@ void lv_preload_set_style(lv_obj_t * preload, lv_preload_style_t type, const lv_
|
||||
* */
|
||||
void lv_preload_set_type(lv_obj_t * preload, lv_preload_type_t type)
|
||||
{
|
||||
LV_ASSERT_OBJ(preload, LV_OBJX_NAME);
|
||||
|
||||
lv_preload_ext_t * ext = lv_obj_get_ext_attr(preload);
|
||||
|
||||
/*delete previous animation*/
|
||||
@@ -220,9 +231,10 @@ void lv_preload_set_type(lv_obj_t * preload, lv_preload_type_t type)
|
||||
lv_anim_create(&b);
|
||||
break;
|
||||
}
|
||||
case LV_PRELOAD_TYPE_CONSTANT_ARC:
|
||||
case LV_PRELOAD_TYPE_SPINNING_ARC:
|
||||
default: {
|
||||
ext->anim_type = LV_PRELOAD_TYPE_SPINNING_ARC;
|
||||
ext->anim_type = type;
|
||||
lv_anim_t a;
|
||||
a.var = preload;
|
||||
if(ext->anim_dir == LV_PRELOAD_DIR_FORWARD) {
|
||||
@@ -234,7 +246,8 @@ void lv_preload_set_type(lv_obj_t * preload, lv_preload_type_t type)
|
||||
a.end = 360;
|
||||
}
|
||||
a.exec_cb = (lv_anim_exec_xcb_t)lv_preload_spinner_anim;
|
||||
a.path_cb = lv_anim_path_ease_in_out;
|
||||
a.path_cb = (LV_PRELOAD_TYPE_CONSTANT_ARC == type ?
|
||||
lv_anim_path_linear : lv_anim_path_ease_in_out);
|
||||
a.ready_cb = NULL;
|
||||
a.act_time = 0;
|
||||
a.time = ext->time;
|
||||
@@ -250,6 +263,8 @@ void lv_preload_set_type(lv_obj_t * preload, lv_preload_type_t type)
|
||||
|
||||
void lv_preload_set_dir(lv_obj_t * preload, lv_preload_dir_t dir)
|
||||
{
|
||||
LV_ASSERT_OBJ(preload, LV_OBJX_NAME);
|
||||
|
||||
lv_preload_ext_t * ext = lv_obj_get_ext_attr(preload);
|
||||
|
||||
ext->anim_dir = dir;
|
||||
@@ -266,6 +281,8 @@ void lv_preload_set_dir(lv_obj_t * preload, lv_preload_dir_t dir)
|
||||
*/
|
||||
lv_anim_value_t lv_preload_get_arc_length(const lv_obj_t * preload)
|
||||
{
|
||||
LV_ASSERT_OBJ(preload, LV_OBJX_NAME);
|
||||
|
||||
lv_preload_ext_t * ext = lv_obj_get_ext_attr(preload);
|
||||
return ext->arc_length;
|
||||
}
|
||||
@@ -276,6 +293,8 @@ lv_anim_value_t lv_preload_get_arc_length(const lv_obj_t * preload)
|
||||
*/
|
||||
uint16_t lv_preload_get_spin_time(const lv_obj_t * preload)
|
||||
{
|
||||
LV_ASSERT_OBJ(preload, LV_OBJX_NAME);
|
||||
|
||||
lv_preload_ext_t * ext = lv_obj_get_ext_attr(preload);
|
||||
return ext->time;
|
||||
}
|
||||
@@ -288,6 +307,8 @@ uint16_t lv_preload_get_spin_time(const lv_obj_t * preload)
|
||||
* */
|
||||
const lv_style_t * lv_preload_get_style(const lv_obj_t * preload, lv_preload_style_t type)
|
||||
{
|
||||
LV_ASSERT_OBJ(preload, LV_OBJX_NAME);
|
||||
|
||||
const lv_style_t * style = NULL;
|
||||
|
||||
switch(type) {
|
||||
@@ -305,6 +326,8 @@ const lv_style_t * lv_preload_get_style(const lv_obj_t * preload, lv_preload_sty
|
||||
* */
|
||||
lv_preload_type_t lv_preload_get_type(lv_obj_t * preload)
|
||||
{
|
||||
LV_ASSERT_OBJ(preload, LV_OBJX_NAME);
|
||||
|
||||
lv_preload_ext_t * ext = lv_obj_get_ext_attr(preload);
|
||||
return ext->anim_type;
|
||||
}
|
||||
@@ -409,16 +432,10 @@ static lv_res_t lv_preload_signal(lv_obj_t * preload, lv_signal_t sign, void * p
|
||||
/* Include the ancient signal function */
|
||||
res = ancestor_signal(preload, sign, param);
|
||||
if(res != LV_RES_OK) return res;
|
||||
if(sign == LV_SIGNAL_GET_TYPE) return lv_obj_handle_get_type_signal(param, LV_OBJX_NAME);
|
||||
|
||||
if(sign == LV_SIGNAL_CLEANUP) {
|
||||
/*Nothing to cleanup. (No dynamically allocated memory in 'ext')*/
|
||||
} else if(sign == LV_SIGNAL_GET_TYPE) {
|
||||
lv_obj_type_t * buf = param;
|
||||
uint8_t i;
|
||||
for(i = 0; i < LV_MAX_ANCESTOR_NUM - 1; i++) { /*Find the last set data*/
|
||||
if(buf->type[i] == NULL) break;
|
||||
}
|
||||
buf->type[i] = "lv_preload";
|
||||
}
|
||||
|
||||
return res;
|
||||
|
||||
@@ -48,6 +48,7 @@ extern "C" {
|
||||
enum {
|
||||
LV_PRELOAD_TYPE_SPINNING_ARC,
|
||||
LV_PRELOAD_TYPE_FILLSPIN_ARC,
|
||||
LV_PRELOAD_TYPE_CONSTANT_ARC,
|
||||
};
|
||||
typedef uint8_t lv_preload_type_t;
|
||||
|
||||
@@ -67,7 +68,7 @@ typedef struct
|
||||
/*New data for this type */
|
||||
lv_anim_value_t arc_length; /*Length of the spinning indicator in degree*/
|
||||
uint16_t time; /*Time of one round*/
|
||||
lv_preload_type_t anim_type : 1; /*Type of the arc animation*/
|
||||
lv_preload_type_t anim_type : 2; /*Type of the arc animation*/
|
||||
lv_preload_dir_t anim_dir : 1; /*Animation Direction*/
|
||||
} lv_preload_ext_t;
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user