From 92a9b77b49e098cc089e724498e4b1268bbb4adb Mon Sep 17 00:00:00 2001 From: Alexander Entinger Date: Mon, 4 Apr 2022 13:19:30 +0200 Subject: [PATCH 1/7] Creating .gitignore for ignoring extras/build folder. --- .gitignore | 1 + 1 file changed, 1 insertion(+) create mode 100644 .gitignore diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..b1babc9 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +extras/build From eb01c25c2e999d509129da28672e0a17a12b2a75 Mon Sep 17 00:00:00 2001 From: Alexander Entinger Date: Mon, 4 Apr 2022 13:09:46 +0200 Subject: [PATCH 2/7] Cleanup: remove 'depends' statement from library.properties. --- library.properties | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/library.properties b/library.properties index c170d23..e38c56e 100644 --- a/library.properties +++ b/library.properties @@ -7,5 +7,6 @@ paragraph=This library allows you to control the Arduino Braccio++ 6-DOF 2nd gen category=Communication url=https://github.com/arduino-libraries/Arduino_Braccio_plusplus architectures=mbed,mbed_nano +precompiled=true +ldflags=-llvgl includes=Braccio++.h -depends=lvgl From a67852d9a6c1d4afe517a48ebfa1c169a5aa205b Mon Sep 17 00:00:00 2001 From: Alexander Entinger Date: Thu, 31 Mar 2022 11:14:30 +0200 Subject: [PATCH 3/7] Remove lvgl as dependency to be installed during CI (we've got it precompiled on board now). --- .github/workflows/compile-examples.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/compile-examples.yml b/.github/workflows/compile-examples.yml index 799f239..d7b4002 100644 --- a/.github/workflows/compile-examples.yml +++ b/.github/workflows/compile-examples.yml @@ -50,7 +50,6 @@ jobs: libraries: | # Install the library from the local path. - source-path: ./ - - name: lvgl # Additional library dependencies can be listed here. # See: https://github.com/arduino/compile-sketches#libraries sketch-paths: | From b9fc40e04e7fa7162ea3074c943d76b0f377905c Mon Sep 17 00:00:00 2001 From: Alexander Entinger Date: Fri, 8 Apr 2022 10:51:40 +0200 Subject: [PATCH 4/7] Adding instruction on how to re-build pre-compiled lvgl library. --- README.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/README.md b/README.md index 2eee7bc..e3cfa98 100644 --- a/README.md +++ b/README.md @@ -9,6 +9,16 @@ This library allows you to control and interact with the 6 DOF Braccio++ robot arm. +## How-to-update precompiled `liblvgl` +```bash +git clone https://github.com/lvgl/lvgl +git clone https://github.com/arduino-libraries/Arduino_Braccio_plusplus +cd Arduino_Braccio_plusplus/extras +mkdir build && cd build +cmake -DCMAKE_BUILD_TYPE=Release .. +make -j8 +``` + ## :mag_right: Resources * [How to install a library](https://www.arduino.cc/en/guide/libraries) From 357072b30734b113618732dc81988d976aa8ee97 Mon Sep 17 00:00:00 2001 From: Alexander Entinger Date: Fri, 8 Apr 2022 10:52:06 +0200 Subject: [PATCH 5/7] Adding CMake file for building pre-compiled libvgl. --- extras/CMakeLists.txt | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 extras/CMakeLists.txt diff --git a/extras/CMakeLists.txt b/extras/CMakeLists.txt new file mode 100644 index 0000000..e84608c --- /dev/null +++ b/extras/CMakeLists.txt @@ -0,0 +1,27 @@ +########################################################################## +cmake_minimum_required(VERSION 3.16) +########################################################################## +project(lvgl) +########################################################################## +set(CMAKE_C_COMPILER arm-none-eabi-gcc) +set(CMAKE_CXX_COMPILER arm-none-eabi-g++) +########################################################################## +add_library(${PROJECT_NAME} STATIC "") +########################################################################## +set(LVGL_ROOT_DIR ${CMAKE_SOURCE_DIR}/../../lvgl) +set(LV_CONF_DIR ${CMAKE_SOURCE_DIR}/../src) +########################################################################## +target_include_directories(${PROJECT_NAME} SYSTEM PUBLIC ${LVGL_ROOT_DIR} ${LV_CONF_DIR}) +########################################################################## +file(GLOB_RECURSE LVGL_SOURCES ${LVGL_ROOT_DIR}/src/*.c) +target_sources(${PROJECT_NAME} PUBLIC ${LVGL_SOURCES}) +########################################################################## +target_compile_options(${PROJECT_NAME} PRIVATE -mcpu=cortex-m0plus) +########################################################################## +file(WRITE ${CMAKE_BINARY_DIR}/cp-lvgl-hdr.cmake + "file(COPY ${LVGL_ROOT_DIR}/src DESTINATION ../../src/lib/lvgl FILES_MATCHING PATTERN *.h)\n" +) +add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD COMMAND cp ${CMAKE_BINARY_DIR}/liblvgl.a ../../src/cortex-m0plus/liblvgl.a COMMENT "Copying libvgl.a") +add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD COMMAND cp ${LVGL_ROOT_DIR}/lvgl.h ../../src/lib/lvgl COMMENT "Copying lvgl.h") +add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD COMMAND ${CMAKE_COMMAND} -P ${CMAKE_BINARY_DIR}/cp-lvgl-hdr.cmake COMMENT "Copying lvgl/src/*.h") +########################################################################## From d6d3857d319ea203f2ee162cbe33ccd75ec45f08 Mon Sep 17 00:00:00 2001 From: Alexander Entinger Date: Fri, 8 Apr 2022 10:53:23 +0200 Subject: [PATCH 6/7] Precompiling lvgl for lvgl:v8.2.0. https://github.com/lvgl/lvgl/commit/0b5a1d4b23975b920ff841ea9cd038802f51711b. --- src/cortex-m0plus/liblvgl.a | Bin 0 -> 854756 bytes src/lib/lvgl/lvgl.h | 143 ++ src/lib/lvgl/src/core/lv_disp.h | 244 ++ src/lib/lvgl/src/core/lv_event.h | 363 +++ src/lib/lvgl/src/core/lv_group.h | 246 ++ src/lib/lvgl/src/core/lv_indev.h | 172 ++ src/lib/lvgl/src/core/lv_indev_scroll.h | 65 + src/lib/lvgl/src/core/lv_obj.h | 408 +++ src/lib/lvgl/src/core/lv_obj_class.h | 94 + src/lib/lvgl/src/core/lv_obj_draw.h | 163 ++ src/lib/lvgl/src/core/lv_obj_pos.h | 431 ++++ src/lib/lvgl/src/core/lv_obj_scroll.h | 294 +++ src/lib/lvgl/src/core/lv_obj_style.h | 240 ++ src/lib/lvgl/src/core/lv_obj_style_gen.h | 640 +++++ src/lib/lvgl/src/core/lv_obj_tree.h | 172 ++ src/lib/lvgl/src/core/lv_refr.h | 115 + src/lib/lvgl/src/core/lv_theme.h | 120 + src/lib/lvgl/src/draw/arm2d/lv_gpu_arm2d.h | 51 + src/lib/lvgl/src/draw/lv_draw.h | 121 + src/lib/lvgl/src/draw/lv_draw_arc.h | 83 + src/lib/lvgl/src/draw/lv_draw_img.h | 104 + src/lib/lvgl/src/draw/lv_draw_label.h | 100 + src/lib/lvgl/src/draw/lv_draw_line.h | 67 + src/lib/lvgl/src/draw/lv_draw_mask.h | 394 +++ src/lib/lvgl/src/draw/lv_draw_rect.h | 102 + src/lib/lvgl/src/draw/lv_draw_triangle.h | 42 + src/lib/lvgl/src/draw/lv_img_buf.h | 310 +++ src/lib/lvgl/src/draw/lv_img_cache.h | 78 + src/lib/lvgl/src/draw/lv_img_decoder.h | 274 ++ .../lvgl/src/draw/nxp_pxp/lv_gpu_nxp_pxp.h | 193 ++ .../src/draw/nxp_pxp/lv_gpu_nxp_pxp_osa.h | 47 + .../src/draw/nxp_vglite/lv_gpu_nxp_vglite.h | 145 ++ src/lib/lvgl/src/draw/sdl/lv_draw_sdl.h | 96 + .../lvgl/src/draw/sdl/lv_draw_sdl_composite.h | 72 + src/lib/lvgl/src/draw/sdl/lv_draw_sdl_img.h | 72 + src/lib/lvgl/src/draw/sdl/lv_draw_sdl_mask.h | 51 + src/lib/lvgl/src/draw/sdl/lv_draw_sdl_priv.h | 70 + src/lib/lvgl/src/draw/sdl/lv_draw_sdl_rect.h | 75 + .../src/draw/sdl/lv_draw_sdl_stack_blur.h | 46 + .../src/draw/sdl/lv_draw_sdl_texture_cache.h | 102 + src/lib/lvgl/src/draw/sdl/lv_draw_sdl_utils.h | 65 + .../src/draw/stm32_dma2d/lv_gpu_stm32_dma2d.h | 66 + src/lib/lvgl/src/draw/sw/lv_draw_sw.h | 78 + src/lib/lvgl/src/draw/sw/lv_draw_sw_blend.h | 69 + src/lib/lvgl/src/draw/sw/lv_draw_sw_dither.h | 70 + .../lvgl/src/draw/sw/lv_draw_sw_gradient.h | 97 + src/lib/lvgl/src/extra/layouts/flex/lv_flex.h | 153 ++ src/lib/lvgl/src/extra/layouts/grid/lv_grid.h | 194 ++ src/lib/lvgl/src/extra/layouts/lv_layouts.h | 44 + src/lib/lvgl/src/extra/libs/bmp/lv_bmp.h | 42 + .../lvgl/src/extra/libs/ffmpeg/lv_ffmpeg.h | 104 + .../src/extra/libs/freetype/lv_freetype.h | 83 + src/lib/lvgl/src/extra/libs/fsdrv/lv_fsdrv.h | 55 + src/lib/lvgl/src/extra/libs/gif/gifdec.h | 60 + src/lib/lvgl/src/extra/libs/gif/lv_gif.h | 58 + src/lib/lvgl/src/extra/libs/lv_libs.h | 46 + src/lib/lvgl/src/extra/libs/png/lodepng.h | 1981 +++++++++++++++ src/lib/lvgl/src/extra/libs/png/lv_png.h | 46 + .../lvgl/src/extra/libs/qrcode/lv_qrcode.h | 69 + .../lvgl/src/extra/libs/qrcode/qrcodegen.h | 319 +++ .../lvgl/src/extra/libs/rlottie/lv_rlottie.h | 75 + src/lib/lvgl/src/extra/libs/sjpg/lv_sjpg.h | 43 + src/lib/lvgl/src/extra/libs/sjpg/tjpgd.h | 93 + src/lib/lvgl/src/extra/libs/sjpg/tjpgdcnf.h | 33 + src/lib/lvgl/src/extra/lv_extra.h | 42 + .../src/extra/others/fragment/lv_fragment.h | 339 +++ .../src/extra/others/gridnav/lv_gridnav.h | 115 + .../src/extra/others/imgfont/lv_imgfont.h | 60 + src/lib/lvgl/src/extra/others/lv_others.h | 40 + .../lvgl/src/extra/others/monkey/lv_monkey.h | 118 + .../src/extra/others/snapshot/lv_snapshot.h | 84 + .../src/extra/themes/basic/lv_theme_basic.h | 55 + .../extra/themes/default/lv_theme_default.h | 64 + src/lib/lvgl/src/extra/themes/lv_themes.h | 40 + .../src/extra/themes/mono/lv_theme_mono.h | 57 + .../src/extra/widgets/animimg/lv_animimg.h | 103 + .../src/extra/widgets/calendar/lv_calendar.h | 164 ++ .../calendar/lv_calendar_header_arrow.h | 49 + .../calendar/lv_calendar_header_dropdown.h | 49 + .../lvgl/src/extra/widgets/chart/lv_chart.h | 456 ++++ .../extra/widgets/colorwheel/lv_colorwheel.h | 142 ++ .../lvgl/src/extra/widgets/imgbtn/lv_imgbtn.h | 131 + .../src/extra/widgets/keyboard/lv_keyboard.h | 187 ++ src/lib/lvgl/src/extra/widgets/led/lv_led.h | 116 + src/lib/lvgl/src/extra/widgets/list/lv_list.h | 54 + src/lib/lvgl/src/extra/widgets/lv_widgets.h | 56 + src/lib/lvgl/src/extra/widgets/menu/lv_menu.h | 233 ++ .../lvgl/src/extra/widgets/meter/lv_meter.h | 267 ++ .../lvgl/src/extra/widgets/msgbox/lv_msgbox.h | 99 + src/lib/lvgl/src/extra/widgets/span/lv_span.h | 230 ++ .../src/extra/widgets/spinbox/lv_spinbox.h | 178 ++ .../src/extra/widgets/spinner/lv_spinner.h | 50 + .../src/extra/widgets/tabview/lv_tabview.h | 63 + .../src/extra/widgets/tileview/lv_tileview.h | 72 + src/lib/lvgl/src/extra/widgets/win/lv_win.h | 51 + src/lib/lvgl/src/font/lv_font.h | 258 ++ src/lib/lvgl/src/font/lv_font_fmt_txt.h | 240 ++ src/lib/lvgl/src/font/lv_font_loader.h | 40 + src/lib/lvgl/src/font/lv_symbol_def.h | 353 +++ src/lib/lvgl/src/hal/lv_hal.h | 48 + src/lib/lvgl/src/hal/lv_hal_disp.h | 364 +++ src/lib/lvgl/src/hal/lv_hal_indev.h | 239 ++ src/lib/lvgl/src/hal/lv_hal_tick.h | 69 + src/lib/lvgl/src/lv_api_map.h | 88 + src/lib/lvgl/src/lv_conf_internal.h | 2255 +++++++++++++++++ src/lib/lvgl/src/lv_conf_kconfig.h | 182 ++ src/lib/lvgl/src/lvgl.h | 39 + src/lib/lvgl/src/misc/lv_anim.h | 463 ++++ src/lib/lvgl/src/misc/lv_anim_timeline.h | 103 + src/lib/lvgl/src/misc/lv_area.h | 293 +++ src/lib/lvgl/src/misc/lv_assert.h | 79 + src/lib/lvgl/src/misc/lv_async.h | 54 + src/lib/lvgl/src/misc/lv_bidi.h | 141 ++ src/lib/lvgl/src/misc/lv_color.h | 712 ++++++ src/lib/lvgl/src/misc/lv_fs.h | 262 ++ src/lib/lvgl/src/misc/lv_gc.h | 96 + src/lib/lvgl/src/misc/lv_ll.h | 167 ++ src/lib/lvgl/src/misc/lv_log.h | 143 ++ src/lib/lvgl/src/misc/lv_lru.h | 81 + src/lib/lvgl/src/misc/lv_math.h | 143 ++ src/lib/lvgl/src/misc/lv_mem.h | 243 ++ src/lib/lvgl/src/misc/lv_printf.h | 92 + src/lib/lvgl/src/misc/lv_style.h | 525 ++++ src/lib/lvgl/src/misc/lv_style_gen.h | 546 ++++ src/lib/lvgl/src/misc/lv_templ.h | 37 + src/lib/lvgl/src/misc/lv_timer.h | 164 ++ src/lib/lvgl/src/misc/lv_tlsf.h | 95 + src/lib/lvgl/src/misc/lv_txt.h | 264 ++ src/lib/lvgl/src/misc/lv_txt_ap.h | 49 + src/lib/lvgl/src/misc/lv_types.h | 94 + src/lib/lvgl/src/misc/lv_utils.h | 58 + src/lib/lvgl/src/widgets/lv_arc.h | 240 ++ src/lib/lvgl/src/widgets/lv_bar.h | 164 ++ src/lib/lvgl/src/widgets/lv_btn.h | 56 + src/lib/lvgl/src/widgets/lv_btnmatrix.h | 225 ++ src/lib/lvgl/src/widgets/lv_canvas.h | 280 ++ src/lib/lvgl/src/widgets/lv_checkbox.h | 97 + src/lib/lvgl/src/widgets/lv_dropdown.h | 246 ++ src/lib/lvgl/src/widgets/lv_img.h | 227 ++ src/lib/lvgl/src/widgets/lv_label.h | 246 ++ src/lib/lvgl/src/widgets/lv_line.h | 93 + src/lib/lvgl/src/widgets/lv_objx_templ.h | 81 + src/lib/lvgl/src/widgets/lv_roller.h | 133 + src/lib/lvgl/src/widgets/lv_slider.h | 195 ++ src/lib/lvgl/src/widgets/lv_switch.h | 61 + src/lib/lvgl/src/widgets/lv_table.h | 210 ++ src/lib/lvgl/src/widgets/lv_textarea.h | 343 +++ 147 files changed, 26288 insertions(+) create mode 100644 src/cortex-m0plus/liblvgl.a create mode 100644 src/lib/lvgl/lvgl.h create mode 100644 src/lib/lvgl/src/core/lv_disp.h create mode 100644 src/lib/lvgl/src/core/lv_event.h create mode 100644 src/lib/lvgl/src/core/lv_group.h create mode 100644 src/lib/lvgl/src/core/lv_indev.h create mode 100644 src/lib/lvgl/src/core/lv_indev_scroll.h create mode 100644 src/lib/lvgl/src/core/lv_obj.h create mode 100644 src/lib/lvgl/src/core/lv_obj_class.h create mode 100644 src/lib/lvgl/src/core/lv_obj_draw.h create mode 100644 src/lib/lvgl/src/core/lv_obj_pos.h create mode 100644 src/lib/lvgl/src/core/lv_obj_scroll.h create mode 100644 src/lib/lvgl/src/core/lv_obj_style.h create mode 100644 src/lib/lvgl/src/core/lv_obj_style_gen.h create mode 100644 src/lib/lvgl/src/core/lv_obj_tree.h create mode 100644 src/lib/lvgl/src/core/lv_refr.h create mode 100644 src/lib/lvgl/src/core/lv_theme.h create mode 100644 src/lib/lvgl/src/draw/arm2d/lv_gpu_arm2d.h create mode 100644 src/lib/lvgl/src/draw/lv_draw.h create mode 100644 src/lib/lvgl/src/draw/lv_draw_arc.h create mode 100644 src/lib/lvgl/src/draw/lv_draw_img.h create mode 100644 src/lib/lvgl/src/draw/lv_draw_label.h create mode 100644 src/lib/lvgl/src/draw/lv_draw_line.h create mode 100644 src/lib/lvgl/src/draw/lv_draw_mask.h create mode 100644 src/lib/lvgl/src/draw/lv_draw_rect.h create mode 100644 src/lib/lvgl/src/draw/lv_draw_triangle.h create mode 100644 src/lib/lvgl/src/draw/lv_img_buf.h create mode 100644 src/lib/lvgl/src/draw/lv_img_cache.h create mode 100644 src/lib/lvgl/src/draw/lv_img_decoder.h create mode 100644 src/lib/lvgl/src/draw/nxp_pxp/lv_gpu_nxp_pxp.h create mode 100644 src/lib/lvgl/src/draw/nxp_pxp/lv_gpu_nxp_pxp_osa.h create mode 100644 src/lib/lvgl/src/draw/nxp_vglite/lv_gpu_nxp_vglite.h create mode 100644 src/lib/lvgl/src/draw/sdl/lv_draw_sdl.h create mode 100644 src/lib/lvgl/src/draw/sdl/lv_draw_sdl_composite.h create mode 100644 src/lib/lvgl/src/draw/sdl/lv_draw_sdl_img.h create mode 100644 src/lib/lvgl/src/draw/sdl/lv_draw_sdl_mask.h create mode 100644 src/lib/lvgl/src/draw/sdl/lv_draw_sdl_priv.h create mode 100644 src/lib/lvgl/src/draw/sdl/lv_draw_sdl_rect.h create mode 100644 src/lib/lvgl/src/draw/sdl/lv_draw_sdl_stack_blur.h create mode 100644 src/lib/lvgl/src/draw/sdl/lv_draw_sdl_texture_cache.h create mode 100644 src/lib/lvgl/src/draw/sdl/lv_draw_sdl_utils.h create mode 100644 src/lib/lvgl/src/draw/stm32_dma2d/lv_gpu_stm32_dma2d.h create mode 100644 src/lib/lvgl/src/draw/sw/lv_draw_sw.h create mode 100644 src/lib/lvgl/src/draw/sw/lv_draw_sw_blend.h create mode 100644 src/lib/lvgl/src/draw/sw/lv_draw_sw_dither.h create mode 100644 src/lib/lvgl/src/draw/sw/lv_draw_sw_gradient.h create mode 100644 src/lib/lvgl/src/extra/layouts/flex/lv_flex.h create mode 100644 src/lib/lvgl/src/extra/layouts/grid/lv_grid.h create mode 100644 src/lib/lvgl/src/extra/layouts/lv_layouts.h create mode 100644 src/lib/lvgl/src/extra/libs/bmp/lv_bmp.h create mode 100644 src/lib/lvgl/src/extra/libs/ffmpeg/lv_ffmpeg.h create mode 100644 src/lib/lvgl/src/extra/libs/freetype/lv_freetype.h create mode 100644 src/lib/lvgl/src/extra/libs/fsdrv/lv_fsdrv.h create mode 100644 src/lib/lvgl/src/extra/libs/gif/gifdec.h create mode 100644 src/lib/lvgl/src/extra/libs/gif/lv_gif.h create mode 100644 src/lib/lvgl/src/extra/libs/lv_libs.h create mode 100644 src/lib/lvgl/src/extra/libs/png/lodepng.h create mode 100644 src/lib/lvgl/src/extra/libs/png/lv_png.h create mode 100644 src/lib/lvgl/src/extra/libs/qrcode/lv_qrcode.h create mode 100644 src/lib/lvgl/src/extra/libs/qrcode/qrcodegen.h create mode 100644 src/lib/lvgl/src/extra/libs/rlottie/lv_rlottie.h create mode 100644 src/lib/lvgl/src/extra/libs/sjpg/lv_sjpg.h create mode 100644 src/lib/lvgl/src/extra/libs/sjpg/tjpgd.h create mode 100644 src/lib/lvgl/src/extra/libs/sjpg/tjpgdcnf.h create mode 100644 src/lib/lvgl/src/extra/lv_extra.h create mode 100644 src/lib/lvgl/src/extra/others/fragment/lv_fragment.h create mode 100644 src/lib/lvgl/src/extra/others/gridnav/lv_gridnav.h create mode 100644 src/lib/lvgl/src/extra/others/imgfont/lv_imgfont.h create mode 100644 src/lib/lvgl/src/extra/others/lv_others.h create mode 100755 src/lib/lvgl/src/extra/others/monkey/lv_monkey.h create mode 100644 src/lib/lvgl/src/extra/others/snapshot/lv_snapshot.h create mode 100644 src/lib/lvgl/src/extra/themes/basic/lv_theme_basic.h create mode 100644 src/lib/lvgl/src/extra/themes/default/lv_theme_default.h create mode 100644 src/lib/lvgl/src/extra/themes/lv_themes.h create mode 100644 src/lib/lvgl/src/extra/themes/mono/lv_theme_mono.h create mode 100644 src/lib/lvgl/src/extra/widgets/animimg/lv_animimg.h create mode 100644 src/lib/lvgl/src/extra/widgets/calendar/lv_calendar.h create mode 100644 src/lib/lvgl/src/extra/widgets/calendar/lv_calendar_header_arrow.h create mode 100644 src/lib/lvgl/src/extra/widgets/calendar/lv_calendar_header_dropdown.h create mode 100644 src/lib/lvgl/src/extra/widgets/chart/lv_chart.h create mode 100644 src/lib/lvgl/src/extra/widgets/colorwheel/lv_colorwheel.h create mode 100644 src/lib/lvgl/src/extra/widgets/imgbtn/lv_imgbtn.h create mode 100644 src/lib/lvgl/src/extra/widgets/keyboard/lv_keyboard.h create mode 100644 src/lib/lvgl/src/extra/widgets/led/lv_led.h create mode 100644 src/lib/lvgl/src/extra/widgets/list/lv_list.h create mode 100644 src/lib/lvgl/src/extra/widgets/lv_widgets.h create mode 100644 src/lib/lvgl/src/extra/widgets/menu/lv_menu.h create mode 100644 src/lib/lvgl/src/extra/widgets/meter/lv_meter.h create mode 100644 src/lib/lvgl/src/extra/widgets/msgbox/lv_msgbox.h create mode 100644 src/lib/lvgl/src/extra/widgets/span/lv_span.h create mode 100644 src/lib/lvgl/src/extra/widgets/spinbox/lv_spinbox.h create mode 100644 src/lib/lvgl/src/extra/widgets/spinner/lv_spinner.h create mode 100644 src/lib/lvgl/src/extra/widgets/tabview/lv_tabview.h create mode 100644 src/lib/lvgl/src/extra/widgets/tileview/lv_tileview.h create mode 100644 src/lib/lvgl/src/extra/widgets/win/lv_win.h create mode 100644 src/lib/lvgl/src/font/lv_font.h create mode 100644 src/lib/lvgl/src/font/lv_font_fmt_txt.h create mode 100644 src/lib/lvgl/src/font/lv_font_loader.h create mode 100644 src/lib/lvgl/src/font/lv_symbol_def.h create mode 100644 src/lib/lvgl/src/hal/lv_hal.h create mode 100644 src/lib/lvgl/src/hal/lv_hal_disp.h create mode 100644 src/lib/lvgl/src/hal/lv_hal_indev.h create mode 100644 src/lib/lvgl/src/hal/lv_hal_tick.h create mode 100644 src/lib/lvgl/src/lv_api_map.h create mode 100644 src/lib/lvgl/src/lv_conf_internal.h create mode 100644 src/lib/lvgl/src/lv_conf_kconfig.h create mode 100644 src/lib/lvgl/src/lvgl.h create mode 100644 src/lib/lvgl/src/misc/lv_anim.h create mode 100644 src/lib/lvgl/src/misc/lv_anim_timeline.h create mode 100644 src/lib/lvgl/src/misc/lv_area.h create mode 100644 src/lib/lvgl/src/misc/lv_assert.h create mode 100644 src/lib/lvgl/src/misc/lv_async.h create mode 100644 src/lib/lvgl/src/misc/lv_bidi.h create mode 100644 src/lib/lvgl/src/misc/lv_color.h create mode 100644 src/lib/lvgl/src/misc/lv_fs.h create mode 100644 src/lib/lvgl/src/misc/lv_gc.h create mode 100644 src/lib/lvgl/src/misc/lv_ll.h create mode 100644 src/lib/lvgl/src/misc/lv_log.h create mode 100644 src/lib/lvgl/src/misc/lv_lru.h create mode 100644 src/lib/lvgl/src/misc/lv_math.h create mode 100644 src/lib/lvgl/src/misc/lv_mem.h create mode 100644 src/lib/lvgl/src/misc/lv_printf.h create mode 100644 src/lib/lvgl/src/misc/lv_style.h create mode 100644 src/lib/lvgl/src/misc/lv_style_gen.h create mode 100644 src/lib/lvgl/src/misc/lv_templ.h create mode 100644 src/lib/lvgl/src/misc/lv_timer.h create mode 100644 src/lib/lvgl/src/misc/lv_tlsf.h create mode 100644 src/lib/lvgl/src/misc/lv_txt.h create mode 100644 src/lib/lvgl/src/misc/lv_txt_ap.h create mode 100644 src/lib/lvgl/src/misc/lv_types.h create mode 100644 src/lib/lvgl/src/misc/lv_utils.h create mode 100644 src/lib/lvgl/src/widgets/lv_arc.h create mode 100644 src/lib/lvgl/src/widgets/lv_bar.h create mode 100644 src/lib/lvgl/src/widgets/lv_btn.h create mode 100644 src/lib/lvgl/src/widgets/lv_btnmatrix.h create mode 100644 src/lib/lvgl/src/widgets/lv_canvas.h create mode 100644 src/lib/lvgl/src/widgets/lv_checkbox.h create mode 100644 src/lib/lvgl/src/widgets/lv_dropdown.h create mode 100644 src/lib/lvgl/src/widgets/lv_img.h create mode 100644 src/lib/lvgl/src/widgets/lv_label.h create mode 100644 src/lib/lvgl/src/widgets/lv_line.h create mode 100644 src/lib/lvgl/src/widgets/lv_objx_templ.h create mode 100644 src/lib/lvgl/src/widgets/lv_roller.h create mode 100644 src/lib/lvgl/src/widgets/lv_slider.h create mode 100644 src/lib/lvgl/src/widgets/lv_switch.h create mode 100644 src/lib/lvgl/src/widgets/lv_table.h create mode 100644 src/lib/lvgl/src/widgets/lv_textarea.h diff --git a/src/cortex-m0plus/liblvgl.a b/src/cortex-m0plus/liblvgl.a new file mode 100644 index 0000000000000000000000000000000000000000..1fc5660c317809499b8d874e001290c8d71b298b GIT binary patch literal 854756 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

ppLlJ{w1x|A87$dHKLKN1Cy5J(JJ*Mx|E= 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�J1mnMGwFI@atw* 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%0A9$1 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�h?W>F(=3%Yc#9iX4 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� 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�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

uD*=J~en!ud}+MKq55gDcP!psM<(c*7s zw6-KspX^z5Co$4xV5H77-w69f{{9=8KUPD_8z^ zT;ybXV;apR4BJ7ZGIPWYP1-Y4WVL7J6SJB1|NHE*j?<0VKIq@M+Q&u8uUZhP?!dpf z)})3RE~yz;>OX}a9kJ`<@7vnPAUI@OFqP?_wS8O!1GZIDnf6e8d=P2j3cZ3eYd;%{ z`d0sA$BdEfXWZDa>f;B<6K+Mn4;5-3yib{YK)p9jT<0eT&Y!Y&e{YeARg!w`+K2my znaI=Eq$J;X@9{F>j`zM&)~`rm^%tgo)O$hdg5*JtZ1IncT(>+F@CJ?~9df+fdwO!3 zW1q7mnJ@M(NUes1z90L(^3l#>Bdva-57PeXpZ7)W|Kvpz2l)AcIE3eGpq)Ddc)?hH z-G~>(_XVmQ^?~3zb<=C9WAJ+6c8NZ6ozn-asTiTwER=Q@@BLWH&O<4|4*mL~_iL%e z$sG-kr{0i%qWARF>B$=$vz;p4pCjF7_`n@j(LUET?LgP@75f8cPInR0I#o)t4dUha zd-n5|Chf%xyhOnlO$|Ct9YHpV%B+dIK=Wil|D@}|&|5T=fm z(^Q$B+5?+PdkC9b3?UZVC3=rqR53)ZPknBe*dR;5EzT=suJLE)E)bcb)}2x`Wc{Lw z#9{qgZKJOln6OF=`@AjFV*^5T&$>OO8IXFpXJ(>AT_0`85MJpo-Yv&U+BSO6I_2We zZO6M9AG04IzE41sarmxG{|rZ~Ta?K-*fOGUZ$@GLbZr!UN6c&;HsVy9YAw9k@!mHd z>HIM5$eJV)<$VR=PTZ?Fmv=ZQciJXm3X>0{XVVuIf0tn2MthW%sa}Z>Vz;B0=r7jp7sIm9 zN>%*4>nkfpt->wQVO6aw(i4YW5K(tnGcrA_J7Pq78~3^P%p4_@{Oh9)g@&p@=*?bu z-Ut|v8oMOovwMAdr>z}tdGjuSN;k&)oDamuP8)7n`eo~j^Tt8SmlSXM5K+ zelz;vqwz4N=}f~wEax>t%7 z!-tEuKLj)J|Igqs{15N2;s5duJN^qh;_?4gFbe-)1bg9sP)Be4Khe<>|4B#s;@@+m z|8Pj|9{z^j84T|mLP~Yp#YY??f2~b=?K9XZ5xA)Cod~?2$xOZn&bGeL-2W@ZLFwBA!3OV1{S$@9Wh2+Sp z;v7A&6um&UxGK~OOvP86HZ`S;3h$Lgy&f}rfeF}sQaK|$d&;tWfA7>S4LzmsWXe`& z<_Kx=R~@inh9}w%cQSr4GS8whvSxMIGi+_A8gkaFI%Uh4*Q&mvGUl}Q!fpRk4S7a7 zeCQ?jeV>!zxxRWDwLV%j_))kh`u@OP`*^ou4OXuI^;N!~Q8!#_ zN>g*|4QHOw#``WRO-DA~T0dU+v1`109pvhnk zR2K&fzi}DXj#mTeZX46;u!$3qm$| zLtOB~(nPd1+o%lz8{WN0ZoND2A8nAt{@x*{7~Z4pq$4Ug>RQ{F-Ff|6Q|BgPZZ$Sl zK>GXVFP0BH>3|Tc;JUnjw9>}*yl83TGuZgJ>uJYHgpYZ4DDOEoXF?v!%cZ`CcHEVS zlO{gK)wo)|%IO-Fs6R%VA35g781sY6x^GnnyDyVN_S%N75&y=?-GA#IK^8pJdjxKL z#*CdYV#*KQ9SE;K8OiV8A23(Nw5|37P>&)M6yOFoUlc8TTFLgdF}?LAMF~c2LuQS14Ol{Dw#HKY_gw;2(;JPq=<4`>mn+qSE_e z1kb$tD1v9W<707W16wa<_~qO*lS=vLi{P1mtCF-a;!pq9MesB~7{Sw=GQ*Uz<`?Ha zkqQxsQ0Kaz@KA&~>&7oF{J&fH_bmKL3;%_MPmG8n{pWs&smOER!&Kz2u<)}j{H+%L zE(^ci!ar!?u_Os8hG&)c`;NuD)53pc;d_PZp4uNBV&NnAgBjjbi}_*;|6>b(w}szh z;h(ec?^yVg7XBLx-zU@-RQ%l*p7#~nP`|lX&GW5X@E?P>BOl0LXR$xm!c$J7shIwi z7XD7~e?wa-gc<$2-(tSk!arl-+bsMM3r}pIsTh7tsI98>IxYNg3xBzVzs|z*jZah2 z{|y%YXBPfh3;#O{-wu8~+P9e>r!D3^kypQm`4EJ~{Gxowe}HE{M*ec}H}(kMPq-HR zdhk4NqWLoLR4h;4A6N&T-zL9Zo6`={v&X`7KiS-ne8p18Ouc2Hc@IFJ9ZDoQu*3^i&#SBu^0oj#v3Rr_pjkXyKPDWE^=woHt|89y zU@*dNi07%DjGEs6R$^JZ9V(hfjp36^Q%7GCFoE?qRxhXq9)F%3#OFy)7 zdp62HEL^!eI{$mo`^edFNYX8D0T3^JHl{ypF@(ssUbhH`&IIZT8$PSn8Y~m@vGeW% zrNhs`M!nR@hLYR%);~v(C(EI9a6Rio+ToBEL!2#QExB>#&CT z8n;yjWu1A&DrOo2pk+h*U1W zG5mZxBN1-s+J)}>5SN9rxt~KDsD628A;QQke#Gr8UGqVEZJ@FIOXlNPE^Ix7EwC7~ zxRe=(kHn!`zB49=oF7tN^8`(=A|0mAvM6tu^H<7?eSma0ut}Q!niTF{*YuC1BZLT& z0>tnYDZ)v{ynvWpi9djTF8OTS9U#SV=>k&tQ>&?u6#g`5{y#`@04H$=@UI8vE5!0T zNXKB`gcPeg&Z~&+<-I)0O}>hB9Nxgy`ir#wGOhm;t=|A@$F!L8pzWAU^M0s(Jkm*X zWD4g~q%V<91QwX|5-l$p>EZl|Sp9g+D~QeK+QRO|yp|OBjSNx@oZ~=wR{)P1|{E%)WG;o3iks^ z5zmpN$mdHmm3JRd4pQFq6?k)+`p7RIDfG9I7GfQw`KL9{wGh+yE_vj~pGc7(Tmw;G z-j!fEW1hf#;r&VG%PP`heK!J?teN~2$luoXULl93^uh)W#kWXyX=5ubjfNLMB)(wRqk1?E+xsPBt3ttFiXj5{gv zOUkDPeL?fDYWfW+{Oc7DT8Q>UYM|Un5#AWm41}X;5h?6fkY0iMP6~UskzNDb8R>MC zv(|rrbO!RDbS5w_eA9gkdBmex(}y*c^0nvVt_1lk$f+kqfA$S2;z5iP%O{?+82*t$|2D0^jTG*v z>{V(mYzOWtoqRRoOWIFiX(%`SU&lZF-^KLrM0!kxrYjZqeo(w3S8~|Laq4yq-i9CT z#p5?v^HHEwtr32ar(G&$7wvzaJ!HFdgX$?2{lgFtQVf@VqFGCdE>|h^*J#QiWu^n& zL$`DkT%gA}=%Xr!(t%=@{xN*2aqtgaQb;jO{?Lq=hFa5r@4E~)8BjC5q@lRs`zhGl zg#eTAjV2|-O$KEin|XpyF%$I$Vv9n`^sf(eBJC|fIu?X%g~P@8zj8@6E)xDgOvptS zXa8VKNEPA+6~crN({IX!?1BBZg9olj7FknTz4f*UB~HHd$d?rd0I^=_bK?J~@1Q#a zXTuxh+3-QgTN+f9Axv(K;f~5fwIx zmDXFwdkfbSV-SVY+=Fgn3>2y$*{x5lT-+bGxzEptdSB@zzbK?$KX;-$VYUVSj{WS& zHyHmg^}zmY;A*5xoP}Q0?JQLJVxHirU3Z^xhhf8c!=WJ2Bgq|oaGrBxhYkOWI_wwb zw8rD>fnXH={lQ-NU)?bb|95uu#s6I$JueikpLQsJqgL5Hsp6jeK9G(TIFd54F~1#> zxL<6m%Q*?egELRG{^+QTmuJ#Ib!s6z=_ozw?d{51F0y_h@hs{b!j`eC&C`-9aPlNi zL?H!wMb`4{(U4u$HucEx z#k=yNuz@mdviM-8;jG#XT?1!9>E(=NIBl17)eW(ETIOaz?qJKcI19X<<|>XVt>Kdp zoHMo#>f)K2Tc0YiROTHKx=sw}Liyk=WR>GBRcQV=U)mMyH}uc*s=O!XcpmfmvP4zR z9Gu-%_?qh>QQg;GKSAiXTswk6T8;~Q~da|=D=j5F7i@bOVae}DC z+lu4G9^Xm0KHJ?poqaC+O)KgLTfg0`JMP5_vj3J$bq##rf8G zha7Wqm%v6!AR+CI-X%EoPD@R5zIR@Uqd1pRmBss+N3uj6&Ory|WL>W$Bd^x6t@BWx zZ4zYNW(k@u#p&!0<2pzKFVp8@HRzM9?Uw1{&+b_}P}OVEI<2$Ly%RN?yqXC;y`4l`K{A&q-e0BRc4Q23(xRH^pjt zyLdS@1GpE)?j~XP`%>59obbh^XB&ZGJJxK5u3Iz?6NdS?MDJw)%U~PLk52eE)g8Kg#{>FX+5`50jjwv9-vimqQIP0rZ!E>T&a&iX3viRt;q-U6V^>OGIm z;O!^W;6~8)`q{=?KE~>x*Ke<^6y81Mdn#w3pEz0`+p?(KJ71P9>f%d5k8mO!^3x%c zEmoeqdqkSnyY9HtT~(GE$aTy%>_cChmy4dkE??jMn@04x93Sa3**jBjN*)`??Xu(5 z+#2tPWp^MKU+G+g+T4_v_kM-vv9h!@VlJj9r=(8TwR#!qdrDxC^Jwq1RMcumNw-@4 zYA{O_8LYJ@A*1x(Np&v}hmObrSd8#QUSWuAbbleKEh=FNCx@md}Ms-(4P8Pd3^apQ){kO&;n>xMsAUX00ffwPK_wsV^V9Qr3xaz@xBE z^n3J_u30v3>|W1&r`v-%yQjPpb%XgaT6`nX7swYqUOjw_y$W;8?tN7DAyc7KWXL?6 z>&!oKt#K^RV2YpbS_|2YF3}=;#EHjPm!FVl&o&WNNZ(b@?*ckZK-J;w-1Z%J*=T2d z9RB`4I4eGeWb!O?An2R;DW%RTX=d_nd>qHG2tV4#wv2qgb1(AAbbnhkG^JARw@2{w z{}}UBDrFwcxtZo^&ULR+%KXy^-ZUZQ*)i>hRm6lFn&-M3cSYE;Jo~_MGo(0=uL*H# zJ$RdiZ?NzWTli-z{OcC}PZs{K7T#tHYcM`37T#;&M_Kqh3(q@2rlNn>TliHLexrro zY2o)-_?ImFe_HqtEj;hhnTqjoMl7z#kGJqwTlj?*{&ov*l?C^p#rzoy{|5{I9{3MX z->__uXK5!a=Jtri8{_K${}0&5)`zrDoB5ls5vY!B~Velq2&{BYeQ{t!EcuE1@$8Gk-#- zU8Y8OW1l+R@BNu}zWWU1oF^6f7>Q>ML+4j0 zsL+YW4?H1ZAkt0bfl9~|)-1Dpq==$$p_rv)(bjUj;LfbK$bq`hP0t^GZm69@j1ppV z{q^dQ#q`rW6k#OPsfUv1%6pRqXlta{YL&EH(`A~n52yK8q}bmhmWh~NAyN3Mv*b5@X0Q5d7_Hl?KNpxZSB6TA?QV+&O^dY=o zNjaH(Uo)K)@fk!q82e77Lool+`trO3=F>D^s_9Qj5ifaeF%;u8d4xlGmE7O`kTgTT zcR39AImvtUyO#(*5q%Nk%|46gKto6of8sm14_Z!&O)&YsCHNhhe~c9VQ@$+ydx;e3 zc$F0KZzV0q35k-~kySkP=CT%@CL zjzfx#%Q{lz*E&+<^A^$^q(k%1k)k|aAsvGF#DSt7ZiDn9{5VdGMR=s} zZy+iB%h3EXZN5(P4Ww}YQ&PD94^oud5mL`4ymbD-^9VzgFOi?pap?sri5SokzK0$_PWDxTUi0Rey*C@U2!PMefJa9+G<2 zUiBDSh)`&DQlSb<`|v`lZ?lIimj0u;gzTZ(gp?USRFQ6b(4Y5J^8^NusubFTMiEH= zXrGGbFX!5Wo(wa@tyWsX-~F)nL-wF4OG~ynxIuOP);;K**sCrw6Ayc4zObr9Xp3a5 z{jPP=tE~Egd(b(f$BvU16o0_IM9TGo>b3`M114BhmE`4DaIHpJB$M

ER>eh=St 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 literal 0 HcmV?d00001 diff --git a/src/lib/lvgl/lvgl.h b/src/lib/lvgl/lvgl.h new file mode 100644 index 0000000..df96d21 --- /dev/null +++ b/src/lib/lvgl/lvgl.h @@ -0,0 +1,143 @@ +/** + * @file lvgl.h + * Include all LVGL related headers + */ + +#ifndef LVGL_H +#define LVGL_H + +#ifdef __cplusplus +extern "C" { +#endif + +/*************************** + * CURRENT VERSION OF LVGL + ***************************/ +#define LVGL_VERSION_MAJOR 8 +#define LVGL_VERSION_MINOR 2 +#define LVGL_VERSION_PATCH 0 +#define LVGL_VERSION_INFO "" + +/********************* + * INCLUDES + *********************/ + +#include "src/misc/lv_log.h" +#include "src/misc/lv_timer.h" +#include "src/misc/lv_math.h" +#include "src/misc/lv_mem.h" +#include "src/misc/lv_async.h" +#include "src/misc/lv_anim_timeline.h" +#include "src/misc/lv_printf.h" + +#include "src/hal/lv_hal.h" + +#include "src/core/lv_obj.h" +#include "src/core/lv_group.h" +#include "src/core/lv_indev.h" +#include "src/core/lv_refr.h" +#include "src/core/lv_disp.h" +#include "src/core/lv_theme.h" + +#include "src/font/lv_font.h" +#include "src/font/lv_font_loader.h" +#include "src/font/lv_font_fmt_txt.h" + +#include "src/widgets/lv_arc.h" +#include "src/widgets/lv_btn.h" +#include "src/widgets/lv_img.h" +#include "src/widgets/lv_label.h" +#include "src/widgets/lv_line.h" +#include "src/widgets/lv_table.h" +#include "src/widgets/lv_checkbox.h" +#include "src/widgets/lv_bar.h" +#include "src/widgets/lv_slider.h" +#include "src/widgets/lv_btnmatrix.h" +#include "src/widgets/lv_dropdown.h" +#include "src/widgets/lv_roller.h" +#include "src/widgets/lv_textarea.h" +#include "src/widgets/lv_canvas.h" +#include "src/widgets/lv_switch.h" + +#include "src/draw/lv_draw.h" + +#include "src/lv_api_map.h" + +/*----------------- + * EXTRAS + *----------------*/ +#include "src/extra/lv_extra.h" +#include "src/extra/widgets/lv_widgets.h" +#include "src/extra/layouts/lv_layouts.h" +#include "src/extra/themes/lv_themes.h" +#include "src/extra/others/lv_others.h" +#include "src/extra/libs/lv_libs.h" + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +/********************** + * MACROS + **********************/ + +/** Gives 1 if the x.y.z version is supported in the current version + * Usage: + * + * - Require v6 + * #if LV_VERSION_CHECK(6,0,0) + * new_func_in_v6(); + * #endif + * + * + * - Require at least v5.3 + * #if LV_VERSION_CHECK(5,3,0) + * new_feature_from_v5_3(); + * #endif + * + * + * - Require v5.3.2 bugfixes + * #if LV_VERSION_CHECK(5,3,2) + * bugfix_in_v5_3_2(); + * #endif + * + */ +#define LV_VERSION_CHECK(x,y,z) (x == LVGL_VERSION_MAJOR && (y < LVGL_VERSION_MINOR || (y == LVGL_VERSION_MINOR && z <= LVGL_VERSION_PATCH))) + +/** + * Wrapper functions for VERSION macros + */ + +static inline int lv_version_major(void) +{ + return LVGL_VERSION_MAJOR; +} + +static inline int lv_version_minor(void) +{ + return LVGL_VERSION_MINOR; +} + +static inline int lv_version_patch(void) +{ + return LVGL_VERSION_PATCH; +} + +static inline const char *lv_version_info(void) +{ + return LVGL_VERSION_INFO; +} + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif /*LVGL_H*/ diff --git a/src/lib/lvgl/src/core/lv_disp.h b/src/lib/lvgl/src/core/lv_disp.h new file mode 100644 index 0000000..01766b3 --- /dev/null +++ b/src/lib/lvgl/src/core/lv_disp.h @@ -0,0 +1,244 @@ +/** + * @file lv_disp.h + * + */ + +#ifndef LV_DISP_H +#define LV_DISP_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include "../hal/lv_hal.h" +#include "lv_obj.h" +#include "lv_theme.h" + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +typedef enum { + LV_SCR_LOAD_ANIM_NONE, + LV_SCR_LOAD_ANIM_OVER_LEFT, + LV_SCR_LOAD_ANIM_OVER_RIGHT, + LV_SCR_LOAD_ANIM_OVER_TOP, + LV_SCR_LOAD_ANIM_OVER_BOTTOM, + LV_SCR_LOAD_ANIM_MOVE_LEFT, + LV_SCR_LOAD_ANIM_MOVE_RIGHT, + LV_SCR_LOAD_ANIM_MOVE_TOP, + LV_SCR_LOAD_ANIM_MOVE_BOTTOM, + LV_SCR_LOAD_ANIM_FADE_ON, +} lv_scr_load_anim_t; + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +/** + * Return with a pointer to the active screen + * @param disp pointer to display which active screen should be get. (NULL to use the default + * screen) + * @return pointer to the active screen object (loaded by 'lv_scr_load()') + */ +lv_obj_t * lv_disp_get_scr_act(lv_disp_t * disp); + +/** + * Return with a pointer to the previous screen. Only used during screen transitions. + * @param disp pointer to display which previous screen should be get. (NULL to use the default + * screen) + * @return pointer to the previous screen object or NULL if not used now + */ +lv_obj_t * lv_disp_get_scr_prev(lv_disp_t * disp); + +/** + * Make a screen active + * @param scr pointer to a screen + */ +void lv_disp_load_scr(lv_obj_t * scr); + +/** + * Return with the top layer. (Same on every screen and it is above the normal screen layer) + * @param disp pointer to display which top layer should be get. (NULL to use the default screen) + * @return pointer to the top layer object (transparent screen sized lv_obj) + */ +lv_obj_t * lv_disp_get_layer_top(lv_disp_t * disp); + +/** + * Return with the sys. layer. (Same on every screen and it is above the normal screen and the top + * layer) + * @param disp pointer to display which sys. layer should be retrieved. (NULL to use the default screen) + * @return pointer to the sys layer object (transparent screen sized lv_obj) + */ +lv_obj_t * lv_disp_get_layer_sys(lv_disp_t * disp); + +/** + * Set the theme of a display + * @param disp pointer to a display + */ +void lv_disp_set_theme(lv_disp_t * disp, lv_theme_t * th); + +/** + * Get the theme of a display + * @param disp pointer to a display + * @return the display's theme (can be NULL) + */ +lv_theme_t * lv_disp_get_theme(lv_disp_t * disp); + +/** + * Set the background color of a display + * @param disp pointer to a display + * @param color color of the background + */ +void lv_disp_set_bg_color(lv_disp_t * disp, lv_color_t color); + +/** + * Set the background image of a display + * @param disp pointer to a display + * @param img_src path to file or pointer to an `lv_img_dsc_t` variable + */ +void lv_disp_set_bg_image(lv_disp_t * disp, const void * img_src); + +/** + * Set opacity of the background + * @param disp pointer to a display + * @param opa opacity (0..255) + */ +void lv_disp_set_bg_opa(lv_disp_t * disp, lv_opa_t opa); + +/** + * Switch screen with animation + * @param scr pointer to the new screen to load + * @param anim_type type of the animation from `lv_scr_load_anim_t`. E.g. `LV_SCR_LOAD_ANIM_MOVE_LEFT` + * @param time time of the animation + * @param delay delay before the transition + * @param auto_del true: automatically delete the old screen + */ +void lv_scr_load_anim(lv_obj_t * scr, lv_scr_load_anim_t anim_type, uint32_t time, uint32_t delay, bool auto_del); + +/** + * Get elapsed time since last user activity on a display (e.g. click) + * @param disp pointer to a display (NULL to get the overall smallest inactivity) + * @return elapsed ticks (milliseconds) since the last activity + */ +uint32_t lv_disp_get_inactive_time(const lv_disp_t * disp); + +/** + * Manually trigger an activity on a display + * @param disp pointer to a display (NULL to use the default display) + */ +void lv_disp_trig_activity(lv_disp_t * disp); + +/** + * Clean any CPU cache that is related to the display. + * @param disp pointer to a display (NULL to use the default display) + */ +void lv_disp_clean_dcache(lv_disp_t * disp); + +/** + * Get a pointer to the screen refresher timer to + * modify its parameters with `lv_timer_...` functions. + * @param disp pointer to a display + * @return pointer to the display refresher timer. (NULL on error) + */ +lv_timer_t * _lv_disp_get_refr_timer(lv_disp_t * disp); + +/*------------------------------------------------ + * To improve backward compatibility + * Recommended only if you have one display + *------------------------------------------------*/ + +/** + * Get the active screen of the default display + * @return pointer to the active screen + */ +static inline lv_obj_t * lv_scr_act(void) +{ + return lv_disp_get_scr_act(lv_disp_get_default()); +} + +/** + * Get the top layer of the default display + * @return pointer to the top layer + */ +static inline lv_obj_t * lv_layer_top(void) +{ + return lv_disp_get_layer_top(lv_disp_get_default()); +} + +/** + * Get the active screen of the default display + * @return pointer to the sys layer + */ +static inline lv_obj_t * lv_layer_sys(void) +{ + return lv_disp_get_layer_sys(lv_disp_get_default()); +} + +static inline void lv_scr_load(lv_obj_t * scr) +{ + lv_disp_load_scr(scr); +} + +/********************** + * MACROS + **********************/ + +/*------------------------------------------------ + * To improve backward compatibility + * Recommended only if you have one display + *------------------------------------------------*/ + +#ifndef LV_HOR_RES +/** + * The horizontal resolution of the currently active display. + */ +#define LV_HOR_RES lv_disp_get_hor_res(lv_disp_get_default()) +#endif + +#ifndef LV_VER_RES +/** + * The vertical resolution of the currently active display. + */ +#define LV_VER_RES lv_disp_get_ver_res(lv_disp_get_default()) +#endif + +/** + * Scale the given number of pixels (a distance or size) relative to a 160 DPI display + * considering the DPI of the default display. + * It ensures that e.g. `lv_dpx(100)` will have the same physical size regardless to the + * DPI of the display. + * @param n the number of pixels to scale + * @return `n x current_dpi/160` + */ +static inline lv_coord_t lv_dpx(lv_coord_t n) +{ + return LV_DPX(n); +} + +/** + * Scale the given number of pixels (a distance or size) relative to a 160 DPI display + * considering the DPI of the given display. + * It ensures that e.g. `lv_dpx(100)` will have the same physical size regardless to the + * DPI of the display. + * @param obj a display whose dpi should be considered + * @param n the number of pixels to scale + * @return `n x current_dpi/160` + */ +static inline lv_coord_t lv_disp_dpx(const lv_disp_t * disp, lv_coord_t n) +{ + return _LV_DPX_CALC(lv_disp_get_dpi(disp), n); +} + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif /*LV_DISP_H*/ diff --git a/src/lib/lvgl/src/core/lv_event.h b/src/lib/lvgl/src/core/lv_event.h new file mode 100644 index 0000000..038570b --- /dev/null +++ b/src/lib/lvgl/src/core/lv_event.h @@ -0,0 +1,363 @@ +/** + * @file lv_event.h + * + */ + +#ifndef LV_EVENT_H +#define LV_EVENT_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +struct _lv_obj_t; +struct _lv_event_dsc_t; + +/** + * Type of event being sent to the object. + */ +typedef enum { + LV_EVENT_ALL = 0, + + /** Input device events*/ + LV_EVENT_PRESSED, /**< The object has been pressed*/ + LV_EVENT_PRESSING, /**< The object is being pressed (called continuously while pressing)*/ + LV_EVENT_PRESS_LOST, /**< The object is still being pressed but slid cursor/finger off of the object */ + LV_EVENT_SHORT_CLICKED, /**< The object was pressed for a short period of time, then released it. Not called if scrolled.*/ + LV_EVENT_LONG_PRESSED, /**< Object has been pressed for at least `long_press_time`. Not called if scrolled.*/ + LV_EVENT_LONG_PRESSED_REPEAT, /**< Called after `long_press_time` in every `long_press_repeat_time` ms. Not called if scrolled.*/ + LV_EVENT_CLICKED, /**< Called on release if not scrolled (regardless to long press)*/ + LV_EVENT_RELEASED, /**< Called in every cases when the object has been released*/ + LV_EVENT_SCROLL_BEGIN, /**< Scrolling begins*/ + LV_EVENT_SCROLL_END, /**< Scrolling ends*/ + LV_EVENT_SCROLL, /**< Scrolling*/ + LV_EVENT_GESTURE, /**< A gesture is detected. Get the gesture with `lv_indev_get_gesture_dir(lv_indev_get_act());` */ + LV_EVENT_KEY, /**< A key is sent to the object. Get the key with `lv_indev_get_key(lv_indev_get_act());`*/ + LV_EVENT_FOCUSED, /**< The object is focused*/ + LV_EVENT_DEFOCUSED, /**< The object is defocused*/ + LV_EVENT_LEAVE, /**< The object is defocused but still selected*/ + LV_EVENT_HIT_TEST, /**< Perform advanced hit-testing*/ + + /** Drawing events*/ + LV_EVENT_COVER_CHECK, /**< Check if the object fully covers an area. The event parameter is `lv_cover_check_info_t *`.*/ + LV_EVENT_REFR_EXT_DRAW_SIZE, /**< Get the required extra draw area around the object (e.g. for shadow). The event parameter is `lv_coord_t *` to store the size.*/ + LV_EVENT_DRAW_MAIN_BEGIN, /**< Starting the main drawing phase*/ + LV_EVENT_DRAW_MAIN, /**< Perform the main drawing*/ + LV_EVENT_DRAW_MAIN_END, /**< Finishing the main drawing phase*/ + LV_EVENT_DRAW_POST_BEGIN, /**< Starting the post draw phase (when all children are drawn)*/ + LV_EVENT_DRAW_POST, /**< Perform the post draw phase (when all children are drawn)*/ + LV_EVENT_DRAW_POST_END, /**< Finishing the post draw phase (when all children are drawn)*/ + LV_EVENT_DRAW_PART_BEGIN, /**< Starting to draw a part. The event parameter is `lv_obj_draw_dsc_t *`. */ + LV_EVENT_DRAW_PART_END, /**< Finishing to draw a part. The event parameter is `lv_obj_draw_dsc_t *`. */ + + /** Special events*/ + LV_EVENT_VALUE_CHANGED, /**< The object's value has changed (i.e. slider moved)*/ + LV_EVENT_INSERT, /**< A text is inserted to the object. The event data is `char *` being inserted.*/ + LV_EVENT_REFRESH, /**< Notify the object to refresh something on it (for the user)*/ + LV_EVENT_READY, /**< A process has finished*/ + LV_EVENT_CANCEL, /**< A process has been cancelled */ + + /** Other events*/ + LV_EVENT_DELETE, /**< Object is being deleted*/ + LV_EVENT_CHILD_CHANGED, /**< Child was removed, added, or its size, position were changed */ + LV_EVENT_CHILD_CREATED, /**< Child was created, always bubbles up to all parents*/ + LV_EVENT_CHILD_DELETED, /**< Child was deleted, always bubbles up to all parents*/ + LV_EVENT_SCREEN_UNLOAD_START, /**< A screen unload started, fired immediately when scr_load is called*/ + LV_EVENT_SCREEN_LOAD_START, /**< A screen load started, fired when the screen change delay is expired*/ + LV_EVENT_SCREEN_LOADED, /**< A screen was loaded*/ + LV_EVENT_SCREEN_UNLOADED, /**< A screen was unloaded*/ + LV_EVENT_SIZE_CHANGED, /**< Object coordinates/size have changed*/ + LV_EVENT_STYLE_CHANGED, /**< Object's style has changed*/ + LV_EVENT_LAYOUT_CHANGED, /**< The children position has changed due to a layout recalculation*/ + LV_EVENT_GET_SELF_SIZE, /**< Get the internal size of a widget*/ + + _LV_EVENT_LAST, /** Number of default events*/ + + + LV_EVENT_PREPROCESS = 0x80, /** This is a flag that can be set with an event so it's processed + before the class default event processing */ +} lv_event_code_t; + +typedef struct _lv_event_t { + struct _lv_obj_t * target; + struct _lv_obj_t * current_target; + lv_event_code_t code; + void * user_data; + void * param; + struct _lv_event_t * prev; + uint8_t deleted : 1; + uint8_t stop_processing : 1; + uint8_t stop_bubbling : 1; +} lv_event_t; + +/** + * @brief Event callback. + * Events are used to notify the user of some action being taken on the object. + * For details, see ::lv_event_t. + */ +typedef void (*lv_event_cb_t)(lv_event_t * e); + +/** + * Used as the event parameter of ::LV_EVENT_HIT_TEST to check if an `point` can click the object or not. + * `res` should be set like this: + * - If already set to `false` an other event wants that point non clickable. If you want to respect it leave it as `false` or set `true` to overwrite it. + * - If already set `true` and `point` shouldn't be clickable set to `false` + * - If already set to `true` you agree that `point` can click the object leave it as `true` + */ +typedef struct { + const lv_point_t * point; /**< A point relative to screen to check if it can click the object or not*/ + bool res; /**< true: `point` can click the object; false: it cannot*/ +} lv_hit_test_info_t; + +/** + * Used as the event parameter of ::LV_EVENT_COVER_CHECK to check if an area is covered by the object or not. + * In the event use `const lv_area_t * area = lv_event_get_cover_area(e)` to get the area to check + * and `lv_event_set_cover_res(e, res)` to set the result. + */ +typedef struct { + lv_cover_res_t res; + const lv_area_t * area; +} lv_cover_check_info_t; + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +/** + * Send an event to the object + * @param obj pointer to an object + * @param event_code the type of the event from `lv_event_t` + * @param param arbitrary data depending on the widget type and the event. (Usually `NULL`) + * @return LV_RES_OK: `obj` was not deleted in the event; LV_RES_INV: `obj` was deleted in the event_code + */ +lv_res_t lv_event_send(struct _lv_obj_t * obj, lv_event_code_t event_code, void * param); + +/** + * Used by the widgets internally to call the ancestor widget types's event handler + * @param class_p pointer to the class of the widget (NOT the ancestor class) + * @param e pointer to the event descriptor + * @return LV_RES_OK: the target object was not deleted in the event; LV_RES_INV: it was deleted in the event_code + */ +lv_res_t lv_obj_event_base(const lv_obj_class_t * class_p, lv_event_t * e); + +/** + * Get the object originally targeted by the event. It's the same even if the event is bubbled. + * @param e pointer to the event descriptor + * @return the target of the event_code + */ +struct _lv_obj_t * lv_event_get_target(lv_event_t * e); + +/** + * Get the current target of the event. It's the object which event handler being called. + * If the event is not bubbled it's the same as "normal" target. + * @param e pointer to the event descriptor + * @return pointer to the current target of the event_code + */ +struct _lv_obj_t * lv_event_get_current_target(lv_event_t * e); + +/** + * Get the event code of an event + * @param e pointer to the event descriptor + * @return the event code. (E.g. `LV_EVENT_CLICKED`, `LV_EVENT_FOCUSED`, etc) + */ +lv_event_code_t lv_event_get_code(lv_event_t * e); + +/** + * Get the parameter passed when the event was sent + * @param e pointer to the event descriptor + * @return pointer to the parameter + */ +void * lv_event_get_param(lv_event_t * e); + +/** + * Get the user_data passed when the event was registered on the object + * @param e pointer to the event descriptor + * @return pointer to the user_data + */ +void * lv_event_get_user_data(lv_event_t * e); + +/** + * Stop the event from bubbling. + * This is only valid when called in the middle of an event processing chain. + * @param e pointer to the event descriptor + */ +void lv_event_stop_bubbling(lv_event_t * e); + +/** + * Stop processing this event. + * This is only valid when called in the middle of an event processing chain. + * @param e pointer to the event descriptor + */ +void lv_event_stop_processing(lv_event_t * e); + +/** + * Register a new, custom event ID. + * It can be used the same way as e.g. `LV_EVENT_CLICKED` to send custom events + * @return the new event id + * @example + * uint32_t LV_EVENT_MINE = 0; + * ... + * e = lv_event_register_id(); + * ... + * lv_event_send(obj, LV_EVENT_MINE, &some_data); + */ +uint32_t lv_event_register_id(void); + +/** + * Nested events can be called and one of them might belong to an object that is being deleted. + * Mark this object's `event_temp_data` deleted to know that its `lv_event_send` should return `LV_RES_INV` + * @param obj pointer to an object to mark as deleted + */ +void _lv_event_mark_deleted(struct _lv_obj_t * obj); + + +/** + * Add an event handler function for an object. + * Used by the user to react on event which happens with the object. + * An object can have multiple event handler. They will be called in the same order as they were added. + * @param obj pointer to an object + * @param filter and event code (e.g. `LV_EVENT_CLICKED`) on which the event should be called. `LV_EVENT_ALL` can be sued the receive all the events. + * @param event_cb the new event function + * @param user_data custom data data will be available in `event_cb` + * @return a pointer the event descriptor. Can be used in ::lv_obj_remove_event_dsc + */ +struct _lv_event_dsc_t * lv_obj_add_event_cb(struct _lv_obj_t * obj, lv_event_cb_t event_cb, lv_event_code_t filter, + void * user_data); + +/** + * Remove an event handler function for an object. + * @param obj pointer to an object + * @param event_cb the event function to remove, or `NULL` to remove the firstly added event callback + * @return true if any event handlers were removed + */ +bool lv_obj_remove_event_cb(struct _lv_obj_t * obj, lv_event_cb_t event_cb); + +/** + * Remove an event handler function with a specific user_data from an object. + * @param obj pointer to an object + * @param event_cb the event function to remove, or `NULL` only `user_data` matters. + * @param event_user_data the user_data specified in ::lv_obj_add_event_cb + * @return true if any event handlers were removed + */ +bool lv_obj_remove_event_cb_with_user_data(struct _lv_obj_t * obj, lv_event_cb_t event_cb, + const void * event_user_data); + +/** + * DEPRECATED because doesn't work if multiple event handlers are added to an object. + * Remove an event handler function for an object. + * @param obj pointer to an object + * @param event_dsc pointer to an event descriptor to remove (returned by ::lv_obj_add_event_cb) + * @return true if any event handlers were removed + */ +bool lv_obj_remove_event_dsc(struct _lv_obj_t * obj, struct _lv_event_dsc_t * event_dsc); + +/** + * The user data of an event object event callback. Always the first match with `event_cb` will be returned. + * @param obj pointer to an object + * @param event_cb the event function + * @return the user_data + */ +void * lv_obj_get_event_user_data(struct _lv_obj_t * obj, lv_event_cb_t event_cb); + +/** + * Get the input device passed as parameter to indev related events. + * @param e pointer to an event + * @return the indev that triggered the event or NULL if called on a not indev related event + */ +lv_indev_t * lv_event_get_indev(lv_event_t * e); + +/** + * Get the part draw descriptor passed as parameter to `LV_EVENT_DRAW_PART_BEGIN/END`. + * @param e pointer to an event + * @return the part draw descriptor to hook the drawing or NULL if called on an unrelated event + */ +lv_obj_draw_part_dsc_t * lv_event_get_draw_part_dsc(lv_event_t * e); + +/** + * Get the draw context which should be the first parameter of the draw functions. + * Namely: `LV_EVENT_DRAW_MAIN/POST`, `LV_EVENT_DRAW_MAIN/POST_BEGIN`, `LV_EVENT_DRAW_MAIN/POST_END` + * @param e pointer to an event + * @return pointer to a draw context or NULL if called on an unrelated event + */ +lv_draw_ctx_t * lv_event_get_draw_ctx(lv_event_t * e); + +/** + * Get the old area of the object before its size was changed. Can be used in `LV_EVENT_SIZE_CHANGED` + * @param e pointer to an event + * @return the old absolute area of the object or NULL if called on an unrelated event + */ +const lv_area_t * lv_event_get_old_size(lv_event_t * e); + +/** + * Get the key passed as parameter to an event. Can be used in `LV_EVENT_KEY` + * @param e pointer to an event + * @return the triggering key or NULL if called on an unrelated event + */ +uint32_t lv_event_get_key(lv_event_t * e); + +/** + * Get the animation descriptor of a scrolling. Can be used in `LV_EVENT_SCROLL_BEGIN` + * @param e pointer to an event + * @return the animation that will scroll the object. (can be modified as required) + */ +lv_anim_t * lv_event_get_scroll_anim(lv_event_t * e); + +/** + * Set the new extra draw size. Can be used in `LV_EVENT_REFR_EXT_DRAW_SIZE` + * @param e pointer to an event + * @param size The new extra draw size + */ +void lv_event_set_ext_draw_size(lv_event_t * e, lv_coord_t size); + +/** + * Get a pointer to an `lv_point_t` variable in which the self size should be saved (width in `point->x` and height `point->y`). + * Can be used in `LV_EVENT_GET_SELF_SIZE` + * @param e pointer to an event + * @return pointer to `lv_point_t` or NULL if called on an unrelated event + */ +lv_point_t * lv_event_get_self_size_info(lv_event_t * e); + +/** + * Get a pointer to an `lv_hit_test_info_t` variable in which the hit test result should be saved. Can be used in `LV_EVENT_HIT_TEST` + * @param e pointer to an event + * @return pointer to `lv_hit_test_info_t` or NULL if called on an unrelated event + */ +lv_hit_test_info_t * lv_event_get_hit_test_info(lv_event_t * e); + +/** + * Get a pointer to an area which should be examined whether the object fully covers it or not. + * Can be used in `LV_EVENT_HIT_TEST` + * @param e pointer to an event + * @return an area with absolute coordinates to check + */ +const lv_area_t * lv_event_get_cover_area(lv_event_t * e); + +/** + * Set the result of cover checking. Can be used in `LV_EVENT_COVER_CHECK` + * @param e pointer to an event + * @param res an element of ::lv_cover_check_info_t + */ +void lv_event_set_cover_res(lv_event_t * e, lv_cover_res_t res); + +/********************** + * MACROS + **********************/ + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif /*LV_EVENT_H*/ diff --git a/src/lib/lvgl/src/core/lv_group.h b/src/lib/lvgl/src/core/lv_group.h new file mode 100644 index 0000000..ecf88df --- /dev/null +++ b/src/lib/lvgl/src/core/lv_group.h @@ -0,0 +1,246 @@ +/** + * @file lv_group.h + * + */ + +#ifndef LV_GROUP_H +#define LV_GROUP_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ + +#include "../lv_conf_internal.h" + +#include +#include +#include "../misc/lv_ll.h" +#include "../misc/lv_types.h" + +/********************* + * DEFINES + *********************/ +/*Predefined keys to control the focused object via lv_group_send(group, c)*/ + +enum { + LV_KEY_UP = 17, /*0x11*/ + LV_KEY_DOWN = 18, /*0x12*/ + LV_KEY_RIGHT = 19, /*0x13*/ + LV_KEY_LEFT = 20, /*0x14*/ + LV_KEY_ESC = 27, /*0x1B*/ + LV_KEY_DEL = 127, /*0x7F*/ + LV_KEY_BACKSPACE = 8, /*0x08*/ + LV_KEY_ENTER = 10, /*0x0A, '\n'*/ + LV_KEY_NEXT = 9, /*0x09, '\t'*/ + LV_KEY_PREV = 11, /*0x0B, '*/ + LV_KEY_HOME = 2, /*0x02, STX*/ + LV_KEY_END = 3, /*0x03, ETX*/ +}; +typedef uint8_t lv_key_t; + +/********************** + * TYPEDEFS + **********************/ + +struct _lv_obj_t; +struct _lv_group_t; + +typedef void (*lv_group_focus_cb_t)(struct _lv_group_t *); + +/** + * Groups can be used to logically hold objects so that they can be individually focused. + * They are NOT for laying out objects on a screen (try layouts for that). + */ +typedef struct _lv_group_t { + lv_ll_t obj_ll; /**< Linked list to store the objects in the group*/ + struct _lv_obj_t ** obj_focus; /**< The object in focus*/ + + lv_group_focus_cb_t focus_cb; /**< A function to call when a new object is focused (optional)*/ +#if LV_USE_USER_DATA + void * user_data; +#endif + + uint8_t frozen : 1; /**< 1: can't focus to new object*/ + uint8_t editing : 1; /**< 1: Edit mode, 0: Navigate mode*/ + uint8_t refocus_policy : 1; /**< 1: Focus prev if focused on deletion. 0: Focus next if focused on + deletion.*/ + uint8_t wrap : 1; /**< 1: Focus next/prev can wrap at end of list. 0: Focus next/prev stops at end + of list.*/ +} lv_group_t; + + +typedef enum { + LV_GROUP_REFOCUS_POLICY_NEXT = 0, + LV_GROUP_REFOCUS_POLICY_PREV = 1 +} lv_group_refocus_policy_t; + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +/** + * Init. the group module + * @remarks Internal function, do not call directly. + */ +void _lv_group_init(void); + +/** + * Create a new object group + * @return pointer to the new object group + */ +lv_group_t * lv_group_create(void); + +/** + * Delete a group object + * @param group pointer to a group + */ +void lv_group_del(lv_group_t * group); + +/** + * Set a default group. New object are added to this group if it's enabled in their class with `add_to_def_group = true` + * @param group pointer to a group (can be `NULL`) + */ +void lv_group_set_default(lv_group_t * group); + +/** + * Get the default group + * @return pointer to the default group + */ +lv_group_t * lv_group_get_default(void); + +/** + * Add an object to a group + * @param group pointer to a group + * @param obj pointer to an object to add + */ +void lv_group_add_obj(lv_group_t * group, struct _lv_obj_t * obj); + +/** + * Swap 2 object in a group. The object must be in the same group + * @param obj1 pointer to an object + * @param obj2 pointer to an other object + */ +void lv_group_swap_obj(struct _lv_obj_t * obj1, struct _lv_obj_t * obj2); + +/** + * Remove an object from its group + * @param obj pointer to an object to remove + */ +void lv_group_remove_obj(struct _lv_obj_t * obj); + +/** + * Remove all objects from a group + * @param group pointer to a group + */ +void lv_group_remove_all_objs(lv_group_t * group); + +/** + * Focus on an object (defocus the current) + * @param obj pointer to an object to focus on + */ +void lv_group_focus_obj(struct _lv_obj_t * obj); + +/** + * Focus the next object in a group (defocus the current) + * @param group pointer to a group + */ +void lv_group_focus_next(lv_group_t * group); + +/** + * Focus the previous object in a group (defocus the current) + * @param group pointer to a group + */ +void lv_group_focus_prev(lv_group_t * group); + +/** + * Do not let to change the focus from the current object + * @param group pointer to a group + * @param en true: freeze, false: release freezing (normal mode) + */ +void lv_group_focus_freeze(lv_group_t * group, bool en); + +/** + * Send a control character to the focuses object of a group + * @param group pointer to a group + * @param c a character (use LV_KEY_.. to navigate) + * @return result of focused object in group. + */ +lv_res_t lv_group_send_data(lv_group_t * group, uint32_t c); + +/** + * Set a function for a group which will be called when a new object is focused + * @param group pointer to a group + * @param focus_cb the call back function or NULL if unused + */ +void lv_group_set_focus_cb(lv_group_t * group, lv_group_focus_cb_t focus_cb); + +/** + * Set whether the next or previous item in a group is focused if the currently focused obj is + * deleted. + * @param group pointer to a group + * @param policy new refocus policy enum + */ +void lv_group_set_refocus_policy(lv_group_t * group, lv_group_refocus_policy_t policy); + +/** + * Manually set the current mode (edit or navigate). + * @param group pointer to group + * @param edit true: edit mode; false: navigate mode + */ +void lv_group_set_editing(lv_group_t * group, bool edit); + +/** + * Set whether focus next/prev will allow wrapping from first->last or last->first object. + * @param group pointer to group + * @param en true: wrapping enabled; false: wrapping disabled + */ +void lv_group_set_wrap(lv_group_t * group, bool en); + +/** + * Get the focused object or NULL if there isn't one + * @param group pointer to a group + * @return pointer to the focused object + */ +struct _lv_obj_t * lv_group_get_focused(const lv_group_t * group); + +/** + * Get the focus callback function of a group + * @param group pointer to a group + * @return the call back function or NULL if not set + */ +lv_group_focus_cb_t lv_group_get_focus_cb(const lv_group_t * group); + +/** + * Get the current mode (edit or navigate). + * @param group pointer to group + * @return true: edit mode; false: navigate mode + */ +bool lv_group_get_editing(const lv_group_t * group); + +/** + * Get whether focus next/prev will allow wrapping from first->last or last->first object. + * @param group pointer to group + * @param en true: wrapping enabled; false: wrapping disabled + */ +bool lv_group_get_wrap(lv_group_t * group); + +/** + * Get the number of object in the group + * @param group pointer to a group + * @return number of objects in the group + */ +uint32_t lv_group_get_obj_count(lv_group_t * group); + +/********************** + * MACROS + **********************/ + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif /*LV_GROUP_H*/ diff --git a/src/lib/lvgl/src/core/lv_indev.h b/src/lib/lvgl/src/core/lv_indev.h new file mode 100644 index 0000000..80c7939 --- /dev/null +++ b/src/lib/lvgl/src/core/lv_indev.h @@ -0,0 +1,172 @@ +/** + * @file lv_indev.h + * + */ + +#ifndef LV_INDEV_H +#define LV_INDEV_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include "lv_obj.h" +#include "../hal/lv_hal_indev.h" +#include "lv_group.h" + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +/** + * Called periodically to read the input devices + * @param timer pointer to a timer to read + */ +void lv_indev_read_timer_cb(lv_timer_t * timer); + + +void lv_indev_enable(lv_indev_t * indev, bool en); + +/** + * Get the currently processed input device. Can be used in action functions too. + * @return pointer to the currently processed input device or NULL if no input device processing + * right now + */ +lv_indev_t * lv_indev_get_act(void); + +/** + * Get the type of an input device + * @param indev pointer to an input device + * @return the type of the input device from `lv_hal_indev_type_t` (`LV_INDEV_TYPE_...`) + */ +lv_indev_type_t lv_indev_get_type(const lv_indev_t * indev); + +/** + * Reset one or all input devices + * @param indev pointer to an input device to reset or NULL to reset all of them + * @param obj pointer to an object which triggers the reset. + */ +void lv_indev_reset(lv_indev_t * indev, lv_obj_t * obj); + +/** + * Reset the long press state of an input device + * @param indev pointer to an input device + */ +void lv_indev_reset_long_press(lv_indev_t * indev); + +/** + * Set a cursor for a pointer input device (for LV_INPUT_TYPE_POINTER and LV_INPUT_TYPE_BUTTON) + * @param indev pointer to an input device + * @param cur_obj pointer to an object to be used as cursor + */ +void lv_indev_set_cursor(lv_indev_t * indev, lv_obj_t * cur_obj); + +/** + * Set a destination group for a keypad input device (for LV_INDEV_TYPE_KEYPAD) + * @param indev pointer to an input device + * @param group point to a group + */ +void lv_indev_set_group(lv_indev_t * indev, lv_group_t * group); + +/** + * Set the an array of points for LV_INDEV_TYPE_BUTTON. + * These points will be assigned to the buttons to press a specific point on the screen + * @param indev pointer to an input device + * @param group point to a group + */ +void lv_indev_set_button_points(lv_indev_t * indev, const lv_point_t points[]); + +/** + * Get the last point of an input device (for LV_INDEV_TYPE_POINTER and LV_INDEV_TYPE_BUTTON) + * @param indev pointer to an input device + * @param point pointer to a point to store the result + */ +void lv_indev_get_point(const lv_indev_t * indev, lv_point_t * point); + +/** +* Get the current gesture direct +* @param indev pointer to an input device +* @return current gesture direct +*/ +lv_dir_t lv_indev_get_gesture_dir(const lv_indev_t * indev); + +/** + * Get the last pressed key of an input device (for LV_INDEV_TYPE_KEYPAD) + * @param indev pointer to an input device + * @return the last pressed key (0 on error) + */ +uint32_t lv_indev_get_key(const lv_indev_t * indev); + +/** + * Check the current scroll direction of an input device (for LV_INDEV_TYPE_POINTER and + * LV_INDEV_TYPE_BUTTON) + * @param indev pointer to an input device + * @return LV_DIR_NONE: no scrolling now + * LV_DIR_HOR/VER + */ +lv_dir_t lv_indev_get_scroll_dir(const lv_indev_t * indev); + +/** + * Get the currently scrolled object (for LV_INDEV_TYPE_POINTER and + * LV_INDEV_TYPE_BUTTON) + * @param indev pointer to an input device + * @return pointer to the currently scrolled object or NULL if no scrolling by this indev + */ +lv_obj_t * lv_indev_get_scroll_obj(const lv_indev_t * indev); + +/** + * Get the movement vector of an input device (for LV_INDEV_TYPE_POINTER and + * LV_INDEV_TYPE_BUTTON) + * @param indev pointer to an input device + * @param point pointer to a point to store the types.pointer.vector + */ +void lv_indev_get_vect(const lv_indev_t * indev, lv_point_t * point); + +/** + * Do nothing until the next release + * @param indev pointer to an input device + */ +void lv_indev_wait_release(lv_indev_t * indev); + +/** + * Gets a pointer to the currently active object in the currently processed input device. + * @return pointer to currently active object or NULL if no active object + */ +lv_obj_t * lv_indev_get_obj_act(void); + +/** + * Get a pointer to the indev read timer to + * modify its parameters with `lv_timer_...` functions. + * @param indev pointer to an input device + * @return pointer to the indev read refresher timer. (NULL on error) + */ +lv_timer_t * lv_indev_get_read_timer(lv_disp_t * indev); + +/** + * Search the most top, clickable object by a point + * @param obj pointer to a start object, typically the screen + * @param point pointer to a point for searching the most top child + * @return pointer to the found object or NULL if there was no suitable object + */ +lv_obj_t * lv_indev_search_obj(lv_obj_t * obj, lv_point_t * point); + +/********************** + * MACROS + **********************/ + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif /*LV_INDEV_H*/ diff --git a/src/lib/lvgl/src/core/lv_indev_scroll.h b/src/lib/lvgl/src/core/lv_indev_scroll.h new file mode 100644 index 0000000..76c64d1 --- /dev/null +++ b/src/lib/lvgl/src/core/lv_indev_scroll.h @@ -0,0 +1,65 @@ +/** + * @file lv_indev_scroll.h + * + */ + +#ifndef LV_INDEV_SCROLL_H +#define LV_INDEV_SCROLL_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include "lv_obj.h" + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +/** + * Handle scrolling. Called by LVGL during input device processing + * @param proc pointer to an input device's proc field + */ +void _lv_indev_scroll_handler(_lv_indev_proc_t * proc); + +/** + * Handle throwing after scrolling. Called by LVGL during input device processing + * @param proc pointer to an input device's proc field + */ +void _lv_indev_scroll_throw_handler(_lv_indev_proc_t * proc); + +/** + * Predict where would a scroll throw end + * @param indev pointer to an input device + * @param dir ` LV_DIR_VER` or `LV_DIR_HOR` + * @return the difference compared to the current position when the throw would be finished + */ +lv_coord_t lv_indev_scroll_throw_predict(lv_indev_t * indev, lv_dir_t dir); + +/** + * Get the distance of the nearest snap point + * @param obj the object on which snap points should be found + * @param p save the distance of the found snap point there + */ +void lv_indev_scroll_get_snap_dist(lv_obj_t * obj, lv_point_t * p); + +/********************** + * MACROS + **********************/ + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif /*LV_INDEV_SCROLL_H*/ diff --git a/src/lib/lvgl/src/core/lv_obj.h b/src/lib/lvgl/src/core/lv_obj.h new file mode 100644 index 0000000..7bd89c8 --- /dev/null +++ b/src/lib/lvgl/src/core/lv_obj.h @@ -0,0 +1,408 @@ +/** + * @file lv_obj.h + * + */ + +#ifndef LV_OBJ_H +#define LV_OBJ_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include "../lv_conf_internal.h" + +#include +#include +#include "../misc/lv_style.h" +#include "../misc/lv_types.h" +#include "../misc/lv_area.h" +#include "../misc/lv_color.h" +#include "../misc/lv_assert.h" +#include "../hal/lv_hal.h" + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +struct _lv_obj_t; + +/** + * Possible states of a widget. + * OR-ed values are possible + */ +enum { + LV_STATE_DEFAULT = 0x0000, + LV_STATE_CHECKED = 0x0001, + LV_STATE_FOCUSED = 0x0002, + LV_STATE_FOCUS_KEY = 0x0004, + LV_STATE_EDITED = 0x0008, + LV_STATE_HOVERED = 0x0010, + LV_STATE_PRESSED = 0x0020, + LV_STATE_SCROLLED = 0x0040, + LV_STATE_DISABLED = 0x0080, + + LV_STATE_USER_1 = 0x1000, + LV_STATE_USER_2 = 0x2000, + LV_STATE_USER_3 = 0x4000, + LV_STATE_USER_4 = 0x8000, + + LV_STATE_ANY = 0xFFFF, /**< Special value can be used in some functions to target all states*/ +}; + +typedef uint16_t lv_state_t; + +/** + * The possible parts of widgets. + * The parts can be considered as the internal building block of the widgets. + * E.g. slider = background + indicator + knob + * Note every part is used by every widget + */ +enum { + LV_PART_MAIN = 0x000000, /**< A background like rectangle*/ + LV_PART_SCROLLBAR = 0x010000, /**< The scrollbar(s)*/ + LV_PART_INDICATOR = 0x020000, /**< Indicator, e.g. for slider, bar, switch, or the tick box of the checkbox*/ + LV_PART_KNOB = 0x030000, /**< Like handle to grab to adjust the value*/ + LV_PART_SELECTED = 0x040000, /**< Indicate the currently selected option or section*/ + LV_PART_ITEMS = 0x050000, /**< Used if the widget has multiple similar elements (e.g. table cells)*/ + LV_PART_TICKS = 0x060000, /**< Ticks on scale e.g. for a chart or meter*/ + LV_PART_CURSOR = 0x070000, /**< Mark a specific place e.g. for text area's cursor or on a chart*/ + + LV_PART_CUSTOM_FIRST = 0x080000, /**< Extension point for custom widgets*/ + + LV_PART_ANY = 0x0F0000, /**< Special value can be used in some functions to target all parts*/ +}; + +typedef uint32_t lv_part_t; + +/** + * On/Off features controlling the object's behavior. + * OR-ed values are possible + */ +enum { + LV_OBJ_FLAG_HIDDEN = (1L << 0), /**< Make the object hidden. (Like it wasn't there at all)*/ + LV_OBJ_FLAG_CLICKABLE = (1L << 1), /**< Make the object clickable by the input devices*/ + LV_OBJ_FLAG_CLICK_FOCUSABLE = (1L << 2), /**< Add focused state to the object when clicked*/ + LV_OBJ_FLAG_CHECKABLE = (1L << 3), /**< Toggle checked state when the object is clicked*/ + LV_OBJ_FLAG_SCROLLABLE = (1L << 4), /**< Make the object scrollable*/ + LV_OBJ_FLAG_SCROLL_ELASTIC = (1L << 5), /**< Allow scrolling inside but with slower speed*/ + LV_OBJ_FLAG_SCROLL_MOMENTUM = (1L << 6), /**< Make the object scroll further when "thrown"*/ + LV_OBJ_FLAG_SCROLL_ONE = (1L << 7), /**< Allow scrolling only one snappable children*/ + LV_OBJ_FLAG_SCROLL_CHAIN_HOR = (1L << 8), /**< Allow propagating the horizontal scroll to a parent*/ + LV_OBJ_FLAG_SCROLL_CHAIN_VER = (1L << 9), /**< Allow propagating the vertical scroll to a parent*/ + LV_OBJ_FLAG_SCROLL_CHAIN = (LV_OBJ_FLAG_SCROLL_CHAIN_HOR | LV_OBJ_FLAG_SCROLL_CHAIN_VER), + LV_OBJ_FLAG_SCROLL_ON_FOCUS = (1L << 10), /**< Automatically scroll object to make it visible when focused*/ + LV_OBJ_FLAG_SCROLL_WITH_ARROW = (1L << 11), /**< Allow scrolling the focused object with arrow keys*/ + LV_OBJ_FLAG_SNAPPABLE = (1L << 12), /**< If scroll snap is enabled on the parent it can snap to this object*/ + LV_OBJ_FLAG_PRESS_LOCK = (1L << 13), /**< Keep the object pressed even if the press slid from the object*/ + LV_OBJ_FLAG_EVENT_BUBBLE = (1L << 14), /**< Propagate the events to the parent too*/ + LV_OBJ_FLAG_GESTURE_BUBBLE = (1L << 15), /**< Propagate the gestures to the parent*/ + LV_OBJ_FLAG_ADV_HITTEST = (1L << 16), /**< Allow performing more accurate hit (click) test. E.g. consider rounded corners.*/ + LV_OBJ_FLAG_IGNORE_LAYOUT = (1L << 17), /**< Make the object position-able by the layouts*/ + LV_OBJ_FLAG_FLOATING = (1L << 18), /**< Do not scroll the object when the parent scrolls and ignore layout*/ + LV_OBJ_FLAG_OVERFLOW_VISIBLE = (1L << 19), /**< Do not clip the children's content to the parent's boundary*/ + + LV_OBJ_FLAG_LAYOUT_1 = (1L << 23), /**< Custom flag, free to use by layouts*/ + LV_OBJ_FLAG_LAYOUT_2 = (1L << 24), /**< Custom flag, free to use by layouts*/ + + LV_OBJ_FLAG_WIDGET_1 = (1L << 25), /**< Custom flag, free to use by widget*/ + LV_OBJ_FLAG_WIDGET_2 = (1L << 26), /**< Custom flag, free to use by widget*/ + LV_OBJ_FLAG_USER_1 = (1L << 27), /**< Custom flag, free to use by user*/ + LV_OBJ_FLAG_USER_2 = (1L << 28), /**< Custom flag, free to use by user*/ + LV_OBJ_FLAG_USER_3 = (1L << 29), /**< Custom flag, free to use by user*/ + LV_OBJ_FLAG_USER_4 = (1L << 30), /**< Custom flag, free to use by user*/ + +}; + + +typedef uint32_t lv_obj_flag_t; + +/** + * `type` field in `lv_obj_draw_part_dsc_t` if `class_p = lv_obj_class` + * Used in `LV_EVENT_DRAW_PART_BEGIN` and `LV_EVENT_DRAW_PART_END` + */ +typedef enum { + LV_OBJ_DRAW_PART_RECTANGLE, /**< The main rectangle*/ + LV_OBJ_DRAW_PART_BORDER_POST,/**< The border if style_border_post = true*/ + LV_OBJ_DRAW_PART_SCROLLBAR, /**< The scrollbar*/ +} lv_obj_draw_part_type_t; + +#include "lv_obj_tree.h" +#include "lv_obj_pos.h" +#include "lv_obj_scroll.h" +#include "lv_obj_style.h" +#include "lv_obj_draw.h" +#include "lv_obj_class.h" +#include "lv_event.h" +#include "lv_group.h" + +/** + * Make the base object's class publicly available. + */ +extern const lv_obj_class_t lv_obj_class; + +/** + * Special, rarely used attributes. + * They are allocated automatically if any elements is set. + */ +typedef struct { + struct _lv_obj_t ** children; /**< Store the pointer of the children in an array.*/ + uint32_t child_cnt; /**< Number of children*/ + lv_group_t * group_p; + + struct _lv_event_dsc_t * event_dsc; /**< Dynamically allocated event callback and user data array*/ + lv_point_t scroll; /**< The current X/Y scroll offset*/ + + lv_coord_t ext_click_pad; /**< Extra click padding in all direction*/ + lv_coord_t ext_draw_size; /**< EXTend the size in every direction for drawing.*/ + + lv_scrollbar_mode_t scrollbar_mode : 2; /**< How to display scrollbars*/ + lv_scroll_snap_t scroll_snap_x : 2; /**< Where to align the snappable children horizontally*/ + lv_scroll_snap_t scroll_snap_y : 2; /**< Where to align the snappable children vertically*/ + lv_dir_t scroll_dir : 4; /**< The allowed scroll direction(s)*/ + uint8_t event_dsc_cnt; /**< Number of event callbacks stored in `event_dsc` array*/ +} _lv_obj_spec_attr_t; + +typedef struct _lv_obj_t { + const lv_obj_class_t * class_p; + struct _lv_obj_t * parent; + _lv_obj_spec_attr_t * spec_attr; + _lv_obj_style_t * styles; +#if LV_USE_USER_DATA + void * user_data; +#endif + lv_area_t coords; + lv_obj_flag_t flags; + lv_state_t state; + uint16_t layout_inv : 1; + uint16_t scr_layout_inv : 1; + uint16_t skip_trans : 1; + uint16_t style_cnt : 6; + uint16_t h_layout : 1; + uint16_t w_layout : 1; +} lv_obj_t; + + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +/** + * Initialize LVGL library. + * Should be called before any other LVGL related function. + */ +void lv_init(void); + +#if LV_ENABLE_GC || !LV_MEM_CUSTOM + +/** + * Deinit the 'lv' library + * Currently only implemented when not using custom allocators, or GC is enabled. + */ +void lv_deinit(void); + +#endif + +/** + * Returns whether the 'lv' library is currently initialized + */ +bool lv_is_initialized(void); + +/** + * Create a base object (a rectangle) + * @param parent pointer to a parent object. If NULL then a screen will be created. + * @return pointer to the new object + */ +lv_obj_t * lv_obj_create(lv_obj_t * parent); + + +/*===================== + * Setter functions + *====================*/ + +/** + * Set one or more flags + * @param obj pointer to an object + * @param f R-ed values from `lv_obj_flag_t` to set. + */ +void lv_obj_add_flag(lv_obj_t * obj, lv_obj_flag_t f); + +/** + * Clear one or more flags + * @param obj pointer to an object + * @param f OR-ed values from `lv_obj_flag_t` to set. + */ +void lv_obj_clear_flag(lv_obj_t * obj, lv_obj_flag_t f); + + +/** + * Add one or more states to the object. The other state bits will remain unchanged. + * If specified in the styles, transition animation will be started from the previous state to the current. + * @param obj pointer to an object + * @param state the states to add. E.g `LV_STATE_PRESSED | LV_STATE_FOCUSED` + */ +void lv_obj_add_state(lv_obj_t * obj, lv_state_t state); + +/** + * Remove one or more states to the object. The other state bits will remain unchanged. + * If specified in the styles, transition animation will be started from the previous state to the current. + * @param obj pointer to an object + * @param state the states to add. E.g `LV_STATE_PRESSED | LV_STATE_FOCUSED` + */ +void lv_obj_clear_state(lv_obj_t * obj, lv_state_t state); + +/** + * Set the user_data field of the object + * @param obj pointer to an object + * @param user_data pointer to the new user_data. + */ +#if LV_USE_USER_DATA +static inline void lv_obj_set_user_data(lv_obj_t * obj, void * user_data) +{ + obj->user_data = user_data; +} +#endif + +/*======================= + * Getter functions + *======================*/ + +/** + * Check if a given flag or all the given flags are set on an object. + * @param obj pointer to an object + * @param f the flag(s) to check (OR-ed values can be used) + * @return true: all flags are set; false: not all flags are set + */ +bool lv_obj_has_flag(const lv_obj_t * obj, lv_obj_flag_t f); + +/** + * Check if a given flag or any of the flags are set on an object. + * @param obj pointer to an object + * @param f the flag(s) to check (OR-ed values can be used) + * @return true: at lest one flag flag is set; false: none of the flags are set + */ +bool lv_obj_has_flag_any(const lv_obj_t * obj, lv_obj_flag_t f); + +/** + * Get the state of an object + * @param obj pointer to an object + * @return the state (OR-ed values from `lv_state_t`) + */ +lv_state_t lv_obj_get_state(const lv_obj_t * obj); + +/** + * Check if the object is in a given state or not. + * @param obj pointer to an object + * @param state a state or combination of states to check + * @return true: `obj` is in `state`; false: `obj` is not in `state` + */ +bool lv_obj_has_state(const lv_obj_t * obj, lv_state_t state); + +/** + * Get the group of the object + * @param obj pointer to an object + * @return the pointer to group of the object + */ +void * lv_obj_get_group(const lv_obj_t * obj); + +/** + * Get the user_data field of the object + * @param obj pointer to an object + * @return the pointer to the user_data of the object + */ +#if LV_USE_USER_DATA +static inline void * lv_obj_get_user_data(lv_obj_t * obj) +{ + return obj->user_data; +} +#endif + +/*======================= + * Other functions + *======================*/ + +/** + * Allocate special data for an object if not allocated yet. + * @param obj pointer to an object + */ +void lv_obj_allocate_spec_attr(lv_obj_t * obj); + +/** + * Check the type of obj. + * @param obj pointer to an object + * @param class_p a class to check (e.g. `lv_slider_class`) + * @return true: `class_p` is the `obj` class. + */ +bool lv_obj_check_type(const lv_obj_t * obj, const lv_obj_class_t * class_p); + +/** + * Check if any object has a given class (type). + * It checks the ancestor classes too. + * @param obj pointer to an object + * @param class_p a class to check (e.g. `lv_slider_class`) + * @return true: `obj` has the given class + */ +bool lv_obj_has_class(const lv_obj_t * obj, const lv_obj_class_t * class_p); + +/** + * Get the class (type) of the object + * @param obj pointer to an object + * @return the class (type) of the object + */ +const lv_obj_class_t * lv_obj_get_class(const lv_obj_t * obj); + +/** + * Check if any object is still "alive". + * @param obj pointer to an object + * @return true: valid + */ +bool lv_obj_is_valid(const lv_obj_t * obj); + +/** + * Scale the given number of pixels (a distance or size) relative to a 160 DPI display + * considering the DPI of the `obj`'s display. + * It ensures that e.g. `lv_dpx(100)` will have the same physical size regardless to the + * DPI of the display. + * @param obj an object whose display's dpi should be considered + * @param n the number of pixels to scale + * @return `n x current_dpi/160` + */ +static inline lv_coord_t lv_obj_dpx(const lv_obj_t * obj, lv_coord_t n) +{ + return _LV_DPX_CALC(lv_disp_get_dpi(lv_obj_get_disp(obj)), n); +} + +/********************** + * MACROS + **********************/ + +#if LV_USE_ASSERT_OBJ +# define LV_ASSERT_OBJ(obj_p, obj_class) \ + do { \ + LV_ASSERT_MSG(obj_p != NULL, "The object is NULL"); \ + LV_ASSERT_MSG(lv_obj_has_class(obj_p, obj_class) == true, "Incompatible object type."); \ + LV_ASSERT_MSG(lv_obj_is_valid(obj_p) == true, "The object is invalid, deleted or corrupted?"); \ + } while(0) +# else +# define LV_ASSERT_OBJ(obj_p, obj_class) do{}while(0) +#endif + +#if LV_USE_LOG && LV_LOG_TRACE_OBJ_CREATE +# define LV_TRACE_OBJ_CREATE(...) LV_LOG_TRACE(__VA_ARGS__) +#else +# define LV_TRACE_OBJ_CREATE(...) +#endif + + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif /*LV_OBJ_H*/ diff --git a/src/lib/lvgl/src/core/lv_obj_class.h b/src/lib/lvgl/src/core/lv_obj_class.h new file mode 100644 index 0000000..01a7248 --- /dev/null +++ b/src/lib/lvgl/src/core/lv_obj_class.h @@ -0,0 +1,94 @@ +/** + * @file lv_obj_class.h + * + */ + +#ifndef LV_OBJ_CLASS_H +#define LV_OBJ_CLASS_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include +#include + +/********************* + * DEFINES + *********************/ + + +/********************** + * TYPEDEFS + **********************/ + +struct _lv_obj_t; +struct _lv_obj_class_t; +struct _lv_event_t; + +typedef enum { + LV_OBJ_CLASS_EDITABLE_INHERIT, /**< Check the base class. Must have 0 value to let zero initialized class inherit*/ + LV_OBJ_CLASS_EDITABLE_TRUE, + LV_OBJ_CLASS_EDITABLE_FALSE, +} lv_obj_class_editable_t; + +typedef enum { + LV_OBJ_CLASS_GROUP_DEF_INHERIT, /**< Check the base class. Must have 0 value to let zero initialized class inherit*/ + LV_OBJ_CLASS_GROUP_DEF_TRUE, + LV_OBJ_CLASS_GROUP_DEF_FALSE, +} lv_obj_class_group_def_t; + +typedef void (*lv_obj_class_event_cb_t)(struct _lv_obj_class_t * class_p, struct _lv_event_t * e); +/** + * Describe the common methods of every object. + * Similar to a C++ class. + */ +typedef struct _lv_obj_class_t { + const struct _lv_obj_class_t * base_class; + void (*constructor_cb)(const struct _lv_obj_class_t * class_p, struct _lv_obj_t * obj); + void (*destructor_cb)(const struct _lv_obj_class_t * class_p, struct _lv_obj_t * obj); +#if LV_USE_USER_DATA + void * user_data; +#endif + void (*event_cb)(const struct _lv_obj_class_t * class_p, + struct _lv_event_t * e); /**< Widget type specific event function*/ + lv_coord_t width_def; + lv_coord_t height_def; + uint32_t editable : 2; /**< Value from ::lv_obj_class_editable_t*/ + uint32_t group_def : 2; /**< Value from ::lv_obj_class_group_def_t*/ + uint32_t instance_size : 16; +} lv_obj_class_t; + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +/** + * Create an object form a class descriptor + * @param class_p pointer to a class + * @param parent pointer to an object where the new object should be created + * @return pointer to the created object + */ +struct _lv_obj_t * lv_obj_class_create_obj(const struct _lv_obj_class_t * class_p, struct _lv_obj_t * parent); + +void lv_obj_class_init_obj(struct _lv_obj_t * obj); + +void _lv_obj_destruct(struct _lv_obj_t * obj); + +bool lv_obj_is_editable(struct _lv_obj_t * obj); + +bool lv_obj_is_group_def(struct _lv_obj_t * obj); + +/********************** + * MACROS + **********************/ + + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif /*LV_OBJ_CLASS_H*/ diff --git a/src/lib/lvgl/src/core/lv_obj_draw.h b/src/lib/lvgl/src/core/lv_obj_draw.h new file mode 100644 index 0000000..0632165 --- /dev/null +++ b/src/lib/lvgl/src/core/lv_obj_draw.h @@ -0,0 +1,163 @@ +/** + * @file lv_obj_draw.h + * + */ + +#ifndef LV_OBJ_DRAW_H +#define LV_OBJ_DRAW_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include "../draw/lv_draw.h" + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +struct _lv_obj_t; +struct _lv_obj_class_t; + +/** Cover check results.*/ +typedef enum { + LV_COVER_RES_COVER = 0, + LV_COVER_RES_NOT_COVER = 1, + LV_COVER_RES_MASKED = 2, +} lv_cover_res_t; + +typedef struct { + lv_draw_ctx_t * draw_ctx; /**< Draw context*/ + const struct _lv_obj_class_t * class_p; /**< The class that sent the event */ + uint32_t type; /**< The type if part being draw. Element of `lv__draw_part_type_t` */ + lv_area_t * draw_area; /**< The area of the part being drawn*/ + lv_draw_rect_dsc_t * + rect_dsc; /**< A draw descriptor that can be modified to changed what LVGL will draw. Set only for rectangle-like parts*/ + lv_draw_label_dsc_t * + label_dsc; /**< A draw descriptor that can be modified to changed what LVGL will draw. Set only for text-like parts*/ + lv_draw_line_dsc_t * + line_dsc; /**< A draw descriptor that can be modified to changed what LVGL will draw. Set only for line-like parts*/ + lv_draw_img_dsc_t * + img_dsc; /**< A draw descriptor that can be modified to changed what LVGL will draw. Set only for image-like parts*/ + lv_draw_arc_dsc_t * + arc_dsc; /**< A draw descriptor that can be modified to changed what LVGL will draw. Set only for arc-like parts*/ + const lv_point_t * + p1; /**< A point calculated during drawing. E.g. a point of chart or the center of an arc.*/ + const lv_point_t * p2; /**< A point calculated during drawing. E.g. a point of chart.*/ + char * text; /**< A text calculated during drawing. Can be modified. E.g. tick labels on a chart axis.*/ + uint32_t text_length; /**< Size of the text buffer containing null-terminated text string calculated during drawing.*/ + uint32_t part; /**< The current part for which the event is sent*/ + uint32_t id; /**< The index of the part. E.g. a button's index on button matrix or table cell index.*/ + lv_coord_t radius; /**< E.g. the radius of an arc (not the corner radius).*/ + int32_t value; /**< A value calculated during drawing. E.g. Chart's tick line value.*/ + const void * sub_part_ptr; /**< A pointer the identifies something in the part. E.g. chart series. */ +} lv_obj_draw_part_dsc_t; + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +/** + * Initialize a rectangle draw descriptor from an object's styles in its current state + * @param obj pointer to an object + * @param part part of the object. E.g. `LV_PART_MAIN`, `LV_PART_SCROLLBAR`, `LV_PART_KNOB`, etc + * @param draw_dsc the descriptor to initialize. + * If an `..._opa` field is set to `LV_OPA_TRANSP` the related properties won't be initialized. + * Should be initialized with `lv_draw_rect_dsc_init(draw_dsc)`. + * @note Only the relevant fields will be set. + * E.g. if `border width == 0` the other border properties won't be evaluated. + */ +void lv_obj_init_draw_rect_dsc(struct _lv_obj_t * obj, uint32_t part, lv_draw_rect_dsc_t * draw_dsc); + +/** + * Initialize a label draw descriptor from an object's styles in its current state + * @param obj pointer to an object + * @param part part of the object. E.g. `LV_PART_MAIN`, `LV_PART_SCROLLBAR`, `LV_PART_KNOB`, etc + * @param draw_dsc the descriptor to initialize. + * If the `opa` field is set to or the property is equal to `LV_OPA_TRANSP` the rest won't be initialized. + * Should be initialized with `lv_draw_label_dsc_init(draw_dsc)`. + */ +void lv_obj_init_draw_label_dsc(struct _lv_obj_t * obj, uint32_t part, lv_draw_label_dsc_t * draw_dsc); + +/** + * Initialize an image draw descriptor from an object's styles in its current state + * @param obj pointer to an object + * @param part part of the object. E.g. `LV_PART_MAIN`, `LV_PART_SCROLLBAR`, `LV_PART_KNOB`, etc + * @param draw_dsc the descriptor to initialize. + * Should be initialized with `lv_draw_image_dsc_init(draw_dsc)`. + */ +void lv_obj_init_draw_img_dsc(struct _lv_obj_t * obj, uint32_t part, lv_draw_img_dsc_t * draw_dsc); + + +/** + * Initialize a line draw descriptor from an object's styles in its current state + * @param obj pointer to an object + * @param part part of the object. E.g. `LV_PART_MAIN`, `LV_PART_SCROLLBAR`, `LV_PART_KNOB`, etc + * @param draw_dsc the descriptor to initialize. + * Should be initialized with `lv_draw_line_dsc_init(draw_dsc)`. + */ +void lv_obj_init_draw_line_dsc(struct _lv_obj_t * obj, uint32_t part, lv_draw_line_dsc_t * draw_dsc); + +/** + * Initialize an arc draw descriptor from an object's styles in its current state + * @param obj pointer to an object + * @param part part of the object. E.g. `LV_PART_MAIN`, `LV_PART_SCROLLBAR`, `LV_PART_KNOB`, etc + * @param draw_dsc the descriptor to initialize. + * Should be initialized with `lv_draw_arc_dsc_init(draw_dsc)`. + */ +void lv_obj_init_draw_arc_dsc(struct _lv_obj_t * obj, uint32_t part, lv_draw_arc_dsc_t * draw_dsc); + +/** + * Get the required extra size (around the object's part) to draw shadow, outline, value etc. + * @param obj pointer to an object + * @param part part of the object + * @return the extra size required around the object + */ +lv_coord_t lv_obj_calculate_ext_draw_size(struct _lv_obj_t * obj, uint32_t part); + +/** + * Initialize a draw descriptor used in events. + * @param dsc pointer to a descriptor. Later it should be passed as parameter to an `LV_EEVNT_DRAW_PART_BEGIN/END` event. + * @param draw the current draw context. (usually returned by `lv_event_get_draw_ctx(e)`) + */ +void lv_obj_draw_dsc_init(lv_obj_draw_part_dsc_t * dsc, lv_draw_ctx_t * draw_ctx); + +/** + * Check the type obj a part draw descriptor + * @param dsc the descriptor (normally the event parameter) + * @param class_p pointer to class to which `type` is related + * @param type element of `lv__draw_part_type_t` + * @return true if ::dsc is related to ::class_p and ::type + */ +bool lv_obj_draw_part_check_type(lv_obj_draw_part_dsc_t * dsc, const struct _lv_obj_class_t * class_p, uint32_t type); + +/** + * Send a 'LV_EVENT_REFR_EXT_DRAW_SIZE' Call the ancestor's event handler to the object to refresh the value of the extended draw size. + * The result will be saved in `obj`. + * @param obj pointer to an object + */ +void lv_obj_refresh_ext_draw_size(struct _lv_obj_t * obj); + +/** + * Get the extended draw area of an object. + * @param obj pointer to an object + * @return the size extended draw area around the real coordinates + */ +lv_coord_t _lv_obj_get_ext_draw_size(const struct _lv_obj_t * obj); + +/********************** + * MACROS + **********************/ + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif /*LV_OBJ_DRAW_H*/ diff --git a/src/lib/lvgl/src/core/lv_obj_pos.h b/src/lib/lvgl/src/core/lv_obj_pos.h new file mode 100644 index 0000000..6013039 --- /dev/null +++ b/src/lib/lvgl/src/core/lv_obj_pos.h @@ -0,0 +1,431 @@ +/** + * @file lv_obj_pos.h + * + */ + +#ifndef LV_OBJ_POS_H +#define LV_OBJ_POS_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include "../misc/lv_area.h" + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ +struct _lv_obj_t; + +typedef void (*lv_layout_update_cb_t)(struct _lv_obj_t *, void * user_data); +typedef struct { + lv_layout_update_cb_t cb; + void * user_data; +} lv_layout_dsc_t; + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +/** + * Set the position of an object relative to the set alignment. + * @param obj pointer to an object + * @param x new x coordinate + * @param y new y coordinate + * @note With default alignment it's the distance from the top left corner + * @note E.g. LV_ALIGN_CENTER alignment it's the offset from the center of the parent + * @note The position is interpreted on the content area of the parent + * @note The values can be set in pixel or in percentage of parent size with `lv_pct(v)` + */ +void lv_obj_set_pos(struct _lv_obj_t * obj, lv_coord_t x, lv_coord_t y); + +/** + * Set the x coordinate of an object + * @param obj pointer to an object + * @param x new x coordinate + * @note With default alignment it's the distance from the top left corner + * @note E.g. LV_ALIGN_CENTER alignment it's the offset from the center of the parent + * @note The position is interpreted on the content area of the parent + * @note The values can be set in pixel or in percentage of parent size with `lv_pct(v)` + */ +void lv_obj_set_x(struct _lv_obj_t * obj, lv_coord_t x); + +/** + * Set the y coordinate of an object + * @param obj pointer to an object + * @param y new y coordinate + * @note With default alignment it's the distance from the top left corner + * @note E.g. LV_ALIGN_CENTER alignment it's the offset from the center of the parent + * @note The position is interpreted on the content area of the parent + * @note The values can be set in pixel or in percentage of parent size with `lv_pct(v)` + */ +void lv_obj_set_y(struct _lv_obj_t * obj, lv_coord_t y); + +/** + * Set the size of an object. + * @param obj pointer to an object + * @param w the new width + * @param h the new height + * @note possible values are: + * pixel simple set the size accordingly + * LV_SIZE_CONTENT set the size to involve all children in the given direction + * LV_SIZE_PCT(x) to set size in percentage of the parent's content area size (the size without paddings). + * x should be in [0..1000]% range + */ +void lv_obj_set_size(struct _lv_obj_t * obj, lv_coord_t w, lv_coord_t h); + +/** + * Recalculate the size of the object + * @param obj pointer to an object + * @return true: the size has been changed + */ +bool lv_obj_refr_size(struct _lv_obj_t * obj); + +/** + * Set the width of an object + * @param obj pointer to an object + * @param w the new width + * @note possible values are: + * pixel simple set the size accordingly + * LV_SIZE_CONTENT set the size to involve all children in the given direction + * lv_pct(x) to set size in percentage of the parent's content area size (the size without paddings). + * x should be in [0..1000]% range + */ +void lv_obj_set_width(struct _lv_obj_t * obj, lv_coord_t w); + +/** + * Set the height of an object + * @param obj pointer to an object + * @param h the new height + * @note possible values are: + * pixel simple set the size accordingly + * LV_SIZE_CONTENT set the size to involve all children in the given direction + * lv_pct(x) to set size in percentage of the parent's content area size (the size without paddings). + * x should be in [0..1000]% range + */ +void lv_obj_set_height(struct _lv_obj_t * obj, lv_coord_t h); + +/** + * Set the width reduced by the left and right padding and the border width. + * @param obj pointer to an object + * @param w the width without paddings in pixels + */ +void lv_obj_set_content_width(struct _lv_obj_t * obj, lv_coord_t w); + +/** + * Set the height reduced by the top and bottom padding and the border width. + * @param obj pointer to an object + * @param h the height without paddings in pixels + */ +void lv_obj_set_content_height(struct _lv_obj_t * obj, lv_coord_t h); + +/** + * Set a layout for an object + * @param obj pointer to an object + * @param layout pointer to a layout descriptor to set + */ +void lv_obj_set_layout(struct _lv_obj_t * obj, uint32_t layout); + +/** + * Test whether the and object is positioned by a layout or not + * @param obj pointer to an object to test + * @return true: positioned by a layout; false: not positioned by a layout + */ +bool lv_obj_is_layout_positioned(const struct _lv_obj_t * obj); + +/** + * Mark the object for layout update. + * @param obj pointer to an object whose children needs to be updated + */ +void lv_obj_mark_layout_as_dirty(struct _lv_obj_t * obj); + +/** + * Update the layout of an object. + * @param obj pointer to an object whose children needs to be updated + */ +void lv_obj_update_layout(const struct _lv_obj_t * obj); + +/** + * Register a new layout + * @param cb the layout update callback + * @param user_data custom data that will be passed to `cb` + * @return the ID of the new layout + */ +uint32_t lv_layout_register(lv_layout_update_cb_t cb, void * user_data); + +/** + * Change the alignment of an object. + * @param obj pointer to an object to align + * @param align type of alignment (see 'lv_align_t' enum) `LV_ALIGN_OUT_...` can't be used. + */ +void lv_obj_set_align(struct _lv_obj_t * obj, lv_align_t align); + +/** + * Change the alignment of an object and set new coordinates. + * Equivalent to: + * lv_obj_set_align(obj, align); + * lv_obj_set_pos(obj, x_ofs, y_ofs); + * @param obj pointer to an object to align + * @param align type of alignment (see 'lv_align_t' enum) `LV_ALIGN_OUT_...` can't be used. + * @param x_ofs x coordinate offset after alignment + * @param y_ofs y coordinate offset after alignment + */ +void lv_obj_align(struct _lv_obj_t * obj, lv_align_t align, lv_coord_t x_ofs, lv_coord_t y_ofs); + +/** + * Align an object to an other object. + * @param obj pointer to an object to align + * @param base pointer to an other object (if NULL `obj`s parent is used). 'obj' will be aligned to it. + * @param align type of alignment (see 'lv_align_t' enum) + * @param x_ofs x coordinate offset after alignment + * @param y_ofs y coordinate offset after alignment + * @note if the position or size of `base` changes `obj` needs to be aligned manually again + */ +void lv_obj_align_to(struct _lv_obj_t * obj, const struct _lv_obj_t * base, lv_align_t align, lv_coord_t x_ofs, + lv_coord_t y_ofs); + +/** + * Align an object to the center on its parent. + * @param obj pointer to an object to align + * @note if the parent size changes `obj` needs to be aligned manually again + */ +static inline void lv_obj_center(struct _lv_obj_t * obj) +{ + lv_obj_align(obj, LV_ALIGN_CENTER, 0, 0); +} + + +/** + * Copy the coordinates of an object to an area + * @param obj pointer to an object + * @param coords pointer to an area to store the coordinates + */ +void lv_obj_get_coords(const struct _lv_obj_t * obj, lv_area_t * coords); + +/** + * Get the x coordinate of object. + * @param obj pointer to an object + * @return distance of `obj` from the left side of its parent plus the parent's left padding + * @note The position of the object is recalculated only on the next redraw. To force coordinate recalculation + * call `lv_obj_update_layout(obj)`. + * @note Zero return value means the object is on the left padding of the parent, and not on the left edge. + * @note Scrolling of the parent doesn't change the returned value. + * @note The returned value is always the distance from the parent even if `obj` is positioned by a layout. + */ +lv_coord_t lv_obj_get_x(const struct _lv_obj_t * obj); + +/** + * Get the x2 coordinate of object. + * @param obj pointer to an object + * @return distance of `obj` from the right side of its parent plus the parent's right padding + * @note The position of the object is recalculated only on the next redraw. To force coordinate recalculation + * call `lv_obj_update_layout(obj)`. + * @note Zero return value means the object is on the right padding of the parent, and not on the right edge. + * @note Scrolling of the parent doesn't change the returned value. + * @note The returned value is always the distance from the parent even if `obj` is positioned by a layout. + */ +lv_coord_t lv_obj_get_x2(const struct _lv_obj_t * obj); + +/** + * Get the y coordinate of object. + * @param obj pointer to an object + * @return distance of `obj` from the top side of its parent plus the parent's top padding + * @note The position of the object is recalculated only on the next redraw. To force coordinate recalculation + * call `lv_obj_update_layout(obj)`. + * @note Zero return value means the object is on the top padding of the parent, and not on the top edge. + * @note Scrolling of the parent doesn't change the returned value. + * @note The returned value is always the distance from the parent even if `obj` is positioned by a layout. + */ +lv_coord_t lv_obj_get_y(const struct _lv_obj_t * obj); + +/** + * Get the y2 coordinate of object. + * @param obj pointer to an object + * @return distance of `obj` from the bottom side of its parent plus the parent's bottom padding + * @note The position of the object is recalculated only on the next redraw. To force coordinate recalculation + * call `lv_obj_update_layout(obj)`. + * @note Zero return value means the object is on the bottom padding of the parent, and not on the bottom edge. + * @note Scrolling of the parent doesn't change the returned value. + * @note The returned value is always the distance from the parent even if `obj` is positioned by a layout. + */ +lv_coord_t lv_obj_get_y2(const struct _lv_obj_t * obj); + +/** + * Get the actually set x coordinate of object, i.e. the offset form the set alignment + * @param obj pointer to an object + * @return the set x coordinate + */ +lv_coord_t lv_obj_get_x_aligned(const struct _lv_obj_t * obj); + +/** + * Get the actually set y coordinate of object, i.e. the offset form the set alignment + * @param obj pointer to an object + * @return the set y coordinate + */ +lv_coord_t lv_obj_get_y_aligned(const struct _lv_obj_t * obj); + +/** + * Get the width of an object + * @param obj pointer to an object + * @note The position of the object is recalculated only on the next redraw. To force coordinate recalculation + * call `lv_obj_update_layout(obj)`. + * @return the width in pixels + */ +lv_coord_t lv_obj_get_width(const struct _lv_obj_t * obj); + +/** + * Get the height of an object + * @param obj pointer to an object + * @note The position of the object is recalculated only on the next redraw. To force coordinate recalculation + * call `lv_obj_update_layout(obj)`. + * @return the height in pixels + */ +lv_coord_t lv_obj_get_height(const struct _lv_obj_t * obj); + +/** + * Get the width reduced by the left and right padding and the border width. + * @param obj pointer to an object + * @note The position of the object is recalculated only on the next redraw. To force coordinate recalculation + * call `lv_obj_update_layout(obj)`. + * @return the width which still fits into its parent without causing overflow (making the parent scrollable) + */ +lv_coord_t lv_obj_get_content_width(const struct _lv_obj_t * obj); + +/** + * Get the height reduced by the top and bottom padding and the border width. + * @param obj pointer to an object + * @note The position of the object is recalculated only on the next redraw. To force coordinate recalculation + * call `lv_obj_update_layout(obj)`. + * @return the height which still fits into the parent without causing overflow (making the parent scrollable) + */ +lv_coord_t lv_obj_get_content_height(const struct _lv_obj_t * obj); + +/** + * Get the area reduced by the paddings and the border width. + * @param obj pointer to an object + * @note The position of the object is recalculated only on the next redraw. To force coordinate recalculation + * call `lv_obj_update_layout(obj)`. + * @param area the area which still fits into the parent without causing overflow (making the parent scrollable) + */ +void lv_obj_get_content_coords(const struct _lv_obj_t * obj, lv_area_t * area); + +/** + * Get the width occupied by the "parts" of the widget. E.g. the width of all columns of a table. + * @param obj pointer to an objects + * @return the width of the virtually drawn content + * @note This size independent from the real size of the widget. + * It just tells how large the internal ("virtual") content is. + */ +lv_coord_t lv_obj_get_self_width(const struct _lv_obj_t * obj); + +/** + * Get the height occupied by the "parts" of the widget. E.g. the height of all rows of a table. + * @param obj pointer to an objects + * @return the width of the virtually drawn content + * @note This size independent from the real size of the widget. + * It just tells how large the internal ("virtual") content is. + */ +lv_coord_t lv_obj_get_self_height(const struct _lv_obj_t * obj); + +/** + * Handle if the size of the internal ("virtual") content of an object has changed. + * @param obj pointer to an object + * @return false: nothing happened; true: refresh happened + */ +bool lv_obj_refresh_self_size(struct _lv_obj_t * obj); + +void lv_obj_refr_pos(struct _lv_obj_t * obj); + +void lv_obj_move_to(struct _lv_obj_t * obj, lv_coord_t x, lv_coord_t y); + + +void lv_obj_move_children_by(struct _lv_obj_t * obj, lv_coord_t x_diff, lv_coord_t y_diff, bool ignore_floating); + +/** + * Mark an area of an object as invalid. + * The area will be truncated to the object's area and marked for redraw. + * @param obj pointer to an object + * @param area the area to redraw + */ +void lv_obj_invalidate_area(const struct _lv_obj_t * obj, const lv_area_t * area); + +/** + * Mark the object as invalid to redrawn its area + * @param obj pointer to an object + */ +void lv_obj_invalidate(const struct _lv_obj_t * obj); + +/** + * Tell whether an area of an object is visible (even partially) now or not + * @param obj pointer to an object + * @param area the are to check. The visible part of the area will be written back here. + * @return true visible; false not visible (hidden, out of parent, on other screen, etc) + */ +bool lv_obj_area_is_visible(const struct _lv_obj_t * obj, lv_area_t * area); + +/** + * Tell whether an object is visible (even partially) now or not + * @param obj pointer to an object + * @return true: visible; false not visible (hidden, out of parent, on other screen, etc) + */ +bool lv_obj_is_visible(const struct _lv_obj_t * obj); + +/** + * Set the size of an extended clickable area + * @param obj pointer to an object + * @param size extended clickable area in all 4 directions [px] + */ +void lv_obj_set_ext_click_area(struct _lv_obj_t * obj, lv_coord_t size); + +/** + * Get the an area where to object can be clicked. + * It's the object's normal area plus the extended click area. + * @param obj pointer to an object + * @param area store the result area here + */ +void lv_obj_get_click_area(const struct _lv_obj_t * obj, lv_area_t * area); + +/** + * Hit-test an object given a particular point in screen space. + * @param obj object to hit-test + * @param point screen-space point (absolute coordinate) + * @return true: if the object is considered under the point + */ +bool lv_obj_hit_test(struct _lv_obj_t * obj, const lv_point_t * point); + +/** + * Clamp a width between min and max width. If the min/max width is in percentage value use the ref_width + * @param width width to clamp + * @param min_width the minimal width + * @param max_width the maximal width + * @param ref_width the reference width used when min/max width is in percentage + * @return the clamped width + */ +lv_coord_t lv_clamp_width(lv_coord_t width, lv_coord_t min_width, lv_coord_t max_width, lv_coord_t ref_width); + +/** + * Clamp a height between min and max height. If the min/max height is in percentage value use the ref_height + * @param height height to clamp + * @param min_height the minimal height + * @param max_height the maximal height + * @param ref_height the reference height used when min/max height is in percentage + * @return the clamped height + */ +lv_coord_t lv_clamp_height(lv_coord_t height, lv_coord_t min_height, lv_coord_t max_height, lv_coord_t ref_height); + +/********************** + * MACROS + **********************/ + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif /*LV_OBJ_POS_H*/ diff --git a/src/lib/lvgl/src/core/lv_obj_scroll.h b/src/lib/lvgl/src/core/lv_obj_scroll.h new file mode 100644 index 0000000..c9fdd72 --- /dev/null +++ b/src/lib/lvgl/src/core/lv_obj_scroll.h @@ -0,0 +1,294 @@ +/** + * @file lv_obj_scroll.h + * + */ + +#ifndef LV_OBJ_SCROLL_H +#define LV_OBJ_SCROLL_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include "../misc/lv_area.h" +#include "../misc/lv_anim.h" + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +/*Can't include lv_obj.h because it includes this header file*/ +struct _lv_obj_t; + +/** Scrollbar modes: shows when should the scrollbars be visible*/ +enum { + LV_SCROLLBAR_MODE_OFF, /**< Never show scrollbars*/ + LV_SCROLLBAR_MODE_ON, /**< Always show scrollbars*/ + LV_SCROLLBAR_MODE_ACTIVE, /**< Show scroll bars when object is being scrolled*/ + LV_SCROLLBAR_MODE_AUTO, /**< Show scroll bars when the content is large enough to be scrolled*/ +}; +typedef uint8_t lv_scrollbar_mode_t; + + +/** Scroll span align options. Tells where to align the snappable children when scroll stops.*/ +enum { + LV_SCROLL_SNAP_NONE, /**< Do not align, leave where it is*/ + LV_SCROLL_SNAP_START, /**< Align to the left/top*/ + LV_SCROLL_SNAP_END, /**< Align to the right/bottom*/ + LV_SCROLL_SNAP_CENTER /**< Align to the center*/ +}; +typedef uint8_t lv_scroll_snap_t; + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +/*===================== + * Setter functions + *====================*/ + +/** + * Set how the scrollbars should behave. + * @param obj pointer to an object + * @param mode LV_SCROLL_MODE_ON/OFF/AUTO/ACTIVE + */ +void lv_obj_set_scrollbar_mode(struct _lv_obj_t * obj, lv_scrollbar_mode_t mode); + +/** + * Set the object in which directions can be scrolled + * @param obj pointer to an object + * @param dir the allow scroll directions. An element or OR-ed values of `lv_dir_t` + */ +void lv_obj_set_scroll_dir(struct _lv_obj_t * obj, lv_dir_t dir); + +/** + * Set where to snap the children when scrolling ends horizontally + * @param obj pointer to an object + * @param align the snap align to set from `lv_scroll_snap_t` + */ +void lv_obj_set_scroll_snap_x(struct _lv_obj_t * obj, lv_scroll_snap_t align); + +/** + * Set where to snap the children when scrolling ends vertically + * @param obj pointer to an object + * @param align the snap align to set from `lv_scroll_snap_t` + */ +void lv_obj_set_scroll_snap_y(struct _lv_obj_t * obj, lv_scroll_snap_t align); + +/*===================== + * Getter functions + *====================*/ + +/** + * Get the current scroll mode (when to hide the scrollbars) + * @param obj pointer to an object + * @return the current scroll mode from `lv_scrollbar_mode_t` + */ +lv_scrollbar_mode_t lv_obj_get_scrollbar_mode(const struct _lv_obj_t * obj); + +/** + * Get the object in which directions can be scrolled + * @param obj pointer to an object + * @param dir the allow scroll directions. An element or OR-ed values of `lv_dir_t` + */ +lv_dir_t lv_obj_get_scroll_dir(const struct _lv_obj_t * obj); + +/** + * Get where to snap the children when scrolling ends horizontally + * @param obj pointer to an object + * @return the current snap align from `lv_scroll_snap_t` + */ +lv_scroll_snap_t lv_obj_get_scroll_snap_x(const struct _lv_obj_t * obj); + +/** + * Get where to snap the children when scrolling ends vertically + * @param obj pointer to an object + * @return the current snap align from `lv_scroll_snap_t` + */ +lv_scroll_snap_t lv_obj_get_scroll_snap_y(const struct _lv_obj_t * obj); + +/** + * Get current X scroll position. + * @param obj pointer to an object + * @return the current scroll position from the left edge. + * If the object is not scrolled return 0 + * If scrolled return > 0 + * If scrolled in (elastic scroll) return < 0 + */ +lv_coord_t lv_obj_get_scroll_x(const struct _lv_obj_t * obj); + +/** + * Get current Y scroll position. + * @param obj pointer to an object + * @return the current scroll position from the top edge. + * If the object is not scrolled return 0 + * If scrolled return > 0 + * If scrolled inside return < 0 + */ +lv_coord_t lv_obj_get_scroll_y(const struct _lv_obj_t * obj); + +/** + * Return the height of the area above the object. + * That is the number of pixels the object can be scrolled down. + * Normally positive but can be negative when scrolled inside. + * @param obj pointer to an object + * @return the scrollable area above the object in pixels + */ +lv_coord_t lv_obj_get_scroll_top(struct _lv_obj_t * obj); + +/** + * Return the height of the area below the object. + * That is the number of pixels the object can be scrolled down. + * Normally positive but can be negative when scrolled inside. + * @param obj pointer to an object + * @return the scrollable area below the object in pixels + */ +lv_coord_t lv_obj_get_scroll_bottom(struct _lv_obj_t * obj); + +/** + * Return the width of the area on the left the object. + * That is the number of pixels the object can be scrolled down. + * Normally positive but can be negative when scrolled inside. + * @param obj pointer to an object + * @return the scrollable area on the left the object in pixels + */ +lv_coord_t lv_obj_get_scroll_left(struct _lv_obj_t * obj); + +/** + * Return the width of the area on the right the object. + * That is the number of pixels the object can be scrolled down. + * Normally positive but can be negative when scrolled inside. + * @param obj pointer to an object + * @return the scrollable area on the right the object in pixels + */ +lv_coord_t lv_obj_get_scroll_right(struct _lv_obj_t * obj); + +/** + * Get the X and Y coordinates where the scrolling will end for this object if a scrolling animation is in progress. + * If no scrolling animation, give the current `x` or `y` scroll position. + * @param obj pointer to an object + * @param end pointer to store the result + */ +void lv_obj_get_scroll_end(struct _lv_obj_t * obj, lv_point_t * end); + +/*===================== + * Other functions + *====================*/ + +/** + * Scroll by a given amount of pixels + * @param obj pointer to an object to scroll + * @param dx pixels to scroll horizontally + * @param dy pixels to scroll vertically + * @param anim_en LV_ANIM_ON: scroll with animation; LV_ANIM_OFF: scroll immediately + * @note > 0 value means scroll right/bottom (show the more content on the right/bottom) + * @note e.g. dy = -20 means scroll down 20 px + */ +void lv_obj_scroll_by(struct _lv_obj_t * obj, lv_coord_t x, lv_coord_t y, lv_anim_enable_t anim_en); + +/** + * Scroll by a given amount of pixels. + * `dx` and `dy` will be limited internally to allow scrolling only on the content area. + * @param obj pointer to an object to scroll + * @param dx pixels to scroll horizontally + * @param dy pixels to scroll vertically + * @param anim_en LV_ANIM_ON: scroll with animation; LV_ANIM_OFF: scroll immediately + * @note e.g. dy = -20 means scroll down 20 px + */ +void lv_obj_scroll_by_bounded(struct _lv_obj_t * obj, lv_coord_t dx, lv_coord_t dy, lv_anim_enable_t anim_en); + +/** + * Scroll to a given coordinate on an object. + * `x` and `y` will be limited internally to allow scrolling only on the content area. + * @param obj pointer to an object to scroll + * @param x pixels to scroll horizontally + * @param y pixels to scroll vertically + * @param anim_en LV_ANIM_ON: scroll with animation; LV_ANIM_OFF: scroll immediately + */ +void lv_obj_scroll_to(struct _lv_obj_t * obj, lv_coord_t x, lv_coord_t y, lv_anim_enable_t anim_en); + +/** + * Scroll to a given X coordinate on an object. + * `x` will be limited internally to allow scrolling only on the content area. + * @param obj pointer to an object to scroll + * @param x pixels to scroll horizontally + * @param anim_en LV_ANIM_ON: scroll with animation; LV_ANIM_OFF: scroll immediately + */ +void lv_obj_scroll_to_x(struct _lv_obj_t * obj, lv_coord_t x, lv_anim_enable_t anim_en); + +/** + * Scroll to a given Y coordinate on an object + * `y` will be limited internally to allow scrolling only on the content area. + * @param obj pointer to an object to scroll + * @param y pixels to scroll vertically + * @param anim_en LV_ANIM_ON: scroll with animation; LV_ANIM_OFF: scroll immediately + */ +void lv_obj_scroll_to_y(struct _lv_obj_t * obj, lv_coord_t y, lv_anim_enable_t anim_en); + +/** + * Scroll to an object until it becomes visible on its parent + * @param obj pointer to an object to scroll into view + * @param anim_en LV_ANIM_ON: scroll with animation; LV_ANIM_OFF: scroll immediately + */ +void lv_obj_scroll_to_view(struct _lv_obj_t * obj, lv_anim_enable_t anim_en); + +/** + * Scroll to an object until it becomes visible on its parent. + * Do the same on the parent's parent, and so on. + * Therefore the object will be scrolled into view even it has nested scrollable parents + * @param obj pointer to an object to scroll into view + * @param anim_en LV_ANIM_ON: scroll with animation; LV_ANIM_OFF: scroll immediately + */ +void lv_obj_scroll_to_view_recursive(struct _lv_obj_t * obj, lv_anim_enable_t anim_en); + +/** + * Tell whether an object is being scrolled or not at this moment + * @param obj pointer to an object + * @return true: `obj` is being scrolled + */ +bool lv_obj_is_scrolling(const struct _lv_obj_t * obj); + +/** + * Check the children of `obj` and scroll `obj` to fulfill the scroll_snap settings + * @param obj an object whose children needs to checked and snapped + * @param anim_en LV_ANIM_ON/OFF + */ +void lv_obj_update_snap(struct _lv_obj_t * obj, lv_anim_enable_t anim_en); + +/** + * Get the area of the scrollbars + * @param obj pointer to an object + * @param hor pointer to store the area of the horizontal scrollbar + * @param ver pointer to store the area of the vertical scrollbar + */ +void lv_obj_get_scrollbar_area(struct _lv_obj_t * obj, lv_area_t * hor, lv_area_t * ver); + +/** + * Invalidate the area of the scrollbars + * @param obj pointer to an object + */ +void lv_obj_scrollbar_invalidate(struct _lv_obj_t * obj); + +/** + * Checked if the content is scrolled "in" and adjusts it to a normal position. + * @param obj pointer to an object + * @param anim_en LV_ANIM_ON/OFF + */ +void lv_obj_readjust_scroll(struct _lv_obj_t * obj, lv_anim_enable_t anim_en); + +/********************** + * MACROS + **********************/ + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif /*LV_OBJ_SCROLL_H*/ diff --git a/src/lib/lvgl/src/core/lv_obj_style.h b/src/lib/lvgl/src/core/lv_obj_style.h new file mode 100644 index 0000000..7fb2723 --- /dev/null +++ b/src/lib/lvgl/src/core/lv_obj_style.h @@ -0,0 +1,240 @@ +/** + * @file lv_obj_style.h + * + */ + +#ifndef LV_OBJ_STYLE_H +#define LV_OBJ_STYLE_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include +#include +#include "../misc/lv_bidi.h" + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ +/*Can't include lv_obj.h because it includes this header file*/ +struct _lv_obj_t; + +typedef enum { + _LV_STYLE_STATE_CMP_SAME, /*The style properties in the 2 states are identical*/ + _LV_STYLE_STATE_CMP_DIFF_REDRAW, /*The differences can be shown with a simple redraw*/ + _LV_STYLE_STATE_CMP_DIFF_DRAW_PAD, /*The differences can be shown with a simple redraw*/ + _LV_STYLE_STATE_CMP_DIFF_LAYOUT, /*The differences can be shown with a simple redraw*/ +} _lv_style_state_cmp_t; + +typedef uint32_t lv_style_selector_t; + +typedef struct { + lv_style_t * style; + uint32_t selector : 24; + uint32_t is_local : 1; + uint32_t is_trans : 1; +} _lv_obj_style_t; + +typedef struct { + uint16_t time; + uint16_t delay; + lv_style_selector_t selector; + lv_style_prop_t prop; + lv_anim_path_cb_t path_cb; +#if LV_USE_USER_DATA + void * user_data; +#endif +} _lv_obj_style_transition_dsc_t; + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +/** + * Initialize the object related style manager module. + * Called by LVGL in `lv_init()` + */ +void _lv_obj_style_init(void); + +/** + * Add a style to an object. + * @param obj pointer to an object + * @param style pointer to a style to add + * @param selector OR-ed value of parts and state to which the style should be added + * @example lv_obj_add_style(btn, &style_btn, 0); //Default button style + * @example lv_obj_add_style(btn, &btn_red, LV_STATE_PRESSED); //Overwrite only some colors to red when pressed + */ +void lv_obj_add_style(struct _lv_obj_t * obj, lv_style_t * style, lv_style_selector_t selector); + +/** + * Add a style to an object. + * @param obj pointer to an object + * @param style pointer to a style to remove. Can be NULL to check only the selector + * @param selector OR-ed values of states and a part to remove only styles with matching selectors. LV_STATE_ANY and LV_PART_ANY can be used + * @example lv_obj_remove_style(obj, &style, LV_PART_ANY | LV_STATE_ANY); //Remove a specific style + * @example lv_obj_remove_style(obj, NULL, LV_PART_MAIN | LV_STATE_ANY); //Remove all styles from the main part + * @example lv_obj_remove_style(obj, NULL, LV_PART_ANY | LV_STATE_ANY); //Remove all styles + */ +void lv_obj_remove_style(struct _lv_obj_t * obj, lv_style_t * style, lv_style_selector_t selector); + +/** + * Remove all styles from an object + * @param obj pointer to an object + */ +static inline void lv_obj_remove_style_all(struct _lv_obj_t * obj) +{ + lv_obj_remove_style(obj, NULL, LV_PART_ANY | LV_STATE_ANY); +} + +/** + * Notify all object if a style is modified + * @param style pointer to a style. Only the objects with this style will be notified + * (NULL to notify all objects) + */ +void lv_obj_report_style_change(lv_style_t * style); + +/** + * Notify an object and its children about its style is modified. + * @param obj pointer to an object + * @param part the part whose style was changed. E.g. `LV_PART_ANY`, `LV_PART_MAIN` + * @param prop `LV_STYLE_PROP_ANY` or an `LV_STYLE_...` property. + * It is used to optimize what needs to be refreshed. + * `LV_STYLE_PROP_INV` to perform only a style cache update + */ +void lv_obj_refresh_style(struct _lv_obj_t * obj, lv_part_t part, lv_style_prop_t prop); + +/** + * Enable or disable automatic style refreshing when a new style is added/removed to/from an object + * or any other style change happens. + * @param en true: enable refreshing; false: disable refreshing + */ +void lv_obj_enable_style_refresh(bool en); + +/** + * Get the value of a style property. The current state of the object will be considered. + * Inherited properties will be inherited. + * If a property is not set a default value will be returned. + * @param obj pointer to an object + * @param part a part from which the property should be get + * @param prop the property to get + * @return the value of the property. + * Should be read from the correct field of the `lv_style_value_t` according to the type of the property. + */ +lv_style_value_t lv_obj_get_style_prop(const struct _lv_obj_t * obj, lv_part_t part, lv_style_prop_t prop); + +/** + * Set local style property on an object's part and state. + * @param obj pointer to an object + * @param prop the property + * @param value value of the property. The correct element should be set according to the type of the property + * @param selector OR-ed value of parts and state for which the style should be set + */ +void lv_obj_set_local_style_prop(struct _lv_obj_t * obj, lv_style_prop_t prop, lv_style_value_t value, + lv_style_selector_t selector); + +lv_res_t lv_obj_get_local_style_prop(struct _lv_obj_t * obj, lv_style_prop_t prop, lv_style_value_t * value, + lv_style_selector_t selector); + +/** + * Remove a local style property from a part of an object with a given state. + * @param obj pointer to an object + * @param prop a style property to remove. + * @param selector OR-ed value of parts and state for which the style should be removed + * @return true the property was found and removed; false: the property was not found + */ +bool lv_obj_remove_local_style_prop(struct _lv_obj_t * obj, lv_style_prop_t prop, lv_style_selector_t selector); + +/** + * Used internally to create a style transition + * @param obj + * @param part + * @param prev_state + * @param new_state + * @param tr + */ +void _lv_obj_style_create_transition(struct _lv_obj_t * obj, lv_part_t part, lv_state_t prev_state, + lv_state_t new_state, const _lv_obj_style_transition_dsc_t * tr); + +/** + * Used internally to compare the appearance of an object in 2 states + * @param obj + * @param state1 + * @param state2 + * @return + */ +_lv_style_state_cmp_t _lv_obj_style_state_compare(struct _lv_obj_t * obj, lv_state_t state1, lv_state_t state2); + +/** + * Fade in an an object and all its children. + * @param obj the object to fade in + * @param time time of fade + * @param delay delay to start the animation + */ +void lv_obj_fade_in(struct _lv_obj_t * obj, uint32_t time, uint32_t delay); + +/** + * Fade out an an object and all its children. + * @param obj the object to fade out + * @param time time of fade + * @param delay delay to start the animation + */ +void lv_obj_fade_out(struct _lv_obj_t * obj, uint32_t time, uint32_t delay); + +lv_state_t lv_obj_style_get_selector_state(lv_style_selector_t selector); + +lv_part_t lv_obj_style_get_selector_part(lv_style_selector_t selector); + +#include "lv_obj_style_gen.h" + +static inline void lv_obj_set_style_pad_all(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector) +{ + lv_obj_set_style_pad_left(obj, value, selector); + lv_obj_set_style_pad_right(obj, value, selector); + lv_obj_set_style_pad_top(obj, value, selector); + lv_obj_set_style_pad_bottom(obj, value, selector); +} + +static inline void lv_obj_set_style_pad_hor(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector) +{ + lv_obj_set_style_pad_left(obj, value, selector); + lv_obj_set_style_pad_right(obj, value, selector); +} + +static inline void lv_obj_set_style_pad_ver(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector) +{ + lv_obj_set_style_pad_top(obj, value, selector); + lv_obj_set_style_pad_bottom(obj, value, selector); +} + +static inline void lv_obj_set_style_pad_gap(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector) +{ + lv_obj_set_style_pad_row(obj, value, selector); + lv_obj_set_style_pad_column(obj, value, selector); +} + +static inline void lv_obj_set_style_size(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector) +{ + lv_obj_set_style_width(obj, value, selector); + lv_obj_set_style_height(obj, value, selector); +} + +lv_text_align_t lv_obj_calculate_style_text_align(const struct _lv_obj_t * obj, lv_part_t part, const char * txt); + + +/********************** + * MACROS + **********************/ + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif /*LV_OBJ_STYLE_H*/ diff --git a/src/lib/lvgl/src/core/lv_obj_style_gen.h b/src/lib/lvgl/src/core/lv_obj_style_gen.h new file mode 100644 index 0000000..e4383d5 --- /dev/null +++ b/src/lib/lvgl/src/core/lv_obj_style_gen.h @@ -0,0 +1,640 @@ +static inline lv_coord_t lv_obj_get_style_width(const struct _lv_obj_t * obj, uint32_t part) +{ + lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_WIDTH); + return (lv_coord_t)v.num; +} + +static inline lv_coord_t lv_obj_get_style_min_width(const struct _lv_obj_t * obj, uint32_t part) +{ + lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_MIN_WIDTH); + return (lv_coord_t)v.num; +} + +static inline lv_coord_t lv_obj_get_style_max_width(const struct _lv_obj_t * obj, uint32_t part) +{ + lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_MAX_WIDTH); + return (lv_coord_t)v.num; +} + +static inline lv_coord_t lv_obj_get_style_height(const struct _lv_obj_t * obj, uint32_t part) +{ + lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_HEIGHT); + return (lv_coord_t)v.num; +} + +static inline lv_coord_t lv_obj_get_style_min_height(const struct _lv_obj_t * obj, uint32_t part) +{ + lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_MIN_HEIGHT); + return (lv_coord_t)v.num; +} + +static inline lv_coord_t lv_obj_get_style_max_height(const struct _lv_obj_t * obj, uint32_t part) +{ + lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_MAX_HEIGHT); + return (lv_coord_t)v.num; +} + +static inline lv_coord_t lv_obj_get_style_x(const struct _lv_obj_t * obj, uint32_t part) +{ + lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_X); + return (lv_coord_t)v.num; +} + +static inline lv_coord_t lv_obj_get_style_y(const struct _lv_obj_t * obj, uint32_t part) +{ + lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_Y); + return (lv_coord_t)v.num; +} + +static inline lv_align_t lv_obj_get_style_align(const struct _lv_obj_t * obj, uint32_t part) +{ + lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_ALIGN); + return (lv_align_t)v.num; +} + +static inline lv_coord_t lv_obj_get_style_transform_width(const struct _lv_obj_t * obj, uint32_t part) +{ + lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_TRANSFORM_WIDTH); + return (lv_coord_t)v.num; +} + +static inline lv_coord_t lv_obj_get_style_transform_height(const struct _lv_obj_t * obj, uint32_t part) +{ + lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_TRANSFORM_HEIGHT); + return (lv_coord_t)v.num; +} + +static inline lv_coord_t lv_obj_get_style_translate_x(const struct _lv_obj_t * obj, uint32_t part) +{ + lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_TRANSLATE_X); + return (lv_coord_t)v.num; +} + +static inline lv_coord_t lv_obj_get_style_translate_y(const struct _lv_obj_t * obj, uint32_t part) +{ + lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_TRANSLATE_Y); + return (lv_coord_t)v.num; +} + +static inline lv_coord_t lv_obj_get_style_transform_zoom(const struct _lv_obj_t * obj, uint32_t part) +{ + lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_TRANSFORM_ZOOM); + return (lv_coord_t)v.num; +} + +static inline lv_coord_t lv_obj_get_style_transform_angle(const struct _lv_obj_t * obj, uint32_t part) +{ + lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_TRANSFORM_ANGLE); + return (lv_coord_t)v.num; +} + +static inline lv_coord_t lv_obj_get_style_pad_top(const struct _lv_obj_t * obj, uint32_t part) +{ + lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_PAD_TOP); + return (lv_coord_t)v.num; +} + +static inline lv_coord_t lv_obj_get_style_pad_bottom(const struct _lv_obj_t * obj, uint32_t part) +{ + lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_PAD_BOTTOM); + return (lv_coord_t)v.num; +} + +static inline lv_coord_t lv_obj_get_style_pad_left(const struct _lv_obj_t * obj, uint32_t part) +{ + lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_PAD_LEFT); + return (lv_coord_t)v.num; +} + +static inline lv_coord_t lv_obj_get_style_pad_right(const struct _lv_obj_t * obj, uint32_t part) +{ + lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_PAD_RIGHT); + return (lv_coord_t)v.num; +} + +static inline lv_coord_t lv_obj_get_style_pad_row(const struct _lv_obj_t * obj, uint32_t part) +{ + lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_PAD_ROW); + return (lv_coord_t)v.num; +} + +static inline lv_coord_t lv_obj_get_style_pad_column(const struct _lv_obj_t * obj, uint32_t part) +{ + lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_PAD_COLUMN); + return (lv_coord_t)v.num; +} + +static inline lv_color_t lv_obj_get_style_bg_color(const struct _lv_obj_t * obj, uint32_t part) +{ + lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_BG_COLOR); + return v.color; +} + +static inline lv_color_t lv_obj_get_style_bg_color_filtered(const struct _lv_obj_t * obj, uint32_t part) +{ + lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_BG_COLOR_FILTERED); + return v.color; +} + +static inline lv_opa_t lv_obj_get_style_bg_opa(const struct _lv_obj_t * obj, uint32_t part) +{ + lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_BG_OPA); + return (lv_opa_t)v.num; +} + +static inline lv_color_t lv_obj_get_style_bg_grad_color(const struct _lv_obj_t * obj, uint32_t part) +{ + lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_BG_GRAD_COLOR); + return v.color; +} + +static inline lv_color_t lv_obj_get_style_bg_grad_color_filtered(const struct _lv_obj_t * obj, uint32_t part) +{ + lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_BG_GRAD_COLOR_FILTERED); + return v.color; +} + +static inline lv_grad_dir_t lv_obj_get_style_bg_grad_dir(const struct _lv_obj_t * obj, uint32_t part) +{ + lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_BG_GRAD_DIR); + return (lv_grad_dir_t)v.num; +} + +static inline lv_coord_t lv_obj_get_style_bg_main_stop(const struct _lv_obj_t * obj, uint32_t part) +{ + lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_BG_MAIN_STOP); + return (lv_coord_t)v.num; +} + +static inline lv_coord_t lv_obj_get_style_bg_grad_stop(const struct _lv_obj_t * obj, uint32_t part) +{ + lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_BG_GRAD_STOP); + return (lv_coord_t)v.num; +} + +static inline const lv_grad_dsc_t * lv_obj_get_style_bg_grad(const struct _lv_obj_t * obj, uint32_t part) +{ + lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_BG_GRAD); + return (const lv_grad_dsc_t *)v.ptr; +} + +static inline lv_dither_mode_t lv_obj_get_style_bg_dither_mode(const struct _lv_obj_t * obj, uint32_t part) +{ + lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_BG_DITHER_MODE); + return (lv_dither_mode_t)v.num; +} + +static inline const void * lv_obj_get_style_bg_img_src(const struct _lv_obj_t * obj, uint32_t part) +{ + lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_BG_IMG_SRC); + return (const void *)v.ptr; +} + +static inline lv_opa_t lv_obj_get_style_bg_img_opa(const struct _lv_obj_t * obj, uint32_t part) +{ + lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_BG_IMG_OPA); + return (lv_opa_t)v.num; +} + +static inline lv_color_t lv_obj_get_style_bg_img_recolor(const struct _lv_obj_t * obj, uint32_t part) +{ + lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_BG_IMG_RECOLOR); + return v.color; +} + +static inline lv_color_t lv_obj_get_style_bg_img_recolor_filtered(const struct _lv_obj_t * obj, uint32_t part) +{ + lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_BG_IMG_RECOLOR_FILTERED); + return v.color; +} + +static inline lv_opa_t lv_obj_get_style_bg_img_recolor_opa(const struct _lv_obj_t * obj, uint32_t part) +{ + lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_BG_IMG_RECOLOR_OPA); + return (lv_opa_t)v.num; +} + +static inline bool lv_obj_get_style_bg_img_tiled(const struct _lv_obj_t * obj, uint32_t part) +{ + lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_BG_IMG_TILED); + return (bool)v.num; +} + +static inline lv_color_t lv_obj_get_style_border_color(const struct _lv_obj_t * obj, uint32_t part) +{ + lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_BORDER_COLOR); + return v.color; +} + +static inline lv_color_t lv_obj_get_style_border_color_filtered(const struct _lv_obj_t * obj, uint32_t part) +{ + lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_BORDER_COLOR_FILTERED); + return v.color; +} + +static inline lv_opa_t lv_obj_get_style_border_opa(const struct _lv_obj_t * obj, uint32_t part) +{ + lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_BORDER_OPA); + return (lv_opa_t)v.num; +} + +static inline lv_coord_t lv_obj_get_style_border_width(const struct _lv_obj_t * obj, uint32_t part) +{ + lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_BORDER_WIDTH); + return (lv_coord_t)v.num; +} + +static inline lv_border_side_t lv_obj_get_style_border_side(const struct _lv_obj_t * obj, uint32_t part) +{ + lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_BORDER_SIDE); + return (lv_border_side_t)v.num; +} + +static inline bool lv_obj_get_style_border_post(const struct _lv_obj_t * obj, uint32_t part) +{ + lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_BORDER_POST); + return (bool)v.num; +} + +static inline lv_coord_t lv_obj_get_style_outline_width(const struct _lv_obj_t * obj, uint32_t part) +{ + lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_OUTLINE_WIDTH); + return (lv_coord_t)v.num; +} + +static inline lv_color_t lv_obj_get_style_outline_color(const struct _lv_obj_t * obj, uint32_t part) +{ + lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_OUTLINE_COLOR); + return v.color; +} + +static inline lv_color_t lv_obj_get_style_outline_color_filtered(const struct _lv_obj_t * obj, uint32_t part) +{ + lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_OUTLINE_COLOR_FILTERED); + return v.color; +} + +static inline lv_opa_t lv_obj_get_style_outline_opa(const struct _lv_obj_t * obj, uint32_t part) +{ + lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_OUTLINE_OPA); + return (lv_opa_t)v.num; +} + +static inline lv_coord_t lv_obj_get_style_outline_pad(const struct _lv_obj_t * obj, uint32_t part) +{ + lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_OUTLINE_PAD); + return (lv_coord_t)v.num; +} + +static inline lv_coord_t lv_obj_get_style_shadow_width(const struct _lv_obj_t * obj, uint32_t part) +{ + lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_SHADOW_WIDTH); + return (lv_coord_t)v.num; +} + +static inline lv_coord_t lv_obj_get_style_shadow_ofs_x(const struct _lv_obj_t * obj, uint32_t part) +{ + lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_SHADOW_OFS_X); + return (lv_coord_t)v.num; +} + +static inline lv_coord_t lv_obj_get_style_shadow_ofs_y(const struct _lv_obj_t * obj, uint32_t part) +{ + lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_SHADOW_OFS_Y); + return (lv_coord_t)v.num; +} + +static inline lv_coord_t lv_obj_get_style_shadow_spread(const struct _lv_obj_t * obj, uint32_t part) +{ + lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_SHADOW_SPREAD); + return (lv_coord_t)v.num; +} + +static inline lv_color_t lv_obj_get_style_shadow_color(const struct _lv_obj_t * obj, uint32_t part) +{ + lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_SHADOW_COLOR); + return v.color; +} + +static inline lv_color_t lv_obj_get_style_shadow_color_filtered(const struct _lv_obj_t * obj, uint32_t part) +{ + lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_SHADOW_COLOR_FILTERED); + return v.color; +} + +static inline lv_opa_t lv_obj_get_style_shadow_opa(const struct _lv_obj_t * obj, uint32_t part) +{ + lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_SHADOW_OPA); + return (lv_opa_t)v.num; +} + +static inline lv_opa_t lv_obj_get_style_img_opa(const struct _lv_obj_t * obj, uint32_t part) +{ + lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_IMG_OPA); + return (lv_opa_t)v.num; +} + +static inline lv_color_t lv_obj_get_style_img_recolor(const struct _lv_obj_t * obj, uint32_t part) +{ + lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_IMG_RECOLOR); + return v.color; +} + +static inline lv_color_t lv_obj_get_style_img_recolor_filtered(const struct _lv_obj_t * obj, uint32_t part) +{ + lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_IMG_RECOLOR_FILTERED); + return v.color; +} + +static inline lv_opa_t lv_obj_get_style_img_recolor_opa(const struct _lv_obj_t * obj, uint32_t part) +{ + lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_IMG_RECOLOR_OPA); + return (lv_opa_t)v.num; +} + +static inline lv_coord_t lv_obj_get_style_line_width(const struct _lv_obj_t * obj, uint32_t part) +{ + lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_LINE_WIDTH); + return (lv_coord_t)v.num; +} + +static inline lv_coord_t lv_obj_get_style_line_dash_width(const struct _lv_obj_t * obj, uint32_t part) +{ + lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_LINE_DASH_WIDTH); + return (lv_coord_t)v.num; +} + +static inline lv_coord_t lv_obj_get_style_line_dash_gap(const struct _lv_obj_t * obj, uint32_t part) +{ + lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_LINE_DASH_GAP); + return (lv_coord_t)v.num; +} + +static inline bool lv_obj_get_style_line_rounded(const struct _lv_obj_t * obj, uint32_t part) +{ + lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_LINE_ROUNDED); + return (bool)v.num; +} + +static inline lv_color_t lv_obj_get_style_line_color(const struct _lv_obj_t * obj, uint32_t part) +{ + lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_LINE_COLOR); + return v.color; +} + +static inline lv_color_t lv_obj_get_style_line_color_filtered(const struct _lv_obj_t * obj, uint32_t part) +{ + lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_LINE_COLOR_FILTERED); + return v.color; +} + +static inline lv_opa_t lv_obj_get_style_line_opa(const struct _lv_obj_t * obj, uint32_t part) +{ + lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_LINE_OPA); + return (lv_opa_t)v.num; +} + +static inline lv_coord_t lv_obj_get_style_arc_width(const struct _lv_obj_t * obj, uint32_t part) +{ + lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_ARC_WIDTH); + return (lv_coord_t)v.num; +} + +static inline bool lv_obj_get_style_arc_rounded(const struct _lv_obj_t * obj, uint32_t part) +{ + lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_ARC_ROUNDED); + return (bool)v.num; +} + +static inline lv_color_t lv_obj_get_style_arc_color(const struct _lv_obj_t * obj, uint32_t part) +{ + lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_ARC_COLOR); + return v.color; +} + +static inline lv_color_t lv_obj_get_style_arc_color_filtered(const struct _lv_obj_t * obj, uint32_t part) +{ + lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_ARC_COLOR_FILTERED); + return v.color; +} + +static inline lv_opa_t lv_obj_get_style_arc_opa(const struct _lv_obj_t * obj, uint32_t part) +{ + lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_ARC_OPA); + return (lv_opa_t)v.num; +} + +static inline const void * lv_obj_get_style_arc_img_src(const struct _lv_obj_t * obj, uint32_t part) +{ + lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_ARC_IMG_SRC); + return (const void *)v.ptr; +} + +static inline lv_color_t lv_obj_get_style_text_color(const struct _lv_obj_t * obj, uint32_t part) +{ + lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_TEXT_COLOR); + return v.color; +} + +static inline lv_color_t lv_obj_get_style_text_color_filtered(const struct _lv_obj_t * obj, uint32_t part) +{ + lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_TEXT_COLOR_FILTERED); + return v.color; +} + +static inline lv_opa_t lv_obj_get_style_text_opa(const struct _lv_obj_t * obj, uint32_t part) +{ + lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_TEXT_OPA); + return (lv_opa_t)v.num; +} + +static inline const lv_font_t * lv_obj_get_style_text_font(const struct _lv_obj_t * obj, uint32_t part) +{ + lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_TEXT_FONT); + return (const lv_font_t *)v.ptr; +} + +static inline lv_coord_t lv_obj_get_style_text_letter_space(const struct _lv_obj_t * obj, uint32_t part) +{ + lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_TEXT_LETTER_SPACE); + return (lv_coord_t)v.num; +} + +static inline lv_coord_t lv_obj_get_style_text_line_space(const struct _lv_obj_t * obj, uint32_t part) +{ + lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_TEXT_LINE_SPACE); + return (lv_coord_t)v.num; +} + +static inline lv_text_decor_t lv_obj_get_style_text_decor(const struct _lv_obj_t * obj, uint32_t part) +{ + lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_TEXT_DECOR); + return (lv_text_decor_t)v.num; +} + +static inline lv_text_align_t lv_obj_get_style_text_align(const struct _lv_obj_t * obj, uint32_t part) +{ + lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_TEXT_ALIGN); + return (lv_text_align_t)v.num; +} + +static inline lv_coord_t lv_obj_get_style_radius(const struct _lv_obj_t * obj, uint32_t part) +{ + lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_RADIUS); + return (lv_coord_t)v.num; +} + +static inline bool lv_obj_get_style_clip_corner(const struct _lv_obj_t * obj, uint32_t part) +{ + lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_CLIP_CORNER); + return (bool)v.num; +} + +static inline lv_opa_t lv_obj_get_style_opa(const struct _lv_obj_t * obj, uint32_t part) +{ + lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_OPA); + return (lv_opa_t)v.num; +} + +static inline const lv_color_filter_dsc_t * lv_obj_get_style_color_filter_dsc(const struct _lv_obj_t * obj, + uint32_t part) +{ + lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_COLOR_FILTER_DSC); + return (const lv_color_filter_dsc_t *)v.ptr; +} + +static inline lv_opa_t lv_obj_get_style_color_filter_opa(const struct _lv_obj_t * obj, uint32_t part) +{ + lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_COLOR_FILTER_OPA); + return (lv_opa_t)v.num; +} + +static inline uint32_t lv_obj_get_style_anim_time(const struct _lv_obj_t * obj, uint32_t part) +{ + lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_ANIM_TIME); + return (uint32_t)v.num; +} + +static inline uint32_t lv_obj_get_style_anim_speed(const struct _lv_obj_t * obj, uint32_t part) +{ + lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_ANIM_SPEED); + return (uint32_t)v.num; +} + +static inline const lv_style_transition_dsc_t * lv_obj_get_style_transition(const struct _lv_obj_t * obj, uint32_t part) +{ + lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_TRANSITION); + return (const lv_style_transition_dsc_t *)v.ptr; +} + +static inline lv_blend_mode_t lv_obj_get_style_blend_mode(const struct _lv_obj_t * obj, uint32_t part) +{ + lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_BLEND_MODE); + return (lv_blend_mode_t)v.num; +} + +static inline uint16_t lv_obj_get_style_layout(const struct _lv_obj_t * obj, uint32_t part) +{ + lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_LAYOUT); + return (uint16_t)v.num; +} + +static inline lv_base_dir_t lv_obj_get_style_base_dir(const struct _lv_obj_t * obj, uint32_t part) +{ + lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_BASE_DIR); + return (lv_base_dir_t)v.num; +} + +void lv_obj_set_style_width(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector); +void lv_obj_set_style_min_width(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector); +void lv_obj_set_style_max_width(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector); +void lv_obj_set_style_height(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector); +void lv_obj_set_style_min_height(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector); +void lv_obj_set_style_max_height(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector); +void lv_obj_set_style_x(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector); +void lv_obj_set_style_y(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector); +void lv_obj_set_style_align(struct _lv_obj_t * obj, lv_align_t value, lv_style_selector_t selector); +void lv_obj_set_style_transform_width(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector); +void lv_obj_set_style_transform_height(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector); +void lv_obj_set_style_translate_x(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector); +void lv_obj_set_style_translate_y(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector); +void lv_obj_set_style_transform_zoom(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector); +void lv_obj_set_style_transform_angle(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector); +void lv_obj_set_style_pad_top(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector); +void lv_obj_set_style_pad_bottom(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector); +void lv_obj_set_style_pad_left(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector); +void lv_obj_set_style_pad_right(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector); +void lv_obj_set_style_pad_row(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector); +void lv_obj_set_style_pad_column(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector); +void lv_obj_set_style_bg_color(struct _lv_obj_t * obj, lv_color_t value, lv_style_selector_t selector); +void lv_obj_set_style_bg_color_filtered(struct _lv_obj_t * obj, lv_color_t value, lv_style_selector_t selector); +void lv_obj_set_style_bg_opa(struct _lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector); +void lv_obj_set_style_bg_grad_color(struct _lv_obj_t * obj, lv_color_t value, lv_style_selector_t selector); +void lv_obj_set_style_bg_grad_color_filtered(struct _lv_obj_t * obj, lv_color_t value, lv_style_selector_t selector); +void lv_obj_set_style_bg_grad_dir(struct _lv_obj_t * obj, lv_grad_dir_t value, lv_style_selector_t selector); +void lv_obj_set_style_bg_main_stop(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector); +void lv_obj_set_style_bg_grad_stop(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector); +void lv_obj_set_style_bg_grad(struct _lv_obj_t * obj, const lv_grad_dsc_t * value, lv_style_selector_t selector); +void lv_obj_set_style_bg_dither_mode(struct _lv_obj_t * obj, lv_dither_mode_t value, lv_style_selector_t selector); +void lv_obj_set_style_bg_img_src(struct _lv_obj_t * obj, const void * value, lv_style_selector_t selector); +void lv_obj_set_style_bg_img_opa(struct _lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector); +void lv_obj_set_style_bg_img_recolor(struct _lv_obj_t * obj, lv_color_t value, lv_style_selector_t selector); +void lv_obj_set_style_bg_img_recolor_filtered(struct _lv_obj_t * obj, lv_color_t value, lv_style_selector_t selector); +void lv_obj_set_style_bg_img_recolor_opa(struct _lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector); +void lv_obj_set_style_bg_img_tiled(struct _lv_obj_t * obj, bool value, lv_style_selector_t selector); +void lv_obj_set_style_border_color(struct _lv_obj_t * obj, lv_color_t value, lv_style_selector_t selector); +void lv_obj_set_style_border_color_filtered(struct _lv_obj_t * obj, lv_color_t value, lv_style_selector_t selector); +void lv_obj_set_style_border_opa(struct _lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector); +void lv_obj_set_style_border_width(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector); +void lv_obj_set_style_border_side(struct _lv_obj_t * obj, lv_border_side_t value, lv_style_selector_t selector); +void lv_obj_set_style_border_post(struct _lv_obj_t * obj, bool value, lv_style_selector_t selector); +void lv_obj_set_style_outline_width(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector); +void lv_obj_set_style_outline_color(struct _lv_obj_t * obj, lv_color_t value, lv_style_selector_t selector); +void lv_obj_set_style_outline_color_filtered(struct _lv_obj_t * obj, lv_color_t value, lv_style_selector_t selector); +void lv_obj_set_style_outline_opa(struct _lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector); +void lv_obj_set_style_outline_pad(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector); +void lv_obj_set_style_shadow_width(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector); +void lv_obj_set_style_shadow_ofs_x(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector); +void lv_obj_set_style_shadow_ofs_y(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector); +void lv_obj_set_style_shadow_spread(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector); +void lv_obj_set_style_shadow_color(struct _lv_obj_t * obj, lv_color_t value, lv_style_selector_t selector); +void lv_obj_set_style_shadow_color_filtered(struct _lv_obj_t * obj, lv_color_t value, lv_style_selector_t selector); +void lv_obj_set_style_shadow_opa(struct _lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector); +void lv_obj_set_style_img_opa(struct _lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector); +void lv_obj_set_style_img_recolor(struct _lv_obj_t * obj, lv_color_t value, lv_style_selector_t selector); +void lv_obj_set_style_img_recolor_filtered(struct _lv_obj_t * obj, lv_color_t value, lv_style_selector_t selector); +void lv_obj_set_style_img_recolor_opa(struct _lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector); +void lv_obj_set_style_line_width(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector); +void lv_obj_set_style_line_dash_width(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector); +void lv_obj_set_style_line_dash_gap(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector); +void lv_obj_set_style_line_rounded(struct _lv_obj_t * obj, bool value, lv_style_selector_t selector); +void lv_obj_set_style_line_color(struct _lv_obj_t * obj, lv_color_t value, lv_style_selector_t selector); +void lv_obj_set_style_line_color_filtered(struct _lv_obj_t * obj, lv_color_t value, lv_style_selector_t selector); +void lv_obj_set_style_line_opa(struct _lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector); +void lv_obj_set_style_arc_width(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector); +void lv_obj_set_style_arc_rounded(struct _lv_obj_t * obj, bool value, lv_style_selector_t selector); +void lv_obj_set_style_arc_color(struct _lv_obj_t * obj, lv_color_t value, lv_style_selector_t selector); +void lv_obj_set_style_arc_color_filtered(struct _lv_obj_t * obj, lv_color_t value, lv_style_selector_t selector); +void lv_obj_set_style_arc_opa(struct _lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector); +void lv_obj_set_style_arc_img_src(struct _lv_obj_t * obj, const void * value, lv_style_selector_t selector); +void lv_obj_set_style_text_color(struct _lv_obj_t * obj, lv_color_t value, lv_style_selector_t selector); +void lv_obj_set_style_text_color_filtered(struct _lv_obj_t * obj, lv_color_t value, lv_style_selector_t selector); +void lv_obj_set_style_text_opa(struct _lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector); +void lv_obj_set_style_text_font(struct _lv_obj_t * obj, const lv_font_t * value, lv_style_selector_t selector); +void lv_obj_set_style_text_letter_space(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector); +void lv_obj_set_style_text_line_space(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector); +void lv_obj_set_style_text_decor(struct _lv_obj_t * obj, lv_text_decor_t value, lv_style_selector_t selector); +void lv_obj_set_style_text_align(struct _lv_obj_t * obj, lv_text_align_t value, lv_style_selector_t selector); +void lv_obj_set_style_radius(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector); +void lv_obj_set_style_clip_corner(struct _lv_obj_t * obj, bool value, lv_style_selector_t selector); +void lv_obj_set_style_opa(struct _lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector); +void lv_obj_set_style_color_filter_dsc(struct _lv_obj_t * obj, const lv_color_filter_dsc_t * value, + lv_style_selector_t selector); +void lv_obj_set_style_color_filter_opa(struct _lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector); +void lv_obj_set_style_anim_time(struct _lv_obj_t * obj, uint32_t value, lv_style_selector_t selector); +void lv_obj_set_style_anim_speed(struct _lv_obj_t * obj, uint32_t value, lv_style_selector_t selector); +void lv_obj_set_style_transition(struct _lv_obj_t * obj, const lv_style_transition_dsc_t * value, + lv_style_selector_t selector); +void lv_obj_set_style_blend_mode(struct _lv_obj_t * obj, lv_blend_mode_t value, lv_style_selector_t selector); +void lv_obj_set_style_layout(struct _lv_obj_t * obj, uint16_t value, lv_style_selector_t selector); +void lv_obj_set_style_base_dir(struct _lv_obj_t * obj, lv_base_dir_t value, lv_style_selector_t selector); diff --git a/src/lib/lvgl/src/core/lv_obj_tree.h b/src/lib/lvgl/src/core/lv_obj_tree.h new file mode 100644 index 0000000..bee9e16 --- /dev/null +++ b/src/lib/lvgl/src/core/lv_obj_tree.h @@ -0,0 +1,172 @@ +/** + * @file struct _lv_obj_tree.h + * + */ + +#ifndef LV_OBJ_TREE_H +#define LV_OBJ_TREE_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include +#include + +/********************* + * DEFINES + *********************/ + + +/********************** + * TYPEDEFS + **********************/ + +struct _lv_obj_t; +struct _lv_obj_class_t; + +typedef enum { + LV_OBJ_TREE_WALK_NEXT, + LV_OBJ_TREE_WALK_SKIP_CHILDREN, + LV_OBJ_TREE_WALK_END, +} lv_obj_tree_walk_res_t; + +typedef lv_obj_tree_walk_res_t (*lv_obj_tree_walk_cb_t)(struct _lv_obj_t *, void *); + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +/** + * Delete an object and all of its children. + * Also remove the objects from their group and remove all animations (if any). + * Send `LV_EVENT_DELETED` to deleted objects. + * @param obj pointer to an object + */ +void lv_obj_del(struct _lv_obj_t * obj); + +/** + * Delete all children of an object. + * Also remove the objects from their group and remove all animations (if any). + * Send `LV_EVENT_DELETED` to deleted objects. + * @param obj pointer to an object + */ +void lv_obj_clean(struct _lv_obj_t * obj); + +/** + * Delete an object after some delay + * @param obj pointer to an object + * @param delay_ms time to wait before delete in milliseconds + */ +void lv_obj_del_delayed(struct _lv_obj_t * obj, uint32_t delay_ms); + +/** + * A function to be easily used in animation ready callback to delete an object when the animation is ready + * @param a pointer to the animation + */ +void lv_obj_del_anim_ready_cb(lv_anim_t * a); + +/** + * Helper function for asynchronously deleting objects. + * Useful for cases where you can't delete an object directly in an `LV_EVENT_DELETE` handler (i.e. parent). + * @param obj object to delete + * @see lv_async_call + */ +void lv_obj_del_async(struct _lv_obj_t * obj); + +/** + * Move the parent of an object. The relative coordinates will be kept. + * + * @param obj pointer to an object whose parent needs to be changed + * @param parent pointer to the new parent + */ +void lv_obj_set_parent(struct _lv_obj_t * obj, struct _lv_obj_t * parent); + +/** + * Swap the positions of two objects. + * When used in listboxes, it can be used to sort the listbox items. + * @param obj1 pointer to the first object + * @param obj2 pointer to the second object + */ +void lv_obj_swap(struct _lv_obj_t * obj1, struct _lv_obj_t * obj2); + +/** + * moves the object to the given index in its parent. + * When used in listboxes, it can be used to sort the listbox items. + * @param obj pointer to the object to be moved. + * @param index new index in parent. -1 to count from the back + * @note to move to the background: lv_obj_move_to_index(obj, 0) + * @note to move forward (up): lv_obj_move_to_index(obj, lv_obj_get_index(obj) - 1) + */ +void lv_obj_move_to_index(struct _lv_obj_t * obj, int32_t index); + +/** + * Get the screen of an object + * @param obj pointer to an object + * @return pointer to the object's screen + */ +struct _lv_obj_t * lv_obj_get_screen(const struct _lv_obj_t * obj); + +/** + * Get the display of the object + * @param obj pointer to an object + * @return pointer to the object's display + */ +lv_disp_t * lv_obj_get_disp(const struct _lv_obj_t * obj); + +/** + * Get the parent of an object + * @param obj pointer to an object + * @return the parent of the object. (NULL if `obj` was a screen) + */ +struct _lv_obj_t * lv_obj_get_parent(const struct _lv_obj_t * obj); + +/** + * Get the child of an object by the child's index. + * @param obj pointer to an object whose child should be get + * @param id the index of the child. + * 0: the oldest (firstly created) child + * 1: the second oldest + * child count-1: the youngest + * -1: the youngest + * -2: the second youngest + * @return pointer to the child or NULL if the index was invalid + */ +struct _lv_obj_t * lv_obj_get_child(const struct _lv_obj_t * obj, int32_t id); + +/** + * Get the number of children + * @param obj pointer to an object + * @return the number of children + */ +uint32_t lv_obj_get_child_cnt(const struct _lv_obj_t * obj); + +/** + * Get the index of a child. + * @param obj pointer to an object + * @return the child index of the object. + * E.g. 0: the oldest (firstly created child) + */ +uint32_t lv_obj_get_index(const struct _lv_obj_t * obj); + +/** + * Iterate through all children of any object. + * @param start_obj start integrating from this object + * @param cb call this callback on the objects + * @param user_data pointer to any user related data (will be passed to `cb`) + */ +void lv_obj_tree_walk(struct _lv_obj_t * start_obj, lv_obj_tree_walk_cb_t cb, void * user_data); + +/********************** + * MACROS + **********************/ + + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif /*LV_OBJ_TREE_H*/ diff --git a/src/lib/lvgl/src/core/lv_refr.h b/src/lib/lvgl/src/core/lv_refr.h new file mode 100644 index 0000000..984168a --- /dev/null +++ b/src/lib/lvgl/src/core/lv_refr.h @@ -0,0 +1,115 @@ +/** + * @file lv_refr.h + * + */ + +#ifndef LV_REFR_H +#define LV_REFR_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include "lv_obj.h" +#include + +/********************* + * DEFINES + *********************/ + +#define LV_REFR_TASK_PRIO LV_TASK_PRIO_MID + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * STATIC PROTOTYPES + **********************/ + +/********************** + * STATIC VARIABLES + **********************/ + +/********************** + * MACROS + **********************/ + +/********************** + * GLOBAL FUNCTIONS + **********************/ + +/** + * Initialize the screen refresh subsystem + */ +void _lv_refr_init(void); + +/** + * Redraw the invalidated areas now. + * Normally the redrawing is periodically executed in `lv_timer_handler` but a long blocking process + * can prevent the call of `lv_timer_handler`. In this case if the GUI is updated in the process + * (e.g. progress bar) this function can be called when the screen should be updated. + * @param disp pointer to display to refresh. NULL to refresh all displays. + */ +void lv_refr_now(lv_disp_t * disp); + +/** + * Redrawn on object an all its children using the passed draw context + * @param draw pointer to an initialized draw context + * @param obj the start object from the redraw should start + */ +void lv_refr_obj(lv_draw_ctx_t * draw_ctx, lv_obj_t * obj); + +/** + * Invalidate an area on display to redraw it + * @param area_p pointer to area which should be invalidated (NULL: delete the invalidated areas) + * @param disp pointer to display where the area should be invalidated (NULL can be used if there is + * only one display) + */ +void _lv_inv_area(lv_disp_t * disp, const lv_area_t * area_p); + +/** + * Get the display which is being refreshed + * @return the display being refreshed + */ +lv_disp_t * _lv_refr_get_disp_refreshing(void); + +/** + * Set the display which is being refreshed. + * It shouldn't be used directly by the user. + * It can be used to trick the drawing functions about there is an active display. + * @param the display being refreshed + */ +void _lv_refr_set_disp_refreshing(lv_disp_t * disp); + +#if LV_USE_PERF_MONITOR +/** + * Reset FPS counter + */ +void lv_refr_reset_fps_counter(void); + +/** + * Get the average FPS + * @return the average FPS + */ +uint32_t lv_refr_get_fps_avg(void); +#endif + +/** + * Called periodically to handle the refreshing + * @param timer pointer to the timer itself + */ +void _lv_disp_refr_timer(lv_timer_t * timer); + +/********************** + * STATIC FUNCTIONS + **********************/ + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif /*LV_REFR_H*/ diff --git a/src/lib/lvgl/src/core/lv_theme.h b/src/lib/lvgl/src/core/lv_theme.h new file mode 100644 index 0000000..ef46336 --- /dev/null +++ b/src/lib/lvgl/src/core/lv_theme.h @@ -0,0 +1,120 @@ +/** + *@file lv_theme.h + * + */ + +#ifndef LV_THEME_H +#define LV_THEME_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include "../core/lv_obj.h" + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +struct _lv_theme_t; +struct _lv_disp_t; + +typedef void (*lv_theme_apply_cb_t)(struct _lv_theme_t *, lv_obj_t *); + +typedef struct _lv_theme_t { + lv_theme_apply_cb_t apply_cb; + struct _lv_theme_t * parent; /**< Apply the current theme's style on top of this theme.*/ + void * user_data; + struct _lv_disp_t * disp; + lv_color_t color_primary; + lv_color_t color_secondary; + const lv_font_t * font_small; + const lv_font_t * font_normal; + const lv_font_t * font_large; + uint32_t flags; /*Any custom flag used by the theme*/ +} lv_theme_t; + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +/** + * Get the theme assigned to the display of the object + * @param obj pointer to a theme object + * @return the theme of the object's display (can be NULL) + */ +lv_theme_t * lv_theme_get_from_obj(lv_obj_t * obj); + +/** + * Apply the active theme on an object + * @param obj pointer to an object + */ +void lv_theme_apply(lv_obj_t * obj); + +/** + * Set a base theme for a theme. + * The styles from the base them will be added before the styles of the current theme. + * Arbitrary long chain of themes can be created by setting base themes. + * @param new_theme pointer to theme which base should be set + * @param parent pointer to the base theme + */ +void lv_theme_set_parent(lv_theme_t * new_theme, lv_theme_t * parent); + +/** + * Set an apply callback for a theme. + * The apply callback is used to add styles to different objects + * @param theme pointer to theme which callback should be set + * @param apply_cb pointer to the callback + */ +void lv_theme_set_apply_cb(lv_theme_t * theme, lv_theme_apply_cb_t apply_cb); + +/** + * Get the small font of the theme + * @param obj pointer to an object + * @return pointer to the font + */ +const lv_font_t * lv_theme_get_font_small(lv_obj_t * obj); +/** + * Get the normal font of the theme + * @param obj pointer to an object + * @return pointer to the font + */ +const lv_font_t * lv_theme_get_font_normal(lv_obj_t * obj); + +/** + * Get the subtitle font of the theme + * @param obj pointer to an object + * @return pointer to the font + */ +const lv_font_t * lv_theme_get_font_large(lv_obj_t * obj); + +/** + * Get the primary color of the theme + * @param obj pointer to an object + * @return the color + */ +lv_color_t lv_theme_get_color_primary(lv_obj_t * obj); + +/** + * Get the secondary color of the theme + * @param obj pointer to an object + * @return the color + */ +lv_color_t lv_theme_get_color_secondary(lv_obj_t * obj); + +/********************** + * MACROS + **********************/ + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif /*LV_THEME_H*/ diff --git a/src/lib/lvgl/src/draw/arm2d/lv_gpu_arm2d.h b/src/lib/lvgl/src/draw/arm2d/lv_gpu_arm2d.h new file mode 100644 index 0000000..50fa5a8 --- /dev/null +++ b/src/lib/lvgl/src/draw/arm2d/lv_gpu_arm2d.h @@ -0,0 +1,51 @@ +/** + * @file lv_gpu_arm2d.h + * + */ + +#ifndef LV_GPU_ARM2D_H +#define LV_GPU_ARM2D_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include "../../misc/lv_color.h" +#include "../../hal/lv_hal_disp.h" +#include "../sw/lv_draw_sw.h" + +#if LV_USE_GPU_ARM2D + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ +typedef lv_draw_sw_ctx_t lv_draw_arm2d_ctx_t; + +struct _lv_disp_drv_t; + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +void lv_draw_arm2d_ctx_init(struct _lv_disp_drv_t * drv, lv_draw_ctx_t * draw_ctx); + +void lv_draw_arm2d_ctx_deinit(struct _lv_disp_drv_t * drv, lv_draw_ctx_t * draw_ctx); + +/********************** + * MACROS + **********************/ + +#endif /*LV_USE_GPU_ARM2D*/ + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif /*LV_GPU_ARM2D_H*/ diff --git a/src/lib/lvgl/src/draw/lv_draw.h b/src/lib/lvgl/src/draw/lv_draw.h new file mode 100644 index 0000000..8e3c6cb --- /dev/null +++ b/src/lib/lvgl/src/draw/lv_draw.h @@ -0,0 +1,121 @@ +/** + * @file lv_draw.h + * + */ + +#ifndef LV_DRAW_H +#define LV_DRAW_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include "../lv_conf_internal.h" + +#include "../misc/lv_style.h" +#include "../misc/lv_txt.h" +#include "lv_img_decoder.h" +#include "lv_img_cache.h" + +#include "lv_draw_rect.h" +#include "lv_draw_label.h" +#include "lv_draw_img.h" +#include "lv_draw_line.h" +#include "lv_draw_triangle.h" +#include "lv_draw_arc.h" +#include "lv_draw_mask.h" + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +typedef struct { + void * user_data; +} lv_draw_mask_t; + + +typedef struct _lv_draw_ctx_t { + /** + * Pointer to a buffer to draw into + */ + void * buf; + + /** + * The position and size of `buf` (absolute coordinates) + */ + lv_area_t * buf_area; + + /** + * The current clip area with absolute coordinates, always the same or smaller than `buf_area` + */ + const lv_area_t * clip_area; + + + void (*draw_rect)(struct _lv_draw_ctx_t * draw_ctx, const lv_draw_rect_dsc_t * dsc, const lv_area_t * coords); + + void (*draw_arc)(struct _lv_draw_ctx_t * draw_ctx, const lv_draw_arc_dsc_t * dsc, const lv_point_t * center, + uint16_t radius, uint16_t start_angle, uint16_t end_angle); + + void (*draw_img_decoded)(struct _lv_draw_ctx_t * draw_ctx, const lv_draw_img_dsc_t * dsc, + const lv_area_t * coords, const uint8_t * map_p, lv_img_cf_t color_format); + + lv_res_t (*draw_img)(struct _lv_draw_ctx_t * draw_ctx, const lv_draw_img_dsc_t * draw_dsc, + const lv_area_t * coords, const void * src); + + void (*draw_letter)(struct _lv_draw_ctx_t * draw_ctx, const lv_draw_label_dsc_t * dsc, const lv_point_t * pos_p, + uint32_t letter); + + + void (*draw_line)(struct _lv_draw_ctx_t * draw_ctx, const lv_draw_line_dsc_t * dsc, const lv_point_t * point1, + const lv_point_t * point2); + + + void (*draw_polygon)(struct _lv_draw_ctx_t * draw_ctx, const lv_draw_rect_dsc_t * draw_dsc, + const lv_point_t * points, uint16_t point_cnt); + + /** + * Replace the buffer with a rect without decoration like radius or borders + */ + void (*draw_bg)(struct _lv_draw_ctx_t * draw_ctx, const lv_draw_rect_dsc_t * draw_dsc, const lv_area_t * coords); + + /** + * Wait until all background operations are finished. (E.g. GPU operations) + */ + void (*wait_for_finish)(struct _lv_draw_ctx_t * draw); + +#if LV_USE_USER_DATA + void * user_data; +#endif + +} lv_draw_ctx_t; + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +void lv_draw_init(void); + +/********************** + * GLOBAL VARIABLES + **********************/ + +/********************** + * MACROS + **********************/ + +/********************** + * POST INCLUDES + *********************/ + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif /*LV_DRAW_H*/ diff --git a/src/lib/lvgl/src/draw/lv_draw_arc.h b/src/lib/lvgl/src/draw/lv_draw_arc.h new file mode 100644 index 0000000..8783f13 --- /dev/null +++ b/src/lib/lvgl/src/draw/lv_draw_arc.h @@ -0,0 +1,83 @@ +/** + * @file lv_draw_arc.h + * + */ + +#ifndef LV_DRAW_ARC_H +#define LV_DRAW_ARC_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include "../lv_conf_internal.h" +#include "../misc/lv_color.h" +#include "../misc/lv_area.h" +#include "../misc/lv_style.h" + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ +typedef struct { + lv_color_t color; + lv_coord_t width; + uint16_t start_angle; + uint16_t end_angle; + const void * img_src; + lv_opa_t opa; + lv_blend_mode_t blend_mode : 2; + uint8_t rounded : 1; +} lv_draw_arc_dsc_t; + +struct _lv_draw_ctx_t; + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +void lv_draw_arc_dsc_init(lv_draw_arc_dsc_t * dsc); + +/** + * Draw an arc. (Can draw pie too with great thickness.) + * @param center_x the x coordinate of the center of the arc + * @param center_y the y coordinate of the center of the arc + * @param radius the radius of the arc + * @param mask the arc will be drawn only in this mask + * @param start_angle the start angle of the arc (0 deg on the bottom, 90 deg on the right) + * @param end_angle the end angle of the arc + * @param clip_area the arc will be drawn only in this area + * @param dsc pointer to an initialized `lv_draw_line_dsc_t` variable + */ +void lv_draw_arc(struct _lv_draw_ctx_t * draw_ctx, const lv_draw_arc_dsc_t * dsc, const lv_point_t * center, + uint16_t radius, uint16_t start_angle, uint16_t end_angle); + +/** + * Get an area the should be invalidated when the arcs angle changed between start_angle and end_ange + * @param x the x coordinate of the center of the arc + * @param y the y coordinate of the center of the arc + * @param radius the radius of the arc + * @param start_angle the start angle of the arc (0 deg on the bottom, 90 deg on the right) + * @param end_angle the end angle of the arc + * @param w width of the arc + * @param rounded true: the arc is rounded + * @param area store the area to invalidate here + */ +void lv_draw_arc_get_area(lv_coord_t x, lv_coord_t y, uint16_t radius, uint16_t start_angle, uint16_t end_angle, + lv_coord_t w, bool rounded, lv_area_t * area); + +/********************** + * MACROS + **********************/ + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif /*LV_DRAW_ARC_H*/ diff --git a/src/lib/lvgl/src/draw/lv_draw_img.h b/src/lib/lvgl/src/draw/lv_draw_img.h new file mode 100644 index 0000000..504beda --- /dev/null +++ b/src/lib/lvgl/src/draw/lv_draw_img.h @@ -0,0 +1,104 @@ +/** + * @file lv_draw_img.h + * + */ + +#ifndef LV_DRAW_IMG_H +#define LV_DRAW_IMG_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include "lv_img_decoder.h" +#include "lv_img_buf.h" +#include "../misc/lv_style.h" + +/********************* + * DEFINES + *********************/ + +/********************** + * MACROS + **********************/ + +/********************** + * TYPEDEFS + **********************/ + +typedef struct { + + uint16_t angle; + uint16_t zoom; + lv_point_t pivot; + + lv_color_t recolor; + lv_opa_t recolor_opa; + + lv_opa_t opa; + lv_blend_mode_t blend_mode : 4; + + int32_t frame_id; + uint8_t antialias : 1; +} lv_draw_img_dsc_t; + +struct _lv_draw_ctx_t; + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +void lv_draw_img_dsc_init(lv_draw_img_dsc_t * dsc); +/** + * Draw an image + * @param coords the coordinates of the image + * @param mask the image will be drawn only in this area + * @param src pointer to a lv_color_t array which contains the pixels of the image + * @param dsc pointer to an initialized `lv_draw_img_dsc_t` variable + */ +void lv_draw_img(struct _lv_draw_ctx_t * draw_ctx, const lv_draw_img_dsc_t * dsc, const lv_area_t * coords, + const void * src); + + +void lv_draw_img_decoded(struct _lv_draw_ctx_t * draw_ctx, const lv_draw_img_dsc_t * dsc, + const lv_area_t * coords, const uint8_t * map_p, lv_img_cf_t color_format); + +/** + * Get the type of an image source + * @param src pointer to an image source: + * - pointer to an 'lv_img_t' variable (image stored internally and compiled into the code) + * - a path to a file (e.g. "S:/folder/image.bin") + * - or a symbol (e.g. LV_SYMBOL_CLOSE) + * @return type of the image source LV_IMG_SRC_VARIABLE/FILE/SYMBOL/UNKNOWN + */ +lv_img_src_t lv_img_src_get_type(const void * src); + +/** + * Get the pixel size of a color format in bits + * @param cf a color format (`LV_IMG_CF_...`) + * @return the pixel size in bits + */ +uint8_t lv_img_cf_get_px_size(lv_img_cf_t cf); + +/** + * Check if a color format is chroma keyed or not + * @param cf a color format (`LV_IMG_CF_...`) + * @return true: chroma keyed; false: not chroma keyed + */ +bool lv_img_cf_is_chroma_keyed(lv_img_cf_t cf); + +/** + * Check if a color format has alpha channel or not + * @param cf a color format (`LV_IMG_CF_...`) + * @return true: has alpha channel; false: doesn't have alpha channel + */ +bool lv_img_cf_has_alpha(lv_img_cf_t cf); + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif /*LV_DRAW_IMG_H*/ diff --git a/src/lib/lvgl/src/draw/lv_draw_label.h b/src/lib/lvgl/src/draw/lv_draw_label.h new file mode 100644 index 0000000..de72edd --- /dev/null +++ b/src/lib/lvgl/src/draw/lv_draw_label.h @@ -0,0 +1,100 @@ +/** + * @file lv_draw_label.h + * + */ + +#ifndef LV_DRAW_LABEL_H +#define LV_DRAW_LABEL_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include "../misc/lv_bidi.h" +#include "../misc/lv_txt.h" +#include "../misc/lv_color.h" +#include "../misc/lv_style.h" + +/********************* + * DEFINES + *********************/ +#define LV_DRAW_LABEL_NO_TXT_SEL (0xFFFF) + +/********************** + * TYPEDEFS + **********************/ + +typedef struct { + const lv_font_t * font; + uint32_t sel_start; + uint32_t sel_end; + lv_color_t color; + lv_color_t sel_color; + lv_color_t sel_bg_color; + lv_coord_t line_space; + lv_coord_t letter_space; + lv_coord_t ofs_x; + lv_coord_t ofs_y; + lv_opa_t opa; + lv_base_dir_t bidi_dir; + lv_text_align_t align; + lv_text_flag_t flag; + lv_text_decor_t decor : 3; + lv_blend_mode_t blend_mode: 3; +} lv_draw_label_dsc_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. + * This structure stores an earlier (e.g. at -1000 px) coordinate and the index of that line. + * Therefore the calculations can start from here.*/ +typedef struct _lv_draw_label_hint_t { + /** Index of the line at `y` coordinate*/ + int32_t line_start; + + /** Give the `y` coordinate of the first letter at `line start` index. Relative to the label's coordinates*/ + int32_t y; + + /** The 'y1' coordinate of the label when the hint was saved. + * Used to invalidate the hint if the label has moved too much.*/ + int32_t coord_y; +} lv_draw_label_hint_t; + +struct _lv_draw_ctx_t; +/********************** + * GLOBAL PROTOTYPES + **********************/ + +LV_ATTRIBUTE_FAST_MEM void lv_draw_label_dsc_init(lv_draw_label_dsc_t * dsc); + +/** + * Write a text + * @param coords coordinates of the label + * @param mask the label will be drawn only in this area + * @param dsc pointer to draw descriptor + * @param txt `\0` terminated text to write + * @param hint pointer to a `lv_draw_label_hint_t` variable. + * It is managed by the draw to speed up the drawing of very long texts (thousands of lines). + */ +LV_ATTRIBUTE_FAST_MEM void lv_draw_label(struct _lv_draw_ctx_t * draw_ctx, const lv_draw_label_dsc_t * dsc, + const lv_area_t * coords, const char * txt, lv_draw_label_hint_t * hint); + +void lv_draw_letter(struct _lv_draw_ctx_t * draw_ctx, const lv_draw_label_dsc_t * dsc, const lv_point_t * pos_p, + uint32_t letter); + +/*********************** + * GLOBAL VARIABLES + ***********************/ + +/********************** + * MACROS + **********************/ + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif /*LV_DRAW_LABEL_H*/ diff --git a/src/lib/lvgl/src/draw/lv_draw_line.h b/src/lib/lvgl/src/draw/lv_draw_line.h new file mode 100644 index 0000000..d82ea51 --- /dev/null +++ b/src/lib/lvgl/src/draw/lv_draw_line.h @@ -0,0 +1,67 @@ +/** + * @file lv_draw_line.h + * + */ + +#ifndef LV_DRAW_LINE_H +#define LV_DRAW_LINE_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include "../lv_conf_internal.h" +#include "../misc/lv_color.h" +#include "../misc/lv_area.h" +#include "../misc/lv_style.h" + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ +typedef struct { + lv_color_t color; + lv_coord_t width; + lv_coord_t dash_width; + lv_coord_t dash_gap; + lv_opa_t opa; + lv_blend_mode_t blend_mode : 2; + uint8_t round_start : 1; + uint8_t round_end : 1; + uint8_t raw_end : 1; /*Do not bother with perpendicular line ending if it's not visible for any reason*/ +} lv_draw_line_dsc_t; + +struct _lv_draw_ctx_t; + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +LV_ATTRIBUTE_FAST_MEM void lv_draw_line_dsc_init(lv_draw_line_dsc_t * dsc); + +/** + * Draw a line + * @param point1 first point of the line + * @param point2 second point of the line + * @param clip the line will be drawn only in this area + * @param dsc pointer to an initialized `lv_draw_line_dsc_t` variable + */ +void lv_draw_line(struct _lv_draw_ctx_t * draw_ctx, const lv_draw_line_dsc_t * dsc, const lv_point_t * point1, + const lv_point_t * point2); + + +/********************** + * MACROS + **********************/ + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif /*LV_DRAW_LINE_H*/ diff --git a/src/lib/lvgl/src/draw/lv_draw_mask.h b/src/lib/lvgl/src/draw/lv_draw_mask.h new file mode 100644 index 0000000..b6ec14f --- /dev/null +++ b/src/lib/lvgl/src/draw/lv_draw_mask.h @@ -0,0 +1,394 @@ +/** + * @file lv_draw_mask.h + * + */ + +#ifndef LV_DRAW_MASK_H +#define LV_DRAW_MASK_H + +#ifdef __cplusplus +extern "C" { +#endif + + +/********************* + * INCLUDES + *********************/ +#include +#include "../misc/lv_area.h" +#include "../misc/lv_color.h" +#include "../misc/lv_math.h" + +/********************* + * DEFINES + *********************/ +#define LV_MASK_ID_INV (-1) +#if LV_DRAW_COMPLEX +# define _LV_MASK_MAX_NUM 16 +#else +# define _LV_MASK_MAX_NUM 1 +#endif + +/********************** + * TYPEDEFS + **********************/ + +enum { + LV_DRAW_MASK_RES_TRANSP, + LV_DRAW_MASK_RES_FULL_COVER, + LV_DRAW_MASK_RES_CHANGED, + LV_DRAW_MASK_RES_UNKNOWN +}; + +typedef uint8_t lv_draw_mask_res_t; + +typedef struct { + void * param; + void * custom_id; +} _lv_draw_mask_saved_t; + +typedef _lv_draw_mask_saved_t _lv_draw_mask_saved_arr_t[_LV_MASK_MAX_NUM]; + + + +#if LV_DRAW_COMPLEX == 0 +static inline uint8_t lv_draw_mask_get_cnt(void) +{ + return 0; +} + +static inline bool lv_draw_mask_is_any(const lv_area_t * a) +{ + LV_UNUSED(a); + return false; +} + +#endif + +#if LV_DRAW_COMPLEX + +enum { + LV_DRAW_MASK_TYPE_LINE, + LV_DRAW_MASK_TYPE_ANGLE, + LV_DRAW_MASK_TYPE_RADIUS, + LV_DRAW_MASK_TYPE_FADE, + LV_DRAW_MASK_TYPE_MAP, + LV_DRAW_MASK_TYPE_POLYGON, +}; + +typedef uint8_t lv_draw_mask_type_t; + +enum { + LV_DRAW_MASK_LINE_SIDE_LEFT = 0, + LV_DRAW_MASK_LINE_SIDE_RIGHT, + LV_DRAW_MASK_LINE_SIDE_TOP, + LV_DRAW_MASK_LINE_SIDE_BOTTOM, +}; + +/** + * A common callback type for every mask type. + * Used internally by the library. + */ +typedef lv_draw_mask_res_t (*lv_draw_mask_xcb_t)(lv_opa_t * mask_buf, lv_coord_t abs_x, lv_coord_t abs_y, + lv_coord_t len, + void * p); + +typedef uint8_t lv_draw_mask_line_side_t; + +typedef struct { + lv_draw_mask_xcb_t cb; + lv_draw_mask_type_t type; +} _lv_draw_mask_common_dsc_t; + +typedef struct { + /*The first element must be the common descriptor*/ + _lv_draw_mask_common_dsc_t dsc; + + struct { + /*First point*/ + lv_point_t p1; + + /*Second point*/ + lv_point_t p2; + + /*Which side to keep?*/ + lv_draw_mask_line_side_t side : 2; + } cfg; + + /*A point of the line*/ + lv_point_t origo; + + /*X / (1024*Y) steepness (X is 0..1023 range). What is the change of X in 1024 Y?*/ + int32_t xy_steep; + + /*Y / (1024*X) steepness (Y is 0..1023 range). What is the change of Y in 1024 X?*/ + int32_t yx_steep; + + /*Helper which stores yx_steep for flat lines and xy_steep for steep (non flat) lines*/ + int32_t steep; + + /*Steepness in 1 px in 0..255 range. Used only by flat lines.*/ + int32_t spx; + + /*1: It's a flat line? (Near to horizontal)*/ + uint8_t flat : 1; + + /*Invert the mask. The default is: Keep the left part. + *It is used to select left/right/top/bottom*/ + uint8_t inv: 1; +} lv_draw_mask_line_param_t; + +typedef struct { + /*The first element must be the common descriptor*/ + _lv_draw_mask_common_dsc_t dsc; + + struct { + lv_point_t vertex_p; + lv_coord_t start_angle; + lv_coord_t end_angle; + } cfg; + + lv_draw_mask_line_param_t start_line; + lv_draw_mask_line_param_t end_line; + uint16_t delta_deg; +} lv_draw_mask_angle_param_t; + +typedef struct { + uint8_t * buf; + lv_opa_t * cir_opa; /*Opacity of values on the circumference of an 1/4 circle*/ + uint16_t * x_start_on_y; /*The x coordinate of the circle for each y value*/ + uint16_t * opa_start_on_y; /*The index of `cir_opa` for each y value*/ + int32_t life; /*How many times the entry way used*/ + uint32_t used_cnt; /*Like a semaphore to count the referencing masks*/ + lv_coord_t radius; /*The radius of the entry*/ +} _lv_draw_mask_radius_circle_dsc_t; + +typedef _lv_draw_mask_radius_circle_dsc_t _lv_draw_mask_radius_circle_dsc_arr_t[LV_CIRCLE_CACHE_SIZE]; + +typedef struct { + /*The first element must be the common descriptor*/ + _lv_draw_mask_common_dsc_t dsc; + + struct { + lv_area_t rect; + lv_coord_t radius; + /*Invert the mask. 0: Keep the pixels inside.*/ + uint8_t outer: 1; + } cfg; + + _lv_draw_mask_radius_circle_dsc_t * circle; +} lv_draw_mask_radius_param_t; + + +typedef struct { + /*The first element must be the common descriptor*/ + _lv_draw_mask_common_dsc_t dsc; + + struct { + lv_area_t coords; + lv_coord_t y_top; + lv_coord_t y_bottom; + lv_opa_t opa_top; + lv_opa_t opa_bottom; + } cfg; + +} lv_draw_mask_fade_param_t; + + +typedef struct _lv_draw_mask_map_param_t { + /*The first element must be the common descriptor*/ + _lv_draw_mask_common_dsc_t dsc; + + struct { + lv_area_t coords; + const lv_opa_t * map; + } cfg; +} lv_draw_mask_map_param_t; + +typedef struct { + /*The first element must be the common descriptor*/ + _lv_draw_mask_common_dsc_t dsc; + + struct { + lv_point_t * points; + uint16_t point_cnt; + } cfg; +} lv_draw_mask_polygon_param_t; + + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +/** + * Add a draw mask. Everything drawn after it (until removing the mask) will be affected by the mask. + * @param param an initialized mask parameter. Only the pointer is saved. + * @param custom_id a custom pointer to identify the mask. Used in `lv_draw_mask_remove_custom`. + * @return the an integer, the ID of the mask. Can be used in `lv_draw_mask_remove_id`. + */ +int16_t lv_draw_mask_add(void * param, void * custom_id); + +//! @cond Doxygen_Suppress + +/** + * Apply the added buffers on a line. Used internally by the library's drawing routines. + * @param mask_buf store the result mask here. Has to be `len` byte long. Should be initialized with `0xFF`. + * @param abs_x absolute X coordinate where the line to calculate start + * @param abs_y absolute Y coordinate where the line to calculate start + * @param len length of the line to calculate (in pixel count) + * @return One of these values: + * - `LV_DRAW_MASK_RES_FULL_TRANSP`: the whole line is transparent. `mask_buf` is not set to zero + * - `LV_DRAW_MASK_RES_FULL_COVER`: the whole line is fully visible. `mask_buf` is unchanged + * - `LV_DRAW_MASK_RES_CHANGED`: `mask_buf` has changed, it shows the desired opacity of each pixel in the given line + */ +LV_ATTRIBUTE_FAST_MEM lv_draw_mask_res_t lv_draw_mask_apply(lv_opa_t * mask_buf, lv_coord_t abs_x, lv_coord_t abs_y, + lv_coord_t len); + +/** + * Apply the specified buffers on a line. Used internally by the library's drawing routines. + * @param mask_buf store the result mask here. Has to be `len` byte long. Should be initialized with `0xFF`. + * @param abs_x absolute X coordinate where the line to calculate start + * @param abs_y absolute Y coordinate where the line to calculate start + * @param len length of the line to calculate (in pixel count) + * @param ids ID array of added buffers + * @param ids_count number of ID array + * @return One of these values: + * - `LV_DRAW_MASK_RES_FULL_TRANSP`: the whole line is transparent. `mask_buf` is not set to zero + * - `LV_DRAW_MASK_RES_FULL_COVER`: the whole line is fully visible. `mask_buf` is unchanged + * - `LV_DRAW_MASK_RES_CHANGED`: `mask_buf` has changed, it shows the desired opacity of each pixel in the given line + */ +LV_ATTRIBUTE_FAST_MEM lv_draw_mask_res_t lv_draw_mask_apply_ids(lv_opa_t * mask_buf, lv_coord_t abs_x, lv_coord_t abs_y, + lv_coord_t len, const int16_t * ids, int16_t ids_count); + +//! @endcond + +/** + * Remove a mask with a given ID + * @param id the ID of the mask. Returned by `lv_draw_mask_add` + * @return the parameter of the removed mask. + * If more masks have `custom_id` ID then the last mask's parameter will be returned + */ +void * lv_draw_mask_remove_id(int16_t id); + +/** + * Remove all mask with a given custom ID + * @param custom_id a pointer used in `lv_draw_mask_add` + * @return return the parameter of the removed mask. + * If more masks have `custom_id` ID then the last mask's parameter will be returned + */ +void * lv_draw_mask_remove_custom(void * custom_id); + +/** + * Free the data from the parameter. + * It's called inside `lv_draw_mask_remove_id` and `lv_draw_mask_remove_custom` + * Needs to be called only in special cases when the mask is not added by `lv_draw_mask_add` + * and not removed by `lv_draw_mask_remove_id` or `lv_draw_mask_remove_custom` + * @param p pointer to a mask parameter + */ +void lv_draw_mask_free_param(void * p); + +/** + * Called by LVGL the rendering of a screen is ready to clean up + * the temporal (cache) data of the masks + */ +void _lv_draw_mask_cleanup(void); + +//! @cond Doxygen_Suppress + +/** + * Count the currently added masks + * @return number of active masks + */ +LV_ATTRIBUTE_FAST_MEM uint8_t lv_draw_mask_get_cnt(void); + + +/** + * Check if there is any added draw mask + * @param a an area to test for affecting masks. + * @return true: there is t least 1 draw mask; false: there are no draw masks + */ +bool lv_draw_mask_is_any(const lv_area_t * a); + +//! @endcond + +/** + *Initialize a line mask from two points. + * @param param pointer to a `lv_draw_mask_param_t` to initialize + * @param p1x X coordinate of the first point of the line + * @param p1y Y coordinate of the first point of the line + * @param p2x X coordinate of the second point of the line + * @param p2y y coordinate of the second point of the line + * @param side and element of `lv_draw_mask_line_side_t` to describe which side to keep. + * With `LV_DRAW_MASK_LINE_SIDE_LEFT/RIGHT` and horizontal line all pixels are kept + * With `LV_DRAW_MASK_LINE_SIDE_TOP/BOTTOM` and vertical line all pixels are kept + */ +void lv_draw_mask_line_points_init(lv_draw_mask_line_param_t * param, lv_coord_t p1x, lv_coord_t p1y, lv_coord_t p2x, + lv_coord_t p2y, lv_draw_mask_line_side_t side); + +/** + *Initialize a line mask from a point and an angle. + * @param param pointer to a `lv_draw_mask_param_t` to initialize + * @param px X coordinate of a point of the line + * @param py X coordinate of a point of the line + * @param angle right 0 deg, bottom: 90 + * @param side and element of `lv_draw_mask_line_side_t` to describe which side to keep. + * With `LV_DRAW_MASK_LINE_SIDE_LEFT/RIGHT` and horizontal line all pixels are kept + * With `LV_DRAW_MASK_LINE_SIDE_TOP/BOTTOM` and vertical line all pixels are kept + */ +void lv_draw_mask_line_angle_init(lv_draw_mask_line_param_t * param, lv_coord_t p1x, lv_coord_t py, int16_t angle, + lv_draw_mask_line_side_t side); + +/** + * Initialize an angle mask. + * @param param pointer to a `lv_draw_mask_param_t` to initialize + * @param vertex_x X coordinate of the angle vertex (absolute coordinates) + * @param vertex_y Y coordinate of the angle vertex (absolute coordinates) + * @param start_angle start angle in degrees. 0 deg on the right, 90 deg, on the bottom + * @param end_angle end angle + */ +void lv_draw_mask_angle_init(lv_draw_mask_angle_param_t * param, lv_coord_t vertex_x, lv_coord_t vertex_y, + lv_coord_t start_angle, lv_coord_t end_angle); + +/** + * Initialize a fade mask. + * @param param pointer to an `lv_draw_mask_radius_param_t` to initialize + * @param rect coordinates of the rectangle to affect (absolute coordinates) + * @param radius radius of the rectangle + * @param inv true: keep the pixels inside the rectangle; keep the pixels outside of the rectangle + */ +void lv_draw_mask_radius_init(lv_draw_mask_radius_param_t * param, const lv_area_t * rect, lv_coord_t radius, bool inv); + +/** + * Initialize a fade mask. + * @param param pointer to a `lv_draw_mask_param_t` to initialize + * @param coords coordinates of the area to affect (absolute coordinates) + * @param opa_top opacity on the top + * @param y_top at which coordinate start to change to opacity to `opa_bottom` + * @param opa_bottom opacity at the bottom + * @param y_bottom at which coordinate reach `opa_bottom`. + */ +void lv_draw_mask_fade_init(lv_draw_mask_fade_param_t * param, const lv_area_t * coords, lv_opa_t opa_top, + lv_coord_t y_top, + lv_opa_t opa_bottom, lv_coord_t y_bottom); + +/** + * Initialize a map mask. + * @param param pointer to a `lv_draw_mask_param_t` to initialize + * @param coords coordinates of the map (absolute coordinates) + * @param map array of bytes with the mask values + */ +void lv_draw_mask_map_init(lv_draw_mask_map_param_t * param, const lv_area_t * coords, const lv_opa_t * map); + +void lv_draw_mask_polygon_init(lv_draw_mask_polygon_param_t * param, const lv_point_t * points, uint16_t point_cnt); + +#endif /*LV_DRAW_COMPLEX*/ + +/********************** + * MACROS + **********************/ + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif /*LV_DRAW_MASK_H*/ diff --git a/src/lib/lvgl/src/draw/lv_draw_rect.h b/src/lib/lvgl/src/draw/lv_draw_rect.h new file mode 100644 index 0000000..efa630c --- /dev/null +++ b/src/lib/lvgl/src/draw/lv_draw_rect.h @@ -0,0 +1,102 @@ +/** + * @file lv_draw_rect.h + * + */ + +#ifndef LV_DRAW_RECT_H +#define LV_DRAW_RECT_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include "../lv_conf_internal.h" +#include "../misc/lv_color.h" +#include "../misc/lv_area.h" +#include "../misc/lv_style.h" +#include "sw/lv_draw_sw_gradient.h" + +/********************* + * DEFINES + *********************/ +#define LV_RADIUS_CIRCLE 0x7FFF /**< A very big radius to always draw as circle*/ +LV_EXPORT_CONST_INT(LV_RADIUS_CIRCLE); + +/********************** + * TYPEDEFS + **********************/ + +typedef struct { + lv_coord_t radius; + lv_blend_mode_t blend_mode; + + /*Background*/ + lv_opa_t bg_opa; +#if __STDC_VERSION__ >= 201112L + union { +#endif + lv_color_t bg_color; /**< First element of a gradient is a color, so it maps well here*/ + lv_grad_dsc_t bg_grad; +#if __STDC_VERSION__ >= 201112L + }; +#endif + + /*Background img*/ + const void * bg_img_src; + const void * bg_img_symbol_font; + lv_color_t bg_img_recolor; + lv_opa_t bg_img_opa; + lv_opa_t bg_img_recolor_opa; + uint8_t bg_img_tiled; + + /*Border*/ + lv_color_t border_color; + lv_coord_t border_width; + lv_opa_t border_opa; + uint8_t border_post : 1; /*There is a border it will be drawn later.*/ + lv_border_side_t border_side : 5; + + /*Outline*/ + lv_color_t outline_color; + lv_coord_t outline_width; + lv_coord_t outline_pad; + lv_opa_t outline_opa; + + /*Shadow*/ + lv_color_t shadow_color; + lv_coord_t shadow_width; + lv_coord_t shadow_ofs_x; + lv_coord_t shadow_ofs_y; + lv_coord_t shadow_spread; + lv_opa_t shadow_opa; +} lv_draw_rect_dsc_t; + +struct _lv_draw_ctx_t; + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +LV_ATTRIBUTE_FAST_MEM void lv_draw_rect_dsc_init(lv_draw_rect_dsc_t * dsc); + + +/** + * Draw a rectangle + * @param coords the coordinates of the rectangle + * @param clip the rectangle will be drawn only in this area + * @param dsc pointer to an initialized `lv_draw_rect_dsc_t` variable + */ +void lv_draw_rect(struct _lv_draw_ctx_t * draw_ctx, const lv_draw_rect_dsc_t * dsc, const lv_area_t * coords); + +/********************** + * MACROS + **********************/ + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif /*LV_DRAW_RECT_H*/ diff --git a/src/lib/lvgl/src/draw/lv_draw_triangle.h b/src/lib/lvgl/src/draw/lv_draw_triangle.h new file mode 100644 index 0000000..e8d8575 --- /dev/null +++ b/src/lib/lvgl/src/draw/lv_draw_triangle.h @@ -0,0 +1,42 @@ +/** + * @file lv_draw_triangle.h + * + */ + +#ifndef LV_DRAW_TRIANGLE_H +#define LV_DRAW_TRIANGLE_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include "lv_draw_rect.h" + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +void lv_draw_polygon(struct _lv_draw_ctx_t * draw_ctx, const lv_draw_rect_dsc_t * draw_dsc, const lv_point_t points[], + uint16_t point_cnt); + +void lv_draw_triangle(struct _lv_draw_ctx_t * draw_ctx, const lv_draw_rect_dsc_t * draw_dsc, const lv_point_t points[]); +/********************** + * MACROS + **********************/ + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif /*LV_DRAW_TRIANGLE_H*/ diff --git a/src/lib/lvgl/src/draw/lv_img_buf.h b/src/lib/lvgl/src/draw/lv_img_buf.h new file mode 100644 index 0000000..984483e --- /dev/null +++ b/src/lib/lvgl/src/draw/lv_img_buf.h @@ -0,0 +1,310 @@ +/** + * @file lv_img_buf.h + * + */ + +#ifndef LV_IMG_BUF_H +#define LV_IMG_BUF_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include +#include "../misc/lv_color.h" +#include "../misc/lv_area.h" + +/********************* + * DEFINES + *********************/ +/*If image pixels contains alpha we need to know how much byte is a pixel*/ +#if LV_COLOR_DEPTH == 1 || LV_COLOR_DEPTH == 8 +#define LV_IMG_PX_SIZE_ALPHA_BYTE 2 +#elif LV_COLOR_DEPTH == 16 +#define LV_IMG_PX_SIZE_ALPHA_BYTE 3 +#elif LV_COLOR_DEPTH == 32 +#define LV_IMG_PX_SIZE_ALPHA_BYTE 4 +#endif + +#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) + +#define _LV_TRANSFORM_TRIGO_SHIFT 10 +#define _LV_ZOOM_INV_UPSCALE 5 + +/********************** + * TYPEDEFS + **********************/ + +/*Image color format*/ +enum { + LV_IMG_CF_UNKNOWN = 0, + + LV_IMG_CF_RAW, /**< Contains the file as it is. Needs custom decoder function*/ + LV_IMG_CF_RAW_ALPHA, /**< Contains the file as it is. The image has alpha. Needs custom decoder + function*/ + LV_IMG_CF_RAW_CHROMA_KEYED, /**< Contains the file as it is. The image is chroma keyed. Needs + custom decoder function*/ + + LV_IMG_CF_TRUE_COLOR, /**< Color format and depth should match with LV_COLOR settings*/ + LV_IMG_CF_TRUE_COLOR_ALPHA, /**< Same as `LV_IMG_CF_TRUE_COLOR` but every pixel has an alpha byte*/ + LV_IMG_CF_TRUE_COLOR_CHROMA_KEYED, /**< Same as `LV_IMG_CF_TRUE_COLOR` but LV_COLOR_TRANSP pixels + will be transparent*/ + + LV_IMG_CF_INDEXED_1BIT, /**< Can have 2 different colors in a palette (always chroma keyed)*/ + LV_IMG_CF_INDEXED_2BIT, /**< Can have 4 different colors in a palette (always chroma keyed)*/ + LV_IMG_CF_INDEXED_4BIT, /**< Can have 16 different colors in a palette (always chroma keyed)*/ + LV_IMG_CF_INDEXED_8BIT, /**< Can have 256 different colors in a palette (always chroma keyed)*/ + + LV_IMG_CF_ALPHA_1BIT, /**< Can have one color and it can be drawn or not*/ + LV_IMG_CF_ALPHA_2BIT, /**< Can have one color but 4 different alpha value*/ + LV_IMG_CF_ALPHA_4BIT, /**< Can have one color but 16 different alpha value*/ + LV_IMG_CF_ALPHA_8BIT, /**< Can have one color but 256 different alpha value*/ + + LV_IMG_CF_RESERVED_15, /**< Reserved for further use.*/ + LV_IMG_CF_RESERVED_16, /**< Reserved for further use.*/ + LV_IMG_CF_RESERVED_17, /**< Reserved for further use.*/ + LV_IMG_CF_RESERVED_18, /**< Reserved for further use.*/ + LV_IMG_CF_RESERVED_19, /**< Reserved for further use.*/ + LV_IMG_CF_RESERVED_20, /**< Reserved for further use.*/ + LV_IMG_CF_RESERVED_21, /**< Reserved for further use.*/ + LV_IMG_CF_RESERVED_22, /**< Reserved for further use.*/ + LV_IMG_CF_RESERVED_23, /**< Reserved for further use.*/ + + LV_IMG_CF_USER_ENCODED_0, /**< User holder encoding format.*/ + LV_IMG_CF_USER_ENCODED_1, /**< User holder encoding format.*/ + LV_IMG_CF_USER_ENCODED_2, /**< User holder encoding format.*/ + LV_IMG_CF_USER_ENCODED_3, /**< User holder encoding format.*/ + LV_IMG_CF_USER_ENCODED_4, /**< User holder encoding format.*/ + LV_IMG_CF_USER_ENCODED_5, /**< User holder encoding format.*/ + LV_IMG_CF_USER_ENCODED_6, /**< User holder encoding format.*/ + LV_IMG_CF_USER_ENCODED_7, /**< User holder encoding format.*/ +}; +typedef uint8_t lv_img_cf_t; + + +/** + * The first 8 bit is very important to distinguish the different source types. + * For more info see `lv_img_get_src_type()` in lv_img.c + * On big endian systems the order is reversed so cf and always_zero must be at + * the end of the struct. + */ +#if LV_BIG_ENDIAN_SYSTEM +typedef struct { + + uint32_t h : 11; /*Height of the image map*/ + uint32_t w : 11; /*Width of the image map*/ + uint32_t reserved : 2; /*Reserved to be used later*/ + uint32_t always_zero : 3; /*It the upper bits of the first byte. Always zero to look like a + non-printable character*/ + uint32_t cf : 5; /*Color format: See `lv_img_color_format_t`*/ + +} lv_img_header_t; +#else +typedef struct { + + uint32_t cf : 5; /*Color format: See `lv_img_color_format_t`*/ + uint32_t always_zero : 3; /*It the upper bits of the first byte. Always zero to look like a + non-printable character*/ + + uint32_t reserved : 2; /*Reserved to be used later*/ + + uint32_t w : 11; /*Width of the image map*/ + uint32_t h : 11; /*Height of the image map*/ +} lv_img_header_t; +#endif + +/** Image header it is compatible with + * the result from image converter utility*/ +typedef struct { + lv_img_header_t header; /**< A header describing the basics of the image*/ + uint32_t data_size; /**< Size of the image in bytes*/ + const uint8_t * data; /**< Pointer to the data of the image*/ +} lv_img_dsc_t; + +typedef struct { + struct { + const void * src; /*image source (array of pixels)*/ + lv_coord_t src_w; /*width of the image source*/ + lv_coord_t src_h; /*height of the image source*/ + lv_coord_t pivot_x; /*pivot x*/ + lv_coord_t pivot_y; /*pivot y*/ + int16_t angle; /*angle to rotate*/ + uint16_t zoom; /*256 no zoom, 128 half size, 512 double size*/ + lv_color_t color; /*a color used for `LV_IMG_CF_INDEXED_1/2/4/8BIT` color formats*/ + lv_img_cf_t cf; /*color format of the image to rotate*/ + bool antialias; + } cfg; + + struct { + lv_color_t color; + lv_opa_t opa; + } res; + + struct { + lv_img_dsc_t img_dsc; + int32_t pivot_x_256; + int32_t pivot_y_256; + int32_t sinma; + int32_t cosma; + + uint8_t chroma_keyed : 1; + uint8_t has_alpha : 1; + uint8_t native_color : 1; + + uint32_t zoom_inv; + + /*Runtime data*/ + lv_coord_t xs; + lv_coord_t ys; + lv_coord_t xs_int; + lv_coord_t ys_int; + uint32_t pxi; + uint8_t px_size; + } tmp; +} lv_img_transform_dsc_t; + + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +/** + * 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); + +/** + * Get the color of an image's pixel + * @param dsc an image descriptor + * @param x x coordinate of the point to get + * @param y x coordinate of the point to get + * @param color the color of the image. In case of `LV_IMG_CF_ALPHA_1/2/4/8` this color is used. + * Not used in other cases. + * @param safe true: check out of bounds + * @return color of the point + */ +lv_color_t lv_img_buf_get_px_color(lv_img_dsc_t * dsc, lv_coord_t x, lv_coord_t y, lv_color_t color); + +/** + * Get the alpha value of an image's pixel + * @param dsc pointer to an image descriptor + * @param x x coordinate of the point to set + * @param y x coordinate of the point to set + * @param safe true: check out of bounds + * @return alpha value of the point + */ +lv_opa_t lv_img_buf_get_px_alpha(lv_img_dsc_t * dsc, lv_coord_t x, lv_coord_t y); + +/** + * Set the color of a pixel of an image. The alpha channel won't be affected. + * @param dsc pointer to an image descriptor + * @param x x coordinate of the point to set + * @param y x coordinate of the point to set + * @param c color of the point + * @param safe true: check out of bounds + */ +void lv_img_buf_set_px_color(lv_img_dsc_t * dsc, lv_coord_t x, lv_coord_t y, lv_color_t c); + +/** + * Set the alpha value of a pixel of an image. The color won't be affected + * @param dsc pointer to an image descriptor + * @param x x coordinate of the point to set + * @param y x coordinate of the point to set + * @param opa the desired opacity + * @param safe true: check out of bounds + */ +void lv_img_buf_set_px_alpha(lv_img_dsc_t * dsc, lv_coord_t x, lv_coord_t y, lv_opa_t opa); + +/** + * Set the palette color of an indexed image. Valid only for `LV_IMG_CF_INDEXED1/2/4/8` + * @param dsc pointer to an image descriptor + * @param id the palette color to set: + * - for `LV_IMG_CF_INDEXED1`: 0..1 + * - for `LV_IMG_CF_INDEXED2`: 0..3 + * - for `LV_IMG_CF_INDEXED4`: 0..15 + * - for `LV_IMG_CF_INDEXED8`: 0..255 + * @param c the color to set + */ +void lv_img_buf_set_palette(lv_img_dsc_t * dsc, uint8_t id, lv_color_t c); + +/** + * 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); + +#if LV_DRAW_COMPLEX +/** + * Initialize a descriptor to rotate an image + * @param dsc pointer to an `lv_img_transform_dsc_t` variable whose `cfg` field is initialized + */ +void _lv_img_buf_transform_init(lv_img_transform_dsc_t * dsc); + +/** + * Continue transformation by taking the neighbors into account + * @param dsc pointer to the transformation descriptor + */ +bool _lv_img_buf_transform_anti_alias(lv_img_transform_dsc_t * dsc); + +/** + * Get which color and opa would come to a pixel if it were rotated + * @param dsc a descriptor initialized by `lv_img_buf_rotate_init` + * @param x the coordinate which color and opa should be get + * @param y the coordinate which color and opa should be get + * @return true: there is valid pixel on these x/y coordinates; false: the rotated pixel was out of the image + * @note the result is written back to `dsc->res_color` and `dsc->res_opa` + */ +bool _lv_img_buf_transform(lv_img_transform_dsc_t * dsc, lv_coord_t x, lv_coord_t y); + +#endif +/** + * Get the area of a rectangle if its rotated and scaled + * @param res store the coordinates here + * @param w width of the rectangle to transform + * @param h height of the rectangle to transform + * @param angle angle of rotation + * @param zoom zoom, (256 no zoom) + * @param pivot x,y pivot coordinates of rotation + */ +void _lv_img_buf_get_transformed_area(lv_area_t * res, lv_coord_t w, lv_coord_t h, int16_t angle, uint16_t zoom, + const lv_point_t * pivot); + +/********************** + * MACROS + **********************/ + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif /*LV_IMG_BUF_H*/ diff --git a/src/lib/lvgl/src/draw/lv_img_cache.h b/src/lib/lvgl/src/draw/lv_img_cache.h new file mode 100644 index 0000000..dc0c5d9 --- /dev/null +++ b/src/lib/lvgl/src/draw/lv_img_cache.h @@ -0,0 +1,78 @@ +/** + * @file lv_img_cache.h + * + */ + +#ifndef LV_IMG_CACHE_H +#define LV_IMG_CACHE_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include "lv_img_decoder.h" + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +/** + * When loading images from the network it can take a long time to download and decode the image. + * + * To avoid repeating this heavy load images can be cached. + */ +typedef struct { + lv_img_decoder_dsc_t dec_dsc; /**< Image information*/ + + /** Count the cache entries's life. Add `time_to_open` to `life` when the entry is used. + * Decrement all lifes by one every in every ::lv_img_cache_open. + * If life == 0 the entry can be reused*/ + int32_t life; +} _lv_img_cache_entry_t; + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +/** + * Open an image using the image decoder interface and cache it. + * The image will be left open meaning if the image decoder open callback allocated memory then it will remain. + * The image is closed if a new image is opened and the new image takes its place in the cache. + * @param src source of the image. Path to file or pointer to an `lv_img_dsc_t` variable + * @param color The color of the image with `LV_IMG_CF_ALPHA_...` + * @param frame_id the index of the frame. Used only with animated images, set 0 for normal images + * @return pointer to the cache entry or NULL if can open the image + */ +_lv_img_cache_entry_t * _lv_img_cache_open(const void * src, lv_color_t color, int32_t frame_id); + +/** + * Set the number of images to be cached. + * More cached images mean more opened image at same time which might mean more memory usage. + * E.g. if 20 PNG or JPG images are open in the RAM they consume memory while opened in the cache. + * @param new_entry_cnt number of image to cache + */ +void lv_img_cache_set_size(uint16_t new_slot_num); + +/** + * Invalidate an image source in the cache. + * Useful if the image source is updated therefore it needs to be cached again. + * @param src an image source path to a file or pointer to an `lv_img_dsc_t` variable. + */ +void lv_img_cache_invalidate_src(const void * src); + +/********************** + * MACROS + **********************/ + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif /*LV_IMG_CACHE_H*/ diff --git a/src/lib/lvgl/src/draw/lv_img_decoder.h b/src/lib/lvgl/src/draw/lv_img_decoder.h new file mode 100644 index 0000000..ebebf10 --- /dev/null +++ b/src/lib/lvgl/src/draw/lv_img_decoder.h @@ -0,0 +1,274 @@ +/** + * @file lv_img_decoder.h + * + */ + +#ifndef LV_IMG_DECODER_H +#define LV_IMG_DECODER_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include "../lv_conf_internal.h" + +#include +#include "lv_img_buf.h" +#include "../misc/lv_fs.h" +#include "../misc/lv_types.h" +#include "../misc/lv_area.h" + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +/** + * Source of image.*/ +enum { + LV_IMG_SRC_VARIABLE, /** Binary/C variable*/ + LV_IMG_SRC_FILE, /** File in filesystem*/ + LV_IMG_SRC_SYMBOL, /** Symbol (@ref lv_symbol_def.h)*/ + LV_IMG_SRC_UNKNOWN, /** Unknown source*/ +}; + +typedef uint8_t lv_img_src_t; + +/*Decoder function definitions*/ +struct _lv_img_decoder_dsc_t; +struct _lv_img_decoder_t; + +/** + * Get info from an image and store in the `header` + * @param src the image source. Can be a pointer to a C array or a file name (Use + * `lv_img_src_get_type` to determine the type) + * @param header store the info here + * @return LV_RES_OK: info written correctly; LV_RES_INV: failed + */ +typedef lv_res_t (*lv_img_decoder_info_f_t)(struct _lv_img_decoder_t * decoder, const void * src, + lv_img_header_t * header); + +/** + * Open an image for decoding. Prepare it as it is required to read it later + * @param decoder pointer to the decoder the function associated with + * @param dsc pointer to decoder descriptor. `src`, `color` are already initialized in it. + */ +typedef lv_res_t (*lv_img_decoder_open_f_t)(struct _lv_img_decoder_t * decoder, struct _lv_img_decoder_dsc_t * dsc); + +/** + * Decode `len` pixels starting from the given `x`, `y` coordinates and store them in `buf`. + * Required only if the "open" function can't return with the whole decoded pixel array. + * @param decoder pointer to the decoder the function associated with + * @param dsc pointer to decoder descriptor + * @param x start x coordinate + * @param y start y coordinate + * @param len number of pixels to decode + * @param buf a buffer to store the decoded pixels + * @return LV_RES_OK: ok; LV_RES_INV: failed + */ +typedef lv_res_t (*lv_img_decoder_read_line_f_t)(struct _lv_img_decoder_t * decoder, struct _lv_img_decoder_dsc_t * dsc, + lv_coord_t x, lv_coord_t y, lv_coord_t len, uint8_t * buf); + +/** + * Close the pending decoding. Free resources etc. + * @param decoder pointer to the decoder the function associated with + * @param dsc pointer to decoder descriptor + */ +typedef void (*lv_img_decoder_close_f_t)(struct _lv_img_decoder_t * decoder, struct _lv_img_decoder_dsc_t * dsc); + + +typedef struct _lv_img_decoder_t { + lv_img_decoder_info_f_t info_cb; + lv_img_decoder_open_f_t open_cb; + lv_img_decoder_read_line_f_t read_line_cb; + lv_img_decoder_close_f_t close_cb; + +#if LV_USE_USER_DATA + void * user_data; +#endif +} lv_img_decoder_t; + + +/**Describe an image decoding session. Stores data about the decoding*/ +typedef struct _lv_img_decoder_dsc_t { + /**The decoder which was able to open the image source*/ + lv_img_decoder_t * decoder; + + /**The image source. A file path like "S:my_img.png" or pointer to an `lv_img_dsc_t` variable*/ + const void * src; + + /**Color to draw the image. USed when the image has alpha channel only*/ + lv_color_t color; + + /**Frame of the image, using with animated images*/ + int32_t frame_id; + + /**Type of the source: file or variable. Can be set in `open` function if required*/ + lv_img_src_t src_type; + + /**Info about the opened image: color format, size, etc. MUST be set in `open` function*/ + lv_img_header_t header; + + /** Pointer to a buffer where the image's data (pixels) are stored in a decoded, plain format. + * MUST be set in `open` function*/ + const uint8_t * img_data; + + /** How much time did it take to open the image. [ms] + * If not set `lv_img_cache` will measure and set the time to open*/ + uint32_t time_to_open; + + /**A text to display instead of the image when the image can't be opened. + * Can be set in `open` function or set NULL.*/ + const char * error_msg; + + /**Store any custom data here is required*/ + void * user_data; +} lv_img_decoder_dsc_t; + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +/** + * Initialize the image decoder module + */ +void _lv_img_decoder_init(void); + +/** + * Get information about an image. + * Try the created image decoder one by one. Once one is able to get info that info will be used. + * @param src the image source. Can be + * 1) File name: E.g. "S:folder/img1.png" (The drivers needs to registered via `lv_fs_add_drv()`) + * 2) Variable: Pointer to an `lv_img_dsc_t` variable + * 3) Symbol: E.g. `LV_SYMBOL_OK` + * @param header the image info will be stored here + * @return LV_RES_OK: success; LV_RES_INV: wasn't able to get info about the image + */ +lv_res_t lv_img_decoder_get_info(const void * src, lv_img_header_t * header); + +/** + * Open an image. + * Try the created image decoder one by one. Once one is able to open the image that decoder is save in `dsc` + * @param dsc describe a decoding session. Simply a pointer to an `lv_img_decoder_dsc_t` variable. + * @param src the image source. Can be + * 1) File name: E.g. "S:folder/img1.png" (The drivers needs to registered via `lv_fs_add_drv()`) + * 2) Variable: Pointer to an `lv_img_dsc_t` variable + * 3) Symbol: E.g. `LV_SYMBOL_OK` + * @param color The color of the image with `LV_IMG_CF_ALPHA_...` + * @param frame_id the index of the frame. Used only with animated images, set 0 for normal images + * @return LV_RES_OK: opened the image. `dsc->img_data` and `dsc->header` are set. + * LV_RES_INV: none of the registered image decoders were able to open the image. + */ +lv_res_t lv_img_decoder_open(lv_img_decoder_dsc_t * dsc, const void * src, lv_color_t color, int32_t frame_id); + +/** + * Read a line from an opened image + * @param dsc pointer to `lv_img_decoder_dsc_t` used in `lv_img_decoder_open` + * @param x start X coordinate (from left) + * @param y start Y coordinate (from top) + * @param len number of pixels to read + * @param buf store the data here + * @return LV_RES_OK: success; LV_RES_INV: an error occurred + */ +lv_res_t lv_img_decoder_read_line(lv_img_decoder_dsc_t * dsc, lv_coord_t x, lv_coord_t y, lv_coord_t len, + uint8_t * buf); + +/** + * Close a decoding session + * @param dsc pointer to `lv_img_decoder_dsc_t` used in `lv_img_decoder_open` + */ +void lv_img_decoder_close(lv_img_decoder_dsc_t * dsc); + +/** + * Create a new image decoder + * @return pointer to the new image decoder + */ +lv_img_decoder_t * lv_img_decoder_create(void); + +/** + * Delete an image decoder + * @param decoder pointer to an image decoder + */ +void lv_img_decoder_delete(lv_img_decoder_t * decoder); + +/** + * Set a callback to get information about the image + * @param decoder pointer to an image decoder + * @param info_cb a function to collect info about an image (fill an `lv_img_header_t` struct) + */ +void lv_img_decoder_set_info_cb(lv_img_decoder_t * decoder, lv_img_decoder_info_f_t info_cb); + +/** + * Set a callback to open an image + * @param decoder pointer to an image decoder + * @param open_cb a function to open an image + */ +void lv_img_decoder_set_open_cb(lv_img_decoder_t * decoder, lv_img_decoder_open_f_t open_cb); + +/** + * Set a callback to a decoded line of an image + * @param decoder pointer to an image decoder + * @param read_line_cb a function to read a line of an image + */ +void lv_img_decoder_set_read_line_cb(lv_img_decoder_t * decoder, lv_img_decoder_read_line_f_t read_line_cb); + +/** + * Set a callback to close a decoding session. E.g. close files and free other resources. + * @param decoder pointer to an image decoder + * @param close_cb a function to close a decoding session + */ +void lv_img_decoder_set_close_cb(lv_img_decoder_t * decoder, lv_img_decoder_close_f_t close_cb); + +/** + * Get info about a built-in image + * @param decoder the decoder where this function belongs + * @param src the image source: pointer to an `lv_img_dsc_t` variable, a file path or a symbol + * @param header store the image data here + * @return LV_RES_OK: the info is successfully stored in `header`; LV_RES_INV: unknown format or other error. + */ +lv_res_t lv_img_decoder_built_in_info(lv_img_decoder_t * decoder, const void * src, lv_img_header_t * header); + +/** + * Open a built in image + * @param decoder the decoder where this function belongs + * @param dsc pointer to decoder descriptor. `src`, `style` are already initialized in it. + * @return LV_RES_OK: the info is successfully stored in `header`; LV_RES_INV: unknown format or other error. + */ +lv_res_t lv_img_decoder_built_in_open(lv_img_decoder_t * decoder, lv_img_decoder_dsc_t * dsc); + +/** + * Decode `len` pixels starting from the given `x`, `y` coordinates and store them in `buf`. + * Required only if the "open" function can't return with the whole decoded pixel array. + * @param decoder pointer to the decoder the function associated with + * @param dsc pointer to decoder descriptor + * @param x start x coordinate + * @param y start y coordinate + * @param len number of pixels to decode + * @param buf a buffer to store the decoded pixels + * @return LV_RES_OK: ok; LV_RES_INV: failed + */ +lv_res_t lv_img_decoder_built_in_read_line(lv_img_decoder_t * decoder, lv_img_decoder_dsc_t * dsc, lv_coord_t x, + lv_coord_t y, lv_coord_t len, uint8_t * buf); + +/** + * Close the pending decoding. Free resources etc. + * @param decoder pointer to the decoder the function associated with + * @param dsc pointer to decoder descriptor + */ +void lv_img_decoder_built_in_close(lv_img_decoder_t * decoder, lv_img_decoder_dsc_t * dsc); + +/********************** + * MACROS + **********************/ + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif /*LV_IMG_DECODER_H*/ diff --git a/src/lib/lvgl/src/draw/nxp_pxp/lv_gpu_nxp_pxp.h b/src/lib/lvgl/src/draw/nxp_pxp/lv_gpu_nxp_pxp.h new file mode 100644 index 0000000..8d81288 --- /dev/null +++ b/src/lib/lvgl/src/draw/nxp_pxp/lv_gpu_nxp_pxp.h @@ -0,0 +1,193 @@ +/** + * @file lv_gpu_nxp_pxp.h + * + */ + +/** + * MIT License + * + * Copyright (c) 2020 NXP + * + * 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 (including the next paragraph) + * 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. + * + */ + +#ifndef LV_SRC_LV_GPU_LV_GPU_NXP_PXP_H_ +#define LV_SRC_LV_GPU_LV_GPU_NXP_PXP_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ + +#include "../../lv_conf_internal.h" + +#if LV_USE_GPU_NXP_PXP + +#include "../misc/lv_area.h" +#include "../misc/lv_color.h" + +/********************* + * DEFINES + *********************/ + +/** PXP module instance to use*/ +#define LV_GPU_NXP_PXP_ID PXP + +/** PXP interrupt line I*/ +#define LV_GPU_NXP_PXP_IRQ_ID PXP_IRQn + +#ifndef LV_GPU_NXP_PXP_BLIT_SIZE_LIMIT +/** Minimum area (in pixels) for image copy with 100% opacity to be handled by PXP*/ +#define LV_GPU_NXP_PXP_BLIT_SIZE_LIMIT 32 +#endif + +#ifndef LV_GPU_NXP_PXP_BLIT_OPA_SIZE_LIMIT +/** Minimum area (in pixels) for image copy with transparency to be handled by PXP*/ +#define LV_GPU_NXP_PXP_BLIT_OPA_SIZE_LIMIT 16 +#endif + +#ifndef LV_GPU_NXP_PXP_BUFF_SYNC_BLIT_SIZE_LIMIT +/** Minimum invalidated area (in pixels) to be synchronized by PXP during buffer sync */ +#define LV_GPU_NXP_PXP_BUFF_SYNC_BLIT_SIZE_LIMIT 32 +#endif + +#ifndef LV_GPU_NXP_PXP_FILL_SIZE_LIMIT +/** Minimum area (in pixels) to be filled by PXP with 100% opacity*/ +#define LV_GPU_NXP_PXP_FILL_SIZE_LIMIT 64 +#endif + +#ifndef LV_GPU_NXP_PXP_FILL_OPA_SIZE_LIMIT +/** Minimum area (in pixels) to be filled by PXP with transparency*/ +#define LV_GPU_NXP_PXP_FILL_OPA_SIZE_LIMIT 32 +#endif + +/********************** + * TYPEDEFS + **********************/ +/** + * NXP PXP device configuration - call-backs used for + * interrupt init/wait/deinit. + */ +typedef struct { + /** Callback for PXP interrupt initialization*/ + lv_res_t (*pxp_interrupt_init)(void); + + /** Callback for PXP interrupt de-initialization*/ + void (*pxp_interrupt_deinit)(void); + + /** Callback that should start PXP and wait for operation complete*/ + void (*pxp_run)(void); +} lv_nxp_pxp_cfg_t; + +/********************** + * STATIC VARIABLES + **********************/ + +/********************** + * MACROS + **********************/ + +/********************** + * GLOBAL FUNCTIONS + **********************/ + +/** + * Reset and initialize PXP device. This function should be called as a part + * of display init sequence. + * + * @return LV_RES_OK: PXP init ok; LV_RES_INV: init error. See error log for more information. + */ +lv_res_t lv_gpu_nxp_pxp_init(lv_nxp_pxp_cfg_t * cfg); + +/** + * Disable PXP device. Should be called during display deinit sequence. + */ +void lv_gpu_nxp_pxp_deinit(void); + +/** + * Fill area, with optional opacity. + * + * @param[in/out] dest_buf destination buffer + * @param[in] dest_width width (stride) of destination buffer in pixels + * @param[in] fill_area area to fill + * @param[in] color color + * @param[in] opa transparency of the color + */ +void lv_gpu_nxp_pxp_fill(lv_color_t * dest_buf, lv_coord_t dest_width, const lv_area_t * fill_area, lv_color_t color, + lv_opa_t opa); + +/** + * @brief BLock Image Transfer - copy rectangular image from src buffer to dst buffer with effects. + * + * By default, image is copied directly, with optional opacity configured by \p opa. + * Color keying can be enabled by calling lv_gpu_nxp_pxp_enable_color_key() before calling this function. + * Recoloring can be enabled by calling lv_gpu_nxp_pxp_enable_recolor() before calling this function. + * Note that color keying and recoloring at the same time is not supported and black rectangle is rendered. + * + * @param[in/out] dest destination buffer + * @param[in] dest_width width (stride) of destination buffer in pixels + * @param[in] src source buffer + * @param[in] src_with width (stride) of source buffer in pixels + * @param[in] copy_w width of area to be copied from src to dest + * @param[in] copy_h height of area to be copied from src to dest + * @param[in] opa opacity of the result + */ +void lv_gpu_nxp_pxp_blit(lv_color_t * dest, lv_coord_t dest_width, const lv_color_t * src, lv_coord_t src_width, + lv_coord_t copy_width, lv_coord_t copy_height, lv_opa_t opa); + +/** + * @brief Enable color keying for subsequent calls to lv_gpu_nxp_pxp_blit() + * + * Color key is defined by LV_COLOR_TRANSP symbol in lv_conf.h + */ +void lv_gpu_nxp_pxp_enable_color_key(void); + +/** + * @brief Disable color keying for subsequent calls to lv_gpu_nxp_pxp_blit() + * + */ +void lv_gpu_nxp_pxp_disable_color_key(void); + +/** + * @brief Enable recolor feature for subsequent calls to lv_gpu_nxp_pxp_blit() + * + * @param[in] color recolor value + * @param[in] opa effect opacity + */ +void lv_gpu_nxp_pxp_enable_recolor(lv_color_t color, lv_opa_t opa); + +/** + * @brief Disable recolor feature for subsequent calls to lv_gpu_nxp_pxp_blit() + */ +void lv_gpu_nxp_pxp_disable_recolor(void); + +/********************** + * STATIC FUNCTIONS + **********************/ + +#endif /*LV_USE_GPU_NXP_PXP*/ + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif /*LV_SRC_LV_GPU_LV_GPU_NXP_PXP_H_*/ diff --git a/src/lib/lvgl/src/draw/nxp_pxp/lv_gpu_nxp_pxp_osa.h b/src/lib/lvgl/src/draw/nxp_pxp/lv_gpu_nxp_pxp_osa.h new file mode 100644 index 0000000..89524da --- /dev/null +++ b/src/lib/lvgl/src/draw/nxp_pxp/lv_gpu_nxp_pxp_osa.h @@ -0,0 +1,47 @@ +/** + * @file lv_gpu_nxp_pxp_osa.h + * + */ + +/** + * MIT License + * + * Copyright (c) 2020 NXP + * + * 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 (including the next paragraph) + * 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. + * + */ + +#ifndef LV_SRC_LV_GPU_LV_GPU_NXP_PXP_OSA_H_ +#define LV_SRC_LV_GPU_LV_GPU_NXP_PXP_OSA_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "../../lv_conf_internal.h" + +#if LV_USE_GPU_NXP_PXP && LV_USE_GPU_NXP_PXP_AUTO_INIT +extern lv_nxp_pxp_cfg_t pxp_default_cfg; +#endif + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif /*LV_SRC_LV_GPU_LV_GPU_NXP_PXP_OSA_H_*/ diff --git a/src/lib/lvgl/src/draw/nxp_vglite/lv_gpu_nxp_vglite.h b/src/lib/lvgl/src/draw/nxp_vglite/lv_gpu_nxp_vglite.h new file mode 100644 index 0000000..26f4c3f --- /dev/null +++ b/src/lib/lvgl/src/draw/nxp_vglite/lv_gpu_nxp_vglite.h @@ -0,0 +1,145 @@ +/** + * @file lv_gpu_nxp_vglite.h + * + */ + +/** + * MIT License + * + * Copyright (c) 2020 NXP + * + * 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 (including the next paragraph) + * 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. + * + */ + +#ifndef LV_SRC_LV_GPU_LV_GPU_NXP_VGLITE_H_ +#define LV_SRC_LV_GPU_LV_GPU_NXP_VGLITE_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include "../../lv_conf_internal.h" + +#if LV_USE_GPU_NXP_VG_LITE + +/********************* + * DEFINES + *********************/ + +/** Use this symbol as limit to disable feature (value has to be larger than supported resolution) */ +#define LV_GPU_NXP_VG_LITE_FEATURE_DISABLED (1920*1080+1) + +/** Stride in px required by VG-Lite HW. Don't change this. */ +#define LV_GPU_NXP_VG_LITE_STRIDE_ALIGN_PX 16U + +#ifndef LV_GPU_NXP_VG_LITE_FILL_SIZE_LIMIT +/** Minimum area (in pixels) to be filled by VG-Lite with 100% opacity*/ +#define LV_GPU_NXP_VG_LITE_FILL_SIZE_LIMIT 32 +#endif + +#ifndef LV_GPU_NXP_VG_LITE_FILL_OPA_SIZE_LIMIT +/** Minimum area (in pixels) to be filled by VG-Lite with transparency*/ +#define LV_GPU_NXP_VG_LITE_FILL_OPA_SIZE_LIMIT 32 +#endif + +#ifndef LV_GPU_NXP_VG_LITE_BLIT_SIZE_LIMIT +/** Minimum area (in pixels) for image copy with 100% opacity to be handled by VG-Lite*/ +#define LV_GPU_NXP_VG_LITE_BLIT_SIZE_LIMIT 32 +#endif + +#ifndef LV_GPU_NXP_VG_LITE_BUFF_SYNC_BLIT_SIZE_LIMIT +/** Minimum invalidated area (in pixels) to be synchronized by VG-Lite during buffer sync */ +#define LV_GPU_NXP_VG_LITE_BUFF_SYNC_BLIT_SIZE_LIMIT 32 +#endif + +#ifndef LV_GPU_NXP_VG_LITE_BLIT_OPA_SIZE_LIMIT +/** Minimum area (in pixels) for image copy with transparency to be handled by VG-Lite*/ +#define LV_GPU_NXP_VG_LITE_BLIT_OPA_SIZE_LIMIT 32 +#endif + +#ifndef LV_GPU_NXP_VG_LITE_LOG_ERRORS +/** Enable logging of VG-Lite errors (\see LV_LOG_ERROR)*/ +#define LV_GPU_NXP_VG_LITE_LOG_ERRORS 1 +#endif + +/********************** + * TYPEDEFS + **********************/ + +/** + * BLock Image Transfer descriptor structure + */ +typedef struct { + + const lv_color_t * src; /**< Source buffer pointer (must be aligned on 32 bytes)*/ + lv_area_t src_area; /**< Area to be copied from source*/ + lv_coord_t src_width; /**< Source buffer width*/ + lv_coord_t src_height; /**< Source buffer height*/ + uint32_t src_stride; /**< Source buffer stride in bytes (must be aligned on 16 px)*/ + + const lv_color_t * dst; /**< Destination buffer pointer (must be aligned on 32 bytes)*/ + lv_area_t dst_area; /**< Target area in destination buffer (must be the same as src_area)*/ + lv_coord_t dst_width; /**< Destination buffer width*/ + lv_coord_t dst_height; /**< Destination buffer height*/ + uint32_t dst_stride; /**< Destination buffer stride in bytes (must be aligned on 16 px)*/ + + lv_opa_t opa; /**< Opacity - alpha mix (0 = source not copied, 255 = 100% opaque)*/ + +} lv_gpu_nxp_vglite_blit_info_t; + +/********************** + * MACROS + **********************/ + +/********************** + * GLOBAL FUNCTIONS + **********************/ + +/*** + * Fills rectangular area in buffer. + * @param[in] dest_buf Destination buffer pointer (must be aligned on 32 bytes) + * @param[in] dest_width Destination buffer width in pixels ((must be aligned on 16 px) + * @param[in] dest_height Destination buffer height in pixels + * @param[in] fill_area Area to be filled + * @param[in] color Fill color + * @param[in] opa Opacity (255 = full, 128 = 50% background/50% color, 0 = no fill) + * @retval LV_RES_OK Fill completed + * @retval LV_RES_INV Error occurred (\see LV_GPU_NXP_VG_LITE_LOG_ERRORS) + */ +lv_res_t lv_gpu_nxp_vglite_fill(lv_color_t * dest_buf, lv_coord_t dest_width, lv_coord_t dest_height, + const lv_area_t * fill_area, lv_color_t color, lv_opa_t opa); + +/*** + * BLock Image Transfer. + * @param[in] blit Description of the transfer + * @retval LV_RES_OK Transfer complete + * @retval LV_RES_INV Error occurred (\see LV_GPU_NXP_VG_LITE_LOG_ERRORS) + */ +lv_res_t lv_gpu_nxp_vglite_blit(lv_gpu_nxp_vglite_blit_info_t * blit); + +#endif /*LV_USE_GPU_NXP_VG_LITE*/ + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif /*LV_SRC_LV_GPU_LV_GPU_NXP_VGLITE_H_*/ diff --git a/src/lib/lvgl/src/draw/sdl/lv_draw_sdl.h b/src/lib/lvgl/src/draw/sdl/lv_draw_sdl.h new file mode 100644 index 0000000..9b44a7b --- /dev/null +++ b/src/lib/lvgl/src/draw/sdl/lv_draw_sdl.h @@ -0,0 +1,96 @@ +/** + * @file lv_draw_sdl.h + * + */ + +#ifndef LV_DRAW_SDL_H +#define LV_DRAW_SDL_H + + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include "../../lv_conf_internal.h" + +#if LV_USE_GPU_SDL + +#include LV_GPU_SDL_INCLUDE_PATH + +#include "../lv_draw.h" +#include "../../core/lv_disp.h" + +/********************* + * DEFINES + *********************/ + +#if SDL_BYTEORDER == SDL_BIG_ENDIAN +#define LV_DRAW_SDL_TEXTURE_FORMAT SDL_PIXELFORMAT_ARGB8888 +#else +#define LV_DRAW_SDL_TEXTURE_FORMAT SDL_PIXELFORMAT_RGBA8888 +#endif + +/********************** + * TYPEDEFS + **********************/ + +struct lv_draw_sdl_context_internals_t; + +typedef struct { + /** + * Render for display driver + */ + SDL_Renderer * renderer; + void * user_data; +} lv_draw_sdl_drv_param_t; + +typedef struct { + lv_draw_ctx_t base_draw; + SDL_Renderer * renderer; + struct lv_draw_sdl_context_internals_t * internals; +} lv_draw_sdl_ctx_t; + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +void lv_draw_sdl_init_ctx(lv_disp_drv_t * disp_drv, lv_draw_ctx_t * draw_ctx); + +/** + * @brief Free caches + * + */ +void lv_draw_sdl_deinit_ctx(lv_disp_drv_t * disp_drv, lv_draw_ctx_t * draw_ctx); + +SDL_Texture * lv_draw_sdl_create_screen_texture(SDL_Renderer * renderer, lv_coord_t hor, lv_coord_t ver); + +/*====================== + * Add/remove functions + *=====================*/ + +/*===================== + * Setter functions + *====================*/ + +/*===================== + * Getter functions + *====================*/ + +/*===================== + * Other functions + *====================*/ + +/********************** + * MACROS + **********************/ + +#endif /*LV_USE_GPU_SDL*/ + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif /*LV_DRAW_SDL_H*/ diff --git a/src/lib/lvgl/src/draw/sdl/lv_draw_sdl_composite.h b/src/lib/lvgl/src/draw/sdl/lv_draw_sdl_composite.h new file mode 100644 index 0000000..3050815 --- /dev/null +++ b/src/lib/lvgl/src/draw/sdl/lv_draw_sdl_composite.h @@ -0,0 +1,72 @@ +/** + * @file lv_draw_sdl_composite.h + * + */ + +#ifndef LV_DRAW_SDL_COMPOSITE_H +#define LV_DRAW_SDL_COMPOSITE_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ + +#include "../../lv_conf_internal.h" + +#include LV_GPU_SDL_INCLUDE_PATH + +#include "lv_draw_sdl.h" +#include "../../misc/lv_area.h" +#include "../../misc/lv_color.h" + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +typedef enum lv_draw_sdl_composite_texture_id_t { + LV_DRAW_SDL_COMPOSITE_TEXTURE_ID_STREAM0, + LV_DRAW_SDL_COMPOSITE_TEXTURE_ID_STREAM1, + LV_DRAW_SDL_COMPOSITE_TEXTURE_ID_TARGET0, + LV_DRAW_SDL_COMPOSITE_TEXTURE_ID_TARGET1, +} lv_draw_sdl_composite_texture_id_t; + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +/** + * Begin drawing with mask. Render target will be switched to a temporary texture, + * and drawing coordinates may get clipped or translated + * @param coords_in Original coordinates + * @param clip_in Original clip area + * @param extension Useful for shadows or outlines, can be NULL + * @param coords_out Translated coords + * @param clip_out Translated clip area + * @param apply_area Area of actual composited texture will be drawn + * @return true if there are any mask needs to be drawn, false otherwise + */ +bool lv_draw_sdl_composite_begin(lv_draw_sdl_ctx_t * ctx, const lv_area_t * coords_in, const lv_area_t * clip_in, + const lv_area_t * extension, lv_blend_mode_t blend_mode, lv_area_t * coords_out, + lv_area_t * clip_out, lv_area_t * apply_area); + +void lv_draw_sdl_composite_end(lv_draw_sdl_ctx_t * ctx, const lv_area_t * apply_area, lv_blend_mode_t blend_mode); + +SDL_Texture * lv_draw_sdl_composite_texture_obtain(lv_draw_sdl_ctx_t * ctx, lv_draw_sdl_composite_texture_id_t id, + lv_coord_t w, lv_coord_t h); + +/********************** + * MACROS + **********************/ + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif /*LV_DRAW_SDL_COMPOSITE_H*/ diff --git a/src/lib/lvgl/src/draw/sdl/lv_draw_sdl_img.h b/src/lib/lvgl/src/draw/sdl/lv_draw_sdl_img.h new file mode 100644 index 0000000..0e27027 --- /dev/null +++ b/src/lib/lvgl/src/draw/sdl/lv_draw_sdl_img.h @@ -0,0 +1,72 @@ +/** + * @file lv_draw_sdl_img.h + * + */ + +#ifndef LV_DRAW_SDL_IMG_H +#define LV_DRAW_SDL_IMG_H + + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include "../../lv_conf_internal.h" + +#if LV_USE_GPU_SDL + +#include LV_GPU_SDL_INCLUDE_PATH + +#include "../lv_draw.h" + +#include "lv_draw_sdl_texture_cache.h" + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +typedef struct lv_draw_sdl_img_header_t { + lv_img_header_t base; + SDL_Rect rect; +} lv_draw_sdl_img_header_t; + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +/*====================== + * Add/remove functions + *=====================*/ + +/*===================== + * Setter functions + *====================*/ + +/*===================== + * Getter functions + *====================*/ + +/*===================== + * Other functions + *====================*/ +bool lv_draw_sdl_img_load_texture(lv_draw_sdl_ctx_t * ctx, lv_draw_sdl_cache_key_head_img_t * key, size_t key_size, + const void * src, int32_t frame_id, SDL_Texture ** texture, + lv_draw_sdl_img_header_t ** header); +/********************** + * MACROS + **********************/ + +#endif /*LV_USE_GPU_SDL*/ + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif /*LV_DRAW_SDL_IMG_H*/ diff --git a/src/lib/lvgl/src/draw/sdl/lv_draw_sdl_mask.h b/src/lib/lvgl/src/draw/sdl/lv_draw_sdl_mask.h new file mode 100644 index 0000000..a562d73 --- /dev/null +++ b/src/lib/lvgl/src/draw/sdl/lv_draw_sdl_mask.h @@ -0,0 +1,51 @@ +/** + * @file lv_draw_sdl_mask.h + * + */ + +#ifndef LV_DRAW_SDL_MASK_H +#define LV_DRAW_SDL_MASK_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ + +#include "../../lv_conf_internal.h" + +#include LV_GPU_SDL_INCLUDE_PATH + +#include "lv_draw_sdl.h" +#include "../../misc/lv_area.h" +#include "../../misc/lv_color.h" + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +lv_opa_t * lv_draw_sdl_mask_dump_opa(const lv_area_t * coords, const int16_t * ids, int16_t ids_count); + +SDL_Texture * lv_draw_sdl_mask_dump_texture(SDL_Renderer * renderer, const lv_area_t * coords, const int16_t * ids, + int16_t ids_count); + + +/********************** + * MACROS + **********************/ + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif /*LV_DRAW_SDL_MASK_H*/ diff --git a/src/lib/lvgl/src/draw/sdl/lv_draw_sdl_priv.h b/src/lib/lvgl/src/draw/sdl/lv_draw_sdl_priv.h new file mode 100644 index 0000000..1f44c22 --- /dev/null +++ b/src/lib/lvgl/src/draw/sdl/lv_draw_sdl_priv.h @@ -0,0 +1,70 @@ +/** + * @file lv_draw_sdl_priv.h + * + */ + +#ifndef LV_DRAW_SDL_PRIV_H +#define LV_DRAW_SDL_PRIV_H + + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include "../../lv_conf_internal.h" + +#if LV_USE_GPU_SDL + +#include LV_GPU_SDL_INCLUDE_PATH + +#include "../lv_draw.h" +#include "../../misc/lv_lru.h" + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +typedef struct lv_draw_sdl_context_internals_t { + lv_lru_t * texture_cache; + SDL_Texture * mask; + SDL_Texture * composition; +} lv_draw_sdl_context_internals_t; + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +/*====================== + * Add/remove functions + *=====================*/ + +/*===================== + * Setter functions + *====================*/ + +/*===================== + * Getter functions + *====================*/ + +/*===================== + * Other functions + *====================*/ + +/********************** + * MACROS + **********************/ + +#endif /*LV_USE_GPU_SDL*/ + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif /*LV_DRAW_SDL_PRIV_H*/ diff --git a/src/lib/lvgl/src/draw/sdl/lv_draw_sdl_rect.h b/src/lib/lvgl/src/draw/sdl/lv_draw_sdl_rect.h new file mode 100644 index 0000000..1e9be34 --- /dev/null +++ b/src/lib/lvgl/src/draw/sdl/lv_draw_sdl_rect.h @@ -0,0 +1,75 @@ +/** + * @file lv_draw_sdl_rect.h + * + */ + +#ifndef LV_DRAW_SDL_RECT_H +#define LV_DRAW_SDL_RECT_H + + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include "../../lv_conf_internal.h" + +#if LV_USE_GPU_SDL + +#include LV_GPU_SDL_INCLUDE_PATH + +#include "../lv_draw.h" + +#include "lv_draw_sdl_texture_cache.h" + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +typedef struct lv_draw_sdl_rect_header_t { + lv_img_header_t base; + SDL_Rect rect; +} lv_draw_sdl_rect_header_t; + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +/*====================== + * Add/remove functions + *=====================*/ + +/*===================== + * Setter functions + *====================*/ + +/*===================== + * Getter functions + *====================*/ + +/*===================== + * Other functions + *====================*/ + +SDL_Texture * lv_draw_sdl_rect_bg_frag_obtain(lv_draw_sdl_ctx_t * ctx, lv_coord_t radius); + +void lv_draw_sdl_rect_bg_frag_draw_corners(lv_draw_sdl_ctx_t * ctx, SDL_Texture * frag, lv_coord_t frag_size, + const lv_area_t * coords, const lv_area_t * clip, bool full); + +/********************** + * MACROS + **********************/ + +#endif /*LV_USE_GPU_SDL*/ + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif /*LV_DRAW_SDL_RECT_H*/ diff --git a/src/lib/lvgl/src/draw/sdl/lv_draw_sdl_stack_blur.h b/src/lib/lvgl/src/draw/sdl/lv_draw_sdl_stack_blur.h new file mode 100644 index 0000000..413b1c9 --- /dev/null +++ b/src/lib/lvgl/src/draw/sdl/lv_draw_sdl_stack_blur.h @@ -0,0 +1,46 @@ +/** + * @file lv_draw_sdl_stack_blur.h + * + */ +#ifndef LV_DRAW_SDL_STACK_BLUR_H +#define LV_DRAW_SDL_STACK_BLUR_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ + +#include "../../lv_conf_internal.h" + +#if LV_USE_GPU_SDL + +#include "../../misc/lv_color.h" + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +void lv_stack_blur_grayscale(lv_opa_t * buf, uint16_t w, uint16_t h, uint16_t r); + +/********************** + * MACROS + **********************/ + +#endif /*LV_USE_GPU_SDL*/ + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif /*LV_DRAW_SDL_STACK_BLUR_H*/ diff --git a/src/lib/lvgl/src/draw/sdl/lv_draw_sdl_texture_cache.h b/src/lib/lvgl/src/draw/sdl/lv_draw_sdl_texture_cache.h new file mode 100644 index 0000000..dc8b578 --- /dev/null +++ b/src/lib/lvgl/src/draw/sdl/lv_draw_sdl_texture_cache.h @@ -0,0 +1,102 @@ +/** + * @file lv_draw_sdl_texture_cache.h + * + */ + +#ifndef LV_DRAW_SDL_TEXTURE_CACHE_H +#define LV_DRAW_SDL_TEXTURE_CACHE_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ + +#include "../../lv_conf_internal.h" + +#if LV_USE_GPU_SDL + +#include LV_GPU_SDL_INCLUDE_PATH +#include "lv_draw_sdl.h" +#include "lv_draw_sdl_priv.h" +#include "../../draw/lv_img_decoder.h" +#include "../../misc/lv_area.h" + +/********************* + * DEFINES + *********************/ + +#define LV_DRAW_SDL_DEC_DSC_TEXTURE_HEAD "@LVSDLTex" + +/********************** + * TYPEDEFS + **********************/ + +typedef struct { + char head[8]; + SDL_Texture * texture; + SDL_Rect rect; + bool texture_managed; + bool texture_referenced; +} lv_draw_sdl_dec_dsc_userdata_t; + +typedef enum { + LV_GPU_CACHE_KEY_MAGIC_ARC = 0x01, + LV_GPU_CACHE_KEY_MAGIC_IMG = 0x11, + LV_GPU_CACHE_KEY_MAGIC_IMG_ROUNDED_CORNERS = 0x12, + LV_GPU_CACHE_KEY_MAGIC_LINE = 0x21, + LV_GPU_CACHE_KEY_MAGIC_RECT_BG = 0x31, + LV_GPU_CACHE_KEY_MAGIC_RECT_SHADOW = 0x32, + LV_GPU_CACHE_KEY_MAGIC_RECT_BORDER = 0x33, + LV_GPU_CACHE_KEY_MAGIC_FONT_GLYPH = 0x41, + LV_GPU_CACHE_KEY_MAGIC_MASK = 0x51, +} lv_sdl_cache_key_magic_t; + +typedef enum { + LV_DRAW_SDL_CACHE_FLAG_NONE = 0, + LV_DRAW_SDL_CACHE_FLAG_MANAGED = 1, +} lv_draw_sdl_cache_flag_t; + +typedef struct { + lv_sdl_cache_key_magic_t magic; + lv_img_src_t type; + int32_t frame_id; +} lv_draw_sdl_cache_key_head_img_t; + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +void lv_draw_sdl_texture_cache_init(lv_draw_sdl_ctx_t * ctx); + +void lv_draw_sdl_texture_cache_deinit(lv_draw_sdl_ctx_t * ctx); + +/** + * Find cached texture by key. The texture can be destroyed during usage. + */ +SDL_Texture * lv_draw_sdl_texture_cache_get(lv_draw_sdl_ctx_t * ctx, const void * key, size_t key_length, bool * found); + +SDL_Texture * lv_draw_sdl_texture_cache_get_with_userdata(lv_draw_sdl_ctx_t * ctx, const void * key, size_t key_length, + bool * found, void ** userdata); + +void lv_draw_sdl_texture_cache_put(lv_draw_sdl_ctx_t * ctx, const void * key, size_t key_length, SDL_Texture * texture); + +void lv_draw_sdl_texture_cache_put_advanced(lv_draw_sdl_ctx_t * ctx, const void * key, size_t key_length, + SDL_Texture * texture, void * userdata, void userdata_free(void *), + lv_draw_sdl_cache_flag_t flags); + +lv_draw_sdl_cache_key_head_img_t * lv_draw_sdl_texture_img_key_create(const void * src, int32_t frame_id, + size_t * size); + +/********************** + * MACROS + **********************/ +#endif /*LV_USE_GPU_SDL*/ + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif /*LV_DRAW_SDL_TEXTURE_CACHE_H*/ diff --git a/src/lib/lvgl/src/draw/sdl/lv_draw_sdl_utils.h b/src/lib/lvgl/src/draw/sdl/lv_draw_sdl_utils.h new file mode 100644 index 0000000..9afae68 --- /dev/null +++ b/src/lib/lvgl/src/draw/sdl/lv_draw_sdl_utils.h @@ -0,0 +1,65 @@ +/** + * @file lv_draw_sdl_utils.h + * + */ +#ifndef LV_DRAW_SDL_UTILS_H +#define LV_DRAW_SDL_UTILS_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ + +#include "../../lv_conf_internal.h" +#if LV_USE_GPU_SDL + +#include "lv_draw_sdl.h" +#include "../../misc/lv_color.h" +#include "../../misc/lv_area.h" + +#include LV_GPU_SDL_INCLUDE_PATH + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +void _lv_draw_sdl_utils_init(); + +void _lv_draw_sdl_utils_deinit(); + +void lv_area_to_sdl_rect(const lv_area_t * in, SDL_Rect * out); + +void lv_color_to_sdl_color(const lv_color_t * in, SDL_Color * out); + +void lv_area_zoom_to_sdl_rect(const lv_area_t * in, SDL_Rect * out, uint16_t zoom, const lv_point_t * pivot); + +SDL_Palette * lv_sdl_alloc_palette_for_bpp(const uint8_t * mapping, uint8_t bpp); + +SDL_Surface * lv_sdl_create_opa_surface(lv_opa_t * opa, lv_coord_t width, lv_coord_t height, lv_coord_t stride); + +SDL_Texture * lv_sdl_create_opa_texture(SDL_Renderer * renderer, lv_opa_t * pixels, lv_coord_t width, + lv_coord_t height, lv_coord_t stride); + +void lv_sdl_to_8bpp(uint8_t * dest, const uint8_t * src, int width, int height, int stride, uint8_t bpp); + +/********************** + * MACROS + **********************/ + +#endif /*LV_USE_GPU_SDL*/ +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif /*LV_DRAW_SDL_UTILS_H*/ diff --git a/src/lib/lvgl/src/draw/stm32_dma2d/lv_gpu_stm32_dma2d.h b/src/lib/lvgl/src/draw/stm32_dma2d/lv_gpu_stm32_dma2d.h new file mode 100644 index 0000000..73054ca --- /dev/null +++ b/src/lib/lvgl/src/draw/stm32_dma2d/lv_gpu_stm32_dma2d.h @@ -0,0 +1,66 @@ +/** + * @file lv_gpu_stm32_dma2d.h + * + */ + +#ifndef LV_GPU_STM32_DMA2D_H +#define LV_GPU_STM32_DMA2D_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include "../../misc/lv_color.h" +#include "../../hal/lv_hal_disp.h" +#include "../sw/lv_draw_sw.h" + +#if LV_USE_GPU_STM32_DMA2D + +/********************* + * DEFINES + *********************/ + +#define LV_DMA2D_ARGB8888 0 +#define LV_DMA2D_RGB888 1 +#define LV_DMA2D_RGB565 2 +#define LV_DMA2D_ARGB1555 3 +#define LV_DMA2D_ARGB4444 4 + +/********************** + * TYPEDEFS + **********************/ +typedef lv_draw_sw_ctx_t lv_draw_stm32_dma2d_ctx_t; + +struct _lv_disp_drv_t; + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +/** + * Turn on the peripheral and set output color mode, this only needs to be done once + */ +void lv_draw_stm32_dma2d_init(void); + +void lv_draw_stm32_dma2d_ctx_init(struct _lv_disp_drv_t * drv, lv_draw_ctx_t * draw_ctx); + +void lv_draw_stm32_dma2d_ctx_deinit(struct _lv_disp_drv_t * drv, lv_draw_ctx_t * draw_ctx); + +void lv_draw_stm32_dma2d_blend(lv_draw_ctx_t * draw_ctx, const lv_draw_sw_blend_dsc_t * dsc); + +void lv_gpu_stm32_dma2d_wait_cb(lv_draw_ctx_t * draw_ctx); + +/********************** + * MACROS + **********************/ + +#endif /*LV_USE_GPU_STM32_DMA2D*/ + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif /*LV_GPU_STM32_DMA2D_H*/ diff --git a/src/lib/lvgl/src/draw/sw/lv_draw_sw.h b/src/lib/lvgl/src/draw/sw/lv_draw_sw.h new file mode 100644 index 0000000..cba5b48 --- /dev/null +++ b/src/lib/lvgl/src/draw/sw/lv_draw_sw.h @@ -0,0 +1,78 @@ +/** + * @file lv_draw_sw.h + * + */ + +#ifndef LV_DRAW_SW_H +#define LV_DRAW_SW_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include "lv_draw_sw_blend.h" +#include "../lv_draw.h" +#include "../../misc/lv_area.h" +#include "../../misc/lv_color.h" +#include "../../hal/lv_hal_disp.h" + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +struct _lv_disp_drv_t; + +typedef struct { + lv_draw_ctx_t base_draw; + + /** Fill an area of the destination buffer with a color*/ + void (*blend)(lv_draw_ctx_t * draw_ctx, const lv_draw_sw_blend_dsc_t * dsc); +} lv_draw_sw_ctx_t; + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +void lv_draw_sw_init_ctx(struct _lv_disp_drv_t * drv, lv_draw_ctx_t * draw_ctx); +void lv_draw_sw_deinit_ctx(struct _lv_disp_drv_t * drv, lv_draw_ctx_t * draw_ctx); + +void lv_draw_sw_wait_for_finish(lv_draw_ctx_t * draw_ctx); + +void lv_draw_sw_arc(lv_draw_ctx_t * draw_ctx, const lv_draw_arc_dsc_t * dsc, const lv_point_t * center, uint16_t radius, + uint16_t start_angle, uint16_t end_angle); + +void lv_draw_sw_rect(lv_draw_ctx_t * draw_ctx, const lv_draw_rect_dsc_t * dsc, const lv_area_t * coords); + +void lv_draw_sw_bg(lv_draw_ctx_t * draw_ctx, const lv_draw_rect_dsc_t * dsc, const lv_area_t * coords); +void lv_draw_sw_letter(lv_draw_ctx_t * draw_ctx, const lv_draw_label_dsc_t * dsc, const lv_point_t * pos_p, + uint32_t letter); + +LV_ATTRIBUTE_FAST_MEM void lv_draw_sw_img_decoded(struct _lv_draw_ctx_t * draw_ctx, const lv_draw_img_dsc_t * draw_dsc, + const lv_area_t * coords, const uint8_t * src_buf, lv_img_cf_t cf); + +LV_ATTRIBUTE_FAST_MEM void lv_draw_sw_line(struct _lv_draw_ctx_t * draw_ctx, const lv_draw_line_dsc_t * dsc, + const lv_point_t * point1, const lv_point_t * point2); + +void lv_draw_sw_polygon(struct _lv_draw_ctx_t * draw_ctx, const lv_draw_rect_dsc_t * draw_dsc, + const lv_point_t * points, uint16_t point_cnt); + +/*********************** + * GLOBAL VARIABLES + ***********************/ + +/********************** + * MACROS + **********************/ + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif /*LV_DRAW_SW_H*/ diff --git a/src/lib/lvgl/src/draw/sw/lv_draw_sw_blend.h b/src/lib/lvgl/src/draw/sw/lv_draw_sw_blend.h new file mode 100644 index 0000000..9a00e53 --- /dev/null +++ b/src/lib/lvgl/src/draw/sw/lv_draw_sw_blend.h @@ -0,0 +1,69 @@ +/** + * @file lv_draw_sw_blend.h + * + */ + +#ifndef LV_DRAW_SW_BLEND_H +#define LV_DRAW_SW_BLEND_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include "../../misc/lv_color.h" +#include "../../misc/lv_area.h" +#include "../../misc/lv_style.h" +#include "../lv_draw_mask.h" + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +typedef struct { + const lv_area_t * blend_area; /**< The area with absolute coordinates to draw on `draw_ctx->buf` + * will be clipped to `draw_ctx->clip_area` */ + const lv_color_t * src_buf; /**< Pointer to an image to blend. If set `fill_color` is ignored */ + lv_color_t color; /**< Fill color*/ + lv_opa_t * mask_buf; /**< NULL if ignored, or an alpha mask to apply on `blend_area`*/ + lv_draw_mask_res_t mask_res; /**< The result of the previous mask operation */ + const lv_area_t * mask_area; /**< The area of `mask_buf` with absolute coordinates*/ + lv_opa_t opa; /**< The overall opacity*/ + lv_blend_mode_t blend_mode; /**< E.g. LV_BLEND_MODE_ADDITIVE*/ +} lv_draw_sw_blend_dsc_t; + +struct _lv_draw_ctx_t; + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +/** + * Call the blend function of the `draw_ctx`. + * @param draw_ctx pointer to a draw context + * @param dsc pointer to an initialized blend descriptor + */ +void lv_draw_sw_blend(struct _lv_draw_ctx_t * draw_ctx, const lv_draw_sw_blend_dsc_t * dsc); + +/** + * The basic blend function used with software rendering. + * @param draw_ctx pointer to a draw context + * @param dsc pointer to an initialized blend descriptor + */ +LV_ATTRIBUTE_FAST_MEM void lv_draw_sw_blend_basic(struct _lv_draw_ctx_t * draw_ctx, const lv_draw_sw_blend_dsc_t * dsc); + +/********************** + * MACROS + **********************/ + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif /*LV_DRAW_SW_BLEND_H*/ diff --git a/src/lib/lvgl/src/draw/sw/lv_draw_sw_dither.h b/src/lib/lvgl/src/draw/sw/lv_draw_sw_dither.h new file mode 100644 index 0000000..6362c5a --- /dev/null +++ b/src/lib/lvgl/src/draw/sw/lv_draw_sw_dither.h @@ -0,0 +1,70 @@ +/** + * @file lv_draw_sw_dither.h + * + */ + +#ifndef LV_DRAW_SW_DITHER_H +#define LV_DRAW_SW_DITHER_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include "../../core/lv_obj_pos.h" + + +/********************* + * DEFINES + *********************/ +#if LV_COLOR_DEPTH < 32 && LV_DITHER_GRADIENT == 1 +#define _DITHER_GRADIENT 1 +#else +#define _DITHER_GRADIENT 0 +#endif + +/********************** + * TYPEDEFS + **********************/ +#if _DITHER_GRADIENT +/*A signed error color component*/ +typedef struct { + int8_t r, g, b; +} lv_scolor24_t; + +struct _lv_gradient_cache_t; +typedef void (*lv_dither_func_t)(struct _lv_gradient_cache_t * grad, lv_coord_t x, lv_coord_t y, lv_coord_t w); + +#endif + + +/********************** + * PROTOTYPES + **********************/ +#if LV_DRAW_COMPLEX +#if _DITHER_GRADIENT +LV_ATTRIBUTE_FAST_MEM void lv_dither_none(struct _lv_gradient_cache_t * grad, lv_coord_t x, lv_coord_t y, lv_coord_t w); + +LV_ATTRIBUTE_FAST_MEM void lv_dither_ordered_hor(struct _lv_gradient_cache_t * grad, const lv_coord_t xs, + const lv_coord_t y, const lv_coord_t w); +LV_ATTRIBUTE_FAST_MEM void lv_dither_ordered_ver(struct _lv_gradient_cache_t * grad, const lv_coord_t xs, + const lv_coord_t y, const lv_coord_t w); + +#if LV_DITHER_ERROR_DIFFUSION == 1 +LV_ATTRIBUTE_FAST_MEM void lv_dither_err_diff_hor(struct _lv_gradient_cache_t * grad, const lv_coord_t xs, + const lv_coord_t y, const lv_coord_t w); +LV_ATTRIBUTE_FAST_MEM void lv_dither_err_diff_ver(struct _lv_gradient_cache_t * grad, const lv_coord_t xs, + const lv_coord_t y, const lv_coord_t w); +#endif /* LV_DITHER_ERROR_DIFFUSION */ + +#endif /* _DITHER_GRADIENT */ +#endif + + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif diff --git a/src/lib/lvgl/src/draw/sw/lv_draw_sw_gradient.h b/src/lib/lvgl/src/draw/sw/lv_draw_sw_gradient.h new file mode 100644 index 0000000..f5f3215 --- /dev/null +++ b/src/lib/lvgl/src/draw/sw/lv_draw_sw_gradient.h @@ -0,0 +1,97 @@ +/** + * @file lv_draw_sw_gradient.h + * + */ + +#ifndef LV_DRAW_SW_GRADIENT_H +#define LV_DRAW_SW_GRADIENT_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include "../../misc/lv_color.h" +#include "../../misc/lv_style.h" +#include "lv_draw_sw_dither.h" + +/********************* + * DEFINES + *********************/ +#if LV_GRADIENT_MAX_STOPS < 2 +#error LVGL needs at least 2 stops for gradients. Please increase the LV_GRADIENT_MAX_STOPS +#endif + + +/********************** + * TYPEDEFS + **********************/ +#if _DITHER_GRADIENT +typedef lv_color32_t lv_grad_color_t; +#else +typedef lv_color_t lv_grad_color_t; +#endif + +/** To avoid recomputing gradient for each draw operation, + * it's possible to cache the computation in this structure instance. + * Whenever possible, this structure is reused instead of recomputing the gradient map */ +typedef struct _lv_gradient_cache_t { + uint32_t key; /**< A discriminating key that's built from the drawing operation. + * If the key does not match, the cache item is not used */ + uint32_t life : 30; /**< A life counter that's incremented on usage. Higher counter is + * less likely to be evicted from the cache */ + uint32_t filled : 1; /**< Used to skip dithering in it if already done */ + uint32_t not_cached: 1; /**< The cache was too small so this item is not managed by the cache*/ + lv_color_t * map; /**< The computed gradient low bitdepth color map, points into the + * cache's buffer, no free needed */ + lv_coord_t alloc_size; /**< The map allocated size in colors */ + lv_coord_t size; /**< The computed gradient color map size, in colors */ +#if _DITHER_GRADIENT + lv_color32_t * hmap; /**< If dithering, we need to store the current, high bitdepth gradient + * map too, points to the cache's buffer, no free needed */ +#if LV_DITHER_ERROR_DIFFUSION == 1 + lv_scolor24_t * error_acc; /**< Error diffusion dithering algorithm requires storing the last error + * drawn, points to the cache's buffer, no free needed */ + lv_coord_t w; /**< The error array width in pixels */ +#endif +#endif +} lv_grad_t; + + +/********************** + * PROTOTYPES + **********************/ +/** Compute the color in the given gradient and fraction + * Gradient are specified in a virtual [0-255] range, so this function scales the virtual range to the given range + * @param dsc The gradient descriptor to use + * @param range The range to use in computation. + * @param frac The current part used in the range. frac is in [0; range] + */ +LV_ATTRIBUTE_FAST_MEM lv_grad_color_t lv_gradient_calculate(const lv_grad_dsc_t * dsc, lv_coord_t range, + lv_coord_t frac); + +/** + * Set the gradient cache size + * @param max_bytes Max cahce size + */ +void lv_gradient_set_cache_size(size_t max_bytes); + +/** Free the gradient cache */ +void lv_gradient_free_cache(void); + +/** Get a gradient cache from the given parameters */ +lv_grad_t * lv_gradient_get(const lv_grad_dsc_t * gradient, lv_coord_t w, lv_coord_t h); + +/** + * Clean up the gradient item after it was get with `lv_grad_get_from_cache`. + * @param grad pointer to a gradient + */ +void lv_gradient_cleanup(lv_grad_t * grad); + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif /*LV_DRAW_GRADIENT_H*/ diff --git a/src/lib/lvgl/src/extra/layouts/flex/lv_flex.h b/src/lib/lvgl/src/extra/layouts/flex/lv_flex.h new file mode 100644 index 0000000..139fd48 --- /dev/null +++ b/src/lib/lvgl/src/extra/layouts/flex/lv_flex.h @@ -0,0 +1,153 @@ +/** + * @file lv_flex.h + * + */ + +#ifndef LV_FLEX_H +#define LV_FLEX_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include "../../../core/lv_obj.h" +#if LV_USE_FLEX + +/********************* + * DEFINES + *********************/ + +#define LV_OBJ_FLAG_FLEX_IN_NEW_TRACK LV_OBJ_FLAG_LAYOUT_1 +LV_EXPORT_CONST_INT(LV_OBJ_FLAG_FLEX_IN_NEW_TRACK); + +#define _LV_FLEX_COLUMN (1 << 0) +#define _LV_FLEX_WRAP (1 << 2) +#define _LV_FLEX_REVERSE (1 << 3) + +/********************** + * TYPEDEFS + **********************/ + +/*Can't include lv_obj.h because it includes this header file*/ +struct _lv_obj_t; + +typedef enum { + LV_FLEX_ALIGN_START, + LV_FLEX_ALIGN_END, + LV_FLEX_ALIGN_CENTER, + LV_FLEX_ALIGN_SPACE_EVENLY, + LV_FLEX_ALIGN_SPACE_AROUND, + LV_FLEX_ALIGN_SPACE_BETWEEN, +} lv_flex_align_t; + +typedef enum { + LV_FLEX_FLOW_ROW = 0x00, + LV_FLEX_FLOW_COLUMN = _LV_FLEX_COLUMN, + LV_FLEX_FLOW_ROW_WRAP = LV_FLEX_FLOW_ROW | _LV_FLEX_WRAP, + LV_FLEX_FLOW_ROW_REVERSE = LV_FLEX_FLOW_ROW | _LV_FLEX_REVERSE, + LV_FLEX_FLOW_ROW_WRAP_REVERSE = LV_FLEX_FLOW_ROW | _LV_FLEX_WRAP | _LV_FLEX_REVERSE, + LV_FLEX_FLOW_COLUMN_WRAP = LV_FLEX_FLOW_COLUMN | _LV_FLEX_WRAP, + LV_FLEX_FLOW_COLUMN_REVERSE = LV_FLEX_FLOW_COLUMN | _LV_FLEX_REVERSE, + LV_FLEX_FLOW_COLUMN_WRAP_REVERSE = LV_FLEX_FLOW_COLUMN | _LV_FLEX_WRAP | _LV_FLEX_REVERSE, +} lv_flex_flow_t; + +/********************** + * GLOBAL VARIABLES + **********************/ +extern uint32_t LV_LAYOUT_FLEX; +extern lv_style_prop_t LV_STYLE_FLEX_FLOW; +extern lv_style_prop_t LV_STYLE_FLEX_MAIN_PLACE; +extern lv_style_prop_t LV_STYLE_FLEX_CROSS_PLACE; +extern lv_style_prop_t LV_STYLE_FLEX_TRACK_PLACE; +extern lv_style_prop_t LV_STYLE_FLEX_GROW; + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +/** + * Initialize a flex layout the default values + * @param flex pointer to a flex layout descriptor + */ +void lv_flex_init(void); + +/** + * Set hot the item should flow + * @param flex pointer to a flex layout descriptor + * @param flow an element of `lv_flex_flow_t`. + */ +void lv_obj_set_flex_flow(lv_obj_t * obj, lv_flex_flow_t flow); + +/** + * Set how to place (where to align) the items and tracks + * @param flex pointer: to a flex layout descriptor + * @param main_place where to place the items on main axis (in their track). Any value of `lv_flex_align_t`. + * @param cross_place where to place the item in their track on the cross axis. `LV_FLEX_ALIGN_START/END/CENTER` + * @param track_place where to place the tracks in the cross direction. Any value of `lv_flex_align_t`. + */ +void lv_obj_set_flex_align(lv_obj_t * obj, lv_flex_align_t main_place, lv_flex_align_t cross_place, + lv_flex_align_t track_cross_place); + +/** + * Sets the width or height (on main axis) to grow the object in order fill the free space + * @param obj pointer to an object. The parent must have flex layout else nothing will happen. + * @param grow a value to set how much free space to take proportionally to other growing items. + */ +void lv_obj_set_flex_grow(lv_obj_t * obj, uint8_t grow); + +void lv_style_set_flex_flow(lv_style_t * style, lv_flex_flow_t value); +void lv_style_set_flex_main_place(lv_style_t * style, lv_flex_align_t value); +void lv_style_set_flex_cross_place(lv_style_t * style, lv_flex_align_t value); +void lv_style_set_flex_track_place(lv_style_t * style, lv_flex_align_t value); +void lv_style_set_flex_grow(lv_style_t * style, uint8_t value); +void lv_obj_set_style_flex_flow(lv_obj_t * obj, lv_flex_flow_t value, lv_style_selector_t selector); +void lv_obj_set_style_flex_main_place(lv_obj_t * obj, lv_flex_align_t value, lv_style_selector_t selector); +void lv_obj_set_style_flex_cross_place(lv_obj_t * obj, lv_flex_align_t value, lv_style_selector_t selector); +void lv_obj_set_style_flex_track_place(lv_obj_t * obj, lv_flex_align_t value, lv_style_selector_t selector); +void lv_obj_set_style_flex_grow(lv_obj_t * obj, uint8_t value, lv_style_selector_t selector); + +static inline lv_flex_flow_t lv_obj_get_style_flex_flow(const lv_obj_t * obj, uint32_t part) +{ + lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_FLEX_FLOW); + return (lv_flex_flow_t)v.num; +} + +static inline lv_flex_align_t lv_obj_get_style_flex_main_place(const lv_obj_t * obj, uint32_t part) +{ + lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_FLEX_MAIN_PLACE); + return (lv_flex_align_t)v.num; +} + +static inline lv_flex_align_t lv_obj_get_style_flex_cross_place(const lv_obj_t * obj, uint32_t part) +{ + lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_FLEX_CROSS_PLACE); + return (lv_flex_align_t)v.num; +} + +static inline lv_flex_align_t lv_obj_get_style_flex_track_place(const lv_obj_t * obj, uint32_t part) +{ + lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_FLEX_TRACK_PLACE); + return (lv_flex_align_t)v.num; +} + +static inline uint8_t lv_obj_get_style_flex_grow(const lv_obj_t * obj, uint32_t part) +{ + lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_FLEX_GROW); + return (uint8_t)v.num; +} + + +/********************** + * MACROS + **********************/ + +#endif /*LV_USE_FLEX*/ + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif /*LV_FLEX_H*/ diff --git a/src/lib/lvgl/src/extra/layouts/grid/lv_grid.h b/src/lib/lvgl/src/extra/layouts/grid/lv_grid.h new file mode 100644 index 0000000..cd2510e --- /dev/null +++ b/src/lib/lvgl/src/extra/layouts/grid/lv_grid.h @@ -0,0 +1,194 @@ +/** + * @file lv_grid.h + * + */ + +#ifndef LV_GRID_H +#define LV_GRID_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include "../../../core/lv_obj.h" +#if LV_USE_GRID + +/********************* + * DEFINES + *********************/ +/** + * Can be used track size to make the track fill the free space. + * @param x how much space to take proportionally to other FR tracks + * @return a special track size + */ +#define LV_GRID_FR(x) (LV_COORD_MAX - 100 + x) + +#define LV_GRID_CONTENT (LV_COORD_MAX - 101) +LV_EXPORT_CONST_INT(LV_GRID_CONTENT); + +#define LV_GRID_TEMPLATE_LAST (LV_COORD_MAX) +LV_EXPORT_CONST_INT(LV_GRID_TEMPLATE_LAST); + +/********************** + * TYPEDEFS + **********************/ + +/*Can't include lv_obj.h because it includes this header file*/ +struct _lv_obj_t; + +typedef enum { + LV_GRID_ALIGN_START, + LV_GRID_ALIGN_CENTER, + LV_GRID_ALIGN_END, + LV_GRID_ALIGN_STRETCH, + LV_GRID_ALIGN_SPACE_EVENLY, + LV_GRID_ALIGN_SPACE_AROUND, + LV_GRID_ALIGN_SPACE_BETWEEN, +} lv_grid_align_t; + +/********************** + * GLOBAL VARIABLES + **********************/ + +extern uint32_t LV_LAYOUT_GRID; +extern lv_style_prop_t LV_STYLE_GRID_COLUMN_DSC_ARRAY; +extern lv_style_prop_t LV_STYLE_GRID_COLUMN_ALIGN; +extern lv_style_prop_t LV_STYLE_GRID_ROW_DSC_ARRAY; +extern lv_style_prop_t LV_STYLE_GRID_ROW_ALIGN; +extern lv_style_prop_t LV_STYLE_GRID_CELL_COLUMN_POS; +extern lv_style_prop_t LV_STYLE_GRID_CELL_COLUMN_SPAN; +extern lv_style_prop_t LV_STYLE_GRID_CELL_X_ALIGN; +extern lv_style_prop_t LV_STYLE_GRID_CELL_ROW_POS; +extern lv_style_prop_t LV_STYLE_GRID_CELL_ROW_SPAN; +extern lv_style_prop_t LV_STYLE_GRID_CELL_Y_ALIGN; + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +void lv_grid_init(void); + +void lv_obj_set_grid_dsc_array(lv_obj_t * obj, const lv_coord_t col_dsc[], const lv_coord_t row_dsc[]); + +void lv_obj_set_grid_align(lv_obj_t * obj, lv_grid_align_t column_align, lv_grid_align_t row_align); + +/** + * Set the cell of an object. The object's parent needs to have grid layout, else nothing will happen + * @param obj pointer to an object + * @param column_align the vertical alignment in the cell. `LV_GRID_START/END/CENTER/STRETCH` + * @param col_pos column ID + * @param col_span number of columns to take (>= 1) + * @param row_align the horizontal alignment in the cell. `LV_GRID_START/END/CENTER/STRETCH` + * @param row_pos row ID + * @param row_span number of rows to take (>= 1) + */ +void lv_obj_set_grid_cell(lv_obj_t * obj, lv_grid_align_t column_align, uint8_t col_pos, uint8_t col_span, + lv_grid_align_t row_align, uint8_t row_pos, uint8_t row_span); + +/** + * Just a wrapper to `LV_GRID_FR` for bindings. + */ +static inline lv_coord_t lv_grid_fr(uint8_t x) +{ + return LV_GRID_FR(x); +} + +void lv_style_set_grid_row_dsc_array(lv_style_t * style, const lv_coord_t value[]); +void lv_style_set_grid_column_dsc_array(lv_style_t * style, const lv_coord_t value[]); +void lv_style_set_grid_row_align(lv_style_t * style, lv_grid_align_t value); +void lv_style_set_grid_column_align(lv_style_t * style, lv_grid_align_t value); +void lv_style_set_grid_cell_column_pos(lv_style_t * style, lv_coord_t value); +void lv_style_set_grid_cell_column_span(lv_style_t * style, lv_coord_t value); +void lv_style_set_grid_cell_row_pos(lv_style_t * style, lv_coord_t value); +void lv_style_set_grid_cell_row_span(lv_style_t * style, lv_coord_t value); +void lv_style_set_grid_cell_x_align(lv_style_t * style, lv_coord_t value); +void lv_style_set_grid_cell_y_align(lv_style_t * style, lv_coord_t value); + +void lv_obj_set_style_grid_row_dsc_array(lv_obj_t * obj, const lv_coord_t value[], lv_style_selector_t selector); +void lv_obj_set_style_grid_column_dsc_array(lv_obj_t * obj, const lv_coord_t value[], lv_style_selector_t selector); +void lv_obj_set_style_grid_row_align(lv_obj_t * obj, lv_grid_align_t value, lv_style_selector_t selector); +void lv_obj_set_style_grid_column_align(lv_obj_t * obj, lv_grid_align_t value, lv_style_selector_t selector); +void lv_obj_set_style_grid_cell_column_pos(lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector); +void lv_obj_set_style_grid_cell_column_span(lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector); +void lv_obj_set_style_grid_cell_row_pos(lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector); +void lv_obj_set_style_grid_cell_row_span(lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector); +void lv_obj_set_style_grid_cell_x_align(lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector); +void lv_obj_set_style_grid_cell_y_align(lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector); + +static inline const lv_coord_t * lv_obj_get_style_grid_row_dsc_array(const lv_obj_t * obj, uint32_t part) +{ + lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_GRID_ROW_DSC_ARRAY); + return (const lv_coord_t *)v.ptr; +} + +static inline const lv_coord_t * lv_obj_get_style_grid_column_dsc_array(const lv_obj_t * obj, uint32_t part) +{ + lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_GRID_COLUMN_DSC_ARRAY); + return (const lv_coord_t *)v.ptr; +} + +static inline lv_grid_align_t lv_obj_get_style_grid_row_align(const lv_obj_t * obj, uint32_t part) +{ + lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_GRID_ROW_ALIGN); + return (lv_grid_align_t)v.num; +} + +static inline lv_grid_align_t lv_obj_get_style_grid_column_align(const lv_obj_t * obj, uint32_t part) +{ + lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_GRID_COLUMN_ALIGN); + return (lv_grid_align_t)v.num; +} + +static inline lv_coord_t lv_obj_get_style_grid_cell_column_pos(const lv_obj_t * obj, uint32_t part) +{ + lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_GRID_CELL_COLUMN_POS); + return (lv_coord_t)v.num; +} + +static inline lv_coord_t lv_obj_get_style_grid_cell_column_span(const lv_obj_t * obj, uint32_t part) +{ + lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_GRID_CELL_COLUMN_SPAN); + return (lv_coord_t)v.num; +} + +static inline lv_coord_t lv_obj_get_style_grid_cell_row_pos(const lv_obj_t * obj, uint32_t part) +{ + lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_GRID_CELL_ROW_POS); + return (lv_coord_t)v.num; +} + +static inline lv_coord_t lv_obj_get_style_grid_cell_row_span(const lv_obj_t * obj, uint32_t part) +{ + lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_GRID_CELL_ROW_SPAN); + return (lv_coord_t)v.num; +} + +static inline lv_coord_t lv_obj_get_style_grid_cell_x_align(const lv_obj_t * obj, uint32_t part) +{ + lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_GRID_CELL_X_ALIGN); + return (lv_coord_t)v.num; +} + +static inline lv_coord_t lv_obj_get_style_grid_cell_y_align(const lv_obj_t * obj, uint32_t part) +{ + lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_GRID_CELL_Y_ALIGN); + return (lv_coord_t)v.num; +} + +/********************** + * GLOBAL VARIABLES + **********************/ + +/********************** + * MACROS + **********************/ +#endif /*LV_USE_GRID*/ + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif /*LV_GRID_H*/ diff --git a/src/lib/lvgl/src/extra/layouts/lv_layouts.h b/src/lib/lvgl/src/extra/layouts/lv_layouts.h new file mode 100644 index 0000000..9c1e958 --- /dev/null +++ b/src/lib/lvgl/src/extra/layouts/lv_layouts.h @@ -0,0 +1,44 @@ +/** + * @file lv_layouts.h + * + */ + +#ifndef LV_LAYOUTS_H +#define LV_LAYOUTS_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include "flex/lv_flex.h" +#include "grid/lv_grid.h" + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +/********************** + * MACROS + **********************/ +#if LV_USE_LOG && LV_LOG_TRACE_LAYOUT +# define LV_TRACE_LAYOUT(...) LV_LOG_TRACE(__VA_ARGS__) +#else +# define LV_TRACE_LAYOUT(...) +#endif + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif /*LV_LAYOUTS_H*/ diff --git a/src/lib/lvgl/src/extra/libs/bmp/lv_bmp.h b/src/lib/lvgl/src/extra/libs/bmp/lv_bmp.h new file mode 100644 index 0000000..db1e540 --- /dev/null +++ b/src/lib/lvgl/src/extra/libs/bmp/lv_bmp.h @@ -0,0 +1,42 @@ +/** + * @file lv_bmp.h + * + */ + +#ifndef LV_BMP_H +#define LV_BMP_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include "../../../lv_conf_internal.h" +#if LV_USE_BMP + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * GLOBAL PROTOTYPES + **********************/ +void lv_bmp_init(void); + +/********************** + * MACROS + **********************/ + +#endif /*LV_USE_BMP*/ + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /*LV_BMP_H*/ diff --git a/src/lib/lvgl/src/extra/libs/ffmpeg/lv_ffmpeg.h b/src/lib/lvgl/src/extra/libs/ffmpeg/lv_ffmpeg.h new file mode 100644 index 0000000..8c7fc26 --- /dev/null +++ b/src/lib/lvgl/src/extra/libs/ffmpeg/lv_ffmpeg.h @@ -0,0 +1,104 @@ +/** + * @file lv_ffmpeg.h + * + */ +#ifndef LV_FFMPEG_H +#define LV_FFMPEG_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include "../../../lvgl.h" +#if LV_USE_FFMPEG != 0 + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ +struct ffmpeg_context_s; + +extern const lv_obj_class_t lv_ffmpeg_player_class; + +typedef struct { + lv_img_t img; + lv_timer_t * timer; + lv_img_dsc_t imgdsc; + bool auto_restart; + struct ffmpeg_context_s * ffmpeg_ctx; +} lv_ffmpeg_player_t; + +typedef enum { + LV_FFMPEG_PLAYER_CMD_START, + LV_FFMPEG_PLAYER_CMD_STOP, + LV_FFMPEG_PLAYER_CMD_PAUSE, + LV_FFMPEG_PLAYER_CMD_RESUME, + _LV_FFMPEG_PLAYER_CMD_LAST +} lv_ffmpeg_player_cmd_t; + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +/** + * Register FFMPEG image decoder + */ +void lv_ffmpeg_init(void); + +/** + * Get the number of frames contained in the file + * @param path image or video file name + * @return Number of frames, less than 0 means failed + */ +int lv_ffmpeg_get_frame_num(const char * path); + +/** + * Create ffmpeg_player object + * @param parent pointer to an object, it will be the parent of the new player + * @return pointer to the created ffmpeg_player + */ +lv_obj_t * lv_ffmpeg_player_create(lv_obj_t * parent); + +/** + * Set the path of the file to be played + * @param obj pointer to a ffmpeg_player object + * @param path video file path + * @return LV_RES_OK: no error; LV_RES_INV: can't get the info. + */ +lv_res_t lv_ffmpeg_player_set_src(lv_obj_t * obj, const char * path); + +/** + * Set command control video player + * @param obj pointer to a ffmpeg_player object + * @param cmd control commands + */ +void lv_ffmpeg_player_set_cmd(lv_obj_t * obj, lv_ffmpeg_player_cmd_t cmd); + +/** + * Set the video to automatically replay + * @param obj pointer to a ffmpeg_player object + * @param en true: enable the auto restart + */ +void lv_ffmpeg_player_set_auto_restart(lv_obj_t * obj, bool en); + +/*===================== + * Other functions + *====================*/ + +/********************** + * MACROS + **********************/ + +#endif /*LV_USE_FFMPEG*/ + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif /*LV_FFMPEG_H*/ diff --git a/src/lib/lvgl/src/extra/libs/freetype/lv_freetype.h b/src/lib/lvgl/src/extra/libs/freetype/lv_freetype.h new file mode 100644 index 0000000..247a7fb --- /dev/null +++ b/src/lib/lvgl/src/extra/libs/freetype/lv_freetype.h @@ -0,0 +1,83 @@ +/** + * @file lv_freetype.h + * + */ +#ifndef LV_FREETYPE_H +#define LV_FREETYPE_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include "../../../lvgl.h" +#if LV_USE_FREETYPE + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ +typedef enum { + FT_FONT_STYLE_NORMAL = 0, + FT_FONT_STYLE_ITALIC = 1 << 0, + FT_FONT_STYLE_BOLD = 1 << 1 +} LV_FT_FONT_STYLE; + +typedef struct { + const char * name; /* The name of the font file */ + const void * mem; /* The pointer of the font file */ + size_t mem_size; /* The size of the memory */ + lv_font_t * font; /* point to lvgl font */ + uint16_t weight; /* font size */ + uint16_t style; /* font style */ +} lv_ft_info_t; + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +/** + * init freetype library + * @param max_faces Maximum number of opened FT_Face objects managed by this cache instance. Use 0 for defaults. + * @param max_sizes Maximum number of opened FT_Size objects managed by this cache instance. Use 0 for defaults. + * @param max_bytes Maximum number of bytes to use for cached data nodes. Use 0 for defaults. + * Note that this value does not account for managed FT_Face and FT_Size objects. + * @return true on success, otherwise false. + */ +bool lv_freetype_init(uint16_t max_faces, uint16_t max_sizes, uint32_t max_bytes); + +/** + * Destroy freetype library + */ +void lv_freetype_destroy(void); + +/** + * Creates a font with info parameter specified. + * @param info See lv_ft_info_t for details. + * when success, lv_ft_info_t->font point to the font you created. + * @return true on success, otherwise false. + */ +bool lv_ft_font_init(lv_ft_info_t * info); + +/** + * Destroy a font that has been created. + * @param font pointer to font. + */ +void lv_ft_font_destroy(lv_font_t * font); + +/********************** + * MACROS + **********************/ + +#endif /*LV_USE_FREETYPE*/ + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* LV_FREETYPE_H */ diff --git a/src/lib/lvgl/src/extra/libs/fsdrv/lv_fsdrv.h b/src/lib/lvgl/src/extra/libs/fsdrv/lv_fsdrv.h new file mode 100644 index 0000000..285d598 --- /dev/null +++ b/src/lib/lvgl/src/extra/libs/fsdrv/lv_fsdrv.h @@ -0,0 +1,55 @@ +/** + * @file lv_fsdrv.h + * + */ + +#ifndef LV_FSDRV_H +#define LV_FSDRV_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include "../../../lv_conf_internal.h" + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +#if LV_USE_FS_FATFS != '\0' +void lv_fs_fatfs_init(void); +#endif + +#if LV_USE_FS_STDIO != '\0' +void lv_fs_stdio_init(void); +#endif + +#if LV_USE_FS_POSIX != '\0' +void lv_fs_posix_init(void); +#endif + +#if LV_USE_FS_WIN32 != '\0' +void lv_fs_win32_init(void); +#endif + +/********************** + * MACROS + **********************/ + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /*LV_FSDRV_H*/ + diff --git a/src/lib/lvgl/src/extra/libs/gif/gifdec.h b/src/lib/lvgl/src/extra/libs/gif/gifdec.h new file mode 100644 index 0000000..00f17c1 --- /dev/null +++ b/src/lib/lvgl/src/extra/libs/gif/gifdec.h @@ -0,0 +1,60 @@ +#ifndef GIFDEC_H +#define GIFDEC_H + +#include +#include "../../../misc/lv_fs.h" + +#if LV_USE_GIF + +typedef struct gd_Palette { + int size; + uint8_t colors[0x100 * 3]; +} gd_Palette; + +typedef struct gd_GCE { + uint16_t delay; + uint8_t tindex; + uint8_t disposal; + int input; + int transparency; +} gd_GCE; + + + +typedef struct gd_GIF { + lv_fs_file_t fd; + const char * data; + uint8_t is_file; + uint32_t f_rw_p; + int32_t anim_start; + uint16_t width, height; + uint16_t depth; + uint16_t loop_count; + gd_GCE gce; + gd_Palette *palette; + gd_Palette lct, gct; + void (*plain_text)( + struct gd_GIF *gif, uint16_t tx, uint16_t ty, + uint16_t tw, uint16_t th, uint8_t cw, uint8_t ch, + uint8_t fg, uint8_t bg + ); + void (*comment)(struct gd_GIF *gif); + void (*application)(struct gd_GIF *gif, char id[8], char auth[3]); + uint16_t fx, fy, fw, fh; + uint8_t bgindex; + uint8_t *canvas, *frame; +} gd_GIF; + +gd_GIF * gd_open_gif_file(const char *fname); + +gd_GIF * gd_open_gif_data(const void *data); + +void gd_render_frame(gd_GIF *gif, uint8_t *buffer); + +int gd_get_frame(gd_GIF *gif); +void gd_rewind(gd_GIF *gif); +void gd_close_gif(gd_GIF *gif); + +#endif /*LV_USE_GIF*/ + +#endif /* GIFDEC_H */ diff --git a/src/lib/lvgl/src/extra/libs/gif/lv_gif.h b/src/lib/lvgl/src/extra/libs/gif/lv_gif.h new file mode 100644 index 0000000..d8c93db --- /dev/null +++ b/src/lib/lvgl/src/extra/libs/gif/lv_gif.h @@ -0,0 +1,58 @@ +/** + * @file lv_gif.h + * + */ + +#ifndef LV_GIF_H +#define LV_GIF_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ + +#include "../../../lvgl.h" +#if LV_USE_GIF + +#include "gifdec.h" + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +typedef struct { + lv_img_t img; + gd_GIF * gif; + lv_timer_t * timer; + lv_img_dsc_t imgdsc; + uint32_t last_call; +} lv_gif_t; + +extern const lv_obj_class_t lv_gif_class; + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +lv_obj_t * lv_gif_create(lv_obj_t * parent); +void lv_gif_set_src(lv_obj_t * obj, const void * src); +void lv_gif_restart(lv_obj_t * gif); + +/********************** + * MACROS + **********************/ + +#endif /*LV_USE_GIF*/ + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /*LV_GIF_H*/ diff --git a/src/lib/lvgl/src/extra/libs/lv_libs.h b/src/lib/lvgl/src/extra/libs/lv_libs.h new file mode 100644 index 0000000..6782b1d --- /dev/null +++ b/src/lib/lvgl/src/extra/libs/lv_libs.h @@ -0,0 +1,46 @@ +/** + * @file lv_libs.h + * + */ + +#ifndef LV_LIBS_H +#define LV_LIBS_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include "bmp/lv_bmp.h" +#include "fsdrv/lv_fsdrv.h" +#include "png/lv_png.h" +#include "gif/lv_gif.h" +#include "qrcode/lv_qrcode.h" +#include "sjpg/lv_sjpg.h" +#include "freetype/lv_freetype.h" +#include "rlottie/lv_rlottie.h" +#include "ffmpeg/lv_ffmpeg.h" + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +/********************** + * MACROS + **********************/ + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif /*LV_LIBS_H*/ diff --git a/src/lib/lvgl/src/extra/libs/png/lodepng.h b/src/lib/lvgl/src/extra/libs/png/lodepng.h new file mode 100644 index 0000000..dbfed72 --- /dev/null +++ b/src/lib/lvgl/src/extra/libs/png/lodepng.h @@ -0,0 +1,1981 @@ +/* +LodePNG version 20201017 + +Copyright (c) 2005-2020 Lode Vandevenne + +This software is provided 'as-is', without any express or implied +warranty. In no event will the authors be held liable for any damages +arising from the use of this software. + +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it +freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + + 3. This notice may not be removed or altered from any source + distribution. +*/ + +#ifndef LODEPNG_H +#define LODEPNG_H + +#include /*for size_t*/ + +#include "../../../lvgl.h" +#if LV_USE_PNG +extern const char* LODEPNG_VERSION_STRING; + +/* +The following #defines are used to create code sections. They can be disabled +to disable code sections, which can give faster compile time and smaller binary. +The "NO_COMPILE" defines are designed to be used to pass as defines to the +compiler command to disable them without modifying this header, e.g. +-DLODEPNG_NO_COMPILE_ZLIB for gcc. +In addition to those below, you can also define LODEPNG_NO_COMPILE_CRC to +allow implementing a custom lodepng_crc32. +*/ +/*deflate & zlib. If disabled, you must specify alternative zlib functions in +the custom_zlib field of the compress and decompress settings*/ +#ifndef LODEPNG_NO_COMPILE_ZLIB +#define LODEPNG_COMPILE_ZLIB +#endif + +/*png encoder and png decoder*/ +#ifndef LODEPNG_NO_COMPILE_PNG +#define LODEPNG_COMPILE_PNG +#endif + +/*deflate&zlib decoder and png decoder*/ +#ifndef LODEPNG_NO_COMPILE_DECODER +#define LODEPNG_COMPILE_DECODER +#endif + +/*deflate&zlib encoder and png encoder*/ +#ifndef LODEPNG_NO_COMPILE_ENCODER +#define LODEPNG_COMPILE_ENCODER +#endif + +/*the optional built in harddisk file loading and saving functions*/ +#ifndef LODEPNG_NO_COMPILE_DISK +#define LODEPNG_COMPILE_DISK +#endif + +/*support for chunks other than IHDR, IDAT, PLTE, tRNS, IEND: ancillary and unknown chunks*/ +#ifndef LODEPNG_NO_COMPILE_ANCILLARY_CHUNKS +#define LODEPNG_COMPILE_ANCILLARY_CHUNKS +#endif + +/*ability to convert error numerical codes to English text string*/ +#ifndef LODEPNG_NO_COMPILE_ERROR_TEXT +#define LODEPNG_COMPILE_ERROR_TEXT +#endif + +/*Compile the default allocators (C's free, malloc and realloc). If you disable this, +you can define the functions lodepng_free, lodepng_malloc and lodepng_realloc in your +source files with custom allocators.*/ +#ifndef LODEPNG_NO_COMPILE_ALLOCATORS +#define LODEPNG_COMPILE_ALLOCATORS +#endif + +/*compile the C++ version (you can disable the C++ wrapper here even when compiling for C++)*/ +#ifdef __cplusplus +#ifndef LODEPNG_NO_COMPILE_CPP +#define LODEPNG_COMPILE_CPP +#endif +#endif + +#ifdef LODEPNG_COMPILE_CPP +#include +#include +#endif /*LODEPNG_COMPILE_CPP*/ + +#ifdef LODEPNG_COMPILE_PNG +/*The PNG color types (also used for raw image).*/ +typedef enum LodePNGColorType { + LCT_GREY = 0, /*grayscale: 1,2,4,8,16 bit*/ + LCT_RGB = 2, /*RGB: 8,16 bit*/ + LCT_PALETTE = 3, /*palette: 1,2,4,8 bit*/ + LCT_GREY_ALPHA = 4, /*grayscale with alpha: 8,16 bit*/ + LCT_RGBA = 6, /*RGB with alpha: 8,16 bit*/ + /*LCT_MAX_OCTET_VALUE lets the compiler allow this enum to represent any invalid + byte value from 0 to 255 that could be present in an invalid PNG file header. Do + not use, compare with or set the name LCT_MAX_OCTET_VALUE, instead either use + the valid color type names above, or numeric values like 1 or 7 when checking for + particular disallowed color type byte values, or cast to integer to print it.*/ + LCT_MAX_OCTET_VALUE = 255 +} LodePNGColorType; + +#ifdef LODEPNG_COMPILE_DECODER +/* +Converts PNG data in memory to raw pixel data. +out: Output parameter. Pointer to buffer that will contain the raw pixel data. + After decoding, its size is w * h * (bytes per pixel) bytes larger than + initially. Bytes per pixel depends on colortype and bitdepth. + Must be freed after usage with free(*out). + Note: for 16-bit per channel colors, uses big endian format like PNG does. +w: Output parameter. Pointer to width of pixel data. +h: Output parameter. Pointer to height of pixel data. +in: Memory buffer with the PNG file. +insize: size of the in buffer. +colortype: the desired color type for the raw output image. See explanation on PNG color types. +bitdepth: the desired bit depth for the raw output image. See explanation on PNG color types. +Return value: LodePNG error code (0 means no error). +*/ +unsigned lodepng_decode_memory(unsigned char** out, unsigned* w, unsigned* h, + const unsigned char* in, size_t insize, + LodePNGColorType colortype, unsigned bitdepth); + +/*Same as lodepng_decode_memory, but always decodes to 32-bit RGBA raw image*/ +unsigned lodepng_decode32(unsigned char** out, unsigned* w, unsigned* h, + const unsigned char* in, size_t insize); + +/*Same as lodepng_decode_memory, but always decodes to 24-bit RGB raw image*/ +unsigned lodepng_decode24(unsigned char** out, unsigned* w, unsigned* h, + const unsigned char* in, size_t insize); + +#ifdef LODEPNG_COMPILE_DISK +/* +Load PNG from disk, from file with given name. +Same as the other decode functions, but instead takes a filename as input. +*/ +unsigned lodepng_decode_file(unsigned char** out, unsigned* w, unsigned* h, + const char* filename, + LodePNGColorType colortype, unsigned bitdepth); + +/*Same as lodepng_decode_file, but always decodes to 32-bit RGBA raw image.*/ +unsigned lodepng_decode32_file(unsigned char** out, unsigned* w, unsigned* h, + const char* filename); + +/*Same as lodepng_decode_file, but always decodes to 24-bit RGB raw image.*/ +unsigned lodepng_decode24_file(unsigned char** out, unsigned* w, unsigned* h, + const char* filename); +#endif /*LODEPNG_COMPILE_DISK*/ +#endif /*LODEPNG_COMPILE_DECODER*/ + + +#ifdef LODEPNG_COMPILE_ENCODER +/* +Converts raw pixel data into a PNG image in memory. The colortype and bitdepth + of the output PNG image cannot be chosen, they are automatically determined + by the colortype, bitdepth and content of the input pixel data. + Note: for 16-bit per channel colors, needs big endian format like PNG does. +out: Output parameter. Pointer to buffer that will contain the PNG image data. + Must be freed after usage with free(*out). +outsize: Output parameter. Pointer to the size in bytes of the out buffer. +image: The raw pixel data to encode. The size of this buffer should be + w * h * (bytes per pixel), bytes per pixel depends on colortype and bitdepth. +w: width of the raw pixel data in pixels. +h: height of the raw pixel data in pixels. +colortype: the color type of the raw input image. See explanation on PNG color types. +bitdepth: the bit depth of the raw input image. See explanation on PNG color types. +Return value: LodePNG error code (0 means no error). +*/ +unsigned lodepng_encode_memory(unsigned char** out, size_t* outsize, + const unsigned char* image, unsigned w, unsigned h, + LodePNGColorType colortype, unsigned bitdepth); + +/*Same as lodepng_encode_memory, but always encodes from 32-bit RGBA raw image.*/ +unsigned lodepng_encode32(unsigned char** out, size_t* outsize, + const unsigned char* image, unsigned w, unsigned h); + +/*Same as lodepng_encode_memory, but always encodes from 24-bit RGB raw image.*/ +unsigned lodepng_encode24(unsigned char** out, size_t* outsize, + const unsigned char* image, unsigned w, unsigned h); + +#ifdef LODEPNG_COMPILE_DISK +/* +Converts raw pixel data into a PNG file on disk. +Same as the other encode functions, but instead takes a filename as output. +NOTE: This overwrites existing files without warning! +*/ +unsigned lodepng_encode_file(const char* filename, + const unsigned char* image, unsigned w, unsigned h, + LodePNGColorType colortype, unsigned bitdepth); + +/*Same as lodepng_encode_file, but always encodes from 32-bit RGBA raw image.*/ +unsigned lodepng_encode32_file(const char* filename, + const unsigned char* image, unsigned w, unsigned h); + +/*Same as lodepng_encode_file, but always encodes from 24-bit RGB raw image.*/ +unsigned lodepng_encode24_file(const char* filename, + const unsigned char* image, unsigned w, unsigned h); +#endif /*LODEPNG_COMPILE_DISK*/ +#endif /*LODEPNG_COMPILE_ENCODER*/ + + +#ifdef LODEPNG_COMPILE_CPP +namespace lodepng { +#ifdef LODEPNG_COMPILE_DECODER +/*Same as lodepng_decode_memory, but decodes to an std::vector. The colortype +is the format to output the pixels to. Default is RGBA 8-bit per channel.*/ +unsigned decode(std::vector& out, unsigned& w, unsigned& h, + const unsigned char* in, size_t insize, + LodePNGColorType colortype = LCT_RGBA, unsigned bitdepth = 8); +unsigned decode(std::vector& out, unsigned& w, unsigned& h, + const std::vector& in, + LodePNGColorType colortype = LCT_RGBA, unsigned bitdepth = 8); +#ifdef LODEPNG_COMPILE_DISK +/* +Converts PNG file from disk to raw pixel data in memory. +Same as the other decode functions, but instead takes a filename as input. +*/ +unsigned decode(std::vector& out, unsigned& w, unsigned& h, + const std::string& filename, + LodePNGColorType colortype = LCT_RGBA, unsigned bitdepth = 8); +#endif /* LODEPNG_COMPILE_DISK */ +#endif /* LODEPNG_COMPILE_DECODER */ + +#ifdef LODEPNG_COMPILE_ENCODER +/*Same as lodepng_encode_memory, but encodes to an std::vector. colortype +is that of the raw input data. The output PNG color type will be auto chosen.*/ +unsigned encode(std::vector& out, + const unsigned char* in, unsigned w, unsigned h, + LodePNGColorType colortype = LCT_RGBA, unsigned bitdepth = 8); +unsigned encode(std::vector& out, + const std::vector& in, unsigned w, unsigned h, + LodePNGColorType colortype = LCT_RGBA, unsigned bitdepth = 8); +#ifdef LODEPNG_COMPILE_DISK +/* +Converts 32-bit RGBA raw pixel data into a PNG file on disk. +Same as the other encode functions, but instead takes a filename as output. +NOTE: This overwrites existing files without warning! +*/ +unsigned encode(const std::string& filename, + const unsigned char* in, unsigned w, unsigned h, + LodePNGColorType colortype = LCT_RGBA, unsigned bitdepth = 8); +unsigned encode(const std::string& filename, + const std::vector& in, unsigned w, unsigned h, + LodePNGColorType colortype = LCT_RGBA, unsigned bitdepth = 8); +#endif /* LODEPNG_COMPILE_DISK */ +#endif /* LODEPNG_COMPILE_ENCODER */ +} /* namespace lodepng */ +#endif /*LODEPNG_COMPILE_CPP*/ +#endif /*LODEPNG_COMPILE_PNG*/ + +#ifdef LODEPNG_COMPILE_ERROR_TEXT +/*Returns an English description of the numerical error code.*/ +const char* lodepng_error_text(unsigned code); +#endif /*LODEPNG_COMPILE_ERROR_TEXT*/ + +#ifdef LODEPNG_COMPILE_DECODER +/*Settings for zlib decompression*/ +typedef struct LodePNGDecompressSettings LodePNGDecompressSettings; +struct LodePNGDecompressSettings { + /* Check LodePNGDecoderSettings for more ignorable errors such as ignore_crc */ + unsigned ignore_adler32; /*if 1, continue and don't give an error message if the Adler32 checksum is corrupted*/ + unsigned ignore_nlen; /*ignore complement of len checksum in uncompressed blocks*/ + + /*Maximum decompressed size, beyond this the decoder may (and is encouraged to) stop decoding, + return an error, output a data size > max_output_size and all the data up to that point. This is + not hard limit nor a guarantee, but can prevent excessive memory usage. This setting is + ignored by the PNG decoder, but is used by the deflate/zlib decoder and can be used by custom ones. + Set to 0 to impose no limit (the default).*/ + size_t max_output_size; + + /*use custom zlib decoder instead of built in one (default: null). + Should return 0 if success, any non-0 if error (numeric value not exposed).*/ + unsigned (*custom_zlib)(unsigned char**, size_t*, + const unsigned char*, size_t, + const LodePNGDecompressSettings*); + /*use custom deflate decoder instead of built in one (default: null) + if custom_zlib is not null, custom_inflate is ignored (the zlib format uses deflate). + Should return 0 if success, any non-0 if error (numeric value not exposed).*/ + unsigned (*custom_inflate)(unsigned char**, size_t*, + const unsigned char*, size_t, + const LodePNGDecompressSettings*); + + const void* custom_context; /*optional custom settings for custom functions*/ +}; + +extern const LodePNGDecompressSettings lodepng_default_decompress_settings; +void lodepng_decompress_settings_init(LodePNGDecompressSettings* settings); +#endif /*LODEPNG_COMPILE_DECODER*/ + +#ifdef LODEPNG_COMPILE_ENCODER +/* +Settings for zlib compression. Tweaking these settings tweaks the balance +between speed and compression ratio. +*/ +typedef struct LodePNGCompressSettings LodePNGCompressSettings; +struct LodePNGCompressSettings /*deflate = compress*/ { + /*LZ77 related settings*/ + unsigned btype; /*the block type for LZ (0, 1, 2 or 3, see zlib standard). Should be 2 for proper compression.*/ + unsigned use_lz77; /*whether or not to use LZ77. Should be 1 for proper compression.*/ + unsigned windowsize; /*must be a power of two <= 32768. higher compresses more but is slower. Default value: 2048.*/ + unsigned minmatch; /*minimum lz77 length. 3 is normally best, 6 can be better for some PNGs. Default: 0*/ + unsigned nicematch; /*stop searching if >= this length found. Set to 258 for best compression. Default: 128*/ + unsigned lazymatching; /*use lazy matching: better compression but a bit slower. Default: true*/ + + /*use custom zlib encoder instead of built in one (default: null)*/ + unsigned (*custom_zlib)(unsigned char**, size_t*, + const unsigned char*, size_t, + const LodePNGCompressSettings*); + /*use custom deflate encoder instead of built in one (default: null) + if custom_zlib is used, custom_deflate is ignored since only the built in + zlib function will call custom_deflate*/ + unsigned (*custom_deflate)(unsigned char**, size_t*, + const unsigned char*, size_t, + const LodePNGCompressSettings*); + + const void* custom_context; /*optional custom settings for custom functions*/ +}; + +extern const LodePNGCompressSettings lodepng_default_compress_settings; +void lodepng_compress_settings_init(LodePNGCompressSettings* settings); +#endif /*LODEPNG_COMPILE_ENCODER*/ + +#ifdef LODEPNG_COMPILE_PNG +/* +Color mode of an image. Contains all information required to decode the pixel +bits to RGBA colors. This information is the same as used in the PNG file +format, and is used both for PNG and raw image data in LodePNG. +*/ +typedef struct LodePNGColorMode { + /*header (IHDR)*/ + LodePNGColorType colortype; /*color type, see PNG standard or documentation further in this header file*/ + unsigned bitdepth; /*bits per sample, see PNG standard or documentation further in this header file*/ + + /* + palette (PLTE and tRNS) + + Dynamically allocated with the colors of the palette, including alpha. + This field may not be allocated directly, use lodepng_color_mode_init first, + then lodepng_palette_add per color to correctly initialize it (to ensure size + of exactly 1024 bytes). + + The alpha channels must be set as well, set them to 255 for opaque images. + + When decoding, by default you can ignore this palette, since LodePNG already + fills the palette colors in the pixels of the raw RGBA output. + + The palette is only supported for color type 3. + */ + unsigned char* palette; /*palette in RGBARGBA... order. Must be either 0, or when allocated must have 1024 bytes*/ + size_t palettesize; /*palette size in number of colors (amount of used bytes is 4 * palettesize)*/ + + /* + transparent color key (tRNS) + + This color uses the same bit depth as the bitdepth value in this struct, which can be 1-bit to 16-bit. + For grayscale PNGs, r, g and b will all 3 be set to the same. + + When decoding, by default you can ignore this information, since LodePNG sets + pixels with this key to transparent already in the raw RGBA output. + + The color key is only supported for color types 0 and 2. + */ + unsigned key_defined; /*is a transparent color key given? 0 = false, 1 = true*/ + unsigned key_r; /*red/grayscale component of color key*/ + unsigned key_g; /*green component of color key*/ + unsigned key_b; /*blue component of color key*/ +} LodePNGColorMode; + +/*init, cleanup and copy functions to use with this struct*/ +void lodepng_color_mode_init(LodePNGColorMode* info); +void lodepng_color_mode_cleanup(LodePNGColorMode* info); +/*return value is error code (0 means no error)*/ +unsigned lodepng_color_mode_copy(LodePNGColorMode* dest, const LodePNGColorMode* source); +/* Makes a temporary LodePNGColorMode that does not need cleanup (no palette) */ +LodePNGColorMode lodepng_color_mode_make(LodePNGColorType colortype, unsigned bitdepth); + +void lodepng_palette_clear(LodePNGColorMode* info); +/*add 1 color to the palette*/ +unsigned lodepng_palette_add(LodePNGColorMode* info, + unsigned char r, unsigned char g, unsigned char b, unsigned char a); + +/*get the total amount of bits per pixel, based on colortype and bitdepth in the struct*/ +unsigned lodepng_get_bpp(const LodePNGColorMode* info); +/*get the amount of color channels used, based on colortype in the struct. +If a palette is used, it counts as 1 channel.*/ +unsigned lodepng_get_channels(const LodePNGColorMode* info); +/*is it a grayscale type? (only colortype 0 or 4)*/ +unsigned lodepng_is_greyscale_type(const LodePNGColorMode* info); +/*has it got an alpha channel? (only colortype 2 or 6)*/ +unsigned lodepng_is_alpha_type(const LodePNGColorMode* info); +/*has it got a palette? (only colortype 3)*/ +unsigned lodepng_is_palette_type(const LodePNGColorMode* info); +/*only returns true if there is a palette and there is a value in the palette with alpha < 255. +Loops through the palette to check this.*/ +unsigned lodepng_has_palette_alpha(const LodePNGColorMode* info); +/* +Check if the given color info indicates the possibility of having non-opaque pixels in the PNG image. +Returns true if the image can have translucent or invisible pixels (it still be opaque if it doesn't use such pixels). +Returns false if the image can only have opaque pixels. +In detail, it returns true only if it's a color type with alpha, or has a palette with non-opaque values, +or if "key_defined" is true. +*/ +unsigned lodepng_can_have_alpha(const LodePNGColorMode* info); +/*Returns the byte size of a raw image buffer with given width, height and color mode*/ +size_t lodepng_get_raw_size(unsigned w, unsigned h, const LodePNGColorMode* color); + +#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS +/*The information of a Time chunk in PNG.*/ +typedef struct LodePNGTime { + unsigned year; /*2 bytes used (0-65535)*/ + unsigned month; /*1-12*/ + unsigned day; /*1-31*/ + unsigned hour; /*0-23*/ + unsigned minute; /*0-59*/ + unsigned second; /*0-60 (to allow for leap seconds)*/ +} LodePNGTime; +#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ + +/*Information about the PNG image, except pixels, width and height.*/ +typedef struct LodePNGInfo { + /*header (IHDR), palette (PLTE) and transparency (tRNS) chunks*/ + unsigned compression_method;/*compression method of the original file. Always 0.*/ + unsigned filter_method; /*filter method of the original file*/ + unsigned interlace_method; /*interlace method of the original file: 0=none, 1=Adam7*/ + LodePNGColorMode color; /*color type and bits, palette and transparency of the PNG file*/ + +#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS + /* + Suggested background color chunk (bKGD) + + This uses the same color mode and bit depth as the PNG (except no alpha channel), + with values truncated to the bit depth in the unsigned integer. + + For grayscale and palette PNGs, the value is stored in background_r. The values + in background_g and background_b are then unused. + + So when decoding, you may get these in a different color mode than the one you requested + for the raw pixels. + + When encoding with auto_convert, you must use the color model defined in info_png.color for + these values. The encoder normally ignores info_png.color when auto_convert is on, but will + use it to interpret these values (and convert copies of them to its chosen color model). + + When encoding, avoid setting this to an expensive color, such as a non-gray value + when the image is gray, or the compression will be worse since it will be forced to + write the PNG with a more expensive color mode (when auto_convert is on). + + The decoder does not use this background color to edit the color of pixels. This is a + completely optional metadata feature. + */ + unsigned background_defined; /*is a suggested background color given?*/ + unsigned background_r; /*red/gray/palette component of suggested background color*/ + unsigned background_g; /*green component of suggested background color*/ + unsigned background_b; /*blue component of suggested background color*/ + + /* + Non-international text chunks (tEXt and zTXt) + + The char** arrays each contain num strings. The actual messages are in + text_strings, while text_keys are keywords that give a short description what + the actual text represents, e.g. Title, Author, Description, or anything else. + + All the string fields below including strings, keys, names and language tags are null terminated. + The PNG specification uses null characters for the keys, names and tags, and forbids null + characters to appear in the main text which is why we can use null termination everywhere here. + + A keyword is minimum 1 character and maximum 79 characters long (plus the + additional null terminator). It's discouraged to use a single line length + longer than 79 characters for texts. + + Don't allocate these text buffers yourself. Use the init/cleanup functions + correctly and use lodepng_add_text and lodepng_clear_text. + + Standard text chunk keywords and strings are encoded using Latin-1. + */ + size_t text_num; /*the amount of texts in these char** buffers (there may be more texts in itext)*/ + char** text_keys; /*the keyword of a text chunk (e.g. "Comment")*/ + char** text_strings; /*the actual text*/ + + /* + International text chunks (iTXt) + Similar to the non-international text chunks, but with additional strings + "langtags" and "transkeys", and the following text encodings are used: + keys: Latin-1, langtags: ASCII, transkeys and strings: UTF-8. + keys must be 1-79 characters (plus the additional null terminator), the other + strings are any length. + */ + size_t itext_num; /*the amount of international texts in this PNG*/ + char** itext_keys; /*the English keyword of the text chunk (e.g. "Comment")*/ + char** itext_langtags; /*language tag for this text's language, ISO/IEC 646 string, e.g. ISO 639 language tag*/ + char** itext_transkeys; /*keyword translated to the international language - UTF-8 string*/ + char** itext_strings; /*the actual international text - UTF-8 string*/ + + /*time chunk (tIME)*/ + unsigned time_defined; /*set to 1 to make the encoder generate a tIME chunk*/ + LodePNGTime time; + + /*phys chunk (pHYs)*/ + unsigned phys_defined; /*if 0, there is no pHYs chunk and the values below are undefined, if 1 else there is one*/ + unsigned phys_x; /*pixels per unit in x direction*/ + unsigned phys_y; /*pixels per unit in y direction*/ + unsigned phys_unit; /*may be 0 (unknown unit) or 1 (metre)*/ + + /* + Color profile related chunks: gAMA, cHRM, sRGB, iCPP + + LodePNG does not apply any color conversions on pixels in the encoder or decoder and does not interpret these color + profile values. It merely passes on the information. If you wish to use color profiles and convert colors, please + use these values with a color management library. + + See the PNG, ICC and sRGB specifications for more information about the meaning of these values. + */ + + /* gAMA chunk: optional, overridden by sRGB or iCCP if those are present. */ + unsigned gama_defined; /* Whether a gAMA chunk is present (0 = not present, 1 = present). */ + unsigned gama_gamma; /* Gamma exponent times 100000 */ + + /* cHRM chunk: optional, overridden by sRGB or iCCP if those are present. */ + unsigned chrm_defined; /* Whether a cHRM chunk is present (0 = not present, 1 = present). */ + unsigned chrm_white_x; /* White Point x times 100000 */ + unsigned chrm_white_y; /* White Point y times 100000 */ + unsigned chrm_red_x; /* Red x times 100000 */ + unsigned chrm_red_y; /* Red y times 100000 */ + unsigned chrm_green_x; /* Green x times 100000 */ + unsigned chrm_green_y; /* Green y times 100000 */ + unsigned chrm_blue_x; /* Blue x times 100000 */ + unsigned chrm_blue_y; /* Blue y times 100000 */ + + /* + sRGB chunk: optional. May not appear at the same time as iCCP. + If gAMA is also present gAMA must contain value 45455. + If cHRM is also present cHRM must contain respectively 31270,32900,64000,33000,30000,60000,15000,6000. + */ + unsigned srgb_defined; /* Whether an sRGB chunk is present (0 = not present, 1 = present). */ + unsigned srgb_intent; /* Rendering intent: 0=perceptual, 1=rel. colorimetric, 2=saturation, 3=abs. colorimetric */ + + /* + iCCP chunk: optional. May not appear at the same time as sRGB. + + LodePNG does not parse or use the ICC profile (except its color space header field for an edge case), a + separate library to handle the ICC data (not included in LodePNG) format is needed to use it for color + management and conversions. + + For encoding, if iCCP is present, gAMA and cHRM are recommended to be added as well with values that match the ICC + profile as closely as possible, if you wish to do this you should provide the correct values for gAMA and cHRM and + enable their '_defined' flags since LodePNG will not automatically compute them from the ICC profile. + + For encoding, the ICC profile is required by the PNG specification to be an "RGB" profile for non-gray + PNG color types and a "GRAY" profile for gray PNG color types. If you disable auto_convert, you must ensure + the ICC profile type matches your requested color type, else the encoder gives an error. If auto_convert is + enabled (the default), and the ICC profile is not a good match for the pixel data, this will result in an encoder + error if the pixel data has non-gray pixels for a GRAY profile, or a silent less-optimal compression of the pixel + data if the pixels could be encoded as grayscale but the ICC profile is RGB. + + To avoid this do not set an ICC profile in the image unless there is a good reason for it, and when doing so + make sure you compute it carefully to avoid the above problems. + */ + unsigned iccp_defined; /* Whether an iCCP chunk is present (0 = not present, 1 = present). */ + char* iccp_name; /* Null terminated string with profile name, 1-79 bytes */ + /* + The ICC profile in iccp_profile_size bytes. + Don't allocate this buffer yourself. Use the init/cleanup functions + correctly and use lodepng_set_icc and lodepng_clear_icc. + */ + unsigned char* iccp_profile; + unsigned iccp_profile_size; /* The size of iccp_profile in bytes */ + + /* End of color profile related chunks */ + + + /* + unknown chunks: chunks not known by LodePNG, passed on byte for byte. + + There are 3 buffers, one for each position in the PNG where unknown chunks can appear. + Each buffer contains all unknown chunks for that position consecutively. + The 3 positions are: + 0: between IHDR and PLTE, 1: between PLTE and IDAT, 2: between IDAT and IEND. + + For encoding, do not store critical chunks or known chunks that are enabled with a "_defined" flag + above in here, since the encoder will blindly follow this and could then encode an invalid PNG file + (such as one with two IHDR chunks or the disallowed combination of sRGB with iCCP). But do use + this if you wish to store an ancillary chunk that is not supported by LodePNG (such as sPLT or hIST), + or any non-standard PNG chunk. + + Do not allocate or traverse this data yourself. Use the chunk traversing functions declared + later, such as lodepng_chunk_next and lodepng_chunk_append, to read/write this struct. + */ + unsigned char* unknown_chunks_data[3]; + size_t unknown_chunks_size[3]; /*size in bytes of the unknown chunks, given for protection*/ +#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ +} LodePNGInfo; + +/*init, cleanup and copy functions to use with this struct*/ +void lodepng_info_init(LodePNGInfo* info); +void lodepng_info_cleanup(LodePNGInfo* info); +/*return value is error code (0 means no error)*/ +unsigned lodepng_info_copy(LodePNGInfo* dest, const LodePNGInfo* source); + +#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS +unsigned lodepng_add_text(LodePNGInfo* info, const char* key, const char* str); /*push back both texts at once*/ +void lodepng_clear_text(LodePNGInfo* info); /*use this to clear the texts again after you filled them in*/ + +unsigned lodepng_add_itext(LodePNGInfo* info, const char* key, const char* langtag, + const char* transkey, const char* str); /*push back the 4 texts of 1 chunk at once*/ +void lodepng_clear_itext(LodePNGInfo* info); /*use this to clear the itexts again after you filled them in*/ + +/*replaces if exists*/ +unsigned lodepng_set_icc(LodePNGInfo* info, const char* name, const unsigned char* profile, unsigned profile_size); +void lodepng_clear_icc(LodePNGInfo* info); /*use this to clear the texts again after you filled them in*/ +#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ + +/* +Converts raw buffer from one color type to another color type, based on +LodePNGColorMode structs to describe the input and output color type. +See the reference manual at the end of this header file to see which color conversions are supported. +return value = LodePNG error code (0 if all went ok, an error if the conversion isn't supported) +The out buffer must have size (w * h * bpp + 7) / 8, where bpp is the bits per pixel +of the output color type (lodepng_get_bpp). +For < 8 bpp images, there should not be padding bits at the end of scanlines. +For 16-bit per channel colors, uses big endian format like PNG does. +Return value is LodePNG error code +*/ +unsigned lodepng_convert(unsigned char* out, const unsigned char* in, + const LodePNGColorMode* mode_out, const LodePNGColorMode* mode_in, + unsigned w, unsigned h); + +#ifdef LODEPNG_COMPILE_DECODER +/* +Settings for the decoder. This contains settings for the PNG and the Zlib +decoder, but not the Info settings from the Info structs. +*/ +typedef struct LodePNGDecoderSettings { + LodePNGDecompressSettings zlibsettings; /*in here is the setting to ignore Adler32 checksums*/ + + /* Check LodePNGDecompressSettings for more ignorable errors such as ignore_adler32 */ + unsigned ignore_crc; /*ignore CRC checksums*/ + unsigned ignore_critical; /*ignore unknown critical chunks*/ + unsigned ignore_end; /*ignore issues at end of file if possible (missing IEND chunk, too large chunk, ...)*/ + /* TODO: make a system involving warnings with levels and a strict mode instead. Other potentially recoverable + errors: srgb rendering intent value, size of content of ancillary chunks, more than 79 characters for some + strings, placement/combination rules for ancillary chunks, crc of unknown chunks, allowed characters + in string keys, etc... */ + + unsigned color_convert; /*whether to convert the PNG to the color type you want. Default: yes*/ + +#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS + unsigned read_text_chunks; /*if false but remember_unknown_chunks is true, they're stored in the unknown chunks*/ + + /*store all bytes from unknown chunks in the LodePNGInfo (off by default, useful for a png editor)*/ + unsigned remember_unknown_chunks; + + /* maximum size for decompressed text chunks. If a text chunk's text is larger than this, an error is returned, + unless reading text chunks is disabled or this limit is set higher or disabled. Set to 0 to allow any size. + By default it is a value that prevents unreasonably large strings from hogging memory. */ + size_t max_text_size; + + /* maximum size for compressed ICC chunks. If the ICC profile is larger than this, an error will be returned. Set to + 0 to allow any size. By default this is a value that prevents ICC profiles that would be much larger than any + legitimate profile could be to hog memory. */ + size_t max_icc_size; +#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ +} LodePNGDecoderSettings; + +void lodepng_decoder_settings_init(LodePNGDecoderSettings* settings); +#endif /*LODEPNG_COMPILE_DECODER*/ + +#ifdef LODEPNG_COMPILE_ENCODER +/*automatically use color type with less bits per pixel if losslessly possible. Default: AUTO*/ +typedef enum LodePNGFilterStrategy { + /*every filter at zero*/ + LFS_ZERO = 0, + /*every filter at 1, 2, 3 or 4 (paeth), unlike LFS_ZERO not a good choice, but for testing*/ + LFS_ONE = 1, + LFS_TWO = 2, + LFS_THREE = 3, + LFS_FOUR = 4, + /*Use filter that gives minimum sum, as described in the official PNG filter heuristic.*/ + LFS_MINSUM, + /*Use the filter type that gives smallest Shannon entropy for this scanline. Depending + on the image, this is better or worse than minsum.*/ + LFS_ENTROPY, + /* + Brute-force-search PNG filters by compressing each filter for each scanline. + Experimental, very slow, and only rarely gives better compression than MINSUM. + */ + LFS_BRUTE_FORCE, + /*use predefined_filters buffer: you specify the filter type for each scanline*/ + LFS_PREDEFINED +} LodePNGFilterStrategy; + +/*Gives characteristics about the integer RGBA colors of the image (count, alpha channel usage, bit depth, ...), +which helps decide which color model to use for encoding. +Used internally by default if "auto_convert" is enabled. Public because it's useful for custom algorithms.*/ +typedef struct LodePNGColorStats { + unsigned colored; /*not grayscale*/ + unsigned key; /*image is not opaque and color key is possible instead of full alpha*/ + unsigned short key_r; /*key values, always as 16-bit, in 8-bit case the byte is duplicated, e.g. 65535 means 255*/ + unsigned short key_g; + unsigned short key_b; + unsigned alpha; /*image is not opaque and alpha channel or alpha palette required*/ + unsigned numcolors; /*amount of colors, up to 257. Not valid if bits == 16 or allow_palette is disabled.*/ + unsigned char palette[1024]; /*Remembers up to the first 256 RGBA colors, in no particular order, only valid when numcolors is valid*/ + unsigned bits; /*bits per channel (not for palette). 1,2 or 4 for grayscale only. 16 if 16-bit per channel required.*/ + size_t numpixels; + + /*user settings for computing/using the stats*/ + unsigned allow_palette; /*default 1. if 0, disallow choosing palette colortype in auto_choose_color, and don't count numcolors*/ + unsigned allow_greyscale; /*default 1. if 0, choose RGB or RGBA even if the image only has gray colors*/ +} LodePNGColorStats; + +void lodepng_color_stats_init(LodePNGColorStats* stats); + +/*Get a LodePNGColorStats of the image. The stats must already have been inited. +Returns error code (e.g. alloc fail) or 0 if ok.*/ +unsigned lodepng_compute_color_stats(LodePNGColorStats* stats, + const unsigned char* image, unsigned w, unsigned h, + const LodePNGColorMode* mode_in); + +/*Settings for the encoder.*/ +typedef struct LodePNGEncoderSettings { + LodePNGCompressSettings zlibsettings; /*settings for the zlib encoder, such as window size, ...*/ + + unsigned auto_convert; /*automatically choose output PNG color type. Default: true*/ + + /*If true, follows the official PNG heuristic: if the PNG uses a palette or lower than + 8 bit depth, set all filters to zero. Otherwise use the filter_strategy. Note that to + completely follow the official PNG heuristic, filter_palette_zero must be true and + filter_strategy must be LFS_MINSUM*/ + unsigned filter_palette_zero; + /*Which filter strategy to use when not using zeroes due to filter_palette_zero. + Set filter_palette_zero to 0 to ensure always using your chosen strategy. Default: LFS_MINSUM*/ + LodePNGFilterStrategy filter_strategy; + /*used if filter_strategy is LFS_PREDEFINED. In that case, this must point to a buffer with + the same length as the amount of scanlines in the image, and each value must <= 5. You + have to cleanup this buffer, LodePNG will never free it. Don't forget that filter_palette_zero + must be set to 0 to ensure this is also used on palette or low bitdepth images.*/ + const unsigned char* predefined_filters; + + /*force creating a PLTE chunk if colortype is 2 or 6 (= a suggested palette). + If colortype is 3, PLTE is _always_ created.*/ + unsigned force_palette; +#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS + /*add LodePNG identifier and version as a text chunk, for debugging*/ + unsigned add_id; + /*encode text chunks as zTXt chunks instead of tEXt chunks, and use compression in iTXt chunks*/ + unsigned text_compression; +#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ +} LodePNGEncoderSettings; + +void lodepng_encoder_settings_init(LodePNGEncoderSettings* settings); +#endif /*LODEPNG_COMPILE_ENCODER*/ + + +#if defined(LODEPNG_COMPILE_DECODER) || defined(LODEPNG_COMPILE_ENCODER) +/*The settings, state and information for extended encoding and decoding.*/ +typedef struct LodePNGState { +#ifdef LODEPNG_COMPILE_DECODER + LodePNGDecoderSettings decoder; /*the decoding settings*/ +#endif /*LODEPNG_COMPILE_DECODER*/ +#ifdef LODEPNG_COMPILE_ENCODER + LodePNGEncoderSettings encoder; /*the encoding settings*/ +#endif /*LODEPNG_COMPILE_ENCODER*/ + LodePNGColorMode info_raw; /*specifies the format in which you would like to get the raw pixel buffer*/ + LodePNGInfo info_png; /*info of the PNG image obtained after decoding*/ + unsigned error; +} LodePNGState; + +/*init, cleanup and copy functions to use with this struct*/ +void lodepng_state_init(LodePNGState* state); +void lodepng_state_cleanup(LodePNGState* state); +void lodepng_state_copy(LodePNGState* dest, const LodePNGState* source); +#endif /* defined(LODEPNG_COMPILE_DECODER) || defined(LODEPNG_COMPILE_ENCODER) */ + +#ifdef LODEPNG_COMPILE_DECODER +/* +Same as lodepng_decode_memory, but uses a LodePNGState to allow custom settings and +getting much more information about the PNG image and color mode. +*/ +unsigned lodepng_decode(unsigned char** out, unsigned* w, unsigned* h, + LodePNGState* state, + const unsigned char* in, size_t insize); + +/* +Read the PNG header, but not the actual data. This returns only the information +that is in the IHDR chunk of the PNG, such as width, height and color type. The +information is placed in the info_png field of the LodePNGState. +*/ +unsigned lodepng_inspect(unsigned* w, unsigned* h, + LodePNGState* state, + const unsigned char* in, size_t insize); +#endif /*LODEPNG_COMPILE_DECODER*/ + +/* +Reads one metadata chunk (other than IHDR) of the PNG file and outputs what it +read in the state. Returns error code on failure. +Use lodepng_inspect first with a new state, then e.g. lodepng_chunk_find_const +to find the desired chunk type, and if non null use lodepng_inspect_chunk (with +chunk_pointer - start_of_file as pos). +Supports most metadata chunks from the PNG standard (gAMA, bKGD, tEXt, ...). +Ignores unsupported, unknown, non-metadata or IHDR chunks (without error). +Requirements: &in[pos] must point to start of a chunk, must use regular +lodepng_inspect first since format of most other chunks depends on IHDR, and if +there is a PLTE chunk, that one must be inspected before tRNS or bKGD. +*/ +unsigned lodepng_inspect_chunk(LodePNGState* state, size_t pos, + const unsigned char* in, size_t insize); + +#ifdef LODEPNG_COMPILE_ENCODER +/*This function allocates the out buffer with standard malloc and stores the size in *outsize.*/ +unsigned lodepng_encode(unsigned char** out, size_t* outsize, + const unsigned char* image, unsigned w, unsigned h, + LodePNGState* state); +#endif /*LODEPNG_COMPILE_ENCODER*/ + +/* +The lodepng_chunk functions are normally not needed, except to traverse the +unknown chunks stored in the LodePNGInfo struct, or add new ones to it. +It also allows traversing the chunks of an encoded PNG file yourself. + +The chunk pointer always points to the beginning of the chunk itself, that is +the first byte of the 4 length bytes. + +In the PNG file format, chunks have the following format: +-4 bytes length: length of the data of the chunk in bytes (chunk itself is 12 bytes longer) +-4 bytes chunk type (ASCII a-z,A-Z only, see below) +-length bytes of data (may be 0 bytes if length was 0) +-4 bytes of CRC, computed on chunk name + data + +The first chunk starts at the 8th byte of the PNG file, the entire rest of the file +exists out of concatenated chunks with the above format. + +PNG standard chunk ASCII naming conventions: +-First byte: uppercase = critical, lowercase = ancillary +-Second byte: uppercase = public, lowercase = private +-Third byte: must be uppercase +-Fourth byte: uppercase = unsafe to copy, lowercase = safe to copy +*/ + +/* +Gets the length of the data of the chunk. Total chunk length has 12 bytes more. +There must be at least 4 bytes to read from. If the result value is too large, +it may be corrupt data. +*/ +unsigned lodepng_chunk_length(const unsigned char* chunk); + +/*puts the 4-byte type in null terminated string*/ +void lodepng_chunk_type(char type[5], const unsigned char* chunk); + +/*check if the type is the given type*/ +unsigned char lodepng_chunk_type_equals(const unsigned char* chunk, const char* type); + +/*0: it's one of the critical chunk types, 1: it's an ancillary chunk (see PNG standard)*/ +unsigned char lodepng_chunk_ancillary(const unsigned char* chunk); + +/*0: public, 1: private (see PNG standard)*/ +unsigned char lodepng_chunk_private(const unsigned char* chunk); + +/*0: the chunk is unsafe to copy, 1: the chunk is safe to copy (see PNG standard)*/ +unsigned char lodepng_chunk_safetocopy(const unsigned char* chunk); + +/*get pointer to the data of the chunk, where the input points to the header of the chunk*/ +unsigned char* lodepng_chunk_data(unsigned char* chunk); +const unsigned char* lodepng_chunk_data_const(const unsigned char* chunk); + +/*returns 0 if the crc is correct, 1 if it's incorrect (0 for OK as usual!)*/ +unsigned lodepng_chunk_check_crc(const unsigned char* chunk); + +/*generates the correct CRC from the data and puts it in the last 4 bytes of the chunk*/ +void lodepng_chunk_generate_crc(unsigned char* chunk); + +/* +Iterate to next chunks, allows iterating through all chunks of the PNG file. +Input must be at the beginning of a chunk (result of a previous lodepng_chunk_next call, +or the 8th byte of a PNG file which always has the first chunk), or alternatively may +point to the first byte of the PNG file (which is not a chunk but the magic header, the +function will then skip over it and return the first real chunk). +Will output pointer to the start of the next chunk, or at or beyond end of the file if there +is no more chunk after this or possibly if the chunk is corrupt. +Start this process at the 8th byte of the PNG file. +In a non-corrupt PNG file, the last chunk should have name "IEND". +*/ +unsigned char* lodepng_chunk_next(unsigned char* chunk, unsigned char* end); +const unsigned char* lodepng_chunk_next_const(const unsigned char* chunk, const unsigned char* end); + +/*Finds the first chunk with the given type in the range [chunk, end), or returns NULL if not found.*/ +unsigned char* lodepng_chunk_find(unsigned char* chunk, unsigned char* end, const char type[5]); +const unsigned char* lodepng_chunk_find_const(const unsigned char* chunk, const unsigned char* end, const char type[5]); + +/* +Appends chunk to the data in out. The given chunk should already have its chunk header. +The out variable and outsize are updated to reflect the new reallocated buffer. +Returns error code (0 if it went ok) +*/ +unsigned lodepng_chunk_append(unsigned char** out, size_t* outsize, const unsigned char* chunk); + +/* +Appends new chunk to out. The chunk to append is given by giving its length, type +and data separately. The type is a 4-letter string. +The out variable and outsize are updated to reflect the new reallocated buffer. +Returne error code (0 if it went ok) +*/ +unsigned lodepng_chunk_create(unsigned char** out, size_t* outsize, unsigned length, + const char* type, const unsigned char* data); + + +/*Calculate CRC32 of buffer*/ +unsigned lodepng_crc32(const unsigned char* buf, size_t len); +#endif /*LODEPNG_COMPILE_PNG*/ + + +#ifdef LODEPNG_COMPILE_ZLIB +/* +This zlib part can be used independently to zlib compress and decompress a +buffer. It cannot be used to create gzip files however, and it only supports the +part of zlib that is required for PNG, it does not support dictionaries. +*/ + +#ifdef LODEPNG_COMPILE_DECODER +/*Inflate a buffer. Inflate is the decompression step of deflate. Out buffer must be freed after use.*/ +unsigned lodepng_inflate(unsigned char** out, size_t* outsize, + const unsigned char* in, size_t insize, + const LodePNGDecompressSettings* settings); + +/* +Decompresses Zlib data. Reallocates the out buffer and appends the data. The +data must be according to the zlib specification. +Either, *out must be NULL and *outsize must be 0, or, *out must be a valid +buffer and *outsize its size in bytes. out must be freed by user after usage. +*/ +unsigned lodepng_zlib_decompress(unsigned char** out, size_t* outsize, + const unsigned char* in, size_t insize, + const LodePNGDecompressSettings* settings); +#endif /*LODEPNG_COMPILE_DECODER*/ + +#ifdef LODEPNG_COMPILE_ENCODER +/* +Compresses data with Zlib. Reallocates the out buffer and appends the data. +Zlib adds a small header and trailer around the deflate data. +The data is output in the format of the zlib specification. +Either, *out must be NULL and *outsize must be 0, or, *out must be a valid +buffer and *outsize its size in bytes. out must be freed by user after usage. +*/ +unsigned lodepng_zlib_compress(unsigned char** out, size_t* outsize, + const unsigned char* in, size_t insize, + const LodePNGCompressSettings* settings); + +/* +Find length-limited Huffman code for given frequencies. This function is in the +public interface only for tests, it's used internally by lodepng_deflate. +*/ +unsigned lodepng_huffman_code_lengths(unsigned* lengths, const unsigned* frequencies, + size_t numcodes, unsigned maxbitlen); + +/*Compress a buffer with deflate. See RFC 1951. Out buffer must be freed after use.*/ +unsigned lodepng_deflate(unsigned char** out, size_t* outsize, + const unsigned char* in, size_t insize, + const LodePNGCompressSettings* settings); + +#endif /*LODEPNG_COMPILE_ENCODER*/ +#endif /*LODEPNG_COMPILE_ZLIB*/ + +#ifdef LODEPNG_COMPILE_DISK +/* +Load a file from disk into buffer. The function allocates the out buffer, and +after usage you should free it. +out: output parameter, contains pointer to loaded buffer. +outsize: output parameter, size of the allocated out buffer +filename: the path to the file to load +return value: error code (0 means ok) +*/ +unsigned lodepng_load_file(unsigned char** out, size_t* outsize, const char* filename); + +/* +Save a file from buffer to disk. Warning, if it exists, this function overwrites +the file without warning! +buffer: the buffer to write +buffersize: size of the buffer to write +filename: the path to the file to save to +return value: error code (0 means ok) +*/ +unsigned lodepng_save_file(const unsigned char* buffer, size_t buffersize, const char* filename); +#endif /*LODEPNG_COMPILE_DISK*/ + +#ifdef LODEPNG_COMPILE_CPP +/* The LodePNG C++ wrapper uses std::vectors instead of manually allocated memory buffers. */ +namespace lodepng { +#ifdef LODEPNG_COMPILE_PNG +class State : public LodePNGState { + public: + State(); + State(const State& other); + ~State(); + State& operator=(const State& other); +}; + +#ifdef LODEPNG_COMPILE_DECODER +/* Same as other lodepng::decode, but using a State for more settings and information. */ +unsigned decode(std::vector& out, unsigned& w, unsigned& h, + State& state, + const unsigned char* in, size_t insize); +unsigned decode(std::vector& out, unsigned& w, unsigned& h, + State& state, + const std::vector& in); +#endif /*LODEPNG_COMPILE_DECODER*/ + +#ifdef LODEPNG_COMPILE_ENCODER +/* Same as other lodepng::encode, but using a State for more settings and information. */ +unsigned encode(std::vector& out, + const unsigned char* in, unsigned w, unsigned h, + State& state); +unsigned encode(std::vector& out, + const std::vector& in, unsigned w, unsigned h, + State& state); +#endif /*LODEPNG_COMPILE_ENCODER*/ + +#ifdef LODEPNG_COMPILE_DISK +/* +Load a file from disk into an std::vector. +return value: error code (0 means ok) +*/ +unsigned load_file(std::vector& buffer, const std::string& filename); + +/* +Save the binary data in an std::vector to a file on disk. The file is overwritten +without warning. +*/ +unsigned save_file(const std::vector& buffer, const std::string& filename); +#endif /* LODEPNG_COMPILE_DISK */ +#endif /* LODEPNG_COMPILE_PNG */ + +#ifdef LODEPNG_COMPILE_ZLIB +#ifdef LODEPNG_COMPILE_DECODER +/* Zlib-decompress an unsigned char buffer */ +unsigned decompress(std::vector& out, const unsigned char* in, size_t insize, + const LodePNGDecompressSettings& settings = lodepng_default_decompress_settings); + +/* Zlib-decompress an std::vector */ +unsigned decompress(std::vector& out, const std::vector& in, + const LodePNGDecompressSettings& settings = lodepng_default_decompress_settings); +#endif /* LODEPNG_COMPILE_DECODER */ + +#ifdef LODEPNG_COMPILE_ENCODER +/* Zlib-compress an unsigned char buffer */ +unsigned compress(std::vector& out, const unsigned char* in, size_t insize, + const LodePNGCompressSettings& settings = lodepng_default_compress_settings); + +/* Zlib-compress an std::vector */ +unsigned compress(std::vector& out, const std::vector& in, + const LodePNGCompressSettings& settings = lodepng_default_compress_settings); +#endif /* LODEPNG_COMPILE_ENCODER */ +#endif /* LODEPNG_COMPILE_ZLIB */ +} /* namespace lodepng */ +#endif /*LODEPNG_COMPILE_CPP*/ + +/* +TODO: +[.] test if there are no memory leaks or security exploits - done a lot but needs to be checked often +[.] check compatibility with various compilers - done but needs to be redone for every newer version +[X] converting color to 16-bit per channel types +[X] support color profile chunk types (but never let them touch RGB values by default) +[ ] support all public PNG chunk types (almost done except sBIT, sPLT and hIST) +[ ] make sure encoder generates no chunks with size > (2^31)-1 +[ ] partial decoding (stream processing) +[X] let the "isFullyOpaque" function check color keys and transparent palettes too +[X] better name for the variables "codes", "codesD", "codelengthcodes", "clcl" and "lldl" +[ ] allow treating some errors like warnings, when image is recoverable (e.g. 69, 57, 58) +[ ] make warnings like: oob palette, checksum fail, data after iend, wrong/unknown crit chunk, no null terminator in text, ... +[ ] error messages with line numbers (and version) +[ ] errors in state instead of as return code? +[ ] new errors/warnings like suspiciously big decompressed ztxt or iccp chunk +[ ] let the C++ wrapper catch exceptions coming from the standard library and return LodePNG error codes +[ ] allow user to provide custom color conversion functions, e.g. for premultiplied alpha, padding bits or not, ... +[ ] allow user to give data (void*) to custom allocator +[X] provide alternatives for C library functions not present on some platforms (memcpy, ...) +*/ + +#endif /*LV_USE_PNG*/ + +#endif /*LODEPNG_H inclusion guard*/ + +/* +LodePNG Documentation +--------------------- + +0. table of contents +-------------------- + + 1. about + 1.1. supported features + 1.2. features not supported + 2. C and C++ version + 3. security + 4. decoding + 5. encoding + 6. color conversions + 6.1. PNG color types + 6.2. color conversions + 6.3. padding bits + 6.4. A note about 16-bits per channel and endianness + 7. error values + 8. chunks and PNG editing + 9. compiler support + 10. examples + 10.1. decoder C++ example + 10.2. decoder C example + 11. state settings reference + 12. changes + 13. contact information + + +1. about +-------- + +PNG is a file format to store raster images losslessly with good compression, +supporting different color types and alpha channel. + +LodePNG is a PNG codec according to the Portable Network Graphics (PNG) +Specification (Second Edition) - W3C Recommendation 10 November 2003. + +The specifications used are: + +*) Portable Network Graphics (PNG) Specification (Second Edition): + http://www.w3.org/TR/2003/REC-PNG-20031110 +*) RFC 1950 ZLIB Compressed Data Format version 3.3: + http://www.gzip.org/zlib/rfc-zlib.html +*) RFC 1951 DEFLATE Compressed Data Format Specification ver 1.3: + http://www.gzip.org/zlib/rfc-deflate.html + +The most recent version of LodePNG can currently be found at +http://lodev.org/lodepng/ + +LodePNG works both in C (ISO C90) and C++, with a C++ wrapper that adds +extra functionality. + +LodePNG exists out of two files: +-lodepng.h: the header file for both C and C++ +-lodepng.c(pp): give it the name lodepng.c or lodepng.cpp (or .cc) depending on your usage + +If you want to start using LodePNG right away without reading this doc, get the +examples from the LodePNG website to see how to use it in code, or check the +smaller examples in chapter 13 here. + +LodePNG is simple but only supports the basic requirements. To achieve +simplicity, the following design choices were made: There are no dependencies +on any external library. There are functions to decode and encode a PNG with +a single function call, and extended versions of these functions taking a +LodePNGState struct allowing to specify or get more information. By default +the colors of the raw image are always RGB or RGBA, no matter what color type +the PNG file uses. To read and write files, there are simple functions to +convert the files to/from buffers in memory. + +This all makes LodePNG suitable for loading textures in games, demos and small +programs, ... It's less suitable for full fledged image editors, loading PNGs +over network (it requires all the image data to be available before decoding can +begin), life-critical systems, ... + +1.1. supported features +----------------------- + +The following features are supported by the decoder: + +*) decoding of PNGs with any color type, bit depth and interlace mode, to a 24- or 32-bit color raw image, + or the same color type as the PNG +*) encoding of PNGs, from any raw image to 24- or 32-bit color, or the same color type as the raw image +*) Adam7 interlace and deinterlace for any color type +*) loading the image from harddisk or decoding it from a buffer from other sources than harddisk +*) support for alpha channels, including RGBA color model, translucent palettes and color keying +*) zlib decompression (inflate) +*) zlib compression (deflate) +*) CRC32 and ADLER32 checksums +*) colorimetric color profile conversions: currently experimentally available in lodepng_util.cpp only, + plus alternatively ability to pass on chroma/gamma/ICC profile information to other color management system. +*) handling of unknown chunks, allowing making a PNG editor that stores custom and unknown chunks. +*) the following chunks are supported by both encoder and decoder: + IHDR: header information + PLTE: color palette + IDAT: pixel data + IEND: the final chunk + tRNS: transparency for palettized images + tEXt: textual information + zTXt: compressed textual information + iTXt: international textual information + bKGD: suggested background color + pHYs: physical dimensions + tIME: modification time + cHRM: RGB chromaticities + gAMA: RGB gamma correction + iCCP: ICC color profile + sRGB: rendering intent + +1.2. features not supported +--------------------------- + +The following features are _not_ supported: + +*) some features needed to make a conformant PNG-Editor might be still missing. +*) partial loading/stream processing. All data must be available and is processed in one call. +*) The following public chunks are not (yet) supported but treated as unknown chunks by LodePNG: + sBIT + hIST + sPLT + + +2. C and C++ version +-------------------- + +The C version uses buffers allocated with alloc that you need to free() +yourself. You need to use init and cleanup functions for each struct whenever +using a struct from the C version to avoid exploits and memory leaks. + +The C++ version has extra functions with std::vectors in the interface and the +lodepng::State class which is a LodePNGState with constructor and destructor. + +These files work without modification for both C and C++ compilers because all +the additional C++ code is in "#ifdef __cplusplus" blocks that make C-compilers +ignore it, and the C code is made to compile both with strict ISO C90 and C++. + +To use the C++ version, you need to rename the source file to lodepng.cpp +(instead of lodepng.c), and compile it with a C++ compiler. + +To use the C version, you need to rename the source file to lodepng.c (instead +of lodepng.cpp), and compile it with a C compiler. + + +3. Security +----------- + +Even if carefully designed, it's always possible that LodePNG contains possible +exploits. If you discover one, please let me know, and it will be fixed. + +When using LodePNG, care has to be taken with the C version of LodePNG, as well +as the C-style structs when working with C++. The following conventions are used +for all C-style structs: + +-if a struct has a corresponding init function, always call the init function when making a new one +-if a struct has a corresponding cleanup function, call it before the struct disappears to avoid memory leaks +-if a struct has a corresponding copy function, use the copy function instead of "=". + The destination must also be inited already. + + +4. Decoding +----------- + +Decoding converts a PNG compressed image to a raw pixel buffer. + +Most documentation on using the decoder is at its declarations in the header +above. For C, simple decoding can be done with functions such as +lodepng_decode32, and more advanced decoding can be done with the struct +LodePNGState and lodepng_decode. For C++, all decoding can be done with the +various lodepng::decode functions, and lodepng::State can be used for advanced +features. + +When using the LodePNGState, it uses the following fields for decoding: +*) LodePNGInfo info_png: it stores extra information about the PNG (the input) in here +*) LodePNGColorMode info_raw: here you can say what color mode of the raw image (the output) you want to get +*) LodePNGDecoderSettings decoder: you can specify a few extra settings for the decoder to use + +LodePNGInfo info_png +-------------------- + +After decoding, this contains extra information of the PNG image, except the actual +pixels, width and height because these are already gotten directly from the decoder +functions. + +It contains for example the original color type of the PNG image, text comments, +suggested background color, etc... More details about the LodePNGInfo struct are +at its declaration documentation. + +LodePNGColorMode info_raw +------------------------- + +When decoding, here you can specify which color type you want +the resulting raw image to be. If this is different from the colortype of the +PNG, then the decoder will automatically convert the result. This conversion +always works, except if you want it to convert a color PNG to grayscale or to +a palette with missing colors. + +By default, 32-bit color is used for the result. + +LodePNGDecoderSettings decoder +------------------------------ + +The settings can be used to ignore the errors created by invalid CRC and Adler32 +chunks, and to disable the decoding of tEXt chunks. + +There's also a setting color_convert, true by default. If false, no conversion +is done, the resulting data will be as it was in the PNG (after decompression) +and you'll have to puzzle the colors of the pixels together yourself using the +color type information in the LodePNGInfo. + + +5. Encoding +----------- + +Encoding converts a raw pixel buffer to a PNG compressed image. + +Most documentation on using the encoder is at its declarations in the header +above. For C, simple encoding can be done with functions such as +lodepng_encode32, and more advanced decoding can be done with the struct +LodePNGState and lodepng_encode. For C++, all encoding can be done with the +various lodepng::encode functions, and lodepng::State can be used for advanced +features. + +Like the decoder, the encoder can also give errors. However it gives less errors +since the encoder input is trusted, the decoder input (a PNG image that could +be forged by anyone) is not trusted. + +When using the LodePNGState, it uses the following fields for encoding: +*) LodePNGInfo info_png: here you specify how you want the PNG (the output) to be. +*) LodePNGColorMode info_raw: here you say what color type of the raw image (the input) has +*) LodePNGEncoderSettings encoder: you can specify a few settings for the encoder to use + +LodePNGInfo info_png +-------------------- + +When encoding, you use this the opposite way as when decoding: for encoding, +you fill in the values you want the PNG to have before encoding. By default it's +not needed to specify a color type for the PNG since it's automatically chosen, +but it's possible to choose it yourself given the right settings. + +The encoder will not always exactly match the LodePNGInfo struct you give, +it tries as close as possible. Some things are ignored by the encoder. The +encoder uses, for example, the following settings from it when applicable: +colortype and bitdepth, text chunks, time chunk, the color key, the palette, the +background color, the interlace method, unknown chunks, ... + +When encoding to a PNG with colortype 3, the encoder will generate a PLTE chunk. +If the palette contains any colors for which the alpha channel is not 255 (so +there are translucent colors in the palette), it'll add a tRNS chunk. + +LodePNGColorMode info_raw +------------------------- + +You specify the color type of the raw image that you give to the input here, +including a possible transparent color key and palette you happen to be using in +your raw image data. + +By default, 32-bit color is assumed, meaning your input has to be in RGBA +format with 4 bytes (unsigned chars) per pixel. + +LodePNGEncoderSettings encoder +------------------------------ + +The following settings are supported (some are in sub-structs): +*) auto_convert: when this option is enabled, the encoder will +automatically choose the smallest possible color mode (including color key) that +can encode the colors of all pixels without information loss. +*) btype: the block type for LZ77. 0 = uncompressed, 1 = fixed huffman tree, + 2 = dynamic huffman tree (best compression). Should be 2 for proper + compression. +*) use_lz77: whether or not to use LZ77 for compressed block types. Should be + true for proper compression. +*) windowsize: the window size used by the LZ77 encoder (1 - 32768). Has value + 2048 by default, but can be set to 32768 for better, but slow, compression. +*) force_palette: if colortype is 2 or 6, you can make the encoder write a PLTE + chunk if force_palette is true. This can used as suggested palette to convert + to by viewers that don't support more than 256 colors (if those still exist) +*) add_id: add text chunk "Encoder: LodePNG " to the image. +*) text_compression: default 1. If 1, it'll store texts as zTXt instead of tEXt chunks. + zTXt chunks use zlib compression on the text. This gives a smaller result on + large texts but a larger result on small texts (such as a single program name). + It's all tEXt or all zTXt though, there's no separate setting per text yet. + + +6. color conversions +-------------------- + +An important thing to note about LodePNG, is that the color type of the PNG, and +the color type of the raw image, are completely independent. By default, when +you decode a PNG, you get the result as a raw image in the color type you want, +no matter whether the PNG was encoded with a palette, grayscale or RGBA color. +And if you encode an image, by default LodePNG will automatically choose the PNG +color type that gives good compression based on the values of colors and amount +of colors in the image. It can be configured to let you control it instead as +well, though. + +To be able to do this, LodePNG does conversions from one color mode to another. +It can convert from almost any color type to any other color type, except the +following conversions: RGB to grayscale is not supported, and converting to a +palette when the palette doesn't have a required color is not supported. This is +not supported on purpose: this is information loss which requires a color +reduction algorithm that is beyond the scope of a PNG encoder (yes, RGB to gray +is easy, but there are multiple ways if you want to give some channels more +weight). + +By default, when decoding, you get the raw image in 32-bit RGBA or 24-bit RGB +color, no matter what color type the PNG has. And by default when encoding, +LodePNG automatically picks the best color model for the output PNG, and expects +the input image to be 32-bit RGBA or 24-bit RGB. So, unless you want to control +the color format of the images yourself, you can skip this chapter. + +6.1. PNG color types +-------------------- + +A PNG image can have many color types, ranging from 1-bit color to 64-bit color, +as well as palettized color modes. After the zlib decompression and unfiltering +in the PNG image is done, the raw pixel data will have that color type and thus +a certain amount of bits per pixel. If you want the output raw image after +decoding to have another color type, a conversion is done by LodePNG. + +The PNG specification gives the following color types: + +0: grayscale, bit depths 1, 2, 4, 8, 16 +2: RGB, bit depths 8 and 16 +3: palette, bit depths 1, 2, 4 and 8 +4: grayscale with alpha, bit depths 8 and 16 +6: RGBA, bit depths 8 and 16 + +Bit depth is the amount of bits per pixel per color channel. So the total amount +of bits per pixel is: amount of channels * bitdepth. + +6.2. color conversions +---------------------- + +As explained in the sections about the encoder and decoder, you can specify +color types and bit depths in info_png and info_raw to change the default +behaviour. + +If, when decoding, you want the raw image to be something else than the default, +you need to set the color type and bit depth you want in the LodePNGColorMode, +or the parameters colortype and bitdepth of the simple decoding function. + +If, when encoding, you use another color type than the default in the raw input +image, you need to specify its color type and bit depth in the LodePNGColorMode +of the raw image, or use the parameters colortype and bitdepth of the simple +encoding function. + +If, when encoding, you don't want LodePNG to choose the output PNG color type +but control it yourself, you need to set auto_convert in the encoder settings +to false, and specify the color type you want in the LodePNGInfo of the +encoder (including palette: it can generate a palette if auto_convert is true, +otherwise not). + +If the input and output color type differ (whether user chosen or auto chosen), +LodePNG will do a color conversion, which follows the rules below, and may +sometimes result in an error. + +To avoid some confusion: +-the decoder converts from PNG to raw image +-the encoder converts from raw image to PNG +-the colortype and bitdepth in LodePNGColorMode info_raw, are those of the raw image +-the colortype and bitdepth in the color field of LodePNGInfo info_png, are those of the PNG +-when encoding, the color type in LodePNGInfo is ignored if auto_convert + is enabled, it is automatically generated instead +-when decoding, the color type in LodePNGInfo is set by the decoder to that of the original + PNG image, but it can be ignored since the raw image has the color type you requested instead +-if the color type of the LodePNGColorMode and PNG image aren't the same, a conversion + between the color types is done if the color types are supported. If it is not + supported, an error is returned. If the types are the same, no conversion is done. +-even though some conversions aren't supported, LodePNG supports loading PNGs from any + colortype and saving PNGs to any colortype, sometimes it just requires preparing + the raw image correctly before encoding. +-both encoder and decoder use the same color converter. + +The function lodepng_convert does the color conversion. It is available in the +interface but normally isn't needed since the encoder and decoder already call +it. + +Non supported color conversions: +-color to grayscale when non-gray pixels are present: no error is thrown, but +the result will look ugly because only the red channel is taken (it assumes all +three channels are the same in this case so ignores green and blue). The reason +no error is given is to allow converting from three-channel grayscale images to +one-channel even if there are numerical imprecisions. +-anything to palette when the palette does not have an exact match for a from-color +in it: in this case an error is thrown + +Supported color conversions: +-anything to 8-bit RGB, 8-bit RGBA, 16-bit RGB, 16-bit RGBA +-any gray or gray+alpha, to gray or gray+alpha +-anything to a palette, as long as the palette has the requested colors in it +-removing alpha channel +-higher to smaller bitdepth, and vice versa + +If you want no color conversion to be done (e.g. for speed or control): +-In the encoder, you can make it save a PNG with any color type by giving the +raw color mode and LodePNGInfo the same color mode, and setting auto_convert to +false. +-In the decoder, you can make it store the pixel data in the same color type +as the PNG has, by setting the color_convert setting to false. Settings in +info_raw are then ignored. + +6.3. padding bits +----------------- + +In the PNG file format, if a less than 8-bit per pixel color type is used and the scanlines +have a bit amount that isn't a multiple of 8, then padding bits are used so that each +scanline starts at a fresh byte. But that is NOT true for the LodePNG raw input and output. +The raw input image you give to the encoder, and the raw output image you get from the decoder +will NOT have these padding bits, e.g. in the case of a 1-bit image with a width +of 7 pixels, the first pixel of the second scanline will the 8th bit of the first byte, +not the first bit of a new byte. + +6.4. A note about 16-bits per channel and endianness +---------------------------------------------------- + +LodePNG uses unsigned char arrays for 16-bit per channel colors too, just like +for any other color format. The 16-bit values are stored in big endian (most +significant byte first) in these arrays. This is the opposite order of the +little endian used by x86 CPU's. + +LodePNG always uses big endian because the PNG file format does so internally. +Conversions to other formats than PNG uses internally are not supported by +LodePNG on purpose, there are myriads of formats, including endianness of 16-bit +colors, the order in which you store R, G, B and A, and so on. Supporting and +converting to/from all that is outside the scope of LodePNG. + +This may mean that, depending on your use case, you may want to convert the big +endian output of LodePNG to little endian with a for loop. This is certainly not +always needed, many applications and libraries support big endian 16-bit colors +anyway, but it means you cannot simply cast the unsigned char* buffer to an +unsigned short* buffer on x86 CPUs. + + +7. error values +--------------- + +All functions in LodePNG that return an error code, return 0 if everything went +OK, or a non-zero code if there was an error. + +The meaning of the LodePNG error values can be retrieved with the function +lodepng_error_text: given the numerical error code, it returns a description +of the error in English as a string. + +Check the implementation of lodepng_error_text to see the meaning of each code. + +It is not recommended to use the numerical values to programmatically make +different decisions based on error types as the numbers are not guaranteed to +stay backwards compatible. They are for human consumption only. Programmatically +only 0 or non-0 matter. + + +8. chunks and PNG editing +------------------------- + +If you want to add extra chunks to a PNG you encode, or use LodePNG for a PNG +editor that should follow the rules about handling of unknown chunks, or if your +program is able to read other types of chunks than the ones handled by LodePNG, +then that's possible with the chunk functions of LodePNG. + +A PNG chunk has the following layout: + +4 bytes length +4 bytes type name +length bytes data +4 bytes CRC + +8.1. iterating through chunks +----------------------------- + +If you have a buffer containing the PNG image data, then the first chunk (the +IHDR chunk) starts at byte number 8 of that buffer. The first 8 bytes are the +signature of the PNG and are not part of a chunk. But if you start at byte 8 +then you have a chunk, and can check the following things of it. + +NOTE: none of these functions check for memory buffer boundaries. To avoid +exploits, always make sure the buffer contains all the data of the chunks. +When using lodepng_chunk_next, make sure the returned value is within the +allocated memory. + +unsigned lodepng_chunk_length(const unsigned char* chunk): + +Get the length of the chunk's data. The total chunk length is this length + 12. + +void lodepng_chunk_type(char type[5], const unsigned char* chunk): +unsigned char lodepng_chunk_type_equals(const unsigned char* chunk, const char* type): + +Get the type of the chunk or compare if it's a certain type + +unsigned char lodepng_chunk_critical(const unsigned char* chunk): +unsigned char lodepng_chunk_private(const unsigned char* chunk): +unsigned char lodepng_chunk_safetocopy(const unsigned char* chunk): + +Check if the chunk is critical in the PNG standard (only IHDR, PLTE, IDAT and IEND are). +Check if the chunk is private (public chunks are part of the standard, private ones not). +Check if the chunk is safe to copy. If it's not, then, when modifying data in a critical +chunk, unsafe to copy chunks of the old image may NOT be saved in the new one if your +program doesn't handle that type of unknown chunk. + +unsigned char* lodepng_chunk_data(unsigned char* chunk): +const unsigned char* lodepng_chunk_data_const(const unsigned char* chunk): + +Get a pointer to the start of the data of the chunk. + +unsigned lodepng_chunk_check_crc(const unsigned char* chunk): +void lodepng_chunk_generate_crc(unsigned char* chunk): + +Check if the crc is correct or generate a correct one. + +unsigned char* lodepng_chunk_next(unsigned char* chunk): +const unsigned char* lodepng_chunk_next_const(const unsigned char* chunk): + +Iterate to the next chunk. This works if you have a buffer with consecutive chunks. Note that these +functions do no boundary checking of the allocated data whatsoever, so make sure there is enough +data available in the buffer to be able to go to the next chunk. + +unsigned lodepng_chunk_append(unsigned char** out, size_t* outsize, const unsigned char* chunk): +unsigned lodepng_chunk_create(unsigned char** out, size_t* outsize, unsigned length, + const char* type, const unsigned char* data): + +These functions are used to create new chunks that are appended to the data in *out that has +length *outsize. The append function appends an existing chunk to the new data. The create +function creates a new chunk with the given parameters and appends it. Type is the 4-letter +name of the chunk. + +8.2. chunks in info_png +----------------------- + +The LodePNGInfo struct contains fields with the unknown chunk in it. It has 3 +buffers (each with size) to contain 3 types of unknown chunks: +the ones that come before the PLTE chunk, the ones that come between the PLTE +and the IDAT chunks, and the ones that come after the IDAT chunks. +It's necessary to make the distinction between these 3 cases because the PNG +standard forces to keep the ordering of unknown chunks compared to the critical +chunks, but does not force any other ordering rules. + +info_png.unknown_chunks_data[0] is the chunks before PLTE +info_png.unknown_chunks_data[1] is the chunks after PLTE, before IDAT +info_png.unknown_chunks_data[2] is the chunks after IDAT + +The chunks in these 3 buffers can be iterated through and read by using the same +way described in the previous subchapter. + +When using the decoder to decode a PNG, you can make it store all unknown chunks +if you set the option settings.remember_unknown_chunks to 1. By default, this +option is off (0). + +The encoder will always encode unknown chunks that are stored in the info_png. +If you need it to add a particular chunk that isn't known by LodePNG, you can +use lodepng_chunk_append or lodepng_chunk_create to the chunk data in +info_png.unknown_chunks_data[x]. + +Chunks that are known by LodePNG should not be added in that way. E.g. to make +LodePNG add a bKGD chunk, set background_defined to true and add the correct +parameters there instead. + + +9. compiler support +------------------- + +No libraries other than the current standard C library are needed to compile +LodePNG. For the C++ version, only the standard C++ library is needed on top. +Add the files lodepng.c(pp) and lodepng.h to your project, include +lodepng.h where needed, and your program can read/write PNG files. + +It is compatible with C90 and up, and C++03 and up. + +If performance is important, use optimization when compiling! For both the +encoder and decoder, this makes a large difference. + +Make sure that LodePNG is compiled with the same compiler of the same version +and with the same settings as the rest of the program, or the interfaces with +std::vectors and std::strings in C++ can be incompatible. + +CHAR_BITS must be 8 or higher, because LodePNG uses unsigned chars for octets. + +*) gcc and g++ + +LodePNG is developed in gcc so this compiler is natively supported. It gives no +warnings with compiler options "-Wall -Wextra -pedantic -ansi", with gcc and g++ +version 4.7.1 on Linux, 32-bit and 64-bit. + +*) Clang + +Fully supported and warning-free. + +*) Mingw + +The Mingw compiler (a port of gcc for Windows) should be fully supported by +LodePNG. + +*) Visual Studio and Visual C++ Express Edition + +LodePNG should be warning-free with warning level W4. Two warnings were disabled +with pragmas though: warning 4244 about implicit conversions, and warning 4996 +where it wants to use a non-standard function fopen_s instead of the standard C +fopen. + +Visual Studio may want "stdafx.h" files to be included in each source file and +give an error "unexpected end of file while looking for precompiled header". +This is not standard C++ and will not be added to the stock LodePNG. You can +disable it for lodepng.cpp only by right clicking it, Properties, C/C++, +Precompiled Headers, and set it to Not Using Precompiled Headers there. + +NOTE: Modern versions of VS should be fully supported, but old versions, e.g. +VS6, are not guaranteed to work. + +*) Compilers on Macintosh + +LodePNG has been reported to work both with gcc and LLVM for Macintosh, both for +C and C++. + +*) Other Compilers + +If you encounter problems on any compilers, feel free to let me know and I may +try to fix it if the compiler is modern and standards compliant. + + +10. examples +------------ + +This decoder example shows the most basic usage of LodePNG. More complex +examples can be found on the LodePNG website. + +10.1. decoder C++ example +------------------------- + +#include "lodepng.h" +#include + +int main(int argc, char *argv[]) { + const char* filename = argc > 1 ? argv[1] : "test.png"; + + //load and decode + std::vector image; + unsigned width, height; + unsigned error = lodepng::decode(image, width, height, filename); + + //if there's an error, display it + if(error) std::cout << "decoder error " << error << ": " << lodepng_error_text(error) << std::endl; + + //the pixels are now in the vector "image", 4 bytes per pixel, ordered RGBARGBA..., use it as texture, draw it, ... +} + +10.2. decoder C example +----------------------- + +#include "lodepng.h" + +int main(int argc, char *argv[]) { + unsigned error; + unsigned char* image; + size_t width, height; + const char* filename = argc > 1 ? argv[1] : "test.png"; + + error = lodepng_decode32_file(&image, &width, &height, filename); + + if(error) printf("decoder error %u: %s\n", error, lodepng_error_text(error)); + + / * use image here * / + + free(image); + return 0; +} + +11. state settings reference +---------------------------- + +A quick reference of some settings to set on the LodePNGState + +For decoding: + +state.decoder.zlibsettings.ignore_adler32: ignore ADLER32 checksums +state.decoder.zlibsettings.custom_...: use custom inflate function +state.decoder.ignore_crc: ignore CRC checksums +state.decoder.ignore_critical: ignore unknown critical chunks +state.decoder.ignore_end: ignore missing IEND chunk. May fail if this corruption causes other errors +state.decoder.color_convert: convert internal PNG color to chosen one +state.decoder.read_text_chunks: whether to read in text metadata chunks +state.decoder.remember_unknown_chunks: whether to read in unknown chunks +state.info_raw.colortype: desired color type for decoded image +state.info_raw.bitdepth: desired bit depth for decoded image +state.info_raw....: more color settings, see struct LodePNGColorMode +state.info_png....: no settings for decoder but ouput, see struct LodePNGInfo + +For encoding: + +state.encoder.zlibsettings.btype: disable compression by setting it to 0 +state.encoder.zlibsettings.use_lz77: use LZ77 in compression +state.encoder.zlibsettings.windowsize: tweak LZ77 windowsize +state.encoder.zlibsettings.minmatch: tweak min LZ77 length to match +state.encoder.zlibsettings.nicematch: tweak LZ77 match where to stop searching +state.encoder.zlibsettings.lazymatching: try one more LZ77 matching +state.encoder.zlibsettings.custom_...: use custom deflate function +state.encoder.auto_convert: choose optimal PNG color type, if 0 uses info_png +state.encoder.filter_palette_zero: PNG filter strategy for palette +state.encoder.filter_strategy: PNG filter strategy to encode with +state.encoder.force_palette: add palette even if not encoding to one +state.encoder.add_id: add LodePNG identifier and version as a text chunk +state.encoder.text_compression: use compressed text chunks for metadata +state.info_raw.colortype: color type of raw input image you provide +state.info_raw.bitdepth: bit depth of raw input image you provide +state.info_raw: more color settings, see struct LodePNGColorMode +state.info_png.color.colortype: desired color type if auto_convert is false +state.info_png.color.bitdepth: desired bit depth if auto_convert is false +state.info_png.color....: more color settings, see struct LodePNGColorMode +state.info_png....: more PNG related settings, see struct LodePNGInfo + + +12. changes +----------- + +The version number of LodePNG is the date of the change given in the format +yyyymmdd. + +Some changes aren't backwards compatible. Those are indicated with a (!) +symbol. + +Not all changes are listed here, the commit history in github lists more: +https://github.com/lvandeve/lodepng + +*) 17 okt 2020: prevent decoding too large text/icc chunks by default. +*) 06 mar 2020: simplified some of the dynamic memory allocations. +*) 12 jan 2020: (!) added 'end' argument to lodepng_chunk_next to allow correct + overflow checks. +*) 14 aug 2019: around 25% faster decoding thanks to huffman lookup tables. +*) 15 jun 2019: (!) auto_choose_color API changed (for bugfix: don't use palette + if gray ICC profile) and non-ICC LodePNGColorProfile renamed to + LodePNGColorStats. +*) 30 dec 2018: code style changes only: removed newlines before opening braces. +*) 10 sep 2018: added way to inspect metadata chunks without full decoding. +*) 19 aug 2018: (!) fixed color mode bKGD is encoded with and made it use + palette index in case of palette. +*) 10 aug 2018: (!) added support for gAMA, cHRM, sRGB and iCCP chunks. This + change is backwards compatible unless you relied on unknown_chunks for those. +*) 11 jun 2018: less restrictive check for pixel size integer overflow +*) 14 jan 2018: allow optionally ignoring a few more recoverable errors +*) 17 sep 2017: fix memory leak for some encoder input error cases +*) 27 nov 2016: grey+alpha auto color model detection bugfix +*) 18 apr 2016: Changed qsort to custom stable sort (for platforms w/o qsort). +*) 09 apr 2016: Fixed colorkey usage detection, and better file loading (within + the limits of pure C90). +*) 08 dec 2015: Made load_file function return error if file can't be opened. +*) 24 okt 2015: Bugfix with decoding to palette output. +*) 18 apr 2015: Boundary PM instead of just package-merge for faster encoding. +*) 24 aug 2014: Moved to github +*) 23 aug 2014: Reduced needless memory usage of decoder. +*) 28 jun 2014: Removed fix_png setting, always support palette OOB for + simplicity. Made ColorProfile public. +*) 09 jun 2014: Faster encoder by fixing hash bug and more zeros optimization. +*) 22 dec 2013: Power of two windowsize required for optimization. +*) 15 apr 2013: Fixed bug with LAC_ALPHA and color key. +*) 25 mar 2013: Added an optional feature to ignore some PNG errors (fix_png). +*) 11 mar 2013: (!) Bugfix with custom free. Changed from "my" to "lodepng_" + prefix for the custom allocators and made it possible with a new #define to + use custom ones in your project without needing to change lodepng's code. +*) 28 jan 2013: Bugfix with color key. +*) 27 okt 2012: Tweaks in text chunk keyword length error handling. +*) 8 okt 2012: (!) Added new filter strategy (entropy) and new auto color mode. + (no palette). Better deflate tree encoding. New compression tweak settings. + Faster color conversions while decoding. Some internal cleanups. +*) 23 sep 2012: Reduced warnings in Visual Studio a little bit. +*) 1 sep 2012: (!) Removed #define's for giving custom (de)compression functions + and made it work with function pointers instead. +*) 23 jun 2012: Added more filter strategies. Made it easier to use custom alloc + and free functions and toggle #defines from compiler flags. Small fixes. +*) 6 may 2012: (!) Made plugging in custom zlib/deflate functions more flexible. +*) 22 apr 2012: (!) Made interface more consistent, renaming a lot. Removed + redundant C++ codec classes. Reduced amount of structs. Everything changed, + but it is cleaner now imho and functionality remains the same. Also fixed + several bugs and shrunk the implementation code. Made new samples. +*) 6 nov 2011: (!) By default, the encoder now automatically chooses the best + PNG color model and bit depth, based on the amount and type of colors of the + raw image. For this, autoLeaveOutAlphaChannel replaced by auto_choose_color. +*) 9 okt 2011: simpler hash chain implementation for the encoder. +*) 8 sep 2011: lz77 encoder lazy matching instead of greedy matching. +*) 23 aug 2011: tweaked the zlib compression parameters after benchmarking. + A bug with the PNG filtertype heuristic was fixed, so that it chooses much + better ones (it's quite significant). A setting to do an experimental, slow, + brute force search for PNG filter types is added. +*) 17 aug 2011: (!) changed some C zlib related function names. +*) 16 aug 2011: made the code less wide (max 120 characters per line). +*) 17 apr 2011: code cleanup. Bugfixes. Convert low to 16-bit per sample colors. +*) 21 feb 2011: fixed compiling for C90. Fixed compiling with sections disabled. +*) 11 dec 2010: encoding is made faster, based on suggestion by Peter Eastman + to optimize long sequences of zeros. +*) 13 nov 2010: added LodePNG_InfoColor_hasPaletteAlpha and + LodePNG_InfoColor_canHaveAlpha functions for convenience. +*) 7 nov 2010: added LodePNG_error_text function to get error code description. +*) 30 okt 2010: made decoding slightly faster +*) 26 okt 2010: (!) changed some C function and struct names (more consistent). + Reorganized the documentation and the declaration order in the header. +*) 08 aug 2010: only changed some comments and external samples. +*) 05 jul 2010: fixed bug thanks to warnings in the new gcc version. +*) 14 mar 2010: fixed bug where too much memory was allocated for char buffers. +*) 02 sep 2008: fixed bug where it could create empty tree that linux apps could + read by ignoring the problem but windows apps couldn't. +*) 06 jun 2008: added more error checks for out of memory cases. +*) 26 apr 2008: added a few more checks here and there to ensure more safety. +*) 06 mar 2008: crash with encoding of strings fixed +*) 02 feb 2008: support for international text chunks added (iTXt) +*) 23 jan 2008: small cleanups, and #defines to divide code in sections +*) 20 jan 2008: support for unknown chunks allowing using LodePNG for an editor. +*) 18 jan 2008: support for tIME and pHYs chunks added to encoder and decoder. +*) 17 jan 2008: ability to encode and decode compressed zTXt chunks added + Also various fixes, such as in the deflate and the padding bits code. +*) 13 jan 2008: Added ability to encode Adam7-interlaced images. Improved + filtering code of encoder. +*) 07 jan 2008: (!) changed LodePNG to use ISO C90 instead of C++. A + C++ wrapper around this provides an interface almost identical to before. + Having LodePNG be pure ISO C90 makes it more portable. The C and C++ code + are together in these files but it works both for C and C++ compilers. +*) 29 dec 2007: (!) changed most integer types to unsigned int + other tweaks +*) 30 aug 2007: bug fixed which makes this Borland C++ compatible +*) 09 aug 2007: some VS2005 warnings removed again +*) 21 jul 2007: deflate code placed in new namespace separate from zlib code +*) 08 jun 2007: fixed bug with 2- and 4-bit color, and small interlaced images +*) 04 jun 2007: improved support for Visual Studio 2005: crash with accessing + invalid std::vector element [0] fixed, and level 3 and 4 warnings removed +*) 02 jun 2007: made the encoder add a tag with version by default +*) 27 may 2007: zlib and png code separated (but still in the same file), + simple encoder/decoder functions added for more simple usage cases +*) 19 may 2007: minor fixes, some code cleaning, new error added (error 69), + moved some examples from here to lodepng_examples.cpp +*) 12 may 2007: palette decoding bug fixed +*) 24 apr 2007: changed the license from BSD to the zlib license +*) 11 mar 2007: very simple addition: ability to encode bKGD chunks. +*) 04 mar 2007: (!) tEXt chunk related fixes, and support for encoding + palettized PNG images. Plus little interface change with palette and texts. +*) 03 mar 2007: Made it encode dynamic Huffman shorter with repeat codes. + Fixed a bug where the end code of a block had length 0 in the Huffman tree. +*) 26 feb 2007: Huffman compression with dynamic trees (BTYPE 2) now implemented + and supported by the encoder, resulting in smaller PNGs at the output. +*) 27 jan 2007: Made the Adler-32 test faster so that a timewaste is gone. +*) 24 jan 2007: gave encoder an error interface. Added color conversion from any + greyscale type to 8-bit greyscale with or without alpha. +*) 21 jan 2007: (!) Totally changed the interface. It allows more color types + to convert to and is more uniform. See the manual for how it works now. +*) 07 jan 2007: Some cleanup & fixes, and a few changes over the last days: + encode/decode custom tEXt chunks, separate classes for zlib & deflate, and + at last made the decoder give errors for incorrect Adler32 or Crc. +*) 01 jan 2007: Fixed bug with encoding PNGs with less than 8 bits per channel. +*) 29 dec 2006: Added support for encoding images without alpha channel, and + cleaned out code as well as making certain parts faster. +*) 28 dec 2006: Added "Settings" to the encoder. +*) 26 dec 2006: The encoder now does LZ77 encoding and produces much smaller files now. + Removed some code duplication in the decoder. Fixed little bug in an example. +*) 09 dec 2006: (!) Placed output parameters of public functions as first parameter. + Fixed a bug of the decoder with 16-bit per color. +*) 15 okt 2006: Changed documentation structure +*) 09 okt 2006: Encoder class added. It encodes a valid PNG image from the + given image buffer, however for now it's not compressed. +*) 08 sep 2006: (!) Changed to interface with a Decoder class +*) 30 jul 2006: (!) LodePNG_InfoPng , width and height are now retrieved in different + way. Renamed decodePNG to decodePNGGeneric. +*) 29 jul 2006: (!) Changed the interface: image info is now returned as a + struct of type LodePNG::LodePNG_Info, instead of a vector, which was a bit clumsy. +*) 28 jul 2006: Cleaned the code and added new error checks. + Corrected terminology "deflate" into "inflate". +*) 23 jun 2006: Added SDL example in the documentation in the header, this + example allows easy debugging by displaying the PNG and its transparency. +*) 22 jun 2006: (!) Changed way to obtain error value. Added + loadFile function for convenience. Made decodePNG32 faster. +*) 21 jun 2006: (!) Changed type of info vector to unsigned. + Changed position of palette in info vector. Fixed an important bug that + happened on PNGs with an uncompressed block. +*) 16 jun 2006: Internally changed unsigned into unsigned where + needed, and performed some optimizations. +*) 07 jun 2006: (!) Renamed functions to decodePNG and placed them + in LodePNG namespace. Changed the order of the parameters. Rewrote the + documentation in the header. Renamed files to lodepng.cpp and lodepng.h +*) 22 apr 2006: Optimized and improved some code +*) 07 sep 2005: (!) Changed to std::vector interface +*) 12 aug 2005: Initial release (C++, decoder only) + + +13. contact information +----------------------- + +Feel free to contact me with suggestions, problems, comments, ... concerning +LodePNG. If you encounter a PNG image that doesn't work properly with this +decoder, feel free to send it and I'll use it to find and fix the problem. + +My email address is (puzzle the account and domain together with an @ symbol): +Domain: gmail dot com. +Account: lode dot vandevenne. + + +Copyright (c) 2005-2020 Lode Vandevenne +*/ diff --git a/src/lib/lvgl/src/extra/libs/png/lv_png.h b/src/lib/lvgl/src/extra/libs/png/lv_png.h new file mode 100644 index 0000000..4380472 --- /dev/null +++ b/src/lib/lvgl/src/extra/libs/png/lv_png.h @@ -0,0 +1,46 @@ +/** + * @file lv_png.h + * + */ + +#ifndef LV_PNG_H +#define LV_PNG_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include "../../../lv_conf_internal.h" +#if LV_USE_PNG + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +/** + * Register the PNG decoder functions in LVGL + */ +void lv_png_init(void); + +/********************** + * MACROS + **********************/ + +#endif /*LV_USE_PNG*/ + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /*LV_PNG_H*/ diff --git a/src/lib/lvgl/src/extra/libs/qrcode/lv_qrcode.h b/src/lib/lvgl/src/extra/libs/qrcode/lv_qrcode.h new file mode 100644 index 0000000..b0752ac --- /dev/null +++ b/src/lib/lvgl/src/extra/libs/qrcode/lv_qrcode.h @@ -0,0 +1,69 @@ +/** + * @file lv_qrcode + * + */ + +#ifndef LV_QRCODE_H +#define LV_QRCODE_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include "../../../lvgl.h" +#if LV_USE_QRCODE + +/********************* + * DEFINES + *********************/ + +extern const lv_obj_class_t lv_qrcode_class; + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +/** + * Create an empty QR code (an `lv_canvas`) object. + * @param parent point to an object where to create the QR code + * @param size width and height of the QR code + * @param dark_color dark color of the QR code + * @param light_color light color of the QR code + * @return pointer to the created QR code object + */ +lv_obj_t * lv_qrcode_create(lv_obj_t * parent, lv_coord_t size, lv_color_t dark_color, lv_color_t light_color); + +/** + * Set the data of a QR code object + * @param qrcode pointer to aQ code object + * @param data data to display + * @param data_len length of data in bytes + * @return LV_RES_OK: if no error; LV_RES_INV: on error + */ +lv_res_t lv_qrcode_update(lv_obj_t * qrcode, const void * data, uint32_t data_len); + +/** + * DEPRECATED: Use normal lv_obj_del instead + * Delete a QR code object + * @param qrcode pointer to a QR code object + */ +void lv_qrcode_delete(lv_obj_t * qrcode); + +/********************** + * MACROS + **********************/ + +#endif /*LV_USE_QRCODE*/ + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /*LV_QRCODE_H*/ diff --git a/src/lib/lvgl/src/extra/libs/qrcode/qrcodegen.h b/src/lib/lvgl/src/extra/libs/qrcode/qrcodegen.h new file mode 100644 index 0000000..dceddf6 --- /dev/null +++ b/src/lib/lvgl/src/extra/libs/qrcode/qrcodegen.h @@ -0,0 +1,319 @@ +/* + * QR Code generator library (C) + * + * Copyright (c) Project Nayuki. (MIT License) + * https://www.nayuki.io/page/qr-code-generator-library + * + * 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. + */ + +#pragma once + +#include +#include +#include + + +#ifdef __cplusplus +extern "C" { +#endif + + +/* + * This library creates QR Code symbols, which is a type of two-dimension barcode. + * Invented by Denso Wave and described in the ISO/IEC 18004 standard. + * A QR Code structure is an immutable square grid of black and white cells. + * The library provides functions to create a QR Code from text or binary data. + * The library covers the QR Code Model 2 specification, supporting all versions (sizes) + * from 1 to 40, all 4 error correction levels, and 4 character encoding modes. + * + * Ways to create a QR Code object: + * - High level: Take the payload data and call qrcodegen_encodeText() or qrcodegen_encodeBinary(). + * - Low level: Custom-make the list of segments and call + * qrcodegen_encodeSegments() or qrcodegen_encodeSegmentsAdvanced(). + * (Note that all ways require supplying the desired error correction level and various byte buffers.) + */ + + +/*---- Enum and struct types----*/ + +/* + * The error correction level in a QR Code symbol. + */ +enum qrcodegen_Ecc { + // Must be declared in ascending order of error protection + // so that an internal qrcodegen function works properly + qrcodegen_Ecc_LOW = 0 , // The QR Code can tolerate about 7% erroneous codewords + qrcodegen_Ecc_MEDIUM , // The QR Code can tolerate about 15% erroneous codewords + qrcodegen_Ecc_QUARTILE, // The QR Code can tolerate about 25% erroneous codewords + qrcodegen_Ecc_HIGH , // The QR Code can tolerate about 30% erroneous codewords +}; + + +/* + * The mask pattern used in a QR Code symbol. + */ +enum qrcodegen_Mask { + // A special value to tell the QR Code encoder to + // automatically select an appropriate mask pattern + qrcodegen_Mask_AUTO = -1, + // The eight actual mask patterns + qrcodegen_Mask_0 = 0, + qrcodegen_Mask_1, + qrcodegen_Mask_2, + qrcodegen_Mask_3, + qrcodegen_Mask_4, + qrcodegen_Mask_5, + qrcodegen_Mask_6, + qrcodegen_Mask_7, +}; + + +/* + * Describes how a segment's data bits are interpreted. + */ +enum qrcodegen_Mode { + qrcodegen_Mode_NUMERIC = 0x1, + qrcodegen_Mode_ALPHANUMERIC = 0x2, + qrcodegen_Mode_BYTE = 0x4, + qrcodegen_Mode_KANJI = 0x8, + qrcodegen_Mode_ECI = 0x7, +}; + + +/* + * A segment of character/binary/control data in a QR Code symbol. + * The mid-level way to create a segment is to take the payload data + * and call a factory function such as qrcodegen_makeNumeric(). + * The low-level way to create a segment is to custom-make the bit buffer + * and initialize a qrcodegen_Segment struct with appropriate values. + * Even in the most favorable conditions, a QR Code can only hold 7089 characters of data. + * Any segment longer than this is meaningless for the purpose of generating QR Codes. + * Moreover, the maximum allowed bit length is 32767 because + * the largest QR Code (version 40) has 31329 modules. + */ +struct qrcodegen_Segment { + // The mode indicator of this segment. + enum qrcodegen_Mode mode; + + // The length of this segment's unencoded data. Measured in characters for + // numeric/alphanumeric/kanji mode, bytes for byte mode, and 0 for ECI mode. + // Always zero or positive. Not the same as the data's bit length. + int numChars; + + // The data bits of this segment, packed in bitwise big endian. + // Can be null if the bit length is zero. + uint8_t *data; + + // The number of valid data bits used in the buffer. Requires + // 0 <= bitLength <= 32767, and bitLength <= (capacity of data array) * 8. + // The character count (numChars) must agree with the mode and the bit buffer length. + int bitLength; +}; + + + +/*---- Macro constants and functions ----*/ + +#define qrcodegen_VERSION_MIN 1 // The minimum version number supported in the QR Code Model 2 standard +#define qrcodegen_VERSION_MAX 40 // The maximum version number supported in the QR Code Model 2 standard + +// Calculates the number of bytes needed to store any QR Code up to and including the given version number, +// as a compile-time constant. For example, 'uint8_t buffer[qrcodegen_BUFFER_LEN_FOR_VERSION(25)];' +// can store any single QR Code from version 1 to 25 (inclusive). The result fits in an int (or int16). +// Requires qrcodegen_VERSION_MIN <= n <= qrcodegen_VERSION_MAX. +#define qrcodegen_BUFFER_LEN_FOR_VERSION(n) ((((n) * 4 + 17) * ((n) * 4 + 17) + 7) / 8 + 1) + +// The worst-case number of bytes needed to store one QR Code, up to and including +// version 40. This value equals 3918, which is just under 4 kilobytes. +// Use this more convenient value to avoid calculating tighter memory bounds for buffers. +#define qrcodegen_BUFFER_LEN_MAX qrcodegen_BUFFER_LEN_FOR_VERSION(qrcodegen_VERSION_MAX) + + + +/*---- Functions (high level) to generate QR Codes ----*/ + +/* + * Encodes the given text string to a QR Code, returning true if encoding succeeded. + * If the data is too long to fit in any version in the given range + * at the given ECC level, then false is returned. + * - The input text must be encoded in UTF-8 and contain no NULs. + * - The variables ecl and mask must correspond to enum constant values. + * - Requires 1 <= minVersion <= maxVersion <= 40. + * - The arrays tempBuffer and qrcode must each have a length + * of at least qrcodegen_BUFFER_LEN_FOR_VERSION(maxVersion). + * - After the function returns, tempBuffer contains no useful data. + * - If successful, the resulting QR Code may use numeric, + * alphanumeric, or byte mode to encode the text. + * - In the most optimistic case, a QR Code at version 40 with low ECC + * can hold any UTF-8 string up to 2953 bytes, or any alphanumeric string + * up to 4296 characters, or any digit string up to 7089 characters. + * These numbers represent the hard upper limit of the QR Code standard. + * - Please consult the QR Code specification for information on + * data capacities per version, ECC level, and text encoding mode. + */ +bool qrcodegen_encodeText(const char *text, uint8_t tempBuffer[], uint8_t qrcode[], + enum qrcodegen_Ecc ecl, int minVersion, int maxVersion, enum qrcodegen_Mask mask, bool boostEcl); + + +/* + * Encodes the given binary data to a QR Code, returning true if encoding succeeded. + * If the data is too long to fit in any version in the given range + * at the given ECC level, then false is returned. + * - The input array range dataAndTemp[0 : dataLen] should normally be + * valid UTF-8 text, but is not required by the QR Code standard. + * - The variables ecl and mask must correspond to enum constant values. + * - Requires 1 <= minVersion <= maxVersion <= 40. + * - The arrays dataAndTemp and qrcode must each have a length + * of at least qrcodegen_BUFFER_LEN_FOR_VERSION(maxVersion). + * - After the function returns, the contents of dataAndTemp may have changed, + * and does not represent useful data anymore. + * - If successful, the resulting QR Code will use byte mode to encode the data. + * - In the most optimistic case, a QR Code at version 40 with low ECC can hold any byte + * sequence up to length 2953. This is the hard upper limit of the QR Code standard. + * - Please consult the QR Code specification for information on + * data capacities per version, ECC level, and text encoding mode. + */ +bool qrcodegen_encodeBinary(uint8_t dataAndTemp[], size_t dataLen, uint8_t qrcode[], + enum qrcodegen_Ecc ecl, int minVersion, int maxVersion, enum qrcodegen_Mask mask, bool boostEcl); + + +/*---- Functions (low level) to generate QR Codes ----*/ + +/* + * Renders a QR Code representing the given segments at the given error correction level. + * The smallest possible QR Code version is automatically chosen for the output. Returns true if + * QR Code creation succeeded, or false if the data is too long to fit in any version. The ECC level + * of the result may be higher than the ecl argument if it can be done without increasing the version. + * This function allows the user to create a custom sequence of segments that switches + * between modes (such as alphanumeric and byte) to encode text in less space. + * This is a low-level API; the high-level API is qrcodegen_encodeText() and qrcodegen_encodeBinary(). + * To save memory, the segments' data buffers can alias/overlap tempBuffer, and will + * result in them being clobbered, but the QR Code output will still be correct. + * But the qrcode array must not overlap tempBuffer or any segment's data buffer. + */ +bool qrcodegen_encodeSegments(const struct qrcodegen_Segment segs[], size_t len, + enum qrcodegen_Ecc ecl, uint8_t tempBuffer[], uint8_t qrcode[]); + + +/* + * Renders a QR Code representing the given segments with the given encoding parameters. + * Returns true if QR Code creation succeeded, or false if the data is too long to fit in the range of versions. + * The smallest possible QR Code version within the given range is automatically + * chosen for the output. Iff boostEcl is true, then the ECC level of the result + * may be higher than the ecl argument if it can be done without increasing the + * version. The mask number is either between 0 to 7 (inclusive) to force that + * mask, or -1 to automatically choose an appropriate mask (which may be slow). + * This function allows the user to create a custom sequence of segments that switches + * between modes (such as alphanumeric and byte) to encode text in less space. + * This is a low-level API; the high-level API is qrcodegen_encodeText() and qrcodegen_encodeBinary(). + * To save memory, the segments' data buffers can alias/overlap tempBuffer, and will + * result in them being clobbered, but the QR Code output will still be correct. + * But the qrcode array must not overlap tempBuffer or any segment's data buffer. + */ +bool qrcodegen_encodeSegmentsAdvanced(const struct qrcodegen_Segment segs[], size_t len, enum qrcodegen_Ecc ecl, + int minVersion, int maxVersion, int mask, bool boostEcl, uint8_t tempBuffer[], uint8_t qrcode[]); + + +/* + * Tests whether the given string can be encoded as a segment in alphanumeric mode. + * A string is encodable iff each character is in the following set: 0 to 9, A to Z + * (uppercase only), space, dollar, percent, asterisk, plus, hyphen, period, slash, colon. + */ +bool qrcodegen_isAlphanumeric(const char *text); + + +/* + * Tests whether the given string can be encoded as a segment in numeric mode. + * A string is encodable iff each character is in the range 0 to 9. + */ +bool qrcodegen_isNumeric(const char *text); + + +/* + * Returns the number of bytes (uint8_t) needed for the data buffer of a segment + * containing the given number of characters using the given mode. Notes: + * - Returns SIZE_MAX on failure, i.e. numChars > INT16_MAX or + * the number of needed bits exceeds INT16_MAX (i.e. 32767). + * - Otherwise, all valid results are in the range [0, ceil(INT16_MAX / 8)], i.e. at most 4096. + * - It is okay for the user to allocate more bytes for the buffer than needed. + * - For byte mode, numChars measures the number of bytes, not Unicode code points. + * - For ECI mode, numChars must be 0, and the worst-case number of bytes is returned. + * An actual ECI segment can have shorter data. For non-ECI modes, the result is exact. + */ +size_t qrcodegen_calcSegmentBufferSize(enum qrcodegen_Mode mode, size_t numChars); + + +/* + * Returns a segment representing the given binary data encoded in + * byte mode. All input byte arrays are acceptable. Any text string + * can be converted to UTF-8 bytes and encoded as a byte mode segment. + */ +struct qrcodegen_Segment qrcodegen_makeBytes(const uint8_t data[], size_t len, uint8_t buf[]); + + +/* + * Returns a segment representing the given string of decimal digits encoded in numeric mode. + */ +struct qrcodegen_Segment qrcodegen_makeNumeric(const char *digits, uint8_t buf[]); + + +/* + * Returns a segment representing the given text string encoded in alphanumeric mode. + * The characters allowed are: 0 to 9, A to Z (uppercase only), space, + * dollar, percent, asterisk, plus, hyphen, period, slash, colon. + */ +struct qrcodegen_Segment qrcodegen_makeAlphanumeric(const char *text, uint8_t buf[]); + + +/* + * Returns a segment representing an Extended Channel Interpretation + * (ECI) designator with the given assignment value. + */ +struct qrcodegen_Segment qrcodegen_makeEci(long assignVal, uint8_t buf[]); + + +/*---- Functions to extract raw data from QR Codes ----*/ + +/* + * Returns the side length of the given QR Code, assuming that encoding succeeded. + * The result is in the range [21, 177]. Note that the length of the array buffer + * is related to the side length - every 'uint8_t qrcode[]' must have length at least + * qrcodegen_BUFFER_LEN_FOR_VERSION(version), which equals ceil(size^2 / 8 + 1). + */ +int qrcodegen_getSize(const uint8_t qrcode[]); + + +/* + * Returns the color of the module (pixel) at the given coordinates, which is false + * for white or true for black. The top left corner has the coordinates (x=0, y=0). + * If the given coordinates are out of bounds, then false (white) is returned. + */ +bool qrcodegen_getModule(const uint8_t qrcode[], int x, int y); + +/* + * Returns the qrcode size of the specified version. Returns -1 on failure + */ +int qrcodegen_version2size(int version); +/* + * Returns the min version of the data that can be stored. Returns -1 on failure + */ +int qrcodegen_getMinFitVersion(enum qrcodegen_Ecc ecl, size_t dataLen); + +#ifdef __cplusplus +} +#endif diff --git a/src/lib/lvgl/src/extra/libs/rlottie/lv_rlottie.h b/src/lib/lvgl/src/extra/libs/rlottie/lv_rlottie.h new file mode 100644 index 0000000..d66dc22 --- /dev/null +++ b/src/lib/lvgl/src/extra/libs/rlottie/lv_rlottie.h @@ -0,0 +1,75 @@ +/** + * @file lv_rlottie.h + * + */ + +#ifndef LV_RLOTTIE_H +#define LV_RLOTTIE_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include "../../../lvgl.h" +#if LV_USE_RLOTTIE + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ +typedef enum { + LV_RLOTTIE_CTRL_FORWARD = 0, + LV_RLOTTIE_CTRL_BACKWARD = 1, + LV_RLOTTIE_CTRL_PAUSE = 2, + LV_RLOTTIE_CTRL_PLAY = 0, /* Yes, play = 0 is the default mode */ + LV_RLOTTIE_CTRL_LOOP = 8, +} lv_rlottie_ctrl_t; + +/** definition in lottieanimation_capi.c */ +struct Lottie_Animation_S; +typedef struct { + lv_img_t img_ext; + struct Lottie_Animation_S * animation; + lv_timer_t * task; + lv_img_dsc_t imgdsc; + size_t total_frames; + size_t current_frame; + size_t framerate; + uint32_t * allocated_buf; + size_t allocated_buffer_size; + size_t scanline_width; + lv_rlottie_ctrl_t play_ctrl; + size_t dest_frame; +} lv_rlottie_t; + +extern const lv_obj_class_t lv_rlottie_class; + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +lv_obj_t * lv_rlottie_create_from_file(lv_obj_t * parent, lv_coord_t width, lv_coord_t height, const char * path); + +lv_obj_t * lv_rlottie_create_from_raw(lv_obj_t * parent, lv_coord_t width, lv_coord_t height, + const char * rlottie_desc); + +void lv_rlottie_set_play_mode(lv_obj_t * rlottie, const lv_rlottie_ctrl_t ctrl); +void lv_rlottie_set_current_frame(lv_obj_t * rlottie, const size_t goto_frame); + +/********************** + * MACROS + **********************/ + +#endif /*LV_USE_RLOTTIE*/ + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /*LV_RLOTTIE_H*/ diff --git a/src/lib/lvgl/src/extra/libs/sjpg/lv_sjpg.h b/src/lib/lvgl/src/extra/libs/sjpg/lv_sjpg.h new file mode 100644 index 0000000..d06e80d --- /dev/null +++ b/src/lib/lvgl/src/extra/libs/sjpg/lv_sjpg.h @@ -0,0 +1,43 @@ +/** + * @file lv_sjpg.h + * + */ + +#ifndef LV_SJPEG_H +#define LV_SJPEG_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ + +#if LV_USE_SJPG + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +void lv_split_jpeg_init(void); + +/********************** + * MACROS + **********************/ + +#endif /*LV_USE_SJPG*/ + +#ifdef __cplusplus +} +#endif + +#endif /* LV_SJPEG_H */ diff --git a/src/lib/lvgl/src/extra/libs/sjpg/tjpgd.h b/src/lib/lvgl/src/extra/libs/sjpg/tjpgd.h new file mode 100644 index 0000000..b255ccf --- /dev/null +++ b/src/lib/lvgl/src/extra/libs/sjpg/tjpgd.h @@ -0,0 +1,93 @@ +/*----------------------------------------------------------------------------/ +/ TJpgDec - Tiny JPEG Decompressor R0.03 include file (C)ChaN, 2021 +/----------------------------------------------------------------------------*/ +#ifndef DEF_TJPGDEC +#define DEF_TJPGDEC + +#ifdef __cplusplus +extern "C" { +#endif + +#include "../../../lv_conf_internal.h" +#if LV_USE_SJPG + +#include "tjpgdcnf.h" +#include +#include + +#if JD_FASTDECODE >= 1 +typedef int16_t jd_yuv_t; +#else +typedef uint8_t jd_yuv_t; +#endif + + +/* Error code */ +typedef enum { + JDR_OK = 0, /* 0: Succeeded */ + JDR_INTR, /* 1: Interrupted by output function */ + JDR_INP, /* 2: Device error or wrong termination of input stream */ + JDR_MEM1, /* 3: Insufficient memory pool for the image */ + JDR_MEM2, /* 4: Insufficient stream input buffer */ + JDR_PAR, /* 5: Parameter error */ + JDR_FMT1, /* 6: Data format error (may be broken data) */ + JDR_FMT2, /* 7: Right format but not supported */ + JDR_FMT3 /* 8: Not supported JPEG standard */ +} JRESULT; + +/* Rectangular region in the output image */ +typedef struct { + uint16_t left; /* Left end */ + uint16_t right; /* Right end */ + uint16_t top; /* Top end */ + uint16_t bottom; /* Bottom end */ +} JRECT; + +/* Decompressor object structure */ +typedef struct JDEC JDEC; +struct JDEC { + size_t dctr; /* Number of bytes available in the input buffer */ + uint8_t* dptr; /* Current data read ptr */ + uint8_t* inbuf; /* Bit stream input buffer */ + uint8_t dbit; /* Number of bits availavble in wreg or reading bit mask */ + uint8_t scale; /* Output scaling ratio */ + uint8_t msx, msy; /* MCU size in unit of block (width, height) */ + uint8_t qtid[3]; /* Quantization table ID of each component, Y, Cb, Cr */ + uint8_t ncomp; /* Number of color components 1:grayscale, 3:color */ + int16_t dcv[3]; /* Previous DC element of each component */ + uint16_t nrst; /* Restart inverval */ + uint16_t width, height; /* Size of the input image (pixel) */ + uint8_t* huffbits[2][2]; /* Huffman bit distribution tables [id][dcac] */ + uint16_t* huffcode[2][2]; /* Huffman code word tables [id][dcac] */ + uint8_t* huffdata[2][2]; /* Huffman decoded data tables [id][dcac] */ + int32_t* qttbl[4]; /* Dequantizer tables [id] */ +#if JD_FASTDECODE >= 1 + uint32_t wreg; /* Working shift register */ + uint8_t marker; /* Detected marker (0:None) */ +#if JD_FASTDECODE == 2 + uint8_t longofs[2][2]; /* Table offset of long code [id][dcac] */ + uint16_t* hufflut_ac[2]; /* Fast huffman decode tables for AC short code [id] */ + uint8_t* hufflut_dc[2]; /* Fast huffman decode tables for DC short code [id] */ +#endif +#endif + void* workbuf; /* Working buffer for IDCT and RGB output */ + jd_yuv_t* mcubuf; /* Working buffer for the MCU */ + void* pool; /* Pointer to available memory pool */ + size_t sz_pool; /* Size of momory pool (bytes available) */ + size_t (*infunc)(JDEC*, uint8_t*, size_t); /* Pointer to jpeg stream input function */ + void* device; /* Pointer to I/O device identifiler for the session */ +}; + + + +/* TJpgDec API functions */ +JRESULT jd_prepare (JDEC* jd, size_t (*infunc)(JDEC*,uint8_t*,size_t), void* pool, size_t sz_pool, void* dev); +JRESULT jd_decomp (JDEC* jd, int (*outfunc)(JDEC*,void*,JRECT*), uint8_t scale); + +#endif /*LV_USE_SJPG*/ + +#ifdef __cplusplus +} +#endif + +#endif /* _TJPGDEC */ diff --git a/src/lib/lvgl/src/extra/libs/sjpg/tjpgdcnf.h b/src/lib/lvgl/src/extra/libs/sjpg/tjpgdcnf.h new file mode 100644 index 0000000..6d425e6 --- /dev/null +++ b/src/lib/lvgl/src/extra/libs/sjpg/tjpgdcnf.h @@ -0,0 +1,33 @@ +/*----------------------------------------------*/ +/* TJpgDec System Configurations R0.03 */ +/*----------------------------------------------*/ + +#define JD_SZBUF 512 +/* Specifies size of stream input buffer */ + +#define JD_FORMAT 0 +/* Specifies output pixel format. +/ 0: RGB888 (24-bit/pix) +/ 1: RGB565 (16-bit/pix) +/ 2: Grayscale (8-bit/pix) +*/ + +#define JD_USE_SCALE 1 +/* Switches output descaling feature. +/ 0: Disable +/ 1: Enable +*/ + +#define JD_TBLCLIP 1 +/* Use table conversion for saturation arithmetic. A bit faster, but increases 1 KB of code size. +/ 0: Disable +/ 1: Enable +*/ + +#define JD_FASTDECODE 0 +/* Optimization level +/ 0: Basic optimization. Suitable for 8/16-bit MCUs. +/ 1: + 32-bit barrel shifter. Suitable for 32-bit MCUs. +/ 2: + Table conversion for huffman decoding (wants 6 << HUFF_BIT bytes of RAM) +*/ + diff --git a/src/lib/lvgl/src/extra/lv_extra.h b/src/lib/lvgl/src/extra/lv_extra.h new file mode 100644 index 0000000..ea9ce38 --- /dev/null +++ b/src/lib/lvgl/src/extra/lv_extra.h @@ -0,0 +1,42 @@ +/** + * @file lv_extra.h + * + */ + +#ifndef LV_EXTRA_H +#define LV_EXTRA_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +/** + * Initialize the extra components + */ +void lv_extra_init(void); + +/********************** + * MACROS + **********************/ + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif /*LV_EXTRA_H*/ diff --git a/src/lib/lvgl/src/extra/others/fragment/lv_fragment.h b/src/lib/lvgl/src/extra/others/fragment/lv_fragment.h new file mode 100644 index 0000000..da30b39 --- /dev/null +++ b/src/lib/lvgl/src/extra/others/fragment/lv_fragment.h @@ -0,0 +1,339 @@ +/** + * Public header for Fragment + * @file lv_fragment.h + */ + +#ifndef LV_FRAGMENT_H +#define LV_FRAGMENT_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include "../../../lv_conf_internal.h" + +#if LV_USE_FRAGMENT + +#include "../../../core/lv_obj.h" + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +typedef struct _lv_fragment_manager_t lv_fragment_manager_t; + +typedef struct _lv_fragment_t lv_fragment_t; +typedef struct _lv_fragment_class_t lv_fragment_class_t; +typedef struct _lv_fragment_managed_states_t lv_fragment_managed_states_t; + +struct _lv_fragment_t { + /** + * Class of this fragment + */ + const lv_fragment_class_t * cls; + /** + * Managed fragment states. If not null, then this fragment is managed. + * + * @warning Don't modify values inside this struct! + */ + lv_fragment_managed_states_t * managed; + /** + * Child fragment manager + */ + lv_fragment_manager_t * child_manager; + /** + * lv_obj returned by create_obj_cb + */ + lv_obj_t * obj; + +}; + +struct _lv_fragment_class_t { + /** + * Constructor function for fragment class + * @param self Fragment instance + * @param args Arguments assigned by fragment manager + */ + void (*constructor_cb)(lv_fragment_t * self, void * args); + + /** + * Destructor function for fragment class + * @param self Fragment instance, will be freed after this call + */ + void (*destructor_cb)(lv_fragment_t * self); + + /** + * Fragment attached to manager + * @param self Fragment instance + */ + void (*attached_cb)(lv_fragment_t * self); + + /** + * Fragment detached from manager + * @param self Fragment instance + */ + void (*detached_cb)(lv_fragment_t * self); + + /** + * Create objects + * @param self Fragment instance + * @param container Container of the objects should be created upon + * @return Created object, NULL if multiple objects has been created + */ + lv_obj_t * (*create_obj_cb)(lv_fragment_t * self, lv_obj_t * container); + + /** + * + * @param self Fragment instance + * @param obj lv_obj returned by create_obj_cb + */ + void (*obj_created_cb)(lv_fragment_t * self, lv_obj_t * obj); + + /** + * Called before objects in the fragment will be deleted. + * + * @param self Fragment instance + * @param obj object with this fragment + */ + void (*obj_will_delete_cb)(lv_fragment_t * self, lv_obj_t * obj); + + /** + * Called when the object created by fragment received `LV_EVENT_DELETE` event + * @param self Fragment instance + * @param obj object with this fragment + */ + void (*obj_deleted_cb)(lv_fragment_t * self, lv_obj_t * obj); + + /** + * Handle event + * @param self Fragment instance + * @param which User-defined ID of event + * @param data1 User-defined data + * @param data2 User-defined data + */ + bool (*event_cb)(lv_fragment_t * self, int code, void * userdata); + + /** + * *REQUIRED*: Allocation size of fragment + */ + size_t instance_size; +}; + +/** + * Fragment states + */ +typedef struct _lv_fragment_managed_states_t { + /** + * Class of the fragment + */ + const lv_fragment_class_t * cls; + /** + * Manager the fragment attached to + */ + lv_fragment_manager_t * manager; + /** + * Container object the fragment adding view to + */ + lv_obj_t * const * container; + /** + * Fragment instance + */ + lv_fragment_t * instance; + /** + * true between `create_obj_cb` and `obj_deleted_cb` + */ + bool obj_created; + /** + * true before `lv_fragment_del_obj` is called. Don't touch any object if this is true + */ + bool destroying_obj; + /** + * true if this fragment is in navigation stack that can be popped + */ + bool in_stack; +} lv_fragment_managed_states_t; + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +/** + * Create fragment manager instance + * @param parent Parent fragment if this manager is placed inside another fragment, can be null. + * @return Fragment manager instance + */ +lv_fragment_manager_t * lv_fragment_manager_create(lv_fragment_t * parent); + +/** + * Destroy fragment manager instance + * @param manager Fragment manager instance + */ +void lv_fragment_manager_del(lv_fragment_manager_t * manager); + +/** + * Create object of all fragments managed by this manager. + * @param manager Fragment manager instance + */ +void lv_fragment_manager_create_obj(lv_fragment_manager_t * manager); + +/** + * Delete object created by all fragments managed by this manager. Instance of fragments will not be deleted. + * @param manager Fragment manager instance + */ +void lv_fragment_manager_del_obj(lv_fragment_manager_t * manager); + +/** + * Attach fragment to manager, and add to container. + * @param manager Fragment manager instance + * @param fragment Fragment instance + * @param container Pointer to container object for manager to add objects to + */ +void lv_fragment_manager_add(lv_fragment_manager_t * manager, lv_fragment_t * fragment, lv_obj_t * const * container); + +/** + * Detach and destroy fragment. If fragment is in navigation stack, remove from it. + * @param manager Fragment manager instance + * @param fragment Fragment instance + */ +void lv_fragment_manager_remove(lv_fragment_manager_t * manager, lv_fragment_t * fragment); + +/** + * Attach fragment to manager and add to navigation stack. + * @param manager Fragment manager instance + * @param fragment Fragment instance + * @param container Pointer to container object for manager to add objects to + */ +void lv_fragment_manager_push(lv_fragment_manager_t * manager, lv_fragment_t * fragment, lv_obj_t * const * container); + +/** + * Remove the top-most fragment for stack + * @param manager Fragment manager instance + * @return true if there is fragment to pop + */ +bool lv_fragment_manager_pop(lv_fragment_manager_t * manager); + +/** + * Replace fragment. Old item in the stack will be removed. + * @param manager Fragment manager instance + * @param fragment Fragment instance + * @param container Pointer to container object for manager to add objects to + */ +void lv_fragment_manager_replace(lv_fragment_manager_t * manager, lv_fragment_t * fragment, + lv_obj_t * const * container); + +/** + * Send event to top-most fragment + * @param manager Fragment manager instance + * @param code User-defined ID of event + * @param userdata User-defined data + * @return true if fragment returned true + */ +bool lv_fragment_manager_send_event(lv_fragment_manager_t * manager, int code, void * userdata); + +/** + * Get stack size of this fragment manager + * @param manager Fragment manager instance + * @return Stack size of this fragment manager + */ +size_t lv_fragment_manager_get_stack_size(lv_fragment_manager_t * manager); + +/** + * Get top most fragment instance + * @param manager Fragment manager instance + * @return Top most fragment instance + */ +lv_fragment_t * lv_fragment_manager_get_top(lv_fragment_manager_t * manager); + +/** + * Find first fragment instance in the container + * @param manager Fragment manager instance + * @param container Container which target fragment added to + * @return First fragment instance in the container + */ +lv_fragment_t * lv_fragment_manager_find_by_container(lv_fragment_manager_t * manager, const lv_obj_t * container); + +/** + * Get parent fragment + * @param manager Fragment manager instance + * @return Parent fragment instance + */ +lv_fragment_t * lv_fragment_manager_get_parent_fragment(lv_fragment_manager_t * manager); + + +/** + * Create a fragment instance. + * + * @param cls Fragment class. This fragment must return non null object. + * @param args Arguments assigned by fragment manager + * @return Fragment instance + */ +lv_fragment_t * lv_fragment_create(const lv_fragment_class_t * cls, void * args); + +/** + * Destroy a fragment. + * @param fragment Fragment instance. + */ +void lv_fragment_del(lv_fragment_t * fragment); + +/** + * Get associated manager of this fragment + * @param fragment Fragment instance + * @return Fragment manager instance + */ +lv_fragment_manager_t * lv_fragment_get_manager(lv_fragment_t * fragment); + +/** + * Get container object of this fragment + * @param fragment Fragment instance + * @return Reference to container object + */ +lv_obj_t * const * lv_fragment_get_container(lv_fragment_t * fragment); + +/** + * Get parent fragment of this fragment + * @param fragment Fragment instance + * @return Parent fragment + */ +lv_fragment_t * lv_fragment_get_parent(lv_fragment_t * fragment); + +/** + * Create object by fragment. + * + * @param fragment Fragment instance. + * @param container Container of the objects should be created upon. + * @return Created object + */ +lv_obj_t * lv_fragment_create_obj(lv_fragment_t * fragment, lv_obj_t * container); + +/** + * Delete created object of a fragment + * + * @param fragment Fragment instance. + */ +void lv_fragment_del_obj(lv_fragment_t * fragment); + +/** + * Destroy obj in fragment, and recreate them. + * @param fragment Fragment instance + */ +void lv_fragment_recreate_obj(lv_fragment_t * fragment); + + +/********************** + * MACROS + **********************/ + +#endif /*LV_USE_FRAGMENT*/ + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif /*LV_FRAGMENT_H*/ diff --git a/src/lib/lvgl/src/extra/others/gridnav/lv_gridnav.h b/src/lib/lvgl/src/extra/others/gridnav/lv_gridnav.h new file mode 100644 index 0000000..ea81595 --- /dev/null +++ b/src/lib/lvgl/src/extra/others/gridnav/lv_gridnav.h @@ -0,0 +1,115 @@ +/** + * @file lv_templ.c + * + */ + +/********************* + * INCLUDES + *********************/ + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +/*This typedef exists purely to keep -Wpedantic happy when the file is empty.*/ +/*It can be removed.*/ +typedef int _keep_pedantic_happy; + +/********************** + * STATIC PROTOTYPES + **********************/ + +/********************** + * STATIC VARIABLES + **********************/ + +/********************** + * MACROS + **********************/ + +/********************** + * GLOBAL FUNCTIONS + **********************/ + +/********************** + * STATIC FUNCTIONS + **********************/ +/** + * @file lv_gridnav.h + * + */ + +#ifndef LV_GRIDFOCUS_H +#define LV_GRIDFOCUS_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include "../../../core/lv_obj.h" + +#if LV_USE_GRIDNAV + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ +typedef enum { + LV_GRIDNAV_CTRL_NONE = 0x0, + + /** + * If there is no next/previous object in a direction, + * the focus goes to the object in the next/previous row (on left/right keys) + * or first/last row (on up/down keys) + */ + LV_GRIDNAV_CTRL_ROLLOVER = 0x1, + + /** + * If an arrow is pressed and the focused object can be scrolled in that direction + * then it will be scrolled instead of going to the next/previous object. + * If there is no more room for scrolling the next/previous object will be focused normally */ + LV_GRIDNAV_CTRL_SCROLL_FIRST = 0x2, + +} lv_gridnav_ctrl_t; + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +/** + * Add grid navigation feature to an object. It expects the children to be arranged + * into a grid-like layout. Although it's not required to have pixel perfect alignment. + * This feature makes possible to use keys to navigate among the children and focus them. + * The keys other than arrows and press/release related events + * are forwarded to the focused child. + * @param obj pointer to an object on which navigation should be applied. + * @param ctrl control flags from `lv_gridnav_ctrl_t`. + */ +void lv_gridnav_add(lv_obj_t * obj, lv_gridnav_ctrl_t ctrl); + +/** + * Remove the grid navigation support from an object + * @param obj pointer to an object + */ +void lv_gridnav_remove(lv_obj_t * obj); + +/********************** + * MACROS + **********************/ +#endif /*LV_USE_GRIDNAV*/ + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif /*LV_GRIDFOCUS_H*/ diff --git a/src/lib/lvgl/src/extra/others/imgfont/lv_imgfont.h b/src/lib/lvgl/src/extra/others/imgfont/lv_imgfont.h new file mode 100644 index 0000000..5069b62 --- /dev/null +++ b/src/lib/lvgl/src/extra/others/imgfont/lv_imgfont.h @@ -0,0 +1,60 @@ +/** + * @file lv_imgfont.h + * + */ + +#ifndef LV_IMGFONT_H +#define LV_IMGFONT_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include "../../../lvgl.h" + +#if LV_USE_IMGFONT + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +/* gets the image path name of this character */ +typedef bool (*lv_get_imgfont_path_cb_t)(const lv_font_t * font, void * img_src, + uint16_t len, uint32_t unicode, uint32_t unicode_next); + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +/** + * Creates a image font with info parameter specified. + * @param height font size + * @param path_cb a function to get the image path name of character. + * @return pointer to the new imgfont or NULL if create error. + */ +lv_font_t * lv_imgfont_create(uint16_t height, lv_get_imgfont_path_cb_t path_cb); + +/** + * Destroy a image font that has been created. + * @param font pointer to image font handle. + */ +void lv_imgfont_destroy(lv_font_t * font); + +/********************** + * MACROS + **********************/ + +#endif /*LV_USE_IMGFONT*/ + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif /* LV_IMGFONT_H */ diff --git a/src/lib/lvgl/src/extra/others/lv_others.h b/src/lib/lvgl/src/extra/others/lv_others.h new file mode 100644 index 0000000..a433866 --- /dev/null +++ b/src/lib/lvgl/src/extra/others/lv_others.h @@ -0,0 +1,40 @@ +/** + * @file lv_others.h + * + */ + +#ifndef LV_OTHERS_H +#define LV_OTHERS_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include "snapshot/lv_snapshot.h" +#include "monkey/lv_monkey.h" +#include "gridnav/lv_gridnav.h" + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +/********************** + * MACROS + **********************/ + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif /*LV_OTHERS_H*/ diff --git a/src/lib/lvgl/src/extra/others/monkey/lv_monkey.h b/src/lib/lvgl/src/extra/others/monkey/lv_monkey.h new file mode 100755 index 0000000..bf5e13c --- /dev/null +++ b/src/lib/lvgl/src/extra/others/monkey/lv_monkey.h @@ -0,0 +1,118 @@ +/** + * @file lv_monkey.h + * + */ +#ifndef LV_MONKEY_H +#define LV_MONKEY_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include "../../../lvgl.h" + +#if LV_USE_MONKEY != 0 + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ +struct _lv_monkey; +typedef struct _lv_monkey lv_monkey_t; + +typedef struct { + /**< Input device type*/ + lv_indev_type_t type; + + /**< Monkey execution period*/ + struct { + uint32_t min; + uint32_t max; + } period_range; + + /**< The range of input value*/ + struct { + int32_t min; + int32_t max; + } input_range; +} lv_monkey_config_t; + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +/** + * Initialize a monkey config with default values + * @param config pointer to 'lv_monkey_config_t' variable to initialize + */ +void lv_monkey_config_init(lv_monkey_config_t * config); + +/** + * Create monkey for test + * @param config pointer to 'lv_monkey_config_t' variable + * @return pointer to the created monkey + */ +lv_monkey_t * lv_monkey_create(const lv_monkey_config_t * config); + +/** + * Get monkey input device + * @param monkey pointer to a monkey + * @return pointer to the input device + */ +lv_indev_t * lv_monkey_get_indev(lv_monkey_t * monkey); + +/** + * Enable monkey + * @param monkey pointer to a monkey + * @param en set to true to enable + */ +void lv_monkey_set_enable(lv_monkey_t * monkey, bool en); + +/** + * Get whether monkey is enabled + * @param monkey pointer to a monkey + * @return return true if monkey enabled + */ +bool lv_monkey_get_enable(lv_monkey_t * monkey); + +#if LV_USE_USER_DATA + +/** + * Set the user_data field of the monkey + * @param monkey pointer to a monkey + * @param user_data pointer to the new user_data. + */ +void lv_monkey_set_user_data(lv_monkey_t * monkey, void * user_data); + +/** + * Get the user_data field of the monkey + * @param monkey pointer to a monkey + * @return the pointer to the user_data of the monkey + */ +void * lv_monkey_get_user_data(lv_monkey_t * monkey); + +#endif/*LV_USE_USER_DATA*/ + +/** + * Delete monkey + * @param monkey pointer to monkey + */ +void lv_monkey_del(lv_monkey_t * monkey); + +/********************** + * MACROS + **********************/ + +#endif /*LV_USE_MONKEY*/ + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif /*LV_MONKEY_H*/ diff --git a/src/lib/lvgl/src/extra/others/snapshot/lv_snapshot.h b/src/lib/lvgl/src/extra/others/snapshot/lv_snapshot.h new file mode 100644 index 0000000..6451926 --- /dev/null +++ b/src/lib/lvgl/src/extra/others/snapshot/lv_snapshot.h @@ -0,0 +1,84 @@ +/** + * @file lv_snapshot.h + * + */ + +#ifndef LV_SNAPSHOT_H +#define LV_SNAPSHOT_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include +#include + +#include "../../../lv_conf_internal.h" +#include "../../../core/lv_obj.h" + +/********************* + * DEFINES + *********************/ + +#if LV_USE_SNAPSHOT +/********************** + * TYPEDEFS + **********************/ + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +/** Take snapshot for object with its children. + * + * @param obj The object to generate snapshot. + * @param cf color format for generated image. + * + * @return a pointer to an image descriptor, or NULL if failed. + */ +lv_img_dsc_t * lv_snapshot_take(lv_obj_t * obj, lv_img_cf_t cf); + +/** Free the snapshot image returned by @ref lv_snapshot_take + * + * It will firstly free the data image takes, then the image descriptor. + * + * @param dsc The image descriptor generated by lv_snapshot_take. + * + */ +void lv_snapshot_free(lv_img_dsc_t * dsc); + +/** Get the buffer needed for object snapshot image. + * + * @param obj The object to generate snapshot. + * @param cf color format for generated image. + * + * @return the buffer size needed in bytes + */ +uint32_t lv_snapshot_buf_size_needed(lv_obj_t * obj, lv_img_cf_t cf); + +/** Take snapshot for object with its children, save image info to provided buffer. + * + * @param obj The object to generate snapshot. + * @param cf color format for generated image. + * @param dsc image descriptor to store the image result. + * @param buff the buffer to store image data. + * @param buff_size provided buffer size in bytes. + * + * @return LV_RES_OK on success, LV_RES_INV on error. + */ +lv_res_t lv_snapshot_take_to_buf(lv_obj_t * obj, lv_img_cf_t cf, lv_img_dsc_t * dsc, void * buf, uint32_t buff_size); + + +/********************** + * MACROS + **********************/ +#endif /*LV_USE_SNAPSHOT*/ + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif diff --git a/src/lib/lvgl/src/extra/themes/basic/lv_theme_basic.h b/src/lib/lvgl/src/extra/themes/basic/lv_theme_basic.h new file mode 100644 index 0000000..93a8fa8 --- /dev/null +++ b/src/lib/lvgl/src/extra/themes/basic/lv_theme_basic.h @@ -0,0 +1,55 @@ +/** + * @file lv_theme_basic.h + * + */ + +#ifndef LV_THEME_BASIC_H +#define LV_THEME_BASIC_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include "../../../core/lv_obj.h" + +#if LV_USE_THEME_BASIC + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +/** + * Initialize the theme + * @param disp pointer to display to attach the theme + * @return a pointer to reference this theme later + */ +lv_theme_t * lv_theme_basic_init(lv_disp_t * disp); + +/** +* Check if the theme is initialized +* @return true if default theme is initialized, false otherwise +*/ +bool lv_theme_basic_is_inited(void); + +/********************** + * MACROS + **********************/ + +#endif + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif /*LV_THEME_BASIC_H*/ diff --git a/src/lib/lvgl/src/extra/themes/default/lv_theme_default.h b/src/lib/lvgl/src/extra/themes/default/lv_theme_default.h new file mode 100644 index 0000000..5b1fd91 --- /dev/null +++ b/src/lib/lvgl/src/extra/themes/default/lv_theme_default.h @@ -0,0 +1,64 @@ +/** + * @file lv_theme_default.h + * + */ + +#ifndef LV_THEME_DEFAULT_H +#define LV_THEME_DEFAULT_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include "../../../core/lv_obj.h" + +#if LV_USE_THEME_DEFAULT + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +/** + * Initialize the theme + * @param color_primary the primary color of the theme + * @param color_secondary the secondary color for the theme + * @param font pointer to a font to use. + * @return a pointer to reference this theme later + */ +lv_theme_t * lv_theme_default_init(lv_disp_t * disp, lv_color_t color_primary, lv_color_t color_secondary, bool dark, + const lv_font_t * font); + +/** + * Get default theme + * @return a pointer to default theme, or NULL if this is not initialized + */ +lv_theme_t * lv_theme_default_get(void); + +/** + * Check if default theme is initialized + * @return true if default theme is initialized, false otherwise + */ +bool lv_theme_default_is_inited(void); + +/********************** + * MACROS + **********************/ + +#endif + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif /*LV_THEME_DEFAULT_H*/ diff --git a/src/lib/lvgl/src/extra/themes/lv_themes.h b/src/lib/lvgl/src/extra/themes/lv_themes.h new file mode 100644 index 0000000..372f626 --- /dev/null +++ b/src/lib/lvgl/src/extra/themes/lv_themes.h @@ -0,0 +1,40 @@ +/** + * @file lv_themes.h + * + */ + +#ifndef LV_THEMES_H +#define LV_THEMES_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include "default/lv_theme_default.h" +#include "mono/lv_theme_mono.h" +#include "basic/lv_theme_basic.h" + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +/********************** + * MACROS + **********************/ + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif /*LV_THEMES_H*/ diff --git a/src/lib/lvgl/src/extra/themes/mono/lv_theme_mono.h b/src/lib/lvgl/src/extra/themes/mono/lv_theme_mono.h new file mode 100644 index 0000000..10b8f18 --- /dev/null +++ b/src/lib/lvgl/src/extra/themes/mono/lv_theme_mono.h @@ -0,0 +1,57 @@ +/** + * @file lv_theme_mono.h + * + */ + +#ifndef LV_USE_THEME_MONO_H +#define LV_USE_THEME_MONO_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include "../../../core/lv_obj.h" + +#if LV_USE_THEME_MONO + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +/** + * Initialize the theme + * @param color_primary the primary color of the theme + * @param color_secondary the secondary color for the theme + * @param font pointer to a font to use. + * @return a pointer to reference this theme later + */ +lv_theme_t * lv_theme_mono_init(lv_disp_t * disp, bool dark_bg, const lv_font_t * font); + +/** +* Check if the theme is initialized +* @return true if default theme is initialized, false otherwise +*/ +bool lv_theme_mono_is_inited(void); + +/********************** + * MACROS + **********************/ + +#endif + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif /*LV_USE_THEME_MONO_H*/ diff --git a/src/lib/lvgl/src/extra/widgets/animimg/lv_animimg.h b/src/lib/lvgl/src/extra/widgets/animimg/lv_animimg.h new file mode 100644 index 0000000..6329494 --- /dev/null +++ b/src/lib/lvgl/src/extra/widgets/animimg/lv_animimg.h @@ -0,0 +1,103 @@ +/** + * @file lv_animimg.h + * + */ + +#ifndef LV_ANIM_IMG_H +#define LV_ANIM_IMG_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include "../../../lvgl.h" + +#if LV_USE_ANIMIMG != 0 + +/*Testing of dependencies*/ +#if LV_USE_IMG == 0 +#error "lv_animimg: lv_img is required. Enable it in lv_conf.h (LV_USE_IMG 1)" +#endif + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +extern const lv_obj_class_t lv_animimg_class; + +/*Data of image*/ +typedef struct { + lv_img_t img; + lv_anim_t anim; + /*picture sequence */ + lv_img_dsc_t ** dsc; + int8_t pic_count; +} lv_animimg_t; + + +/*Image parts*/ +enum { + LV_ANIM_IMG_PART_MAIN, +}; +typedef uint8_t lv_animimg_part_t; + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +/** + * Create an animation image objects + * @param parent pointer to an object, it will be the parent of the new button + * @return pointer to the created animation image object + */ +lv_obj_t * lv_animimg_create(lv_obj_t * parent); + +/*===================== + * Setter functions + *====================*/ + +/** + * Set the image animation images source. + * @param img pointer to an animation image object + * @param dsc pointer to a series images + * @param num images' number + */ +void lv_animimg_set_src(lv_obj_t * img, lv_img_dsc_t * dsc[], uint8_t num); + +/** + * Startup the image animation. + * @param obj pointer to an animation image object + */ +void lv_animimg_start(lv_obj_t * obj); + +/** + * Set the image animation duration time. unit:ms + * @param img pointer to an animation image object + */ +void lv_animimg_set_duration(lv_obj_t * img, uint32_t duration); + +/** + * Set the image animation reapeatly play times. + * @param img pointer to an animation image object + * @param count the number of times to repeat the animation + */ +void lv_animimg_set_repeat_count(lv_obj_t * img, uint16_t count); + +/*===================== + * Getter functions + *====================*/ + +#endif /*LV_USE_ANIMIMG*/ + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /*LV_ANIM_IMG_H*/ diff --git a/src/lib/lvgl/src/extra/widgets/calendar/lv_calendar.h b/src/lib/lvgl/src/extra/widgets/calendar/lv_calendar.h new file mode 100644 index 0000000..2511b2f --- /dev/null +++ b/src/lib/lvgl/src/extra/widgets/calendar/lv_calendar.h @@ -0,0 +1,164 @@ +/** + * @file lv_calendar.h + * + */ + +#ifndef LV_CALENDAR_H +#define LV_CALENDAR_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include "../../../widgets/lv_btnmatrix.h" + +#if LV_USE_CALENDAR + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +/** + * Represents a date on the calendar object (platform-agnostic). + */ +typedef struct { + uint16_t year; + int8_t month; /** 1..12*/ + int8_t day; /** 1..31*/ +} lv_calendar_date_t; + +/*Data of calendar*/ +typedef struct { + lv_obj_t obj; + lv_obj_t * btnm; + /*New data for this type*/ + lv_calendar_date_t today; /*Date of today*/ + lv_calendar_date_t showed_date; /*Currently visible month (day is ignored)*/ + lv_calendar_date_t * + highlighted_dates; /*Apply different style on these days (pointer to an array defined by the user)*/ + uint16_t highlighted_dates_num; /*Number of elements in `highlighted_days`*/ + const char * map[8 * 7]; + char nums [7 * 6][4]; +} lv_calendar_t; + +extern const lv_obj_class_t lv_calendar_class; + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +lv_obj_t * lv_calendar_create(lv_obj_t * parent); + +/*====================== + * Add/remove functions + *=====================*/ + +/*===================== + * Setter functions + *====================*/ + +/** + * Set the today's date + * @param obj pointer to a calendar object + * @param year today's year + * @param month today's month [1..12] + * @param day today's day [1..31] + */ +void lv_calendar_set_today_date(lv_obj_t * obj, uint32_t year, uint32_t month, uint32_t day); + +/** + * Set the currently showed + * @param obj pointer to a calendar object + * @param year today's year + * @param month today's month [1..12] + */ +void lv_calendar_set_showed_date(lv_obj_t * obj, uint32_t year, uint32_t month); + +/** + * Set the highlighted dates + * @param obj pointer to a calendar object + * @param highlighted pointer to an `lv_calendar_date_t` array containing the dates. + * Only the pointer will be saved so this variable can't be local which will be destroyed later. + * @param date_num number of dates in the array + */ +void lv_calendar_set_highlighted_dates(lv_obj_t * obj, lv_calendar_date_t highlighted[], uint16_t date_num); + +/** + * Set the name of the days + * @param obj pointer to a calendar object + * @param day_names pointer to an array with the names. + * E.g. `const char * days[7] = {"Sun", "Mon", ...}` + * Only the pointer will be saved so this variable can't be local which will be destroyed later. + */ +void lv_calendar_set_day_names(lv_obj_t * obj, const char ** day_names); + +/*===================== + * Getter functions + *====================*/ + +/** + * Get the button matrix object of the calendar. + * It shows the dates and day names. + * @param obj pointer to a calendar object + * @return pointer to a the button matrix + */ +lv_obj_t * lv_calendar_get_btnmatrix(const lv_obj_t * obj); + +/** + * Get the today's date + * @param calendar pointer to a calendar object + * @return return pointer to an `lv_calendar_date_t` variable containing the date of today. + */ +const lv_calendar_date_t * lv_calendar_get_today_date(const lv_obj_t * calendar); + +/** + * Get the currently showed + * @param calendar pointer to a calendar object + * @return pointer to an `lv_calendar_date_t` variable containing the date is being shown. + */ +const lv_calendar_date_t * lv_calendar_get_showed_date(const lv_obj_t * calendar); + +/** + * Get the highlighted dates + * @param calendar pointer to a calendar object + * @return pointer to an `lv_calendar_date_t` array containing the dates. + */ +lv_calendar_date_t * lv_calendar_get_highlighted_dates(const lv_obj_t * calendar); + +/** + * Get the number of the highlighted dates + * @param calendar pointer to a calendar object + * @return number of highlighted days + */ +uint16_t lv_calendar_get_highlighted_dates_num(const lv_obj_t * calendar); + +/** + * Get the currently pressed day + * @param calendar pointer to a calendar object + * @param date store the pressed date here + * @return LV_RES_OK: there is a valid pressed date; LV_RES_INV: there is no pressed data + */ +lv_res_t lv_calendar_get_pressed_date(const lv_obj_t * calendar, lv_calendar_date_t * date); + +/*===================== + * Other functions + *====================*/ + +/********************** + * MACROS + **********************/ + +#endif /*LV_USE_CALENDAR*/ + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif /*LV_CALENDAR_H*/ diff --git a/src/lib/lvgl/src/extra/widgets/calendar/lv_calendar_header_arrow.h b/src/lib/lvgl/src/extra/widgets/calendar/lv_calendar_header_arrow.h new file mode 100644 index 0000000..609ccb0 --- /dev/null +++ b/src/lib/lvgl/src/extra/widgets/calendar/lv_calendar_header_arrow.h @@ -0,0 +1,49 @@ +/** + * @file lv_calendar_header_arrow.h + * + */ + +#ifndef LV_CALENDAR_HEADER_ARROW_H +#define LV_CALENDAR_HEADER_ARROW_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include "../../../core/lv_obj.h" +#if LV_USE_CALENDAR_HEADER_ARROW + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ +extern const lv_obj_class_t lv_calendar_header_arrow_class; + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +/** + * Create a calendar header with drop-drowns to select the year and month + * @param parent pointer to a calendar object. + * @return the created header + */ +lv_obj_t * lv_calendar_header_arrow_create(lv_obj_t * parent); + +/********************** + * MACROS + **********************/ + +#endif /*LV_USE_CALENDAR_HEADER_ARROW*/ + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif /*LV_CALENDAR_HEADER_ARROW_H*/ diff --git a/src/lib/lvgl/src/extra/widgets/calendar/lv_calendar_header_dropdown.h b/src/lib/lvgl/src/extra/widgets/calendar/lv_calendar_header_dropdown.h new file mode 100644 index 0000000..fca2197 --- /dev/null +++ b/src/lib/lvgl/src/extra/widgets/calendar/lv_calendar_header_dropdown.h @@ -0,0 +1,49 @@ +/** + * @file lv_calendar_header_dropdown.h + * + */ + +#ifndef LV_CALENDAR_HEADER_DROPDOWN_H +#define LV_CALENDAR_HEADER_DROPDOWN_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include "../../../core/lv_obj.h" +#if LV_USE_CALENDAR_HEADER_DROPDOWN + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ +extern const lv_obj_class_t lv_calendar_header_dropdown_class; + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +/** + * Create a calendar header with drop-drowns to select the year and month + * @param parent pointer to a calendar object. + * @return the created header + */ +lv_obj_t * lv_calendar_header_dropdown_create(lv_obj_t * parent); + +/********************** + * MACROS + **********************/ + +#endif /*LV_USE_CALENDAR_HEADER_ARROW*/ + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif /*LV_CALENDAR_HEADER_DROPDOWN_H*/ diff --git a/src/lib/lvgl/src/extra/widgets/chart/lv_chart.h b/src/lib/lvgl/src/extra/widgets/chart/lv_chart.h new file mode 100644 index 0000000..8a9b8cf --- /dev/null +++ b/src/lib/lvgl/src/extra/widgets/chart/lv_chart.h @@ -0,0 +1,456 @@ +/** + * @file lv_chart.h + * + */ + +#ifndef LV_CHART_H +#define LV_CHART_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include "../../../lvgl.h" + +#if LV_USE_CHART != 0 + +/********************* + * DEFINES + *********************/ + +/**Default value of points. Can be used to not draw a point*/ +#define LV_CHART_POINT_NONE (INT16_MAX) +LV_EXPORT_CONST_INT(LV_CHART_POINT_NONE); + +/********************** + * TYPEDEFS + **********************/ + +/** + * Chart types + */ +enum { + LV_CHART_TYPE_NONE, /**< Don't draw the series*/ + LV_CHART_TYPE_LINE, /**< Connect the points with lines*/ + LV_CHART_TYPE_BAR, /**< Draw columns*/ + LV_CHART_TYPE_SCATTER, /**< Draw points and lines in 2D (x,y coordinates)*/ +}; +typedef uint8_t lv_chart_type_t; + +/** + * Chart update mode for `lv_chart_set_next` + */ +enum { + LV_CHART_UPDATE_MODE_SHIFT, /**< Shift old data to the left and add the new one the right*/ + LV_CHART_UPDATE_MODE_CIRCULAR, /**< Add the new data in a circular way*/ +}; +typedef uint8_t lv_chart_update_mode_t; + +/** + * Enumeration of the axis' + */ +enum { + LV_CHART_AXIS_PRIMARY_Y = 0x00, + LV_CHART_AXIS_SECONDARY_Y = 0x01, + LV_CHART_AXIS_PRIMARY_X = 0x02, + LV_CHART_AXIS_SECONDARY_X = 0x04, + _LV_CHART_AXIS_LAST +}; +typedef uint8_t lv_chart_axis_t; + +/** + * Descriptor a chart series + */ +typedef struct { + lv_coord_t * x_points; + lv_coord_t * y_points; + lv_color_t color; + uint16_t start_point; + uint8_t hidden : 1; + uint8_t x_ext_buf_assigned : 1; + uint8_t y_ext_buf_assigned : 1; + uint8_t x_axis_sec : 1; + uint8_t y_axis_sec : 1; +} lv_chart_series_t; + +typedef struct { + lv_point_t pos; + uint16_t point_id; + lv_color_t color; + lv_chart_series_t * ser; + lv_dir_t dir; + uint8_t pos_set: 1; /*1: pos is set; 0: point_id is set*/ +} lv_chart_cursor_t; + +typedef struct { + lv_coord_t major_len; + lv_coord_t minor_len; + lv_coord_t draw_size; + uint32_t minor_cnt : 15; + uint32_t major_cnt : 15; + uint32_t label_en : 1; +} lv_chart_tick_dsc_t; + + +typedef struct { + lv_obj_t obj; + lv_ll_t series_ll; /**< Linked list for the series (stores lv_chart_series_t)*/ + lv_ll_t cursor_ll; /**< Linked list for the cursors (stores lv_chart_cursor_t)*/ + lv_chart_tick_dsc_t tick[4]; + lv_coord_t ymin[2]; + lv_coord_t ymax[2]; + lv_coord_t xmin[2]; + lv_coord_t xmax[2]; + uint16_t pressed_point_id; + uint16_t hdiv_cnt; /**< Number of horizontal division lines*/ + uint16_t vdiv_cnt; /**< Number of vertical division lines*/ + uint16_t point_cnt; /**< Point number in a data line*/ + uint16_t zoom_x; + uint16_t zoom_y; + lv_chart_type_t type : 3; /**< Line or column chart*/ + lv_chart_update_mode_t update_mode : 1; +} lv_chart_t; + +extern const lv_obj_class_t lv_chart_class; + +/** + * `type` field in `lv_obj_draw_part_dsc_t` if `class_p = lv_chart_class` + * Used in `LV_EVENT_DRAW_PART_BEGIN` and `LV_EVENT_DRAW_PART_END` + */ +typedef enum { + LV_CHART_DRAW_PART_DIV_LINE_INIT, /**< Used before/after drawn the div lines*/ + LV_CHART_DRAW_PART_DIV_LINE_HOR, /**< Used for each horizontal division lines*/ + LV_CHART_DRAW_PART_DIV_LINE_VER, /**< Used for each vertical division lines*/ + LV_CHART_DRAW_PART_LINE_AND_POINT, /**< Used on line and scatter charts for lines and points*/ + LV_CHART_DRAW_PART_BAR, /**< Used on bar charts for the rectangles*/ + LV_CHART_DRAW_PART_CURSOR, /**< Used on cursor lines and points*/ + LV_CHART_DRAW_PART_TICK_LABEL, /**< Used on tick lines and labels*/ +} lv_chart_draw_part_type_t; + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +/** + * Create a chart object + * @param parent pointer to an object, it will be the parent of the new chart + * @return pointer to the created chart + */ +lv_obj_t * lv_chart_create(lv_obj_t * parent); + +/** + * Set a new type for a chart + * @param obj pointer to a chart object + * @param type new type of the chart (from 'lv_chart_type_t' enum) + */ +void lv_chart_set_type(lv_obj_t * obj, lv_chart_type_t type); +/** + * Set the number of points on a data line on a chart + * @param obj pointer to a chart object + * @param cnt new number of points on the data lines + */ +void lv_chart_set_point_count(lv_obj_t * obj, uint16_t cnt); + +/** + * Set the minimal and maximal y values on an axis + * @param obj pointer to a chart object + * @param axis `LV_CHART_AXIS_PRIMARY_Y` or `LV_CHART_AXIS_SECONDARY_Y` + * @param min minimum value of the y axis + * @param max maximum value of the y axis + */ +void lv_chart_set_range(lv_obj_t * obj, lv_chart_axis_t axis, lv_coord_t min, lv_coord_t max); + +/** + * Set update mode of the chart object. Affects + * @param obj pointer to a chart object + * @param mode the update mode + */ +void lv_chart_set_update_mode(lv_obj_t * obj, lv_chart_update_mode_t update_mode); + +/** + * Set the number of horizontal and vertical division lines + * @param obj pointer to a chart object + * @param hdiv number of horizontal division lines + * @param vdiv number of vertical division lines + */ +void lv_chart_set_div_line_count(lv_obj_t * obj, uint8_t hdiv, uint8_t vdiv); + +/** + * Zoom into the chart in X direction + * @param obj pointer to a chart object + * @param zoom_x zoom in x direction. LV_ZOOM_NONE or 256 for no zoom, 512 double zoom + */ +void lv_chart_set_zoom_x(lv_obj_t * obj, uint16_t zoom_x); + +/** + * Zoom into the chart in Y direction + * @param obj pointer to a chart object + * @param zoom_y zoom in y direction. LV_ZOOM_NONE or 256 for no zoom, 512 double zoom + */ +void lv_chart_set_zoom_y(lv_obj_t * obj, uint16_t zoom_y); + +/** + * Get X zoom of a chart + * @param obj pointer to a chart object + * @return the X zoom value + */ +uint16_t lv_chart_get_zoom_x(const lv_obj_t * obj); + +/** + * Get Y zoom of a chart + * @param obj pointer to a chart object + * @return the Y zoom value + */ +uint16_t lv_chart_get_zoom_y(const lv_obj_t * obj); + +/** + * Set the number of tick lines on an axis + * @param obj pointer to a chart object + * @param axis an axis which ticks count should be set + * @param major_len length of major ticks + * @param minor_len length of minor ticks + * @param major_cnt number of major ticks on the axis + * @param minor_cnt number of minor ticks between two major ticks + * @param label_en true: enable label drawing on major ticks + * @param draw_size extra size required to draw the tick and labels + * (start with 20 px and increase if the ticks/labels are clipped) + */ +void lv_chart_set_axis_tick(lv_obj_t * obj, lv_chart_axis_t axis, lv_coord_t major_len, lv_coord_t minor_len, + lv_coord_t major_cnt, lv_coord_t minor_cnt, bool label_en, lv_coord_t draw_size); + +/** + * Get the type of a chart + * @param obj pointer to chart object + * @return type of the chart (from 'lv_chart_t' enum) + */ +lv_chart_type_t lv_chart_get_type(const lv_obj_t * obj); + +/** + * Get the data point number per data line on chart + * @param chart pointer to chart object + * @return point number on each data line + */ +uint16_t lv_chart_get_point_count(const lv_obj_t * obj); + +/** + * Get the current index of the x-axis start point in the data array + * @param chart pointer to a chart object + * @param ser pointer to a data series on 'chart' + * @return the index of the current x start point in the data array + */ +uint16_t lv_chart_get_x_start_point(const lv_obj_t * obj, lv_chart_series_t * ser); + +/** + * Get the position of a point to the chart. + * @param chart pointer to a chart object + * @param ser pointer to series + * @param id the index. + * @param p_out store the result position here + */ +void lv_chart_get_point_pos_by_id(lv_obj_t * obj, lv_chart_series_t * ser, uint16_t id, lv_point_t * p_out); + +/** + * Refresh a chart if its data line has changed + * @param chart pointer to chart object + */ +void lv_chart_refresh(lv_obj_t * obj); + +/*====================== + * Series + *=====================*/ + +/** + * Allocate and add a data series to the chart + * @param obj pointer to a chart object + * @param color color of the data series + * @param axis the y axis to which the series should be attached (::LV_CHART_AXIS_PRIMARY_Y or ::LV_CHART_AXIS_SECONDARY_Y) + * @return pointer to the allocated data series + */ +lv_chart_series_t * lv_chart_add_series(lv_obj_t * obj, lv_color_t color, lv_chart_axis_t axis); + +/** + * Deallocate and remove a data series from a chart + * @param chart pointer to a chart object + * @param series pointer to a data series on 'chart' + */ +void lv_chart_remove_series(lv_obj_t * obj, lv_chart_series_t * series); + +/** + * Hide/Unhide a single series of a chart. + * @param obj pointer to a chart object. + * @param series pointer to a series object + * @param hide true: hide the series + */ +void lv_chart_hide_series(lv_obj_t * chart, lv_chart_series_t * series, bool hide); + +/** + * Change the color of a series + * @param obj pointer to a chart object. + * @param series pointer to a series object + * @param color the new color of the series + */ +void lv_chart_set_series_color(lv_obj_t * chart, lv_chart_series_t * series, lv_color_t color); + +/** + * Set the index of the x-axis start point in the data array. + * This point will be considers the first (left) point and the other points will be drawn after it. + * @param obj pointer to a chart object + * @param ser pointer to a data series on 'chart' + * @param id the index of the x point in the data array + */ +void lv_chart_set_x_start_point(lv_obj_t * obj, lv_chart_series_t * ser, uint16_t id); + +/** + * Get the next series. + * @param chart pointer to a chart + * @param ser the previous series or NULL to get the first + * @return the next series or NULL if there is no more. + */ +lv_chart_series_t * lv_chart_get_series_next(const lv_obj_t * chart, const lv_chart_series_t * ser); + + + +/*===================== + * Cursor + *====================*/ + +/** + * Add a cursor with a given color + * @param obj pointer to chart object + * @param color color of the cursor + * @param dir direction of the cursor. `LV_DIR_RIGHT/LEFT/TOP/DOWN/HOR/VER/ALL`. OR-ed values are possible + * @return pointer to the created cursor + */ +lv_chart_cursor_t * lv_chart_add_cursor(lv_obj_t * obj, lv_color_t color, lv_dir_t dir); + +/** + * Set the coordinate of the cursor with respect to the paddings + * @param obj pointer to a chart object + * @param cursor pointer to the cursor + * @param pos the new coordinate of cursor relative to the chart + */ +void lv_chart_set_cursor_pos(lv_obj_t * chart, lv_chart_cursor_t * cursor, lv_point_t * pos); + +/** + * Stick the cursor to a point + * @param obj pointer to a chart object + * @param cursor pointer to the cursor + * @param ser pointer to a series + * @param point_id the point's index or `LV_CHART_POINT_NONE` to not assign to any points. + */ +void lv_chart_set_cursor_point(lv_obj_t * chart, lv_chart_cursor_t * cursor, lv_chart_series_t * ser, + uint16_t point_id); + +/** + * Get the coordinate of the cursor with respect to the paddings + * @param obj pointer to a chart object + * @param cursor pointer to cursor + * @return coordinate of the cursor as lv_point_t + */ +lv_point_t lv_chart_get_cursor_point(lv_obj_t * chart, lv_chart_cursor_t * cursor); + +/*===================== + * Set/Get value(s) + *====================*/ + +/** + * Initialize all data points of a series with a value + * @param obj pointer to chart object + * @param ser pointer to a data series on 'chart' + * @param value the new value for all points. `LV_CHART_POINT_NONE` can be used to hide the points. + */ +void lv_chart_set_all_value(lv_obj_t * obj, lv_chart_series_t * ser, lv_coord_t value); + +/** + * Set the next point's Y value according to the update mode policy. + * @param obj pointer to chart object + * @param ser pointer to a data series on 'chart' + * @param value the new value of the next data + */ +void lv_chart_set_next_value(lv_obj_t * obj, lv_chart_series_t * ser, lv_coord_t value); + +/** + * Set the next point's X and Y value according to the update mode policy. + * @param obj pointer to chart object + * @param ser pointer to a data series on 'chart' + * @param x_value the new X value of the next data + * @param y_value the new Y value of the next data + */ +void lv_chart_set_next_value2(lv_obj_t * obj, lv_chart_series_t * ser, lv_coord_t x_value, lv_coord_t y_value); + +/** + * Set an individual point's y value of a chart's series directly based on its index + * @param obj pointer to a chart object + * @param ser pointer to a data series on 'chart' + * @param id the index of the x point in the array + * @param value value to assign to array point + */ +void lv_chart_set_value_by_id(lv_obj_t * obj, lv_chart_series_t * ser, uint16_t id, lv_coord_t value); + +/** + * Set an individual point's x and y value of a chart's series directly based on its index + * Can be used only with `LV_CHART_TYPE_SCATTER`. + * @param obj pointer to chart object + * @param ser pointer to a data series on 'chart' + * @param id the index of the x point in the array + * @param x_value the new X value of the next data + * @param y_value the new Y value of the next data + */ +void lv_chart_set_value_by_id2(lv_obj_t * obj, lv_chart_series_t * ser, uint16_t id, lv_coord_t x_value, + lv_coord_t y_value); + +/** + * Set an external array for the y data points to use for the chart + * NOTE: It is the users responsibility to make sure the `point_cnt` matches the external array size. + * @param obj pointer to a chart object + * @param ser pointer to a data series on 'chart' + * @param array external array of points for chart + */ +void lv_chart_set_ext_y_array(lv_obj_t * obj, lv_chart_series_t * ser, lv_coord_t array[]); + +/** + * Set an external array for the x data points to use for the chart + * NOTE: It is the users responsibility to make sure the `point_cnt` matches the external array size. + * @param obj pointer to a chart object + * @param ser pointer to a data series on 'chart' + * @param array external array of points for chart + */ +void lv_chart_set_ext_x_array(lv_obj_t * obj, lv_chart_series_t * ser, lv_coord_t array[]); + +/** + * Get the array of y values of a series + * @param obj pointer to a chart object + * @param ser pointer to a data series on 'chart' + * @return the array of values with 'point_count' elements + */ +lv_coord_t * lv_chart_get_y_array(const lv_obj_t * obj, lv_chart_series_t * ser); + +/** + * Get the array of x values of a series + * @param obj pointer to a chart object + * @param ser pointer to a data series on 'chart' + * @return the array of values with 'point_count' elements + */ +lv_coord_t * lv_chart_get_x_array(const lv_obj_t * obj, lv_chart_series_t * ser); + +/** + * Get the index of the currently pressed point. It's the same for every series. + * @param obj pointer to a chart object + * @return the index of the point [0 .. point count] or LV_CHART_POINT_ID_NONE if no point is being pressed + */ +uint32_t lv_chart_get_pressed_point(const lv_obj_t * obj); + +/********************** + * MACROS + **********************/ + +#endif /*LV_USE_CHART*/ + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif /*LV_CHART_H*/ diff --git a/src/lib/lvgl/src/extra/widgets/colorwheel/lv_colorwheel.h b/src/lib/lvgl/src/extra/widgets/colorwheel/lv_colorwheel.h new file mode 100644 index 0000000..e9c9d92 --- /dev/null +++ b/src/lib/lvgl/src/extra/widgets/colorwheel/lv_colorwheel.h @@ -0,0 +1,142 @@ +/** + * @file lv_colorwheel.h + * + */ + +#ifndef LV_COLORWHEEL_H +#define LV_COLORWHEEL_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include "../../../lvgl.h" + +#if LV_USE_COLORWHEEL + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +enum { + LV_COLORWHEEL_MODE_HUE, + LV_COLORWHEEL_MODE_SATURATION, + LV_COLORWHEEL_MODE_VALUE +}; +typedef uint8_t lv_colorwheel_mode_t; + + +/*Data of color picker*/ +typedef struct { + lv_obj_t obj; + lv_color_hsv_t hsv; + struct { + lv_point_t pos; + uint8_t recolor : 1; + } knob; + uint32_t last_click_time; + uint32_t last_change_time; + lv_point_t last_press_point; + lv_colorwheel_mode_t mode : 2; + uint8_t mode_fixed : 1; +} lv_colorwheel_t; + +extern const lv_obj_class_t lv_colorwheel_class; + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +/** + * Create a color picker object with disc shape + * @param parent pointer to an object, it will be the parent of the new color picker + * @param knob_recolor true: set the knob's color to the current color + * @return pointer to the created color picker + */ +lv_obj_t * lv_colorwheel_create(lv_obj_t * parent, bool knob_recolor); + +/*===================== + * Setter functions + *====================*/ + +/** + * Set the current hsv of a color wheel. + * @param colorwheel pointer to color wheel object + * @param color current selected hsv + * @return true if changed, otherwise false + */ +bool lv_colorwheel_set_hsv(lv_obj_t * obj, lv_color_hsv_t hsv); + +/** + * Set the current color of a color wheel. + * @param colorwheel pointer to color wheel object + * @param color current selected color + * @return true if changed, otherwise false + */ +bool lv_colorwheel_set_rgb(lv_obj_t * obj, lv_color_t color); + +/** + * Set the current color mode. + * @param colorwheel pointer to color wheel object + * @param mode color mode (hue/sat/val) + */ +void lv_colorwheel_set_mode(lv_obj_t * obj, lv_colorwheel_mode_t mode); + +/** + * Set if the color mode is changed on long press on center + * @param colorwheel pointer to color wheel object + * @param fixed color mode cannot be changed on long press + */ +void lv_colorwheel_set_mode_fixed(lv_obj_t * obj, bool fixed); + +/*===================== + * Getter functions + *====================*/ + +/** + * Get the current selected hsv of a color wheel. + * @param colorwheel pointer to color wheel object + * @return current selected hsv + */ +lv_color_hsv_t lv_colorwheel_get_hsv(lv_obj_t * obj); + +/** + * Get the current selected color of a color wheel. + * @param colorwheel pointer to color wheel object + * @return color current selected color + */ +lv_color_t lv_colorwheel_get_rgb(lv_obj_t * obj); + +/** + * Get the current color mode. + * @param colorwheel pointer to color wheel object + * @return color mode (hue/sat/val) + */ +lv_colorwheel_mode_t lv_colorwheel_get_color_mode(lv_obj_t * obj); + +/** + * Get if the color mode is changed on long press on center + * @param colorwheel pointer to color wheel object + * @return mode cannot be changed on long press + */ +bool lv_colorwheel_get_color_mode_fixed(lv_obj_t * obj); + +/********************** + * MACROS + **********************/ + +#endif /*LV_USE_COLORWHEEL*/ + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif /*LV_COLORWHEEL_H*/ + diff --git a/src/lib/lvgl/src/extra/widgets/imgbtn/lv_imgbtn.h b/src/lib/lvgl/src/extra/widgets/imgbtn/lv_imgbtn.h new file mode 100644 index 0000000..597faea --- /dev/null +++ b/src/lib/lvgl/src/extra/widgets/imgbtn/lv_imgbtn.h @@ -0,0 +1,131 @@ +/** + * @file lv_imgbtn.h + * + */ + +#ifndef LV_IMGBTN_H +#define LV_IMGBTN_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include "../../../lvgl.h" + +#if LV_USE_IMGBTN != 0 + +/********************* + * DEFINES + *********************/ +typedef enum { + LV_IMGBTN_STATE_RELEASED, + LV_IMGBTN_STATE_PRESSED, + LV_IMGBTN_STATE_DISABLED, + LV_IMGBTN_STATE_CHECKED_RELEASED, + LV_IMGBTN_STATE_CHECKED_PRESSED, + LV_IMGBTN_STATE_CHECKED_DISABLED, + _LV_IMGBTN_STATE_NUM, +} lv_imgbtn_state_t; + +/********************** + * TYPEDEFS + **********************/ +/*Data of image button*/ +typedef struct { + lv_obj_t obj; + const void * img_src_mid[_LV_IMGBTN_STATE_NUM]; /*Store center images to each state*/ + const void * img_src_left[_LV_IMGBTN_STATE_NUM]; /*Store left side images to each state*/ + const void * img_src_right[_LV_IMGBTN_STATE_NUM]; /*Store right side images to each state*/ + lv_img_cf_t act_cf; /*Color format of the currently active image*/ +} lv_imgbtn_t; + +extern const lv_obj_class_t lv_imgbtn_class; + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +/** + * Create an image button object + * @param parent pointer to an object, it will be the parent of the new image button + * @return pointer to the created image button + */ +lv_obj_t * lv_imgbtn_create(lv_obj_t * parent); + +/*====================== + * Add/remove functions + *=====================*/ + +/*===================== + * Setter functions + *====================*/ + +/** + * Set images for a state of the image button + * @param imgbtn pointer to an image button object + * @param state for which state set the new image + * @param src_left pointer to an image source for the left side of the button (a C array or path to + * a file) + * @param src_mid pointer to an image source for the middle of the button (ideally 1px wide) (a C + * array or path to a file) + * @param src_right pointer to an image source for the right side of the button (a C array or path + * to a file) + */ +void lv_imgbtn_set_src(lv_obj_t * imgbtn, lv_imgbtn_state_t state, const void * src_left, const void * src_mid, + const void * src_right); + + +/** + * Use this function instead of `lv_obj_add/clear_state` to set a state manually + * @param imgbtn pointer to an image button object + * @param state the new state + */ +void lv_imgbtn_set_state(lv_obj_t * imgbtn, lv_imgbtn_state_t state); + +/*===================== + * Getter functions + *====================*/ + +/** + * Get the left image in a given state + * @param imgbtn pointer to an image button object + * @param state the state where to get the image (from `lv_btn_state_t`) ` + * @return pointer to the left image source (a C array or path to a file) + */ +const void * lv_imgbtn_get_src_left(lv_obj_t * imgbtn, lv_imgbtn_state_t state); + +/** + * Get the middle image in a given state + * @param imgbtn pointer to an image button object + * @param state the state where to get the image (from `lv_btn_state_t`) ` + * @return pointer to the middle image source (a C array or path to a file) + */ +const void * lv_imgbtn_get_src_middle(lv_obj_t * imgbtn, lv_imgbtn_state_t state); + +/** + * Get the right image in a given state + * @param imgbtn pointer to an image button object + * @param state the state where to get the image (from `lv_btn_state_t`) ` + * @return pointer to the left image source (a C array or path to a file) + */ +const void * lv_imgbtn_get_src_right(lv_obj_t * imgbtn, lv_imgbtn_state_t state); + + +/*===================== + * Other functions + *====================*/ + +/********************** + * MACROS + **********************/ + +#endif /*LV_USE_IMGBTN*/ + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif /*LV_IMGBTN_H*/ diff --git a/src/lib/lvgl/src/extra/widgets/keyboard/lv_keyboard.h b/src/lib/lvgl/src/extra/widgets/keyboard/lv_keyboard.h new file mode 100644 index 0000000..7f65cd7 --- /dev/null +++ b/src/lib/lvgl/src/extra/widgets/keyboard/lv_keyboard.h @@ -0,0 +1,187 @@ +/** + * @file lv_keyboard.h + * + */ + +#ifndef LV_KEYBOARD_H +#define LV_KEYBOARD_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include "../../../widgets/lv_btnmatrix.h" + +#if LV_USE_KEYBOARD + +/*Testing of dependencies*/ +#if LV_USE_BTNMATRIX == 0 +#error "lv_kb: lv_btnm is required. Enable it in lv_conf.h (LV_USE_BTNMATRIX 1) " +#endif + +#if LV_USE_TEXTAREA == 0 +#error "lv_kb: lv_ta is required. Enable it in lv_conf.h (LV_USE_TEXTAREA 1) " +#endif + +/********************* + * DEFINES + *********************/ +#define LV_KEYBOARD_CTRL_BTN_FLAGS (LV_BTNMATRIX_CTRL_NO_REPEAT | LV_BTNMATRIX_CTRL_CLICK_TRIG | LV_BTNMATRIX_CTRL_CHECKED) + +/********************** + * TYPEDEFS + **********************/ + +/** Current keyboard mode.*/ +enum { + LV_KEYBOARD_MODE_TEXT_LOWER, + LV_KEYBOARD_MODE_TEXT_UPPER, + LV_KEYBOARD_MODE_SPECIAL, + LV_KEYBOARD_MODE_NUMBER, + LV_KEYBOARD_MODE_USER_1, + LV_KEYBOARD_MODE_USER_2, + LV_KEYBOARD_MODE_USER_3, + LV_KEYBOARD_MODE_USER_4, +}; +typedef uint8_t lv_keyboard_mode_t; + +/*Data of keyboard*/ +typedef struct { + lv_btnmatrix_t btnm; + lv_obj_t * ta; /*Pointer to the assigned text area*/ + lv_keyboard_mode_t mode; /*Key map type*/ + uint8_t popovers : 1; /*Show button titles in popovers on press*/ +} lv_keyboard_t; + +extern const lv_obj_class_t lv_keyboard_class; + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +/** + * Create a Keyboard object + * @param parent pointer to an object, it will be the parent of the new keyboard + * @return pointer to the created keyboard + */ +lv_obj_t * lv_keyboard_create(lv_obj_t * parent); + +/*===================== + * Setter functions + *====================*/ + +/** + * Assign a Text Area to the Keyboard. The pressed characters will be put there. + * @param kb pointer to a Keyboard object + * @param ta pointer to a Text Area object to write there + */ +void lv_keyboard_set_textarea(lv_obj_t * kb, lv_obj_t * ta); + +/** + * Set a new a mode (text or number map) + * @param kb pointer to a Keyboard object + * @param mode the mode from 'lv_keyboard_mode_t' + */ +void lv_keyboard_set_mode(lv_obj_t * kb, lv_keyboard_mode_t mode); + +/** + * Show the button title in a popover when pressed. + * @param kb pointer to a Keyboard object + * @param en whether "popovers" mode is enabled + */ +void lv_keyboard_set_popovers(lv_obj_t * kb, bool en); + +/** + * Set a new map for the keyboard + * @param kb pointer to a Keyboard object + * @param mode keyboard map to alter 'lv_keyboard_mode_t' + * @param map pointer to a string array to describe the map. + * See 'lv_btnmatrix_set_map()' for more info. + */ +void lv_keyboard_set_map(lv_obj_t * kb, lv_keyboard_mode_t mode, const char * map[], + const lv_btnmatrix_ctrl_t ctrl_map[]); + +/*===================== + * Getter functions + *====================*/ + +/** + * Assign a Text Area to the Keyboard. The pressed characters will be put there. + * @param kb pointer to a Keyboard object + * @return pointer to the assigned Text Area object + */ +lv_obj_t * lv_keyboard_get_textarea(const lv_obj_t * kb); + +/** + * Set a new a mode (text or number map) + * @param kb pointer to a Keyboard object + * @return the current mode from 'lv_keyboard_mode_t' + */ +lv_keyboard_mode_t lv_keyboard_get_mode(const lv_obj_t * kb); + +/** + * Tell whether "popovers" mode is enabled or not. + * @param kb pointer to a Keyboard object + * @return true: "popovers" mode is enabled; false: disabled + */ +bool lv_btnmatrix_get_popovers(const lv_obj_t * obj); + +/** + * Get the current map of a keyboard + * @param kb pointer to a keyboard object + * @return the current map + */ +static inline const char ** lv_keyboard_get_map_array(const lv_obj_t * kb) +{ + return lv_btnmatrix_get_map(kb); +} + +/** + * Get the index of the lastly "activated" button by the user (pressed, released, focused etc) + * Useful in the `event_cb` to get the text of the button, check if hidden etc. + * @param obj pointer to button matrix object + * @return index of the last released button (LV_BTNMATRIX_BTN_NONE: if unset) + */ +static inline uint16_t lv_keyboard_get_selected_btn(const lv_obj_t * obj) +{ + return lv_btnmatrix_get_selected_btn(obj); +} + +/** + * Get the button's text + * @param obj pointer to button matrix object + * @param btn_id the index a button not counting new line characters. + * @return text of btn_index` button + */ +static inline const char * lv_keyboard_get_btn_text(const lv_obj_t * obj, uint16_t btn_id) +{ + return lv_btnmatrix_get_btn_text(obj, btn_id); +} + +/*===================== + * Other functions + *====================*/ + +/** + * Default keyboard event to add characters to the Text area and change the map. + * If a custom `event_cb` is added to the keyboard this function can be called from it to handle the + * button clicks + * @param kb pointer to a keyboard + * @param event the triggering event + */ +void lv_keyboard_def_event_cb(lv_event_t * e); + +/********************** + * MACROS + **********************/ + +#endif /*LV_USE_KEYBOARD*/ + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif /*LV_KEYBOARD_H*/ diff --git a/src/lib/lvgl/src/extra/widgets/led/lv_led.h b/src/lib/lvgl/src/extra/widgets/led/lv_led.h new file mode 100644 index 0000000..368bcd2 --- /dev/null +++ b/src/lib/lvgl/src/extra/widgets/led/lv_led.h @@ -0,0 +1,116 @@ +/** + * @file lv_led.h + * + */ + +#ifndef LV_LED_H +#define LV_LED_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include "../../../lvgl.h" + +#if LV_USE_LED + + +/********************* + * DEFINES + *********************/ +/** Brightness when the LED if OFF */ +#ifndef LV_LED_BRIGHT_MIN +# define LV_LED_BRIGHT_MIN 80 +#endif + +/** Brightness when the LED if ON */ +#ifndef LV_LED_BRIGHT_MAX +# define LV_LED_BRIGHT_MAX 255 +#endif + +/********************** + * TYPEDEFS + **********************/ + +/*Data of led*/ +typedef struct { + lv_obj_t obj; + lv_color_t color; + uint8_t bright; /**< Current brightness of the LED (0..255)*/ +} lv_led_t; + +extern const lv_obj_class_t lv_led_class; + +/** + * `type` field in `lv_obj_draw_part_dsc_t` if `class_p = lv_led_class` + * Used in `LV_EVENT_DRAW_PART_BEGIN` and `LV_EVENT_DRAW_PART_END` + */ +typedef enum { + LV_LED_DRAW_PART_RECTANGLE, /**< The main rectangle*/ +} lv_led_draw_part_type_t; + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +/** + * Create a led object + * @param parent pointer to an object, it will be the parent of the new led + * @return pointer to the created led + */ +lv_obj_t * lv_led_create(lv_obj_t * parent); + +/** + * Set the color of the LED + * @param led pointer to a LED object + * @param color the color of the LED + */ +void lv_led_set_color(lv_obj_t * led, lv_color_t color); + +/** + * Set the brightness of a LED object + * @param led pointer to a LED object + * @param bright LV_LED_BRIGHT_MIN (max. dark) ... LV_LED_BRIGHT_MAX (max. light) + */ +void lv_led_set_brightness(lv_obj_t * led, uint8_t bright); + +/** + * Light on a LED + * @param led pointer to a LED object + */ +void lv_led_on(lv_obj_t * led); + +/** + * Light off a LED + * @param led pointer to a LED object + */ +void lv_led_off(lv_obj_t * led); + +/** + * Toggle the state of a LED + * @param led pointer to a LED object + */ +void lv_led_toggle(lv_obj_t * led); + +/** + * Get the brightness of a LEd object + * @param led pointer to LED object + * @return bright 0 (max. dark) ... 255 (max. light) + */ +uint8_t lv_led_get_brightness(const lv_obj_t * obj); + +/********************** + * MACROS + **********************/ + +#endif /*LV_USE_LED*/ + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + + +#endif /*LV_LED_H*/ diff --git a/src/lib/lvgl/src/extra/widgets/list/lv_list.h b/src/lib/lvgl/src/extra/widgets/list/lv_list.h new file mode 100644 index 0000000..8b91644 --- /dev/null +++ b/src/lib/lvgl/src/extra/widgets/list/lv_list.h @@ -0,0 +1,54 @@ +/** + * @file lv_win.h + * + */ + +#ifndef LV_LIST_H +#define LV_LIST_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include "../../../core/lv_obj.h" +#include "../../layouts/flex/lv_flex.h" + +#if LV_USE_LIST + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +extern const lv_obj_class_t lv_list_class; +extern const lv_obj_class_t lv_list_text_class; +extern const lv_obj_class_t lv_list_btn_class; +/********************** + * GLOBAL PROTOTYPES + **********************/ + +lv_obj_t * lv_list_create(lv_obj_t * parent); + +lv_obj_t * lv_list_add_text(lv_obj_t * list, const char * txt); + +lv_obj_t * lv_list_add_btn(lv_obj_t * list, const char * icon, const char * txt); + +const char * lv_list_get_btn_text(lv_obj_t * list, lv_obj_t * btn); + +/********************** + * MACROS + **********************/ + +#endif /*LV_USE_LIST*/ + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif /*LV_LIST_H*/ diff --git a/src/lib/lvgl/src/extra/widgets/lv_widgets.h b/src/lib/lvgl/src/extra/widgets/lv_widgets.h new file mode 100644 index 0000000..1141810 --- /dev/null +++ b/src/lib/lvgl/src/extra/widgets/lv_widgets.h @@ -0,0 +1,56 @@ +/** + * @file lv_widgets.h + * + */ + +#ifndef LV_WIDGETS_H +#define LV_WIDGETS_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include "animimg/lv_animimg.h" +#include "calendar/lv_calendar.h" +#include "calendar/lv_calendar_header_arrow.h" +#include "calendar/lv_calendar_header_dropdown.h" +#include "chart/lv_chart.h" +#include "keyboard/lv_keyboard.h" +#include "list/lv_list.h" +#include "menu/lv_menu.h" +#include "msgbox/lv_msgbox.h" +#include "meter/lv_meter.h" +#include "spinbox/lv_spinbox.h" +#include "spinner/lv_spinner.h" +#include "tabview/lv_tabview.h" +#include "tileview/lv_tileview.h" +#include "win/lv_win.h" +#include "colorwheel/lv_colorwheel.h" +#include "led/lv_led.h" +#include "imgbtn/lv_imgbtn.h" +#include "span/lv_span.h" + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +/********************** + * MACROS + **********************/ + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif /*LV_WIDGETS_H*/ diff --git a/src/lib/lvgl/src/extra/widgets/menu/lv_menu.h b/src/lib/lvgl/src/extra/widgets/menu/lv_menu.h new file mode 100644 index 0000000..0449059 --- /dev/null +++ b/src/lib/lvgl/src/extra/widgets/menu/lv_menu.h @@ -0,0 +1,233 @@ +/** + * @file lv_menu.h + * + */ + +#ifndef LV_MENU_H +#define LV_MENU_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include "../../../core/lv_obj.h" + +#if LV_USE_MENU + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +enum { + LV_MENU_HEADER_TOP_FIXED, /* Header is positioned at the top */ + LV_MENU_HEADER_TOP_UNFIXED, /* Header is positioned at the top and can be scrolled out of view*/ + LV_MENU_HEADER_BOTTOM_FIXED /* Header is positioned at the bottom */ +}; +typedef uint8_t lv_menu_mode_header_t; + +enum { + LV_MENU_ROOT_BACK_BTN_DISABLED, + LV_MENU_ROOT_BACK_BTN_ENABLED +}; +typedef uint8_t lv_menu_mode_root_back_btn_t; + +typedef struct lv_menu_load_page_event_data_t { + lv_obj_t * menu; + lv_obj_t * page; +} lv_menu_load_page_event_data_t; + +typedef struct { + lv_obj_t * page; +} lv_menu_history_t; + +typedef struct { + lv_obj_t obj; + lv_obj_t * storage; /* a pointer to obj that is the parent of all pages not displayed */ + lv_obj_t * main; + lv_obj_t * main_page; + lv_obj_t * main_header; + lv_obj_t * + main_header_back_btn; /* a pointer to obj that on click triggers back btn event handler, can be same as 'main_header' */ + lv_obj_t * main_header_title; + lv_obj_t * sidebar; + lv_obj_t * sidebar_page; + lv_obj_t * sidebar_header; + lv_obj_t * + sidebar_header_back_btn; /* a pointer to obj that on click triggers back btn event handler, can be same as 'sidebar_header' */ + lv_obj_t * sidebar_header_title; + lv_obj_t * selected_tab; + lv_ll_t history_ll; + uint8_t cur_depth; + uint8_t prev_depth; + uint8_t sidebar_generated : 1; + lv_menu_mode_header_t mode_header : 2; + lv_menu_mode_root_back_btn_t mode_root_back_btn : 1; +} lv_menu_t; + +typedef struct { + lv_obj_t obj; + char * title; +} lv_menu_page_t; + +extern const lv_obj_class_t lv_menu_class; +extern const lv_obj_class_t lv_menu_page_class; +extern const lv_obj_class_t lv_menu_cont_class; +extern const lv_obj_class_t lv_menu_section_class; +extern const lv_obj_class_t lv_menu_separator_class; +extern const lv_obj_class_t lv_menu_sidebar_cont_class; +extern const lv_obj_class_t lv_menu_main_cont_class; +extern const lv_obj_class_t lv_menu_sidebar_header_cont_class; +extern const lv_obj_class_t lv_menu_main_header_cont_class; +/********************** + * GLOBAL PROTOTYPES + **********************/ + +/** + * Create a menu object + * @param parent pointer to an object, it will be the parent of the new menu + * @return pointer to the created menu + */ +lv_obj_t * lv_menu_create(lv_obj_t * parent); + +/** + * Create a menu page object + * @param parent pointer to menu object + * @param title pointer to text for title in header (NULL to not display title) + * @return pointer to the created menu page + */ +lv_obj_t * lv_menu_page_create(lv_obj_t * parent, char * title); + +/** + * Create a menu cont object + * @param parent pointer to an object, it will be the parent of the new menu cont object + * @return pointer to the created menu cont + */ +lv_obj_t * lv_menu_cont_create(lv_obj_t * parent); + +/** + * Create a menu section object + * @param parent pointer to an object, it will be the parent of the new menu section object + * @return pointer to the created menu section + */ +lv_obj_t * lv_menu_section_create(lv_obj_t * parent); + +/** + * Create a menu separator object + * @param parent pointer to an object, it will be the parent of the new menu separator object + * @return pointer to the created menu separator + */ +lv_obj_t * lv_menu_separator_create(lv_obj_t * parent); +/*===================== + * Setter functions + *====================*/ +/** + * Set menu page to display in main + * @param obj pointer to the menu + * @param page pointer to the menu page to set (NULL to clear main and clear menu history) + */ +void lv_menu_set_page(lv_obj_t * obj, lv_obj_t * page); + +/** + * Set menu page to display in sidebar + * @param obj pointer to the menu + * @param page pointer to the menu page to set (NULL to clear sidebar) + */ +void lv_menu_set_sidebar_page(lv_obj_t * obj, lv_obj_t * page); + +/** + * Set the how the header should behave and its position + * @param obj pointer to a menu + * @param mode_header + */ +void lv_menu_set_mode_header(lv_obj_t * obj, lv_menu_mode_header_t mode_header); + +/** + * Set whether back button should appear at root + * @param obj pointer to a menu + * @param mode_root_back_btn + */ +void lv_menu_set_mode_root_back_btn(lv_obj_t * obj, lv_menu_mode_root_back_btn_t mode_root_back_btn); + +/** + * Add menu to the menu item + * @param menu pointer to the menu + * @param obj pointer to the obj + * @param page pointer to the page to load when obj is clicked + */ +void lv_menu_set_load_page_event(lv_obj_t * menu, lv_obj_t * obj, lv_obj_t * page); + +/*===================== + * Getter functions + *====================*/ +/** +* Get a pointer to menu page that is currently displayed in main +* @param obj pointer to the menu +* @return pointer to current page +*/ +lv_obj_t * lv_menu_get_cur_main_page(lv_obj_t * obj); + +/** +* Get a pointer to menu page that is currently displayed in sidebar +* @param obj pointer to the menu +* @return pointer to current page +*/ +lv_obj_t * lv_menu_get_cur_sidebar_page(lv_obj_t * obj); + +/** +* Get a pointer to main header obj +* @param obj pointer to the menu +* @return pointer to main header obj +*/ +lv_obj_t * lv_menu_get_main_header(lv_obj_t * obj); + +/** +* Get a pointer to main header back btn obj +* @param obj pointer to the menu +* @return pointer to main header back btn obj +*/ +lv_obj_t * lv_menu_get_main_header_back_btn(lv_obj_t * obj); + +/** +* Get a pointer to sidebar header obj +* @param obj pointer to the menu +* @return pointer to sidebar header obj +*/ +lv_obj_t * lv_menu_get_sidebar_header(lv_obj_t * obj); + +/** +* Get a pointer to sidebar header obj +* @param obj pointer to the menu +* @return pointer to sidebar header back btn obj +*/ +lv_obj_t * lv_menu_get_sidebar_header_back_btn(lv_obj_t * obj); + +/** + * Check if an obj is a root back btn + * @param menu pointer to the menu + * @return true if it is a root back btn + */ +bool lv_menu_back_btn_is_root(lv_obj_t * menu, lv_obj_t * obj); + +/** + * Clear menu history + * @param obj pointer to the menu + */ +void lv_menu_clear_history(lv_obj_t * obj); +/********************** + * MACROS + **********************/ + +#endif /*LV_USE_MENU*/ + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif /*LV_MENU_H*/ diff --git a/src/lib/lvgl/src/extra/widgets/meter/lv_meter.h b/src/lib/lvgl/src/extra/widgets/meter/lv_meter.h new file mode 100644 index 0000000..24c1dae --- /dev/null +++ b/src/lib/lvgl/src/extra/widgets/meter/lv_meter.h @@ -0,0 +1,267 @@ +/** + * @file lv_meter.h + * + */ + +#ifndef LV_METER_H +#define LV_METER_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include "../../../lvgl.h" + +#if LV_USE_METER != 0 + +/*Testing of dependencies*/ +#if LV_DRAW_COMPLEX == 0 +#error "lv_meter: Complex drawing is required. Enable it in lv_conf.h (LV_DRAW_COMPLEX 1)" +#endif + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +typedef struct { + lv_color_t tick_color; + uint16_t tick_cnt; + uint16_t tick_length; + uint16_t tick_width; + + lv_color_t tick_major_color; + uint16_t tick_major_nth; + uint16_t tick_major_length; + uint16_t tick_major_width; + + int16_t label_gap; + int16_t label_color; + + int32_t min; + int32_t max; + int16_t r_mod; + uint16_t angle_range; + int16_t rotation; +} lv_meter_scale_t; + +enum { + LV_METER_INDICATOR_TYPE_NEEDLE_IMG, + LV_METER_INDICATOR_TYPE_NEEDLE_LINE, + LV_METER_INDICATOR_TYPE_SCALE_LINES, + LV_METER_INDICATOR_TYPE_ARC, +}; +typedef uint8_t lv_meter_indicator_type_t; + +typedef struct { + lv_meter_scale_t * scale; + lv_meter_indicator_type_t type; + lv_opa_t opa; + int32_t start_value; + int32_t end_value; + union { + struct { + const void * src; + lv_point_t pivot; + } needle_img; + struct { + uint16_t width; + int16_t r_mod; + lv_color_t color; + } needle_line; + struct { + uint16_t width; + const void * src; + lv_color_t color; + int16_t r_mod; + } arc; + struct { + int16_t width_mod; + lv_color_t color_start; + lv_color_t color_end; + uint8_t local_grad : 1; + } scale_lines; + } type_data; +} lv_meter_indicator_t; + +/*Data of line meter*/ +typedef struct { + lv_obj_t obj; + lv_ll_t scale_ll; + lv_ll_t indicator_ll; +} lv_meter_t; + +extern const lv_obj_class_t lv_meter_class; + +/** + * `type` field in `lv_obj_draw_part_dsc_t` if `class_p = lv_meter_class` + * Used in `LV_EVENT_DRAW_PART_BEGIN` and `LV_EVENT_DRAW_PART_END` + */ +typedef enum { + LV_METER_DRAW_PART_ARC, /**< The arc indicator*/ + LV_METER_DRAW_PART_NEEDLE_LINE, /**< The needle lines*/ + LV_METER_DRAW_PART_NEEDLE_IMG, /**< The needle images*/ + LV_METER_DRAW_PART_TICK, /**< The tick lines and labels*/ +} lv_meter_draw_part_type_t; + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +/** + * Create a Meter object + * @param parent pointer to an object, it will be the parent of the new bar. + * @return pointer to the created meter + */ +lv_obj_t * lv_meter_create(lv_obj_t * parent); + +/*===================== + * Add scale + *====================*/ + +/** + * Add a new scale to the meter. + * @param obj pointer to a meter object + * @return the new scale + * @note Indicators can be attached to scales. + */ +lv_meter_scale_t * lv_meter_add_scale(lv_obj_t * obj); + +/** + * Set the properties of the ticks of a scale + * @param obj pointer to a meter object + * @param scale pointer to scale (added to `meter`) + * @param cnt number of tick lines + * @param width width of tick lines + * @param len length of tick lines + * @param color color of tick lines + */ +void lv_meter_set_scale_ticks(lv_obj_t * obj, lv_meter_scale_t * scale, uint16_t cnt, uint16_t width, uint16_t len, + lv_color_t color); + +/** + * Make some "normal" ticks major ticks and set their attributes. + * Texts with the current value are also added to the major ticks. + * @param obj pointer to a meter object + * @param scale pointer to scale (added to `meter`) + * @param nth make every Nth normal tick major tick. (start from the first on the left) + * @param width width of the major ticks + * @param len length of the major ticks + * @param color color of the major ticks + * @param label_gap gap between the major ticks and the labels + */ +void lv_meter_set_scale_major_ticks(lv_obj_t * obj, lv_meter_scale_t * scale, uint16_t nth, uint16_t width, + uint16_t len, lv_color_t color, int16_t label_gap); + +/** + * Set the value and angular range of a scale. + * @param obj pointer to a meter object + * @param scale pointer to scale (added to `meter`) + * @param min the minimum value + * @param max the maximal value + * @param angle_range the angular range of the scale + * @param rotation the angular offset from the 3 o'clock position (clock-wise) + */ +void lv_meter_set_scale_range(lv_obj_t * obj, lv_meter_scale_t * scale, int32_t min, int32_t max, uint32_t angle_range, + uint32_t rotation); + +/*===================== + * Add indicator + *====================*/ + +/** + * Add a needle line indicator the scale + * @param obj pointer to a meter object + * @param scale pointer to scale (added to `meter`) + * @param width width of the line + * @param color color of the line + * @param r_mod the radius modifier (added to the scale's radius) to get the lines length + * @return the new indicator + */ +lv_meter_indicator_t * lv_meter_add_needle_line(lv_obj_t * obj, lv_meter_scale_t * scale, uint16_t width, + lv_color_t color, int16_t r_mod); + +/** + * Add a needle image indicator the scale + * @param obj pointer to a meter object + * @param scale pointer to scale (added to `meter`) + * @param src the image source of the indicator. path or pointer to ::lv_img_dsc_t + * @param pivot_x the X pivot point of the needle + * @param pivot_y the Y pivot point of the needle + * @return the new indicator + * @note the needle image should point to the right, like -O-----> + */ +lv_meter_indicator_t * lv_meter_add_needle_img(lv_obj_t * obj, lv_meter_scale_t * scale, const void * src, + lv_coord_t pivot_x, lv_coord_t pivot_y); + +/** + * Add an arc indicator the scale + * @param obj pointer to a meter object + * @param scale pointer to scale (added to `meter`) + * @param width width of the arc + * @param color color of the arc + * @param r_mod the radius modifier (added to the scale's radius) to get the outer radius of the arc + * @return the new indicator + */ +lv_meter_indicator_t * lv_meter_add_arc(lv_obj_t * obj, lv_meter_scale_t * scale, uint16_t width, lv_color_t color, + int16_t r_mod); + + +/** + * Add a scale line indicator the scale. It will modify the ticks. + * @param obj pointer to a meter object + * @param scale pointer to scale (added to `meter`) + * @param color_start the start color + * @param color_end the end color + * @param local tell how to map start and end color. true: the indicator's start and end_value; false: the scale's min max value + * @param width_mod add this the affected tick's width + * @return the new indicator + */ +lv_meter_indicator_t * lv_meter_add_scale_lines(lv_obj_t * obj, lv_meter_scale_t * scale, lv_color_t color_start, + lv_color_t color_end, bool local, int16_t width_mod); + +/*===================== + * Set indicator value + *====================*/ + +/** + * Set the value of the indicator. It will set start and and value to the same value + * @param obj pointer to a meter object + * @param indic pointer to an indicator + * @param value the new value + */ +void lv_meter_set_indicator_value(lv_obj_t * obj, lv_meter_indicator_t * indic, int32_t value); + +/** + * Set the start value of the indicator. + * @param obj pointer to a meter object + * @param indic pointer to an indicator + * @param value the new value + */ +void lv_meter_set_indicator_start_value(lv_obj_t * obj, lv_meter_indicator_t * indic, int32_t value); + +/** + * Set the start value of the indicator. + * @param obj pointer to a meter object + * @param indic pointer to an indicator + * @param value the new value + */ +void lv_meter_set_indicator_end_value(lv_obj_t * obj, lv_meter_indicator_t * indic, int32_t value); + +/********************** + * MACROS + **********************/ + +#endif /*LV_USE_METER*/ + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif /*LV_METER_H*/ diff --git a/src/lib/lvgl/src/extra/widgets/msgbox/lv_msgbox.h b/src/lib/lvgl/src/extra/widgets/msgbox/lv_msgbox.h new file mode 100644 index 0000000..2eaf0d3 --- /dev/null +++ b/src/lib/lvgl/src/extra/widgets/msgbox/lv_msgbox.h @@ -0,0 +1,99 @@ +/** + * @file lv_mbox.h + * + */ + +#ifndef LV_MSGBOX_H +#define LV_MSGBOX_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include "../../../lvgl.h" + +#if LV_USE_MSGBOX + +/*Testing of dependencies*/ +#if LV_USE_BTNMATRIX == 0 +#error "lv_mbox: lv_btnm is required. Enable it in lv_conf.h (LV_USE_BTNMATRIX 1) " +#endif + +#if LV_USE_LABEL == 0 +#error "lv_mbox: lv_label is required. Enable it in lv_conf.h (LV_USE_LABEL 1) " +#endif + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +typedef struct { + lv_obj_t obj; + lv_obj_t * title; + lv_obj_t * close_btn; + lv_obj_t * content; + lv_obj_t * text; + lv_obj_t * btns; +} lv_msgbox_t; + +extern const lv_obj_class_t lv_msgbox_class; +extern const lv_obj_class_t lv_msgbox_content_class; +extern const lv_obj_class_t lv_msgbox_backdrop_class; + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +/** + * Create a message box object + * @param parent pointer to parent or NULL to create a full screen modal message box + * @param title the title of the message box + * @param txt the text of the message box + * @param btn_txts the buttons as an array of texts terminated by an "" element. E.g. {"btn1", "btn2", ""} + * @param add_close_btn true: add a close button + * @return pointer to the message box object + */ +lv_obj_t * lv_msgbox_create(lv_obj_t * parent, const char * title, const char * txt, const char * btn_txts[], + bool add_close_btn); + +lv_obj_t * lv_msgbox_get_title(lv_obj_t * obj); + +lv_obj_t * lv_msgbox_get_close_btn(lv_obj_t * obj); + +lv_obj_t * lv_msgbox_get_text(lv_obj_t * obj); + +lv_obj_t * lv_msgbox_get_content(lv_obj_t * obj); + +lv_obj_t * lv_msgbox_get_btns(lv_obj_t * obj); + +/** + * Get the index of the selected button + * @param mbox message box object + * @return index of the button (LV_BTNMATRIX_BTN_NONE: if unset) + */ +uint16_t lv_msgbox_get_active_btn(lv_obj_t * mbox); + +const char * lv_msgbox_get_active_btn_text(lv_obj_t * mbox); + +void lv_msgbox_close(lv_obj_t * mbox); + +void lv_msgbox_close_async(lv_obj_t * mbox); + +/********************** + * MACROS + **********************/ + +#endif /*LV_USE_MSGBOX*/ + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif /*LV_MSGBOX_H*/ diff --git a/src/lib/lvgl/src/extra/widgets/span/lv_span.h b/src/lib/lvgl/src/extra/widgets/span/lv_span.h new file mode 100644 index 0000000..418ad87 --- /dev/null +++ b/src/lib/lvgl/src/extra/widgets/span/lv_span.h @@ -0,0 +1,230 @@ +/** + * @file lv_span.h + * + */ + +#ifndef LV_SPAN_H +#define LV_SPAN_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include "../../../lvgl.h" + +#if LV_USE_SPAN != 0 + +/********************* + * DEFINES + *********************/ +#ifndef LV_SPAN_SNIPPET_STACK_SIZE +#define LV_SPAN_SNIPPET_STACK_SIZE 64 +#endif + +/********************** + * TYPEDEFS + **********************/ +enum { + LV_SPAN_OVERFLOW_CLIP, + LV_SPAN_OVERFLOW_ELLIPSIS, +}; +typedef uint8_t lv_span_overflow_t; + +enum { + LV_SPAN_MODE_FIXED, /**< fixed the obj size*/ + LV_SPAN_MODE_EXPAND, /**< Expand the object size to the text size*/ + LV_SPAN_MODE_BREAK, /**< Keep width, break the too long lines and expand height*/ +}; +typedef uint8_t lv_span_mode_t; + +typedef struct { + char * txt; /* a pointer to display text */ + lv_obj_t * spangroup; /* a pointer to spangroup */ + lv_style_t style; /* display text style */ + uint8_t static_flag : 1;/* the text is static flag */ +} lv_span_t; + +/** Data of label*/ +typedef struct { + lv_obj_t obj; + lv_coord_t indent; /* first line indent */ + lv_coord_t cache_w; /* the cache automatically calculates the width */ + lv_coord_t cache_h; /* similar cache_w */ + lv_ll_t child_ll; + uint8_t mode : 2; /* details see lv_span_mode_t */ + uint8_t overflow : 1; /* details see lv_span_overflow_t */ + uint8_t refresh : 1; /* the spangroup need refresh cache_w and cache_h */ +} lv_spangroup_t; + +extern const lv_obj_class_t lv_spangroup_class; + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +/** + * Create a spangroup object + * @param par pointer to an object, it will be the parent of the new spangroup + * @return pointer to the created spangroup + */ +lv_obj_t * lv_spangroup_create(lv_obj_t * par); + +/** + * Create a span string descriptor and add to spangroup. + * @param obj pointer to a spangroup object. + * @return pointer to the created span. + */ +lv_span_t * lv_spangroup_new_span(lv_obj_t * obj); + +/** + * Remove the span from the spangroup and free memory. + * @param obj pointer to a spangroup object. + * @param span pointer to a span. + */ +void lv_spangroup_del_span(lv_obj_t * obj, lv_span_t * span); + +/*===================== + * Setter functions + *====================*/ + +/** + * Set a new text for a span. Memory will be allocated to store the text by the span. + * @param span pointer to a span. + * @param text pointer to a text. + */ +void lv_span_set_text(lv_span_t * span, const char * text); + +/** + * Set a static text. It will not be saved by the span so the 'text' variable + * has to be 'alive' while the span exist. + * @param span pointer to a span. + * @param text pointer to a text. + */ +void lv_span_set_text_static(lv_span_t * span, const char * text); + +/** + * Set the align of the spangroup. + * @param obj pointer to a spangroup object. + * @param align see lv_text_align_t for details. + */ +void lv_spangroup_set_align(lv_obj_t * obj, lv_text_align_t align); + +/** + * Set the overflow of the spangroup. + * @param obj pointer to a spangroup object. + * @param overflow see lv_span_overflow_t for details. + */ +void lv_spangroup_set_overflow(lv_obj_t * obj, lv_span_overflow_t overflow); + +/** + * Set the indent of the spangroup. + * @param obj pointer to a spangroup object. + * @param indent The first line indentation + */ +void lv_spangroup_set_indent(lv_obj_t * obj, lv_coord_t indent); + +/** + * Set the mode of the spangroup. + * @param obj pointer to a spangroup object. + * @param mode see lv_span_mode_t for details. + */ +void lv_spangroup_set_mode(lv_obj_t * obj, lv_span_mode_t mode); + +/*===================== + * Getter functions + *====================*/ + +/** + * Get a spangroup child by its index. + * + * @param obj The spangroup object + * @param id the index of the child. + * 0: the oldest (firstly created) child + * 1: the second oldest + * child count-1: the youngest + * -1: the youngest + * -2: the second youngest + * @return The child span at index `id`, or NULL if the ID does not exist + */ +lv_span_t * lv_spangroup_get_child(const lv_obj_t * obj, int32_t id); + +/** + * + * @param obj The spangroup object to get the child count of. + * @return The span count of the spangroup. + */ +uint32_t lv_spangroup_get_child_cnt(const lv_obj_t * obj); + +/** + * get the align of the spangroup. + * @param obj pointer to a spangroup object. + * @return the align value. + */ +lv_text_align_t lv_spangroup_get_align(lv_obj_t * obj); + +/** + * get the overflow of the spangroup. + * @param obj pointer to a spangroup object. + * @return the overflow value. + */ +lv_span_overflow_t lv_spangroup_get_overflow(lv_obj_t * obj); + +/** + * get the indent of the spangroup. + * @param obj pointer to a spangroup object. + * @return the indent value. + */ +lv_coord_t lv_spangroup_get_indent(lv_obj_t * obj); + +/** + * get the mode of the spangroup. + * @param obj pointer to a spangroup object. + */ +lv_span_mode_t lv_spangroup_get_mode(lv_obj_t * obj); + +/** + * get max line height of all span in the spangroup. + * @param obj pointer to a spangroup object. + */ +lv_coord_t lv_spangroup_get_max_line_h(lv_obj_t * obj); + +/** + * get the text content width when all span of spangroup on a line. + * @param obj pointer to a spangroup object. + * @param max_width if text content width >= max_width, return max_width + * to reduce computation, if max_width == 0, returns the text content width. + * @return text content width or max_width. + */ +uint32_t lv_spangroup_get_expand_width(lv_obj_t * obj, uint32_t max_width); + +/** + * get the text content height with width fixed. + * @param obj pointer to a spangroup object. + */ +lv_coord_t lv_spangroup_get_expand_height(lv_obj_t * obj, lv_coord_t width); + + +/*===================== + * Other functions + *====================*/ + +/** + * update the mode of the spangroup. + * @param obj pointer to a spangroup object. + */ +void lv_spangroup_refr_mode(lv_obj_t * obj); + +/********************** + * MACROS + **********************/ + +#endif /*LV_USE_SPAN*/ + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /*LV_SPAN_H*/ diff --git a/src/lib/lvgl/src/extra/widgets/spinbox/lv_spinbox.h b/src/lib/lvgl/src/extra/widgets/spinbox/lv_spinbox.h new file mode 100644 index 0000000..14c73ba --- /dev/null +++ b/src/lib/lvgl/src/extra/widgets/spinbox/lv_spinbox.h @@ -0,0 +1,178 @@ +/** + * @file lv_spinbox.h + * + */ + +#ifndef LV_SPINBOX_H +#define LV_SPINBOX_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include "../../../lvgl.h" + +#if LV_USE_SPINBOX + +/*Testing of dependencies*/ +#if LV_USE_TEXTAREA == 0 +#error "lv_spinbox: lv_ta is required. Enable it in lv_conf.h (LV_USE_TEXTAREA 1) " +#endif + +/********************* + * DEFINES + *********************/ +#define LV_SPINBOX_MAX_DIGIT_COUNT 10 + +/********************** + * TYPEDEFS + **********************/ + +/*Data of spinbox*/ +typedef struct { + lv_textarea_t ta; /*Ext. of ancestor*/ + /*New data for this type*/ + int32_t value; + int32_t range_max; + int32_t range_min; + int32_t step; + uint16_t digit_count : 4; + uint16_t dec_point_pos : 4; /*if 0, there is no separator and the number is an integer*/ + uint16_t rollover : 1; // Set to true for rollover functionality + uint16_t digit_step_dir : 2; // the direction the digit will step on encoder button press when editing +} lv_spinbox_t; + +extern const lv_obj_class_t lv_spinbox_class; + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +/** + * Create a Spinbox object + * @param parent pointer to an object, it will be the parent of the new spinbox + * @return pointer to the created spinbox + */ +lv_obj_t * lv_spinbox_create(lv_obj_t * parent); + +/*===================== + * Setter functions + *====================*/ + +/** + * Set spinbox value + * @param obj pointer to spinbox + * @param i value to be set + */ +void lv_spinbox_set_value(lv_obj_t * obj, int32_t i); + +/** + * Set spinbox rollover function + * @param obj pointer to spinbox + * @param b true or false to enable or disable (default) + */ +void lv_spinbox_set_rollover(lv_obj_t * obj, bool b); + +/** + * Set spinbox digit format (digit count and decimal format) + * @param obj pointer to spinbox + * @param digit_count number of digit excluding the decimal separator and the sign + * @param separator_position number of digit before the decimal point. If 0, decimal point is not + * shown + */ +void lv_spinbox_set_digit_format(lv_obj_t * obj, uint8_t digit_count, uint8_t separator_position); + +/** + * Set spinbox step + * @param obj pointer to spinbox + * @param step steps on increment/decrement. Can be 1, 10, 100, 1000, etc the digit that will change. + */ +void lv_spinbox_set_step(lv_obj_t * obj, uint32_t step); + +/** + * Set spinbox value range + * @param obj pointer to spinbox + * @param range_min maximum value, inclusive + * @param range_max minimum value, inclusive + */ +void lv_spinbox_set_range(lv_obj_t * obj, int32_t range_min, int32_t range_max); + +/** + * Set cursor position to a specific digit for edition + * @param obj pointer to spinbox + * @param pos selected position in spinbox + */ +void lv_spinbox_set_pos(lv_obj_t * obj, uint8_t pos); + +/** + * Set direction of digit step when clicking an encoder button while in editing mode + * @param obj pointer to spinbox + * @param direction the direction (LV_DIR_RIGHT or LV_DIR_LEFT) + */ +void lv_spinbox_set_digit_step_direction(lv_obj_t * obj, lv_dir_t direction); + +/*===================== + * Getter functions + *====================*/ + +/** + * Get spinbox rollover function status + * @param obj pointer to spinbox + */ +bool lv_spinbox_get_rollover(lv_obj_t * obj); + +/** + * Get the spinbox numeral value (user has to convert to float according to its digit format) + * @param obj pointer to spinbox + * @return value integer value of the spinbox + */ +int32_t lv_spinbox_get_value(lv_obj_t * obj); + +/** + * Get the spinbox step value (user has to convert to float according to its digit format) + * @param obj pointer to spinbox + * @return value integer step value of the spinbox + */ +int32_t lv_spinbox_get_step(lv_obj_t * obj); + +/*===================== + * Other functions + *====================*/ + +/** + * Select next lower digit for edition by dividing the step by 10 + * @param obj pointer to spinbox + */ +void lv_spinbox_step_next(lv_obj_t * obj); + +/** + * Select next higher digit for edition by multiplying the step by 10 + * @param obj pointer to spinbox + */ +void lv_spinbox_step_prev(lv_obj_t * obj); + +/** + * Increment spinbox value by one step + * @param obj pointer to spinbox + */ +void lv_spinbox_increment(lv_obj_t * obj); + +/** + * Decrement spinbox value by one step + * @param obj pointer to spinbox + */ +void lv_spinbox_decrement(lv_obj_t * obj); + +/********************** + * MACROS + **********************/ + +#endif /*LV_USE_SPINBOX*/ + +#ifdef __cplusplus +} /*extern "C"*/ +#endif +#endif /*LV_SPINBOX_H*/ diff --git a/src/lib/lvgl/src/extra/widgets/spinner/lv_spinner.h b/src/lib/lvgl/src/extra/widgets/spinner/lv_spinner.h new file mode 100644 index 0000000..2ab36f6 --- /dev/null +++ b/src/lib/lvgl/src/extra/widgets/spinner/lv_spinner.h @@ -0,0 +1,50 @@ +/** + * @file lv_spinner.h + * + */ + +#ifndef LV_SPINNER_H +#define LV_SPINNER_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include "../../../lvgl.h" + +#if LV_USE_SPINNER + +/*Testing of dependencies*/ +#if LV_USE_ARC == 0 +#error "lv_spinner: lv_arc is required. Enable it in lv_conf.h (LV_USE_ARC 1) " +#endif + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ +extern const lv_obj_class_t lv_spinner_class; + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +lv_obj_t * lv_spinner_create(lv_obj_t * parent, uint32_t time, uint32_t arc_length); + +/********************** + * MACROS + **********************/ + +#endif /*LV_USE_SPINNER*/ + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif /*LV_SPINNER_H*/ diff --git a/src/lib/lvgl/src/extra/widgets/tabview/lv_tabview.h b/src/lib/lvgl/src/extra/widgets/tabview/lv_tabview.h new file mode 100644 index 0000000..a01c6b9 --- /dev/null +++ b/src/lib/lvgl/src/extra/widgets/tabview/lv_tabview.h @@ -0,0 +1,63 @@ +/** + * @file lv_templ.h + * + */ + +#ifndef LV_TABVIEW_H +#define LV_TABVIEW_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include "../../../lvgl.h" + +#if LV_USE_TABVIEW + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +typedef struct { + lv_obj_t obj; + char ** map; + uint16_t tab_cnt; + uint16_t tab_cur; + lv_dir_t tab_pos; +} lv_tabview_t; + +extern const lv_obj_class_t lv_tabview_class; + +/********************** + * GLOBAL PROTOTYPES + **********************/ +lv_obj_t * lv_tabview_create(lv_obj_t * parent, lv_dir_t tab_pos, lv_coord_t tab_size); + +lv_obj_t * lv_tabview_add_tab(lv_obj_t * tv, const char * name); + +lv_obj_t * lv_tabview_get_content(lv_obj_t * tv); + +lv_obj_t * lv_tabview_get_tab_btns(lv_obj_t * tv); + +void lv_tabview_set_act(lv_obj_t * obj, uint32_t id, lv_anim_enable_t anim_en); + +uint16_t lv_tabview_get_tab_act(lv_obj_t * tv); + +/********************** + * MACROS + **********************/ + +#endif /*LV_USE_TABVIEW*/ + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif /*LV_TABVIEW_H*/ diff --git a/src/lib/lvgl/src/extra/widgets/tileview/lv_tileview.h b/src/lib/lvgl/src/extra/widgets/tileview/lv_tileview.h new file mode 100644 index 0000000..7adeec3 --- /dev/null +++ b/src/lib/lvgl/src/extra/widgets/tileview/lv_tileview.h @@ -0,0 +1,72 @@ +/** + * @file lv_tileview.h + * + */ + +#ifndef LV_TILEVIEW_H +#define LV_TILEVIEW_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include "../../../core/lv_obj.h" + +#if LV_USE_TILEVIEW + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ +typedef struct { + lv_obj_t obj; + lv_obj_t * tile_act; +} lv_tileview_t; + +typedef struct { + lv_obj_t obj; + lv_dir_t dir; +} lv_tileview_tile_t; + +extern const lv_obj_class_t lv_tileview_class; +extern const lv_obj_class_t lv_tileview_tile_class; + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +/** + * Create a Tileview object + * @param parent pointer to an object, it will be the parent of the new tileview + * @return pointer to the created tileview + */ +lv_obj_t * lv_tileview_create(lv_obj_t * parent); + +lv_obj_t * lv_tileview_add_tile(lv_obj_t * tv, uint8_t col_id, uint8_t row_id, lv_dir_t dir); + +void lv_obj_set_tile(lv_obj_t * tv, lv_obj_t * tile_obj, lv_anim_enable_t anim_en); +void lv_obj_set_tile_id(lv_obj_t * tv, uint32_t col_id, uint32_t row_id, lv_anim_enable_t anim_en); + +lv_obj_t * lv_tileview_get_tile_act(lv_obj_t * obj); + +/*===================== + * Other functions + *====================*/ + +/********************** + * MACROS + **********************/ + +#endif /*LV_USE_TILEVIEW*/ + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif /*LV_TILEVIEW_H*/ diff --git a/src/lib/lvgl/src/extra/widgets/win/lv_win.h b/src/lib/lvgl/src/extra/widgets/win/lv_win.h new file mode 100644 index 0000000..4342b31 --- /dev/null +++ b/src/lib/lvgl/src/extra/widgets/win/lv_win.h @@ -0,0 +1,51 @@ +/** + * @file lv_win.h + * + */ + +#ifndef LV_WIN_H +#define LV_WIN_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include "../../../lvgl.h" + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ +typedef struct { + lv_obj_t obj; +} lv_win_t; + +extern const lv_obj_class_t lv_win_class; + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +lv_obj_t * lv_win_create(lv_obj_t * parent, lv_coord_t header_height); + + +lv_obj_t * lv_win_add_title(lv_obj_t * win, const char * txt); +lv_obj_t * lv_win_add_btn(lv_obj_t * win, const void * icon, lv_coord_t btn_w); + +lv_obj_t * lv_win_get_header(lv_obj_t * win); +lv_obj_t * lv_win_get_content(lv_obj_t * win); +/********************** + * MACROS + **********************/ + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif /*LV_WIN_H*/ diff --git a/src/lib/lvgl/src/font/lv_font.h b/src/lib/lvgl/src/font/lv_font.h new file mode 100644 index 0000000..3d716dd --- /dev/null +++ b/src/lib/lvgl/src/font/lv_font.h @@ -0,0 +1,258 @@ +/** + * @file lv_font.h + * + */ + +#ifndef LV_FONT_H +#define LV_FONT_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include "../lv_conf_internal.h" +#include +#include +#include + +#include "lv_symbol_def.h" +#include "../misc/lv_area.h" + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +/*------------------ + * General types + *-----------------*/ + +struct _lv_font_t; +/** Describes the properties of a glyph.*/ +typedef struct { + const struct _lv_font_t * + resolved_font; /**< Pointer to a font where the gylph was actually found after handling fallbacks*/ + uint16_t adv_w; /**< The glyph needs this space. Draw the next glyph after this width.*/ + uint16_t box_w; /**< Width of the glyph's bounding box*/ + uint16_t box_h; /**< Height of the glyph's bounding box*/ + int16_t ofs_x; /**< x offset of the bounding box*/ + int16_t ofs_y; /**< y offset of the bounding box*/ + uint8_t bpp: 4; /**< Bit-per-pixel: 1, 2, 4, 8*/ + uint8_t is_placeholder: 1; /** Glyph is missing. But placeholder will still be displayed */ +} lv_font_glyph_dsc_t; + +/** 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_t { + /** Get a glyph's descriptor from a font*/ + bool (*get_glyph_dsc)(const struct _lv_font_t *, lv_font_glyph_dsc_t *, uint32_t letter, uint32_t letter_next); + + /** Get a glyph's bitmap from a font*/ + const uint8_t * (*get_glyph_bitmap)(const struct _lv_font_t *, uint32_t); + + /*Pointer to the font in a font pack (must have the same line height)*/ + lv_coord_t line_height; /**< The real line height where any text fits*/ + lv_coord_t base_line; /**< Base line measured from the top of the line_height*/ + uint8_t subpx : 2; /**< An element of `lv_font_subpx_t`*/ + + int8_t underline_position; /**< Distance between the top of the underline and base line (< 0 means below the base line)*/ + int8_t underline_thickness; /**< Thickness of the underline*/ + + const void * dsc; /**< Store implementation specific or run_time data or caching here*/ + const struct _lv_font_t * fallback; /**< Fallback font for missing glyph. Resolved recursively */ +#if LV_USE_USER_DATA + void * user_data; /**< Custom user data for font.*/ +#endif +} lv_font_t; + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +/** + * Return with the bitmap of a font. + * @param font_p pointer to a font + * @param letter an UNICODE character code + * @return pointer to the bitmap of the letter + */ +const uint8_t * lv_font_get_glyph_bitmap(const lv_font_t * font_p, uint32_t letter); + +/** + * Get the descriptor of a glyph + * @param font_p pointer to font + * @param dsc_out store the result descriptor here + * @param letter an UNICODE letter code + * @param letter_next the next letter after `letter`. Used for kerning + * @return true: descriptor is successfully loaded into `dsc_out`. + * false: the letter was not found, no data is loaded to `dsc_out` + */ +bool lv_font_get_glyph_dsc(const lv_font_t * font_p, lv_font_glyph_dsc_t * dsc_out, uint32_t letter, + uint32_t letter_next); + +/** + * Get the width of a glyph with kerning + * @param font pointer to a font + * @param letter an UNICODE letter + * @param letter_next the next letter after `letter`. Used for kerning + * @return the width of the glyph + */ +uint16_t lv_font_get_glyph_width(const lv_font_t * font, uint32_t letter, uint32_t letter_next); + +/** + * Get the line height of a font. All characters fit into this height + * @param font_p pointer to a font + * @return the height of a font + */ +static inline lv_coord_t lv_font_get_line_height(const lv_font_t * font_p) +{ + return font_p->line_height; +} + +/********************** + * MACROS + **********************/ + +#define LV_FONT_DECLARE(font_name) extern const lv_font_t font_name; + +#if LV_FONT_MONTSERRAT_8 +LV_FONT_DECLARE(lv_font_montserrat_8) +#endif + +#if LV_FONT_MONTSERRAT_10 +LV_FONT_DECLARE(lv_font_montserrat_10) +#endif + +#if LV_FONT_MONTSERRAT_12 +LV_FONT_DECLARE(lv_font_montserrat_12) +#endif + +#if LV_FONT_MONTSERRAT_14 +LV_FONT_DECLARE(lv_font_montserrat_14) +#endif + +#if LV_FONT_MONTSERRAT_16 +LV_FONT_DECLARE(lv_font_montserrat_16) +#endif + +#if LV_FONT_MONTSERRAT_18 +LV_FONT_DECLARE(lv_font_montserrat_18) +#endif + +#if LV_FONT_MONTSERRAT_20 +LV_FONT_DECLARE(lv_font_montserrat_20) +#endif + +#if LV_FONT_MONTSERRAT_22 +LV_FONT_DECLARE(lv_font_montserrat_22) +#endif + +#if LV_FONT_MONTSERRAT_24 +LV_FONT_DECLARE(lv_font_montserrat_24) +#endif + +#if LV_FONT_MONTSERRAT_26 +LV_FONT_DECLARE(lv_font_montserrat_26) +#endif + +#if LV_FONT_MONTSERRAT_28 +LV_FONT_DECLARE(lv_font_montserrat_28) +#endif + +#if LV_FONT_MONTSERRAT_30 +LV_FONT_DECLARE(lv_font_montserrat_30) +#endif + +#if LV_FONT_MONTSERRAT_32 +LV_FONT_DECLARE(lv_font_montserrat_32) +#endif + +#if LV_FONT_MONTSERRAT_34 +LV_FONT_DECLARE(lv_font_montserrat_34) +#endif + +#if LV_FONT_MONTSERRAT_36 +LV_FONT_DECLARE(lv_font_montserrat_36) +#endif + +#if LV_FONT_MONTSERRAT_38 +LV_FONT_DECLARE(lv_font_montserrat_38) +#endif + +#if LV_FONT_MONTSERRAT_40 +LV_FONT_DECLARE(lv_font_montserrat_40) +#endif + +#if LV_FONT_MONTSERRAT_42 +LV_FONT_DECLARE(lv_font_montserrat_42) +#endif + +#if LV_FONT_MONTSERRAT_44 +LV_FONT_DECLARE(lv_font_montserrat_44) +#endif + +#if LV_FONT_MONTSERRAT_46 +LV_FONT_DECLARE(lv_font_montserrat_46) +#endif + +#if LV_FONT_MONTSERRAT_48 +LV_FONT_DECLARE(lv_font_montserrat_48) +#endif + +#if LV_FONT_MONTSERRAT_12_SUBPX +LV_FONT_DECLARE(lv_font_montserrat_12_subpx) +#endif + +#if LV_FONT_MONTSERRAT_28_COMPRESSED +LV_FONT_DECLARE(lv_font_montserrat_28_compressed) +#endif + +#if LV_FONT_DEJAVU_16_PERSIAN_HEBREW +LV_FONT_DECLARE(lv_font_dejavu_16_persian_hebrew) +#endif + +#if LV_FONT_SIMSUN_16_CJK +LV_FONT_DECLARE(lv_font_simsun_16_cjk) +#endif + +#if LV_FONT_UNSCII_8 +LV_FONT_DECLARE(lv_font_unscii_8) +#endif + +#if LV_FONT_UNSCII_16 +LV_FONT_DECLARE(lv_font_unscii_16) +#endif + +/*Declare the custom (user defined) fonts*/ +#ifdef LV_FONT_CUSTOM_DECLARE +LV_FONT_CUSTOM_DECLARE +#endif + +/** + * Just a wrapper around LV_FONT_DEFAULT because it might be more convenient to use a function is some cases + * @return pointer to LV_FONT_DEFAULT + */ +static inline const lv_font_t * lv_font_default(void) +{ + return LV_FONT_DEFAULT; +} + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif /*USE_FONT*/ diff --git a/src/lib/lvgl/src/font/lv_font_fmt_txt.h b/src/lib/lvgl/src/font/lv_font_fmt_txt.h new file mode 100644 index 0000000..9c9d422 --- /dev/null +++ b/src/lib/lvgl/src/font/lv_font_fmt_txt.h @@ -0,0 +1,240 @@ +/** + * @file lv_font_fmt_txt.h + * + */ + +#ifndef LV_FONT_FMT_TXT_H +#define LV_FONT_FMT_TXT_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include +#include +#include +#include "lv_font.h" + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +/** This describes a glyph.*/ +typedef struct { +#if LV_FONT_FMT_TXT_LARGE == 0 + uint32_t bitmap_index : 20; /**< Start index of the bitmap. A font can be max 1 MB.*/ + uint32_t adv_w : 12; /**< Draw the next glyph after this width. 8.4 format (real_value * 16 is stored).*/ + 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*/ + int8_t ofs_y; /**< y offset of the bounding box. Measured from the top of the line*/ +#else + uint32_t bitmap_index; /**< Start index of the bitmap. A font can be max 4 GB.*/ + uint32_t adv_w; /**< Draw the next glyph after this width. 28.4 format (real_value * 16 is stored).*/ + uint16_t box_w; /**< Width of the glyph's bounding box*/ + uint16_t box_h; /**< Height of the glyph's bounding box*/ + int16_t ofs_x; /**< x offset of the bounding box*/ + int16_t ofs_y; /**< y offset of the bounding box. Measured from the top of the line*/ +#endif +} lv_font_fmt_txt_glyph_dsc_t; + +/** Format of font character map.*/ +enum { + LV_FONT_FMT_TXT_CMAP_FORMAT0_FULL, + LV_FONT_FMT_TXT_CMAP_SPARSE_FULL, + LV_FONT_FMT_TXT_CMAP_FORMAT0_TINY, + LV_FONT_FMT_TXT_CMAP_SPARSE_TINY, +}; + +typedef uint8_t lv_font_fmt_txt_cmap_type_t; + +/** + * Map codepoints to a `glyph_dsc`s + * Several formats are supported to optimize memory usage + * See https://github.com/lvgl/lv_font_conv/blob/master/doc/font_spec.md + */ +typedef struct { + /** First Unicode character for this range*/ + uint32_t range_start; + + /** Number of Unicode characters related to this range. + * Last Unicode character = range_start + range_length - 1*/ + uint16_t range_length; + + /** First glyph ID (array index of `glyph_dsc`) for this range*/ + uint16_t glyph_id_start; + + /* + According the specification there are 4 formats: + https://github.com/lvgl/lv_font_conv/blob/master/doc/font_spec.md + + For simplicity introduce "relative code point": + rcp = codepoint - range_start + + and a search function: + search a "value" in an "array" and returns the index of "value". + + Format 0 tiny + unicode_list == NULL && glyph_id_ofs_list == NULL + glyph_id = glyph_id_start + rcp + + Format 0 full + unicode_list == NULL && glyph_id_ofs_list != NULL + glyph_id = glyph_id_start + glyph_id_ofs_list[rcp] + + Sparse tiny + unicode_list != NULL && glyph_id_ofs_list == NULL + glyph_id = glyph_id_start + search(unicode_list, rcp) + + Sparse full + unicode_list != NULL && glyph_id_ofs_list != NULL + glyph_id = glyph_id_start + glyph_id_ofs_list[search(unicode_list, rcp)] + */ + + const uint16_t * unicode_list; + + /** if(type == LV_FONT_FMT_TXT_CMAP_FORMAT0_...) it's `uint8_t *` + * if(type == LV_FONT_FMT_TXT_CMAP_SPARSE_...) it's `uint16_t *` + */ + const void * glyph_id_ofs_list; + + /** Length of `unicode_list` and/or `glyph_id_ofs_list`*/ + uint16_t list_length; + + /** Type of this character map*/ + lv_font_fmt_txt_cmap_type_t type; +} lv_font_fmt_txt_cmap_t; + +/** A simple mapping of kern values from pairs*/ +typedef struct { + /*To get a kern value of two code points: + 1. Get the `glyph_id_left` and `glyph_id_right` from `lv_font_fmt_txt_cmap_t + 2. for(i = 0; i < pair_cnt * 2; i += 2) + if(gylph_ids[i] == glyph_id_left && + gylph_ids[i+1] == glyph_id_right) + return values[i / 2]; + */ + const void * glyph_ids; + const int8_t * values; + uint32_t pair_cnt : 30; + uint32_t glyph_ids_size : 2; /*0: `glyph_ids` is stored as `uint8_t`; 1: as `uint16_t`*/ +} lv_font_fmt_txt_kern_pair_t; + +/** More complex but more optimal class based kern value storage*/ +typedef struct { + /*To get a kern value of two code points: + 1. Get the `glyph_id_left` and `glyph_id_right` from `lv_font_fmt_txt_cmap_t + 2. Get the class of the left and right glyphs as `left_class` and `right_class` + left_class = left_class_mapping[glyph_id_left]; + right_class = right_class_mapping[glyph_id_right]; + 3. value = class_pair_values[(left_class-1)*right_class_cnt + (right_class-1)] + */ + + const int8_t * class_pair_values; /*left_class_cnt * right_class_cnt 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; + uint8_t right_class_cnt; +} lv_font_fmt_txt_kern_classes_t; + +/** Bitmap formats*/ +typedef enum { + LV_FONT_FMT_TXT_PLAIN = 0, + LV_FONT_FMT_TXT_COMPRESSED = 1, + LV_FONT_FMT_TXT_COMPRESSED_NO_PREFILTER = 1, +} lv_font_fmt_txt_bitmap_format_t; + +typedef struct { + uint32_t last_letter; + uint32_t last_glyph_id; +} lv_font_fmt_txt_glyph_cache_t; + +/*Describe store additional data for fonts*/ +typedef struct { + /*The bitmaps of all glyphs*/ + const uint8_t * glyph_bitmap; + + /*Describe the glyphs*/ + const lv_font_fmt_txt_glyph_dsc_t * glyph_dsc; + + /*Map the glyphs to Unicode characters. + *Array of `lv_font_cmap_fmt_txt_t` variables*/ + const lv_font_fmt_txt_cmap_t * cmaps; + + /** + * Store kerning values. + * Can be `lv_font_fmt_txt_kern_pair_t * or `lv_font_kern_classes_fmt_txt_t *` + * depending on `kern_classes` + */ + const void * kern_dsc; + + /*Scale kern values in 12.4 format*/ + uint16_t kern_scale; + + /*Number of cmap tables*/ + uint16_t cmap_num : 9; + + /*Bit per pixel: 1, 2, 3, 4, 8*/ + uint16_t bpp : 4; + + /*Type of `kern_dsc`*/ + uint16_t kern_classes : 1; + + /* + * storage format of the bitmap + * from `lv_font_fmt_txt_bitmap_format_t` + */ + uint16_t bitmap_format : 2; + + /*Cache the last letter and is glyph id*/ + lv_font_fmt_txt_glyph_cache_t * cache; +} lv_font_fmt_txt_dsc_t; + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +/** + * Used as `get_glyph_bitmap` callback in LittelvGL's native font format if the font is uncompressed. + * @param font pointer to font + * @param unicode_letter an unicode letter which bitmap should be get + * @return pointer to the bitmap or NULL if not found + */ +const uint8_t * lv_font_get_bitmap_fmt_txt(const lv_font_t * font, uint32_t letter); + +/** + * Used as `get_glyph_dsc` callback in LittelvGL's native font format if the font is uncompressed. + * @param font_p pointer to font + * @param dsc_out store the result descriptor here + * @param letter an UNICODE letter code + * @return true: descriptor is successfully loaded into `dsc_out`. + * false: the letter was not found, no data is loaded to `dsc_out` + */ +bool lv_font_get_glyph_dsc_fmt_txt(const lv_font_t * font, lv_font_glyph_dsc_t * dsc_out, uint32_t unicode_letter, + uint32_t unicode_letter_next); + +/** + * Free the allocated memories. + */ +void _lv_font_clean_up_fmt_txt(void); + +/********************** + * MACROS + **********************/ + +/********************** + * ADD BUILT IN FONTS + **********************/ + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif /*LV_FONT_FMT_TXT_H*/ diff --git a/src/lib/lvgl/src/font/lv_font_loader.h b/src/lib/lvgl/src/font/lv_font_loader.h new file mode 100644 index 0000000..783cb2e --- /dev/null +++ b/src/lib/lvgl/src/font/lv_font_loader.h @@ -0,0 +1,40 @@ +/** + * @file lv_font_loader.h + * + */ + +#ifndef LV_FONT_LOADER_H +#define LV_FONT_LOADER_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +lv_font_t * lv_font_load(const char * fontName); +void lv_font_free(lv_font_t * font); + +/********************** + * MACROS + **********************/ + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif /*LV_FONT_LOADER_H*/ diff --git a/src/lib/lvgl/src/font/lv_symbol_def.h b/src/lib/lvgl/src/font/lv_symbol_def.h new file mode 100644 index 0000000..696daf1 --- /dev/null +++ b/src/lib/lvgl/src/font/lv_symbol_def.h @@ -0,0 +1,353 @@ +#ifndef LV_SYMBOL_DEF_H +#define LV_SYMBOL_DEF_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "../lv_conf_internal.h" + +/*------------------------------- + * Symbols from "normal" font + *-----------------------------*/ +#if !defined LV_SYMBOL_BULLET +#define LV_SYMBOL_BULLET "\xE2\x80\xA2" /*20042, 0x2022*/ +#endif + +/*------------------------------- + * Symbols from FontAwesome font + *-----------------------------*/ + +/*In the font converter use this list as range: + 61441, 61448, 61451, 61452, 61453, 61457, 61459, 61461, 61465, 61468, + 61473, 61478, 61479, 61480, 61502, 61507, 61512, 61515, 61516, 61517, + 61521, 61522, 61523, 61524, 61543, 61544, 61550, 61552, 61553, 61556, + 61559, 61560, 61561, 61563, 61587, 61589, 61636, 61637, 61639, 61641, + 61664, 61671, 61674, 61683, 61724, 61732, 61787, 61931, 62016, 62017, + 62018, 62019, 62020, 62087, 62099, 62189, 62212, 62810, 63426, 63650 +*/ + +/* These symbols can be prefined in the lv_conf.h file. + * If they are not predefined, they will use the following values + */ + + +#if !defined LV_SYMBOL_AUDIO +#define LV_SYMBOL_AUDIO "\xEF\x80\x81" /*61441, 0xF001*/ +#endif + +#if !defined LV_SYMBOL_VIDEO +#define LV_SYMBOL_VIDEO "\xEF\x80\x88" /*61448, 0xF008*/ +#endif + +#if !defined LV_SYMBOL_LIST +#define LV_SYMBOL_LIST "\xEF\x80\x8B" /*61451, 0xF00B*/ +#endif + +#if !defined LV_SYMBOL_OK +#define LV_SYMBOL_OK "\xEF\x80\x8C" /*61452, 0xF00C*/ +#endif + +#if !defined LV_SYMBOL_CLOSE +#define LV_SYMBOL_CLOSE "\xEF\x80\x8D" /*61453, 0xF00D*/ +#endif + +#if !defined LV_SYMBOL_POWER +#define LV_SYMBOL_POWER "\xEF\x80\x91" /*61457, 0xF011*/ +#endif + +#if !defined LV_SYMBOL_SETTINGS +#define LV_SYMBOL_SETTINGS "\xEF\x80\x93" /*61459, 0xF013*/ +#endif + +#if !defined LV_SYMBOL_HOME +#define LV_SYMBOL_HOME "\xEF\x80\x95" /*61461, 0xF015*/ +#endif + +#if !defined LV_SYMBOL_DOWNLOAD +#define LV_SYMBOL_DOWNLOAD "\xEF\x80\x99" /*61465, 0xF019*/ +#endif + +#if !defined LV_SYMBOL_DRIVE +#define LV_SYMBOL_DRIVE "\xEF\x80\x9C" /*61468, 0xF01C*/ +#endif + +#if !defined LV_SYMBOL_REFRESH +#define LV_SYMBOL_REFRESH "\xEF\x80\xA1" /*61473, 0xF021*/ +#endif + +#if !defined LV_SYMBOL_MUTE +#define LV_SYMBOL_MUTE "\xEF\x80\xA6" /*61478, 0xF026*/ +#endif + +#if !defined LV_SYMBOL_VOLUME_MID +#define LV_SYMBOL_VOLUME_MID "\xEF\x80\xA7" /*61479, 0xF027*/ +#endif + +#if !defined LV_SYMBOL_VOLUME_MAX +#define LV_SYMBOL_VOLUME_MAX "\xEF\x80\xA8" /*61480, 0xF028*/ +#endif + +#if !defined LV_SYMBOL_IMAGE +#define LV_SYMBOL_IMAGE "\xEF\x80\xBE" /*61502, 0xF03E*/ +#endif + +#if !defined LV_SYMBOL_TINT +#define LV_SYMBOL_TINT "\xEF\x81\x83" /*61507, 0xF043*/ +#endif + +#if !defined LV_SYMBOL_PREV +#define LV_SYMBOL_PREV "\xEF\x81\x88" /*61512, 0xF048*/ +#endif + +#if !defined LV_SYMBOL_PLAY +#define LV_SYMBOL_PLAY "\xEF\x81\x8B" /*61515, 0xF04B*/ +#endif + +#if !defined LV_SYMBOL_PAUSE +#define LV_SYMBOL_PAUSE "\xEF\x81\x8C" /*61516, 0xF04C*/ +#endif + +#if !defined LV_SYMBOL_STOP +#define LV_SYMBOL_STOP "\xEF\x81\x8D" /*61517, 0xF04D*/ +#endif + +#if !defined LV_SYMBOL_NEXT +#define LV_SYMBOL_NEXT "\xEF\x81\x91" /*61521, 0xF051*/ +#endif + +#if !defined LV_SYMBOL_EJECT +#define LV_SYMBOL_EJECT "\xEF\x81\x92" /*61522, 0xF052*/ +#endif + +#if !defined LV_SYMBOL_LEFT +#define LV_SYMBOL_LEFT "\xEF\x81\x93" /*61523, 0xF053*/ +#endif + +#if !defined LV_SYMBOL_RIGHT +#define LV_SYMBOL_RIGHT "\xEF\x81\x94" /*61524, 0xF054*/ +#endif + +#if !defined LV_SYMBOL_PLUS +#define LV_SYMBOL_PLUS "\xEF\x81\xA7" /*61543, 0xF067*/ +#endif + +#if !defined LV_SYMBOL_MINUS +#define LV_SYMBOL_MINUS "\xEF\x81\xA8" /*61544, 0xF068*/ +#endif + +#if !defined LV_SYMBOL_EYE_OPEN +#define LV_SYMBOL_EYE_OPEN "\xEF\x81\xAE" /*61550, 0xF06E*/ +#endif + +#if !defined LV_SYMBOL_EYE_CLOSE +#define LV_SYMBOL_EYE_CLOSE "\xEF\x81\xB0" /*61552, 0xF070*/ +#endif + +#if !defined LV_SYMBOL_WARNING +#define LV_SYMBOL_WARNING "\xEF\x81\xB1" /*61553, 0xF071*/ +#endif + +#if !defined LV_SYMBOL_SHUFFLE +#define LV_SYMBOL_SHUFFLE "\xEF\x81\xB4" /*61556, 0xF074*/ +#endif + +#if !defined LV_SYMBOL_UP +#define LV_SYMBOL_UP "\xEF\x81\xB7" /*61559, 0xF077*/ +#endif + +#if !defined LV_SYMBOL_DOWN +#define LV_SYMBOL_DOWN "\xEF\x81\xB8" /*61560, 0xF078*/ +#endif + +#if !defined LV_SYMBOL_LOOP +#define LV_SYMBOL_LOOP "\xEF\x81\xB9" /*61561, 0xF079*/ +#endif + +#if !defined LV_SYMBOL_DIRECTORY +#define LV_SYMBOL_DIRECTORY "\xEF\x81\xBB" /*61563, 0xF07B*/ +#endif + +#if !defined LV_SYMBOL_UPLOAD +#define LV_SYMBOL_UPLOAD "\xEF\x82\x93" /*61587, 0xF093*/ +#endif + +#if !defined LV_SYMBOL_CALL +#define LV_SYMBOL_CALL "\xEF\x82\x95" /*61589, 0xF095*/ +#endif + +#if !defined LV_SYMBOL_CUT +#define LV_SYMBOL_CUT "\xEF\x83\x84" /*61636, 0xF0C4*/ +#endif + +#if !defined LV_SYMBOL_COPY +#define LV_SYMBOL_COPY "\xEF\x83\x85" /*61637, 0xF0C5*/ +#endif + +#if !defined LV_SYMBOL_SAVE +#define LV_SYMBOL_SAVE "\xEF\x83\x87" /*61639, 0xF0C7*/ +#endif + +#if !defined LV_SYMBOL_BARS +#define LV_SYMBOL_BARS "\xEF\x83\x89" /*61641, 0xF0C9*/ +#endif + +#if !defined LV_SYMBOL_ENVELOPE +#define LV_SYMBOL_ENVELOPE "\xEF\x83\xA0" /*61664, 0xF0E0*/ +#endif + +#if !defined LV_SYMBOL_CHARGE +#define LV_SYMBOL_CHARGE "\xEF\x83\xA7" /*61671, 0xF0E7*/ +#endif + +#if !defined LV_SYMBOL_PASTE +#define LV_SYMBOL_PASTE "\xEF\x83\xAA" /*61674, 0xF0EA*/ +#endif + +#if !defined LV_SYMBOL_BELL +#define LV_SYMBOL_BELL "\xEF\x83\xB3" /*61683, 0xF0F3*/ +#endif + +#if !defined LV_SYMBOL_KEYBOARD +#define LV_SYMBOL_KEYBOARD "\xEF\x84\x9C" /*61724, 0xF11C*/ +#endif + +#if !defined LV_SYMBOL_GPS +#define LV_SYMBOL_GPS "\xEF\x84\xA4" /*61732, 0xF124*/ +#endif + +#if !defined LV_SYMBOL_FILE +#define LV_SYMBOL_FILE "\xEF\x85\x9B" /*61787, 0xF158*/ +#endif + +#if !defined LV_SYMBOL_WIFI +#define LV_SYMBOL_WIFI "\xEF\x87\xAB" /*61931, 0xF1EB*/ +#endif + +#if !defined LV_SYMBOL_BATTERY_FULL +#define LV_SYMBOL_BATTERY_FULL "\xEF\x89\x80" /*62016, 0xF240*/ +#endif + +#if !defined LV_SYMBOL_BATTERY_3 +#define LV_SYMBOL_BATTERY_3 "\xEF\x89\x81" /*62017, 0xF241*/ +#endif + +#if !defined LV_SYMBOL_BATTERY_2 +#define LV_SYMBOL_BATTERY_2 "\xEF\x89\x82" /*62018, 0xF242*/ +#endif + +#if !defined LV_SYMBOL_BATTERY_1 +#define LV_SYMBOL_BATTERY_1 "\xEF\x89\x83" /*62019, 0xF243*/ +#endif + +#if !defined LV_SYMBOL_BATTERY_EMPTY +#define LV_SYMBOL_BATTERY_EMPTY "\xEF\x89\x84" /*62020, 0xF244*/ +#endif + +#if !defined LV_SYMBOL_USB +#define LV_SYMBOL_USB "\xEF\x8a\x87" /*62087, 0xF287*/ +#endif + +#if !defined LV_SYMBOL_BLUETOOTH +#define LV_SYMBOL_BLUETOOTH "\xEF\x8a\x93" /*62099, 0xF293*/ +#endif + +#if !defined LV_SYMBOL_TRASH +#define LV_SYMBOL_TRASH "\xEF\x8B\xAD" /*62189, 0xF2ED*/ +#endif + +#if !defined LV_SYMBOL_EDIT +#define LV_SYMBOL_EDIT "\xEF\x8C\x84" /*62212, 0xF304*/ +#endif + +#if !defined LV_SYMBOL_BACKSPACE +#define LV_SYMBOL_BACKSPACE "\xEF\x95\x9A" /*62810, 0xF55A*/ +#endif + +#if !defined LV_SYMBOL_SD_CARD +#define LV_SYMBOL_SD_CARD "\xEF\x9F\x82" /*63426, 0xF7C2*/ +#endif + +#if !defined LV_SYMBOL_NEW_LINE +#define LV_SYMBOL_NEW_LINE "\xEF\xA2\xA2" /*63650, 0xF8A2*/ +#endif + +#if !defined LV_SYMBOL_DUMMY +/** 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" +#endif + +/* + * The following list is generated using + * cat src/font/lv_symbol_def.h | sed -E -n 's/^#define\s+LV_(SYMBOL_\w+).*".*$/ _LV_STR_\1,/p' + */ +enum { + _LV_STR_SYMBOL_BULLET, + _LV_STR_SYMBOL_AUDIO, + _LV_STR_SYMBOL_VIDEO, + _LV_STR_SYMBOL_LIST, + _LV_STR_SYMBOL_OK, + _LV_STR_SYMBOL_CLOSE, + _LV_STR_SYMBOL_POWER, + _LV_STR_SYMBOL_SETTINGS, + _LV_STR_SYMBOL_HOME, + _LV_STR_SYMBOL_DOWNLOAD, + _LV_STR_SYMBOL_DRIVE, + _LV_STR_SYMBOL_REFRESH, + _LV_STR_SYMBOL_MUTE, + _LV_STR_SYMBOL_VOLUME_MID, + _LV_STR_SYMBOL_VOLUME_MAX, + _LV_STR_SYMBOL_IMAGE, + _LV_STR_SYMBOL_TINT, + _LV_STR_SYMBOL_PREV, + _LV_STR_SYMBOL_PLAY, + _LV_STR_SYMBOL_PAUSE, + _LV_STR_SYMBOL_STOP, + _LV_STR_SYMBOL_NEXT, + _LV_STR_SYMBOL_EJECT, + _LV_STR_SYMBOL_LEFT, + _LV_STR_SYMBOL_RIGHT, + _LV_STR_SYMBOL_PLUS, + _LV_STR_SYMBOL_MINUS, + _LV_STR_SYMBOL_EYE_OPEN, + _LV_STR_SYMBOL_EYE_CLOSE, + _LV_STR_SYMBOL_WARNING, + _LV_STR_SYMBOL_SHUFFLE, + _LV_STR_SYMBOL_UP, + _LV_STR_SYMBOL_DOWN, + _LV_STR_SYMBOL_LOOP, + _LV_STR_SYMBOL_DIRECTORY, + _LV_STR_SYMBOL_UPLOAD, + _LV_STR_SYMBOL_CALL, + _LV_STR_SYMBOL_CUT, + _LV_STR_SYMBOL_COPY, + _LV_STR_SYMBOL_SAVE, + _LV_STR_SYMBOL_BARS, + _LV_STR_SYMBOL_ENVELOPE, + _LV_STR_SYMBOL_CHARGE, + _LV_STR_SYMBOL_PASTE, + _LV_STR_SYMBOL_BELL, + _LV_STR_SYMBOL_KEYBOARD, + _LV_STR_SYMBOL_GPS, + _LV_STR_SYMBOL_FILE, + _LV_STR_SYMBOL_WIFI, + _LV_STR_SYMBOL_BATTERY_FULL, + _LV_STR_SYMBOL_BATTERY_3, + _LV_STR_SYMBOL_BATTERY_2, + _LV_STR_SYMBOL_BATTERY_1, + _LV_STR_SYMBOL_BATTERY_EMPTY, + _LV_STR_SYMBOL_USB, + _LV_STR_SYMBOL_BLUETOOTH, + _LV_STR_SYMBOL_TRASH, + _LV_STR_SYMBOL_EDIT, + _LV_STR_SYMBOL_BACKSPACE, + _LV_STR_SYMBOL_SD_CARD, + _LV_STR_SYMBOL_NEW_LINE, + _LV_STR_SYMBOL_DUMMY, +}; + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif /*LV_SYMBOL_DEF_H*/ diff --git a/src/lib/lvgl/src/hal/lv_hal.h b/src/lib/lvgl/src/hal/lv_hal.h new file mode 100644 index 0000000..167da1f --- /dev/null +++ b/src/lib/lvgl/src/hal/lv_hal.h @@ -0,0 +1,48 @@ +/** + * @file lv_hal.h + * + */ + +#ifndef LV_HAL_H +#define LV_HAL_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include "lv_hal_disp.h" +#include "lv_hal_indev.h" +#include "lv_hal_tick.h" + +/********************* + * DEFINES + *********************/ +/** + * Same as Android's DIP. (Different name is chosen to avoid mistype between LV_DPI and LV_DIP) + * 1 dip is 1 px on a 160 DPI screen + * 1 dip is 2 px on a 320 DPI screen + * https://stackoverflow.com/questions/2025282/what-is-the-difference-between-px-dip-dp-and-sp + */ +#define _LV_DPX_CALC(dpi, n) ((n) == 0 ? 0 :LV_MAX((( (dpi) * (n) + 80) / 160), 1)) /*+80 for rounding*/ +#define LV_DPX(n) _LV_DPX_CALC(lv_disp_get_dpi(NULL), n) + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +/********************** + * MACROS + **********************/ + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif diff --git a/src/lib/lvgl/src/hal/lv_hal_disp.h b/src/lib/lvgl/src/hal/lv_hal_disp.h new file mode 100644 index 0000000..6abbab1 --- /dev/null +++ b/src/lib/lvgl/src/hal/lv_hal_disp.h @@ -0,0 +1,364 @@ +/** + * @file lv_hal_disp.h + * + * @description Display Driver HAL interface header file + * + */ + +#ifndef LV_HAL_DISP_H +#define LV_HAL_DISP_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include +#include +#include "lv_hal.h" +#include "../draw/lv_draw.h" +#include "../misc/lv_color.h" +#include "../misc/lv_area.h" +#include "../misc/lv_ll.h" +#include "../misc/lv_timer.h" + +/********************* + * DEFINES + *********************/ +#ifndef LV_INV_BUF_SIZE +#define LV_INV_BUF_SIZE 32 /*Buffer size for invalid areas*/ +#endif + +#ifndef LV_ATTRIBUTE_FLUSH_READY +#define LV_ATTRIBUTE_FLUSH_READY +#endif + +/********************** + * TYPEDEFS + **********************/ + +struct _lv_obj_t; +struct _lv_disp_t; +struct _lv_disp_drv_t; +struct _lv_theme_t; + +/** + * Structure for holding display buffer information. + */ +typedef struct _lv_disp_draw_buf_t { + void * buf1; /**< First display buffer.*/ + void * buf2; /**< Second display buffer.*/ + + /*Internal, used by the library*/ + void * buf_act; + uint32_t size; /*In pixel count*/ + /*1: flushing is in progress. (It can't be a bit field because when it's cleared from IRQ Read-Modify-Write issue might occur)*/ + volatile int flushing; + /*1: It was the last chunk to flush. (It can't be a bit field because when it's cleared from IRQ Read-Modify-Write issue might occur)*/ + volatile int flushing_last; + volatile uint32_t last_area : 1; /*1: the last area is being rendered*/ + volatile uint32_t last_part : 1; /*1: the last part of the current area is being rendered*/ +} lv_disp_draw_buf_t; + +typedef enum { + LV_DISP_ROT_NONE = 0, + LV_DISP_ROT_90, + LV_DISP_ROT_180, + LV_DISP_ROT_270 +} lv_disp_rot_t; + +/** + * Display Driver structure to be registered by HAL. + * Only its pointer will be saved in `lv_disp_t` so it should be declared as + * `static lv_disp_drv_t my_drv` or allocated dynamically. + */ +typedef struct _lv_disp_drv_t { + + lv_coord_t hor_res; /**< Horizontal resolution.*/ + lv_coord_t ver_res; /**< Vertical resolution.*/ + + lv_coord_t + physical_hor_res; /**< Horizontal resolution of the full / physical display. Set to -1 for fullscreen mode.*/ + lv_coord_t + physical_ver_res; /**< Vertical resolution of the full / physical display. Set to -1 for fullscreen mode.*/ + lv_coord_t + offset_x; /**< Horizontal offset from the full / physical display. Set to 0 for fullscreen mode.*/ + lv_coord_t offset_y; /**< Vertical offset from the full / physical display. Set to 0 for fullscreen mode.*/ + + /** Pointer to a buffer initialized with `lv_disp_draw_buf_init()`. + * LVGL will use this buffer(s) to draw the screens contents*/ + lv_disp_draw_buf_t * draw_buf; + + uint32_t direct_mode : 1; /**< 1: Use screen-sized buffers and draw to absolute coordinates*/ + uint32_t full_refresh : 1; /**< 1: Always make the whole screen redrawn*/ + uint32_t sw_rotate : 1; /**< 1: use software rotation (slower)*/ + uint32_t antialiasing : 1; /**< 1: anti-aliasing is enabled on this display.*/ + uint32_t rotated : 2; /**< 1: turn the display by 90 degree. @warning Does not update coordinates for you!*/ + uint32_t screen_transp : 1; /**Handle if the screen doesn't have a solid (opa == LV_OPA_COVER) background. + * Use only if required because it's slower.*/ + + uint32_t dpi : 10; /** DPI (dot per inch) of the display. Default value is `LV_DPI_DEF`.*/ + + /** MANDATORY: Write the internal buffer (draw_buf) to the display. 'lv_disp_flush_ready()' has to be + * called when finished*/ + void (*flush_cb)(struct _lv_disp_drv_t * disp_drv, const lv_area_t * area, lv_color_t * color_p); + + /** OPTIONAL: Extend the invalidated areas to match with the display drivers requirements + * E.g. round `y` to, 8, 16 ..) on a monochrome display*/ + void (*rounder_cb)(struct _lv_disp_drv_t * disp_drv, lv_area_t * area); + + /** OPTIONAL: Set a pixel in a buffer according to the special requirements of the display + * Can be used for color format not supported in LittelvGL. E.g. 2 bit -> 4 gray scales + * @note Much slower then drawing with supported color formats.*/ + void (*set_px_cb)(struct _lv_disp_drv_t * disp_drv, uint8_t * buf, lv_coord_t buf_w, lv_coord_t x, lv_coord_t y, + lv_color_t color, lv_opa_t opa); + + void (*clear_cb)(struct _lv_disp_drv_t * disp_drv, uint8_t * buf, uint32_t size); + + + /** OPTIONAL: Called after every refresh cycle to tell the rendering and flushing time + the + * number of flushed pixels*/ + void (*monitor_cb)(struct _lv_disp_drv_t * disp_drv, uint32_t time, uint32_t px); + + /** OPTIONAL: Called periodically while lvgl waits for operation to be completed. + * For example flushing or GPU + * User can execute very simple tasks here or yield the task*/ + void (*wait_cb)(struct _lv_disp_drv_t * disp_drv); + + /** OPTIONAL: Called when lvgl needs any CPU cache that affects rendering to be cleaned*/ + void (*clean_dcache_cb)(struct _lv_disp_drv_t * disp_drv); + + /** OPTIONAL: called when driver parameters are updated */ + void (*drv_update_cb)(struct _lv_disp_drv_t * disp_drv); + + /** On CHROMA_KEYED images this color will be transparent. + * `LV_COLOR_CHROMA_KEY` by default. (lv_conf.h)*/ + lv_color_t color_chroma_key; + + lv_draw_ctx_t * draw_ctx; + void (*draw_ctx_init)(struct _lv_disp_drv_t * disp_drv, lv_draw_ctx_t * draw_ctx); + void (*draw_ctx_deinit)(struct _lv_disp_drv_t * disp_drv, lv_draw_ctx_t * draw_ctx); + size_t draw_ctx_size; + +#if LV_USE_USER_DATA + void * user_data; /**< Custom display driver user data*/ +#endif + +} lv_disp_drv_t; + +/** + * Display structure. + * @note `lv_disp_drv_t` should be the first member of the structure. + */ +typedef struct _lv_disp_t { + /**< Driver to the display*/ + struct _lv_disp_drv_t * driver; + + /**< A timer which periodically checks the dirty areas and refreshes them*/ + lv_timer_t * refr_timer; + + /**< The theme assigned to the screen*/ + struct _lv_theme_t * theme; + + /** Screens of the display*/ + struct _lv_obj_t ** screens; /**< Array of screen objects.*/ + struct _lv_obj_t * act_scr; /**< Currently active screen on this display*/ + struct _lv_obj_t * prev_scr; /**< Previous screen. Used during screen animations*/ + struct _lv_obj_t * scr_to_load; /**< The screen prepared to load in lv_scr_load_anim*/ + struct _lv_obj_t * top_layer; /**< @see lv_disp_get_layer_top*/ + struct _lv_obj_t * sys_layer; /**< @see lv_disp_get_layer_sys*/ + uint32_t screen_cnt; +uint8_t del_prev : + 1; /**< 1: Automatically delete the previous screen when the screen load animation is ready*/ + + lv_opa_t bg_opa; /**flush` you should use DMA or similar hardware to send + * the image to the display in the background. + * It lets LVGL to render next frame into the other buffer while previous is being + * sent. Set to `NULL` if unused. + * @param size_in_px_cnt size of the `buf1` and `buf2` in pixel count. + */ +void lv_disp_draw_buf_init(lv_disp_draw_buf_t * draw_buf, void * buf1, void * buf2, uint32_t size_in_px_cnt); + +/** + * Register an initialized display driver. + * Automatically set the first display as active. + * @param driver pointer to an initialized 'lv_disp_drv_t' variable. Only its pointer is saved! + * @return pointer to the new display or NULL on error + */ +lv_disp_t * lv_disp_drv_register(lv_disp_drv_t * driver); + +/** + * Update the driver in run time. + * @param disp pointer to a display. (return value of `lv_disp_drv_register`) + * @param new_drv pointer to the new driver + */ +void lv_disp_drv_update(lv_disp_t * disp, lv_disp_drv_t * new_drv); + +/** + * Remove a display + * @param disp pointer to display + */ +void lv_disp_remove(lv_disp_t * disp); + +/** + * Set a default display. The new screens will be created on it by default. + * @param disp pointer to a display + */ +void lv_disp_set_default(lv_disp_t * disp); + +/** + * Get the default display + * @return pointer to the default display + */ +lv_disp_t * lv_disp_get_default(void); + +/** + * Get the horizontal resolution of a display + * @param disp pointer to a display (NULL to use the default display) + * @return the horizontal resolution of the display + */ +lv_coord_t lv_disp_get_hor_res(lv_disp_t * disp); + +/** + * Get the vertical resolution of a display + * @param disp pointer to a display (NULL to use the default display) + * @return the vertical resolution of the display + */ +lv_coord_t lv_disp_get_ver_res(lv_disp_t * disp); + +/** + * Get the full / physical horizontal resolution of a display + * @param disp pointer to a display (NULL to use the default display) + * @return the full / physical horizontal resolution of the display + */ +lv_coord_t lv_disp_get_physical_hor_res(lv_disp_t * disp); + +/** + * Get the full / physical vertical resolution of a display + * @param disp pointer to a display (NULL to use the default display) + * @return the full / physical vertical resolution of the display + */ +lv_coord_t lv_disp_get_physical_ver_res(lv_disp_t * disp); + +/** + * Get the horizontal offset from the full / physical display + * @param disp pointer to a display (NULL to use the default display) + * @return the horizontal offset from the full / physical display + */ +lv_coord_t lv_disp_get_offset_x(lv_disp_t * disp); + +/** + * Get the vertical offset from the full / physical display + * @param disp pointer to a display (NULL to use the default display) + * @return the horizontal offset from the full / physical display + */ +lv_coord_t lv_disp_get_offset_y(lv_disp_t * disp); + +/** + * Get if anti-aliasing is enabled for a display or not + * @param disp pointer to a display (NULL to use the default display) + * @return true: anti-aliasing is enabled; false: disabled + */ +bool lv_disp_get_antialiasing(lv_disp_t * disp); + +/** + * Get the DPI of the display + * @param disp pointer to a display (NULL to use the default display) + * @return dpi of the display + */ +lv_coord_t lv_disp_get_dpi(const lv_disp_t * disp); + + +/** + * Set the rotation of this display. + * @param disp pointer to a display (NULL to use the default display) + * @param rotation rotation angle + */ +void lv_disp_set_rotation(lv_disp_t * disp, lv_disp_rot_t rotation); + +/** + * Get the current rotation of this display. + * @param disp pointer to a display (NULL to use the default display) + * @return rotation angle + */ +lv_disp_rot_t lv_disp_get_rotation(lv_disp_t * disp); + +//! @cond Doxygen_Suppress + +/** + * Call in the display driver's `flush_cb` function when the flushing is finished + * @param disp_drv pointer to display driver in `flush_cb` where this function is called + */ +LV_ATTRIBUTE_FLUSH_READY void lv_disp_flush_ready(lv_disp_drv_t * disp_drv); + +/** + * Tell if it's the last area of the refreshing process. + * Can be called from `flush_cb` to execute some special display refreshing if needed when all areas area flushed. + * @param disp_drv pointer to display driver + * @return true: it's the last area to flush; false: there are other areas too which will be refreshed soon + */ +LV_ATTRIBUTE_FLUSH_READY bool lv_disp_flush_is_last(lv_disp_drv_t * disp_drv); + +//! @endcond + +/** + * Get the next display. + * @param disp pointer to the current display. NULL to initialize. + * @return the next display or NULL if no more. Give the first display when the parameter is NULL + */ +lv_disp_t * lv_disp_get_next(lv_disp_t * disp); + +/** + * Get the internal buffer of a display + * @param disp pointer to a display + * @return pointer to the internal buffers + */ +lv_disp_draw_buf_t * lv_disp_get_draw_buf(lv_disp_t * disp); + +void lv_disp_drv_use_generic_set_px_cb(lv_disp_drv_t * disp_drv, lv_img_cf_t cf); + +/********************** + * MACROS + **********************/ + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif diff --git a/src/lib/lvgl/src/hal/lv_hal_indev.h b/src/lib/lvgl/src/hal/lv_hal_indev.h new file mode 100644 index 0000000..ca51a08 --- /dev/null +++ b/src/lib/lvgl/src/hal/lv_hal_indev.h @@ -0,0 +1,239 @@ +/** + * @file lv_hal_indev.h + * + * @description Input Device HAL interface layer header file + * + */ + +#ifndef LV_HAL_INDEV_H +#define LV_HAL_INDEV_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include "../lv_conf_internal.h" + +#include +#include +#include "../misc/lv_area.h" +#include "../misc/lv_timer.h" + +/********************* + * DEFINES + *********************/ + +/*Drag threshold in pixels*/ +#define LV_INDEV_DEF_SCROLL_LIMIT 10 + +/*Drag throw slow-down in [%]. Greater value -> faster slow-down*/ +#define LV_INDEV_DEF_SCROLL_THROW 10 + +/*Long press time in milliseconds. + *Time to send `LV_EVENT_LONG_PRESSSED`)*/ +#define LV_INDEV_DEF_LONG_PRESS_TIME 400 + +/*Repeated trigger period in long press [ms] + *Time between `LV_EVENT_LONG_PRESSED_REPEAT*/ +#define LV_INDEV_DEF_LONG_PRESS_REP_TIME 100 + + +/*Gesture threshold in pixels*/ +#define LV_INDEV_DEF_GESTURE_LIMIT 50 + +/*Gesture min velocity at release before swipe (pixels)*/ +#define LV_INDEV_DEF_GESTURE_MIN_VELOCITY 3 + + +/********************** + * TYPEDEFS + **********************/ + +struct _lv_obj_t; +struct _lv_disp_t; +struct _lv_group_t; +struct _lv_indev_t; +struct _lv_indev_drv_t; + +/** Possible input device types*/ +typedef enum { + LV_INDEV_TYPE_NONE, /**< Uninitialized state*/ + LV_INDEV_TYPE_POINTER, /**< Touch pad, mouse, external button*/ + LV_INDEV_TYPE_KEYPAD, /**< Keypad or keyboard*/ + LV_INDEV_TYPE_BUTTON, /**< External (hardware button) which is assigned to a specific point of the screen*/ + LV_INDEV_TYPE_ENCODER, /**< Encoder with only Left, Right turn and a Button*/ +} lv_indev_type_t; + +/** States for input devices*/ +typedef enum { + LV_INDEV_STATE_RELEASED = 0, + LV_INDEV_STATE_PRESSED +} lv_indev_state_t; + +/** Data structure passed to an input driver to fill*/ +typedef struct { + lv_point_t point; /**< For LV_INDEV_TYPE_POINTER the currently pressed point*/ + uint32_t key; /**< For LV_INDEV_TYPE_KEYPAD the currently pressed key*/ + uint32_t btn_id; /**< For LV_INDEV_TYPE_BUTTON the currently pressed button*/ + int16_t enc_diff; /**< For LV_INDEV_TYPE_ENCODER number of steps since the previous read*/ + + lv_indev_state_t state; /**< LV_INDEV_STATE_REL or LV_INDEV_STATE_PR*/ + bool continue_reading; /**< If set to true, the read callback is invoked again*/ +} lv_indev_data_t; + +/** Initialized by the user and registered by 'lv_indev_add()'*/ +typedef struct _lv_indev_drv_t { + + /**< Input device type*/ + lv_indev_type_t type; + + /**< Function pointer to read input device data.*/ + void (*read_cb)(struct _lv_indev_drv_t * indev_drv, lv_indev_data_t * data); + + /** Called when an action happened on the input device. + * The second parameter is the event from `lv_event_t`*/ + void (*feedback_cb)(struct _lv_indev_drv_t *, uint8_t); + +#if LV_USE_USER_DATA + void * user_data; +#endif + + /**< Pointer to the assigned display*/ + struct _lv_disp_t * disp; + + /**< Timer to periodically read the input device*/ + lv_timer_t * read_timer; + + /**< Number of pixels to slide before actually drag the object*/ + uint8_t scroll_limit; + + /**< Drag throw slow-down in [%]. Greater value means faster slow-down*/ + uint8_t scroll_throw; + + /**< At least this difference should be between two points to evaluate as gesture*/ + uint8_t gesture_min_velocity; + + /**< At least this difference should be to send a gesture*/ + uint8_t gesture_limit; + + /**< Long press time in milliseconds*/ + uint16_t long_press_time; + + /**< Repeated trigger period in long press [ms]*/ + uint16_t long_press_repeat_time; +} lv_indev_drv_t; + +/** Run time data of input devices + * Internally used by the library, you should not need to touch it. + */ +typedef struct _lv_indev_proc_t { + lv_indev_state_t state; /**< Current state of the input device.*/ + /*Flags*/ + uint8_t long_pr_sent : 1; + uint8_t reset_query : 1; + uint8_t disabled : 1; + uint8_t wait_until_release : 1; + + union { + struct { + /*Pointer and button data*/ + lv_point_t act_point; /**< Current point of input device.*/ + lv_point_t last_point; /**< Last point of input device.*/ + lv_point_t last_raw_point; /**< Last point read from read_cb. */ + lv_point_t vect; /**< Difference between `act_point` and `last_point`.*/ + lv_point_t scroll_sum; /*Count the dragged pixels to check LV_INDEV_DEF_SCROLL_LIMIT*/ + lv_point_t scroll_throw_vect; + lv_point_t scroll_throw_vect_ori; + struct _lv_obj_t * act_obj; /*The object being pressed*/ + struct _lv_obj_t * last_obj; /*The last object which was pressed*/ + struct _lv_obj_t * scroll_obj; /*The object being scrolled*/ + struct _lv_obj_t * last_pressed; /*The lastly pressed object*/ + lv_area_t scroll_area; + + lv_point_t gesture_sum; /*Count the gesture pixels to check LV_INDEV_DEF_GESTURE_LIMIT*/ + /*Flags*/ + lv_dir_t scroll_dir : 4; + lv_dir_t gesture_dir : 4; + uint8_t gesture_sent : 1; + } pointer; + struct { + /*Keypad data*/ + lv_indev_state_t last_state; + uint32_t last_key; + } keypad; + } types; + + uint32_t pr_timestamp; /**< Pressed time stamp*/ + uint32_t longpr_rep_timestamp; /**< Long press repeat time stamp*/ +} _lv_indev_proc_t; + +/** The main input device descriptor with driver, runtime data ('proc') and some additional + * information*/ +typedef struct _lv_indev_t { + struct _lv_indev_drv_t * driver; + _lv_indev_proc_t proc; + struct _lv_obj_t * cursor; /**< Cursor for LV_INPUT_TYPE_POINTER*/ + struct _lv_group_t * group; /**< Keypad destination group*/ + const lv_point_t * btn_points; /**< Array points assigned to the button ()screen will be pressed + here by the buttons*/ +} lv_indev_t; + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +/** + * Initialize an input device driver with default values. + * It is used to surely have known values in the fields and not memory junk. + * After it you can set the fields. + * @param driver pointer to driver variable to initialize + */ +void lv_indev_drv_init(struct _lv_indev_drv_t * driver); + +/** + * Register an initialized input device driver. + * @param driver pointer to an initialized 'lv_indev_drv_t' variable (can be local variable) + * @return pointer to the new input device or NULL on error + */ +lv_indev_t * lv_indev_drv_register(struct _lv_indev_drv_t * driver); + +/** + * Update the driver in run time. + * @param indev pointer to an input device. (return value of `lv_indev_drv_register`) + * @param new_drv pointer to the new driver + */ +void lv_indev_drv_update(lv_indev_t * indev, struct _lv_indev_drv_t * new_drv); + +/** +* Remove the provided input device. Make sure not to use the provided input device afterwards anymore. +* @param indev pointer to delete +*/ +void lv_indev_delete(lv_indev_t * indev); + +/** + * Get the next input device. + * @param indev pointer to the current input device. NULL to initialize. + * @return the next input device or NULL if there are no more. Provide the first input device when + * the parameter is NULL + */ +lv_indev_t * lv_indev_get_next(lv_indev_t * indev); + +/** + * Read data from an input device. + * @param indev pointer to an input device + * @param data input device will write its data here + */ +void _lv_indev_read(lv_indev_t * indev, lv_indev_data_t * data); + +/********************** + * MACROS + **********************/ + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif diff --git a/src/lib/lvgl/src/hal/lv_hal_tick.h b/src/lib/lvgl/src/hal/lv_hal_tick.h new file mode 100644 index 0000000..949f56b --- /dev/null +++ b/src/lib/lvgl/src/hal/lv_hal_tick.h @@ -0,0 +1,69 @@ +/** + * @file lv_hal_tick.h + * Provide access to the system tick with 1 millisecond resolution + */ + +#ifndef LV_HAL_TICK_H +#define LV_HAL_TICK_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include "../lv_conf_internal.h" + +#include +#include + +/********************* + * DEFINES + *********************/ +#ifndef LV_ATTRIBUTE_TICK_INC +#define LV_ATTRIBUTE_TICK_INC +#endif + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +//! @cond Doxygen_Suppress + +#if !LV_TICK_CUSTOM +/** + * You have to call this function periodically + * @param tick_period the call period of this function in milliseconds + */ +LV_ATTRIBUTE_TICK_INC void lv_tick_inc(uint32_t tick_period); +#endif + +//! @endcond + +/** + * Get the elapsed milliseconds since start up + * @return the elapsed milliseconds + */ +uint32_t lv_tick_get(void); + +/** + * Get the elapsed milliseconds since a previous time stamp + * @param prev_tick a previous time stamp (return value of lv_tick_get() ) + * @return the elapsed milliseconds since 'prev_tick' + */ +uint32_t lv_tick_elaps(uint32_t prev_tick); + +/********************** + * MACROS + **********************/ + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif /*LV_HAL_TICK_H*/ diff --git a/src/lib/lvgl/src/lv_api_map.h b/src/lib/lvgl/src/lv_api_map.h new file mode 100644 index 0000000..f2b640a --- /dev/null +++ b/src/lib/lvgl/src/lv_api_map.h @@ -0,0 +1,88 @@ +/** + * @file lv_api_map.h + * + */ + +#ifndef LV_API_MAP_H +#define LV_API_MAP_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include "../lvgl.h" + +/********************* + * DEFINES + *********************/ + +#define LV_NO_TASK_READY LV_NO_TIMER_READY +#define LV_INDEV_STATE_REL LV_INDEV_STATE_RELEASED +#define LV_INDEV_STATE_PR LV_INDEV_STATE_PRESSED +#define LV_OBJ_FLAG_SNAPABLE LV_OBJ_FLAG_SNAPPABLE /*Fixed typo*/ + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +static inline LV_ATTRIBUTE_TIMER_HANDLER uint32_t lv_task_handler(void) +{ + return lv_timer_handler(); +} + +/********************** + * MACROS + **********************/ + + +/********************** + * INLINE FUNCTIONS + **********************/ + +/** + * Move the object to the foreground. + * It will look like if it was created as the last child of its parent. + * It also means it can cover any of the siblings. + * @param obj pointer to an object + */ +static inline void lv_obj_move_foreground(lv_obj_t * obj) +{ + lv_obj_t * parent = lv_obj_get_parent(obj); + lv_obj_move_to_index(obj, lv_obj_get_child_cnt(parent) - 1); +} + +/** + * Move the object to the background. + * It will look like if it was created as the first child of its parent. + * It also means any of the siblings can cover the object. + * @param obj pointer to an object + */ +static inline void lv_obj_move_background(lv_obj_t * obj) +{ + lv_obj_move_to_index(obj, 0); +} + + + +/********************** + * DEPRECATED FUNCTIONS + **********************/ + +static inline uint32_t lv_obj_get_child_id(const struct _lv_obj_t * obj) +{ + LV_LOG_WARN("lv_obj_get_child_id(obj) is deprecated, please use lv_obj_get_index(obj)."); + return lv_obj_get_index(obj); +} + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif /*LV_API_MAP_H*/ diff --git a/src/lib/lvgl/src/lv_conf_internal.h b/src/lib/lvgl/src/lv_conf_internal.h new file mode 100644 index 0000000..ebc1057 --- /dev/null +++ b/src/lib/lvgl/src/lv_conf_internal.h @@ -0,0 +1,2255 @@ +/** + * GENERATED FILE, DO NOT EDIT IT! + * @file lv_conf_internal.h + * Make sure all the defines of lv_conf.h have a default value +**/ + +#ifndef LV_CONF_INTERNAL_H +#define LV_CONF_INTERNAL_H +/* clang-format off */ + +#include + +/* Handle special Kconfig options */ +#ifndef LV_KCONFIG_IGNORE + #include "lv_conf_kconfig.h" + #ifdef CONFIG_LV_CONF_SKIP + #define LV_CONF_SKIP + #endif +#endif + +/*If "lv_conf.h" is available from here try to use it later.*/ +#ifdef __has_include + #if __has_include("lv_conf.h") + #ifndef LV_CONF_INCLUDE_SIMPLE + #define LV_CONF_INCLUDE_SIMPLE + #endif + #endif +#endif + +/*If lv_conf.h is not skipped include it*/ +#ifndef LV_CONF_SKIP + #ifdef LV_CONF_PATH /*If there is a path defined for lv_conf.h use it*/ + #define __LV_TO_STR_AUX(x) #x + #define __LV_TO_STR(x) __LV_TO_STR_AUX(x) + #include __LV_TO_STR(LV_CONF_PATH) + #undef __LV_TO_STR_AUX + #undef __LV_TO_STR + #elif defined(LV_CONF_INCLUDE_SIMPLE) /*Or simply include lv_conf.h is enabled*/ + #include "lv_conf.h" + #else + #include "../../lv_conf.h" /*Else assume lv_conf.h is next to the lvgl folder*/ + #endif +#endif + +#ifdef CONFIG_LV_COLOR_DEPTH + #define _LV_KCONFIG_PRESENT +#endif + +/*---------------------------------- + * Start parsing lv_conf_template.h + -----------------------------------*/ + +#include + +/*==================== + COLOR SETTINGS + *====================*/ + +/*Color depth: 1 (1 byte per pixel), 8 (RGB332), 16 (RGB565), 32 (ARGB8888)*/ +#ifndef LV_COLOR_DEPTH + #ifdef CONFIG_LV_COLOR_DEPTH + #define LV_COLOR_DEPTH CONFIG_LV_COLOR_DEPTH + #else + #define LV_COLOR_DEPTH 16 + #endif +#endif + +/*Swap the 2 bytes of RGB565 color. Useful if the display has an 8-bit interface (e.g. SPI)*/ +#ifndef LV_COLOR_16_SWAP + #ifdef CONFIG_LV_COLOR_16_SWAP + #define LV_COLOR_16_SWAP CONFIG_LV_COLOR_16_SWAP + #else + #define LV_COLOR_16_SWAP 0 + #endif +#endif + +/*Enable more complex drawing routines to manage screens transparency. + *Can be used if the UI is above another layer, e.g. an OSD menu or video player. + *Requires `LV_COLOR_DEPTH = 32` colors and the screen's `bg_opa` should be set to non LV_OPA_COVER value*/ +#ifndef LV_COLOR_SCREEN_TRANSP + #ifdef CONFIG_LV_COLOR_SCREEN_TRANSP + #define LV_COLOR_SCREEN_TRANSP CONFIG_LV_COLOR_SCREEN_TRANSP + #else + #define LV_COLOR_SCREEN_TRANSP 0 + #endif +#endif + +/* Adjust color mix functions rounding. GPUs might calculate color mix (blending) differently. + * 0: round down, 64: round up from x.75, 128: round up from half, 192: round up from x.25, 254: round up */ +#ifndef LV_COLOR_MIX_ROUND_OFS + #ifdef CONFIG_LV_COLOR_MIX_ROUND_OFS + #define LV_COLOR_MIX_ROUND_OFS CONFIG_LV_COLOR_MIX_ROUND_OFS + #else + #define LV_COLOR_MIX_ROUND_OFS (LV_COLOR_DEPTH == 32 ? 0: 128) + #endif +#endif + +/*Images pixels with this color will not be drawn if they are chroma keyed)*/ +#ifndef LV_COLOR_CHROMA_KEY + #ifdef CONFIG_LV_COLOR_CHROMA_KEY + #define LV_COLOR_CHROMA_KEY CONFIG_LV_COLOR_CHROMA_KEY + #else + #define LV_COLOR_CHROMA_KEY lv_color_hex(0x00ff00) /*pure green*/ + #endif +#endif + +/*========================= + MEMORY SETTINGS + *=========================*/ + +/*1: use custom malloc/free, 0: use the built-in `lv_mem_alloc()` and `lv_mem_free()`*/ +#ifndef LV_MEM_CUSTOM + #ifdef CONFIG_LV_MEM_CUSTOM + #define LV_MEM_CUSTOM CONFIG_LV_MEM_CUSTOM + #else + #define LV_MEM_CUSTOM 0 + #endif +#endif +#if LV_MEM_CUSTOM == 0 + /*Size of the memory available for `lv_mem_alloc()` in bytes (>= 2kB)*/ + #ifndef LV_MEM_SIZE + #ifdef CONFIG_LV_MEM_SIZE + #define LV_MEM_SIZE CONFIG_LV_MEM_SIZE + #else + #define LV_MEM_SIZE (48U * 1024U) /*[bytes]*/ + #endif + #endif + + /*Set an address for the memory pool instead of allocating it as a normal array. Can be in external SRAM too.*/ + #ifndef LV_MEM_ADR + #ifdef CONFIG_LV_MEM_ADR + #define LV_MEM_ADR CONFIG_LV_MEM_ADR + #else + #define LV_MEM_ADR 0 /*0: unused*/ + #endif + #endif + /*Instead of an address give a memory allocator that will be called to get a memory pool for LVGL. E.g. my_malloc*/ + #if LV_MEM_ADR == 0 + //#define LV_MEM_POOL_INCLUDE your_alloc_library /* Uncomment if using an external allocator*/ + //#define LV_MEM_POOL_ALLOC your_alloc /* Uncomment if using an external allocator*/ + #endif + +#else /*LV_MEM_CUSTOM*/ + #ifndef LV_MEM_CUSTOM_INCLUDE + #ifdef CONFIG_LV_MEM_CUSTOM_INCLUDE + #define LV_MEM_CUSTOM_INCLUDE CONFIG_LV_MEM_CUSTOM_INCLUDE + #else + #define LV_MEM_CUSTOM_INCLUDE /*Header for the dynamic memory function*/ + #endif + #endif + #ifndef LV_MEM_CUSTOM_ALLOC + #ifdef CONFIG_LV_MEM_CUSTOM_ALLOC + #define LV_MEM_CUSTOM_ALLOC CONFIG_LV_MEM_CUSTOM_ALLOC + #else + #define LV_MEM_CUSTOM_ALLOC malloc + #endif + #endif + #ifndef LV_MEM_CUSTOM_FREE + #ifdef CONFIG_LV_MEM_CUSTOM_FREE + #define LV_MEM_CUSTOM_FREE CONFIG_LV_MEM_CUSTOM_FREE + #else + #define LV_MEM_CUSTOM_FREE free + #endif + #endif + #ifndef LV_MEM_CUSTOM_REALLOC + #ifdef CONFIG_LV_MEM_CUSTOM_REALLOC + #define LV_MEM_CUSTOM_REALLOC CONFIG_LV_MEM_CUSTOM_REALLOC + #else + #define LV_MEM_CUSTOM_REALLOC realloc + #endif + #endif +#endif /*LV_MEM_CUSTOM*/ + +/*Number of the intermediate memory buffer used during rendering and other internal processing mechanisms. + *You will see an error log message if there wasn't enough buffers. */ +#ifndef LV_MEM_BUF_MAX_NUM + #ifdef CONFIG_LV_MEM_BUF_MAX_NUM + #define LV_MEM_BUF_MAX_NUM CONFIG_LV_MEM_BUF_MAX_NUM + #else + #define LV_MEM_BUF_MAX_NUM 16 + #endif +#endif + +/*Use the standard `memcpy` and `memset` instead of LVGL's own functions. (Might or might not be faster).*/ +#ifndef LV_MEMCPY_MEMSET_STD + #ifdef CONFIG_LV_MEMCPY_MEMSET_STD + #define LV_MEMCPY_MEMSET_STD CONFIG_LV_MEMCPY_MEMSET_STD + #else + #define LV_MEMCPY_MEMSET_STD 0 + #endif +#endif + +/*==================== + HAL SETTINGS + *====================*/ + +/*Default display refresh period. LVG will redraw changed areas with this period time*/ +#ifndef LV_DISP_DEF_REFR_PERIOD + #ifdef CONFIG_LV_DISP_DEF_REFR_PERIOD + #define LV_DISP_DEF_REFR_PERIOD CONFIG_LV_DISP_DEF_REFR_PERIOD + #else + #define LV_DISP_DEF_REFR_PERIOD 30 /*[ms]*/ + #endif +#endif + +/*Input device read period in milliseconds*/ +#ifndef LV_INDEV_DEF_READ_PERIOD + #ifdef CONFIG_LV_INDEV_DEF_READ_PERIOD + #define LV_INDEV_DEF_READ_PERIOD CONFIG_LV_INDEV_DEF_READ_PERIOD + #else + #define LV_INDEV_DEF_READ_PERIOD 30 /*[ms]*/ + #endif +#endif + +/*Use a custom tick source that tells the elapsed time in milliseconds. + *It removes the need to manually update the tick with `lv_tick_inc()`)*/ +#ifndef LV_TICK_CUSTOM + #ifdef CONFIG_LV_TICK_CUSTOM + #define LV_TICK_CUSTOM CONFIG_LV_TICK_CUSTOM + #else + #define LV_TICK_CUSTOM 0 + #endif +#endif +#if LV_TICK_CUSTOM + #ifndef LV_TICK_CUSTOM_INCLUDE + #ifdef CONFIG_LV_TICK_CUSTOM_INCLUDE + #define LV_TICK_CUSTOM_INCLUDE CONFIG_LV_TICK_CUSTOM_INCLUDE + #else + #define LV_TICK_CUSTOM_INCLUDE "Arduino.h" /*Header for the system time function*/ + #endif + #endif + #ifndef LV_TICK_CUSTOM_SYS_TIME_EXPR + #ifdef CONFIG_LV_TICK_CUSTOM_SYS_TIME_EXPR + #define LV_TICK_CUSTOM_SYS_TIME_EXPR CONFIG_LV_TICK_CUSTOM_SYS_TIME_EXPR + #else + #define LV_TICK_CUSTOM_SYS_TIME_EXPR (millis()) /*Expression evaluating to current system time in ms*/ + #endif + #endif +#endif /*LV_TICK_CUSTOM*/ + +/*Default Dot Per Inch. Used to initialize default sizes such as widgets sized, style paddings. + *(Not so important, you can adjust it to modify default sizes and spaces)*/ +#ifndef LV_DPI_DEF + #ifdef CONFIG_LV_DPI_DEF + #define LV_DPI_DEF CONFIG_LV_DPI_DEF + #else + #define LV_DPI_DEF 130 /*[px/inch]*/ + #endif +#endif + +/*======================= + * FEATURE CONFIGURATION + *=======================*/ + +/*------------- + * Drawing + *-----------*/ + +/*Enable complex draw engine. + *Required to draw shadow, gradient, rounded corners, circles, arc, skew lines, image transformations or any masks*/ +#ifndef LV_DRAW_COMPLEX + #ifdef _LV_KCONFIG_PRESENT + #ifdef CONFIG_LV_DRAW_COMPLEX + #define LV_DRAW_COMPLEX CONFIG_LV_DRAW_COMPLEX + #else + #define LV_DRAW_COMPLEX 0 + #endif + #else + #define LV_DRAW_COMPLEX 1 + #endif +#endif +#if LV_DRAW_COMPLEX != 0 + + /*Allow buffering some shadow calculation. + *LV_SHADOW_CACHE_SIZE is the max. shadow size to buffer, where shadow size is `shadow_width + radius` + *Caching has LV_SHADOW_CACHE_SIZE^2 RAM cost*/ + #ifndef LV_SHADOW_CACHE_SIZE + #ifdef CONFIG_LV_SHADOW_CACHE_SIZE + #define LV_SHADOW_CACHE_SIZE CONFIG_LV_SHADOW_CACHE_SIZE + #else + #define LV_SHADOW_CACHE_SIZE 0 + #endif + #endif + + /* Set number of maximally cached circle data. + * The circumference of 1/4 circle are saved for anti-aliasing + * radius * 4 bytes are used per circle (the most often used radiuses are saved) + * 0: to disable caching */ + #ifndef LV_CIRCLE_CACHE_SIZE + #ifdef CONFIG_LV_CIRCLE_CACHE_SIZE + #define LV_CIRCLE_CACHE_SIZE CONFIG_LV_CIRCLE_CACHE_SIZE + #else + #define LV_CIRCLE_CACHE_SIZE 4 + #endif + #endif +#endif /*LV_DRAW_COMPLEX*/ + +/*Default image cache size. Image caching keeps the images opened. + *If only the built-in image formats are used there is no real advantage of caching. (I.e. if no new image decoder is added) + *With complex image decoders (e.g. PNG or JPG) caching can save the continuous open/decode of images. + *However the opened images might consume additional RAM. + *0: to disable caching*/ +#ifndef LV_IMG_CACHE_DEF_SIZE + #ifdef CONFIG_LV_IMG_CACHE_DEF_SIZE + #define LV_IMG_CACHE_DEF_SIZE CONFIG_LV_IMG_CACHE_DEF_SIZE + #else + #define LV_IMG_CACHE_DEF_SIZE 0 + #endif +#endif + +/*Number of stops allowed per gradient. Increase this to allow more stops. + *This adds (sizeof(lv_color_t) + 1) bytes per additional stop*/ +#ifndef LV_GRADIENT_MAX_STOPS + #ifdef CONFIG_LV_GRADIENT_MAX_STOPS + #define LV_GRADIENT_MAX_STOPS CONFIG_LV_GRADIENT_MAX_STOPS + #else + #define LV_GRADIENT_MAX_STOPS 2 + #endif +#endif + +/*Default gradient buffer size. + *When LVGL calculates the gradient "maps" it can save them into a cache to avoid calculating them again. + *LV_GRAD_CACHE_DEF_SIZE sets the size of this cache in bytes. + *If the cache is too small the map will be allocated only while it's required for the drawing. + *0 mean no caching.*/ +#ifndef LV_GRAD_CACHE_DEF_SIZE + #ifdef CONFIG_LV_GRAD_CACHE_DEF_SIZE + #define LV_GRAD_CACHE_DEF_SIZE CONFIG_LV_GRAD_CACHE_DEF_SIZE + #else + #define LV_GRAD_CACHE_DEF_SIZE 0 + #endif +#endif + +/*Allow dithering the gradients (to achieve visual smooth color gradients on limited color depth display) + *LV_DITHER_GRADIENT implies allocating one or two more lines of the object's rendering surface + *The increase in memory consumption is (32 bits * object width) plus 24 bits * object width if using error diffusion */ +#ifndef LV_DITHER_GRADIENT + #ifdef CONFIG_LV_DITHER_GRADIENT + #define LV_DITHER_GRADIENT CONFIG_LV_DITHER_GRADIENT + #else + #define LV_DITHER_GRADIENT 0 + #endif +#endif +#if LV_DITHER_GRADIENT + /*Add support for error diffusion dithering. + *Error diffusion dithering gets a much better visual result, but implies more CPU consumption and memory when drawing. + *The increase in memory consumption is (24 bits * object's width)*/ + #ifndef LV_DITHER_ERROR_DIFFUSION + #ifdef CONFIG_LV_DITHER_ERROR_DIFFUSION + #define LV_DITHER_ERROR_DIFFUSION CONFIG_LV_DITHER_ERROR_DIFFUSION + #else + #define LV_DITHER_ERROR_DIFFUSION 0 + #endif + #endif +#endif + +/*Maximum buffer size to allocate for rotation. + *Only used if software rotation is enabled in the display driver.*/ +#ifndef LV_DISP_ROT_MAX_BUF + #ifdef CONFIG_LV_DISP_ROT_MAX_BUF + #define LV_DISP_ROT_MAX_BUF CONFIG_LV_DISP_ROT_MAX_BUF + #else + #define LV_DISP_ROT_MAX_BUF (10*1024) + #endif +#endif + +/*------------- + * GPU + *-----------*/ + +/*Use STM32's DMA2D (aka Chrom Art) GPU*/ +#ifndef LV_USE_GPU_STM32_DMA2D + #ifdef CONFIG_LV_USE_GPU_STM32_DMA2D + #define LV_USE_GPU_STM32_DMA2D CONFIG_LV_USE_GPU_STM32_DMA2D + #else + #define LV_USE_GPU_STM32_DMA2D 0 + #endif +#endif +#if LV_USE_GPU_STM32_DMA2D + /*Must be defined to include path of CMSIS header of target processor + e.g. "stm32f769xx.h" or "stm32f429xx.h"*/ + #ifndef LV_GPU_DMA2D_CMSIS_INCLUDE + #ifdef CONFIG_LV_GPU_DMA2D_CMSIS_INCLUDE + #define LV_GPU_DMA2D_CMSIS_INCLUDE CONFIG_LV_GPU_DMA2D_CMSIS_INCLUDE + #else + #define LV_GPU_DMA2D_CMSIS_INCLUDE + #endif + #endif +#endif + +/*Use NXP's PXP GPU iMX RTxxx platforms*/ +#ifndef LV_USE_GPU_NXP_PXP + #ifdef CONFIG_LV_USE_GPU_NXP_PXP + #define LV_USE_GPU_NXP_PXP CONFIG_LV_USE_GPU_NXP_PXP + #else + #define LV_USE_GPU_NXP_PXP 0 + #endif +#endif +#if LV_USE_GPU_NXP_PXP + /*1: Add default bare metal and FreeRTOS interrupt handling routines for PXP (lv_gpu_nxp_pxp_osa.c) + * and call lv_gpu_nxp_pxp_init() automatically during lv_init(). Note that symbol SDK_OS_FREE_RTOS + * has to be defined in order to use FreeRTOS OSA, otherwise bare-metal implementation is selected. + *0: lv_gpu_nxp_pxp_init() has to be called manually before lv_init() + */ + #ifndef LV_USE_GPU_NXP_PXP_AUTO_INIT + #ifdef CONFIG_LV_USE_GPU_NXP_PXP_AUTO_INIT + #define LV_USE_GPU_NXP_PXP_AUTO_INIT CONFIG_LV_USE_GPU_NXP_PXP_AUTO_INIT + #else + #define LV_USE_GPU_NXP_PXP_AUTO_INIT 0 + #endif + #endif +#endif + +/*Use NXP's VG-Lite GPU iMX RTxxx platforms*/ +#ifndef LV_USE_GPU_NXP_VG_LITE + #ifdef CONFIG_LV_USE_GPU_NXP_VG_LITE + #define LV_USE_GPU_NXP_VG_LITE CONFIG_LV_USE_GPU_NXP_VG_LITE + #else + #define LV_USE_GPU_NXP_VG_LITE 0 + #endif +#endif + +/*Use SDL renderer API*/ +#ifndef LV_USE_GPU_SDL + #ifdef CONFIG_LV_USE_GPU_SDL + #define LV_USE_GPU_SDL CONFIG_LV_USE_GPU_SDL + #else + #define LV_USE_GPU_SDL 0 + #endif +#endif +#if LV_USE_GPU_SDL + #ifndef LV_GPU_SDL_INCLUDE_PATH + #ifdef CONFIG_LV_GPU_SDL_INCLUDE_PATH + #define LV_GPU_SDL_INCLUDE_PATH CONFIG_LV_GPU_SDL_INCLUDE_PATH + #else + #define LV_GPU_SDL_INCLUDE_PATH + #endif + #endif + /*Texture cache size, 8MB by default*/ + #ifndef LV_GPU_SDL_LRU_SIZE + #ifdef CONFIG_LV_GPU_SDL_LRU_SIZE + #define LV_GPU_SDL_LRU_SIZE CONFIG_LV_GPU_SDL_LRU_SIZE + #else + #define LV_GPU_SDL_LRU_SIZE (1024 * 1024 * 8) + #endif + #endif + /*Custom blend mode for mask drawing, disable if you need to link with older SDL2 lib*/ + #ifndef LV_GPU_SDL_CUSTOM_BLEND_MODE + #ifdef CONFIG_LV_GPU_SDL_CUSTOM_BLEND_MODE + #define LV_GPU_SDL_CUSTOM_BLEND_MODE CONFIG_LV_GPU_SDL_CUSTOM_BLEND_MODE + #else + #define LV_GPU_SDL_CUSTOM_BLEND_MODE (SDL_VERSION_ATLEAST(2, 0, 6)) + #endif + #endif +#endif + +/*------------- + * Logging + *-----------*/ + +/*Enable the log module*/ +#ifndef LV_USE_LOG + #ifdef CONFIG_LV_USE_LOG + #define LV_USE_LOG CONFIG_LV_USE_LOG + #else + #define LV_USE_LOG 0 + #endif +#endif +#if LV_USE_LOG + + /*How important log should be added: + *LV_LOG_LEVEL_TRACE A lot of logs to give detailed information + *LV_LOG_LEVEL_INFO Log important events + *LV_LOG_LEVEL_WARN Log if something unwanted happened but didn't cause a problem + *LV_LOG_LEVEL_ERROR Only critical issue, when the system may fail + *LV_LOG_LEVEL_USER Only logs added by the user + *LV_LOG_LEVEL_NONE Do not log anything*/ + #ifndef LV_LOG_LEVEL + #ifdef CONFIG_LV_LOG_LEVEL + #define LV_LOG_LEVEL CONFIG_LV_LOG_LEVEL + #else + #define LV_LOG_LEVEL LV_LOG_LEVEL_WARN + #endif + #endif + + /*1: Print the log with 'printf'; + *0: User need to register a callback with `lv_log_register_print_cb()`*/ + #ifndef LV_LOG_PRINTF + #ifdef CONFIG_LV_LOG_PRINTF + #define LV_LOG_PRINTF CONFIG_LV_LOG_PRINTF + #else + #define LV_LOG_PRINTF 0 + #endif + #endif + + /*Enable/disable LV_LOG_TRACE in modules that produces a huge number of logs*/ + #ifndef LV_LOG_TRACE_MEM + #ifdef _LV_KCONFIG_PRESENT + #ifdef CONFIG_LV_LOG_TRACE_MEM + #define LV_LOG_TRACE_MEM CONFIG_LV_LOG_TRACE_MEM + #else + #define LV_LOG_TRACE_MEM 0 + #endif + #else + #define LV_LOG_TRACE_MEM 1 + #endif + #endif + #ifndef LV_LOG_TRACE_TIMER + #ifdef _LV_KCONFIG_PRESENT + #ifdef CONFIG_LV_LOG_TRACE_TIMER + #define LV_LOG_TRACE_TIMER CONFIG_LV_LOG_TRACE_TIMER + #else + #define LV_LOG_TRACE_TIMER 0 + #endif + #else + #define LV_LOG_TRACE_TIMER 1 + #endif + #endif + #ifndef LV_LOG_TRACE_INDEV + #ifdef _LV_KCONFIG_PRESENT + #ifdef CONFIG_LV_LOG_TRACE_INDEV + #define LV_LOG_TRACE_INDEV CONFIG_LV_LOG_TRACE_INDEV + #else + #define LV_LOG_TRACE_INDEV 0 + #endif + #else + #define LV_LOG_TRACE_INDEV 1 + #endif + #endif + #ifndef LV_LOG_TRACE_DISP_REFR + #ifdef _LV_KCONFIG_PRESENT + #ifdef CONFIG_LV_LOG_TRACE_DISP_REFR + #define LV_LOG_TRACE_DISP_REFR CONFIG_LV_LOG_TRACE_DISP_REFR + #else + #define LV_LOG_TRACE_DISP_REFR 0 + #endif + #else + #define LV_LOG_TRACE_DISP_REFR 1 + #endif + #endif + #ifndef LV_LOG_TRACE_EVENT + #ifdef _LV_KCONFIG_PRESENT + #ifdef CONFIG_LV_LOG_TRACE_EVENT + #define LV_LOG_TRACE_EVENT CONFIG_LV_LOG_TRACE_EVENT + #else + #define LV_LOG_TRACE_EVENT 0 + #endif + #else + #define LV_LOG_TRACE_EVENT 1 + #endif + #endif + #ifndef LV_LOG_TRACE_OBJ_CREATE + #ifdef _LV_KCONFIG_PRESENT + #ifdef CONFIG_LV_LOG_TRACE_OBJ_CREATE + #define LV_LOG_TRACE_OBJ_CREATE CONFIG_LV_LOG_TRACE_OBJ_CREATE + #else + #define LV_LOG_TRACE_OBJ_CREATE 0 + #endif + #else + #define LV_LOG_TRACE_OBJ_CREATE 1 + #endif + #endif + #ifndef LV_LOG_TRACE_LAYOUT + #ifdef _LV_KCONFIG_PRESENT + #ifdef CONFIG_LV_LOG_TRACE_LAYOUT + #define LV_LOG_TRACE_LAYOUT CONFIG_LV_LOG_TRACE_LAYOUT + #else + #define LV_LOG_TRACE_LAYOUT 0 + #endif + #else + #define LV_LOG_TRACE_LAYOUT 1 + #endif + #endif + #ifndef LV_LOG_TRACE_ANIM + #ifdef _LV_KCONFIG_PRESENT + #ifdef CONFIG_LV_LOG_TRACE_ANIM + #define LV_LOG_TRACE_ANIM CONFIG_LV_LOG_TRACE_ANIM + #else + #define LV_LOG_TRACE_ANIM 0 + #endif + #else + #define LV_LOG_TRACE_ANIM 1 + #endif + #endif + +#endif /*LV_USE_LOG*/ + +/*------------- + * Asserts + *-----------*/ + +/*Enable asserts if an operation is failed or an invalid data is found. + *If LV_USE_LOG is enabled an error message will be printed on failure*/ +#ifndef LV_USE_ASSERT_NULL + #ifdef CONFIG_LV_USE_ASSERT_NULL + #define LV_USE_ASSERT_NULL CONFIG_LV_USE_ASSERT_NULL + #else + #define LV_USE_ASSERT_NULL 1 /*Check if the parameter is NULL. (Very fast, recommended)*/ + #endif +#endif +#ifndef LV_USE_ASSERT_MALLOC + #ifdef CONFIG_LV_USE_ASSERT_MALLOC + #define LV_USE_ASSERT_MALLOC CONFIG_LV_USE_ASSERT_MALLOC + #else + #define LV_USE_ASSERT_MALLOC 1 /*Checks is the memory is successfully allocated or no. (Very fast, recommended)*/ + #endif +#endif +#ifndef LV_USE_ASSERT_STYLE + #ifdef CONFIG_LV_USE_ASSERT_STYLE + #define LV_USE_ASSERT_STYLE CONFIG_LV_USE_ASSERT_STYLE + #else + #define LV_USE_ASSERT_STYLE 0 /*Check if the styles are properly initialized. (Very fast, recommended)*/ + #endif +#endif +#ifndef LV_USE_ASSERT_MEM_INTEGRITY + #ifdef CONFIG_LV_USE_ASSERT_MEM_INTEGRITY + #define LV_USE_ASSERT_MEM_INTEGRITY CONFIG_LV_USE_ASSERT_MEM_INTEGRITY + #else + #define LV_USE_ASSERT_MEM_INTEGRITY 0 /*Check the integrity of `lv_mem` after critical operations. (Slow)*/ + #endif +#endif +#ifndef LV_USE_ASSERT_OBJ + #ifdef CONFIG_LV_USE_ASSERT_OBJ + #define LV_USE_ASSERT_OBJ CONFIG_LV_USE_ASSERT_OBJ + #else + #define LV_USE_ASSERT_OBJ 0 /*Check the object's type and existence (e.g. not deleted). (Slow)*/ + #endif +#endif + +/*Add a custom handler when assert happens e.g. to restart the MCU*/ +#ifndef LV_ASSERT_HANDLER_INCLUDE + #ifdef CONFIG_LV_ASSERT_HANDLER_INCLUDE + #define LV_ASSERT_HANDLER_INCLUDE CONFIG_LV_ASSERT_HANDLER_INCLUDE + #else + #define LV_ASSERT_HANDLER_INCLUDE + #endif +#endif +#ifndef LV_ASSERT_HANDLER + #ifdef CONFIG_LV_ASSERT_HANDLER + #define LV_ASSERT_HANDLER CONFIG_LV_ASSERT_HANDLER + #else + #define LV_ASSERT_HANDLER while(1); /*Halt by default*/ + #endif +#endif + +/*------------- + * Others + *-----------*/ + +/*1: Show CPU usage and FPS count*/ +#ifndef LV_USE_PERF_MONITOR + #ifdef CONFIG_LV_USE_PERF_MONITOR + #define LV_USE_PERF_MONITOR CONFIG_LV_USE_PERF_MONITOR + #else + #define LV_USE_PERF_MONITOR 0 + #endif +#endif +#if LV_USE_PERF_MONITOR + #ifndef LV_USE_PERF_MONITOR_POS + #ifdef CONFIG_LV_USE_PERF_MONITOR_POS + #define LV_USE_PERF_MONITOR_POS CONFIG_LV_USE_PERF_MONITOR_POS + #else + #define LV_USE_PERF_MONITOR_POS LV_ALIGN_BOTTOM_RIGHT + #endif + #endif +#endif + +/*1: Show the used memory and the memory fragmentation + * Requires LV_MEM_CUSTOM = 0*/ +#ifndef LV_USE_MEM_MONITOR + #ifdef CONFIG_LV_USE_MEM_MONITOR + #define LV_USE_MEM_MONITOR CONFIG_LV_USE_MEM_MONITOR + #else + #define LV_USE_MEM_MONITOR 0 + #endif +#endif +#if LV_USE_MEM_MONITOR + #ifndef LV_USE_MEM_MONITOR_POS + #ifdef CONFIG_LV_USE_MEM_MONITOR_POS + #define LV_USE_MEM_MONITOR_POS CONFIG_LV_USE_MEM_MONITOR_POS + #else + #define LV_USE_MEM_MONITOR_POS LV_ALIGN_BOTTOM_LEFT + #endif + #endif +#endif + +/*1: Draw random colored rectangles over the redrawn areas*/ +#ifndef LV_USE_REFR_DEBUG + #ifdef CONFIG_LV_USE_REFR_DEBUG + #define LV_USE_REFR_DEBUG CONFIG_LV_USE_REFR_DEBUG + #else + #define LV_USE_REFR_DEBUG 0 + #endif +#endif + +/*Change the built in (v)snprintf functions*/ +#ifndef LV_SPRINTF_CUSTOM + #ifdef CONFIG_LV_SPRINTF_CUSTOM + #define LV_SPRINTF_CUSTOM CONFIG_LV_SPRINTF_CUSTOM + #else + #define LV_SPRINTF_CUSTOM 0 + #endif +#endif +#if LV_SPRINTF_CUSTOM + #ifndef LV_SPRINTF_INCLUDE + #ifdef CONFIG_LV_SPRINTF_INCLUDE + #define LV_SPRINTF_INCLUDE CONFIG_LV_SPRINTF_INCLUDE + #else + #define LV_SPRINTF_INCLUDE + #endif + #endif + #ifndef lv_snprintf + #ifdef CONFIG_LV_SNPRINTF + #define lv_snprintf CONFIG_LV_SNPRINTF + #else + #define lv_snprintf snprintf + #endif + #endif + #ifndef lv_vsnprintf + #ifdef CONFIG_LV_VSNPRINTF + #define lv_vsnprintf CONFIG_LV_VSNPRINTF + #else + #define lv_vsnprintf vsnprintf + #endif + #endif +#else /*LV_SPRINTF_CUSTOM*/ + #ifndef LV_SPRINTF_USE_FLOAT + #ifdef CONFIG_LV_SPRINTF_USE_FLOAT + #define LV_SPRINTF_USE_FLOAT CONFIG_LV_SPRINTF_USE_FLOAT + #else + #define LV_SPRINTF_USE_FLOAT 0 + #endif + #endif +#endif /*LV_SPRINTF_CUSTOM*/ + +#ifndef LV_USE_USER_DATA + #ifdef _LV_KCONFIG_PRESENT + #ifdef CONFIG_LV_USE_USER_DATA + #define LV_USE_USER_DATA CONFIG_LV_USE_USER_DATA + #else + #define LV_USE_USER_DATA 0 + #endif + #else + #define LV_USE_USER_DATA 1 + #endif +#endif + +/*Garbage Collector settings + *Used if lvgl is bound to higher level language and the memory is managed by that language*/ +#ifndef LV_ENABLE_GC + #ifdef CONFIG_LV_ENABLE_GC + #define LV_ENABLE_GC CONFIG_LV_ENABLE_GC + #else + #define LV_ENABLE_GC 0 + #endif +#endif +#if LV_ENABLE_GC != 0 + #ifndef LV_GC_INCLUDE + #ifdef CONFIG_LV_GC_INCLUDE + #define LV_GC_INCLUDE CONFIG_LV_GC_INCLUDE + #else + #define LV_GC_INCLUDE "gc.h" /*Include Garbage Collector related things*/ + #endif + #endif +#endif /*LV_ENABLE_GC*/ + +/*===================== + * COMPILER SETTINGS + *====================*/ + +/*For big endian systems set to 1*/ +#ifndef LV_BIG_ENDIAN_SYSTEM + #ifdef CONFIG_LV_BIG_ENDIAN_SYSTEM + #define LV_BIG_ENDIAN_SYSTEM CONFIG_LV_BIG_ENDIAN_SYSTEM + #else + #define LV_BIG_ENDIAN_SYSTEM 0 + #endif +#endif + +/*Define a custom attribute to `lv_tick_inc` function*/ +#ifndef LV_ATTRIBUTE_TICK_INC + #ifdef CONFIG_LV_ATTRIBUTE_TICK_INC + #define LV_ATTRIBUTE_TICK_INC CONFIG_LV_ATTRIBUTE_TICK_INC + #else + #define LV_ATTRIBUTE_TICK_INC + #endif +#endif + +/*Define a custom attribute to `lv_timer_handler` function*/ +#ifndef LV_ATTRIBUTE_TIMER_HANDLER + #ifdef CONFIG_LV_ATTRIBUTE_TIMER_HANDLER + #define LV_ATTRIBUTE_TIMER_HANDLER CONFIG_LV_ATTRIBUTE_TIMER_HANDLER + #else + #define LV_ATTRIBUTE_TIMER_HANDLER + #endif +#endif + +/*Define a custom attribute to `lv_disp_flush_ready` function*/ +#ifndef LV_ATTRIBUTE_FLUSH_READY + #ifdef CONFIG_LV_ATTRIBUTE_FLUSH_READY + #define LV_ATTRIBUTE_FLUSH_READY CONFIG_LV_ATTRIBUTE_FLUSH_READY + #else + #define LV_ATTRIBUTE_FLUSH_READY + #endif +#endif + +/*Required alignment size for buffers*/ +#ifndef LV_ATTRIBUTE_MEM_ALIGN_SIZE + #ifdef _LV_KCONFIG_PRESENT + #ifdef CONFIG_LV_ATTRIBUTE_MEM_ALIGN_SIZE + #define LV_ATTRIBUTE_MEM_ALIGN_SIZE CONFIG_LV_ATTRIBUTE_MEM_ALIGN_SIZE + #else + #define LV_ATTRIBUTE_MEM_ALIGN_SIZE 0 + #endif + #else + #define LV_ATTRIBUTE_MEM_ALIGN_SIZE 1 + #endif +#endif + +/*Will be added where memories needs to be aligned (with -Os data might not be aligned to boundary by default). + * E.g. __attribute__((aligned(4)))*/ +#ifndef LV_ATTRIBUTE_MEM_ALIGN + #ifdef CONFIG_LV_ATTRIBUTE_MEM_ALIGN + #define LV_ATTRIBUTE_MEM_ALIGN CONFIG_LV_ATTRIBUTE_MEM_ALIGN + #else + #define LV_ATTRIBUTE_MEM_ALIGN + #endif +#endif + +/*Attribute to mark large constant arrays for example font's bitmaps*/ +#ifndef LV_ATTRIBUTE_LARGE_CONST + #ifdef CONFIG_LV_ATTRIBUTE_LARGE_CONST + #define LV_ATTRIBUTE_LARGE_CONST CONFIG_LV_ATTRIBUTE_LARGE_CONST + #else + #define LV_ATTRIBUTE_LARGE_CONST + #endif +#endif + +/*Compiler prefix for a big array declaration in RAM*/ +#ifndef LV_ATTRIBUTE_LARGE_RAM_ARRAY + #ifdef CONFIG_LV_ATTRIBUTE_LARGE_RAM_ARRAY + #define LV_ATTRIBUTE_LARGE_RAM_ARRAY CONFIG_LV_ATTRIBUTE_LARGE_RAM_ARRAY + #else + #define LV_ATTRIBUTE_LARGE_RAM_ARRAY + #endif +#endif + +/*Place performance critical functions into a faster memory (e.g RAM)*/ +#ifndef LV_ATTRIBUTE_FAST_MEM + #ifdef CONFIG_LV_ATTRIBUTE_FAST_MEM + #define LV_ATTRIBUTE_FAST_MEM CONFIG_LV_ATTRIBUTE_FAST_MEM + #else + #define LV_ATTRIBUTE_FAST_MEM + #endif +#endif + +/*Prefix variables that are used in GPU accelerated operations, often these need to be placed in RAM sections that are DMA accessible*/ +#ifndef LV_ATTRIBUTE_DMA + #ifdef CONFIG_LV_ATTRIBUTE_DMA + #define LV_ATTRIBUTE_DMA CONFIG_LV_ATTRIBUTE_DMA + #else + #define LV_ATTRIBUTE_DMA + #endif +#endif + +/*Export integer constant to binding. This macro is used with constants in the form of LV_ that + *should also appear on LVGL binding API such as Micropython.*/ +#ifndef LV_EXPORT_CONST_INT + #ifdef CONFIG_LV_EXPORT_CONST_INT + #define LV_EXPORT_CONST_INT CONFIG_LV_EXPORT_CONST_INT + #else + #define LV_EXPORT_CONST_INT(int_value) struct _silence_gcc_warning /*The default value just prevents GCC warning*/ + #endif +#endif + +/*Extend the default -32k..32k coordinate range to -4M..4M by using int32_t for coordinates instead of int16_t*/ +#ifndef LV_USE_LARGE_COORD + #ifdef CONFIG_LV_USE_LARGE_COORD + #define LV_USE_LARGE_COORD CONFIG_LV_USE_LARGE_COORD + #else + #define LV_USE_LARGE_COORD 0 + #endif +#endif + +/*================== + * FONT USAGE + *===================*/ + +/*Montserrat fonts with ASCII range and some symbols using bpp = 4 + *https://fonts.google.com/specimen/Montserrat*/ +#ifndef LV_FONT_MONTSERRAT_8 + #ifdef CONFIG_LV_FONT_MONTSERRAT_8 + #define LV_FONT_MONTSERRAT_8 CONFIG_LV_FONT_MONTSERRAT_8 + #else + #define LV_FONT_MONTSERRAT_8 0 + #endif +#endif +#ifndef LV_FONT_MONTSERRAT_10 + #ifdef CONFIG_LV_FONT_MONTSERRAT_10 + #define LV_FONT_MONTSERRAT_10 CONFIG_LV_FONT_MONTSERRAT_10 + #else + #define LV_FONT_MONTSERRAT_10 0 + #endif +#endif +#ifndef LV_FONT_MONTSERRAT_12 + #ifdef CONFIG_LV_FONT_MONTSERRAT_12 + #define LV_FONT_MONTSERRAT_12 CONFIG_LV_FONT_MONTSERRAT_12 + #else + #define LV_FONT_MONTSERRAT_12 0 + #endif +#endif +#ifndef LV_FONT_MONTSERRAT_14 + #ifdef _LV_KCONFIG_PRESENT + #ifdef CONFIG_LV_FONT_MONTSERRAT_14 + #define LV_FONT_MONTSERRAT_14 CONFIG_LV_FONT_MONTSERRAT_14 + #else + #define LV_FONT_MONTSERRAT_14 0 + #endif + #else + #define LV_FONT_MONTSERRAT_14 1 + #endif +#endif +#ifndef LV_FONT_MONTSERRAT_16 + #ifdef CONFIG_LV_FONT_MONTSERRAT_16 + #define LV_FONT_MONTSERRAT_16 CONFIG_LV_FONT_MONTSERRAT_16 + #else + #define LV_FONT_MONTSERRAT_16 0 + #endif +#endif +#ifndef LV_FONT_MONTSERRAT_18 + #ifdef CONFIG_LV_FONT_MONTSERRAT_18 + #define LV_FONT_MONTSERRAT_18 CONFIG_LV_FONT_MONTSERRAT_18 + #else + #define LV_FONT_MONTSERRAT_18 0 + #endif +#endif +#ifndef LV_FONT_MONTSERRAT_20 + #ifdef CONFIG_LV_FONT_MONTSERRAT_20 + #define LV_FONT_MONTSERRAT_20 CONFIG_LV_FONT_MONTSERRAT_20 + #else + #define LV_FONT_MONTSERRAT_20 0 + #endif +#endif +#ifndef LV_FONT_MONTSERRAT_22 + #ifdef CONFIG_LV_FONT_MONTSERRAT_22 + #define LV_FONT_MONTSERRAT_22 CONFIG_LV_FONT_MONTSERRAT_22 + #else + #define LV_FONT_MONTSERRAT_22 0 + #endif +#endif +#ifndef LV_FONT_MONTSERRAT_24 + #ifdef CONFIG_LV_FONT_MONTSERRAT_24 + #define LV_FONT_MONTSERRAT_24 CONFIG_LV_FONT_MONTSERRAT_24 + #else + #define LV_FONT_MONTSERRAT_24 0 + #endif +#endif +#ifndef LV_FONT_MONTSERRAT_26 + #ifdef CONFIG_LV_FONT_MONTSERRAT_26 + #define LV_FONT_MONTSERRAT_26 CONFIG_LV_FONT_MONTSERRAT_26 + #else + #define LV_FONT_MONTSERRAT_26 0 + #endif +#endif +#ifndef LV_FONT_MONTSERRAT_28 + #ifdef CONFIG_LV_FONT_MONTSERRAT_28 + #define LV_FONT_MONTSERRAT_28 CONFIG_LV_FONT_MONTSERRAT_28 + #else + #define LV_FONT_MONTSERRAT_28 0 + #endif +#endif +#ifndef LV_FONT_MONTSERRAT_30 + #ifdef CONFIG_LV_FONT_MONTSERRAT_30 + #define LV_FONT_MONTSERRAT_30 CONFIG_LV_FONT_MONTSERRAT_30 + #else + #define LV_FONT_MONTSERRAT_30 0 + #endif +#endif +#ifndef LV_FONT_MONTSERRAT_32 + #ifdef CONFIG_LV_FONT_MONTSERRAT_32 + #define LV_FONT_MONTSERRAT_32 CONFIG_LV_FONT_MONTSERRAT_32 + #else + #define LV_FONT_MONTSERRAT_32 0 + #endif +#endif +#ifndef LV_FONT_MONTSERRAT_34 + #ifdef CONFIG_LV_FONT_MONTSERRAT_34 + #define LV_FONT_MONTSERRAT_34 CONFIG_LV_FONT_MONTSERRAT_34 + #else + #define LV_FONT_MONTSERRAT_34 0 + #endif +#endif +#ifndef LV_FONT_MONTSERRAT_36 + #ifdef CONFIG_LV_FONT_MONTSERRAT_36 + #define LV_FONT_MONTSERRAT_36 CONFIG_LV_FONT_MONTSERRAT_36 + #else + #define LV_FONT_MONTSERRAT_36 0 + #endif +#endif +#ifndef LV_FONT_MONTSERRAT_38 + #ifdef CONFIG_LV_FONT_MONTSERRAT_38 + #define LV_FONT_MONTSERRAT_38 CONFIG_LV_FONT_MONTSERRAT_38 + #else + #define LV_FONT_MONTSERRAT_38 0 + #endif +#endif +#ifndef LV_FONT_MONTSERRAT_40 + #ifdef CONFIG_LV_FONT_MONTSERRAT_40 + #define LV_FONT_MONTSERRAT_40 CONFIG_LV_FONT_MONTSERRAT_40 + #else + #define LV_FONT_MONTSERRAT_40 0 + #endif +#endif +#ifndef LV_FONT_MONTSERRAT_42 + #ifdef CONFIG_LV_FONT_MONTSERRAT_42 + #define LV_FONT_MONTSERRAT_42 CONFIG_LV_FONT_MONTSERRAT_42 + #else + #define LV_FONT_MONTSERRAT_42 0 + #endif +#endif +#ifndef LV_FONT_MONTSERRAT_44 + #ifdef CONFIG_LV_FONT_MONTSERRAT_44 + #define LV_FONT_MONTSERRAT_44 CONFIG_LV_FONT_MONTSERRAT_44 + #else + #define LV_FONT_MONTSERRAT_44 0 + #endif +#endif +#ifndef LV_FONT_MONTSERRAT_46 + #ifdef CONFIG_LV_FONT_MONTSERRAT_46 + #define LV_FONT_MONTSERRAT_46 CONFIG_LV_FONT_MONTSERRAT_46 + #else + #define LV_FONT_MONTSERRAT_46 0 + #endif +#endif +#ifndef LV_FONT_MONTSERRAT_48 + #ifdef CONFIG_LV_FONT_MONTSERRAT_48 + #define LV_FONT_MONTSERRAT_48 CONFIG_LV_FONT_MONTSERRAT_48 + #else + #define LV_FONT_MONTSERRAT_48 0 + #endif +#endif + +/*Demonstrate special features*/ +#ifndef LV_FONT_MONTSERRAT_12_SUBPX + #ifdef CONFIG_LV_FONT_MONTSERRAT_12_SUBPX + #define LV_FONT_MONTSERRAT_12_SUBPX CONFIG_LV_FONT_MONTSERRAT_12_SUBPX + #else + #define LV_FONT_MONTSERRAT_12_SUBPX 0 + #endif +#endif +#ifndef LV_FONT_MONTSERRAT_28_COMPRESSED + #ifdef CONFIG_LV_FONT_MONTSERRAT_28_COMPRESSED + #define LV_FONT_MONTSERRAT_28_COMPRESSED CONFIG_LV_FONT_MONTSERRAT_28_COMPRESSED + #else + #define LV_FONT_MONTSERRAT_28_COMPRESSED 0 /*bpp = 3*/ + #endif +#endif +#ifndef LV_FONT_DEJAVU_16_PERSIAN_HEBREW + #ifdef CONFIG_LV_FONT_DEJAVU_16_PERSIAN_HEBREW + #define LV_FONT_DEJAVU_16_PERSIAN_HEBREW CONFIG_LV_FONT_DEJAVU_16_PERSIAN_HEBREW + #else + #define LV_FONT_DEJAVU_16_PERSIAN_HEBREW 0 /*Hebrew, Arabic, Persian letters and all their forms*/ + #endif +#endif +#ifndef LV_FONT_SIMSUN_16_CJK + #ifdef CONFIG_LV_FONT_SIMSUN_16_CJK + #define LV_FONT_SIMSUN_16_CJK CONFIG_LV_FONT_SIMSUN_16_CJK + #else + #define LV_FONT_SIMSUN_16_CJK 0 /*1000 most common CJK radicals*/ + #endif +#endif + +/*Pixel perfect monospace fonts*/ +#ifndef LV_FONT_UNSCII_8 + #ifdef CONFIG_LV_FONT_UNSCII_8 + #define LV_FONT_UNSCII_8 CONFIG_LV_FONT_UNSCII_8 + #else + #define LV_FONT_UNSCII_8 0 + #endif +#endif +#ifndef LV_FONT_UNSCII_16 + #ifdef CONFIG_LV_FONT_UNSCII_16 + #define LV_FONT_UNSCII_16 CONFIG_LV_FONT_UNSCII_16 + #else + #define LV_FONT_UNSCII_16 0 + #endif +#endif + +/*Optionally declare custom fonts here. + *You can use these fonts as default font too and they will be available globally. + *E.g. #define LV_FONT_CUSTOM_DECLARE LV_FONT_DECLARE(my_font_1) LV_FONT_DECLARE(my_font_2)*/ +#ifndef LV_FONT_CUSTOM_DECLARE + #ifdef CONFIG_LV_FONT_CUSTOM_DECLARE + #define LV_FONT_CUSTOM_DECLARE CONFIG_LV_FONT_CUSTOM_DECLARE + #else + #define LV_FONT_CUSTOM_DECLARE + #endif +#endif + +/*Always set a default font*/ +#ifndef LV_FONT_DEFAULT + #ifdef CONFIG_LV_FONT_DEFAULT + #define LV_FONT_DEFAULT CONFIG_LV_FONT_DEFAULT + #else + #define LV_FONT_DEFAULT &lv_font_montserrat_14 + #endif +#endif + +/*Enable handling large font and/or fonts with a lot of characters. + *The limit depends on the font size, font face and bpp. + *Compiler error will be triggered if a font needs it.*/ +#ifndef LV_FONT_FMT_TXT_LARGE + #ifdef CONFIG_LV_FONT_FMT_TXT_LARGE + #define LV_FONT_FMT_TXT_LARGE CONFIG_LV_FONT_FMT_TXT_LARGE + #else + #define LV_FONT_FMT_TXT_LARGE 0 + #endif +#endif + +/*Enables/disables support for compressed fonts.*/ +#ifndef LV_USE_FONT_COMPRESSED + #ifdef CONFIG_LV_USE_FONT_COMPRESSED + #define LV_USE_FONT_COMPRESSED CONFIG_LV_USE_FONT_COMPRESSED + #else + #define LV_USE_FONT_COMPRESSED 0 + #endif +#endif + +/*Enable subpixel rendering*/ +#ifndef LV_USE_FONT_SUBPX + #ifdef CONFIG_LV_USE_FONT_SUBPX + #define LV_USE_FONT_SUBPX CONFIG_LV_USE_FONT_SUBPX + #else + #define LV_USE_FONT_SUBPX 0 + #endif +#endif +#if LV_USE_FONT_SUBPX + /*Set the pixel order of the display. Physical order of RGB channels. Doesn't matter with "normal" fonts.*/ + #ifndef LV_FONT_SUBPX_BGR + #ifdef CONFIG_LV_FONT_SUBPX_BGR + #define LV_FONT_SUBPX_BGR CONFIG_LV_FONT_SUBPX_BGR + #else + #define LV_FONT_SUBPX_BGR 0 /*0: RGB; 1:BGR order*/ + #endif + #endif +#endif + +/*================= + * TEXT SETTINGS + *=================*/ + +/** + * Select a character encoding for strings. + * Your IDE or editor should have the same character encoding + * - LV_TXT_ENC_UTF8 + * - LV_TXT_ENC_ASCII + */ +#ifndef LV_TXT_ENC + #ifdef CONFIG_LV_TXT_ENC + #define LV_TXT_ENC CONFIG_LV_TXT_ENC + #else + #define LV_TXT_ENC LV_TXT_ENC_UTF8 + #endif +#endif + +/*Can break (wrap) texts on these chars*/ +#ifndef LV_TXT_BREAK_CHARS + #ifdef CONFIG_LV_TXT_BREAK_CHARS + #define LV_TXT_BREAK_CHARS CONFIG_LV_TXT_BREAK_CHARS + #else + #define LV_TXT_BREAK_CHARS " ,.;:-_" + #endif +#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 + #ifdef CONFIG_LV_TXT_LINE_BREAK_LONG_LEN + #define LV_TXT_LINE_BREAK_LONG_LEN CONFIG_LV_TXT_LINE_BREAK_LONG_LEN + #else + #define LV_TXT_LINE_BREAK_LONG_LEN 0 + #endif +#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 + #ifdef CONFIG_LV_TXT_LINE_BREAK_LONG_PRE_MIN_LEN + #define LV_TXT_LINE_BREAK_LONG_PRE_MIN_LEN CONFIG_LV_TXT_LINE_BREAK_LONG_PRE_MIN_LEN + #else + #define LV_TXT_LINE_BREAK_LONG_PRE_MIN_LEN 3 + #endif +#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 + #ifdef CONFIG_LV_TXT_LINE_BREAK_LONG_POST_MIN_LEN + #define LV_TXT_LINE_BREAK_LONG_POST_MIN_LEN CONFIG_LV_TXT_LINE_BREAK_LONG_POST_MIN_LEN + #else + #define LV_TXT_LINE_BREAK_LONG_POST_MIN_LEN 3 + #endif +#endif + +/*The control character to use for signalling text recoloring.*/ +#ifndef LV_TXT_COLOR_CMD + #ifdef CONFIG_LV_TXT_COLOR_CMD + #define LV_TXT_COLOR_CMD CONFIG_LV_TXT_COLOR_CMD + #else + #define LV_TXT_COLOR_CMD "#" + #endif +#endif + +/*Support bidirectional texts. Allows mixing Left-to-Right and Right-to-Left texts. + *The direction will be processed according to the Unicode Bidirectional Algorithm: + *https://www.w3.org/International/articles/inline-bidi-markup/uba-basics*/ +#ifndef LV_USE_BIDI + #ifdef CONFIG_LV_USE_BIDI + #define LV_USE_BIDI CONFIG_LV_USE_BIDI + #else + #define LV_USE_BIDI 0 + #endif +#endif +#if LV_USE_BIDI + /*Set the default direction. Supported values: + *`LV_BASE_DIR_LTR` Left-to-Right + *`LV_BASE_DIR_RTL` Right-to-Left + *`LV_BASE_DIR_AUTO` detect texts base direction*/ + #ifndef LV_BIDI_BASE_DIR_DEF + #ifdef CONFIG_LV_BIDI_BASE_DIR_DEF + #define LV_BIDI_BASE_DIR_DEF CONFIG_LV_BIDI_BASE_DIR_DEF + #else + #define LV_BIDI_BASE_DIR_DEF LV_BASE_DIR_AUTO + #endif + #endif +#endif + +/*Enable Arabic/Persian processing + *In these languages characters should be replaced with an other form based on their position in the text*/ +#ifndef LV_USE_ARABIC_PERSIAN_CHARS + #ifdef CONFIG_LV_USE_ARABIC_PERSIAN_CHARS + #define LV_USE_ARABIC_PERSIAN_CHARS CONFIG_LV_USE_ARABIC_PERSIAN_CHARS + #else + #define LV_USE_ARABIC_PERSIAN_CHARS 0 + #endif +#endif + +/*================== + * WIDGET USAGE + *================*/ + +/*Documentation of the widgets: https://docs.lvgl.io/latest/en/html/widgets/index.html*/ + +#ifndef LV_USE_ARC + #ifdef _LV_KCONFIG_PRESENT + #ifdef CONFIG_LV_USE_ARC + #define LV_USE_ARC CONFIG_LV_USE_ARC + #else + #define LV_USE_ARC 0 + #endif + #else + #define LV_USE_ARC 1 + #endif +#endif + +#ifndef LV_USE_ANIMIMG + #ifdef _LV_KCONFIG_PRESENT + #ifdef CONFIG_LV_USE_ANIMIMG + #define LV_USE_ANIMIMG CONFIG_LV_USE_ANIMIMG + #else + #define LV_USE_ANIMIMG 0 + #endif + #else + #define LV_USE_ANIMIMG 1 + #endif +#endif + +#ifndef LV_USE_BAR + #ifdef _LV_KCONFIG_PRESENT + #ifdef CONFIG_LV_USE_BAR + #define LV_USE_BAR CONFIG_LV_USE_BAR + #else + #define LV_USE_BAR 0 + #endif + #else + #define LV_USE_BAR 1 + #endif +#endif + +#ifndef LV_USE_BTN + #ifdef _LV_KCONFIG_PRESENT + #ifdef CONFIG_LV_USE_BTN + #define LV_USE_BTN CONFIG_LV_USE_BTN + #else + #define LV_USE_BTN 0 + #endif + #else + #define LV_USE_BTN 1 + #endif +#endif + +#ifndef LV_USE_BTNMATRIX + #ifdef _LV_KCONFIG_PRESENT + #ifdef CONFIG_LV_USE_BTNMATRIX + #define LV_USE_BTNMATRIX CONFIG_LV_USE_BTNMATRIX + #else + #define LV_USE_BTNMATRIX 0 + #endif + #else + #define LV_USE_BTNMATRIX 1 + #endif +#endif + +#ifndef LV_USE_CANVAS + #ifdef _LV_KCONFIG_PRESENT + #ifdef CONFIG_LV_USE_CANVAS + #define LV_USE_CANVAS CONFIG_LV_USE_CANVAS + #else + #define LV_USE_CANVAS 0 + #endif + #else + #define LV_USE_CANVAS 1 + #endif +#endif + +#ifndef LV_USE_CHECKBOX + #ifdef _LV_KCONFIG_PRESENT + #ifdef CONFIG_LV_USE_CHECKBOX + #define LV_USE_CHECKBOX CONFIG_LV_USE_CHECKBOX + #else + #define LV_USE_CHECKBOX 0 + #endif + #else + #define LV_USE_CHECKBOX 1 + #endif +#endif + +#ifndef LV_USE_DROPDOWN + #ifdef CONFIG_LV_USE_DROPDOWN + #define LV_USE_DROPDOWN CONFIG_LV_USE_DROPDOWN + #else + #define LV_USE_DROPDOWN 1 /*Requires: lv_label*/ + #endif +#endif + +#ifndef LV_USE_IMG + #ifdef CONFIG_LV_USE_IMG + #define LV_USE_IMG CONFIG_LV_USE_IMG + #else + #define LV_USE_IMG 1 /*Requires: lv_label*/ + #endif +#endif + +#ifndef LV_USE_LABEL + #ifdef _LV_KCONFIG_PRESENT + #ifdef CONFIG_LV_USE_LABEL + #define LV_USE_LABEL CONFIG_LV_USE_LABEL + #else + #define LV_USE_LABEL 0 + #endif + #else + #define LV_USE_LABEL 1 + #endif +#endif +#if LV_USE_LABEL + #ifndef LV_LABEL_TEXT_SELECTION + #ifdef CONFIG_LV_LABEL_TEXT_SELECTION + #define LV_LABEL_TEXT_SELECTION CONFIG_LV_LABEL_TEXT_SELECTION + #else + #define LV_LABEL_TEXT_SELECTION 1 /*Enable selecting text of the label*/ + #endif + #endif + #ifndef LV_LABEL_LONG_TXT_HINT + #ifdef CONFIG_LV_LABEL_LONG_TXT_HINT + #define LV_LABEL_LONG_TXT_HINT CONFIG_LV_LABEL_LONG_TXT_HINT + #else + #define LV_LABEL_LONG_TXT_HINT 1 /*Store some extra info in labels to speed up drawing of very long texts*/ + #endif + #endif +#endif + +#ifndef LV_USE_LINE + #ifdef _LV_KCONFIG_PRESENT + #ifdef CONFIG_LV_USE_LINE + #define LV_USE_LINE CONFIG_LV_USE_LINE + #else + #define LV_USE_LINE 0 + #endif + #else + #define LV_USE_LINE 1 + #endif +#endif + +#ifndef LV_USE_ROLLER + #ifdef CONFIG_LV_USE_ROLLER + #define LV_USE_ROLLER CONFIG_LV_USE_ROLLER + #else + #define LV_USE_ROLLER 1 /*Requires: lv_label*/ + #endif +#endif +#if LV_USE_ROLLER + #ifndef LV_ROLLER_INF_PAGES + #ifdef CONFIG_LV_ROLLER_INF_PAGES + #define LV_ROLLER_INF_PAGES CONFIG_LV_ROLLER_INF_PAGES + #else + #define LV_ROLLER_INF_PAGES 7 /*Number of extra "pages" when the roller is infinite*/ + #endif + #endif +#endif + +#ifndef LV_USE_SLIDER + #ifdef CONFIG_LV_USE_SLIDER + #define LV_USE_SLIDER CONFIG_LV_USE_SLIDER + #else + #define LV_USE_SLIDER 1 /*Requires: lv_bar*/ + #endif +#endif + +#ifndef LV_USE_SWITCH + #ifdef _LV_KCONFIG_PRESENT + #ifdef CONFIG_LV_USE_SWITCH + #define LV_USE_SWITCH CONFIG_LV_USE_SWITCH + #else + #define LV_USE_SWITCH 0 + #endif + #else + #define LV_USE_SWITCH 1 + #endif +#endif + +#ifndef LV_USE_TEXTAREA + #ifdef CONFIG_LV_USE_TEXTAREA + #define LV_USE_TEXTAREA CONFIG_LV_USE_TEXTAREA + #else + #define LV_USE_TEXTAREA 1 /*Requires: lv_label*/ + #endif +#endif +#if LV_USE_TEXTAREA != 0 + #ifndef LV_TEXTAREA_DEF_PWD_SHOW_TIME + #ifdef CONFIG_LV_TEXTAREA_DEF_PWD_SHOW_TIME + #define LV_TEXTAREA_DEF_PWD_SHOW_TIME CONFIG_LV_TEXTAREA_DEF_PWD_SHOW_TIME + #else + #define LV_TEXTAREA_DEF_PWD_SHOW_TIME 1500 /*ms*/ + #endif + #endif +#endif + +#ifndef LV_USE_TABLE + #ifdef _LV_KCONFIG_PRESENT + #ifdef CONFIG_LV_USE_TABLE + #define LV_USE_TABLE CONFIG_LV_USE_TABLE + #else + #define LV_USE_TABLE 0 + #endif + #else + #define LV_USE_TABLE 1 + #endif +#endif + +/*================== + * EXTRA COMPONENTS + *==================*/ + +/*----------- + * Widgets + *----------*/ +#ifndef LV_USE_CALENDAR + #ifdef _LV_KCONFIG_PRESENT + #ifdef CONFIG_LV_USE_CALENDAR + #define LV_USE_CALENDAR CONFIG_LV_USE_CALENDAR + #else + #define LV_USE_CALENDAR 0 + #endif + #else + #define LV_USE_CALENDAR 1 + #endif +#endif +#if LV_USE_CALENDAR + #ifndef LV_CALENDAR_WEEK_STARTS_MONDAY + #ifdef CONFIG_LV_CALENDAR_WEEK_STARTS_MONDAY + #define LV_CALENDAR_WEEK_STARTS_MONDAY CONFIG_LV_CALENDAR_WEEK_STARTS_MONDAY + #else + #define LV_CALENDAR_WEEK_STARTS_MONDAY 0 + #endif + #endif + #if LV_CALENDAR_WEEK_STARTS_MONDAY + #ifndef LV_CALENDAR_DEFAULT_DAY_NAMES + #ifdef CONFIG_LV_CALENDAR_DEFAULT_DAY_NAMES + #define LV_CALENDAR_DEFAULT_DAY_NAMES CONFIG_LV_CALENDAR_DEFAULT_DAY_NAMES + #else + #define LV_CALENDAR_DEFAULT_DAY_NAMES {"Mo", "Tu", "We", "Th", "Fr", "Sa", "Su"} + #endif + #endif + #else + #ifndef LV_CALENDAR_DEFAULT_DAY_NAMES + #ifdef CONFIG_LV_CALENDAR_DEFAULT_DAY_NAMES + #define LV_CALENDAR_DEFAULT_DAY_NAMES CONFIG_LV_CALENDAR_DEFAULT_DAY_NAMES + #else + #define LV_CALENDAR_DEFAULT_DAY_NAMES {"Su", "Mo", "Tu", "We", "Th", "Fr", "Sa"} + #endif + #endif + #endif + + #ifndef LV_CALENDAR_DEFAULT_MONTH_NAMES + #ifdef CONFIG_LV_CALENDAR_DEFAULT_MONTH_NAMES + #define LV_CALENDAR_DEFAULT_MONTH_NAMES CONFIG_LV_CALENDAR_DEFAULT_MONTH_NAMES + #else + #define LV_CALENDAR_DEFAULT_MONTH_NAMES {"January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"} + #endif + #endif + #ifndef LV_USE_CALENDAR_HEADER_ARROW + #ifdef _LV_KCONFIG_PRESENT + #ifdef CONFIG_LV_USE_CALENDAR_HEADER_ARROW + #define LV_USE_CALENDAR_HEADER_ARROW CONFIG_LV_USE_CALENDAR_HEADER_ARROW + #else + #define LV_USE_CALENDAR_HEADER_ARROW 0 + #endif + #else + #define LV_USE_CALENDAR_HEADER_ARROW 1 + #endif + #endif + #ifndef LV_USE_CALENDAR_HEADER_DROPDOWN + #ifdef _LV_KCONFIG_PRESENT + #ifdef CONFIG_LV_USE_CALENDAR_HEADER_DROPDOWN + #define LV_USE_CALENDAR_HEADER_DROPDOWN CONFIG_LV_USE_CALENDAR_HEADER_DROPDOWN + #else + #define LV_USE_CALENDAR_HEADER_DROPDOWN 0 + #endif + #else + #define LV_USE_CALENDAR_HEADER_DROPDOWN 1 + #endif + #endif +#endif /*LV_USE_CALENDAR*/ + +#ifndef LV_USE_CHART + #ifdef _LV_KCONFIG_PRESENT + #ifdef CONFIG_LV_USE_CHART + #define LV_USE_CHART CONFIG_LV_USE_CHART + #else + #define LV_USE_CHART 0 + #endif + #else + #define LV_USE_CHART 1 + #endif +#endif + +#ifndef LV_USE_COLORWHEEL + #ifdef _LV_KCONFIG_PRESENT + #ifdef CONFIG_LV_USE_COLORWHEEL + #define LV_USE_COLORWHEEL CONFIG_LV_USE_COLORWHEEL + #else + #define LV_USE_COLORWHEEL 0 + #endif + #else + #define LV_USE_COLORWHEEL 1 + #endif +#endif + +#ifndef LV_USE_IMGBTN + #ifdef _LV_KCONFIG_PRESENT + #ifdef CONFIG_LV_USE_IMGBTN + #define LV_USE_IMGBTN CONFIG_LV_USE_IMGBTN + #else + #define LV_USE_IMGBTN 0 + #endif + #else + #define LV_USE_IMGBTN 1 + #endif +#endif + +#ifndef LV_USE_KEYBOARD + #ifdef _LV_KCONFIG_PRESENT + #ifdef CONFIG_LV_USE_KEYBOARD + #define LV_USE_KEYBOARD CONFIG_LV_USE_KEYBOARD + #else + #define LV_USE_KEYBOARD 0 + #endif + #else + #define LV_USE_KEYBOARD 1 + #endif +#endif + +#ifndef LV_USE_LED + #ifdef _LV_KCONFIG_PRESENT + #ifdef CONFIG_LV_USE_LED + #define LV_USE_LED CONFIG_LV_USE_LED + #else + #define LV_USE_LED 0 + #endif + #else + #define LV_USE_LED 1 + #endif +#endif + +#ifndef LV_USE_LIST + #ifdef _LV_KCONFIG_PRESENT + #ifdef CONFIG_LV_USE_LIST + #define LV_USE_LIST CONFIG_LV_USE_LIST + #else + #define LV_USE_LIST 0 + #endif + #else + #define LV_USE_LIST 1 + #endif +#endif + +#ifndef LV_USE_MENU + #ifdef _LV_KCONFIG_PRESENT + #ifdef CONFIG_LV_USE_MENU + #define LV_USE_MENU CONFIG_LV_USE_MENU + #else + #define LV_USE_MENU 0 + #endif + #else + #define LV_USE_MENU 1 + #endif +#endif + +#ifndef LV_USE_METER + #ifdef _LV_KCONFIG_PRESENT + #ifdef CONFIG_LV_USE_METER + #define LV_USE_METER CONFIG_LV_USE_METER + #else + #define LV_USE_METER 0 + #endif + #else + #define LV_USE_METER 1 + #endif +#endif + +#ifndef LV_USE_MSGBOX + #ifdef _LV_KCONFIG_PRESENT + #ifdef CONFIG_LV_USE_MSGBOX + #define LV_USE_MSGBOX CONFIG_LV_USE_MSGBOX + #else + #define LV_USE_MSGBOX 0 + #endif + #else + #define LV_USE_MSGBOX 1 + #endif +#endif + +#ifndef LV_USE_SPINBOX + #ifdef _LV_KCONFIG_PRESENT + #ifdef CONFIG_LV_USE_SPINBOX + #define LV_USE_SPINBOX CONFIG_LV_USE_SPINBOX + #else + #define LV_USE_SPINBOX 0 + #endif + #else + #define LV_USE_SPINBOX 1 + #endif +#endif + +#ifndef LV_USE_SPINNER + #ifdef _LV_KCONFIG_PRESENT + #ifdef CONFIG_LV_USE_SPINNER + #define LV_USE_SPINNER CONFIG_LV_USE_SPINNER + #else + #define LV_USE_SPINNER 0 + #endif + #else + #define LV_USE_SPINNER 1 + #endif +#endif + +#ifndef LV_USE_TABVIEW + #ifdef _LV_KCONFIG_PRESENT + #ifdef CONFIG_LV_USE_TABVIEW + #define LV_USE_TABVIEW CONFIG_LV_USE_TABVIEW + #else + #define LV_USE_TABVIEW 0 + #endif + #else + #define LV_USE_TABVIEW 1 + #endif +#endif + +#ifndef LV_USE_TILEVIEW + #ifdef _LV_KCONFIG_PRESENT + #ifdef CONFIG_LV_USE_TILEVIEW + #define LV_USE_TILEVIEW CONFIG_LV_USE_TILEVIEW + #else + #define LV_USE_TILEVIEW 0 + #endif + #else + #define LV_USE_TILEVIEW 1 + #endif +#endif + +#ifndef LV_USE_WIN + #ifdef _LV_KCONFIG_PRESENT + #ifdef CONFIG_LV_USE_WIN + #define LV_USE_WIN CONFIG_LV_USE_WIN + #else + #define LV_USE_WIN 0 + #endif + #else + #define LV_USE_WIN 1 + #endif +#endif + +#ifndef LV_USE_SPAN + #ifdef _LV_KCONFIG_PRESENT + #ifdef CONFIG_LV_USE_SPAN + #define LV_USE_SPAN CONFIG_LV_USE_SPAN + #else + #define LV_USE_SPAN 0 + #endif + #else + #define LV_USE_SPAN 1 + #endif +#endif +#if LV_USE_SPAN + /*A line text can contain maximum num of span descriptor */ + #ifndef LV_SPAN_SNIPPET_STACK_SIZE + #ifdef CONFIG_LV_SPAN_SNIPPET_STACK_SIZE + #define LV_SPAN_SNIPPET_STACK_SIZE CONFIG_LV_SPAN_SNIPPET_STACK_SIZE + #else + #define LV_SPAN_SNIPPET_STACK_SIZE 64 + #endif + #endif +#endif + +/*----------- + * Themes + *----------*/ + +/*A simple, impressive and very complete theme*/ +#ifndef LV_USE_THEME_DEFAULT + #ifdef _LV_KCONFIG_PRESENT + #ifdef CONFIG_LV_USE_THEME_DEFAULT + #define LV_USE_THEME_DEFAULT CONFIG_LV_USE_THEME_DEFAULT + #else + #define LV_USE_THEME_DEFAULT 0 + #endif + #else + #define LV_USE_THEME_DEFAULT 1 + #endif +#endif +#if LV_USE_THEME_DEFAULT + + /*0: Light mode; 1: Dark mode*/ + #ifndef LV_THEME_DEFAULT_DARK + #ifdef CONFIG_LV_THEME_DEFAULT_DARK + #define LV_THEME_DEFAULT_DARK CONFIG_LV_THEME_DEFAULT_DARK + #else + #define LV_THEME_DEFAULT_DARK 0 + #endif + #endif + + /*1: Enable grow on press*/ + #ifndef LV_THEME_DEFAULT_GROW + #ifdef _LV_KCONFIG_PRESENT + #ifdef CONFIG_LV_THEME_DEFAULT_GROW + #define LV_THEME_DEFAULT_GROW CONFIG_LV_THEME_DEFAULT_GROW + #else + #define LV_THEME_DEFAULT_GROW 0 + #endif + #else + #define LV_THEME_DEFAULT_GROW 1 + #endif + #endif + + /*Default transition time in [ms]*/ + #ifndef LV_THEME_DEFAULT_TRANSITION_TIME + #ifdef CONFIG_LV_THEME_DEFAULT_TRANSITION_TIME + #define LV_THEME_DEFAULT_TRANSITION_TIME CONFIG_LV_THEME_DEFAULT_TRANSITION_TIME + #else + #define LV_THEME_DEFAULT_TRANSITION_TIME 80 + #endif + #endif +#endif /*LV_USE_THEME_DEFAULT*/ + +/*A very simple theme that is a good starting point for a custom theme*/ +#ifndef LV_USE_THEME_BASIC + #ifdef _LV_KCONFIG_PRESENT + #ifdef CONFIG_LV_USE_THEME_BASIC + #define LV_USE_THEME_BASIC CONFIG_LV_USE_THEME_BASIC + #else + #define LV_USE_THEME_BASIC 0 + #endif + #else + #define LV_USE_THEME_BASIC 1 + #endif +#endif + +/*A theme designed for monochrome displays*/ +#ifndef LV_USE_THEME_MONO + #ifdef _LV_KCONFIG_PRESENT + #ifdef CONFIG_LV_USE_THEME_MONO + #define LV_USE_THEME_MONO CONFIG_LV_USE_THEME_MONO + #else + #define LV_USE_THEME_MONO 0 + #endif + #else + #define LV_USE_THEME_MONO 1 + #endif +#endif + +/*----------- + * Layouts + *----------*/ + +/*A layout similar to Flexbox in CSS.*/ +#ifndef LV_USE_FLEX + #ifdef _LV_KCONFIG_PRESENT + #ifdef CONFIG_LV_USE_FLEX + #define LV_USE_FLEX CONFIG_LV_USE_FLEX + #else + #define LV_USE_FLEX 0 + #endif + #else + #define LV_USE_FLEX 1 + #endif +#endif + +/*A layout similar to Grid in CSS.*/ +#ifndef LV_USE_GRID + #ifdef _LV_KCONFIG_PRESENT + #ifdef CONFIG_LV_USE_GRID + #define LV_USE_GRID CONFIG_LV_USE_GRID + #else + #define LV_USE_GRID 0 + #endif + #else + #define LV_USE_GRID 1 + #endif +#endif + +/*--------------------- + * 3rd party libraries + *--------------------*/ + +/*File system interfaces for common APIs */ + +/*API for fopen, fread, etc*/ +#ifndef LV_USE_FS_STDIO + #ifdef CONFIG_LV_USE_FS_STDIO + #define LV_USE_FS_STDIO CONFIG_LV_USE_FS_STDIO + #else + #define LV_USE_FS_STDIO 0 + #endif +#endif +#if LV_USE_FS_STDIO + #ifndef LV_FS_STDIO_LETTER + #ifdef CONFIG_LV_FS_STDIO_LETTER + #define LV_FS_STDIO_LETTER CONFIG_LV_FS_STDIO_LETTER + #else + #define LV_FS_STDIO_LETTER '\0' /*Set an upper cased letter on which the drive will accessible (e.g. 'A')*/ + #endif + #endif + #ifndef LV_FS_STDIO_PATH + #ifdef CONFIG_LV_FS_STDIO_PATH + #define LV_FS_STDIO_PATH CONFIG_LV_FS_STDIO_PATH + #else + #define LV_FS_STDIO_PATH "" /*Set the working directory. File/directory paths will be appended to it.*/ + #endif + #endif + #ifndef LV_FS_STDIO_CACHE_SIZE + #ifdef CONFIG_LV_FS_STDIO_CACHE_SIZE + #define LV_FS_STDIO_CACHE_SIZE CONFIG_LV_FS_STDIO_CACHE_SIZE + #else + #define LV_FS_STDIO_CACHE_SIZE 0 /*>0 to cache this number of bytes in lv_fs_read()*/ + #endif + #endif +#endif + +/*API for open, read, etc*/ +#ifndef LV_USE_FS_POSIX + #ifdef CONFIG_LV_USE_FS_POSIX + #define LV_USE_FS_POSIX CONFIG_LV_USE_FS_POSIX + #else + #define LV_USE_FS_POSIX 0 + #endif +#endif +#if LV_USE_FS_POSIX + #ifndef LV_FS_POSIX_LETTER + #ifdef CONFIG_LV_FS_POSIX_LETTER + #define LV_FS_POSIX_LETTER CONFIG_LV_FS_POSIX_LETTER + #else + #define LV_FS_POSIX_LETTER '\0' /*Set an upper cased letter on which the drive will accessible (e.g. 'A')*/ + #endif + #endif + #ifndef LV_FS_POSIX_PATH + #ifdef CONFIG_LV_FS_POSIX_PATH + #define LV_FS_POSIX_PATH CONFIG_LV_FS_POSIX_PATH + #else + #define LV_FS_POSIX_PATH "" /*Set the working directory. File/directory paths will be appended to it.*/ + #endif + #endif + #ifndef LV_FS_POSIX_CACHE_SIZE + #ifdef CONFIG_LV_FS_POSIX_CACHE_SIZE + #define LV_FS_POSIX_CACHE_SIZE CONFIG_LV_FS_POSIX_CACHE_SIZE + #else + #define LV_FS_POSIX_CACHE_SIZE 0 /*>0 to cache this number of bytes in lv_fs_read()*/ + #endif + #endif +#endif + +/*API for CreateFile, ReadFile, etc*/ +#ifndef LV_USE_FS_WIN32 + #ifdef CONFIG_LV_USE_FS_WIN32 + #define LV_USE_FS_WIN32 CONFIG_LV_USE_FS_WIN32 + #else + #define LV_USE_FS_WIN32 0 + #endif +#endif +#if LV_USE_FS_WIN32 + #ifndef LV_FS_WIN32_LETTER + #ifdef CONFIG_LV_FS_WIN32_LETTER + #define LV_FS_WIN32_LETTER CONFIG_LV_FS_WIN32_LETTER + #else + #define LV_FS_WIN32_LETTER '\0' /*Set an upper cased letter on which the drive will accessible (e.g. 'A')*/ + #endif + #endif + #ifndef LV_FS_WIN32_PATH + #ifdef CONFIG_LV_FS_WIN32_PATH + #define LV_FS_WIN32_PATH CONFIG_LV_FS_WIN32_PATH + #else + #define LV_FS_WIN32_PATH "" /*Set the working directory. File/directory paths will be appended to it.*/ + #endif + #endif + #ifndef LV_FS_WIN32_CACHE_SIZE + #ifdef CONFIG_LV_FS_WIN32_CACHE_SIZE + #define LV_FS_WIN32_CACHE_SIZE CONFIG_LV_FS_WIN32_CACHE_SIZE + #else + #define LV_FS_WIN32_CACHE_SIZE 0 /*>0 to cache this number of bytes in lv_fs_read()*/ + #endif + #endif +#endif + +/*API for FATFS (needs to be added separately). Uses f_open, f_read, etc*/ +#ifndef LV_USE_FS_FATFS + #ifdef CONFIG_LV_USE_FS_FATFS + #define LV_USE_FS_FATFS CONFIG_LV_USE_FS_FATFS + #else + #define LV_USE_FS_FATFS 0 + #endif +#endif +#if LV_USE_FS_FATFS + #ifndef LV_FS_FATFS_LETTER + #ifdef CONFIG_LV_FS_FATFS_LETTER + #define LV_FS_FATFS_LETTER CONFIG_LV_FS_FATFS_LETTER + #else + #define LV_FS_FATFS_LETTER '\0' /*Set an upper cased letter on which the drive will accessible (e.g. 'A')*/ + #endif + #endif + #ifndef LV_FS_FATFS_CACHE_SIZE + #ifdef CONFIG_LV_FS_FATFS_CACHE_SIZE + #define LV_FS_FATFS_CACHE_SIZE CONFIG_LV_FS_FATFS_CACHE_SIZE + #else + #define LV_FS_FATFS_CACHE_SIZE 0 /*>0 to cache this number of bytes in lv_fs_read()*/ + #endif + #endif +#endif + +/*PNG decoder library*/ +#ifndef LV_USE_PNG + #ifdef CONFIG_LV_USE_PNG + #define LV_USE_PNG CONFIG_LV_USE_PNG + #else + #define LV_USE_PNG 0 + #endif +#endif + +/*BMP decoder library*/ +#ifndef LV_USE_BMP + #ifdef CONFIG_LV_USE_BMP + #define LV_USE_BMP CONFIG_LV_USE_BMP + #else + #define LV_USE_BMP 0 + #endif +#endif + +/* JPG + split JPG decoder library. + * Split JPG is a custom format optimized for embedded systems. */ +#ifndef LV_USE_SJPG + #ifdef CONFIG_LV_USE_SJPG + #define LV_USE_SJPG CONFIG_LV_USE_SJPG + #else + #define LV_USE_SJPG 0 + #endif +#endif + +/*GIF decoder library*/ +#ifndef LV_USE_GIF + #ifdef CONFIG_LV_USE_GIF + #define LV_USE_GIF CONFIG_LV_USE_GIF + #else + #define LV_USE_GIF 0 + #endif +#endif + +/*QR code library*/ +#ifndef LV_USE_QRCODE + #ifdef CONFIG_LV_USE_QRCODE + #define LV_USE_QRCODE CONFIG_LV_USE_QRCODE + #else + #define LV_USE_QRCODE 0 + #endif +#endif + +/*FreeType library*/ +#ifndef LV_USE_FREETYPE + #ifdef CONFIG_LV_USE_FREETYPE + #define LV_USE_FREETYPE CONFIG_LV_USE_FREETYPE + #else + #define LV_USE_FREETYPE 0 + #endif +#endif +#if LV_USE_FREETYPE + /*Memory used by FreeType to cache characters [bytes] (-1: no caching)*/ + #ifndef LV_FREETYPE_CACHE_SIZE + #ifdef CONFIG_LV_FREETYPE_CACHE_SIZE + #define LV_FREETYPE_CACHE_SIZE CONFIG_LV_FREETYPE_CACHE_SIZE + #else + #define LV_FREETYPE_CACHE_SIZE (16 * 1024) + #endif + #endif + #if LV_FREETYPE_CACHE_SIZE >= 0 + /* 1: bitmap cache use the sbit cache, 0:bitmap cache use the image cache. */ + /* sbit cache:it is much more memory efficient for small bitmaps(font size < 256) */ + /* if font size >= 256, must be configured as image cache */ + #ifndef LV_FREETYPE_SBIT_CACHE + #ifdef CONFIG_LV_FREETYPE_SBIT_CACHE + #define LV_FREETYPE_SBIT_CACHE CONFIG_LV_FREETYPE_SBIT_CACHE + #else + #define LV_FREETYPE_SBIT_CACHE 0 + #endif + #endif + /* Maximum number of opened FT_Face/FT_Size objects managed by this cache instance. */ + /* (0:use system defaults) */ + #ifndef LV_FREETYPE_CACHE_FT_FACES + #ifdef CONFIG_LV_FREETYPE_CACHE_FT_FACES + #define LV_FREETYPE_CACHE_FT_FACES CONFIG_LV_FREETYPE_CACHE_FT_FACES + #else + #define LV_FREETYPE_CACHE_FT_FACES 0 + #endif + #endif + #ifndef LV_FREETYPE_CACHE_FT_SIZES + #ifdef CONFIG_LV_FREETYPE_CACHE_FT_SIZES + #define LV_FREETYPE_CACHE_FT_SIZES CONFIG_LV_FREETYPE_CACHE_FT_SIZES + #else + #define LV_FREETYPE_CACHE_FT_SIZES 0 + #endif + #endif + #endif +#endif + +/*Rlottie library*/ +#ifndef LV_USE_RLOTTIE + #ifdef CONFIG_LV_USE_RLOTTIE + #define LV_USE_RLOTTIE CONFIG_LV_USE_RLOTTIE + #else + #define LV_USE_RLOTTIE 0 + #endif +#endif + +/*FFmpeg library for image decoding and playing videos + *Supports all major image formats so do not enable other image decoder with it*/ +#ifndef LV_USE_FFMPEG + #ifdef CONFIG_LV_USE_FFMPEG + #define LV_USE_FFMPEG CONFIG_LV_USE_FFMPEG + #else + #define LV_USE_FFMPEG 0 + #endif +#endif +#if LV_USE_FFMPEG + /*Dump input information to stderr*/ + #ifndef LV_FFMPEG_AV_DUMP_FORMAT + #ifdef CONFIG_LV_FFMPEG_AV_DUMP_FORMAT + #define LV_FFMPEG_AV_DUMP_FORMAT CONFIG_LV_FFMPEG_AV_DUMP_FORMAT + #else + #define LV_FFMPEG_AV_DUMP_FORMAT 0 + #endif + #endif +#endif + +/*----------- + * Others + *----------*/ + +/*1: Enable API to take snapshot for object*/ +#ifndef LV_USE_SNAPSHOT + #ifdef CONFIG_LV_USE_SNAPSHOT + #define LV_USE_SNAPSHOT CONFIG_LV_USE_SNAPSHOT + #else + #define LV_USE_SNAPSHOT 0 + #endif +#endif + +/*1: Enable Monkey test*/ +#ifndef LV_USE_MONKEY + #ifdef CONFIG_LV_USE_MONKEY + #define LV_USE_MONKEY CONFIG_LV_USE_MONKEY + #else + #define LV_USE_MONKEY 0 + #endif +#endif + +/*1: Enable grid navigation*/ +#ifndef LV_USE_GRIDNAV + #ifdef CONFIG_LV_USE_GRIDNAV + #define LV_USE_GRIDNAV CONFIG_LV_USE_GRIDNAV + #else + #define LV_USE_GRIDNAV 0 + #endif +#endif + +/*================== +* EXAMPLES +*==================*/ + +/*Enable the examples to be built with the library*/ +#ifndef LV_BUILD_EXAMPLES + #ifdef _LV_KCONFIG_PRESENT + #ifdef CONFIG_LV_BUILD_EXAMPLES + #define LV_BUILD_EXAMPLES CONFIG_LV_BUILD_EXAMPLES + #else + #define LV_BUILD_EXAMPLES 0 + #endif + #else + #define LV_BUILD_EXAMPLES 1 + #endif +#endif + +/*=================== + * DEMO USAGE + ====================*/ + +/*Show some widget. It might be required to increase `LV_MEM_SIZE` */ +#ifndef LV_USE_DEMO_WIDGETS + #ifdef CONFIG_LV_USE_DEMO_WIDGETS + #define LV_USE_DEMO_WIDGETS CONFIG_LV_USE_DEMO_WIDGETS + #else + #define LV_USE_DEMO_WIDGETS 0 + #endif +#endif +#if LV_USE_DEMO_WIDGETS +#ifndef LV_DEMO_WIDGETS_SLIDESHOW + #ifdef CONFIG_LV_DEMO_WIDGETS_SLIDESHOW + #define LV_DEMO_WIDGETS_SLIDESHOW CONFIG_LV_DEMO_WIDGETS_SLIDESHOW + #else + #define LV_DEMO_WIDGETS_SLIDESHOW 0 + #endif +#endif +#endif + +/*Demonstrate the usage of encoder and keyboard*/ +#ifndef LV_USE_DEMO_KEYPAD_AND_ENCODER + #ifdef CONFIG_LV_USE_DEMO_KEYPAD_AND_ENCODER + #define LV_USE_DEMO_KEYPAD_AND_ENCODER CONFIG_LV_USE_DEMO_KEYPAD_AND_ENCODER + #else + #define LV_USE_DEMO_KEYPAD_AND_ENCODER 0 + #endif +#endif + +/*Benchmark your system*/ +#ifndef LV_USE_DEMO_BENCHMARK + #ifdef CONFIG_LV_USE_DEMO_BENCHMARK + #define LV_USE_DEMO_BENCHMARK CONFIG_LV_USE_DEMO_BENCHMARK + #else + #define LV_USE_DEMO_BENCHMARK 0 + #endif +#endif + +/*Stress test for LVGL*/ +#ifndef LV_USE_DEMO_STRESS + #ifdef CONFIG_LV_USE_DEMO_STRESS + #define LV_USE_DEMO_STRESS CONFIG_LV_USE_DEMO_STRESS + #else + #define LV_USE_DEMO_STRESS 0 + #endif +#endif + +/*Music player demo*/ +#ifndef LV_USE_DEMO_MUSIC + #ifdef CONFIG_LV_USE_DEMO_MUSIC + #define LV_USE_DEMO_MUSIC CONFIG_LV_USE_DEMO_MUSIC + #else + #define LV_USE_DEMO_MUSIC 0 + #endif +#endif +#if LV_USE_DEMO_MUSIC +#ifndef LV_DEMO_MUSIC_SQUARE + #ifdef CONFIG_LV_DEMO_MUSIC_SQUARE + #define LV_DEMO_MUSIC_SQUARE CONFIG_LV_DEMO_MUSIC_SQUARE + #else + #define LV_DEMO_MUSIC_SQUARE 0 + #endif +#endif +#ifndef LV_DEMO_MUSIC_LANDSCAPE + #ifdef CONFIG_LV_DEMO_MUSIC_LANDSCAPE + #define LV_DEMO_MUSIC_LANDSCAPE CONFIG_LV_DEMO_MUSIC_LANDSCAPE + #else + #define LV_DEMO_MUSIC_LANDSCAPE 0 + #endif +#endif +#ifndef LV_DEMO_MUSIC_ROUND + #ifdef CONFIG_LV_DEMO_MUSIC_ROUND + #define LV_DEMO_MUSIC_ROUND CONFIG_LV_DEMO_MUSIC_ROUND + #else + #define LV_DEMO_MUSIC_ROUND 0 + #endif +#endif +#ifndef LV_DEMO_MUSIC_LARGE + #ifdef CONFIG_LV_DEMO_MUSIC_LARGE + #define LV_DEMO_MUSIC_LARGE CONFIG_LV_DEMO_MUSIC_LARGE + #else + #define LV_DEMO_MUSIC_LARGE 0 + #endif +#endif +#ifndef LV_DEMO_MUSIC_AUTO_PLAY + #ifdef CONFIG_LV_DEMO_MUSIC_AUTO_PLAY + #define LV_DEMO_MUSIC_AUTO_PLAY CONFIG_LV_DEMO_MUSIC_AUTO_PLAY + #else + #define LV_DEMO_MUSIC_AUTO_PLAY 0 + #endif +#endif +#endif + + + +/*---------------------------------- + * End of parsing lv_conf_template.h + -----------------------------------*/ + +LV_EXPORT_CONST_INT(LV_DPI_DEF); + +#undef _LV_KCONFIG_PRESENT + + +/*Set some defines if a dependency is disabled*/ +#if LV_USE_LOG == 0 + #define LV_LOG_LEVEL LV_LOG_LEVEL_NONE + #define LV_LOG_TRACE_MEM 0 + #define LV_LOG_TRACE_TIMER 0 + #define LV_LOG_TRACE_INDEV 0 + #define LV_LOG_TRACE_DISP_REFR 0 + #define LV_LOG_TRACE_EVENT 0 + #define LV_LOG_TRACE_OBJ_CREATE 0 + #define LV_LOG_TRACE_LAYOUT 0 + #define LV_LOG_TRACE_ANIM 0 +#endif /*LV_USE_LOG*/ + + +/*If running without lv_conf.h add typedefs with default value*/ +#ifdef LV_CONF_SKIP + #if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_WARNINGS) /*Disable warnings for Visual Studio*/ + #define _CRT_SECURE_NO_WARNINGS + #endif +#endif /*defined(LV_CONF_SKIP)*/ + +#endif /*LV_CONF_INTERNAL_H*/ diff --git a/src/lib/lvgl/src/lv_conf_kconfig.h b/src/lib/lvgl/src/lv_conf_kconfig.h new file mode 100644 index 0000000..7424789 --- /dev/null +++ b/src/lib/lvgl/src/lv_conf_kconfig.h @@ -0,0 +1,182 @@ +/** * @file lv_conf_kconfig.h * Configs that need special handling when LVGL is used with Kconfig */ + +#ifndef LV_CONF_KCONFIG_H +#define LV_CONF_KCONFIG_H + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef LV_CONF_KCONFIG_EXTERNAL_INCLUDE +# include LV_CONF_KCONFIG_EXTERNAL_INCLUDE +#else + +# ifdef ESP_PLATFORM +# include "sdkconfig.h" +# include "esp_attr.h" +# endif + +# ifdef __NuttX__ +# include +# elif defined(__RTTHREAD__) +# define LV_CONF_INCLUDE_SIMPLE +# include +# endif + +#endif /*LV_CONF_KCONFIG_EXTERNAL_INCLUDE*/ + +/******************* + * LV COLOR CHROMA KEY + *******************/ + +#ifdef CONFIG_LV_COLOR_CHROMA_KEY_HEX +# define CONFIG_LV_COLOR_CHROMA_KEY lv_color_hex(CONFIG_LV_COLOR_CHROMA_KEY_HEX) +#endif + +/******************* + * LV_MEM_SIZE + *******************/ + +#ifdef CONFIG_LV_MEM_SIZE_KILOBYTES +# define CONFIG_LV_MEM_SIZE (CONFIG_LV_MEM_SIZE_KILOBYTES * 1024U) +#endif + +/******************** + * FONT SELECTION + *******************/ + +/** + * NOTE: In Kconfig instead of `LV_DEFAULT_FONT` + * `CONFIG_LV_FONT_DEFAULT_` is defined + * hence the large selection with if-s + */ + +/*------------------ + * DEFAULT FONT + *-----------------*/ +#ifdef CONFIG_LV_FONT_DEFAULT_MONTSERRAT_8 +# define CONFIG_LV_FONT_DEFAULT &lv_font_montserrat_8 +#elif defined(CONFIG_LV_FONT_DEFAULT_MONTSERRAT_10) +# define CONFIG_LV_FONT_DEFAULT &lv_font_montserrat_10 +#elif defined(CONFIG_LV_FONT_DEFAULT_MONTSERRAT_12) +# define CONFIG_LV_FONT_DEFAULT &lv_font_montserrat_12 +#elif defined(CONFIG_LV_FONT_DEFAULT_MONTSERRAT_14) +# define CONFIG_LV_FONT_DEFAULT &lv_font_montserrat_14 +#elif defined(CONFIG_LV_FONT_DEFAULT_MONTSERRAT_16) +# define CONFIG_LV_FONT_DEFAULT &lv_font_montserrat_16 +#elif defined(CONFIG_LV_FONT_DEFAULT_MONTSERRAT_18) +# define CONFIG_LV_FONT_DEFAULT &lv_font_montserrat_18 +#elif defined(CONFIG_LV_FONT_DEFAULT_MONTSERRAT_20) +# define CONFIG_LV_FONT_DEFAULT &lv_font_montserrat_20 +#elif defined(CONFIG_LV_FONT_DEFAULT_MONTSERRAT_22) +# define CONFIG_LV_FONT_DEFAULT &lv_font_montserrat_22 +#elif defined(CONFIG_LV_FONT_DEFAULT_MONTSERRAT_24) +# define CONFIG_LV_FONT_DEFAULT &lv_font_montserrat_24 +#elif defined(CONFIG_LV_FONT_DEFAULT_MONTSERRAT_26) +# define CONFIG_LV_FONT_DEFAULT &lv_font_montserrat_26 +#elif defined(CONFIG_LV_FONT_DEFAULT_MONTSERRAT_28) +# define CONFIG_LV_FONT_DEFAULT &lv_font_montserrat_28 +#elif defined(CONFIG_LV_FONT_DEFAULT_MONTSERRAT_30) +# define CONFIG_LV_FONT_DEFAULT &lv_font_montserrat_30 +#elif defined(CONFIG_LV_FONT_DEFAULT_MONTSERRAT_32) +# define CONFIG_LV_FONT_DEFAULT &lv_font_montserrat_32 +#elif defined(CONFIG_LV_FONT_DEFAULT_MONTSERRAT_34) +# define CONFIG_LV_FONT_DEFAULT &lv_font_montserrat_34 +#elif defined(CONFIG_LV_FONT_DEFAULT_MONTSERRAT_36) +# define CONFIG_LV_FONT_DEFAULT &lv_font_montserrat_36 +#elif defined(CONFIG_LV_FONT_DEFAULT_MONTSERRAT_38) +# define CONFIG_LV_FONT_DEFAULT &lv_font_montserrat_38 +#elif defined(CONFIG_LV_FONT_DEFAULT_MONTSERRAT_40) +# define CONFIG_LV_FONT_DEFAULT &lv_font_montserrat_40 +#elif defined(CONFIG_LV_FONT_DEFAULT_MONTSERRAT_42) +# define CONFIG_LV_FONT_DEFAULT &lv_font_montserrat_42 +#elif defined(CONFIG_LV_FONT_DEFAULT_MONTSERRAT_44) +# define CONFIG_LV_FONT_DEFAULT &lv_font_montserrat_44 +#elif defined(CONFIG_LV_FONT_DEFAULT_MONTSERRAT_46) +# define CONFIG_LV_FONT_DEFAULT &lv_font_montserrat_46 +#elif defined(CONFIG_LV_FONT_DEFAULT_MONTSERRAT_48) +# define CONFIG_LV_FONT_DEFAULT &lv_font_montserrat_48 +#elif defined(CONFIG_LV_FONT_DEFAULT_MONTSERRAT_12_SUBPX) +# define CONFIG_LV_FONT_DEFAULT &lv_font_montserrat_12_subpx +#elif defined(CONFIG_LV_FONT_DEFAULT_MONTSERRAT_28_COMPRESSED) +# define CONFIG_LV_FONT_DEFAULT &lv_font_montserrat_28_compressed +#elif defined(CONFIG_LV_FONT_DEFAULT_DEJAVU_16_PERSIAN_HEBREW) +# define CONFIG_LV_FONT_DEFAULT &lv_font_dejavu_16_persian_hebrew +#elif defined(CONFIG_LV_FONT_DEFAULT_SIMSUN_16_CJK) +# define CONFIG_LV_FONT_DEFAULT &lv_font_simsun_16_cjk +#elif defined(CONFIG_LV_FONT_DEFAULT_UNSCII_8) +# define CONFIG_LV_FONT_DEFAULT &lv_font_unscii_8 +#elif defined(CONFIG_LV_FONT_DEFAULT_UNSCII_16) +# define CONFIG_LV_FONT_DEFAULT &lv_font_unscii_16 +#endif + +/*------------------ + * TEXT ENCODING + *-----------------*/ +#ifdef CONFIG_LV_TXT_ENC_UTF8 +# define CONFIG_LV_TXT_ENC LV_TXT_ENC_UTF8 +#elif defined(CONFIG_LV_TXT_ENC_ASCII) +# define CONFIG_LV_TXT_ENC LV_TXT_ENC_ASCII +#endif + +/*------------------ + * BIDI DIRECTION + *-----------------*/ + +#ifdef CONFIG_LV_BASE_DIR_LTR +# define CONFIG_LV_BIDI_BASE_DIR_DEF LV_BASE_DIR_LTR +#elif defined(CONFIG_LV_BASE_DIR_RTL) +# define CONFIG_LV_BIDI_BASE_DIR_DEF LV_BASE_DIR_RTL +#elif defined(CONFIG_LV_BASE_DIR_AUTO) +# define CONFIG_LV_BIDI_BASE_DIR_DEF LV_BASE_DIR_AUTO +#endif + +/*------------------ + * MONITOR POSITION + *-----------------*/ + +#ifdef CONFIG_LV_PERF_MONITOR_ALIGN_TOP_LEFT +# define CONFIG_LV_USE_PERF_MONITOR_POS LV_ALIGN_TOP_LEFT +#elif defined(CONFIG_LV_USE_PERF_MONITOR_ALIGN_TOP_MID) +# define CONFIG_LV_USE_PERF_MONITOR_POS LV_ALIGN_TOP_MID +#elif defined(CONFIG_LV_PERF_MONITOR_ALIGN_TOP_RIGHT) +# define CONFIG_LV_USE_PERF_MONITOR_POS LV_ALIGN_TOP_RIGHT +#elif defined(CONFIG_LV_PERF_MONITOR_ALIGN_BOTTOM_LEFT) +# define CONFIG_LV_USE_PERF_MONITOR_POS LV_ALIGN_BOTTOM_LEFT +#elif defined(CONFIG_LV_PERF_MONITOR_ALIGN_BOTTOM_MID) +# define CONFIG_LV_USE_PERF_MONITOR_POS LV_ALIGN_BOTTOM_MID +#elif defined(CONFIG_LV_PERF_MONITOR_ALIGN_BOTTOM_RIGHT) +# define CONFIG_LV_USE_PERF_MONITOR_POS LV_ALIGN_BOTTOM_RIGHT +#elif defined(CONFIG_LV_PERF_MONITOR_ALIGN_LEFT_MID) +# define CONFIG_LV_USE_PERF_MONITOR_POS LV_ALIGN_LEFT_MID +#elif defined(CONFIG_LV_PERF_MONITOR_ALIGN_RIGHT_MID) +# define CONFIG_LV_USE_PERF_MONITOR_POS LV_ALIGN_RIGHT_MID +#elif defined(CONFIG_LV_PERF_MONITOR_ALIGN_CENTER) +# define CONFIG_LV_USE_PERF_MONITOR_POS LV_ALIGN_CENTER +#endif + +#ifdef CONFIG_LV_MEM_MONITOR_ALIGN_TOP_LEFT +# define CONFIG_LV_USE_MEM_MONITOR_POS LV_ALIGN_TOP_LEFT +#elif defined(CONFIG_LV_USE_MEM_MONITOR_ALIGN_TOP_MID) +# define CONFIG_LV_USE_MEM_MONITOR_POS LV_ALIGN_TOP_MID +#elif defined(CONFIG_LV_MEM_MONITOR_ALIGN_TOP_RIGHT) +# define CONFIG_LV_USE_MEM_MONITOR_POS LV_ALIGN_TOP_RIGHT +#elif defined(CONFIG_LV_MEM_MONITOR_ALIGN_BOTTOM_LEFT) +# define CONFIG_LV_USE_MEM_MONITOR_POS LV_ALIGN_BOTTOM_LEFT +#elif defined(CONFIG_LV_MEM_MONITOR_ALIGN_BOTTOM_MID) +# define CONFIG_LV_USE_MEM_MONITOR_POS LV_ALIGN_BOTTOM_MID +#elif defined(CONFIG_LV_MEM_MONITOR_ALIGN_BOTTOM_RIGHT) +# define CONFIG_LV_USE_MEM_MONITOR_POS LV_ALIGN_BOTTOM_RIGHT +#elif defined(CONFIG_LV_MEM_MONITOR_ALIGN_LEFT_MID) +# define CONFIG_LV_USE_MEM_MONITOR_POS LV_ALIGN_LEFT_MID +#elif defined(CONFIG_LV_MEM_MONITOR_ALIGN_RIGHT_MID) +# define CONFIG_LV_USE_MEM_MONITOR_POS LV_ALIGN_RIGHT_MID +#elif defined(CONFIG_LV_MEM_MONITOR_ALIGN_CENTER) +# define CONFIG_LV_USE_MEM_MONITOR_POS LV_ALIGN_CENTER +#endif + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif /*LV_CONF_KCONFIG_H*/ diff --git a/src/lib/lvgl/src/lvgl.h b/src/lib/lvgl/src/lvgl.h new file mode 100644 index 0000000..a7db27c --- /dev/null +++ b/src/lib/lvgl/src/lvgl.h @@ -0,0 +1,39 @@ +/** + * @file lvgl.h + * This file exists only to be compatible with Arduino's library structure + */ + +#ifndef LVGL_SRC_H +#define LVGL_SRC_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ + +#include "../lvgl.h" + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +/********************** + * MACROS + **********************/ + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif /*LVGL_SRC_H*/ diff --git a/src/lib/lvgl/src/misc/lv_anim.h b/src/lib/lvgl/src/misc/lv_anim.h new file mode 100644 index 0000000..18317eb --- /dev/null +++ b/src/lib/lvgl/src/misc/lv_anim.h @@ -0,0 +1,463 @@ +/** + * @file lv_anim.h + * + */ + +#ifndef LV_ANIM_H +#define LV_ANIM_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include "../lv_conf_internal.h" + +#include +#include +#include + +/********************* + * DEFINES + *********************/ + +#define LV_ANIM_REPEAT_INFINITE 0xFFFF +#define LV_ANIM_PLAYTIME_INFINITE 0xFFFFFFFF + +LV_EXPORT_CONST_INT(LV_ANIM_REPEAT_INFINITE); +LV_EXPORT_CONST_INT(LV_ANIM_PLAYTIME_INFINITE); + +/********************** + * TYPEDEFS + **********************/ + +/** Can be used to indicate if animations are enabled or disabled in a case*/ +typedef enum { + LV_ANIM_OFF, + LV_ANIM_ON, +} lv_anim_enable_t; + +struct _lv_anim_t; + +/** Get the current value during an animation*/ +typedef int32_t (*lv_anim_path_cb_t)(const struct _lv_anim_t *); + +/** Generic prototype of "animator" functions. + * First parameter is the variable to animate. + * Second parameter is the value to set. + * Compatible with `lv_xxx_set_yyy(obj, value)` functions + * The `x` in `_xcb_t` means it's not a fully generic prototype because + * it doesn't receive `lv_anim_t *` as its first argument*/ +typedef void (*lv_anim_exec_xcb_t)(void *, int32_t); + +/** Same as `lv_anim_exec_xcb_t` but receives `lv_anim_t *` as the first parameter. + * It's more consistent but less convenient. Might be used by binding generator functions.*/ +typedef void (*lv_anim_custom_exec_cb_t)(struct _lv_anim_t *, int32_t); + +/** Callback to call when the animation is ready*/ +typedef void (*lv_anim_ready_cb_t)(struct _lv_anim_t *); + +/** Callback to call when the animation really stars (considering `delay`)*/ +typedef void (*lv_anim_start_cb_t)(struct _lv_anim_t *); + +/** Callback used when the animation values are relative to get the current value*/ +typedef int32_t (*lv_anim_get_value_cb_t)(struct _lv_anim_t *); + +/** Describes an animation*/ +typedef struct _lv_anim_t { + void * var; /**var = var; +} + +/** + * Set a function to animate `var` + * @param a pointer to an initialized `lv_anim_t` variable + * @param exec_cb a function to execute during animation + * LVGL's built-in functions can be used. + * E.g. lv_obj_set_x + */ +static inline void lv_anim_set_exec_cb(lv_anim_t * a, lv_anim_exec_xcb_t exec_cb) +{ + a->exec_cb = exec_cb; +} + +/** + * Set the duration of an animation + * @param a pointer to an initialized `lv_anim_t` variable + * @param duration duration of the animation in milliseconds + */ +static inline void lv_anim_set_time(lv_anim_t * a, uint32_t duration) +{ + a->time = duration; +} + +/** + * Set a delay before starting the animation + * @param a pointer to an initialized `lv_anim_t` variable + * @param delay delay before the animation in milliseconds + */ +static inline void lv_anim_set_delay(lv_anim_t * a, uint32_t delay) +{ + a->act_time = -(int32_t)(delay); +} + +/** + * Set the start and end values of an animation + * @param a pointer to an initialized `lv_anim_t` variable + * @param start the start value + * @param end the end value + */ +static inline void lv_anim_set_values(lv_anim_t * a, int32_t start, int32_t end) +{ + a->start_value = start; + a->current_value = start; + a->end_value = end; +} + +/** + * Similar to `lv_anim_set_exec_cb` but `lv_anim_custom_exec_cb_t` receives + * `lv_anim_t * ` as its first parameter instead of `void *`. + * This function might be used when LVGL is bound to other languages because + * it's more consistent to have `lv_anim_t *` as first parameter. + * The variable to animate can be stored in the animation's `user_data` + * @param a pointer to an initialized `lv_anim_t` variable + * @param exec_cb a function to execute. + */ +static inline void lv_anim_set_custom_exec_cb(lv_anim_t * a, lv_anim_custom_exec_cb_t exec_cb) +{ + a->var = a; + a->exec_cb = (lv_anim_exec_xcb_t)exec_cb; +} + +/** + * Set the path (curve) of the animation. + * @param a pointer to an initialized `lv_anim_t` variable + * @param path_cb a function to set the current value of the animation. + */ +static inline void lv_anim_set_path_cb(lv_anim_t * a, lv_anim_path_cb_t path_cb) +{ + a->path_cb = path_cb; +} + +/** + * Set a function call when the animation really starts (considering `delay`) + * @param a pointer to an initialized `lv_anim_t` variable + * @param start_cb a function call when the animation starts + */ +static inline void lv_anim_set_start_cb(lv_anim_t * a, lv_anim_start_cb_t start_cb) +{ + a->start_cb = start_cb; +} + +/** + * Set a function to use the current value of the variable and make start and end value + * relative to the returned current value. + * @param a pointer to an initialized `lv_anim_t` variable + * @param get_value_cb a function call when the animation starts + */ +static inline void lv_anim_set_get_value_cb(lv_anim_t * a, lv_anim_get_value_cb_t get_value_cb) +{ + a->get_value_cb = get_value_cb; +} + +/** + * Set a function call when the animation is ready + * @param a pointer to an initialized `lv_anim_t` variable + * @param ready_cb a function call when the animation is ready + */ +static inline void lv_anim_set_ready_cb(lv_anim_t * a, lv_anim_ready_cb_t ready_cb) +{ + a->ready_cb = ready_cb; +} + +/** + * Make the animation to play back to when the forward direction is ready + * @param a pointer to an initialized `lv_anim_t` variable + * @param time the duration of the playback animation in milliseconds. 0: disable playback + */ +static inline void lv_anim_set_playback_time(lv_anim_t * a, uint32_t time) +{ + a->playback_time = time; +} + +/** + * Make the animation to play back to when the forward direction is ready + * @param a pointer to an initialized `lv_anim_t` variable + * @param delay delay in milliseconds before starting the playback animation. + */ +static inline void lv_anim_set_playback_delay(lv_anim_t * a, uint32_t delay) +{ + a->playback_delay = delay; +} + +/** + * Make the animation repeat itself. + * @param a pointer to an initialized `lv_anim_t` variable + * @param cnt repeat count or `LV_ANIM_REPEAT_INFINITE` for infinite repetition. 0: to disable repetition. + */ +static inline void lv_anim_set_repeat_count(lv_anim_t * a, uint16_t cnt) +{ + a->repeat_cnt = cnt; +} + +/** + * Set a delay before repeating the animation. + * @param a pointer to an initialized `lv_anim_t` variable + * @param delay delay in milliseconds before repeating the animation. + */ +static inline void lv_anim_set_repeat_delay(lv_anim_t * a, uint32_t delay) +{ + a->repeat_delay = delay; +} + +/** + * Set a whether the animation's should be applied immediately or only when the delay expired. + * @param a pointer to an initialized `lv_anim_t` variable + * @param en true: apply the start value immediately in `lv_anim_start`; + * false: apply the start value only when `delay` ms is elapsed and the animations really starts + */ +static inline void lv_anim_set_early_apply(lv_anim_t * a, bool en) +{ + a->early_apply = en; +} + +/** + * Set the custom user data field of the animation. + * @param a pointer to an initialized `lv_anim_t` variable + * @param user_data pointer to the new user_data. + */ +#if LV_USE_USER_DATA +static inline void lv_anim_set_user_data(lv_anim_t * a, void * user_data) +{ + a->user_data = user_data; +} +#endif + +/** + * Create an animation + * @param a an initialized 'anim_t' variable. Not required after call. + * @return pointer to the created animation (different from the `a` parameter) + */ +lv_anim_t * lv_anim_start(const lv_anim_t * a); + +/** + * Get a delay before starting the animation + * @param a pointer to an initialized `lv_anim_t` variable + * @return delay before the animation in milliseconds + */ +static inline uint32_t lv_anim_get_delay(lv_anim_t * a) +{ + return -a->act_time; +} + +/** + * Get the time used to play the animation. + * @param a pointer to an animation. + * @return the play time in milliseconds. + */ +uint32_t lv_anim_get_playtime(lv_anim_t * a); + +/** + * Get the user_data field of the animation + * @param a pointer to an initialized `lv_anim_t` variable + * @return the pointer to the custom user_data of the animation + */ +#if LV_USE_USER_DATA +static inline void * lv_anim_get_user_data(lv_anim_t * a) +{ + return a->user_data; +} +#endif + +/** + * Delete an animation of a variable with a given animator function + * @param var pointer to variable + * @param exec_cb a function pointer which is animating 'var', + * or NULL to ignore it and delete all the animations of 'var + * @return true: at least 1 animation is deleted, false: no animation is deleted + */ +bool lv_anim_del(void * var, lv_anim_exec_xcb_t exec_cb); + +/** + * Delete all the animations + */ +void lv_anim_del_all(void); + +/** + * Get the animation of a variable and its `exec_cb`. + * @param var pointer to variable + * @param exec_cb a function pointer which is animating 'var', or NULL to return first matching 'var' + * @return pointer to the animation. + */ +lv_anim_t * lv_anim_get(void * var, lv_anim_exec_xcb_t exec_cb); + +/** + * Delete an animation by getting the animated variable from `a`. + * Only animations with `exec_cb` will be deleted. + * This function exists because it's logical that all anim. functions receives an + * `lv_anim_t` as their first parameter. It's not practical in C but might make + * the API more consequent and makes easier to generate bindings. + * @param a pointer to an animation. + * @param exec_cb a function pointer which is animating 'var', + * or NULL to ignore it and delete all the animations of 'var + * @return true: at least 1 animation is deleted, false: no animation is deleted + */ +static inline bool lv_anim_custom_del(lv_anim_t * a, lv_anim_custom_exec_cb_t exec_cb) +{ + return lv_anim_del(a ? a->var : NULL, (lv_anim_exec_xcb_t)exec_cb); +} + +/** + * Get the animation of a variable and its `exec_cb`. + * This function exists because it's logical that all anim. functions receives an + * `lv_anim_t` as their first parameter. It's not practical in C but might make + * the API more consequent and makes easier to generate bindings. + * @param a pointer to an animation. + * @param exec_cb a function pointer which is animating 'var', or NULL to return first matching 'var' + * @return pointer to the animation. + */ +static inline lv_anim_t * lv_anim_custom_get(lv_anim_t * a, lv_anim_custom_exec_cb_t exec_cb) +{ + return lv_anim_get(a ? a->var : NULL, (lv_anim_exec_xcb_t)exec_cb); +} + +/** + * Get the number of currently running animations + * @return the number of running animations + */ +uint16_t lv_anim_count_running(void); + +/** + * Calculate the time of an animation with a given speed and the start and end values + * @param speed speed of animation in unit/sec + * @param start start value of the animation + * @param end end value of the animation + * @return the required time [ms] for the animation with the given parameters + */ +uint32_t lv_anim_speed_to_time(uint32_t speed, int32_t start, int32_t end); + +/** + * Manually refresh the state of the animations. + * Useful to make the animations running in a blocking process where + * `lv_timer_handler` can't run for a while. + * Shouldn't be used directly because it is called in `lv_refr_now()`. + */ +void lv_anim_refr_now(void); + +/** + * Calculate the current value of an animation applying linear characteristic + * @param a pointer to an animation + * @return the current value to set + */ +int32_t lv_anim_path_linear(const lv_anim_t * a); + +/** + * Calculate the current value of an animation slowing down the start phase + * @param a pointer to an animation + * @return the current value to set + */ +int32_t lv_anim_path_ease_in(const lv_anim_t * a); + +/** + * Calculate the current value of an animation slowing down the end phase + * @param a pointer to an animation + * @return the current value to set + */ +int32_t lv_anim_path_ease_out(const lv_anim_t * a); + +/** + * Calculate the current value of an animation applying an "S" characteristic (cosine) + * @param a pointer to an animation + * @return the current value to set + */ +int32_t lv_anim_path_ease_in_out(const lv_anim_t * a); + +/** + * Calculate the current value of an animation with overshoot at the end + * @param a pointer to an animation + * @return the current value to set + */ +int32_t lv_anim_path_overshoot(const lv_anim_t * a); + +/** + * Calculate the current value of an animation with 3 bounces + * @param a pointer to an animation + * @return the current value to set + */ +int32_t lv_anim_path_bounce(const lv_anim_t * a); + +/** + * Calculate the current value of an animation applying step characteristic. + * (Set end value on the end of the animation) + * @param a pointer to an animation + * @return the current value to set + */ +int32_t lv_anim_path_step(const lv_anim_t * a); + +/********************** + * GLOBAL VARIABLES + **********************/ + +/********************** + * MACROS + **********************/ + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif /*LV_ANIM_H*/ diff --git a/src/lib/lvgl/src/misc/lv_anim_timeline.h b/src/lib/lvgl/src/misc/lv_anim_timeline.h new file mode 100644 index 0000000..d4dd0fc --- /dev/null +++ b/src/lib/lvgl/src/misc/lv_anim_timeline.h @@ -0,0 +1,103 @@ +/** + * @file lv_anim_timeline.h + * + */ + +#ifndef LV_ANIM_TIMELINE_H +#define LV_ANIM_TIMELINE_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include "lv_anim.h" + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +struct _lv_anim_timeline_t; + +typedef struct _lv_anim_timeline_t lv_anim_timeline_t; + +/********************** +* GLOBAL PROTOTYPES +**********************/ + +/** + * Create an animation timeline. + * @return pointer to the animation timeline. + */ +lv_anim_timeline_t * lv_anim_timeline_create(void); + +/** + * Delete animation timeline. + * @param at pointer to the animation timeline. + */ +void lv_anim_timeline_del(lv_anim_timeline_t * at); + +/** + * Add animation to the animation timeline. + * @param at pointer to the animation timeline. + * @param start_time the time the animation started on the timeline, note that start_time will override the value of delay. + * @param a pointer to an animation. + */ +void lv_anim_timeline_add(lv_anim_timeline_t * at, uint32_t start_time, lv_anim_t * a); + +/** + * Start the animation timeline. + * @param at pointer to the animation timeline. + * @return total time spent in animation timeline. + */ +uint32_t lv_anim_timeline_start(lv_anim_timeline_t * at); + +/** + * Stop the animation timeline. + * @param at pointer to the animation timeline. + */ +void lv_anim_timeline_stop(lv_anim_timeline_t * at); + +/** + * Set the playback direction of the animation timeline. + * @param at pointer to the animation timeline. + * @param reverse whether to play in reverse. + */ +void lv_anim_timeline_set_reverse(lv_anim_timeline_t * at, bool reverse); + +/** + * Set the progress of the animation timeline. + * @param at pointer to the animation timeline. + * @param progress set value 0~65535 to map 0~100% animation progress. + */ +void lv_anim_timeline_set_progress(lv_anim_timeline_t * at, uint16_t progress); + +/** + * Get the time used to play the animation timeline. + * @param at pointer to the animation timeline. + * @return total time spent in animation timeline. + */ +uint32_t lv_anim_timeline_get_playtime(lv_anim_timeline_t * at); + +/** + * Get whether the animation timeline is played in reverse. + * @param at pointer to the animation timeline. + * @return return true if it is reverse playback. + */ +bool lv_anim_timeline_get_reverse(lv_anim_timeline_t * at); + +/********************** + * MACROS + **********************/ + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif /*LV_ANIM_TIMELINE_H*/ diff --git a/src/lib/lvgl/src/misc/lv_area.h b/src/lib/lvgl/src/misc/lv_area.h new file mode 100644 index 0000000..542d86b --- /dev/null +++ b/src/lib/lvgl/src/misc/lv_area.h @@ -0,0 +1,293 @@ +/** + * @file lv_area.h + * + */ + +#ifndef LV_AREA_H +#define LV_AREA_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include "../lv_conf_internal.h" +#include +#include + +/********************* + * DEFINES + *********************/ + +#if LV_USE_LARGE_COORD +typedef int32_t lv_coord_t; +#else +typedef int16_t lv_coord_t; +#endif + +/********************** + * TYPEDEFS + **********************/ + +/** + * Represents a point on the screen. + */ +typedef struct { + lv_coord_t x; + lv_coord_t y; +} lv_point_t; + +/** Represents an area of the screen.*/ +typedef struct { + lv_coord_t x1; + lv_coord_t y1; + lv_coord_t x2; + lv_coord_t y2; +} lv_area_t; + +/** Alignments*/ +enum { + LV_ALIGN_DEFAULT = 0, + LV_ALIGN_TOP_LEFT, + LV_ALIGN_TOP_MID, + LV_ALIGN_TOP_RIGHT, + LV_ALIGN_BOTTOM_LEFT, + LV_ALIGN_BOTTOM_MID, + LV_ALIGN_BOTTOM_RIGHT, + LV_ALIGN_LEFT_MID, + LV_ALIGN_RIGHT_MID, + LV_ALIGN_CENTER, + + LV_ALIGN_OUT_TOP_LEFT, + LV_ALIGN_OUT_TOP_MID, + LV_ALIGN_OUT_TOP_RIGHT, + LV_ALIGN_OUT_BOTTOM_LEFT, + LV_ALIGN_OUT_BOTTOM_MID, + LV_ALIGN_OUT_BOTTOM_RIGHT, + LV_ALIGN_OUT_LEFT_TOP, + LV_ALIGN_OUT_LEFT_MID, + LV_ALIGN_OUT_LEFT_BOTTOM, + LV_ALIGN_OUT_RIGHT_TOP, + LV_ALIGN_OUT_RIGHT_MID, + LV_ALIGN_OUT_RIGHT_BOTTOM, +}; +typedef uint8_t lv_align_t; + +enum { + LV_DIR_NONE = 0x00, + LV_DIR_LEFT = (1 << 0), + LV_DIR_RIGHT = (1 << 1), + LV_DIR_TOP = (1 << 2), + LV_DIR_BOTTOM = (1 << 3), + LV_DIR_HOR = LV_DIR_LEFT | LV_DIR_RIGHT, + LV_DIR_VER = LV_DIR_TOP | LV_DIR_BOTTOM, + LV_DIR_ALL = LV_DIR_HOR | LV_DIR_VER, +}; + +typedef uint8_t lv_dir_t; + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +/** + * Initialize an area + * @param area_p pointer to an area + * @param x1 left coordinate of the area + * @param y1 top coordinate of the area + * @param x2 right coordinate of the area + * @param y2 bottom coordinate of the area + */ +void lv_area_set(lv_area_t * area_p, lv_coord_t x1, lv_coord_t y1, lv_coord_t x2, lv_coord_t y2); + +/** + * Copy an area + * @param dest pointer to the destination area + * @param src pointer to the source area + */ +inline static void lv_area_copy(lv_area_t * dest, const lv_area_t * src) +{ + dest->x1 = src->x1; + dest->y1 = src->y1; + dest->x2 = src->x2; + dest->y2 = src->y2; +} + +/** + * Get the width of an area + * @param area_p pointer to an area + * @return the width of the area (if x1 == x2 -> width = 1) + */ +static inline lv_coord_t lv_area_get_width(const lv_area_t * area_p) +{ + return (lv_coord_t)(area_p->x2 - area_p->x1 + 1); +} + +/** + * Get the height of an area + * @param area_p pointer to an area + * @return the height of the area (if y1 == y2 -> height = 1) + */ +static inline lv_coord_t lv_area_get_height(const lv_area_t * area_p) +{ + return (lv_coord_t)(area_p->y2 - area_p->y1 + 1); +} + +/** + * Set the width of an area + * @param area_p pointer to an area + * @param w the new width of the area (w == 1 makes x1 == x2) + */ +void lv_area_set_width(lv_area_t * area_p, lv_coord_t w); + +/** + * Set the height of an area + * @param area_p pointer to an area + * @param h the new height of the area (h == 1 makes y1 == y2) + */ +void lv_area_set_height(lv_area_t * area_p, lv_coord_t h); + +/** + * Set the position of an area (width and height will be kept) + * @param area_p pointer to an area + * @param x the new x coordinate of the area + * @param y the new y coordinate of the area + */ +void _lv_area_set_pos(lv_area_t * area_p, lv_coord_t x, lv_coord_t y); + +/** + * Return with area of an area (x * y) + * @param area_p pointer to an area + * @return size of area + */ +uint32_t lv_area_get_size(const lv_area_t * area_p); + +void lv_area_increase(lv_area_t * area, lv_coord_t w_extra, lv_coord_t h_extra); + +void lv_area_move(lv_area_t * area, lv_coord_t x_ofs, lv_coord_t y_ofs); + +/** + * Get the common parts of two areas + * @param res_p pointer to an area, the result will be stored her + * @param a1_p pointer to the first area + * @param a2_p pointer to the second area + * @return false: the two area has NO common parts, res_p is invalid + */ +bool _lv_area_intersect(lv_area_t * res_p, const lv_area_t * a1_p, const lv_area_t * a2_p); + +/** + * Join two areas into a third which involves the other two + * @param res_p pointer to an area, the result will be stored here + * @param a1_p pointer to the first area + * @param a2_p pointer to the second area + */ +void _lv_area_join(lv_area_t * a_res_p, const lv_area_t * a1_p, const lv_area_t * a2_p); + +/** + * Check if a point is on an area + * @param a_p pointer to an area + * @param p_p pointer to a point + * @param radius radius of area (e.g. for rounded rectangle) + * @return false:the point is out of the area + */ +bool _lv_area_is_point_on(const lv_area_t * a_p, const lv_point_t * p_p, lv_coord_t radius); + +/** + * Check if two area has common parts + * @param a1_p pointer to an area. + * @param a2_p pointer to an other area + * @return false: a1_p and a2_p has no common parts + */ +bool _lv_area_is_on(const lv_area_t * a1_p, const lv_area_t * a2_p); + +/** + * Check if an area is fully on an other + * @param ain_p pointer to an area which could be in 'aholder_p' + * @param aholder_p pointer to an area which could involve 'ain_p' + * @param radius radius of `aholder_p` (e.g. for rounded rectangle) + * @return true: `ain_p` is fully inside `aholder_p` + */ +bool _lv_area_is_in(const lv_area_t * ain_p, const lv_area_t * aholder_p, lv_coord_t radius); + + +/** + * Check if an area is fully out of an other + * @param aout_p pointer to an area which could be in 'aholder_p' + * @param aholder_p pointer to an area which could involve 'ain_p' + * @param radius radius of `aholder_p` (e.g. for rounded rectangle) + * @return true: `aout_p` is fully outside `aholder_p` + */ +bool _lv_area_is_out(const lv_area_t * aout_p, const lv_area_t * aholder_p, lv_coord_t radius); + +/** + * Check if 2 area is the same + * @param a pointer to an area + * @param b pointer to another area + */ +bool _lv_area_is_equal(const lv_area_t * a, const lv_area_t * b); + +/** + * Align an area to an other + * @param base an are where the other will be aligned + * @param to_align the area to align + * @param align `LV_ALIGN_...` + */ +void lv_area_align(const lv_area_t * base, lv_area_t * to_align, lv_align_t align, lv_coord_t ofs_x, lv_coord_t ofs_y); + +/********************** + * MACROS + **********************/ + +#if LV_USE_LARGE_COORD +#define _LV_COORD_TYPE_SHIFT (29U) +#else +#define _LV_COORD_TYPE_SHIFT (13U) +#endif + +#define _LV_COORD_TYPE_MASK (3 << _LV_COORD_TYPE_SHIFT) +#define _LV_COORD_TYPE(x) ((x) & _LV_COORD_TYPE_MASK) /*Extract type specifiers*/ +#define _LV_COORD_PLAIN(x) ((x) & ~_LV_COORD_TYPE_MASK) /*Remove type specifiers*/ + +#define _LV_COORD_TYPE_PX (0 << _LV_COORD_TYPE_SHIFT) +#define _LV_COORD_TYPE_SPEC (1 << _LV_COORD_TYPE_SHIFT) +#define _LV_COORD_TYPE_PX_NEG (3 << _LV_COORD_TYPE_SHIFT) + +#define LV_COORD_IS_PX(x) (_LV_COORD_TYPE(x) == _LV_COORD_TYPE_PX || \ + _LV_COORD_TYPE(x) == _LV_COORD_TYPE_PX_NEG ? true : false) +#define LV_COORD_IS_SPEC(x) (_LV_COORD_TYPE(x) == _LV_COORD_TYPE_SPEC ? true : false) + +#define LV_COORD_SET_SPEC(x) ((x) | _LV_COORD_TYPE_SPEC) + +/*Special coordinates*/ +#define LV_PCT(x) (x < 0 ? LV_COORD_SET_SPEC(1000 - (x)) : LV_COORD_SET_SPEC(x)) +#define LV_COORD_IS_PCT(x) ((LV_COORD_IS_SPEC(x) && _LV_COORD_PLAIN(x) <= 2000) ? true : false) +#define LV_COORD_GET_PCT(x) (_LV_COORD_PLAIN(x) > 1000 ? 1000 - _LV_COORD_PLAIN(x) : _LV_COORD_PLAIN(x)) +#define LV_SIZE_CONTENT LV_COORD_SET_SPEC(2001) + +LV_EXPORT_CONST_INT(LV_SIZE_CONTENT); + +/*Max coordinate value*/ +#define LV_COORD_MAX ((1 << _LV_COORD_TYPE_SHIFT) - 1) +#define LV_COORD_MIN (-LV_COORD_MAX) + +LV_EXPORT_CONST_INT(LV_COORD_MAX); +LV_EXPORT_CONST_INT(LV_COORD_MIN); + +/** + * Convert a percentage value to `lv_coord_t`. + * Percentage values are stored in special range + * @param x the percentage (0..1000) + * @return a coordinate that stores the percentage + */ +static inline lv_coord_t lv_pct(lv_coord_t x) +{ + return LV_PCT(x); +} + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif diff --git a/src/lib/lvgl/src/misc/lv_assert.h b/src/lib/lvgl/src/misc/lv_assert.h new file mode 100644 index 0000000..48db744 --- /dev/null +++ b/src/lib/lvgl/src/misc/lv_assert.h @@ -0,0 +1,79 @@ +/** + * @file lv_assert.h + * + */ + +#ifndef LV_ASSERT_H +#define LV_ASSERT_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include "../lv_conf_internal.h" +#include "lv_log.h" +#include "lv_mem.h" +#include LV_ASSERT_HANDLER_INCLUDE + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +/********************** + * MACROS + **********************/ + +#define LV_ASSERT(expr) \ + do { \ + if(!(expr)) { \ + LV_LOG_ERROR("Asserted at expression: %s", #expr); \ + LV_ASSERT_HANDLER \ + } \ + } while(0) + +#define LV_ASSERT_MSG(expr, msg) \ + do { \ + if(!(expr)) { \ + LV_LOG_ERROR("Asserted at expression: %s (%s)", #expr, msg); \ + LV_ASSERT_HANDLER \ + } \ + } while(0) + +/*----------------- + * ASSERTS + *-----------------*/ + +#if LV_USE_ASSERT_NULL +# define LV_ASSERT_NULL(p) LV_ASSERT_MSG(p != NULL, "NULL pointer"); +#else +# define LV_ASSERT_NULL(p) +#endif + +#if LV_USE_ASSERT_MALLOC +# define LV_ASSERT_MALLOC(p) LV_ASSERT_MSG(p != NULL, "Out of memory"); +#else +# define LV_ASSERT_MALLOC(p) +#endif + +#if LV_USE_ASSERT_MEM_INTEGRITY +# define LV_ASSERT_MEM_INTEGRITY() LV_ASSERT_MSG(lv_mem_test() == LV_RES_OK, "Memory integrity error"); +#else +# define LV_ASSERT_MEM_INTEGRITY() +#endif + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif /*LV_ASSERT_H*/ diff --git a/src/lib/lvgl/src/misc/lv_async.h b/src/lib/lvgl/src/misc/lv_async.h new file mode 100644 index 0000000..3e6cb63 --- /dev/null +++ b/src/lib/lvgl/src/misc/lv_async.h @@ -0,0 +1,54 @@ +/** + * @file lv_async.h + * + */ + +#ifndef LV_ASYNC_H +#define LV_ASYNC_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ + +#include "lv_types.h" + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +/** + * Type for async callback. + */ +typedef void (*lv_async_cb_t)(void *); + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +/** + * Call an asynchronous function the next time lv_timer_handler() is run. This function is likely to return + * **before** the call actually happens! + * @param async_xcb a callback which is the task itself. + * (the 'x' in the argument name indicates that it's not a fully generic function because it not follows + * the `func_name(object, callback, ...)` convention) + * @param user_data custom parameter + */ +lv_res_t lv_async_call(lv_async_cb_t async_xcb, void * user_data); + +/********************** + * MACROS + **********************/ + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif /*LV_ASYNC_H*/ diff --git a/src/lib/lvgl/src/misc/lv_bidi.h b/src/lib/lvgl/src/misc/lv_bidi.h new file mode 100644 index 0000000..a27b580 --- /dev/null +++ b/src/lib/lvgl/src/misc/lv_bidi.h @@ -0,0 +1,141 @@ +/** + * @file lv_bidi.h + * + */ + +#ifndef LV_BIDI_H +#define LV_BIDI_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include "../lv_conf_internal.h" + +#include +#include +#include "lv_txt.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 { + LV_BASE_DIR_LTR = 0x00, + LV_BASE_DIR_RTL = 0x01, + LV_BASE_DIR_AUTO = 0x02, + + LV_BASE_DIR_NEUTRAL = 0x20, + LV_BASE_DIR_WEAK = 0x21, +}; + +typedef uint8_t lv_base_dir_t; + +/********************** + * GLOBAL PROTOTYPES + **********************/ +#if LV_USE_BIDI + +/** + * Convert a text to get the characters in the correct visual order according to + * Unicode Bidirectional Algorithm + * @param str_in the text to process + * @param str_out store the result here. Has the be `strlen(str_in)` length + * @param base_dir `LV_BASE_DIR_LTR` or `LV_BASE_DIR_RTL` + */ +void _lv_bidi_process(const char * str_in, char * str_out, lv_base_dir_t base_dir); + +/** + * Auto-detect the direction of a text based on the first strong character + * @param txt the text to process + * @return `LV_BASE_DIR_LTR` or `LV_BASE_DIR_RTL` + */ +lv_base_dir_t _lv_bidi_detect_base_dir(const char * txt); + +/** + * Get the logical position of a character in a line + * @param str_in the input string. Can be only one line. + * @param bidi_txt internally the text is bidi processed which buffer can be get here. + * If not required anymore has to freed with `lv_mem_free()` + * Can be `NULL` is unused + * @param len length of the line in character count + * @param base_dir base direction of the text: `LV_BASE_DIR_LTR` or `LV_BASE_DIR_RTL` + * @param visual_pos the visual character position which logical position should be get + * @param is_rtl tell the char at `visual_pos` is RTL or LTR context + * @return the logical character position + */ +uint16_t _lv_bidi_get_logical_pos(const char * str_in, char ** bidi_txt, uint32_t len, lv_base_dir_t base_dir, + uint32_t visual_pos, bool * is_rtl); + +/** + * Get the visual position of a character in a line + * @param str_in the input string. Can be only one line. + * @param bidi_txt internally the text is bidi processed which buffer can be get here. + * If not required anymore has to freed with `lv_mem_free()` + * Can be `NULL` is unused + * @param len length of the line in character count + * @param base_dir base direction of the text: `LV_BASE_DIR_LTR` or `LV_BASE_DIR_RTL` + * @param logical_pos the logical character position which visual position should be get + * @param is_rtl tell the char at `logical_pos` is RTL or LTR context + * @return the visual character position + */ +uint16_t _lv_bidi_get_visual_pos(const char * str_in, char ** bidi_txt, uint16_t len, lv_base_dir_t base_dir, + uint32_t logical_pos, bool * is_rtl); + +/** + * Bidi process a paragraph of text + * @param str_in the string to process + * @param str_out store the result here + * @param len length of the text + * @param base_dir base dir of the text + * @param pos_conv_out an `uint16_t` array to store the related logical position of the character. + * Can be `NULL` is unused + * @param pos_conv_len length of `pos_conv_out` in element count + */ +void _lv_bidi_process_paragraph(const char * str_in, char * str_out, uint32_t len, lv_base_dir_t base_dir, + uint16_t * pos_conv_out, uint16_t pos_conv_len); + +/** + * Get the real text alignment from the a text alignment, base direction and a text. + * @param align LV_TEXT_ALIGN_..., write back the calculated align here (LV_TEXT_ALIGN_LEFT/RIGHT/CENTER) + * @param base_dir LV_BASE_DIR_..., write the calculated base dir here (LV_BASE_DIR_LTR/RTL) + * @param txt a text, used with LV_BASE_DIR_AUTO to determine the base direction + */ +void lv_bidi_calculate_align(lv_text_align_t * align, lv_base_dir_t * base_dir, const char * txt); + + +/********************** + * MACROS + **********************/ + +#else /*LV_USE_BIDI*/ +/** + * For compatibility if LV_USE_BIDI = 0 + * Get the real text alignment from the a text alignment, base direction and a text. + * @param align For LV_TEXT_ALIGN_AUTO give LV_TEXT_ALIGN_LEFT else leave unchanged, write back the calculated align here + * @param base_dir Unused + * @param txt Unused + */ +static inline void lv_bidi_calculate_align(lv_text_align_t * align, lv_base_dir_t * base_dir, const char * txt) +{ + LV_UNUSED(txt); + LV_UNUSED(base_dir); + if(*align == LV_TEXT_ALIGN_AUTO) * align = LV_TEXT_ALIGN_LEFT; +} +#endif /*LV_USE_BIDI*/ + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif /*LV_BIDI_H*/ diff --git a/src/lib/lvgl/src/misc/lv_color.h b/src/lib/lvgl/src/misc/lv_color.h new file mode 100644 index 0000000..37445cc --- /dev/null +++ b/src/lib/lvgl/src/misc/lv_color.h @@ -0,0 +1,712 @@ +/** + * @file lv_color.h + * + */ + +#ifndef LV_COLOR_H +#define LV_COLOR_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include "../lv_conf_internal.h" +#include "lv_assert.h" +#include "lv_math.h" +#include "lv_types.h" + +/*Error checking*/ +#if LV_COLOR_DEPTH == 24 +#error "LV_COLOR_DEPTH 24 is deprecated. Use LV_COLOR_DEPTH 32 instead (lv_conf.h)" +#endif + +#if LV_COLOR_DEPTH != 32 && LV_COLOR_SCREEN_TRANSP != 0 +#error "LV_COLOR_SCREEN_TRANSP requires LV_COLOR_DEPTH == 32. Set it in lv_conf.h" +#endif + +#if LV_COLOR_DEPTH != 16 && LV_COLOR_16_SWAP != 0 +#error "LV_COLOR_16_SWAP requires LV_COLOR_DEPTH == 16. Set it in lv_conf.h" +#endif + +#include + +/********************* + * DEFINES + *********************/ +LV_EXPORT_CONST_INT(LV_COLOR_DEPTH); +LV_EXPORT_CONST_INT(LV_COLOR_16_SWAP); + +/** + * Opacity percentages. + */ +enum { + LV_OPA_TRANSP = 0, + LV_OPA_0 = 0, + LV_OPA_10 = 25, + LV_OPA_20 = 51, + LV_OPA_30 = 76, + LV_OPA_40 = 102, + LV_OPA_50 = 127, + LV_OPA_60 = 153, + LV_OPA_70 = 178, + LV_OPA_80 = 204, + LV_OPA_90 = 229, + LV_OPA_100 = 255, + LV_OPA_COVER = 255, +}; + +#define LV_OPA_MIN 2 /*Opacities below this will be transparent*/ +#define LV_OPA_MAX 253 /*Opacities above this will fully cover*/ + +#if LV_COLOR_DEPTH == 1 +#define LV_COLOR_SIZE 8 +#elif LV_COLOR_DEPTH == 8 +#define LV_COLOR_SIZE 8 +#elif LV_COLOR_DEPTH == 16 +#define LV_COLOR_SIZE 16 +#elif LV_COLOR_DEPTH == 32 +#define LV_COLOR_SIZE 32 +#else +#error "Invalid LV_COLOR_DEPTH in lv_conf.h! Set it to 1, 8, 16 or 32!" +#endif + +#if defined(__cplusplus) && !defined(_LV_COLOR_HAS_MODERN_CPP) +/** +* MSVC compiler's definition of the __cplusplus indicating 199711L regardless to C++ standard version +* see https://devblogs.microsoft.com/cppblog/msvc-now-correctly-reports-cplusplus +* so we use _MSC_VER macro instead of __cplusplus +*/ +#ifdef _MSC_VER +#if _MSC_VER >= 1900 /*Visual Studio 2015*/ +#define _LV_COLOR_HAS_MODERN_CPP 1 +#endif +#else +#if __cplusplus >= 201103L +#define _LV_COLOR_HAS_MODERN_CPP 1 +#endif +#endif +#endif /*__cplusplus*/ + +#ifndef _LV_COLOR_HAS_MODERN_CPP +#define _LV_COLOR_HAS_MODERN_CPP 0 +#endif + +#if _LV_COLOR_HAS_MODERN_CPP +/*Fix msvc compiler error C4576 inside C++ code*/ +#define _LV_COLOR_MAKE_TYPE_HELPER lv_color_t +#else +#define _LV_COLOR_MAKE_TYPE_HELPER (lv_color_t) +#endif + +/*--------------------------------------- + * Macros for all existing color depths + * 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) do {} while(0) + +# define LV_COLOR_GET_R1(c) (c).ch.red +# define LV_COLOR_GET_G1(c) (c).ch.green +# define LV_COLOR_GET_B1(c) (c).ch.blue +# define LV_COLOR_GET_A1(c) 0xFF + +# define _LV_COLOR_ZERO_INITIALIZER1 {0x00} +# define LV_COLOR_MAKE1(r8, g8, b8) {(uint8_t)((b8 >> 7) | (g8 >> 7) | (r8 >> 7))} + +# define LV_COLOR_SET_R8(c, v) (c).ch.red = (uint8_t)((v) & 0x7U) +# define LV_COLOR_SET_G8(c, v) (c).ch.green = (uint8_t)((v) & 0x7U) +# define LV_COLOR_SET_B8(c, v) (c).ch.blue = (uint8_t)((v) & 0x3U) +# define LV_COLOR_SET_A8(c, v) do {} while(0) + +# define LV_COLOR_GET_R8(c) (c).ch.red +# 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_ZERO_INITIALIZER8 {{0x00, 0x00, 0x00}} +# define LV_COLOR_MAKE8(r8, g8, b8) {{(uint8_t)((b8 >> 6) & 0x3U), (uint8_t)((g8 >> 5) & 0x7U), (uint8_t)((r8 >> 5) & 0x7U)}} + +# define LV_COLOR_SET_R16(c, v) (c).ch.red = (uint8_t)((v) & 0x1FU) +#if LV_COLOR_16_SWAP == 0 +# define LV_COLOR_SET_G16(c, v) (c).ch.green = (uint8_t)((v) & 0x3FU) +#else +# define LV_COLOR_SET_G16(c, v) {(c).ch.green_h = (uint8_t)(((v) >> 3) & 0x7); (c).ch.green_l = (uint8_t)((v) & 0x7);} +#endif +# define LV_COLOR_SET_B16(c, v) (c).ch.blue = (uint8_t)((v) & 0x1FU) +# define LV_COLOR_SET_A16(c, v) do {} while(0) + +# define LV_COLOR_GET_R16(c) (c).ch.red +#if LV_COLOR_16_SWAP == 0 +# define LV_COLOR_GET_G16(c) (c).ch.green +#else +# define LV_COLOR_GET_G16(c) (((c).ch.green_h << 3) + (c).ch.green_l) +#endif +# define LV_COLOR_GET_B16(c) (c).ch.blue +# define LV_COLOR_GET_A16(c) 0xFF + +#if LV_COLOR_16_SWAP == 0 +# define _LV_COLOR_ZERO_INITIALIZER16 {{0x00, 0x00, 0x00}} +# define LV_COLOR_MAKE16(r8, g8, b8) {{(uint8_t)((b8 >> 3) & 0x1FU), (uint8_t)((g8 >> 2) & 0x3FU), (uint8_t)((r8 >> 3) & 0x1FU)}} +#else +# define _LV_COLOR_ZERO_INITIALIZER16 {{0x00, 0x00, 0x00, 0x00}} +# define LV_COLOR_MAKE16(r8, g8, b8) {{(uint8_t)((g8 >> 5) & 0x7U), (uint8_t)((r8 >> 3) & 0x1FU), (uint8_t)((b8 >> 3) & 0x1FU), (uint8_t)((g8 >> 2) & 0x7U)}} +#endif + +# define LV_COLOR_SET_R32(c, v) (c).ch.red = (uint8_t)((v) & 0xFF) +# define LV_COLOR_SET_G32(c, v) (c).ch.green = (uint8_t)((v) & 0xFF) +# define LV_COLOR_SET_B32(c, v) (c).ch.blue = (uint8_t)((v) & 0xFF) +# define LV_COLOR_SET_A32(c, v) (c).ch.alpha = (uint8_t)((v) & 0xFF) + +# define LV_COLOR_GET_R32(c) (c).ch.red +# define LV_COLOR_GET_G32(c) (c).ch.green +# define LV_COLOR_GET_B32(c) (c).ch.blue +# define LV_COLOR_GET_A32(c) (c).ch.alpha + +# define _LV_COLOR_ZERO_INITIALIZER32 {{0x00, 0x00, 0x00, 0x00}} +# define LV_COLOR_MAKE32(r8, g8, b8) {{b8, g8, r8, 0xff}} /*Fix 0xff alpha*/ + +/*--------------------------------------- + * Macros for the current color depth + * to set/get values of the color channels + *------------------------------------------*/ +#define LV_COLOR_SET_R(c, v) LV_CONCAT(LV_COLOR_SET_R, LV_COLOR_DEPTH)(c, v) +#define LV_COLOR_SET_G(c, v) LV_CONCAT(LV_COLOR_SET_G, LV_COLOR_DEPTH)(c, v) +#define LV_COLOR_SET_B(c, v) LV_CONCAT(LV_COLOR_SET_B, LV_COLOR_DEPTH)(c, v) +#define LV_COLOR_SET_A(c, v) LV_CONCAT(LV_COLOR_SET_A, LV_COLOR_DEPTH)(c, v) + +#define LV_COLOR_GET_R(c) LV_CONCAT(LV_COLOR_GET_R, LV_COLOR_DEPTH)(c) +#define LV_COLOR_GET_G(c) LV_CONCAT(LV_COLOR_GET_G, LV_COLOR_DEPTH)(c) +#define LV_COLOR_GET_B(c) LV_CONCAT(LV_COLOR_GET_B, LV_COLOR_DEPTH)(c) +#define LV_COLOR_GET_A(c) LV_CONCAT(LV_COLOR_GET_A, LV_COLOR_DEPTH)(c) + +#define _LV_COLOR_ZERO_INITIALIZER LV_CONCAT(_LV_COLOR_ZERO_INITIALIZER, LV_COLOR_DEPTH) +#define LV_COLOR_MAKE(r8, g8, b8) LV_CONCAT(LV_COLOR_MAKE, LV_COLOR_DEPTH)(r8, g8, b8) + +/********************** + * TYPEDEFS + **********************/ + +typedef union { + uint8_t full; /*must be declared first to set all bits of byte via initializer list*/ + union { + uint8_t blue : 1; + uint8_t green : 1; + uint8_t red : 1; + } ch; +} lv_color1_t; + +typedef union { + struct { + uint8_t blue : 2; + uint8_t green : 3; + uint8_t red : 3; + } ch; + uint8_t full; +} lv_color8_t; + +typedef union { + struct { +#if LV_COLOR_16_SWAP == 0 + uint16_t blue : 5; + uint16_t green : 6; + uint16_t red : 5; +#else + uint16_t green_h : 3; + uint16_t red : 5; + uint16_t blue : 5; + uint16_t green_l : 3; +#endif + } ch; + uint16_t full; +} lv_color16_t; + +typedef union { + struct { + uint8_t blue; + uint8_t green; + uint8_t red; + uint8_t alpha; + } ch; + uint32_t full; +} lv_color32_t; + +typedef LV_CONCAT3(uint, LV_COLOR_SIZE, _t) lv_color_int_t; +typedef LV_CONCAT3(lv_color, LV_COLOR_DEPTH, _t) lv_color_t; + +typedef struct { + uint16_t h; + uint8_t s; + uint8_t v; +} lv_color_hsv_t; + +//! @cond Doxygen_Suppress +/*No idea where the guard is required but else throws warnings in the docs*/ +typedef uint8_t lv_opa_t; +//! @endcond + +struct _lv_color_filter_dsc_t; + +typedef lv_color_t (*lv_color_filter_cb_t)(const struct _lv_color_filter_dsc_t *, lv_color_t, lv_opa_t); + +typedef struct _lv_color_filter_dsc_t { + lv_color_filter_cb_t filter_cb; + void * user_data; +} lv_color_filter_dsc_t; + + +typedef enum { + LV_PALETTE_RED, + LV_PALETTE_PINK, + LV_PALETTE_PURPLE, + LV_PALETTE_DEEP_PURPLE, + LV_PALETTE_INDIGO, + LV_PALETTE_BLUE, + LV_PALETTE_LIGHT_BLUE, + LV_PALETTE_CYAN, + LV_PALETTE_TEAL, + LV_PALETTE_GREEN, + LV_PALETTE_LIGHT_GREEN, + LV_PALETTE_LIME, + LV_PALETTE_YELLOW, + LV_PALETTE_AMBER, + LV_PALETTE_ORANGE, + LV_PALETTE_DEEP_ORANGE, + LV_PALETTE_BROWN, + LV_PALETTE_BLUE_GREY, + LV_PALETTE_GREY, + _LV_PALETTE_LAST, + LV_PALETTE_NONE = 0xff, +} lv_palette_t; + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +/*In color conversations: + * - When converting to bigger color type the LSB weight of 1 LSB is calculated + * E.g. 16 bit Red has 5 bits + * 8 bit Red has 3 bits + * ---------------------- + * 8 bit red LSB = (2^5 - 1) / (2^3 - 1) = 31 / 7 = 4 + * + * - When calculating to smaller color type simply shift out the LSBs + * E.g. 8 bit Red has 3 bits + * 16 bit Red has 5 bits + * ---------------------- + * Shift right with 5 - 3 = 2 + */ +static inline uint8_t lv_color_to1(lv_color_t color) +{ +#if LV_COLOR_DEPTH == 1 + return color.full; +#elif LV_COLOR_DEPTH == 8 + if((LV_COLOR_GET_R(color) & 0x4) || (LV_COLOR_GET_G(color) & 0x4) || (LV_COLOR_GET_B(color) & 0x2)) { + return 1; + } + else { + return 0; + } +#elif LV_COLOR_DEPTH == 16 + if((LV_COLOR_GET_R(color) & 0x10) || (LV_COLOR_GET_G(color) & 0x20) || (LV_COLOR_GET_B(color) & 0x10)) { + return 1; + } + else { + return 0; + } +#elif LV_COLOR_DEPTH == 32 + if((LV_COLOR_GET_R(color) & 0x80) || (LV_COLOR_GET_G(color) & 0x80) || (LV_COLOR_GET_B(color) & 0x80)) { + return 1; + } + else { + return 0; + } +#endif +} + +static inline uint8_t lv_color_to8(lv_color_t color) +{ +#if LV_COLOR_DEPTH == 1 + if(color.full == 0) + return 0; + else + return 0xFF; +#elif LV_COLOR_DEPTH == 8 + return color.full; +#elif LV_COLOR_DEPTH == 16 + lv_color8_t ret; + LV_COLOR_SET_R8(ret, LV_COLOR_GET_R(color) >> 2); /*5 - 3 = 2*/ + LV_COLOR_SET_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; +#elif LV_COLOR_DEPTH == 32 + lv_color8_t ret; + LV_COLOR_SET_R8(ret, LV_COLOR_GET_R(color) >> 5); /*8 - 3 = 5*/ + LV_COLOR_SET_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; + else + 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*/ + LV_COLOR_SET_G16(ret, LV_COLOR_GET_G(color) * 9); /*(2^6 - 1)/(2^3 - 1) = 63/7 = 9*/ + LV_COLOR_SET_B16(ret, LV_COLOR_GET_B(color) * 10); /*(2^5 - 1)/(2^2 - 1) = 31/3 = 10*/ + return ret.full; +#elif LV_COLOR_DEPTH == 16 + return color.full; +#elif LV_COLOR_DEPTH == 32 + lv_color16_t ret; + LV_COLOR_SET_R16(ret, LV_COLOR_GET_R(color) >> 3); /*8 - 5 = 3*/ + LV_COLOR_SET_G16(ret, LV_COLOR_GET_G(color) >> 2); /*8 - 6 = 2*/ + LV_COLOR_SET_B16(ret, LV_COLOR_GET_B(color) >> 3); /*8 - 5 = 3*/ + return ret.full; +#endif +} + +static inline uint32_t lv_color_to32(lv_color_t color) +{ +#if LV_COLOR_DEPTH == 1 + if(color.full == 0) + return 0xFF000000; + else + return 0xFFFFFFFF; +#elif LV_COLOR_DEPTH == 8 + lv_color32_t ret; + LV_COLOR_SET_R32(ret, LV_COLOR_GET_R(color) * 36); /*(2^8 - 1)/(2^3 - 1) = 255/7 = 36*/ + LV_COLOR_SET_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(ret, 0xFF); + return ret.full; +#elif LV_COLOR_DEPTH == 16 + /** + * 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; + LV_COLOR_SET_R32(ret, (LV_COLOR_GET_R(color) * 263 + 7) >> 5); + LV_COLOR_SET_G32(ret, (LV_COLOR_GET_G(color) * 259 + 3) >> 6); + LV_COLOR_SET_B32(ret, (LV_COLOR_GET_B(color) * 263 + 7) >> 5); + LV_COLOR_SET_A32(ret, 0xFF); + return ret.full; +#elif LV_COLOR_DEPTH == 32 + return color.full; +#endif +} + +//! @cond Doxygen_Suppress + +/** + * Mix two colors with a given ratio. + * @param c1 the first color to mix (usually the foreground) + * @param c2 the second color to mix (usually the background) + * @param mix The ratio of the colors. 0: full `c2`, 255: full `c1`, 127: half `c1` and half`c2` + * @return the mixed color + */ +LV_ATTRIBUTE_FAST_MEM static inline lv_color_t lv_color_mix(lv_color_t c1, lv_color_t c2, uint8_t mix) +{ + lv_color_t ret; + +#if LV_COLOR_DEPTH == 16 && LV_COLOR_16_SWAP == 0 + /*Source: https://stackoverflow.com/a/50012418/1999969*/ + mix = (mix + 4) >> 3; + uint32_t bg = (uint32_t)((uint32_t)c2.full | ((uint32_t)c2.full << 16)) & + 0x7E0F81F; /*0b00000111111000001111100000011111*/ + uint32_t fg = (uint32_t)((uint32_t)c1.full | ((uint32_t)c1.full << 16)) & 0x7E0F81F; + uint32_t result = ((((fg - bg) * mix) >> 5) + bg) & 0x7E0F81F; + ret.full = (uint16_t)((result >> 16) | result); +#elif LV_COLOR_DEPTH != 1 + /*LV_COLOR_DEPTH == 8, 16 or 32*/ + LV_COLOR_SET_R(ret, LV_UDIV255((uint16_t)LV_COLOR_GET_R(c1) * mix + LV_COLOR_GET_R(c2) * + (255 - mix) + LV_COLOR_MIX_ROUND_OFS)); + LV_COLOR_SET_G(ret, LV_UDIV255((uint16_t)LV_COLOR_GET_G(c1) * mix + LV_COLOR_GET_G(c2) * + (255 - mix) + LV_COLOR_MIX_ROUND_OFS)); + LV_COLOR_SET_B(ret, LV_UDIV255((uint16_t)LV_COLOR_GET_B(c1) * mix + LV_COLOR_GET_B(c2) * + (255 - mix) + LV_COLOR_MIX_ROUND_OFS)); + LV_COLOR_SET_A(ret, 0xFF); +#else + /*LV_COLOR_DEPTH == 1*/ + ret.full = mix > LV_OPA_50 ? c1.full : c2.full; +#endif + + return ret; +} + +LV_ATTRIBUTE_FAST_MEM static inline void lv_color_premult(lv_color_t c, uint8_t mix, uint16_t * out) +{ +#if LV_COLOR_DEPTH != 1 + out[0] = (uint16_t)LV_COLOR_GET_R(c) * mix; + out[1] = (uint16_t)LV_COLOR_GET_G(c) * mix; + out[2] = (uint16_t)LV_COLOR_GET_B(c) * mix; +#else + (void) mix; + /*Pre-multiplication can't be used with 1 bpp*/ + out[0] = LV_COLOR_GET_R(c); + out[1] = LV_COLOR_GET_G(c); + out[2] = LV_COLOR_GET_B(c); +#endif + +} + +/** + * Mix two colors with a given ratio. It runs faster then `lv_color_mix` but requires some pre computation. + * @param premult_c1 The first color. Should be preprocessed with `lv_color_premult(c1)` + * @param c2 The second color. As it is no pre computation required on it + * @param mix The ratio of the colors. 0: full `c1`, 255: full `c2`, 127: half `c1` and half `c2`. + * Should be modified like mix = `255 - mix` + * @return the mixed color + * @note 255 won't give clearly `c1`. + */ +LV_ATTRIBUTE_FAST_MEM static inline lv_color_t lv_color_mix_premult(uint16_t * premult_c1, lv_color_t c2, uint8_t mix) +{ + lv_color_t ret; +#if LV_COLOR_DEPTH != 1 + /*LV_COLOR_DEPTH == 8 or 32*/ + LV_COLOR_SET_R(ret, LV_UDIV255(premult_c1[0] + LV_COLOR_GET_R(c2) * mix + LV_COLOR_MIX_ROUND_OFS)); + LV_COLOR_SET_G(ret, LV_UDIV255(premult_c1[1] + LV_COLOR_GET_G(c2) * mix + LV_COLOR_MIX_ROUND_OFS)); + LV_COLOR_SET_B(ret, LV_UDIV255(premult_c1[2] + LV_COLOR_GET_B(c2) * mix + LV_COLOR_MIX_ROUND_OFS)); + LV_COLOR_SET_A(ret, 0xFF); +#else + /*LV_COLOR_DEPTH == 1*/ + /*Restore color1*/ + lv_color_t c1; + LV_COLOR_SET_R(c1, premult_c1[0]); + LV_COLOR_SET_G(c1, premult_c1[1]); + LV_COLOR_SET_B(c1, premult_c1[2]); + ret.full = mix > LV_OPA_50 ? c2.full : c1.full; +#endif + + return ret; +} + +/** + * Mix two colors. Both color can have alpha value. + * @param bg_color background color + * @param bg_opa alpha of the background color + * @param fg_color foreground color + * @param fg_opa alpha of the foreground color + * @param res_color the result color + * @param res_opa the result opacity + */ +LV_ATTRIBUTE_FAST_MEM static inline void lv_color_mix_with_alpha(lv_color_t bg_color, lv_opa_t bg_opa, + lv_color_t fg_color, lv_opa_t fg_opa, + lv_color_t * res_color, lv_opa_t * res_opa) +{ + /*Pick the foreground if it's fully opaque or the Background is fully transparent*/ + if(fg_opa >= LV_OPA_MAX || bg_opa <= LV_OPA_MIN) { + res_color->full = fg_color.full; + *res_opa = fg_opa; + } + /*Transparent foreground: use the Background*/ + else if(fg_opa <= LV_OPA_MIN) { + res_color->full = bg_color.full; + *res_opa = bg_opa; + } + /*Opaque background: use simple mix*/ + else if(bg_opa >= LV_OPA_MAX) { + *res_color = lv_color_mix(fg_color, bg_color, fg_opa); + *res_opa = LV_OPA_COVER; + } + /*Both colors have alpha. Expensive calculation need to be applied*/ + else { + /*Save the parameters and the result. If they will be asked again don't compute again*/ + static lv_opa_t fg_opa_save = 0; + static lv_opa_t bg_opa_save = 0; + static lv_color_t fg_color_save = _LV_COLOR_ZERO_INITIALIZER; + static lv_color_t bg_color_save = _LV_COLOR_ZERO_INITIALIZER; + static lv_color_t res_color_saved = _LV_COLOR_ZERO_INITIALIZER; + static lv_opa_t res_opa_saved = 0; + + if(fg_opa != fg_opa_save || bg_opa != bg_opa_save || fg_color.full != fg_color_save.full || + bg_color.full != bg_color_save.full) { + fg_opa_save = fg_opa; + bg_opa_save = bg_opa; + fg_color_save.full = fg_color.full; + bg_color_save.full = bg_color.full; + /*Info: + * https://en.wikipedia.org/wiki/Alpha_compositing#Analytical_derivation_of_the_over_operator*/ + res_opa_saved = 255 - ((uint16_t)((uint16_t)(255 - fg_opa) * (255 - bg_opa)) >> 8); + LV_ASSERT(res_opa_saved != 0); + lv_opa_t ratio = (uint16_t)((uint16_t)fg_opa * 255) / res_opa_saved; + res_color_saved = lv_color_mix(fg_color, bg_color, ratio); + + } + + res_color->full = res_color_saved.full; + *res_opa = res_opa_saved; + } +} + +//! @endcond + +/** + * Get the brightness of a color + * @param color a color + * @return the brightness [0..255] + */ +static inline uint8_t lv_color_brightness(lv_color_t color) +{ + lv_color32_t c32; + c32.full = lv_color_to32(color); + 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); +} + +static inline lv_color_t lv_color_make(uint8_t r, uint8_t g, uint8_t b) +{ + return _LV_COLOR_MAKE_TYPE_HELPER LV_COLOR_MAKE(r, g, b); +} + +static inline lv_color_t lv_color_hex(uint32_t c) +{ +#if LV_COLOR_DEPTH == 16 + lv_color_t r; +#if LV_COLOR_16_SWAP == 0 + /* Convert a 4 bytes per pixel in format ARGB32 to R5G6B5 format + naive way (by calling lv_color_make with components): + r = ((c & 0xFF0000) >> 19) + g = ((c & 0xFF00) >> 10) + b = ((c & 0xFF) >> 3) + rgb565 = (r << 11) | (g << 5) | b + That's 3 mask, 5 bitshift and 2 or operations + + A bit better: + r = ((c & 0xF80000) >> 8) + g = ((c & 0xFC00) >> 5) + b = ((c & 0xFF) >> 3) + rgb565 = r | g | b + That's 3 mask, 3 bitshifts and 2 or operations */ + r.full = (uint16_t)(((c & 0xF80000) >> 8) | ((c & 0xFC00) >> 5) | ((c & 0xFF) >> 3)); +#else + /* We want: rrrr rrrr GGGg gggg bbbb bbbb => gggb bbbb rrrr rGGG */ + r.full = (uint16_t)(((c & 0xF80000) >> 16) | ((c & 0xFC00) >> 13) | ((c & 0x1C00) << 3) | ((c & 0xF8) << 5)); +#endif + return r; +#elif LV_COLOR_DEPTH == 32 + lv_color_t r; + r.full = c | 0xFF000000; + return r; +#else /*LV_COLOR_DEPTH == 8*/ + return lv_color_make((uint8_t)((c >> 16) & 0xFF), (uint8_t)((c >> 8) & 0xFF), (uint8_t)(c & 0xFF)); +#endif +} + +static inline lv_color_t lv_color_hex3(uint32_t c) +{ + return lv_color_make((uint8_t)(((c >> 4) & 0xF0) | ((c >> 8) & 0xF)), (uint8_t)((c & 0xF0) | ((c & 0xF0) >> 4)), + (uint8_t)((c & 0xF) | ((c & 0xF) << 4))); +} + +static inline void lv_color_filter_dsc_init(lv_color_filter_dsc_t * dsc, lv_color_filter_cb_t cb) +{ + dsc->filter_cb = cb; +} + +//! @cond Doxygen_Suppress +//! +LV_ATTRIBUTE_FAST_MEM void lv_color_fill(lv_color_t * buf, lv_color_t color, uint32_t px_num); + +//! @endcond +lv_color_t lv_color_lighten(lv_color_t c, lv_opa_t lvl); + +lv_color_t lv_color_darken(lv_color_t c, lv_opa_t lvl); + +lv_color_t lv_color_change_lightness(lv_color_t c, lv_opa_t lvl); + +/** + * Convert a HSV color to RGB + * @param h hue [0..359] + * @param s saturation [0..100] + * @param v value [0..100] + * @return the given RGB color in RGB (with LV_COLOR_DEPTH depth) + */ +lv_color_t lv_color_hsv_to_rgb(uint16_t h, uint8_t s, uint8_t v); + +/** + * 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 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); + +/** + * Just a wrapper around LV_COLOR_CHROMA_KEY because it might be more convenient to use a function is some cases + * @return LV_COLOR_CHROMA_KEY + */ +static inline lv_color_t lv_color_chroma_key(void) +{ + return LV_COLOR_CHROMA_KEY; +} + +/********************** + * PREDEFINED COLORS + **********************/ +/*Source: https://vuetifyjs.com/en/styles/colors/#material-colors*/ + +lv_color_t lv_palette_main(lv_palette_t p); +static inline lv_color_t lv_color_white(void) +{ + return lv_color_make(0xff, 0xff, 0xff); +} +static inline lv_color_t lv_color_black(void) +{ + return lv_color_make(0x00, 0x0, 0x00); +} +lv_color_t lv_palette_lighten(lv_palette_t p, uint8_t lvl); +lv_color_t lv_palette_darken(lv_palette_t p, uint8_t lvl); + +/********************** + * MACROS + **********************/ + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif /*LV_COLOR_H*/ diff --git a/src/lib/lvgl/src/misc/lv_fs.h b/src/lib/lvgl/src/misc/lv_fs.h new file mode 100644 index 0000000..0a9b241 --- /dev/null +++ b/src/lib/lvgl/src/misc/lv_fs.h @@ -0,0 +1,262 @@ +/** + * @file lv_fs.h + * + */ + +#ifndef LV_FS_H +#define LV_FS_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include "../lv_conf_internal.h" + +#include +#include + +/********************* + * DEFINES + *********************/ +#define LV_FS_MAX_FN_LENGTH 64 +#define LV_FS_MAX_PATH_LENGTH 256 + +/********************** + * TYPEDEFS + **********************/ + +/** + * Errors in the file system module. + */ +enum { + LV_FS_RES_OK = 0, + LV_FS_RES_HW_ERR, /*Low level hardware error*/ + LV_FS_RES_FS_ERR, /*Error in the file system structure*/ + LV_FS_RES_NOT_EX, /*Driver, file or directory is not exists*/ + LV_FS_RES_FULL, /*Disk full*/ + LV_FS_RES_LOCKED, /*The file is already opened*/ + LV_FS_RES_DENIED, /*Access denied. Check 'fs_open' modes and write protect*/ + LV_FS_RES_BUSY, /*The file system now can't handle it, try later*/ + LV_FS_RES_TOUT, /*Process time outed*/ + LV_FS_RES_NOT_IMP, /*Requested function is not implemented*/ + LV_FS_RES_OUT_OF_MEM, /*Not enough memory for an internal operation*/ + LV_FS_RES_INV_PARAM, /*Invalid parameter among arguments*/ + LV_FS_RES_UNKNOWN, /*Other unknown error*/ +}; +typedef uint8_t lv_fs_res_t; + +/** + * File open mode. + */ +enum { + LV_FS_MODE_WR = 0x01, + LV_FS_MODE_RD = 0x02, +}; +typedef uint8_t lv_fs_mode_t; + + +/** + * Seek modes. + */ +typedef enum { + LV_FS_SEEK_SET = 0x00, /**< Set the position from absolutely (from the start of file)*/ + LV_FS_SEEK_CUR = 0x01, /**< Set the position from the current position*/ + LV_FS_SEEK_END = 0x02, /**< Set the position from the end of the file*/ +} lv_fs_whence_t; + +typedef struct _lv_fs_drv_t { + char letter; + uint16_t cache_size; + bool (*ready_cb)(struct _lv_fs_drv_t * drv); + + void * (*open_cb)(struct _lv_fs_drv_t * drv, const char * path, lv_fs_mode_t mode); + lv_fs_res_t (*close_cb)(struct _lv_fs_drv_t * drv, void * file_p); + lv_fs_res_t (*read_cb)(struct _lv_fs_drv_t * drv, void * file_p, void * buf, uint32_t btr, uint32_t * br); + lv_fs_res_t (*write_cb)(struct _lv_fs_drv_t * drv, void * file_p, const void * buf, uint32_t btw, uint32_t * bw); + lv_fs_res_t (*seek_cb)(struct _lv_fs_drv_t * drv, void * file_p, uint32_t pos, lv_fs_whence_t whence); + lv_fs_res_t (*tell_cb)(struct _lv_fs_drv_t * drv, void * file_p, uint32_t * pos_p); + + void * (*dir_open_cb)(struct _lv_fs_drv_t * drv, const char * path); + lv_fs_res_t (*dir_read_cb)(struct _lv_fs_drv_t * drv, void * rddir_p, char * fn); + lv_fs_res_t (*dir_close_cb)(struct _lv_fs_drv_t * drv, void * rddir_p); + +#if LV_USE_USER_DATA + void * user_data; /**< Custom file user data*/ +#endif +} lv_fs_drv_t; + +typedef struct { + uint32_t start; + uint32_t end; + uint32_t file_position; + void * buffer; +} lv_fs_file_cache_t; + +typedef struct { + void * file_d; + lv_fs_drv_t * drv; + lv_fs_file_cache_t * cache; +} lv_fs_file_t; + +typedef struct { + void * dir_d; + lv_fs_drv_t * drv; +} lv_fs_dir_t; + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +/** + * Initialize the File system interface + */ +void _lv_fs_init(void); + +/** + * Initialize a file system driver with default values. + * It is used to surly have known values in the fields ant not memory junk. + * After it you can set the fields. + * @param drv pointer to driver variable to initialize + */ +void lv_fs_drv_init(lv_fs_drv_t * drv); + +/** + * Add a new drive + * @param drv pointer to an lv_fs_drv_t structure which is inited with the + * corresponding function pointers. Only pointer is saved, so the + * driver should be static or dynamically allocated. + */ +void lv_fs_drv_register(lv_fs_drv_t * drv); + +/** + * Give a pointer to a driver from its letter + * @param letter the driver letter + * @return pointer to a driver or NULL if not found + */ +lv_fs_drv_t * lv_fs_get_drv(char letter); + +/** + * Test if a drive is ready or not. If the `ready` function was not initialized `true` will be + * returned. + * @param letter letter of the drive + * @return true: drive is ready; false: drive is not ready + */ +bool lv_fs_is_ready(char letter); + +/** + * Open a file + * @param file_p pointer to a lv_fs_file_t variable + * @param path path to the file beginning with the driver letter (e.g. S:/folder/file.txt) + * @param mode read: FS_MODE_RD, write: FS_MODE_WR, both: FS_MODE_RD | FS_MODE_WR + * @return LV_FS_RES_OK or any error from lv_fs_res_t enum + */ +lv_fs_res_t lv_fs_open(lv_fs_file_t * file_p, const char * path, lv_fs_mode_t mode); + +/** + * Close an already opened file + * @param file_p pointer to a lv_fs_file_t variable + * @return LV_FS_RES_OK or any error from lv_fs_res_t enum + */ +lv_fs_res_t lv_fs_close(lv_fs_file_t * file_p); + +/** + * Read from a file + * @param file_p pointer to a lv_fs_file_t variable + * @param buf pointer to a buffer where the read bytes are stored + * @param btr Bytes To Read + * @param br the number of real read bytes (Bytes Read). NULL if unused. + * @return LV_FS_RES_OK or any error from lv_fs_res_t enum + */ +lv_fs_res_t lv_fs_read(lv_fs_file_t * file_p, void * buf, uint32_t btr, uint32_t * br); + +/** + * Write into a file + * @param file_p pointer to a lv_fs_file_t variable + * @param buf pointer to a buffer with the bytes to write + * @param btr Bytes To Write + * @param br the number of real written bytes (Bytes Written). NULL if unused. + * @return LV_FS_RES_OK or any error from lv_fs_res_t enum + */ +lv_fs_res_t lv_fs_write(lv_fs_file_t * file_p, const void * buf, uint32_t btw, uint32_t * bw); + +/** + * Set the position of the 'cursor' (read write pointer) in a file + * @param file_p pointer to a lv_fs_file_t variable + * @param pos the new position expressed in bytes index (0: start of file) + * @param whence tells from where set the position. See @lv_fs_whence_t + * @return LV_FS_RES_OK or any error from lv_fs_res_t enum + */ +lv_fs_res_t lv_fs_seek(lv_fs_file_t * file_p, uint32_t pos, lv_fs_whence_t whence); + +/** + * Give the position of the read write pointer + * @param file_p pointer to a lv_fs_file_t variable + * @param pos_p pointer to store the position of the read write pointer + * @return LV_FS_RES_OK or any error from 'fs_res_t' + */ +lv_fs_res_t lv_fs_tell(lv_fs_file_t * file_p, uint32_t * pos); + +/** + * Initialize a 'fs_dir_t' variable for directory reading + * @param rddir_p pointer to a 'lv_fs_dir_t' variable + * @param path path to a directory + * @return LV_FS_RES_OK or any error from lv_fs_res_t enum + */ +lv_fs_res_t lv_fs_dir_open(lv_fs_dir_t * rddir_p, const char * path); + +/** + * Read the next filename form a directory. + * The name of the directories will begin with '/' + * @param rddir_p pointer to an initialized 'fs_dir_t' variable + * @param fn pointer to a buffer to store the filename + * @return LV_FS_RES_OK or any error from lv_fs_res_t enum + */ +lv_fs_res_t lv_fs_dir_read(lv_fs_dir_t * rddir_p, char * fn); + +/** + * Close the directory reading + * @param rddir_p pointer to an initialized 'fs_dir_t' variable + * @return LV_FS_RES_OK or any error from lv_fs_res_t enum + */ +lv_fs_res_t lv_fs_dir_close(lv_fs_dir_t * rddir_p); + +/** + * Fill a buffer with the letters of existing drivers + * @param buf buffer to store the letters ('\0' added after the last letter) + * @return the buffer + */ +char * lv_fs_get_letters(char * buf); + +/** + * Return with the extension of the filename + * @param fn string with a filename + * @return pointer to the beginning extension or empty string if no extension + */ +const char * lv_fs_get_ext(const char * fn); + +/** + * Step up one level + * @param path pointer to a file name + * @return the truncated file name + */ +char * lv_fs_up(char * path); + +/** + * Get the last element of a path (e.g. U:/folder/file -> file) + * @param path pointer to a file name + * @return pointer to the beginning of the last element in the path + */ +const char * lv_fs_get_last(const char * path); + +/********************** + * MACROS + **********************/ + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif /*LV_FS_H*/ diff --git a/src/lib/lvgl/src/misc/lv_gc.h b/src/lib/lvgl/src/misc/lv_gc.h new file mode 100644 index 0000000..7551252 --- /dev/null +++ b/src/lib/lvgl/src/misc/lv_gc.h @@ -0,0 +1,96 @@ +/** + * @file lv_gc.h + * + */ + +#ifndef LV_GC_H +#define LV_GC_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include "../lv_conf_internal.h" +#include +#include "lv_mem.h" +#include "lv_ll.h" +#include "lv_timer.h" +#include "lv_types.h" +#include "../draw/lv_img_cache.h" +#include "../draw/lv_draw_mask.h" +#include "../core/lv_obj_pos.h" + +/********************* + * DEFINES + *********************/ +#if LV_IMG_CACHE_DEF_SIZE +# define LV_IMG_CACHE_DEF 1 +#else +# define LV_IMG_CACHE_DEF 0 +#endif + +#define LV_DISPATCH(f, t, n) f(t, n) +#define LV_DISPATCH_COND(f, t, n, m, v) LV_CONCAT3(LV_DISPATCH, m, v)(f, t, n) + +#define LV_DISPATCH00(f, t, n) LV_DISPATCH(f, t, n) +#define LV_DISPATCH01(f, t, n) +#define LV_DISPATCH10(f, t, n) +#define LV_DISPATCH11(f, t, n) LV_DISPATCH(f, t, n) + +#define LV_ITERATE_ROOTS(f) \ + LV_DISPATCH(f, lv_ll_t, _lv_timer_ll) /*Linked list to store the lv_timers*/ \ + LV_DISPATCH(f, lv_ll_t, _lv_disp_ll) /*Linked list of display device*/ \ + LV_DISPATCH(f, lv_ll_t, _lv_indev_ll) /*Linked list of input device*/ \ + LV_DISPATCH(f, lv_ll_t, _lv_fsdrv_ll) \ + LV_DISPATCH(f, lv_ll_t, _lv_anim_ll) \ + LV_DISPATCH(f, lv_ll_t, _lv_group_ll) \ + LV_DISPATCH(f, lv_ll_t, _lv_img_decoder_ll) \ + LV_DISPATCH(f, lv_ll_t, _lv_obj_style_trans_ll) \ + LV_DISPATCH(f, lv_layout_dsc_t *, _lv_layout_list) \ + LV_DISPATCH_COND(f, _lv_img_cache_entry_t*, _lv_img_cache_array, LV_IMG_CACHE_DEF, 1) \ + LV_DISPATCH_COND(f, _lv_img_cache_entry_t, _lv_img_cache_single, LV_IMG_CACHE_DEF, 0) \ + LV_DISPATCH(f, lv_timer_t*, _lv_timer_act) \ + LV_DISPATCH(f, lv_mem_buf_arr_t , lv_mem_buf) \ + LV_DISPATCH_COND(f, _lv_draw_mask_radius_circle_dsc_arr_t , _lv_circle_cache, LV_DRAW_COMPLEX, 1) \ + LV_DISPATCH_COND(f, _lv_draw_mask_saved_arr_t , _lv_draw_mask_list, LV_DRAW_COMPLEX, 1) \ + LV_DISPATCH(f, void * , _lv_theme_default_styles) \ + LV_DISPATCH(f, void * , _lv_theme_basic_styles) \ + LV_DISPATCH_COND(f, uint8_t *, _lv_font_decompr_buf, LV_USE_FONT_COMPRESSED, 1) \ + LV_DISPATCH(f, uint8_t * , _lv_grad_cache_mem) + +#define LV_DEFINE_ROOT(root_type, root_name) root_type root_name; +#define LV_ROOTS LV_ITERATE_ROOTS(LV_DEFINE_ROOT) + +#if LV_ENABLE_GC == 1 +#if LV_MEM_CUSTOM != 1 +#error "GC requires CUSTOM_MEM" +#endif /*LV_MEM_CUSTOM*/ +#include LV_GC_INCLUDE +#else /*LV_ENABLE_GC*/ +#define LV_GC_ROOT(x) x +#define LV_EXTERN_ROOT(root_type, root_name) extern root_type root_name; +LV_ITERATE_ROOTS(LV_EXTERN_ROOT) +#endif /*LV_ENABLE_GC*/ + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +void _lv_gc_clear_roots(void); + +/********************** + * MACROS + **********************/ + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif /*LV_GC_H*/ diff --git a/src/lib/lvgl/src/misc/lv_ll.h b/src/lib/lvgl/src/misc/lv_ll.h new file mode 100644 index 0000000..d38f692 --- /dev/null +++ b/src/lib/lvgl/src/misc/lv_ll.h @@ -0,0 +1,167 @@ +/** + * @file lv_ll.h + * Handle linked lists. The nodes are dynamically allocated by the 'lv_mem' module. + */ + +#ifndef LV_LL_H +#define LV_LL_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include +#include +#include + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +/** Dummy type to make handling easier*/ +typedef uint8_t lv_ll_node_t; + +/** Description of a linked list*/ +typedef struct { + uint32_t n_size; + lv_ll_node_t * head; + lv_ll_node_t * tail; +} lv_ll_t; + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +/** + * Initialize linked list + * @param ll_p pointer to lv_ll_t variable + * @param node_size the size of 1 node in bytes + */ +void _lv_ll_init(lv_ll_t * ll_p, uint32_t node_size); + +/** + * Add a new head to a linked list + * @param ll_p pointer to linked list + * @return pointer to the new head + */ +void * _lv_ll_ins_head(lv_ll_t * ll_p); + +/** + * Insert a new node in front of the n_act node + * @param ll_p pointer to linked list + * @param n_act pointer a node + * @return pointer to the new node + */ +void * _lv_ll_ins_prev(lv_ll_t * ll_p, void * n_act); + +/** + * Add a new tail to a linked list + * @param ll_p pointer to linked list + * @return pointer to the new tail + */ +void * _lv_ll_ins_tail(lv_ll_t * ll_p); + +/** + * Remove the node 'node_p' from 'll_p' linked list. + * It does not free the memory of node. + * @param ll_p pointer to the linked list of 'node_p' + * @param node_p pointer to node in 'll_p' linked list + */ +void _lv_ll_remove(lv_ll_t * ll_p, void * node_p); + +/** + * Remove and free all elements from a linked list. The list remain valid but become empty. + * @param ll_p pointer to linked list + */ +void _lv_ll_clear(lv_ll_t * ll_p); + +/** + * Move a node to a new linked list + * @param ll_ori_p pointer to the original (old) linked list + * @param ll_new_p pointer to the new linked list + * @param node pointer to a node + * @param head true: be the head in the new list + * false be the tail in the new list + */ +void _lv_ll_chg_list(lv_ll_t * ll_ori_p, lv_ll_t * ll_new_p, void * node, bool head); + +/** + * Return with head node of the linked list + * @param ll_p pointer to linked list + * @return pointer to the head of 'll_p' + */ +void * _lv_ll_get_head(const lv_ll_t * ll_p); + +/** + * Return with tail node of the linked list + * @param ll_p pointer to linked list + * @return pointer to the tail of 'll_p' + */ +void * _lv_ll_get_tail(const lv_ll_t * ll_p); + +/** + * Return with the pointer of the next node after 'n_act' + * @param ll_p pointer to linked list + * @param n_act pointer a node + * @return pointer to the next node + */ +void * _lv_ll_get_next(const lv_ll_t * ll_p, const void * n_act); + +/** + * Return with the pointer of the previous node after 'n_act' + * @param ll_p pointer to linked list + * @param n_act pointer a node + * @return pointer to the previous node + */ +void * _lv_ll_get_prev(const lv_ll_t * ll_p, const void * n_act); + +/** + * Return the length of the linked list. + * @param ll_p pointer to linked list + * @return length of the linked list + */ +uint32_t _lv_ll_get_len(const lv_ll_t * ll_p); + +/** + * TODO + * @param ll_p + * @param n1_p + * @param n2_p +void lv_ll_swap(lv_ll_t * ll_p, void * n1_p, void * n2_p); + */ + +/** + * Move a node before an other node in the same linked list + * @param ll_p pointer to a linked list + * @param n_act pointer to node to move + * @param n_after pointer to a node which should be after `n_act` + */ +void _lv_ll_move_before(lv_ll_t * ll_p, void * n_act, void * n_after); + +/** + * Check if a linked list is empty + * @param ll_p pointer to a linked list + * @return true: the linked list is empty; false: not empty + */ +bool _lv_ll_is_empty(lv_ll_t * ll_p); + +/********************** + * MACROS + **********************/ + +#define _LV_LL_READ(list, i) for(i = _lv_ll_get_head(list); i != NULL; i = _lv_ll_get_next(list, i)) + +#define _LV_LL_READ_BACK(list, i) for(i = _lv_ll_get_tail(list); i != NULL; i = _lv_ll_get_prev(list, i)) + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif diff --git a/src/lib/lvgl/src/misc/lv_log.h b/src/lib/lvgl/src/misc/lv_log.h new file mode 100644 index 0000000..fa6f5ac --- /dev/null +++ b/src/lib/lvgl/src/misc/lv_log.h @@ -0,0 +1,143 @@ +/** + * @file lv_log.h + * + */ + +#ifndef LV_LOG_H +#define LV_LOG_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include "../lv_conf_internal.h" +#include + +#include "lv_types.h" + +/********************* + * DEFINES + *********************/ + +/*Possible log level. For compatibility declare it independently from `LV_USE_LOG`*/ + +#define LV_LOG_LEVEL_TRACE 0 /**< A lot of logs to give detailed information*/ +#define LV_LOG_LEVEL_INFO 1 /**< Log important events*/ +#define LV_LOG_LEVEL_WARN 2 /**< Log if something unwanted happened but didn't caused problem*/ +#define LV_LOG_LEVEL_ERROR 3 /**< Only critical issue, when the system may fail*/ +#define LV_LOG_LEVEL_USER 4 /**< Custom logs from the user*/ +#define LV_LOG_LEVEL_NONE 5 /**< Do not log anything*/ +#define _LV_LOG_LEVEL_NUM 6 /**< Number of log levels*/ + +LV_EXPORT_CONST_INT(LV_LOG_LEVEL_TRACE); +LV_EXPORT_CONST_INT(LV_LOG_LEVEL_INFO); +LV_EXPORT_CONST_INT(LV_LOG_LEVEL_WARN); +LV_EXPORT_CONST_INT(LV_LOG_LEVEL_ERROR); +LV_EXPORT_CONST_INT(LV_LOG_LEVEL_USER); +LV_EXPORT_CONST_INT(LV_LOG_LEVEL_NONE); + +typedef int8_t lv_log_level_t; + +#if LV_USE_LOG +/********************** + * TYPEDEFS + **********************/ + +/** + * Log print function. Receives a string buffer to print". + */ +typedef void (*lv_log_print_g_cb_t)(const char * buf); + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +/** + * Register custom print/write function to call when a log is added. + * It can format its "File path", "Line number" and "Description" as required + * and send the formatted log message to a console or serial port. + * @param print_cb a function pointer to print a log + */ +void lv_log_register_print_cb(lv_log_print_g_cb_t print_cb); + +/** + * Print a log message via `printf` if enabled with `LV_LOG_PRINTF` in `lv_conf.h` + * and/or a print callback if registered with `lv_log_register_print_cb` + * @param buf a string message to print + */ +void lv_log(const char * buf); + +/** + * Add a log + * @param level the level of log. (From `lv_log_level_t` enum) + * @param file name of the file when the log added + * @param line line number in the source code where the log added + * @param func name of the function when the log added + * @param format printf-like format string + * @param ... parameters for `format` + */ +void _lv_log_add(lv_log_level_t level, const char * file, int line, + const char * func, const char * format, ...) LV_FORMAT_ATTRIBUTE(5, 6); + +/********************** + * MACROS + **********************/ +#ifndef LV_LOG_TRACE +# if LV_LOG_LEVEL <= LV_LOG_LEVEL_TRACE +# define LV_LOG_TRACE(...) _lv_log_add(LV_LOG_LEVEL_TRACE, __FILE__, __LINE__, __func__, __VA_ARGS__) +# else +# define LV_LOG_TRACE(...) do {}while(0) +# endif +#endif + +#ifndef LV_LOG_INFO +# if LV_LOG_LEVEL <= LV_LOG_LEVEL_INFO +# define LV_LOG_INFO(...) _lv_log_add(LV_LOG_LEVEL_INFO, __FILE__, __LINE__, __func__, __VA_ARGS__) +# else +# define LV_LOG_INFO(...) do {}while(0) +# endif +#endif + +#ifndef LV_LOG_WARN +# if LV_LOG_LEVEL <= LV_LOG_LEVEL_WARN +# define LV_LOG_WARN(...) _lv_log_add(LV_LOG_LEVEL_WARN, __FILE__, __LINE__, __func__, __VA_ARGS__) +# else +# define LV_LOG_WARN(...) do {}while(0) +# endif +#endif + +#ifndef LV_LOG_ERROR +# if LV_LOG_LEVEL <= LV_LOG_LEVEL_ERROR +# define LV_LOG_ERROR(...) _lv_log_add(LV_LOG_LEVEL_ERROR, __FILE__, __LINE__, __func__, __VA_ARGS__) +# else +# define LV_LOG_ERROR(...) do {}while(0) +# endif +#endif + +#ifndef LV_LOG_USER +# if LV_LOG_LEVEL <= LV_LOG_LEVEL_USER +# define LV_LOG_USER(...) _lv_log_add(LV_LOG_LEVEL_USER, __FILE__, __LINE__, __func__, __VA_ARGS__) +# else +# define LV_LOG_USER(...) do {}while(0) +# endif +#endif + +#else /*LV_USE_LOG*/ + +/*Do nothing if `LV_USE_LOG 0`*/ +#define _lv_log_add(level, file, line, ...) +#define LV_LOG_TRACE(...) do {}while(0) +#define LV_LOG_INFO(...) do {}while(0) +#define LV_LOG_WARN(...) do {}while(0) +#define LV_LOG_ERROR(...) do {}while(0) +#define LV_LOG_USER(...) do {}while(0) +#endif /*LV_USE_LOG*/ + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif /*LV_LOG_H*/ diff --git a/src/lib/lvgl/src/misc/lv_lru.h b/src/lib/lvgl/src/misc/lv_lru.h new file mode 100644 index 0000000..07d3bd3 --- /dev/null +++ b/src/lib/lvgl/src/misc/lv_lru.h @@ -0,0 +1,81 @@ +/** + * @file lv_lru.h + * + */ + +#ifndef LV_LRU_H +#define LV_LRU_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ + +#include "../lv_conf_internal.h" + +#include "lv_types.h" + +#include +#include + + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +typedef enum { + LV_LRU_OK = 0, + LV_LRU_MISSING_CACHE, + LV_LRU_MISSING_KEY, + LV_LRU_MISSING_VALUE, + LV_LRU_LOCK_ERROR, + LV_LRU_VALUE_TOO_LARGE +} lv_lru_res_t; + +typedef void (lv_lru_free_t)(void * v); +typedef struct _lv_lru_item_t lv_lru_item_t; + +typedef struct lv_lru_t { + lv_lru_item_t ** items; + uint64_t access_count; + size_t free_memory; + size_t total_memory; + size_t average_item_length; + size_t hash_table_size; + uint32_t seed; + lv_lru_free_t * value_free; + lv_lru_free_t * key_free; + lv_lru_item_t * free_items; +} lv_lru_t; + + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +lv_lru_t * lv_lru_create(size_t cache_size, size_t average_length, lv_lru_free_t * value_free, + lv_lru_free_t * key_free); + +void lv_lru_del(lv_lru_t * cache); + +lv_lru_res_t lv_lru_set(lv_lru_t * cache, const void * key, size_t key_length, void * value, size_t value_length); + +lv_lru_res_t lv_lru_get(lv_lru_t * cache, const void * key, size_t key_size, void ** value); + +lv_lru_res_t lv_lru_remove(lv_lru_t * cache, const void * key, size_t key_size); + +/********************** + * MACROS + **********************/ +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif /*LV_LRU_H*/ diff --git a/src/lib/lvgl/src/misc/lv_math.h b/src/lib/lvgl/src/misc/lv_math.h new file mode 100644 index 0000000..4b2860a --- /dev/null +++ b/src/lib/lvgl/src/misc/lv_math.h @@ -0,0 +1,143 @@ +/** + * @file lv_math.h + * + */ + +#ifndef LV_MATH_H +#define LV_MATH_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include "../lv_conf_internal.h" +#include + +/********************* + * DEFINES + *********************/ +#define LV_TRIGO_SIN_MAX 32767 +#define LV_TRIGO_SHIFT 15 /**< >> LV_TRIGO_SHIFT to normalize*/ + +#define LV_BEZIER_VAL_MAX 1024 /**< Max time in Bezier functions (not [0..1] to use integers)*/ +#define LV_BEZIER_VAL_SHIFT 10 /**< log2(LV_BEZIER_VAL_MAX): used to normalize up scaled values*/ + +/********************** + * TYPEDEFS + **********************/ + +typedef struct { + uint16_t i; + uint16_t f; +} lv_sqrt_res_t; + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +//! @cond Doxygen_Suppress +/** + * Return with sinus of an angle + * @param angle + * @return sinus of 'angle'. sin(-90) = -32767, sin(90) = 32767 + */ +LV_ATTRIBUTE_FAST_MEM int16_t lv_trigo_sin(int16_t angle); + +static inline LV_ATTRIBUTE_FAST_MEM int16_t lv_trigo_cos(int16_t angle) +{ + return lv_trigo_sin(angle + 90); +} + +//! @endcond + +/** + * Calculate a value of a Cubic Bezier function. + * @param t time in range of [0..LV_BEZIER_VAL_MAX] + * @param u0 start values in range of [0..LV_BEZIER_VAL_MAX] + * @param u1 control value 1 values in range of [0..LV_BEZIER_VAL_MAX] + * @param u2 control value 2 in range of [0..LV_BEZIER_VAL_MAX] + * @param u3 end values in range of [0..LV_BEZIER_VAL_MAX] + * @return the value calculated from the given parameters in range of [0..LV_BEZIER_VAL_MAX] + */ +uint32_t lv_bezier3(uint32_t t, uint32_t u0, uint32_t u1, uint32_t u2, uint32_t u3); + +/** + * Calculate the atan2 of a vector. + * @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); + +//! @cond Doxygen_Suppress + +/** + * Get the square root of a number + * @param x integer which square root should be calculated + * @param q store the result here. q->i: integer part, q->f: fractional part in 1/256 unit + * @param mask optional to skip some iterations if the magnitude of the root is known. + * Set to 0x8000 by default. + * If root < 16: mask = 0x80 + * If root < 256: mask = 0x800 + * Else: mask = 0x8000 + */ +LV_ATTRIBUTE_FAST_MEM void lv_sqrt(uint32_t x, lv_sqrt_res_t * q, uint32_t mask); + +//! @endcond + +/** + * Calculate the integer exponents. + * @param base + * @param power + * @return base raised to the power exponent + */ +int64_t lv_pow(int64_t base, int8_t exp); + +/** + * Get the mapped of a number given an input and output range + * @param x integer which mapped value should be calculated + * @param min_in min input range + * @param max_in max input range + * @param min_out max output range + * @param max_out max output range + * @return the mapped number + */ +int32_t lv_map(int32_t x, int32_t min_in, int32_t max_in, int32_t min_out, int32_t max_out); + +/** + * Get a pseudo random number in the given range + * @param min the minimum value + * @param max the maximum value + * @return return the random number. min <= return_value <= max + */ +uint32_t lv_rand(uint32_t min, uint32_t max); + +/********************** + * MACROS + **********************/ +#define LV_MIN(a, b) ((a) < (b) ? (a) : (b)) +#define LV_MIN3(a, b, c) (LV_MIN(LV_MIN(a,b), c)) +#define LV_MIN4(a, b, c, d) (LV_MIN(LV_MIN(a,b), LV_MIN(c,d))) + +#define LV_MAX(a, b) ((a) > (b) ? (a) : (b)) +#define LV_MAX3(a, b, c) (LV_MAX(LV_MAX(a,b), c)) +#define LV_MAX4(a, b, c, d) (LV_MAX(LV_MAX(a,b), LV_MAX(c,d))) + +#define LV_CLAMP(min, val, max) (LV_MAX(min, (LV_MIN(val, max)))) + +#define LV_ABS(x) ((x) > 0 ? (x) : (-(x))) +#define LV_UDIV255(x) (((x) * 0x8081U) >> 0x17) + +#define LV_IS_SIGNED(t) (((t)(-1)) < ((t)0)) +#define LV_UMAX_OF(t) (((0x1ULL << ((sizeof(t) * 8ULL) - 1ULL)) - 1ULL) | (0xFULL << ((sizeof(t) * 8ULL) - 4ULL))) +#define LV_SMAX_OF(t) (((0x1ULL << ((sizeof(t) * 8ULL) - 1ULL)) - 1ULL) | (0x7ULL << ((sizeof(t) * 8ULL) - 4ULL))) +#define LV_MAX_OF(t) ((unsigned long)(LV_IS_SIGNED(t) ? LV_SMAX_OF(t) : LV_UMAX_OF(t))) + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif diff --git a/src/lib/lvgl/src/misc/lv_mem.h b/src/lib/lvgl/src/misc/lv_mem.h new file mode 100644 index 0000000..7a83b3d --- /dev/null +++ b/src/lib/lvgl/src/misc/lv_mem.h @@ -0,0 +1,243 @@ +/** + * @file lv_mem.h + * + */ + +#ifndef LV_MEM_H +#define LV_MEM_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include "../lv_conf_internal.h" + +#include +#include +#include + +#include "lv_types.h" + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +/** + * Heap information structure. + */ +typedef struct { + uint32_t total_size; /**< Total heap size*/ + uint32_t free_cnt; + uint32_t free_size; /**< Size of available memory*/ + uint32_t free_biggest_size; + uint32_t used_cnt; + uint32_t max_used; /**< Max size of Heap memory used*/ + uint8_t used_pct; /**< Percentage used*/ + uint8_t frag_pct; /**< Amount of fragmentation*/ +} lv_mem_monitor_t; + +typedef struct { + void * p; + uint16_t size; + uint8_t used : 1; +} lv_mem_buf_t; + +typedef lv_mem_buf_t lv_mem_buf_arr_t[LV_MEM_BUF_MAX_NUM]; + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +/** + * Initialize the dyn_mem module (work memory and other variables) + */ +void lv_mem_init(void); + +/** + * Clean up the memory buffer which frees all the allocated memories. + * @note It work only if `LV_MEM_CUSTOM == 0` + */ +void lv_mem_deinit(void); + +/** + * Allocate a memory dynamically + * @param size size of the memory to allocate in bytes + * @return pointer to the allocated memory + */ +void * lv_mem_alloc(size_t size); + +/** + * Free an allocated data + * @param data pointer to an allocated memory + */ +void lv_mem_free(void * data); + +/** + * Reallocate a memory with a new size. The old content will be kept. + * @param data pointer to an allocated memory. + * Its content will be copied to the new memory block and freed + * @param new_size the desired new size in byte + * @return pointer to the new memory, NULL on failure + */ +void * lv_mem_realloc(void * data_p, size_t new_size); + +/** + * + * @return + */ +lv_res_t lv_mem_test(void); + +/** + * Give information about the work memory of dynamic allocation + * @param mon_p pointer to a lv_mem_monitor_t variable, + * the result of the analysis will be stored here + */ +void lv_mem_monitor(lv_mem_monitor_t * mon_p); + + +/** + * Get a temporal buffer with the given size. + * @param size the required size + */ +void * lv_mem_buf_get(uint32_t size); + +/** + * Release a memory buffer + * @param p buffer to release + */ +void lv_mem_buf_release(void * p); + +/** + * Free all memory buffers + */ +void lv_mem_buf_free_all(void); + +//! @cond Doxygen_Suppress + +#if LV_MEMCPY_MEMSET_STD + +/** + * Wrapper for the standard memcpy + * @param dst pointer to the destination buffer + * @param src pointer to the source buffer + * @param len number of byte to copy + */ +static inline void * lv_memcpy(void * dst, const void * src, size_t len) +{ + return memcpy(dst, src, len); +} + +/** + * Wrapper for the standard memcpy + * @param dst pointer to the destination buffer + * @param src pointer to the source buffer + * @param len number of byte to copy + */ +static inline void * lv_memcpy_small(void * dst, const void * src, size_t len) +{ + return memcpy(dst, src, len); +} + +/** + * Wrapper for the standard memset + * @param dst pointer to the destination buffer + * @param v value to set [0..255] + * @param len number of byte to set + */ +static inline void lv_memset(void * dst, uint8_t v, size_t len) +{ + memset(dst, v, len); +} + +/** + * Wrapper for the standard memset with fixed 0x00 value + * @param dst pointer to the destination buffer + * @param len number of byte to set + */ +static inline void lv_memset_00(void * dst, size_t len) +{ + memset(dst, 0x00, len); +} + +/** + * Wrapper for the standard memset with fixed 0xFF value + * @param dst pointer to the destination buffer + * @param len number of byte to set + */ +static inline void lv_memset_ff(void * dst, size_t len) +{ + memset(dst, 0xFF, len); +} + +#else +/** + * Same as `memcpy` but optimized for 4 byte operation. + * @param dst pointer to the destination buffer + * @param src pointer to the source buffer + * @param len number of byte to copy + */ +LV_ATTRIBUTE_FAST_MEM void * lv_memcpy(void * dst, const void * src, size_t len); + +/** + * Same as `memcpy` but optimized to copy only a few bytes. + * @param dst pointer to the destination buffer + * @param src pointer to the source buffer + * @param len number of byte to copy + */ +LV_ATTRIBUTE_FAST_MEM static inline void * lv_memcpy_small(void * dst, const void * src, size_t len) +{ + uint8_t * d8 = (uint8_t *)dst; + const uint8_t * s8 = (const uint8_t *)src; + + while(len) { + *d8 = *s8; + d8++; + s8++; + len--; + } + + return dst; +} + +/** + * Same as `memset` but optimized for 4 byte operation. + * @param dst pointer to the destination buffer + * @param v value to set [0..255] + * @param len number of byte to set + */ +LV_ATTRIBUTE_FAST_MEM void lv_memset(void * dst, uint8_t v, size_t len); + +/** + * Same as `memset(dst, 0x00, len)` but optimized for 4 byte operation. + * @param dst pointer to the destination buffer + * @param len number of byte to set + */ +LV_ATTRIBUTE_FAST_MEM void lv_memset_00(void * dst, size_t len); + +/** + * Same as `memset(dst, 0xFF, len)` but optimized for 4 byte operation. + * @param dst pointer to the destination buffer + * @param len number of byte to set + */ +LV_ATTRIBUTE_FAST_MEM void lv_memset_ff(void * dst, size_t len); + +//! @endcond + +#endif + +/********************** + * MACROS + **********************/ + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif /*LV_MEM_H*/ diff --git a/src/lib/lvgl/src/misc/lv_printf.h b/src/lib/lvgl/src/misc/lv_printf.h new file mode 100644 index 0000000..4cbbd84 --- /dev/null +++ b/src/lib/lvgl/src/misc/lv_printf.h @@ -0,0 +1,92 @@ +/////////////////////////////////////////////////////////////////////////////// +// \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. +// +/////////////////////////////////////////////////////////////////////////////// + +/*Original repository: https://github.com/mpaland/printf*/ + +#ifndef _LV_PRINTF_H_ +#define _LV_PRINTF_H_ + +#if defined(__has_include) + #if __has_include() + #include + /* platform-specific printf format for int32_t, usually "d" or "ld" */ + #define LV_PRId32 PRId32 + #define LV_PRIu32 PRIu32 + #else + #define LV_PRId32 "d" + #define LV_PRIu32 "u" + #endif +#else + /* hope this is correct for ports without __has_include or without inttypes.h */ + #define LV_PRId32 "d" + #define LV_PRIu32 "u" +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +#include "../lv_conf_internal.h" + +#if LV_SPRINTF_CUSTOM == 0 + +#include +#include + +#include "lv_types.h" + +typedef struct { + const char * fmt; + va_list * va; +} lv_vaformat_t; + +/** + * 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, ...) LV_FORMAT_ATTRIBUTE(3, 4); +int lv_vsnprintf(char * buffer, size_t count, const char * format, va_list va) LV_FORMAT_ATTRIBUTE(3, 0); + +#else +#include LV_SPRINTF_INCLUDE +#endif + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif // _LV_PRINTF_H_ diff --git a/src/lib/lvgl/src/misc/lv_style.h b/src/lib/lvgl/src/misc/lv_style.h new file mode 100644 index 0000000..6ec97cb --- /dev/null +++ b/src/lib/lvgl/src/misc/lv_style.h @@ -0,0 +1,525 @@ +/** + * @file lv_style.h + * + */ + +#ifndef LV_STYLE_H +#define LV_STYLE_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include +#include +#include "../font/lv_font.h" +#include "lv_color.h" +#include "lv_area.h" +#include "lv_anim.h" +#include "lv_txt.h" +#include "lv_types.h" +#include "lv_assert.h" +#include "lv_bidi.h" + +/********************* + * DEFINES + *********************/ + +#define LV_STYLE_SENTINEL_VALUE 0xAABBCCDD + +/** + * Flags for style properties + */ +#define LV_STYLE_PROP_INHERIT (1 << 10) /*Inherited*/ +#define LV_STYLE_PROP_EXT_DRAW (1 << 11) /*Requires ext. draw size update when changed*/ +#define LV_STYLE_PROP_LAYOUT_REFR (1 << 12) /*Requires layout update when changed*/ +#define LV_STYLE_PROP_PARENT_LAYOUT_REFR (1 << 13) /*Requires layout update on parent when changed*/ +#define LV_STYLE_PROP_FILTER (1 << 14) /*Apply color filter*/ + +/** + * Other constants + */ +#define LV_IMG_ZOOM_NONE 256 /*Value for not zooming the image*/ +LV_EXPORT_CONST_INT(LV_IMG_ZOOM_NONE); + +#if LV_USE_ASSERT_STYLE +#define LV_STYLE_CONST_INIT(var_name, prop_array) const lv_style_t var_name = { .sentinel = LV_STYLE_SENTINEL_VALUE, .v_p = { .const_props = prop_array }, .has_group = 0xFF, .is_const = 1 } +#else +#define LV_STYLE_CONST_INIT(var_name, prop_array) const lv_style_t var_name = { .v_p = { .const_props = prop_array }, .has_group = 0xFF, .is_const = 1 } +#endif + +/** On simple system, don't waste resources on gradients */ +#if !defined(LV_DRAW_COMPLEX) || !defined(LV_GRADIENT_MAX_STOPS) +#define LV_GRADIENT_MAX_STOPS 2 +#endif + + +/********************** + * TYPEDEFS + **********************/ + +/** + * Possible options how to blend opaque drawings + */ +enum { + LV_BLEND_MODE_NORMAL, /**< Simply mix according to the opacity value*/ + LV_BLEND_MODE_ADDITIVE, /**< Add the respective color channels*/ + LV_BLEND_MODE_SUBTRACTIVE,/**< Subtract the foreground from the background*/ + LV_BLEND_MODE_MULTIPLY, /**< Multiply the foreground and background*/ + LV_BLEND_MODE_REPLACE, /**< Replace background with foreground in the area*/ +}; + +typedef uint8_t lv_blend_mode_t; + +/** + * Some options to apply decorations on texts. + * 'OR'ed values can be used. + */ +enum { + LV_TEXT_DECOR_NONE = 0x00, + LV_TEXT_DECOR_UNDERLINE = 0x01, + LV_TEXT_DECOR_STRIKETHROUGH = 0x02, +}; + +typedef uint8_t lv_text_decor_t; + +/** + * Selects on which sides border should be drawn + * 'OR'ed values can be used. + */ +enum { + LV_BORDER_SIDE_NONE = 0x00, + LV_BORDER_SIDE_BOTTOM = 0x01, + LV_BORDER_SIDE_TOP = 0x02, + LV_BORDER_SIDE_LEFT = 0x04, + LV_BORDER_SIDE_RIGHT = 0x08, + LV_BORDER_SIDE_FULL = 0x0F, + LV_BORDER_SIDE_INTERNAL = 0x10, /**< FOR matrix-like objects (e.g. Button matrix)*/ +}; +typedef uint8_t lv_border_side_t; + +/** + * The direction of the gradient. + */ +enum { + LV_GRAD_DIR_NONE, /**< No gradient (the `grad_color` property is ignored)*/ + LV_GRAD_DIR_VER, /**< Vertical (top to bottom) gradient*/ + LV_GRAD_DIR_HOR, /**< Horizontal (left to right) gradient*/ +}; + +typedef uint8_t lv_grad_dir_t; + +/** + * The dithering algorithm for the gradient + * Depends on LV_DITHER_GRADIENT + */ +enum { + LV_DITHER_NONE, /**< No dithering, colors are just quantized to the output resolution*/ + LV_DITHER_ORDERED, /**< Ordered dithering. Faster to compute and use less memory but lower quality*/ + LV_DITHER_ERR_DIFF, /**< Error diffusion mode. Slower to compute and use more memory but give highest dither quality*/ +}; + +typedef uint8_t lv_dither_mode_t; + +/** A gradient stop definition. + * This matches a color and a position in a virtual 0-255 scale. + */ +typedef struct { + lv_color_t color; /**< The stop color */ + uint8_t frac; /**< The stop position in 1/255 unit */ +} lv_gradient_stop_t; + +/** A descriptor of a gradient. */ +typedef struct { + lv_gradient_stop_t stops[LV_GRADIENT_MAX_STOPS]; /**< A gradient stop array */ + uint8_t stops_count; /**< The number of used stops in the array */ + lv_grad_dir_t dir : 3; /**< The gradient direction. + * Any of LV_GRAD_DIR_HOR, LV_GRAD_DIR_VER, LV_GRAD_DIR_NONE */ + lv_dither_mode_t dither : 3; /**< Whether to dither the gradient or not. + * Any of LV_DITHER_NONE, LV_DITHER_ORDERED, LV_DITHER_ERR_DIFF */ +} lv_grad_dsc_t; + +/** + * A common type to handle all the property types in the same way. + */ +typedef union { + int32_t num; /**< Number integer number (opacity, enums, booleans or "normal" numbers)*/ + const void * ptr; /**< Constant pointers (font, cone text, etc)*/ + lv_color_t color; /**< Colors*/ +} lv_style_value_t; + +/** + * Enumeration of all built in style properties + */ +typedef enum { + LV_STYLE_PROP_INV = 0, + + /*Group 0*/ + LV_STYLE_WIDTH = 1 | LV_STYLE_PROP_LAYOUT_REFR, + LV_STYLE_MIN_WIDTH = 2 | LV_STYLE_PROP_LAYOUT_REFR, + LV_STYLE_MAX_WIDTH = 3 | LV_STYLE_PROP_LAYOUT_REFR, + LV_STYLE_HEIGHT = 4 | LV_STYLE_PROP_LAYOUT_REFR, + LV_STYLE_MIN_HEIGHT = 5 | LV_STYLE_PROP_LAYOUT_REFR, + LV_STYLE_MAX_HEIGHT = 6 | LV_STYLE_PROP_LAYOUT_REFR, + LV_STYLE_X = 7 | LV_STYLE_PROP_LAYOUT_REFR, + LV_STYLE_Y = 8 | LV_STYLE_PROP_LAYOUT_REFR, + LV_STYLE_ALIGN = 9 | LV_STYLE_PROP_LAYOUT_REFR, + LV_STYLE_TRANSFORM_WIDTH = 10 | LV_STYLE_PROP_EXT_DRAW, + LV_STYLE_TRANSFORM_HEIGHT = 11 | LV_STYLE_PROP_EXT_DRAW, + LV_STYLE_TRANSLATE_X = 12 | LV_STYLE_PROP_LAYOUT_REFR | LV_STYLE_PROP_PARENT_LAYOUT_REFR, + LV_STYLE_TRANSLATE_Y = 13 | LV_STYLE_PROP_LAYOUT_REFR | LV_STYLE_PROP_PARENT_LAYOUT_REFR, + LV_STYLE_TRANSFORM_ZOOM = 14 | LV_STYLE_PROP_EXT_DRAW | LV_STYLE_PROP_LAYOUT_REFR | LV_STYLE_PROP_PARENT_LAYOUT_REFR, + LV_STYLE_TRANSFORM_ANGLE = 15 | LV_STYLE_PROP_EXT_DRAW | LV_STYLE_PROP_LAYOUT_REFR | LV_STYLE_PROP_PARENT_LAYOUT_REFR, + + /*Group 1*/ + LV_STYLE_PAD_TOP = 16 | LV_STYLE_PROP_EXT_DRAW | LV_STYLE_PROP_LAYOUT_REFR, + LV_STYLE_PAD_BOTTOM = 17 | LV_STYLE_PROP_EXT_DRAW | LV_STYLE_PROP_LAYOUT_REFR, + LV_STYLE_PAD_LEFT = 18 | LV_STYLE_PROP_EXT_DRAW | LV_STYLE_PROP_LAYOUT_REFR, + LV_STYLE_PAD_RIGHT = 19 | LV_STYLE_PROP_EXT_DRAW | LV_STYLE_PROP_LAYOUT_REFR, + LV_STYLE_PAD_ROW = 20 | LV_STYLE_PROP_EXT_DRAW | LV_STYLE_PROP_LAYOUT_REFR, + LV_STYLE_PAD_COLUMN = 21 | LV_STYLE_PROP_EXT_DRAW | LV_STYLE_PROP_LAYOUT_REFR, + + /*Group 2*/ + LV_STYLE_BG_COLOR = 32, + LV_STYLE_BG_COLOR_FILTERED = 32 | LV_STYLE_PROP_FILTER, + LV_STYLE_BG_OPA = 33, + LV_STYLE_BG_GRAD_COLOR = 34, + LV_STYLE_BG_GRAD_COLOR_FILTERED = 34 | LV_STYLE_PROP_FILTER, + LV_STYLE_BG_GRAD_DIR = 35, + LV_STYLE_BG_MAIN_STOP = 36, + LV_STYLE_BG_GRAD_STOP = 37, + LV_STYLE_BG_GRAD = 38, + LV_STYLE_BG_DITHER_MODE = 39, + + + LV_STYLE_BG_IMG_SRC = 40 | LV_STYLE_PROP_EXT_DRAW, + LV_STYLE_BG_IMG_OPA = 41, + LV_STYLE_BG_IMG_RECOLOR = 42, + LV_STYLE_BG_IMG_RECOLOR_FILTERED = 42 | LV_STYLE_PROP_FILTER, + LV_STYLE_BG_IMG_RECOLOR_OPA = 43, + LV_STYLE_BG_IMG_TILED = 44, + + /*Group 3*/ + LV_STYLE_BORDER_COLOR = 48, + LV_STYLE_BORDER_COLOR_FILTERED = 48 | LV_STYLE_PROP_FILTER, + LV_STYLE_BORDER_OPA = 49, + LV_STYLE_BORDER_WIDTH = 50 | LV_STYLE_PROP_LAYOUT_REFR, + LV_STYLE_BORDER_SIDE = 51, + LV_STYLE_BORDER_POST = 52, + + LV_STYLE_OUTLINE_WIDTH = 58 | LV_STYLE_PROP_EXT_DRAW, + LV_STYLE_OUTLINE_COLOR = 59, + LV_STYLE_OUTLINE_COLOR_FILTERED = 59 | LV_STYLE_PROP_FILTER, + LV_STYLE_OUTLINE_OPA = 60 | LV_STYLE_PROP_EXT_DRAW, + LV_STYLE_OUTLINE_PAD = 61 | LV_STYLE_PROP_EXT_DRAW, + + /*Group 4*/ + LV_STYLE_SHADOW_WIDTH = 64 | LV_STYLE_PROP_EXT_DRAW, + LV_STYLE_SHADOW_OFS_X = 65 | LV_STYLE_PROP_EXT_DRAW, + LV_STYLE_SHADOW_OFS_Y = 66 | LV_STYLE_PROP_EXT_DRAW, + LV_STYLE_SHADOW_SPREAD = 67 | LV_STYLE_PROP_EXT_DRAW, + LV_STYLE_SHADOW_COLOR = 68, + LV_STYLE_SHADOW_COLOR_FILTERED = 68 | LV_STYLE_PROP_FILTER, + LV_STYLE_SHADOW_OPA = 69 | LV_STYLE_PROP_EXT_DRAW, + + LV_STYLE_IMG_OPA = 70, + LV_STYLE_IMG_RECOLOR = 71, + LV_STYLE_IMG_RECOLOR_FILTERED = 71 | LV_STYLE_PROP_FILTER, + LV_STYLE_IMG_RECOLOR_OPA = 72, + + LV_STYLE_LINE_WIDTH = 73 | LV_STYLE_PROP_EXT_DRAW, + LV_STYLE_LINE_DASH_WIDTH = 74, + LV_STYLE_LINE_DASH_GAP = 75, + LV_STYLE_LINE_ROUNDED = 76, + LV_STYLE_LINE_COLOR = 77, + LV_STYLE_LINE_COLOR_FILTERED = 77 | LV_STYLE_PROP_FILTER, + LV_STYLE_LINE_OPA = 78, + + /*Group 5*/ + LV_STYLE_ARC_WIDTH = 80 | LV_STYLE_PROP_EXT_DRAW, + LV_STYLE_ARC_ROUNDED = 81, + LV_STYLE_ARC_COLOR = 82, + LV_STYLE_ARC_COLOR_FILTERED = 82 | LV_STYLE_PROP_FILTER, + LV_STYLE_ARC_OPA = 83, + LV_STYLE_ARC_IMG_SRC = 84, + + LV_STYLE_TEXT_COLOR = 87 | LV_STYLE_PROP_INHERIT, + LV_STYLE_TEXT_COLOR_FILTERED = 87 | LV_STYLE_PROP_INHERIT | LV_STYLE_PROP_FILTER, + LV_STYLE_TEXT_OPA = 88 | LV_STYLE_PROP_INHERIT, + LV_STYLE_TEXT_FONT = 89 | LV_STYLE_PROP_INHERIT | LV_STYLE_PROP_LAYOUT_REFR, + LV_STYLE_TEXT_LETTER_SPACE = 90 | LV_STYLE_PROP_INHERIT | LV_STYLE_PROP_LAYOUT_REFR, + LV_STYLE_TEXT_LINE_SPACE = 91 | LV_STYLE_PROP_INHERIT | LV_STYLE_PROP_LAYOUT_REFR, + LV_STYLE_TEXT_DECOR = 92 | LV_STYLE_PROP_INHERIT, + LV_STYLE_TEXT_ALIGN = 93 | LV_STYLE_PROP_INHERIT | LV_STYLE_PROP_LAYOUT_REFR, + + /*Group 6*/ + LV_STYLE_RADIUS = 96, + LV_STYLE_CLIP_CORNER = 97, + LV_STYLE_OPA = 98 | LV_STYLE_PROP_INHERIT, + LV_STYLE_COLOR_FILTER_DSC = 99, + LV_STYLE_COLOR_FILTER_OPA = 100, + LV_STYLE_ANIM_TIME = 101, + LV_STYLE_ANIM_SPEED = 102, + LV_STYLE_TRANSITION = 103, + LV_STYLE_BLEND_MODE = 104, + LV_STYLE_LAYOUT = 105 | LV_STYLE_PROP_LAYOUT_REFR, + LV_STYLE_BASE_DIR = 106 | LV_STYLE_PROP_INHERIT | LV_STYLE_PROP_LAYOUT_REFR, + + _LV_STYLE_LAST_BUILT_IN_PROP = 111, + + LV_STYLE_PROP_ANY = 0xFFFF +} lv_style_prop_t; + +/** + * Descriptor for style transitions + */ +typedef struct { + const lv_style_prop_t * props; /**< An array with the properties to animate.*/ +#if LV_USE_USER_DATA + void * user_data; /**< A custom user data that will be passed to the animation's user_data */ +#endif + lv_anim_path_cb_t path_xcb; /**< A path for the animation.*/ + uint32_t time; /**< Duration of the transition in [ms]*/ + uint32_t delay; /**< Delay before the transition in [ms]*/ +} lv_style_transition_dsc_t; + +/** + * Descriptor of a constant style property. + */ +typedef struct { + lv_style_prop_t prop; + lv_style_value_t value; +} lv_style_const_prop_t; + +/** + * Descriptor of a style (a collection of properties and values). + */ +typedef struct { + +#if LV_USE_ASSERT_STYLE + uint32_t sentinel; +#endif + + /*If there is only one property store it directly. + *For more properties allocate an array*/ + union { + lv_style_value_t value1; + uint8_t * values_and_props; + const lv_style_const_prop_t * const_props; + } v_p; + + uint16_t prop1 : 15; + uint16_t is_const : 1; + uint8_t has_group; + uint8_t prop_cnt; +} lv_style_t; + +/********************** + * GLOBAL PROTOTYPES + **********************/ + + +/** + * Initialize a style + * @param style pointer to a style to initialize + * @note Do not call `lv_style_init` on styles that already have some properties + * because this function won't free the used memory, just sets a default state for the style. + * In other words be sure to initialize styles only once! + */ +void lv_style_init(lv_style_t * style); + +/** + * Clear all properties from a style and free all allocated memories. + * @param style pointer to a style + */ +void lv_style_reset(lv_style_t * style); + +/** + * Register a new style property for custom usage + * @return a new property ID. + * @example + * lv_style_prop_t MY_PROP; + * static inline void lv_style_set_my_prop(lv_style_t * style, lv_color_t value) { + * lv_style_value_t v = {.color = value}; lv_style_set_prop(style, MY_PROP, v); } + * + * ... + * MY_PROP = lv_style_register_prop(); + * ... + * lv_style_set_my_prop(&style1, lv_palette_main(LV_PALETTE_RED)); + */ +lv_style_prop_t lv_style_register_prop(void); + +/** + * Remove a property from a style + * @param style pointer to a style + * @param prop a style property ORed with a state. + * @return true: the property was found and removed; false: the property wasn't found + */ +bool lv_style_remove_prop(lv_style_t * style, lv_style_prop_t prop); + +/** + * Set the value of property in a style. + * This function shouldn't be used directly by the user. + * Instead use `lv_style_set_()`. E.g. `lv_style_set_bg_color()` + * @param style pointer to style + * @param prop the ID of a property (e.g. `LV_STYLE_BG_COLOR`) + * @param value `lv_style_value_t` variable in which a field is set according to the type of `prop` + */ +void lv_style_set_prop(lv_style_t * style, lv_style_prop_t prop, lv_style_value_t value); + +/** + * Get the value of a property + * @param style pointer to a style + * @param prop the ID of a property + * @param value pointer to a `lv_style_value_t` variable to store the value + * @return LV_RES_INV: the property wasn't found in the style (`value` is unchanged) + * LV_RES_OK: the property was fond, and `value` is set accordingly + * @note For performance reasons there are no sanity check on `style` + */ +lv_res_t lv_style_get_prop(const lv_style_t * style, lv_style_prop_t prop, lv_style_value_t * value); + + +/** + * Get the value of a property + * @param style pointer to a style + * @param prop the ID of a property + * @param value pointer to a `lv_style_value_t` variable to store the value + * @return LV_RES_INV: the property wasn't found in the style (`value` is unchanged) + * LV_RES_OK: the property was fond, and `value` is set accordingly + * @note For performance reasons there are no sanity check on `style` + * @note This function is the same as ::lv_style_get_prop but inlined. Use it only on performance critical places + */ +static inline lv_res_t lv_style_get_prop_inlined(const lv_style_t * style, lv_style_prop_t prop, + lv_style_value_t * value) +{ + if(style->is_const) { + const lv_style_const_prop_t * const_prop; + for(const_prop = style->v_p.const_props; const_prop->prop != LV_STYLE_PROP_INV; const_prop++) { + if(const_prop->prop == prop) { + *value = const_prop->value; + return LV_RES_OK; + } + } + return LV_RES_INV; + } + + if(style->prop_cnt == 0) return LV_RES_INV; + + if(style->prop_cnt > 1) { + uint8_t * tmp = style->v_p.values_and_props + style->prop_cnt * sizeof(lv_style_value_t); + uint16_t * props = (uint16_t *)tmp; + uint32_t i; + for(i = 0; i < style->prop_cnt; i++) { + if(props[i] == prop) { + lv_style_value_t * values = (lv_style_value_t *)style->v_p.values_and_props; + *value = values[i]; + return LV_RES_OK; + } + } + } + else if(style->prop1 == prop) { + *value = style->v_p.value1; + return LV_RES_OK; + } + return LV_RES_INV; +} + +/** + * Initialize a transition descriptor. + * @param tr pointer to a transition descriptor to initialize + * @param props an array with the properties to transition. The last element must be zero. + * @param path_cb an animation path (ease) callback. If `NULL` liner path will be used. + * @param time duration of the transition in [ms] + * @param delay delay before the transition in [ms] + * @param user_data any custom data that will be saved in the transition animation and will be available when `path_cb` is called + * @example + * const static lv_style_prop_t trans_props[] = { LV_STYLE_BG_OPA, LV_STYLE_BG_COLOR, 0 }; + * static lv_style_transition_dsc_t trans1; + * lv_style_transition_dsc_init(&trans1, trans_props, NULL, 300, 0, NULL); + */ +void lv_style_transition_dsc_init(lv_style_transition_dsc_t * tr, const lv_style_prop_t props[], + lv_anim_path_cb_t path_cb, uint32_t time, uint32_t delay, void * user_data); + +/** + * Get the default value of a property + * @param prop the ID of a property + * @return the default value + */ +lv_style_value_t lv_style_prop_get_default(lv_style_prop_t prop); + +/** + * Checks if a style is empty (has no properties) + * @param style pointer to a style + * @return true if the style is empty + */ +bool lv_style_is_empty(const lv_style_t * style); + +/** + * Tell the group of a property. If the a property from a group is set in a style the (1 << group) bit of style->has_group is set. + * It allows early skipping the style if the property is not exists in the style at all. + * @param prop a style property + * @return the group [0..7] 7 means all the custom properties with index > 112 + */ +uint8_t _lv_style_get_prop_group(lv_style_prop_t prop); + +#include "lv_style_gen.h" + +static inline void lv_style_set_size(lv_style_t * style, lv_coord_t value) +{ + lv_style_set_width(style, value); + lv_style_set_height(style, value); +} + +static inline void lv_style_set_pad_all(lv_style_t * style, lv_coord_t value) +{ + lv_style_set_pad_left(style, value); + lv_style_set_pad_right(style, value); + lv_style_set_pad_top(style, value); + lv_style_set_pad_bottom(style, value); +} + +static inline void lv_style_set_pad_hor(lv_style_t * style, lv_coord_t value) +{ + lv_style_set_pad_left(style, value); + lv_style_set_pad_right(style, value); +} + +static inline void lv_style_set_pad_ver(lv_style_t * style, lv_coord_t value) +{ + lv_style_set_pad_top(style, value); + lv_style_set_pad_bottom(style, value); +} + +static inline void lv_style_set_pad_gap(lv_style_t * style, lv_coord_t value) +{ + lv_style_set_pad_row(style, value); + lv_style_set_pad_column(style, value); +} + + +/************************* + * GLOBAL VARIABLES + *************************/ + +/********************** + * MACROS + **********************/ + +#if LV_USE_ASSERT_STYLE +# define LV_ASSERT_STYLE(style_p) \ + do { \ + LV_ASSERT_MSG(style_p != NULL, "The style is NULL"); \ + LV_ASSERT_MSG(style_p->sentinel == LV_STYLE_SENTINEL_VALUE, "Style is not initialized or corrupted"); \ + } while(0) +#else +# define LV_ASSERT_STYLE(p) do{}while(0) +#endif + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif /*LV_STYLE_H*/ diff --git a/src/lib/lvgl/src/misc/lv_style_gen.h b/src/lib/lvgl/src/misc/lv_style_gen.h new file mode 100644 index 0000000..04e1f1a --- /dev/null +++ b/src/lib/lvgl/src/misc/lv_style_gen.h @@ -0,0 +1,546 @@ +void lv_style_set_width(lv_style_t * style, lv_coord_t value); +void lv_style_set_min_width(lv_style_t * style, lv_coord_t value); +void lv_style_set_max_width(lv_style_t * style, lv_coord_t value); +void lv_style_set_height(lv_style_t * style, lv_coord_t value); +void lv_style_set_min_height(lv_style_t * style, lv_coord_t value); +void lv_style_set_max_height(lv_style_t * style, lv_coord_t value); +void lv_style_set_x(lv_style_t * style, lv_coord_t value); +void lv_style_set_y(lv_style_t * style, lv_coord_t value); +void lv_style_set_align(lv_style_t * style, lv_align_t value); +void lv_style_set_transform_width(lv_style_t * style, lv_coord_t value); +void lv_style_set_transform_height(lv_style_t * style, lv_coord_t value); +void lv_style_set_translate_x(lv_style_t * style, lv_coord_t value); +void lv_style_set_translate_y(lv_style_t * style, lv_coord_t value); +void lv_style_set_transform_zoom(lv_style_t * style, lv_coord_t value); +void lv_style_set_transform_angle(lv_style_t * style, lv_coord_t value); +void lv_style_set_pad_top(lv_style_t * style, lv_coord_t value); +void lv_style_set_pad_bottom(lv_style_t * style, lv_coord_t value); +void lv_style_set_pad_left(lv_style_t * style, lv_coord_t value); +void lv_style_set_pad_right(lv_style_t * style, lv_coord_t value); +void lv_style_set_pad_row(lv_style_t * style, lv_coord_t value); +void lv_style_set_pad_column(lv_style_t * style, lv_coord_t value); +void lv_style_set_bg_color(lv_style_t * style, lv_color_t value); +void lv_style_set_bg_color_filtered(lv_style_t * style, lv_color_t value); +void lv_style_set_bg_opa(lv_style_t * style, lv_opa_t value); +void lv_style_set_bg_grad_color(lv_style_t * style, lv_color_t value); +void lv_style_set_bg_grad_color_filtered(lv_style_t * style, lv_color_t value); +void lv_style_set_bg_grad_dir(lv_style_t * style, lv_grad_dir_t value); +void lv_style_set_bg_main_stop(lv_style_t * style, lv_coord_t value); +void lv_style_set_bg_grad_stop(lv_style_t * style, lv_coord_t value); +void lv_style_set_bg_grad(lv_style_t * style, const lv_grad_dsc_t * value); +void lv_style_set_bg_dither_mode(lv_style_t * style, lv_dither_mode_t value); +void lv_style_set_bg_img_src(lv_style_t * style, const void * value); +void lv_style_set_bg_img_opa(lv_style_t * style, lv_opa_t value); +void lv_style_set_bg_img_recolor(lv_style_t * style, lv_color_t value); +void lv_style_set_bg_img_recolor_filtered(lv_style_t * style, lv_color_t value); +void lv_style_set_bg_img_recolor_opa(lv_style_t * style, lv_opa_t value); +void lv_style_set_bg_img_tiled(lv_style_t * style, bool value); +void lv_style_set_border_color(lv_style_t * style, lv_color_t value); +void lv_style_set_border_color_filtered(lv_style_t * style, lv_color_t value); +void lv_style_set_border_opa(lv_style_t * style, lv_opa_t value); +void lv_style_set_border_width(lv_style_t * style, lv_coord_t value); +void lv_style_set_border_side(lv_style_t * style, lv_border_side_t value); +void lv_style_set_border_post(lv_style_t * style, bool value); +void lv_style_set_outline_width(lv_style_t * style, lv_coord_t value); +void lv_style_set_outline_color(lv_style_t * style, lv_color_t value); +void lv_style_set_outline_color_filtered(lv_style_t * style, lv_color_t value); +void lv_style_set_outline_opa(lv_style_t * style, lv_opa_t value); +void lv_style_set_outline_pad(lv_style_t * style, lv_coord_t value); +void lv_style_set_shadow_width(lv_style_t * style, lv_coord_t value); +void lv_style_set_shadow_ofs_x(lv_style_t * style, lv_coord_t value); +void lv_style_set_shadow_ofs_y(lv_style_t * style, lv_coord_t value); +void lv_style_set_shadow_spread(lv_style_t * style, lv_coord_t value); +void lv_style_set_shadow_color(lv_style_t * style, lv_color_t value); +void lv_style_set_shadow_color_filtered(lv_style_t * style, lv_color_t value); +void lv_style_set_shadow_opa(lv_style_t * style, lv_opa_t value); +void lv_style_set_img_opa(lv_style_t * style, lv_opa_t value); +void lv_style_set_img_recolor(lv_style_t * style, lv_color_t value); +void lv_style_set_img_recolor_filtered(lv_style_t * style, lv_color_t value); +void lv_style_set_img_recolor_opa(lv_style_t * style, lv_opa_t value); +void lv_style_set_line_width(lv_style_t * style, lv_coord_t value); +void lv_style_set_line_dash_width(lv_style_t * style, lv_coord_t value); +void lv_style_set_line_dash_gap(lv_style_t * style, lv_coord_t value); +void lv_style_set_line_rounded(lv_style_t * style, bool value); +void lv_style_set_line_color(lv_style_t * style, lv_color_t value); +void lv_style_set_line_color_filtered(lv_style_t * style, lv_color_t value); +void lv_style_set_line_opa(lv_style_t * style, lv_opa_t value); +void lv_style_set_arc_width(lv_style_t * style, lv_coord_t value); +void lv_style_set_arc_rounded(lv_style_t * style, bool value); +void lv_style_set_arc_color(lv_style_t * style, lv_color_t value); +void lv_style_set_arc_color_filtered(lv_style_t * style, lv_color_t value); +void lv_style_set_arc_opa(lv_style_t * style, lv_opa_t value); +void lv_style_set_arc_img_src(lv_style_t * style, const void * value); +void lv_style_set_text_color(lv_style_t * style, lv_color_t value); +void lv_style_set_text_color_filtered(lv_style_t * style, lv_color_t value); +void lv_style_set_text_opa(lv_style_t * style, lv_opa_t value); +void lv_style_set_text_font(lv_style_t * style, const lv_font_t * value); +void lv_style_set_text_letter_space(lv_style_t * style, lv_coord_t value); +void lv_style_set_text_line_space(lv_style_t * style, lv_coord_t value); +void lv_style_set_text_decor(lv_style_t * style, lv_text_decor_t value); +void lv_style_set_text_align(lv_style_t * style, lv_text_align_t value); +void lv_style_set_radius(lv_style_t * style, lv_coord_t value); +void lv_style_set_clip_corner(lv_style_t * style, bool value); +void lv_style_set_opa(lv_style_t * style, lv_opa_t value); +void lv_style_set_color_filter_dsc(lv_style_t * style, const lv_color_filter_dsc_t * value); +void lv_style_set_color_filter_opa(lv_style_t * style, lv_opa_t value); +void lv_style_set_anim_time(lv_style_t * style, uint32_t value); +void lv_style_set_anim_speed(lv_style_t * style, uint32_t value); +void lv_style_set_transition(lv_style_t * style, const lv_style_transition_dsc_t * value); +void lv_style_set_blend_mode(lv_style_t * style, lv_blend_mode_t value); +void lv_style_set_layout(lv_style_t * style, uint16_t value); +void lv_style_set_base_dir(lv_style_t * style, lv_base_dir_t value); + +#define LV_STYLE_CONST_WIDTH(val) \ + { \ + .prop = LV_STYLE_WIDTH, .value = { .num = (int32_t)val } \ + } + +#define LV_STYLE_CONST_MIN_WIDTH(val) \ + { \ + .prop = LV_STYLE_MIN_WIDTH, .value = { .num = (int32_t)val } \ + } + +#define LV_STYLE_CONST_MAX_WIDTH(val) \ + { \ + .prop = LV_STYLE_MAX_WIDTH, .value = { .num = (int32_t)val } \ + } + +#define LV_STYLE_CONST_HEIGHT(val) \ + { \ + .prop = LV_STYLE_HEIGHT, .value = { .num = (int32_t)val } \ + } + +#define LV_STYLE_CONST_MIN_HEIGHT(val) \ + { \ + .prop = LV_STYLE_MIN_HEIGHT, .value = { .num = (int32_t)val } \ + } + +#define LV_STYLE_CONST_MAX_HEIGHT(val) \ + { \ + .prop = LV_STYLE_MAX_HEIGHT, .value = { .num = (int32_t)val } \ + } + +#define LV_STYLE_CONST_X(val) \ + { \ + .prop = LV_STYLE_X, .value = { .num = (int32_t)val } \ + } + +#define LV_STYLE_CONST_Y(val) \ + { \ + .prop = LV_STYLE_Y, .value = { .num = (int32_t)val } \ + } + +#define LV_STYLE_CONST_ALIGN(val) \ + { \ + .prop = LV_STYLE_ALIGN, .value = { .num = (int32_t)val } \ + } + +#define LV_STYLE_CONST_TRANSFORM_WIDTH(val) \ + { \ + .prop = LV_STYLE_TRANSFORM_WIDTH, .value = { .num = (int32_t)val } \ + } + +#define LV_STYLE_CONST_TRANSFORM_HEIGHT(val) \ + { \ + .prop = LV_STYLE_TRANSFORM_HEIGHT, .value = { .num = (int32_t)val } \ + } + +#define LV_STYLE_CONST_TRANSLATE_X(val) \ + { \ + .prop = LV_STYLE_TRANSLATE_X, .value = { .num = (int32_t)val } \ + } + +#define LV_STYLE_CONST_TRANSLATE_Y(val) \ + { \ + .prop = LV_STYLE_TRANSLATE_Y, .value = { .num = (int32_t)val } \ + } + +#define LV_STYLE_CONST_TRANSFORM_ZOOM(val) \ + { \ + .prop = LV_STYLE_TRANSFORM_ZOOM, .value = { .num = (int32_t)val } \ + } + +#define LV_STYLE_CONST_TRANSFORM_ANGLE(val) \ + { \ + .prop = LV_STYLE_TRANSFORM_ANGLE, .value = { .num = (int32_t)val } \ + } + +#define LV_STYLE_CONST_PAD_TOP(val) \ + { \ + .prop = LV_STYLE_PAD_TOP, .value = { .num = (int32_t)val } \ + } + +#define LV_STYLE_CONST_PAD_BOTTOM(val) \ + { \ + .prop = LV_STYLE_PAD_BOTTOM, .value = { .num = (int32_t)val } \ + } + +#define LV_STYLE_CONST_PAD_LEFT(val) \ + { \ + .prop = LV_STYLE_PAD_LEFT, .value = { .num = (int32_t)val } \ + } + +#define LV_STYLE_CONST_PAD_RIGHT(val) \ + { \ + .prop = LV_STYLE_PAD_RIGHT, .value = { .num = (int32_t)val } \ + } + +#define LV_STYLE_CONST_PAD_ROW(val) \ + { \ + .prop = LV_STYLE_PAD_ROW, .value = { .num = (int32_t)val } \ + } + +#define LV_STYLE_CONST_PAD_COLUMN(val) \ + { \ + .prop = LV_STYLE_PAD_COLUMN, .value = { .num = (int32_t)val } \ + } + +#define LV_STYLE_CONST_BG_COLOR(val) \ + { \ + .prop = LV_STYLE_BG_COLOR, .value = { .color = val } \ + } + +#define LV_STYLE_CONST_BG_COLOR_FILTERED(val) \ + { \ + .prop = LV_STYLE_BG_COLOR_FILTERED, .value = { .color = val } \ + } + +#define LV_STYLE_CONST_BG_OPA(val) \ + { \ + .prop = LV_STYLE_BG_OPA, .value = { .num = (int32_t)val } \ + } + +#define LV_STYLE_CONST_BG_GRAD_COLOR(val) \ + { \ + .prop = LV_STYLE_BG_GRAD_COLOR, .value = { .color = val } \ + } + +#define LV_STYLE_CONST_BG_GRAD_COLOR_FILTERED(val) \ + { \ + .prop = LV_STYLE_BG_GRAD_COLOR_FILTERED, .value = { .color = val } \ + } + +#define LV_STYLE_CONST_BG_GRAD_DIR(val) \ + { \ + .prop = LV_STYLE_BG_GRAD_DIR, .value = { .num = (int32_t)val } \ + } + +#define LV_STYLE_CONST_BG_MAIN_STOP(val) \ + { \ + .prop = LV_STYLE_BG_MAIN_STOP, .value = { .num = (int32_t)val } \ + } + +#define LV_STYLE_CONST_BG_GRAD_STOP(val) \ + { \ + .prop = LV_STYLE_BG_GRAD_STOP, .value = { .num = (int32_t)val } \ + } + +#define LV_STYLE_CONST_BG_GRAD(val) \ + { \ + .prop = LV_STYLE_BG_GRAD, .value = { .ptr = val } \ + } + +#define LV_STYLE_CONST_BG_DITHER_MODE(val) \ + { \ + .prop = LV_STYLE_BG_DITHER_MODE, .value = { .num = (int32_t)val } \ + } + +#define LV_STYLE_CONST_BG_IMG_SRC(val) \ + { \ + .prop = LV_STYLE_BG_IMG_SRC, .value = { .ptr = val } \ + } + +#define LV_STYLE_CONST_BG_IMG_OPA(val) \ + { \ + .prop = LV_STYLE_BG_IMG_OPA, .value = { .num = (int32_t)val } \ + } + +#define LV_STYLE_CONST_BG_IMG_RECOLOR(val) \ + { \ + .prop = LV_STYLE_BG_IMG_RECOLOR, .value = { .color = val } \ + } + +#define LV_STYLE_CONST_BG_IMG_RECOLOR_FILTERED(val) \ + { \ + .prop = LV_STYLE_BG_IMG_RECOLOR_FILTERED, .value = { .color = val } \ + } + +#define LV_STYLE_CONST_BG_IMG_RECOLOR_OPA(val) \ + { \ + .prop = LV_STYLE_BG_IMG_RECOLOR_OPA, .value = { .num = (int32_t)val } \ + } + +#define LV_STYLE_CONST_BG_IMG_TILED(val) \ + { \ + .prop = LV_STYLE_BG_IMG_TILED, .value = { .num = (int32_t)val } \ + } + +#define LV_STYLE_CONST_BORDER_COLOR(val) \ + { \ + .prop = LV_STYLE_BORDER_COLOR, .value = { .color = val } \ + } + +#define LV_STYLE_CONST_BORDER_COLOR_FILTERED(val) \ + { \ + .prop = LV_STYLE_BORDER_COLOR_FILTERED, .value = { .color = val } \ + } + +#define LV_STYLE_CONST_BORDER_OPA(val) \ + { \ + .prop = LV_STYLE_BORDER_OPA, .value = { .num = (int32_t)val } \ + } + +#define LV_STYLE_CONST_BORDER_WIDTH(val) \ + { \ + .prop = LV_STYLE_BORDER_WIDTH, .value = { .num = (int32_t)val } \ + } + +#define LV_STYLE_CONST_BORDER_SIDE(val) \ + { \ + .prop = LV_STYLE_BORDER_SIDE, .value = { .num = (int32_t)val } \ + } + +#define LV_STYLE_CONST_BORDER_POST(val) \ + { \ + .prop = LV_STYLE_BORDER_POST, .value = { .num = (int32_t)val } \ + } + +#define LV_STYLE_CONST_OUTLINE_WIDTH(val) \ + { \ + .prop = LV_STYLE_OUTLINE_WIDTH, .value = { .num = (int32_t)val } \ + } + +#define LV_STYLE_CONST_OUTLINE_COLOR(val) \ + { \ + .prop = LV_STYLE_OUTLINE_COLOR, .value = { .color = val } \ + } + +#define LV_STYLE_CONST_OUTLINE_COLOR_FILTERED(val) \ + { \ + .prop = LV_STYLE_OUTLINE_COLOR_FILTERED, .value = { .color = val } \ + } + +#define LV_STYLE_CONST_OUTLINE_OPA(val) \ + { \ + .prop = LV_STYLE_OUTLINE_OPA, .value = { .num = (int32_t)val } \ + } + +#define LV_STYLE_CONST_OUTLINE_PAD(val) \ + { \ + .prop = LV_STYLE_OUTLINE_PAD, .value = { .num = (int32_t)val } \ + } + +#define LV_STYLE_CONST_SHADOW_WIDTH(val) \ + { \ + .prop = LV_STYLE_SHADOW_WIDTH, .value = { .num = (int32_t)val } \ + } + +#define LV_STYLE_CONST_SHADOW_OFS_X(val) \ + { \ + .prop = LV_STYLE_SHADOW_OFS_X, .value = { .num = (int32_t)val } \ + } + +#define LV_STYLE_CONST_SHADOW_OFS_Y(val) \ + { \ + .prop = LV_STYLE_SHADOW_OFS_Y, .value = { .num = (int32_t)val } \ + } + +#define LV_STYLE_CONST_SHADOW_SPREAD(val) \ + { \ + .prop = LV_STYLE_SHADOW_SPREAD, .value = { .num = (int32_t)val } \ + } + +#define LV_STYLE_CONST_SHADOW_COLOR(val) \ + { \ + .prop = LV_STYLE_SHADOW_COLOR, .value = { .color = val } \ + } + +#define LV_STYLE_CONST_SHADOW_COLOR_FILTERED(val) \ + { \ + .prop = LV_STYLE_SHADOW_COLOR_FILTERED, .value = { .color = val } \ + } + +#define LV_STYLE_CONST_SHADOW_OPA(val) \ + { \ + .prop = LV_STYLE_SHADOW_OPA, .value = { .num = (int32_t)val } \ + } + +#define LV_STYLE_CONST_IMG_OPA(val) \ + { \ + .prop = LV_STYLE_IMG_OPA, .value = { .num = (int32_t)val } \ + } + +#define LV_STYLE_CONST_IMG_RECOLOR(val) \ + { \ + .prop = LV_STYLE_IMG_RECOLOR, .value = { .color = val } \ + } + +#define LV_STYLE_CONST_IMG_RECOLOR_FILTERED(val) \ + { \ + .prop = LV_STYLE_IMG_RECOLOR_FILTERED, .value = { .color = val } \ + } + +#define LV_STYLE_CONST_IMG_RECOLOR_OPA(val) \ + { \ + .prop = LV_STYLE_IMG_RECOLOR_OPA, .value = { .num = (int32_t)val } \ + } + +#define LV_STYLE_CONST_LINE_WIDTH(val) \ + { \ + .prop = LV_STYLE_LINE_WIDTH, .value = { .num = (int32_t)val } \ + } + +#define LV_STYLE_CONST_LINE_DASH_WIDTH(val) \ + { \ + .prop = LV_STYLE_LINE_DASH_WIDTH, .value = { .num = (int32_t)val } \ + } + +#define LV_STYLE_CONST_LINE_DASH_GAP(val) \ + { \ + .prop = LV_STYLE_LINE_DASH_GAP, .value = { .num = (int32_t)val } \ + } + +#define LV_STYLE_CONST_LINE_ROUNDED(val) \ + { \ + .prop = LV_STYLE_LINE_ROUNDED, .value = { .num = (int32_t)val } \ + } + +#define LV_STYLE_CONST_LINE_COLOR(val) \ + { \ + .prop = LV_STYLE_LINE_COLOR, .value = { .color = val } \ + } + +#define LV_STYLE_CONST_LINE_COLOR_FILTERED(val) \ + { \ + .prop = LV_STYLE_LINE_COLOR_FILTERED, .value = { .color = val } \ + } + +#define LV_STYLE_CONST_LINE_OPA(val) \ + { \ + .prop = LV_STYLE_LINE_OPA, .value = { .num = (int32_t)val } \ + } + +#define LV_STYLE_CONST_ARC_WIDTH(val) \ + { \ + .prop = LV_STYLE_ARC_WIDTH, .value = { .num = (int32_t)val } \ + } + +#define LV_STYLE_CONST_ARC_ROUNDED(val) \ + { \ + .prop = LV_STYLE_ARC_ROUNDED, .value = { .num = (int32_t)val } \ + } + +#define LV_STYLE_CONST_ARC_COLOR(val) \ + { \ + .prop = LV_STYLE_ARC_COLOR, .value = { .color = val } \ + } + +#define LV_STYLE_CONST_ARC_COLOR_FILTERED(val) \ + { \ + .prop = LV_STYLE_ARC_COLOR_FILTERED, .value = { .color = val } \ + } + +#define LV_STYLE_CONST_ARC_OPA(val) \ + { \ + .prop = LV_STYLE_ARC_OPA, .value = { .num = (int32_t)val } \ + } + +#define LV_STYLE_CONST_ARC_IMG_SRC(val) \ + { \ + .prop = LV_STYLE_ARC_IMG_SRC, .value = { .ptr = val } \ + } + +#define LV_STYLE_CONST_TEXT_COLOR(val) \ + { \ + .prop = LV_STYLE_TEXT_COLOR, .value = { .color = val } \ + } + +#define LV_STYLE_CONST_TEXT_COLOR_FILTERED(val) \ + { \ + .prop = LV_STYLE_TEXT_COLOR_FILTERED, .value = { .color = val } \ + } + +#define LV_STYLE_CONST_TEXT_OPA(val) \ + { \ + .prop = LV_STYLE_TEXT_OPA, .value = { .num = (int32_t)val } \ + } + +#define LV_STYLE_CONST_TEXT_FONT(val) \ + { \ + .prop = LV_STYLE_TEXT_FONT, .value = { .ptr = val } \ + } + +#define LV_STYLE_CONST_TEXT_LETTER_SPACE(val) \ + { \ + .prop = LV_STYLE_TEXT_LETTER_SPACE, .value = { .num = (int32_t)val } \ + } + +#define LV_STYLE_CONST_TEXT_LINE_SPACE(val) \ + { \ + .prop = LV_STYLE_TEXT_LINE_SPACE, .value = { .num = (int32_t)val } \ + } + +#define LV_STYLE_CONST_TEXT_DECOR(val) \ + { \ + .prop = LV_STYLE_TEXT_DECOR, .value = { .num = (int32_t)val } \ + } + +#define LV_STYLE_CONST_TEXT_ALIGN(val) \ + { \ + .prop = LV_STYLE_TEXT_ALIGN, .value = { .num = (int32_t)val } \ + } + +#define LV_STYLE_CONST_RADIUS(val) \ + { \ + .prop = LV_STYLE_RADIUS, .value = { .num = (int32_t)val } \ + } + +#define LV_STYLE_CONST_CLIP_CORNER(val) \ + { \ + .prop = LV_STYLE_CLIP_CORNER, .value = { .num = (int32_t)val } \ + } + +#define LV_STYLE_CONST_OPA(val) \ + { \ + .prop = LV_STYLE_OPA, .value = { .num = (int32_t)val } \ + } + +#define LV_STYLE_CONST_COLOR_FILTER_DSC(val) \ + { \ + .prop = LV_STYLE_COLOR_FILTER_DSC, .value = { .ptr = val } \ + } + +#define LV_STYLE_CONST_COLOR_FILTER_OPA(val) \ + { \ + .prop = LV_STYLE_COLOR_FILTER_OPA, .value = { .num = (int32_t)val } \ + } + +#define LV_STYLE_CONST_ANIM_TIME(val) \ + { \ + .prop = LV_STYLE_ANIM_TIME, .value = { .num = (int32_t)val } \ + } + +#define LV_STYLE_CONST_ANIM_SPEED(val) \ + { \ + .prop = LV_STYLE_ANIM_SPEED, .value = { .num = (int32_t)val } \ + } + +#define LV_STYLE_CONST_TRANSITION(val) \ + { \ + .prop = LV_STYLE_TRANSITION, .value = { .ptr = val } \ + } + +#define LV_STYLE_CONST_BLEND_MODE(val) \ + { \ + .prop = LV_STYLE_BLEND_MODE, .value = { .num = (int32_t)val } \ + } + +#define LV_STYLE_CONST_LAYOUT(val) \ + { \ + .prop = LV_STYLE_LAYOUT, .value = { .num = (int32_t)val } \ + } + +#define LV_STYLE_CONST_BASE_DIR(val) \ + { \ + .prop = LV_STYLE_BASE_DIR, .value = { .num = (int32_t)val } \ + } diff --git a/src/lib/lvgl/src/misc/lv_templ.h b/src/lib/lvgl/src/misc/lv_templ.h new file mode 100644 index 0000000..f7e3c26 --- /dev/null +++ b/src/lib/lvgl/src/misc/lv_templ.h @@ -0,0 +1,37 @@ +/** + * @file lv_templ.h + * + */ + +#ifndef LV_TEMPL_H +#define LV_TEMPL_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +/********************** + * MACROS + **********************/ + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif /*LV_TEMPL_H*/ diff --git a/src/lib/lvgl/src/misc/lv_timer.h b/src/lib/lvgl/src/misc/lv_timer.h new file mode 100644 index 0000000..ce94c7b --- /dev/null +++ b/src/lib/lvgl/src/misc/lv_timer.h @@ -0,0 +1,164 @@ +/** + * @file lv_timer.h + */ + +#ifndef LV_TIMER_H +#define LV_TIMER_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include "../lv_conf_internal.h" + +#include +#include + +/********************* + * DEFINES + *********************/ +#ifndef LV_ATTRIBUTE_TIMER_HANDLER +#define LV_ATTRIBUTE_TIMER_HANDLER +#endif + +#define LV_NO_TIMER_READY 0xFFFFFFFF + +/********************** + * TYPEDEFS + **********************/ + +struct _lv_timer_t; + +/** + * Timers execute this type of functions. + */ +typedef void (*lv_timer_cb_t)(struct _lv_timer_t *); + +/** + * Descriptor of a lv_timer + */ +typedef struct _lv_timer_t { + uint32_t period; /**< How often the timer should run*/ + uint32_t last_run; /**< Last time the timer ran*/ + lv_timer_cb_t timer_cb; /**< Timer function*/ + void * user_data; /**< Custom user data*/ + int32_t repeat_count; /**< 1: One time; -1 : infinity; n>0: residual times*/ + uint32_t paused : 1; +} lv_timer_t; + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +/** + * Init the lv_timer module + */ +void _lv_timer_core_init(void); + +//! @cond Doxygen_Suppress + +/** + * Call it periodically to handle lv_timers. + * @return time till it needs to be run next (in ms) + */ +LV_ATTRIBUTE_TIMER_HANDLER uint32_t lv_timer_handler(void); + +//! @endcond + +/** + * Create an "empty" timer. It needs to initialized with at least + * `lv_timer_set_cb` and `lv_timer_set_period` + * @return pointer to the created timer + */ +lv_timer_t * lv_timer_create_basic(void); + +/** + * Create a new lv_timer + * @param timer_xcb a callback to call periodically. + * (the 'x' in the argument name indicates that it's not a fully generic function because it not follows + * the `func_name(object, callback, ...)` convention) + * @param period call period in ms unit + * @param user_data custom parameter + * @return pointer to the new timer + */ +lv_timer_t * lv_timer_create(lv_timer_cb_t timer_xcb, uint32_t period, void * user_data); + +/** + * Delete a lv_timer + * @param timer pointer to an lv_timer + */ +void lv_timer_del(lv_timer_t * timer); + +/** + * Pause/resume a timer. + * @param timer pointer to an lv_timer + */ +void lv_timer_pause(lv_timer_t * timer); + +void lv_timer_resume(lv_timer_t * timer); + +/** + * Set the callback the timer (the function to call periodically) + * @param timer pointer to a timer + * @param timer_cb the function to call periodically + */ +void lv_timer_set_cb(lv_timer_t * timer, lv_timer_cb_t timer_cb); + +/** + * Set new period for a lv_timer + * @param timer pointer to a lv_timer + * @param period the new period + */ +void lv_timer_set_period(lv_timer_t * timer, uint32_t period); + +/** + * Make a lv_timer ready. It will not wait its period. + * @param timer pointer to a lv_timer. + */ +void lv_timer_ready(lv_timer_t * timer); + +/** + * Set the number of times a timer will repeat. + * @param timer pointer to a lv_timer. + * @param repeat_count -1 : infinity; 0 : stop ; n>0: residual times + */ +void lv_timer_set_repeat_count(lv_timer_t * timer, int32_t repeat_count); + +/** + * Reset a lv_timer. + * It will be called the previously set period milliseconds later. + * @param timer pointer to a lv_timer. + */ +void lv_timer_reset(lv_timer_t * timer); + +/** + * Enable or disable the whole lv_timer handling + * @param en true: lv_timer handling is running, false: lv_timer handling is suspended + */ +void lv_timer_enable(bool en); + +/** + * Get idle percentage + * @return the lv_timer idle in percentage + */ +uint8_t lv_timer_get_idle(void); + +/** + * Iterate through the timers + * @param timer NULL to start iteration or the previous return value to get the next timer + * @return the next timer or NULL if there is no more timer + */ +lv_timer_t * lv_timer_get_next(lv_timer_t * timer); + +/********************** + * MACROS + **********************/ + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif diff --git a/src/lib/lvgl/src/misc/lv_tlsf.h b/src/lib/lvgl/src/misc/lv_tlsf.h new file mode 100644 index 0000000..9380ee8 --- /dev/null +++ b/src/lib/lvgl/src/misc/lv_tlsf.h @@ -0,0 +1,95 @@ +#include "../lv_conf_internal.h" +#if LV_MEM_CUSTOM == 0 + +#ifndef LV_TLSF_H +#define LV_TLSF_H + +/* +** Two Level Segregated Fit memory allocator, version 3.1. +** Written by Matthew Conte +** http://tlsf.baisoku.org +** +** Based on the original documentation by Miguel Masmano: +** http://www.gii.upv.es/tlsf/main/docs +** +** This implementation was written to the specification +** of the document, therefore no GPL restrictions apply. +** +** Copyright (c) 2006-2016, Matthew Conte +** All rights reserved. +** +** Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** * Neither the name of the copyright holder nor the +** names of its contributors may be used to endorse or promote products +** derived from this software without specific prior written permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +** WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +** DISCLAIMED. IN NO EVENT SHALL MATTHEW CONTE BE LIABLE FOR ANY +** DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +** (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +** LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +** ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +** SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include + +#if defined(__cplusplus) +extern "C" { +#endif + +/* lv_tlsf_t: a TLSF structure. Can contain 1 to N pools. */ +/* lv_pool_t: a block of memory that TLSF can manage. */ +typedef void * lv_tlsf_t; +typedef void * lv_pool_t; + +/* Create/destroy a memory pool. */ +lv_tlsf_t lv_tlsf_create(void * mem); +lv_tlsf_t lv_tlsf_create_with_pool(void * mem, size_t bytes); +void lv_tlsf_destroy(lv_tlsf_t tlsf); +lv_pool_t lv_tlsf_get_pool(lv_tlsf_t tlsf); + +/* Add/remove memory pools. */ +lv_pool_t lv_tlsf_add_pool(lv_tlsf_t tlsf, void * mem, size_t bytes); +void lv_tlsf_remove_pool(lv_tlsf_t tlsf, lv_pool_t pool); + +/* malloc/memalign/realloc/free replacements. */ +void * lv_tlsf_malloc(lv_tlsf_t tlsf, size_t bytes); +void * lv_tlsf_memalign(lv_tlsf_t tlsf, size_t align, size_t bytes); +void * lv_tlsf_realloc(lv_tlsf_t tlsf, void * ptr, size_t size); +void lv_tlsf_free(lv_tlsf_t tlsf, const void * ptr); + +/* Returns internal block size, not original request size */ +size_t lv_tlsf_block_size(void * ptr); + +/* Overheads/limits of internal structures. */ +size_t lv_tlsf_size(void); +size_t lv_tlsf_align_size(void); +size_t lv_tlsf_block_size_min(void); +size_t lv_tlsf_block_size_max(void); +size_t lv_tlsf_pool_overhead(void); +size_t lv_tlsf_alloc_overhead(void); + +/* Debugging. */ +typedef void (*lv_tlsf_walker)(void * ptr, size_t size, int used, void * user); +void lv_tlsf_walk_pool(lv_pool_t pool, lv_tlsf_walker walker, void * user); +/* Returns nonzero if any internal consistency check fails. */ +int lv_tlsf_check(lv_tlsf_t tlsf); +int lv_tlsf_check_pool(lv_pool_t pool); + +#if defined(__cplusplus) +}; +#endif + +#endif /*LV_TLSF_H*/ + +#endif /* LV_MEM_CUSTOM == 0 */ diff --git a/src/lib/lvgl/src/misc/lv_txt.h b/src/lib/lvgl/src/misc/lv_txt.h new file mode 100644 index 0000000..4f134ab --- /dev/null +++ b/src/lib/lvgl/src/misc/lv_txt.h @@ -0,0 +1,264 @@ +/** + * @file lv_txt.h + * + */ + +#ifndef LV_TXT_H +#define LV_TXT_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include "../lv_conf_internal.h" + +#include +#include +#include "lv_area.h" +#include "../font/lv_font.h" +#include "lv_printf.h" +#include "lv_types.h" + +/********************* + * DEFINES + *********************/ +#ifndef LV_TXT_COLOR_CMD +#define LV_TXT_COLOR_CMD "#" +#endif + +#define LV_TXT_ENC_UTF8 1 +#define LV_TXT_ENC_ASCII 2 + +/********************** + * TYPEDEFS + **********************/ + +/** + * Options for text rendering. + */ +enum { + LV_TEXT_FLAG_NONE = 0x00, + LV_TEXT_FLAG_RECOLOR = 0x01, /**< Enable parsing of recolor command*/ + LV_TEXT_FLAG_EXPAND = 0x02, /**< Ignore max-width to avoid automatic word wrapping*/ + LV_TEXT_FLAG_FIT = 0x04, /**< Max-width is already equal to the longest line. (Used to skip some calculation)*/ +}; +typedef uint8_t lv_text_flag_t; + +/** + * State machine for text renderer.*/ +enum { + LV_TEXT_CMD_STATE_WAIT, /**< Waiting for command*/ + LV_TEXT_CMD_STATE_PAR, /**< Processing the parameter*/ + LV_TEXT_CMD_STATE_IN, /**< Processing the command*/ +}; +typedef uint8_t lv_text_cmd_state_t; + +/** Label align policy*/ +enum { + LV_TEXT_ALIGN_AUTO, /**< Align text auto*/ + LV_TEXT_ALIGN_LEFT, /**< Align text to left*/ + LV_TEXT_ALIGN_CENTER, /**< Align text to center*/ + LV_TEXT_ALIGN_RIGHT, /**< Align text to right*/ +}; +typedef uint8_t lv_text_align_t; + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +/** + * Get size of a text + * @param size_res pointer to a 'point_t' variable to store the result + * @param text pointer to a text + * @param font pointer to font of the text + * @param letter_space letter space of the text + * @param line_space line space of the text + * @param flags settings for the text from ::lv_text_flag_t + * @param max_width max with of the text (break the lines to fit this size) Set CORD_MAX to avoid + * line breaks + */ +void lv_txt_get_size(lv_point_t * size_res, const char * text, const lv_font_t * font, lv_coord_t letter_space, + lv_coord_t line_space, lv_coord_t max_width, lv_text_flag_t flag); + +/** + * Get the next line of text. Check line length and break chars too. + * @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 used_width When used_width != NULL, save the width of this line if + * flag == LV_TEXT_FLAG_NONE, otherwise save -1. + * @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) + */ +uint32_t _lv_txt_get_next_line(const char * txt, const lv_font_t * font, lv_coord_t letter_space, + lv_coord_t max_width, lv_coord_t * used_width, lv_text_flag_t flag); + +/** + * Give the length of a text with a given font + * @param txt a '\0' terminate string + * @param length length of 'txt' in byte count and not characters (Á is 1 character but 2 bytes in + * UTF-8) + * @param font pointer to a font + * @param letter_space letter space + * @param flags settings for the text from 'txt_flag_t' enum + * @return length of a char_num long text + */ +lv_coord_t lv_txt_get_width(const char * txt, uint32_t length, const lv_font_t * font, lv_coord_t letter_space, + lv_text_flag_t flag); + +/** + * Check next character in a string and decide if the character is part of the command or not + * @param state pointer to a txt_cmd_state_t variable which stores the current state of command + * processing + * @param c the current character + * @return true: the character is part of a command and should not be written, + * false: the character should be written + */ +bool _lv_txt_is_cmd(lv_text_cmd_state_t * state, uint32_t c); + +/** + * Insert a string into an other + * @param txt_buf the original text (must be big enough for the result text and NULL terminated) + * @param pos position to insert (0: before the original text, 1: after the first char etc.) + * @param ins_txt text to insert, must be '\0' terminated + */ +void _lv_txt_ins(char * txt_buf, uint32_t pos, const char * ins_txt); + +/** + * Delete a part of a string + * @param txt string to modify, must be '\0' terminated and should point to a heap or stack frame, not read-only memory. + * @param pos position where to start the deleting (0: before the first char, 1: after the first + * char etc.) + * @param len number of characters to delete + */ +void _lv_txt_cut(char * txt, uint32_t pos, uint32_t len); + +/** + * return a new formatted text. Memory will be allocated to store the text. + * @param fmt `printf`-like format + * @return pointer to the allocated text string. + */ +char * _lv_txt_set_text_vfmt(const char * fmt, va_list ap) LV_FORMAT_ATTRIBUTE(1, 0); + +/** + * Decode two encoded character from a string. + * @param txt pointer to '\0' terminated string + * @param letter the first decoded Unicode character or 0 on invalid data code + * @param letter_next the second decoded Unicode character or 0 on invalid data code + * @param ofs start index in 'txt' where to start. + * After the call it will point to the next encoded char in 'txt'. + * NULL to use txt[0] as index + */ +void _lv_txt_encoded_letter_next_2(const char * txt, uint32_t * letter, uint32_t * letter_next, uint32_t * ofs); + +/** + * Test if char is break char or not (a text can broken here or not) + * @param letter a letter + * @return false: 'letter' is not break char + */ +static inline bool _lv_txt_is_break_char(uint32_t letter) +{ + uint8_t i; + bool ret = false; + + /* each chinese character can be break */ + if(letter >= 0x4E00 && letter <= 0x9FA5) { + return true; + } + + /*Compare the letter to TXT_BREAK_CHARS*/ + for(i = 0; LV_TXT_BREAK_CHARS[i] != '\0'; i++) { + if(letter == (uint32_t)LV_TXT_BREAK_CHARS[i]) { + ret = true; /*If match then it is break char*/ + break; + } + } + + return ret; +} + +/*************************************************************** + * GLOBAL FUNCTION POINTERS FOR CHARACTER ENCODING INTERFACE + ***************************************************************/ + +/** + * Give the size of an encoded character + * @param str pointer to a character in a string + * @return length of the encoded character (1,2,3 ...). O in invalid + */ +extern uint8_t (*_lv_txt_encoded_size)(const char *); + +/** + * Convert an Unicode letter to encoded + * @param letter_uni an Unicode letter + * @return Encoded character in Little Endian to be compatible with C chars (e.g. 'Á', 'Ü') + */ +extern uint32_t (*_lv_txt_unicode_to_encoded)(uint32_t); + +/** + * Convert a wide character, e.g. 'Á' little endian to be compatible with the encoded format. + * @param c a wide character + * @return `c` in the encoded format + */ +extern uint32_t (*_lv_txt_encoded_conv_wc)(uint32_t c); + +/** + * Decode the next encoded character from a string. + * @param txt pointer to '\0' terminated string + * @param i start index in 'txt' where to start. + * After the call it will point to the next encoded char in 'txt'. + * NULL to use txt[0] as index + * @return the decoded Unicode character or 0 on invalid data code + */ +extern uint32_t (*_lv_txt_encoded_next)(const char *, uint32_t *); + +/** + * Get the previous encoded character form a string. + * @param txt pointer to '\0' terminated string + * @param i_start index in 'txt' where to start. After the call it will point to the previous + * encoded char in 'txt'. + * @return the decoded Unicode character or 0 on invalid data + */ +extern uint32_t (*_lv_txt_encoded_prev)(const char *, uint32_t *); + +/** + * Convert a letter index (in the encoded text) to byte index. + * E.g. in UTF-8 "AÁRT" index of 'R' is 2 but start at byte 3 because 'Á' is 2 bytes long + * @param txt a '\0' terminated UTF-8 string + * @param enc_id letter index + * @return byte index of the 'enc_id'th letter + */ +extern uint32_t (*_lv_txt_encoded_get_byte_id)(const char *, uint32_t); + +/** + * Convert a byte index (in an encoded text) to character index. + * E.g. in UTF-8 "AÁRT" index of 'R' is 2 but start at byte 3 because 'Á' is 2 bytes long + * @param txt a '\0' terminated UTF-8 string + * @param byte_id byte index + * @return character index of the letter at 'byte_id'th position + */ +extern uint32_t (*_lv_txt_encoded_get_char_id)(const char *, uint32_t); + +/** + * Get the number of characters (and NOT bytes) in a string. + * E.g. in UTF-8 "ÁBC" is 3 characters (but 4 bytes) + * @param txt a '\0' terminated char string + * @return number of characters + */ +extern uint32_t (*_lv_txt_get_encoded_length)(const char *); + +/********************** + * MACROS + **********************/ + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif /*LV_TXT_H*/ diff --git a/src/lib/lvgl/src/misc/lv_txt_ap.h b/src/lib/lvgl/src/misc/lv_txt_ap.h new file mode 100644 index 0000000..e2d94b8 --- /dev/null +++ b/src/lib/lvgl/src/misc/lv_txt_ap.h @@ -0,0 +1,49 @@ +/** + * @file lv_txt_ap.h + * + */ + +#ifndef LV_TXT_AP_H +#define LV_TXT_AP_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include +#include "lv_txt.h" +#include "../draw/lv_draw.h" + +#if LV_USE_ARABIC_PERSIAN_CHARS == 1 + +/********************* + * DEFINES + *********************/ + +#define LV_UNDEF_ARABIC_PERSIAN_CHARS (UINT32_MAX) +#define LV_AP_ALPHABET_BASE_CODE 0x0622 +#define LV_AP_END_CHARS_LIST {0,0,0,0,0,{0,0}} +/********************** + * TYPEDEFS + **********************/ + +/********************** + * GLOBAL PROTOTYPES + **********************/ +uint32_t _lv_txt_ap_calc_bytes_cnt(const char * txt); +void _lv_txt_ap_proc(const char * txt, char * txt_out); + +/********************** + * MACROS + **********************/ + +#endif // LV_USE_ARABIC_PERSIAN_CHARS + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif /*LV_TXT_AP_H*/ diff --git a/src/lib/lvgl/src/misc/lv_types.h b/src/lib/lvgl/src/misc/lv_types.h new file mode 100644 index 0000000..9f8ef4c --- /dev/null +++ b/src/lib/lvgl/src/misc/lv_types.h @@ -0,0 +1,94 @@ +/** + * @file lv_types.h + * + */ + +#ifndef LV_TYPES_H +#define LV_TYPES_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include + +/********************* + * DEFINES + *********************/ + +// If __UINTPTR_MAX__ or UINTPTR_MAX are available, use them to determine arch size +#if defined(__UINTPTR_MAX__) && __UINTPTR_MAX__ > 0xFFFFFFFF +#define LV_ARCH_64 + +#elif defined(UINTPTR_MAX) && UINTPTR_MAX > 0xFFFFFFFF +#define LV_ARCH_64 + +// Otherwise use compiler-dependent means to determine arch size +#elif defined(_WIN64) || defined(__x86_64__) || defined(__ppc64__) || defined (__aarch64__) +#define LV_ARCH_64 + +#endif + +/********************** + * TYPEDEFS + **********************/ + +/** + * LVGL error codes. + */ +enum { + LV_RES_INV = 0, /*Typically indicates that the object is deleted (become invalid) in the action + function or an operation was failed*/ + LV_RES_OK, /*The object is valid (no deleted) after the action*/ +}; +typedef uint8_t lv_res_t; + +#if defined(__cplusplus) || __STDC_VERSION__ >= 199901L +// If c99 or newer, use the definition of uintptr_t directly from +typedef uintptr_t lv_uintptr_t; + +#else + +// Otherwise, use the arch size determination +#ifdef LV_ARCH_64 +typedef uint64_t lv_uintptr_t; +#else +typedef uint32_t lv_uintptr_t; +#endif + +#endif + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +/********************** + * MACROS + **********************/ + +#define LV_UNUSED(x) ((void)x) + +#define _LV_CONCAT(x, y) x ## y +#define LV_CONCAT(x, y) _LV_CONCAT(x, y) + +#define _LV_CONCAT3(x, y, z) x ## y ## z +#define LV_CONCAT3(x, y, z) _LV_CONCAT3(x, y, z) + +#if defined(PYCPARSER) +#define LV_FORMAT_ATTRIBUTE(fmtstr, vararg) +#elif defined(__GNUC__) && ((__GNUC__ == 4 && __GNUC_MINOR__ >= 4) || __GNUC__ > 4) +#define LV_FORMAT_ATTRIBUTE(fmtstr, vararg) __attribute__((format(gnu_printf, fmtstr, vararg))) +#elif (defined(__clang__) || defined(__GNUC__) || defined(__GNUG__)) +#define LV_FORMAT_ATTRIBUTE(fmtstr, vararg) __attribute__((format(printf, fmtstr, vararg))) +#else +#define LV_FORMAT_ATTRIBUTE(fmtstr, vararg) +#endif + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif /*LV_TYPES_H*/ diff --git a/src/lib/lvgl/src/misc/lv_utils.h b/src/lib/lvgl/src/misc/lv_utils.h new file mode 100644 index 0000000..84d2bb9 --- /dev/null +++ b/src/lib/lvgl/src/misc/lv_utils.h @@ -0,0 +1,58 @@ +/** + * @file lv_utils.h + * + */ + +#ifndef LV_UTILS_H +#define LV_UTILS_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +/** Searches base[0] to base[n - 1] for an item that matches *key. + * + * @note The function cmp must return negative if it's first + * argument (the search key) is less that it's second (a table entry), + * zero if equal, and positive if greater. + * + * @note Items in the array must be in ascending order. + * + * @param key Pointer to item being searched for + * @param base Pointer to first element to search + * @param n Number of elements + * @param size Size of each element + * @param cmp Pointer to comparison function (see #unicode_list_compare as a comparison function + * example) + * + * @return a pointer to a matching item, or NULL if none exists. + */ +void * _lv_utils_bsearch(const void * key, const void * base, uint32_t n, uint32_t size, + int32_t (*cmp)(const void * pRef, const void * pElement)); + +/********************** + * MACROS + **********************/ + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif diff --git a/src/lib/lvgl/src/widgets/lv_arc.h b/src/lib/lvgl/src/widgets/lv_arc.h new file mode 100644 index 0000000..8ec39a4 --- /dev/null +++ b/src/lib/lvgl/src/widgets/lv_arc.h @@ -0,0 +1,240 @@ +/** + * @file lv_arc.h + * + */ + +#ifndef LV_ARC_H +#define LV_ARC_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include "../lv_conf_internal.h" + +#if LV_USE_ARC != 0 + +#include "../core/lv_obj.h" + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +enum { + LV_ARC_MODE_NORMAL, + LV_ARC_MODE_SYMMETRICAL, + LV_ARC_MODE_REVERSE +}; +typedef uint8_t lv_arc_mode_t; + +typedef struct { + lv_obj_t obj; + uint16_t rotation; + uint16_t indic_angle_start; + uint16_t indic_angle_end; + uint16_t bg_angle_start; + uint16_t bg_angle_end; + int16_t value; /*Current value of the arc*/ + int16_t min_value; /*Minimum value of the arc*/ + int16_t max_value; /*Maximum value of the arc*/ + uint16_t dragging : 1; + uint16_t type : 2; + uint16_t min_close : 1; /*1: the last pressed angle was closer to minimum end*/ + uint16_t chg_rate; /*Drag angle rate of change of the arc (degrees/sec)*/ + uint32_t last_tick; /*Last dragging event timestamp of the arc*/ + int16_t last_angle; /*Last dragging angle of the arc*/ +} lv_arc_t; + +extern const lv_obj_class_t lv_arc_class; + +/** + * `type` field in `lv_obj_draw_part_dsc_t` if `class_p = lv_arc_class` + * Used in `LV_EVENT_DRAW_PART_BEGIN` and `LV_EVENT_DRAW_PART_END` + */ +typedef enum { + LV_ARC_DRAW_PART_BACKGROUND, /**< The background arc*/ + LV_ARC_DRAW_PART_FOREGROUND, /**< The foreground arc*/ + LV_ARC_DRAW_PART_KNOB, /**< The knob*/ +} lv_arc_draw_part_type_t; + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +/** + * Create an arc object + * @param parent pointer to an object, it will be the parent of the new arc + * @return pointer to the created arc + */ +lv_obj_t * lv_arc_create(lv_obj_t * parent); + +/*====================== + * Add/remove functions + *=====================*/ + +/*===================== + * Setter functions + *====================*/ + +/** + * Set the start angle of an arc. 0 deg: right, 90 bottom, etc. + * @param arc pointer to an arc object + * @param start the start angle + */ +void lv_arc_set_start_angle(lv_obj_t * arc, uint16_t start); + +/** + * Set the end angle of an arc. 0 deg: right, 90 bottom, etc. + * @param arc pointer to an arc object + * @param end the end angle + */ +void lv_arc_set_end_angle(lv_obj_t * arc, uint16_t end); + +/** + * Set the start and end angles + * @param arc pointer to an arc object + * @param start the start angle + * @param end the end angle + */ +void lv_arc_set_angles(lv_obj_t * arc, uint16_t start, uint16_t end); + +/** + * Set the start angle of an arc background. 0 deg: right, 90 bottom, etc. + * @param arc pointer to an arc object + * @param start the start angle + */ +void lv_arc_set_bg_start_angle(lv_obj_t * arc, uint16_t start); + +/** + * Set the start angle of an arc background. 0 deg: right, 90 bottom etc. + * @param arc pointer to an arc object + * @param end the end angle + */ +void lv_arc_set_bg_end_angle(lv_obj_t * arc, uint16_t end); + +/** + * Set the start and end angles of the arc background + * @param arc pointer to an arc object + * @param start the start angle + * @param end the end angle + */ +void lv_arc_set_bg_angles(lv_obj_t * arc, uint16_t start, uint16_t end); + +/** + * Set the rotation for the whole arc + * @param arc pointer to an arc object + * @param rotation rotation angle + */ +void lv_arc_set_rotation(lv_obj_t * arc, uint16_t rotation); + +/** + * Set the type of arc. + * @param arc pointer to arc object + * @param mode arc's mode + */ +void lv_arc_set_mode(lv_obj_t * arc, lv_arc_mode_t type); + +/** + * Set a new value on the arc + * @param arc pointer to an arc object + * @param value new value + */ +void lv_arc_set_value(lv_obj_t * arc, int16_t value); + +/** + * Set minimum and the maximum values of an arc + * @param arc pointer to the arc object + * @param min minimum value + * @param max maximum value + */ +void lv_arc_set_range(lv_obj_t * arc, int16_t min, int16_t max); + +/** + * Set a change rate to limit the speed how fast the arc should reach the pressed point. + * @param arc pointer to an arc object + * @param rate the change rate + */ +void lv_arc_set_change_rate(lv_obj_t * arc, uint16_t rate); + +/*===================== + * Getter functions + *====================*/ + +/** + * Get the start angle of an arc. + * @param arc pointer to an arc object + * @return the start angle [0..360] + */ +uint16_t lv_arc_get_angle_start(lv_obj_t * obj); + +/** + * Get the end angle of an arc. + * @param arc pointer to an arc object + * @return the end angle [0..360] + */ +uint16_t lv_arc_get_angle_end(lv_obj_t * obj); + +/** + * Get the start angle of an arc background. + * @param arc pointer to an arc object + * @return the start angle [0..360] + */ +uint16_t lv_arc_get_bg_angle_start(lv_obj_t * obj); + +/** + * Get the end angle of an arc background. + * @param arc pointer to an arc object + * @return the end angle [0..360] + */ +uint16_t lv_arc_get_bg_angle_end(lv_obj_t * obj); + +/** + * Get the value of an arc + * @param arc pointer to an arc object + * @return the value of the arc + */ +int16_t lv_arc_get_value(const lv_obj_t * obj); + +/** + * Get the minimum value of an arc + * @param arc pointer to an arc object + * @return the minimum value of the arc + */ +int16_t lv_arc_get_min_value(const lv_obj_t * obj); + +/** + * Get the maximum value of an arc + * @param arc pointer to an arc object + * @return the maximum value of the arc + */ +int16_t lv_arc_get_max_value(const lv_obj_t * obj); + +/** + * Get whether the arc is type or not. + * @param arc pointer to an arc object + * @return arc's mode + */ +lv_arc_mode_t lv_arc_get_mode(const lv_obj_t * obj); + +/*===================== + * Other functions + *====================*/ + +/********************** + * MACROS + **********************/ + +#endif /*LV_USE_ARC*/ + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif /*LV_ARC_H*/ diff --git a/src/lib/lvgl/src/widgets/lv_bar.h b/src/lib/lvgl/src/widgets/lv_bar.h new file mode 100644 index 0000000..1726425 --- /dev/null +++ b/src/lib/lvgl/src/widgets/lv_bar.h @@ -0,0 +1,164 @@ +/** + * @file lv_bar.h + * + */ + +#ifndef LV_BAR_H +#define LV_BAR_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include "../lv_conf_internal.h" + +#if LV_USE_BAR != 0 + +#include "../core/lv_obj.h" +#include "../misc/lv_anim.h" +#include "lv_btn.h" +#include "lv_label.h" + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +enum { + LV_BAR_MODE_NORMAL, + LV_BAR_MODE_SYMMETRICAL, + LV_BAR_MODE_RANGE +}; +typedef uint8_t lv_bar_mode_t; + +typedef struct { + lv_obj_t * bar; + int32_t anim_start; + int32_t anim_end; + int32_t anim_state; +} _lv_bar_anim_t; + +typedef struct { + lv_obj_t obj; + int32_t cur_value; /**< Current value of the bar*/ + int32_t min_value; /**< Minimum value of the bar*/ + int32_t max_value; /**< Maximum value of the bar*/ + int32_t start_value; /**< Start value of the bar*/ + lv_area_t indic_area; /**< Save the indicator area. Might be used by derived types*/ + _lv_bar_anim_t cur_value_anim; + _lv_bar_anim_t start_value_anim; + lv_bar_mode_t mode : 2; /**< Type of bar*/ +} lv_bar_t; + +extern const lv_obj_class_t lv_bar_class; + +/** + * `type` field in `lv_obj_draw_part_dsc_t` if `class_p = lv_bar_class` + * Used in `LV_EVENT_DRAW_PART_BEGIN` and `LV_EVENT_DRAW_PART_END` + */ +typedef enum { + LV_BAR_DRAW_PART_INDICATOR, /**< The indicator*/ +} lv_bar_draw_part_type_t; + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +/** + * Create a bar object + * @param parent pointer to an object, it will be the parent of the new bar + * @return pointer to the created bar + */ +lv_obj_t * lv_bar_create(lv_obj_t * parent); + +/*===================== + * Setter functions + *====================*/ + +/** + * Set a new value on the bar + * @param bar pointer to a bar object + * @param value new value + * @param anim LV_ANIM_ON: set the value with an animation; LV_ANIM_OFF: change the value immediately + */ +void lv_bar_set_value(lv_obj_t * obj, int32_t value, lv_anim_enable_t anim); + +/** + * Set a new start value on the bar + * @param obj pointer to a bar object + * @param value new start value + * @param anim LV_ANIM_ON: set the value with an animation; LV_ANIM_OFF: change the value immediately + */ +void lv_bar_set_start_value(lv_obj_t * obj, int32_t start_value, lv_anim_enable_t anim); + +/** + * Set minimum and the maximum values of a bar + * @param obj pointer to the bar object + * @param min minimum value + * @param max maximum value + */ +void lv_bar_set_range(lv_obj_t * obj, int32_t min, int32_t max); + +/** + * Set the type of bar. + * @param obj pointer to bar object + * @param mode bar type from ::lv_bar_mode_t + */ +void lv_bar_set_mode(lv_obj_t * obj, lv_bar_mode_t mode); + +/*===================== + * Getter functions + *====================*/ + +/** + * Get the value of a bar + * @param obj pointer to a bar object + * @return the value of the bar + */ +int32_t lv_bar_get_value(const lv_obj_t * obj); + +/** + * Get the start value of a bar + * @param obj pointer to a bar object + * @return the start value of the bar + */ +int32_t lv_bar_get_start_value(const lv_obj_t * obj); + +/** + * Get the minimum value of a bar + * @param obj pointer to a bar object + * @return the minimum value of the bar + */ +int32_t lv_bar_get_min_value(const lv_obj_t * obj); + +/** + * Get the maximum value of a bar + * @param obj pointer to a bar object + * @return the maximum value of the bar + */ +int32_t lv_bar_get_max_value(const lv_obj_t * obj); + +/** + * Get the type of bar. + * @param obj pointer to bar object + * @return bar type from ::lv_bar_mode_t + */ +lv_bar_mode_t lv_bar_get_mode(lv_obj_t * obj); + +/********************** + * MACROS + **********************/ + +#endif /*LV_USE_BAR*/ + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif /*LV_BAR_H*/ diff --git a/src/lib/lvgl/src/widgets/lv_btn.h b/src/lib/lvgl/src/widgets/lv_btn.h new file mode 100644 index 0000000..1d471f9 --- /dev/null +++ b/src/lib/lvgl/src/widgets/lv_btn.h @@ -0,0 +1,56 @@ +/** + * @file lv_btn.h + * + */ + +#ifndef LV_BTN_H +#define LV_BTN_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include "../lv_conf_internal.h" + +#if LV_USE_BTN != 0 +#include "../core/lv_obj.h" + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +typedef struct { + lv_obj_t obj; +} lv_btn_t; + +extern const lv_obj_class_t lv_btn_class; + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +/** + * Create a button object + * @param parent pointer to an object, it will be the parent of the new button + * @return pointer to the created button + */ +lv_obj_t * lv_btn_create(lv_obj_t * parent); + +/********************** + * MACROS + **********************/ + +#endif /*LV_USE_BTN*/ + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif /*LV_BTN_H*/ diff --git a/src/lib/lvgl/src/widgets/lv_btnmatrix.h b/src/lib/lvgl/src/widgets/lv_btnmatrix.h new file mode 100644 index 0000000..cf586d7 --- /dev/null +++ b/src/lib/lvgl/src/widgets/lv_btnmatrix.h @@ -0,0 +1,225 @@ +/** + * @file lv_btnmatrix.h + * + */ + +#ifndef LV_BTNMATRIX_H +#define LV_BTNMATRIX_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include "../lv_conf_internal.h" + +#if LV_USE_BTNMATRIX != 0 + +#include "../core/lv_obj.h" + +/********************* + * DEFINES + *********************/ +#define LV_BTNMATRIX_BTN_NONE 0xFFFF +LV_EXPORT_CONST_INT(LV_BTNMATRIX_BTN_NONE); + +/********************** + * TYPEDEFS + **********************/ + +/** Type to store button control bits (disabled, hidden etc.) + * The first 3 bits are used to store the width*/ +enum { + _LV_BTNMATRIX_WIDTH = 0x0007, /**< Reserved to stire the size units*/ + LV_BTNMATRIX_CTRL_HIDDEN = 0x0008, /**< Button hidden*/ + LV_BTNMATRIX_CTRL_NO_REPEAT = 0x0010, /**< Do not repeat press this button.*/ + LV_BTNMATRIX_CTRL_DISABLED = 0x0020, /**< Disable this button.*/ + LV_BTNMATRIX_CTRL_CHECKABLE = 0x0040, /**< The button can be toggled.*/ + LV_BTNMATRIX_CTRL_CHECKED = 0x0080, /**< Button is currently toggled (e.g. checked).*/ + LV_BTNMATRIX_CTRL_CLICK_TRIG = 0x0100, /**< 1: Send LV_EVENT_VALUE_CHANGE on CLICK, 0: Send LV_EVENT_VALUE_CHANGE on PRESS*/ + LV_BTNMATRIX_CTRL_POPOVER = 0x0200, /**< Show a popover when pressing this key*/ + LV_BTNMATRIX_CTRL_RECOLOR = 0x1000, /**< Enable text recoloring with `#color`*/ + _LV_BTNMATRIX_CTRL_RESERVED = 0x2000, /**< Reserved for later use*/ + LV_BTNMATRIX_CTRL_CUSTOM_1 = 0x4000, /**< Custom free to use flag*/ + LV_BTNMATRIX_CTRL_CUSTOM_2 = 0x8000, /**< Custom free to use flag*/ +}; + +typedef uint16_t lv_btnmatrix_ctrl_t; + +typedef bool (*lv_btnmatrix_btn_draw_cb_t)(lv_obj_t * btnm, uint32_t btn_id, const lv_area_t * draw_area, + const lv_area_t * clip_area); + +/*Data of button matrix*/ +typedef struct { + lv_obj_t obj; + const char ** map_p; /*Pointer to the current map*/ + lv_area_t * button_areas; /*Array of areas of buttons*/ + lv_btnmatrix_ctrl_t * ctrl_bits; /*Array of control bytes*/ + uint16_t btn_cnt; /*Number of button in 'map_p'(Handled by the library)*/ + uint16_t row_cnt; /*Number of rows in 'map_p'(Handled by the library)*/ + uint16_t btn_id_sel; /*Index of the active button (being pressed/released etc) or LV_BTNMATRIX_BTN_NONE*/ + uint8_t one_check : 1; /*Single button toggled at once*/ +} lv_btnmatrix_t; + +extern const lv_obj_class_t lv_btnmatrix_class; + +/** + * `type` field in `lv_obj_draw_part_dsc_t` if `class_p = lv_btnmatrix_class` + * Used in `LV_EVENT_DRAW_PART_BEGIN` and `LV_EVENT_DRAW_PART_END` + */ +typedef enum { + LV_BTNMATRIX_DRAW_PART_BTN, /**< The rectangle and label of buttons*/ +} lv_btnmatrix_draw_part_type_t; + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +/** + * Create a button matrix object + * @param parent pointer to an object, it will be the parent of the new button matrix + * @return pointer to the created button matrix + */ +lv_obj_t * lv_btnmatrix_create(lv_obj_t * parent); + +/*===================== + * Setter functions + *====================*/ + +/** + * Set a new map. Buttons will be created/deleted according to the map. The + * button matrix keeps a reference to the map and so the string array must not + * be deallocated during the life of the matrix. + * @param obj pointer to a button matrix object + * @param map pointer a string array. The last string has to be: "". Use "\n" to make a line break. + */ +void lv_btnmatrix_set_map(lv_obj_t * obj, const char * map[]); + +/** + * Set the button control map (hidden, disabled etc.) for a button matrix. + * The control map array will be copied and so may be deallocated after this + * function returns. + * @param obj pointer to a button matrix object + * @param ctrl_map pointer to an array of `lv_btn_ctrl_t` control bytes. The + * length of the array and position of the elements must match + * the number and order of the individual buttons (i.e. excludes + * newline entries). + * An element of the map should look like e.g.: + * `ctrl_map[0] = width | LV_BTNMATRIX_CTRL_NO_REPEAT | LV_BTNMATRIX_CTRL_TGL_ENABLE` + */ +void lv_btnmatrix_set_ctrl_map(lv_obj_t * obj, const lv_btnmatrix_ctrl_t ctrl_map[]); + +/** + * Set the selected buttons + * @param obj pointer to button matrix object + * @param btn_id 0 based index of the button to modify. (Not counting new lines) + */ +void lv_btnmatrix_set_selected_btn(lv_obj_t * obj, uint16_t btn_id); + +/** + * Set the attributes of a button of the button matrix + * @param obj pointer to button matrix object + * @param btn_id 0 based index of the button to modify. (Not counting new lines) + * @param ctrl OR-ed attributs. E.g. `LV_BTNMATRIX_CTRL_NO_REPEAT | LV_BTNMATRIX_CTRL_CHECKABLE` + */ +void lv_btnmatrix_set_btn_ctrl(lv_obj_t * obj, uint16_t btn_id, lv_btnmatrix_ctrl_t ctrl); + +/** + * Clear the attributes of a button of the button matrix + * @param obj pointer to button matrix object + * @param btn_id 0 based index of the button to modify. (Not counting new lines) + * @param ctrl OR-ed attributs. E.g. `LV_BTNMATRIX_CTRL_NO_REPEAT | LV_BTNMATRIX_CTRL_CHECKABLE` + */ +void lv_btnmatrix_clear_btn_ctrl(lv_obj_t * obj, uint16_t btn_id, lv_btnmatrix_ctrl_t ctrl); + +/** + * Set attributes of all buttons of a button matrix + * @param obj pointer to a button matrix object + * @param ctrl attribute(s) to set from `lv_btnmatrix_ctrl_t`. Values can be ORed. + */ +void lv_btnmatrix_set_btn_ctrl_all(lv_obj_t * obj, lv_btnmatrix_ctrl_t ctrl); + +/** + * Clear the attributes of all buttons of a button matrix + * @param obj pointer to a button matrix object + * @param ctrl attribute(s) to set from `lv_btnmatrix_ctrl_t`. Values can be ORed. + * @param en true: set the attributes; false: clear the attributes + */ +void lv_btnmatrix_clear_btn_ctrl_all(lv_obj_t * obj, lv_btnmatrix_ctrl_t ctrl); + +/** + * Set a single button's relative width. + * This method will cause the matrix be regenerated and is a relatively + * expensive operation. It is recommended that initial width be specified using + * `lv_btnmatrix_set_ctrl_map` and this method only be used for dynamic changes. + * @param obj pointer to button matrix object + * @param btn_id 0 based index of the button to modify. + * @param width relative width compared to the buttons in the same row. [1..7] + */ +void lv_btnmatrix_set_btn_width(lv_obj_t * obj, uint16_t btn_id, uint8_t width); + +/** + * Make the button matrix like a selector widget (only one button may be checked at a time). + * `LV_BTNMATRIX_CTRL_CHECKABLE` must be enabled on the buttons to be selected using + * `lv_btnmatrix_set_ctrl()` or `lv_btnmatrix_set_btn_ctrl_all()`. + * @param obj pointer to a button matrix object + * @param en whether "one check" mode is enabled + */ +void lv_btnmatrix_set_one_checked(lv_obj_t * obj, bool en); + +/*===================== + * Getter functions + *====================*/ + +/** + * Get the current map of a button matrix + * @param obj pointer to a button matrix object + * @return the current map + */ +const char ** lv_btnmatrix_get_map(const lv_obj_t * obj); + +/** + * Get the index of the lastly "activated" button by the user (pressed, released, focused etc) + * Useful in the `event_cb` to get the text of the button, check if hidden etc. + * @param obj pointer to button matrix object + * @return index of the last released button (LV_BTNMATRIX_BTN_NONE: if unset) + */ +uint16_t lv_btnmatrix_get_selected_btn(const lv_obj_t * obj); + +/** + * Get the button's text + * @param obj pointer to button matrix object + * @param btn_id the index a button not counting new line characters. + * @return text of btn_index` button + */ +const char * lv_btnmatrix_get_btn_text(const lv_obj_t * obj, uint16_t btn_id); + +/** + * Get the whether a control value is enabled or disabled for button of a button matrix + * @param obj pointer to a button matrix object + * @param btn_id the index of a button not counting new line characters. + * @param ctrl control values to check (ORed value can be used) + * @return true: the control attribute is enabled false: disabled + */ +bool lv_btnmatrix_has_btn_ctrl(lv_obj_t * obj, uint16_t btn_id, lv_btnmatrix_ctrl_t ctrl); + +/** + * Tell whether "one check" mode is enabled or not. + * @param obj Button matrix object + * @return true: "one check" mode is enabled; false: disabled + */ +bool lv_btnmatrix_get_one_checked(const lv_obj_t * obj); + +/********************** + * MACROS + **********************/ + +#endif /*LV_USE_BTNMATRIX*/ + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif /*LV_BTNMATRIX_H*/ diff --git a/src/lib/lvgl/src/widgets/lv_canvas.h b/src/lib/lvgl/src/widgets/lv_canvas.h new file mode 100644 index 0000000..71f0516 --- /dev/null +++ b/src/lib/lvgl/src/widgets/lv_canvas.h @@ -0,0 +1,280 @@ +/** + * @file lv_canvas.h + * + */ + +#ifndef LV_CANVAS_H +#define LV_CANVAS_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include "../lv_conf_internal.h" + +#if LV_USE_CANVAS != 0 + +#include "../core/lv_obj.h" +#include "../widgets/lv_img.h" +#include "../draw/lv_draw_img.h" + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ +extern const lv_obj_class_t lv_canvas_class; + +/*Data of canvas*/ +typedef struct { + lv_img_t img; + lv_img_dsc_t dsc; +} lv_canvas_t; + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +/** + * Create a canvas object + * @param parent pointer to an object, it will be the parent of the new canvas + * @return pointer to the created canvas + */ +lv_obj_t * lv_canvas_create(lv_obj_t * parent); + +/*===================== + * Setter functions + *====================*/ + +/** + * Set a buffer for the canvas. + * @param buf a buffer where the content of the canvas will be. + * The required size is (lv_img_color_format_get_px_size(cf) * w) / 8 * h) + * It can be allocated with `lv_mem_alloc()` or + * it can be statically allocated array (e.g. static lv_color_t buf[100*50]) or + * it can be an address in RAM or external SRAM + * @param canvas pointer to a canvas object + * @param w width of the canvas + * @param h height of the canvas + * @param cf color format. `LV_IMG_CF_...` + */ +void lv_canvas_set_buffer(lv_obj_t * canvas, void * buf, lv_coord_t w, lv_coord_t h, lv_img_cf_t cf); + +/** + * Set the color of a pixel on the canvas + * @param canvas + * @param x x coordinate of the point to set + * @param y x coordinate of the point to set + * @param c color of the pixel + */ +void lv_canvas_set_px_color(lv_obj_t * canvas, lv_coord_t x, lv_coord_t y, lv_color_t c); + +/** + * DEPRECATED: added only for backward compatibility + */ +static inline void lv_canvas_set_px(lv_obj_t * canvas, lv_coord_t x, lv_coord_t y, lv_color_t c) +{ + lv_canvas_set_px_color(canvas, x, y, c); +} + +/** + * Set the opacity of a pixel on the canvas + * @param canvas + * @param x x coordinate of the point to set + * @param y x coordinate of the point to set + * @param opa opacity of the pixel (0..255) + */ +void lv_canvas_set_px_opa(lv_obj_t * canvas, lv_coord_t x, lv_coord_t y, lv_opa_t opa); + + +/** + * Set the palette color of a canvas with index format. Valid only for `LV_IMG_CF_INDEXED1/2/4/8` + * @param canvas pointer to canvas object + * @param id the palette color to set: + * - for `LV_IMG_CF_INDEXED1`: 0..1 + * - for `LV_IMG_CF_INDEXED2`: 0..3 + * - for `LV_IMG_CF_INDEXED4`: 0..15 + * - for `LV_IMG_CF_INDEXED8`: 0..255 + * @param c the color to set + */ +void lv_canvas_set_palette(lv_obj_t * canvas, uint8_t id, lv_color_t c); + +/*===================== + * Getter functions + *====================*/ + +/** + * Get the color of a pixel on the canvas + * @param canvas + * @param x x coordinate of the point to set + * @param y x coordinate of the point to set + * @return color of the point + */ +lv_color_t lv_canvas_get_px(lv_obj_t * canvas, lv_coord_t x, lv_coord_t y); + +/** + * Get the image of the canvas as a pointer to an `lv_img_dsc_t` variable. + * @param canvas pointer to a canvas object + * @return pointer to the image descriptor. + */ +lv_img_dsc_t * lv_canvas_get_img(lv_obj_t * canvas); + +/*===================== + * Other functions + *====================*/ + +/** + * Copy a buffer to the canvas + * @param canvas pointer to a canvas object + * @param to_copy buffer to copy. The color format has to match with the canvas's buffer color + * format + * @param x left side of the destination position + * @param y top side of the destination position + * @param w width of the buffer to copy + * @param h height of the buffer to copy + */ +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); + +/** + * Transform and image and store the result on a canvas. + * @param canvas pointer to a canvas object to store the result of the transformation. + * @param img pointer to an image descriptor to transform. + * Can be the image descriptor of an other canvas too (`lv_canvas_get_img()`). + * @param angle the angle of rotation (0..3600), 0.1 deg resolution + * @param zoom zoom factor (256 no zoom); + * @param offset_x offset X to tell where to put the result data on destination canvas + * @param offset_y offset X to tell where to put the result data on destination canvas + * @param pivot_x pivot X of rotation. Relative to the source canvas + * Set to `source width / 2` to rotate around the center + * @param pivot_y pivot Y of rotation. Relative to the source canvas + * Set to `source height / 2` to rotate around the center + * @param antialias apply anti-aliasing during the transformation. Looks better but slower. + */ +void lv_canvas_transform(lv_obj_t * canvas, lv_img_dsc_t * img, int16_t angle, uint16_t zoom, lv_coord_t offset_x, + lv_coord_t offset_y, + int32_t pivot_x, int32_t pivot_y, bool antialias); + +/** + * Apply horizontal blur on the canvas + * @param canvas pointer to a canvas object + * @param area the area to blur. If `NULL` the whole canvas will be blurred. + * @param r radius of the blur + */ +void lv_canvas_blur_hor(lv_obj_t * canvas, const lv_area_t * area, uint16_t r); + +/** + * Apply vertical blur on the canvas + * @param canvas pointer to a canvas object + * @param area the area to blur. If `NULL` the whole canvas will be blurred. + * @param r radius of the blur + */ +void lv_canvas_blur_ver(lv_obj_t * canvas, const lv_area_t * area, uint16_t r); + +/** + * Fill the canvas with color + * @param canvas pointer to a canvas + * @param color the background color + * @param opa the desired opacity + */ +void lv_canvas_fill_bg(lv_obj_t * canvas, lv_color_t color, lv_opa_t opa); + +/** + * Draw a rectangle on the canvas + * @param canvas pointer to a canvas object + * @param x left coordinate of the rectangle + * @param y top coordinate of the rectangle + * @param w width of the rectangle + * @param h height of the rectangle + * @param draw_dsc descriptor of the rectangle + */ +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_draw_rect_dsc_t * draw_dsc); + +/** + * Draw a text on the canvas. + * @param canvas pointer to a canvas object + * @param x left coordinate of the text + * @param y top coordinate of the text + * @param max_w max width of the text. The text will be wrapped to fit into this size + * @param draw_dsc pointer to a valid label descriptor `lv_draw_label_dsc_t` + * @param txt text to display + */ +void lv_canvas_draw_text(lv_obj_t * canvas, lv_coord_t x, lv_coord_t y, lv_coord_t max_w, + lv_draw_label_dsc_t * draw_dsc, const char * txt); + +/** + * Draw an image on the canvas + * @param canvas pointer to a canvas object + * @param x left coordinate of the image + * @param y top coordinate of the image + * @param src image source. Can be a pointer an `lv_img_dsc_t` variable or a path an image. + * @param draw_dsc pointer to a valid label descriptor `lv_draw_img_dsc_t` + */ +void lv_canvas_draw_img(lv_obj_t * canvas, lv_coord_t x, lv_coord_t y, const void * src, + const lv_draw_img_dsc_t * draw_dsc); + +/** + * Draw a line on the canvas + * @param canvas pointer to a canvas object + * @param points point of the line + * @param point_cnt number of points + * @param draw_dsc pointer to an initialized `lv_draw_line_dsc_t` variable + */ +void lv_canvas_draw_line(lv_obj_t * canvas, const lv_point_t points[], uint32_t point_cnt, + const lv_draw_line_dsc_t * draw_dsc); + +/** + * Draw a polygon on the canvas + * @param canvas pointer to a canvas object + * @param points point of the polygon + * @param point_cnt number of points + * @param draw_dsc pointer to an initialized `lv_draw_rect_dsc_t` variable + */ +void lv_canvas_draw_polygon(lv_obj_t * canvas, const lv_point_t points[], uint32_t point_cnt, + const lv_draw_rect_dsc_t * draw_dsc); + +/** + * Draw an arc on the canvas + * @param canvas pointer to a canvas object + * @param x origo x of the arc + * @param y origo y of the arc + * @param r radius of the arc + * @param start_angle start angle in degrees + * @param end_angle end angle in degrees + * @param draw_dsc pointer to an initialized `lv_draw_line_dsc_t` variable + */ +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_draw_arc_dsc_t * draw_dsc); + +/********************** + * MACROS + **********************/ +#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) 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_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*/ + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif /*LV_CANVAS_H*/ diff --git a/src/lib/lvgl/src/widgets/lv_checkbox.h b/src/lib/lvgl/src/widgets/lv_checkbox.h new file mode 100644 index 0000000..772f500 --- /dev/null +++ b/src/lib/lvgl/src/widgets/lv_checkbox.h @@ -0,0 +1,97 @@ +/** + * @file lv_cb.h + * + */ + +#ifndef LV_CHECKBOX_H +#define LV_CHECKBOX_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include "../lv_conf_internal.h" +#include "../core/lv_obj.h" + +#if LV_USE_CHECKBOX != 0 + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +typedef struct { + lv_obj_t obj; + char * txt; + uint32_t static_txt : 1; +} lv_checkbox_t; + +extern const lv_obj_class_t lv_checkbox_class; + +/** + * `type` field in `lv_obj_draw_part_dsc_t` if `class_p = lv_checkbox_class` + * Used in `LV_EVENT_DRAW_PART_BEGIN` and `LV_EVENT_DRAW_PART_END` + */ +typedef enum { + LV_CHECKBOX_DRAW_PART_BOX, /**< The tick box*/ +} lv_checkbox_draw_part_type_t; + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +/** + * Create a check box object + * @param parent pointer to an object, it will be the parent of the new button + * @return pointer to the created check box + */ +lv_obj_t * lv_checkbox_create(lv_obj_t * parent); + +/*===================== + * Setter functions + *====================*/ + +/** + * Set the text of a check box. `txt` will be copied and may be deallocated + * after this function returns. + * @param cb pointer to a check box + * @param txt the text of the check box. NULL to refresh with the current text. + */ +void lv_checkbox_set_text(lv_obj_t * obj, const char * txt); + +/** + * Set the text of a check box. `txt` must not be deallocated during the life + * of this checkbox. + * @param cb pointer to a check box + * @param txt the text of the check box. + */ +void lv_checkbox_set_text_static(lv_obj_t * obj, const char * txt); + +/*===================== + * Getter functions + *====================*/ + +/** + * Get the text of a check box + * @param cb pointer to check box object + * @return pointer to the text of the check box + */ +const char * lv_checkbox_get_text(const lv_obj_t * obj); + +/********************** + * MACROS + **********************/ + +#endif /*LV_USE_CHECKBOX*/ + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif /*LV_CHECKBOX_H*/ diff --git a/src/lib/lvgl/src/widgets/lv_dropdown.h b/src/lib/lvgl/src/widgets/lv_dropdown.h new file mode 100644 index 0000000..63412f7 --- /dev/null +++ b/src/lib/lvgl/src/widgets/lv_dropdown.h @@ -0,0 +1,246 @@ +/** + * @file lv_dropdown.h + * + */ + +#ifndef LV_DROPDOWN_H +#define LV_DROPDOWN_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include "../lv_conf_internal.h" + +#if LV_USE_DROPDOWN != 0 + +/*Testing of dependencies*/ + +#if LV_USE_LABEL == 0 +#error "lv_dropdown: lv_label is required. Enable it in lv_conf.h (LV_USE_LABEL 1)" +#endif + +#include "../widgets/lv_label.h" + +/********************* + * DEFINES + *********************/ +#define LV_DROPDOWN_POS_LAST 0xFFFF +LV_EXPORT_CONST_INT(LV_DROPDOWN_POS_LAST); + +/********************** + * TYPEDEFS + **********************/ + +typedef struct { + lv_obj_t obj; + lv_obj_t * list; /**< The dropped down list*/ + const char * text; /**< Text to display on the dropdown's button*/ + const void * symbol; /**< Arrow or other icon when the drop-down list is closed*/ + char * options; /**< Options in a '\n' separated list*/ + uint16_t option_cnt; /**< Number of options*/ + uint16_t sel_opt_id; /**< Index of the currently selected option*/ + uint16_t sel_opt_id_orig; /**< Store the original index on focus*/ + uint16_t pr_opt_id; /**< Index of the currently pressed option*/ + lv_dir_t dir : 4; /**< Direction in which the list should open*/ + uint8_t static_txt : 1; /**< 1: Only a pointer is saved in `options`*/ + uint8_t selected_highlight: 1; /**< 1: Make the selected option highlighted in the list*/ +} lv_dropdown_t; + +typedef struct { + lv_obj_t obj; + lv_obj_t * dropdown; +} lv_dropdown_list_t; + +extern const lv_obj_class_t lv_dropdown_class; +extern const lv_obj_class_t lv_dropdownlist_class; + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +/** + * Create a drop-down list object + * @param parent pointer to an object, it will be the parent of the new drop-down list + * @return pointer to the created drop-down list + */ +lv_obj_t * lv_dropdown_create(lv_obj_t * parent); + +/*===================== + * Setter functions + *====================*/ + +/** + * Set text of the drop-down list's button. + * If set to `NULL` the selected option's text will be displayed on the button. + * If set to a specific text then that text will be shown regardless of the selected option. + * @param obj pointer to a drop-down list object + * @param txt the text as a string (Only its pointer is saved) + */ +void lv_dropdown_set_text(lv_obj_t * obj, const char * txt); + +/** + * Set the options in a drop-down list from a string. + * The options will be copied and saved in the object so the `options` can be destroyed after calling this function + * @param obj pointer to drop-down list object + * @param options a string with '\n' separated options. E.g. "One\nTwo\nThree" + */ +void lv_dropdown_set_options(lv_obj_t * obj, const char * options); + +/** + * Set the options in a drop-down list from a static string (global, static or dynamically allocated). + * Only the pointer of the option string will be saved. + * @param obj pointer to drop-down list object + * @param options a static string with '\n' separated options. E.g. "One\nTwo\nThree" + */ +void lv_dropdown_set_options_static(lv_obj_t * obj, const char * options); + +/** + * Add an options to a drop-down list from a string. Only works for non-static options. + * @param obj pointer to drop-down list object + * @param option a string without '\n'. E.g. "Four" + * @param pos the insert position, indexed from 0, LV_DROPDOWN_POS_LAST = end of string + */ +void lv_dropdown_add_option(lv_obj_t * obj, const char * option, uint32_t pos); + +/** + * Clear all options in a drop-down list. Works with both static and dynamic options. + * @param obj pointer to drop-down list object + */ +void lv_dropdown_clear_options(lv_obj_t * obj); + +/** + * Set the selected option + * @param obj pointer to drop-down list object + * @param sel_opt id of the selected option (0 ... number of option - 1); + */ +void lv_dropdown_set_selected(lv_obj_t * obj, uint16_t sel_opt); + +/** + * Set the direction of the a drop-down list + * @param obj pointer to a drop-down list object + * @param dir LV_DIR_LEFT/RIGHT/TOP/BOTTOM + */ +void lv_dropdown_set_dir(lv_obj_t * obj, lv_dir_t dir); + +/** + * Set an arrow or other symbol to display when on drop-down list's button. Typically a down caret or arrow. + * @param obj pointer to drop-down list object + * @param symbol a text like `LV_SYMBOL_DOWN`, an image (pointer or path) or NULL to not draw symbol icon + * @note angle and zoom transformation can be applied if the symbol is an image. + * E.g. when drop down is checked (opened) rotate the symbol by 180 degree + */ +void lv_dropdown_set_symbol(lv_obj_t * obj, const void * symbol); + +/** + * Set whether the selected option in the list should be highlighted or not + * @param obj pointer to drop-down list object + * @param en true: highlight enabled; false: disabled + */ +void lv_dropdown_set_selected_highlight(lv_obj_t * obj, bool en); + +/*===================== + * Getter functions + *====================*/ + +/** + * Get the list of a drop-down to allow styling or other modifications + * @param obj pointer to a drop-down list object + * @return pointer to the list of the drop-down + */ +lv_obj_t * lv_dropdown_get_list(lv_obj_t * obj); + +/** + * Get text of the drop-down list's button. + * @param obj pointer to a drop-down list object + * @return the text as string, `NULL` if no text + */ +const char * lv_dropdown_get_text(lv_obj_t * obj); + +/** + * Get the options of a drop-down list + * @param obj pointer to drop-down list object + * @return the options separated by '\n'-s (E.g. "Option1\nOption2\nOption3") + */ +const char * lv_dropdown_get_options(const lv_obj_t * obj); + +/** + * Get the index of the selected option + * @param obj pointer to drop-down list object + * @return index of the selected option (0 ... number of option - 1); + */ +uint16_t lv_dropdown_get_selected(const lv_obj_t * obj); + +/** + * Get the total number of options + * @param obj pointer to drop-down list object + * @return the total number of options in the list + */ +uint16_t lv_dropdown_get_option_cnt(const lv_obj_t * obj); + +/** + * Get the current selected option as a string + * @param obj pointer to drop-down object + * @param buf pointer to an array to store the string + * @param buf_size size of `buf` in bytes. 0: to ignore it. + */ +void lv_dropdown_get_selected_str(const lv_obj_t * obj, char * buf, uint32_t buf_size); + +/** + * Get the symbol on the drop-down list. Typically a down caret or arrow. + * @param obj pointer to drop-down list object + * @return the symbol or NULL if not enabled + */ +const char * lv_dropdown_get_symbol(lv_obj_t * obj); + +/** + * Get whether the selected option in the list should be highlighted or not + * @param obj pointer to drop-down list object + * @return true: highlight enabled; false: disabled + */ +bool lv_dropdown_get_selected_highlight(lv_obj_t * obj); + +/** + * Get the direction of the drop-down list + * @param obj pointer to a drop-down list object + * @return LV_DIR_LEF/RIGHT/TOP/BOTTOM + */ +lv_dir_t lv_dropdown_get_dir(const lv_obj_t * obj); + +/*===================== + * Other functions + *====================*/ + +/** + * Open the drop.down list + * @param obj pointer to drop-down list object + */ +void lv_dropdown_open(lv_obj_t * dropdown_obj); + +/** + * Close (Collapse) the drop-down list + * @param obj pointer to drop-down list object + */ +void lv_dropdown_close(lv_obj_t * obj); + +/** + * Tells whether the list is opened or not + * @param obj pointer to a drop-down list object + * @return true if the list os opened + */ +bool lv_dropdown_is_open(lv_obj_t * obj); + +/********************** + * MACROS + **********************/ + +#endif /*LV_USE_DROPDOWN*/ + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif /*LV_DROPDOWN_H*/ diff --git a/src/lib/lvgl/src/widgets/lv_img.h b/src/lib/lvgl/src/widgets/lv_img.h new file mode 100644 index 0000000..2a00564 --- /dev/null +++ b/src/lib/lvgl/src/widgets/lv_img.h @@ -0,0 +1,227 @@ +/** + * @file lv_img.h + * + */ + +#ifndef LV_IMG_H +#define LV_IMG_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include "../lv_conf_internal.h" + +#if LV_USE_IMG != 0 + +#include "../core/lv_obj.h" +#include "../misc/lv_fs.h" +#include "../draw/lv_draw.h" + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +/** + * Data of image + */ +typedef struct { + lv_obj_t obj; + const void * src; /*Image source: Pointer to an array or a file or a symbol*/ + lv_point_t offset; + lv_coord_t w; /*Width of the image (Handled by the library)*/ + lv_coord_t h; /*Height of the image (Handled by the library)*/ + uint16_t angle; /*rotation angle of the image*/ + lv_point_t pivot; /*rotation center of the image*/ + uint16_t zoom; /*256 means no zoom, 512 double size, 128 half size*/ + uint8_t src_type : 2; /*See: lv_img_src_t*/ + uint8_t cf : 5; /*Color format from `lv_img_color_format_t`*/ + uint8_t antialias : 1; /*Apply anti-aliasing in transformations (rotate, zoom)*/ + uint8_t obj_size_mode: 2; /*Image size mode when image size and object size is different.*/ +} lv_img_t; + +extern const lv_obj_class_t lv_img_class; + +/** + * Image size mode, when image size and object size is different + */ +enum { + /** Zoom doesn't affect the coordinates of the object, + * however if zoomed in the image is drawn out of the its coordinates. + * The layout's won't change on zoom */ + LV_IMG_SIZE_MODE_VIRTUAL = 0, + + /** If the object size is set to SIZE_CONTENT, then object size equals zoomed image size. + * It causes layout recalculation. + * If the object size is set explicitly, the image will be cropped when zoomed in.*/ + LV_IMG_SIZE_MODE_REAL, +}; + +typedef uint8_t lv_img_size_mode_t; + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +/** + * Create an image object + * @param parent pointer to an object, it will be the parent of the new image + * @return pointer to the created image + */ +lv_obj_t * lv_img_create(lv_obj_t * parent); + +/*===================== + * Setter functions + *====================*/ + +/** + * Set the image data to display on the object + * @param obj pointer to an image object + * @param src_img 1) pointer to an ::lv_img_dsc_t descriptor (converted by LVGL's image converter) (e.g. &my_img) or + * 2) path to an image file (e.g. "S:/dir/img.bin")or + * 3) a SYMBOL (e.g. LV_SYMBOL_OK) + */ +void lv_img_set_src(lv_obj_t * obj, const void * src); + +/** + * Set an offset for the source of an image so the image will be displayed from the new origin. + * @param obj pointer to an image + * @param x the new offset along x axis. + */ +void lv_img_set_offset_x(lv_obj_t * obj, lv_coord_t x); + +/** + * Set an offset for the source of an image. + * so the image will be displayed from the new origin. + * @param obj pointer to an image + * @param y the new offset along y axis. + */ +void lv_img_set_offset_y(lv_obj_t * obj, lv_coord_t y); + + +/** + * Set the rotation angle of the image. + * The image will be rotated around the set pivot set by `lv_img_set_pivot()` + * @param obj pointer to an image object + * @param angle rotation angle in degree with 0.1 degree resolution (0..3600: clock wise) + */ +void lv_img_set_angle(lv_obj_t * obj, int16_t angle); + +/** + * Set the rotation center of the image. + * The image will be rotated around this point + * @param obj pointer to an image object + * @param x rotation center x of the image + * @param y rotation center y of the image + */ +void lv_img_set_pivot(lv_obj_t * obj, lv_coord_t x, lv_coord_t y); + + +/** + * Set the zoom factor of the image. + * @param img pointer to an image object + * @param zoom the zoom factor. + * @example 256 or LV_ZOOM_IMG_NONE for no zoom + * @example <256: scale down + * @example >256 scale up + * @example 128 half size + * @example 512 double size + */ +void lv_img_set_zoom(lv_obj_t * obj, uint16_t zoom); + +/** + * Enable/disable anti-aliasing for the transformations (rotate, zoom) or not. + * The quality is better with anti-aliasing looks better but slower. + * @param obj pointer to an image object + * @param antialias true: anti-aliased; false: not anti-aliased + */ +void lv_img_set_antialias(lv_obj_t * obj, bool antialias); + +/** + * Set the image object size mode. + * + * @param obj pointer to an image object + * @param mode the new size mode. + */ +void lv_img_set_size_mode(lv_obj_t * obj, lv_img_size_mode_t mode); +/*===================== + * Getter functions + *====================*/ + +/** + * Get the source of the image + * @param obj pointer to an image object + * @return the image source (symbol, file name or ::lv-img_dsc_t for C arrays) + */ +const void * lv_img_get_src(lv_obj_t * obj); + +/** + * Get the offset's x attribute of the image object. + * @param img pointer to an image + * @return offset X value. + */ +lv_coord_t lv_img_get_offset_x(lv_obj_t * obj); + +/** + * Get the offset's y attribute of the image object. + * @param obj pointer to an image + * @return offset Y value. + */ +lv_coord_t lv_img_get_offset_y(lv_obj_t * obj); + +/** + * Get the rotation angle of the image. + * @param obj pointer to an image object + * @return rotation angle in 0.1 degrees (0..3600) + */ +uint16_t lv_img_get_angle(lv_obj_t * obj); + +/** + * Get the pivot (rotation center) of the image. + * @param img pointer to an image object + * @param pivot store the rotation center here + */ +void lv_img_get_pivot(lv_obj_t * obj, lv_point_t * pivot); + +/** + * Get the zoom factor of the image. + * @param obj pointer to an image object + * @return zoom factor (256: no zoom) + */ +uint16_t lv_img_get_zoom(lv_obj_t * obj); + +/** + * Get whether the transformations (rotate, zoom) are anti-aliased or not + * @param obj pointer to an image object + * @return true: anti-aliased; false: not anti-aliased + */ +bool lv_img_get_antialias(lv_obj_t * obj); + +/** + * Get the size mode of the image + * @param obj pointer to an image object + * @return element of @ref lv_img_size_mode_t + */ +lv_img_size_mode_t lv_img_get_size_mode(lv_obj_t * obj); + +/********************** + * MACROS + **********************/ + +/** Use this macro to declare an image in a C file*/ +#define LV_IMG_DECLARE(var_name) extern const lv_img_dsc_t var_name; + +#endif /*LV_USE_IMG*/ + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif /*LV_IMG_H*/ diff --git a/src/lib/lvgl/src/widgets/lv_label.h b/src/lib/lvgl/src/widgets/lv_label.h new file mode 100644 index 0000000..342e004 --- /dev/null +++ b/src/lib/lvgl/src/widgets/lv_label.h @@ -0,0 +1,246 @@ +/** + * @file lv_label.h + * + */ + +#ifndef LV_LABEL_H +#define LV_LABEL_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include "../lv_conf_internal.h" + +#if LV_USE_LABEL != 0 + +#include +#include "../core/lv_obj.h" +#include "../font/lv_font.h" +#include "../font/lv_symbol_def.h" +#include "../misc/lv_txt.h" +#include "../draw/lv_draw.h" + +/********************* + * DEFINES + *********************/ +#define LV_LABEL_WAIT_CHAR_COUNT 3 +#define LV_LABEL_DOT_NUM 3 +#define LV_LABEL_POS_LAST 0xFFFF +#define LV_LABEL_TEXT_SELECTION_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_SELECTION_OFF); + +/********************** + * TYPEDEFS + **********************/ + +/** Long mode behaviors. Used in 'lv_label_ext_t'*/ +enum { + LV_LABEL_LONG_WRAP, /**< Keep the object width, wrap the too long lines and expand the object height*/ + LV_LABEL_LONG_DOT, /**< Keep the size and write dots at the end if the text is too long*/ + LV_LABEL_LONG_SCROLL, /**< Keep the size and roll the text back and forth*/ + LV_LABEL_LONG_SCROLL_CIRCULAR, /**< Keep the size and roll the text circularly*/ + LV_LABEL_LONG_CLIP, /**< Keep the size and clip the text out of it*/ +}; +typedef uint8_t lv_label_long_mode_t; + +typedef struct { + lv_obj_t obj; + char * text; + union { + char * tmp_ptr; /*Pointer to the allocated memory containing the character replaced by dots*/ + char tmp[LV_LABEL_DOT_NUM + 1]; /*Directly store the characters if <=4 characters*/ + } dot; + uint32_t dot_end; /*The real text length, used in dot mode*/ + +#if LV_LABEL_LONG_TXT_HINT + lv_draw_label_hint_t hint; +#endif + +#if LV_LABEL_TEXT_SELECTION + uint32_t sel_start; + uint32_t sel_end; +#endif + + lv_point_t offset; /*Text draw position offset*/ + lv_label_long_mode_t long_mode : 3; /*Determine what to do with the long texts*/ + uint8_t static_txt : 1; /*Flag to indicate the text is static*/ + uint8_t recolor : 1; /*Enable in-line letter re-coloring*/ + uint8_t expand : 1; /*Ignore real width (used by the library with LV_LABEL_LONG_SCROLL)*/ + uint8_t dot_tmp_alloc : 1; /*1: dot is allocated, 0: dot directly holds up to 4 chars*/ +} lv_label_t; + +extern const lv_obj_class_t lv_label_class; + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +/** + * Create a label object + * @param parent pointer to an object, it will be the parent of the new label. + * @return pointer to the created button + */ +lv_obj_t * lv_label_create(lv_obj_t * parent); + +/*===================== + * Setter functions + *====================*/ + +/** + * Set a new text for a label. Memory will be allocated to store the text by the label. + * @param obj pointer to a label object + * @param text '\0' terminated character string. NULL to refresh with the current text. + */ +void lv_label_set_text(lv_obj_t * obj, const char * text); + +/** + * Set a new formatted text for a label. Memory will be allocated to store the text by the label. + * @param obj pointer to a label object + * @param fmt `printf`-like format + * @example lv_label_set_text_fmt(label1, "%d user", user_num); + */ +void lv_label_set_text_fmt(lv_obj_t * obj, const char * fmt, ...) LV_FORMAT_ATTRIBUTE(2, 3); + +/** + * Set a static text. It will not be saved by the label so the 'text' variable + * has to be 'alive' while the label exists. + * @param obj pointer to a label object + * @param text pointer to a text. NULL to refresh with the current text. + */ +void lv_label_set_text_static(lv_obj_t * obj, const char * text); + +/** + * Set the behavior of the label with longer text then the object size + * @param obj pointer to a label object + * @param long_mode the new mode from 'lv_label_long_mode' enum. + * In LV_LONG_WRAP/DOT/SCROLL/SCROLL_CIRC the size of the label should be set AFTER this function + */ +void lv_label_set_long_mode(lv_obj_t * obj, lv_label_long_mode_t long_mode); + +/** + * Enable the recoloring by in-line commands + * @param obj pointer to a label object + * @param en true: enable recoloring, false: disable + * @example "This is a #ff0000 red# word" + */ +void lv_label_set_recolor(lv_obj_t * obj, bool en); + +/** + * Set where text selection should start + * @param obj pointer to a label object + * @param index character index from where selection should start. `LV_LABEL_TEXT_SELECTION_OFF` for no selection + */ +void lv_label_set_text_sel_start(lv_obj_t * obj, uint32_t index); + +/** + * Set where text selection should end + * @param obj pointer to a label object + * @param index character index where selection should end. `LV_LABEL_TEXT_SELECTION_OFF` for no selection + */ +void lv_label_set_text_sel_end(lv_obj_t * obj, uint32_t index); + +/*===================== + * Getter functions + *====================*/ + +/** + * Get the text of a label + * @param obj pointer to a label object + * @return the text of the label + */ +char * lv_label_get_text(const lv_obj_t * obj); + +/** + * Get the long mode of a label + * @param obj pointer to a label object + * @return the current long mode + */ +lv_label_long_mode_t lv_label_get_long_mode(const lv_obj_t * obj); + +/** + * Get the recoloring attribute + * @param obj pointer to a label object + * @return true: recoloring is enabled, false: disable + */ +bool lv_label_get_recolor(const lv_obj_t * obj); + +/** + * Get the relative x and y coordinates of a letter + * @param obj pointer to a label object + * @param index index of the character [0 ... text length - 1]. + * Expressed in character index, not byte index (different in UTF-8) + * @param pos store the result here (E.g. index = 0 gives 0;0 coordinates if the text if aligned to the left) + */ +void lv_label_get_letter_pos(const lv_obj_t * obj, uint32_t char_id, lv_point_t * pos); + +/** + * Get the index of letter on a relative point of a label. + * @param obj pointer to label object + * @param pos pointer to point with coordinates on a the label + * @return The index of the letter on the 'pos_p' point (E.g. on 0;0 is the 0. letter if aligned to the left) + * Expressed in character index and not byte index (different in UTF-8) + */ +uint32_t lv_label_get_letter_on(const lv_obj_t * obj, lv_point_t * pos_in); + +/** + * Check if a character is drawn under a point. + * @param obj pointer to a label object + * @param pos Point to check for character under + * @return whether a character is drawn under the point + */ +bool lv_label_is_char_under_pos(const lv_obj_t * obj, lv_point_t * pos); + +/** + * @brief Get the selection start index. + * @param obj pointer to a label object. + * @return selection start index. `LV_LABEL_TEXT_SELECTION_OFF` if nothing is selected. + */ +uint32_t lv_label_get_text_selection_start(const lv_obj_t * obj); + +/** + * @brief Get the selection end index. + * @param obj pointer to a label object. + * @return selection end index. `LV_LABEL_TXT_SEL_OFF` if nothing is selected. + */ +uint32_t lv_label_get_text_selection_end(const lv_obj_t * obj); + +/*===================== + * Other functions + *====================*/ + +/** + * Insert a text to a label. The label text can not be static. + * @param obj pointer to a label object + * @param pos character index to insert. Expressed in character index and not byte index. + * 0: before first char. LV_LABEL_POS_LAST: after last char. + * @param txt pointer to the text to insert + */ +void lv_label_ins_text(lv_obj_t * obj, uint32_t pos, const char * txt); + +/** + * Delete characters from a label. The label text can not be static. + * @param obj pointer to a label object + * @param pos character index from where to cut. Expressed in character index and not byte index. + * 0: start in from of the first character + * @param cnt number of characters to cut + */ +void lv_label_cut_text(lv_obj_t * obj, uint32_t pos, uint32_t cnt); + +/********************** + * MACROS + **********************/ + +#endif /*LV_USE_LABEL*/ + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif /*LV_LABEL_H*/ diff --git a/src/lib/lvgl/src/widgets/lv_line.h b/src/lib/lvgl/src/widgets/lv_line.h new file mode 100644 index 0000000..54fa248 --- /dev/null +++ b/src/lib/lvgl/src/widgets/lv_line.h @@ -0,0 +1,93 @@ +/** + * @file lv_line.h + * + */ + +#ifndef LV_LINE_H +#define LV_LINE_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include "../lv_conf_internal.h" + +#if LV_USE_LINE != 0 + +#include "../core/lv_obj.h" + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +/*Data of line*/ +typedef struct { + lv_obj_t obj; + const lv_point_t * point_array; /**< Pointer to an array with the points of the line*/ + uint16_t point_num; /**< Number of points in 'point_array'*/ + uint8_t y_inv : 1; /**< 1: y == 0 will be on the bottom*/ +} lv_line_t; + +extern const lv_obj_class_t lv_line_class; + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +/** + * Create a line object + * @param parent pointer to an object, it will be the parent of the new line + * @return pointer to the created line + */ +lv_obj_t * lv_line_create(lv_obj_t * parent); + +/*===================== + * Setter functions + *====================*/ + +/** + * Set an array of points. The line object will connect these points. + * @param obj pointer to a line object + * @param points an array of points. Only the address is saved, so the array needs to be alive while the line exists + * @param point_num number of points in 'point_a' + */ +void lv_line_set_points(lv_obj_t * obj, const lv_point_t points[], uint16_t point_num); + +/** + * Enable (or disable) the y coordinate inversion. + * If enabled then y will be subtracted from the height of the object, + * therefore the y = 0 coordinate will be on the bottom. + * @param obj pointer to a line object + * @param en true: enable the y inversion, false:disable the y inversion + */ +void lv_line_set_y_invert(lv_obj_t * obj, bool en); + +/*===================== + * Getter functions + *====================*/ + +/** + * Get the y inversion attribute + * @param obj pointer to a line object + * @return true: y inversion is enabled, false: disabled + */ +bool lv_line_get_y_invert(const lv_obj_t * obj); + +/********************** + * MACROS + **********************/ + +#endif /*LV_USE_LINE*/ + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif /*LV_LINE_H*/ diff --git a/src/lib/lvgl/src/widgets/lv_objx_templ.h b/src/lib/lvgl/src/widgets/lv_objx_templ.h new file mode 100644 index 0000000..9de5285 --- /dev/null +++ b/src/lib/lvgl/src/widgets/lv_objx_templ.h @@ -0,0 +1,81 @@ +/** + * @file lv_templ.h + * + */ + +/** + * TODO Remove these instructions + * Search and replace: templ -> object short name with lower case(e.g. btn, label etc) + * TEMPL -> object short name with upper case (e.g. BTN, LABEL etc.) + * + */ + +#ifndef LV_TEMPL_H +#define LV_TEMPL_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include "../lv_conf_internal.h" + +#if LV_USE_TEMPL != 0 + +#include "../core/lv_obj.h" + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ +/*Data of template*/ +typedef struct { + lv_ANCESTOR_t ancestor; /*The ancestor widget, e.g. lv_slider_t slider*/ + /*New data for this type*/ +} lv_templ_t; + +extern const lv_obj_class_t lv_templ_class; + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +/** + * Create a templ object + * @param parent pointer to an object, it will be the parent of the new templ + * @return pointer to the created bar + */ +lv_obj_t * lv_templ_create(lv_obj_t * parent); + +/*====================== + * Add/remove functions + *=====================*/ + +/*===================== + * Setter functions + *====================*/ + +/*===================== + * Getter functions + *====================*/ + +/*===================== + * Other functions + *====================*/ + +/********************** + * MACROS + **********************/ + +#endif /*LV_USE_TEMPL*/ + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif /*LV_TEMPL_H*/ diff --git a/src/lib/lvgl/src/widgets/lv_roller.h b/src/lib/lvgl/src/widgets/lv_roller.h new file mode 100644 index 0000000..d90001d --- /dev/null +++ b/src/lib/lvgl/src/widgets/lv_roller.h @@ -0,0 +1,133 @@ +/** + * @file lv_roller.h + * + */ + +#ifndef LV_ROLLER_H +#define LV_ROLLER_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include "../lv_conf_internal.h" + +#if LV_USE_ROLLER != 0 + +#include "../core/lv_obj.h" +#include "lv_label.h" + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +/** Roller mode.*/ +enum { + LV_ROLLER_MODE_NORMAL, /**< Normal mode (roller ends at the end of the options).*/ + LV_ROLLER_MODE_INFINITE, /**< Infinite mode (roller can be scrolled forever).*/ +}; + +typedef uint8_t lv_roller_mode_t; + +typedef struct { + lv_obj_t obj; + uint16_t option_cnt; /**< Number of options*/ + uint16_t sel_opt_id; /**< Index of the current option*/ + uint16_t sel_opt_id_ori; /**< Store the original index on focus*/ + lv_roller_mode_t mode : 1; + uint32_t moved : 1; +} lv_roller_t; + +extern const lv_obj_class_t lv_roller_class; + + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +/** + * Create a roller object + * @param parent pointer to an object, it will be the parent of the new roller. + * @return pointer to the created roller + */ +lv_obj_t * lv_roller_create(lv_obj_t * parent); + +/*===================== + * Setter functions + *====================*/ + +/** + * Set the options on a roller + * @param obj pointer to roller object + * @param options a string with '\n' separated options. E.g. "One\nTwo\nThree" + * @param mode `LV_ROLLER_MODE_NORMAL` or `LV_ROLLER_MODE_INFINITE` + */ +void lv_roller_set_options(lv_obj_t * obj, const char * options, lv_roller_mode_t mode); + +/** + * Set the selected option + * @param obj pointer to a roller object + * @param sel_opt index of the selected option (0 ... number of option - 1); + * @param anim_en LV_ANIM_ON: set with animation; LV_ANOM_OFF set immediately + */ +void lv_roller_set_selected(lv_obj_t * obj, uint16_t sel_opt, lv_anim_enable_t anim); + +/** + * Set the height to show the given number of rows (options) + * @param obj pointer to a roller object + * @param row_cnt number of desired visible rows + */ +void lv_roller_set_visible_row_count(lv_obj_t * obj, uint8_t row_cnt); + +/*===================== + * Getter functions + *====================*/ + +/** + * Get the index of the selected option + * @param obj pointer to a roller object + * @return index of the selected option (0 ... number of option - 1); + */ +uint16_t lv_roller_get_selected(const lv_obj_t * obj); + +/** + * Get the current selected option as a string. + * @param obj pointer to ddlist object + * @param buf pointer to an array to store the string + * @param buf_size size of `buf` in bytes. 0: to ignore it. + */ +void lv_roller_get_selected_str(const lv_obj_t * obj, char * buf, uint32_t buf_size); + + +/** + * Get the options of a roller + * @param obj pointer to roller object + * @return the options separated by '\n'-s (E.g. "Option1\nOption2\nOption3") + */ +const char * lv_roller_get_options(const lv_obj_t * obj); + +/** + * Get the total number of options + * @param obj pointer to a roller object + * @return the total number of options + */ +uint16_t lv_roller_get_option_cnt(const lv_obj_t * obj); + +/********************** + * MACROS + **********************/ + +#endif /*LV_USE_ROLLER*/ + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif /*LV_ROLLER_H*/ diff --git a/src/lib/lvgl/src/widgets/lv_slider.h b/src/lib/lvgl/src/widgets/lv_slider.h new file mode 100644 index 0000000..386950c --- /dev/null +++ b/src/lib/lvgl/src/widgets/lv_slider.h @@ -0,0 +1,195 @@ +/** + * @file lv_slider.h + * + */ + +#ifndef LV_SLIDER_H +#define LV_SLIDER_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include "../lv_conf_internal.h" + +#if LV_USE_SLIDER != 0 + +/*Testing of dependencies*/ +#if LV_USE_BAR == 0 +#error "lv_slider: lv_bar is required. Enable it in lv_conf.h (LV_USE_BAR 1)" +#endif + +#include "../core/lv_obj.h" +#include "lv_bar.h" + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +enum { + LV_SLIDER_MODE_NORMAL = LV_BAR_MODE_NORMAL, + LV_SLIDER_MODE_SYMMETRICAL = LV_BAR_MODE_SYMMETRICAL, + LV_SLIDER_MODE_RANGE = LV_BAR_MODE_RANGE +}; +typedef uint8_t lv_slider_mode_t; + +typedef struct { + lv_bar_t bar; /*Add the ancestor's type first*/ + lv_area_t left_knob_area; + lv_area_t right_knob_area; + int32_t * value_to_set; /*Which bar value to set*/ + uint8_t dragging : 1; /*1: the slider is being dragged*/ + uint8_t left_knob_focus : 1; /*1: with encoder now the right knob can be adjusted*/ +} lv_slider_t; + +extern const lv_obj_class_t lv_slider_class; + +/** + * `type` field in `lv_obj_draw_part_dsc_t` if `class_p = lv_slider_class` + * Used in `LV_EVENT_DRAW_PART_BEGIN` and `LV_EVENT_DRAW_PART_END` + */ +typedef enum { + LV_SLIDER_DRAW_PART_KNOB, /**< The main (right) knob's rectangle*/ + LV_SLIDER_DRAW_PART_KNOB_LEFT, /**< The left knob's rectangle*/ +} lv_slider_draw_part_type_t; + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +/** + * Create a slider object + * @param parent pointer to an object, it will be the parent of the new slider. + * @return pointer to the created slider + */ +lv_obj_t * lv_slider_create(lv_obj_t * parent); + +/*===================== + * Setter functions + *====================*/ + +/** + * Set a new value on the slider + * @param obj pointer to a slider object + * @param value the new value + * @param anim LV_ANIM_ON: set the value with an animation; LV_ANIM_OFF: change the value immediately + */ +static inline void lv_slider_set_value(lv_obj_t * obj, int32_t value, lv_anim_enable_t anim) +{ + lv_bar_set_value(obj, value, anim); +} + +/** + * Set a new value for the left knob of a slider + * @param obj pointer to a slider object + * @param value new value + * @param anim LV_ANIM_ON: set the value with an animation; LV_ANIM_OFF: change the value immediately + */ +static inline void lv_slider_set_left_value(lv_obj_t * obj, int32_t value, lv_anim_enable_t anim) +{ + lv_bar_set_start_value(obj, value, anim); +} + +/** + * Set minimum and the maximum values of a bar + * @param obj pointer to the slider object + * @param min minimum value + * @param max maximum value + */ +static inline void lv_slider_set_range(lv_obj_t * obj, int32_t min, int32_t max) +{ + lv_bar_set_range(obj, min, max); +} + +/** + * Set the mode of slider. + * @param obj pointer to a slider object + * @param mode the mode of the slider. See ::lv_slider_mode_t + */ +static inline void lv_slider_set_mode(lv_obj_t * obj, lv_slider_mode_t mode) +{ + lv_bar_set_mode(obj, (lv_bar_mode_t)mode); +} + +/*===================== + * Getter functions + *====================*/ + +/** + * Get the value of the main knob of a slider + * @param obj pointer to a slider object + * @return the value of the main knob of the slider + */ +static inline int32_t lv_slider_get_value(const lv_obj_t * obj) +{ + return lv_bar_get_value(obj); +} + +/** + * Get the value of the left knob of a slider + * @param obj pointer to a slider object + * @return the value of the left knob of the slider + */ +static inline int32_t lv_slider_get_left_value(const lv_obj_t * obj) +{ + return lv_bar_get_start_value(obj); +} + +/** + * Get the minimum value of a slider + * @param obj pointer to a slider object + * @return the minimum value of the slider + */ +static inline int32_t lv_slider_get_min_value(const lv_obj_t * obj) +{ + return lv_bar_get_min_value(obj); +} + +/** + * Get the maximum value of a slider + * @param obj pointer to a slider object + * @return the maximum value of the slider + */ +static inline int32_t lv_slider_get_max_value(const lv_obj_t * obj) +{ + return lv_bar_get_max_value(obj); +} + +/** + * Give the slider is being dragged or not + * @param obj pointer to a slider object + * @return true: drag in progress false: not dragged + */ +bool lv_slider_is_dragged(const lv_obj_t * obj); + +/** + * Get the mode of the slider. + * @param obj pointer to a bar object + * @return see ::lv_slider_mode_t + */ +static inline lv_slider_mode_t lv_slider_get_mode(lv_obj_t * slider) +{ + lv_bar_mode_t mode = lv_bar_get_mode(slider); + if(mode == LV_BAR_MODE_SYMMETRICAL) return LV_SLIDER_MODE_SYMMETRICAL; + else if(mode == LV_BAR_MODE_RANGE) return LV_SLIDER_MODE_RANGE; + else return LV_SLIDER_MODE_NORMAL; +} + +/********************** + * MACROS + **********************/ + +#endif /*LV_USE_SLIDER*/ + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif /*LV_SLIDER_H*/ diff --git a/src/lib/lvgl/src/widgets/lv_switch.h b/src/lib/lvgl/src/widgets/lv_switch.h new file mode 100644 index 0000000..83ca81b --- /dev/null +++ b/src/lib/lvgl/src/widgets/lv_switch.h @@ -0,0 +1,61 @@ +/** + * @file lv_switch.h + * + */ + +#ifndef LV_SWITCH_H +#define LV_SWITCH_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include "../lv_conf_internal.h" + +#if LV_USE_SWITCH != 0 + +#include "../core/lv_obj.h" + +/********************* + * DEFINES + *********************/ + +/** Switch knob extra area correction factor */ +#define _LV_SWITCH_KNOB_EXT_AREA_CORRECTION 2 + +/********************** + * TYPEDEFS + **********************/ + +typedef struct { + lv_obj_t obj; + int32_t anim_state; +} lv_switch_t; + +extern const lv_obj_class_t lv_switch_class; + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +/** + * Create a switch object + * @param parent pointer to an object, it will be the parent of the new switch + * @return pointer to the created switch + */ +lv_obj_t * lv_switch_create(lv_obj_t * parent); + +/********************** + * MACROS + **********************/ + +#endif /*LV_USE_SWITCH*/ + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif /*LV_SWITCH_H*/ diff --git a/src/lib/lvgl/src/widgets/lv_table.h b/src/lib/lvgl/src/widgets/lv_table.h new file mode 100644 index 0000000..9106270 --- /dev/null +++ b/src/lib/lvgl/src/widgets/lv_table.h @@ -0,0 +1,210 @@ +/** + * @file lv_table.h + * + */ + +#ifndef LV_TABLE_H +#define LV_TABLE_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include "../lv_conf_internal.h" + +#if LV_USE_TABLE != 0 + +/*Testing of dependencies*/ +#if LV_USE_LABEL == 0 +#error "lv_table: lv_label is required. Enable it in lv_conf.h (LV_USE_LABEL 1)" +#endif + +#include "../core/lv_obj.h" +#include "lv_label.h" + +/********************* + * DEFINES + *********************/ +#define LV_TABLE_CELL_NONE 0XFFFF +LV_EXPORT_CONST_INT(LV_TABLE_CELL_NONE); + +/********************** + * TYPEDEFS + **********************/ + +enum { + LV_TABLE_CELL_CTRL_MERGE_RIGHT = 1 << 0, + LV_TABLE_CELL_CTRL_TEXT_CROP = 1 << 1, + LV_TABLE_CELL_CTRL_CUSTOM_1 = 1 << 4, + LV_TABLE_CELL_CTRL_CUSTOM_2 = 1 << 5, + LV_TABLE_CELL_CTRL_CUSTOM_3 = 1 << 6, + LV_TABLE_CELL_CTRL_CUSTOM_4 = 1 << 7, +}; + +typedef uint8_t lv_table_cell_ctrl_t; + +/*Data of table*/ +typedef struct { + lv_obj_t obj; + uint16_t col_cnt; + uint16_t row_cnt; + char ** cell_data; + lv_coord_t * row_h; + lv_coord_t * col_w; + uint16_t col_act; + uint16_t row_act; +} lv_table_t; + +extern const lv_obj_class_t lv_table_class; + +/** + * `type` field in `lv_obj_draw_part_dsc_t` if `class_p = lv_table_class` + * Used in `LV_EVENT_DRAW_PART_BEGIN` and `LV_EVENT_DRAW_PART_END` + */ +typedef enum { + LV_TABLE_DRAW_PART_CELL, /**< A cell*/ +} lv_table_draw_part_type_t; + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +/** + * Create a table object + * @param parent pointer to an object, it will be the parent of the new table + * @return pointer to the created table + */ +lv_obj_t * lv_table_create(lv_obj_t * parent); + +/*===================== + * Setter functions + *====================*/ + +/** + * Set the value of a cell. + * @param obj pointer to a Table object + * @param row id of the row [0 .. row_cnt -1] + * @param col id of the column [0 .. col_cnt -1] + * @param txt text to display in the cell. It will be copied and saved so this variable is not required after this function call. + * @note New roes/columns are added automatically if required + */ +void lv_table_set_cell_value(lv_obj_t * obj, uint16_t row, uint16_t col, const char * txt); + +/** + * Set the value of a cell. Memory will be allocated to store the text by the table. + * @param obj pointer to a Table object + * @param row id of the row [0 .. row_cnt -1] + * @param col id of the column [0 .. col_cnt -1] + * @param fmt `printf`-like format + * @note New roes/columns are added automatically if required + */ +void lv_table_set_cell_value_fmt(lv_obj_t * obj, uint16_t row, uint16_t col, const char * fmt, ...); + +/** + * Set the number of rows + * @param obj table pointer to a Table object + * @param row_cnt number of rows + */ +void lv_table_set_row_cnt(lv_obj_t * obj, uint16_t row_cnt); + +/** + * Set the number of columns + * @param obj table pointer to a Table object + * @param col_cnt number of columns. + */ +void lv_table_set_col_cnt(lv_obj_t * obj, uint16_t col_cnt); + +/** + * Set the width of a column + * @param obj table pointer to a Table object + * @param col_id id of the column [0 .. LV_TABLE_COL_MAX -1] + * @param w width of the column + */ +void lv_table_set_col_width(lv_obj_t * obj, uint16_t col_id, lv_coord_t w); + +/** + * Add control bits to the cell. + * @param obj pointer to a Table object + * @param row id of the row [0 .. row_cnt -1] + * @param col id of the column [0 .. col_cnt -1] + * @param ctrl OR-ed values from ::lv_table_cell_ctrl_t + */ +void lv_table_add_cell_ctrl(lv_obj_t * obj, uint16_t row, uint16_t col, lv_table_cell_ctrl_t ctrl); + + +/** + * Clear control bits of the cell. + * @param obj pointer to a Table object + * @param row id of the row [0 .. row_cnt -1] + * @param col id of the column [0 .. col_cnt -1] + * @param ctrl OR-ed values from ::lv_table_cell_ctrl_t + */ +void lv_table_clear_cell_ctrl(lv_obj_t * obj, uint16_t row, uint16_t col, lv_table_cell_ctrl_t ctrl); + +/*===================== + * Getter functions + *====================*/ + +/** + * Get the value of a cell. + * @param obj pointer to a Table object + * @param row id of the row [0 .. row_cnt -1] + * @param col id of the column [0 .. col_cnt -1] + * @return text in the cell + */ +const char * lv_table_get_cell_value(lv_obj_t * obj, uint16_t row, uint16_t col); + +/** + * Get the number of rows. + * @param obj table pointer to a Table object + * @return number of rows. + */ +uint16_t lv_table_get_row_cnt(lv_obj_t * obj); + +/** + * Get the number of columns. + * @param obj table pointer to a Table object + * @return number of columns. + */ +uint16_t lv_table_get_col_cnt(lv_obj_t * obj); + +/** + * Get the width of a column + * @param obj table pointer to a Table object + * @param col id of the column [0 .. LV_TABLE_COL_MAX -1] + * @return width of the column + */ +lv_coord_t lv_table_get_col_width(lv_obj_t * obj, uint16_t col); + +/** + * Get whether a cell has the control bits + * @param obj pointer to a Table object + * @param row id of the row [0 .. row_cnt -1] + * @param col id of the column [0 .. col_cnt -1] + * @param ctrl OR-ed values from ::lv_table_cell_ctrl_t + * @return true: all control bits are set; false: not all control bits are set + */ +bool lv_table_has_cell_ctrl(lv_obj_t * obj, uint16_t row, uint16_t col, lv_table_cell_ctrl_t ctrl); + +/** + * Get the selected cell (pressed and or focused) + * @param obj pointer to a table object + * @param row pointer to variable to store the selected row (LV_TABLE_CELL_NONE: if no cell selected) + * @param col pointer to variable to store the selected column (LV_TABLE_CELL_NONE: if no cell selected) + */ +void lv_table_get_selected_cell(lv_obj_t * obj, uint16_t * row, uint16_t * col); + +/********************** + * MACROS + **********************/ + +#endif /*LV_USE_TABLE*/ + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif /*LV_TABLE_H*/ diff --git a/src/lib/lvgl/src/widgets/lv_textarea.h b/src/lib/lvgl/src/widgets/lv_textarea.h new file mode 100644 index 0000000..219e272 --- /dev/null +++ b/src/lib/lvgl/src/widgets/lv_textarea.h @@ -0,0 +1,343 @@ +/** + * @file lv_textarea.h + * + */ + +#ifndef LV_TEXTAREA_H +#define LV_TEXTAREA_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include "../lv_conf_internal.h" + +#if LV_USE_TEXTAREA != 0 + +/*Testing of dependencies*/ +#if LV_USE_LABEL == 0 +#error "lv_ta: lv_label is required. Enable it in lv_conf.h (LV_USE_LABEL 1)" +#endif + +#include "../core/lv_obj.h" +#include "lv_label.h" + +/********************* + * DEFINES + *********************/ +#define LV_TEXTAREA_CURSOR_LAST (0x7FFF) /*Put the cursor after the last character*/ + +LV_EXPORT_CONST_INT(LV_TEXTAREA_CURSOR_LAST); + +/********************** + * TYPEDEFS + **********************/ + +/*Data of text area*/ +typedef struct { + lv_obj_t obj; + lv_obj_t * label; /*Label of the text area*/ + char * placeholder_txt; /*Place holder label. only visible if text is an empty string*/ + char * pwd_tmp; /*Used to store the original text in password mode*/ + const char * accepted_chars; /*Only these characters will be accepted. NULL: accept all*/ + uint32_t max_length; /*The max. number of characters. 0: no limit*/ + uint16_t pwd_show_time; /*Time to show characters in password mode before change them to '*'*/ + struct { + lv_coord_t valid_x; /*Used when stepping up/down to a shorter line. + *(Used by the library)*/ + uint32_t pos; /*The current cursor position + *(0: before 1st letter; 1: before 2nd letter ...)*/ + lv_area_t area; /*Cursor area relative to the Text Area*/ + uint32_t txt_byte_pos; /*Byte index of the letter after (on) the cursor*/ + uint8_t show : 1; /*Cursor is visible now or not (Handled by the library)*/ + uint8_t click_pos : 1; /*1: Enable positioning the cursor by clicking the text area*/ + } cursor; +#if LV_LABEL_TEXT_SELECTION + uint32_t sel_start; /*Temporary values for text selection*/ + uint32_t sel_end; + uint8_t text_sel_in_prog : 1; /*User is in process of selecting*/ + uint8_t text_sel_en : 1; /*Text can be selected on this text area*/ +#endif + uint8_t pwd_mode : 1; /*Replace characters with '*'*/ + uint8_t one_line : 1; /*One line mode (ignore line breaks)*/ +} lv_textarea_t; + +extern const lv_obj_class_t lv_textarea_class; + +enum { + LV_PART_TEXTAREA_PLACEHOLDER = LV_PART_CUSTOM_FIRST, +}; + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +/** + * Create a text area object + * @param parent pointer to an object, it will be the parent of the new text area + * @return pointer to the created text area + */ +lv_obj_t * lv_textarea_create(lv_obj_t * parent); + +/*====================== + * Add/remove functions + *=====================*/ + +/** + * Insert a character to the current cursor position. + * To add a wide char, e.g. 'Á' use `_lv_txt_encoded_conv_wc('Á')` + * @param obj pointer to a text area object + * @param c a character (e.g. 'a') + */ +void lv_textarea_add_char(lv_obj_t * obj, uint32_t c); + +/** + * Insert a text to the current cursor position + * @param obj pointer to a text area object + * @param txt a '\0' terminated string to insert + */ +void lv_textarea_add_text(lv_obj_t * obj, const char * txt); + +/** + * Delete a the left character from the current cursor position + * @param obj pointer to a text area object + */ +void lv_textarea_del_char(lv_obj_t * obj); + +/** + * Delete the right character from the current cursor position + * @param obj pointer to a text area object + */ +void lv_textarea_del_char_forward(lv_obj_t * obj); + +/*===================== + * Setter functions + *====================*/ + +/** + * Set the text of a text area + * @param obj pointer to a text area object + * @param txt pointer to the text + */ +void lv_textarea_set_text(lv_obj_t * obj, const char * txt); + +/** + * Set the placeholder text of a text area + * @param obj pointer to a text area object + * @param txt pointer to the text + */ +void lv_textarea_set_placeholder_text(lv_obj_t * obj, const char * txt); + +/** + * Set the cursor position + * @param obj pointer to a text area object + * @param pos the new cursor position in character index + * < 0 : index from the end of the text + * LV_TEXTAREA_CURSOR_LAST: go after the last character + */ +void lv_textarea_set_cursor_pos(lv_obj_t * obj, int32_t pos); + +/** + * Enable/Disable the positioning of the cursor by clicking the text on the text area. + * @param obj pointer to a text area object + * @param en true: enable click positions; false: disable + */ +void lv_textarea_set_cursor_click_pos(lv_obj_t * obj, bool en); + +/** + * Enable/Disable password mode + * @param obj pointer to a text area object + * @param en true: enable, false: disable + */ +void lv_textarea_set_password_mode(lv_obj_t * obj, bool en); + +/** + * Configure the text area to one line or back to normal + * @param obj pointer to a text area object + * @param en true: one line, false: normal + */ +void lv_textarea_set_one_line(lv_obj_t * obj, bool en); + +/** + * Set a list of characters. Only these characters will be accepted by the text area + * @param obj pointer to a text area object + * @param list list of characters. Only the pointer is saved. E.g. "+-.,0123456789" + */ +void lv_textarea_set_accepted_chars(lv_obj_t * obj, const char * list); + +/** + * Set max length of a Text Area. + * @param obj pointer to a text area object + * @param num the maximal number of characters can be added (`lv_textarea_set_text` ignores it) + */ +void lv_textarea_set_max_length(lv_obj_t * obj, uint32_t num); + +/** + * In `LV_EVENT_INSERT` the text which planned to be inserted can be replaced by an other text. + * It can be used to add automatic formatting to the text area. + * @param obj pointer to a text area object + * @param txt pointer to a new string to insert. If `""` no text will be added. + * The variable must be live after the `event_cb` exists. (Should be `global` or `static`) + */ +void lv_textarea_set_insert_replace(lv_obj_t * obj, const char * txt); + +/** + * Enable/disable selection mode. + * @param obj pointer to a text area object + * @param en true or false to enable/disable selection mode + */ +void lv_textarea_set_text_selection(lv_obj_t * obj, bool en); + +/** + * Set how long show the password before changing it to '*' + * @param obj pointer to a text area object + * @param time show time in milliseconds. 0: hide immediately. + */ +void lv_textarea_set_password_show_time(lv_obj_t * obj, uint16_t time); + +/** + * Deprecated: use the normal text_align style property instead + * Set the label's alignment. + * It sets where the label is aligned (in one line mode it can be smaller than the text area) + * and how the lines of the area align in case of multiline text area + * @param obj pointer to a text area object + * @param align the align mode from ::lv_text_align_t + */ +void lv_textarea_set_align(lv_obj_t * obj, lv_text_align_t align); + +/*===================== + * Getter functions + *====================*/ + +/** + * Get the text of a text area. In password mode it gives the real text (not '*'s). + * @param obj pointer to a text area object + * @return pointer to the text + */ +const char * lv_textarea_get_text(const lv_obj_t * obj); + +/** + * Get the placeholder text of a text area + * @param obj pointer to a text area object + * @return pointer to the text + */ +const char * lv_textarea_get_placeholder_text(lv_obj_t * obj); + +/** + * Get the label of a text area + * @param obj pointer to a text area object + * @return pointer to the label object + */ +lv_obj_t * lv_textarea_get_label(const lv_obj_t * obj); + +/** + * Get the current cursor position in character index + * @param obj pointer to a text area object + * @return the cursor position + */ +uint32_t lv_textarea_get_cursor_pos(const lv_obj_t * obj); + +/** + * Get whether the cursor click positioning is enabled or not. + * @param obj pointer to a text area object + * @return true: enable click positions; false: disable + */ +bool lv_textarea_get_cursor_click_pos(lv_obj_t * obj); + +/** + * Get the password mode attribute + * @param obj pointer to a text area object + * @return true: password mode is enabled, false: disabled + */ +bool lv_textarea_get_password_mode(const lv_obj_t * obj); + +/** + * Get the one line configuration attribute + * @param obj pointer to a text area object + * @return true: one line configuration is enabled, false: disabled + */ +bool lv_textarea_get_one_line(const lv_obj_t * obj); + +/** + * Get a list of accepted characters. + * @param obj pointer to a text area object + * @return list of accented characters. + */ +const char * lv_textarea_get_accepted_chars(lv_obj_t * obj); + +/** + * Get max length of a Text Area. + * @param obj pointer to a text area object + * @return the maximal number of characters to be add + */ +uint32_t lv_textarea_get_max_length(lv_obj_t * obj); + +/** + * Find whether text is selected or not. + * @param obj pointer to a text area object + * @return whether text is selected or not + */ +bool lv_textarea_text_is_selected(const lv_obj_t * obj); + +/** + * Find whether selection mode is enabled. + * @param obj pointer to a text area object + * @return true: selection mode is enabled, false: disabled + */ +bool lv_textarea_get_text_selection(lv_obj_t * obj); + +/** + * Set how long show the password before changing it to '*' + * @param obj pointer to a text area object + * @return show time in milliseconds. 0: hide immediately. + */ +uint16_t lv_textarea_get_password_show_time(lv_obj_t * obj); + +/*===================== + * Other functions + *====================*/ + +/** + * Clear the selection on the text area. + * @param obj pointer to a text area object + */ +void lv_textarea_clear_selection(lv_obj_t * obj); + +/** + * Move the cursor one character right + * @param obj pointer to a text area object + */ +void lv_textarea_cursor_right(lv_obj_t * obj); + +/** + * Move the cursor one character left + * @param obj pointer to a text area object + */ +void lv_textarea_cursor_left(lv_obj_t * obj); + +/** + * Move the cursor one line down + * @param obj pointer to a text area object + */ +void lv_textarea_cursor_down(lv_obj_t * obj); + +/** + * Move the cursor one line up + * @param obj pointer to a text area object + */ +void lv_textarea_cursor_up(lv_obj_t * obj); + +/********************** + * MACROS + **********************/ + +#endif /*LV_USE_TEXTAREA_H*/ + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif /*LV_TEXTAREA_H*/ From 8ad014af7bc1daaf494442cc851ead387bec666d Mon Sep 17 00:00:00 2001 From: Alexander Entinger Date: Fri, 8 Apr 2022 11:01:51 +0200 Subject: [PATCH 7/7] Fix: Relative include path to find the right header files. --- src/Braccio++.h | 2 +- src/gif.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Braccio++.h b/src/Braccio++.h index 4e5ecf9..5ba6db9 100644 --- a/src/Braccio++.h +++ b/src/Braccio++.h @@ -33,7 +33,7 @@ #include "drivers/Ticker.h" #include "lib/TFT_eSPI/TFT_eSPI.h" // Hardware-specific library -#include +#include "lib/lvgl/lvgl.h" #include using namespace std::chrono; diff --git a/src/gif.c b/src/gif.c index c795050..78bf383 100644 --- a/src/gif.c +++ b/src/gif.c @@ -18,7 +18,7 @@ * USA. */ -#include +#include "lib/lvgl/lvgl.h" #ifndef LV_ATTRIBUTE_MEM_ALIGN #define LV_ATTRIBUTE_MEM_ALIGN